issue-flow 0.18.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -100
- package/dist/agent-EWKA7357.js +32 -0
- package/dist/{analyze-Q4ONIWRZ.js → analyze-Z7ODC27F.js} +42 -41
- package/dist/analyze-Z7ODC27F.js.map +1 -0
- package/dist/{apply-EEFPY2W4.js → apply-VNSWQS6O.js} +22 -24
- package/dist/apply-VNSWQS6O.js.map +1 -0
- package/dist/artifacts-AMJQJFFV.js +82 -0
- package/dist/artifacts-AMJQJFFV.js.map +1 -0
- package/dist/{bench-WWWXLTFH.js → bench-ZJEIACUK.js} +42 -42
- package/dist/{chunk-RYOUZ6EK.js → chunk-23VHVVKW.js} +3 -3
- package/dist/chunk-2EYLOS5I.js +99 -0
- package/dist/chunk-2EYLOS5I.js.map +1 -0
- package/dist/{chunk-XUEMATVY.js → chunk-2EZW4X57.js} +28 -25
- package/dist/chunk-2EZW4X57.js.map +1 -0
- package/dist/{chunk-LGHND47K.js → chunk-2Q6PG3MT.js} +15 -15
- package/dist/chunk-2Q6PG3MT.js.map +1 -0
- package/dist/{chunk-C5TL7T4V.js → chunk-2YM2VH6R.js} +2 -2
- package/dist/{chunk-OODXFCQV.js → chunk-2YYP7AE6.js} +14 -16
- package/dist/{chunk-OODXFCQV.js.map → chunk-2YYP7AE6.js.map} +1 -1
- package/dist/chunk-3JD25HHJ.js +278 -0
- package/dist/chunk-3JD25HHJ.js.map +1 -0
- package/dist/{chunk-PMLE7KAQ.js → chunk-46S7APLQ.js} +30 -14
- package/dist/chunk-46S7APLQ.js.map +1 -0
- package/dist/chunk-6AOZCWN2.js +21 -0
- package/dist/chunk-6AOZCWN2.js.map +1 -0
- package/dist/{chunk-QPGEFLMY.js → chunk-7CMVL4X6.js} +7 -7
- package/dist/chunk-7MJGYPHF.js +1571 -0
- package/dist/chunk-7MJGYPHF.js.map +1 -0
- package/dist/chunk-7ZZUSMBJ.js +35 -0
- package/dist/chunk-7ZZUSMBJ.js.map +1 -0
- package/dist/{chunk-DUS5ZNKL.js → chunk-DIMDAYZS.js} +7 -6
- package/dist/{chunk-DGRTJD5R.js → chunk-DXH4TQRB.js} +7 -7
- package/dist/{chunk-CRGIQFUQ.js → chunk-E2H3JV2E.js} +3 -1
- package/dist/chunk-E2H3JV2E.js.map +1 -0
- package/dist/{chunk-YUNBOUQH.js → chunk-ERAG5IQB.js} +8 -8
- package/dist/{chunk-ZVZMWNCG.js → chunk-F2NFJ27Z.js} +2 -2
- package/dist/{chunk-SOM4QA6C.js → chunk-GD7JZMSJ.js} +93 -18
- package/dist/chunk-GD7JZMSJ.js.map +1 -0
- package/dist/{chunk-6K2LCFG6.js → chunk-HEHHQU4G.js} +70 -81
- package/dist/chunk-HEHHQU4G.js.map +1 -0
- package/dist/{chunk-34OCSKOB.js → chunk-HHXWAWU6.js} +159 -114
- package/dist/chunk-HHXWAWU6.js.map +1 -0
- package/dist/{chunk-E4I6MMHD.js → chunk-HWWB22HC.js} +152 -100
- package/dist/chunk-HWWB22HC.js.map +1 -0
- package/dist/chunk-IMB6FA2F.js +673 -0
- package/dist/chunk-IMB6FA2F.js.map +1 -0
- package/dist/{chunk-ECU7YO7S.js → chunk-IQYXXFRC.js} +22 -6
- package/dist/chunk-IQYXXFRC.js.map +1 -0
- package/dist/chunk-J6VJ5M2U.js +1201 -0
- package/dist/chunk-J6VJ5M2U.js.map +1 -0
- package/dist/{chunk-QJ44VG5G.js → chunk-KDQRNVBZ.js} +3 -3
- package/dist/{chunk-7UMMFOL2.js → chunk-LRWIP7QS.js} +39 -24
- package/dist/chunk-LRWIP7QS.js.map +1 -0
- package/dist/{chunk-LI35PIIS.js → chunk-LYC57OXF.js} +20 -117
- package/dist/chunk-LYC57OXF.js.map +1 -0
- package/dist/{chunk-HAKDLR6N.js → chunk-MAJ6QDRL.js} +65 -78
- package/dist/chunk-MAJ6QDRL.js.map +1 -0
- package/dist/{chunk-CWSQVHVV.js → chunk-MHA7Q3KU.js} +248 -102
- package/dist/chunk-MHA7Q3KU.js.map +1 -0
- package/dist/{chunk-TZYINKCC.js → chunk-MQTVMB7W.js} +33 -28
- package/dist/chunk-MQTVMB7W.js.map +1 -0
- package/dist/chunk-NP47HRX2.js +136 -0
- package/dist/chunk-NP47HRX2.js.map +1 -0
- package/dist/{chunk-EG2MGDP5.js → chunk-NYDAHE3Y.js} +52 -46
- package/dist/chunk-NYDAHE3Y.js.map +1 -0
- package/dist/{chunk-45WZ6GMI.js → chunk-P7ZYOC23.js} +16 -16
- package/dist/{chunk-3R27MJ5R.js → chunk-PFWHHYEO.js} +3 -3
- package/dist/{chunk-NEWNXZ65.js → chunk-PHPAK2L6.js} +28 -26
- package/dist/{chunk-NEWNXZ65.js.map → chunk-PHPAK2L6.js.map} +1 -1
- package/dist/{chunk-PPZ3K4YM.js → chunk-PRGPSNGA.js} +2 -2
- package/dist/{chunk-V7QOIQYC.js → chunk-RGFMQFX7.js} +9 -23
- package/dist/{chunk-V7QOIQYC.js.map → chunk-RGFMQFX7.js.map} +1 -1
- package/dist/{chunk-YVPZUN6X.js → chunk-TJVX42KY.js} +335 -38
- package/dist/chunk-TJVX42KY.js.map +1 -0
- package/dist/{chunk-HOAHMERN.js → chunk-UDRAD7MF.js} +21 -21
- package/dist/{chunk-QF7VEL3M.js → chunk-UHDXXLYH.js} +39 -127
- package/dist/chunk-UHDXXLYH.js.map +1 -0
- package/dist/{chunk-RNFUVKC3.js → chunk-UPAAZU4W.js} +30 -13
- package/dist/chunk-UPAAZU4W.js.map +1 -0
- package/dist/{chunk-L6HSKTQE.js → chunk-W7LZLJAF.js} +4 -4
- package/dist/{chunk-KMCS76ZW.js → chunk-WB2FVIUS.js} +44 -12
- package/dist/chunk-WB2FVIUS.js.map +1 -0
- package/dist/{chunk-SA6HXL4Y.js → chunk-WPHC6JBR.js} +9 -9
- package/dist/chunk-WPHC6JBR.js.map +1 -0
- package/dist/{chunk-KRAGAUKD.js → chunk-XHCP6ZNO.js} +201 -64
- package/dist/chunk-XHCP6ZNO.js.map +1 -0
- package/dist/{chunk-7F7LGMVO.js → chunk-XKR3VD2Z.js} +12 -12
- package/dist/{chunk-7F7LGMVO.js.map → chunk-XKR3VD2Z.js.map} +1 -1
- package/dist/{chunk-ICM463EO.js → chunk-XNK5UN2D.js} +5 -649
- package/dist/chunk-XNK5UN2D.js.map +1 -0
- package/dist/{chunk-LTH6XYZ3.js → chunk-XQLNZW7I.js} +40 -30
- package/dist/chunk-XQLNZW7I.js.map +1 -0
- package/dist/{chunk-62GVVZQO.js → chunk-ZAYATXJD.js} +32 -316
- package/dist/chunk-ZAYATXJD.js.map +1 -0
- package/dist/cli.js +127 -59
- package/dist/cli.js.map +1 -1
- package/dist/compat-YPDZB34U.js +24 -0
- package/dist/{config-LEBZZCJP.js → config-56B4OHZE.js} +20 -17
- package/dist/{contract-JH2WBIO6.js → contract-HWLFFL3F.js} +2 -2
- package/dist/{conventions-XOT6YW5L.js → conventions-DW2CM5I3.js} +20 -16
- package/dist/{conventions-XOT6YW5L.js.map → conventions-DW2CM5I3.js.map} +1 -1
- package/dist/db-5NU77PJA.js +264 -0
- package/dist/db-5NU77PJA.js.map +1 -0
- package/dist/diagnostics-UCTS2VUF.js +25 -0
- package/dist/execute-R7AVOLNG.js +38 -0
- package/dist/{generate-JGW5JSKB.js → generate-O7GUXLN4.js} +46 -43
- package/dist/generate-O7GUXLN4.js.map +1 -0
- package/dist/{git-A2IP32PQ.js → git-LCG45YXD.js} +2 -3
- package/dist/history-6GSURU3H.js +101 -0
- package/dist/history-6GSURU3H.js.map +1 -0
- package/dist/init-DD6DBRC5.js +28 -0
- package/dist/{operations-O4FORFIH.js → operations-HU5ZFEBA.js} +78 -52
- package/dist/operations-HU5ZFEBA.js.map +1 -0
- package/dist/{permissions-G4XCAESF.js → permissions-NNNSRC4P.js} +5 -6
- package/dist/plan-XR6B7EM3.js +38 -0
- package/dist/{policy-U5NBFAO5.js → policy-RFJOJQL6.js} +17 -15
- package/dist/{policy-U5NBFAO5.js.map → policy-RFJOJQL6.js.map} +1 -1
- package/dist/pr-OSCNJCOO.js +42 -0
- package/dist/pr-review-IKIYHFBO.js +33 -0
- package/dist/prd-HFDZJJQR.js +37 -0
- package/dist/{ps-76L6ZAZL.js → ps-AKRHGPSR.js} +26 -15
- package/dist/ps-AKRHGPSR.js.map +1 -0
- package/dist/{recorder-2BAKPBRA.js → recorder-T7426CKV.js} +11 -7
- package/dist/registry-DWRKD65A.js +17 -0
- package/dist/repository-TABBRW2C.js +80 -0
- package/dist/resume-GDXKK5XP.js +278 -0
- package/dist/resume-GDXKK5XP.js.map +1 -0
- package/dist/review-JJHMQA2O.js +38 -0
- package/dist/routing-FPNUVE7T.js +35 -0
- package/dist/run-RLCURLLL.js +61 -0
- package/dist/{session-publisher-KAJQRHNZ.js → session-publisher-Q5TNEZPX.js} +3 -3
- package/dist/session-publisher-Q5TNEZPX.js.map +1 -0
- package/dist/{state-manager-UPHO2EA2.js → state-manager-IGNTD4AB.js} +9 -4
- package/dist/state-manager-IGNTD4AB.js.map +1 -0
- package/dist/{usage-KTMYXAPF.js → usage-XW27AL5K.js} +69 -63
- package/dist/usage-XW27AL5K.js.map +1 -0
- package/dist/web-NCDBVZ5Y.js +205 -0
- package/dist/web-NCDBVZ5Y.js.map +1 -0
- package/package.json +20 -7
- package/prompts/analyze.md +16 -19
- package/prompts/execute.md +73 -144
- package/prompts/generate.md +23 -10
- package/prompts/plan.md +32 -60
- package/prompts/pr-review.md +58 -40
- package/prompts/pr.md +50 -16
- package/prompts/prd.md +26 -19
- package/prompts/review.md +41 -18
- package/web/public/app.js +109 -110
- package/dist/agent-HMZTXCRT.js +0 -30
- package/dist/analyze-Q4ONIWRZ.js.map +0 -1
- package/dist/apply-EEFPY2W4.js.map +0 -1
- package/dist/chunk-34OCSKOB.js.map +0 -1
- package/dist/chunk-62GVVZQO.js.map +0 -1
- package/dist/chunk-6K2LCFG6.js.map +0 -1
- package/dist/chunk-7UMMFOL2.js.map +0 -1
- package/dist/chunk-CRGIQFUQ.js.map +0 -1
- package/dist/chunk-CWSQVHVV.js.map +0 -1
- package/dist/chunk-E4I6MMHD.js.map +0 -1
- package/dist/chunk-ECU7YO7S.js.map +0 -1
- package/dist/chunk-EG2MGDP5.js.map +0 -1
- package/dist/chunk-HAKDLR6N.js.map +0 -1
- package/dist/chunk-ICM463EO.js.map +0 -1
- package/dist/chunk-KMCS76ZW.js.map +0 -1
- package/dist/chunk-KRAGAUKD.js.map +0 -1
- package/dist/chunk-LGHND47K.js.map +0 -1
- package/dist/chunk-LI35PIIS.js.map +0 -1
- package/dist/chunk-LTH6XYZ3.js.map +0 -1
- package/dist/chunk-PMLE7KAQ.js.map +0 -1
- package/dist/chunk-QF7VEL3M.js.map +0 -1
- package/dist/chunk-RNFUVKC3.js.map +0 -1
- package/dist/chunk-SA6HXL4Y.js.map +0 -1
- package/dist/chunk-SOM4QA6C.js.map +0 -1
- package/dist/chunk-TZYINKCC.js.map +0 -1
- package/dist/chunk-WCCZJL7W.js +0 -141
- package/dist/chunk-WCCZJL7W.js.map +0 -1
- package/dist/chunk-XEYH6ZZI.js +0 -289
- package/dist/chunk-XEYH6ZZI.js.map +0 -1
- package/dist/chunk-XUEMATVY.js.map +0 -1
- package/dist/chunk-XZUEFTUP.js +0 -243
- package/dist/chunk-XZUEFTUP.js.map +0 -1
- package/dist/chunk-YVPZUN6X.js.map +0 -1
- package/dist/diagnostics-HTCWF7F4.js +0 -23
- package/dist/execute-LELOSR5T.js +0 -37
- package/dist/generate-JGW5JSKB.js.map +0 -1
- package/dist/init-TO6MUXO4.js +0 -26
- package/dist/operations-O4FORFIH.js.map +0 -1
- package/dist/plan-OXAT344Q.js +0 -34
- package/dist/pr-UZHNKKZC.js +0 -39
- package/dist/pr-review-Q4ACAWDM.js +0 -32
- package/dist/prd-6CYEMLDY.js +0 -33
- package/dist/ps-76L6ZAZL.js.map +0 -1
- package/dist/registry-XLHHYLTR.js +0 -15
- package/dist/resume-URCU6CIJ.js +0 -244
- package/dist/resume-URCU6CIJ.js.map +0 -1
- package/dist/review-LVZT2TMW.js +0 -35
- package/dist/routing-EK6RBZM4.js +0 -33
- package/dist/run-2RXJCJKT.js +0 -56
- package/dist/usage-KTMYXAPF.js.map +0 -1
- package/dist/web-B5UPHHR5.js +0 -172
- package/dist/web-B5UPHHR5.js.map +0 -1
- /package/dist/{agent-HMZTXCRT.js.map → agent-EWKA7357.js.map} +0 -0
- /package/dist/{bench-WWWXLTFH.js.map → bench-ZJEIACUK.js.map} +0 -0
- /package/dist/{chunk-RYOUZ6EK.js.map → chunk-23VHVVKW.js.map} +0 -0
- /package/dist/{chunk-C5TL7T4V.js.map → chunk-2YM2VH6R.js.map} +0 -0
- /package/dist/{chunk-QPGEFLMY.js.map → chunk-7CMVL4X6.js.map} +0 -0
- /package/dist/{chunk-DUS5ZNKL.js.map → chunk-DIMDAYZS.js.map} +0 -0
- /package/dist/{chunk-DGRTJD5R.js.map → chunk-DXH4TQRB.js.map} +0 -0
- /package/dist/{chunk-YUNBOUQH.js.map → chunk-ERAG5IQB.js.map} +0 -0
- /package/dist/{chunk-ZVZMWNCG.js.map → chunk-F2NFJ27Z.js.map} +0 -0
- /package/dist/{chunk-QJ44VG5G.js.map → chunk-KDQRNVBZ.js.map} +0 -0
- /package/dist/{chunk-45WZ6GMI.js.map → chunk-P7ZYOC23.js.map} +0 -0
- /package/dist/{chunk-3R27MJ5R.js.map → chunk-PFWHHYEO.js.map} +0 -0
- /package/dist/{chunk-PPZ3K4YM.js.map → chunk-PRGPSNGA.js.map} +0 -0
- /package/dist/{chunk-HOAHMERN.js.map → chunk-UDRAD7MF.js.map} +0 -0
- /package/dist/{chunk-L6HSKTQE.js.map → chunk-W7LZLJAF.js.map} +0 -0
- /package/dist/{config-LEBZZCJP.js.map → compat-YPDZB34U.js.map} +0 -0
- /package/dist/{contract-JH2WBIO6.js.map → config-56B4OHZE.js.map} +0 -0
- /package/dist/{diagnostics-HTCWF7F4.js.map → contract-HWLFFL3F.js.map} +0 -0
- /package/dist/{execute-LELOSR5T.js.map → diagnostics-UCTS2VUF.js.map} +0 -0
- /package/dist/{git-A2IP32PQ.js.map → execute-R7AVOLNG.js.map} +0 -0
- /package/dist/{init-TO6MUXO4.js.map → git-LCG45YXD.js.map} +0 -0
- /package/dist/{permissions-G4XCAESF.js.map → init-DD6DBRC5.js.map} +0 -0
- /package/dist/{plan-OXAT344Q.js.map → permissions-NNNSRC4P.js.map} +0 -0
- /package/dist/{pr-UZHNKKZC.js.map → plan-XR6B7EM3.js.map} +0 -0
- /package/dist/{pr-review-Q4ACAWDM.js.map → pr-OSCNJCOO.js.map} +0 -0
- /package/dist/{prd-6CYEMLDY.js.map → pr-review-IKIYHFBO.js.map} +0 -0
- /package/dist/{recorder-2BAKPBRA.js.map → prd-HFDZJJQR.js.map} +0 -0
- /package/dist/{registry-XLHHYLTR.js.map → recorder-T7426CKV.js.map} +0 -0
- /package/dist/{review-LVZT2TMW.js.map → registry-DWRKD65A.js.map} +0 -0
- /package/dist/{routing-EK6RBZM4.js.map → repository-TABBRW2C.js.map} +0 -0
- /package/dist/{run-2RXJCJKT.js.map → review-JJHMQA2O.js.map} +0 -0
- /package/dist/{session-publisher-KAJQRHNZ.js.map → routing-FPNUVE7T.js.map} +0 -0
- /package/dist/{state-manager-UPHO2EA2.js.map → run-RLCURLLL.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/shell.ts","../src/resilience/policy.ts","../src/resilience/retry.ts","../src/utils/git.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport { type Options as ExecaOptions, execa } from 'execa';\nimport {\n type ClassifiedFailure,\n classify,\n type FailureSignal,\n type FailureSource,\n} from '../resilience/errors.js';\nimport type { RetryPolicy } from '../resilience/policy.js';\nimport { type RetryPolicyFor, withRetry } from '../resilience/retry.js';\n\nexport interface ExecResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n /**\n * The classified failure of the last attempt. Only ever set on the retry\n * path, and only when that attempt failed — a caller that passes no `retry`\n * gets exactly the three fields it has always got.\n */\n failure?: ClassifiedFailure;\n /** How many times the command actually ran. Only set on the retry path. */\n attempts?: number;\n}\n\n/** What `onRetryAttempt` is told once an attempt has produced a result. */\nexport interface RunRetryAttempt {\n /** 1-based number of the attempt that just finished. */\n attempt: number;\n result: ExecResult;\n /** `null` when the attempt succeeded. */\n failure: ClassifiedFailure | null;\n /** Whether another attempt follows this one. */\n willRetry: boolean;\n /** The wait before that next attempt; `0` when there is none. */\n delayMs: number;\n}\n\nexport interface RunOptions extends ExecaOptions {\n /** Skip global diagnostics when a non-zero exit is an expected probe result. */\n diagnostics?: boolean;\n /**\n * Opt in to retrying this invocation.\n *\n * Absent — the default, and what every call site of this project did before\n * this option existed — means one `execa` call with `reject: false` and no\n * extra attempt, byte for byte.\n *\n * Only pass a policy for a command whose non-zero exit means *it failed*.\n * A command whose non-zero exit is a legitimate answer (`git rev-parse\n * --verify --quiet`, `gh pr view` on a branch with no PR) is safe anyway —\n * an unclassifiable exit lands on `unknown`, which is not a retryable kind —\n * but the intent is worth being explicit about.\n *\n * A function instead of a policy resolves it from the failure that actually\n * happened, which is how one `gh` call gets the `network` budget for a DNS\n * blip and the `rate_limit` budget for a rate limit.\n */\n retry?: RetryPolicy | RetryPolicyFor;\n /** Overrides the subsystem inferred from `command` (`git`, `gh`). */\n source?: FailureSource;\n /**\n * Cuts a pending backoff short. Named apart from execa's own `cancelSignal`\n * because it governs the wait *between* attempts, not the child process.\n */\n retrySignal?: AbortSignal;\n /** Observe each attempt: log it, publish an event, persist the error. */\n onRetryAttempt?: (info: RunRetryAttempt) => void | Promise<void>;\n}\n\n/* ── which subsystem produced the failure ───────────────────────────────── */\n\nconst SOURCE_BY_COMMAND: Readonly<Record<string, FailureSource>> = {\n git: 'git',\n gh: 'github',\n};\n\nfunction inferSource(command: string): FailureSource {\n return SOURCE_BY_COMMAND[basename(command)] ?? 'internal';\n}\n\nfunction diagnoseCommandFailure(command: string, args: string[], result: ExecResult): void {\n if (result.exitCode === 0) return;\n void import('../storage/diagnostics.js').then(({ writeDiagnostic }) => {\n writeDiagnostic({\n level: 'warning',\n message: `Command failed: ${basename(command)}`,\n context: {\n command: basename(command),\n args,\n exitCode: result.exitCode,\n stderr: result.stderr.slice(0, 4_000),\n },\n });\n });\n}\n\n/* ── git invocations that are never repeated ────────────────────────────── */\n\n/**\n * `git` global options that swallow the token after them, so the subcommand of\n * `git -C /repo push --force` is `push` and not `/repo`.\n */\nconst GIT_GLOBAL_OPTIONS_WITH_VALUE: ReadonlySet<string> = new Set([\n '-C',\n '-c',\n '--git-dir',\n '--work-tree',\n '--namespace',\n '--exec-path',\n '--super-prefix',\n]);\n\n/**\n * git invocations no retry policy may repeat, whatever the caller asked for.\n *\n * `true` means the subcommand is never retried; a list means it is destructive\n * only when one of those tokens is present. This is the second of the Epic's\n * three limits — *no destructive operation is run automatically to fix state* —\n * enforced at the one chokepoint every `git` call of the project goes through.\n *\n * It errs on the side of not retrying: a sequencer operation left half-applied\n * (`rebase`, `cherry-pick`, `merge`, `am`, `revert`) is exactly the state a\n * blind second attempt turns into a lost commit, so those are absolute even\n * though a transient failure of one of them is conceivable.\n */\nconst DESTRUCTIVE_GIT_COMMANDS: Readonly<Record<string, true | readonly string[]>> = {\n rebase: true,\n 'cherry-pick': true,\n revert: true,\n merge: true,\n am: true,\n restore: true,\n 'filter-branch': true,\n gc: true,\n prune: true,\n 'update-ref': true,\n push: ['-f', '--force', '--force-with-lease', '--force-if-includes', '--delete', '--mirror'],\n reset: ['--hard', '--merge', '--keep'],\n clean: ['-f', '--force'],\n checkout: ['-f', '--force', '-B'],\n switch: ['-f', '--force', '--discard-changes'],\n branch: ['-d', '-D', '--delete', '-M'],\n tag: ['-d', '--delete', '-f', '--force'],\n stash: ['drop', 'clear', 'pop'],\n worktree: ['remove', 'prune'],\n submodule: ['deinit'],\n};\n\nfunction gitSubcommand(args: readonly string[]): { name: string; rest: readonly string[] } | null {\n for (let index = 0; index < args.length; index++) {\n const arg = args[index];\n if (arg === undefined) continue;\n if (GIT_GLOBAL_OPTIONS_WITH_VALUE.has(arg)) {\n index++;\n continue;\n }\n if (arg.startsWith('-')) continue;\n return { name: arg, rest: args.slice(index + 1) };\n }\n return null;\n}\n\n/**\n * Whether `rest` carries `token`. Long options also match their `=value` form,\n * and a short option also matches bundled into another (`git clean -fd` is\n * `-f -d`), which is how `-f` is actually written in practice.\n */\nfunction hasToken(rest: readonly string[], token: string): boolean {\n if (token.startsWith('--')) {\n return rest.some((arg) => arg === token || arg.startsWith(`${token}=`));\n }\n if (token.startsWith('-')) {\n const letter = token.slice(1);\n return rest.some((arg) => /^-[A-Za-z]+$/.test(arg) && arg.slice(1).includes(letter));\n }\n return rest.includes(token);\n}\n\n/** Whether this invocation may be retried at all, whatever the policy says. */\nexport function isRetryableInvocation(command: string, args: readonly string[]): boolean {\n if (basename(command) !== 'git') return true;\n\n const subcommand = gitSubcommand(args);\n if (subcommand === null) return true;\n\n const rule = DESTRUCTIVE_GIT_COMMANDS[subcommand.name];\n if (rule === undefined) return true;\n if (rule === true) return false;\n\n return !rule.some((token) => hasToken(subcommand.rest, token));\n}\n\n/* ── the failure signal ─────────────────────────────────────────────────── */\n\n/**\n * The fields execa puts on a failed result when `reject: false` is set. They\n * are not on its success type, hence the narrowing: `code` is where the spawn\n * errno lands (`ENOENT`, `ETIMEDOUT`, `ECONNRESET`, `EAI_AGAIN`), and\n * `originalMessage` is the only place the reason shows up when the child never\n * started and therefore wrote nothing to stderr.\n */\ninterface ExecaFailureFields {\n code?: unknown;\n signal?: unknown;\n timedOut?: unknown;\n originalMessage?: unknown;\n shortMessage?: unknown;\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction toFailureSignal(raw: unknown, result: ExecResult, source: FailureSource): FailureSignal {\n const fields = (raw ?? {}) as ExecaFailureFields;\n const errno = asString(fields.code);\n const signal = asString(fields.signal);\n // A command that never started has an empty stderr; execa's own message is\n // then the only evidence there is, so it stands in for the missing output.\n const stderr =\n result.stderr.trim() !== ''\n ? result.stderr\n : (asString(fields.originalMessage) ?? asString(fields.shortMessage) ?? '');\n\n return {\n source,\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr,\n ...(errno === undefined ? {} : { errno }),\n ...(signal === undefined ? {} : { signal }),\n ...(fields.timedOut === true ? { timedOut: true } : {}),\n };\n}\n\n/* ── the executor ───────────────────────────────────────────────────────── */\n\nasync function execOnce(\n command: string,\n args: string[],\n options: ExecaOptions,\n): Promise<{ result: ExecResult; raw: unknown }> {\n const raw = await execa(command, args, {\n reject: false,\n ...options,\n });\n\n return {\n raw,\n result: {\n stdout: raw.stdout?.toString() ?? '',\n stderr: raw.stderr?.toString() ?? '',\n exitCode: raw.exitCode ?? 1,\n },\n };\n}\n\n/**\n * Execute a command with arguments and capture its output.\n * Uses execa which calls execFile internally (no shell injection risk).\n * Does not throw on non-zero exit codes.\n *\n * With `options.retry` it becomes the retrying chokepoint every `gh` and `git`\n * call of the project already passes through: the failure is classified from\n * structured evidence (errno, signal, `timedOut`, exit code — text last) and\n * handed to `withRetry`, the single retry executor. Without it nothing changes.\n */\nexport async function run(\n command: string,\n args: string[] = [],\n options?: RunOptions,\n): Promise<ExecResult> {\n const {\n retry,\n source,\n retrySignal,\n onRetryAttempt,\n diagnostics = true,\n ...execaOptions\n } = options ?? {};\n\n if (retry === undefined || !isRetryableInvocation(command, args)) {\n const result = (await execOnce(command, args, execaOptions)).result;\n if (diagnostics) diagnoseCommandFailure(command, args, result);\n return result;\n }\n\n const failureSource = source ?? inferSource(command);\n\n const outcome = await withRetry(\n async () => {\n const { result, raw } = await execOnce(command, args, execaOptions);\n const failure =\n result.exitCode === 0 ? null : classify(toFailureSignal(raw, result, failureSource));\n return { result, failure };\n },\n {\n policy: retry,\n evaluate: (attempt) => attempt.failure,\n ...(retrySignal === undefined ? {} : { signal: retrySignal }),\n ...(onRetryAttempt === undefined\n ? {}\n : {\n onAttempt: (info) =>\n onRetryAttempt({\n attempt: info.attempt,\n result: info.value.result,\n failure: info.value.failure,\n willRetry: info.willRetry,\n delayMs: info.delayMs,\n }),\n }),\n },\n );\n\n const result = {\n ...outcome.value.result,\n attempts: outcome.attempts,\n ...(outcome.failure === null ? {} : { failure: outcome.failure }),\n };\n if (diagnostics) diagnoseCommandFailure(command, args, result);\n return result;\n}\n","/**\n * Retry policy: how long to wait, how many times, and what to do when the\n * budget runs out.\n *\n * `errors.ts` answers *what went wrong*; this module answers *what to do about\n * it*. It is pure — no I/O, no clock of its own, no knowledge of phases — so\n * every decision here is reproducible from its arguments. `retry.ts` is the\n * only executor that acts on what this module returns.\n *\n * The run-level state machine lives here too, for the same reason: whether a\n * run may go from `blocked` to `running` is a policy question, and there must\n * be exactly one answer to it in the codebase.\n *\n * The invariants of this layer are in `src/resilience/AGENTS.md`.\n */\n\nimport { type FailureKind, requiresHumanAction } from './errors.js';\n\n/* ── the policy ─────────────────────────────────────────────────────────── */\n\n/** What to do with the provider once a kind keeps failing. */\nexport type FailoverMode = 'never' | 'after_attempts' | 'immediate';\n\n/** What a failure becomes once the attempt budget is spent. */\nexport type ExhaustedAction = 'fail' | 'block';\n\nexport interface RetryPolicy {\n /** `0` means the kind is never retried by this layer. */\n maxAttempts: number;\n initialDelayMs: number;\n /** The ceiling of the backoff — honoured even under `retryForever`. */\n maxDelayMs: number;\n backoffFactor: number;\n jitter: 'none' | 'full';\n retryForever: boolean;\n failover: FailoverMode;\n /** Attempts to burn before `failover: 'after_attempts'` kicks in. */\n failoverAfterAttempts: number;\n onExhausted: ExhaustedAction;\n}\n\n/** A partial policy, as a configuration layer supplies it. */\nexport type RetryPolicyOverride = Partial<RetryPolicy>;\n\n/* ── configuration ──────────────────────────────────────────────────────── */\n\nexport type ResilienceProfile = 'default' | 'continuous';\n\n/**\n * The configuration keys of `resilience.retry`, one per `FailureKind` in the\n * camelCase spelling the JSON uses.\n */\nexport type RetryConfigKey =\n | 'network'\n | 'timeout'\n | 'stalled'\n | 'rateLimit'\n | 'providerDown'\n | 'providerCrash'\n | 'authentication'\n | 'configuration'\n | 'repositoryState'\n | 'taskExecution'\n | 'internal'\n | 'unknown';\n\nconst CONFIG_KEYS: Readonly<Record<FailureKind, RetryConfigKey>> = {\n network: 'network',\n timeout: 'timeout',\n stalled: 'stalled',\n rate_limit: 'rateLimit',\n provider_down: 'providerDown',\n provider_crash: 'providerCrash',\n authentication: 'authentication',\n configuration: 'configuration',\n repository_state: 'repositoryState',\n task_execution: 'taskExecution',\n internal: 'internal',\n unknown: 'unknown',\n};\n\n/** The configuration key `resilience.retry` uses for `kind`. */\nexport function retryConfigKey(kind: FailureKind): RetryConfigKey {\n return CONFIG_KEYS[kind];\n}\n\n/**\n * Every key `resilience.retry` accepts, for the layers that have to iterate\n * them (the schema in `storage/schemas.ts`, the merge in `config.ts`). Derived\n * from `CONFIG_KEYS` rather than written a second time, so a new `FailureKind`\n * cannot reach the configuration surface half-declared.\n */\nexport const RETRY_CONFIG_KEYS: readonly RetryConfigKey[] = Object.values(CONFIG_KEYS);\n\n/**\n * The slice of the `resilience` configuration this module reads. The full key\n * (providers, queue, watchdog, journal, decompose) is a superset of this, and\n * satisfies it structurally.\n */\nexport interface PolicyConfig {\n profile?: ResilienceProfile;\n /**\n * Whether a credential failure may migrate to another provider. Explicit on\n * purpose, never a default: switching provider because the main one lost its\n * credential hides exactly what the user needs to be told.\n */\n failoverOnAuth?: boolean;\n retry?: Partial<Record<RetryConfigKey, RetryPolicyOverride>>;\n}\n\n/* ── the defaults ───────────────────────────────────────────────────────── */\n\nconst SECOND = 1000;\n\nfunction policy(overrides: RetryPolicyOverride): RetryPolicy {\n return {\n maxAttempts: 0,\n initialDelayMs: 0,\n maxDelayMs: 0,\n backoffFactor: 2,\n jitter: 'full',\n retryForever: false,\n failover: 'never',\n failoverAfterAttempts: 2,\n onExhausted: 'fail',\n ...overrides,\n };\n}\n\n/**\n * The table of the PRD, verbatim. Changing a number here changes documented\n * behaviour: `policy.test.ts` asserts this table cell by cell on purpose.\n */\nconst BASE_POLICIES: Readonly<Record<FailureKind, RetryPolicy>> = {\n network: policy({ maxAttempts: 8, initialDelayMs: 2 * SECOND, maxDelayMs: 120 * SECOND }),\n timeout: policy({\n maxAttempts: 2,\n initialDelayMs: 30 * SECOND,\n maxDelayMs: 120 * SECOND,\n failover: 'after_attempts',\n }),\n stalled: policy({\n maxAttempts: 2,\n initialDelayMs: 15 * SECOND,\n maxDelayMs: 15 * SECOND,\n failover: 'after_attempts',\n }),\n rate_limit: policy({\n maxAttempts: 6,\n initialDelayMs: 60 * SECOND,\n maxDelayMs: 900 * SECOND,\n failover: 'after_attempts',\n }),\n provider_down: policy({\n maxAttempts: 4,\n initialDelayMs: 10 * SECOND,\n maxDelayMs: 300 * SECOND,\n failover: 'after_attempts',\n }),\n provider_crash: policy({\n maxAttempts: 3,\n initialDelayMs: 5 * SECOND,\n maxDelayMs: 60 * SECOND,\n failover: 'after_attempts',\n }),\n authentication: policy({ maxAttempts: 0, onExhausted: 'block' }),\n configuration: policy({ maxAttempts: 0 }),\n repository_state: policy({ maxAttempts: 0, onExhausted: 'block' }),\n task_execution: policy({ maxAttempts: 0 }),\n internal: policy({ maxAttempts: 2, initialDelayMs: 5 * SECOND, maxDelayMs: 5 * SECOND }),\n unknown: policy({ maxAttempts: 2, initialDelayMs: 5 * SECOND, maxDelayMs: 5 * SECOND }),\n};\n\n/**\n * The `continuous` profile — autonomous, long-running execution. It only ever\n * *widens* a budget: what is not retryable under `default` is not retryable\n * here either.\n */\nconst CONTINUOUS_OVERRIDES: Readonly<Partial<Record<FailureKind, RetryPolicyOverride>>> = {\n network: { retryForever: true },\n timeout: { maxAttempts: 3 },\n stalled: { maxAttempts: 3 },\n rate_limit: { retryForever: true },\n provider_down: { retryForever: true, failover: 'after_attempts' },\n provider_crash: { maxAttempts: 5 },\n};\n\n/**\n * Resolve the policy of a `FailureKind`: base table → profile → user\n * configuration, in that order.\n *\n * The kinds that need a human (`authentication`, `configuration`,\n * `repository_state`, `task_execution`) are clamped **after** the user layer:\n * no configuration, no profile and no `retryForever` can buy them an attempt.\n * That clamp is the golden rule of `AGENTS.md` made unbypassable.\n */\nexport function resolvePolicy(kind: FailureKind, config: PolicyConfig = {}): RetryPolicy {\n const base = BASE_POLICIES[kind];\n const profile = config.profile === 'continuous' ? CONTINUOUS_OVERRIDES[kind] : undefined;\n const user = config.retry?.[retryConfigKey(kind)];\n\n const resolved: RetryPolicy = { ...base, ...profile, ...user };\n\n if (!requiresHumanAction(kind)) return sanitize(resolved);\n\n return sanitize({\n ...resolved,\n maxAttempts: 0,\n retryForever: false,\n failover:\n kind === 'authentication' && config.failoverOnAuth === true ? resolved.failover : 'never',\n });\n}\n\n/** Guard against a configuration layer supplying a number that breaks the math. */\nfunction sanitize(value: RetryPolicy): RetryPolicy {\n return {\n ...value,\n maxAttempts: Math.max(0, Math.trunc(value.maxAttempts)),\n initialDelayMs: Math.max(0, value.initialDelayMs),\n maxDelayMs: Math.max(0, value.maxDelayMs),\n backoffFactor: value.backoffFactor >= 1 ? value.backoffFactor : 1,\n failoverAfterAttempts: Math.max(1, Math.trunc(value.failoverAfterAttempts)),\n };\n}\n\n/* ── the decisions ──────────────────────────────────────────────────────── */\n\n/**\n * Whether another attempt is allowed after `attemptsMade` attempts have\n * already failed.\n */\nexport function shouldRetry(policy: RetryPolicy, attemptsMade: number): boolean {\n if (policy.maxAttempts <= 0) return false;\n if (policy.retryForever) return true;\n return attemptsMade < policy.maxAttempts;\n}\n\n/** Whether the next attempt should be handed to a different provider. */\nexport function shouldFailover(policy: RetryPolicy, attemptsMade: number): boolean {\n if (policy.failover === 'never') return false;\n if (policy.failover === 'immediate') return true;\n return attemptsMade >= policy.failoverAfterAttempts;\n}\n\nexport interface DelayOptions {\n /** Injectable RNG, so the jitter is deterministic under test. */\n random?: () => number;\n /** What the server asked for, when it asked (`Retry-After`). */\n retryAfterMs?: number;\n}\n\n/**\n * The delay before attempt number `attemptsMade + 1`.\n *\n * `ceiling = min(maxDelayMs, initialDelayMs * backoffFactor^(attemptsMade-1))`,\n * and full jitter — the default — draws uniformly from `[0, ceiling)`. The\n * ceiling applies under `retryForever` exactly as it does otherwise: waiting\n * forever is allowed, hammering is not.\n *\n * A server-supplied `Retry-After` wins outright, un-jittered and uncapped: the\n * point of honouring it is not to come back before it says, and capping it by\n * `maxDelayMs` would do precisely that.\n */\nexport function computeDelayMs(\n policy: RetryPolicy,\n attemptsMade: number,\n options: DelayOptions = {},\n): number {\n if (options.retryAfterMs !== undefined && options.retryAfterMs >= 0) {\n return Math.round(options.retryAfterMs);\n }\n\n const exponent = Math.max(0, attemptsMade - 1);\n const growth = policy.initialDelayMs * policy.backoffFactor ** exponent;\n const ceiling = Math.min(policy.maxDelayMs, growth);\n if (ceiling <= 0) return 0;\n\n if (policy.jitter === 'none') return Math.round(ceiling);\n\n const random = options.random ?? Math.random;\n return Math.round(random() * ceiling);\n}\n\n/* ── the abortable delay ────────────────────────────────────────────────── */\n\n/**\n * Wait `ms`, unless `signal` fires first.\n *\n * Resolves `true` when the full delay elapsed and `false` when it was cut\n * short — a caller that waited fifteen minutes and a caller that was\n * interrupted must not take the same next step. It never throws: an abort is\n * an expected outcome here, not an error.\n */\nexport function abortableDelay(\n ms: number,\n options: { signal?: AbortSignal } = {},\n): Promise<boolean> {\n const { signal } = options;\n if (signal?.aborted === true) return Promise.resolve(false);\n if (ms <= 0) return Promise.resolve(true);\n\n return new Promise((resolve) => {\n const onAbort = () => {\n clearTimeout(timer);\n resolve(false);\n };\n\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve(true);\n }, ms);\n\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/* ── the run state machine ──────────────────────────────────────────────── */\n\n/**\n * The state of a run — a queued issue in `execution-plan.json`, or the single\n * issue of a `tasks.json`.\n */\nexport type RunStatus =\n | 'queued'\n | 'running'\n | 'waiting'\n | 'retrying'\n | 'paused'\n | 'blocked'\n | 'failed'\n | 'completed'\n | 'cancelled';\n\n/**\n * Every legal transition, in one place.\n *\n * `completed` and `cancelled` are terminal: nothing leaves them. `blocked` has\n * exits, but none the pipeline may take on its own — see `canTransition`.\n */\nexport const RUN_TRANSITIONS: Readonly<Record<RunStatus, readonly RunStatus[]>> = {\n queued: ['running', 'blocked', 'cancelled'],\n running: ['waiting', 'retrying', 'paused', 'blocked', 'failed', 'completed', 'cancelled'],\n waiting: ['running', 'retrying', 'paused', 'blocked', 'failed', 'cancelled'],\n retrying: ['running', 'waiting', 'paused', 'blocked', 'failed', 'cancelled'],\n paused: ['running', 'blocked', 'cancelled'],\n blocked: ['running', 'cancelled'],\n failed: ['running', 'cancelled'],\n completed: [],\n cancelled: [],\n};\n\n/** Nothing leaves these, by anyone. */\nconst TERMINAL_STATUSES: ReadonlySet<RunStatus> = new Set<RunStatus>(['completed', 'cancelled']);\n\n/** Whether `status` is terminal. */\nexport function isTerminalRunStatus(status: RunStatus): boolean {\n return TERMINAL_STATUSES.has(status);\n}\n\n/** Who is attempting the transition. The pipeline is the default. */\nexport type TransitionActor = 'pipeline' | 'human';\n\n/**\n * Whether `from → to` is legal for `actor`.\n *\n * `blocked` exists precisely to stop the machine until someone looks at it, so\n * the pipeline may enter it but never leave it: only `actor: 'human'` — a\n * `resume`, a `cancel` — can. A pipeline able to unblock itself would spin on\n * the same missing credential forever.\n */\nexport function canTransition(\n from: RunStatus,\n to: RunStatus,\n options: { actor?: TransitionActor } = {},\n): boolean {\n if (!RUN_TRANSITIONS[from].includes(to)) return false;\n if (from === 'blocked' && (options.actor ?? 'pipeline') !== 'human') return false;\n return true;\n}\n","/**\n * The single retry executor of the project.\n *\n * `errors.ts` says *what went wrong*, `policy.ts` says *what to do about it*,\n * and this module is the only place that actually does it: one loop, one\n * backoff, one veto. Before it existed the codebase had two independent retry\n * loops — `core/phase-runner.ts` for single-shot phases and the `execute` loop\n * of `core/engine.ts` — with their own counters, their own delays and no way\n * to keep them in step. Both now delegate here.\n *\n * The loop performs no I/O and knows nothing about phases, sessions or\n * publishers: everything observable is handed back through `onAttempt`, so the\n * caller keeps ownership of its own logging, events and persistence.\n *\n * The invariants of this layer are in `src/resilience/AGENTS.md`.\n */\n\nimport { type ClassifiedFailure, requiresHumanAction } from './errors.js';\nimport { abortableDelay, computeDelayMs, type RetryPolicy, shouldRetry } from './policy.js';\n\n/** What `onAttempt` is told once an attempt has produced a value. */\nexport interface RetryAttemptInfo<T> {\n /** 1-based number of the attempt that just finished. */\n attempt: number;\n /** Whatever `fn` returned, failure or not. */\n value: T;\n /** `null` when the attempt succeeded. */\n failure: ClassifiedFailure | null;\n /** Whether another attempt follows this one. */\n willRetry: boolean;\n /** The wait before that next attempt; `0` when there is none. */\n delayMs: number;\n}\n\n/**\n * A policy chosen from the failure that just happened.\n *\n * The kind is only known *after* an attempt, so a call site that spans several\n * kinds — every `gh` invocation is a network failure, a rate limit or an\n * authentication failure depending on the day — hands over the resolver rather\n * than one frozen policy. `resolvePolicy(failure.kind, config)` is what a\n * caller normally passes.\n */\nexport type RetryPolicyFor = (failure: ClassifiedFailure) => RetryPolicy;\n\nexport interface WithRetryOptions<T> {\n /** One policy, or one chosen per classified failure. */\n policy: RetryPolicy | RetryPolicyFor;\n /**\n * The verdict on one attempt's value: `null` for success, a classified\n * failure otherwise.\n *\n * It belongs to the caller because only the caller knows what a failure\n * looks like in its own return type — an exit code, an `ok: false`, a\n * rejected HTTP response. Callers holding structured evidence should build\n * the failure with `classify()` rather than re-deriving it from text.\n */\n evaluate: (value: T, attempt: number) => ClassifiedFailure | null;\n /** Cuts a pending backoff short; see `abortableDelay`. */\n signal?: AbortSignal;\n /**\n * Called once per attempt, before the backoff, with the decision already\n * taken. This is where a caller publishes its `retry` event, prints, or\n * persists an error — awaited, so those writes finish before the wait.\n */\n onAttempt?: (info: RetryAttemptInfo<T>) => void | Promise<void>;\n /** Injectable RNG for the jitter, so a test can assert the exact curve. */\n random?: () => number;\n /** Injectable wait, so a test never sleeps for real. */\n delay?: (ms: number, options: { signal?: AbortSignal }) => Promise<boolean>;\n}\n\nexport interface RetryOutcome<T> {\n /** The value of the last attempt — the successful one, or the final failure. */\n value: T;\n /** How many times `fn` ran. */\n attempts: number;\n /** `null` when the last attempt succeeded. */\n failure: ClassifiedFailure | null;\n /** The failure was retryable and the budget ran out. */\n exhausted: boolean;\n /** `signal` fired during a backoff, so the next attempt never happened. */\n aborted: boolean;\n}\n\n/**\n * Run `fn` until it succeeds, until the policy's budget is spent, or until\n * `signal` fires.\n *\n * Three separate conditions have to hold for another attempt, and all three\n * are checked here rather than by the caller:\n *\n * 1. the failure is retryable at all (`ClassifiedFailure.retryable`);\n * 2. the kind is not one that needs a human — `task_execution`,\n * `authentication`, `configuration` and `repository_state` are vetoed\n * outright, whatever the policy says and even under `retryForever`. This is\n * the golden rule of `AGENTS.md`, enforced a second time here: a caller can\n * hand-build a `RetryPolicy` without going through `resolvePolicy()`, so\n * the clamp there is not on its own enough;\n * 3. the policy still has budget (`shouldRetry`).\n */\nexport async function withRetry<T>(\n fn: (attempt: number) => Promise<T>,\n options: WithRetryOptions<T>,\n): Promise<RetryOutcome<T>> {\n const { policy, evaluate, signal, onAttempt, random } = options;\n const delay = options.delay ?? abortableDelay;\n const policyFor: RetryPolicyFor = typeof policy === 'function' ? policy : () => policy;\n\n for (let attempt = 1; ; attempt++) {\n const value = await fn(attempt);\n const failure = evaluate(value, attempt);\n\n if (failure === null) {\n await onAttempt?.({ attempt, value, failure, willRetry: false, delayMs: 0 });\n return { value, attempts: attempt, failure: null, exhausted: false, aborted: false };\n }\n\n const active = policyFor(failure);\n const eligible = failure.retryable && !requiresHumanAction(failure.kind);\n const willRetry = eligible && shouldRetry(active, attempt);\n const delayMs = willRetry\n ? computeDelayMs(active, attempt, { random, retryAfterMs: failure.retryAfterMs })\n : 0;\n\n await onAttempt?.({ attempt, value, failure, willRetry, delayMs });\n\n if (!willRetry) {\n return { value, attempts: attempt, failure, exhausted: eligible, aborted: false };\n }\n\n if (!(await delay(delayMs, { signal }))) {\n return { value, attempts: attempt, failure, exhausted: false, aborted: true };\n }\n }\n}\n\n/**\n * A fixed policy in the shape the two legacy call sites express their settings\n * in: a number of attempts and a base/max delay in seconds.\n *\n * Deliberately un-jittered. Both call sites have always used a bare\n * `base * 2^(n-1)` and both publish that number in a `retry` event and print\n * it; adding jitter here would change today's behaviour with no configuration\n * asking for it. Jitter arrives with the `resilience` key that configures it.\n */\nexport function fixedBackoffPolicy(\n maxAttempts: number,\n baseSeconds: number,\n maxSeconds: number,\n overrides: Partial<RetryPolicy> = {},\n): RetryPolicy {\n return {\n maxAttempts,\n initialDelayMs: baseSeconds * 1000,\n maxDelayMs: maxSeconds * 1000,\n backoffFactor: 2,\n jitter: 'none',\n retryForever: false,\n failover: 'never',\n failoverAfterAttempts: 2,\n onExhausted: 'fail',\n ...overrides,\n };\n}\n","import { type ExecResult, run } from './shell.js';\n\n/**\n * Get the root directory of the current git repository.\n * Throws if not inside a git repository.\n */\nexport async function getProjectRoot(): Promise<string> {\n const result = await run('git', ['rev-parse', '--show-toplevel']);\n\n if (result.exitCode !== 0) {\n throw new Error(\n 'Not inside a git repository. Please run issue-flow from within a git project.',\n );\n }\n\n return result.stdout.trim();\n}\n\n/**\n * Get the current git branch name.\n * Returns an empty string if in detached HEAD state.\n */\nexport async function getCurrentBranch(): Promise<string> {\n const result = await run('git', ['branch', '--show-current']);\n\n if (result.exitCode !== 0) {\n throw new Error(\n 'Failed to detect git branch. Ensure git is installed and you are inside a repository.',\n );\n }\n\n return result.stdout.trim();\n}\n\n/** Whether a local branch exists, without consulting or mutating remotes. */\nexport async function localBranchExists(name: string, cwd?: string): Promise<boolean> {\n if (name.trim() === '') return false;\n const result = await run('git', ['show-ref', '--verify', '--quiet', `refs/heads/${name}`], {\n ...(cwd === undefined ? {} : { cwd }),\n diagnostics: false,\n });\n return result.exitCode === 0;\n}\n\nexport interface CommitInfo {\n hash: string;\n subject: string;\n committedAt?: string | null;\n storyId?: string | null;\n}\n\n/**\n * Get the base branch of the repository: the remote HEAD (origin/HEAD) when\n * available, otherwise the first of main/master that exists locally.\n * Never throws; defaults to 'main'.\n */\nexport async function getBaseBranch(): Promise<string> {\n const remoteHead = await run('git', ['symbolic-ref', '--short', 'refs/remotes/origin/HEAD'], {\n diagnostics: false,\n });\n if (remoteHead.exitCode === 0) {\n const name = remoteHead.stdout.trim().replace(/^origin\\//, '');\n if (name) return name;\n }\n\n for (const candidate of ['main', 'master']) {\n const check = await run(\n 'git',\n ['rev-parse', '--verify', '--quiet', `refs/heads/${candidate}`],\n { diagnostics: false },\n );\n if (check.exitCode === 0) return candidate;\n }\n\n return 'main';\n}\n\n/**\n * Get the URL of the `origin` remote.\n * Never throws: a missing remote, a non-zero exit code, an empty stdout or a\n * git binary that cannot even be spawned all resolve to `null` — the same\n * discipline as {@link getBaseBranch}, so callers can treat \"no remote\" as an\n * ordinary state instead of an error path.\n *\n * `cwd` selects which repository is queried; omitting it falls back to\n * `process.cwd()`, which is almost never what a caller resolving a specific\n * `projectRoot` wants — pass it explicitly whenever one is available.\n */\nexport async function getRemoteUrl(cwd?: string): Promise<string | null> {\n let result: ExecResult;\n try {\n result = await run('git', ['remote', 'get-url', 'origin'], { cwd, diagnostics: false });\n } catch {\n return null;\n }\n\n if (result.exitCode !== 0) return null;\n\n const url = result.stdout.trim();\n return url === '' ? null : url;\n}\n\n/**\n * Get the abbreviated hash of the current HEAD commit.\n * Never throws, same discipline as {@link getRemoteUrl}: a repository with no\n * commits yet, a non-zero exit code, an empty stdout or a git binary that\n * cannot be spawned all resolve to `null`, so callers can treat \"no HEAD\" as\n * an ordinary state instead of an error path.\n *\n * `cwd` selects which repository is queried; omitting it falls back to\n * `process.cwd()`.\n */\nexport async function getHeadCommit(cwd?: string): Promise<string | null> {\n let result: ExecResult;\n try {\n result = await run('git', ['rev-parse', '--short', 'HEAD'], { cwd, diagnostics: false });\n } catch {\n return null;\n }\n\n if (result.exitCode !== 0) return null;\n\n const hash = result.stdout.trim();\n return hash === '' ? null : hash;\n}\n\n/**\n * Reduce a git remote URL to a canonical `host/path` identity, so that every\n * way of addressing the same repository collapses to the same string:\n *\n * ```\n * https://github.com/org/repo.git -> github.com/org/repo\n * git@github.com:org/repo.git -> github.com/org/repo\n * ssh://git@github.com:22/org/repo.git -> github.com/org/repo\n * https://user:token@github.com/org/repo -> github.com/org/repo\n * https://github.com/Org/Repo/ -> github.com/org/repo\n * ```\n *\n * Pure function: it never shells out, so it is testable without a git\n * repository. Returns `null` when no host and path can be extracted.\n *\n * Known limitation: both host and path are lowercased. Hostnames are\n * case-insensitive by definition, but repository paths are case-sensitive on\n * some self-hosted servers — so `host/org/Repo` and `host/org/repo` normalize\n * to the same identity even if that server considers them distinct. This is a\n * deliberate trade: matching the same repository across clones (where users\n * routinely type the wrong case) matters more than telling apart two repos\n * whose paths differ only by case.\n */\nexport function normalizeRemoteUrl(url: string | null | undefined): string | null {\n if (typeof url !== 'string') return null;\n\n const trimmed = url.trim();\n if (trimmed === '') return null;\n\n let authority: string;\n let path: string;\n\n const scheme = /^[a-zA-Z][a-zA-Z0-9+.-]*:\\/\\//.exec(trimmed);\n if (scheme) {\n const rest = trimmed.slice(scheme[0].length);\n const slash = rest.indexOf('/');\n if (slash === -1) return null;\n authority = rest.slice(0, slash);\n path = rest.slice(slash + 1);\n } else {\n // scp-like syntax: [user@]host:path — everything after the first colon is\n // the path, which is how git itself reads it (no port is possible here).\n const colon = trimmed.indexOf(':');\n if (colon === -1) return null;\n authority = trimmed.slice(0, colon);\n path = trimmed.slice(colon + 1);\n }\n\n // Drop embedded credentials (user, user:token) and the ssh user.\n const at = authority.lastIndexOf('@');\n if (at !== -1) authority = authority.slice(at + 1);\n\n const host = authority.replace(/:\\d+$/, '').toLowerCase();\n if (host === '') return null;\n\n const normalizedPath = path\n .replace(/[?#].*$/, '')\n .replace(/\\/+/g, '/')\n .replace(/^\\/+|\\/+$/g, '')\n .replace(/\\.git$/i, '')\n .replace(/\\/+$/, '')\n .toLowerCase();\n if (normalizedPath === '') return null;\n\n return `${host}/${normalizedPath}`;\n}\n\n/**\n * Remove Basic-Auth-style credentials (`user:token@`, `user@`) embedded in an\n * `http(s)` remote URL, without touching anything else about it — case, port,\n * the `.git` suffix, query string and trailing slashes are all preserved.\n *\n * Deliberately scoped to `http`/`https`: that is the only place a git remote\n * can carry a real secret (a PAT is routinely embedded as\n * `https://x-access-token:TOKEN@host/...` by CI and automation), and the URL\n * stays a valid, clonable remote once the userinfo is gone. SSH has no\n * equivalent syntax — both `ssh://user@host/path` and the scp-like shorthand\n * `user@host:path` require that user segment to connect at all (it is almost\n * always the fixed, non-secret `git` service account), so this function\n * leaves any other scheme, the scp-like form and local paths untouched.\n *\n * Unlike {@link normalizeRemoteUrl}, which collapses a URL to a lossy\n * `host/path` identity, this keeps the URL \"as configured\" — it exists for\n * surfaces (like the web monitor's `repository.remoteUrl`) that want to show\n * the real remote, minus whatever secret an HTTPS token commonly embeds in\n * it.\n *\n * Pure function, never throws. Returns `null` for a nullish or empty input.\n */\nexport function stripRemoteUrlCredentials(url: string | null | undefined): string | null {\n if (typeof url !== 'string') return null;\n\n const trimmed = url.trim();\n if (trimmed === '') return null;\n\n const httpScheme = /^https?:\\/\\//i.exec(trimmed);\n if (!httpScheme) return trimmed;\n\n const rest = trimmed.slice(httpScheme[0].length);\n const slash = rest.indexOf('/');\n const authority = slash === -1 ? rest : rest.slice(0, slash);\n const remainder = slash === -1 ? '' : rest.slice(slash);\n\n const at = authority.lastIndexOf('@');\n if (at === -1) return trimmed;\n return `${httpScheme[0]}${authority.slice(at + 1)}${remainder}`;\n}\n\n/**\n * List commits on HEAD that are not on the given base branch (base..HEAD),\n * most recent first. Never throws; returns [] when the range cannot be\n * resolved (e.g. unknown base branch or shallow clone).\n */\nexport async function getCommitsSince(base: string): Promise<CommitInfo[]> {\n const result = await run('git', [\n 'log',\n '--pretty=format:%h%x09%cI%x09%s%x09%b%x1e',\n `${base}..HEAD`,\n ]);\n if (result.exitCode !== 0) return [];\n\n if (!result.stdout.includes('\\x1e')) {\n return result.stdout\n .split('\\n')\n .filter((line) => line.trim() !== '')\n .map((line) => {\n const tab = line.indexOf('\\t');\n return tab === -1\n ? { hash: line.trim(), subject: '' }\n : { hash: line.slice(0, tab), subject: line.slice(tab + 1) };\n });\n }\n const records = result.stdout.split('\\x1e');\n return records.flatMap((raw) => {\n const record = raw.trim();\n if (record === '') return [];\n const fields = record.split('\\t');\n const [hash = '', committedAt = '', subject = '', ...bodyParts] = fields;\n const body = bodyParts.join('\\t');\n const storyId = /(?:Story:\\s*|\\[)(US-\\d+)/i.exec(`${subject}\\n${body}`)?.[1] ?? null;\n return [\n {\n hash,\n subject,\n committedAt: committedAt || null,\n storyId: storyId?.toUpperCase() ?? null,\n },\n ];\n });\n}\n\n/* ── repository preflight ───────────────────────────────────────────────── */\n\n/**\n * A repository state that stops the pipeline.\n *\n * The whole point of this type is that it is *reported*, never acted on: the\n * second explicit limit of the resilience Epic is that **no destructive\n * operation is ever run automatically to fix state**. A repository mid-rebase\n * is a person's unfinished work, and an `--abort` issued by a tool at 3am is\n * indistinguishable from data loss.\n */\nexport type PreflightBlockKind =\n | 'rebase_in_progress'\n | 'merge_in_progress'\n | 'cherry_pick_in_progress'\n | 'revert_in_progress'\n | 'unmerged_paths'\n | 'detached_head'\n | 'branch_mismatch'\n | 'dirty_tree';\n\nexport interface PreflightBlock {\n kind: PreflightBlockKind;\n /** What is wrong, in one line. */\n message: string;\n /** The command a human would run. Printed, never executed. */\n suggestion: string;\n}\n\nexport interface PreflightResult {\n ok: boolean;\n blocks: PreflightBlock[];\n /** Current branch, or `null` on a detached HEAD. */\n branch: string | null;\n /** Whether the working tree has uncommitted changes. */\n dirty: boolean;\n}\n\n/** What the caller is about to do, which decides how a dirty tree is read. */\nexport type PreflightIntent =\n | /** Continuing the phase that produced the changes. */ 'resume-same-phase'\n | /** Starting a different phase, or a different issue. */ 'new-phase';\n\nexport interface PreflightOptions {\n /** Branch the plan says this work belongs to. `null` skips the check. */\n expectedBranch?: string | null;\n /** Default `new-phase`, the strict reading. */\n intent?: PreflightIntent;\n cwd?: string;\n}\n\n/** `git rev-parse --verify --quiet <ref>` — exit 0 means the ref exists. */\nasync function refExists(ref: string, cwd?: string): Promise<boolean> {\n const result = await run('git', ['rev-parse', '--verify', '--quiet', ref], {\n ...(cwd === undefined ? {} : { cwd }),\n diagnostics: false,\n });\n return result.exitCode === 0;\n}\n\n/** The in-progress sequencer operations, by the ref each one leaves behind. */\nconst SEQUENCER_REFS: readonly {\n ref: string;\n kind: PreflightBlockKind;\n name: string;\n suggestion: string;\n}[] = [\n {\n ref: 'REBASE_HEAD',\n kind: 'rebase_in_progress',\n name: 'a rebase',\n suggestion: 'git rebase --continue (or git rebase --abort)',\n },\n {\n ref: 'MERGE_HEAD',\n kind: 'merge_in_progress',\n name: 'a merge',\n suggestion: 'git merge --continue (or git merge --abort)',\n },\n {\n ref: 'CHERRY_PICK_HEAD',\n kind: 'cherry_pick_in_progress',\n name: 'a cherry-pick',\n suggestion: 'git cherry-pick --continue (or git cherry-pick --abort)',\n },\n {\n ref: 'REVERT_HEAD',\n kind: 'revert_in_progress',\n name: 'a revert',\n suggestion: 'git revert --continue (or git revert --abort)',\n },\n];\n\n/**\n * Describe the repository and decide whether it is safe to write to it.\n *\n * Every check is a *read*: `rev-parse`, `symbolic-ref`, `diff --name-only`,\n * `status --porcelain`, `branch --show-current`. Nothing here checks anything\n * out, resets anything, aborts anything or stashes anything — not on a resume,\n * not under a continuous profile, not ever. A repository in an ambiguous state\n * escalates to a human, which is the only correct answer for a tool that did\n * not put it there.\n *\n * A **dirty tree is not always a problem**: resuming the phase that produced\n * those changes is exactly the case where uncommitted work is expected. It\n * blocks only when the run is about to move on to something else, where the\n * changes would be carried into work they do not belong to.\n */\nexport async function preflightRepository(\n options: PreflightOptions = {},\n): Promise<PreflightResult> {\n const { cwd, expectedBranch, intent = 'new-phase' } = options;\n const at = cwd === undefined ? {} : { cwd };\n const blocks: PreflightBlock[] = [];\n\n for (const sequencer of SEQUENCER_REFS) {\n if (await refExists(sequencer.ref, cwd)) {\n blocks.push({\n kind: sequencer.kind,\n message: `The repository is in the middle of ${sequencer.name} (${sequencer.ref} is present).`,\n suggestion: sequencer.suggestion,\n });\n }\n }\n\n const unmerged = await run('git', ['diff', '--name-only', '--diff-filter=U'], at);\n const conflicted = unmerged.stdout\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line !== '');\n if (conflicted.length > 0) {\n blocks.push({\n kind: 'unmerged_paths',\n message: `${conflicted.length} file(s) still have unresolved conflicts: ${conflicted.slice(0, 5).join(', ')}${conflicted.length > 5 ? ', …' : ''}.`,\n suggestion: 'Resolve them, then git add the files',\n });\n }\n\n // `symbolic-ref -q HEAD` fails on a detached HEAD, which is the whole test.\n const symbolic = await run('git', ['symbolic-ref', '-q', 'HEAD'], at);\n const detached = symbolic.exitCode !== 0;\n const branch = detached ? null : symbolic.stdout.trim().replace(/^refs\\/heads\\//, '');\n\n if (detached) {\n blocks.push({\n kind: 'detached_head',\n message: 'HEAD is detached, so a commit would belong to no branch.',\n suggestion: `git switch ${expectedBranch ?? '<branch>'}`,\n });\n } else if (\n expectedBranch !== undefined &&\n expectedBranch !== null &&\n expectedBranch !== '' &&\n branch !== expectedBranch\n ) {\n blocks.push({\n kind: 'branch_mismatch',\n message: `The plan works on '${expectedBranch}' but the repository is on '${branch}'.`,\n suggestion: `git switch ${expectedBranch}`,\n });\n }\n\n const status = await run('git', ['status', '--porcelain'], at);\n const dirty = status.stdout.trim() !== '';\n if (dirty && intent !== 'resume-same-phase') {\n blocks.push({\n kind: 'dirty_tree',\n message: 'The working tree has uncommitted changes that do not belong to this phase.',\n suggestion: 'Commit or stash them yourself, then run again',\n });\n }\n\n return { ok: blocks.length === 0, blocks, branch, dirty };\n}\n\n/** The report a caller prints when the preflight blocks. Never a fix. */\nexport function describePreflight(result: PreflightResult): string[] {\n return result.blocks.map((block) => `${block.message} Suggested: ${block.suggestion}`);\n}\n\n/* ── story-level idempotence ────────────────────────────────────────────── */\n\n/** A story id as it appears in a commit subject: `feat(issue-63): US-012 - …`. */\nconst STORY_ID_IN_SUBJECT = /\\bUS-\\d+\\b/g;\n\n/**\n * The story ids already committed on this branch.\n *\n * The execute prompt commits one story per commit, with the id in the subject\n * (`<type>(scope): US-001 - Title`), so the branch's own history is a record of\n * what is done — and it is the *only* record that survives a crash between the\n * commit and the agent writing `passes: true` into the plan.\n *\n * Read-only, and deliberately so: this answers a question, it never fixes\n * anything. Never throws — an unreadable history means \"nothing known\", which\n * leaves the engine doing exactly what it did before.\n */\nexport async function committedStoryIds(baseBranch: string, cwd?: string): Promise<Set<string>> {\n const at = cwd === undefined ? {} : { cwd };\n const range = baseBranch === '' ? 'HEAD' : `${baseBranch}..HEAD`;\n const result = await run('git', ['log', range, '--format=%s'], at);\n if (result.exitCode !== 0) return new Set();\n\n const ids = new Set<string>();\n for (const subject of result.stdout.split('\\n')) {\n for (const match of subject.matchAll(STORY_ID_IN_SUBJECT)) {\n ids.add(match[0]);\n }\n }\n return ids;\n}\n\n/** Whether the working tree has no uncommitted change. Never throws. */\nexport async function isWorkingTreeClean(cwd?: string): Promise<boolean> {\n const at = cwd === undefined ? {} : { cwd };\n const result = await run('git', ['status', '--porcelain'], at);\n if (result.exitCode !== 0) return false;\n return result.stdout.trim() === '';\n}\n"],"mappings":"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","names":["policy","policy","result"]}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
bindDiagnosticContext,
|
|
4
|
-
flushDiagnostics,
|
|
5
|
-
readDiagnostics,
|
|
6
|
-
resetDiagnosticsState,
|
|
7
|
-
writeDiagnostic
|
|
8
|
-
} from "./chunk-QPGEFLMY.js";
|
|
9
|
-
import "./chunk-HAKDLR6N.js";
|
|
10
|
-
import "./chunk-YVPZUN6X.js";
|
|
11
|
-
import "./chunk-PPZ3K4YM.js";
|
|
12
|
-
import "./chunk-SOM4QA6C.js";
|
|
13
|
-
import "./chunk-ICM463EO.js";
|
|
14
|
-
import "./chunk-XEYH6ZZI.js";
|
|
15
|
-
import "./chunk-3R27MJ5R.js";
|
|
16
|
-
export {
|
|
17
|
-
bindDiagnosticContext,
|
|
18
|
-
flushDiagnostics,
|
|
19
|
-
readDiagnostics,
|
|
20
|
-
resetDiagnosticsState,
|
|
21
|
-
writeDiagnostic
|
|
22
|
-
};
|
|
23
|
-
//# sourceMappingURL=diagnostics-HTCWF7F4.js.map
|
package/dist/execute-LELOSR5T.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
runExecute
|
|
4
|
-
} from "./chunk-KRAGAUKD.js";
|
|
5
|
-
import "./chunk-NEWNXZ65.js";
|
|
6
|
-
import "./chunk-ECU7YO7S.js";
|
|
7
|
-
import "./chunk-E4I6MMHD.js";
|
|
8
|
-
import "./chunk-CRGIQFUQ.js";
|
|
9
|
-
import "./chunk-L6HSKTQE.js";
|
|
10
|
-
import "./chunk-45WZ6GMI.js";
|
|
11
|
-
import "./chunk-HOAHMERN.js";
|
|
12
|
-
import "./chunk-KMCS76ZW.js";
|
|
13
|
-
import "./chunk-7F7LGMVO.js";
|
|
14
|
-
import "./chunk-TZYINKCC.js";
|
|
15
|
-
import "./chunk-WCCZJL7W.js";
|
|
16
|
-
import "./chunk-DGRTJD5R.js";
|
|
17
|
-
import "./chunk-ZVZMWNCG.js";
|
|
18
|
-
import "./chunk-C5TL7T4V.js";
|
|
19
|
-
import "./chunk-LGHND47K.js";
|
|
20
|
-
import "./chunk-QF7VEL3M.js";
|
|
21
|
-
import "./chunk-LI35PIIS.js";
|
|
22
|
-
import "./chunk-XZUEFTUP.js";
|
|
23
|
-
import "./chunk-QPGEFLMY.js";
|
|
24
|
-
import "./chunk-HAKDLR6N.js";
|
|
25
|
-
import "./chunk-YVPZUN6X.js";
|
|
26
|
-
import "./chunk-DUS5ZNKL.js";
|
|
27
|
-
import "./chunk-6K2LCFG6.js";
|
|
28
|
-
import "./chunk-PPZ3K4YM.js";
|
|
29
|
-
import "./chunk-SOM4QA6C.js";
|
|
30
|
-
import "./chunk-ICM463EO.js";
|
|
31
|
-
import "./chunk-XEYH6ZZI.js";
|
|
32
|
-
import "./chunk-P3LRUNC6.js";
|
|
33
|
-
import "./chunk-3R27MJ5R.js";
|
|
34
|
-
export {
|
|
35
|
-
runExecute
|
|
36
|
-
};
|
|
37
|
-
//# sourceMappingURL=execute-LELOSR5T.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/issues/draft.ts","../src/issues/label-policy.ts","../src/commands/generate.ts"],"sourcesContent":["import type { IssueDraft } from './types.js';\n\n/**\n * Structured Issue draft emitted by the `generate` prompt.\n *\n * The agent no longer creates the Issue itself: it returns the content and the\n * providers persist it, so the same draft can reach GitHub, the local files, or\n * both. Capturing the result therefore has to be exact — the old approach of\n * fishing an issue URL out of free-form prose only ever worked for GitHub.\n *\n * The block mirrors the `<issue-body>` convention already used by the phase\n * templates, which keeps a multi-line markdown body readable and free of the\n * escaping a JSON payload would demand.\n */\n\n/** Wrapper the agent must emit around the draft. */\nexport const DRAFT_TAG = 'issue-draft';\n\n/** Failure to capture a draft from the agent output. */\nexport class IssueDraftParseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'IssueDraftParseError';\n }\n}\n\n/**\n * Last occurrence of `<tag>...</tag>` in `source`, or `null`.\n *\n * The last one wins: an agent that shows the format before filling it in (or\n * restates the draft after a correction) would otherwise have its first,\n * throwaway attempt captured. The closing tag is searched from the end for the\n * same reason a body may legitimately quote one.\n */\nfunction extractTag(source: string, tag: string): string | null {\n const open = `<${tag}>`;\n const close = `</${tag}>`;\n\n const start = source.lastIndexOf(open);\n if (start === -1) return null;\n\n const end = source.lastIndexOf(close);\n if (end === -1 || end < start) return null;\n\n return source.slice(start + open.length, end);\n}\n\nfunction parseLabels(raw: string | null): string[] {\n if (raw === null) return [];\n return raw\n .split(',')\n .map((label) => label.trim())\n .filter((label) => label.length > 0 && label.toLowerCase() !== '(none)');\n}\n\n/**\n * Read the draft the agent produced.\n *\n * @throws IssueDraftParseError when the block is absent or has no usable\n * title/body, so a malformed answer fails loudly instead of creating an empty\n * Issue.\n */\nexport function parseIssueDraft(output: string): IssueDraft {\n const normalized = output.replace(/\\r\\n?/g, '\\n');\n const block = extractTag(normalized, DRAFT_TAG);\n\n if (block === null) {\n throw new IssueDraftParseError(\n `The agent did not emit an <${DRAFT_TAG}> block, so there is no Issue to create. ` +\n `Output was: ${normalized.trim().slice(0, 300) || '(empty)'}`,\n );\n }\n\n const title = (extractTag(block, 'title') ?? '').trim();\n const body = (extractTag(block, 'body') ?? '').trim();\n\n if (title.length === 0) {\n throw new IssueDraftParseError(`The <${DRAFT_TAG}> block has no <title>.`);\n }\n if (body.length === 0) {\n throw new IssueDraftParseError(`The <${DRAFT_TAG}> block has no <body>.`);\n }\n\n // Optional, and deliberately so: a repository with no Issue Types and no\n // templates emits neither, and the draft is exactly what it was before.\n const type = (extractTag(block, 'type') ?? '').trim();\n const template = (extractTag(block, 'template') ?? '').trim();\n\n return {\n title,\n body,\n labels: parseLabels(extractTag(block, 'labels')),\n ...(type === '' || type.toLowerCase() === '(none)' ? {} : { type }),\n ...(template === '' || template.toLowerCase() === '(none)' ? {} : { template }),\n };\n}\n","import type { LabelDefinition } from '../policy/types.js';\nimport { run } from '../utils/shell.js';\n\n/**\n * Reconciling the labels an agent suggested with the ones the repository\n * actually has.\n *\n * A workflow tool has no business changing a repository's taxonomy. Labels are\n * governance: a team that deleted `high`/`medium`/`low` in favour of a native\n * priority field, or `bug`/`enhancement` in favour of Issue Types, made a\n * decision — and a generator that silently recreates them undoes it, quietly and\n * repository-wide.\n *\n * So the default is to **validate, never create**. `policy.issues.allowLabelCreation`\n * restores the old behaviour for repositories that want it.\n */\n\nexport interface LabelReconciliation {\n /** Labels to apply, in the repository's own casing. */\n labels: string[];\n /** Suggested labels the repository does not have. */\n missing: string[];\n}\n\n/**\n * Intersect the suggested labels with the repository's real ones.\n *\n * Matching is case-insensitive and the result carries the **repository's**\n * casing: `gh issue create --label Bug` fails on a repository whose label is\n * `bug`, and an agent has no way to know which one it is.\n *\n * An empty `known` means the labels could not be read at all — no policy, no\n * `gh`, no network. That is not evidence the labels do not exist, so the\n * suggestions pass through untouched and the behaviour is the one that shipped\n * before this layer. Refusing to label an issue because discovery was offline\n * would be the wrong failure.\n */\nexport function reconcileLabels(\n suggested: string[],\n known: LabelDefinition[],\n): LabelReconciliation {\n if (known.length === 0) {\n return { labels: [...suggested], missing: [] };\n }\n\n const canonical = new Map(known.map((label) => [label.name.toLowerCase(), label.name]));\n\n const labels: string[] = [];\n const missing: string[] = [];\n for (const suggestion of suggested) {\n const match = canonical.get(suggestion.trim().toLowerCase());\n if (match === undefined) {\n if (!missing.includes(suggestion)) missing.push(suggestion);\n continue;\n }\n if (!labels.includes(match)) labels.push(match);\n }\n\n return { labels, missing };\n}\n\n/**\n * Create the labels the repository is missing, for\n * `policy.issues.allowLabelCreation: true`.\n *\n * Best-effort per label: one that cannot be created is reported and skipped, so\n * a single failure does not cost the Issue. Returns the labels that now exist.\n */\nexport async function createMissingLabels(\n names: string[],\n warn: (message: string) => void,\n): Promise<string[]> {\n const created: string[] = [];\n\n for (const name of names) {\n const result = await run('gh', ['label', 'create', name]);\n if (result.exitCode === 0) {\n created.push(name);\n continue;\n }\n // gh answers \"already exists\" when a label was created between the\n // discovery and now, which is a success for our purposes.\n const detail = (result.stderr || result.stdout).trim();\n if (/already exists/i.test(detail)) {\n created.push(name);\n continue;\n }\n warn(`Could not create label \"${name}\": ${detail || 'gh label create failed'}`);\n }\n\n return created;\n}\n","import { loadIssuesConfig, loadPolicyConfig } from '../config.js';\nimport { DEFAULT_HEADLESS_TIMEOUT_MS, runHeadless } from '../core/headless.js';\nimport { applyPlaceholders, loadPrompt } from '../core/prompt-resolver.js';\nimport { publishPhaseMetrics } from '../core/session-metrics.js';\nimport { isoNow } from '../core/state-manager.js';\nimport { getGlobalTimeout } from '../core/verbose.js';\nimport { ensureProvidersRegistered } from '../issues/bootstrap.js';\nimport { localIssueRef } from '../issues/context.js';\nimport { IssueDraftParseError, parseIssueDraft } from '../issues/draft.js';\nimport { createMissingLabels, reconcileLabels } from '../issues/label-policy.js';\nimport { getProvider } from '../issues/registry.js';\nimport type { Issue, IssueDraft, IssueGenerateTarget } from '../issues/types.js';\nimport { loadRepositoryPolicy } from '../policy/index.js';\nimport { resolvePolicyPlaceholders } from '../policy/placeholders.js';\nimport { resolveProjectPaths } from '../storage/resolve.js';\nimport { printError, printInfo, printSuccess, printWarning } from '../ui/logger.js';\n\n/** Human-readable pointer to a created Issue. */\nfunction issueLocation(issue: Issue): string {\n return issue.remoteRef ?? localIssueRef(issue.id);\n}\n\n/**\n * Ask the agent for the Issue content.\n *\n * The agent only drafts: creation belongs to the providers, so the same draft\n * can be persisted to GitHub, to the local files, or to both.\n */\nasync function draftIssue(promptText: string): Promise<IssueDraft> {\n // The duplicate check reads the local issues, which live in the global\n // storage: the path has to be handed over (and allowed) explicitly, since it\n // is outside the working directory the agent is started in.\n const { issuesDir } = await resolveProjectPaths();\n\n const template = await loadPrompt('generate');\n const prompt = applyPlaceholders(template, {\n // The repository's own conventions. Empty when it declares none, which is\n // what keeps the rendered prompt identical to the pre-policy one.\n ...(await resolvePolicyPlaceholders()),\n __USER_PROMPT__: promptText,\n __LOCAL_ISSUES_DIR__: issuesDir,\n });\n\n const startedAtMs = Date.now();\n const result = await runHeadless({\n prompt,\n maxTurns: 15,\n timeout: getGlobalTimeout() ?? DEFAULT_HEADLESS_TIMEOUT_MS,\n // json (not text) so the CLI reports usage: the envelope's `result` field\n // carries the same assistant text parseIssueDraft() already consumed.\n outputFormat: 'json',\n allowedTools: ['Bash', 'Read', 'Glob', 'Grep'],\n addDirs: [issuesDir],\n statusMessage: 'Drafting issue...',\n phase: 'generate',\n permission: 'workspace',\n });\n // Before the success check: the tokens were spent either way.\n publishPhaseMetrics('generate', result.cost, startedAtMs, result.agent?.provider);\n\n if (!result.success) {\n throw new Error(`Issue creation failed: ${result.error}`);\n }\n\n return parseIssueDraft(result.result);\n}\n\n/**\n * Create the GitHub Issue and mirror it locally.\n *\n * The remote comes first on purpose: it owns the identifier, and the mirror has\n * to reuse it so both copies describe one demand. A remote failure therefore\n * leaves nothing behind, and a mirror failure is reported with the remote\n * reference that already exists.\n */\nasync function createBoth(draft: IssueDraft): Promise<Issue[]> {\n const remote = await getProvider('github').create(draft);\n\n try {\n const mirror = await getProvider('local').create({\n ...draft,\n id: remote.id,\n ...(remote.remoteRef\n ? {\n remote: {\n provider: 'github' as const,\n ref: remote.remoteRef,\n syncedAt: isoNow(),\n syncedContentHash: remote.contentHash,\n },\n }\n : {}),\n });\n return [remote, mirror];\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `GitHub issue created at ${issueLocation(remote)}, but the local mirror was not written: ` +\n `${message}. Nothing else was persisted; re-run with --local to create the mirror.`,\n );\n }\n}\n\nasync function createIssues(target: IssueGenerateTarget, draft: IssueDraft): Promise<Issue[]> {\n if (target === 'both') {\n return createBoth(draft);\n }\n return [await getProvider(target).create(draft)];\n}\n\n/**\n * Reconcile the draft's labels with the ones the repository really has.\n *\n * Two failures are being prevented here, and only one of them is cosmetic.\n * GitHub rejects an issue whose label does not exist, so an invented label costs\n * the whole Issue. And a tool that creates the label instead rewrites a taxonomy\n * the team may have curated deliberately — which is worse, because it succeeds.\n *\n * Never throws: a policy that could not be resolved leaves the draft untouched.\n */\nasync function applyLabelPolicy(draft: IssueDraft): Promise<IssueDraft> {\n let known: Awaited<ReturnType<typeof loadRepositoryPolicy>>['issues']['labels'];\n let allowCreation: boolean;\n try {\n const policy = await loadRepositoryPolicy();\n known = policy.issues.labels;\n const config = await loadPolicyConfig({ projectRoot: policy.root });\n allowCreation = config.issues.allowLabelCreation ?? false;\n } catch {\n return draft;\n }\n\n const { labels, missing } = reconcileLabels(draft.labels, known);\n if (missing.length === 0) {\n return { ...draft, labels };\n }\n\n if (!allowCreation) {\n printWarning(\n `Dropping ${missing.length} label(s) this repository does not have: ${missing.join(', ')}. ` +\n 'Issue Flow does not create labels; set policy.issues.allowLabelCreation to change that.',\n );\n return { ...draft, labels };\n }\n\n const created = await createMissingLabels(missing, printWarning);\n return { ...draft, labels: [...labels, ...created] };\n}\n\nexport async function runGenerate(\n promptText: string,\n target?: IssueGenerateTarget,\n): Promise<number> {\n const config = await loadIssuesConfig();\n const destination = target ?? config.defaultGenerateTarget;\n\n ensureProvidersRegistered();\n\n let draft: IssueDraft;\n try {\n draft = await draftIssue(promptText);\n } catch (err) {\n if (err instanceof IssueDraftParseError) {\n printError(`Could not read the generated Issue draft: ${err.message}`);\n } else {\n printError(err instanceof Error ? err.message : String(err));\n }\n return 1;\n }\n\n const finalDraft = await applyLabelPolicy(draft);\n if (finalDraft.template !== undefined) {\n printInfo(`Following the repository's Issue Template: ${finalDraft.template}`);\n }\n if (finalDraft.type !== undefined) {\n printInfo(`Issue Type: ${finalDraft.type}`);\n }\n\n let created: Issue[];\n try {\n created = await createIssues(destination, finalDraft);\n } catch (err) {\n printError(err instanceof Error ? err.message : String(err));\n return 1;\n }\n\n for (const issue of created) {\n printSuccess(`Issue created (${issue.source}): ${issueLocation(issue)}`);\n }\n return 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBO,IAAM,YAAY;AAGlB,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC9C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAUA,SAAS,WAAW,QAAgB,KAA4B;AAC9D,QAAM,OAAO,IAAI,GAAG;AACpB,QAAM,QAAQ,KAAK,GAAG;AAEtB,QAAM,QAAQ,OAAO,YAAY,IAAI;AACrC,MAAI,UAAU,GAAI,QAAO;AAEzB,QAAM,MAAM,OAAO,YAAY,KAAK;AACpC,MAAI,QAAQ,MAAM,MAAM,MAAO,QAAO;AAEtC,SAAO,OAAO,MAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9C;AAEA,SAAS,YAAY,KAA8B;AACjD,MAAI,QAAQ,KAAM,QAAO,CAAC;AAC1B,SAAO,IACJ,MAAM,GAAG,EACT,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,OAAO,CAAC,UAAU,MAAM,SAAS,KAAK,MAAM,YAAY,MAAM,QAAQ;AAC3E;AASO,SAAS,gBAAgB,QAA4B;AAC1D,QAAM,aAAa,OAAO,QAAQ,UAAU,IAAI;AAChD,QAAM,QAAQ,WAAW,YAAY,SAAS;AAE9C,MAAI,UAAU,MAAM;AAClB,UAAM,IAAI;AAAA,MACR,8BAA8B,SAAS,wDACtB,WAAW,KAAK,EAAE,MAAM,GAAG,GAAG,KAAK,SAAS;AAAA,IAC/D;AAAA,EACF;AAEA,QAAM,SAAS,WAAW,OAAO,OAAO,KAAK,IAAI,KAAK;AACtD,QAAM,QAAQ,WAAW,OAAO,MAAM,KAAK,IAAI,KAAK;AAEpD,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,IAAI,qBAAqB,QAAQ,SAAS,yBAAyB;AAAA,EAC3E;AACA,MAAI,KAAK,WAAW,GAAG;AACrB,UAAM,IAAI,qBAAqB,QAAQ,SAAS,wBAAwB;AAAA,EAC1E;AAIA,QAAM,QAAQ,WAAW,OAAO,MAAM,KAAK,IAAI,KAAK;AACpD,QAAM,YAAY,WAAW,OAAO,UAAU,KAAK,IAAI,KAAK;AAE5D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,QAAQ,YAAY,WAAW,OAAO,QAAQ,CAAC;AAAA,IAC/C,GAAI,SAAS,MAAM,KAAK,YAAY,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK;AAAA,IACjE,GAAI,aAAa,MAAM,SAAS,YAAY,MAAM,WAAW,CAAC,IAAI,EAAE,SAAS;AAAA,EAC/E;AACF;;;AC1DO,SAAS,gBACd,WACA,OACqB;AACrB,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,EAAE,QAAQ,CAAC,GAAG,SAAS,GAAG,SAAS,CAAC,EAAE;AAAA,EAC/C;AAEA,QAAM,YAAY,IAAI,IAAI,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,YAAY,GAAG,MAAM,IAAI,CAAC,CAAC;AAEtF,QAAM,SAAmB,CAAC;AAC1B,QAAM,UAAoB,CAAC;AAC3B,aAAW,cAAc,WAAW;AAClC,UAAM,QAAQ,UAAU,IAAI,WAAW,KAAK,EAAE,YAAY,CAAC;AAC3D,QAAI,UAAU,QAAW;AACvB,UAAI,CAAC,QAAQ,SAAS,UAAU,EAAG,SAAQ,KAAK,UAAU;AAC1D;AAAA,IACF;AACA,QAAI,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO,KAAK,KAAK;AAAA,EAChD;AAEA,SAAO,EAAE,QAAQ,QAAQ;AAC3B;AASA,eAAsB,oBACpB,OACA,MACmB;AACnB,QAAM,UAAoB,CAAC;AAE3B,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,MAAM,IAAI,MAAM,CAAC,SAAS,UAAU,IAAI,CAAC;AACxD,QAAI,OAAO,aAAa,GAAG;AACzB,cAAQ,KAAK,IAAI;AACjB;AAAA,IACF;AAGA,UAAM,UAAU,OAAO,UAAU,OAAO,QAAQ,KAAK;AACrD,QAAI,kBAAkB,KAAK,MAAM,GAAG;AAClC,cAAQ,KAAK,IAAI;AACjB;AAAA,IACF;AACA,SAAK,2BAA2B,IAAI,MAAM,UAAU,wBAAwB,EAAE;AAAA,EAChF;AAEA,SAAO;AACT;;;ACzEA,SAAS,cAAc,OAAsB;AAC3C,SAAO,MAAM,aAAa,cAAc,MAAM,EAAE;AAClD;AAQA,eAAe,WAAW,YAAyC;AAIjE,QAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAEhD,QAAM,WAAW,MAAM,WAAW,UAAU;AAC5C,QAAM,SAAS,kBAAkB,UAAU;AAAA;AAAA;AAAA,IAGzC,GAAI,MAAM,0BAA0B;AAAA,IACpC,iBAAiB;AAAA,IACjB,sBAAsB;AAAA,EACxB,CAAC;AAED,QAAM,cAAc,KAAK,IAAI;AAC7B,QAAM,SAAS,MAAM,YAAY;AAAA,IAC/B;AAAA,IACA,UAAU;AAAA,IACV,SAAS,iBAAiB,KAAK;AAAA;AAAA;AAAA,IAG/B,cAAc;AAAA,IACd,cAAc,CAAC,QAAQ,QAAQ,QAAQ,MAAM;AAAA,IAC7C,SAAS,CAAC,SAAS;AAAA,IACnB,eAAe;AAAA,IACf,OAAO;AAAA,IACP,YAAY;AAAA,EACd,CAAC;AAED,sBAAoB,YAAY,OAAO,MAAM,aAAa,OAAO,OAAO,QAAQ;AAEhF,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI,MAAM,0BAA0B,OAAO,KAAK,EAAE;AAAA,EAC1D;AAEA,SAAO,gBAAgB,OAAO,MAAM;AACtC;AAUA,eAAe,WAAW,OAAqC;AAC7D,QAAM,SAAS,MAAM,YAAY,QAAQ,EAAE,OAAO,KAAK;AAEvD,MAAI;AACF,UAAM,SAAS,MAAM,YAAY,OAAO,EAAE,OAAO;AAAA,MAC/C,GAAG;AAAA,MACH,IAAI,OAAO;AAAA,MACX,GAAI,OAAO,YACP;AAAA,QACE,QAAQ;AAAA,UACN,UAAU;AAAA,UACV,KAAK,OAAO;AAAA,UACZ,UAAU,OAAO;AAAA,UACjB,mBAAmB,OAAO;AAAA,QAC5B;AAAA,MACF,IACA,CAAC;AAAA,IACP,CAAC;AACD,WAAO,CAAC,QAAQ,MAAM;AAAA,EACxB,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,UAAM,IAAI;AAAA,MACR,2BAA2B,cAAc,MAAM,CAAC,2CAC3C,OAAO;AAAA,IACd;AAAA,EACF;AACF;AAEA,eAAe,aAAa,QAA6B,OAAqC;AAC5F,MAAI,WAAW,QAAQ;AACrB,WAAO,WAAW,KAAK;AAAA,EACzB;AACA,SAAO,CAAC,MAAM,YAAY,MAAM,EAAE,OAAO,KAAK,CAAC;AACjD;AAYA,eAAe,iBAAiB,OAAwC;AACtE,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,UAAM,SAAS,MAAM,qBAAqB;AAC1C,YAAQ,OAAO,OAAO;AACtB,UAAM,SAAS,MAAM,iBAAiB,EAAE,aAAa,OAAO,KAAK,CAAC;AAClE,oBAAgB,OAAO,OAAO,sBAAsB;AAAA,EACtD,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,QAAQ,QAAQ,IAAI,gBAAgB,MAAM,QAAQ,KAAK;AAC/D,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,EAAE,GAAG,OAAO,OAAO;AAAA,EAC5B;AAEA,MAAI,CAAC,eAAe;AAClB;AAAA,MACE,YAAY,QAAQ,MAAM,4CAA4C,QAAQ,KAAK,IAAI,CAAC;AAAA,IAE1F;AACA,WAAO,EAAE,GAAG,OAAO,OAAO;AAAA,EAC5B;AAEA,QAAM,UAAU,MAAM,oBAAoB,SAAS,YAAY;AAC/D,SAAO,EAAE,GAAG,OAAO,QAAQ,CAAC,GAAG,QAAQ,GAAG,OAAO,EAAE;AACrD;AAEA,eAAsB,YACpB,YACA,QACiB;AACjB,QAAM,SAAS,MAAM,iBAAiB;AACtC,QAAM,cAAc,UAAU,OAAO;AAErC,4BAA0B;AAE1B,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,WAAW,UAAU;AAAA,EACrC,SAAS,KAAK;AACZ,QAAI,eAAe,sBAAsB;AACvC,iBAAW,6CAA6C,IAAI,OAAO,EAAE;AAAA,IACvE,OAAO;AACL,iBAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC7D;AACA,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM,iBAAiB,KAAK;AAC/C,MAAI,WAAW,aAAa,QAAW;AACrC,cAAU,8CAA8C,WAAW,QAAQ,EAAE;AAAA,EAC/E;AACA,MAAI,WAAW,SAAS,QAAW;AACjC,cAAU,eAAe,WAAW,IAAI,EAAE;AAAA,EAC5C;AAEA,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,aAAa,aAAa,UAAU;AAAA,EACtD,SAAS,KAAK;AACZ,eAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC3D,WAAO;AAAA,EACT;AAEA,aAAW,SAAS,SAAS;AAC3B,iBAAa,kBAAkB,MAAM,MAAM,MAAM,cAAc,KAAK,CAAC,EAAE;AAAA,EACzE;AACA,SAAO;AACT;","names":[]}
|
package/dist/init-TO6MUXO4.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
runInit,
|
|
4
|
-
shouldOfferAgentPrompt,
|
|
5
|
-
summarizePreflight
|
|
6
|
-
} from "./chunk-PMLE7KAQ.js";
|
|
7
|
-
import "./chunk-QF7VEL3M.js";
|
|
8
|
-
import "./chunk-LI35PIIS.js";
|
|
9
|
-
import "./chunk-XZUEFTUP.js";
|
|
10
|
-
import "./chunk-QPGEFLMY.js";
|
|
11
|
-
import "./chunk-HAKDLR6N.js";
|
|
12
|
-
import "./chunk-YVPZUN6X.js";
|
|
13
|
-
import "./chunk-DUS5ZNKL.js";
|
|
14
|
-
import "./chunk-6K2LCFG6.js";
|
|
15
|
-
import "./chunk-PPZ3K4YM.js";
|
|
16
|
-
import "./chunk-SOM4QA6C.js";
|
|
17
|
-
import "./chunk-ICM463EO.js";
|
|
18
|
-
import "./chunk-XEYH6ZZI.js";
|
|
19
|
-
import "./chunk-P3LRUNC6.js";
|
|
20
|
-
import "./chunk-3R27MJ5R.js";
|
|
21
|
-
export {
|
|
22
|
-
runInit,
|
|
23
|
-
shouldOfferAgentPrompt,
|
|
24
|
-
summarizePreflight
|
|
25
|
-
};
|
|
26
|
-
//# sourceMappingURL=init-TO6MUXO4.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/operations.ts"],"sourcesContent":["import { readdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parseJournal } from '../core/journal.js';\nimport { PIPELINE_PHASES, PipelineManager, type PipelinePhase } from '../core/pipeline.js';\nimport type { SessionEvent, SessionSnapshot } from '../core/session-state.js';\nimport { loadTaskPlan } from '../core/state-manager.js';\nimport { loadExecutionPlan } from '../execution/plan.js';\nimport type { ExecutionPlan } from '../execution/types.js';\nimport { describeRunLockOwner, isRunLockStale, readRunLock } from '../storage/lock.js';\nimport { getIssuePaths, QUEUES_DIR_NAME } from '../storage/paths.js';\nimport { resolveProjectPaths } from '../storage/resolve.js';\nimport type { RunLock } from '../storage/schemas.js';\nimport type { TaskPlan } from '../types.js';\nimport { printError, printInfo, printWarning } from '../ui/logger.js';\n\n/**\n * The operation surface of a long run: `status`, `runs`, `logs`, `pause`,\n * `cancel`.\n *\n * The CLI declared thirteen commands and not one of them answered \"what is\n * running\", \"what failed\", or \"stop what you are doing\". During a six-hour\n * unattended execution the only way to find out was to read JSON by hand, and\n * the only way to stop it was to find the pid.\n *\n * Everything here **reads state that already exists** — `run.lock`,\n * `tasks.json`, `session.json`, `execution-plan.json`, `events.jsonl` — and\n * writes nothing except the two control commands, which do the one thing a\n * person cannot do from outside: ask the owner to stop, gracefully.\n */\n\ninterface ProjectPaths {\n projectId: string;\n projectDir: string;\n issuesDir: string;\n runLockFile: string;\n}\n\n/** One issue's state, assembled from every artifact that knows part of it. */\ninterface IssueState {\n id: string;\n plan: TaskPlan | null;\n snapshot: SessionSnapshot | null;\n nextPhase: PipelinePhase | null;\n paths: ReturnType<typeof getIssuePaths>;\n}\n\nasync function project(): Promise<ProjectPaths | null> {\n try {\n return await resolveProjectPaths();\n } catch (err) {\n printError(`Not inside a usable project: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n}\n\nasync function readJson<T>(path: string): Promise<T | null> {\n try {\n return JSON.parse(await readFile(path, 'utf-8')) as T;\n } catch {\n return null;\n }\n}\n\nasync function loadIssueState(projectId: string, id: string): Promise<IssueState | null> {\n let paths: ReturnType<typeof getIssuePaths>;\n try {\n paths = getIssuePaths(projectId, id);\n } catch {\n return null;\n }\n\n let plan: TaskPlan | null = null;\n try {\n plan = await loadTaskPlan(paths.tasksFile);\n } catch {\n plan = null;\n }\n if (plan === null) return null;\n\n const snapshot = await readJson<SessionSnapshot>(paths.sessionFile);\n const phases: PipelinePhase[] =\n plan.noBranch === true\n ? PIPELINE_PHASES.filter((phase) => phase !== 'pr')\n : [...PIPELINE_PHASES];\n if (plan.prReview?.enabled === true) phases.push('pr-review');\n\n return {\n id,\n plan,\n snapshot,\n nextPhase: new PipelineManager(plan, paths.tasksFile, phases).getNextPhase(),\n paths,\n };\n}\n\n/** Every issue this project has state for, newest attempt first. */\nasync function allIssues(paths: ProjectPaths): Promise<IssueState[]> {\n let ids: string[];\n try {\n ids = await readdir(paths.issuesDir);\n } catch {\n return [];\n }\n\n const states: IssueState[] = [];\n for (const id of ids) {\n const state = await loadIssueState(paths.projectId, id);\n if (state !== null) states.push(state);\n }\n return states.sort((a, b) => attemptedAt(b.plan) - attemptedAt(a.plan));\n}\n\nfunction attemptedAt(plan: TaskPlan | null): number {\n const at = Date.parse(plan?.lastAttemptAt ?? '');\n return Number.isNaN(at) ? 0 : at;\n}\n\n/** Every queue plan of the project. */\nasync function allQueues(paths: ProjectPaths): Promise<ExecutionPlan[]> {\n const dir = join(paths.projectDir, QUEUES_DIR_NAME);\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch {\n return [];\n }\n\n const plans: ExecutionPlan[] = [];\n for (const entry of entries) {\n const plan = await loadExecutionPlan(join(dir, entry, 'execution-plan.json'));\n if (plan !== null) plans.push(plan);\n }\n return plans;\n}\n\n/** `2m 13s ago`, or `never`. */\nfunction since(at: string | null | undefined, now = Date.now()): string {\n if (at === null || at === undefined || at === '') return 'never';\n const parsed = Date.parse(at);\n if (Number.isNaN(parsed)) return 'unknown';\n return `${formatSeconds(Math.max(0, Math.round((now - parsed) / 1000)))} ago`;\n}\n\nfunction formatSeconds(total: number): string {\n if (total < 60) return `${total}s`;\n const minutes = Math.floor(total / 60);\n if (minutes < 60) return `${minutes}m ${total % 60}s`;\n const hours = Math.floor(minutes / 60);\n return `${hours}h ${minutes % 60}m`;\n}\n\n/* ── status ─────────────────────────────────────────────────────────────── */\n\nexport interface StatusOptions {\n /** Emit the assembled state as JSON instead of a screen. */\n json?: boolean;\n}\n\n/**\n * One screen answering \"what is happening right now\".\n *\n * The three artifacts each know part of it and none knows all of it: the lock\n * knows *who* and *how long since it last said anything*, the task plan knows\n * *which phase and which attempt*, and the queue plan knows *where in the\n * queue*. Reading them together is the whole command.\n */\nexport async function runStatus(issue?: string, options: StatusOptions = {}): Promise<number> {\n const paths = await project();\n if (paths === null) return 1;\n\n const lock = await readRunLock(paths.runLockFile);\n const issues =\n issue === undefined\n ? await allIssues(paths)\n : [await loadIssueState(paths.projectId, issue)].filter(\n (state): state is IssueState => state !== null,\n );\n const queues = await allQueues(paths);\n\n if (options.json === true) {\n printInfo(\n JSON.stringify(\n {\n owner: lock,\n ownerStale: lock === null ? null : isRunLockStale(lock),\n issues: issues.map((state) => ({\n id: state.id,\n issueStatus: state.plan?.issueStatus ?? null,\n runState: state.plan?.runState ?? null,\n nextPhase: state.nextPhase,\n branch: state.plan?.branchName ?? null,\n lastActivityAt: state.snapshot?.updatedAt ?? state.plan?.lastAttemptAt ?? null,\n retries: state.snapshot?.execution.retries ?? null,\n })),\n queues: queues.map((plan) => ({\n id: plan.id,\n status: plan.status,\n issues: plan.issues.map((entry) => ({\n id: entry.id,\n status: entry.status,\n attempts: entry.attempts,\n blockedReason: entry.blockedReason,\n })),\n })),\n },\n null,\n 2,\n ),\n );\n return 0;\n }\n\n printOwner(lock);\n\n if (issues.length === 0) {\n printInfo('No issue in this project has any state yet.');\n return 0;\n }\n\n for (const state of issues.slice(0, issue === undefined ? 5 : 1)) {\n printIssueLine(state);\n }\n\n for (const plan of queues) {\n if (plan.status === 'completed') continue;\n printInfo(`Queue ${plan.id} — ${plan.status}`);\n for (const entry of plan.issues) {\n const attempts = entry.attempts > 0 ? `, ${entry.attempts} attempt(s)` : '';\n const blocked = entry.blockedReason === null ? '' : ` — ${entry.blockedReason}`;\n printInfo(` #${entry.id} ${entry.status}${attempts}${blocked}`);\n }\n }\n\n return 0;\n}\n\nfunction printOwner(lock: RunLock | null): void {\n if (lock === null) {\n printInfo('Nothing is running in this project (no run.lock).');\n return;\n }\n if (isRunLockStale(lock)) {\n printWarning(`A stale lock is left behind: ${describeRunLockOwner(lock)}.`);\n printInfo('It will be taken over by the next run or resume.');\n return;\n }\n printInfo(`Running: ${describeRunLockOwner(lock)}`);\n printInfo(`Last heartbeat ${since(lock.lastHeartbeatAt)}.`);\n}\n\nfunction printIssueLine(state: IssueState): void {\n const plan = state.plan;\n const run = plan?.runState;\n const phase = run?.currentPhase ?? state.nextPhase ?? '—';\n const attempt = run !== undefined && run.attempt > 0 ? `, attempt ${run.attempt}` : '';\n const retries = state.snapshot?.execution.retries;\n const retryLine = retries === undefined || retries === 0 ? '' : `, ${retries} retry(ies)`;\n const activity = since(state.snapshot?.updatedAt ?? plan?.lastAttemptAt);\n\n printInfo(\n `#${state.id} ${plan?.issueStatus ?? 'unknown'}${run === undefined ? '' : ` / ${run.status}`}` +\n ` — phase ${phase}${attempt}${retryLine}; last activity ${activity}`,\n );\n if (run?.blockedReason !== null && run?.blockedReason !== undefined) {\n printWarning(` Blocked: ${run.blockedReason}`);\n }\n}\n\n/* ── runs ───────────────────────────────────────────────────────────────── */\n\n/**\n * The history: what has been run in this project, how it ended, and why.\n *\n * Deliberately built from the same artifacts `status` reads rather than from a\n * separate history file — a second record of the truth is a second thing that\n * can be wrong.\n */\nexport async function runRuns(): Promise<number> {\n const paths = await project();\n if (paths === null) return 1;\n\n const issues = await allIssues(paths);\n if (issues.length === 0) {\n printInfo('No runs recorded for this project yet.');\n return 0;\n }\n\n for (const state of issues) {\n const plan = state.plan;\n if (plan === null) continue;\n const duration =\n state.snapshot?.elapsedSeconds === null || state.snapshot?.elapsedSeconds === undefined\n ? '—'\n : formatSeconds(state.snapshot.elapsedSeconds);\n const cause =\n plan.lastError === null ? '' : ` — ${plan.lastError.message.split('\\n')[0] ?? ''}`;\n\n printInfo(\n `#${state.id.padEnd(6)} ${plan.issueStatus.padEnd(12)} ${duration.padEnd(10)} ` +\n `last attempt ${since(plan.lastAttemptAt)}${cause}`,\n );\n }\n return 0;\n}\n\n/* ── logs ───────────────────────────────────────────────────────────────── */\n\nexport interface LogsOptions {\n /** Only these event types (`retry`, `phase:end`, …). Empty means all. */\n kind?: string[];\n /** Keep reading as the journal grows. */\n follow?: boolean;\n /** How many entries to show before following. */\n tail?: number;\n /** Polling interval of `--follow`, for tests. */\n pollMs?: number;\n /** Stops `--follow`. */\n signal?: AbortSignal;\n}\n\nconst DEFAULT_TAIL = 50;\nconst FOLLOW_POLL_MS = 1000;\n\n/**\n * Read the journal, filtered and readable.\n *\n * The journal is the only record that keeps *what happened in which order* —\n * the snapshot folded it away — so this is the command that answers \"what was\n * it doing at 3am\". `--kind retry,failover` is the filter that matters most:\n * on a six-hour run those are a handful of lines among thousands.\n */\nexport async function runLogs(issue?: string, options: LogsOptions = {}): Promise<number> {\n const paths = await project();\n if (paths === null) return 1;\n\n const target = issue ?? (await allIssues(paths))[0]?.id;\n if (target === undefined) {\n printInfo('No issue in this project has a journal yet.');\n return 0;\n }\n\n const issuePaths = getIssuePaths(paths.projectId, target);\n const kinds = new Set(options.kind ?? []);\n const tail = options.tail ?? DEFAULT_TAIL;\n\n const shown = new Set<number>();\n const render = (content: string, limit: number | null): void => {\n const entries = parseJournal(content).filter(\n (entry) => kinds.size === 0 || kinds.has(entry.event.type),\n );\n const slice = limit === null ? entries : entries.slice(-limit);\n for (const entry of slice) {\n if (shown.has(entry.seq)) continue;\n shown.add(entry.seq);\n printInfo(formatEvent(entry.seq, entry.event));\n }\n };\n\n const readAll = async (): Promise<string> =>\n `${await readIfPresent(issuePaths.rotatedEventsFile)}${await readIfPresent(issuePaths.eventsFile)}`;\n\n const initial = await readAll();\n if (initial === '') {\n printInfo(\n `Issue #${target} has no journal. Enable it with resilience.journal.enabled or --continuous.`,\n );\n return 0;\n }\n render(initial, tail);\n\n if (options.follow !== true) return 0;\n\n const poll = options.pollMs ?? FOLLOW_POLL_MS;\n const signal = options.signal;\n while (signal === undefined || !signal.aborted) {\n await sleep(poll, signal);\n if (signal?.aborted === true) break;\n render(await readAll(), null);\n }\n return 0;\n}\n\nfunction formatEvent(seq: number, event: SessionEvent): string {\n const at = 'at' in event ? event.at : '';\n const detail = describeEvent(event);\n return `${String(seq).padStart(5)} ${at} ${event.type}${detail === '' ? '' : ` — ${detail}`}`;\n}\n\nfunction describeEvent(event: SessionEvent): string {\n switch (event.type) {\n case 'phase:start':\n return event.phase;\n case 'phase:end':\n return `${event.phase} ${event.success ? 'ok' : `failed: ${event.error ?? ''}`}`;\n case 'retry':\n return `attempt ${event.attempt}, ${event.delaySeconds}s — ${event.reason}`;\n case 'log':\n return `${event.level}: ${event.message}`;\n case 'session:end':\n return event.status;\n default:\n return '';\n }\n}\n\nasync function readIfPresent(path: string): Promise<string> {\n try {\n return await readFile(path, 'utf-8');\n } catch {\n return '';\n }\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n timer.unref?.();\n signal?.addEventListener('abort', () => {\n clearTimeout(timer);\n resolve();\n });\n });\n}\n\n/* ── pause and cancel ───────────────────────────────────────────────────── */\n\nexport interface ControlOptions {\n /** Injectable signaller, so a test never signals a real process. */\n signalProcess?: (pid: number, signal: NodeJS.Signals) => void;\n}\n\n/**\n * Ask the running owner to stop, gracefully.\n *\n * `SIGTERM` is the whole implementation, and deliberately so: the owner already\n * knows how to stop well (`core/shutdown.ts` writes the checkpoint, stops the\n * agent with a grace period and closes the journal). Reimplementing any of that\n * from outside the process would be a second, worse version of it.\n */\nexport async function runPause(options: ControlOptions = {}): Promise<number> {\n return stopOwner('paused', options);\n}\n\n/**\n * Stop the run and mark it so a later `resume` does not pick it up silently.\n *\n * The difference from `pause` is not in how the process ends — it ends the same\n * way — but in what the state says afterwards: a paused run is meant to be\n * resumed, a cancelled one is not.\n */\nexport async function runCancel(issue?: string, options: ControlOptions = {}): Promise<number> {\n const code = await stopOwner('cancelled', options);\n if (code !== 0) return code;\n\n const paths = await project();\n if (paths === null) return 1;\n\n const target = issue ?? (await allIssues(paths))[0]?.id;\n if (target === undefined) return 0;\n\n const state = await loadIssueState(paths.projectId, target);\n if (state === null || state.plan === null) return 0;\n\n const { saveTaskPlan, isoNow } = await import('../core/state-manager.js');\n await saveTaskPlan(state.paths.tasksFile, {\n ...state.plan,\n runState: {\n currentPhase: state.plan.runState?.currentPhase ?? null,\n attempt: state.plan.runState?.attempt ?? 0,\n owner: null,\n status: 'blocked',\n blockedReason: 'Cancelled by the user',\n lastHeartbeatAt: isoNow(),\n },\n });\n printInfo(`Issue #${target} is marked cancelled. A resume will report it instead of running it.`);\n return 0;\n}\n\nasync function stopOwner(intent: string, options: ControlOptions): Promise<number> {\n const paths = await project();\n if (paths === null) return 1;\n\n const lock = await readRunLock(paths.runLockFile);\n if (lock === null) {\n printInfo('Nothing is running in this project.');\n return 0;\n }\n if (isRunLockStale(lock)) {\n printWarning(`The lock is stale (${describeRunLockOwner(lock)}); nothing to stop.`);\n return 0;\n }\n\n const send =\n options.signalProcess ?? ((pid: number, signal: NodeJS.Signals) => process.kill(pid, signal));\n try {\n send(lock.pid, 'SIGTERM');\n } catch (err) {\n printError(\n `Could not signal pid ${lock.pid}: ${err instanceof Error ? err.message : String(err)}`,\n );\n return 1;\n }\n\n printInfo(\n `Asked pid ${lock.pid} to stop (${intent}). It writes a checkpoint, stops the agent and closes its journal before exiting.`,\n );\n return 0;\n}\n"],"mappings":"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","names":[]}
|
package/dist/plan-OXAT344Q.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
runPlan
|
|
4
|
-
} from "./chunk-34OCSKOB.js";
|
|
5
|
-
import "./chunk-V7QOIQYC.js";
|
|
6
|
-
import "./chunk-SA6HXL4Y.js";
|
|
7
|
-
import "./chunk-62GVVZQO.js";
|
|
8
|
-
import "./chunk-KMMASOA6.js";
|
|
9
|
-
import "./chunk-KMCS76ZW.js";
|
|
10
|
-
import "./chunk-7F7LGMVO.js";
|
|
11
|
-
import "./chunk-TZYINKCC.js";
|
|
12
|
-
import "./chunk-WCCZJL7W.js";
|
|
13
|
-
import "./chunk-DGRTJD5R.js";
|
|
14
|
-
import "./chunk-ZVZMWNCG.js";
|
|
15
|
-
import "./chunk-3D4A4B46.js";
|
|
16
|
-
import "./chunk-LGHND47K.js";
|
|
17
|
-
import "./chunk-QF7VEL3M.js";
|
|
18
|
-
import "./chunk-LI35PIIS.js";
|
|
19
|
-
import "./chunk-XZUEFTUP.js";
|
|
20
|
-
import "./chunk-QPGEFLMY.js";
|
|
21
|
-
import "./chunk-HAKDLR6N.js";
|
|
22
|
-
import "./chunk-YVPZUN6X.js";
|
|
23
|
-
import "./chunk-DUS5ZNKL.js";
|
|
24
|
-
import "./chunk-6K2LCFG6.js";
|
|
25
|
-
import "./chunk-PPZ3K4YM.js";
|
|
26
|
-
import "./chunk-SOM4QA6C.js";
|
|
27
|
-
import "./chunk-ICM463EO.js";
|
|
28
|
-
import "./chunk-XEYH6ZZI.js";
|
|
29
|
-
import "./chunk-P3LRUNC6.js";
|
|
30
|
-
import "./chunk-3R27MJ5R.js";
|
|
31
|
-
export {
|
|
32
|
-
runPlan
|
|
33
|
-
};
|
|
34
|
-
//# sourceMappingURL=plan-OXAT344Q.js.map
|
package/dist/pr-UZHNKKZC.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
issueClosesLines,
|
|
4
|
-
multiIssueContext,
|
|
5
|
-
runPr
|
|
6
|
-
} from "./chunk-OODXFCQV.js";
|
|
7
|
-
import "./chunk-YUNBOUQH.js";
|
|
8
|
-
import "./chunk-V7QOIQYC.js";
|
|
9
|
-
import "./chunk-SA6HXL4Y.js";
|
|
10
|
-
import "./chunk-62GVVZQO.js";
|
|
11
|
-
import "./chunk-KMMASOA6.js";
|
|
12
|
-
import "./chunk-KMCS76ZW.js";
|
|
13
|
-
import "./chunk-7F7LGMVO.js";
|
|
14
|
-
import "./chunk-TZYINKCC.js";
|
|
15
|
-
import "./chunk-WCCZJL7W.js";
|
|
16
|
-
import "./chunk-DGRTJD5R.js";
|
|
17
|
-
import "./chunk-ZVZMWNCG.js";
|
|
18
|
-
import "./chunk-3D4A4B46.js";
|
|
19
|
-
import "./chunk-LGHND47K.js";
|
|
20
|
-
import "./chunk-QF7VEL3M.js";
|
|
21
|
-
import "./chunk-LI35PIIS.js";
|
|
22
|
-
import "./chunk-XZUEFTUP.js";
|
|
23
|
-
import "./chunk-QPGEFLMY.js";
|
|
24
|
-
import "./chunk-HAKDLR6N.js";
|
|
25
|
-
import "./chunk-YVPZUN6X.js";
|
|
26
|
-
import "./chunk-DUS5ZNKL.js";
|
|
27
|
-
import "./chunk-6K2LCFG6.js";
|
|
28
|
-
import "./chunk-PPZ3K4YM.js";
|
|
29
|
-
import "./chunk-SOM4QA6C.js";
|
|
30
|
-
import "./chunk-ICM463EO.js";
|
|
31
|
-
import "./chunk-XEYH6ZZI.js";
|
|
32
|
-
import "./chunk-P3LRUNC6.js";
|
|
33
|
-
import "./chunk-3R27MJ5R.js";
|
|
34
|
-
export {
|
|
35
|
-
issueClosesLines,
|
|
36
|
-
multiIssueContext,
|
|
37
|
-
runPr
|
|
38
|
-
};
|
|
39
|
-
//# sourceMappingURL=pr-UZHNKKZC.js.map
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
exitCodeFor,
|
|
4
|
-
runPrReview
|
|
5
|
-
} from "./chunk-LTH6XYZ3.js";
|
|
6
|
-
import "./chunk-YUNBOUQH.js";
|
|
7
|
-
import "./chunk-KMCS76ZW.js";
|
|
8
|
-
import "./chunk-7F7LGMVO.js";
|
|
9
|
-
import "./chunk-TZYINKCC.js";
|
|
10
|
-
import "./chunk-WCCZJL7W.js";
|
|
11
|
-
import "./chunk-DGRTJD5R.js";
|
|
12
|
-
import "./chunk-ZVZMWNCG.js";
|
|
13
|
-
import "./chunk-LGHND47K.js";
|
|
14
|
-
import "./chunk-QF7VEL3M.js";
|
|
15
|
-
import "./chunk-LI35PIIS.js";
|
|
16
|
-
import "./chunk-XZUEFTUP.js";
|
|
17
|
-
import "./chunk-QPGEFLMY.js";
|
|
18
|
-
import "./chunk-HAKDLR6N.js";
|
|
19
|
-
import "./chunk-YVPZUN6X.js";
|
|
20
|
-
import "./chunk-DUS5ZNKL.js";
|
|
21
|
-
import "./chunk-6K2LCFG6.js";
|
|
22
|
-
import "./chunk-PPZ3K4YM.js";
|
|
23
|
-
import "./chunk-SOM4QA6C.js";
|
|
24
|
-
import "./chunk-ICM463EO.js";
|
|
25
|
-
import "./chunk-XEYH6ZZI.js";
|
|
26
|
-
import "./chunk-P3LRUNC6.js";
|
|
27
|
-
import "./chunk-3R27MJ5R.js";
|
|
28
|
-
export {
|
|
29
|
-
exitCodeFor,
|
|
30
|
-
runPrReview
|
|
31
|
-
};
|
|
32
|
-
//# sourceMappingURL=pr-review-Q4ACAWDM.js.map
|
package/dist/prd-6CYEMLDY.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
runPrd
|
|
4
|
-
} from "./chunk-XUEMATVY.js";
|
|
5
|
-
import "./chunk-V7QOIQYC.js";
|
|
6
|
-
import "./chunk-SA6HXL4Y.js";
|
|
7
|
-
import "./chunk-62GVVZQO.js";
|
|
8
|
-
import "./chunk-KMMASOA6.js";
|
|
9
|
-
import "./chunk-KMCS76ZW.js";
|
|
10
|
-
import "./chunk-7F7LGMVO.js";
|
|
11
|
-
import "./chunk-TZYINKCC.js";
|
|
12
|
-
import "./chunk-WCCZJL7W.js";
|
|
13
|
-
import "./chunk-DGRTJD5R.js";
|
|
14
|
-
import "./chunk-ZVZMWNCG.js";
|
|
15
|
-
import "./chunk-LGHND47K.js";
|
|
16
|
-
import "./chunk-QF7VEL3M.js";
|
|
17
|
-
import "./chunk-LI35PIIS.js";
|
|
18
|
-
import "./chunk-XZUEFTUP.js";
|
|
19
|
-
import "./chunk-QPGEFLMY.js";
|
|
20
|
-
import "./chunk-HAKDLR6N.js";
|
|
21
|
-
import "./chunk-YVPZUN6X.js";
|
|
22
|
-
import "./chunk-DUS5ZNKL.js";
|
|
23
|
-
import "./chunk-6K2LCFG6.js";
|
|
24
|
-
import "./chunk-PPZ3K4YM.js";
|
|
25
|
-
import "./chunk-SOM4QA6C.js";
|
|
26
|
-
import "./chunk-ICM463EO.js";
|
|
27
|
-
import "./chunk-XEYH6ZZI.js";
|
|
28
|
-
import "./chunk-P3LRUNC6.js";
|
|
29
|
-
import "./chunk-3R27MJ5R.js";
|
|
30
|
-
export {
|
|
31
|
-
runPrd
|
|
32
|
-
};
|
|
33
|
-
//# sourceMappingURL=prd-6CYEMLDY.js.map
|
package/dist/ps-76L6ZAZL.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/ps.ts"],"sourcesContent":["import { z } from 'zod';\nimport { type LiveRun, listLiveRuns } from '../execution/registry.js';\nimport { formatDuration, printInfo } from '../ui/logger.js';\n\nexport const liveRunJsonSchema = z.object({\n schemaVersion: z.literal(1),\n runs: z.array(\n z.object({\n projectId: z.string(),\n target: z.string(),\n pid: z.number(),\n host: z.string(),\n detached: z.boolean(),\n status: z.enum(['running', 'unsignaled', 'orphan']),\n startedAt: z.string(),\n lastHeartbeatAt: z.string(),\n issue: z.number().nullable(),\n phase: z.string().nullable(),\n storiesCompleted: z.number().nullable(),\n storiesTotal: z.number().nullable(),\n elapsedSeconds: z.number().nullable(),\n }),\n ),\n});\n\nexport interface PsOptions {\n json?: boolean;\n watch?: boolean;\n}\n\nexport function formatPsTable(runs: readonly LiveRun[]): string[] {\n if (runs.length === 0) return ['No issue-flow run is active on this machine.'];\n\n const header = pad(['STATUS', 'ISSUE', 'PHASE', 'PROGRESS', 'ELAPSED', 'PID', 'PROJECT']);\n const rows = runs.map((run) =>\n pad([\n run.status,\n run.issue !== null ? `#${run.issue}` : run.target,\n run.phase ?? '—',\n run.storiesTotal !== null ? `${run.storiesCompleted ?? 0}/${run.storiesTotal}` : '—',\n run.elapsedSeconds !== null ? formatDuration(run.elapsedSeconds) : '—',\n String(run.pid),\n `${run.projectId}${run.detached ? ' (bg)' : ''}`,\n ]),\n );\n return [header, ...rows];\n}\n\nfunction pad(cells: string[]): string {\n const widths = [12, 10, 12, 10, 10, 8, 24];\n return cells.map((cell, i) => cell.padEnd(widths[i] ?? 12)).join(' ');\n}\n\nexport async function runPs(options: PsOptions = {}): Promise<number> {\n const render = async () => {\n const runs = await listLiveRuns();\n if (options.json === true) {\n const payload = liveRunJsonSchema.parse({\n schemaVersion: 1,\n runs: runs.map(({ lockFile: _lockFile, ...rest }) => rest),\n });\n printInfo(JSON.stringify(payload, null, 2));\n return runs.length;\n }\n for (const line of formatPsTable(runs)) {\n printInfo(line);\n }\n return runs.length;\n };\n\n if (options.watch === true) {\n for (;;) {\n await render();\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n }\n\n await render();\n return 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS;AAIX,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,eAAe,EAAE,QAAQ,CAAC;AAAA,EAC1B,MAAM,EAAE;AAAA,IACN,EAAE,OAAO;AAAA,MACP,WAAW,EAAE,OAAO;AAAA,MACpB,QAAQ,EAAE,OAAO;AAAA,MACjB,KAAK,EAAE,OAAO;AAAA,MACd,MAAM,EAAE,OAAO;AAAA,MACf,UAAU,EAAE,QAAQ;AAAA,MACpB,QAAQ,EAAE,KAAK,CAAC,WAAW,cAAc,QAAQ,CAAC;AAAA,MAClD,WAAW,EAAE,OAAO;AAAA,MACpB,iBAAiB,EAAE,OAAO;AAAA,MAC1B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,MAC3B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,MAC3B,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,MACtC,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,MAClC,gBAAgB,EAAE,OAAO,EAAE,SAAS;AAAA,IACtC,CAAC;AAAA,EACH;AACF,CAAC;AAOM,SAAS,cAAc,MAAoC;AAChE,MAAI,KAAK,WAAW,EAAG,QAAO,CAAC,8CAA8C;AAE7E,QAAM,SAAS,IAAI,CAAC,UAAU,SAAS,SAAS,YAAY,WAAW,OAAO,SAAS,CAAC;AACxF,QAAM,OAAO,KAAK;AAAA,IAAI,CAAC,QACrB,IAAI;AAAA,MACF,IAAI;AAAA,MACJ,IAAI,UAAU,OAAO,IAAI,IAAI,KAAK,KAAK,IAAI;AAAA,MAC3C,IAAI,SAAS;AAAA,MACb,IAAI,iBAAiB,OAAO,GAAG,IAAI,oBAAoB,CAAC,IAAI,IAAI,YAAY,KAAK;AAAA,MACjF,IAAI,mBAAmB,OAAO,eAAe,IAAI,cAAc,IAAI;AAAA,MACnE,OAAO,IAAI,GAAG;AAAA,MACd,GAAG,IAAI,SAAS,GAAG,IAAI,WAAW,UAAU,EAAE;AAAA,IAChD,CAAC;AAAA,EACH;AACA,SAAO,CAAC,QAAQ,GAAG,IAAI;AACzB;AAEA,SAAS,IAAI,OAAyB;AACpC,QAAM,SAAS,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE;AACzC,SAAO,MAAM,IAAI,CAAC,MAAM,MAAM,KAAK,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG;AACtE;AAEA,eAAsB,MAAM,UAAqB,CAAC,GAAoB;AACpE,QAAM,SAAS,YAAY;AACzB,UAAM,OAAO,MAAM,aAAa;AAChC,QAAI,QAAQ,SAAS,MAAM;AACzB,YAAM,UAAU,kBAAkB,MAAM;AAAA,QACtC,eAAe;AAAA,QACf,MAAM,KAAK,IAAI,CAAC,EAAE,UAAU,WAAW,GAAG,KAAK,MAAM,IAAI;AAAA,MAC3D,CAAC;AACD,gBAAU,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAC1C,aAAO,KAAK;AAAA,IACd;AACA,eAAW,QAAQ,cAAc,IAAI,GAAG;AACtC,gBAAU,IAAI;AAAA,IAChB;AACA,WAAO,KAAK;AAAA,EACd;AAEA,MAAI,QAAQ,UAAU,MAAM;AAC1B,eAAS;AACP,YAAM,OAAO;AACb,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AAEA,QAAM,OAAO;AACb,SAAO;AACT;","names":[]}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
classifyRunLock,
|
|
4
|
-
listLiveRuns
|
|
5
|
-
} from "./chunk-RNFUVKC3.js";
|
|
6
|
-
import "./chunk-RYOUZ6EK.js";
|
|
7
|
-
import "./chunk-HAKDLR6N.js";
|
|
8
|
-
import "./chunk-YVPZUN6X.js";
|
|
9
|
-
import "./chunk-ICM463EO.js";
|
|
10
|
-
import "./chunk-XEYH6ZZI.js";
|
|
11
|
-
export {
|
|
12
|
-
classifyRunLock,
|
|
13
|
-
listLiveRuns
|
|
14
|
-
};
|
|
15
|
-
//# sourceMappingURL=registry-XLHHYLTR.js.map
|