issue-flow 0.11.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{analyze-XV3K25K3.js → analyze-OEET7KGE.js} +15 -10
- package/dist/{analyze-XV3K25K3.js.map → analyze-OEET7KGE.js.map} +1 -1
- package/dist/{apply-WUJHDD7A.js → apply-ZIA3C52S.js} +6 -4
- package/dist/{apply-WUJHDD7A.js.map → apply-ZIA3C52S.js.map} +1 -1
- package/dist/{chunk-6N7LZZ5U.js → chunk-3QHK4YQA.js} +204 -107
- package/dist/chunk-3QHK4YQA.js.map +1 -0
- package/dist/chunk-42PJFMAR.js +605 -0
- package/dist/chunk-42PJFMAR.js.map +1 -0
- package/dist/{chunk-EWDJENFW.js → chunk-4JSOYE4G.js} +77 -12
- package/dist/chunk-4JSOYE4G.js.map +1 -0
- package/dist/chunk-56KS3TFQ.js +703 -0
- package/dist/chunk-56KS3TFQ.js.map +1 -0
- package/dist/{chunk-AAY6KM7N.js → chunk-73ATPIYX.js} +160 -154
- package/dist/chunk-73ATPIYX.js.map +1 -0
- package/dist/{chunk-KQ4JQN7T.js → chunk-A4SLHOW7.js} +68 -12
- package/dist/chunk-A4SLHOW7.js.map +1 -0
- package/dist/chunk-BAUPQXPE.js +173 -0
- package/dist/chunk-BAUPQXPE.js.map +1 -0
- package/dist/{chunk-HC2MT7BX.js → chunk-BYZDPR7N.js} +14 -581
- package/dist/chunk-BYZDPR7N.js.map +1 -0
- package/dist/chunk-CD5ULRVC.js +615 -0
- package/dist/chunk-CD5ULRVC.js.map +1 -0
- package/dist/chunk-DIDUVL6O.js +1365 -0
- package/dist/chunk-DIDUVL6O.js.map +1 -0
- package/dist/{chunk-47VIN33V.js → chunk-EZATO3DW.js} +7 -5
- package/dist/{chunk-47VIN33V.js.map → chunk-EZATO3DW.js.map} +1 -1
- package/dist/{chunk-BXCPXRBR.js → chunk-FADTCQGM.js} +46 -11
- package/dist/chunk-FADTCQGM.js.map +1 -0
- package/dist/{chunk-GANSDJV7.js → chunk-FJP3UQGD.js} +15 -13
- package/dist/chunk-FJP3UQGD.js.map +1 -0
- package/dist/chunk-KMMASOA6.js +134 -0
- package/dist/chunk-KMMASOA6.js.map +1 -0
- package/dist/{chunk-HQYXVIH6.js → chunk-LAFNLLQP.js} +3 -3
- package/dist/chunk-LWRSMTTZ.js +18 -0
- package/dist/chunk-LWRSMTTZ.js.map +1 -0
- package/dist/{chunk-IVHZEYAX.js → chunk-M5UCXTIT.js} +13 -11
- package/dist/{chunk-IVHZEYAX.js.map → chunk-M5UCXTIT.js.map} +1 -1
- package/dist/chunk-M66SJHQQ.js +206 -0
- package/dist/chunk-M66SJHQQ.js.map +1 -0
- package/dist/{chunk-OBLVLIUS.js → chunk-MJULIKQU.js} +42 -6
- package/dist/chunk-MJULIKQU.js.map +1 -0
- package/dist/{chunk-RKTEV6EG.js → chunk-NS6R37II.js} +4 -4
- package/dist/{run-DBF2VWUN.js → chunk-NTMMF5UD.js} +515 -544
- package/dist/chunk-NTMMF5UD.js.map +1 -0
- package/dist/{chunk-EY6WMHV2.js → chunk-QCPGHBSZ.js} +14 -12
- package/dist/{chunk-EY6WMHV2.js.map → chunk-QCPGHBSZ.js.map} +1 -1
- package/dist/{chunk-LVKQ2AKT.js → chunk-TSOLWK7Y.js} +8 -6
- package/dist/chunk-TSOLWK7Y.js.map +1 -0
- package/dist/{chunk-34WNTK3K.js → chunk-XQUSIEKA.js} +11 -9
- package/dist/{chunk-34WNTK3K.js.map → chunk-XQUSIEKA.js.map} +1 -1
- package/dist/chunk-Y5ZDJ4PJ.js +76 -0
- package/dist/chunk-Y5ZDJ4PJ.js.map +1 -0
- package/dist/cli.js +156 -26
- package/dist/cli.js.map +1 -1
- package/dist/{config-4THHOXNN.js → config-PRJGWW7J.js} +15 -3
- package/dist/execute-XBNVL753.js +18 -0
- package/dist/{generate-TBVTLMOP.js → generate-EGB4KV2B.js} +16 -10
- package/dist/{generate-TBVTLMOP.js.map → generate-EGB4KV2B.js.map} +1 -1
- package/dist/init-AJHCXJBP.js +10 -0
- package/dist/operations-BYT626KQ.js +365 -0
- package/dist/operations-BYT626KQ.js.map +1 -0
- package/dist/plan-QOZ3RIO6.js +21 -0
- package/dist/{policy-XQW5NUIE.js → policy-6S4GFC76.js} +6 -4
- package/dist/{policy-XQW5NUIE.js.map → policy-6S4GFC76.js.map} +1 -1
- package/dist/pr-EBBHD2ZX.js +26 -0
- package/dist/pr-review-VVMW5PO4.js +20 -0
- package/dist/prd-JQSZF7PR.js +21 -0
- package/dist/resume-PPCNQVVV.js +221 -0
- package/dist/resume-PPCNQVVV.js.map +1 -0
- package/dist/review-3F6MARWH.js +19 -0
- package/dist/run-RXE5GDQO.js +36 -0
- package/dist/run-RXE5GDQO.js.map +1 -0
- package/dist/state-manager-2EDVDBAR.js +34 -0
- package/dist/state-manager-2EDVDBAR.js.map +1 -0
- package/dist/{web-ANQQTTRD.js → web-EF5WIIGG.js} +13 -8
- package/dist/{web-ANQQTTRD.js.map → web-EF5WIIGG.js.map} +1 -1
- package/package.json +1 -1
- package/prompts/pr.md +11 -4
- package/web/public/app.js +12 -0
- package/dist/chunk-3BOHTH4V.js +0 -58
- package/dist/chunk-3BOHTH4V.js.map +0 -1
- package/dist/chunk-6N7LZZ5U.js.map +0 -1
- package/dist/chunk-AAY6KM7N.js.map +0 -1
- package/dist/chunk-BXCPXRBR.js.map +0 -1
- package/dist/chunk-EWDJENFW.js.map +0 -1
- package/dist/chunk-GANSDJV7.js.map +0 -1
- package/dist/chunk-HC2MT7BX.js.map +0 -1
- package/dist/chunk-HDV3YDTG.js +0 -52
- package/dist/chunk-HDV3YDTG.js.map +0 -1
- package/dist/chunk-KQ4JQN7T.js.map +0 -1
- package/dist/chunk-LVKQ2AKT.js.map +0 -1
- package/dist/chunk-OBLVLIUS.js.map +0 -1
- package/dist/chunk-VQ5VN7DF.js +0 -1018
- package/dist/chunk-VQ5VN7DF.js.map +0 -1
- package/dist/execute-5OEKLM5X.js +0 -15
- package/dist/init-PRMOTQ7N.js +0 -9
- package/dist/plan-Y2BYZD24.js +0 -17
- package/dist/pr-H6GLOSXF.js +0 -21
- package/dist/pr-review-CK5FR6WX.js +0 -17
- package/dist/prd-4PWLCGH5.js +0 -17
- package/dist/review-QGVAHEZF.js +0 -15
- package/dist/run-DBF2VWUN.js.map +0 -1
- /package/dist/{chunk-HQYXVIH6.js.map → chunk-LAFNLLQP.js.map} +0 -0
- /package/dist/{chunk-RKTEV6EG.js.map → chunk-NS6R37II.js.map} +0 -0
- /package/dist/{config-4THHOXNN.js.map → config-PRJGWW7J.js.map} +0 -0
- /package/dist/{execute-5OEKLM5X.js.map → execute-XBNVL753.js.map} +0 -0
- /package/dist/{init-PRMOTQ7N.js.map → init-AJHCXJBP.js.map} +0 -0
- /package/dist/{plan-Y2BYZD24.js.map → plan-QOZ3RIO6.js.map} +0 -0
- /package/dist/{pr-H6GLOSXF.js.map → pr-EBBHD2ZX.js.map} +0 -0
- /package/dist/{pr-review-CK5FR6WX.js.map → pr-review-VVMW5PO4.js.map} +0 -0
- /package/dist/{prd-4PWLCGH5.js.map → prd-JQSZF7PR.js.map} +0 -0
- /package/dist/{review-QGVAHEZF.js.map → review-3F6MARWH.js.map} +0 -0
|
@@ -2,29 +2,31 @@
|
|
|
2
2
|
import {
|
|
3
3
|
issuePlaceholders,
|
|
4
4
|
resolveCommandIssue
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-73ATPIYX.js";
|
|
6
6
|
import {
|
|
7
7
|
DEFAULT_HEADLESS_TIMEOUT_MS,
|
|
8
8
|
runHeadless
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-4JSOYE4G.js";
|
|
10
10
|
import {
|
|
11
11
|
publishPhaseMetrics,
|
|
12
12
|
resolvePolicyPlaceholders
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-MJULIKQU.js";
|
|
14
14
|
import {
|
|
15
15
|
applyPlaceholders,
|
|
16
16
|
loadPrompt
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-LAFNLLQP.js";
|
|
18
18
|
import {
|
|
19
19
|
resolveIssuePaths
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-DIDUVL6O.js";
|
|
21
21
|
import {
|
|
22
22
|
getGlobalTimeout,
|
|
23
|
-
loadTaskPlan,
|
|
24
23
|
printError,
|
|
25
|
-
printSuccess
|
|
24
|
+
printSuccess
|
|
25
|
+
} from "./chunk-BYZDPR7N.js";
|
|
26
|
+
import {
|
|
27
|
+
loadTaskPlan,
|
|
26
28
|
saveTaskPlan
|
|
27
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-CD5ULRVC.js";
|
|
28
30
|
|
|
29
31
|
// src/commands/review.ts
|
|
30
32
|
function parseReviewResult(output) {
|
|
@@ -112,4 +114,4 @@ async function runReview(issue, resolvedIssue) {
|
|
|
112
114
|
export {
|
|
113
115
|
runReview
|
|
114
116
|
};
|
|
115
|
-
//# sourceMappingURL=chunk-
|
|
117
|
+
//# sourceMappingURL=chunk-XQUSIEKA.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/review.ts"],"sourcesContent":["import { 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 { loadTaskPlan, saveTaskPlan } from '../core/state-manager.js';\nimport { getGlobalTimeout } from '../core/verbose.js';\nimport { issuePlaceholders, resolveCommandIssue } from '../issues/context.js';\nimport type { ResolvedIssue } from '../issues/types.js';\nimport { resolvePolicyPlaceholders } from '../policy/placeholders.js';\nimport { resolveIssuePaths } from '../storage/resolve.js';\nimport { printError, printSuccess } from '../ui/logger.js';\n\nexport interface ReviewResult {\n status: 'PASS' | 'FAIL';\n findings?: string;\n}\n\n/**\n * Parse the <review-result> block from headless output.\n */\nfunction parseReviewResult(output: string): ReviewResult {\n const match = output.match(/<review-result>([\\s\\S]*?)<\\/review-result>/);\n if (!match) {\n // Try to detect PASS/FAIL from the raw output\n if (/STATUS:\\s*PASS/i.test(output)) {\n return { status: 'PASS' };\n }\n if (/STATUS:\\s*FAIL/i.test(output)) {\n const findingsMatch = output.match(/FINDINGS:([\\s\\S]*?)(?:$|<\\/)/);\n return { status: 'FAIL', findings: findingsMatch?.[1]?.trim() ?? 'Unknown findings' };\n }\n // Default to PASS if no explicit status found and no errors\n return { status: 'PASS' };\n }\n\n const block = match[1];\n if (/STATUS:\\s*PASS/i.test(block)) {\n return { status: 'PASS' };\n }\n\n const findingsMatch = block.match(/FINDINGS:([\\s\\S]*)/);\n return {\n status: 'FAIL',\n findings: findingsMatch?.[1]?.trim() ?? 'Unknown findings',\n };\n}\n\nexport async function runReview(issue: string, resolvedIssue?: ResolvedIssue): Promise<number> {\n const issueNumber = issue.replace(/^#/, '');\n const paths = await resolveIssuePaths(issueNumber);\n const tasksPath = paths.tasksFile;\n\n const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);\n if (!resolution.ok) {\n return resolution.code;\n }\n\n const template = await loadPrompt('review');\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 __ISSUE_NUMBER__: issueNumber,\n __TASKS_PATH__: tasksPath,\n ...issuePlaceholders(resolution.resolved),\n });\n\n const startedAtMs = Date.now();\n const result = await runHeadless({\n prompt,\n maxTurns: 25,\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 parseReviewResult() already consumed.\n outputFormat: 'json',\n allowedTools: ['Bash', 'Read', 'Glob', 'Grep'],\n addDirs: [paths.issueDir],\n statusMessage: `Reviewing issue #${issueNumber} resolution...`,\n });\n // Before the success check: the tokens were spent either way. A correction\n // cycle calls runReview() again and the reducer sums both invocations.\n publishPhaseMetrics('review', result.cost, startedAtMs);\n\n if (!result.success) {\n printError(`Review failed: ${result.error}`);\n return 1;\n }\n\n const review = parseReviewResult(result.result);\n\n if (review.status === 'PASS') {\n // Update pipeline state\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.reviewCompleted = true;\n plan.lastReviewFindings = null;\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist\n }\n\n printSuccess('Review PASSED — implementation meets acceptance criteria');\n return 0;\n }\n\n printError('Review FAILED — issues found:');\n if (review.findings) {\n console.log(review.findings);\n }\n\n // Persist the findings so a correction cycle can act on them: without this,\n // a re-run of execute sees every userStories[].passes already true and\n // exits immediately without attempting any fix (see engine.ts's\n // \"already complete\" guards).\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.reviewCompleted = false;\n plan.lastReviewFindings = review.findings ?? 'Unknown findings';\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist\n }\n\n return 1;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/commands/review.ts"],"sourcesContent":["import { 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 { loadTaskPlan, saveTaskPlan } from '../core/state-manager.js';\nimport { getGlobalTimeout } from '../core/verbose.js';\nimport { issuePlaceholders, resolveCommandIssue } from '../issues/context.js';\nimport type { ResolvedIssue } from '../issues/types.js';\nimport { resolvePolicyPlaceholders } from '../policy/placeholders.js';\nimport { resolveIssuePaths } from '../storage/resolve.js';\nimport { printError, printSuccess } from '../ui/logger.js';\n\nexport interface ReviewResult {\n status: 'PASS' | 'FAIL';\n findings?: string;\n}\n\n/**\n * Parse the <review-result> block from headless output.\n */\nfunction parseReviewResult(output: string): ReviewResult {\n const match = output.match(/<review-result>([\\s\\S]*?)<\\/review-result>/);\n if (!match) {\n // Try to detect PASS/FAIL from the raw output\n if (/STATUS:\\s*PASS/i.test(output)) {\n return { status: 'PASS' };\n }\n if (/STATUS:\\s*FAIL/i.test(output)) {\n const findingsMatch = output.match(/FINDINGS:([\\s\\S]*?)(?:$|<\\/)/);\n return { status: 'FAIL', findings: findingsMatch?.[1]?.trim() ?? 'Unknown findings' };\n }\n // Default to PASS if no explicit status found and no errors\n return { status: 'PASS' };\n }\n\n const block = match[1];\n if (/STATUS:\\s*PASS/i.test(block)) {\n return { status: 'PASS' };\n }\n\n const findingsMatch = block.match(/FINDINGS:([\\s\\S]*)/);\n return {\n status: 'FAIL',\n findings: findingsMatch?.[1]?.trim() ?? 'Unknown findings',\n };\n}\n\nexport async function runReview(issue: string, resolvedIssue?: ResolvedIssue): Promise<number> {\n const issueNumber = issue.replace(/^#/, '');\n const paths = await resolveIssuePaths(issueNumber);\n const tasksPath = paths.tasksFile;\n\n const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);\n if (!resolution.ok) {\n return resolution.code;\n }\n\n const template = await loadPrompt('review');\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 __ISSUE_NUMBER__: issueNumber,\n __TASKS_PATH__: tasksPath,\n ...issuePlaceholders(resolution.resolved),\n });\n\n const startedAtMs = Date.now();\n const result = await runHeadless({\n prompt,\n maxTurns: 25,\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 parseReviewResult() already consumed.\n outputFormat: 'json',\n allowedTools: ['Bash', 'Read', 'Glob', 'Grep'],\n addDirs: [paths.issueDir],\n statusMessage: `Reviewing issue #${issueNumber} resolution...`,\n });\n // Before the success check: the tokens were spent either way. A correction\n // cycle calls runReview() again and the reducer sums both invocations.\n publishPhaseMetrics('review', result.cost, startedAtMs);\n\n if (!result.success) {\n printError(`Review failed: ${result.error}`);\n return 1;\n }\n\n const review = parseReviewResult(result.result);\n\n if (review.status === 'PASS') {\n // Update pipeline state\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.reviewCompleted = true;\n plan.lastReviewFindings = null;\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist\n }\n\n printSuccess('Review PASSED — implementation meets acceptance criteria');\n return 0;\n }\n\n printError('Review FAILED — issues found:');\n if (review.findings) {\n console.log(review.findings);\n }\n\n // Persist the findings so a correction cycle can act on them: without this,\n // a re-run of execute sees every userStories[].passes already true and\n // exits immediately without attempting any fix (see engine.ts's\n // \"already complete\" guards).\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.reviewCompleted = false;\n plan.lastReviewFindings = review.findings ?? 'Unknown findings';\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist\n }\n\n return 1;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmBA,SAAS,kBAAkB,QAA8B;AACvD,QAAM,QAAQ,OAAO,MAAM,4CAA4C;AACvE,MAAI,CAAC,OAAO;AAEV,QAAI,kBAAkB,KAAK,MAAM,GAAG;AAClC,aAAO,EAAE,QAAQ,OAAO;AAAA,IAC1B;AACA,QAAI,kBAAkB,KAAK,MAAM,GAAG;AAClC,YAAMA,iBAAgB,OAAO,MAAM,8BAA8B;AACjE,aAAO,EAAE,QAAQ,QAAQ,UAAUA,iBAAgB,CAAC,GAAG,KAAK,KAAK,mBAAmB;AAAA,IACtF;AAEA,WAAO,EAAE,QAAQ,OAAO;AAAA,EAC1B;AAEA,QAAM,QAAQ,MAAM,CAAC;AACrB,MAAI,kBAAkB,KAAK,KAAK,GAAG;AACjC,WAAO,EAAE,QAAQ,OAAO;AAAA,EAC1B;AAEA,QAAM,gBAAgB,MAAM,MAAM,oBAAoB;AACtD,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,UAAU,gBAAgB,CAAC,GAAG,KAAK,KAAK;AAAA,EAC1C;AACF;AAEA,eAAsB,UAAU,OAAe,eAAgD;AAC7F,QAAM,cAAc,MAAM,QAAQ,MAAM,EAAE;AAC1C,QAAM,QAAQ,MAAM,kBAAkB,WAAW;AACjD,QAAM,YAAY,MAAM;AAExB,QAAM,aAAa,MAAM,oBAAoB,aAAa,aAAa;AACvE,MAAI,CAAC,WAAW,IAAI;AAClB,WAAO,WAAW;AAAA,EACpB;AAEA,QAAM,WAAW,MAAM,WAAW,QAAQ;AAC1C,QAAM,SAAS,kBAAkB,UAAU;AAAA;AAAA;AAAA,IAGzC,GAAI,MAAM,0BAA0B;AAAA,IACpC,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,GAAG,kBAAkB,WAAW,QAAQ;AAAA,EAC1C,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,MAAM,QAAQ;AAAA,IACxB,eAAe,oBAAoB,WAAW;AAAA,EAChD,CAAC;AAGD,sBAAoB,UAAU,OAAO,MAAM,WAAW;AAEtD,MAAI,CAAC,OAAO,SAAS;AACnB,eAAW,kBAAkB,OAAO,KAAK,EAAE;AAC3C,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,kBAAkB,OAAO,MAAM;AAE9C,MAAI,OAAO,WAAW,QAAQ;AAE5B,QAAI;AACF,YAAM,OAAO,MAAM,aAAa,SAAS;AACzC,WAAK,SAAS,kBAAkB;AAChC,WAAK,qBAAqB;AAC1B,YAAM,aAAa,WAAW,IAAI;AAAA,IACpC,QAAQ;AAAA,IAER;AAEA,iBAAa,+DAA0D;AACvE,WAAO;AAAA,EACT;AAEA,aAAW,oCAA+B;AAC1C,MAAI,OAAO,UAAU;AACnB,YAAQ,IAAI,OAAO,QAAQ;AAAA,EAC7B;AAMA,MAAI;AACF,UAAM,OAAO,MAAM,aAAa,SAAS;AACzC,SAAK,SAAS,kBAAkB;AAChC,SAAK,qBAAqB,OAAO,YAAY;AAC7C,UAAM,aAAa,WAAW,IAAI;AAAA,EACpC,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;","names":["findingsMatch"]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getShutdownSignal
|
|
4
|
+
} from "./chunk-M66SJHQQ.js";
|
|
5
|
+
import {
|
|
6
|
+
classify,
|
|
7
|
+
fixedBackoffPolicy,
|
|
8
|
+
withRetry
|
|
9
|
+
} from "./chunk-DIDUVL6O.js";
|
|
10
|
+
import {
|
|
11
|
+
getSessionPublisher,
|
|
12
|
+
printRetry
|
|
13
|
+
} from "./chunk-BYZDPR7N.js";
|
|
14
|
+
import {
|
|
15
|
+
isoNow
|
|
16
|
+
} from "./chunk-CD5ULRVC.js";
|
|
17
|
+
|
|
18
|
+
// src/core/phase-runner.ts
|
|
19
|
+
import { readFile } from "fs/promises";
|
|
20
|
+
var DEFAULT_PHASE_RETRY_LIMIT = 3;
|
|
21
|
+
var DEFAULT_BACKOFF_BASE_SECONDS = 15;
|
|
22
|
+
var DEFAULT_BACKOFF_MAX_SECONDS = 120;
|
|
23
|
+
async function runPhaseWithRetry(options) {
|
|
24
|
+
const retryLimit = options.retryLimit ?? DEFAULT_PHASE_RETRY_LIMIT;
|
|
25
|
+
const backoffBaseSeconds = options.backoffBaseSeconds ?? DEFAULT_BACKOFF_BASE_SECONDS;
|
|
26
|
+
const backoffMaxSeconds = options.backoffMaxSeconds ?? DEFAULT_BACKOFF_MAX_SECONDS;
|
|
27
|
+
if (retryLimit < 1) return { ok: false, error: "Phase never attempted" };
|
|
28
|
+
const outcome = await withRetry((attempt) => options.attempt(attempt), {
|
|
29
|
+
policy: fixedBackoffPolicy(retryLimit, backoffBaseSeconds, backoffMaxSeconds),
|
|
30
|
+
// The caller's own signal when it has one, and the process-wide shutdown
|
|
31
|
+
// otherwise: a backoff nobody can interrupt is a `Ctrl+C` that appears to
|
|
32
|
+
// do nothing for two minutes.
|
|
33
|
+
signal: options.signal ?? getShutdownSignal(),
|
|
34
|
+
evaluate: (result) => result.ok ? null : phaseFailure(result),
|
|
35
|
+
onAttempt: ({ attempt, failure, willRetry, delayMs }) => {
|
|
36
|
+
if (failure === null || !willRetry) return;
|
|
37
|
+
const delaySeconds = delayMs / 1e3;
|
|
38
|
+
getSessionPublisher().publish({
|
|
39
|
+
type: "retry",
|
|
40
|
+
at: isoNow(),
|
|
41
|
+
attempt,
|
|
42
|
+
delaySeconds,
|
|
43
|
+
reason: failure.message,
|
|
44
|
+
kind: failure.kind
|
|
45
|
+
});
|
|
46
|
+
printRetry(
|
|
47
|
+
`Phase ${options.phase} hit a recoverable failure (attempt ${attempt}/${retryLimit}): ${failure.message}. Retrying in ${delaySeconds}s.`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return outcome.value;
|
|
52
|
+
}
|
|
53
|
+
function phaseFailure(result) {
|
|
54
|
+
const message = result.error ?? "Phase failed";
|
|
55
|
+
return {
|
|
56
|
+
...classify({ source: "agent", stdout: message }),
|
|
57
|
+
message,
|
|
58
|
+
retryable: result.transient === true
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
async function readFileWithGrace(path, delaysMs = [300, 800]) {
|
|
62
|
+
for (let i = 0; ; i++) {
|
|
63
|
+
try {
|
|
64
|
+
return await readFile(path, "utf-8");
|
|
65
|
+
} catch (err) {
|
|
66
|
+
if (i >= delaysMs.length) throw err;
|
|
67
|
+
await new Promise((resolve) => setTimeout(resolve, delaysMs[i]));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export {
|
|
73
|
+
runPhaseWithRetry,
|
|
74
|
+
readFileWithGrace
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=chunk-Y5ZDJ4PJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/phase-runner.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { type ClassifiedFailure, classify } from '../resilience/errors.js';\nimport { fixedBackoffPolicy, withRetry } from '../resilience/retry.js';\nimport { printRetry } from '../ui/logger.js';\nimport { getSessionPublisher } from './session-publisher.js';\nimport { getShutdownSignal } from './shutdown.js';\nimport { isoNow } from './state-manager.js';\n\nexport interface PhaseAttemptResult {\n ok: boolean;\n /** Whether a failed attempt is worth retrying. Ignored when ok is true. */\n transient?: boolean;\n error?: string;\n}\n\nexport interface PhaseRetryOptions {\n phase: string;\n attempt: (attemptNumber: number) => Promise<PhaseAttemptResult>;\n retryLimit?: number;\n backoffBaseSeconds?: number;\n backoffMaxSeconds?: number;\n /** Cuts a pending backoff short, so a phase stops waiting on shutdown. */\n signal?: AbortSignal;\n}\n\nconst DEFAULT_PHASE_RETRY_LIMIT = 3;\nconst DEFAULT_BACKOFF_BASE_SECONDS = 15;\nconst DEFAULT_BACKOFF_MAX_SECONDS = 120;\n\n/**\n * Bounded retry wrapper for single-shot phases (prd, plan, pr) that invoke\n * the Claude CLI once and validate an artifact. Applied to phases that\n * previously aborted the whole pipeline on the first failure with no chance\n * to recover. Non-transient failures (or exhausting the retry budget) still\n * end the phase — this bounds recovery attempts, it never retries forever.\n *\n * The loop itself is `resilience/retry.ts:withRetry`, shared with the\n * `execute` loop of `core/engine.ts`. What stays here is what is specific to a\n * phase: the caller's `transient` verdict, the `retry` event and the printed\n * line. With no options supplied the effective numbers are the ones this\n * module has always used — 3 attempts, 15s doubling to 120s, no jitter.\n */\nexport async function runPhaseWithRetry(options: PhaseRetryOptions): Promise<PhaseAttemptResult> {\n const retryLimit = options.retryLimit ?? DEFAULT_PHASE_RETRY_LIMIT;\n const backoffBaseSeconds = options.backoffBaseSeconds ?? DEFAULT_BACKOFF_BASE_SECONDS;\n const backoffMaxSeconds = options.backoffMaxSeconds ?? DEFAULT_BACKOFF_MAX_SECONDS;\n\n if (retryLimit < 1) return { ok: false, error: 'Phase never attempted' };\n\n const outcome = await withRetry<PhaseAttemptResult>((attempt) => options.attempt(attempt), {\n policy: fixedBackoffPolicy(retryLimit, backoffBaseSeconds, backoffMaxSeconds),\n // The caller's own signal when it has one, and the process-wide shutdown\n // otherwise: a backoff nobody can interrupt is a `Ctrl+C` that appears to\n // do nothing for two minutes.\n signal: options.signal ?? getShutdownSignal(),\n evaluate: (result) => (result.ok ? null : phaseFailure(result)),\n onAttempt: ({ attempt, failure, willRetry, delayMs }) => {\n if (failure === null || !willRetry) return;\n\n const delaySeconds = delayMs / 1000;\n getSessionPublisher().publish({\n type: 'retry',\n at: isoNow(),\n attempt,\n delaySeconds,\n reason: failure.message,\n kind: failure.kind,\n });\n printRetry(\n `Phase ${options.phase} hit a recoverable failure (attempt ${attempt}/${retryLimit}): ${failure.message}. Retrying in ${delaySeconds}s.`,\n );\n },\n });\n\n return outcome.value;\n}\n\n/**\n * Turn a phase's own verdict into the classified failure `withRetry` decides\n * on.\n *\n * `transient` stays authoritative: the phases build it with\n * `isTransientFailure()` over the CLI's output, but a phase can also fail on\n * something it alone can see — a PRD file that never appeared — and that\n * judgement is not recoverable from the error text. `classify()` is consulted\n * only to name the *kind*, which is what the `retry` event now reports.\n */\nfunction phaseFailure(result: PhaseAttemptResult): ClassifiedFailure {\n const message = result.error ?? 'Phase failed';\n return {\n ...classify({ source: 'agent', stdout: message }),\n message,\n retryable: result.transient === true,\n };\n}\n\n/**\n * Re-read a file a few times with short delays before giving up. Absorbs a\n * brief filesystem-visibility lag between the Claude CLI's Write tool\n * completing and this process observing the result, without spending a full\n * phase retry (and a new Claude invocation) on what may just be a timing gap.\n */\nexport async function readFileWithGrace(\n path: string,\n delaysMs: number[] = [300, 800],\n): Promise<string> {\n for (let i = 0; ; i++) {\n try {\n return await readFile(path, 'utf-8');\n } catch (err) {\n if (i >= delaysMs.length) throw err;\n await new Promise((resolve) => setTimeout(resolve, delaysMs[i]));\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA,SAAS,gBAAgB;AAyBzB,IAAM,4BAA4B;AAClC,IAAM,+BAA+B;AACrC,IAAM,8BAA8B;AAepC,eAAsB,kBAAkB,SAAyD;AAC/F,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,qBAAqB,QAAQ,sBAAsB;AACzD,QAAM,oBAAoB,QAAQ,qBAAqB;AAEvD,MAAI,aAAa,EAAG,QAAO,EAAE,IAAI,OAAO,OAAO,wBAAwB;AAEvE,QAAM,UAAU,MAAM,UAA8B,CAAC,YAAY,QAAQ,QAAQ,OAAO,GAAG;AAAA,IACzF,QAAQ,mBAAmB,YAAY,oBAAoB,iBAAiB;AAAA;AAAA;AAAA;AAAA,IAI5E,QAAQ,QAAQ,UAAU,kBAAkB;AAAA,IAC5C,UAAU,CAAC,WAAY,OAAO,KAAK,OAAO,aAAa,MAAM;AAAA,IAC7D,WAAW,CAAC,EAAE,SAAS,SAAS,WAAW,QAAQ,MAAM;AACvD,UAAI,YAAY,QAAQ,CAAC,UAAW;AAEpC,YAAM,eAAe,UAAU;AAC/B,0BAAoB,EAAE,QAAQ;AAAA,QAC5B,MAAM;AAAA,QACN,IAAI,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,MAAM,QAAQ;AAAA,MAChB,CAAC;AACD;AAAA,QACE,SAAS,QAAQ,KAAK,uCAAuC,OAAO,IAAI,UAAU,MAAM,QAAQ,OAAO,iBAAiB,YAAY;AAAA,MACtI;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO,QAAQ;AACjB;AAYA,SAAS,aAAa,QAA+C;AACnE,QAAM,UAAU,OAAO,SAAS;AAChC,SAAO;AAAA,IACL,GAAG,SAAS,EAAE,QAAQ,SAAS,QAAQ,QAAQ,CAAC;AAAA,IAChD;AAAA,IACA,WAAW,OAAO,cAAc;AAAA,EAClC;AACF;AAQA,eAAsB,kBACpB,MACA,WAAqB,CAAC,KAAK,GAAG,GACb;AACjB,WAAS,IAAI,KAAK,KAAK;AACrB,QAAI;AACF,aAAO,MAAM,SAAS,MAAM,OAAO;AAAA,IACrC,SAAS,KAAK;AACZ,UAAI,KAAK,SAAS,OAAQ,OAAM;AAChC,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,SAAS,CAAC,CAAC,CAAC;AAAA,IACjE;AAAA,EACF;AACF;","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_INACTIVITY_TIMEOUT_MS,
|
|
4
|
+
installShutdownHandlers
|
|
5
|
+
} from "./chunk-M66SJHQQ.js";
|
|
2
6
|
import {
|
|
3
7
|
setIssuesCliOverrides,
|
|
8
|
+
setResilienceCliOverrides,
|
|
4
9
|
setWebCliOverrides
|
|
5
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-42PJFMAR.js";
|
|
11
|
+
import "./chunk-DIDUVL6O.js";
|
|
6
12
|
import {
|
|
7
13
|
printError,
|
|
8
14
|
setGlobalTimeout,
|
|
15
|
+
setInactivityTimeout,
|
|
9
16
|
setVerbose
|
|
10
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-BYZDPR7N.js";
|
|
18
|
+
import "./chunk-CD5ULRVC.js";
|
|
11
19
|
|
|
12
20
|
// src/cli.ts
|
|
13
21
|
import { createRequire } from "module";
|
|
@@ -107,6 +115,37 @@ function resolveGenerateTarget(opts) {
|
|
|
107
115
|
return selected[0];
|
|
108
116
|
}
|
|
109
117
|
|
|
118
|
+
// src/resilience/cli-flags.ts
|
|
119
|
+
function continuousProfile() {
|
|
120
|
+
return {
|
|
121
|
+
profile: "continuous",
|
|
122
|
+
providers: { failover: true },
|
|
123
|
+
queue: { onIssueFailure: "skip" },
|
|
124
|
+
journal: { enabled: true },
|
|
125
|
+
watchdog: { inactivityTimeoutMs: DEFAULT_INACTIVITY_TIMEOUT_MS }
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function resolveResilienceOverrides(flags) {
|
|
129
|
+
const continuous = flags.continuous === true || flags.resilient === true;
|
|
130
|
+
const overrides = continuous ? continuousProfile() : {};
|
|
131
|
+
if (flags.failover === false) {
|
|
132
|
+
overrides.providers = { ...overrides.providers, failover: false };
|
|
133
|
+
}
|
|
134
|
+
if (flags.autoDecompose === true) {
|
|
135
|
+
overrides.decompose = { ...overrides.decompose, auto: true };
|
|
136
|
+
}
|
|
137
|
+
if (flags.inactivityTimeout !== void 0) {
|
|
138
|
+
overrides.watchdog = {
|
|
139
|
+
...overrides.watchdog,
|
|
140
|
+
inactivityTimeoutMs: flags.inactivityTimeout * 1e3
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
if (flags.onIssueFailure !== void 0) {
|
|
144
|
+
overrides.queue = { ...overrides.queue, onIssueFailure: flags.onIssueFailure };
|
|
145
|
+
}
|
|
146
|
+
return overrides;
|
|
147
|
+
}
|
|
148
|
+
|
|
110
149
|
// src/cli.ts
|
|
111
150
|
var require2 = createRequire(import.meta.url);
|
|
112
151
|
var { version } = require2("../package.json");
|
|
@@ -117,6 +156,10 @@ function parseInteger(value) {
|
|
|
117
156
|
}
|
|
118
157
|
return parsed;
|
|
119
158
|
}
|
|
159
|
+
function parseQueueFailureMode(value) {
|
|
160
|
+
if (value === "stop" || value === "skip" || value === "block") return value;
|
|
161
|
+
throw new InvalidArgumentError("Must be one of: stop, skip, block.");
|
|
162
|
+
}
|
|
120
163
|
function parseStartUs(value) {
|
|
121
164
|
const parsed = parseInteger(value);
|
|
122
165
|
if (parsed < 1) {
|
|
@@ -136,8 +179,15 @@ function withGlobalOptions(cmd) {
|
|
|
136
179
|
"-t, --timeout <seconds>",
|
|
137
180
|
"Override headless timeout in seconds (0 = no limit)",
|
|
138
181
|
parseInteger
|
|
182
|
+
).option(
|
|
183
|
+
"--inactivity-timeout <seconds>",
|
|
184
|
+
"Stop the agent after this many seconds with no output (0 = no watchdog)",
|
|
185
|
+
parseInteger
|
|
139
186
|
);
|
|
140
187
|
}
|
|
188
|
+
function withResilienceOptions(cmd) {
|
|
189
|
+
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");
|
|
190
|
+
}
|
|
141
191
|
function withWebOptions(cmd) {
|
|
142
192
|
return cmd.option("--web", "Enable the web monitoring server").option("--serve", "Alias for --web").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).option("--web-log-limit <n>", "Max log entries kept in the snapshot", parseInteger).option("--web-no-logs", "Exclude logs from the published snapshot");
|
|
143
193
|
}
|
|
@@ -171,6 +221,7 @@ program.name("issue-flow").description(
|
|
|
171
221
|
"Unified CLI for orchestrating the full issue-flow pipeline via Claude Code Headless."
|
|
172
222
|
).version(version);
|
|
173
223
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
224
|
+
installShutdownHandlers();
|
|
174
225
|
const opts = actionCommand.opts();
|
|
175
226
|
if (opts.verbose) {
|
|
176
227
|
setVerbose(true);
|
|
@@ -178,7 +229,20 @@ program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
|
178
229
|
if (opts.timeout !== void 0) {
|
|
179
230
|
setGlobalTimeout(opts.timeout * 1e3);
|
|
180
231
|
}
|
|
232
|
+
if (opts.inactivityTimeout !== void 0) {
|
|
233
|
+
setInactivityTimeout(opts.inactivityTimeout * 1e3);
|
|
234
|
+
}
|
|
181
235
|
setWebCliOverrides(resolveWebOverrides(opts));
|
|
236
|
+
setResilienceCliOverrides(
|
|
237
|
+
resolveResilienceOverrides({
|
|
238
|
+
continuous: opts.continuous,
|
|
239
|
+
resilient: opts.resilient,
|
|
240
|
+
failover: opts.failover,
|
|
241
|
+
autoDecompose: opts.autoDecompose,
|
|
242
|
+
inactivityTimeout: opts.inactivityTimeout,
|
|
243
|
+
onIssueFailure: opts.onIssueFailure
|
|
244
|
+
})
|
|
245
|
+
);
|
|
182
246
|
try {
|
|
183
247
|
setIssuesCliOverrides(resolveIssuesOverrides(opts));
|
|
184
248
|
} catch (error) {
|
|
@@ -197,8 +261,8 @@ withIssueOptions(
|
|
|
197
261
|
)
|
|
198
262
|
).action(
|
|
199
263
|
async (options) => {
|
|
200
|
-
const { loadIssuesConfig } = await import("./config-
|
|
201
|
-
const { runInit } = await import("./init-
|
|
264
|
+
const { loadIssuesConfig } = await import("./config-PRJGWW7J.js");
|
|
265
|
+
const { runInit } = await import("./init-AJHCXJBP.js");
|
|
202
266
|
const { preferredProvider } = await loadIssuesConfig();
|
|
203
267
|
const code = await runInit(preferredProvider, options);
|
|
204
268
|
process.exit(code);
|
|
@@ -217,20 +281,30 @@ withGlobalOptions(
|
|
|
217
281
|
}
|
|
218
282
|
throw error;
|
|
219
283
|
}
|
|
220
|
-
const { runGenerate } = await import("./generate-
|
|
284
|
+
const { runGenerate } = await import("./generate-EGB4KV2B.js");
|
|
221
285
|
const code = await runGenerate(options.prompt, target);
|
|
222
286
|
process.exit(code);
|
|
223
287
|
});
|
|
224
288
|
withUserStoryNumberingOptions(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
"
|
|
230
|
-
|
|
231
|
-
"--
|
|
232
|
-
|
|
233
|
-
|
|
289
|
+
withResilienceOptions(
|
|
290
|
+
withWebOptions(
|
|
291
|
+
withIssueOptions(
|
|
292
|
+
withGlobalOptions(
|
|
293
|
+
program.command("run").description(
|
|
294
|
+
"Execute the full pipeline: prd \u2192 plan \u2192 execute \u2192 review \u2192 pr (\u2192 pr-review, optional)"
|
|
295
|
+
).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
|
+
"--no-branch",
|
|
297
|
+
"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(
|
|
299
|
+
"--retry-limit <number>",
|
|
300
|
+
"Retry transient Claude failures up to N consecutive times",
|
|
301
|
+
parseInteger
|
|
302
|
+
).option("--retry-forever", "Retry transient Claude failures indefinitely").option(
|
|
303
|
+
"--on-issue-failure <mode>",
|
|
304
|
+
"In a queue, on a failing issue: stop | skip | block",
|
|
305
|
+
parseQueueFailureMode
|
|
306
|
+
)
|
|
307
|
+
)
|
|
234
308
|
)
|
|
235
309
|
)
|
|
236
310
|
)
|
|
@@ -250,7 +324,7 @@ withUserStoryNumberingOptions(
|
|
|
250
324
|
}
|
|
251
325
|
throw error;
|
|
252
326
|
}
|
|
253
|
-
const { runPipeline } = await import("./run-
|
|
327
|
+
const { runPipeline } = await import("./run-RXE5GDQO.js");
|
|
254
328
|
const code = await runPipeline(
|
|
255
329
|
issues,
|
|
256
330
|
options.mode,
|
|
@@ -261,18 +335,74 @@ withUserStoryNumberingOptions(
|
|
|
261
335
|
yes: scope.yes,
|
|
262
336
|
only: scope.only,
|
|
263
337
|
continueNumbering: numbering.continueFlag,
|
|
264
|
-
startUs: numbering.startUs
|
|
338
|
+
startUs: numbering.startUs,
|
|
339
|
+
retryLimit: options.retryLimit,
|
|
340
|
+
retryForever: options.retryForever,
|
|
341
|
+
onIssueFailure: options.onIssueFailure
|
|
265
342
|
}
|
|
266
343
|
);
|
|
267
344
|
process.exit(code);
|
|
268
345
|
}
|
|
269
346
|
);
|
|
347
|
+
withIssueOptions(
|
|
348
|
+
withGlobalOptions(
|
|
349
|
+
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
|
+
)
|
|
351
|
+
).action(async (issue, options) => {
|
|
352
|
+
const { runResume } = await import("./resume-PPCNQVVV.js");
|
|
353
|
+
const code = await runResume(issue, {
|
|
354
|
+
...options.all === void 0 ? {} : { all: options.all },
|
|
355
|
+
...options.mode === void 0 ? {} : { mode: options.mode }
|
|
356
|
+
});
|
|
357
|
+
process.exit(code);
|
|
358
|
+
});
|
|
359
|
+
withGlobalOptions(
|
|
360
|
+
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
|
+
).action(async (issue, options) => {
|
|
362
|
+
const { runStatus } = await import("./operations-BYT626KQ.js");
|
|
363
|
+
process.exit(
|
|
364
|
+
await runStatus(issue, { ...options.json === void 0 ? {} : { json: options.json } })
|
|
365
|
+
);
|
|
366
|
+
});
|
|
367
|
+
withGlobalOptions(
|
|
368
|
+
program.command("runs").description("History of the runs of this project, with how each ended")
|
|
369
|
+
).action(async () => {
|
|
370
|
+
const { runRuns } = await import("./operations-BYT626KQ.js");
|
|
371
|
+
process.exit(await runRuns());
|
|
372
|
+
});
|
|
373
|
+
withGlobalOptions(
|
|
374
|
+
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
|
+
).action(
|
|
376
|
+
async (issue, options) => {
|
|
377
|
+
const { runLogs } = await import("./operations-BYT626KQ.js");
|
|
378
|
+
const kinds = options.kind === void 0 ? void 0 : options.kind.split(",").map((kind) => kind.trim()).filter((kind) => kind !== "");
|
|
379
|
+
process.exit(
|
|
380
|
+
await runLogs(issue ?? options.issue, {
|
|
381
|
+
...kinds === void 0 ? {} : { kind: kinds },
|
|
382
|
+
...options.follow === void 0 ? {} : { follow: options.follow },
|
|
383
|
+
...options.tail === void 0 ? {} : { tail: options.tail }
|
|
384
|
+
})
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
);
|
|
388
|
+
withGlobalOptions(
|
|
389
|
+
program.command("pause").description("Ask the running pipeline to stop after writing a checkpoint")
|
|
390
|
+
).action(async () => {
|
|
391
|
+
const { runPause } = await import("./operations-BYT626KQ.js");
|
|
392
|
+
process.exit(await runPause());
|
|
393
|
+
});
|
|
394
|
+
withGlobalOptions(
|
|
395
|
+
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
|
+
).action(async (issue) => {
|
|
397
|
+
const { runCancel } = await import("./operations-BYT626KQ.js");
|
|
398
|
+
process.exit(await runCancel(issue));
|
|
399
|
+
});
|
|
270
400
|
withIssueOptions(
|
|
271
401
|
withGlobalOptions(
|
|
272
402
|
program.command("analyze").description("Analyze an issue via Claude Code Headless").argument("<issue>", "Issue number")
|
|
273
403
|
)
|
|
274
404
|
).action(async (issue) => {
|
|
275
|
-
const { runAnalyze } = await import("./analyze-
|
|
405
|
+
const { runAnalyze } = await import("./analyze-OEET7KGE.js");
|
|
276
406
|
const code = await runAnalyze(issue);
|
|
277
407
|
process.exit(code);
|
|
278
408
|
});
|
|
@@ -281,7 +411,7 @@ withIssueOptions(
|
|
|
281
411
|
program.command("prd").description("Generate a PRD from an analyzed issue via Claude Code Headless").argument("<issue>", "Issue number")
|
|
282
412
|
)
|
|
283
413
|
).action(async (issue) => {
|
|
284
|
-
const { runPrd } = await import("./prd-
|
|
414
|
+
const { runPrd } = await import("./prd-JQSZF7PR.js");
|
|
285
415
|
const code = await runPrd(issue);
|
|
286
416
|
process.exit(code);
|
|
287
417
|
});
|
|
@@ -302,7 +432,7 @@ withUserStoryNumberingOptions(
|
|
|
302
432
|
}
|
|
303
433
|
throw error;
|
|
304
434
|
}
|
|
305
|
-
const { runPlan } = await import("./plan-
|
|
435
|
+
const { runPlan } = await import("./plan-QOZ3RIO6.js");
|
|
306
436
|
const code = await runPlan(issue, void 0, numbering);
|
|
307
437
|
process.exit(code);
|
|
308
438
|
});
|
|
@@ -321,7 +451,7 @@ withWebOptions(
|
|
|
321
451
|
).action(
|
|
322
452
|
async (positionalMaxIter, options) => {
|
|
323
453
|
try {
|
|
324
|
-
const { runExecute } = await import("./execute-
|
|
454
|
+
const { runExecute } = await import("./execute-XBNVL753.js");
|
|
325
455
|
const code = await runExecute(positionalMaxIter, options);
|
|
326
456
|
process.exit(code);
|
|
327
457
|
} catch (error) {
|
|
@@ -335,7 +465,7 @@ withIssueOptions(
|
|
|
335
465
|
program.command("review").description("Validate an issue resolution via Claude Code Headless").argument("<issue>", "Issue number")
|
|
336
466
|
)
|
|
337
467
|
).action(async (issue) => {
|
|
338
|
-
const { runReview } = await import("./review-
|
|
468
|
+
const { runReview } = await import("./review-3F6MARWH.js");
|
|
339
469
|
const code = await runReview(issue);
|
|
340
470
|
process.exit(code);
|
|
341
471
|
});
|
|
@@ -344,7 +474,7 @@ withIssueOptions(
|
|
|
344
474
|
program.command("pr").description("Create a pull request via Claude Code Headless").argument("<issue>", "Issue number")
|
|
345
475
|
)
|
|
346
476
|
).action(async (issue) => {
|
|
347
|
-
const { runPr } = await import("./pr-
|
|
477
|
+
const { runPr } = await import("./pr-EBBHD2ZX.js");
|
|
348
478
|
const code = await runPr(issue);
|
|
349
479
|
process.exit(code);
|
|
350
480
|
});
|
|
@@ -352,21 +482,21 @@ var webCommand = program.command("web").description("Manage the web monitoring s
|
|
|
352
482
|
webCommand.command("serve").description(
|
|
353
483
|
"Run the web monitor server in the foreground (internal \u2014 spawned detached by --web)"
|
|
354
484
|
).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) => {
|
|
355
|
-
const { runWebServe } = await import("./web-
|
|
485
|
+
const { runWebServe } = await import("./web-EF5WIIGG.js");
|
|
356
486
|
const code = await runWebServe(options);
|
|
357
487
|
if (code !== 0) {
|
|
358
488
|
process.exit(code);
|
|
359
489
|
}
|
|
360
490
|
});
|
|
361
491
|
webCommand.command("stop").description("Stop the running web monitor server").action(async () => {
|
|
362
|
-
const { runWebStop } = await import("./web-
|
|
492
|
+
const { runWebStop } = await import("./web-EF5WIIGG.js");
|
|
363
493
|
const code = await runWebStop();
|
|
364
494
|
process.exit(code);
|
|
365
495
|
});
|
|
366
496
|
withGlobalOptions(
|
|
367
497
|
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")
|
|
368
498
|
).action(async (options) => {
|
|
369
|
-
const { runPolicy } = await import("./policy-
|
|
499
|
+
const { runPolicy } = await import("./policy-6S4GFC76.js");
|
|
370
500
|
const code = await runPolicy(options);
|
|
371
501
|
process.exit(code);
|
|
372
502
|
});
|
|
@@ -377,7 +507,7 @@ withGlobalOptions(
|
|
|
377
507
|
)
|
|
378
508
|
).action(
|
|
379
509
|
async (pr, options) => {
|
|
380
|
-
const { runPrReview } = await import("./pr-review-
|
|
510
|
+
const { runPrReview } = await import("./pr-review-VVMW5PO4.js");
|
|
381
511
|
const code = await runPrReview(pr, options);
|
|
382
512
|
process.exit(code);
|
|
383
513
|
}
|