issue-flow 0.18.0 → 0.20.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 +43 -97
- package/dist/agent-4DHRKZ2Z.js +32 -0
- package/dist/{analyze-Q4ONIWRZ.js → analyze-UEJ2R3H5.js} +42 -41
- package/dist/analyze-UEJ2R3H5.js.map +1 -0
- package/dist/{apply-EEFPY2W4.js → apply-QDYNQMUX.js} +22 -24
- package/dist/apply-QDYNQMUX.js.map +1 -0
- package/dist/artifacts-AMJQJFFV.js +82 -0
- package/dist/artifacts-AMJQJFFV.js.map +1 -0
- package/dist/{bench-WWWXLTFH.js → bench-RNRXVEFK.js} +42 -42
- package/dist/{chunk-RYOUZ6EK.js → chunk-23VHVVKW.js} +3 -3
- package/dist/chunk-2EYLOS5I.js +99 -0
- package/dist/chunk-2EYLOS5I.js.map +1 -0
- package/dist/{chunk-C5TL7T4V.js → chunk-2YM2VH6R.js} +2 -2
- package/dist/{chunk-XUEMATVY.js → chunk-37O2FMAN.js} +28 -25
- package/dist/chunk-37O2FMAN.js.map +1 -0
- package/dist/chunk-44RF3VFG.js +717 -0
- package/dist/chunk-44RF3VFG.js.map +1 -0
- package/dist/chunk-6AOZCWN2.js +21 -0
- package/dist/chunk-6AOZCWN2.js.map +1 -0
- package/dist/chunk-7MJGYPHF.js +1571 -0
- package/dist/chunk-7MJGYPHF.js.map +1 -0
- package/dist/{chunk-SA6HXL4Y.js → chunk-7WBUEBD5.js} +9 -9
- package/dist/chunk-7WBUEBD5.js.map +1 -0
- package/dist/chunk-7ZZUSMBJ.js +35 -0
- package/dist/chunk-7ZZUSMBJ.js.map +1 -0
- package/dist/{chunk-QJ44VG5G.js → chunk-ADH6RJNX.js} +3 -3
- package/dist/{chunk-34OCSKOB.js → chunk-AKL5UPR6.js} +159 -114
- package/dist/chunk-AKL5UPR6.js.map +1 -0
- package/dist/{chunk-7F7LGMVO.js → chunk-BTBJ5UOO.js} +12 -12
- package/dist/{chunk-7F7LGMVO.js.map → chunk-BTBJ5UOO.js.map} +1 -1
- package/dist/{chunk-HOAHMERN.js → chunk-CLZ6RRZL.js} +21 -21
- package/dist/chunk-DBLXLKGU.js +1201 -0
- package/dist/chunk-DBLXLKGU.js.map +1 -0
- package/dist/{chunk-DUS5ZNKL.js → chunk-DIMDAYZS.js} +7 -6
- package/dist/chunk-DZ3DZ3EN.js +278 -0
- package/dist/chunk-DZ3DZ3EN.js.map +1 -0
- package/dist/{chunk-CRGIQFUQ.js → chunk-E2H3JV2E.js} +3 -1
- package/dist/chunk-E2H3JV2E.js.map +1 -0
- package/dist/{chunk-45WZ6GMI.js → chunk-EORDSKWZ.js} +17 -17
- package/dist/chunk-EORDSKWZ.js.map +1 -0
- package/dist/{chunk-LTH6XYZ3.js → chunk-EYKPWHT7.js} +40 -30
- package/dist/chunk-EYKPWHT7.js.map +1 -0
- package/dist/{chunk-OODXFCQV.js → chunk-FU2FQ4JE.js} +14 -16
- package/dist/{chunk-OODXFCQV.js.map → chunk-FU2FQ4JE.js.map} +1 -1
- package/dist/{chunk-V7QOIQYC.js → chunk-G442RDFX.js} +9 -23
- package/dist/{chunk-V7QOIQYC.js.map → chunk-G442RDFX.js.map} +1 -1
- package/dist/{chunk-QPGEFLMY.js → chunk-I64N6RL6.js} +7 -7
- package/dist/{chunk-KRAGAUKD.js → chunk-JBYXJOJJ.js} +201 -64
- package/dist/chunk-JBYXJOJJ.js.map +1 -0
- package/dist/{chunk-SOM4QA6C.js → chunk-JCR5C5A7.js} +93 -18
- package/dist/chunk-JCR5C5A7.js.map +1 -0
- package/dist/{chunk-RNFUVKC3.js → chunk-K5NM26NV.js} +30 -13
- package/dist/chunk-K5NM26NV.js.map +1 -0
- package/dist/{chunk-YVPZUN6X.js → chunk-KUA6KBBD.js} +335 -38
- package/dist/chunk-KUA6KBBD.js.map +1 -0
- package/dist/{chunk-KMCS76ZW.js → chunk-KUL64XUF.js} +44 -12
- package/dist/chunk-KUL64XUF.js.map +1 -0
- package/dist/{chunk-HAKDLR6N.js → chunk-MAJ6QDRL.js} +65 -78
- package/dist/chunk-MAJ6QDRL.js.map +1 -0
- package/dist/{chunk-DGRTJD5R.js → chunk-MML2G7IC.js} +7 -7
- package/dist/chunk-NP47HRX2.js +136 -0
- package/dist/chunk-NP47HRX2.js.map +1 -0
- package/dist/{chunk-3R27MJ5R.js → chunk-PFWHHYEO.js} +3 -3
- package/dist/{chunk-ECU7YO7S.js → chunk-PM5YWJYO.js} +22 -6
- package/dist/chunk-PM5YWJYO.js.map +1 -0
- package/dist/{chunk-E4I6MMHD.js → chunk-PXPTIXJF.js} +154 -101
- package/dist/chunk-PXPTIXJF.js.map +1 -0
- package/dist/{chunk-CWSQVHVV.js → chunk-QJHZ3HYJ.js} +248 -102
- package/dist/chunk-QJHZ3HYJ.js.map +1 -0
- package/dist/{chunk-LI35PIIS.js → chunk-RDPK7LYK.js} +20 -117
- package/dist/chunk-RDPK7LYK.js.map +1 -0
- package/dist/{chunk-PMLE7KAQ.js → chunk-RMIBLFG3.js} +30 -14
- package/dist/chunk-RMIBLFG3.js.map +1 -0
- package/dist/{chunk-62GVVZQO.js → chunk-T736DSZI.js} +32 -316
- package/dist/chunk-T736DSZI.js.map +1 -0
- package/dist/{chunk-TZYINKCC.js → chunk-UDUUUFQF.js} +57 -29
- package/dist/chunk-UDUUUFQF.js.map +1 -0
- package/dist/{chunk-NEWNXZ65.js → chunk-V7GETODQ.js} +36 -28
- package/dist/{chunk-NEWNXZ65.js.map → chunk-V7GETODQ.js.map} +1 -1
- package/dist/{chunk-PPZ3K4YM.js → chunk-VHQMMY2D.js} +2 -2
- package/dist/{chunk-ZVZMWNCG.js → chunk-VJ3PF6B7.js} +50 -16
- package/dist/chunk-VJ3PF6B7.js.map +1 -0
- package/dist/{chunk-L6HSKTQE.js → chunk-W7LZLJAF.js} +4 -4
- package/dist/{chunk-6K2LCFG6.js → chunk-WB4FA2EH.js} +70 -81
- package/dist/chunk-WB4FA2EH.js.map +1 -0
- package/dist/{chunk-LGHND47K.js → chunk-WQSGL5LX.js} +22 -16
- package/dist/chunk-WQSGL5LX.js.map +1 -0
- package/dist/{chunk-ICM463EO.js → chunk-XNK5UN2D.js} +5 -649
- package/dist/chunk-XNK5UN2D.js.map +1 -0
- package/dist/{chunk-7UMMFOL2.js → chunk-Y2KOWABB.js} +39 -24
- package/dist/chunk-Y2KOWABB.js.map +1 -0
- package/dist/{chunk-QF7VEL3M.js → chunk-YC24E66P.js} +568 -158
- package/dist/chunk-YC24E66P.js.map +1 -0
- package/dist/{chunk-EG2MGDP5.js → chunk-Z6RCKCVB.js} +52 -46
- package/dist/chunk-Z6RCKCVB.js.map +1 -0
- package/dist/{chunk-YUNBOUQH.js → chunk-ZPGNVBWY.js} +8 -8
- package/dist/cli.js +132 -62
- package/dist/cli.js.map +1 -1
- package/dist/compat-OJG76J4I.js +24 -0
- package/dist/{config-LEBZZCJP.js → config-6YTWPDBK.js} +20 -17
- package/dist/{contract-JH2WBIO6.js → contract-HWLFFL3F.js} +2 -2
- package/dist/{conventions-XOT6YW5L.js → conventions-5UPOTU42.js} +20 -16
- package/dist/{conventions-XOT6YW5L.js.map → conventions-5UPOTU42.js.map} +1 -1
- package/dist/db-QAZG4LQD.js +264 -0
- package/dist/db-QAZG4LQD.js.map +1 -0
- package/dist/diagnostics-YEFB42E5.js +25 -0
- package/dist/execute-QCT64D37.js +38 -0
- package/dist/{generate-JGW5JSKB.js → generate-QATMDKOK.js} +46 -43
- package/dist/generate-QATMDKOK.js.map +1 -0
- package/dist/{git-A2IP32PQ.js → git-XGOECXWG.js} +2 -3
- package/dist/history-NBPUZVGQ.js +101 -0
- package/dist/history-NBPUZVGQ.js.map +1 -0
- package/dist/init-4LB2YKWP.js +28 -0
- package/dist/{operations-O4FORFIH.js → operations-RUQP2Y2F.js} +78 -52
- package/dist/operations-RUQP2Y2F.js.map +1 -0
- package/dist/{permissions-G4XCAESF.js → permissions-QZPUUBSO.js} +5 -6
- package/dist/plan-2NMSHTMD.js +38 -0
- package/dist/{policy-U5NBFAO5.js → policy-RKKFF5A2.js} +17 -15
- package/dist/{policy-U5NBFAO5.js.map → policy-RKKFF5A2.js.map} +1 -1
- package/dist/pr-QKFO5HI3.js +42 -0
- package/dist/pr-review-H2BFD6F2.js +33 -0
- package/dist/prd-ET6XKYRS.js +37 -0
- package/dist/{ps-76L6ZAZL.js → ps-UIKSOUAQ.js} +26 -15
- package/dist/ps-UIKSOUAQ.js.map +1 -0
- package/dist/{recorder-2BAKPBRA.js → recorder-LOU3PTIE.js} +11 -7
- package/dist/registry-HV7M6MAH.js +17 -0
- package/dist/repository-RCRR6RDE.js +80 -0
- package/dist/resume-BWJZGBLZ.js +278 -0
- package/dist/resume-BWJZGBLZ.js.map +1 -0
- package/dist/review-2MTZLNSS.js +38 -0
- package/dist/routing-RM5ABHHD.js +35 -0
- package/dist/run-XMACQBRJ.js +61 -0
- package/dist/{session-publisher-KAJQRHNZ.js → session-publisher-Q5TNEZPX.js} +3 -3
- package/dist/session-publisher-Q5TNEZPX.js.map +1 -0
- package/dist/{state-manager-UPHO2EA2.js → state-manager-SRN4VJSX.js} +9 -4
- package/dist/state-manager-SRN4VJSX.js.map +1 -0
- package/dist/{usage-KTMYXAPF.js → usage-JOODVE5O.js} +69 -63
- package/dist/usage-JOODVE5O.js.map +1 -0
- package/dist/web-TLMWJ2BM.js +205 -0
- package/dist/web-TLMWJ2BM.js.map +1 -0
- package/package.json +22 -8
- package/prompts/analyze.md +16 -19
- package/prompts/execute.md +73 -144
- package/prompts/generate.md +23 -10
- package/prompts/plan.md +32 -60
- package/prompts/pr-review.md +58 -40
- package/prompts/pr.md +50 -16
- package/prompts/prd.md +26 -19
- package/prompts/review.md +41 -18
- package/web/public/app.js +111 -112
- package/dist/agent-HMZTXCRT.js +0 -30
- package/dist/analyze-Q4ONIWRZ.js.map +0 -1
- package/dist/apply-EEFPY2W4.js.map +0 -1
- package/dist/chunk-34OCSKOB.js.map +0 -1
- package/dist/chunk-45WZ6GMI.js.map +0 -1
- package/dist/chunk-62GVVZQO.js.map +0 -1
- package/dist/chunk-6K2LCFG6.js.map +0 -1
- package/dist/chunk-7UMMFOL2.js.map +0 -1
- package/dist/chunk-CRGIQFUQ.js.map +0 -1
- package/dist/chunk-CWSQVHVV.js.map +0 -1
- package/dist/chunk-E4I6MMHD.js.map +0 -1
- package/dist/chunk-ECU7YO7S.js.map +0 -1
- package/dist/chunk-EG2MGDP5.js.map +0 -1
- package/dist/chunk-HAKDLR6N.js.map +0 -1
- package/dist/chunk-ICM463EO.js.map +0 -1
- package/dist/chunk-KMCS76ZW.js.map +0 -1
- package/dist/chunk-KRAGAUKD.js.map +0 -1
- package/dist/chunk-LGHND47K.js.map +0 -1
- package/dist/chunk-LI35PIIS.js.map +0 -1
- package/dist/chunk-LTH6XYZ3.js.map +0 -1
- package/dist/chunk-PMLE7KAQ.js.map +0 -1
- package/dist/chunk-QF7VEL3M.js.map +0 -1
- package/dist/chunk-RNFUVKC3.js.map +0 -1
- package/dist/chunk-SA6HXL4Y.js.map +0 -1
- package/dist/chunk-SOM4QA6C.js.map +0 -1
- package/dist/chunk-TZYINKCC.js.map +0 -1
- package/dist/chunk-WCCZJL7W.js +0 -141
- package/dist/chunk-WCCZJL7W.js.map +0 -1
- package/dist/chunk-XEYH6ZZI.js +0 -289
- package/dist/chunk-XEYH6ZZI.js.map +0 -1
- package/dist/chunk-XUEMATVY.js.map +0 -1
- package/dist/chunk-XZUEFTUP.js +0 -243
- package/dist/chunk-XZUEFTUP.js.map +0 -1
- package/dist/chunk-YVPZUN6X.js.map +0 -1
- package/dist/chunk-ZVZMWNCG.js.map +0 -1
- package/dist/diagnostics-HTCWF7F4.js +0 -23
- package/dist/execute-LELOSR5T.js +0 -37
- package/dist/generate-JGW5JSKB.js.map +0 -1
- package/dist/init-TO6MUXO4.js +0 -26
- package/dist/operations-O4FORFIH.js.map +0 -1
- package/dist/plan-OXAT344Q.js +0 -34
- package/dist/pr-UZHNKKZC.js +0 -39
- package/dist/pr-review-Q4ACAWDM.js +0 -32
- package/dist/prd-6CYEMLDY.js +0 -33
- package/dist/ps-76L6ZAZL.js.map +0 -1
- package/dist/registry-XLHHYLTR.js +0 -15
- package/dist/resume-URCU6CIJ.js +0 -244
- package/dist/resume-URCU6CIJ.js.map +0 -1
- package/dist/review-LVZT2TMW.js +0 -35
- package/dist/routing-EK6RBZM4.js +0 -33
- package/dist/run-2RXJCJKT.js +0 -56
- package/dist/usage-KTMYXAPF.js.map +0 -1
- package/dist/web-B5UPHHR5.js +0 -172
- package/dist/web-B5UPHHR5.js.map +0 -1
- /package/dist/{agent-HMZTXCRT.js.map → agent-4DHRKZ2Z.js.map} +0 -0
- /package/dist/{bench-WWWXLTFH.js.map → bench-RNRXVEFK.js.map} +0 -0
- /package/dist/{chunk-RYOUZ6EK.js.map → chunk-23VHVVKW.js.map} +0 -0
- /package/dist/{chunk-C5TL7T4V.js.map → chunk-2YM2VH6R.js.map} +0 -0
- /package/dist/{chunk-QJ44VG5G.js.map → chunk-ADH6RJNX.js.map} +0 -0
- /package/dist/{chunk-HOAHMERN.js.map → chunk-CLZ6RRZL.js.map} +0 -0
- /package/dist/{chunk-DUS5ZNKL.js.map → chunk-DIMDAYZS.js.map} +0 -0
- /package/dist/{chunk-QPGEFLMY.js.map → chunk-I64N6RL6.js.map} +0 -0
- /package/dist/{chunk-DGRTJD5R.js.map → chunk-MML2G7IC.js.map} +0 -0
- /package/dist/{chunk-3R27MJ5R.js.map → chunk-PFWHHYEO.js.map} +0 -0
- /package/dist/{chunk-PPZ3K4YM.js.map → chunk-VHQMMY2D.js.map} +0 -0
- /package/dist/{chunk-L6HSKTQE.js.map → chunk-W7LZLJAF.js.map} +0 -0
- /package/dist/{chunk-YUNBOUQH.js.map → chunk-ZPGNVBWY.js.map} +0 -0
- /package/dist/{config-LEBZZCJP.js.map → compat-OJG76J4I.js.map} +0 -0
- /package/dist/{contract-JH2WBIO6.js.map → config-6YTWPDBK.js.map} +0 -0
- /package/dist/{diagnostics-HTCWF7F4.js.map → contract-HWLFFL3F.js.map} +0 -0
- /package/dist/{execute-LELOSR5T.js.map → diagnostics-YEFB42E5.js.map} +0 -0
- /package/dist/{git-A2IP32PQ.js.map → execute-QCT64D37.js.map} +0 -0
- /package/dist/{init-TO6MUXO4.js.map → git-XGOECXWG.js.map} +0 -0
- /package/dist/{permissions-G4XCAESF.js.map → init-4LB2YKWP.js.map} +0 -0
- /package/dist/{plan-OXAT344Q.js.map → permissions-QZPUUBSO.js.map} +0 -0
- /package/dist/{pr-UZHNKKZC.js.map → plan-2NMSHTMD.js.map} +0 -0
- /package/dist/{pr-review-Q4ACAWDM.js.map → pr-QKFO5HI3.js.map} +0 -0
- /package/dist/{prd-6CYEMLDY.js.map → pr-review-H2BFD6F2.js.map} +0 -0
- /package/dist/{recorder-2BAKPBRA.js.map → prd-ET6XKYRS.js.map} +0 -0
- /package/dist/{registry-XLHHYLTR.js.map → recorder-LOU3PTIE.js.map} +0 -0
- /package/dist/{review-LVZT2TMW.js.map → registry-HV7M6MAH.js.map} +0 -0
- /package/dist/{routing-EK6RBZM4.js.map → repository-RCRR6RDE.js.map} +0 -0
- /package/dist/{run-2RXJCJKT.js.map → review-2MTZLNSS.js.map} +0 -0
- /package/dist/{session-publisher-KAJQRHNZ.js.map → routing-RM5ABHHD.js.map} +0 -0
- /package/dist/{state-manager-UPHO2EA2.js.map → run-XMACQBRJ.js.map} +0 -0
|
@@ -1,43 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
printInfo
|
|
4
|
-
} from "./chunk-XZUEFTUP.js";
|
|
5
|
-
import {
|
|
6
|
-
ISSUES_DIR_NAME,
|
|
7
|
-
PROVIDERS_HEALTH_FILENAME,
|
|
8
|
-
RUN_LOCK_FILENAME,
|
|
9
|
-
getGlobalRoot,
|
|
10
|
-
getIssuePaths,
|
|
11
|
-
getProjectDir,
|
|
12
|
-
getQueuePaths,
|
|
13
|
-
projectIdFromRemote
|
|
14
|
-
} from "./chunk-HAKDLR6N.js";
|
|
15
|
-
import {
|
|
16
|
-
getProjectRoot,
|
|
17
|
-
getRemoteUrl,
|
|
18
|
-
normalizeRemoteUrl
|
|
19
|
-
} from "./chunk-YVPZUN6X.js";
|
|
20
|
-
import {
|
|
21
|
-
bindTelemetry
|
|
22
|
-
} from "./chunk-6K2LCFG6.js";
|
|
23
2
|
import {
|
|
24
3
|
isoNow
|
|
25
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JCR5C5A7.js";
|
|
26
5
|
import {
|
|
27
6
|
STORAGE_SCHEMA_VERSION,
|
|
28
7
|
projectMetadataSchema
|
|
29
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-44RF3VFG.js";
|
|
9
|
+
import {
|
|
10
|
+
ISSUES_DIR_NAME,
|
|
11
|
+
getProjectDir
|
|
12
|
+
} from "./chunk-MAJ6QDRL.js";
|
|
13
|
+
import {
|
|
14
|
+
getRemoteUrl,
|
|
15
|
+
normalizeRemoteUrl,
|
|
16
|
+
projectIdFromRemote
|
|
17
|
+
} from "./chunk-KUA6KBBD.js";
|
|
30
18
|
import {
|
|
31
19
|
writeFileAtomic
|
|
32
|
-
} from "./chunk-
|
|
33
|
-
|
|
34
|
-
// src/storage/resolve.ts
|
|
35
|
-
import { stat as stat2 } from "fs/promises";
|
|
36
|
-
import { basename, join as join2, resolve as resolve2 } from "path";
|
|
20
|
+
} from "./chunk-PFWHHYEO.js";
|
|
37
21
|
|
|
38
22
|
// src/storage/compat.ts
|
|
39
|
-
import { copyFile, mkdir, readdir, readFile, stat } from "fs/promises";
|
|
40
|
-
import { join, resolve, sep } from "path";
|
|
23
|
+
import { copyFile, mkdir, readdir, readFile, stat } from "node:fs/promises";
|
|
24
|
+
import { join, resolve, sep } from "node:path";
|
|
41
25
|
var LEGACY_ISSUES_DIR_NAME = "issues";
|
|
42
26
|
var METADATA_FILENAME = "metadata.json";
|
|
43
27
|
async function directoryExists(path) {
|
|
@@ -192,92 +176,11 @@ async function recordUserStoryNumbering(projectRoot, decision, options = {}) {
|
|
|
192
176
|
`);
|
|
193
177
|
}
|
|
194
178
|
|
|
195
|
-
// src/storage/resolve.ts
|
|
196
|
-
var projectCache = /* @__PURE__ */ new Map();
|
|
197
|
-
var checkedIssues = /* @__PURE__ */ new Set();
|
|
198
|
-
function resetStorageResolutionCache() {
|
|
199
|
-
projectCache.clear();
|
|
200
|
-
checkedIssues.clear();
|
|
201
|
-
}
|
|
202
|
-
async function directoryExists2(path) {
|
|
203
|
-
try {
|
|
204
|
-
return (await stat2(path)).isDirectory();
|
|
205
|
-
} catch {
|
|
206
|
-
return false;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
function announceMigration(result) {
|
|
210
|
-
if (result.copied.length === 0) return;
|
|
211
|
-
const count = result.copied.length;
|
|
212
|
-
const target = join2(result.globalDir, ISSUES_DIR_NAME);
|
|
213
|
-
printInfo(
|
|
214
|
-
`Migrated ${count} file${count === 1 ? "" : "s"} from ${result.legacyDir} to ${target}`
|
|
215
|
-
);
|
|
216
|
-
printInfo(
|
|
217
|
-
`The legacy directory was not modified or removed \u2014 ${result.legacyDir} is kept as-is, read-only, for compatibility.`
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
async function resolveProject(projectRoot, options) {
|
|
221
|
-
const status = await resolveStorageMode(projectRoot, options);
|
|
222
|
-
if (status.mode === "needs-migration") {
|
|
223
|
-
announceMigration(await migrateLegacyStorage(projectRoot, options));
|
|
224
|
-
}
|
|
225
|
-
return {
|
|
226
|
-
projectId: status.projectId,
|
|
227
|
-
legacyDir: status.legacyDir
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
function getProjectResolution(projectRoot, options) {
|
|
231
|
-
const key = `${getGlobalRoot(options)}::${projectRoot}`;
|
|
232
|
-
const cached = projectCache.get(key);
|
|
233
|
-
if (cached) return cached;
|
|
234
|
-
const pending = resolveProject(projectRoot, options).catch((err) => {
|
|
235
|
-
projectCache.delete(key);
|
|
236
|
-
throw err;
|
|
237
|
-
});
|
|
238
|
-
projectCache.set(key, pending);
|
|
239
|
-
return pending;
|
|
240
|
-
}
|
|
241
|
-
async function resolveProjectPaths(options = {}) {
|
|
242
|
-
const { projectRoot: projectRootOption, ...rootOptions } = options;
|
|
243
|
-
const projectRoot = resolve2(projectRootOption ?? await getProjectRoot());
|
|
244
|
-
const project = await getProjectResolution(projectRoot, rootOptions);
|
|
245
|
-
const projectDir = getProjectDir(project.projectId, rootOptions);
|
|
246
|
-
return {
|
|
247
|
-
projectId: project.projectId,
|
|
248
|
-
projectDir,
|
|
249
|
-
issuesDir: join2(projectDir, ISSUES_DIR_NAME),
|
|
250
|
-
runLockFile: join2(projectDir, RUN_LOCK_FILENAME),
|
|
251
|
-
providersHealthFile: join2(projectDir, PROVIDERS_HEALTH_FILENAME)
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
async function resolveQueuePaths(queueId, options = {}) {
|
|
255
|
-
const { projectRoot: projectRootOption, ...rootOptions } = options;
|
|
256
|
-
const projectRoot = resolve2(projectRootOption ?? await getProjectRoot());
|
|
257
|
-
const project = await getProjectResolution(projectRoot, rootOptions);
|
|
258
|
-
return getQueuePaths(project.projectId, queueId, rootOptions);
|
|
259
|
-
}
|
|
260
|
-
async function resolveIssuePaths(issueNumber, options = {}) {
|
|
261
|
-
const { projectRoot: projectRootOption, ...rootOptions } = options;
|
|
262
|
-
const projectRoot = resolve2(projectRootOption ?? await getProjectRoot());
|
|
263
|
-
const project = await getProjectResolution(projectRoot, rootOptions);
|
|
264
|
-
const paths = getIssuePaths(project.projectId, issueNumber, rootOptions);
|
|
265
|
-
if (!checkedIssues.has(paths.issueDir)) {
|
|
266
|
-
const legacyIssueDir = join2(project.legacyDir, basename(paths.issueDir));
|
|
267
|
-
if (!await directoryExists2(paths.issueDir) && await directoryExists2(legacyIssueDir)) {
|
|
268
|
-
announceMigration(await migrateLegacyStorage(projectRoot, rootOptions));
|
|
269
|
-
}
|
|
270
|
-
checkedIssues.add(paths.issueDir);
|
|
271
|
-
}
|
|
272
|
-
bindTelemetry({ tasksPath: paths.tasksFile });
|
|
273
|
-
return paths;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
179
|
export {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
180
|
+
LEGACY_ISSUES_DIR_NAME,
|
|
181
|
+
METADATA_FILENAME,
|
|
182
|
+
resolveStorageMode,
|
|
183
|
+
migrateLegacyStorage,
|
|
184
|
+
recordUserStoryNumbering
|
|
282
185
|
};
|
|
283
|
-
//# sourceMappingURL=chunk-
|
|
186
|
+
//# sourceMappingURL=chunk-RDPK7LYK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/storage/compat.ts"],"sourcesContent":["import type { Dirent } from 'node:fs';\nimport { copyFile, mkdir, readdir, readFile, stat } from 'node:fs/promises';\nimport { join, resolve, sep } from 'node:path';\nimport { isoNow } from '../core/state-manager.js';\nimport { writeFileAtomic } from '../utils/fs.js';\nimport { getRemoteUrl, normalizeRemoteUrl } from '../utils/git.js';\nimport {\n type GetGlobalRootOptions,\n getProjectDir,\n ISSUES_DIR_NAME,\n projectIdFromRemote,\n} from './paths.js';\nimport {\n type ProjectMetadata,\n projectMetadataSchema,\n STORAGE_SCHEMA_VERSION,\n type UserStoryNumberingDecision,\n} from './schemas.js';\n\n/**\n * Coexistence between the legacy per-project layout (`<projectRoot>/issues/`)\n * and the global storage tree (`~/.issue-flow/projects/<project-id>/`).\n *\n * The single rule of this module: **the legacy directory is read-only.** Nothing\n * here removes or rewrites a byte under `<projectRoot>/issues/` — not even\n * behind an opt-in flag — so adopting the global storage can never cost a user\n * their history. Migration is a copy, and a copy that refuses to overwrite.\n */\n\n/** Directory holding the legacy per-project artifacts. */\nexport const LEGACY_ISSUES_DIR_NAME = 'issues';\n\n/** File holding the per-project metadata inside the global storage. */\nexport const METADATA_FILENAME = 'metadata.json';\n\n/**\n * - `global`: the global directory is the source of truth (it already exists,\n * or neither layout does and a fresh project starts there).\n * - `needs-migration`: only the legacy directory exists, so its content has not\n * been copied over yet.\n */\nexport type StorageMode = 'global' | 'needs-migration';\n\nexport interface StorageStatus {\n mode: StorageMode;\n /** Deterministic id, derived from {@link projectIdFromRemote}. */\n projectId: string;\n /** `<globalRoot>/projects/<projectId>`. */\n globalDir: string;\n /** `<projectRoot>/issues`. */\n legacyDir: string;\n /** Whether `globalDir` currently exists on disk. */\n globalExists: boolean;\n /** Whether `legacyDir` currently exists on disk. */\n legacyExists: boolean;\n /**\n * Normalized `origin` remote of `projectRoot`, or `null` without one.\n * Resolved once here so `migrateLegacyStorage` can reuse it instead of\n * shelling out to git a second time for `metadata.json`.\n */\n remoteUrl: string | null;\n}\n\nexport interface MigrationResult {\n projectId: string;\n globalDir: string;\n legacyDir: string;\n /** Mode observed *before* the migration ran. */\n previousMode: StorageMode;\n /** Paths copied, relative to `legacyDir`. */\n copied: string[];\n /** Paths left alone because the destination already had a file. */\n skipped: string[];\n /** Absolute path of the metadata file written by this run. */\n metadataFile: string;\n /** Metadata as persisted. */\n metadata: ProjectMetadata;\n}\n\nexport interface MigrateLegacyStorageOptions extends GetGlobalRootOptions {\n /** Timestamp source, injectable so tests can assert createdAt/updatedAt. */\n now?: () => string;\n}\n\nasync function directoryExists(path: string): Promise<boolean> {\n try {\n return (await stat(path)).isDirectory();\n } catch {\n return false;\n }\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Describe where a project's artifacts live, without touching anything.\n *\n * Read-only by construction: it stats the two candidate directories and reports\n * what it found. It never creates a directory, so a caller can ask the question\n * (a status command, a warning banner) without committing the user to the new\n * layout.\n *\n * An existing global directory always wins: once artifacts are there, that is\n * the source of truth, and a legacy directory left behind is simply preserved\n * rather than re-read or re-migrated.\n */\nexport async function resolveStorageMode(\n projectRoot: string,\n options: GetGlobalRootOptions = {},\n): Promise<StorageStatus> {\n const remoteUrl = normalizeRemoteUrl(await getRemoteUrl(projectRoot));\n const projectId = projectIdFromRemote(remoteUrl, projectRoot);\n const globalDir = getProjectDir(projectId, options);\n const legacyDir = join(resolve(projectRoot), LEGACY_ISSUES_DIR_NAME);\n\n const [globalExists, legacyExists] = await Promise.all([\n directoryExists(globalDir),\n directoryExists(legacyDir),\n ]);\n\n return {\n // Only one state calls for work: legacy content that has nowhere to be read\n // from yet. Everything else — including \"neither exists\" — is already the\n // global layout.\n mode: legacyExists && !globalExists ? 'needs-migration' : 'global',\n projectId,\n globalDir,\n legacyDir,\n globalExists,\n legacyExists,\n remoteUrl,\n };\n}\n\n/**\n * Wrap an IO failure with the issue and file it happened on, so a partial\n * migration is diagnosable instead of a bare `EACCES`.\n */\nfunction migrationFailure(issue: string, relativePath: string, err: unknown): Error {\n const reason = err instanceof Error ? err.message : String(err);\n\n return new Error(\n `Failed to migrate '${relativePath}' (issue '${issue}'): ${reason}. ` +\n 'The legacy directory was left untouched — fix the cause and run the migration again.',\n );\n}\n\n/** First path segment of a relative path — the issue a file belongs to. */\nfunction issueOf(relativePath: string): string {\n return relativePath.split(sep)[0] || '.';\n}\n\n/**\n * Copy one directory level, recursing into subdirectories.\n *\n * Symlinks and other non-regular entries are skipped on purpose: following them\n * could copy content from outside the legacy directory into the global tree.\n */\nasync function copyTree(\n sourceRoot: string,\n targetRoot: string,\n relativeDir: string,\n result: { copied: string[]; skipped: string[] },\n): Promise<void> {\n const source = join(sourceRoot, relativeDir);\n const target = join(targetRoot, relativeDir);\n\n let entries: Dirent[];\n try {\n entries = await readdir(source, { withFileTypes: true });\n } catch (err) {\n throw migrationFailure(issueOf(relativeDir), relativeDir || '.', err);\n }\n\n try {\n // recursive: true also makes re-running a no-op on an existing directory.\n await mkdir(target, { recursive: true });\n } catch (err) {\n throw migrationFailure(issueOf(relativeDir), relativeDir || '.', err);\n }\n\n for (const entry of entries) {\n const relativePath = join(relativeDir, entry.name);\n\n if (entry.isDirectory()) {\n await copyTree(sourceRoot, targetRoot, relativePath, result);\n continue;\n }\n if (!entry.isFile()) {\n continue;\n }\n\n const to = join(targetRoot, relativePath);\n try {\n // Idempotency and safety in one check: a destination that already exists\n // is never overwritten, so a second run copies nothing and a hand-edited\n // artifact in the global tree survives.\n if (await pathExists(to)) {\n result.skipped.push(relativePath);\n continue;\n }\n await copyFile(join(sourceRoot, relativePath), to);\n result.copied.push(relativePath);\n } catch (err) {\n throw migrationFailure(issueOf(relativePath), relativePath, err);\n }\n }\n}\n\n/**\n * Read `metadata.json`, tolerating every failure.\n *\n * A missing, corrupt or schema-invalid file must not block a migration: the\n * caller simply writes a fresh one. The only thing worth recovering is\n * `createdAt`/`lastAttemptAt` from a valid previous file.\n */\nasync function readExistingMetadata(file: string): Promise<ProjectMetadata | null> {\n let raw: string;\n try {\n raw = await readFile(file, 'utf-8');\n } catch {\n return null;\n }\n\n try {\n const parsed = projectMetadataSchema.safeParse(JSON.parse(raw));\n return parsed.success ? parsed.data : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Copy `<projectRoot>/issues/` into the project's global directory and stamp\n * its `metadata.json`.\n *\n * Non-destructive and idempotent, by design rather than by convention:\n *\n * - the source is only ever read — there is no removal option in this release;\n * - a destination file that already exists is skipped, never overwritten, so a\n * second run reports everything as skipped and changes nothing but\n * `updatedAt`;\n * - a failure mid-way leaves the legacy directory intact and names the issue\n * and file that failed, so the run can be repeated after the fix and will\n * resume by skipping what already made it across.\n *\n * Called on a project with no legacy directory it is still useful: it creates\n * the project directory and its metadata.\n */\nexport async function migrateLegacyStorage(\n projectRoot: string,\n options: MigrateLegacyStorageOptions = {},\n): Promise<MigrationResult> {\n const status = await resolveStorageMode(projectRoot, { env: options.env });\n const result = { copied: [] as string[], skipped: [] as string[] };\n\n try {\n await mkdir(status.globalDir, { recursive: true });\n } catch (err) {\n throw migrationFailure('.', status.globalDir, err);\n }\n\n if (status.legacyExists) {\n await copyTree(status.legacyDir, join(status.globalDir, ISSUES_DIR_NAME), '', result);\n }\n\n const now = (options.now ?? isoNow)();\n const metadataFile = join(status.globalDir, METADATA_FILENAME);\n const existing = await readExistingMetadata(metadataFile);\n\n const metadata: ProjectMetadata = {\n schemaVersion: STORAGE_SCHEMA_VERSION,\n projectId: status.projectId,\n root: resolve(projectRoot),\n remoteUrl: status.remoteUrl,\n // The project was first seen whenever it was first written, not now.\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n lastAttemptAt: existing?.lastAttemptAt ?? null,\n };\n\n await writeFileAtomic(metadataFile, `${JSON.stringify(metadata, null, 2)}\\n`);\n\n return {\n projectId: status.projectId,\n globalDir: status.globalDir,\n legacyDir: status.legacyDir,\n previousMode: status.mode,\n ...result,\n metadataFile,\n metadata,\n };\n}\n\nexport interface RecordUserStoryNumberingOptions extends GetGlobalRootOptions {\n /** Timestamp source, injectable so tests can assert `updatedAt`. */\n now?: () => string;\n}\n\n/**\n * Persist a `plan` run's User Story numbering decision into the project's\n * `metadata.json`, for audit (issue #36) — this is a read-modify-write on the\n * same file {@link migrateLegacyStorage} stamps, never a second file.\n *\n * The decision itself is never read back to resolve a *later* one: the next\n * `plan` run always re-scans `tasks.json` from scratch (see\n * `storage/user-story-numbering.ts`). Losing this field only costs an audit\n * trail entry, never correctness.\n *\n * A missing `metadata.json` (a project whose first command ever is a numbered\n * `plan`, with no legacy directory to trigger a migration) is created here\n * from scratch, exactly like {@link migrateLegacyStorage} would.\n */\nexport async function recordUserStoryNumbering(\n projectRoot: string,\n decision: UserStoryNumberingDecision,\n options: RecordUserStoryNumberingOptions = {},\n): Promise<void> {\n const status = await resolveStorageMode(projectRoot, { env: options.env });\n const metadataFile = join(status.globalDir, METADATA_FILENAME);\n const existing = await readExistingMetadata(metadataFile);\n const now = (options.now ?? isoNow)();\n\n const metadata: ProjectMetadata = {\n schemaVersion: STORAGE_SCHEMA_VERSION,\n projectId: status.projectId,\n root: resolve(projectRoot),\n remoteUrl: status.remoteUrl,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n lastAttemptAt: existing?.lastAttemptAt ?? null,\n userStoryNumbering: decision,\n };\n\n await mkdir(status.globalDir, { recursive: true });\n await writeFileAtomic(metadataFile, `${JSON.stringify(metadata, null, 2)}\\n`);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -4,21 +4,21 @@ import {
|
|
|
4
4
|
hasExplicitAgentSelection,
|
|
5
5
|
loadAgentConfig,
|
|
6
6
|
loadRoutingConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YC24E66P.js";
|
|
8
8
|
import {
|
|
9
9
|
printError,
|
|
10
10
|
printInfo,
|
|
11
11
|
printSuccess,
|
|
12
12
|
printWarning
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-DBLXLKGU.js";
|
|
14
14
|
import {
|
|
15
15
|
AGENT_PHASES
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-44RF3VFG.js";
|
|
17
17
|
|
|
18
18
|
// src/commands/init.ts
|
|
19
|
-
import { readFile } from "fs/promises";
|
|
20
|
-
import { homedir } from "os";
|
|
21
|
-
import { join } from "path";
|
|
19
|
+
import { readFile } from "node:fs/promises";
|
|
20
|
+
import { homedir } from "node:os";
|
|
21
|
+
import { join } from "node:path";
|
|
22
22
|
import { execa } from "execa";
|
|
23
23
|
async function checkClaude() {
|
|
24
24
|
try {
|
|
@@ -194,6 +194,7 @@ async function runInit(source = "github", options = {}) {
|
|
|
194
194
|
const json = options.json === true;
|
|
195
195
|
const compact = options.compact === true;
|
|
196
196
|
if (!json && !compact) {
|
|
197
|
+
printExperimentalNotice();
|
|
197
198
|
printInfo("Checking prerequisites...\n");
|
|
198
199
|
}
|
|
199
200
|
const agent = await loadAgentConfig();
|
|
@@ -240,7 +241,7 @@ async function runInit(source = "github", options = {}) {
|
|
|
240
241
|
}
|
|
241
242
|
let plan;
|
|
242
243
|
try {
|
|
243
|
-
const { planRepositoryScaffold } = await import("./apply-
|
|
244
|
+
const { planRepositoryScaffold } = await import("./apply-QDYNQMUX.js");
|
|
244
245
|
plan = await planRepositoryScaffold({ scope: options.scope ?? null });
|
|
245
246
|
} catch (err) {
|
|
246
247
|
if (json) {
|
|
@@ -260,7 +261,7 @@ async function runInit(source = "github", options = {}) {
|
|
|
260
261
|
}
|
|
261
262
|
let applied = null;
|
|
262
263
|
if (options.apply === true) {
|
|
263
|
-
const { applyScaffoldPlan } = await import("./apply-
|
|
264
|
+
const { applyScaffoldPlan } = await import("./apply-QDYNQMUX.js");
|
|
264
265
|
applied = await applyScaffoldPlan(plan);
|
|
265
266
|
}
|
|
266
267
|
if (json) {
|
|
@@ -312,9 +313,9 @@ async function runInit(source = "github", options = {}) {
|
|
|
312
313
|
await maybeOfferAgentChoice(options, agent);
|
|
313
314
|
if (!json) {
|
|
314
315
|
try {
|
|
315
|
-
const { resolveContract } = await import("./contract-
|
|
316
|
-
const { getProjectRoot } = await import("./git-
|
|
317
|
-
const { loadVerifyConfig } = await import("./config-
|
|
316
|
+
const { resolveContract } = await import("./contract-HWLFFL3F.js");
|
|
317
|
+
const { getProjectRoot } = await import("./git-XGOECXWG.js");
|
|
318
|
+
const { loadVerifyConfig } = await import("./config-6YTWPDBK.js");
|
|
318
319
|
const cwd = await getProjectRoot();
|
|
319
320
|
const verify = await loadVerifyConfig({ projectRoot: cwd });
|
|
320
321
|
const contract = await resolveContract({ cwd, declared: verify.contract });
|
|
@@ -328,6 +329,21 @@ async function runInit(source = "github", options = {}) {
|
|
|
328
329
|
}
|
|
329
330
|
return allPassed ? 0 : 1;
|
|
330
331
|
}
|
|
332
|
+
function printExperimentalNotice() {
|
|
333
|
+
printWarning(
|
|
334
|
+
"Issue Flow is experimental and under active development, built mostly with AI coding agents and not audited."
|
|
335
|
+
);
|
|
336
|
+
for (const line of [
|
|
337
|
+
"Expect bugs, incomplete implementations, regressions and possibly undiscovered security flaws.",
|
|
338
|
+
"Not recommended for real projects, production environments, critical systems or repositories",
|
|
339
|
+
"with sensitive information. Keep backups, use a dedicated branch and review every change it makes.",
|
|
340
|
+
"Token consumption is not optimized yet: a run may use significantly more tokens than necessary.",
|
|
341
|
+
"https://github.com/fabioassuncao/issue-flow/blob/main/docs/project-status.md"
|
|
342
|
+
]) {
|
|
343
|
+
console.log(` ${line}`);
|
|
344
|
+
}
|
|
345
|
+
console.log("");
|
|
346
|
+
}
|
|
331
347
|
var ESCALATING_CODEX_KEYS = ["approvals_reviewer", "sandbox_mode", "sandbox_workspace_write"];
|
|
332
348
|
async function warnEscalatingCodexConfig() {
|
|
333
349
|
const configPath = join(homedir(), ".codex", "config.toml");
|
|
@@ -356,7 +372,7 @@ async function maybeOfferAgentChoice(options, agent) {
|
|
|
356
372
|
if (!shouldOfferAgentPrompt(hasExplicitAgentSelection(agent, getAgentCliOverrides()), routing.mode)) {
|
|
357
373
|
return;
|
|
358
374
|
}
|
|
359
|
-
const { createInterface } = await import("readline");
|
|
375
|
+
const { createInterface } = await import("node:readline");
|
|
360
376
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
361
377
|
const answer = await new Promise((resolve) => {
|
|
362
378
|
rl.question("Agent [claude/codex] (default claude): ", resolve);
|
|
@@ -365,7 +381,7 @@ async function maybeOfferAgentChoice(options, agent) {
|
|
|
365
381
|
const trimmed = answer.trim().toLowerCase();
|
|
366
382
|
const chosen = trimmed === "codex" ? "codex" : "claude";
|
|
367
383
|
if (options.apply === true) {
|
|
368
|
-
const { persistFirstAgentChoice } = await import("./agent-
|
|
384
|
+
const { persistFirstAgentChoice } = await import("./agent-4DHRKZ2Z.js");
|
|
369
385
|
const path = await persistFirstAgentChoice(chosen);
|
|
370
386
|
printSuccess(`Saved agent '${chosen}' to ${path}`);
|
|
371
387
|
return;
|
|
@@ -380,4 +396,4 @@ export {
|
|
|
380
396
|
runInit,
|
|
381
397
|
shouldOfferAgentPrompt
|
|
382
398
|
};
|
|
383
|
-
//# sourceMappingURL=chunk-
|
|
399
|
+
//# sourceMappingURL=chunk-RMIBLFG3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/init.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { execa } from 'execa';\nimport { hasExplicitAgentSelection } from '../agents/resolve.js';\nimport { AGENT_PHASES } from '../agents/types.js';\nimport { getAgentCliOverrides, loadAgentConfig, loadRoutingConfig } from '../config.js';\nimport type { IssueSource } from '../issues/types.js';\nimport type { ScaffoldActionKind, ScaffoldPlan } from '../scaffold/plan.js';\nimport { printError, printInfo, printSuccess, printWarning } from '../ui/logger.js';\n\n/** Stable identifier of a check, used to decide whether it blocks. */\ntype CheckKey = 'claude' | 'codex' | 'gh' | 'git';\n\ninterface CheckResult {\n key: CheckKey;\n name: string;\n passed: boolean;\n detail: string;\n hint?: string;\n}\n\nasync function checkClaude(): Promise<CheckResult> {\n try {\n const proc = await execa('claude', ['--version'], { reject: false, timeout: 10_000 });\n if (proc.exitCode === 0) {\n const version = proc.stdout?.toString().trim() ?? 'unknown';\n return { key: 'claude', name: 'claude CLI', passed: true, detail: version };\n }\n return {\n key: 'claude',\n name: 'claude CLI',\n passed: false,\n detail: 'claude command failed',\n hint: 'Install Claude Code: https://docs.anthropic.com/en/docs/claude-code',\n };\n } catch {\n return {\n key: 'claude',\n name: 'claude CLI',\n passed: false,\n detail: 'claude not found',\n hint: 'Install Claude Code: https://docs.anthropic.com/en/docs/claude-code',\n };\n }\n}\n\nasync function checkGh(): Promise<CheckResult> {\n try {\n const proc = await execa('gh', ['--version'], { reject: false, timeout: 10_000 });\n if (proc.exitCode !== 0) {\n return {\n key: 'gh',\n name: 'gh CLI',\n passed: false,\n detail: 'gh command failed',\n hint: 'Install GitHub CLI: https://cli.github.com/',\n };\n }\n const version = proc.stdout?.toString().split('\\n')[0]?.trim() ?? 'unknown';\n\n // Check auth status\n const auth = await execa('gh', ['auth', 'status'], { reject: false, timeout: 10_000 });\n if (auth.exitCode !== 0) {\n return {\n key: 'gh',\n name: 'gh CLI',\n passed: false,\n detail: `${version} (not authenticated)`,\n hint: 'Run: gh auth login',\n };\n }\n return { key: 'gh', name: 'gh CLI', passed: true, detail: `${version} (authenticated)` };\n } catch {\n return {\n key: 'gh',\n name: 'gh CLI',\n passed: false,\n detail: 'gh not found',\n hint: 'Install GitHub CLI: https://cli.github.com/',\n };\n }\n}\n\nasync function checkCodex(): Promise<CheckResult> {\n try {\n const proc = await execa('codex', ['--version'], { reject: false, timeout: 10_000 });\n if (proc.exitCode !== 0) {\n return {\n key: 'codex',\n name: 'codex CLI',\n passed: false,\n detail: 'codex command failed',\n hint: 'Install Codex CLI: https://developers.openai.com/codex/noninteractive',\n };\n }\n const version = proc.stdout?.toString().trim() ?? 'unknown';\n const auth = await execa('codex', ['login', 'status'], { reject: false, timeout: 10_000 });\n if (auth.exitCode !== 0) {\n return {\n key: 'codex',\n name: 'codex CLI',\n passed: false,\n detail: `${version} (not authenticated)`,\n hint: 'Run: codex login --with-api-key (or set CODEX_API_KEY)',\n };\n }\n return { key: 'codex', name: 'codex CLI', passed: true, detail: `${version} (authenticated)` };\n } catch {\n return {\n key: 'codex',\n name: 'codex CLI',\n passed: false,\n detail: 'codex not found',\n hint: 'Install Codex CLI: https://developers.openai.com/codex/noninteractive',\n };\n }\n}\n\nasync function checkGit(): Promise<CheckResult> {\n try {\n const proc = await execa('git', ['--version'], { reject: false, timeout: 10_000 });\n if (proc.exitCode !== 0) {\n return {\n key: 'git',\n name: 'git',\n passed: false,\n detail: 'git command failed',\n hint: 'Install git: https://git-scm.com/',\n };\n }\n const version = proc.stdout?.toString().trim() ?? 'unknown';\n\n // Check if current directory is a git repo\n const repo = await execa('git', ['rev-parse', '--is-inside-work-tree'], {\n reject: false,\n timeout: 5_000,\n });\n if (repo.exitCode !== 0) {\n return {\n key: 'git',\n name: 'git',\n passed: false,\n detail: `${version} (not a git repository)`,\n hint: 'Run this command inside a git repository',\n };\n }\n return { key: 'git', name: 'git', passed: true, detail: `${version} (inside repo)` };\n } catch {\n return {\n key: 'git',\n name: 'git',\n passed: false,\n detail: 'git not found',\n hint: 'Install git: https://git-scm.com/',\n };\n }\n}\n\nexport interface InitOptions {\n /** Write the missing files instead of only reporting them. */\n apply?: boolean;\n /** Emit the plan as JSON — the bridge the initialization skill reads. */\n json?: boolean;\n /** Subdirectory the conventions apply to, in a monorepo. */\n scope?: string;\n /** Skip the convention report entirely and only check prerequisites. */\n checkOnly?: boolean;\n /** Skip the first-run agent choice. */\n noAgentPrompt?: boolean;\n /**\n * One-line preflight for `issue-flow run` in clean mode. `issue-flow init`\n * itself never passes this — its product is the full report.\n */\n compact?: boolean;\n}\n\nconst ACTION_ICON: Record<ScaffoldActionKind, string> = {\n create: '+',\n keep: '=',\n review: '!',\n};\n\n/**\n * One-line preflight for the clean terminal. The full report stays on\n * `issue-flow init` and on `--verbose`.\n */\nexport function summarizePreflight(\n results: ReadonlyArray<{ passed: boolean }>,\n plan: { actions: ReadonlyArray<{ kind: string }> },\n): string {\n const kept = plan.actions.filter((action) => action.kind === 'keep').length;\n const creates = plan.actions.filter((action) => action.kind === 'create').length;\n const env = results.every((result) => result.passed) ? 'environment ok' : 'environment failed';\n const createBit = creates === 0 ? 'nothing to create' : `${creates} to create`;\n return `Preflight: ${env} · ${kept} conventions kept · ${createBit}`;\n}\n\n/**\n * Render the plan for a human.\n *\n * `keep` lines are printed, not hidden: the most valuable thing this report\n * says is usually *what it is not going to touch*, and a list of only the\n * missing files would read as if the repository had nothing.\n */\nfunction renderPlan(plan: ScaffoldPlan, apply: boolean): void {\n const creates = plan.actions.filter((a) => a.kind === 'create');\n const reviews = plan.actions.filter((a) => a.kind === 'review');\n\n console.log('');\n printInfo(`Repository conventions (${plan.root})\\n`);\n\n for (const item of plan.actions) {\n console.log(` ${ACTION_ICON[item.kind]} ${item.path}`);\n console.log(` ${item.reason}`);\n }\n\n if (plan.notes.length > 0) {\n console.log('');\n for (const note of plan.notes) {\n printWarning(note);\n }\n }\n\n console.log('');\n if (creates.length === 0 && reviews.length === 0) {\n printSuccess('This repository already declares everything Issue Flow would add.');\n return;\n }\n if (creates.length === 0) {\n printSuccess('Nothing to create.');\n return;\n }\n if (!apply) {\n printInfo(`${creates.length} file(s) would be created. Re-run with --apply to write them.`);\n }\n}\n\n/**\n * Verify the prerequisites of the pipeline and report the repository's\n * conventions.\n *\n * `source` is the Issue origin the run is headed for. `gh` only blocks when\n * that origin is GitHub: no other origin shells out to it, so a missing or\n * unauthenticated gh is reported as a warning instead of failing the\n * environment. `claude` and `git` stay blocking for every origin, and the\n * default ('github') keeps the previous behaviour byte for byte.\n *\n * The convention report is additive: the prerequisite checks run first and still\n * decide the exit code, so an existing script calling `issue-flow init` sees the\n * same pass/fail it always did. Nothing is written without `--apply`.\n */\nexport async function runInit(\n source: IssueSource = 'github',\n options: InitOptions = {},\n): Promise<number> {\n const json = options.json === true;\n const compact = options.compact === true;\n\n if (!json && !compact) {\n printExperimentalNotice();\n printInfo('Checking prerequisites...\\n');\n }\n\n const agent = await loadAgentConfig();\n const usesCodex =\n agent.provider === 'codex' ||\n AGENT_PHASES.some((phase) => agent.phases[phase]?.provider === 'codex');\n\n const checks = [checkClaude(), checkGh(), checkGit()];\n if (usesCodex) checks.push(checkCodex());\n const results = await Promise.all(checks);\n const isBlocking = (r: CheckResult): boolean => {\n if (r.key === 'gh') return source === 'github';\n if (r.key === 'codex') return usesCodex;\n if (r.key === 'claude') return agent.provider === 'claude' || !usesCodex;\n return true;\n };\n\n if (!json && (!compact || !results.every((r) => r.passed || !isBlocking(r)))) {\n for (const r of results) {\n if (r.passed) {\n if (!compact) printSuccess(`${r.name}: ${r.detail}`);\n } else if (isBlocking(r)) {\n printError(`${r.name}: ${r.detail}`);\n if (r.hint) {\n console.log(` ${r.hint}`);\n }\n } else if (!compact) {\n printWarning(`${r.name}: ${r.detail} (not required for ${source} issues)`);\n }\n }\n }\n\n const allPassed = results.filter(isBlocking).every((r) => r.passed);\n\n if (!json && !compact) {\n console.log('');\n if (allPassed) {\n printSuccess('All prerequisites met. Ready to run the pipeline.');\n } else {\n printError('Some prerequisites are missing. Please fix the issues above.');\n }\n } else if (!json && compact && !allPassed) {\n printError('Prerequisites not met. Fix the issues above and try again.');\n }\n\n if (usesCodex) {\n await warnEscalatingCodexConfig();\n }\n\n if (options.checkOnly === true) {\n return allPassed ? 0 : 1;\n }\n\n // The conventions half. It never changes the exit code: a repository missing\n // a template is not a broken environment, and failing here would break every\n // script that treats `init` as a prerequisite gate.\n let plan: ScaffoldPlan;\n try {\n const { planRepositoryScaffold } = await import('../scaffold/apply.js');\n plan = await planRepositoryScaffold({ scope: options.scope ?? null });\n } catch (err) {\n if (json) {\n console.log(\n JSON.stringify(\n { schemaVersion: 1, error: err instanceof Error ? err.message : String(err) },\n null,\n 2,\n ),\n );\n return allPassed ? 0 : 1;\n }\n printWarning(\n `Could not inspect the repository conventions: ${err instanceof Error ? err.message : String(err)}`,\n );\n return allPassed ? 0 : 1;\n }\n\n let applied: { written: string[]; skipped: string[] } | null = null;\n if (options.apply === true) {\n const { applyScaffoldPlan } = await import('../scaffold/apply.js');\n applied = await applyScaffoldPlan(plan);\n }\n\n if (json) {\n console.log(\n JSON.stringify(\n {\n schemaVersion: 1,\n prerequisites: results.map((r) => ({\n key: r.key,\n passed: r.passed,\n detail: r.detail,\n blocking: isBlocking(r),\n })),\n root: plan.root,\n // Content is omitted: a skill decides from the actions, and the bodies\n // would make the payload unreadable for no gain.\n actions: plan.actions.map(({ path, kind, tier, reason }) => ({\n path,\n kind,\n tier,\n reason,\n })),\n notes: plan.notes,\n applied,\n },\n null,\n 2,\n ),\n );\n return allPassed ? 0 : 1;\n }\n\n if (compact) {\n printInfo(summarizePreflight(results, plan));\n } else {\n renderPlan(plan, options.apply === true);\n }\n\n if (applied !== null) {\n console.log('');\n for (const path of applied.written) {\n printSuccess(`Created ${path}`);\n }\n for (const path of applied.skipped) {\n printWarning(`Skipped ${path}: it already exists.`);\n }\n if (applied.written.length === 0) {\n printInfo('Nothing was written — the repository already had everything.');\n }\n }\n\n await maybeOfferAgentChoice(options, agent);\n\n if (!json) {\n try {\n const { resolveContract } = await import('../verify/contract.js');\n const { getProjectRoot } = await import('../utils/git.js');\n const { loadVerifyConfig } = await import('../config.js');\n const cwd = await getProjectRoot();\n const verify = await loadVerifyConfig({ projectRoot: cwd });\n const contract = await resolveContract({ cwd, declared: verify.contract });\n if (contract.source === 'empty') {\n printWarning(\n 'No acceptance contract declared or discovered — runs will finish unverified.',\n );\n }\n } catch {\n // Observational: init still reports prerequisites if discovery fails.\n }\n }\n\n return allPassed ? 0 : 1;\n}\n\n/**\n * `init` is the first command a new user runs, so it is where the maturity of\n * the project is stated. The full notice lives in `docs/project-status.md`; this\n * is the short form, printed only on the human path — `--json` is consumed by\n * tooling and `--compact` is the preflight inside `run`.\n */\nfunction printExperimentalNotice(): void {\n printWarning(\n 'Issue Flow is experimental and under active development, built mostly with AI coding agents and not audited.',\n );\n for (const line of [\n 'Expect bugs, incomplete implementations, regressions and possibly undiscovered security flaws.',\n 'Not recommended for real projects, production environments, critical systems or repositories',\n 'with sensitive information. Keep backups, use a dedicated branch and review every change it makes.',\n 'Token consumption is not optimized yet: a run may use significantly more tokens than necessary.',\n 'https://github.com/fabioassuncao/issue-flow/blob/main/docs/project-status.md',\n ]) {\n console.log(` ${line}`);\n }\n console.log('');\n}\n\nconst ESCALATING_CODEX_KEYS = ['approvals_reviewer', 'sandbox_mode', 'sandbox_workspace_write'];\n\nasync function warnEscalatingCodexConfig(): Promise<void> {\n const configPath = join(homedir(), '.codex', 'config.toml');\n try {\n const raw = await readFile(configPath, 'utf-8');\n const hits = ESCALATING_CODEX_KEYS.filter((key) => raw.includes(key));\n if (hits.length === 0) return;\n printWarning(\n `$CODEX_HOME/config.toml contains ${hits.join(', ')}, which can escalate --sandbox. Set agent.codex.ignoreUserConfig: true for reproducible runs (recommended in CI). Claude's equivalent is --setting-sources project (agent.claude.ignoreUserConfig).`,\n );\n } catch {\n // Absence is the common case.\n }\n}\n\nfunction isInteractiveInit(): boolean {\n const ci = process.env.CI;\n const inCi = ci !== undefined && ci !== '' && ci !== '0' && ci.toLowerCase() !== 'false';\n return Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY) && !inCi;\n}\n\n/**\n * An active router owns the per-phase harness choice, so asking for one agent\n * at startup would immediately contradict the resolved configuration.\n */\nexport function shouldOfferAgentPrompt(\n hasExplicitSelection: boolean,\n routingMode: string,\n): boolean {\n return !hasExplicitSelection && routingMode !== 'active';\n}\n\nasync function maybeOfferAgentChoice(\n options: InitOptions,\n agent: Awaited<ReturnType<typeof loadAgentConfig>>,\n): Promise<void> {\n if (options.json === true || options.noAgentPrompt === true) return;\n if (!isInteractiveInit()) return;\n const routing = await loadRoutingConfig();\n if (\n !shouldOfferAgentPrompt(hasExplicitAgentSelection(agent, getAgentCliOverrides()), routing.mode)\n ) {\n return;\n }\n\n const { createInterface } = await import('node:readline');\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) => {\n rl.question('Agent [claude/codex] (default claude): ', resolve);\n });\n rl.close();\n const trimmed = answer.trim().toLowerCase();\n const chosen = trimmed === 'codex' ? 'codex' : 'claude';\n\n if (options.apply === true) {\n const { persistFirstAgentChoice } = await import('./agent.js');\n const path = await persistFirstAgentChoice(chosen);\n printSuccess(`Saved agent '${chosen}' to ${path}`);\n return;\n }\n printInfo(\n `Using ${chosen} for this check. Persist with: issue-flow agent use ${chosen} --global`,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA,SAAS,gBAAgB;AACzB,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,aAAa;AAmBtB,eAAe,cAAoC;AACjD,MAAI;AACF,UAAM,OAAO,MAAM,MAAM,UAAU,CAAC,WAAW,GAAG,EAAE,QAAQ,OAAO,SAAS,IAAO,CAAC;AACpF,QAAI,KAAK,aAAa,GAAG;AACvB,YAAM,UAAU,KAAK,QAAQ,SAAS,EAAE,KAAK,KAAK;AAClD,aAAO,EAAE,KAAK,UAAU,MAAM,cAAc,QAAQ,MAAM,QAAQ,QAAQ;AAAA,IAC5E;AACA,WAAO;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,MAAM;AAAA,IACR;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,eAAe,UAAgC;AAC7C,MAAI;AACF,UAAM,OAAO,MAAM,MAAM,MAAM,CAAC,WAAW,GAAG,EAAE,QAAQ,OAAO,SAAS,IAAO,CAAC;AAChF,QAAI,KAAK,aAAa,GAAG;AACvB,aAAO;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,IACF;AACA,UAAM,UAAU,KAAK,QAAQ,SAAS,EAAE,MAAM,IAAI,EAAE,CAAC,GAAG,KAAK,KAAK;AAGlE,UAAM,OAAO,MAAM,MAAM,MAAM,CAAC,QAAQ,QAAQ,GAAG,EAAE,QAAQ,OAAO,SAAS,IAAO,CAAC;AACrF,QAAI,KAAK,aAAa,GAAG;AACvB,aAAO;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,QAAQ,GAAG,OAAO;AAAA,QAClB,MAAM;AAAA,MACR;AAAA,IACF;AACA,WAAO,EAAE,KAAK,MAAM,MAAM,UAAU,QAAQ,MAAM,QAAQ,GAAG,OAAO,mBAAmB;AAAA,EACzF,QAAQ;AACN,WAAO;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,eAAe,aAAmC;AAChD,MAAI;AACF,UAAM,OAAO,MAAM,MAAM,SAAS,CAAC,WAAW,GAAG,EAAE,QAAQ,OAAO,SAAS,IAAO,CAAC;AACnF,QAAI,KAAK,aAAa,GAAG;AACvB,aAAO;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,IACF;AACA,UAAM,UAAU,KAAK,QAAQ,SAAS,EAAE,KAAK,KAAK;AAClD,UAAM,OAAO,MAAM,MAAM,SAAS,CAAC,SAAS,QAAQ,GAAG,EAAE,QAAQ,OAAO,SAAS,IAAO,CAAC;AACzF,QAAI,KAAK,aAAa,GAAG;AACvB,aAAO;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,QAAQ,GAAG,OAAO;AAAA,QAClB,MAAM;AAAA,MACR;AAAA,IACF;AACA,WAAO,EAAE,KAAK,SAAS,MAAM,aAAa,QAAQ,MAAM,QAAQ,GAAG,OAAO,mBAAmB;AAAA,EAC/F,QAAQ;AACN,WAAO;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,eAAe,WAAiC;AAC9C,MAAI;AACF,UAAM,OAAO,MAAM,MAAM,OAAO,CAAC,WAAW,GAAG,EAAE,QAAQ,OAAO,SAAS,IAAO,CAAC;AACjF,QAAI,KAAK,aAAa,GAAG;AACvB,aAAO;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,IACF;AACA,UAAM,UAAU,KAAK,QAAQ,SAAS,EAAE,KAAK,KAAK;AAGlD,UAAM,OAAO,MAAM,MAAM,OAAO,CAAC,aAAa,uBAAuB,GAAG;AAAA,MACtE,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AACD,QAAI,KAAK,aAAa,GAAG;AACvB,aAAO;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,QAAQ,GAAG,OAAO;AAAA,QAClB,MAAM;AAAA,MACR;AAAA,IACF;AACA,WAAO,EAAE,KAAK,OAAO,MAAM,OAAO,QAAQ,MAAM,QAAQ,GAAG,OAAO,iBAAiB;AAAA,EACrF,QAAQ;AACN,WAAO;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAoBA,IAAM,cAAkD;AAAA,EACtD,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AACV;AAMO,SAAS,mBACd,SACA,MACQ;AACR,QAAM,OAAO,KAAK,QAAQ,OAAO,CAAC,WAAW,OAAO,SAAS,MAAM,EAAE;AACrE,QAAM,UAAU,KAAK,QAAQ,OAAO,CAAC,WAAW,OAAO,SAAS,QAAQ,EAAE;AAC1E,QAAM,MAAM,QAAQ,MAAM,CAAC,WAAW,OAAO,MAAM,IAAI,mBAAmB;AAC1E,QAAM,YAAY,YAAY,IAAI,sBAAsB,GAAG,OAAO;AAClE,SAAO,cAAc,GAAG,SAAM,IAAI,0BAAuB,SAAS;AACpE;AASA,SAAS,WAAW,MAAoB,OAAsB;AAC5D,QAAM,UAAU,KAAK,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ;AAC9D,QAAM,UAAU,KAAK,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ;AAE9D,UAAQ,IAAI,EAAE;AACd,YAAU,2BAA2B,KAAK,IAAI;AAAA,CAAK;AAEnD,aAAW,QAAQ,KAAK,SAAS;AAC/B,YAAQ,IAAI,KAAK,YAAY,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;AACtD,YAAQ,IAAI,SAAS,KAAK,MAAM,EAAE;AAAA,EACpC;AAEA,MAAI,KAAK,MAAM,SAAS,GAAG;AACzB,YAAQ,IAAI,EAAE;AACd,eAAW,QAAQ,KAAK,OAAO;AAC7B,mBAAa,IAAI;AAAA,IACnB;AAAA,EACF;AAEA,UAAQ,IAAI,EAAE;AACd,MAAI,QAAQ,WAAW,KAAK,QAAQ,WAAW,GAAG;AAChD,iBAAa,mEAAmE;AAChF;AAAA,EACF;AACA,MAAI,QAAQ,WAAW,GAAG;AACxB,iBAAa,oBAAoB;AACjC;AAAA,EACF;AACA,MAAI,CAAC,OAAO;AACV,cAAU,GAAG,QAAQ,MAAM,+DAA+D;AAAA,EAC5F;AACF;AAgBA,eAAsB,QACpB,SAAsB,UACtB,UAAuB,CAAC,GACP;AACjB,QAAM,OAAO,QAAQ,SAAS;AAC9B,QAAM,UAAU,QAAQ,YAAY;AAEpC,MAAI,CAAC,QAAQ,CAAC,SAAS;AACrB,4BAAwB;AACxB,cAAU,6BAA6B;AAAA,EACzC;AAEA,QAAM,QAAQ,MAAM,gBAAgB;AACpC,QAAM,YACJ,MAAM,aAAa,WACnB,aAAa,KAAK,CAAC,UAAU,MAAM,OAAO,KAAK,GAAG,aAAa,OAAO;AAExE,QAAM,SAAS,CAAC,YAAY,GAAG,QAAQ,GAAG,SAAS,CAAC;AACpD,MAAI,UAAW,QAAO,KAAK,WAAW,CAAC;AACvC,QAAM,UAAU,MAAM,QAAQ,IAAI,MAAM;AACxC,QAAM,aAAa,CAAC,MAA4B;AAC9C,QAAI,EAAE,QAAQ,KAAM,QAAO,WAAW;AACtC,QAAI,EAAE,QAAQ,QAAS,QAAO;AAC9B,QAAI,EAAE,QAAQ,SAAU,QAAO,MAAM,aAAa,YAAY,CAAC;AAC/D,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,SAAS,CAAC,WAAW,CAAC,QAAQ,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC,IAAI;AAC5E,eAAW,KAAK,SAAS;AACvB,UAAI,EAAE,QAAQ;AACZ,YAAI,CAAC,QAAS,cAAa,GAAG,EAAE,IAAI,KAAK,EAAE,MAAM,EAAE;AAAA,MACrD,WAAW,WAAW,CAAC,GAAG;AACxB,mBAAW,GAAG,EAAE,IAAI,KAAK,EAAE,MAAM,EAAE;AACnC,YAAI,EAAE,MAAM;AACV,kBAAQ,IAAI,OAAO,EAAE,IAAI,EAAE;AAAA,QAC7B;AAAA,MACF,WAAW,CAAC,SAAS;AACnB,qBAAa,GAAG,EAAE,IAAI,KAAK,EAAE,MAAM,sBAAsB,MAAM,UAAU;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,QAAQ,OAAO,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM;AAElE,MAAI,CAAC,QAAQ,CAAC,SAAS;AACrB,YAAQ,IAAI,EAAE;AACd,QAAI,WAAW;AACb,mBAAa,mDAAmD;AAAA,IAClE,OAAO;AACL,iBAAW,8DAA8D;AAAA,IAC3E;AAAA,EACF,WAAW,CAAC,QAAQ,WAAW,CAAC,WAAW;AACzC,eAAW,4DAA4D;AAAA,EACzE;AAEA,MAAI,WAAW;AACb,UAAM,0BAA0B;AAAA,EAClC;AAEA,MAAI,QAAQ,cAAc,MAAM;AAC9B,WAAO,YAAY,IAAI;AAAA,EACzB;AAKA,MAAI;AACJ,MAAI;AACF,UAAM,EAAE,uBAAuB,IAAI,MAAM,OAAO,qBAAsB;AACtE,WAAO,MAAM,uBAAuB,EAAE,OAAO,QAAQ,SAAS,KAAK,CAAC;AAAA,EACtE,SAAS,KAAK;AACZ,QAAI,MAAM;AACR,cAAQ;AAAA,QACN,KAAK;AAAA,UACH,EAAE,eAAe,GAAG,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE;AAAA,UAC5E;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,aAAO,YAAY,IAAI;AAAA,IACzB;AACA;AAAA,MACE,iDAAiD,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACnG;AACA,WAAO,YAAY,IAAI;AAAA,EACzB;AAEA,MAAI,UAA2D;AAC/D,MAAI,QAAQ,UAAU,MAAM;AAC1B,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,qBAAsB;AACjE,cAAU,MAAM,kBAAkB,IAAI;AAAA,EACxC;AAEA,MAAI,MAAM;AACR,YAAQ;AAAA,MACN,KAAK;AAAA,QACH;AAAA,UACE,eAAe;AAAA,UACf,eAAe,QAAQ,IAAI,CAAC,OAAO;AAAA,YACjC,KAAK,EAAE;AAAA,YACP,QAAQ,EAAE;AAAA,YACV,QAAQ,EAAE;AAAA,YACV,UAAU,WAAW,CAAC;AAAA,UACxB,EAAE;AAAA,UACF,MAAM,KAAK;AAAA;AAAA;AAAA,UAGX,SAAS,KAAK,QAAQ,IAAI,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,OAAO;AAAA,YAC3D;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,EAAE;AAAA,UACF,OAAO,KAAK;AAAA,UACZ;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,WAAO,YAAY,IAAI;AAAA,EACzB;AAEA,MAAI,SAAS;AACX,cAAU,mBAAmB,SAAS,IAAI,CAAC;AAAA,EAC7C,OAAO;AACL,eAAW,MAAM,QAAQ,UAAU,IAAI;AAAA,EACzC;AAEA,MAAI,YAAY,MAAM;AACpB,YAAQ,IAAI,EAAE;AACd,eAAW,QAAQ,QAAQ,SAAS;AAClC,mBAAa,WAAW,IAAI,EAAE;AAAA,IAChC;AACA,eAAW,QAAQ,QAAQ,SAAS;AAClC,mBAAa,WAAW,IAAI,sBAAsB;AAAA,IACpD;AACA,QAAI,QAAQ,QAAQ,WAAW,GAAG;AAChC,gBAAU,mEAA8D;AAAA,IAC1E;AAAA,EACF;AAEA,QAAM,sBAAsB,SAAS,KAAK;AAE1C,MAAI,CAAC,MAAM;AACT,QAAI;AACF,YAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,wBAAuB;AAChE,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,mBAAiB;AACzD,YAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,sBAAc;AACxD,YAAM,MAAM,MAAM,eAAe;AACjC,YAAM,SAAS,MAAM,iBAAiB,EAAE,aAAa,IAAI,CAAC;AAC1D,YAAM,WAAW,MAAM,gBAAgB,EAAE,KAAK,UAAU,OAAO,SAAS,CAAC;AACzE,UAAI,SAAS,WAAW,SAAS;AAC/B;AAAA,UACE;AAAA,QACF;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,YAAY,IAAI;AACzB;AAQA,SAAS,0BAAgC;AACvC;AAAA,IACE;AAAA,EACF;AACA,aAAW,QAAQ;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG;AACD,YAAQ,IAAI,OAAO,IAAI,EAAE;AAAA,EAC3B;AACA,UAAQ,IAAI,EAAE;AAChB;AAEA,IAAM,wBAAwB,CAAC,sBAAsB,gBAAgB,yBAAyB;AAE9F,eAAe,4BAA2C;AACxD,QAAM,aAAa,KAAK,QAAQ,GAAG,UAAU,aAAa;AAC1D,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,YAAY,OAAO;AAC9C,UAAM,OAAO,sBAAsB,OAAO,CAAC,QAAQ,IAAI,SAAS,GAAG,CAAC;AACpE,QAAI,KAAK,WAAW,EAAG;AACvB;AAAA,MACE,oCAAoC,KAAK,KAAK,IAAI,CAAC;AAAA,IACrD;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,oBAA6B;AACpC,QAAM,KAAK,QAAQ,IAAI;AACvB,QAAM,OAAO,OAAO,UAAa,OAAO,MAAM,OAAO,OAAO,GAAG,YAAY,MAAM;AACjF,SAAO,QAAQ,QAAQ,MAAM,KAAK,KAAK,QAAQ,QAAQ,OAAO,KAAK,KAAK,CAAC;AAC3E;AAMO,SAAS,uBACd,sBACA,aACS;AACT,SAAO,CAAC,wBAAwB,gBAAgB;AAClD;AAEA,eAAe,sBACb,SACA,OACe;AACf,MAAI,QAAQ,SAAS,QAAQ,QAAQ,kBAAkB,KAAM;AAC7D,MAAI,CAAC,kBAAkB,EAAG;AAC1B,QAAM,UAAU,MAAM,kBAAkB;AACxC,MACE,CAAC,uBAAuB,0BAA0B,OAAO,qBAAqB,CAAC,GAAG,QAAQ,IAAI,GAC9F;AACA;AAAA,EACF;AAEA,QAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,eAAe;AACxD,QAAM,KAAK,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,QAAM,SAAS,MAAM,IAAI,QAAgB,CAAC,YAAY;AACpD,OAAG,SAAS,2CAA2C,OAAO;AAAA,EAChE,CAAC;AACD,KAAG,MAAM;AACT,QAAM,UAAU,OAAO,KAAK,EAAE,YAAY;AAC1C,QAAM,SAAS,YAAY,UAAU,UAAU;AAE/C,MAAI,QAAQ,UAAU,MAAM;AAC1B,UAAM,EAAE,wBAAwB,IAAI,MAAM,OAAO,qBAAY;AAC7D,UAAM,OAAO,MAAM,wBAAwB,MAAM;AACjD,iBAAa,gBAAgB,MAAM,QAAQ,IAAI,EAAE;AACjD;AAAA,EACF;AACA;AAAA,IACE,SAAS,MAAM,uDAAuD,MAAM;AAAA,EAC9E;AACF;","names":[]}
|