issue-flow 0.13.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 (162) hide show
  1. package/dist/agent-OX3KPHE4.js +30 -0
  2. package/dist/{analyze-WS47UYGN.js → analyze-WIND2SEB.js} +21 -18
  3. package/dist/{analyze-WS47UYGN.js.map → analyze-WIND2SEB.js.map} +1 -1
  4. package/dist/{apply-OS62UWRN.js → apply-JNOI2LR4.js} +14 -11
  5. package/dist/{apply-OS62UWRN.js.map → apply-JNOI2LR4.js.map} +1 -1
  6. package/dist/{bench-SA3BOME5.js → bench-B4VZON7E.js} +30 -26
  7. package/dist/{bench-SA3BOME5.js.map → bench-B4VZON7E.js.map} +1 -1
  8. package/dist/{chunk-PIVGJM6K.js → chunk-2IQ6M4ZE.js} +11 -11
  9. package/dist/{chunk-QCXPNSEL.js → chunk-3BWZO4YI.js} +2 -2
  10. package/dist/chunk-3WFZETIM.js +163 -0
  11. package/dist/chunk-3WFZETIM.js.map +1 -0
  12. package/dist/{chunk-6FDFRNXZ.js → chunk-67YIU2VB.js} +25 -20
  13. package/dist/chunk-67YIU2VB.js.map +1 -0
  14. package/dist/{chunk-TM67EHSV.js → chunk-6BENHR2I.js} +19 -19
  15. package/dist/chunk-6BENHR2I.js.map +1 -0
  16. package/dist/{chunk-IYV6KNVF.js → chunk-6QYMSNVA.js} +66 -240
  17. package/dist/chunk-6QYMSNVA.js.map +1 -0
  18. package/dist/{chunk-IV5SS4JN.js → chunk-76MMPJ53.js} +9 -7
  19. package/dist/{chunk-IV5SS4JN.js.map → chunk-76MMPJ53.js.map} +1 -1
  20. package/dist/{chunk-LZ6GFQAG.js → chunk-B72RQZBV.js} +35 -25
  21. package/dist/chunk-B72RQZBV.js.map +1 -0
  22. package/dist/{chunk-KQHB7ZT3.js → chunk-BEZ5BA5U.js} +82 -16
  23. package/dist/chunk-BEZ5BA5U.js.map +1 -0
  24. package/dist/{chunk-BQDQTIM7.js → chunk-BRCNQXYQ.js} +4 -4
  25. package/dist/{chunk-ARFVHC2F.js → chunk-CGKLE6WR.js} +115 -23
  26. package/dist/chunk-CGKLE6WR.js.map +1 -0
  27. package/dist/{chunk-BHJCGWQX.js → chunk-F6TOYSYY.js} +9 -9
  28. package/dist/chunk-G5EK2XRN.js +25 -0
  29. package/dist/chunk-G5EK2XRN.js.map +1 -0
  30. package/dist/{chunk-TX5WIVYP.js → chunk-HAKDLR6N.js} +6 -1
  31. package/dist/chunk-HAKDLR6N.js.map +1 -0
  32. package/dist/{chunk-DIG5XKQQ.js → chunk-J3SOTUVI.js} +2 -2
  33. package/dist/{chunk-SNTTOQAD.js → chunk-JN6D3MY6.js} +2 -2
  34. package/dist/{chunk-MIVHK5YI.js → chunk-KMRFRXIT.js} +3 -3
  35. package/dist/{chunk-5TB6KLC2.js → chunk-KT7JKOXB.js} +8 -8
  36. package/dist/{chunk-NEZZ6KDR.js → chunk-LBGHI4S2.js} +49 -2
  37. package/dist/chunk-LBGHI4S2.js.map +1 -0
  38. package/dist/{chunk-3XLCNVMD.js → chunk-LEW4QM74.js} +2 -2
  39. package/dist/{chunk-IHIEXUTC.js → chunk-LFEQIZLB.js} +85 -10
  40. package/dist/chunk-LFEQIZLB.js.map +1 -0
  41. package/dist/{chunk-TVN2JVOF.js → chunk-OOVG2KBY.js} +3 -3
  42. package/dist/{chunk-7KD66LIM.js → chunk-OR43364P.js} +3 -3
  43. package/dist/{chunk-J62QSVP6.js → chunk-PBTA3QQX.js} +8 -7
  44. package/dist/{chunk-J62QSVP6.js.map → chunk-PBTA3QQX.js.map} +1 -1
  45. package/dist/{chunk-664Y3NDX.js → chunk-PHW2YV6N.js} +8 -8
  46. package/dist/{chunk-PV4OX5TC.js → chunk-PZTWU277.js} +11 -11
  47. package/dist/{chunk-HJGGNLWI.js → chunk-QD4VOILZ.js} +9 -9
  48. package/dist/{chunk-CNBYCMSU.js → chunk-QJ5UZAH5.js} +27 -18
  49. package/dist/{chunk-CNBYCMSU.js.map → chunk-QJ5UZAH5.js.map} +1 -1
  50. package/dist/{chunk-HQAHNIAR.js → chunk-QK7WUO7A.js} +14 -14
  51. package/dist/{chunk-UJ7XWK7J.js → chunk-QZVKRDJY.js} +16 -14
  52. package/dist/{chunk-UJ7XWK7J.js.map → chunk-QZVKRDJY.js.map} +1 -1
  53. package/dist/{chunk-FZDR7CGH.js → chunk-REO3PXXO.js} +3 -3
  54. package/dist/{chunk-UOCPC2Y2.js → chunk-RVO7L4FX.js} +4 -4
  55. package/dist/{chunk-QXDNBYQF.js → chunk-SZMHCEYV.js} +21 -10
  56. package/dist/chunk-SZMHCEYV.js.map +1 -0
  57. package/dist/chunk-TYRNTSPJ.js +243 -0
  58. package/dist/chunk-TYRNTSPJ.js.map +1 -0
  59. package/dist/{agent-BXRIEKVM.js → chunk-UJ3L2MS7.js} +22 -22
  60. package/dist/chunk-UJ3L2MS7.js.map +1 -0
  61. package/dist/{chunk-37N2RJW2.js → chunk-V7MO5EDS.js} +3 -3
  62. package/dist/{chunk-HEF2RMKN.js → chunk-WB2X37MO.js} +18 -16
  63. package/dist/{chunk-HEF2RMKN.js.map → chunk-WB2X37MO.js.map} +1 -1
  64. package/dist/{chunk-OPNGPUKJ.js → chunk-X44FKNKP.js} +133 -42
  65. package/dist/chunk-X44FKNKP.js.map +1 -0
  66. package/dist/cli.js +43 -40
  67. package/dist/cli.js.map +1 -1
  68. package/dist/{config-MEM2IWWN.js → config-HMFMCY2M.js} +12 -9
  69. package/dist/{conventions-WV4NDXGH.js → conventions-NJF2OPVQ.js} +14 -11
  70. package/dist/{conventions-WV4NDXGH.js.map → conventions-NJF2OPVQ.js.map} +1 -1
  71. package/dist/diagnostics-THH42ZMP.js +23 -0
  72. package/dist/execute-KFNNZZHI.js +35 -0
  73. package/dist/{generate-MVQI7A45.js → generate-FW5C6NP7.js} +23 -20
  74. package/dist/{generate-MVQI7A45.js.map → generate-FW5C6NP7.js.map} +1 -1
  75. package/dist/{git-YRVRUN3C.js → git-W72QQ6GT.js} +4 -2
  76. package/dist/init-HTN4V67Q.js +24 -0
  77. package/dist/{operations-LU6JA3BX.js → operations-BCFOBH42.js} +17 -14
  78. package/dist/{operations-LU6JA3BX.js.map → operations-BCFOBH42.js.map} +1 -1
  79. package/dist/{permissions-7NMDFU27.js → permissions-4AKNQZHK.js} +4 -4
  80. package/dist/plan-SIZLGA4V.js +34 -0
  81. package/dist/{policy-JSYEK5B2.js → policy-DT6Q6ZVM.js} +13 -10
  82. package/dist/{policy-JSYEK5B2.js.map → policy-DT6Q6ZVM.js.map} +1 -1
  83. package/dist/pr-OMWCGUOW.js +39 -0
  84. package/dist/pr-review-N24CZPKR.js +32 -0
  85. package/dist/prd-5OFTZAHJ.js +33 -0
  86. package/dist/{ps-TNE44R5V.js → ps-RFORTCUD.js} +11 -8
  87. package/dist/{ps-TNE44R5V.js.map → ps-RFORTCUD.js.map} +1 -1
  88. package/dist/{recorder-XGF55WXI.js → recorder-KCCPMKQG.js} +5 -4
  89. package/dist/registry-GLPXOMFG.js +15 -0
  90. package/dist/{resume-QMEPMSZW.js → resume-M5RLKP4I.js} +44 -40
  91. package/dist/{resume-QMEPMSZW.js.map → resume-M5RLKP4I.js.map} +1 -1
  92. package/dist/review-YM4JAABY.js +35 -0
  93. package/dist/{routing-2ZUMZPJB.js → routing-NNT5WKGX.js} +13 -10
  94. package/dist/{routing-2ZUMZPJB.js.map → routing-NNT5WKGX.js.map} +1 -1
  95. package/dist/run-PZUKHPQK.js +54 -0
  96. package/dist/run-PZUKHPQK.js.map +1 -0
  97. package/dist/session-publisher-T7EI3CIP.js +11 -0
  98. package/dist/session-publisher-T7EI3CIP.js.map +1 -0
  99. package/dist/{state-manager-X3PT3FGT.js → state-manager-GQH32C44.js} +3 -3
  100. package/dist/state-manager-GQH32C44.js.map +1 -0
  101. package/dist/{usage-VCFLDA5Y.js → usage-V2CHE5PY.js} +13 -10
  102. package/dist/{usage-VCFLDA5Y.js.map → usage-V2CHE5PY.js.map} +1 -1
  103. package/dist/{web-XVHLX62B.js → web-EA3KGNFN.js} +18 -14
  104. package/dist/{web-XVHLX62B.js.map → web-EA3KGNFN.js.map} +1 -1
  105. package/package.json +1 -1
  106. package/web/AGENTS.md +150 -11
  107. package/web/public/app.css +343 -110
  108. package/web/public/app.js +408 -18
  109. package/web/public/index.html +44 -1
  110. package/dist/agent-BXRIEKVM.js.map +0 -1
  111. package/dist/chunk-6FDFRNXZ.js.map +0 -1
  112. package/dist/chunk-ARFVHC2F.js.map +0 -1
  113. package/dist/chunk-IHIEXUTC.js.map +0 -1
  114. package/dist/chunk-IYV6KNVF.js.map +0 -1
  115. package/dist/chunk-KQHB7ZT3.js.map +0 -1
  116. package/dist/chunk-LZ6GFQAG.js.map +0 -1
  117. package/dist/chunk-NEZZ6KDR.js.map +0 -1
  118. package/dist/chunk-OPNGPUKJ.js.map +0 -1
  119. package/dist/chunk-QXDNBYQF.js.map +0 -1
  120. package/dist/chunk-TM67EHSV.js.map +0 -1
  121. package/dist/chunk-TX5WIVYP.js.map +0 -1
  122. package/dist/execute-NITIHHCK.js +0 -31
  123. package/dist/init-OKWEC3EV.js +0 -21
  124. package/dist/plan-LEJJF3DE.js +0 -31
  125. package/dist/pr-HPVUZ7S3.js +0 -36
  126. package/dist/pr-review-R2QZBT3F.js +0 -29
  127. package/dist/prd-5O6GYCC6.js +0 -30
  128. package/dist/registry-LGPE53QD.js +0 -15
  129. package/dist/review-YKWD6SNN.js +0 -32
  130. package/dist/run-YU4TR62R.js +0 -50
  131. /package/dist/{config-MEM2IWWN.js.map → agent-OX3KPHE4.js.map} +0 -0
  132. /package/dist/{chunk-PIVGJM6K.js.map → chunk-2IQ6M4ZE.js.map} +0 -0
  133. /package/dist/{chunk-QCXPNSEL.js.map → chunk-3BWZO4YI.js.map} +0 -0
  134. /package/dist/{chunk-BQDQTIM7.js.map → chunk-BRCNQXYQ.js.map} +0 -0
  135. /package/dist/{chunk-BHJCGWQX.js.map → chunk-F6TOYSYY.js.map} +0 -0
  136. /package/dist/{chunk-DIG5XKQQ.js.map → chunk-J3SOTUVI.js.map} +0 -0
  137. /package/dist/{chunk-SNTTOQAD.js.map → chunk-JN6D3MY6.js.map} +0 -0
  138. /package/dist/{chunk-MIVHK5YI.js.map → chunk-KMRFRXIT.js.map} +0 -0
  139. /package/dist/{chunk-5TB6KLC2.js.map → chunk-KT7JKOXB.js.map} +0 -0
  140. /package/dist/{chunk-3XLCNVMD.js.map → chunk-LEW4QM74.js.map} +0 -0
  141. /package/dist/{chunk-TVN2JVOF.js.map → chunk-OOVG2KBY.js.map} +0 -0
  142. /package/dist/{chunk-7KD66LIM.js.map → chunk-OR43364P.js.map} +0 -0
  143. /package/dist/{chunk-664Y3NDX.js.map → chunk-PHW2YV6N.js.map} +0 -0
  144. /package/dist/{chunk-PV4OX5TC.js.map → chunk-PZTWU277.js.map} +0 -0
  145. /package/dist/{chunk-HJGGNLWI.js.map → chunk-QD4VOILZ.js.map} +0 -0
  146. /package/dist/{chunk-HQAHNIAR.js.map → chunk-QK7WUO7A.js.map} +0 -0
  147. /package/dist/{chunk-FZDR7CGH.js.map → chunk-REO3PXXO.js.map} +0 -0
  148. /package/dist/{chunk-UOCPC2Y2.js.map → chunk-RVO7L4FX.js.map} +0 -0
  149. /package/dist/{chunk-37N2RJW2.js.map → chunk-V7MO5EDS.js.map} +0 -0
  150. /package/dist/{execute-NITIHHCK.js.map → config-HMFMCY2M.js.map} +0 -0
  151. /package/dist/{git-YRVRUN3C.js.map → diagnostics-THH42ZMP.js.map} +0 -0
  152. /package/dist/{init-OKWEC3EV.js.map → execute-KFNNZZHI.js.map} +0 -0
  153. /package/dist/{permissions-7NMDFU27.js.map → git-W72QQ6GT.js.map} +0 -0
  154. /package/dist/{plan-LEJJF3DE.js.map → init-HTN4V67Q.js.map} +0 -0
  155. /package/dist/{pr-HPVUZ7S3.js.map → permissions-4AKNQZHK.js.map} +0 -0
  156. /package/dist/{pr-review-R2QZBT3F.js.map → plan-SIZLGA4V.js.map} +0 -0
  157. /package/dist/{prd-5O6GYCC6.js.map → pr-OMWCGUOW.js.map} +0 -0
  158. /package/dist/{recorder-XGF55WXI.js.map → pr-review-N24CZPKR.js.map} +0 -0
  159. /package/dist/{registry-LGPE53QD.js.map → prd-5OFTZAHJ.js.map} +0 -0
  160. /package/dist/{review-YKWD6SNN.js.map → recorder-KCCPMKQG.js.map} +0 -0
  161. /package/dist/{run-YU4TR62R.js.map → registry-GLPXOMFG.js.map} +0 -0
  162. /package/dist/{state-manager-X3PT3FGT.js.map → review-YM4JAABY.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/bench.ts","../src/benchmark/corpus.ts","../src/benchmark/live.ts","../src/benchmark/real.ts","../src/benchmark/fixtures/materialize.ts","../src/benchmark/fixtures/templates.ts","../src/benchmark/stats.ts","../src/benchmark/tuple.ts","../src/benchmark/report.ts","../src/benchmark/synthetic.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { createInterface } from 'node:readline';\nimport { TASK_CLASSES, type TaskClass } from '../benchmark/corpus.js';\nimport { createLiveRepeatRunner } from '../benchmark/live.js';\nimport { type BenchCampaign, type RepeatRunner, runRealCorpus } from '../benchmark/real.js';\nimport { renderCampaignMarkdown } from '../benchmark/report.js';\nimport { runSyntheticCorpus } from '../benchmark/synthetic.js';\nimport { collectHarnessVersion } from '../benchmark/tuple.js';\nimport { printError, printInfo, printWarning } from '../ui/logger.js';\n\n/** p50 USD from the #79 before table — used only for the pre-flight estimate. */\nexport const BASELINE_COST_P50_USD: Record<TaskClass, number> = {\n trivial: 0.2,\n small: 3.17,\n medium: 6.08,\n analysis: 1.86,\n};\n\nexport class BenchConfirmationError extends Error {\n readonly exitCode = 1;\n constructor(message: string) {\n super(message);\n this.name = 'BenchConfirmationError';\n }\n}\n\nexport interface BenchOptions {\n mode?: 'synthetic' | 'real';\n task?: string[];\n arm?: string[];\n repeats?: number;\n maxCost?: number;\n maxDuration?: number;\n out?: string;\n yes?: boolean;\n repo?: string;\n json?: boolean;\n interactive?: boolean;\n stdin?: NodeJS.ReadableStream;\n stdout?: NodeJS.WritableStream;\n runPipeline?: (issue: string) => Promise<number>;\n runner?: RepeatRunner;\n harnessVersion?: string;\n}\n\nexport function estimateCampaignUsd(tasks: TaskClass[], arms: number, repeats: number): number {\n const perRepeat = tasks.reduce((sum, task) => sum + BASELINE_COST_P50_USD[task], 0);\n return perRepeat * arms * repeats;\n}\n\nfunction isInteractiveByDefault(): 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\nexport async function confirmRealCampaign(\n estimate: { cells: number; repeats: number; usd: number; maxCost?: number; maxDuration?: number },\n options: Pick<BenchOptions, 'yes' | 'interactive' | 'stdin' | 'stdout'> = {},\n): Promise<void> {\n printInfo(\n `Real campaign: ${estimate.cells} cells × ${estimate.repeats} repeats ≈ $${estimate.usd.toFixed(2)} (p50 of the #79 baseline).`,\n );\n if (estimate.maxCost !== undefined) {\n printInfo(`Cost ceiling: $${estimate.maxCost.toFixed(2)}.`);\n }\n if (estimate.maxDuration !== undefined) {\n printInfo(`Duration ceiling: ${estimate.maxDuration}ms.`);\n }\n if (options.yes === true) {\n printInfo('--yes: starting the campaign.');\n return;\n }\n const interactive = options.interactive ?? isInteractiveByDefault();\n if (!interactive) {\n throw new BenchConfirmationError(\n 'A real campaign spends money and the terminal is not interactive. Re-run with --yes.',\n );\n }\n const stdin = options.stdin ?? process.stdin;\n const stdout = options.stdout ?? process.stdout;\n const rl = createInterface({ input: stdin, output: stdout });\n try {\n const answer = await new Promise<string>((resolve) => {\n rl.question('Proceed with a paid campaign? [y/N] ', resolve);\n });\n if (!/^\\s*y(es)?\\s*$/i.test(answer)) {\n throw new BenchConfirmationError('Cancelled: the campaign was not confirmed.');\n }\n } finally {\n rl.close();\n }\n}\n\nfunction parseTasks(values: string[] | undefined): TaskClass[] {\n if (values === undefined || values.length === 0) return [...TASK_CLASSES];\n const tasks: TaskClass[] = [];\n for (const value of values) {\n if (!(TASK_CLASSES as readonly string[]).includes(value)) {\n throw new BenchConfirmationError(\n `Unknown task class '${value}'. Must be one of: ${TASK_CLASSES.join(', ')}.`,\n );\n }\n if (!tasks.includes(value as TaskClass)) tasks.push(value as TaskClass);\n }\n return tasks;\n}\n\nfunction printSynthetic(): void {\n const rows = runSyntheticCorpus();\n printInfo('Synthetic corpus (orchestration only; harness is a number).');\n for (const row of rows) {\n printInfo(\n `${row.task} duration=${row.taskDurationMs.toFixed(1)}ms overhead=${row.orchestrationOverheadMs.toFixed(1)}ms verdict=${row.verdict}`,\n );\n }\n}\n\nexport async function runBench(options: BenchOptions = {}): Promise<number> {\n const mode = options.mode ?? 'synthetic';\n if (mode !== 'synthetic' && mode !== 'real') {\n printError(`Unknown bench mode '${mode}'. Use synthetic or real.`);\n return 1;\n }\n if (mode === 'synthetic') {\n printSynthetic();\n return 0;\n }\n if (options.repo !== undefined) {\n printWarning(\n '--repo is an investigation escape: the row is not publishable. A disposable fixture is the only source of a comparable line.',\n );\n }\n\n let tasks: TaskClass[];\n try {\n tasks = parseTasks(options.task);\n } catch (error) {\n printError(error instanceof Error ? error.message : String(error));\n return 1;\n }\n const arms = options.arm !== undefined && options.arm.length > 0 ? options.arm : ['baseline'];\n const repeats = options.repeats ?? 5;\n const usd = estimateCampaignUsd(tasks, arms.length, repeats);\n\n try {\n await confirmRealCampaign(\n {\n cells: tasks.length * arms.length,\n repeats,\n usd,\n ...(options.maxCost === undefined ? {} : { maxCost: options.maxCost }),\n ...(options.maxDuration === undefined ? {} : { maxDuration: options.maxDuration }),\n },\n options,\n );\n } catch (error) {\n if (error instanceof BenchConfirmationError) {\n printError(error.message);\n return error.exitCode;\n }\n throw error;\n }\n\n const harnessVersion = options.harnessVersion ?? (await collectHarnessVersion('claude'));\n const runner =\n options.runner ??\n createLiveRepeatRunner({\n runPipeline:\n options.runPipeline ??\n (async (issue) => {\n const { runPipeline } = await import('./run.js');\n return runPipeline(issue, 'auto', undefined, true, false, { yes: true, only: true });\n }),\n });\n\n const campaign: BenchCampaign = await runRealCorpus({\n tasks,\n arms,\n repeats,\n tupleBase: {\n harness: 'claude',\n harnessVersion,\n model: 'default',\n modelVersion: null,\n effort: 'default',\n verification: 'none',\n strategy: 'pipeline',\n settingSourcesPinned: true,\n fallbackModelPassed: false,\n },\n ...(options.maxCost === undefined ? {} : { maxCostUsd: options.maxCost }),\n ...(options.maxDuration === undefined ? {} : { maxDurationMs: options.maxDuration }),\n runner,\n });\n\n if (campaign.stop.reason !== 'completed') {\n printWarning(\n `Campaign stopped on ${campaign.stop.reason} (spent ${campaign.stop.spent}, ceiling ${campaign.stop.ceiling}). Report is partial.`,\n );\n }\n\n const markdown = renderCampaignMarkdown(campaign, arms.join('-vs-'));\n if (options.out) {\n await mkdir(dirname(options.out), { recursive: true });\n await writeFile(options.out, markdown, 'utf-8');\n printInfo(`Wrote ${options.out}`);\n } else {\n (options.stdout ?? process.stdout).write(markdown);\n }\n if (options.json === true) {\n (options.stdout ?? process.stdout).write(`${JSON.stringify(campaign, null, 2)}\\n`);\n }\n return campaign.stop.reason === 'completed' ? 0 : 2;\n}\n","export const TASK_CLASSES = ['trivial', 'small', 'medium', 'analysis'] as const;\n\nexport type TaskClass = (typeof TASK_CLASSES)[number];\n\nexport interface CorpusTask {\n id: TaskClass;\n title: string;\n /** What a fixture repository should contain. */\n fixture: string;\n verification: 'none' | 'existing-tests' | 'tests-and-docs' | 'artifact-only';\n strategy: 'direct' | 'pipeline';\n}\n\n/**\n * Four representative tasks. The synthetic runner never opens a real repo;\n * `real` mode materializes a disposable git fixture per repetition via\n * `fixtures/materialize.ts`. `--repo` is an investigation escape and does\n * not produce a publishable row.\n */\nexport const CORPUS: readonly CorpusTask[] = [\n {\n id: 'trivial',\n title: 'Change one constant and its comment',\n fixture: '1–2 files, no test change',\n verification: 'none',\n strategy: 'direct',\n },\n {\n id: 'small',\n title: 'Fix a failing assertion in an existing test',\n fixture: 'correction against tests that already exist',\n verification: 'existing-tests',\n strategy: 'pipeline',\n },\n {\n id: 'medium',\n title: 'Add a function, tests and a README note',\n fixture: 'implementation plus tests plus documentation',\n verification: 'tests-and-docs',\n strategy: 'pipeline',\n },\n {\n id: 'analysis',\n title: 'Read the tree and write a short report',\n fixture: 'read-only artifact, no implementation',\n verification: 'artifact-only',\n strategy: 'direct',\n },\n];\n\nexport const BENCH_AXES = [\n 'task',\n 'harness',\n 'model',\n 'effort',\n 'verification',\n 'strategy',\n] as const;\n","import { setIssuesCliOverrides } from '../config.js';\nimport { loadTaskPlan } from '../core/state-manager.js';\nimport { GLOBAL_ROOT_ENV } from '../storage/paths.js';\nimport { resetStorageResolutionCache, resolveIssuePaths } from '../storage/resolve.js';\nimport { runAcceptance } from '../verify/run-issue.js';\nimport type { RepeatOutcome, RepeatRunner, RepeatRunnerInput } from './real.js';\n\n/**\n * Live repeats spend money. Unit tests must never take this path.\n * The only escape is an explicit `ISSUE_FLOW_E2E_BENCH=1`, matching the\n * `#80` Antigravity e2e gate.\n */\nexport function assertLiveBenchAllowed(env: NodeJS.ProcessEnv = process.env): void {\n if (env.VITEST && env.ISSUE_FLOW_E2E_BENCH !== '1') {\n throw new Error(\n 'issue-flow bench --mode real does not run under npm test. Set ISSUE_FLOW_E2E_BENCH=1 for a deliberate live campaign.',\n );\n }\n}\n\nexport interface LiveRepeatDeps {\n runPipeline: (issue: string) => Promise<number>;\n}\n\n/**\n * Isolate one repetition: own ISSUE_FLOW_HOME, local issues, no GitHub,\n * `--setting-sources` pinned, `--fallback-model` never passed.\n */\nexport function createLiveRepeatRunner(deps: LiveRepeatDeps): RepeatRunner {\n return async (input: RepeatRunnerInput): Promise<RepeatOutcome> => {\n assertLiveBenchAllowed();\n const previousHome = process.env[GLOBAL_ROOT_ENV];\n const previousCwd = process.cwd();\n process.env[GLOBAL_ROOT_ENV] = input.campaignHome;\n resetStorageResolutionCache();\n setIssuesCliOverrides({ preferredProvider: 'local' });\n process.chdir(input.fixture.root);\n const started = performance.now();\n try {\n await deps.runPipeline(input.fixture.issueRef);\n const paths = await resolveIssuePaths(input.fixture.issueRef, {\n projectRoot: input.fixture.root,\n });\n const plan = await loadTaskPlan(paths.tasksFile);\n const records = plan.executions ?? [];\n const acceptance = await runAcceptance({\n cwd: input.fixture.root,\n issueDir: paths.issueDir,\n declared: input.fixture.expectedVerification,\n executionId: records.at(-1)?.id ?? null,\n skipReviewer: input.arm !== 'L2',\n explicit: input.arm === 'L2',\n });\n const wall = performance.now() - started;\n const harness = records.reduce((sum, record) => sum + (record.durationMs ?? 0), 0);\n const reported = records.flatMap((record) =>\n record.cost.status === 'reported' ? [record.cost.amount] : [],\n );\n const cost =\n reported.length > 0\n ? {\n status: 'reported' as const,\n amount: reported.reduce((sum, amount) => sum + amount, 0),\n currency: 'USD' as const,\n }\n : ({ status: 'unknown' as const, reason: 'not_reported' as const } as const);\n return {\n records,\n verdict: acceptance.verdict,\n taskDurationMs: wall,\n harnessExecutionMs: harness,\n orchestrationOverheadMs: Math.max(0, wall - harness),\n attemptCount: records.reduce((max, record) => Math.max(max, record.attempt), 0) || 1,\n cost,\n };\n } finally {\n process.chdir(previousCwd);\n if (previousHome === undefined) delete process.env[GLOBAL_ROOT_ENV];\n else process.env[GLOBAL_ROOT_ENV] = previousHome;\n resetStorageResolutionCache();\n setIssuesCliOverrides({});\n }\n };\n}\n","import { mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { evaluateCeilings, spendFromCost } from '../routing/budget.js';\nimport { getGlobalRoot } from '../storage/paths.js';\nimport type { CostRecord, ExecutionRecord } from '../telemetry/types.js';\nimport type { VerdictStatus } from '../verify/types.js';\nimport { CORPUS, type TaskClass } from './corpus.js';\nimport { corpusTask, type FixtureHandle, materialize } from './fixtures/index.js';\nimport { p50, p95 } from './stats.js';\nimport {\n assertComparable,\n type ComparabilityTuple,\n isRowInvalid,\n type TupleField,\n tupleAxisForArm,\n} from './tuple.js';\n\nexport interface BenchRepeat {\n seed: number;\n taskDurationMs: number;\n harnessExecutionMs: number;\n orchestrationOverheadMs: number;\n timeToAcceptedResultMs: number | null;\n verdict: VerdictStatus;\n cost: CostRecord;\n attemptCount: number;\n executionIds: string[];\n invalid: boolean;\n}\n\nexport interface BenchCell {\n task: TaskClass;\n tuple: ComparabilityTuple;\n arm: string;\n repeats: BenchRepeat[];\n}\n\nexport interface PercentilePair {\n p50: number;\n p95: number;\n n: number;\n}\n\nexport interface CellSummary {\n n: number;\n taskDurationMs: PercentilePair;\n harnessExecutionMs: PercentilePair;\n orchestrationOverheadMs: PercentilePair;\n timeToAcceptedResultMs: { p50: number | null; p95: number | null; n: number };\n cost: {\n reportedP50: number | null;\n reportedP95: number | null;\n unknownRepeats: number;\n estimatedRepeats: number;\n };\n verdicts: Record<VerdictStatus, number>;\n}\n\nexport type CampaignStop =\n | { reason: 'completed' }\n | { reason: 'max_cost' | 'max_duration'; spent: number; ceiling: number; partial: true };\n\nexport interface BenchCampaign {\n id: string;\n home: string;\n cells: BenchCell[];\n stop: CampaignStop;\n}\n\nexport interface RepeatOutcome {\n records: ExecutionRecord[];\n verdict: VerdictStatus;\n taskDurationMs: number;\n harnessExecutionMs: number;\n orchestrationOverheadMs: number;\n attemptCount: number;\n cost: CostRecord;\n}\n\nexport interface RepeatRunnerInput {\n fixture: FixtureHandle;\n arm: string;\n tuple: ComparabilityTuple;\n campaignHome: string;\n}\n\nexport type RepeatRunner = (input: RepeatRunnerInput) => Promise<RepeatOutcome>;\n\nexport interface RealCorpusOptions {\n tasks?: TaskClass[];\n arms: string[];\n repeats: number;\n tupleBase: Omit<ComparabilityTuple, 'task' | 'strictMcpConfig' | 'fallbackModelPassed'> & {\n strictMcpConfig?: boolean;\n fallbackModelPassed?: boolean;\n };\n maxCostUsd?: number;\n maxDurationMs?: number;\n campaignId?: string;\n runner: RepeatRunner;\n now?: () => number;\n env?: NodeJS.ProcessEnv;\n}\n\nexport function campaignHome(campaignId: string, env?: NodeJS.ProcessEnv): string {\n return join(getGlobalRoot({ env }), 'bench', campaignId);\n}\n\nfunction combineCost(records: readonly ExecutionRecord[]): CostRecord {\n let reported = 0;\n let estimated = 0;\n let unknown = 0;\n for (const record of records) {\n if (record.cost.status === 'reported') reported += record.cost.amount;\n else if (record.cost.status === 'estimated') estimated += record.cost.amount;\n else unknown += 1;\n }\n if (reported > 0) return { status: 'reported', amount: reported, currency: 'USD' };\n if (estimated > 0) {\n return {\n status: 'estimated',\n amount: estimated,\n currency: 'USD',\n pricing: {\n tableVersion: 'bench',\n modelKey: 'aggregated',\n inputPerMillion: 0,\n outputPerMillion: 0,\n capturedAt: new Date(0).toISOString(),\n },\n };\n }\n return { status: 'unknown', reason: unknown > 0 ? 'not_reported' : 'not_reported' };\n}\n\nexport function summarizeCell(cell: BenchCell): CellSummary {\n const durations = cell.repeats.map((repeat) => repeat.taskDurationMs);\n const harness = cell.repeats.map((repeat) => repeat.harnessExecutionMs);\n const overhead = cell.repeats.map((repeat) => repeat.orchestrationOverheadMs);\n const accepted = cell.repeats\n .map((repeat) => repeat.timeToAcceptedResultMs)\n .filter((value): value is number => value !== null);\n const reported = cell.repeats\n .map((repeat) => (repeat.cost.status === 'reported' ? repeat.cost.amount : null))\n .filter((value): value is number => value !== null);\n const verdicts: Record<VerdictStatus, number> = { passed: 0, failed: 0, unverified: 0 };\n let unknownRepeats = 0;\n let estimatedRepeats = 0;\n for (const repeat of cell.repeats) {\n verdicts[repeat.verdict] += 1;\n if (repeat.cost.status === 'unknown') unknownRepeats += 1;\n if (repeat.cost.status === 'estimated') estimatedRepeats += 1;\n }\n return {\n n: cell.repeats.length,\n taskDurationMs: { p50: p50(durations), p95: p95(durations), n: durations.length },\n harnessExecutionMs: { p50: p50(harness), p95: p95(harness), n: harness.length },\n orchestrationOverheadMs: { p50: p50(overhead), p95: p95(overhead), n: overhead.length },\n timeToAcceptedResultMs: {\n p50: accepted.length === 0 ? null : p50(accepted),\n p95: accepted.length === 0 ? null : p95(accepted),\n n: accepted.length,\n },\n cost: {\n reportedP50: reported.length === 0 ? null : p50(reported),\n reportedP95: reported.length === 0 ? null : p95(reported),\n unknownRepeats,\n estimatedRepeats,\n },\n verdicts,\n };\n}\n\nfunction tupleForArm(\n task: TaskClass,\n arm: string,\n base: RealCorpusOptions['tupleBase'],\n): ComparabilityTuple {\n return {\n task,\n harness: base.harness,\n harnessVersion: base.harnessVersion,\n model: base.model,\n modelVersion: base.modelVersion,\n effort: base.effort,\n verification: base.verification,\n strategy: base.strategy,\n settingSourcesPinned: base.settingSourcesPinned,\n strictMcpConfig: arm === 'strict-mcp' ? true : (base.strictMcpConfig ?? false),\n fallbackModelPassed: base.fallbackModelPassed ?? false,\n };\n}\n\nfunction declaredIgnore(arms: readonly string[]): TupleField[] {\n const fields = new Set<TupleField>();\n for (const arm of arms) {\n const axis = tupleAxisForArm(arm);\n if (axis) fields.add(axis);\n }\n return [...fields];\n}\n\n/**\n * Run the real corpus. Arms are a parameter: new experiments do not add\n * runner code. Repeats of different arms are interleaved, not blocked.\n */\nexport async function runRealCorpus(options: RealCorpusOptions): Promise<BenchCampaign> {\n const tasks = options.tasks ?? CORPUS.map((entry) => entry.id);\n const campaignId = options.campaignId ?? `campaign-${Date.now()}`;\n const home = campaignHome(campaignId, options.env);\n await mkdir(home, { recursive: true });\n\n const cells = new Map<string, BenchCell>();\n const ignore = declaredIgnore(options.arms);\n const now = options.now ?? Date.now;\n const started = now();\n let reportedUsd = 0;\n let knownCost: CostRecord['status'] = 'unknown';\n let stop: CampaignStop = { reason: 'completed' };\n\n const schedule: Array<{ task: TaskClass; arm: string; seed: number }> = [];\n for (let seed = 0; seed < options.repeats; seed += 1) {\n for (const arm of options.arms) {\n for (const task of tasks) {\n schedule.push({ task, arm, seed });\n }\n }\n }\n\n for (const step of schedule) {\n const task = corpusTask(step.task);\n const tuple = tupleForArm(step.task, step.arm, {\n ...options.tupleBase,\n verification: task.verification,\n strategy: task.strategy,\n });\n const key = `${step.task}:${step.arm}`;\n const existing = cells.get(key);\n if (existing) {\n assertComparable(existing.tuple, tuple, { ignore });\n } else {\n for (const cell of cells.values()) {\n if (cell.task !== step.task) continue;\n assertComparable(cell.tuple, tuple, { ignore });\n }\n cells.set(key, { task: step.task, tuple, arm: step.arm, repeats: [] });\n }\n\n const fixture = await materialize(task, step.seed);\n try {\n const outcome = await options.runner({\n fixture,\n arm: step.arm,\n tuple,\n campaignHome: home,\n });\n const cost = outcome.cost.status !== undefined ? outcome.cost : combineCost(outcome.records);\n const spent = spendFromCost(cost);\n if (spent.costStatus === 'reported') {\n reportedUsd += spent.reportedUsd;\n knownCost = 'reported';\n }\n const cell = cells.get(key);\n if (!cell) throw new Error(`missing cell ${key}`);\n cell.repeats.push({\n seed: step.seed,\n taskDurationMs: outcome.taskDurationMs,\n harnessExecutionMs: outcome.harnessExecutionMs,\n orchestrationOverheadMs: outcome.orchestrationOverheadMs,\n timeToAcceptedResultMs: outcome.verdict === 'passed' ? outcome.taskDurationMs : null,\n verdict: outcome.verdict,\n cost,\n attemptCount: outcome.attemptCount,\n executionIds: outcome.records.map((record) => record.id),\n invalid: isRowInvalid(tuple),\n });\n } finally {\n await fixture.dispose();\n }\n\n const ceiling = evaluateCeilings({\n ceilings: {\n maxCostUsdPerIssue: options.maxCostUsd ?? null,\n maxDurationMsPerIssue: options.maxDurationMs ?? null,\n maxExecutionsPerIssue: null,\n onCeiling: 'block',\n },\n spent: {\n reportedUsd,\n costStatus: knownCost,\n durationMs: now() - started,\n executions: [...cells.values()].reduce((sum, cell) => sum + cell.repeats.length, 0),\n },\n });\n if (!ceiling.ok) {\n stop = {\n reason: ceiling.stopReason === 'max_attempts' ? 'max_duration' : ceiling.stopReason,\n spent: ceiling.numbers.spent,\n ceiling: ceiling.numbers.ceiling,\n partial: true,\n };\n break;\n }\n }\n\n return { id: campaignId, home, cells: [...cells.values()], stop };\n}\n","import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { ISSUES_DIR_NAME } from '../../storage/paths.js';\nimport { run } from '../../utils/shell.js';\nimport type { AcceptanceCheck } from '../../verify/types.js';\nimport type { CorpusTask } from '../corpus.js';\nimport { CORPUS } from '../corpus.js';\nimport { templateFor } from './templates.js';\n\nexport interface FixtureHandle {\n root: string;\n issueRef: string;\n expectedVerification: AcceptanceCheck[];\n seed: number;\n task: CorpusTask['id'];\n dispose(): Promise<void>;\n}\n\nconst GIT_IDENT = ['-c', 'user.name=issue-flow-bench', '-c', 'user.email=bench@issue-flow.test'];\n\nasync function git(cwd: string, args: string[]): Promise<void> {\n const result = await run('git', args, { cwd });\n if (result.exitCode !== 0) {\n throw new Error(\n `git ${args.join(' ')} failed (${result.exitCode}): ${result.stderr || result.stdout}`,\n );\n }\n}\n\nasync function writeTree(root: string, files: Record<string, string>): Promise<void> {\n for (const [relative, content] of Object.entries(files)) {\n const path = join(root, relative);\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content, 'utf-8');\n }\n}\n\nasync function writeLocalIssue(root: string, title: string, body: string): Promise<void> {\n const issueDir = join(root, ISSUES_DIR_NAME, '1');\n await mkdir(issueDir, { recursive: true });\n await writeFile(join(issueDir, 'issue.md'), `# ${title}\\n\\n${body.trim()}\\n`, 'utf-8');\n await writeFile(\n join(issueDir, 'metadata.json'),\n `${JSON.stringify(\n {\n schemaVersion: 1,\n id: '1',\n number: 1,\n source: 'local',\n title,\n labels: ['bench'],\n state: 'open',\n createdAt: '2026-08-30T00:00:00.000Z',\n updatedAt: '2026-08-30T00:00:00.000Z',\n contentHash: 'sha256:fixture',\n },\n null,\n 2,\n )}\\n`,\n 'utf-8',\n );\n}\n\n/**\n * Materialize a disposable git repository for one corpus class and one seed.\n * A new call always starts from the same unfinished state — never from the\n * work of a previous repetition.\n */\nexport async function materialize(task: CorpusTask, seed: number): Promise<FixtureHandle> {\n const root = await mkdtemp(join(tmpdir(), `issue-flow-bench-${task.id}-${seed}-`));\n const template = templateFor(task.id, seed);\n await writeTree(root, template.files);\n await writeLocalIssue(root, template.issueTitle, template.issueBody);\n\n // An empty template skips sample hooks. Some sandboxes forbid writing\n // executable files under `.git/hooks/`.\n await git(root, ['-c', 'init.templateDir=', 'init']);\n await git(root, ['add', '.']);\n await git(root, [...GIT_IDENT, 'commit', '-m', `fixture ${task.id} seed=${seed}`]);\n\n return {\n root,\n issueRef: '1',\n expectedVerification: template.expectedVerification,\n seed,\n task: task.id,\n async dispose() {\n await rm(root, { recursive: true, force: true });\n },\n };\n}\n\nexport function corpusTask(id: CorpusTask['id']): CorpusTask {\n const task = CORPUS.find((entry) => entry.id === id);\n if (!task) throw new Error(`Unknown corpus class: ${id}`);\n return task;\n}\n","import type { AcceptanceCheck } from '../../verify/types.js';\nimport type { TaskClass } from '../corpus.js';\n\nexport interface FixtureTemplate {\n files: Record<string, string>;\n issueTitle: string;\n issueBody: string;\n expectedVerification: AcceptanceCheck[];\n}\n\nfunction withSeed(content: string, seed: number): string {\n return `${content}\\n// fixture-seed:${seed}\\n`;\n}\n\nexport function templateFor(task: TaskClass, seed: number): FixtureTemplate {\n switch (task) {\n case 'trivial':\n return {\n files: {\n 'src/answer.js': withSeed(\n [\n '/** The answer to life, the universe and everything. */',\n 'export const ANSWER = 41;',\n ].join('\\n'),\n seed,\n ),\n },\n issueTitle: 'Change one constant and its comment',\n issueBody: [\n 'Change `ANSWER` in `src/answer.js` from 41 to 42.',\n 'Update the comment so it no longer claims the wrong value.',\n 'Do not add tests.',\n ].join('\\n'),\n expectedVerification: [],\n };\n case 'small':\n return {\n files: {\n 'src/sum.js': withSeed('export function sum(a, b) {\\n return a - b;\\n}\\n', seed),\n 'src/sum.test.js': [\n \"import { sum } from './sum.js';\",\n \"import assert from 'node:assert/strict';\",\n 'assert.equal(sum(2, 2), 4);',\n '',\n ].join('\\n'),\n 'package.json': `${JSON.stringify({ name: 'bench-small', type: 'module', scripts: { test: 'node src/sum.test.js' } }, null, 2)}\\n`,\n },\n issueTitle: 'Fix a failing assertion in an existing test',\n issueBody: [\n '`src/sum.test.js` fails because `sum` subtracts instead of adding.',\n 'Fix `src/sum.js` so `node src/sum.test.js` exits 0.',\n 'Do not change the test.',\n ].join('\\n'),\n expectedVerification: [{ id: 'existing-tests', run: 'node src/sum.test.js', fatal: true }],\n };\n case 'medium':\n return {\n files: {\n 'src/greet.js': withSeed('// greet(name) is not implemented yet.\\n', seed),\n 'src/greet.test.js': [\n \"import { greet } from './greet.js';\",\n \"import assert from 'node:assert/strict';\",\n \"assert.equal(greet('Ada'), 'Hello, Ada');\",\n '',\n ].join('\\n'),\n 'README.md': ['# bench-medium', '', 'A tiny library.', ''].join('\\n'),\n 'package.json': `${JSON.stringify({ name: 'bench-medium', type: 'module', scripts: { test: 'node src/greet.test.js' } }, null, 2)}\\n`,\n },\n issueTitle: 'Add a function, tests and a README note',\n issueBody: [\n 'Implement `greet(name)` in `src/greet.js` so it returns Hello, <name>.',\n 'Keep `src/greet.test.js` as the contract.',\n 'Add an `## API` section to `README.md` documenting `greet`.',\n ].join('\\n'),\n expectedVerification: [\n { id: 'tests', run: 'node src/greet.test.js', fatal: true },\n { id: 'docs', expectFiles: ['README.md'], fatal: true },\n ],\n };\n case 'analysis':\n return {\n files: {\n 'src/alpha.js': withSeed('export const ALPHA = 1;\\n', seed),\n 'src/beta.js': withSeed(\n \"import { ALPHA } from './alpha.js';\\nexport const BETA = ALPHA + 1;\\n\",\n seed,\n ),\n 'src/gamma.js': withSeed(\n \"import { BETA } from './beta.js';\\nexport const GAMMA = BETA + 1;\\n\",\n seed,\n ),\n },\n issueTitle: 'Read the tree and write a short report',\n issueBody: [\n 'Read `src/` and write `report.md` describing the module graph.',\n 'Do not change the source files.',\n ].join('\\n'),\n expectedVerification: [{ id: 'artifact', expectFiles: ['report.md'], fatal: true }],\n };\n default: {\n const _exhaustive: never = task;\n throw new Error(`Unknown corpus class: ${_exhaustive}`);\n }\n }\n}\n","/** Shared percentiles. Used by both the synthetic CI guard and the real campaign. */\n\nfunction percentile(values: number[], p: number): number {\n const sorted = [...values].sort((a, b) => a - b);\n if (sorted.length === 0) return 0;\n const index = Math.min(sorted.length - 1, Math.ceil((p / 100) * sorted.length) - 1);\n return sorted[index] ?? 0;\n}\n\nexport function p50(values: number[]): number {\n return percentile(values, 50);\n}\n\nexport function p95(values: number[]): number {\n return percentile(values, 95);\n}\n","import { ensureHarnessVersion } from '../agents/registry.js';\nimport type { AgentProviderId } from '../agents/types.js';\nimport type { TaskClass } from './corpus.js';\n\nexport interface ComparabilityTuple {\n task: TaskClass;\n harness: string;\n harnessVersion: string;\n model: string;\n modelVersion: string | null;\n effort: string;\n verification: string;\n strategy: 'direct' | 'pipeline';\n settingSourcesPinned: boolean;\n strictMcpConfig: boolean;\n fallbackModelPassed: boolean;\n}\n\nexport type TupleField = keyof ComparabilityTuple;\n\nexport const TUPLE_FIELDS: readonly TupleField[] = [\n 'task',\n 'harness',\n 'harnessVersion',\n 'model',\n 'modelVersion',\n 'effort',\n 'verification',\n 'strategy',\n 'settingSourcesPinned',\n 'strictMcpConfig',\n 'fallbackModelPassed',\n] as const;\n\nexport class ComparabilityError extends Error {\n readonly field: TupleField;\n readonly left: unknown;\n readonly right: unknown;\n\n constructor(field: TupleField, left: unknown, right: unknown) {\n super(`ComparabilityTuple.${field} differs: ${String(left)} vs ${String(right)}`);\n this.name = 'ComparabilityError';\n this.field = field;\n this.left = left;\n this.right = right;\n }\n}\n\n/**\n * Two cells may be compared only when every field matches, except axes the\n * experiment declared (the arm). A silent mismatch is a bug.\n */\nexport function assertComparable(\n left: ComparabilityTuple,\n right: ComparabilityTuple,\n options: { ignore?: readonly TupleField[] } = {},\n): void {\n const ignored = new Set(options.ignore ?? []);\n for (const field of TUPLE_FIELDS) {\n if (ignored.has(field)) continue;\n if (left[field] !== right[field]) {\n throw new ComparabilityError(field, left[field], right[field]);\n }\n }\n}\n\n/** `--fallback-model` present means the measured model is not the one that ran. */\nexport function isRowInvalid(tuple: ComparabilityTuple): boolean {\n return tuple.fallbackModelPassed || !tuple.settingSourcesPinned;\n}\n\n/** Collect at campaign time. Never assume a version from a document. */\nexport async function collectHarnessVersion(provider: AgentProviderId): Promise<string> {\n const version = await ensureHarnessVersion(provider);\n return version ?? 'unknown';\n}\n\nexport function tupleAxisForArm(arm: string): TupleField | null {\n if (arm === 'strict-mcp') return 'strictMcpConfig';\n return null;\n}\n","import { hostname } from 'node:os';\nimport { getGlobalRoot } from '../storage/paths.js';\nimport { redactSecrets } from '../telemetry/redact.js';\nimport type { BenchCampaign, CellSummary } from './real.js';\nimport { summarizeCell } from './real.js';\nimport type { ComparabilityTuple } from './tuple.js';\n\nfunction formatMs(value: number | null): string {\n return value === null ? '—' : `${Math.round(value)}`;\n}\n\nfunction formatUsd(value: number | null): string {\n return value === null ? '—' : `$${value.toFixed(2)}`;\n}\n\nfunction tupleLine(tuple: ComparabilityTuple): string {\n return [\n tuple.task,\n tuple.harness,\n tuple.harnessVersion,\n tuple.model,\n tuple.modelVersion ?? '—',\n tuple.effort,\n tuple.verification,\n tuple.strategy,\n tuple.settingSourcesPinned ? 'setting-sources:pinned' : 'setting-sources:unpinned',\n tuple.strictMcpConfig ? 'strict-mcp' : 'mcp:default',\n tuple.fallbackModelPassed ? 'INVALID:fallback-model' : 'fallback:none',\n ].join(' × ');\n}\n\nfunction verdictCounts(summary: CellSummary): string {\n return `passed=${summary.verdicts.passed} failed=${summary.verdicts.failed} unverified=${summary.verdicts.unverified}`;\n}\n\nfunction scrubPaths(text: string): string {\n const home = getGlobalRoot();\n return text.split(home).join('<issue-flow-home>');\n}\n\nexport function renderCampaignMarkdown(campaign: BenchCampaign, subject: string): string {\n const lines: string[] = [\n `# Harness campaign — ${subject}`,\n '',\n `> **Research document.** Campaign \\`${campaign.id}\\`.`,\n `> Machine: \\`${hostname()}\\`. Node ${process.version}.`,\n campaign.stop.reason === 'completed'\n ? '> Status: complete.'\n : `> Status: **partial** — stopped on \\`${campaign.stop.reason}\\` (spent ${campaign.stop.spent}, ceiling ${campaign.stop.ceiling}). Results below are the repeats that finished; they are not a silently truncated table.`,\n '',\n '`time-to-accepted-result` is null when the verdict is not `passed`. Cost `unknown` is never summed as zero.',\n '',\n '## Cells',\n '',\n '| Task | Arm | n | duration p50/p95 (ms) | harness p50/p95 | overhead p50/p95 | accepted p50/p95 | cost p50/p95 | verdicts | invalid |',\n '|---|---|---:|---|---|---|---|---|---|---|',\n ];\n\n for (const cell of campaign.cells) {\n const summary = summarizeCell(cell);\n const invalid = cell.repeats.some((repeat) => repeat.invalid);\n lines.push(\n `| ${cell.task} | ${cell.arm} | ${summary.n} | ${formatMs(summary.taskDurationMs.p50)} / ${formatMs(summary.taskDurationMs.p95)} | ${formatMs(summary.harnessExecutionMs.p50)} / ${formatMs(summary.harnessExecutionMs.p95)} | ${formatMs(summary.orchestrationOverheadMs.p50)} / ${formatMs(summary.orchestrationOverheadMs.p95)} | ${formatMs(summary.timeToAcceptedResultMs.p50)} / ${formatMs(summary.timeToAcceptedResultMs.p95)} | ${formatUsd(summary.cost.reportedP50)} / ${formatUsd(summary.cost.reportedP95)} | ${verdictCounts(summary)} | ${invalid ? 'yes' : 'no'} |`,\n );\n }\n\n lines.push('', '## Comparability tuples', '');\n for (const cell of campaign.cells) {\n lines.push(`- **${cell.task} / ${cell.arm}**: \\`${tupleLine(cell.tuple)}\\``);\n }\n lines.push('');\n return redactSecrets(scrubPaths(lines.join('\\n')));\n}\n","import {\n createInitialSnapshot,\n reduceSessionEvent,\n type SessionEvent,\n} from '../core/session-state.js';\nimport { sessionSnapshotSchema } from '../schemas.js';\nimport { summarizePhaseTiming } from '../telemetry/timing.js';\nimport type { ExecutionRecord } from '../telemetry/types.js';\nimport { CORPUS } from './corpus.js';\nimport { p50, p95 } from './stats.js';\n\nexport { p50, p95 };\n\n/** Derived from the #79 investigation: orchestration must stay a rounding error. */\nexport const SYNTHETIC_BUDGETS = {\n /** p95 of reducing a short scripted run, in milliseconds. */\n reduceP95Ms: 50,\n /** p95 of parsing a snapshot through the lockstep schema. */\n parseP95Ms: 20,\n} as const;\n\nexport interface SyntheticResult {\n task: string;\n mode: 'synthetic';\n harness: 'mocked';\n model: 'none';\n effort: 'none';\n verification: string;\n strategy: string;\n taskDurationMs: number;\n harnessExecutionDurationMs: number;\n orchestrationOverheadMs: number;\n timeToFirstOutputMs: number | null;\n attemptCount: number;\n retryDurationMs: number;\n verdict: 'unverified';\n}\n\nfunction scriptedEvents(): SessionEvent[] {\n return [\n {\n type: 'session:start',\n at: '2026-08-30T03:00:00.000Z',\n sessionId: 'bench',\n issueNumber: 79,\n phases: ['prd', 'execute'],\n },\n { type: 'phase:start', at: '2026-08-30T03:00:01.000Z', phase: 'prd' },\n {\n type: 'phase:end',\n at: '2026-08-30T03:00:02.000Z',\n phase: 'prd',\n success: true,\n harnessExecutionMs: 800,\n orchestrationOverheadMs: 200,\n },\n { type: 'phase:start', at: '2026-08-30T03:00:02.000Z', phase: 'execute' },\n {\n type: 'phase:end',\n at: '2026-08-30T03:00:03.000Z',\n phase: 'execute',\n success: true,\n harnessExecutionMs: 900,\n orchestrationOverheadMs: 100,\n attemptCount: 1,\n },\n { type: 'session:end', at: '2026-08-30T03:00:03.000Z', status: 'completed' },\n ];\n}\n\nexport function reduceScriptedRun(): ReturnType<typeof reduceSessionEvent> {\n let snap = createInitialSnapshot();\n for (const event of scriptedEvents()) {\n snap = reduceSessionEvent(snap, event);\n }\n return snap;\n}\n\nexport function timeReduce(repeats = 20): number[] {\n const samples: number[] = [];\n for (let i = 0; i < repeats; i += 1) {\n const start = performance.now();\n reduceScriptedRun();\n samples.push(performance.now() - start);\n }\n return samples;\n}\n\nexport function timeParse(repeats = 20): number[] {\n const snap = reduceScriptedRun();\n const samples: number[] = [];\n for (let i = 0; i < repeats; i += 1) {\n const start = performance.now();\n sessionSnapshotSchema.parse(snap);\n samples.push(performance.now() - start);\n }\n return samples;\n}\n\nfunction mockedRecord(durationMs: number): ExecutionRecord {\n return {\n id: 'synthetic',\n sessionId: 'bench',\n purpose: 'execute',\n attempt: 1,\n trigger: 'initial',\n triggerReason: null,\n agent: {\n harness: 'mocked',\n provider: null,\n model: { requested: null, resolved: null, source: 'unavailable' },\n providerSessionId: null,\n },\n startedAt: '2026-08-30T03:00:00.000Z',\n finishedAt: '2026-08-30T03:00:01.000Z',\n durationMs,\n cliDurationMs: Math.max(0, durationMs - 5),\n harnessStartupMs: 5,\n ttftMs: null,\n usage: { source: 'unavailable' },\n cost: { status: 'unknown', reason: 'not_reported' },\n status: 'completed',\n failure: null,\n };\n}\n\n/** Orchestration-only measurement: the harness is a number, not a process. */\nexport function runSyntheticCorpus(): SyntheticResult[] {\n return CORPUS.map((task) => {\n const harnessMs = 1000;\n const orchestrateStart = performance.now();\n const snap = reduceScriptedRun();\n sessionSnapshotSchema.parse(snap);\n const orchestrationMs = performance.now() - orchestrateStart;\n const timing = summarizePhaseTiming(\n [mockedRecord(harnessMs)],\n 'execute',\n harnessMs + orchestrationMs,\n );\n return {\n task: task.id,\n mode: 'synthetic',\n harness: 'mocked',\n model: 'none',\n effort: 'none',\n verification: task.verification,\n strategy: task.strategy,\n taskDurationMs: harnessMs + orchestrationMs,\n harnessExecutionDurationMs: timing.harnessExecutionMs ?? harnessMs,\n orchestrationOverheadMs: timing.orchestrationOverheadMs ?? orchestrationMs,\n timeToFirstOutputMs: timing.ttftMs,\n attemptCount: timing.attemptCount ?? 1,\n retryDurationMs: timing.retryDurationMs ?? 0, // no retries in the mocked record\n verdict: 'unverified',\n };\n });\n}\n"],"mappings":"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","names":["mkdir","writeFile","dirname","mkdir","join","join","mkdir","mkdir","dirname","writeFile"]}
1
+ {"version":3,"sources":["../src/commands/bench.ts","../src/benchmark/corpus.ts","../src/benchmark/live.ts","../src/benchmark/real.ts","../src/benchmark/fixtures/materialize.ts","../src/benchmark/fixtures/templates.ts","../src/benchmark/stats.ts","../src/benchmark/tuple.ts","../src/benchmark/report.ts","../src/benchmark/synthetic.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { createInterface } from 'node:readline';\nimport { TASK_CLASSES, type TaskClass } from '../benchmark/corpus.js';\nimport { createLiveRepeatRunner } from '../benchmark/live.js';\nimport { type BenchCampaign, type RepeatRunner, runRealCorpus } from '../benchmark/real.js';\nimport { renderCampaignMarkdown } from '../benchmark/report.js';\nimport { runSyntheticCorpus } from '../benchmark/synthetic.js';\nimport { collectHarnessVersion } from '../benchmark/tuple.js';\nimport { printError, printInfo, printWarning } from '../ui/logger.js';\n\n/** p50 USD from the #79 before table — used only for the pre-flight estimate. */\nexport const BASELINE_COST_P50_USD: Record<TaskClass, number> = {\n trivial: 0.2,\n small: 3.17,\n medium: 6.08,\n analysis: 1.86,\n};\n\nexport class BenchConfirmationError extends Error {\n readonly exitCode = 1;\n constructor(message: string) {\n super(message);\n this.name = 'BenchConfirmationError';\n }\n}\n\nexport interface BenchOptions {\n mode?: 'synthetic' | 'real';\n task?: string[];\n arm?: string[];\n repeats?: number;\n maxCost?: number;\n maxDuration?: number;\n out?: string;\n yes?: boolean;\n repo?: string;\n json?: boolean;\n interactive?: boolean;\n stdin?: NodeJS.ReadableStream;\n stdout?: NodeJS.WritableStream;\n runPipeline?: (issue: string) => Promise<number>;\n runner?: RepeatRunner;\n harnessVersion?: string;\n}\n\nexport function estimateCampaignUsd(tasks: TaskClass[], arms: number, repeats: number): number {\n const perRepeat = tasks.reduce((sum, task) => sum + BASELINE_COST_P50_USD[task], 0);\n return perRepeat * arms * repeats;\n}\n\nfunction isInteractiveByDefault(): 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\nexport async function confirmRealCampaign(\n estimate: { cells: number; repeats: number; usd: number; maxCost?: number; maxDuration?: number },\n options: Pick<BenchOptions, 'yes' | 'interactive' | 'stdin' | 'stdout'> = {},\n): Promise<void> {\n printInfo(\n `Real campaign: ${estimate.cells} cells × ${estimate.repeats} repeats ≈ $${estimate.usd.toFixed(2)} (p50 of the #79 baseline).`,\n );\n if (estimate.maxCost !== undefined) {\n printInfo(`Cost ceiling: $${estimate.maxCost.toFixed(2)}.`);\n }\n if (estimate.maxDuration !== undefined) {\n printInfo(`Duration ceiling: ${estimate.maxDuration}ms.`);\n }\n if (options.yes === true) {\n printInfo('--yes: starting the campaign.');\n return;\n }\n const interactive = options.interactive ?? isInteractiveByDefault();\n if (!interactive) {\n throw new BenchConfirmationError(\n 'A real campaign spends money and the terminal is not interactive. Re-run with --yes.',\n );\n }\n const stdin = options.stdin ?? process.stdin;\n const stdout = options.stdout ?? process.stdout;\n const rl = createInterface({ input: stdin, output: stdout });\n try {\n const answer = await new Promise<string>((resolve) => {\n rl.question('Proceed with a paid campaign? [y/N] ', resolve);\n });\n if (!/^\\s*y(es)?\\s*$/i.test(answer)) {\n throw new BenchConfirmationError('Cancelled: the campaign was not confirmed.');\n }\n } finally {\n rl.close();\n }\n}\n\nfunction parseTasks(values: string[] | undefined): TaskClass[] {\n if (values === undefined || values.length === 0) return [...TASK_CLASSES];\n const tasks: TaskClass[] = [];\n for (const value of values) {\n if (!(TASK_CLASSES as readonly string[]).includes(value)) {\n throw new BenchConfirmationError(\n `Unknown task class '${value}'. Must be one of: ${TASK_CLASSES.join(', ')}.`,\n );\n }\n if (!tasks.includes(value as TaskClass)) tasks.push(value as TaskClass);\n }\n return tasks;\n}\n\nfunction printSynthetic(): void {\n const rows = runSyntheticCorpus();\n printInfo('Synthetic corpus (orchestration only; harness is a number).');\n for (const row of rows) {\n printInfo(\n `${row.task} duration=${row.taskDurationMs.toFixed(1)}ms overhead=${row.orchestrationOverheadMs.toFixed(1)}ms verdict=${row.verdict}`,\n );\n }\n}\n\nexport async function runBench(options: BenchOptions = {}): Promise<number> {\n const mode = options.mode ?? 'synthetic';\n if (mode !== 'synthetic' && mode !== 'real') {\n printError(`Unknown bench mode '${mode}'. Use synthetic or real.`);\n return 1;\n }\n if (mode === 'synthetic') {\n printSynthetic();\n return 0;\n }\n if (options.repo !== undefined) {\n printWarning(\n '--repo is an investigation escape: the row is not publishable. A disposable fixture is the only source of a comparable line.',\n );\n }\n\n let tasks: TaskClass[];\n try {\n tasks = parseTasks(options.task);\n } catch (error) {\n printError(error instanceof Error ? error.message : String(error));\n return 1;\n }\n const arms = options.arm !== undefined && options.arm.length > 0 ? options.arm : ['baseline'];\n const repeats = options.repeats ?? 5;\n const usd = estimateCampaignUsd(tasks, arms.length, repeats);\n\n try {\n await confirmRealCampaign(\n {\n cells: tasks.length * arms.length,\n repeats,\n usd,\n ...(options.maxCost === undefined ? {} : { maxCost: options.maxCost }),\n ...(options.maxDuration === undefined ? {} : { maxDuration: options.maxDuration }),\n },\n options,\n );\n } catch (error) {\n if (error instanceof BenchConfirmationError) {\n printError(error.message);\n return error.exitCode;\n }\n throw error;\n }\n\n const harnessVersion = options.harnessVersion ?? (await collectHarnessVersion('claude'));\n const runner =\n options.runner ??\n createLiveRepeatRunner({\n runPipeline:\n options.runPipeline ??\n (async (issue) => {\n const { runPipeline } = await import('./run.js');\n return runPipeline(issue, 'auto', undefined, true, false, { yes: true, only: true });\n }),\n });\n\n const campaign: BenchCampaign = await runRealCorpus({\n tasks,\n arms,\n repeats,\n tupleBase: {\n harness: 'claude',\n harnessVersion,\n model: 'default',\n modelVersion: null,\n effort: 'default',\n verification: 'none',\n strategy: 'pipeline',\n settingSourcesPinned: true,\n fallbackModelPassed: false,\n },\n ...(options.maxCost === undefined ? {} : { maxCostUsd: options.maxCost }),\n ...(options.maxDuration === undefined ? {} : { maxDurationMs: options.maxDuration }),\n runner,\n });\n\n if (campaign.stop.reason !== 'completed') {\n printWarning(\n `Campaign stopped on ${campaign.stop.reason} (spent ${campaign.stop.spent}, ceiling ${campaign.stop.ceiling}). Report is partial.`,\n );\n }\n\n const markdown = renderCampaignMarkdown(campaign, arms.join('-vs-'));\n if (options.out) {\n await mkdir(dirname(options.out), { recursive: true });\n await writeFile(options.out, markdown, 'utf-8');\n printInfo(`Wrote ${options.out}`);\n } else {\n (options.stdout ?? process.stdout).write(markdown);\n }\n if (options.json === true) {\n (options.stdout ?? process.stdout).write(`${JSON.stringify(campaign, null, 2)}\\n`);\n }\n return campaign.stop.reason === 'completed' ? 0 : 2;\n}\n","export const TASK_CLASSES = ['trivial', 'small', 'medium', 'analysis'] as const;\n\nexport type TaskClass = (typeof TASK_CLASSES)[number];\n\nexport interface CorpusTask {\n id: TaskClass;\n title: string;\n /** What a fixture repository should contain. */\n fixture: string;\n verification: 'none' | 'existing-tests' | 'tests-and-docs' | 'artifact-only';\n strategy: 'direct' | 'pipeline';\n}\n\n/**\n * Four representative tasks. The synthetic runner never opens a real repo;\n * `real` mode materializes a disposable git fixture per repetition via\n * `fixtures/materialize.ts`. `--repo` is an investigation escape and does\n * not produce a publishable row.\n */\nexport const CORPUS: readonly CorpusTask[] = [\n {\n id: 'trivial',\n title: 'Change one constant and its comment',\n fixture: '1–2 files, no test change',\n verification: 'none',\n strategy: 'direct',\n },\n {\n id: 'small',\n title: 'Fix a failing assertion in an existing test',\n fixture: 'correction against tests that already exist',\n verification: 'existing-tests',\n strategy: 'pipeline',\n },\n {\n id: 'medium',\n title: 'Add a function, tests and a README note',\n fixture: 'implementation plus tests plus documentation',\n verification: 'tests-and-docs',\n strategy: 'pipeline',\n },\n {\n id: 'analysis',\n title: 'Read the tree and write a short report',\n fixture: 'read-only artifact, no implementation',\n verification: 'artifact-only',\n strategy: 'direct',\n },\n];\n\nexport const BENCH_AXES = [\n 'task',\n 'harness',\n 'model',\n 'effort',\n 'verification',\n 'strategy',\n] as const;\n","import { setIssuesCliOverrides } from '../config.js';\nimport { loadTaskPlan } from '../core/state-manager.js';\nimport { GLOBAL_ROOT_ENV } from '../storage/paths.js';\nimport { resetStorageResolutionCache, resolveIssuePaths } from '../storage/resolve.js';\nimport { runAcceptance } from '../verify/run-issue.js';\nimport type { RepeatOutcome, RepeatRunner, RepeatRunnerInput } from './real.js';\n\n/**\n * Live repeats spend money. Unit tests must never take this path.\n * The only escape is an explicit `ISSUE_FLOW_E2E_BENCH=1`, matching the\n * `#80` Antigravity e2e gate.\n */\nexport function assertLiveBenchAllowed(env: NodeJS.ProcessEnv = process.env): void {\n if (env.VITEST && env.ISSUE_FLOW_E2E_BENCH !== '1') {\n throw new Error(\n 'issue-flow bench --mode real does not run under npm test. Set ISSUE_FLOW_E2E_BENCH=1 for a deliberate live campaign.',\n );\n }\n}\n\nexport interface LiveRepeatDeps {\n runPipeline: (issue: string) => Promise<number>;\n}\n\n/**\n * Isolate one repetition: own ISSUE_FLOW_HOME, local issues, no GitHub,\n * `--setting-sources` pinned, `--fallback-model` never passed.\n */\nexport function createLiveRepeatRunner(deps: LiveRepeatDeps): RepeatRunner {\n return async (input: RepeatRunnerInput): Promise<RepeatOutcome> => {\n assertLiveBenchAllowed();\n const previousHome = process.env[GLOBAL_ROOT_ENV];\n const previousCwd = process.cwd();\n process.env[GLOBAL_ROOT_ENV] = input.campaignHome;\n resetStorageResolutionCache();\n setIssuesCliOverrides({ preferredProvider: 'local' });\n process.chdir(input.fixture.root);\n const started = performance.now();\n try {\n await deps.runPipeline(input.fixture.issueRef);\n const paths = await resolveIssuePaths(input.fixture.issueRef, {\n projectRoot: input.fixture.root,\n });\n const plan = await loadTaskPlan(paths.tasksFile);\n const records = plan.executions ?? [];\n const acceptance = await runAcceptance({\n cwd: input.fixture.root,\n issueDir: paths.issueDir,\n declared: input.fixture.expectedVerification,\n executionId: records.at(-1)?.id ?? null,\n skipReviewer: input.arm !== 'L2',\n explicit: input.arm === 'L2',\n });\n const wall = performance.now() - started;\n const harness = records.reduce((sum, record) => sum + (record.durationMs ?? 0), 0);\n const reported = records.flatMap((record) =>\n record.cost.status === 'reported' ? [record.cost.amount] : [],\n );\n const cost =\n reported.length > 0\n ? {\n status: 'reported' as const,\n amount: reported.reduce((sum, amount) => sum + amount, 0),\n currency: 'USD' as const,\n }\n : ({ status: 'unknown' as const, reason: 'not_reported' as const } as const);\n return {\n records,\n verdict: acceptance.verdict,\n taskDurationMs: wall,\n harnessExecutionMs: harness,\n orchestrationOverheadMs: Math.max(0, wall - harness),\n attemptCount: records.reduce((max, record) => Math.max(max, record.attempt), 0) || 1,\n cost,\n };\n } finally {\n process.chdir(previousCwd);\n if (previousHome === undefined) delete process.env[GLOBAL_ROOT_ENV];\n else process.env[GLOBAL_ROOT_ENV] = previousHome;\n resetStorageResolutionCache();\n setIssuesCliOverrides({});\n }\n };\n}\n","import { mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { evaluateCeilings, spendFromCost } from '../routing/budget.js';\nimport { getGlobalRoot } from '../storage/paths.js';\nimport type { CostRecord, ExecutionRecord } from '../telemetry/types.js';\nimport type { VerdictStatus } from '../verify/types.js';\nimport { CORPUS, type TaskClass } from './corpus.js';\nimport { corpusTask, type FixtureHandle, materialize } from './fixtures/index.js';\nimport { p50, p95 } from './stats.js';\nimport {\n assertComparable,\n type ComparabilityTuple,\n isRowInvalid,\n type TupleField,\n tupleAxisForArm,\n} from './tuple.js';\n\nexport interface BenchRepeat {\n seed: number;\n taskDurationMs: number;\n harnessExecutionMs: number;\n orchestrationOverheadMs: number;\n timeToAcceptedResultMs: number | null;\n verdict: VerdictStatus;\n cost: CostRecord;\n attemptCount: number;\n executionIds: string[];\n invalid: boolean;\n}\n\nexport interface BenchCell {\n task: TaskClass;\n tuple: ComparabilityTuple;\n arm: string;\n repeats: BenchRepeat[];\n}\n\nexport interface PercentilePair {\n p50: number;\n p95: number;\n n: number;\n}\n\nexport interface CellSummary {\n n: number;\n taskDurationMs: PercentilePair;\n harnessExecutionMs: PercentilePair;\n orchestrationOverheadMs: PercentilePair;\n timeToAcceptedResultMs: { p50: number | null; p95: number | null; n: number };\n cost: {\n reportedP50: number | null;\n reportedP95: number | null;\n unknownRepeats: number;\n estimatedRepeats: number;\n };\n verdicts: Record<VerdictStatus, number>;\n}\n\nexport type CampaignStop =\n | { reason: 'completed' }\n | { reason: 'max_cost' | 'max_duration'; spent: number; ceiling: number; partial: true };\n\nexport interface BenchCampaign {\n id: string;\n home: string;\n cells: BenchCell[];\n stop: CampaignStop;\n}\n\nexport interface RepeatOutcome {\n records: ExecutionRecord[];\n verdict: VerdictStatus;\n taskDurationMs: number;\n harnessExecutionMs: number;\n orchestrationOverheadMs: number;\n attemptCount: number;\n cost: CostRecord;\n}\n\nexport interface RepeatRunnerInput {\n fixture: FixtureHandle;\n arm: string;\n tuple: ComparabilityTuple;\n campaignHome: string;\n}\n\nexport type RepeatRunner = (input: RepeatRunnerInput) => Promise<RepeatOutcome>;\n\nexport interface RealCorpusOptions {\n tasks?: TaskClass[];\n arms: string[];\n repeats: number;\n tupleBase: Omit<ComparabilityTuple, 'task' | 'strictMcpConfig' | 'fallbackModelPassed'> & {\n strictMcpConfig?: boolean;\n fallbackModelPassed?: boolean;\n };\n maxCostUsd?: number;\n maxDurationMs?: number;\n campaignId?: string;\n runner: RepeatRunner;\n now?: () => number;\n env?: NodeJS.ProcessEnv;\n}\n\nexport function campaignHome(campaignId: string, env?: NodeJS.ProcessEnv): string {\n return join(getGlobalRoot({ env }), 'bench', campaignId);\n}\n\nfunction combineCost(records: readonly ExecutionRecord[]): CostRecord {\n let reported = 0;\n let estimated = 0;\n let unknown = 0;\n for (const record of records) {\n if (record.cost.status === 'reported') reported += record.cost.amount;\n else if (record.cost.status === 'estimated') estimated += record.cost.amount;\n else unknown += 1;\n }\n if (reported > 0) return { status: 'reported', amount: reported, currency: 'USD' };\n if (estimated > 0) {\n return {\n status: 'estimated',\n amount: estimated,\n currency: 'USD',\n pricing: {\n tableVersion: 'bench',\n modelKey: 'aggregated',\n inputPerMillion: 0,\n outputPerMillion: 0,\n capturedAt: new Date(0).toISOString(),\n },\n };\n }\n return { status: 'unknown', reason: unknown > 0 ? 'not_reported' : 'not_reported' };\n}\n\nexport function summarizeCell(cell: BenchCell): CellSummary {\n const durations = cell.repeats.map((repeat) => repeat.taskDurationMs);\n const harness = cell.repeats.map((repeat) => repeat.harnessExecutionMs);\n const overhead = cell.repeats.map((repeat) => repeat.orchestrationOverheadMs);\n const accepted = cell.repeats\n .map((repeat) => repeat.timeToAcceptedResultMs)\n .filter((value): value is number => value !== null);\n const reported = cell.repeats\n .map((repeat) => (repeat.cost.status === 'reported' ? repeat.cost.amount : null))\n .filter((value): value is number => value !== null);\n const verdicts: Record<VerdictStatus, number> = { passed: 0, failed: 0, unverified: 0 };\n let unknownRepeats = 0;\n let estimatedRepeats = 0;\n for (const repeat of cell.repeats) {\n verdicts[repeat.verdict] += 1;\n if (repeat.cost.status === 'unknown') unknownRepeats += 1;\n if (repeat.cost.status === 'estimated') estimatedRepeats += 1;\n }\n return {\n n: cell.repeats.length,\n taskDurationMs: { p50: p50(durations), p95: p95(durations), n: durations.length },\n harnessExecutionMs: { p50: p50(harness), p95: p95(harness), n: harness.length },\n orchestrationOverheadMs: { p50: p50(overhead), p95: p95(overhead), n: overhead.length },\n timeToAcceptedResultMs: {\n p50: accepted.length === 0 ? null : p50(accepted),\n p95: accepted.length === 0 ? null : p95(accepted),\n n: accepted.length,\n },\n cost: {\n reportedP50: reported.length === 0 ? null : p50(reported),\n reportedP95: reported.length === 0 ? null : p95(reported),\n unknownRepeats,\n estimatedRepeats,\n },\n verdicts,\n };\n}\n\nfunction tupleForArm(\n task: TaskClass,\n arm: string,\n base: RealCorpusOptions['tupleBase'],\n): ComparabilityTuple {\n return {\n task,\n harness: base.harness,\n harnessVersion: base.harnessVersion,\n model: base.model,\n modelVersion: base.modelVersion,\n effort: base.effort,\n verification: base.verification,\n strategy: base.strategy,\n settingSourcesPinned: base.settingSourcesPinned,\n strictMcpConfig: arm === 'strict-mcp' ? true : (base.strictMcpConfig ?? false),\n fallbackModelPassed: base.fallbackModelPassed ?? false,\n };\n}\n\nfunction declaredIgnore(arms: readonly string[]): TupleField[] {\n const fields = new Set<TupleField>();\n for (const arm of arms) {\n const axis = tupleAxisForArm(arm);\n if (axis) fields.add(axis);\n }\n return [...fields];\n}\n\n/**\n * Run the real corpus. Arms are a parameter: new experiments do not add\n * runner code. Repeats of different arms are interleaved, not blocked.\n */\nexport async function runRealCorpus(options: RealCorpusOptions): Promise<BenchCampaign> {\n const tasks = options.tasks ?? CORPUS.map((entry) => entry.id);\n const campaignId = options.campaignId ?? `campaign-${Date.now()}`;\n const home = campaignHome(campaignId, options.env);\n await mkdir(home, { recursive: true });\n\n const cells = new Map<string, BenchCell>();\n const ignore = declaredIgnore(options.arms);\n const now = options.now ?? Date.now;\n const started = now();\n let reportedUsd = 0;\n let knownCost: CostRecord['status'] = 'unknown';\n let stop: CampaignStop = { reason: 'completed' };\n\n const schedule: Array<{ task: TaskClass; arm: string; seed: number }> = [];\n for (let seed = 0; seed < options.repeats; seed += 1) {\n for (const arm of options.arms) {\n for (const task of tasks) {\n schedule.push({ task, arm, seed });\n }\n }\n }\n\n for (const step of schedule) {\n const task = corpusTask(step.task);\n const tuple = tupleForArm(step.task, step.arm, {\n ...options.tupleBase,\n verification: task.verification,\n strategy: task.strategy,\n });\n const key = `${step.task}:${step.arm}`;\n const existing = cells.get(key);\n if (existing) {\n assertComparable(existing.tuple, tuple, { ignore });\n } else {\n for (const cell of cells.values()) {\n if (cell.task !== step.task) continue;\n assertComparable(cell.tuple, tuple, { ignore });\n }\n cells.set(key, { task: step.task, tuple, arm: step.arm, repeats: [] });\n }\n\n const fixture = await materialize(task, step.seed);\n try {\n const outcome = await options.runner({\n fixture,\n arm: step.arm,\n tuple,\n campaignHome: home,\n });\n const cost = outcome.cost.status !== undefined ? outcome.cost : combineCost(outcome.records);\n const spent = spendFromCost(cost);\n if (spent.costStatus === 'reported') {\n reportedUsd += spent.reportedUsd;\n knownCost = 'reported';\n }\n const cell = cells.get(key);\n if (!cell) throw new Error(`missing cell ${key}`);\n cell.repeats.push({\n seed: step.seed,\n taskDurationMs: outcome.taskDurationMs,\n harnessExecutionMs: outcome.harnessExecutionMs,\n orchestrationOverheadMs: outcome.orchestrationOverheadMs,\n timeToAcceptedResultMs: outcome.verdict === 'passed' ? outcome.taskDurationMs : null,\n verdict: outcome.verdict,\n cost,\n attemptCount: outcome.attemptCount,\n executionIds: outcome.records.map((record) => record.id),\n invalid: isRowInvalid(tuple),\n });\n } finally {\n await fixture.dispose();\n }\n\n const ceiling = evaluateCeilings({\n ceilings: {\n maxCostUsdPerIssue: options.maxCostUsd ?? null,\n maxDurationMsPerIssue: options.maxDurationMs ?? null,\n maxExecutionsPerIssue: null,\n onCeiling: 'block',\n },\n spent: {\n reportedUsd,\n costStatus: knownCost,\n durationMs: now() - started,\n executions: [...cells.values()].reduce((sum, cell) => sum + cell.repeats.length, 0),\n },\n });\n if (!ceiling.ok) {\n stop = {\n reason: ceiling.stopReason === 'max_attempts' ? 'max_duration' : ceiling.stopReason,\n spent: ceiling.numbers.spent,\n ceiling: ceiling.numbers.ceiling,\n partial: true,\n };\n break;\n }\n }\n\n return { id: campaignId, home, cells: [...cells.values()], stop };\n}\n","import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { ISSUES_DIR_NAME } from '../../storage/paths.js';\nimport { run } from '../../utils/shell.js';\nimport type { AcceptanceCheck } from '../../verify/types.js';\nimport type { CorpusTask } from '../corpus.js';\nimport { CORPUS } from '../corpus.js';\nimport { templateFor } from './templates.js';\n\nexport interface FixtureHandle {\n root: string;\n issueRef: string;\n expectedVerification: AcceptanceCheck[];\n seed: number;\n task: CorpusTask['id'];\n dispose(): Promise<void>;\n}\n\nconst GIT_IDENT = ['-c', 'user.name=issue-flow-bench', '-c', 'user.email=bench@issue-flow.test'];\n\nasync function git(cwd: string, args: string[]): Promise<void> {\n const result = await run('git', args, { cwd });\n if (result.exitCode !== 0) {\n throw new Error(\n `git ${args.join(' ')} failed (${result.exitCode}): ${result.stderr || result.stdout}`,\n );\n }\n}\n\nasync function writeTree(root: string, files: Record<string, string>): Promise<void> {\n for (const [relative, content] of Object.entries(files)) {\n const path = join(root, relative);\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content, 'utf-8');\n }\n}\n\nasync function writeLocalIssue(root: string, title: string, body: string): Promise<void> {\n const issueDir = join(root, ISSUES_DIR_NAME, '1');\n await mkdir(issueDir, { recursive: true });\n await writeFile(join(issueDir, 'issue.md'), `# ${title}\\n\\n${body.trim()}\\n`, 'utf-8');\n await writeFile(\n join(issueDir, 'metadata.json'),\n `${JSON.stringify(\n {\n schemaVersion: 1,\n id: '1',\n number: 1,\n source: 'local',\n title,\n labels: ['bench'],\n state: 'open',\n createdAt: '2026-08-30T00:00:00.000Z',\n updatedAt: '2026-08-30T00:00:00.000Z',\n contentHash: 'sha256:fixture',\n },\n null,\n 2,\n )}\\n`,\n 'utf-8',\n );\n}\n\n/**\n * Materialize a disposable git repository for one corpus class and one seed.\n * A new call always starts from the same unfinished state — never from the\n * work of a previous repetition.\n */\nexport async function materialize(task: CorpusTask, seed: number): Promise<FixtureHandle> {\n const root = await mkdtemp(join(tmpdir(), `issue-flow-bench-${task.id}-${seed}-`));\n const template = templateFor(task.id, seed);\n await writeTree(root, template.files);\n await writeLocalIssue(root, template.issueTitle, template.issueBody);\n\n // An empty template skips sample hooks. Some sandboxes forbid writing\n // executable files under `.git/hooks/`.\n await git(root, ['-c', 'init.templateDir=', 'init']);\n await git(root, ['add', '.']);\n await git(root, [...GIT_IDENT, 'commit', '-m', `fixture ${task.id} seed=${seed}`]);\n\n return {\n root,\n issueRef: '1',\n expectedVerification: template.expectedVerification,\n seed,\n task: task.id,\n async dispose() {\n await rm(root, { recursive: true, force: true });\n },\n };\n}\n\nexport function corpusTask(id: CorpusTask['id']): CorpusTask {\n const task = CORPUS.find((entry) => entry.id === id);\n if (!task) throw new Error(`Unknown corpus class: ${id}`);\n return task;\n}\n","import type { AcceptanceCheck } from '../../verify/types.js';\nimport type { TaskClass } from '../corpus.js';\n\nexport interface FixtureTemplate {\n files: Record<string, string>;\n issueTitle: string;\n issueBody: string;\n expectedVerification: AcceptanceCheck[];\n}\n\nfunction withSeed(content: string, seed: number): string {\n return `${content}\\n// fixture-seed:${seed}\\n`;\n}\n\nexport function templateFor(task: TaskClass, seed: number): FixtureTemplate {\n switch (task) {\n case 'trivial':\n return {\n files: {\n 'src/answer.js': withSeed(\n [\n '/** The answer to life, the universe and everything. */',\n 'export const ANSWER = 41;',\n ].join('\\n'),\n seed,\n ),\n },\n issueTitle: 'Change one constant and its comment',\n issueBody: [\n 'Change `ANSWER` in `src/answer.js` from 41 to 42.',\n 'Update the comment so it no longer claims the wrong value.',\n 'Do not add tests.',\n ].join('\\n'),\n expectedVerification: [],\n };\n case 'small':\n return {\n files: {\n 'src/sum.js': withSeed('export function sum(a, b) {\\n return a - b;\\n}\\n', seed),\n 'src/sum.test.js': [\n \"import { sum } from './sum.js';\",\n \"import assert from 'node:assert/strict';\",\n 'assert.equal(sum(2, 2), 4);',\n '',\n ].join('\\n'),\n 'package.json': `${JSON.stringify({ name: 'bench-small', type: 'module', scripts: { test: 'node src/sum.test.js' } }, null, 2)}\\n`,\n },\n issueTitle: 'Fix a failing assertion in an existing test',\n issueBody: [\n '`src/sum.test.js` fails because `sum` subtracts instead of adding.',\n 'Fix `src/sum.js` so `node src/sum.test.js` exits 0.',\n 'Do not change the test.',\n ].join('\\n'),\n expectedVerification: [{ id: 'existing-tests', run: 'node src/sum.test.js', fatal: true }],\n };\n case 'medium':\n return {\n files: {\n 'src/greet.js': withSeed('// greet(name) is not implemented yet.\\n', seed),\n 'src/greet.test.js': [\n \"import { greet } from './greet.js';\",\n \"import assert from 'node:assert/strict';\",\n \"assert.equal(greet('Ada'), 'Hello, Ada');\",\n '',\n ].join('\\n'),\n 'README.md': ['# bench-medium', '', 'A tiny library.', ''].join('\\n'),\n 'package.json': `${JSON.stringify({ name: 'bench-medium', type: 'module', scripts: { test: 'node src/greet.test.js' } }, null, 2)}\\n`,\n },\n issueTitle: 'Add a function, tests and a README note',\n issueBody: [\n 'Implement `greet(name)` in `src/greet.js` so it returns Hello, <name>.',\n 'Keep `src/greet.test.js` as the contract.',\n 'Add an `## API` section to `README.md` documenting `greet`.',\n ].join('\\n'),\n expectedVerification: [\n { id: 'tests', run: 'node src/greet.test.js', fatal: true },\n { id: 'docs', expectFiles: ['README.md'], fatal: true },\n ],\n };\n case 'analysis':\n return {\n files: {\n 'src/alpha.js': withSeed('export const ALPHA = 1;\\n', seed),\n 'src/beta.js': withSeed(\n \"import { ALPHA } from './alpha.js';\\nexport const BETA = ALPHA + 1;\\n\",\n seed,\n ),\n 'src/gamma.js': withSeed(\n \"import { BETA } from './beta.js';\\nexport const GAMMA = BETA + 1;\\n\",\n seed,\n ),\n },\n issueTitle: 'Read the tree and write a short report',\n issueBody: [\n 'Read `src/` and write `report.md` describing the module graph.',\n 'Do not change the source files.',\n ].join('\\n'),\n expectedVerification: [{ id: 'artifact', expectFiles: ['report.md'], fatal: true }],\n };\n default: {\n const _exhaustive: never = task;\n throw new Error(`Unknown corpus class: ${_exhaustive}`);\n }\n }\n}\n","/** Shared percentiles. Used by both the synthetic CI guard and the real campaign. */\n\nfunction percentile(values: number[], p: number): number {\n const sorted = [...values].sort((a, b) => a - b);\n if (sorted.length === 0) return 0;\n const index = Math.min(sorted.length - 1, Math.ceil((p / 100) * sorted.length) - 1);\n return sorted[index] ?? 0;\n}\n\nexport function p50(values: number[]): number {\n return percentile(values, 50);\n}\n\nexport function p95(values: number[]): number {\n return percentile(values, 95);\n}\n","import { ensureHarnessVersion } from '../agents/registry.js';\nimport type { AgentProviderId } from '../agents/types.js';\nimport type { TaskClass } from './corpus.js';\n\nexport interface ComparabilityTuple {\n task: TaskClass;\n harness: string;\n harnessVersion: string;\n model: string;\n modelVersion: string | null;\n effort: string;\n verification: string;\n strategy: 'direct' | 'pipeline';\n settingSourcesPinned: boolean;\n strictMcpConfig: boolean;\n fallbackModelPassed: boolean;\n}\n\nexport type TupleField = keyof ComparabilityTuple;\n\nexport const TUPLE_FIELDS: readonly TupleField[] = [\n 'task',\n 'harness',\n 'harnessVersion',\n 'model',\n 'modelVersion',\n 'effort',\n 'verification',\n 'strategy',\n 'settingSourcesPinned',\n 'strictMcpConfig',\n 'fallbackModelPassed',\n] as const;\n\nexport class ComparabilityError extends Error {\n readonly field: TupleField;\n readonly left: unknown;\n readonly right: unknown;\n\n constructor(field: TupleField, left: unknown, right: unknown) {\n super(`ComparabilityTuple.${field} differs: ${String(left)} vs ${String(right)}`);\n this.name = 'ComparabilityError';\n this.field = field;\n this.left = left;\n this.right = right;\n }\n}\n\n/**\n * Two cells may be compared only when every field matches, except axes the\n * experiment declared (the arm). A silent mismatch is a bug.\n */\nexport function assertComparable(\n left: ComparabilityTuple,\n right: ComparabilityTuple,\n options: { ignore?: readonly TupleField[] } = {},\n): void {\n const ignored = new Set(options.ignore ?? []);\n for (const field of TUPLE_FIELDS) {\n if (ignored.has(field)) continue;\n if (left[field] !== right[field]) {\n throw new ComparabilityError(field, left[field], right[field]);\n }\n }\n}\n\n/** `--fallback-model` present means the measured model is not the one that ran. */\nexport function isRowInvalid(tuple: ComparabilityTuple): boolean {\n return tuple.fallbackModelPassed || !tuple.settingSourcesPinned;\n}\n\n/** Collect at campaign time. Never assume a version from a document. */\nexport async function collectHarnessVersion(provider: AgentProviderId): Promise<string> {\n const version = await ensureHarnessVersion(provider);\n return version ?? 'unknown';\n}\n\nexport function tupleAxisForArm(arm: string): TupleField | null {\n if (arm === 'strict-mcp') return 'strictMcpConfig';\n return null;\n}\n","import { hostname } from 'node:os';\nimport { getGlobalRoot } from '../storage/paths.js';\nimport { redactSecrets } from '../telemetry/redact.js';\nimport type { BenchCampaign, CellSummary } from './real.js';\nimport { summarizeCell } from './real.js';\nimport type { ComparabilityTuple } from './tuple.js';\n\nfunction formatMs(value: number | null): string {\n return value === null ? '—' : `${Math.round(value)}`;\n}\n\nfunction formatUsd(value: number | null): string {\n return value === null ? '—' : `$${value.toFixed(2)}`;\n}\n\nfunction tupleLine(tuple: ComparabilityTuple): string {\n return [\n tuple.task,\n tuple.harness,\n tuple.harnessVersion,\n tuple.model,\n tuple.modelVersion ?? '—',\n tuple.effort,\n tuple.verification,\n tuple.strategy,\n tuple.settingSourcesPinned ? 'setting-sources:pinned' : 'setting-sources:unpinned',\n tuple.strictMcpConfig ? 'strict-mcp' : 'mcp:default',\n tuple.fallbackModelPassed ? 'INVALID:fallback-model' : 'fallback:none',\n ].join(' × ');\n}\n\nfunction verdictCounts(summary: CellSummary): string {\n return `passed=${summary.verdicts.passed} failed=${summary.verdicts.failed} unverified=${summary.verdicts.unverified}`;\n}\n\nfunction scrubPaths(text: string): string {\n const home = getGlobalRoot();\n return text.split(home).join('<issue-flow-home>');\n}\n\nexport function renderCampaignMarkdown(campaign: BenchCampaign, subject: string): string {\n const lines: string[] = [\n `# Harness campaign — ${subject}`,\n '',\n `> **Research document.** Campaign \\`${campaign.id}\\`.`,\n `> Machine: \\`${hostname()}\\`. Node ${process.version}.`,\n campaign.stop.reason === 'completed'\n ? '> Status: complete.'\n : `> Status: **partial** — stopped on \\`${campaign.stop.reason}\\` (spent ${campaign.stop.spent}, ceiling ${campaign.stop.ceiling}). Results below are the repeats that finished; they are not a silently truncated table.`,\n '',\n '`time-to-accepted-result` is null when the verdict is not `passed`. Cost `unknown` is never summed as zero.',\n '',\n '## Cells',\n '',\n '| Task | Arm | n | duration p50/p95 (ms) | harness p50/p95 | overhead p50/p95 | accepted p50/p95 | cost p50/p95 | verdicts | invalid |',\n '|---|---|---:|---|---|---|---|---|---|---|',\n ];\n\n for (const cell of campaign.cells) {\n const summary = summarizeCell(cell);\n const invalid = cell.repeats.some((repeat) => repeat.invalid);\n lines.push(\n `| ${cell.task} | ${cell.arm} | ${summary.n} | ${formatMs(summary.taskDurationMs.p50)} / ${formatMs(summary.taskDurationMs.p95)} | ${formatMs(summary.harnessExecutionMs.p50)} / ${formatMs(summary.harnessExecutionMs.p95)} | ${formatMs(summary.orchestrationOverheadMs.p50)} / ${formatMs(summary.orchestrationOverheadMs.p95)} | ${formatMs(summary.timeToAcceptedResultMs.p50)} / ${formatMs(summary.timeToAcceptedResultMs.p95)} | ${formatUsd(summary.cost.reportedP50)} / ${formatUsd(summary.cost.reportedP95)} | ${verdictCounts(summary)} | ${invalid ? 'yes' : 'no'} |`,\n );\n }\n\n lines.push('', '## Comparability tuples', '');\n for (const cell of campaign.cells) {\n lines.push(`- **${cell.task} / ${cell.arm}**: \\`${tupleLine(cell.tuple)}\\``);\n }\n lines.push('');\n return redactSecrets(scrubPaths(lines.join('\\n')));\n}\n","import {\n createInitialSnapshot,\n reduceSessionEvent,\n type SessionEvent,\n} from '../core/session-state.js';\nimport { sessionSnapshotSchema } from '../schemas.js';\nimport { summarizePhaseTiming } from '../telemetry/timing.js';\nimport type { ExecutionRecord } from '../telemetry/types.js';\nimport { CORPUS } from './corpus.js';\nimport { p50, p95 } from './stats.js';\n\nexport { p50, p95 };\n\n/** Derived from the #79 investigation: orchestration must stay a rounding error. */\nexport const SYNTHETIC_BUDGETS = {\n /** p95 of reducing a short scripted run, in milliseconds. */\n reduceP95Ms: 50,\n /** p95 of parsing a snapshot through the lockstep schema. */\n parseP95Ms: 20,\n} as const;\n\nexport interface SyntheticResult {\n task: string;\n mode: 'synthetic';\n harness: 'mocked';\n model: 'none';\n effort: 'none';\n verification: string;\n strategy: string;\n taskDurationMs: number;\n harnessExecutionDurationMs: number;\n orchestrationOverheadMs: number;\n timeToFirstOutputMs: number | null;\n attemptCount: number;\n retryDurationMs: number;\n verdict: 'unverified';\n}\n\nfunction scriptedEvents(): SessionEvent[] {\n return [\n {\n type: 'session:start',\n at: '2026-08-30T03:00:00.000Z',\n sessionId: 'bench',\n issueNumber: 79,\n phases: ['prd', 'execute'],\n },\n { type: 'phase:start', at: '2026-08-30T03:00:01.000Z', phase: 'prd' },\n {\n type: 'phase:end',\n at: '2026-08-30T03:00:02.000Z',\n phase: 'prd',\n success: true,\n harnessExecutionMs: 800,\n orchestrationOverheadMs: 200,\n },\n { type: 'phase:start', at: '2026-08-30T03:00:02.000Z', phase: 'execute' },\n {\n type: 'phase:end',\n at: '2026-08-30T03:00:03.000Z',\n phase: 'execute',\n success: true,\n harnessExecutionMs: 900,\n orchestrationOverheadMs: 100,\n attemptCount: 1,\n },\n { type: 'session:end', at: '2026-08-30T03:00:03.000Z', status: 'completed' },\n ];\n}\n\nexport function reduceScriptedRun(): ReturnType<typeof reduceSessionEvent> {\n let snap = createInitialSnapshot();\n for (const event of scriptedEvents()) {\n snap = reduceSessionEvent(snap, event);\n }\n return snap;\n}\n\nexport function timeReduce(repeats = 20): number[] {\n const samples: number[] = [];\n for (let i = 0; i < repeats; i += 1) {\n const start = performance.now();\n reduceScriptedRun();\n samples.push(performance.now() - start);\n }\n return samples;\n}\n\nexport function timeParse(repeats = 20): number[] {\n const snap = reduceScriptedRun();\n const samples: number[] = [];\n for (let i = 0; i < repeats; i += 1) {\n const start = performance.now();\n sessionSnapshotSchema.parse(snap);\n samples.push(performance.now() - start);\n }\n return samples;\n}\n\nfunction mockedRecord(durationMs: number): ExecutionRecord {\n return {\n id: 'synthetic',\n sessionId: 'bench',\n purpose: 'execute',\n attempt: 1,\n trigger: 'initial',\n triggerReason: null,\n agent: {\n harness: 'mocked',\n provider: null,\n model: { requested: null, resolved: null, source: 'unavailable' },\n providerSessionId: null,\n },\n startedAt: '2026-08-30T03:00:00.000Z',\n finishedAt: '2026-08-30T03:00:01.000Z',\n durationMs,\n cliDurationMs: Math.max(0, durationMs - 5),\n harnessStartupMs: 5,\n ttftMs: null,\n usage: { source: 'unavailable' },\n cost: { status: 'unknown', reason: 'not_reported' },\n status: 'completed',\n failure: null,\n };\n}\n\n/** Orchestration-only measurement: the harness is a number, not a process. */\nexport function runSyntheticCorpus(): SyntheticResult[] {\n return CORPUS.map((task) => {\n const harnessMs = 1000;\n const orchestrateStart = performance.now();\n const snap = reduceScriptedRun();\n sessionSnapshotSchema.parse(snap);\n const orchestrationMs = performance.now() - orchestrateStart;\n const timing = summarizePhaseTiming(\n [mockedRecord(harnessMs)],\n 'execute',\n harnessMs + orchestrationMs,\n );\n return {\n task: task.id,\n mode: 'synthetic',\n harness: 'mocked',\n model: 'none',\n effort: 'none',\n verification: task.verification,\n strategy: task.strategy,\n taskDurationMs: harnessMs + orchestrationMs,\n harnessExecutionDurationMs: timing.harnessExecutionMs ?? harnessMs,\n orchestrationOverheadMs: timing.orchestrationOverheadMs ?? orchestrationMs,\n timeToFirstOutputMs: timing.ttftMs,\n attemptCount: timing.attemptCount ?? 1,\n retryDurationMs: timing.retryDurationMs ?? 0, // no retries in the mocked record\n verdict: 'unverified',\n };\n });\n}\n"],"mappings":"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","names":["mkdir","writeFile","dirname","mkdir","join","join","mkdir","mkdir","dirname","writeFile"]}
@@ -1,46 +1,46 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  listPullRequests
4
- } from "./chunk-J62QSVP6.js";
4
+ } from "./chunk-PBTA3QQX.js";
5
5
  import {
6
6
  isTransientFailure,
7
7
  runPhaseWithRetry
8
- } from "./chunk-IV5SS4JN.js";
8
+ } from "./chunk-76MMPJ53.js";
9
9
  import {
10
10
  issuePlaceholders,
11
11
  resolveCommandIssue
12
- } from "./chunk-FZDR7CGH.js";
12
+ } from "./chunk-REO3PXXO.js";
13
13
  import {
14
14
  publishPhaseMetrics,
15
15
  resolvePolicyPlaceholders
16
- } from "./chunk-664Y3NDX.js";
16
+ } from "./chunk-PHW2YV6N.js";
17
17
  import {
18
18
  applyPlaceholders,
19
19
  loadPrompt
20
- } from "./chunk-MIVHK5YI.js";
20
+ } from "./chunk-KMRFRXIT.js";
21
21
  import {
22
22
  DEFAULT_HEADLESS_TIMEOUT_MS,
23
23
  runHeadless
24
- } from "./chunk-ARFVHC2F.js";
24
+ } from "./chunk-CGKLE6WR.js";
25
25
  import {
26
26
  issueReferenceLines,
27
27
  loadRepositoryPolicy,
28
28
  pullRequestTitle,
29
29
  resolveChangeType
30
- } from "./chunk-UOCPC2Y2.js";
30
+ } from "./chunk-RVO7L4FX.js";
31
31
  import {
32
32
  resolveIssuePaths
33
- } from "./chunk-HQAHNIAR.js";
33
+ } from "./chunk-QK7WUO7A.js";
34
34
  import {
35
35
  getGlobalTimeout,
36
36
  printError,
37
37
  printSuccess
38
- } from "./chunk-IYV6KNVF.js";
38
+ } from "./chunk-TYRNTSPJ.js";
39
39
  import {
40
40
  isoNow,
41
41
  loadTaskPlan,
42
42
  saveTaskPlan
43
- } from "./chunk-DIG5XKQQ.js";
43
+ } from "./chunk-J3SOTUVI.js";
44
44
 
45
45
  // src/commands/pr.ts
46
46
  import { execa } from "execa";
@@ -280,4 +280,4 @@ export {
280
280
  multiIssueContext,
281
281
  runPr
282
282
  };
283
- //# sourceMappingURL=chunk-PIVGJM6K.js.map
283
+ //# sourceMappingURL=chunk-2IQ6M4ZE.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  MemoryPublisher
4
- } from "./chunk-IYV6KNVF.js";
4
+ } from "./chunk-6QYMSNVA.js";
5
5
 
6
6
  // src/core/journal.ts
7
7
  import { appendFile, mkdir, rename, stat, unlink } from "fs/promises";
@@ -138,4 +138,4 @@ export {
138
138
  parseJournal,
139
139
  MultiPublisher
140
140
  };
141
- //# sourceMappingURL=chunk-QCXPNSEL.js.map
141
+ //# sourceMappingURL=chunk-3BWZO4YI.js.map
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getDiagnosticsDir
4
+ } from "./chunk-HAKDLR6N.js";
5
+ import {
6
+ redactSecrets
7
+ } from "./chunk-G5EK2XRN.js";
8
+
9
+ // src/storage/diagnostics.ts
10
+ import { appendFile, mkdir, readdir, readFile, rename, stat, unlink } from "fs/promises";
11
+ import { join } from "path";
12
+ var MAX_FILE_BYTES = 10 * 1024 * 1024;
13
+ var MAX_GENERATIONS = 5;
14
+ var RETENTION_DAYS = 30;
15
+ var bound = {};
16
+ var pending = Promise.resolve();
17
+ var retentionChecked = false;
18
+ var SENSITIVE_KEY = /(?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|password|secret|authorization)/i;
19
+ function bindDiagnosticContext(context) {
20
+ bound = { ...bound, ...context };
21
+ }
22
+ function sanitize(value) {
23
+ if (typeof value === "string") return redactSecrets(value);
24
+ if (Array.isArray(value)) return value.map(sanitize);
25
+ if (value !== null && typeof value === "object") {
26
+ return Object.fromEntries(
27
+ Object.entries(value).map(([key, item]) => [
28
+ key,
29
+ SENSITIVE_KEY.test(key) ? "[redacted]" : sanitize(item)
30
+ ])
31
+ );
32
+ }
33
+ return value;
34
+ }
35
+ function diagnosticFile(timestamp) {
36
+ return join(getDiagnosticsDir(), `issue-flow-${timestamp.slice(0, 10)}.jsonl`);
37
+ }
38
+ async function rotate(file, incomingBytes) {
39
+ let size = 0;
40
+ try {
41
+ size = (await stat(file)).size;
42
+ } catch {
43
+ return;
44
+ }
45
+ if (size + incomingBytes < MAX_FILE_BYTES) return;
46
+ try {
47
+ await unlink(`${file}.${MAX_GENERATIONS}`);
48
+ } catch {
49
+ }
50
+ for (let generation = MAX_GENERATIONS - 1; generation >= 1; generation--) {
51
+ try {
52
+ await rename(`${file}.${generation}`, `${file}.${generation + 1}`);
53
+ } catch {
54
+ }
55
+ }
56
+ try {
57
+ await rename(file, `${file}.1`);
58
+ } catch {
59
+ }
60
+ }
61
+ async function enforceRetention(directory) {
62
+ if (retentionChecked) return;
63
+ retentionChecked = true;
64
+ let names;
65
+ try {
66
+ names = await readdir(directory);
67
+ } catch {
68
+ return;
69
+ }
70
+ const cutoff = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1e3;
71
+ await Promise.all(
72
+ names.filter((name) => /^issue-flow-\d{4}-\d{2}-\d{2}\.jsonl(?:\.\d+)?$/.test(name)).map(async (name) => {
73
+ const path = join(directory, name);
74
+ try {
75
+ if ((await stat(path)).mtimeMs < cutoff) await unlink(path);
76
+ } catch {
77
+ }
78
+ })
79
+ );
80
+ }
81
+ function writeDiagnostic(input) {
82
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
83
+ const error = input.exception instanceof Error ? input.exception : null;
84
+ const record = {
85
+ ...bound,
86
+ ...input.fields,
87
+ timestamp,
88
+ level: input.level,
89
+ message: redactSecrets(input.message),
90
+ context: input.context === void 0 ? null : sanitize(input.context),
91
+ exception: error === null ? null : {
92
+ name: error.name,
93
+ message: redactSecrets(error.message),
94
+ stack: error.stack ? redactSecrets(error.stack) : null
95
+ }
96
+ };
97
+ const line = `${JSON.stringify(record)}
98
+ `;
99
+ pending = pending.then(async () => {
100
+ const directory = getDiagnosticsDir();
101
+ await mkdir(directory, { recursive: true });
102
+ await enforceRetention(directory);
103
+ const file = diagnosticFile(timestamp);
104
+ await rotate(file, Buffer.byteLength(line));
105
+ await appendFile(file, line, "utf-8");
106
+ }).catch(() => {
107
+ });
108
+ }
109
+ async function flushDiagnostics() {
110
+ await pending;
111
+ }
112
+ async function resetDiagnosticsState() {
113
+ await pending;
114
+ bound = {};
115
+ pending = Promise.resolve();
116
+ retentionChecked = false;
117
+ }
118
+ async function readDiagnostics(options = {}) {
119
+ const directory = getDiagnosticsDir();
120
+ let names;
121
+ try {
122
+ names = (await readdir(directory)).filter((name) => /^issue-flow-\d{4}-\d{2}-\d{2}\.jsonl(?:\.\d+)?$/.test(name)).sort((left, right) => {
123
+ const leftDate = left.slice(11, 21);
124
+ const rightDate = right.slice(11, 21);
125
+ if (leftDate !== rightDate) return rightDate.localeCompare(leftDate);
126
+ const generation = (name) => Number(name.match(/\.jsonl\.(\d+)$/)?.[1] ?? 0);
127
+ return generation(left) - generation(right);
128
+ });
129
+ } catch {
130
+ return [];
131
+ }
132
+ const limit = Math.max(1, Math.min(options.limit ?? 500, 2e3));
133
+ const records = [];
134
+ for (const name of names) {
135
+ let raw;
136
+ try {
137
+ raw = await readFile(join(directory, name), "utf-8");
138
+ } catch {
139
+ continue;
140
+ }
141
+ for (const line of raw.split("\n").reverse()) {
142
+ if (line.trim() === "") continue;
143
+ try {
144
+ const record = JSON.parse(line);
145
+ if (options.sessionId && record.sessionId !== options.sessionId) continue;
146
+ if (options.project && record.project !== options.project) continue;
147
+ records.push(record);
148
+ if (records.length >= limit) return records;
149
+ } catch {
150
+ }
151
+ }
152
+ }
153
+ return records;
154
+ }
155
+
156
+ export {
157
+ bindDiagnosticContext,
158
+ writeDiagnostic,
159
+ flushDiagnostics,
160
+ resetDiagnosticsState,
161
+ readDiagnostics
162
+ };
163
+ //# sourceMappingURL=chunk-3WFZETIM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/storage/diagnostics.ts"],"sourcesContent":["import { appendFile, mkdir, readdir, readFile, rename, stat, unlink } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { redactSecrets } from '../telemetry/redact.js';\nimport { getDiagnosticsDir } from './paths.js';\n\nexport type DiagnosticLevel = 'debug' | 'info' | 'warning' | 'error';\n\nexport interface DiagnosticContext {\n project?: string | null;\n projectRoot?: string | null;\n sessionId?: string | null;\n executionId?: string | null;\n issue?: string | number | null;\n phase?: string | null;\n story?: string | null;\n harness?: string | null;\n model?: string | null;\n}\n\nexport interface DiagnosticRecord extends DiagnosticContext {\n timestamp: string;\n level: DiagnosticLevel;\n message: string;\n context: unknown | null;\n exception: { name: string; message: string; stack: string | null } | null;\n}\n\nconst MAX_FILE_BYTES = 10 * 1024 * 1024;\nconst MAX_GENERATIONS = 5;\nconst RETENTION_DAYS = 30;\nlet bound: DiagnosticContext = {};\nlet pending: Promise<void> = Promise.resolve();\nlet retentionChecked = false;\nconst SENSITIVE_KEY =\n /(?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|password|secret|authorization)/i;\n\nexport function bindDiagnosticContext(context: DiagnosticContext): void {\n bound = { ...bound, ...context };\n}\n\nfunction sanitize(value: unknown): unknown {\n if (typeof value === 'string') return redactSecrets(value);\n if (Array.isArray(value)) return value.map(sanitize);\n if (value !== null && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).map(([key, item]) => [\n key,\n SENSITIVE_KEY.test(key) ? '[redacted]' : sanitize(item),\n ]),\n );\n }\n return value;\n}\n\nfunction diagnosticFile(timestamp: string): string {\n return join(getDiagnosticsDir(), `issue-flow-${timestamp.slice(0, 10)}.jsonl`);\n}\n\nasync function rotate(file: string, incomingBytes: number): Promise<void> {\n let size = 0;\n try {\n size = (await stat(file)).size;\n } catch {\n return;\n }\n if (size + incomingBytes < MAX_FILE_BYTES) return;\n try {\n await unlink(`${file}.${MAX_GENERATIONS}`);\n } catch {}\n for (let generation = MAX_GENERATIONS - 1; generation >= 1; generation--) {\n try {\n await rename(`${file}.${generation}`, `${file}.${generation + 1}`);\n } catch {}\n }\n try {\n await rename(file, `${file}.1`);\n } catch {}\n}\n\nasync function enforceRetention(directory: string): Promise<void> {\n if (retentionChecked) return;\n retentionChecked = true;\n let names: string[];\n try {\n names = await readdir(directory);\n } catch {\n return;\n }\n const cutoff = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1_000;\n await Promise.all(\n names\n .filter((name) => /^issue-flow-\\d{4}-\\d{2}-\\d{2}\\.jsonl(?:\\.\\d+)?$/.test(name))\n .map(async (name) => {\n const path = join(directory, name);\n try {\n if ((await stat(path)).mtimeMs < cutoff) await unlink(path);\n } catch {}\n }),\n );\n}\n\nexport function writeDiagnostic(input: {\n level: DiagnosticLevel;\n message: string;\n context?: unknown;\n exception?: unknown;\n fields?: DiagnosticContext;\n}): void {\n const timestamp = new Date().toISOString();\n const error = input.exception instanceof Error ? input.exception : null;\n const record: DiagnosticRecord = {\n ...bound,\n ...input.fields,\n timestamp,\n level: input.level,\n message: redactSecrets(input.message),\n context: input.context === undefined ? null : sanitize(input.context),\n exception:\n error === null\n ? null\n : {\n name: error.name,\n message: redactSecrets(error.message),\n stack: error.stack ? redactSecrets(error.stack) : null,\n },\n };\n const line = `${JSON.stringify(record)}\\n`;\n pending = pending\n .then(async () => {\n const directory = getDiagnosticsDir();\n await mkdir(directory, { recursive: true });\n await enforceRetention(directory);\n const file = diagnosticFile(timestamp);\n await rotate(file, Buffer.byteLength(line));\n await appendFile(file, line, 'utf-8');\n })\n .catch(() => {});\n}\n\nexport async function flushDiagnostics(): Promise<void> {\n await pending;\n}\n\n/** Test seam: diagnostics are process-global like the terminal/session publishers. */\nexport async function resetDiagnosticsState(): Promise<void> {\n await pending;\n bound = {};\n pending = Promise.resolve();\n retentionChecked = false;\n}\n\nexport async function readDiagnostics(\n options: { sessionId?: string; project?: string; limit?: number } = {},\n): Promise<DiagnosticRecord[]> {\n const directory = getDiagnosticsDir();\n let names: string[];\n try {\n names = (await readdir(directory))\n .filter((name) => /^issue-flow-\\d{4}-\\d{2}-\\d{2}\\.jsonl(?:\\.\\d+)?$/.test(name))\n .sort((left, right) => {\n const leftDate = left.slice(11, 21);\n const rightDate = right.slice(11, 21);\n if (leftDate !== rightDate) return rightDate.localeCompare(leftDate);\n const generation = (name: string): number =>\n Number(name.match(/\\.jsonl\\.(\\d+)$/)?.[1] ?? 0);\n return generation(left) - generation(right);\n });\n } catch {\n return [];\n }\n const limit = Math.max(1, Math.min(options.limit ?? 500, 2_000));\n const records: DiagnosticRecord[] = [];\n for (const name of names) {\n let raw: string;\n try {\n raw = await readFile(join(directory, name), 'utf-8');\n } catch {\n continue;\n }\n for (const line of raw.split('\\n').reverse()) {\n if (line.trim() === '') continue;\n try {\n const record = JSON.parse(line) as DiagnosticRecord;\n if (options.sessionId && record.sessionId !== options.sessionId) continue;\n if (options.project && record.project !== options.project) continue;\n records.push(record);\n if (records.length >= limit) return records;\n } catch {}\n }\n }\n return records;\n}\n"],"mappings":"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","names":[]}