issue-flow 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -274
- package/dist/agent-BXRIEKVM.js +238 -0
- package/dist/agent-BXRIEKVM.js.map +1 -0
- package/dist/{analyze-OEET7KGE.js → analyze-WS47UYGN.js} +28 -16
- package/dist/analyze-WS47UYGN.js.map +1 -0
- package/dist/{apply-ZIA3C52S.js → apply-OS62UWRN.js} +15 -7
- package/dist/{apply-ZIA3C52S.js.map → apply-OS62UWRN.js.map} +1 -1
- package/dist/bench-SA3BOME5.js +906 -0
- package/dist/bench-SA3BOME5.js.map +1 -0
- package/dist/chunk-37N2RJW2.js +120 -0
- package/dist/chunk-37N2RJW2.js.map +1 -0
- package/dist/chunk-3XLCNVMD.js +180 -0
- package/dist/chunk-3XLCNVMD.js.map +1 -0
- package/dist/chunk-5TB6KLC2.js +72 -0
- package/dist/chunk-5TB6KLC2.js.map +1 -0
- package/dist/{chunk-MJULIKQU.js → chunk-664Y3NDX.js} +23 -47
- package/dist/chunk-664Y3NDX.js.map +1 -0
- package/dist/chunk-6FDFRNXZ.js +357 -0
- package/dist/chunk-6FDFRNXZ.js.map +1 -0
- package/dist/{chunk-56KS3TFQ.js → chunk-7KD66LIM.js} +115 -160
- package/dist/chunk-7KD66LIM.js.map +1 -0
- package/dist/chunk-7Z4Y3VKM.js +26 -0
- package/dist/chunk-7Z4Y3VKM.js.map +1 -0
- package/dist/chunk-ARFVHC2F.js +1111 -0
- package/dist/chunk-ARFVHC2F.js.map +1 -0
- package/dist/{chunk-NS6R37II.js → chunk-BHJCGWQX.js} +141 -12
- package/dist/chunk-BHJCGWQX.js.map +1 -0
- package/dist/chunk-BQDQTIM7.js +74 -0
- package/dist/chunk-BQDQTIM7.js.map +1 -0
- package/dist/chunk-CNBYCMSU.js +2709 -0
- package/dist/chunk-CNBYCMSU.js.map +1 -0
- package/dist/chunk-CRGIQFUQ.js +83 -0
- package/dist/chunk-CRGIQFUQ.js.map +1 -0
- package/dist/chunk-DIG5XKQQ.js +298 -0
- package/dist/chunk-DIG5XKQQ.js.map +1 -0
- package/dist/chunk-FZDR7CGH.js +71 -0
- package/dist/chunk-FZDR7CGH.js.map +1 -0
- package/dist/chunk-HEF2RMKN.js +413 -0
- package/dist/chunk-HEF2RMKN.js.map +1 -0
- package/dist/{chunk-M5UCXTIT.js → chunk-HJGGNLWI.js} +22 -18
- package/dist/chunk-HJGGNLWI.js.map +1 -0
- package/dist/chunk-HQAHNIAR.js +283 -0
- package/dist/chunk-HQAHNIAR.js.map +1 -0
- package/dist/{chunk-FJP3UQGD.js → chunk-IHIEXUTC.js} +39 -19
- package/dist/chunk-IHIEXUTC.js.map +1 -0
- package/dist/{chunk-Y5ZDJ4PJ.js → chunk-IV5SS4JN.js} +18 -10
- package/dist/chunk-IV5SS4JN.js.map +1 -0
- package/dist/{chunk-BYZDPR7N.js → chunk-IYV6KNVF.js} +146 -13
- package/dist/chunk-IYV6KNVF.js.map +1 -0
- package/dist/{chunk-TSOLWK7Y.js → chunk-J62QSVP6.js} +8 -8
- package/dist/chunk-KQHB7ZT3.js +559 -0
- package/dist/chunk-KQHB7ZT3.js.map +1 -0
- package/dist/chunk-L6HSKTQE.js +77 -0
- package/dist/chunk-L6HSKTQE.js.map +1 -0
- package/dist/{chunk-3QHK4YQA.js → chunk-LZ6GFQAG.js} +334 -117
- package/dist/chunk-LZ6GFQAG.js.map +1 -0
- package/dist/{chunk-LAFNLLQP.js → chunk-MIVHK5YI.js} +5 -5
- package/dist/chunk-NEZZ6KDR.js +1217 -0
- package/dist/chunk-NEZZ6KDR.js.map +1 -0
- package/dist/{chunk-NTMMF5UD.js → chunk-OPNGPUKJ.js} +436 -254
- package/dist/chunk-OPNGPUKJ.js.map +1 -0
- package/dist/chunk-P3LRUNC6.js +16 -0
- package/dist/chunk-P3LRUNC6.js.map +1 -0
- package/dist/{chunk-FADTCQGM.js → chunk-PIVGJM6K.js} +94 -32
- package/dist/chunk-PIVGJM6K.js.map +1 -0
- package/dist/{chunk-73ATPIYX.js → chunk-PV4OX5TC.js} +36 -71
- package/dist/chunk-PV4OX5TC.js.map +1 -0
- package/dist/chunk-QCXPNSEL.js +141 -0
- package/dist/chunk-QCXPNSEL.js.map +1 -0
- package/dist/{chunk-XQUSIEKA.js → chunk-QXDNBYQF.js} +52 -14
- package/dist/chunk-QXDNBYQF.js.map +1 -0
- package/dist/chunk-SNTTOQAD.js +30 -0
- package/dist/chunk-SNTTOQAD.js.map +1 -0
- package/dist/{chunk-QCPGHBSZ.js → chunk-TM67EHSV.js} +63 -21
- package/dist/chunk-TM67EHSV.js.map +1 -0
- package/dist/chunk-TVN2JVOF.js +77 -0
- package/dist/chunk-TVN2JVOF.js.map +1 -0
- package/dist/chunk-TX5WIVYP.js +129 -0
- package/dist/chunk-TX5WIVYP.js.map +1 -0
- package/dist/{chunk-A4SLHOW7.js → chunk-UJ7XWK7J.js} +24 -18
- package/dist/chunk-UJ7XWK7J.js.map +1 -0
- package/dist/{chunk-EZATO3DW.js → chunk-UOCPC2Y2.js} +594 -17
- package/dist/chunk-UOCPC2Y2.js.map +1 -0
- package/dist/chunk-XEYH6ZZI.js +289 -0
- package/dist/chunk-XEYH6ZZI.js.map +1 -0
- package/dist/cli.js +264 -44
- package/dist/cli.js.map +1 -1
- package/dist/{config-PRJGWW7J.js → config-MEM2IWWN.js} +28 -5
- package/dist/contract-JH2WBIO6.js +8 -0
- package/dist/conventions-WV4NDXGH.js +143 -0
- package/dist/conventions-WV4NDXGH.js.map +1 -0
- package/dist/execute-NITIHHCK.js +31 -0
- package/dist/{generate-EGB4KV2B.js → generate-MVQI7A45.js} +34 -20
- package/dist/{generate-EGB4KV2B.js.map → generate-MVQI7A45.js.map} +1 -1
- package/dist/git-YRVRUN3C.js +31 -0
- package/dist/init-OKWEC3EV.js +21 -0
- package/dist/{operations-BYT626KQ.js → operations-LU6JA3BX.js} +24 -15
- package/dist/{operations-BYT626KQ.js.map → operations-LU6JA3BX.js.map} +1 -1
- package/dist/permissions-7NMDFU27.js +18 -0
- package/dist/plan-LEJJF3DE.js +31 -0
- package/dist/{policy-6S4GFC76.js → policy-JSYEK5B2.js} +17 -6
- package/dist/policy-JSYEK5B2.js.map +1 -0
- package/dist/pr-HPVUZ7S3.js +36 -0
- package/dist/pr-review-R2QZBT3F.js +29 -0
- package/dist/prd-5O6GYCC6.js +30 -0
- package/dist/ps-TNE44R5V.js +90 -0
- package/dist/ps-TNE44R5V.js.map +1 -0
- package/dist/recorder-XGF55WXI.js +31 -0
- package/dist/recorder-XGF55WXI.js.map +1 -0
- package/dist/registry-LGPE53QD.js +15 -0
- package/dist/registry-LGPE53QD.js.map +1 -0
- package/dist/{resume-PPCNQVVV.js → resume-QMEPMSZW.js} +51 -34
- package/dist/{resume-PPCNQVVV.js.map → resume-QMEPMSZW.js.map} +1 -1
- package/dist/review-YKWD6SNN.js +32 -0
- package/dist/review-YKWD6SNN.js.map +1 -0
- package/dist/routing-2ZUMZPJB.js +91 -0
- package/dist/routing-2ZUMZPJB.js.map +1 -0
- package/dist/run-YU4TR62R.js +50 -0
- package/dist/run-YU4TR62R.js.map +1 -0
- package/dist/{state-manager-2EDVDBAR.js → state-manager-X3PT3FGT.js} +4 -2
- package/dist/state-manager-X3PT3FGT.js.map +1 -0
- package/dist/usage-VCFLDA5Y.js +174 -0
- package/dist/usage-VCFLDA5Y.js.map +1 -0
- package/dist/{web-EF5WIIGG.js → web-XVHLX62B.js} +41 -30
- package/dist/web-XVHLX62B.js.map +1 -0
- package/package.json +6 -2
- package/prompts/execute.md +7 -8
- package/prompts/plan.md +4 -5
- package/prompts/pr.md +2 -2
- package/web/AGENTS.md +3 -3
- package/web/public/app.css +38 -0
- package/web/public/app.js +121 -11
- package/web/public/index.html +24 -0
- package/dist/analyze-OEET7KGE.js.map +0 -1
- package/dist/chunk-3QHK4YQA.js.map +0 -1
- package/dist/chunk-42PJFMAR.js +0 -605
- package/dist/chunk-42PJFMAR.js.map +0 -1
- package/dist/chunk-4JSOYE4G.js +0 -368
- package/dist/chunk-4JSOYE4G.js.map +0 -1
- package/dist/chunk-56KS3TFQ.js.map +0 -1
- package/dist/chunk-73ATPIYX.js.map +0 -1
- package/dist/chunk-A4SLHOW7.js.map +0 -1
- package/dist/chunk-BAUPQXPE.js +0 -173
- package/dist/chunk-BAUPQXPE.js.map +0 -1
- package/dist/chunk-BYZDPR7N.js.map +0 -1
- package/dist/chunk-CD5ULRVC.js +0 -615
- package/dist/chunk-CD5ULRVC.js.map +0 -1
- package/dist/chunk-DIDUVL6O.js +0 -1365
- package/dist/chunk-DIDUVL6O.js.map +0 -1
- package/dist/chunk-EZATO3DW.js.map +0 -1
- package/dist/chunk-FADTCQGM.js.map +0 -1
- package/dist/chunk-FJP3UQGD.js.map +0 -1
- package/dist/chunk-LWRSMTTZ.js +0 -18
- package/dist/chunk-LWRSMTTZ.js.map +0 -1
- package/dist/chunk-M5UCXTIT.js.map +0 -1
- package/dist/chunk-M66SJHQQ.js +0 -206
- package/dist/chunk-M66SJHQQ.js.map +0 -1
- package/dist/chunk-MJULIKQU.js.map +0 -1
- package/dist/chunk-NS6R37II.js.map +0 -1
- package/dist/chunk-NTMMF5UD.js.map +0 -1
- package/dist/chunk-QCPGHBSZ.js.map +0 -1
- package/dist/chunk-XQUSIEKA.js.map +0 -1
- package/dist/chunk-Y5ZDJ4PJ.js.map +0 -1
- package/dist/execute-XBNVL753.js +0 -18
- package/dist/init-AJHCXJBP.js +0 -10
- package/dist/plan-QOZ3RIO6.js +0 -21
- package/dist/policy-6S4GFC76.js.map +0 -1
- package/dist/pr-EBBHD2ZX.js +0 -26
- package/dist/pr-review-VVMW5PO4.js +0 -20
- package/dist/prd-JQSZF7PR.js +0 -21
- package/dist/review-3F6MARWH.js +0 -19
- package/dist/run-RXE5GDQO.js +0 -36
- package/dist/web-EF5WIIGG.js.map +0 -1
- /package/dist/{chunk-TSOLWK7Y.js.map → chunk-J62QSVP6.js.map} +0 -0
- /package/dist/{chunk-LAFNLLQP.js.map → chunk-MIVHK5YI.js.map} +0 -0
- /package/dist/{config-PRJGWW7J.js.map → config-MEM2IWWN.js.map} +0 -0
- /package/dist/{execute-XBNVL753.js.map → contract-JH2WBIO6.js.map} +0 -0
- /package/dist/{init-AJHCXJBP.js.map → execute-NITIHHCK.js.map} +0 -0
- /package/dist/{plan-QOZ3RIO6.js.map → git-YRVRUN3C.js.map} +0 -0
- /package/dist/{pr-EBBHD2ZX.js.map → init-OKWEC3EV.js.map} +0 -0
- /package/dist/{pr-review-VVMW5PO4.js.map → permissions-7NMDFU27.js.map} +0 -0
- /package/dist/{prd-JQSZF7PR.js.map → plan-LEJJF3DE.js.map} +0 -0
- /package/dist/{review-3F6MARWH.js.map → pr-HPVUZ7S3.js.map} +0 -0
- /package/dist/{run-RXE5GDQO.js.map → pr-review-R2QZBT3F.js.map} +0 -0
- /package/dist/{state-manager-2EDVDBAR.js.map → prd-5O6GYCC6.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resilience/errors.ts"],"sourcesContent":["/**\n * Failure taxonomy.\n *\n * Every failure the pipeline reacts to is classified here, from a structured\n * `FailureSignal`, into one `FailureKind`. The point is that the decision to\n * retry stops depending on `String.includes` over an error message: text is the\n * last resort of `classify()`, not its first move.\n *\n * The invariants of this layer — above all, that `task_execution` is never\n * retried here — are in `src/resilience/AGENTS.md`.\n */\n\n/** What went wrong, in the terms the retry policy is written in. */\nexport type FailureKind =\n | 'network'\n | 'timeout'\n | 'stalled'\n | 'rate_limit'\n | 'provider_down'\n | 'provider_crash'\n | 'authentication'\n | 'configuration'\n | 'repository_state'\n | 'task_execution'\n | 'internal'\n | 'unknown';\n\n/** Which subsystem produced the failure. */\nexport type FailureSource = 'agent' | 'github' | 'git' | 'filesystem' | 'internal';\n\n/**\n * The raw evidence of a failure, as the caller observed it.\n *\n * Everything is optional but `source`: a caller hands over what it actually\n * has. `execa` supplies `exitCode`, `signal`, `timedOut` and — on the thrown\n * error — `errno`; an HTTP client supplies `httpStatus` and `retryAfter`.\n */\nexport interface FailureSignal {\n source: FailureSource;\n exitCode?: number | null;\n /** POSIX signal name that terminated the process (`SIGTERM`, `SIGKILL`). */\n signal?: string | null;\n /** `execa`'s own verdict that it killed the child on the configured limit. */\n timedOut?: boolean;\n stdout?: string;\n stderr?: string;\n /** `ENOTFOUND`, `ECONNRESET`, `ETIMEDOUT`, `EAI_AGAIN`… */\n errno?: string;\n httpStatus?: number;\n /** A server's `Retry-After` header: delay in seconds, or an HTTP date. */\n retryAfter?: string | number;\n /** Set by the watchdog when a child produced no output for too long. */\n stalled?: boolean;\n}\n\n/** The verdict. `retryable` is advice; the attempt budget belongs to the policy. */\nexport interface ClassifiedFailure {\n kind: FailureKind;\n message: string;\n retryable: boolean;\n source: FailureSource;\n /** Present only when the server told us how long to wait. */\n retryAfterMs?: number;\n}\n\n/**\n * Kinds worth another attempt: the cause is outside the work being done and is\n * expected to pass on its own.\n */\nconst RETRYABLE_KINDS: ReadonlySet<FailureKind> = new Set<FailureKind>([\n 'network',\n 'timeout',\n 'stalled',\n 'rate_limit',\n 'provider_down',\n 'provider_crash',\n]);\n\n/**\n * Kinds that no configuration may retry. Waiting cannot fix any of them: they\n * need a human, or they belong to a different loop entirely (`task_execution`\n * is the pipeline's own correction cycle — see `AGENTS.md` here).\n */\nconst HUMAN_ACTION_KINDS: ReadonlySet<FailureKind> = new Set<FailureKind>([\n 'authentication',\n 'configuration',\n 'repository_state',\n 'task_execution',\n]);\n\n/** Whether this layer considers `kind` worth retrying at all. */\nexport function isRetryableKind(kind: FailureKind): boolean {\n return RETRYABLE_KINDS.has(kind);\n}\n\n/** Whether `kind` escalates to a human instead of being retried, ever. */\nexport function requiresHumanAction(kind: FailureKind): boolean {\n return HUMAN_ACTION_KINDS.has(kind);\n}\n\n/* ── carrying a verdict through a throw ─────────────────────────────────── */\n\n/**\n * An `Error` that carries its own classification.\n *\n * A `catch` normally flattens a failure back into a string, which is exactly\n * the loss this layer exists to prevent: the caller that has to decide between\n * \"retry\" and \"escalate to a human\" then has nothing but a message again. Any\n * boundary that must throw — a provider, a phase — throws this instead.\n *\n * `action` is what a human has to do, and it is only ever set for a kind that\n * needs one (`gh auth login` for `authentication`). It is written at the throw\n * site because only that site knows which CLI is involved.\n */\nexport class ClassifiedError extends Error {\n readonly failure: ClassifiedFailure;\n readonly action: string | undefined;\n\n constructor(message: string, failure: ClassifiedFailure, action?: string) {\n super(message);\n this.name = 'ClassifiedError';\n this.failure = failure;\n this.action = action;\n }\n}\n\n/** The verdict an error carries, or `null` when it carries none. */\nexport function failureOf(error: unknown): ClassifiedFailure | null {\n return error instanceof ClassifiedError ? error.failure : null;\n}\n\n/** The human action an error asks for, or `null`. */\nexport function actionOf(error: unknown): string | null {\n return error instanceof ClassifiedError ? (error.action ?? null) : null;\n}\n\n/* ── step 1: errno ──────────────────────────────────────────────────────── */\n\nconst ERRNO_KINDS: Readonly<Record<string, FailureKind>> = {\n ENOTFOUND: 'network',\n EAI_AGAIN: 'network',\n ECONNRESET: 'network',\n ECONNREFUSED: 'network',\n ECONNABORTED: 'network',\n EHOSTUNREACH: 'network',\n ENETUNREACH: 'network',\n ENETDOWN: 'network',\n EPIPE: 'network',\n ETIMEDOUT: 'timeout',\n ENOENT: 'configuration',\n EACCES: 'configuration',\n EPERM: 'configuration',\n};\n\nfunction kindFromErrno(errno: string | undefined): FailureKind | undefined {\n if (!errno) return undefined;\n return ERRNO_KINDS[errno.toUpperCase()];\n}\n\n/* ── step 2: HTTP status ────────────────────────────────────────────────── */\n\n/**\n * GitHub reports a secondary rate limit as `403`, not `429`, so the text is\n * consulted before calling a `403` an authentication failure. Everywhere else\n * the status alone decides.\n */\nfunction kindFromHttpStatus(status: number | undefined, lowered: string): FailureKind | undefined {\n if (status === undefined || status < 400) return undefined;\n if (status === 429) return 'rate_limit';\n if (status === 401) return 'authentication';\n if (status === 403)\n return matchesAny(lowered, RATE_LIMIT_PATTERNS) ? 'rate_limit' : 'authentication';\n if (status === 408) return 'timeout';\n if (status >= 500) return 'provider_down';\n return 'configuration';\n}\n\n/* ── step 3: how the process ended ──────────────────────────────────────── */\n\nconst CRASH_SIGNALS: ReadonlySet<string> = new Set(['SIGKILL', 'SIGABRT', 'SIGSEGV', 'SIGBUS']);\n\nfunction kindFromTermination(signal: FailureSignal): FailureKind | undefined {\n if (signal.stalled === true) return 'stalled';\n if (signal.timedOut === true) return 'timeout';\n const name = signal.signal?.toUpperCase();\n if (!name) return undefined;\n if (name === 'SIGTERM') return 'timeout';\n if (CRASH_SIGNALS.has(name)) return 'provider_crash';\n return undefined;\n}\n\n/* ── step 4: exit codes we know the meaning of ──────────────────────────── */\n\n/**\n * Only codes whose meaning is unambiguous. `143` (SIGTERM) is deliberately\n * absent: the Claude CLI handles the signal itself and exits `143` for a\n * user's Ctrl+C just as it does for our timeout, so it decides nothing on its\n * own — `timedOut` or `signal` is what tells the two apart.\n */\nconst EXIT_CODE_KINDS: Readonly<Record<number, FailureKind>> = {\n 75: 'provider_down', // EX_TEMPFAIL\n 126: 'configuration', // found, not executable\n 127: 'configuration', // command not found\n 137: 'provider_crash', // 128 + SIGKILL, typically the OOM killer\n 139: 'provider_crash', // 128 + SIGSEGV\n};\n\nfunction kindFromExitCode(exitCode: number | null | undefined): FailureKind | undefined {\n if (exitCode === null || exitCode === undefined) return undefined;\n return EXIT_CODE_KINDS[exitCode];\n}\n\n/* ── step 5: text, and only as a last resort ────────────────────────────── */\n\nconst RATE_LIMIT_PATTERNS = [\n 'rate limit',\n 'rate-limit',\n 'ratelimit',\n 'too many requests',\n 'http 429',\n] as const;\n\n/**\n * Ordered on purpose. A message is scanned rule by rule and the first hit\n * wins, so the specific causes (rate limit, credentials) are consulted before\n * the generic ones, and `task_execution` comes last: an infrastructure failure\n * surfacing inside a test run is still an infrastructure failure.\n */\ntype TextPattern = string | RegExp;\n\nconst TEXT_RULES: readonly { kind: FailureKind; patterns: readonly TextPattern[] }[] = [\n { kind: 'rate_limit', patterns: RATE_LIMIT_PATTERNS },\n {\n kind: 'authentication',\n patterns: [\n 'authentication failed',\n 'authentication_error',\n 'gh auth login',\n 'not logged into',\n 'bad credentials',\n 'invalid api key',\n 'invalid_api_key',\n 'token expired',\n 'expired token',\n 'unauthorized',\n 'http 401',\n 'http 403',\n ],\n },\n {\n kind: 'network',\n patterns: [\n 'connection reset',\n 'connection refused',\n 'connection aborted',\n 'network error',\n 'network unavailable',\n 'temporary failure',\n 'econnreset',\n 'econnrefused',\n 'enotfound',\n 'eai_again',\n 'socket hang up',\n // What Go prints, and therefore what `gh` prints: its network errors\n // never mention \"connection reset\", they mention the resolver.\n 'no such host',\n 'dial tcp',\n 'i/o timeout',\n 'tls handshake timeout',\n 'server misbehaving',\n 'error connecting to',\n ],\n },\n // Before the timeout rule: a stall *is* a kind of timeout, and the specific\n // reading is the useful one — it has its own budget and its own escalation.\n { kind: 'stalled', patterns: ['produced no output for', '(stalled)'] },\n { kind: 'timeout', patterns: ['timed out', 'timeout', 'etimedout'] },\n {\n kind: 'provider_down',\n patterns: [\n 'service unavailable',\n 'temporarily unavailable',\n 'overloaded',\n 'bad gateway',\n 'gateway timeout',\n 'internal server error',\n 'http 500',\n 'http 502',\n 'http 503',\n 'http 504',\n ],\n },\n {\n kind: 'provider_crash',\n patterns: ['segmentation fault', 'core dumped', 'out of memory', 'killed by signal'],\n },\n {\n kind: 'repository_state',\n patterns: [\n 'unmerged paths',\n 'needs merge',\n 'automatic merge failed',\n 'rebase in progress',\n 'you are in the middle of',\n 'cherry-pick is in progress',\n 'not a git repository',\n ],\n },\n {\n kind: 'configuration',\n patterns: [\n 'command not found',\n 'unknown flag',\n 'unknown option',\n 'no such file or directory',\n 'permission check failed',\n 'user denied permission',\n 'waiting for human input',\n 'status: waiting',\n 'below the minimum',\n 'prompt exceeds',\n 'nativetimeout',\n 'agy is not installed',\n ],\n },\n {\n kind: 'task_execution',\n patterns: [\n 'test failed',\n 'tests failed',\n 'failed tests',\n 'failing test',\n 'assertion failed',\n 'assertionerror',\n 'expect(received)',\n 'typecheck failed',\n 'npm err! test failed',\n 'lint failed',\n 'build failed',\n 'compilation failed',\n 'syntaxerror',\n 'typeerror',\n 'referenceerror',\n // What a runner actually prints: \"Tests 3 failed | 41 passed\",\n // \"Test Files 1 failed (12)\", \"Tests: 2 failed, 8 total\".\n /\\b\\d+\\s+failed\\b/,\n ],\n },\n];\n\nfunction matchesAny(lowered: string, patterns: readonly TextPattern[]): boolean {\n return patterns.some((pattern) =>\n typeof pattern === 'string' ? lowered.includes(pattern) : pattern.test(lowered),\n );\n}\n\nfunction kindFromText(lowered: string): FailureKind | undefined {\n if (!lowered) return undefined;\n for (const rule of TEXT_RULES) {\n if (matchesAny(lowered, rule.patterns)) return rule.kind;\n }\n return undefined;\n}\n\n/* ── Retry-After ────────────────────────────────────────────────────────── */\n\nconst RETRY_AFTER_IN_TEXT = /retry[\\s-]?after:?\\s*(\\d+)/i;\n\n/**\n * `Retry-After` is either a delay in seconds or an HTTP date. Both are\n * accepted; anything else, and a date already in the past, yields nothing\n * rather than a bogus zero.\n */\nfunction parseRetryAfter(value: string | number | undefined, now: number): number | undefined {\n if (value === undefined) return undefined;\n if (typeof value === 'number')\n return Number.isFinite(value) && value >= 0 ? value * 1000 : undefined;\n\n const trimmed = value.trim();\n if (trimmed === '') return undefined;\n if (/^\\d+$/.test(trimmed)) return Number(trimmed) * 1000;\n\n const at = Date.parse(trimmed);\n if (Number.isNaN(at)) return undefined;\n return at > now ? at - now : undefined;\n}\n\nfunction resolveRetryAfterMs(signal: FailureSignal, text: string, now: number): number | undefined {\n const explicit = parseRetryAfter(signal.retryAfter, now);\n if (explicit !== undefined) return explicit;\n\n const inText = RETRY_AFTER_IN_TEXT.exec(text);\n return inText ? Number(inText[1]) * 1000 : undefined;\n}\n\n/* ── message ────────────────────────────────────────────────────────────── */\n\nfunction combineOutput(signal: FailureSignal): string {\n return [signal.stderr, signal.stdout].filter((part) => part && part.trim() !== '').join('\\n');\n}\n\n/** The output verbatim when there is any, and a synthesised line when there is not. */\nfunction describe(signal: FailureSignal, text: string): string {\n const trimmed = text.trim();\n if (trimmed !== '') return trimmed;\n if (signal.errno) return `${signal.source} failed with ${signal.errno}`;\n if (signal.httpStatus !== undefined)\n return `${signal.source} responded HTTP ${signal.httpStatus}`;\n if (signal.timedOut === true) return `${signal.source} timed out`;\n if (signal.signal) return `${signal.source} was terminated by ${signal.signal}`;\n if (signal.exitCode !== null && signal.exitCode !== undefined) {\n return `${signal.source} exited with code ${signal.exitCode}`;\n }\n return `${signal.source} failed for an unreported reason`;\n}\n\n/* ── the classifier ─────────────────────────────────────────────────────── */\n\nexport interface ClassifyOptions {\n /** Injectable clock, so an HTTP-date `Retry-After` is testable. */\n now?: () => number;\n}\n\n/**\n * Classify a failure by precedence: errno and HTTP status first (a machine\n * told us), then how the process ended, then an exit code we know the meaning\n * of, and only then the text — which is a heuristic and is treated as one.\n */\nexport function classify(signal: FailureSignal, options: ClassifyOptions = {}): ClassifiedFailure {\n const now = options.now?.() ?? Date.now();\n const text = combineOutput(signal);\n const lowered = text.toLowerCase();\n\n const kind =\n kindFromErrno(signal.errno) ??\n kindFromHttpStatus(signal.httpStatus, lowered) ??\n kindFromTermination(signal) ??\n kindFromExitCode(signal.exitCode) ??\n kindFromText(lowered) ??\n 'unknown';\n\n const retryAfterMs = resolveRetryAfterMs(signal, text, now);\n\n return {\n kind,\n message: describe(signal, text),\n retryable: isRetryableKind(kind),\n source: signal.source,\n ...(retryAfterMs === undefined ? {} : { retryAfterMs }),\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -1,25 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
DEFAULT_INACTIVITY_TIMEOUT_MS,
|
|
4
|
-
installShutdownHandlers
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
installShutdownHandlers,
|
|
5
|
+
parseAgentPhaseFlag,
|
|
6
|
+
setAgentCliOverrides,
|
|
7
7
|
setIssuesCliOverrides,
|
|
8
8
|
setResilienceCliOverrides,
|
|
9
|
+
setRoutingCliOverrides,
|
|
10
|
+
setVerifyCliOverrides,
|
|
9
11
|
setWebCliOverrides
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-CNBYCMSU.js";
|
|
13
|
+
import "./chunk-HQAHNIAR.js";
|
|
12
14
|
import {
|
|
13
15
|
printError,
|
|
14
16
|
setGlobalTimeout,
|
|
15
17
|
setInactivityTimeout,
|
|
16
18
|
setVerbose
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-IYV6KNVF.js";
|
|
20
|
+
import "./chunk-6FDFRNXZ.js";
|
|
21
|
+
import "./chunk-P3LRUNC6.js";
|
|
22
|
+
import "./chunk-DIG5XKQQ.js";
|
|
23
|
+
import {
|
|
24
|
+
isAgentProviderId
|
|
25
|
+
} from "./chunk-NEZZ6KDR.js";
|
|
26
|
+
import "./chunk-TX5WIVYP.js";
|
|
27
|
+
import "./chunk-KQHB7ZT3.js";
|
|
28
|
+
import "./chunk-7Z4Y3VKM.js";
|
|
29
|
+
import "./chunk-XEYH6ZZI.js";
|
|
19
30
|
|
|
20
31
|
// src/cli.ts
|
|
21
32
|
import { createRequire } from "module";
|
|
22
|
-
import { Command, InvalidArgumentError } from "commander";
|
|
33
|
+
import { Command, InvalidArgumentError, Option } from "commander";
|
|
23
34
|
|
|
24
35
|
// src/cli-options.ts
|
|
25
36
|
function resolveNoBranch(options) {
|
|
@@ -37,9 +48,15 @@ function resolveQueueScopeFlags(options) {
|
|
|
37
48
|
"--yes cannot be combined with --only: --yes runs the whole discovered hierarchy, --only runs just the issues you informed."
|
|
38
49
|
);
|
|
39
50
|
}
|
|
51
|
+
if (options.cascade === true && options.only === true) {
|
|
52
|
+
throw new CliFlagError(
|
|
53
|
+
"--cascade cannot be combined with --only: --cascade runs the container hierarchy, --only runs just the issues you informed."
|
|
54
|
+
);
|
|
55
|
+
}
|
|
40
56
|
return {
|
|
41
57
|
yes: options.yes === true ? true : void 0,
|
|
42
|
-
only: options.only === true ? true : void 0
|
|
58
|
+
only: options.only === true ? true : void 0,
|
|
59
|
+
cascade: options.cascade === true ? true : void 0
|
|
43
60
|
};
|
|
44
61
|
}
|
|
45
62
|
function resolveRunPhaseFlags(options) {
|
|
@@ -156,6 +173,16 @@ function parseInteger(value) {
|
|
|
156
173
|
}
|
|
157
174
|
return parsed;
|
|
158
175
|
}
|
|
176
|
+
function parseUsd(value) {
|
|
177
|
+
const parsed = Number.parseFloat(value);
|
|
178
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
179
|
+
throw new InvalidArgumentError("Must be a non-negative number.");
|
|
180
|
+
}
|
|
181
|
+
return parsed;
|
|
182
|
+
}
|
|
183
|
+
function collectString(value, previous) {
|
|
184
|
+
return [...previous, value];
|
|
185
|
+
}
|
|
159
186
|
function parseQueueFailureMode(value) {
|
|
160
187
|
if (value === "stop" || value === "skip" || value === "block") return value;
|
|
161
188
|
throw new InvalidArgumentError("Must be one of: stop, skip, block.");
|
|
@@ -175,7 +202,7 @@ function withUserStoryNumberingOptions(cmd) {
|
|
|
175
202
|
);
|
|
176
203
|
}
|
|
177
204
|
function withGlobalOptions(cmd) {
|
|
178
|
-
return cmd.option("-v, --verbose", "Show
|
|
205
|
+
return cmd.option("-v, --verbose", "Show agent progress output in real time").option(
|
|
179
206
|
"-t, --timeout <seconds>",
|
|
180
207
|
"Override headless timeout in seconds (0 = no limit)",
|
|
181
208
|
parseInteger
|
|
@@ -183,7 +210,67 @@ function withGlobalOptions(cmd) {
|
|
|
183
210
|
"--inactivity-timeout <seconds>",
|
|
184
211
|
"Stop the agent after this many seconds with no output (0 = no watchdog)",
|
|
185
212
|
parseInteger
|
|
186
|
-
)
|
|
213
|
+
).option(
|
|
214
|
+
"--agent <provider>",
|
|
215
|
+
"Run every phase on this agent (claude|codex|cursor|antigravity)"
|
|
216
|
+
).option("--agent-model <model>", "Override the model for every phase").option(
|
|
217
|
+
"--agent-phase <phase>=<provider>[:<model>]",
|
|
218
|
+
"Override one phase (repeatable)",
|
|
219
|
+
collectAgentPhase,
|
|
220
|
+
{}
|
|
221
|
+
).option("--verify-level <level>", "Acceptance-contract level: L0 | L1 | L2 | L3 | L5").option("--no-cross-verify", "Keep L2 off even when a trigger would fire").option("--no-escalation", "Keep routing.escalation.enabled off").option("--max-cost <usd>", "Issue cost ceiling in USD (Issue Flow enforces it)", parseUsd).option("--max-duration <seconds>", "Issue duration ceiling in seconds", parseInteger);
|
|
222
|
+
}
|
|
223
|
+
function collectAgentPhase(value, previous) {
|
|
224
|
+
const parsed = parseAgentPhaseFlag(value);
|
|
225
|
+
return { ...previous, [parsed.phase]: parsed.block };
|
|
226
|
+
}
|
|
227
|
+
function resolveAgentOverrides(opts) {
|
|
228
|
+
const overrides = {};
|
|
229
|
+
if (typeof opts.agent === "string") {
|
|
230
|
+
if (!isAgentProviderId(opts.agent)) {
|
|
231
|
+
throw new InvalidArgumentError("Must be one of: claude, codex, cursor, antigravity.");
|
|
232
|
+
}
|
|
233
|
+
overrides.forceProvider = opts.agent;
|
|
234
|
+
}
|
|
235
|
+
if (typeof opts.agentModel === "string") {
|
|
236
|
+
overrides.forceModel = opts.agentModel;
|
|
237
|
+
}
|
|
238
|
+
if (opts.agentPhase && typeof opts.agentPhase === "object") {
|
|
239
|
+
overrides.phases = opts.agentPhase;
|
|
240
|
+
}
|
|
241
|
+
return overrides;
|
|
242
|
+
}
|
|
243
|
+
var VERIFY_LEVELS = ["L0", "L1", "L2", "L3", "L5"];
|
|
244
|
+
function resolveVerifyOverrides(opts) {
|
|
245
|
+
const overrides = {};
|
|
246
|
+
if (typeof opts.verifyLevel === "string") {
|
|
247
|
+
if (!VERIFY_LEVELS.includes(opts.verifyLevel)) {
|
|
248
|
+
throw new InvalidArgumentError("Must be one of: L0, L1, L2, L3, L5.");
|
|
249
|
+
}
|
|
250
|
+
overrides.level = opts.verifyLevel;
|
|
251
|
+
}
|
|
252
|
+
if (opts.crossVerify === false) overrides.crossVerify = false;
|
|
253
|
+
return overrides;
|
|
254
|
+
}
|
|
255
|
+
function resolveRoutingOverrides(opts) {
|
|
256
|
+
const overrides = {};
|
|
257
|
+
if (opts.escalation === false) {
|
|
258
|
+
overrides.escalation = {
|
|
259
|
+
enabled: false,
|
|
260
|
+
minAttemptsBeforeEscalation: 2,
|
|
261
|
+
maxEscalations: 2,
|
|
262
|
+
maxRungs: ["effort", "model", "harness"]
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
if (typeof opts.maxCost === "number" || typeof opts.maxDuration === "number") {
|
|
266
|
+
overrides.ceilings = {
|
|
267
|
+
maxCostUsdPerIssue: typeof opts.maxCost === "number" ? opts.maxCost : null,
|
|
268
|
+
maxDurationMsPerIssue: typeof opts.maxDuration === "number" ? opts.maxDuration * 1e3 : null,
|
|
269
|
+
maxExecutionsPerIssue: null,
|
|
270
|
+
onCeiling: "block"
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
return overrides;
|
|
187
274
|
}
|
|
188
275
|
function withResilienceOptions(cmd) {
|
|
189
276
|
return cmd.option("--continuous", "Long-running profile: keep going without supervision").option("--resilient", "Alias of --continuous").option("--no-failover", "Never migrate a phase to another agent provider").option("--auto-decompose", "Act on a decomposition report instead of only writing it");
|
|
@@ -218,7 +305,7 @@ function resolveWebOverrides(opts) {
|
|
|
218
305
|
}
|
|
219
306
|
var program = new Command();
|
|
220
307
|
program.name("issue-flow").description(
|
|
221
|
-
"Unified CLI for orchestrating the full issue-flow pipeline via Claude Code
|
|
308
|
+
"Unified CLI for orchestrating the full issue-flow pipeline via Claude Code, Codex CLI, Cursor CLI or Antigravity CLI."
|
|
222
309
|
).version(version);
|
|
223
310
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
224
311
|
installShutdownHandlers();
|
|
@@ -233,6 +320,17 @@ program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
|
233
320
|
setInactivityTimeout(opts.inactivityTimeout * 1e3);
|
|
234
321
|
}
|
|
235
322
|
setWebCliOverrides(resolveWebOverrides(opts));
|
|
323
|
+
try {
|
|
324
|
+
setVerifyCliOverrides(resolveVerifyOverrides(opts));
|
|
325
|
+
setAgentCliOverrides(resolveAgentOverrides(opts));
|
|
326
|
+
setRoutingCliOverrides(resolveRoutingOverrides(opts));
|
|
327
|
+
} catch (error) {
|
|
328
|
+
if (error instanceof InvalidArgumentError) {
|
|
329
|
+
printError(error.message);
|
|
330
|
+
process.exit(1);
|
|
331
|
+
}
|
|
332
|
+
throw error;
|
|
333
|
+
}
|
|
236
334
|
setResilienceCliOverrides(
|
|
237
335
|
resolveResilienceOverrides({
|
|
238
336
|
continuous: opts.continuous,
|
|
@@ -257,19 +355,22 @@ withIssueOptions(
|
|
|
257
355
|
withGlobalOptions(
|
|
258
356
|
program.command("init").description(
|
|
259
357
|
"Check prerequisites and report (or create) the conventions this repository is missing"
|
|
260
|
-
).option("--apply", "Create the missing files instead of only reporting them").option("--json", "Emit the plan as JSON").option("--scope <dir>", "Resolve the conventions for a subdirectory (monorepo)").option("--check-only", "Only verify prerequisites, as earlier releases did")
|
|
358
|
+
).option("--apply", "Create the missing files instead of only reporting them").option("--json", "Emit the plan as JSON").option("--scope <dir>", "Resolve the conventions for a subdirectory (monorepo)").option("--check-only", "Only verify prerequisites, as earlier releases did").option("--no-agent-prompt", "Skip the first-run agent choice")
|
|
261
359
|
)
|
|
262
360
|
).action(
|
|
263
361
|
async (options) => {
|
|
264
|
-
const { loadIssuesConfig } = await import("./config-
|
|
265
|
-
const { runInit } = await import("./init-
|
|
362
|
+
const { loadIssuesConfig } = await import("./config-MEM2IWWN.js");
|
|
363
|
+
const { runInit } = await import("./init-OKWEC3EV.js");
|
|
266
364
|
const { preferredProvider } = await loadIssuesConfig();
|
|
267
|
-
const code = await runInit(preferredProvider,
|
|
365
|
+
const code = await runInit(preferredProvider, {
|
|
366
|
+
...options,
|
|
367
|
+
noAgentPrompt: options.agentPrompt === false
|
|
368
|
+
});
|
|
268
369
|
process.exit(code);
|
|
269
370
|
}
|
|
270
371
|
);
|
|
271
372
|
withGlobalOptions(
|
|
272
|
-
program.command("generate").description("Draft an issue
|
|
373
|
+
program.command("generate").description("Draft an issue with the configured agent and create it").requiredOption("--prompt <text>", "Issue description text").option("--github", "Create the issue on GitHub").option("--local", "Create the issue under issues/<n>/ only").option("--both", "Create the issue on GitHub and mirror it locally")
|
|
273
374
|
).action(async (options) => {
|
|
274
375
|
let target;
|
|
275
376
|
try {
|
|
@@ -281,7 +382,7 @@ withGlobalOptions(
|
|
|
281
382
|
}
|
|
282
383
|
throw error;
|
|
283
384
|
}
|
|
284
|
-
const { runGenerate } = await import("./generate-
|
|
385
|
+
const { runGenerate } = await import("./generate-MVQI7A45.js");
|
|
285
386
|
const code = await runGenerate(options.prompt, target);
|
|
286
387
|
process.exit(code);
|
|
287
388
|
});
|
|
@@ -295,7 +396,7 @@ withUserStoryNumberingOptions(
|
|
|
295
396
|
).argument("<issues...>", 'Issue number(s): 42, "42,43" or 42 43').option("--mode <mode>", "Execution mode: auto | manual", "auto").option("--from <phase>", "Resume from a specific phase").option(
|
|
296
397
|
"--no-branch",
|
|
297
398
|
"Run pipeline on current branch without creating a new branch or PR"
|
|
298
|
-
).option("--pr-review", "Review the created Pull Request after the pr phase").option("-y, --yes", "Run the whole discovered hierarchy without confirmation").option("--only", "Run just the issues informed, without their hierarchy").option(
|
|
399
|
+
).option("--pr-review", "Review the created Pull Request after the pr phase").option("-y, --yes", "Run the whole discovered hierarchy without confirmation").option("--cascade", "Run the children of a container, without implementing it").option("--only", "Run just the issues informed, without their hierarchy").option(
|
|
299
400
|
"--retry-limit <number>",
|
|
300
401
|
"Retry transient Claude failures up to N consecutive times",
|
|
301
402
|
parseInteger
|
|
@@ -303,7 +404,7 @@ withUserStoryNumberingOptions(
|
|
|
303
404
|
"--on-issue-failure <mode>",
|
|
304
405
|
"In a queue, on a failing issue: stop | skip | block",
|
|
305
406
|
parseQueueFailureMode
|
|
306
|
-
)
|
|
407
|
+
).option("-d, --background", "Detach after confirmation and return the terminal").addOption(new Option("--detached-child").hideHelp())
|
|
307
408
|
)
|
|
308
409
|
)
|
|
309
410
|
)
|
|
@@ -324,7 +425,7 @@ withUserStoryNumberingOptions(
|
|
|
324
425
|
}
|
|
325
426
|
throw error;
|
|
326
427
|
}
|
|
327
|
-
const { runPipeline } = await import("./run-
|
|
428
|
+
const { runPipeline } = await import("./run-YU4TR62R.js");
|
|
328
429
|
const code = await runPipeline(
|
|
329
430
|
issues,
|
|
330
431
|
options.mode,
|
|
@@ -334,11 +435,14 @@ withUserStoryNumberingOptions(
|
|
|
334
435
|
{
|
|
335
436
|
yes: scope.yes,
|
|
336
437
|
only: scope.only,
|
|
438
|
+
cascade: scope.cascade,
|
|
337
439
|
continueNumbering: numbering.continueFlag,
|
|
338
440
|
startUs: numbering.startUs,
|
|
339
441
|
retryLimit: options.retryLimit,
|
|
340
442
|
retryForever: options.retryForever,
|
|
341
|
-
onIssueFailure: options.onIssueFailure
|
|
443
|
+
onIssueFailure: options.onIssueFailure,
|
|
444
|
+
background: options.background,
|
|
445
|
+
detachedChild: options.detachedChild
|
|
342
446
|
}
|
|
343
447
|
);
|
|
344
448
|
process.exit(code);
|
|
@@ -349,7 +453,7 @@ withIssueOptions(
|
|
|
349
453
|
program.command("resume").description("Resume an interrupted pipeline from the phase it stopped at").argument("[issue]", "Issue to resume. Omitted: the most recently attempted one").option("--all", "Resume every unfinished issue of this project, in order").option("--mode <mode>", "Execution mode: auto | manual", "auto")
|
|
350
454
|
)
|
|
351
455
|
).action(async (issue, options) => {
|
|
352
|
-
const { runResume } = await import("./resume-
|
|
456
|
+
const { runResume } = await import("./resume-QMEPMSZW.js");
|
|
353
457
|
const code = await runResume(issue, {
|
|
354
458
|
...options.all === void 0 ? {} : { all: options.all },
|
|
355
459
|
...options.mode === void 0 ? {} : { mode: options.mode }
|
|
@@ -359,22 +463,47 @@ withIssueOptions(
|
|
|
359
463
|
withGlobalOptions(
|
|
360
464
|
program.command("status").description("What is running right now, in which phase, and since when").argument("[issue]", "Restrict the report to one issue").option("--json", "Emit the assembled state as JSON")
|
|
361
465
|
).action(async (issue, options) => {
|
|
362
|
-
const { runStatus } = await import("./operations-
|
|
466
|
+
const { runStatus } = await import("./operations-LU6JA3BX.js");
|
|
363
467
|
process.exit(
|
|
364
468
|
await runStatus(issue, { ...options.json === void 0 ? {} : { json: options.json } })
|
|
365
469
|
);
|
|
366
470
|
});
|
|
471
|
+
withGlobalOptions(
|
|
472
|
+
program.command("usage").description("Aggregate execution telemetry from tasks.json").argument("[issue]", "Restrict the report to one issue").option("--issue <issue>", "Same as the positional argument").option("--since <date>", "Only executions started on or after this ISO date").option("--by <key>", "Group by harness, provider, model, purpose or status").option("--json", "Emit the assembled totals as JSON")
|
|
473
|
+
).action(
|
|
474
|
+
async (issue, options) => {
|
|
475
|
+
const { runUsage, USAGE_GROUP_KEYS } = await import("./usage-VCFLDA5Y.js");
|
|
476
|
+
const by = options.by;
|
|
477
|
+
if (by !== void 0 && !USAGE_GROUP_KEYS.includes(by)) {
|
|
478
|
+
printError("Must be one of: harness, provider, model, purpose, status.");
|
|
479
|
+
process.exit(1);
|
|
480
|
+
}
|
|
481
|
+
process.exit(
|
|
482
|
+
await runUsage(issue ?? options.issue, {
|
|
483
|
+
...options.since === void 0 ? {} : { since: options.since },
|
|
484
|
+
...by === void 0 ? {} : { by },
|
|
485
|
+
...options.json === void 0 ? {} : { json: options.json }
|
|
486
|
+
})
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
);
|
|
490
|
+
withGlobalOptions(
|
|
491
|
+
program.command("ps").description("Every issue-flow run active on this machine").option("--json", "Emit the listing as JSON").option("--watch", "Refresh the listing until interrupted")
|
|
492
|
+
).action(async (options) => {
|
|
493
|
+
const { runPs } = await import("./ps-TNE44R5V.js");
|
|
494
|
+
process.exit(await runPs(options));
|
|
495
|
+
});
|
|
367
496
|
withGlobalOptions(
|
|
368
497
|
program.command("runs").description("History of the runs of this project, with how each ended")
|
|
369
498
|
).action(async () => {
|
|
370
|
-
const { runRuns } = await import("./operations-
|
|
499
|
+
const { runRuns } = await import("./operations-LU6JA3BX.js");
|
|
371
500
|
process.exit(await runRuns());
|
|
372
501
|
});
|
|
373
502
|
withGlobalOptions(
|
|
374
503
|
program.command("logs").description("Read the execution journal (events.jsonl), filtered and readable").argument("[issue]", "Issue to read. Omitted: the most recently attempted one").option("--issue <issue>", "Same as the positional argument").option("--follow", "Keep reading as the journal grows").option("--tail <n>", "How many entries to show first (default 50)", parseInteger).option("--kind <kinds>", "Only these event types, comma separated (retry, phase:end, \u2026)")
|
|
375
504
|
).action(
|
|
376
505
|
async (issue, options) => {
|
|
377
|
-
const { runLogs } = await import("./operations-
|
|
506
|
+
const { runLogs } = await import("./operations-LU6JA3BX.js");
|
|
378
507
|
const kinds = options.kind === void 0 ? void 0 : options.kind.split(",").map((kind) => kind.trim()).filter((kind) => kind !== "");
|
|
379
508
|
process.exit(
|
|
380
509
|
await runLogs(issue ?? options.issue, {
|
|
@@ -388,37 +517,37 @@ withGlobalOptions(
|
|
|
388
517
|
withGlobalOptions(
|
|
389
518
|
program.command("pause").description("Ask the running pipeline to stop after writing a checkpoint")
|
|
390
519
|
).action(async () => {
|
|
391
|
-
const { runPause } = await import("./operations-
|
|
520
|
+
const { runPause } = await import("./operations-LU6JA3BX.js");
|
|
392
521
|
process.exit(await runPause());
|
|
393
522
|
});
|
|
394
523
|
withGlobalOptions(
|
|
395
524
|
program.command("cancel").description("Stop the run and mark the issue so a resume does not pick it up").argument("[issue]", "Issue to cancel. Omitted: the most recently attempted one")
|
|
396
525
|
).action(async (issue) => {
|
|
397
|
-
const { runCancel } = await import("./operations-
|
|
526
|
+
const { runCancel } = await import("./operations-LU6JA3BX.js");
|
|
398
527
|
process.exit(await runCancel(issue));
|
|
399
528
|
});
|
|
400
529
|
withIssueOptions(
|
|
401
530
|
withGlobalOptions(
|
|
402
|
-
program.command("analyze").description("Analyze an issue
|
|
531
|
+
program.command("analyze").description("Analyze an issue with the configured agent").argument("<issue>", "Issue number")
|
|
403
532
|
)
|
|
404
533
|
).action(async (issue) => {
|
|
405
|
-
const { runAnalyze } = await import("./analyze-
|
|
534
|
+
const { runAnalyze } = await import("./analyze-WS47UYGN.js");
|
|
406
535
|
const code = await runAnalyze(issue);
|
|
407
536
|
process.exit(code);
|
|
408
537
|
});
|
|
409
538
|
withIssueOptions(
|
|
410
539
|
withGlobalOptions(
|
|
411
|
-
program.command("prd").description("Generate a PRD from an analyzed issue
|
|
540
|
+
program.command("prd").description("Generate a PRD from an analyzed issue with the configured agent").argument("<issue>", "Issue number")
|
|
412
541
|
)
|
|
413
542
|
).action(async (issue) => {
|
|
414
|
-
const { runPrd } = await import("./prd-
|
|
543
|
+
const { runPrd } = await import("./prd-5O6GYCC6.js");
|
|
415
544
|
const code = await runPrd(issue);
|
|
416
545
|
process.exit(code);
|
|
417
546
|
});
|
|
418
547
|
withUserStoryNumberingOptions(
|
|
419
548
|
withIssueOptions(
|
|
420
549
|
withGlobalOptions(
|
|
421
|
-
program.command("plan").description("Convert a PRD to a tasks.json task plan
|
|
550
|
+
program.command("plan").description("Convert a PRD to a tasks.json task plan with the configured agent").argument("<issue>", "Issue number")
|
|
422
551
|
)
|
|
423
552
|
)
|
|
424
553
|
).action(async (issue, options) => {
|
|
@@ -432,7 +561,7 @@ withUserStoryNumberingOptions(
|
|
|
432
561
|
}
|
|
433
562
|
throw error;
|
|
434
563
|
}
|
|
435
|
-
const { runPlan } = await import("./plan-
|
|
564
|
+
const { runPlan } = await import("./plan-LEJJF3DE.js");
|
|
436
565
|
const code = await runPlan(issue, void 0, numbering);
|
|
437
566
|
process.exit(code);
|
|
438
567
|
});
|
|
@@ -451,7 +580,7 @@ withWebOptions(
|
|
|
451
580
|
).action(
|
|
452
581
|
async (positionalMaxIter, options) => {
|
|
453
582
|
try {
|
|
454
|
-
const { runExecute } = await import("./execute-
|
|
583
|
+
const { runExecute } = await import("./execute-NITIHHCK.js");
|
|
455
584
|
const code = await runExecute(positionalMaxIter, options);
|
|
456
585
|
process.exit(code);
|
|
457
586
|
} catch (error) {
|
|
@@ -462,19 +591,19 @@ withWebOptions(
|
|
|
462
591
|
);
|
|
463
592
|
withIssueOptions(
|
|
464
593
|
withGlobalOptions(
|
|
465
|
-
program.command("review").description("Validate an issue resolution
|
|
594
|
+
program.command("review").description("Validate an issue resolution with the configured agent").argument("<issue>", "Issue number")
|
|
466
595
|
)
|
|
467
596
|
).action(async (issue) => {
|
|
468
|
-
const { runReview } = await import("./review-
|
|
597
|
+
const { runReview } = await import("./review-YKWD6SNN.js");
|
|
469
598
|
const code = await runReview(issue);
|
|
470
599
|
process.exit(code);
|
|
471
600
|
});
|
|
472
601
|
withIssueOptions(
|
|
473
602
|
withGlobalOptions(
|
|
474
|
-
program.command("pr").description("Create a pull request
|
|
603
|
+
program.command("pr").description("Create a pull request with the configured agent").argument("<issue>", "Issue number")
|
|
475
604
|
)
|
|
476
605
|
).action(async (issue) => {
|
|
477
|
-
const { runPr } = await import("./pr-
|
|
606
|
+
const { runPr } = await import("./pr-HPVUZ7S3.js");
|
|
478
607
|
const code = await runPr(issue);
|
|
479
608
|
process.exit(code);
|
|
480
609
|
});
|
|
@@ -482,35 +611,126 @@ var webCommand = program.command("web").description("Manage the web monitoring s
|
|
|
482
611
|
webCommand.command("serve").description(
|
|
483
612
|
"Run the web monitor server in the foreground (internal \u2014 spawned detached by --web)"
|
|
484
613
|
).option("--port <n>", "Web server port (default: 3737)", parseInteger).option("--host <h>", "Web server host (default: 0.0.0.0)").option("--refresh <s>", "Suggested UI polling interval in seconds", parseInteger).action(async (options) => {
|
|
485
|
-
const { runWebServe } = await import("./web-
|
|
614
|
+
const { runWebServe } = await import("./web-XVHLX62B.js");
|
|
486
615
|
const code = await runWebServe(options);
|
|
487
616
|
if (code !== 0) {
|
|
488
617
|
process.exit(code);
|
|
489
618
|
}
|
|
490
619
|
});
|
|
491
620
|
webCommand.command("stop").description("Stop the running web monitor server").action(async () => {
|
|
492
|
-
const { runWebStop } = await import("./web-
|
|
621
|
+
const { runWebStop } = await import("./web-XVHLX62B.js");
|
|
493
622
|
const code = await runWebStop();
|
|
494
623
|
process.exit(code);
|
|
495
624
|
});
|
|
496
625
|
withGlobalOptions(
|
|
497
626
|
program.command("policy").description("Inspect the policies discovered in this repository and their provenance").option("--scope <dir>", "Resolve the policy for a subdirectory (monorepo)").option("--json", "Emit the resolved policy as JSON")
|
|
498
627
|
).action(async (options) => {
|
|
499
|
-
const { runPolicy } = await import("./policy-
|
|
628
|
+
const { runPolicy } = await import("./policy-JSYEK5B2.js");
|
|
500
629
|
const code = await runPolicy(options);
|
|
501
630
|
process.exit(code);
|
|
502
631
|
});
|
|
632
|
+
var routingCommand = withGlobalOptions(
|
|
633
|
+
program.command("routing").description("Inspect the shadow router (records a recommendation, does not act)")
|
|
634
|
+
);
|
|
635
|
+
routingCommand.option("--json", "Emit the resolved routing config as JSON").action(async (options) => {
|
|
636
|
+
const { runRoutingInspect } = await import("./routing-2ZUMZPJB.js");
|
|
637
|
+
process.exit(await runRoutingInspect(options));
|
|
638
|
+
});
|
|
639
|
+
routingCommand.command("report").description("Shadow agreement between selected and actual harness").option("--issue <n>", "Issue number").option("--json", "Emit JSON").action(async (options) => {
|
|
640
|
+
const { runRoutingReport } = await import("./routing-2ZUMZPJB.js");
|
|
641
|
+
process.exit(await runRoutingReport(options));
|
|
642
|
+
});
|
|
643
|
+
var conventionsCommand = withGlobalOptions(
|
|
644
|
+
program.command("conventions").description("Compute the repository Git convention (branch, commit, PR title)")
|
|
645
|
+
);
|
|
646
|
+
conventionsCommand.command("branch").description("Print the deterministic branch name for an issue").option("--issue <n>", "Issue number").option("--title <text>", "Issue title, when the issue cannot be resolved").option("--json", "Emit JSON").action(async (options) => {
|
|
647
|
+
const { runConventionsBranch } = await import("./conventions-WV4NDXGH.js");
|
|
648
|
+
process.exit(await runConventionsBranch(options));
|
|
649
|
+
});
|
|
650
|
+
conventionsCommand.command("commit").description("Print a Conventional Commit message").requiredOption("--type <type>", "Change type (feat, fix, docs, \u2026)").option("--scope <scope>", "Optional scope").requiredOption("--subject <text>", "Commit subject").option("--issue <n>", "Issue number for the Refs trailer").option("--story <id>", "Story id (US-010)").option("--breaking <text>", "Breaking change description").option("--json", "Emit JSON").action(
|
|
651
|
+
async (options) => {
|
|
652
|
+
const { runConventionsCommit } = await import("./conventions-WV4NDXGH.js");
|
|
653
|
+
process.exit(await runConventionsCommit(options));
|
|
654
|
+
}
|
|
655
|
+
);
|
|
656
|
+
conventionsCommand.command("pr-title").description("Print the Conventional Commit Pull Request title").option("--issue <n>", "Issue number").option("--title <text>", "Issue title, when the issue cannot be resolved").option("--json", "Emit JSON").action(async (options) => {
|
|
657
|
+
const { runConventionsPrTitle } = await import("./conventions-WV4NDXGH.js");
|
|
658
|
+
process.exit(await runConventionsPrTitle(options));
|
|
659
|
+
});
|
|
660
|
+
var agentCommand = withGlobalOptions(
|
|
661
|
+
program.command("agent").description("Inspect the resolved agent and model for each phase").option("--json", "Emit the resolved agent configuration as JSON")
|
|
662
|
+
);
|
|
663
|
+
agentCommand.action(async (options) => {
|
|
664
|
+
const { runAgent } = await import("./agent-BXRIEKVM.js");
|
|
665
|
+
const code = await runAgent(options);
|
|
666
|
+
process.exit(code);
|
|
667
|
+
});
|
|
668
|
+
agentCommand.command("use").description("Write an agent preference to config.json or .issue-flow.json").argument("<provider>", "claude, codex, cursor or antigravity").option("--model <model>", "Model identifier for this preference").option("--global", "Write to ~/.issue-flow/config.json (default)").option("--project", "Write to .issue-flow.json in the repository").option("--phase <phase>", "Write only the override for this phase").action(
|
|
669
|
+
async (provider, options) => {
|
|
670
|
+
const { runAgentUse } = await import("./agent-BXRIEKVM.js");
|
|
671
|
+
const code = await runAgentUse(provider, options);
|
|
672
|
+
process.exit(code);
|
|
673
|
+
}
|
|
674
|
+
);
|
|
503
675
|
withGlobalOptions(
|
|
504
|
-
program.command("pr-review").description("Review a Pull Request as a whole
|
|
676
|
+
program.command("pr-review").description("Review a Pull Request as a whole with the configured agent").argument("[pr]", "Pull Request number (discovered from the session when omitted)").option("--issue <n>", "Issue the Pull Request belongs to").option("--round <n>", "Rewrite a specific review round instead of appending a new one").option("--yes", "Skip the confirmation of the discovered Pull Request").option(
|
|
505
677
|
"--fail-on <level>",
|
|
506
678
|
"Verdict that fails the command: request-changes | suggestions | none"
|
|
507
679
|
)
|
|
508
680
|
).action(
|
|
509
681
|
async (pr, options) => {
|
|
510
|
-
const { runPrReview } = await import("./pr-review-
|
|
682
|
+
const { runPrReview } = await import("./pr-review-R2QZBT3F.js");
|
|
511
683
|
const code = await runPrReview(pr, options);
|
|
512
684
|
process.exit(code);
|
|
513
685
|
}
|
|
514
686
|
);
|
|
687
|
+
withGlobalOptions(
|
|
688
|
+
program.command("bench").description("Measure the corpus: synthetic (CI) or real (paid, on demand)").option("--mode <mode>", "synthetic (default, free) or real (fixtures + harness)").option(
|
|
689
|
+
"--task <class>",
|
|
690
|
+
"Corpus class (repeatable): trivial, small, medium, analysis",
|
|
691
|
+
collectString,
|
|
692
|
+
[]
|
|
693
|
+
).option("--arm <name>", "Experiment arm (repeatable). Default: baseline", collectString, []).option("--repeats <n>", "Repetitions per cell (default 5)", parseInteger).option(
|
|
694
|
+
"--campaign-max-cost <usd>",
|
|
695
|
+
"Campaign cost ceiling in USD (evaluateCeilings)",
|
|
696
|
+
parseUsd
|
|
697
|
+
).option(
|
|
698
|
+
"--campaign-max-duration <ms>",
|
|
699
|
+
"Campaign duration ceiling in milliseconds",
|
|
700
|
+
parseInteger
|
|
701
|
+
).option("--out <path>", "Write the markdown report to this path").option("--yes", "Skip the paid-campaign confirmation").option("--repo <path>", "Investigation escape; does not produce a publishable row").option("--json", "Also emit the campaign JSON")
|
|
702
|
+
).action(
|
|
703
|
+
async (options) => {
|
|
704
|
+
if (options.mode !== void 0 && options.mode !== "synthetic" && options.mode !== "real") {
|
|
705
|
+
printError("Unknown bench mode. Use 'synthetic' or 'real'.");
|
|
706
|
+
process.exit(1);
|
|
707
|
+
}
|
|
708
|
+
const { runBench } = await import("./bench-SA3BOME5.js");
|
|
709
|
+
process.exit(
|
|
710
|
+
await runBench({
|
|
711
|
+
...options.mode === void 0 ? {} : { mode: options.mode },
|
|
712
|
+
...options.task === void 0 || options.task.length === 0 ? {} : { task: options.task },
|
|
713
|
+
...options.arm === void 0 || options.arm.length === 0 ? {} : { arm: options.arm },
|
|
714
|
+
...options.repeats === void 0 ? {} : { repeats: options.repeats },
|
|
715
|
+
...options.campaignMaxCost === void 0 ? {} : { maxCost: options.campaignMaxCost },
|
|
716
|
+
...options.campaignMaxDuration === void 0 ? {} : { maxDuration: options.campaignMaxDuration },
|
|
717
|
+
...options.out === void 0 ? {} : { out: options.out },
|
|
718
|
+
...options.yes === void 0 ? {} : { yes: options.yes },
|
|
719
|
+
...options.repo === void 0 ? {} : { repo: options.repo },
|
|
720
|
+
...options.json === void 0 ? {} : { json: options.json }
|
|
721
|
+
})
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
);
|
|
725
|
+
program.action(async () => {
|
|
726
|
+
const { listLiveRuns } = await import("./registry-LGPE53QD.js");
|
|
727
|
+
const runs = await listLiveRuns();
|
|
728
|
+
if (runs.length === 0) {
|
|
729
|
+
program.help();
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
const { runPs } = await import("./ps-TNE44R5V.js");
|
|
733
|
+
process.exit(await runPs());
|
|
734
|
+
});
|
|
515
735
|
program.parse();
|
|
516
736
|
//# sourceMappingURL=cli.js.map
|