@unbrained/pm-cli 2026.7.13 → 2026.7.14
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/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +28 -0
- package/dist/cli/commands/aggregate.d.ts +1 -1
- package/dist/cli/commands/aggregate.js +18 -6
- package/dist/cli/commands/aggregate.js.map +1 -1
- package/dist/cli/commands/context.d.ts +16 -1
- package/dist/cli/commands/context.js +98 -16
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/create.d.ts +1 -1
- package/dist/cli/commands/create.js +11 -7
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/deps.d.ts +6 -96
- package/dist/cli/commands/deps.js +4 -214
- package/dist/cli/commands/deps.js.map +1 -1
- package/dist/cli/commands/docs.d.ts +2 -44
- package/dist/cli/commands/docs.js +8 -13
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/files.d.ts +6 -134
- package/dist/cli/commands/files.js +4 -294
- package/dist/cli/commands/files.js.map +1 -1
- package/dist/cli/commands/get.js +15 -2
- package/dist/cli/commands/get.js.map +1 -1
- package/dist/cli/commands/list.js +5 -6
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/next.d.ts +3 -1
- package/dist/cli/commands/next.js +77 -20
- package/dist/cli/commands/next.js.map +1 -1
- package/dist/cli/commands/update-many.js +6 -3
- package/dist/cli/commands/update-many.js.map +1 -1
- package/dist/cli/commands/update.js +14 -7
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +1 -1
- package/dist/cli/commands/validate.js +32 -35
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/main.d.ts +2 -14
- package/dist/cli/main.js +27 -8
- package/dist/cli/main.js.map +1 -1
- package/dist/cli-bundle/chunks/append-DYQWQK2J.js +11 -0
- package/dist/cli-bundle/chunks/{append-2FS6MVG7.js → append-PVZJDM6J.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-J2WAWP4U.js → chunk-2FNWQXZ2.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-YFGYDZRP.js → chunk-2GA3NK35.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-XFEIASAC.js → chunk-2QIQGYPW.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-3WCGYH5Q.js → chunk-3CMRNVTO.js} +7 -7
- package/dist/cli-bundle/chunks/chunk-3HKUXVKV.js +9 -0
- package/dist/cli-bundle/chunks/{chunk-VDAZPPRU.js → chunk-3I3LRT2G.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-3P3RFJIQ.js → chunk-3TL7WOEF.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-4SHJ5JS3.js → chunk-44LNIULG.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-QFOAWBOB.js → chunk-4DY4KPQI.js} +11 -10
- package/dist/cli-bundle/chunks/{chunk-QFOAWBOB.js.map → chunk-4DY4KPQI.js.map} +2 -2
- package/dist/cli-bundle/chunks/{chunk-BVCF4ULV.js → chunk-4RXTMU57.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-XMI2TRY5.js → chunk-4WREH7RT.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-JYUGUXFW.js → chunk-5CT5BW6E.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-NA5SBIB4.js → chunk-5URI7TPJ.js} +44 -44
- package/dist/cli-bundle/chunks/chunk-5URI7TPJ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-QGH6WL6L.js → chunk-655STMGA.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-DGKBWCMA.js → chunk-6IIVBC56.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-SRQLQUO6.js → chunk-6MHSBDGD.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-SRQLQUO6.js.map → chunk-6MHSBDGD.js.map} +2 -2
- package/dist/cli-bundle/chunks/{chunk-D4GPNYYP.js → chunk-6OTZMORS.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-JVRVXO6M.js → chunk-6PKA3SJQ.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-2PR4ZTRO.js → chunk-6TTOHMTB.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-2PR4ZTRO.js.map → chunk-6TTOHMTB.js.map} +1 -1
- package/dist/cli-bundle/chunks/chunk-6X5MZ5R2.js +9 -0
- package/dist/cli-bundle/chunks/chunk-76UBY2EE.js +5 -0
- package/dist/cli-bundle/chunks/{chunk-ZS2KPCJN.js → chunk-7QDSYUMF.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-Z7TFPIJ6.js → chunk-7TQMR6LK.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-AHA4POA6.js → chunk-ABRCOSDC.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-XY3CC3EM.js → chunk-AFWZRL7M.js} +59 -53
- package/dist/cli-bundle/chunks/chunk-AFWZRL7M.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-KQJVTQVK.js → chunk-ANSJHDOZ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-OMT4NO7T.js → chunk-B5DZYTT3.js} +113 -24
- package/dist/cli-bundle/chunks/chunk-B5DZYTT3.js.map +7 -0
- package/dist/cli-bundle/chunks/chunk-B7SWOIP6.js +5 -0
- package/dist/cli-bundle/chunks/{chunk-D2LXG7WX.js → chunk-BN62TO2S.js} +5 -5
- package/dist/cli-bundle/chunks/chunk-BN62TO2S.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-ZTSV7P2T.js → chunk-BPD26E3P.js} +357 -42
- package/dist/cli-bundle/chunks/chunk-BPD26E3P.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-RKGFUC4O.js → chunk-CDJYP7OQ.js} +36 -14
- package/dist/cli-bundle/chunks/chunk-CDJYP7OQ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-VLFLRFJP.js → chunk-CIOZ376P.js} +20 -13
- package/dist/cli-bundle/chunks/chunk-CIOZ376P.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-HXTCZSAI.js → chunk-DBZVUJTK.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-2QNOWOIB.js → chunk-DO5RGJXT.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-MKONZ4UO.js → chunk-DRNJPEPQ.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-XDT2PSXA.js → chunk-DVOLZJ3C.js} +12 -11
- package/dist/cli-bundle/chunks/{chunk-XDT2PSXA.js.map → chunk-DVOLZJ3C.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-H36FXA7B.js → chunk-DYEX6NFH.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-G3IB5GTD.js → chunk-E2WC6S4P.js} +15 -11
- package/dist/cli-bundle/chunks/chunk-E2WC6S4P.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-GAJ7U7B4.js → chunk-ERL2YFJ2.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-FPEYOFEF.js → chunk-F7PSHRNO.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-UH7OLT6F.js → chunk-FDSBDNYE.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-DGJF32JF.js → chunk-FIGXOCEQ.js} +66 -21
- package/dist/cli-bundle/chunks/chunk-FIGXOCEQ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-RQAY7C5T.js → chunk-FJZDA6MS.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-B4TVNGRX.js → chunk-FO7GMJKG.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-FRQ63VPB.js +5 -0
- package/dist/cli-bundle/chunks/{chunk-UTYNQ2WH.js → chunk-FS6UM5WH.js} +48 -27
- package/dist/cli-bundle/chunks/chunk-FS6UM5WH.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-U252II47.js → chunk-FTQLW4JD.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-TNGLCRKS.js → chunk-GSEADLRH.js} +1821 -1809
- package/dist/cli-bundle/chunks/chunk-GSEADLRH.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-TGG7YGMC.js → chunk-GXXC7QSK.js} +53 -47
- package/dist/cli-bundle/chunks/chunk-GXXC7QSK.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-AGD4VZXH.js → chunk-H2QBAKLQ.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-CJVQ4XIG.js → chunk-HAMLIWAF.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-56DX6QYG.js → chunk-HL7V2PHX.js} +19 -13
- package/dist/cli-bundle/chunks/chunk-HL7V2PHX.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-7QOIQTPB.js → chunk-HLHSQ5CA.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-AHC7J6XD.js → chunk-IA3YFTXT.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-5ZCVF4WF.js → chunk-IAPHYPRL.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-OCSQWIOW.js → chunk-IFZA4VB5.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-6O2HJENY.js → chunk-IGED7NH2.js} +61 -48
- package/dist/cli-bundle/chunks/chunk-IGED7NH2.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-RPCCQDG2.js → chunk-ILLUE5DI.js} +36 -14
- package/dist/cli-bundle/chunks/chunk-ILLUE5DI.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-4WMFM77X.js → chunk-J4NZOP3I.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-57JVERX3.js → chunk-JAF4TUQ7.js} +4 -4
- package/dist/cli-bundle/chunks/chunk-JAF4TUQ7.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-MTNKSSSO.js → chunk-JL7WZ4O2.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-AZ52LTCY.js → chunk-K7WNZ7KD.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-2OLSXXIV.js → chunk-KADLSPIU.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-RQKORMM4.js → chunk-KB726FMH.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-WKSFBBZT.js → chunk-L24HCJFC.js} +114 -25
- package/dist/cli-bundle/chunks/chunk-L24HCJFC.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-LDO24J5I.js → chunk-LWTIRS3Y.js} +365 -43
- package/dist/cli-bundle/chunks/chunk-LWTIRS3Y.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-TZTQ4TVV.js → chunk-M6ASXYCU.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-WDDOAU7Z.js → chunk-M7EWN4TF.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-327DSGW2.js → chunk-MD6ULIPJ.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-OKDBHOON.js → chunk-MKL4CP2I.js} +61 -48
- package/dist/cli-bundle/chunks/chunk-MKL4CP2I.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-M52DG2QJ.js → chunk-MQZ3PLCF.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-GQ2CQNGI.js → chunk-N3CMP4NI.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-J7SBFUZC.js → chunk-NAQYVWSQ.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-U2GMYP3L.js → chunk-NKW36AMT.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-5WEYOVZ7.js → chunk-OBDLEQG5.js} +19 -12
- package/dist/cli-bundle/chunks/chunk-OBDLEQG5.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-VL4LYTJN.js → chunk-OI4S4KCI.js} +18 -12
- package/dist/cli-bundle/chunks/chunk-OI4S4KCI.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-FCVVMAEX.js → chunk-P6MYFH6K.js} +60 -22
- package/dist/cli-bundle/chunks/chunk-P6MYFH6K.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-FTQQAPRX.js → chunk-PHKP3AGR.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-WVUXNIYO.js → chunk-Q37E63AM.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-JVXV7ANV.js → chunk-Q7E6OYZK.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-WVUYATII.js → chunk-QABYZYLU.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-QRRUGIJN.js → chunk-QASRVKUQ.js} +45 -45
- package/dist/cli-bundle/chunks/chunk-QASRVKUQ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-L4262MFB.js → chunk-QK2ZN6UL.js} +14 -5
- package/dist/cli-bundle/chunks/{chunk-L4262MFB.js.map → chunk-QK2ZN6UL.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-7TQPV7HR.js → chunk-QSPARJWF.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-GTKILM6F.js → chunk-QZ7LT3XE.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-L3VKY6R6.js → chunk-RA5AIAMP.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-BJS27ALI.js → chunk-RGXD5JJR.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-TSEPW2P6.js → chunk-RMF3IOYQ.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-QXYKH56X.js → chunk-T4BRCB6Z.js} +1894 -1875
- package/dist/cli-bundle/chunks/chunk-T4BRCB6Z.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-TGGTXC52.js → chunk-TH7U4KLY.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-LP4UATP6.js → chunk-TWLDBKQU.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-OTZ3C2NE.js → chunk-TZ2PSLLT.js} +49 -28
- package/dist/cli-bundle/chunks/chunk-TZ2PSLLT.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-UK222BHQ.js → chunk-TZRTLMWM.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-6E6S2X6S.js → chunk-UB2QYSTO.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-S6CXUSYC.js → chunk-UGTVWL3E.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-BNS6QHTZ.js → chunk-UJ4HJYWL.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-BYVOEJPQ.js → chunk-UKUIIBDW.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-SGDBVR7X.js → chunk-UVBA6F5A.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-DZRZMBBF.js → chunk-VJTAEIPC.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-74PWVJON.js → chunk-W6HZ55JO.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-HR2MQAO5.js → chunk-WD6MSYMP.js} +13 -4
- package/dist/cli-bundle/chunks/{chunk-HR2MQAO5.js.map → chunk-WD6MSYMP.js.map} +2 -2
- package/dist/cli-bundle/chunks/{chunk-P7IFURWH.js → chunk-WPAWZW7S.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-36LEOWSX.js → chunk-WQUEHPZB.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-FCKJF7G2.js → chunk-WRKB56FC.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-KR5EHAN4.js → chunk-X3GYR4P2.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-J567OZJY.js → chunk-X6BVXQ52.js} +16 -12
- package/dist/cli-bundle/chunks/chunk-X6BVXQ52.js.map +1 -0
- package/dist/cli-bundle/chunks/chunk-Y72FV7RM.js +178 -0
- package/dist/cli-bundle/chunks/chunk-Y72FV7RM.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-OWW2KXOV.js → chunk-YQYG2V23.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-G2SCT7BC.js → chunk-YVKE5ZDM.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-QHIN4UTF.js → chunk-ZAYYDNB3.js} +4 -4
- package/dist/cli-bundle/chunks/chunk-ZHBI2AP7.js +9 -0
- package/dist/cli-bundle/chunks/chunk-ZNP64HOW.js +175 -0
- package/dist/cli-bundle/chunks/chunk-ZNP64HOW.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-GNVBUNJQ.js → chunk-ZTRBSABY.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-PY32KGQU.js → chunk-ZUKSZVBW.js} +5 -5
- package/dist/cli-bundle/chunks/{close-CU56F47E.js → close-LZECOMHO.js} +5 -5
- package/dist/cli-bundle/chunks/close-RI4JQQHU.js +12 -0
- package/dist/cli-bundle/chunks/close-many-LY2XJ52M.js +21 -0
- package/dist/cli-bundle/chunks/{close-many-ZQ2WP67J.js → close-many-ZHI6A5TN.js} +12 -12
- package/dist/cli-bundle/chunks/comments-35M273DN.js +13 -0
- package/dist/cli-bundle/chunks/{comments-UDUMKXL6.js → comments-AJWRTFZ5.js} +7 -7
- package/dist/cli-bundle/chunks/{copy-VFHECFBV.js → copy-GMXYKBXT.js} +4 -4
- package/dist/cli-bundle/chunks/copy-NPYM7M7U.js +9 -0
- package/dist/cli-bundle/chunks/create-F53OBTOU.js +27 -0
- package/dist/cli-bundle/chunks/{create-CE2X3SGF.js → create-HU4Q7RJX.js} +11 -9
- package/dist/cli-bundle/chunks/{delete-2JXQCHHT.js → delete-GSDZLTRC.js} +4 -4
- package/dist/cli-bundle/chunks/delete-ODRWJWAM.js +10 -0
- package/dist/cli-bundle/chunks/deps-U57I7EAK.js +16 -0
- package/dist/cli-bundle/chunks/{deps-FPXNLO6C.js → deps-WWB7P2GT.js} +7 -4
- package/dist/cli-bundle/chunks/docs-G7N4E2JO.js +14 -0
- package/dist/cli-bundle/chunks/{docs-AMAR4OHU.js → docs-MQIY2ZQS.js} +7 -7
- package/dist/cli-bundle/chunks/files-TBZD7V6H.js +18 -0
- package/dist/cli-bundle/chunks/{files-JFHN7DYM.js → files-TTY6N2AV.js} +7 -7
- package/dist/cli-bundle/chunks/focus-U5TRVCRS.js +10 -0
- package/dist/cli-bundle/chunks/{focus-QFN2RRZ7.js → focus-XT6YVFFX.js} +5 -5
- package/dist/cli-bundle/chunks/{history-compact-G34XMABV.js → history-compact-KKVUWB4V.js} +8 -8
- package/dist/cli-bundle/chunks/{history-compact-SAHT5D46.js → history-compact-M7GHYVFN.js} +8 -8
- package/dist/cli-bundle/chunks/{history-redact-IFJDNKLZ.js → history-redact-3DVZOILD.js} +6 -6
- package/dist/cli-bundle/chunks/history-redact-JIHZLHDP.js +16 -0
- package/dist/cli-bundle/chunks/{history-repair-NXLQTCVN.js → history-repair-ITDUMK4N.js} +8 -8
- package/dist/cli-bundle/chunks/history-repair-NAFCHLH7.js +18 -0
- package/dist/cli-bundle/chunks/{learnings-5CZKAMBS.js → learnings-FGO3NSFW.js} +7 -7
- package/dist/cli-bundle/chunks/learnings-SONGPSHI.js +13 -0
- package/dist/cli-bundle/chunks/notes-BSD53H2W.js +13 -0
- package/dist/cli-bundle/chunks/{notes-POMK37UI.js → notes-NQ6RXVW6.js} +7 -7
- package/dist/cli-bundle/chunks/{plan-YBNYNT3A.js → plan-2NNEO46V.js} +10 -10
- package/dist/cli-bundle/chunks/plan-AWLYGBNV.js +24 -0
- package/dist/cli-bundle/chunks/{profile-JNKSU6EQ.js → profile-AAQUU6T3.js} +9 -9
- package/dist/cli-bundle/chunks/{profile-A2WPVG6I.js → profile-U725ATWZ.js} +9 -9
- package/dist/cli-bundle/chunks/{register-list-query-UG4ZA5AU.js → register-list-query-BUWCYHBT.js} +14 -13
- package/dist/cli-bundle/chunks/{register-list-query-UG4ZA5AU.js.map → register-list-query-BUWCYHBT.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-list-query-KJULL4W3.js → register-list-query-KTZ6AGE7.js} +16 -15
- package/dist/cli-bundle/chunks/{register-list-query-KJULL4W3.js.map → register-list-query-KTZ6AGE7.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-mutation-3OXYXBKH.js → register-mutation-4FMGJJF7.js} +29 -29
- package/dist/cli-bundle/chunks/{register-mutation-WK265BM7.js → register-mutation-UELYYOR7.js} +29 -29
- package/dist/cli-bundle/chunks/{register-operations-C5SQH3FJ.js → register-operations-ISUX6LY5.js} +33 -29
- package/dist/cli-bundle/chunks/{register-operations-C5SQH3FJ.js.map → register-operations-ISUX6LY5.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-operations-FH3PBHYN.js → register-operations-JVW24J2Y.js} +35 -31
- package/dist/cli-bundle/chunks/{register-operations-FH3PBHYN.js.map → register-operations-JVW24J2Y.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-setup-CCK7CJVR.js → register-setup-5XNGKJ22.js} +15 -15
- package/dist/cli-bundle/chunks/{register-setup-CPZBGSOJ.js → register-setup-ZTNY6S7R.js} +15 -15
- package/dist/cli-bundle/chunks/restore-66GLMHIX.js +14 -0
- package/dist/cli-bundle/chunks/{restore-IVS5XGYR.js → restore-B3BAB6X2.js} +6 -6
- package/dist/cli-bundle/chunks/{schema-P2MF23JO.js → schema-LZNUYHDB.js} +6 -6
- package/dist/cli-bundle/chunks/schema-LZNUYHDB.js.map +7 -0
- package/dist/cli-bundle/chunks/{schema-R3U2REY4.js → schema-U7IM2DXV.js} +6 -6
- package/dist/cli-bundle/chunks/schema-U7IM2DXV.js.map +1 -0
- package/dist/cli-bundle/chunks/update-2XGHIVQ2.js +21 -0
- package/dist/cli-bundle/chunks/update-2XGHIVQ2.js.map +7 -0
- package/dist/cli-bundle/chunks/{update-YBIQESMH.js → update-Q3UCILNR.js} +12 -12
- package/dist/cli-bundle/chunks/update-Q3UCILNR.js.map +1 -0
- package/dist/cli-bundle/chunks/{update-many-F3CIV5SQ.js → update-many-75K57FS3.js} +19 -19
- package/dist/cli-bundle/chunks/update-many-75K57FS3.js.map +1 -0
- package/dist/cli-bundle/chunks/update-many-U42YA445.js +30 -0
- package/dist/cli-bundle/chunks/update-many-U42YA445.js.map +7 -0
- package/dist/cli-bundle/main.js +39 -16
- package/dist/cli-bundle/main.js.map +2 -2
- package/dist/cli-bundle/sdk-runtime.js +56 -53
- package/dist/cli-bundle/sdk-testing.js +6 -6
- package/dist/cli-bundle/sdk.js +115 -55
- package/dist/cli-bundle/sdk.js.map +2 -2
- package/dist/core/extensions/command-hook-context.d.ts +40 -0
- package/dist/core/extensions/command-hook-context.js +14 -0
- package/dist/core/extensions/command-hook-context.js.map +1 -0
- package/dist/core/extensions/index.d.ts +1 -0
- package/dist/core/extensions/index.js +4 -3
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/item/parse.d.ts +2 -0
- package/dist/core/item/parse.js +11 -2
- package/dist/core/item/parse.js.map +1 -1
- package/dist/core/store/paths.d.ts +2 -0
- package/dist/core/store/paths.js +10 -2
- package/dist/core/store/paths.js.map +1 -1
- package/dist/mcp/tool-definitions.js +12 -2
- package/dist/mcp/tool-definitions.js.map +1 -1
- package/dist/sdk/context-packing.d.ts +114 -0
- package/dist/sdk/context-packing.js +219 -0
- package/dist/sdk/context-packing.js.map +1 -0
- package/dist/sdk/context-relevance.d.ts +1 -1
- package/dist/sdk/context-relevance.js +4 -2
- package/dist/sdk/context-relevance.js.map +1 -1
- package/dist/sdk/context-usage.d.ts +79 -0
- package/dist/sdk/context-usage.js +193 -0
- package/dist/sdk/context-usage.js.map +1 -0
- package/dist/sdk/dependencies.d.ts +145 -0
- package/dist/sdk/dependencies.js +327 -0
- package/dist/sdk/dependencies.js.map +1 -0
- package/dist/sdk/docs.d.ts +48 -0
- package/dist/sdk/docs.js +15 -0
- package/dist/sdk/docs.js.map +1 -0
- package/dist/sdk/files.d.ts +135 -0
- package/dist/sdk/files.js +320 -0
- package/dist/sdk/files.js.map +1 -0
- package/dist/sdk/index.d.ts +6 -0
- package/dist/sdk/index.js +8 -2
- package/dist/sdk/index.js.map +1 -1
- package/dist/{cli/commands → sdk}/linked-artifacts.d.ts +11 -5
- package/dist/{cli/commands → sdk}/linked-artifacts.js +49 -25
- package/dist/sdk/linked-artifacts.js.map +1 -0
- package/dist/sdk/runtime.d.ts +4 -4
- package/dist/sdk/runtime.js +7 -4
- package/dist/sdk/runtime.js.map +1 -1
- package/dist/sdk/workspace.js +3 -2
- package/dist/sdk/workspace.js.map +1 -1
- package/docs/AGENT_GUIDE.md +1 -1
- package/docs/CONFIGURATION.md +1 -0
- package/docs/PR_REVIEW_LOOP.md +21 -11
- package/docs/SDK.md +94 -0
- package/marketplace.json +2 -2
- package/package.json +1 -1
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/dist/cli/commands/linked-artifacts.js.map +0 -1
- package/dist/cli-bundle/chunks/append-CTKFDEAX.js +0 -11
- package/dist/cli-bundle/chunks/chunk-56DX6QYG.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-57JVERX3.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-5WEYOVZ7.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-6O2HJENY.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-CCAGZCZK.js +0 -17
- package/dist/cli-bundle/chunks/chunk-CCAGZCZK.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-D2LXG7WX.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-DGJF32JF.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-FCVVMAEX.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-FUOK7JZ6.js +0 -14
- package/dist/cli-bundle/chunks/chunk-FUOK7JZ6.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-G3IB5GTD.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-J567OZJY.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-LDO24J5I.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-NA5SBIB4.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-OKDBHOON.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-OMT4NO7T.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-OTZ3C2NE.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-QRRUGIJN.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-QXYKH56X.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-RKGFUC4O.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-RPCCQDG2.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-TGG7YGMC.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-TNGLCRKS.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-UTYNQ2WH.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-VL4LYTJN.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-VLFLRFJP.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-WKSFBBZT.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-XY3CC3EM.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-ZTSV7P2T.js.map +0 -1
- package/dist/cli-bundle/chunks/close-BWM7FTF4.js +0 -12
- package/dist/cli-bundle/chunks/close-many-AUHTVFUQ.js +0 -21
- package/dist/cli-bundle/chunks/comments-7D5VPBZI.js +0 -13
- package/dist/cli-bundle/chunks/copy-QJ6ZVWZV.js +0 -9
- package/dist/cli-bundle/chunks/create-FGMTTYOI.js +0 -25
- package/dist/cli-bundle/chunks/delete-L2GMMMPR.js +0 -10
- package/dist/cli-bundle/chunks/deps-KTFI4RWD.js +0 -13
- package/dist/cli-bundle/chunks/docs-VNURA275.js +0 -14
- package/dist/cli-bundle/chunks/files-UNFPZLTG.js +0 -18
- package/dist/cli-bundle/chunks/focus-MI2UHBP4.js +0 -10
- package/dist/cli-bundle/chunks/history-redact-VAHGBUHI.js +0 -16
- package/dist/cli-bundle/chunks/history-repair-DDYQXR43.js +0 -18
- package/dist/cli-bundle/chunks/learnings-VWJEKHEO.js +0 -13
- package/dist/cli-bundle/chunks/notes-NGVJJJQO.js +0 -13
- package/dist/cli-bundle/chunks/plan-U6SQJUFI.js +0 -24
- package/dist/cli-bundle/chunks/restore-AX6ZMGHZ.js +0 -14
- package/dist/cli-bundle/chunks/update-XYHF3YZF.js +0 -21
- package/dist/cli-bundle/chunks/update-many-5HKVHFUL.js +0 -30
- /package/dist/cli-bundle/chunks/{append-CTKFDEAX.js.map → append-DYQWQK2J.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{append-2FS6MVG7.js.map → append-PVZJDM6J.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-J2WAWP4U.js.map → chunk-2FNWQXZ2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-YFGYDZRP.js.map → chunk-2GA3NK35.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-XFEIASAC.js.map → chunk-2QIQGYPW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-3WCGYH5Q.js.map → chunk-3CMRNVTO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-BWM7FTF4.js.map → chunk-3HKUXVKV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-VDAZPPRU.js.map → chunk-3I3LRT2G.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-3P3RFJIQ.js.map → chunk-3TL7WOEF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-4SHJ5JS3.js.map → chunk-44LNIULG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-BVCF4ULV.js.map → chunk-4RXTMU57.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-XMI2TRY5.js.map → chunk-4WREH7RT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JYUGUXFW.js.map → chunk-5CT5BW6E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-QGH6WL6L.js.map → chunk-655STMGA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-DGKBWCMA.js.map → chunk-6IIVBC56.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-D4GPNYYP.js.map → chunk-6OTZMORS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JVRVXO6M.js.map → chunk-6PKA3SJQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-many-AUHTVFUQ.js.map → chunk-6X5MZ5R2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-CU56F47E.js.map → chunk-76UBY2EE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZS2KPCJN.js.map → chunk-7QDSYUMF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-Z7TFPIJ6.js.map → chunk-7TQMR6LK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-AHA4POA6.js.map → chunk-ABRCOSDC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-KQJVTQVK.js.map → chunk-ANSJHDOZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-many-ZQ2WP67J.js.map → chunk-B7SWOIP6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HXTCZSAI.js.map → chunk-DBZVUJTK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2QNOWOIB.js.map → chunk-DO5RGJXT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-MKONZ4UO.js.map → chunk-DRNJPEPQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-H36FXA7B.js.map → chunk-DYEX6NFH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-GAJ7U7B4.js.map → chunk-ERL2YFJ2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FPEYOFEF.js.map → chunk-F7PSHRNO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-UH7OLT6F.js.map → chunk-FDSBDNYE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-RQAY7C5T.js.map → chunk-FJZDA6MS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-B4TVNGRX.js.map → chunk-FO7GMJKG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-UDUMKXL6.js.map → chunk-FRQ63VPB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-U252II47.js.map → chunk-FTQLW4JD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-AGD4VZXH.js.map → chunk-H2QBAKLQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-CJVQ4XIG.js.map → chunk-HAMLIWAF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-7QOIQTPB.js.map → chunk-HLHSQ5CA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-AHC7J6XD.js.map → chunk-IA3YFTXT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-5ZCVF4WF.js.map → chunk-IAPHYPRL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-OCSQWIOW.js.map → chunk-IFZA4VB5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-4WMFM77X.js.map → chunk-J4NZOP3I.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-MTNKSSSO.js.map → chunk-JL7WZ4O2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-AZ52LTCY.js.map → chunk-K7WNZ7KD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2OLSXXIV.js.map → chunk-KADLSPIU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-RQKORMM4.js.map → chunk-KB726FMH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-TZTQ4TVV.js.map → chunk-M6ASXYCU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-WDDOAU7Z.js.map → chunk-M7EWN4TF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-327DSGW2.js.map → chunk-MD6ULIPJ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-M52DG2QJ.js.map → chunk-MQZ3PLCF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-GQ2CQNGI.js.map → chunk-N3CMP4NI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-J7SBFUZC.js.map → chunk-NAQYVWSQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-U2GMYP3L.js.map → chunk-NKW36AMT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FTQQAPRX.js.map → chunk-PHKP3AGR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-WVUXNIYO.js.map → chunk-Q37E63AM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JVXV7ANV.js.map → chunk-Q7E6OYZK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-WVUYATII.js.map → chunk-QABYZYLU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-7TQPV7HR.js.map → chunk-QSPARJWF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-GTKILM6F.js.map → chunk-QZ7LT3XE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-L3VKY6R6.js.map → chunk-RA5AIAMP.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-BJS27ALI.js.map → chunk-RGXD5JJR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-TSEPW2P6.js.map → chunk-RMF3IOYQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-TGGTXC52.js.map → chunk-TH7U4KLY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-LP4UATP6.js.map → chunk-TWLDBKQU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-UK222BHQ.js.map → chunk-TZRTLMWM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-6E6S2X6S.js.map → chunk-UB2QYSTO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-S6CXUSYC.js.map → chunk-UGTVWL3E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-BNS6QHTZ.js.map → chunk-UJ4HJYWL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-BYVOEJPQ.js.map → chunk-UKUIIBDW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-SGDBVR7X.js.map → chunk-UVBA6F5A.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-DZRZMBBF.js.map → chunk-VJTAEIPC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-74PWVJON.js.map → chunk-W6HZ55JO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-P7IFURWH.js.map → chunk-WPAWZW7S.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-36LEOWSX.js.map → chunk-WQUEHPZB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FCKJF7G2.js.map → chunk-WRKB56FC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-KR5EHAN4.js.map → chunk-X3GYR4P2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-OWW2KXOV.js.map → chunk-YQYG2V23.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-G2SCT7BC.js.map → chunk-YVKE5ZDM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-QHIN4UTF.js.map → chunk-ZAYYDNB3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-7D5VPBZI.js.map → chunk-ZHBI2AP7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-GNVBUNJQ.js.map → chunk-ZTRBSABY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-PY32KGQU.js.map → chunk-ZUKSZVBW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{copy-VFHECFBV.js.map → close-LZECOMHO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{copy-QJ6ZVWZV.js.map → close-RI4JQQHU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-FGMTTYOI.js.map → close-many-LY2XJ52M.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-CE2X3SGF.js.map → close-many-ZHI6A5TN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{delete-L2GMMMPR.js.map → comments-35M273DN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{delete-2JXQCHHT.js.map → comments-AJWRTFZ5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-FPXNLO6C.js.map → copy-GMXYKBXT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-KTFI4RWD.js.map → copy-NPYM7M7U.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{docs-VNURA275.js.map → create-F53OBTOU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{docs-AMAR4OHU.js.map → create-HU4Q7RJX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{files-JFHN7DYM.js.map → delete-GSDZLTRC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{files-UNFPZLTG.js.map → delete-ODRWJWAM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{focus-MI2UHBP4.js.map → deps-U57I7EAK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{focus-QFN2RRZ7.js.map → deps-WWB7P2GT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-compact-SAHT5D46.js.map → docs-G7N4E2JO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-compact-G34XMABV.js.map → docs-MQIY2ZQS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-VAHGBUHI.js.map → files-TBZD7V6H.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-IFJDNKLZ.js.map → files-TTY6N2AV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-repair-DDYQXR43.js.map → focus-U5TRVCRS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-repair-NXLQTCVN.js.map → focus-XT6YVFFX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-5CZKAMBS.js.map → history-compact-KKVUWB4V.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-VWJEKHEO.js.map → history-compact-M7GHYVFN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-POMK37UI.js.map → history-redact-3DVZOILD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-NGVJJJQO.js.map → history-redact-JIHZLHDP.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{plan-YBNYNT3A.js.map → history-repair-ITDUMK4N.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{plan-U6SQJUFI.js.map → history-repair-NAFCHLH7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{profile-JNKSU6EQ.js.map → learnings-FGO3NSFW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{profile-A2WPVG6I.js.map → learnings-SONGPSHI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-AX6ZMGHZ.js.map → notes-BSD53H2W.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-IVS5XGYR.js.map → notes-NQ6RXVW6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-R3U2REY4.js.map → plan-2NNEO46V.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-P2MF23JO.js.map → plan-AWLYGBNV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-YBIQESMH.js.map → profile-AAQUU6T3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-XYHF3YZF.js.map → profile-U725ATWZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-mutation-3OXYXBKH.js.map → register-mutation-4FMGJJF7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-mutation-WK265BM7.js.map → register-mutation-UELYYOR7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-setup-CCK7CJVR.js.map → register-setup-5XNGKJ22.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-setup-CPZBGSOJ.js.map → register-setup-ZTNY6S7R.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-5HKVHFUL.js.map → restore-66GLMHIX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-F3CIV5SQ.js.map → restore-B3BAB6X2.js.map} +0 -0
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
appendLineAtomic,
|
|
23
23
|
coerceFiniteNumber,
|
|
24
24
|
collectRegisteredItemFieldNames,
|
|
25
|
+
createEmptyExtensionHookRegistry,
|
|
25
26
|
ensureDir,
|
|
26
27
|
ensureRuntimeSchemaFileScaffold,
|
|
27
28
|
evictOldestMemoEntries,
|
|
@@ -55,7 +56,24 @@ import {
|
|
|
55
56
|
toErrorMessage,
|
|
56
57
|
weekdayOrderIndex,
|
|
57
58
|
writeFileAtomic
|
|
58
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-AFWZRL7M.js";
|
|
60
|
+
|
|
61
|
+
// dist/core/extensions/command-hook-context.js
|
|
62
|
+
!(function() {
|
|
63
|
+
try {
|
|
64
|
+
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
65
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "3efead0c-2ad9-5fa1-af60-57b781a534fc");
|
|
66
|
+
} catch (e2) {
|
|
67
|
+
}
|
|
68
|
+
})();
|
|
69
|
+
function createCoreCommandHookContext(options) {
|
|
70
|
+
return {
|
|
71
|
+
...options,
|
|
72
|
+
hooks: createEmptyExtensionHookRegistry(),
|
|
73
|
+
profileEnabled: Boolean(options.globalOptions.profile),
|
|
74
|
+
migrationBlockers: []
|
|
75
|
+
};
|
|
76
|
+
}
|
|
59
77
|
|
|
60
78
|
// dist/core/shared/serial-queue.js
|
|
61
79
|
!(function() {
|
|
@@ -98,7 +116,7 @@ function createSerialQueue() {
|
|
|
98
116
|
!(function() {
|
|
99
117
|
try {
|
|
100
118
|
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
101
|
-
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "
|
|
119
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "27bb9504-233c-5768-8932-d1cae84313be");
|
|
102
120
|
} catch (e2) {
|
|
103
121
|
}
|
|
104
122
|
})();
|
|
@@ -170,7 +188,7 @@ function getActiveCommandResult() {
|
|
|
170
188
|
return activeCommandResult;
|
|
171
189
|
}
|
|
172
190
|
function recordAfterCommandAffectedItem(item) {
|
|
173
|
-
if (!item
|
|
191
|
+
if (!item) {
|
|
174
192
|
return;
|
|
175
193
|
}
|
|
176
194
|
activeAfterCommandAffectedItems.push(item);
|
|
@@ -2262,2173 +2280,2173 @@ function resolveIsoOrRelative(input, now = /* @__PURE__ */ new Date(), fieldLabe
|
|
|
2262
2280
|
return new Date(timestamp).toISOString();
|
|
2263
2281
|
}
|
|
2264
2282
|
|
|
2265
|
-
// dist/core/
|
|
2283
|
+
// dist/core/lock/lock.js
|
|
2284
|
+
import fs from "node:fs/promises";
|
|
2285
|
+
import path from "node:path";
|
|
2286
|
+
import { randomUUID } from "node:crypto";
|
|
2266
2287
|
!(function() {
|
|
2267
2288
|
try {
|
|
2268
2289
|
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
2269
|
-
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "
|
|
2290
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "d23246e1-c423-5100-bcde-8162e01587f0");
|
|
2270
2291
|
} catch (e2) {
|
|
2271
2292
|
}
|
|
2272
2293
|
})();
|
|
2273
|
-
function
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2294
|
+
function parseLockInfo(raw) {
|
|
2295
|
+
let parsed;
|
|
2296
|
+
try {
|
|
2297
|
+
parsed = JSON.parse(raw);
|
|
2298
|
+
} catch {
|
|
2299
|
+
return {
|
|
2300
|
+
info: null,
|
|
2301
|
+
warnings: ["lock_info_invalid_json"]
|
|
2302
|
+
};
|
|
2277
2303
|
}
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2304
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
2305
|
+
return {
|
|
2306
|
+
info: null,
|
|
2307
|
+
warnings: ["lock_info_invalid_shape"]
|
|
2308
|
+
};
|
|
2309
|
+
}
|
|
2310
|
+
const candidate = parsed;
|
|
2311
|
+
const id = candidate.id;
|
|
2312
|
+
const pid = candidate.pid;
|
|
2313
|
+
const owner = candidate.owner;
|
|
2314
|
+
const createdAt = candidate.created_at;
|
|
2315
|
+
const ttlSeconds = candidate.ttl_seconds;
|
|
2316
|
+
if (typeof id !== "string" || typeof pid !== "number" || !Number.isFinite(pid) || typeof owner !== "string" || typeof createdAt !== "string" || typeof ttlSeconds !== "number" || !Number.isFinite(ttlSeconds)) {
|
|
2317
|
+
return {
|
|
2318
|
+
info: null,
|
|
2319
|
+
warnings: ["lock_info_invalid_shape"]
|
|
2320
|
+
};
|
|
2321
|
+
}
|
|
2322
|
+
return {
|
|
2323
|
+
info: {
|
|
2324
|
+
id,
|
|
2325
|
+
pid,
|
|
2326
|
+
owner,
|
|
2327
|
+
created_at: createdAt,
|
|
2328
|
+
ttl_seconds: ttlSeconds
|
|
2329
|
+
},
|
|
2330
|
+
warnings: []
|
|
2331
|
+
};
|
|
2290
2332
|
}
|
|
2291
|
-
function
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2333
|
+
async function readLockInfo(lockPath) {
|
|
2334
|
+
try {
|
|
2335
|
+
const raw = await fs.readFile(lockPath, "utf8");
|
|
2336
|
+
await runActiveOnReadHooks({
|
|
2337
|
+
path: lockPath,
|
|
2338
|
+
scope: "project"
|
|
2339
|
+
});
|
|
2340
|
+
return parseLockInfo(raw);
|
|
2341
|
+
} catch (error) {
|
|
2342
|
+
if (isErrno(error, "ENOENT")) {
|
|
2343
|
+
return {
|
|
2344
|
+
info: null,
|
|
2345
|
+
warnings: []
|
|
2346
|
+
};
|
|
2299
2347
|
}
|
|
2348
|
+
return {
|
|
2349
|
+
info: null,
|
|
2350
|
+
warnings: ["lock_info_read_failed"]
|
|
2351
|
+
};
|
|
2300
2352
|
}
|
|
2301
|
-
return void 0;
|
|
2302
2353
|
}
|
|
2303
|
-
function
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2354
|
+
function isErrno(error, code) {
|
|
2355
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
2356
|
+
}
|
|
2357
|
+
async function emitLockWriteHook(lockPath, op) {
|
|
2358
|
+
await runActiveOnWriteHooks({
|
|
2359
|
+
path: lockPath,
|
|
2360
|
+
scope: "project",
|
|
2361
|
+
op
|
|
2362
|
+
});
|
|
2363
|
+
}
|
|
2364
|
+
function buildLockPayload(id, owner, ttlSeconds) {
|
|
2365
|
+
return {
|
|
2366
|
+
id,
|
|
2367
|
+
pid: process.pid,
|
|
2368
|
+
owner,
|
|
2369
|
+
created_at: nowIso(),
|
|
2370
|
+
ttl_seconds: ttlSeconds
|
|
2371
|
+
};
|
|
2372
|
+
}
|
|
2373
|
+
async function createLockFile(lockPath, id, owner, ttlSeconds) {
|
|
2374
|
+
await fs.mkdir(path.dirname(lockPath), { recursive: true });
|
|
2375
|
+
const handle = await fs.open(lockPath, "wx");
|
|
2376
|
+
try {
|
|
2377
|
+
await handle.writeFile(`${JSON.stringify(buildLockPayload(id, owner, ttlSeconds), null, 2)}
|
|
2378
|
+
`, "utf8");
|
|
2379
|
+
} finally {
|
|
2380
|
+
await handle.close();
|
|
2312
2381
|
}
|
|
2313
|
-
|
|
2382
|
+
await emitLockWriteHook(lockPath, "lock:create");
|
|
2314
2383
|
}
|
|
2315
|
-
function
|
|
2316
|
-
|
|
2317
|
-
|
|
2384
|
+
async function unlinkLockWithHook(lockPath, op) {
|
|
2385
|
+
try {
|
|
2386
|
+
await fs.unlink(lockPath);
|
|
2387
|
+
await emitLockWriteHook(lockPath, op);
|
|
2388
|
+
return true;
|
|
2389
|
+
} catch {
|
|
2390
|
+
return false;
|
|
2318
2391
|
}
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2392
|
+
}
|
|
2393
|
+
function isStaleLock(info, ttlSeconds) {
|
|
2394
|
+
const createdAtMs = info?.created_at ? Date.parse(info.created_at) : Number.NaN;
|
|
2395
|
+
const ageMs = Number.isFinite(createdAtMs) ? Date.now() - createdAtMs : Number.POSITIVE_INFINITY;
|
|
2396
|
+
return ageMs > ttlSeconds * 1e3;
|
|
2397
|
+
}
|
|
2398
|
+
function lockOwnerSuffix(info) {
|
|
2399
|
+
return info?.owner ? ` (owner ${info.owner})` : "";
|
|
2400
|
+
}
|
|
2401
|
+
var LOCK_WAIT_INITIAL_DELAY_MS = 25;
|
|
2402
|
+
var LOCK_WAIT_MAX_DELAY_MS = 200;
|
|
2403
|
+
var LOCK_CONFLICT_RETRY_HINT_MS = 250;
|
|
2404
|
+
var MAX_STALE_LOCK_REMOVALS = 3;
|
|
2405
|
+
var STALE_CLEANUP_GATE_SUFFIX = ".stale-cleanup";
|
|
2406
|
+
var STALE_CLEANUP_GATE_OWNER_FILE = "owner.json";
|
|
2407
|
+
var STALE_CLEANUP_GATE_STALE_MS = 1e4;
|
|
2408
|
+
var STALE_CLEANUP_GATE_MAX_ACTIVE_MS = 5 * 6e4;
|
|
2409
|
+
function parseNonNegativeIntegerWaitMs(value) {
|
|
2410
|
+
if (typeof value === "string") {
|
|
2411
|
+
const trimmed = value.trim();
|
|
2412
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
2413
|
+
return void 0;
|
|
2325
2414
|
}
|
|
2415
|
+
const parsed = Number(trimmed);
|
|
2416
|
+
return Number.isSafeInteger(parsed) ? parsed : void 0;
|
|
2326
2417
|
}
|
|
2327
|
-
if (typeof
|
|
2328
|
-
|
|
2329
|
-
if (normalized === "true" || normalized === "1" || normalized === "yes") {
|
|
2330
|
-
return true;
|
|
2331
|
-
}
|
|
2332
|
-
if (normalized === "false" || normalized === "0" || normalized === "no") {
|
|
2333
|
-
return false;
|
|
2334
|
-
}
|
|
2418
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
2419
|
+
return Math.trunc(value);
|
|
2335
2420
|
}
|
|
2336
|
-
|
|
2421
|
+
return void 0;
|
|
2337
2422
|
}
|
|
2338
|
-
function
|
|
2339
|
-
|
|
2340
|
-
|
|
2423
|
+
function resolveLockWaitMs(waitMs) {
|
|
2424
|
+
const envRaw = process.env.PM_LOCK_WAIT_MS;
|
|
2425
|
+
const envParsed = parseNonNegativeIntegerWaitMs(envRaw);
|
|
2426
|
+
if (envParsed !== void 0) {
|
|
2427
|
+
return envParsed;
|
|
2341
2428
|
}
|
|
2342
|
-
const
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
throw new PmCliError(`${label} must be a number`, EXIT_CODE.USAGE);
|
|
2429
|
+
const callerParsed = parseNonNegativeIntegerWaitMs(waitMs);
|
|
2430
|
+
if (callerParsed !== void 0) {
|
|
2431
|
+
return callerParsed;
|
|
2346
2432
|
}
|
|
2347
|
-
return
|
|
2433
|
+
return 0;
|
|
2348
2434
|
}
|
|
2349
|
-
function
|
|
2350
|
-
const
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2435
|
+
function sleepWithJitter(baseDelayMs) {
|
|
2436
|
+
const jitteredMs = Math.max(1, Math.round(baseDelayMs * (0.5 + Math.random())));
|
|
2437
|
+
return new Promise((resolve) => setTimeout(resolve, jitteredMs));
|
|
2438
|
+
}
|
|
2439
|
+
function buildLockConflictError(id, info, waitedMs) {
|
|
2440
|
+
const waitedSuffix = waitedMs > 0 ? ` after waiting ${waitedMs}ms` : "";
|
|
2441
|
+
return new PmCliError(`Item ${id} is locked${lockOwnerSuffix(info)}${waitedSuffix}`, EXIT_CODE.CONFLICT, {
|
|
2442
|
+
code: "lock_conflict",
|
|
2443
|
+
recovery: {
|
|
2444
|
+
retry_after_ms: LOCK_CONFLICT_RETRY_HINT_MS
|
|
2358
2445
|
}
|
|
2359
|
-
|
|
2360
|
-
}
|
|
2361
|
-
const scalarRaw = Array.isArray(rawValue) ? rawValue[rawValue.length - 1] : rawValue;
|
|
2362
|
-
if (scalarRaw === void 0) {
|
|
2363
|
-
return void 0;
|
|
2364
|
-
}
|
|
2365
|
-
if (definition.type === "number") {
|
|
2366
|
-
return parseNumberValue(scalarRaw, label);
|
|
2367
|
-
}
|
|
2368
|
-
if (definition.type === "boolean") {
|
|
2369
|
-
return parseBooleanValue(scalarRaw, label);
|
|
2370
|
-
}
|
|
2371
|
-
return typeof scalarRaw === "string" ? scalarRaw : String(scalarRaw);
|
|
2446
|
+
});
|
|
2372
2447
|
}
|
|
2373
|
-
function
|
|
2374
|
-
if (
|
|
2375
|
-
return
|
|
2448
|
+
function resolveLockOverrideRelease(result) {
|
|
2449
|
+
if (typeof result === "function") {
|
|
2450
|
+
return result;
|
|
2376
2451
|
}
|
|
2377
|
-
if (
|
|
2378
|
-
|
|
2452
|
+
if (typeof result === "object" && result !== null && "release" in result) {
|
|
2453
|
+
const release = result.release;
|
|
2454
|
+
return typeof release === "function" ? release : null;
|
|
2379
2455
|
}
|
|
2380
|
-
|
|
2381
|
-
|
|
2456
|
+
return null;
|
|
2457
|
+
}
|
|
2458
|
+
function throwIfStaleLockNeedsForce(id, lockInfo, force, forceRequired) {
|
|
2459
|
+
if (!force && forceRequired) {
|
|
2460
|
+
const warningSuffix = lockInfo.warnings.length > 0 ? ` (${lockInfo.warnings.join(",")})` : "";
|
|
2461
|
+
throw new PmCliError(`Item ${id} lock is stale${warningSuffix}; rerun with --force when supported for this command`, EXIT_CODE.CONFLICT);
|
|
2382
2462
|
}
|
|
2383
|
-
return definition.required_types.map((value) => value.toLowerCase()).includes(itemTypeName.trim().toLowerCase());
|
|
2384
2463
|
}
|
|
2385
|
-
function
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
if (shouldRequireFieldOnCreate(definition, itemTypeName)) {
|
|
2392
|
-
missingRequiredFlags.push(`--${definition.cli_flag}`);
|
|
2393
|
-
}
|
|
2394
|
-
continue;
|
|
2395
|
-
}
|
|
2396
|
-
values[definition.metadata_key] = coerceRuntimeFieldValue(definition, rawValue);
|
|
2464
|
+
function parseStaleCleanupGateOwner(raw) {
|
|
2465
|
+
let parsed;
|
|
2466
|
+
try {
|
|
2467
|
+
parsed = JSON.parse(raw);
|
|
2468
|
+
} catch {
|
|
2469
|
+
return null;
|
|
2397
2470
|
}
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
missing_required_flags: [...new Set(missingRequiredFlags)].sort((left, right) => left.localeCompare(right))
|
|
2401
|
-
};
|
|
2402
|
-
}
|
|
2403
|
-
function collectRuntimeUpdateFieldValues(options, fieldRegistry, commands = ["update"]) {
|
|
2404
|
-
const values = {};
|
|
2405
|
-
const definitions = (commands ?? ["update"]).flatMap((command) => fieldRegistry.command_to_fields.get(command) ?? []);
|
|
2406
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2407
|
-
for (const definition of definitions) {
|
|
2408
|
-
const rawValue = readRuntimeFieldOptionValue(options, definition);
|
|
2409
|
-
if (rawValue === void 0) {
|
|
2410
|
-
continue;
|
|
2411
|
-
}
|
|
2412
|
-
if (seen.has(definition.metadata_key)) {
|
|
2413
|
-
continue;
|
|
2414
|
-
}
|
|
2415
|
-
seen.add(definition.metadata_key);
|
|
2416
|
-
values[definition.metadata_key] = coerceRuntimeFieldValue(definition, rawValue);
|
|
2471
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
2472
|
+
return null;
|
|
2417
2473
|
}
|
|
2418
|
-
|
|
2474
|
+
const candidate = parsed;
|
|
2475
|
+
const pid = candidate.pid;
|
|
2476
|
+
const token = candidate.token;
|
|
2477
|
+
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || typeof token !== "string" || token.length === 0) {
|
|
2478
|
+
return null;
|
|
2479
|
+
}
|
|
2480
|
+
return { pid, token };
|
|
2419
2481
|
}
|
|
2420
|
-
|
|
2421
|
-
// dist/core/item/item-format-version.js
|
|
2422
|
-
!(function() {
|
|
2482
|
+
async function readStaleCleanupGateOwner(gatePath) {
|
|
2423
2483
|
try {
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
}
|
|
2428
|
-
})();
|
|
2429
|
-
var BASELINE_ITEM_FORMAT_VERSION = 1;
|
|
2430
|
-
var CURRENT_ITEM_FORMAT_VERSION = 1;
|
|
2431
|
-
function effectiveItemFormatVersion(metadata) {
|
|
2432
|
-
const raw = metadata.pm_format_version;
|
|
2433
|
-
if (typeof raw === "number" && Number.isInteger(raw) && raw >= BASELINE_ITEM_FORMAT_VERSION) {
|
|
2434
|
-
return raw;
|
|
2484
|
+
return parseStaleCleanupGateOwner(await fs.readFile(path.join(gatePath, STALE_CLEANUP_GATE_OWNER_FILE), "utf8"));
|
|
2485
|
+
} catch {
|
|
2486
|
+
return null;
|
|
2435
2487
|
}
|
|
2436
|
-
return BASELINE_ITEM_FORMAT_VERSION;
|
|
2437
2488
|
}
|
|
2438
|
-
function
|
|
2439
|
-
|
|
2440
|
-
|
|
2489
|
+
function isProcessAlive(pid) {
|
|
2490
|
+
try {
|
|
2491
|
+
process.kill(pid, 0);
|
|
2492
|
+
return true;
|
|
2493
|
+
} catch (error) {
|
|
2494
|
+
if (isErrno(error, "ESRCH")) {
|
|
2495
|
+
return false;
|
|
2496
|
+
}
|
|
2497
|
+
return true;
|
|
2441
2498
|
}
|
|
2442
|
-
return value;
|
|
2443
2499
|
}
|
|
2444
|
-
function
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
return
|
|
2500
|
+
async function removeStaleCleanupGateDirectory(gatePath) {
|
|
2501
|
+
try {
|
|
2502
|
+
await fs.rm(gatePath, { recursive: true, force: true });
|
|
2503
|
+
return true;
|
|
2504
|
+
} catch {
|
|
2505
|
+
return false;
|
|
2450
2506
|
}
|
|
2451
|
-
return "current";
|
|
2452
2507
|
}
|
|
2453
|
-
function
|
|
2454
|
-
const
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
const status = classifyItemFormatVersion(entry.version, current);
|
|
2458
|
-
if (status === "outdated") {
|
|
2459
|
-
outdated.push(entry.ref);
|
|
2460
|
-
} else if (status === "ahead") {
|
|
2461
|
-
ahead.push(entry.ref);
|
|
2462
|
-
}
|
|
2508
|
+
async function releaseStaleCleanupGate(gatePath, token) {
|
|
2509
|
+
const owner = await readStaleCleanupGateOwner(gatePath);
|
|
2510
|
+
if (owner === null || owner.token !== token) {
|
|
2511
|
+
return;
|
|
2463
2512
|
}
|
|
2464
|
-
|
|
2465
|
-
outdated: outdated.sort((left, right) => left.localeCompare(right)),
|
|
2466
|
-
ahead: ahead.sort((left, right) => left.localeCompare(right))
|
|
2467
|
-
};
|
|
2513
|
+
await removeStaleCleanupGateDirectory(gatePath);
|
|
2468
2514
|
}
|
|
2469
|
-
|
|
2470
|
-
// dist/core/item/status.js
|
|
2471
|
-
!(function() {
|
|
2515
|
+
async function tryCreateStaleCleanupGate(gatePath) {
|
|
2472
2516
|
try {
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
})();
|
|
2478
|
-
var STATUS_ALIAS_MAP = {
|
|
2479
|
-
"in-progress": "in_progress",
|
|
2480
|
-
cancelled: "canceled"
|
|
2481
|
-
};
|
|
2482
|
-
function normalizeStatusInput(value, registry) {
|
|
2483
|
-
if (registry) {
|
|
2484
|
-
const normalizedFromRegistry = normalizeStatusInputWithRegistry(value, registry);
|
|
2485
|
-
if (normalizedFromRegistry) {
|
|
2486
|
-
return normalizedFromRegistry;
|
|
2517
|
+
await fs.mkdir(gatePath);
|
|
2518
|
+
} catch (error) {
|
|
2519
|
+
if (isErrno(error, "EEXIST")) {
|
|
2520
|
+
return null;
|
|
2487
2521
|
}
|
|
2522
|
+
return null;
|
|
2488
2523
|
}
|
|
2489
|
-
|
|
2490
|
-
return void 0;
|
|
2491
|
-
}
|
|
2492
|
-
const normalized = value.trim().toLowerCase();
|
|
2493
|
-
if (!normalized) {
|
|
2494
|
-
return void 0;
|
|
2495
|
-
}
|
|
2496
|
-
const canonical = STATUS_ALIAS_MAP[normalized] ?? normalized;
|
|
2497
|
-
if (!STATUS_VALUES.includes(canonical)) {
|
|
2498
|
-
return void 0;
|
|
2499
|
-
}
|
|
2500
|
-
return canonical;
|
|
2501
|
-
}
|
|
2502
|
-
function normalizeStatusForRegistry(status, registry) {
|
|
2503
|
-
return normalizeStatusInput(status, registry) ?? status;
|
|
2504
|
-
}
|
|
2505
|
-
function isTerminalStatus(status, registry) {
|
|
2506
|
-
return registry.terminal_statuses.has(normalizeStatusForRegistry(status, registry));
|
|
2507
|
-
}
|
|
2508
|
-
|
|
2509
|
-
// dist/core/item/item-format.js
|
|
2510
|
-
import { encode as encodeToon } from "@toon-format/toon";
|
|
2511
|
-
|
|
2512
|
-
// dist/core/item/toon-decode.js
|
|
2513
|
-
import { decode as decodeToon } from "@toon-format/toon";
|
|
2514
|
-
!(function() {
|
|
2524
|
+
const owner = { pid: process.pid, token: randomUUID() };
|
|
2515
2525
|
try {
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
} catch
|
|
2526
|
+
await fs.writeFile(path.join(gatePath, STALE_CLEANUP_GATE_OWNER_FILE), `${JSON.stringify(owner)}
|
|
2527
|
+
`, "utf8");
|
|
2528
|
+
} catch {
|
|
2529
|
+
await removeStaleCleanupGateDirectory(gatePath);
|
|
2530
|
+
return null;
|
|
2519
2531
|
}
|
|
2520
|
-
|
|
2521
|
-
function escapeBracketsInQuotedScalars(content) {
|
|
2522
|
-
return content.split("\n").map((line) => {
|
|
2523
|
-
const separatorIndex = line.indexOf(": ");
|
|
2524
|
-
const bracketIndex = line.indexOf("[");
|
|
2525
|
-
if (separatorIndex === -1 || bracketIndex === -1 || bracketIndex < separatorIndex) {
|
|
2526
|
-
return line;
|
|
2527
|
-
}
|
|
2528
|
-
const key = line.slice(0, separatorIndex + 2);
|
|
2529
|
-
const value = line.slice(separatorIndex + 2);
|
|
2530
|
-
if (!value.startsWith('"')) {
|
|
2531
|
-
return line;
|
|
2532
|
-
}
|
|
2533
|
-
return key + value.replaceAll("[", "\\u005b");
|
|
2534
|
-
}).join("\n");
|
|
2532
|
+
return owner;
|
|
2535
2533
|
}
|
|
2536
|
-
function
|
|
2534
|
+
async function removeExpiredStaleCleanupGate(gatePath) {
|
|
2535
|
+
let gateAgeMs;
|
|
2537
2536
|
try {
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
throw strictError;
|
|
2537
|
+
const stats = await fs.stat(gatePath);
|
|
2538
|
+
gateAgeMs = Date.now() - stats.mtimeMs;
|
|
2539
|
+
if (gateAgeMs <= STALE_CLEANUP_GATE_STALE_MS) {
|
|
2540
|
+
return false;
|
|
2543
2541
|
}
|
|
2544
|
-
|
|
2542
|
+
} catch (error) {
|
|
2543
|
+
return isErrno(error, "ENOENT");
|
|
2544
|
+
}
|
|
2545
|
+
const owner = await readStaleCleanupGateOwner(gatePath);
|
|
2546
|
+
if (owner !== null && isProcessAlive(owner.pid) && gateAgeMs <= STALE_CLEANUP_GATE_MAX_ACTIVE_MS) {
|
|
2547
|
+
return false;
|
|
2545
2548
|
}
|
|
2549
|
+
return removeStaleCleanupGateDirectory(gatePath);
|
|
2546
2550
|
}
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "d4a8b193-c056-5ac6-b08f-a3fcc10a5ba9");
|
|
2553
|
-
} catch (e2) {
|
|
2551
|
+
async function acquireStaleCleanupGate(lockPath, _id) {
|
|
2552
|
+
const gatePath = `${lockPath}${STALE_CLEANUP_GATE_SUFFIX}`;
|
|
2553
|
+
const owner = await tryCreateStaleCleanupGate(gatePath);
|
|
2554
|
+
if (owner !== null) {
|
|
2555
|
+
return async () => releaseStaleCleanupGate(gatePath, owner.token);
|
|
2554
2556
|
}
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
function findMergeConflictMarkers(content) {
|
|
2558
|
-
if (content.length === 0) {
|
|
2559
|
-
return [];
|
|
2557
|
+
if (!await removeExpiredStaleCleanupGate(gatePath)) {
|
|
2558
|
+
return null;
|
|
2560
2559
|
}
|
|
2561
|
-
const
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
const line = lines[index] ?? "";
|
|
2565
|
-
const markerMatch = line.match(CONFLICT_MARKER_PATTERN);
|
|
2566
|
-
if (!markerMatch) {
|
|
2567
|
-
continue;
|
|
2568
|
-
}
|
|
2569
|
-
const marker = markerMatch[1];
|
|
2570
|
-
matches.push({
|
|
2571
|
-
line: index + 1,
|
|
2572
|
-
marker,
|
|
2573
|
-
text: line
|
|
2574
|
-
});
|
|
2560
|
+
const recoveredOwner = await tryCreateStaleCleanupGate(gatePath);
|
|
2561
|
+
if (recoveredOwner === null) {
|
|
2562
|
+
return null;
|
|
2575
2563
|
}
|
|
2576
|
-
return
|
|
2577
|
-
}
|
|
2578
|
-
function findFirstMergeConflictMarker(content) {
|
|
2579
|
-
const matches = findMergeConflictMarkers(content);
|
|
2580
|
-
return matches[0];
|
|
2564
|
+
return async () => releaseStaleCleanupGate(gatePath, recoveredOwner.token);
|
|
2581
2565
|
}
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2566
|
+
async function removeConfirmedStaleLock(params) {
|
|
2567
|
+
const releaseCleanupGate = await acquireStaleCleanupGate(params.lockPath, params.id);
|
|
2568
|
+
if (releaseCleanupGate === null) {
|
|
2569
|
+
return {
|
|
2570
|
+
lockInfo: params.fallbackLockInfo,
|
|
2571
|
+
shouldRetryCreate: false,
|
|
2572
|
+
staleRemovalCounted: false
|
|
2573
|
+
};
|
|
2589
2574
|
}
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
}
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
return comparison;
|
|
2575
|
+
try {
|
|
2576
|
+
const currentLockInfo = await readLockInfo(params.lockPath);
|
|
2577
|
+
if (currentLockInfo.info === null && currentLockInfo.warnings.length === 0) {
|
|
2578
|
+
return {
|
|
2579
|
+
lockInfo: currentLockInfo,
|
|
2580
|
+
shouldRetryCreate: true,
|
|
2581
|
+
staleRemovalCounted: false
|
|
2582
|
+
};
|
|
2583
|
+
}
|
|
2584
|
+
if (!isStaleLock(currentLockInfo.info, params.ttlSeconds)) {
|
|
2585
|
+
return {
|
|
2586
|
+
lockInfo: currentLockInfo,
|
|
2587
|
+
shouldRetryCreate: false,
|
|
2588
|
+
staleRemovalCounted: false
|
|
2589
|
+
};
|
|
2590
|
+
}
|
|
2591
|
+
throwIfStaleLockNeedsForce(params.id, currentLockInfo, params.force, params.forceRequiredForStaleLock);
|
|
2592
|
+
if (params.staleRemovals >= MAX_STALE_LOCK_REMOVALS) {
|
|
2593
|
+
throw buildLockConflictError(params.id, currentLockInfo.info, Date.now() - params.startedAtMs);
|
|
2610
2594
|
}
|
|
2595
|
+
return {
|
|
2596
|
+
lockInfo: currentLockInfo,
|
|
2597
|
+
shouldRetryCreate: await unlinkLockWithHook(params.lockPath, "lock:stale_remove"),
|
|
2598
|
+
staleRemovalCounted: true
|
|
2599
|
+
};
|
|
2600
|
+
} finally {
|
|
2601
|
+
await releaseCleanupGate();
|
|
2611
2602
|
}
|
|
2612
|
-
return 0;
|
|
2613
2603
|
}
|
|
2614
|
-
function
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2604
|
+
async function acquireLock(pmRoot, id, ttlSeconds, owner, force = false, forceRequiredForStaleLock = true, waitMs) {
|
|
2605
|
+
const lockOverride = await runActiveServiceOverride("lock_acquire", {
|
|
2606
|
+
pm_root: pmRoot,
|
|
2607
|
+
id,
|
|
2608
|
+
ttl_seconds: ttlSeconds,
|
|
2609
|
+
owner,
|
|
2610
|
+
force,
|
|
2611
|
+
force_required_for_stale_lock: forceRequiredForStaleLock
|
|
2612
|
+
});
|
|
2613
|
+
if (lockOverride.handled) {
|
|
2614
|
+
const release = resolveLockOverrideRelease(lockOverride.result);
|
|
2615
|
+
if (release) {
|
|
2616
|
+
return async () => {
|
|
2617
|
+
await Promise.resolve(release());
|
|
2618
|
+
await runActiveServiceOverride("lock_release", {
|
|
2619
|
+
pm_root: pmRoot,
|
|
2620
|
+
id,
|
|
2621
|
+
owner
|
|
2622
|
+
});
|
|
2623
|
+
};
|
|
2618
2624
|
}
|
|
2619
2625
|
}
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2626
|
+
const lockPath = getLockPath(pmRoot, id);
|
|
2627
|
+
const waitBudgetMs = resolveLockWaitMs(waitMs);
|
|
2628
|
+
const startedAtMs = Date.now();
|
|
2629
|
+
let staleRemovals = 0;
|
|
2630
|
+
let backoffMs = LOCK_WAIT_INITIAL_DELAY_MS;
|
|
2631
|
+
for (; ; ) {
|
|
2632
|
+
try {
|
|
2633
|
+
await createLockFile(lockPath, id, owner, ttlSeconds);
|
|
2634
|
+
return async () => {
|
|
2635
|
+
await unlinkLockWithHook(lockPath, "lock:release");
|
|
2636
|
+
await runActiveServiceOverride("lock_release", {
|
|
2637
|
+
pm_root: pmRoot,
|
|
2638
|
+
id,
|
|
2639
|
+
owner
|
|
2640
|
+
});
|
|
2641
|
+
};
|
|
2642
|
+
} catch (error) {
|
|
2643
|
+
if (!isErrno(error, "EEXIST")) {
|
|
2644
|
+
throw new PmCliError(`Failed to acquire lock for ${id}: ${toErrorMessage(error)}`, EXIT_CODE.GENERIC_FAILURE);
|
|
2645
|
+
}
|
|
2646
|
+
let lockInfo = await readLockInfo(lockPath);
|
|
2647
|
+
if (isStaleLock(lockInfo.info, ttlSeconds)) {
|
|
2648
|
+
const staleRemoval = await removeConfirmedStaleLock({
|
|
2649
|
+
lockPath,
|
|
2650
|
+
id,
|
|
2651
|
+
ttlSeconds,
|
|
2652
|
+
force,
|
|
2653
|
+
forceRequiredForStaleLock,
|
|
2654
|
+
staleRemovals,
|
|
2655
|
+
waitBudgetMs,
|
|
2656
|
+
startedAtMs,
|
|
2657
|
+
fallbackLockInfo: lockInfo
|
|
2658
|
+
});
|
|
2659
|
+
lockInfo = staleRemoval.lockInfo;
|
|
2660
|
+
if (staleRemoval.staleRemovalCounted) {
|
|
2661
|
+
staleRemovals += 1;
|
|
2662
|
+
}
|
|
2663
|
+
if (staleRemoval.shouldRetryCreate) {
|
|
2664
|
+
continue;
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2667
|
+
const elapsedMs = Date.now() - startedAtMs;
|
|
2668
|
+
if (waitBudgetMs === 0 || elapsedMs >= waitBudgetMs) {
|
|
2669
|
+
throw buildLockConflictError(id, lockInfo.info, waitBudgetMs === 0 ? 0 : elapsedMs);
|
|
2670
|
+
}
|
|
2671
|
+
await sleepWithJitter(Math.min(backoffMs, waitBudgetMs - elapsedMs));
|
|
2672
|
+
backoffMs = Math.min(backoffMs * 2, LOCK_WAIT_MAX_DELAY_MS);
|
|
2673
|
+
}
|
|
2632
2674
|
}
|
|
2633
|
-
return {
|
|
2634
|
-
statusRegistry: resolveRuntimeStatusRegistry(options.schema),
|
|
2635
|
-
fieldRegistry: resolveRuntimeFieldRegistry(options.schema),
|
|
2636
|
-
unknownFieldPolicy: options.schema.unknown_field_policy ?? "allow",
|
|
2637
|
-
extensionFieldNames: new Set(options.extensionFieldNames ?? []),
|
|
2638
|
-
onWarning: options.onWarning
|
|
2639
|
-
};
|
|
2640
2675
|
}
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2676
|
+
|
|
2677
|
+
// dist/core/schema/runtime-field-values.js
|
|
2678
|
+
!(function() {
|
|
2679
|
+
try {
|
|
2680
|
+
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
2681
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "e31fbd91-9662-592e-abd5-1db822ac04eb");
|
|
2682
|
+
} catch (e2) {
|
|
2644
2683
|
}
|
|
2645
|
-
|
|
2646
|
-
|
|
2684
|
+
})();
|
|
2685
|
+
function toCamelToken(value) {
|
|
2686
|
+
const segments = value.trim().replaceAll(/[^A-Za-z0-9]+/g, " ").split(/\s+/).filter((segment) => segment.length > 0).map((segment) => segment.toLowerCase());
|
|
2687
|
+
if (segments.length === 0) {
|
|
2688
|
+
return value;
|
|
2647
2689
|
}
|
|
2648
|
-
|
|
2690
|
+
const [first, ...rest] = segments;
|
|
2691
|
+
return `${first}${rest.map((segment) => `${segment.slice(0, 1).toUpperCase()}${segment.slice(1)}`).join("")}`;
|
|
2649
2692
|
}
|
|
2650
|
-
function
|
|
2651
|
-
|
|
2693
|
+
function resolveCandidateOptionKeys(definition) {
|
|
2694
|
+
return [
|
|
2695
|
+
.../* @__PURE__ */ new Set([
|
|
2696
|
+
runtimeFieldOptionTarget(definition),
|
|
2697
|
+
toCamelToken(definition.key),
|
|
2698
|
+
toCamelToken(definition.cli_flag),
|
|
2699
|
+
...definition.cli_aliases.map((alias) => toCamelToken(alias))
|
|
2700
|
+
])
|
|
2701
|
+
];
|
|
2652
2702
|
}
|
|
2653
|
-
function
|
|
2654
|
-
const
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2703
|
+
function readRuntimeFieldOptionValue(options, definition) {
|
|
2704
|
+
for (const candidateKey of resolveCandidateOptionKeys(definition)) {
|
|
2705
|
+
if (!Object.hasOwn(options, candidateKey)) {
|
|
2706
|
+
continue;
|
|
2707
|
+
}
|
|
2708
|
+
const value = options[candidateKey];
|
|
2709
|
+
if (value !== void 0) {
|
|
2710
|
+
return value;
|
|
2711
|
+
}
|
|
2660
2712
|
}
|
|
2661
|
-
return
|
|
2713
|
+
return void 0;
|
|
2662
2714
|
}
|
|
2663
|
-
function
|
|
2664
|
-
if (
|
|
2665
|
-
|
|
2715
|
+
function normalizeStringArrayValue(value) {
|
|
2716
|
+
if (Array.isArray(value)) {
|
|
2717
|
+
return value.flatMap((entry) => normalizeStringArrayValue(entry)).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
2666
2718
|
}
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
const rawValue = record[fieldName];
|
|
2670
|
-
assertItemMetadataCondition(typeof rawValue === "string", `${fieldName} must be a string`);
|
|
2671
|
-
const timestamp = rawValue;
|
|
2672
|
-
assertItemMetadataCondition(isTimestampLiteral(timestamp), `${fieldName} must be a valid ISO timestamp`);
|
|
2673
|
-
}
|
|
2674
|
-
function assertPositiveIntegerField(record, fieldName, messagePrefix) {
|
|
2675
|
-
const value = record[fieldName];
|
|
2676
|
-
if (value === void 0) {
|
|
2677
|
-
return;
|
|
2719
|
+
if (typeof value === "string") {
|
|
2720
|
+
return value.split(/[,\n|]/).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
2678
2721
|
}
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
function assertOptionalTimestampString(record, fieldName, messagePrefix) {
|
|
2682
|
-
const value = record[fieldName];
|
|
2683
|
-
if (value === void 0) {
|
|
2684
|
-
return;
|
|
2722
|
+
if (value === void 0 || value === null) {
|
|
2723
|
+
return [];
|
|
2685
2724
|
}
|
|
2686
|
-
|
|
2687
|
-
assertItemMetadataCondition(isTimestampLiteral(value), `${messagePrefix} must be a valid ISO timestamp`);
|
|
2725
|
+
return [String(value).trim()].filter((entry) => entry.length > 0);
|
|
2688
2726
|
}
|
|
2689
|
-
function
|
|
2690
|
-
if (
|
|
2691
|
-
return;
|
|
2692
|
-
}
|
|
2693
|
-
assertItemMetadataCondition(Array.isArray(value), "event.recurrence.by_weekday must be an array");
|
|
2694
|
-
for (const weekday of value) {
|
|
2695
|
-
assertItemMetadataCondition(typeof weekday === "string", "event.recurrence.by_weekday entries must be strings");
|
|
2696
|
-
const normalizedWeekday = weekday.trim().toLowerCase();
|
|
2697
|
-
assertItemMetadataCondition(RECURRENCE_WEEKDAY_VALUES.includes(normalizedWeekday), `event.recurrence.by_weekday entries must be one of: ${RECURRENCE_WEEKDAY_VALUES.join(", ")}`);
|
|
2727
|
+
function parseBooleanValue(raw, label) {
|
|
2728
|
+
if (typeof raw === "boolean") {
|
|
2729
|
+
return raw;
|
|
2698
2730
|
}
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2731
|
+
if (typeof raw === "number") {
|
|
2732
|
+
if (raw === 1) {
|
|
2733
|
+
return true;
|
|
2734
|
+
}
|
|
2735
|
+
if (raw === 0) {
|
|
2736
|
+
return false;
|
|
2737
|
+
}
|
|
2703
2738
|
}
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2739
|
+
if (typeof raw === "string") {
|
|
2740
|
+
const normalized = raw.trim().toLowerCase();
|
|
2741
|
+
if (normalized === "true" || normalized === "1" || normalized === "yes") {
|
|
2742
|
+
return true;
|
|
2743
|
+
}
|
|
2744
|
+
if (normalized === "false" || normalized === "0" || normalized === "no") {
|
|
2745
|
+
return false;
|
|
2746
|
+
}
|
|
2707
2747
|
}
|
|
2748
|
+
throw new PmCliError(`${label} must be one of true|false|1|0|yes|no`, EXIT_CODE.USAGE);
|
|
2708
2749
|
}
|
|
2709
|
-
function
|
|
2710
|
-
if (
|
|
2711
|
-
return;
|
|
2712
|
-
}
|
|
2713
|
-
assertItemMetadataCondition(Array.isArray(value), "event.recurrence.exdates must be an array");
|
|
2714
|
-
for (const exdate of value) {
|
|
2715
|
-
assertItemMetadataCondition(typeof exdate === "string", "event.recurrence.exdates entries must be strings");
|
|
2716
|
-
assertItemMetadataCondition(isTimestampLiteral(exdate), "event.recurrence.exdates entries must be valid ISO timestamps");
|
|
2717
|
-
}
|
|
2718
|
-
}
|
|
2719
|
-
function assertValidRecurrenceRule(recurrence) {
|
|
2720
|
-
assertItemMetadataCondition(typeof recurrence === "object" && recurrence !== null && !Array.isArray(recurrence), "event.recurrence must be an object");
|
|
2721
|
-
const recurrenceRecord = recurrence;
|
|
2722
|
-
assertItemMetadataCondition(typeof recurrenceRecord.freq === "string", "event.recurrence.freq must be a string");
|
|
2723
|
-
const frequency = recurrenceRecord.freq.trim().toLowerCase();
|
|
2724
|
-
assertItemMetadataCondition(RECURRENCE_FREQUENCY_VALUES.includes(frequency), `event.recurrence.freq must be one of: ${RECURRENCE_FREQUENCY_VALUES.join(", ")}`);
|
|
2725
|
-
assertPositiveIntegerField(recurrenceRecord, "interval", "event.recurrence.interval");
|
|
2726
|
-
assertPositiveIntegerField(recurrenceRecord, "count", "event.recurrence.count");
|
|
2727
|
-
assertOptionalTimestampString(recurrenceRecord, "until", "event.recurrence.until");
|
|
2728
|
-
assertRecurrenceWeekdays(recurrenceRecord.by_weekday);
|
|
2729
|
-
assertRecurrenceMonthDays(recurrenceRecord.by_month_day);
|
|
2730
|
-
assertRecurrenceExdates(recurrenceRecord.exdates);
|
|
2731
|
-
}
|
|
2732
|
-
function assertRequiredItemMetadataFields(record) {
|
|
2733
|
-
for (const fieldName of REQUIRED_STRING_FIELDS) {
|
|
2734
|
-
assertItemMetadataCondition(typeof record[fieldName] === "string", `${fieldName} is required and must be a string`);
|
|
2750
|
+
function parseNumberValue(raw, label) {
|
|
2751
|
+
if (typeof raw === "number" && Number.isFinite(raw)) {
|
|
2752
|
+
return raw;
|
|
2735
2753
|
}
|
|
2736
|
-
const
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
assertItemMetadataCondition(typeof formatVersion === "number" && Number.isInteger(formatVersion) && formatVersion >= BASELINE_ITEM_FORMAT_VERSION, `pm_format_version must be an integer >= ${BASELINE_ITEM_FORMAT_VERSION}`);
|
|
2754
|
+
const candidate = typeof raw === "string" ? raw.trim() : String(raw);
|
|
2755
|
+
const parsed = Number(candidate);
|
|
2756
|
+
if (!Number.isFinite(parsed)) {
|
|
2757
|
+
throw new PmCliError(`${label} must be a number`, EXIT_CODE.USAGE);
|
|
2741
2758
|
}
|
|
2742
|
-
return
|
|
2743
|
-
}
|
|
2744
|
-
function assertStatusItemMetadataField(record, runtimeContext) {
|
|
2745
|
-
const status = record.status;
|
|
2746
|
-
assertItemMetadataCondition(typeof status === "string" && status.trim().length > 0, "status must be a non-empty string");
|
|
2747
|
-
const statusRegistry = runtimeContext?.statusRegistry;
|
|
2748
|
-
const normalizedStatus = normalizeStatusInput(status, statusRegistry);
|
|
2749
|
-
const statusDomain = statusRegistry ? statusRegistry.definitions.map((definition) => definition.id) : [...STATUS_VALUES];
|
|
2750
|
-
assertItemMetadataCondition(normalizedStatus !== void 0, `status must be one of: ${statusDomain.join(", ")}`);
|
|
2759
|
+
return parsed;
|
|
2751
2760
|
}
|
|
2752
|
-
function
|
|
2753
|
-
const
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2761
|
+
function coerceRuntimeFieldValue(definition, rawValue, labelOverride) {
|
|
2762
|
+
const label = labelOverride ?? `--${definition.cli_flag}`;
|
|
2763
|
+
if (definition.repeatable || definition.type === "string_array") {
|
|
2764
|
+
const values = normalizeStringArrayValue(rawValue);
|
|
2765
|
+
if (definition.type === "number") {
|
|
2766
|
+
return values.map((value) => parseNumberValue(value, label));
|
|
2767
|
+
}
|
|
2768
|
+
if (definition.type === "boolean") {
|
|
2769
|
+
return values.map((value) => parseBooleanValue(value, label));
|
|
2770
|
+
}
|
|
2771
|
+
return values;
|
|
2759
2772
|
}
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
if (confidence === void 0) {
|
|
2764
|
-
return;
|
|
2773
|
+
const scalarRaw = Array.isArray(rawValue) ? rawValue[rawValue.length - 1] : rawValue;
|
|
2774
|
+
if (scalarRaw === void 0) {
|
|
2775
|
+
return void 0;
|
|
2765
2776
|
}
|
|
2766
|
-
if (
|
|
2767
|
-
|
|
2768
|
-
return;
|
|
2777
|
+
if (definition.type === "number") {
|
|
2778
|
+
return parseNumberValue(scalarRaw, label);
|
|
2769
2779
|
}
|
|
2770
|
-
if (
|
|
2771
|
-
|
|
2772
|
-
const isKnownTextConfidence = normalizedConfidence === "med" || CONFIDENCE_TEXT_VALUES.includes(normalizedConfidence);
|
|
2773
|
-
assertItemMetadataCondition(isKnownTextConfidence, `confidence string value must be one of: ${[...CONFIDENCE_TEXT_VALUES, "med"].join(", ")}`);
|
|
2774
|
-
return;
|
|
2780
|
+
if (definition.type === "boolean") {
|
|
2781
|
+
return parseBooleanValue(scalarRaw, label);
|
|
2775
2782
|
}
|
|
2776
|
-
|
|
2783
|
+
return typeof scalarRaw === "string" ? scalarRaw : String(scalarRaw);
|
|
2777
2784
|
}
|
|
2778
|
-
function
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
return;
|
|
2785
|
+
function shouldRequireFieldOnCreate(definition, itemTypeName) {
|
|
2786
|
+
if (!definition.required && !definition.required_on_create) {
|
|
2787
|
+
return false;
|
|
2782
2788
|
}
|
|
2783
|
-
if (
|
|
2784
|
-
|
|
2789
|
+
if (definition.required_types.length === 0) {
|
|
2790
|
+
return true;
|
|
2785
2791
|
}
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
assertItemMetadataCondition(isKnownSeverity, `severity value must be one of: ${[...ISSUE_SEVERITY_VALUES, "med"].join(", ")}`);
|
|
2789
|
-
}
|
|
2790
|
-
function assertRegressionItemMetadataField(record) {
|
|
2791
|
-
if (record.regression !== void 0 && typeof record.regression !== "boolean") {
|
|
2792
|
-
validationError("regression must be a boolean");
|
|
2792
|
+
if (!itemTypeName) {
|
|
2793
|
+
return false;
|
|
2793
2794
|
}
|
|
2795
|
+
return definition.required_types.map((value) => value.toLowerCase()).includes(itemTypeName.trim().toLowerCase());
|
|
2794
2796
|
}
|
|
2795
|
-
function
|
|
2796
|
-
const
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
assertItemMetadataCondition(reminderRecord.text.trim().length > 0, "reminder.text must not be empty");
|
|
2797
|
+
function collectRuntimeCreateFieldValues(options, fieldRegistry, itemTypeName) {
|
|
2798
|
+
const values = {};
|
|
2799
|
+
const missingRequiredFlags = [];
|
|
2800
|
+
for (const definition of fieldRegistry.command_to_fields.get("create") ?? []) {
|
|
2801
|
+
const rawValue = readRuntimeFieldOptionValue(options, definition);
|
|
2802
|
+
if (rawValue === void 0) {
|
|
2803
|
+
if (shouldRequireFieldOnCreate(definition, itemTypeName)) {
|
|
2804
|
+
missingRequiredFlags.push(`--${definition.cli_flag}`);
|
|
2805
|
+
}
|
|
2806
|
+
continue;
|
|
2807
|
+
}
|
|
2808
|
+
values[definition.metadata_key] = coerceRuntimeFieldValue(definition, rawValue);
|
|
2808
2809
|
}
|
|
2810
|
+
return {
|
|
2811
|
+
values,
|
|
2812
|
+
missing_required_flags: [...new Set(missingRequiredFlags)].sort((left, right) => left.localeCompare(right))
|
|
2813
|
+
};
|
|
2809
2814
|
}
|
|
2810
|
-
function
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2815
|
+
function collectRuntimeUpdateFieldValues(options, fieldRegistry, commands = ["update"]) {
|
|
2816
|
+
const values = {};
|
|
2817
|
+
const definitions = (commands ?? ["update"]).flatMap((command) => fieldRegistry.command_to_fields.get(command) ?? []);
|
|
2818
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2819
|
+
for (const definition of definitions) {
|
|
2820
|
+
const rawValue = readRuntimeFieldOptionValue(options, definition);
|
|
2821
|
+
if (rawValue === void 0) {
|
|
2822
|
+
continue;
|
|
2823
|
+
}
|
|
2824
|
+
if (seen.has(definition.metadata_key)) {
|
|
2825
|
+
continue;
|
|
2820
2826
|
}
|
|
2827
|
+
seen.add(definition.metadata_key);
|
|
2828
|
+
values[definition.metadata_key] = coerceRuntimeFieldValue(definition, rawValue);
|
|
2821
2829
|
}
|
|
2830
|
+
return values;
|
|
2822
2831
|
}
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2832
|
+
|
|
2833
|
+
// dist/core/item/item-format-version.js
|
|
2834
|
+
!(function() {
|
|
2835
|
+
try {
|
|
2836
|
+
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
2837
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "08a25299-87bd-5c86-8e00-c42c5183e555");
|
|
2838
|
+
} catch (e2) {
|
|
2826
2839
|
}
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2840
|
+
})();
|
|
2841
|
+
var BASELINE_ITEM_FORMAT_VERSION = 1;
|
|
2842
|
+
var CURRENT_ITEM_FORMAT_VERSION = 1;
|
|
2843
|
+
function effectiveItemFormatVersion(metadata) {
|
|
2844
|
+
const raw = metadata.pm_format_version;
|
|
2845
|
+
if (typeof raw === "number" && Number.isInteger(raw) && raw >= BASELINE_ITEM_FORMAT_VERSION) {
|
|
2846
|
+
return raw;
|
|
2830
2847
|
}
|
|
2848
|
+
return BASELINE_ITEM_FORMAT_VERSION;
|
|
2831
2849
|
}
|
|
2832
|
-
function
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
assertItemMetadataCondition(typeof eventRecord.start_at === "string", "event.start_at must be a string");
|
|
2836
|
-
assertItemMetadataCondition(isTimestampLiteral(eventRecord.start_at), "event.start_at must be a valid ISO timestamp");
|
|
2837
|
-
if (eventRecord.end_at !== void 0) {
|
|
2838
|
-
assertItemMetadataCondition(typeof eventRecord.end_at === "string", "event.end_at must be a string");
|
|
2839
|
-
assertItemMetadataCondition(isTimestampLiteral(eventRecord.end_at), "event.end_at must be a valid ISO timestamp");
|
|
2840
|
-
assertItemMetadataCondition(compareTimestampStrings(eventRecord.end_at, eventRecord.start_at) > 0, "event.end_at must be after event.start_at");
|
|
2841
|
-
}
|
|
2842
|
-
assertEventStringFields(eventRecord);
|
|
2843
|
-
if (eventRecord.all_day !== void 0) {
|
|
2844
|
-
assertItemMetadataCondition(typeof eventRecord.all_day === "boolean", "event.all_day must be a boolean");
|
|
2850
|
+
function normalizeItemFormatVersion(value) {
|
|
2851
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value <= BASELINE_ITEM_FORMAT_VERSION) {
|
|
2852
|
+
return void 0;
|
|
2845
2853
|
}
|
|
2846
|
-
|
|
2854
|
+
return value;
|
|
2847
2855
|
}
|
|
2848
|
-
function
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
return;
|
|
2856
|
+
function classifyItemFormatVersion(version, current = CURRENT_ITEM_FORMAT_VERSION) {
|
|
2857
|
+
if (version < current) {
|
|
2858
|
+
return "outdated";
|
|
2852
2859
|
}
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
assertCalendarEventEntry(event);
|
|
2860
|
+
if (version > current) {
|
|
2861
|
+
return "ahead";
|
|
2856
2862
|
}
|
|
2863
|
+
return "current";
|
|
2857
2864
|
}
|
|
2858
|
-
function
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
"
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
assertItemMetadataCondition(typeof value === "string", `${fieldName} must be a string`);
|
|
2865
|
+
function scanItemFormatVersions(entries, current = CURRENT_ITEM_FORMAT_VERSION) {
|
|
2866
|
+
const outdated = [];
|
|
2867
|
+
const ahead = [];
|
|
2868
|
+
for (const entry of entries) {
|
|
2869
|
+
const status = classifyItemFormatVersion(entry.version, current);
|
|
2870
|
+
if (status === "outdated") {
|
|
2871
|
+
outdated.push(entry.ref);
|
|
2872
|
+
} else if (status === "ahead") {
|
|
2873
|
+
ahead.push(entry.ref);
|
|
2868
2874
|
}
|
|
2869
2875
|
}
|
|
2876
|
+
return {
|
|
2877
|
+
outdated: outdated.sort((left, right) => left.localeCompare(right)),
|
|
2878
|
+
ahead: ahead.sort((left, right) => left.localeCompare(right))
|
|
2879
|
+
};
|
|
2870
2880
|
}
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
assertItemMetadataCondition(optionKey.trim().length > 0, "type_options keys must be non-empty");
|
|
2879
|
-
assertItemMetadataCondition(typeof optionValue === "string", "type_options values must be strings");
|
|
2880
|
-
const optionText = optionValue;
|
|
2881
|
-
assertItemMetadataCondition(optionText.trim().length > 0, "type_options values must be non-empty strings");
|
|
2882
|
-
}
|
|
2883
|
-
}
|
|
2884
|
-
function coerceRuntimeItemMetadataFields(record, itemType, runtimeContext) {
|
|
2885
|
-
if (!runtimeContext?.fieldRegistry) {
|
|
2886
|
-
return;
|
|
2881
|
+
|
|
2882
|
+
// dist/core/item/status.js
|
|
2883
|
+
!(function() {
|
|
2884
|
+
try {
|
|
2885
|
+
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
2886
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "fd8870cc-85e1-502e-acd4-a6049537c9e3");
|
|
2887
|
+
} catch (e2) {
|
|
2887
2888
|
}
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
} catch (error) {
|
|
2899
|
-
validationError(String(error?.message).replace(/^Invalid\s+/u, ""));
|
|
2889
|
+
})();
|
|
2890
|
+
var STATUS_ALIAS_MAP = {
|
|
2891
|
+
"in-progress": "in_progress",
|
|
2892
|
+
cancelled: "canceled"
|
|
2893
|
+
};
|
|
2894
|
+
function normalizeStatusInput(value, registry) {
|
|
2895
|
+
if (registry) {
|
|
2896
|
+
const normalizedFromRegistry = normalizeStatusInputWithRegistry(value, registry);
|
|
2897
|
+
if (normalizedFromRegistry) {
|
|
2898
|
+
return normalizedFromRegistry;
|
|
2900
2899
|
}
|
|
2901
2900
|
}
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
if (!runtimeContext || runtimeContext.unknownFieldPolicy === "allow") {
|
|
2905
|
-
return;
|
|
2901
|
+
if (typeof value !== "string") {
|
|
2902
|
+
return void 0;
|
|
2906
2903
|
}
|
|
2907
|
-
const
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
return;
|
|
2904
|
+
const normalized = value.trim().toLowerCase();
|
|
2905
|
+
if (!normalized) {
|
|
2906
|
+
return void 0;
|
|
2911
2907
|
}
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
runtimeContext.onWarning?.(`item_unknown_schema_fields:${unknownKeys.join(",")}`);
|
|
2908
|
+
const canonical = STATUS_ALIAS_MAP[normalized] ?? normalized;
|
|
2909
|
+
if (!STATUS_VALUES.includes(canonical)) {
|
|
2910
|
+
return void 0;
|
|
2916
2911
|
}
|
|
2912
|
+
return canonical;
|
|
2917
2913
|
}
|
|
2918
|
-
function
|
|
2919
|
-
|
|
2920
|
-
const record = itemMetadata;
|
|
2921
|
-
const itemType = assertRequiredItemMetadataFields(record);
|
|
2922
|
-
assertStatusItemMetadataField(record, runtimeContext);
|
|
2923
|
-
assertPriorityAndTags(record);
|
|
2924
|
-
assertConfidenceItemMetadataField(record);
|
|
2925
|
-
assertSeverityItemMetadataField(record);
|
|
2926
|
-
assertRegressionItemMetadataField(record);
|
|
2927
|
-
assertTimestampField(record, "created_at");
|
|
2928
|
-
assertTimestampField(record, "updated_at");
|
|
2929
|
-
if (record.deadline !== void 0) {
|
|
2930
|
-
assertTimestampField(record, "deadline");
|
|
2931
|
-
}
|
|
2932
|
-
assertReminderEntries(record);
|
|
2933
|
-
assertCalendarEvents(record);
|
|
2934
|
-
assertOptionalTimestampString(record, "closed_at", "closed_at");
|
|
2935
|
-
assertOptionalStringFields(record);
|
|
2936
|
-
assertTypeOptionsField(record);
|
|
2937
|
-
coerceRuntimeItemMetadataFields(record, itemType, runtimeContext);
|
|
2938
|
-
assertRuntimeUnknownItemMetadataFields(record, runtimeContext);
|
|
2914
|
+
function normalizeStatusForRegistry(status, registry) {
|
|
2915
|
+
return normalizeStatusInput(status, registry) ?? status;
|
|
2939
2916
|
}
|
|
2940
|
-
function
|
|
2941
|
-
|
|
2942
|
-
return void 0;
|
|
2943
|
-
return [...values].map((value) => ({
|
|
2944
|
-
id: value.id.trim().toLowerCase(),
|
|
2945
|
-
kind: value.kind,
|
|
2946
|
-
created_at: value.created_at,
|
|
2947
|
-
author: value.author?.trim() || void 0,
|
|
2948
|
-
source_kind: value.source_kind?.trim() || void 0
|
|
2949
|
-
})).sort((a, b) => {
|
|
2950
|
-
const byCreated = compareTimestampStrings(a.created_at, b.created_at);
|
|
2951
|
-
if (byCreated !== 0)
|
|
2952
|
-
return byCreated;
|
|
2953
|
-
const byId = a.id.localeCompare(b.id);
|
|
2954
|
-
if (byId !== 0)
|
|
2955
|
-
return byId;
|
|
2956
|
-
const byKind = a.kind.localeCompare(b.kind);
|
|
2957
|
-
if (byKind !== 0)
|
|
2958
|
-
return byKind;
|
|
2959
|
-
return (a.source_kind ?? "").localeCompare(b.source_kind ?? "");
|
|
2960
|
-
});
|
|
2917
|
+
function isTerminalStatus(status, registry) {
|
|
2918
|
+
return registry.terminal_statuses.has(normalizeStatusForRegistry(status, registry));
|
|
2961
2919
|
}
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
}
|
|
2920
|
+
|
|
2921
|
+
// dist/core/item/item-format.js
|
|
2922
|
+
import { encode as encodeToon } from "@toon-format/toon";
|
|
2923
|
+
|
|
2924
|
+
// dist/core/item/toon-decode.js
|
|
2925
|
+
import { decode as decodeToon } from "@toon-format/toon";
|
|
2926
|
+
!(function() {
|
|
2927
|
+
try {
|
|
2928
|
+
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
2929
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "748d78fa-94ca-562d-bf40-05ec1b2bffc2");
|
|
2930
|
+
} catch (e2) {
|
|
2931
|
+
}
|
|
2932
|
+
})();
|
|
2933
|
+
function escapeBracketsInQuotedScalars(content) {
|
|
2934
|
+
return content.split("\n").map((line) => {
|
|
2935
|
+
const separatorIndex = line.indexOf(": ");
|
|
2936
|
+
const bracketIndex = line.indexOf("[");
|
|
2937
|
+
if (separatorIndex === -1 || bracketIndex === -1 || bracketIndex < separatorIndex) {
|
|
2938
|
+
return line;
|
|
2939
|
+
}
|
|
2940
|
+
const key = line.slice(0, separatorIndex + 2);
|
|
2941
|
+
const value = line.slice(separatorIndex + 2);
|
|
2942
|
+
if (!value.startsWith('"')) {
|
|
2943
|
+
return line;
|
|
2944
|
+
}
|
|
2945
|
+
return key + value.replaceAll("[", "\\u005b");
|
|
2946
|
+
}).join("\n");
|
|
2974
2947
|
}
|
|
2975
|
-
function
|
|
2976
|
-
|
|
2977
|
-
return
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
return a.text.localeCompare(b.text);
|
|
2986
|
-
});
|
|
2987
|
-
return normalized.length === 0 ? void 0 : normalized;
|
|
2948
|
+
function decodeToonItemContent(content) {
|
|
2949
|
+
try {
|
|
2950
|
+
return { value: decodeToon(content), usedScalarBracketEscape: false };
|
|
2951
|
+
} catch (strictError) {
|
|
2952
|
+
const escaped = escapeBracketsInQuotedScalars(content);
|
|
2953
|
+
if (escaped === content) {
|
|
2954
|
+
throw strictError;
|
|
2955
|
+
}
|
|
2956
|
+
return { value: decodeToon(escaped), usedScalarBracketEscape: true };
|
|
2957
|
+
}
|
|
2988
2958
|
}
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2959
|
+
|
|
2960
|
+
// dist/core/shared/conflict-markers.js
|
|
2961
|
+
!(function() {
|
|
2962
|
+
try {
|
|
2963
|
+
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
2964
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "d4a8b193-c056-5ac6-b08f-a3fcc10a5ba9");
|
|
2965
|
+
} catch (e2) {
|
|
2992
2966
|
}
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2967
|
+
})();
|
|
2968
|
+
var CONFLICT_MARKER_PATTERN = /^\s*(<<<<<<<|=======|>>>>>>>)(?:\s.*)?$/;
|
|
2969
|
+
function findMergeConflictMarkers(content) {
|
|
2970
|
+
if (content.length === 0) {
|
|
2971
|
+
return [];
|
|
2996
2972
|
}
|
|
2997
|
-
const
|
|
2998
|
-
const
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
until: value.until?.trim() || void 0,
|
|
3005
|
-
by_weekday: byWeekday.length > 0 ? byWeekday : void 0,
|
|
3006
|
-
by_month_day: byMonthDay.length > 0 ? byMonthDay : void 0,
|
|
3007
|
-
exdates: exdates.length > 0 ? exdates : void 0
|
|
3008
|
-
};
|
|
3009
|
-
for (const [key, fieldValue] of Object.entries(normalized)) {
|
|
3010
|
-
if (fieldValue === void 0) {
|
|
3011
|
-
delete normalized[key];
|
|
2973
|
+
const lines = content.split(/\r?\n/);
|
|
2974
|
+
const matches = [];
|
|
2975
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
2976
|
+
const line = lines[index] ?? "";
|
|
2977
|
+
const markerMatch = line.match(CONFLICT_MARKER_PATTERN);
|
|
2978
|
+
if (!markerMatch) {
|
|
2979
|
+
continue;
|
|
3012
2980
|
}
|
|
2981
|
+
const marker = markerMatch[1];
|
|
2982
|
+
matches.push({
|
|
2983
|
+
line: index + 1,
|
|
2984
|
+
marker,
|
|
2985
|
+
text: line
|
|
2986
|
+
});
|
|
3013
2987
|
}
|
|
3014
|
-
return
|
|
2988
|
+
return matches;
|
|
3015
2989
|
}
|
|
3016
|
-
function
|
|
3017
|
-
|
|
3018
|
-
|
|
2990
|
+
function findFirstMergeConflictMarker(content) {
|
|
2991
|
+
const matches = findMergeConflictMarkers(content);
|
|
2992
|
+
return matches[0];
|
|
2993
|
+
}
|
|
2994
|
+
|
|
2995
|
+
// dist/core/item/item-format.js
|
|
2996
|
+
!(function() {
|
|
2997
|
+
try {
|
|
2998
|
+
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
2999
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "bc77f061-b1cd-5989-9a55-cd4259d397e0");
|
|
3000
|
+
} catch (e2) {
|
|
3019
3001
|
}
|
|
3020
|
-
|
|
3021
|
-
|
|
3002
|
+
})();
|
|
3003
|
+
var LINKED_TEST_PM_CONTEXT_MODE_VALUES = /* @__PURE__ */ new Set([
|
|
3004
|
+
"schema",
|
|
3005
|
+
"tracker",
|
|
3006
|
+
"auto"
|
|
3007
|
+
]);
|
|
3008
|
+
var ITEM_TEST_RUN_STATUS_VALUES = /* @__PURE__ */ new Set([
|
|
3009
|
+
"passed",
|
|
3010
|
+
"failed",
|
|
3011
|
+
"stopped",
|
|
3012
|
+
"canceled"
|
|
3013
|
+
]);
|
|
3014
|
+
var PLAN_STEP_STATUS_SET = new Set(PLAN_STEP_STATUS_VALUES);
|
|
3015
|
+
function normalizePathValue(value) {
|
|
3016
|
+
return value.replaceAll("\\", "/");
|
|
3022
3017
|
}
|
|
3023
|
-
function
|
|
3024
|
-
const
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
all_day: value.all_day,
|
|
3031
|
-
timezone: value.timezone?.trim() || void 0,
|
|
3032
|
-
recurrence: normalizeRecurrenceRule(value.recurrence)
|
|
3033
|
-
};
|
|
3034
|
-
deleteUndefinedFields(event);
|
|
3035
|
-
return event;
|
|
3018
|
+
function firstNonZeroComparison(comparisons) {
|
|
3019
|
+
for (const comparison of comparisons) {
|
|
3020
|
+
if (comparison !== 0) {
|
|
3021
|
+
return comparison;
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
return 0;
|
|
3036
3025
|
}
|
|
3037
|
-
function
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
(a.timezone ?? "").localeCompare(b.timezone ?? ""),
|
|
3044
|
-
(a.location ?? "").localeCompare(b.location ?? ""),
|
|
3045
|
-
(a.description ?? "").localeCompare(b.description ?? ""),
|
|
3046
|
-
JSON.stringify(a.recurrence ?? {}).localeCompare(JSON.stringify(b.recurrence ?? {}))
|
|
3047
|
-
]);
|
|
3048
|
-
}
|
|
3049
|
-
function normalizeFiles(values) {
|
|
3050
|
-
if (!values || values.length === 0)
|
|
3051
|
-
return void 0;
|
|
3052
|
-
return values.map((value) => ({
|
|
3053
|
-
path: normalizePathValue(value.path),
|
|
3054
|
-
scope: value.scope,
|
|
3055
|
-
note: value.note?.trim() || void 0
|
|
3056
|
-
}));
|
|
3026
|
+
function deleteUndefinedFields(record) {
|
|
3027
|
+
for (const [key, value] of Object.entries(record)) {
|
|
3028
|
+
if (value === void 0) {
|
|
3029
|
+
delete record[key];
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3057
3032
|
}
|
|
3058
|
-
|
|
3059
|
-
|
|
3033
|
+
var REQUIRED_STRING_FIELDS = [
|
|
3034
|
+
"id",
|
|
3035
|
+
"title",
|
|
3036
|
+
"description",
|
|
3037
|
+
"created_at",
|
|
3038
|
+
"updated_at"
|
|
3039
|
+
];
|
|
3040
|
+
var STATIC_ITEM_METADATA_FIELD_SET = new Set(ITEM_METADATA_KEY_ORDER);
|
|
3041
|
+
function resolveRuntimeSchemaValidationContext(options) {
|
|
3042
|
+
if (!options?.schema) {
|
|
3060
3043
|
return void 0;
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3044
|
+
}
|
|
3045
|
+
return {
|
|
3046
|
+
statusRegistry: resolveRuntimeStatusRegistry(options.schema),
|
|
3047
|
+
fieldRegistry: resolveRuntimeFieldRegistry(options.schema),
|
|
3048
|
+
unknownFieldPolicy: options.schema.unknown_field_policy ?? "allow",
|
|
3049
|
+
extensionFieldNames: new Set(options.extensionFieldNames ?? []),
|
|
3050
|
+
onWarning: options.onWarning
|
|
3051
|
+
};
|
|
3067
3052
|
}
|
|
3068
|
-
function
|
|
3069
|
-
|
|
3053
|
+
function runtimeFieldRequiredForType(definition, typeName) {
|
|
3054
|
+
if (!definition.required) {
|
|
3055
|
+
return false;
|
|
3056
|
+
}
|
|
3057
|
+
if (definition.required_types.length === 0) {
|
|
3058
|
+
return true;
|
|
3059
|
+
}
|
|
3060
|
+
return definition.required_types.map((value) => value.toLowerCase()).includes(typeName.trim().toLowerCase());
|
|
3070
3061
|
}
|
|
3071
|
-
function
|
|
3072
|
-
|
|
3062
|
+
function validationError(message) {
|
|
3063
|
+
throw new PmCliError(`Invalid item metadata: ${message}`, EXIT_CODE.GENERIC_FAILURE);
|
|
3073
3064
|
}
|
|
3074
|
-
function
|
|
3075
|
-
|
|
3065
|
+
function buildKnownItemMetadataKeys(runtimeContext) {
|
|
3066
|
+
const knownKeys = new Set(STATIC_ITEM_METADATA_FIELD_SET);
|
|
3067
|
+
for (const definition of runtimeContext.fieldRegistry?.definitions ?? []) {
|
|
3068
|
+
knownKeys.add(definition.metadata_key);
|
|
3069
|
+
}
|
|
3070
|
+
for (const fieldName of runtimeContext.extensionFieldNames) {
|
|
3071
|
+
knownKeys.add(fieldName);
|
|
3072
|
+
}
|
|
3073
|
+
return knownKeys;
|
|
3076
3074
|
}
|
|
3077
|
-
function
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
const summary = {
|
|
3082
|
-
run_id: runId,
|
|
3083
|
-
kind,
|
|
3084
|
-
status,
|
|
3085
|
-
started_at: stringOrEmpty(value.started_at),
|
|
3086
|
-
finished_at: stringOrEmpty(value.finished_at),
|
|
3087
|
-
recorded_at: stringOrEmpty(value.recorded_at),
|
|
3088
|
-
attempt: normalizePositiveInteger(value.attempt),
|
|
3089
|
-
resumed_from: value.resumed_from?.trim() || void 0,
|
|
3090
|
-
passed: normalizeNonNegativeInteger(value.passed) ?? 0,
|
|
3091
|
-
failed: normalizeNonNegativeInteger(value.failed) ?? 0,
|
|
3092
|
-
skipped: normalizeNonNegativeInteger(value.skipped) ?? 0,
|
|
3093
|
-
items: normalizeNonNegativeInteger(value.items),
|
|
3094
|
-
linked_tests: normalizeNonNegativeInteger(value.linked_tests),
|
|
3095
|
-
fail_on_skipped_triggered: value.fail_on_skipped_triggered === true ? true : void 0
|
|
3096
|
-
};
|
|
3097
|
-
deleteUndefinedFields(summary);
|
|
3098
|
-
return summary;
|
|
3075
|
+
function assertItemMetadataCondition(condition, message) {
|
|
3076
|
+
if (!condition) {
|
|
3077
|
+
validationError(message);
|
|
3078
|
+
}
|
|
3099
3079
|
}
|
|
3100
|
-
function
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3080
|
+
function assertTimestampField(record, fieldName) {
|
|
3081
|
+
const rawValue = record[fieldName];
|
|
3082
|
+
assertItemMetadataCondition(typeof rawValue === "string", `${fieldName} must be a string`);
|
|
3083
|
+
const timestamp = rawValue;
|
|
3084
|
+
assertItemMetadataCondition(isTimestampLiteral(timestamp), `${fieldName} must be a valid ISO timestamp`);
|
|
3104
3085
|
}
|
|
3105
|
-
function
|
|
3106
|
-
|
|
3107
|
-
|
|
3086
|
+
function assertPositiveIntegerField(record, fieldName, messagePrefix) {
|
|
3087
|
+
const value = record[fieldName];
|
|
3088
|
+
if (value === void 0) {
|
|
3089
|
+
return;
|
|
3108
3090
|
}
|
|
3109
|
-
|
|
3110
|
-
...new Set(value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter((entry) => entry.length > 0))
|
|
3111
|
-
].sort((a, b) => a.localeCompare(b));
|
|
3112
|
-
return normalized.length > 0 ? normalized : void 0;
|
|
3091
|
+
assertItemMetadataCondition(typeof value === "number" && Number.isInteger(value) && value >= 1, `${messagePrefix} must be an integer >= 1`);
|
|
3113
3092
|
}
|
|
3114
|
-
function
|
|
3115
|
-
|
|
3116
|
-
|
|
3093
|
+
function assertOptionalTimestampString(record, fieldName, messagePrefix) {
|
|
3094
|
+
const value = record[fieldName];
|
|
3095
|
+
if (value === void 0) {
|
|
3096
|
+
return;
|
|
3117
3097
|
}
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
}
|
|
3121
|
-
function isUnsafeObjectKey(key) {
|
|
3122
|
-
return key === "__proto__" || key === "constructor" || key === "prototype";
|
|
3098
|
+
assertItemMetadataCondition(typeof value === "string", `${messagePrefix} must be a string`);
|
|
3099
|
+
assertItemMetadataCondition(isTimestampLiteral(value), `${messagePrefix} must be a valid ISO timestamp`);
|
|
3123
3100
|
}
|
|
3124
|
-
function
|
|
3125
|
-
if (
|
|
3126
|
-
return
|
|
3101
|
+
function assertRecurrenceWeekdays(value) {
|
|
3102
|
+
if (value === void 0) {
|
|
3103
|
+
return;
|
|
3127
3104
|
}
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
return void 0;
|
|
3105
|
+
assertItemMetadataCondition(Array.isArray(value), "event.recurrence.by_weekday must be an array");
|
|
3106
|
+
for (const weekday of value) {
|
|
3107
|
+
assertItemMetadataCondition(typeof weekday === "string", "event.recurrence.by_weekday entries must be strings");
|
|
3108
|
+
const normalizedWeekday = weekday.trim().toLowerCase();
|
|
3109
|
+
assertItemMetadataCondition(RECURRENCE_WEEKDAY_VALUES.includes(normalizedWeekday), `event.recurrence.by_weekday entries must be one of: ${RECURRENCE_WEEKDAY_VALUES.join(", ")}`);
|
|
3134
3110
|
}
|
|
3135
|
-
const entries = Object.entries(value).map(([key, recordValue]) => [key.trim(), Number(recordValue)]).filter(([key, recordValue]) => key.length > 0 && !isUnsafeObjectKey(key) && Number.isFinite(recordValue)).sort(([left], [right]) => left.localeCompare(right));
|
|
3136
|
-
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
3137
3111
|
}
|
|
3138
|
-
function
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3112
|
+
function assertRecurrenceMonthDays(value) {
|
|
3113
|
+
if (value === void 0) {
|
|
3114
|
+
return;
|
|
3115
|
+
}
|
|
3116
|
+
assertItemMetadataCondition(Array.isArray(value), "event.recurrence.by_month_day must be an array");
|
|
3117
|
+
for (const day of value) {
|
|
3118
|
+
assertItemMetadataCondition(typeof day === "number" && Number.isInteger(day) && day >= 1 && day <= 31, "event.recurrence.by_month_day entries must be integers 1..31");
|
|
3142
3119
|
}
|
|
3143
|
-
return normalized;
|
|
3144
3120
|
}
|
|
3145
|
-
function
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
shared_host_safe: value.shared_host_safe === true ? true : void 0,
|
|
3155
|
-
assert_stdout_contains: normalizeTrimmedStringList(value.assert_stdout_contains),
|
|
3156
|
-
assert_stdout_regex: normalizeTrimmedStringList(value.assert_stdout_regex),
|
|
3157
|
-
assert_stderr_contains: normalizeTrimmedStringList(value.assert_stderr_contains),
|
|
3158
|
-
assert_stderr_regex: normalizeTrimmedStringList(value.assert_stderr_regex),
|
|
3159
|
-
assert_stdout_min_lines: normalizeNonNegativeInteger(value.assert_stdout_min_lines),
|
|
3160
|
-
assert_json_field_equals: normalizeStringRecord(value.assert_json_field_equals),
|
|
3161
|
-
assert_json_field_gte: normalizeNumericRecord(value.assert_json_field_gte),
|
|
3162
|
-
note: value.note?.trim() || void 0
|
|
3163
|
-
};
|
|
3164
|
-
deleteUndefinedFields(test);
|
|
3165
|
-
return test;
|
|
3121
|
+
function assertRecurrenceExdates(value) {
|
|
3122
|
+
if (value === void 0) {
|
|
3123
|
+
return;
|
|
3124
|
+
}
|
|
3125
|
+
assertItemMetadataCondition(Array.isArray(value), "event.recurrence.exdates must be an array");
|
|
3126
|
+
for (const exdate of value) {
|
|
3127
|
+
assertItemMetadataCondition(typeof exdate === "string", "event.recurrence.exdates entries must be strings");
|
|
3128
|
+
assertItemMetadataCondition(isTimestampLiteral(exdate), "event.recurrence.exdates entries must be valid ISO timestamps");
|
|
3129
|
+
}
|
|
3166
3130
|
}
|
|
3167
|
-
function
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
compareJsonValues(a.assert_stderr_contains, b.assert_stderr_contains, []),
|
|
3180
|
-
compareJsonValues(a.assert_stderr_regex, b.assert_stderr_regex, []),
|
|
3181
|
-
compareOptionalNumbers(a.assert_stdout_min_lines, b.assert_stdout_min_lines),
|
|
3182
|
-
compareJsonValues(a.assert_json_field_equals, b.assert_json_field_equals, {}),
|
|
3183
|
-
compareJsonValues(a.assert_json_field_gte, b.assert_json_field_gte, {}),
|
|
3184
|
-
compareOptionalStrings(a.note, b.note)
|
|
3185
|
-
]);
|
|
3131
|
+
function assertValidRecurrenceRule(recurrence) {
|
|
3132
|
+
assertItemMetadataCondition(typeof recurrence === "object" && recurrence !== null && !Array.isArray(recurrence), "event.recurrence must be an object");
|
|
3133
|
+
const recurrenceRecord = recurrence;
|
|
3134
|
+
assertItemMetadataCondition(typeof recurrenceRecord.freq === "string", "event.recurrence.freq must be a string");
|
|
3135
|
+
const frequency = recurrenceRecord.freq.trim().toLowerCase();
|
|
3136
|
+
assertItemMetadataCondition(RECURRENCE_FREQUENCY_VALUES.includes(frequency), `event.recurrence.freq must be one of: ${RECURRENCE_FREQUENCY_VALUES.join(", ")}`);
|
|
3137
|
+
assertPositiveIntegerField(recurrenceRecord, "interval", "event.recurrence.interval");
|
|
3138
|
+
assertPositiveIntegerField(recurrenceRecord, "count", "event.recurrence.count");
|
|
3139
|
+
assertOptionalTimestampString(recurrenceRecord, "until", "event.recurrence.until");
|
|
3140
|
+
assertRecurrenceWeekdays(recurrenceRecord.by_weekday);
|
|
3141
|
+
assertRecurrenceMonthDays(recurrenceRecord.by_month_day);
|
|
3142
|
+
assertRecurrenceExdates(recurrenceRecord.exdates);
|
|
3186
3143
|
}
|
|
3187
|
-
function
|
|
3188
|
-
|
|
3144
|
+
function assertRequiredItemMetadataFields(record) {
|
|
3145
|
+
for (const fieldName of REQUIRED_STRING_FIELDS) {
|
|
3146
|
+
assertItemMetadataCondition(typeof record[fieldName] === "string", `${fieldName} is required and must be a string`);
|
|
3147
|
+
}
|
|
3148
|
+
const itemType = record.type;
|
|
3149
|
+
assertItemMetadataCondition(typeof itemType === "string" && itemType.trim().length > 0, "type must be a non-empty string");
|
|
3150
|
+
const formatVersion = record.pm_format_version;
|
|
3151
|
+
if (formatVersion !== void 0) {
|
|
3152
|
+
assertItemMetadataCondition(typeof formatVersion === "number" && Number.isInteger(formatVersion) && formatVersion >= BASELINE_ITEM_FORMAT_VERSION, `pm_format_version must be an integer >= ${BASELINE_ITEM_FORMAT_VERSION}`);
|
|
3153
|
+
}
|
|
3154
|
+
return itemType;
|
|
3189
3155
|
}
|
|
3190
|
-
function
|
|
3191
|
-
|
|
3156
|
+
function assertStatusItemMetadataField(record, runtimeContext) {
|
|
3157
|
+
const status = record.status;
|
|
3158
|
+
assertItemMetadataCondition(typeof status === "string" && status.trim().length > 0, "status must be a non-empty string");
|
|
3159
|
+
const statusRegistry = runtimeContext?.statusRegistry;
|
|
3160
|
+
const normalizedStatus = normalizeStatusInput(status, statusRegistry);
|
|
3161
|
+
const statusDomain = statusRegistry ? statusRegistry.definitions.map((definition) => definition.id) : [...STATUS_VALUES];
|
|
3162
|
+
assertItemMetadataCondition(normalizedStatus !== void 0, `status must be one of: ${statusDomain.join(", ")}`);
|
|
3192
3163
|
}
|
|
3193
|
-
function
|
|
3194
|
-
|
|
3164
|
+
function assertPriorityAndTags(record) {
|
|
3165
|
+
const priority = record.priority;
|
|
3166
|
+
assertItemMetadataCondition(typeof priority === "number" && Number.isInteger(priority) && [0, 1, 2, 3, 4].includes(priority), "priority must be an integer 0..4");
|
|
3167
|
+
const tags = record.tags;
|
|
3168
|
+
assertItemMetadataCondition(Array.isArray(tags), "tags must be an array");
|
|
3169
|
+
for (const tag of tags) {
|
|
3170
|
+
assertItemMetadataCondition(typeof tag === "string", "tags entries must be strings");
|
|
3171
|
+
}
|
|
3195
3172
|
}
|
|
3196
|
-
function
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
const
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3173
|
+
function assertConfidenceItemMetadataField(record) {
|
|
3174
|
+
const confidence = record.confidence;
|
|
3175
|
+
if (confidence === void 0) {
|
|
3176
|
+
return;
|
|
3177
|
+
}
|
|
3178
|
+
if (typeof confidence === "number") {
|
|
3179
|
+
assertItemMetadataCondition(Number.isInteger(confidence) && confidence >= 0 && confidence <= 100, "confidence number value must be an integer 0..100");
|
|
3180
|
+
return;
|
|
3181
|
+
}
|
|
3182
|
+
if (typeof confidence === "string") {
|
|
3183
|
+
const normalizedConfidence = confidence.trim().toLowerCase();
|
|
3184
|
+
const isKnownTextConfidence = normalizedConfidence === "med" || CONFIDENCE_TEXT_VALUES.includes(normalizedConfidence);
|
|
3185
|
+
assertItemMetadataCondition(isKnownTextConfidence, `confidence string value must be one of: ${[...CONFIDENCE_TEXT_VALUES, "med"].join(", ")}`);
|
|
3186
|
+
return;
|
|
3187
|
+
}
|
|
3188
|
+
assertItemMetadataCondition(false, "confidence must be a number or string");
|
|
3212
3189
|
}
|
|
3213
|
-
function
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3190
|
+
function assertSeverityItemMetadataField(record) {
|
|
3191
|
+
const severity = record.severity;
|
|
3192
|
+
if (severity === void 0) {
|
|
3193
|
+
return;
|
|
3194
|
+
}
|
|
3195
|
+
if (typeof severity !== "string") {
|
|
3196
|
+
validationError("severity must be a string");
|
|
3197
|
+
}
|
|
3198
|
+
const normalizedSeverity = severity.trim().toLowerCase();
|
|
3199
|
+
const isKnownSeverity = normalizedSeverity === "med" || ISSUE_SEVERITY_VALUES.includes(normalizedSeverity);
|
|
3200
|
+
assertItemMetadataCondition(isKnownSeverity, `severity value must be one of: ${[...ISSUE_SEVERITY_VALUES, "med"].join(", ")}`);
|
|
3218
3201
|
}
|
|
3219
|
-
function
|
|
3220
|
-
if (
|
|
3221
|
-
|
|
3222
|
-
const out = [];
|
|
3223
|
-
for (const entry of value) {
|
|
3224
|
-
if (entry === null || typeof entry !== "object")
|
|
3225
|
-
continue;
|
|
3226
|
-
const record = entry;
|
|
3227
|
-
const id = trimStringOrUndefined(record.id);
|
|
3228
|
-
const kind = trimStringOrUndefined(record.kind);
|
|
3229
|
-
if (!id || !kind)
|
|
3230
|
-
continue;
|
|
3231
|
-
const link = { id, kind };
|
|
3232
|
-
const note = trimStringOrUndefined(record.note);
|
|
3233
|
-
if (note)
|
|
3234
|
-
link.note = note;
|
|
3235
|
-
if (record.required_before_step === true)
|
|
3236
|
-
link.required_before_step = true;
|
|
3237
|
-
out.push(link);
|
|
3202
|
+
function assertRegressionItemMetadataField(record) {
|
|
3203
|
+
if (record.regression !== void 0 && typeof record.regression !== "boolean") {
|
|
3204
|
+
validationError("regression must be a boolean");
|
|
3238
3205
|
}
|
|
3239
|
-
return out.length > 0 ? out : void 0;
|
|
3240
3206
|
}
|
|
3241
|
-
function
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
const
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
file.scope = record.scope;
|
|
3255
|
-
const note = trimStringOrUndefined(record.note);
|
|
3256
|
-
if (note)
|
|
3257
|
-
file.note = note;
|
|
3258
|
-
out.push(file);
|
|
3207
|
+
function assertReminderEntries(record) {
|
|
3208
|
+
const reminders = record.reminders;
|
|
3209
|
+
if (reminders === void 0) {
|
|
3210
|
+
return;
|
|
3211
|
+
}
|
|
3212
|
+
assertItemMetadataCondition(Array.isArray(reminders), "reminders must be an array");
|
|
3213
|
+
for (const reminder of reminders) {
|
|
3214
|
+
assertItemMetadataCondition(typeof reminder === "object" && reminder !== null && !Array.isArray(reminder), "reminders entries must be objects");
|
|
3215
|
+
const reminderRecord = reminder;
|
|
3216
|
+
assertItemMetadataCondition(typeof reminderRecord.at === "string", "reminder.at must be a string");
|
|
3217
|
+
assertItemMetadataCondition(isTimestampLiteral(reminderRecord.at), "reminder.at must be a valid ISO timestamp");
|
|
3218
|
+
assertItemMetadataCondition(typeof reminderRecord.text === "string", "reminder.text must be a string");
|
|
3219
|
+
assertItemMetadataCondition(reminderRecord.text.trim().length > 0, "reminder.text must not be empty");
|
|
3259
3220
|
}
|
|
3260
|
-
return out.length > 0 ? out : void 0;
|
|
3261
3221
|
}
|
|
3262
|
-
function
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
continue;
|
|
3274
|
-
const test = {};
|
|
3275
|
-
if (command)
|
|
3276
|
-
test.command = command;
|
|
3277
|
-
if (path6)
|
|
3278
|
-
test.path = normalizePathValue(path6);
|
|
3279
|
-
const note = trimStringOrUndefined(record.note);
|
|
3280
|
-
if (note)
|
|
3281
|
-
test.note = note;
|
|
3282
|
-
out.push(test);
|
|
3222
|
+
function assertEventStringFields(eventRecord) {
|
|
3223
|
+
for (const stringField of [
|
|
3224
|
+
"title",
|
|
3225
|
+
"description",
|
|
3226
|
+
"location",
|
|
3227
|
+
"timezone"
|
|
3228
|
+
]) {
|
|
3229
|
+
if (eventRecord[stringField] !== void 0) {
|
|
3230
|
+
assertItemMetadataCondition(typeof eventRecord[stringField] === "string", `event.${stringField} must be a string`);
|
|
3231
|
+
assertItemMetadataCondition(eventRecord[stringField].trim().length > 0, `event.${stringField} must not be empty`);
|
|
3232
|
+
}
|
|
3283
3233
|
}
|
|
3284
|
-
return out.length > 0 ? out : void 0;
|
|
3285
3234
|
}
|
|
3286
|
-
function
|
|
3287
|
-
if (
|
|
3288
|
-
return
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
const record = entry;
|
|
3294
|
-
const path6 = trimStringOrUndefined(record.path);
|
|
3295
|
-
if (!path6)
|
|
3296
|
-
continue;
|
|
3297
|
-
const doc = { path: normalizePathValue(path6) };
|
|
3298
|
-
if (record.scope === "project" || record.scope === "global")
|
|
3299
|
-
doc.scope = record.scope;
|
|
3300
|
-
const note = trimStringOrUndefined(record.note);
|
|
3301
|
-
if (note)
|
|
3302
|
-
doc.note = note;
|
|
3303
|
-
out.push(doc);
|
|
3235
|
+
function assertEventRecurrence(eventRecord) {
|
|
3236
|
+
if (eventRecord.recurrence === void 0) {
|
|
3237
|
+
return;
|
|
3238
|
+
}
|
|
3239
|
+
assertValidRecurrenceRule(eventRecord.recurrence);
|
|
3240
|
+
if (eventRecord.recurrence.until !== void 0) {
|
|
3241
|
+
assertItemMetadataCondition(compareTimestampStrings(eventRecord.recurrence.until, eventRecord.start_at) >= 0, "event.recurrence.until must be at or after event.start_at");
|
|
3304
3242
|
}
|
|
3305
|
-
return out.length > 0 ? out : void 0;
|
|
3306
3243
|
}
|
|
3307
|
-
function
|
|
3308
|
-
|
|
3309
|
-
|
|
3244
|
+
function assertCalendarEventEntry(event) {
|
|
3245
|
+
assertItemMetadataCondition(typeof event === "object" && event !== null && !Array.isArray(event), "events entries must be objects");
|
|
3246
|
+
const eventRecord = event;
|
|
3247
|
+
assertItemMetadataCondition(typeof eventRecord.start_at === "string", "event.start_at must be a string");
|
|
3248
|
+
assertItemMetadataCondition(isTimestampLiteral(eventRecord.start_at), "event.start_at must be a valid ISO timestamp");
|
|
3249
|
+
if (eventRecord.end_at !== void 0) {
|
|
3250
|
+
assertItemMetadataCondition(typeof eventRecord.end_at === "string", "event.end_at must be a string");
|
|
3251
|
+
assertItemMetadataCondition(isTimestampLiteral(eventRecord.end_at), "event.end_at must be a valid ISO timestamp");
|
|
3252
|
+
assertItemMetadataCondition(compareTimestampStrings(eventRecord.end_at, eventRecord.start_at) > 0, "event.end_at must be after event.start_at");
|
|
3310
3253
|
}
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
const statusRaw = trimStringOrUndefined(record.status);
|
|
3315
|
-
const status = statusRaw && PLAN_STEP_STATUS_SET.has(statusRaw) ? statusRaw : void 0;
|
|
3316
|
-
const order = coerceFiniteNumber(record.order) ?? Number.NaN;
|
|
3317
|
-
const created_at = typeof record.created_at === "string" ? record.created_at : "";
|
|
3318
|
-
const updated_at = typeof record.updated_at === "string" ? record.updated_at : "";
|
|
3319
|
-
if (!id || !title || !status || !Number.isFinite(order) || !created_at || !updated_at) {
|
|
3320
|
-
return void 0;
|
|
3254
|
+
assertEventStringFields(eventRecord);
|
|
3255
|
+
if (eventRecord.all_day !== void 0) {
|
|
3256
|
+
assertItemMetadataCondition(typeof eventRecord.all_day === "boolean", "event.all_day must be a boolean");
|
|
3321
3257
|
}
|
|
3322
|
-
|
|
3323
|
-
id,
|
|
3324
|
-
order,
|
|
3325
|
-
title,
|
|
3326
|
-
status,
|
|
3327
|
-
created_at,
|
|
3328
|
-
updated_at
|
|
3329
|
-
};
|
|
3330
|
-
applyPlanStepOptionalFields(step, record);
|
|
3331
|
-
return step;
|
|
3258
|
+
assertEventRecurrence(eventRecord);
|
|
3332
3259
|
}
|
|
3333
|
-
function
|
|
3334
|
-
const
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
["evidence", "evidence"],
|
|
3338
|
-
["blocked_reason", "blocked_reason"],
|
|
3339
|
-
["superseded_by", "superseded_by"]
|
|
3340
|
-
];
|
|
3341
|
-
for (const [target, source] of stringFields) {
|
|
3342
|
-
const value = trimStringOrUndefined(record[source]);
|
|
3343
|
-
if (value) {
|
|
3344
|
-
step[target] = value;
|
|
3345
|
-
}
|
|
3260
|
+
function assertCalendarEvents(record) {
|
|
3261
|
+
const events = record.events;
|
|
3262
|
+
if (events === void 0) {
|
|
3263
|
+
return;
|
|
3346
3264
|
}
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3265
|
+
assertItemMetadataCondition(Array.isArray(events), "events must be an array");
|
|
3266
|
+
for (const event of events) {
|
|
3267
|
+
assertCalendarEventEntry(event);
|
|
3350
3268
|
}
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3269
|
+
}
|
|
3270
|
+
function assertOptionalStringFields(record) {
|
|
3271
|
+
for (const fieldName of [
|
|
3272
|
+
"source_type",
|
|
3273
|
+
"source_owner",
|
|
3274
|
+
"design",
|
|
3275
|
+
"external_ref"
|
|
3276
|
+
]) {
|
|
3277
|
+
const value = record[fieldName];
|
|
3278
|
+
if (value !== void 0) {
|
|
3279
|
+
assertItemMetadataCondition(typeof value === "string", `${fieldName} must be a string`);
|
|
3361
3280
|
}
|
|
3362
3281
|
}
|
|
3363
3282
|
}
|
|
3364
|
-
function
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
const step = normalizePlanStepEntry(entry);
|
|
3369
|
-
return step ? [step] : [];
|
|
3370
|
-
});
|
|
3371
|
-
out.sort((left, right) => left.order - right.order);
|
|
3372
|
-
return out.length > 0 ? out : void 0;
|
|
3373
|
-
}
|
|
3374
|
-
function normalizePlanDecisions(value) {
|
|
3375
|
-
if (!Array.isArray(value))
|
|
3376
|
-
return void 0;
|
|
3377
|
-
const out = [];
|
|
3378
|
-
for (const entry of value) {
|
|
3379
|
-
if (entry === null || typeof entry !== "object")
|
|
3380
|
-
continue;
|
|
3381
|
-
const record = entry;
|
|
3382
|
-
const ts = typeof record.ts === "string" ? record.ts : "";
|
|
3383
|
-
const author = typeof record.author === "string" ? record.author : "";
|
|
3384
|
-
const decision = trimStringOrUndefined(record.decision);
|
|
3385
|
-
if (!ts || !author || !decision)
|
|
3386
|
-
continue;
|
|
3387
|
-
const item = { ts, author, decision };
|
|
3388
|
-
const rationale = trimStringOrUndefined(record.rationale);
|
|
3389
|
-
if (rationale)
|
|
3390
|
-
item.rationale = rationale;
|
|
3391
|
-
const evidence = trimStringOrUndefined(record.evidence);
|
|
3392
|
-
if (evidence)
|
|
3393
|
-
item.evidence = evidence;
|
|
3394
|
-
const stepId = trimStringOrUndefined(record.step_id);
|
|
3395
|
-
if (stepId)
|
|
3396
|
-
item.step_id = stepId;
|
|
3397
|
-
out.push(item);
|
|
3283
|
+
function assertTypeOptionsField(record) {
|
|
3284
|
+
const typeOptions = record.type_options;
|
|
3285
|
+
if (typeOptions === void 0) {
|
|
3286
|
+
return;
|
|
3398
3287
|
}
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
for (const entry of value) {
|
|
3406
|
-
if (entry === null || typeof entry !== "object")
|
|
3407
|
-
continue;
|
|
3408
|
-
const record = entry;
|
|
3409
|
-
const ts = typeof record.ts === "string" ? record.ts : "";
|
|
3410
|
-
const author = typeof record.author === "string" ? record.author : "";
|
|
3411
|
-
const text = trimStringOrUndefined(record.text);
|
|
3412
|
-
if (!ts || !author || !text)
|
|
3413
|
-
continue;
|
|
3414
|
-
const item = { ts, author, text };
|
|
3415
|
-
const stepId = trimStringOrUndefined(record.step_id);
|
|
3416
|
-
if (stepId)
|
|
3417
|
-
item.step_id = stepId;
|
|
3418
|
-
out.push(item);
|
|
3288
|
+
assertItemMetadataCondition(typeof typeOptions === "object" && typeOptions !== null && !Array.isArray(typeOptions), "type_options must be an object");
|
|
3289
|
+
for (const [optionKey, optionValue] of Object.entries(typeOptions)) {
|
|
3290
|
+
assertItemMetadataCondition(optionKey.trim().length > 0, "type_options keys must be non-empty");
|
|
3291
|
+
assertItemMetadataCondition(typeof optionValue === "string", "type_options values must be strings");
|
|
3292
|
+
const optionText = optionValue;
|
|
3293
|
+
assertItemMetadataCondition(optionText.trim().length > 0, "type_options values must be non-empty strings");
|
|
3419
3294
|
}
|
|
3420
|
-
return out.length > 0 ? out : void 0;
|
|
3421
3295
|
}
|
|
3422
|
-
function
|
|
3423
|
-
if (!
|
|
3424
|
-
return
|
|
3425
|
-
|
|
3426
|
-
for (const
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3296
|
+
function coerceRuntimeItemMetadataFields(record, itemType, runtimeContext) {
|
|
3297
|
+
if (!runtimeContext?.fieldRegistry) {
|
|
3298
|
+
return;
|
|
3299
|
+
}
|
|
3300
|
+
for (const definition of runtimeContext.fieldRegistry.definitions) {
|
|
3301
|
+
const fieldValue = record[definition.metadata_key];
|
|
3302
|
+
if (fieldValue === void 0) {
|
|
3303
|
+
if (runtimeFieldRequiredForType(definition, itemType)) {
|
|
3304
|
+
validationError(`missing required schema field: ${definition.metadata_key}`);
|
|
3305
|
+
}
|
|
3432
3306
|
continue;
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
item.expected = expected;
|
|
3440
|
-
out.push(item);
|
|
3307
|
+
}
|
|
3308
|
+
try {
|
|
3309
|
+
record[definition.metadata_key] = coerceRuntimeFieldValue(definition, fieldValue, `metadata field "${definition.metadata_key}"`);
|
|
3310
|
+
} catch (error) {
|
|
3311
|
+
validationError(String(error?.message).replace(/^Invalid\s+/u, ""));
|
|
3312
|
+
}
|
|
3441
3313
|
}
|
|
3442
|
-
return out.length > 0 ? out : void 0;
|
|
3443
3314
|
}
|
|
3444
|
-
function
|
|
3445
|
-
if (!
|
|
3446
|
-
return
|
|
3315
|
+
function assertRuntimeUnknownItemMetadataFields(record, runtimeContext) {
|
|
3316
|
+
if (!runtimeContext || runtimeContext.unknownFieldPolicy === "allow") {
|
|
3317
|
+
return;
|
|
3447
3318
|
}
|
|
3448
|
-
const
|
|
3449
|
-
|
|
3450
|
-
|
|
3319
|
+
const knownKeys = buildKnownItemMetadataKeys(runtimeContext);
|
|
3320
|
+
const unknownKeys = Object.keys(record).filter((key) => !knownKeys.has(key)).sort((left, right) => left.localeCompare(right));
|
|
3321
|
+
if (unknownKeys.length === 0) {
|
|
3322
|
+
return;
|
|
3323
|
+
}
|
|
3324
|
+
if (runtimeContext.unknownFieldPolicy === "reject") {
|
|
3325
|
+
validationError(`unknown schema fields are not allowed: ${unknownKeys.join(", ")}`);
|
|
3326
|
+
} else {
|
|
3327
|
+
runtimeContext.onWarning?.(`item_unknown_schema_fields:${unknownKeys.join(",")}`);
|
|
3451
3328
|
}
|
|
3452
|
-
return Object.fromEntries(normalizedEntries);
|
|
3453
3329
|
}
|
|
3454
|
-
function
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3330
|
+
function assertValidItemMetadata(itemMetadata, runtimeContext) {
|
|
3331
|
+
assertItemMetadataCondition(typeof itemMetadata === "object" && itemMetadata !== null && !Array.isArray(itemMetadata), "item metadata must be an object");
|
|
3332
|
+
const record = itemMetadata;
|
|
3333
|
+
const itemType = assertRequiredItemMetadataFields(record);
|
|
3334
|
+
assertStatusItemMetadataField(record, runtimeContext);
|
|
3335
|
+
assertPriorityAndTags(record);
|
|
3336
|
+
assertConfidenceItemMetadataField(record);
|
|
3337
|
+
assertSeverityItemMetadataField(record);
|
|
3338
|
+
assertRegressionItemMetadataField(record);
|
|
3339
|
+
assertTimestampField(record, "created_at");
|
|
3340
|
+
assertTimestampField(record, "updated_at");
|
|
3341
|
+
if (record.deadline !== void 0) {
|
|
3342
|
+
assertTimestampField(record, "deadline");
|
|
3458
3343
|
}
|
|
3459
|
-
|
|
3344
|
+
assertReminderEntries(record);
|
|
3345
|
+
assertCalendarEvents(record);
|
|
3346
|
+
assertOptionalTimestampString(record, "closed_at", "closed_at");
|
|
3347
|
+
assertOptionalStringFields(record);
|
|
3348
|
+
assertTypeOptionsField(record);
|
|
3349
|
+
coerceRuntimeItemMetadataFields(record, itemType, runtimeContext);
|
|
3350
|
+
assertRuntimeUnknownItemMetadataFields(record, runtimeContext);
|
|
3460
3351
|
}
|
|
3461
|
-
function
|
|
3462
|
-
if (
|
|
3352
|
+
function sortDependencies(values) {
|
|
3353
|
+
if (!values || values.length === 0)
|
|
3463
3354
|
return void 0;
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3355
|
+
return [...values].map((value) => ({
|
|
3356
|
+
id: value.id.trim().toLowerCase(),
|
|
3357
|
+
kind: value.kind,
|
|
3358
|
+
created_at: value.created_at,
|
|
3359
|
+
author: value.author?.trim() || void 0,
|
|
3360
|
+
source_kind: value.source_kind?.trim() || void 0
|
|
3361
|
+
})).sort((a, b) => {
|
|
3362
|
+
const byCreated = compareTimestampStrings(a.created_at, b.created_at);
|
|
3363
|
+
if (byCreated !== 0)
|
|
3364
|
+
return byCreated;
|
|
3365
|
+
const byId = a.id.localeCompare(b.id);
|
|
3366
|
+
if (byId !== 0)
|
|
3367
|
+
return byId;
|
|
3368
|
+
const byKind = a.kind.localeCompare(b.kind);
|
|
3369
|
+
if (byKind !== 0)
|
|
3370
|
+
return byKind;
|
|
3371
|
+
return (a.source_kind ?? "").localeCompare(b.source_kind ?? "");
|
|
3372
|
+
});
|
|
3476
3373
|
}
|
|
3477
|
-
function
|
|
3478
|
-
if (
|
|
3374
|
+
function sortLogValues(values) {
|
|
3375
|
+
if (!values || values.length === 0)
|
|
3479
3376
|
return void 0;
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3377
|
+
return [...values].sort((a, b) => {
|
|
3378
|
+
const byCreated = compareTimestampStrings(a.created_at, b.created_at);
|
|
3379
|
+
if (byCreated !== 0)
|
|
3380
|
+
return byCreated;
|
|
3381
|
+
const byText = a.text.localeCompare(b.text);
|
|
3382
|
+
if (byText !== 0)
|
|
3383
|
+
return byText;
|
|
3384
|
+
return a.author.localeCompare(b.author);
|
|
3385
|
+
});
|
|
3489
3386
|
}
|
|
3490
|
-
function
|
|
3491
|
-
|
|
3387
|
+
function sortReminders(values) {
|
|
3388
|
+
if (!values || values.length === 0)
|
|
3389
|
+
return void 0;
|
|
3390
|
+
const normalized = [...values].map((value) => ({
|
|
3391
|
+
at: value.at,
|
|
3392
|
+
text: value.text.trim()
|
|
3393
|
+
})).filter((value) => value.text.length > 0).sort((a, b) => {
|
|
3394
|
+
const byAt = compareTimestampStrings(a.at, b.at);
|
|
3395
|
+
if (byAt !== 0)
|
|
3396
|
+
return byAt;
|
|
3397
|
+
return a.text.localeCompare(b.text);
|
|
3398
|
+
});
|
|
3399
|
+
return normalized.length === 0 ? void 0 : normalized;
|
|
3492
3400
|
}
|
|
3493
|
-
function
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
for (const [key, value] of Object.entries(sourceRecord)) {
|
|
3497
|
-
if (isUnsafeObjectKey(key) || Object.prototype.hasOwnProperty.call(targetRecord, key) || value === void 0) {
|
|
3498
|
-
continue;
|
|
3499
|
-
}
|
|
3500
|
-
targetRecord[key] = value;
|
|
3401
|
+
function normalizeRecurrenceRule(value) {
|
|
3402
|
+
if (!value) {
|
|
3403
|
+
return void 0;
|
|
3501
3404
|
}
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
return;
|
|
3405
|
+
const normalizedFrequency = value.freq.trim().toLowerCase();
|
|
3406
|
+
if (!RECURRENCE_FREQUENCY_VALUES.includes(normalizedFrequency)) {
|
|
3407
|
+
return void 0;
|
|
3506
3408
|
}
|
|
3507
|
-
const
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3409
|
+
const byWeekday = Array.from(new Set((value.by_weekday ?? []).map((weekday) => weekday.trim().toLowerCase()).filter((weekday) => RECURRENCE_WEEKDAY_VALUES.includes(weekday)))).sort((a, b) => weekdayOrderIndex(a) - weekdayOrderIndex(b));
|
|
3410
|
+
const byMonthDay = Array.from(new Set((value.by_month_day ?? []).filter((day) => Number.isInteger(day) && day >= 1 && day <= 31).map((day) => day))).sort((a, b) => a - b);
|
|
3411
|
+
const exdates = Array.from(new Set((value.exdates ?? []).map((timestamp) => timestamp.trim()).filter((timestamp) => isTimestampLiteral(timestamp)))).sort((a, b) => compareTimestampStrings(a, b));
|
|
3412
|
+
const normalized = {
|
|
3413
|
+
freq: normalizedFrequency,
|
|
3414
|
+
interval: value.interval !== void 0 && value.interval > 1 ? value.interval : void 0,
|
|
3415
|
+
count: value.count,
|
|
3416
|
+
until: value.until?.trim() || void 0,
|
|
3417
|
+
by_weekday: byWeekday.length > 0 ? byWeekday : void 0,
|
|
3418
|
+
by_month_day: byMonthDay.length > 0 ? byMonthDay : void 0,
|
|
3419
|
+
exdates: exdates.length > 0 ? exdates : void 0
|
|
3420
|
+
};
|
|
3421
|
+
for (const [key, fieldValue] of Object.entries(normalized)) {
|
|
3422
|
+
if (fieldValue === void 0) {
|
|
3423
|
+
delete normalized[key];
|
|
3512
3424
|
}
|
|
3513
|
-
record[definition.metadata_key] = coerceRuntimeFieldValue(definition, currentValue, `metadata field "${definition.metadata_key}"`);
|
|
3514
3425
|
}
|
|
3426
|
+
return normalized;
|
|
3515
3427
|
}
|
|
3516
|
-
function
|
|
3517
|
-
if (!
|
|
3518
|
-
return;
|
|
3519
|
-
}
|
|
3520
|
-
const knownKeys = buildKnownItemMetadataKeys(runtimeContext);
|
|
3521
|
-
const record = normalized;
|
|
3522
|
-
const unknownKeys = Object.keys(record).filter((key) => !knownKeys.has(key)).sort((left, right) => left.localeCompare(right));
|
|
3523
|
-
if (unknownKeys.length > 0 && runtimeContext.unknownFieldPolicy === "reject") {
|
|
3524
|
-
validationError(`unknown schema fields are not allowed: ${unknownKeys.join(", ")}`);
|
|
3525
|
-
}
|
|
3526
|
-
if (unknownKeys.length > 0) {
|
|
3527
|
-
runtimeContext.onWarning?.(`item_unknown_schema_fields:${unknownKeys.join(",")}`);
|
|
3428
|
+
function sortEvents(values) {
|
|
3429
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
3430
|
+
return void 0;
|
|
3528
3431
|
}
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
const
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
title:
|
|
3537
|
-
description:
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
status: normalizedStatus,
|
|
3543
|
-
priority: itemMetadata.priority,
|
|
3544
|
-
tags,
|
|
3545
|
-
created_at: itemMetadata.created_at,
|
|
3546
|
-
updated_at: itemMetadata.updated_at,
|
|
3547
|
-
dependencies: sortDependencies(itemMetadata.dependencies),
|
|
3548
|
-
comments: sortLogValues(itemMetadata.comments),
|
|
3549
|
-
notes: sortLogValues(itemMetadata.notes),
|
|
3550
|
-
learnings: sortLogValues(itemMetadata.learnings),
|
|
3551
|
-
files: normalizeFiles(itemMetadata.files),
|
|
3552
|
-
tests: sortTests(itemMetadata.tests),
|
|
3553
|
-
test_runs: normalizeTestRunSummaries(itemMetadata.test_runs),
|
|
3554
|
-
docs: sortDocs(itemMetadata.docs),
|
|
3555
|
-
deadline: emptyStringToUndefined(itemMetadata.deadline),
|
|
3556
|
-
reminders: sortReminders(itemMetadata.reminders),
|
|
3557
|
-
events: sortEvents(itemMetadata.events),
|
|
3558
|
-
closed_at: emptyStringToUndefined(itemMetadata.closed_at),
|
|
3559
|
-
assignee: trimStringOrUndefined(itemMetadata.assignee),
|
|
3560
|
-
source_owner: trimStringOrUndefined(itemMetadata.source_owner),
|
|
3561
|
-
author: emptyStringToUndefined(itemMetadata.author),
|
|
3562
|
-
estimated_minutes: itemMetadata.estimated_minutes,
|
|
3563
|
-
acceptance_criteria: itemMetadata.acceptance_criteria ?? void 0,
|
|
3564
|
-
design: itemMetadata.design ?? void 0,
|
|
3565
|
-
external_ref: itemMetadata.external_ref ?? void 0,
|
|
3566
|
-
definition_of_ready: trimStringOrUndefined(itemMetadata.definition_of_ready),
|
|
3567
|
-
order: itemMetadata.order,
|
|
3568
|
-
goal: trimStringOrUndefined(itemMetadata.goal),
|
|
3569
|
-
objective: trimStringOrUndefined(itemMetadata.objective),
|
|
3570
|
-
value: trimStringOrUndefined(itemMetadata.value),
|
|
3571
|
-
impact: trimStringOrUndefined(itemMetadata.impact),
|
|
3572
|
-
outcome: trimStringOrUndefined(itemMetadata.outcome),
|
|
3573
|
-
why_now: trimStringOrUndefined(itemMetadata.why_now),
|
|
3574
|
-
parent: trimStringOrUndefined(itemMetadata.parent),
|
|
3575
|
-
reviewer: trimStringOrUndefined(itemMetadata.reviewer),
|
|
3576
|
-
risk: itemMetadata.risk ?? void 0,
|
|
3577
|
-
confidence: normalizeConfidenceValue(itemMetadata.confidence),
|
|
3578
|
-
sprint: trimStringOrUndefined(itemMetadata.sprint),
|
|
3579
|
-
release: trimStringOrUndefined(itemMetadata.release),
|
|
3580
|
-
blocked_by: trimStringOrUndefined(itemMetadata.blocked_by),
|
|
3581
|
-
blocked_reason: trimStringOrUndefined(itemMetadata.blocked_reason),
|
|
3582
|
-
unblock_note: trimStringOrUndefined(itemMetadata.unblock_note),
|
|
3583
|
-
reporter: trimStringOrUndefined(itemMetadata.reporter),
|
|
3584
|
-
severity: normalizeSeverityValue(itemMetadata.severity),
|
|
3585
|
-
environment: trimStringOrUndefined(itemMetadata.environment),
|
|
3586
|
-
repro_steps: trimStringOrUndefined(itemMetadata.repro_steps),
|
|
3587
|
-
resolution: trimStringOrUndefined(itemMetadata.resolution),
|
|
3588
|
-
expected_result: trimStringOrUndefined(itemMetadata.expected_result),
|
|
3589
|
-
actual_result: trimStringOrUndefined(itemMetadata.actual_result),
|
|
3590
|
-
affected_version: trimStringOrUndefined(itemMetadata.affected_version),
|
|
3591
|
-
fixed_version: trimStringOrUndefined(itemMetadata.fixed_version),
|
|
3592
|
-
component: trimStringOrUndefined(itemMetadata.component),
|
|
3593
|
-
regression: itemMetadata.regression,
|
|
3594
|
-
customer_impact: trimStringOrUndefined(itemMetadata.customer_impact),
|
|
3595
|
-
close_reason: emptyStringToUndefined(itemMetadata.close_reason),
|
|
3596
|
-
plan_mode: trimStringOrUndefined(itemMetadata.plan_mode),
|
|
3597
|
-
plan_scope: trimStringOrUndefined(itemMetadata.plan_scope),
|
|
3598
|
-
plan_harness: trimStringOrUndefined(itemMetadata.plan_harness),
|
|
3599
|
-
plan_resume_context: trimStringOrUndefined(itemMetadata.plan_resume_context),
|
|
3600
|
-
plan_steps: normalizePlanSteps(itemMetadata.plan_steps),
|
|
3601
|
-
plan_decisions: normalizePlanDecisions(itemMetadata.plan_decisions),
|
|
3602
|
-
plan_discoveries: normalizePlanDiscoveries(itemMetadata.plan_discoveries),
|
|
3603
|
-
plan_validation: normalizePlanValidation(itemMetadata.plan_validation)
|
|
3432
|
+
const normalized = [...values].map(normalizeCalendarEvent).sort(compareCalendarEvents);
|
|
3433
|
+
return normalized;
|
|
3434
|
+
}
|
|
3435
|
+
function normalizeCalendarEvent(value) {
|
|
3436
|
+
const event = {
|
|
3437
|
+
start_at: value.start_at,
|
|
3438
|
+
end_at: value.end_at || void 0,
|
|
3439
|
+
title: value.title?.trim() || void 0,
|
|
3440
|
+
description: value.description?.trim() || void 0,
|
|
3441
|
+
location: value.location?.trim() || void 0,
|
|
3442
|
+
all_day: value.all_day,
|
|
3443
|
+
timezone: value.timezone?.trim() || void 0,
|
|
3444
|
+
recurrence: normalizeRecurrenceRule(value.recurrence)
|
|
3604
3445
|
};
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3446
|
+
deleteUndefinedFields(event);
|
|
3447
|
+
return event;
|
|
3448
|
+
}
|
|
3449
|
+
function compareCalendarEvents(a, b) {
|
|
3450
|
+
return firstNonZeroComparison([
|
|
3451
|
+
compareTimestampStrings(a.start_at, b.start_at),
|
|
3452
|
+
(a.end_at ?? "").localeCompare(b.end_at ?? ""),
|
|
3453
|
+
(a.title ?? "").localeCompare(b.title ?? ""),
|
|
3454
|
+
Number(Boolean(a.all_day)) - Number(Boolean(b.all_day)),
|
|
3455
|
+
(a.timezone ?? "").localeCompare(b.timezone ?? ""),
|
|
3456
|
+
(a.location ?? "").localeCompare(b.location ?? ""),
|
|
3457
|
+
(a.description ?? "").localeCompare(b.description ?? ""),
|
|
3458
|
+
JSON.stringify(a.recurrence ?? {}).localeCompare(JSON.stringify(b.recurrence ?? {}))
|
|
3459
|
+
]);
|
|
3460
|
+
}
|
|
3461
|
+
function normalizeFiles(values) {
|
|
3462
|
+
if (!values || values.length === 0)
|
|
3463
|
+
return void 0;
|
|
3464
|
+
return values.map((value) => ({
|
|
3465
|
+
path: normalizePathValue(value.path),
|
|
3466
|
+
scope: value.scope,
|
|
3467
|
+
note: value.note?.trim() || void 0
|
|
3468
|
+
}));
|
|
3469
|
+
}
|
|
3470
|
+
function normalizeTestRunSummaries(values) {
|
|
3471
|
+
if (!values || values.length === 0)
|
|
3472
|
+
return void 0;
|
|
3473
|
+
const normalized = values.map(normalizeTestRunSummary).filter((value) => value.run_id.length > 0 && value.started_at.length > 0 && value.finished_at.length > 0 && value.recorded_at.length > 0).sort((a, b) => firstNonZeroComparison([
|
|
3474
|
+
compareTimestampStrings(a.recorded_at, b.recorded_at),
|
|
3475
|
+
a.run_id.localeCompare(b.run_id),
|
|
3476
|
+
a.kind.localeCompare(b.kind)
|
|
3477
|
+
]));
|
|
3478
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
3479
|
+
}
|
|
3480
|
+
function normalizeNonNegativeInteger(value) {
|
|
3481
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : void 0;
|
|
3482
|
+
}
|
|
3483
|
+
function normalizePositiveInteger(value) {
|
|
3484
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 1 ? Math.floor(value) : void 0;
|
|
3485
|
+
}
|
|
3486
|
+
function stringOrEmpty(value) {
|
|
3487
|
+
return typeof value === "string" ? value : "";
|
|
3488
|
+
}
|
|
3489
|
+
function normalizeTestRunSummary(value) {
|
|
3490
|
+
const runId = typeof value.run_id === "string" ? value.run_id.trim() : "";
|
|
3491
|
+
const kind = value.kind === "test" || value.kind === "test-all" ? value.kind : "test";
|
|
3492
|
+
const status = ITEM_TEST_RUN_STATUS_VALUES.has(value.status) ? value.status : "failed";
|
|
3493
|
+
const summary = {
|
|
3494
|
+
run_id: runId,
|
|
3495
|
+
kind,
|
|
3496
|
+
status,
|
|
3497
|
+
started_at: stringOrEmpty(value.started_at),
|
|
3498
|
+
finished_at: stringOrEmpty(value.finished_at),
|
|
3499
|
+
recorded_at: stringOrEmpty(value.recorded_at),
|
|
3500
|
+
attempt: normalizePositiveInteger(value.attempt),
|
|
3501
|
+
resumed_from: value.resumed_from?.trim() || void 0,
|
|
3502
|
+
passed: normalizeNonNegativeInteger(value.passed) ?? 0,
|
|
3503
|
+
failed: normalizeNonNegativeInteger(value.failed) ?? 0,
|
|
3504
|
+
skipped: normalizeNonNegativeInteger(value.skipped) ?? 0,
|
|
3505
|
+
items: normalizeNonNegativeInteger(value.items),
|
|
3506
|
+
linked_tests: normalizeNonNegativeInteger(value.linked_tests),
|
|
3507
|
+
fail_on_skipped_triggered: value.fail_on_skipped_triggered === true ? true : void 0
|
|
3508
|
+
};
|
|
3509
|
+
deleteUndefinedFields(summary);
|
|
3510
|
+
return summary;
|
|
3511
|
+
}
|
|
3512
|
+
function sortTests(values) {
|
|
3513
|
+
if (!Array.isArray(values) || values.length === 0)
|
|
3514
|
+
return void 0;
|
|
3515
|
+
return [...values].map(normalizeLinkedTest).sort(compareLinkedTests);
|
|
3516
|
+
}
|
|
3517
|
+
function normalizeTrimmedStringList(value) {
|
|
3518
|
+
if (!Array.isArray(value)) {
|
|
3519
|
+
return void 0;
|
|
3520
|
+
}
|
|
3521
|
+
const normalized = [
|
|
3522
|
+
...new Set(value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter((entry) => entry.length > 0))
|
|
3523
|
+
].sort((a, b) => a.localeCompare(b));
|
|
3524
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
3525
|
+
}
|
|
3526
|
+
function isPlainObjectRecord(value) {
|
|
3527
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3528
|
+
return false;
|
|
3529
|
+
}
|
|
3530
|
+
const prototype = Object.getPrototypeOf(value);
|
|
3531
|
+
return prototype === Object.prototype || prototype === null;
|
|
3532
|
+
}
|
|
3533
|
+
function isUnsafeObjectKey(key) {
|
|
3534
|
+
return key === "__proto__" || key === "constructor" || key === "prototype";
|
|
3535
|
+
}
|
|
3536
|
+
function normalizeStringRecord(value) {
|
|
3537
|
+
if (!isPlainObjectRecord(value)) {
|
|
3538
|
+
return void 0;
|
|
3539
|
+
}
|
|
3540
|
+
const entries = Object.entries(value).map(([key, recordValue]) => [key.trim(), String(recordValue).trim()]).filter(([key, recordValue]) => key.length > 0 && !isUnsafeObjectKey(key) && recordValue.length > 0).sort(([left], [right]) => left.localeCompare(right));
|
|
3541
|
+
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
3542
|
+
}
|
|
3543
|
+
function normalizeNumericRecord(value) {
|
|
3544
|
+
if (!isPlainObjectRecord(value)) {
|
|
3545
|
+
return void 0;
|
|
3546
|
+
}
|
|
3547
|
+
const entries = Object.entries(value).map(([key, recordValue]) => [key.trim(), Number(recordValue)]).filter(([key, recordValue]) => key.length > 0 && !isUnsafeObjectKey(key) && Number.isFinite(recordValue)).sort(([left], [right]) => left.localeCompare(right));
|
|
3548
|
+
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
3549
|
+
}
|
|
3550
|
+
function normalizeLinkedTestContextMode(value) {
|
|
3551
|
+
const normalized = value?.trim().toLowerCase();
|
|
3552
|
+
if (!normalized || !LINKED_TEST_PM_CONTEXT_MODE_VALUES.has(normalized)) {
|
|
3553
|
+
return void 0;
|
|
3554
|
+
}
|
|
3609
3555
|
return normalized;
|
|
3610
3556
|
}
|
|
3611
|
-
function
|
|
3612
|
-
|
|
3557
|
+
function normalizeLinkedTest(value) {
|
|
3558
|
+
const test = {
|
|
3559
|
+
command: value.command?.trim() || void 0,
|
|
3560
|
+
path: value.path ? normalizePathValue(value.path) : void 0,
|
|
3561
|
+
scope: value.scope,
|
|
3562
|
+
timeout_seconds: typeof value.timeout_seconds === "number" && Number.isFinite(value.timeout_seconds) && value.timeout_seconds > 0 ? value.timeout_seconds : void 0,
|
|
3563
|
+
pm_context_mode: normalizeLinkedTestContextMode(value.pm_context_mode),
|
|
3564
|
+
env_set: normalizeStringRecord(value.env_set),
|
|
3565
|
+
env_clear: normalizeTrimmedStringList(value.env_clear),
|
|
3566
|
+
shared_host_safe: value.shared_host_safe === true ? true : void 0,
|
|
3567
|
+
assert_stdout_contains: normalizeTrimmedStringList(value.assert_stdout_contains),
|
|
3568
|
+
assert_stdout_regex: normalizeTrimmedStringList(value.assert_stdout_regex),
|
|
3569
|
+
assert_stderr_contains: normalizeTrimmedStringList(value.assert_stderr_contains),
|
|
3570
|
+
assert_stderr_regex: normalizeTrimmedStringList(value.assert_stderr_regex),
|
|
3571
|
+
assert_stdout_min_lines: normalizeNonNegativeInteger(value.assert_stdout_min_lines),
|
|
3572
|
+
assert_json_field_equals: normalizeStringRecord(value.assert_json_field_equals),
|
|
3573
|
+
assert_json_field_gte: normalizeNumericRecord(value.assert_json_field_gte),
|
|
3574
|
+
note: value.note?.trim() || void 0
|
|
3575
|
+
};
|
|
3576
|
+
deleteUndefinedFields(test);
|
|
3577
|
+
return test;
|
|
3613
3578
|
}
|
|
3614
|
-
function
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3579
|
+
function compareLinkedTests(a, b) {
|
|
3580
|
+
return firstNonZeroComparison([
|
|
3581
|
+
a.scope.localeCompare(b.scope),
|
|
3582
|
+
compareOptionalStrings(a.path, b.path),
|
|
3583
|
+
compareOptionalStrings(a.command, b.command),
|
|
3584
|
+
compareOptionalNumbers(a.timeout_seconds, b.timeout_seconds),
|
|
3585
|
+
compareOptionalStrings(a.pm_context_mode, b.pm_context_mode),
|
|
3586
|
+
Number(Boolean(a.shared_host_safe)) - Number(Boolean(b.shared_host_safe)),
|
|
3587
|
+
compareJsonValues(a.env_clear, b.env_clear, []),
|
|
3588
|
+
compareJsonValues(a.env_set, b.env_set, {}),
|
|
3589
|
+
compareJsonValues(a.assert_stdout_contains, b.assert_stdout_contains, []),
|
|
3590
|
+
compareJsonValues(a.assert_stdout_regex, b.assert_stdout_regex, []),
|
|
3591
|
+
compareJsonValues(a.assert_stderr_contains, b.assert_stderr_contains, []),
|
|
3592
|
+
compareJsonValues(a.assert_stderr_regex, b.assert_stderr_regex, []),
|
|
3593
|
+
compareOptionalNumbers(a.assert_stdout_min_lines, b.assert_stdout_min_lines),
|
|
3594
|
+
compareJsonValues(a.assert_json_field_equals, b.assert_json_field_equals, {}),
|
|
3595
|
+
compareJsonValues(a.assert_json_field_gte, b.assert_json_field_gte, {}),
|
|
3596
|
+
compareOptionalStrings(a.note, b.note)
|
|
3597
|
+
]);
|
|
3598
|
+
}
|
|
3599
|
+
function compareOptionalStrings(left, right) {
|
|
3600
|
+
return (left ?? "").localeCompare(right ?? "");
|
|
3601
|
+
}
|
|
3602
|
+
function compareOptionalNumbers(left, right) {
|
|
3603
|
+
return (left ?? 0) - (right ?? 0);
|
|
3604
|
+
}
|
|
3605
|
+
function compareJsonValues(left, right, fallback) {
|
|
3606
|
+
return JSON.stringify(left ?? fallback).localeCompare(JSON.stringify(right ?? fallback));
|
|
3607
|
+
}
|
|
3608
|
+
function sortDocs(values) {
|
|
3609
|
+
if (!values || values.length === 0)
|
|
3610
|
+
return void 0;
|
|
3611
|
+
return [...values].map((value) => ({
|
|
3612
|
+
path: normalizePathValue(value.path),
|
|
3613
|
+
scope: value.scope,
|
|
3614
|
+
note: value.note?.trim() || void 0
|
|
3615
|
+
})).sort((a, b) => {
|
|
3616
|
+
const byScope = a.scope.localeCompare(b.scope);
|
|
3617
|
+
if (byScope !== 0)
|
|
3618
|
+
return byScope;
|
|
3619
|
+
const byPath = a.path.localeCompare(b.path);
|
|
3620
|
+
if (byPath !== 0)
|
|
3621
|
+
return byPath;
|
|
3622
|
+
return (a.note ?? "").localeCompare(b.note ?? "");
|
|
3623
|
+
});
|
|
3624
|
+
}
|
|
3625
|
+
function trimStringOrUndefined(value) {
|
|
3626
|
+
if (typeof value !== "string")
|
|
3627
|
+
return void 0;
|
|
3628
|
+
const trimmed = value.trim();
|
|
3629
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
3630
|
+
}
|
|
3631
|
+
function normalizePlanStepLinks(value) {
|
|
3632
|
+
if (!Array.isArray(value))
|
|
3633
|
+
return void 0;
|
|
3634
|
+
const out = [];
|
|
3635
|
+
for (const entry of value) {
|
|
3636
|
+
if (entry === null || typeof entry !== "object")
|
|
3632
3637
|
continue;
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3638
|
+
const record = entry;
|
|
3639
|
+
const id = trimStringOrUndefined(record.id);
|
|
3640
|
+
const kind = trimStringOrUndefined(record.kind);
|
|
3641
|
+
if (!id || !kind)
|
|
3636
3642
|
continue;
|
|
3637
|
-
}
|
|
3638
|
-
|
|
3639
|
-
|
|
3643
|
+
const link = { id, kind };
|
|
3644
|
+
const note = trimStringOrUndefined(record.note);
|
|
3645
|
+
if (note)
|
|
3646
|
+
link.note = note;
|
|
3647
|
+
if (record.required_before_step === true)
|
|
3648
|
+
link.required_before_step = true;
|
|
3649
|
+
out.push(link);
|
|
3650
|
+
}
|
|
3651
|
+
return out.length > 0 ? out : void 0;
|
|
3652
|
+
}
|
|
3653
|
+
function normalizePlanStepFiles(value) {
|
|
3654
|
+
if (!Array.isArray(value))
|
|
3655
|
+
return void 0;
|
|
3656
|
+
const out = [];
|
|
3657
|
+
for (const entry of value) {
|
|
3658
|
+
if (entry === null || typeof entry !== "object")
|
|
3640
3659
|
continue;
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3660
|
+
const record = entry;
|
|
3661
|
+
const path6 = trimStringOrUndefined(record.path);
|
|
3662
|
+
if (!path6)
|
|
3663
|
+
continue;
|
|
3664
|
+
const file = { path: normalizePathValue(path6) };
|
|
3665
|
+
if (record.scope === "project" || record.scope === "global")
|
|
3666
|
+
file.scope = record.scope;
|
|
3667
|
+
const note = trimStringOrUndefined(record.note);
|
|
3668
|
+
if (note)
|
|
3669
|
+
file.note = note;
|
|
3670
|
+
out.push(file);
|
|
3671
|
+
}
|
|
3672
|
+
return out.length > 0 ? out : void 0;
|
|
3673
|
+
}
|
|
3674
|
+
function normalizePlanStepTests(value) {
|
|
3675
|
+
if (!Array.isArray(value))
|
|
3676
|
+
return void 0;
|
|
3677
|
+
const out = [];
|
|
3678
|
+
for (const entry of value) {
|
|
3679
|
+
if (entry === null || typeof entry !== "object")
|
|
3680
|
+
continue;
|
|
3681
|
+
const record = entry;
|
|
3682
|
+
const command = trimStringOrUndefined(record.command);
|
|
3683
|
+
const path6 = trimStringOrUndefined(record.path);
|
|
3684
|
+
if (!command && !path6)
|
|
3685
|
+
continue;
|
|
3686
|
+
const test = {};
|
|
3687
|
+
if (command)
|
|
3688
|
+
test.command = command;
|
|
3689
|
+
if (path6)
|
|
3690
|
+
test.path = normalizePathValue(path6);
|
|
3691
|
+
const note = trimStringOrUndefined(record.note);
|
|
3692
|
+
if (note)
|
|
3693
|
+
test.note = note;
|
|
3694
|
+
out.push(test);
|
|
3695
|
+
}
|
|
3696
|
+
return out.length > 0 ? out : void 0;
|
|
3697
|
+
}
|
|
3698
|
+
function normalizePlanStepDocs(value) {
|
|
3699
|
+
if (!Array.isArray(value))
|
|
3700
|
+
return void 0;
|
|
3701
|
+
const out = [];
|
|
3702
|
+
for (const entry of value) {
|
|
3703
|
+
if (entry === null || typeof entry !== "object")
|
|
3704
|
+
continue;
|
|
3705
|
+
const record = entry;
|
|
3706
|
+
const path6 = trimStringOrUndefined(record.path);
|
|
3707
|
+
if (!path6)
|
|
3708
|
+
continue;
|
|
3709
|
+
const doc = { path: normalizePathValue(path6) };
|
|
3710
|
+
if (record.scope === "project" || record.scope === "global")
|
|
3711
|
+
doc.scope = record.scope;
|
|
3712
|
+
const note = trimStringOrUndefined(record.note);
|
|
3713
|
+
if (note)
|
|
3714
|
+
doc.note = note;
|
|
3715
|
+
out.push(doc);
|
|
3716
|
+
}
|
|
3717
|
+
return out.length > 0 ? out : void 0;
|
|
3718
|
+
}
|
|
3719
|
+
function normalizePlanStepEntry(entry) {
|
|
3720
|
+
if (entry === null || typeof entry !== "object") {
|
|
3721
|
+
return void 0;
|
|
3722
|
+
}
|
|
3723
|
+
const record = entry;
|
|
3724
|
+
const id = trimStringOrUndefined(record.id);
|
|
3725
|
+
const title = trimStringOrUndefined(record.title);
|
|
3726
|
+
const statusRaw = trimStringOrUndefined(record.status);
|
|
3727
|
+
const status = statusRaw && PLAN_STEP_STATUS_SET.has(statusRaw) ? statusRaw : void 0;
|
|
3728
|
+
const order = coerceFiniteNumber(record.order) ?? Number.NaN;
|
|
3729
|
+
const created_at = typeof record.created_at === "string" ? record.created_at : "";
|
|
3730
|
+
const updated_at = typeof record.updated_at === "string" ? record.updated_at : "";
|
|
3731
|
+
if (!id || !title || !status || !Number.isFinite(order) || !created_at || !updated_at) {
|
|
3732
|
+
return void 0;
|
|
3648
3733
|
}
|
|
3649
|
-
|
|
3734
|
+
const step = {
|
|
3735
|
+
id,
|
|
3736
|
+
order,
|
|
3737
|
+
title,
|
|
3738
|
+
status,
|
|
3739
|
+
created_at,
|
|
3740
|
+
updated_at
|
|
3741
|
+
};
|
|
3742
|
+
applyPlanStepOptionalFields(step, record);
|
|
3743
|
+
return step;
|
|
3650
3744
|
}
|
|
3651
|
-
function
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3745
|
+
function applyPlanStepOptionalFields(step, record) {
|
|
3746
|
+
const stringFields = [
|
|
3747
|
+
["body", "body"],
|
|
3748
|
+
["owner", "owner"],
|
|
3749
|
+
["evidence", "evidence"],
|
|
3750
|
+
["blocked_reason", "blocked_reason"],
|
|
3751
|
+
["superseded_by", "superseded_by"]
|
|
3752
|
+
];
|
|
3753
|
+
for (const [target, source] of stringFields) {
|
|
3754
|
+
const value = trimStringOrUndefined(record[source]);
|
|
3755
|
+
if (value) {
|
|
3756
|
+
step[target] = value;
|
|
3757
|
+
}
|
|
3658
3758
|
}
|
|
3659
|
-
const
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
}
|
|
3663
|
-
function stripLeadingYamlDocument(content) {
|
|
3664
|
-
const normalizedContent = content.charCodeAt(0) === 65279 ? content.slice(1) : content;
|
|
3665
|
-
const opener = normalizedContent.match(/^[ \t]*---[ \t]*(?:\r?\n|$)/);
|
|
3666
|
-
if (!opener) {
|
|
3667
|
-
return { content: normalizedContent, stripped: false };
|
|
3759
|
+
const completedAt = typeof record.completed_at === "string" ? record.completed_at : void 0;
|
|
3760
|
+
if (completedAt && completedAt.length > 0) {
|
|
3761
|
+
step.completed_at = completedAt;
|
|
3668
3762
|
}
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
};
|
|
3763
|
+
const collectionFields = [
|
|
3764
|
+
["linked_items", "linked_items", normalizePlanStepLinks],
|
|
3765
|
+
["files", "files", normalizePlanStepFiles],
|
|
3766
|
+
["tests", "tests", normalizePlanStepTests],
|
|
3767
|
+
["docs", "docs", normalizePlanStepDocs]
|
|
3768
|
+
];
|
|
3769
|
+
for (const [target, source, normalize] of collectionFields) {
|
|
3770
|
+
const value = normalize(record[source]);
|
|
3771
|
+
if (value) {
|
|
3772
|
+
step[target] = value;
|
|
3680
3773
|
}
|
|
3681
|
-
cursor = afterLine;
|
|
3682
3774
|
}
|
|
3683
|
-
return { content: normalizedContent, stripped: false };
|
|
3684
3775
|
}
|
|
3685
|
-
function
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3776
|
+
function normalizePlanSteps(value) {
|
|
3777
|
+
if (!Array.isArray(value))
|
|
3778
|
+
return void 0;
|
|
3779
|
+
const out = value.flatMap((entry) => {
|
|
3780
|
+
const step = normalizePlanStepEntry(entry);
|
|
3781
|
+
return step ? [step] : [];
|
|
3689
3782
|
});
|
|
3783
|
+
out.sort((left, right) => left.order - right.order);
|
|
3784
|
+
return out.length > 0 ? out : void 0;
|
|
3690
3785
|
}
|
|
3691
|
-
function
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
const
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3786
|
+
function normalizePlanDecisions(value) {
|
|
3787
|
+
if (!Array.isArray(value))
|
|
3788
|
+
return void 0;
|
|
3789
|
+
const out = [];
|
|
3790
|
+
for (const entry of value) {
|
|
3791
|
+
if (entry === null || typeof entry !== "object")
|
|
3792
|
+
continue;
|
|
3793
|
+
const record = entry;
|
|
3794
|
+
const ts = typeof record.ts === "string" ? record.ts : "";
|
|
3795
|
+
const author = typeof record.author === "string" ? record.author : "";
|
|
3796
|
+
const decision = trimStringOrUndefined(record.decision);
|
|
3797
|
+
if (!ts || !author || !decision)
|
|
3798
|
+
continue;
|
|
3799
|
+
const item = { ts, author, decision };
|
|
3800
|
+
const rationale = trimStringOrUndefined(record.rationale);
|
|
3801
|
+
if (rationale)
|
|
3802
|
+
item.rationale = rationale;
|
|
3803
|
+
const evidence = trimStringOrUndefined(record.evidence);
|
|
3804
|
+
if (evidence)
|
|
3805
|
+
item.evidence = evidence;
|
|
3806
|
+
const stepId = trimStringOrUndefined(record.step_id);
|
|
3807
|
+
if (stepId)
|
|
3808
|
+
item.step_id = stepId;
|
|
3809
|
+
out.push(item);
|
|
3709
3810
|
}
|
|
3710
|
-
|
|
3711
|
-
return {
|
|
3712
|
-
metadata: normalizeParsedItemMetadata(parsed, options),
|
|
3713
|
-
body: normalizeBody(body)
|
|
3714
|
-
};
|
|
3811
|
+
return out.length > 0 ? out : void 0;
|
|
3715
3812
|
}
|
|
3716
|
-
function
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3813
|
+
function normalizePlanDiscoveries(value) {
|
|
3814
|
+
if (!Array.isArray(value))
|
|
3815
|
+
return void 0;
|
|
3816
|
+
const out = [];
|
|
3817
|
+
for (const entry of value) {
|
|
3818
|
+
if (entry === null || typeof entry !== "object")
|
|
3819
|
+
continue;
|
|
3820
|
+
const record = entry;
|
|
3821
|
+
const ts = typeof record.ts === "string" ? record.ts : "";
|
|
3822
|
+
const author = typeof record.author === "string" ? record.author : "";
|
|
3823
|
+
const text = trimStringOrUndefined(record.text);
|
|
3824
|
+
if (!ts || !author || !text)
|
|
3825
|
+
continue;
|
|
3826
|
+
const item = { ts, author, text };
|
|
3827
|
+
const stepId = trimStringOrUndefined(record.step_id);
|
|
3828
|
+
if (stepId)
|
|
3829
|
+
item.step_id = stepId;
|
|
3830
|
+
out.push(item);
|
|
3732
3831
|
}
|
|
3733
|
-
|
|
3734
|
-
assertItemMetadataCondition(body === void 0 || typeof body === "string", "TOON item document body must be a string");
|
|
3735
|
-
assertValidItemMetadata(itemMetadataRecord, runtimeContext);
|
|
3736
|
-
return {
|
|
3737
|
-
metadata: normalizeParsedItemMetadata(itemMetadataRecord, options),
|
|
3738
|
-
body: normalizeBody(typeof body === "string" ? body : "")
|
|
3739
|
-
};
|
|
3832
|
+
return out.length > 0 ? out : void 0;
|
|
3740
3833
|
}
|
|
3741
|
-
function
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
const
|
|
3745
|
-
const
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3834
|
+
function normalizePlanValidation(value) {
|
|
3835
|
+
if (!Array.isArray(value))
|
|
3836
|
+
return void 0;
|
|
3837
|
+
const out = [];
|
|
3838
|
+
for (const entry of value) {
|
|
3839
|
+
if (entry === null || typeof entry !== "object")
|
|
3840
|
+
continue;
|
|
3841
|
+
const record = entry;
|
|
3842
|
+
const text = trimStringOrUndefined(record.text);
|
|
3843
|
+
if (!text)
|
|
3844
|
+
continue;
|
|
3845
|
+
const item = { text };
|
|
3846
|
+
const command = trimStringOrUndefined(record.command);
|
|
3847
|
+
if (command)
|
|
3848
|
+
item.command = command;
|
|
3849
|
+
const expected = trimStringOrUndefined(record.expected);
|
|
3850
|
+
if (expected)
|
|
3851
|
+
item.expected = expected;
|
|
3852
|
+
out.push(item);
|
|
3749
3853
|
}
|
|
3750
|
-
return
|
|
3751
|
-
|
|
3752
|
-
${normalizedBody}
|
|
3753
|
-
`;
|
|
3754
|
-
}
|
|
3755
|
-
function serializeToonItemDocument(document, options = {}) {
|
|
3756
|
-
const normalizedMetadata = normalizeItemMetadata(document.metadata, options);
|
|
3757
|
-
const orderedMetadata = orderItemMetadata(normalizedMetadata);
|
|
3758
|
-
const normalizedBody = normalizeBody(document.body ?? "");
|
|
3759
|
-
return `${encodeToon({ ...orderedMetadata, body: normalizedBody })}
|
|
3760
|
-
`;
|
|
3854
|
+
return out.length > 0 ? out : void 0;
|
|
3761
3855
|
}
|
|
3762
|
-
function
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
throw new PmCliError(`Merge conflict markers detected in item document at line ${conflictMarker.line} (${conflictMarker.marker}). Resolve <<<<<<< ======= >>>>>>> markers and retry.`, EXIT_CODE.GENERIC_FAILURE, {
|
|
3766
|
-
code: "merge_conflict_markers_detected",
|
|
3767
|
-
required: "Resolve merge-conflict markers in the item file before parsing or mutation commands.",
|
|
3768
|
-
why: "Partially merged documents can corrupt item metadata and history integrity.",
|
|
3769
|
-
examples: ["git status", "git add <resolved-file> && git commit"],
|
|
3770
|
-
nextSteps: [
|
|
3771
|
-
"Resolve conflicts, save the file, then rerun the pm command."
|
|
3772
|
-
]
|
|
3773
|
-
});
|
|
3856
|
+
function normalizeTypeOptions(values) {
|
|
3857
|
+
if (!values) {
|
|
3858
|
+
return void 0;
|
|
3774
3859
|
}
|
|
3775
|
-
const
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
}
|
|
3779
|
-
function serializeItemDocument(document, options = {}) {
|
|
3780
|
-
const format = options.format ?? "toon";
|
|
3781
|
-
return format === "toon" ? serializeToonItemDocument(document, options) : serializeJsonMarkdownItemDocument(document, options);
|
|
3782
|
-
}
|
|
3783
|
-
function canonicalDocument(document, options = {}) {
|
|
3784
|
-
return {
|
|
3785
|
-
metadata: normalizeItemMetadata(document.metadata, options),
|
|
3786
|
-
body: normalizeBody(document.body ?? "")
|
|
3787
|
-
};
|
|
3788
|
-
}
|
|
3789
|
-
|
|
3790
|
-
// dist/core/item/item-record.js
|
|
3791
|
-
!(function() {
|
|
3792
|
-
try {
|
|
3793
|
-
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
3794
|
-
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "30de0e7a-3307-5231-af8c-bae7a2b6374b");
|
|
3795
|
-
} catch (e2) {
|
|
3860
|
+
const normalizedEntries = Object.entries(values).map(([key, value]) => [key.trim(), value.trim()]).filter(([key, value]) => key.length > 0 && value.length > 0).sort((left, right) => left[0].localeCompare(right[0]));
|
|
3861
|
+
if (normalizedEntries.length === 0) {
|
|
3862
|
+
return void 0;
|
|
3796
3863
|
}
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3864
|
+
return Object.fromEntries(normalizedEntries);
|
|
3865
|
+
}
|
|
3866
|
+
function normalizeBody(body) {
|
|
3867
|
+
let start = 0;
|
|
3868
|
+
while (start < body.length && body[start] === "\n") {
|
|
3869
|
+
start += 1;
|
|
3870
|
+
}
|
|
3871
|
+
return body.slice(start).trimEnd();
|
|
3800
3872
|
}
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
!(function() {
|
|
3805
|
-
try {
|
|
3806
|
-
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
3807
|
-
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "45cc07c9-b6f9-5851-9f98-4167976035b1");
|
|
3808
|
-
} catch (e2) {
|
|
3873
|
+
function normalizeConfidenceValue(value) {
|
|
3874
|
+
if (value === void 0) {
|
|
3875
|
+
return void 0;
|
|
3809
3876
|
}
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
front_matter: {},
|
|
3813
|
-
body: ""
|
|
3814
|
-
};
|
|
3815
|
-
function decodeJsonPointer(path6) {
|
|
3816
|
-
if (!path6 || path6 === "/") {
|
|
3817
|
-
return [];
|
|
3877
|
+
if (typeof value === "number") {
|
|
3878
|
+
return value;
|
|
3818
3879
|
}
|
|
3819
|
-
|
|
3820
|
-
|
|
3880
|
+
const normalized = value.trim().toLowerCase();
|
|
3881
|
+
if (normalized === "med") {
|
|
3882
|
+
return "medium";
|
|
3821
3883
|
}
|
|
3822
|
-
|
|
3884
|
+
if (CONFIDENCE_TEXT_VALUES.includes(normalized)) {
|
|
3885
|
+
return normalized;
|
|
3886
|
+
}
|
|
3887
|
+
return void 0;
|
|
3823
3888
|
}
|
|
3824
|
-
function
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
return true;
|
|
3889
|
+
function normalizeSeverityValue(value) {
|
|
3890
|
+
if (value === void 0) {
|
|
3891
|
+
return void 0;
|
|
3828
3892
|
}
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3893
|
+
const normalized = value.trim().toLowerCase();
|
|
3894
|
+
if (normalized === "med") {
|
|
3895
|
+
return "medium";
|
|
3896
|
+
}
|
|
3897
|
+
if (ISSUE_SEVERITY_VALUES.includes(normalized)) {
|
|
3898
|
+
return normalized;
|
|
3899
|
+
}
|
|
3900
|
+
return void 0;
|
|
3901
|
+
}
|
|
3902
|
+
function emptyStringToUndefined(value) {
|
|
3903
|
+
return value || void 0;
|
|
3904
|
+
}
|
|
3905
|
+
function copyExtensionItemMetadataFields(normalized, source) {
|
|
3906
|
+
const targetRecord = normalized;
|
|
3907
|
+
const sourceRecord = source;
|
|
3908
|
+
for (const [key, value] of Object.entries(sourceRecord)) {
|
|
3909
|
+
if (isUnsafeObjectKey(key) || Object.prototype.hasOwnProperty.call(targetRecord, key) || value === void 0) {
|
|
3844
3910
|
continue;
|
|
3845
3911
|
}
|
|
3846
|
-
|
|
3847
|
-
return false;
|
|
3848
|
-
}
|
|
3849
|
-
if (!Object.prototype.hasOwnProperty.call(cursor, segment)) {
|
|
3850
|
-
return false;
|
|
3851
|
-
}
|
|
3852
|
-
const next = cursor[segment];
|
|
3853
|
-
if (next === void 0) {
|
|
3854
|
-
return false;
|
|
3855
|
-
}
|
|
3856
|
-
cursor = next;
|
|
3912
|
+
targetRecord[key] = value;
|
|
3857
3913
|
}
|
|
3858
|
-
return true;
|
|
3859
3914
|
}
|
|
3860
|
-
function
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
for (const operation of patch) {
|
|
3864
|
-
const normalizedOperation = operation.op === "replace" && !isDefinedPointerPath(replayCursor, operation.path) ? { ...operation, op: "add" } : operation;
|
|
3865
|
-
normalized.push(normalizedOperation);
|
|
3866
|
-
replayCursor = jsonPatch.applyPatch(replayCursor, [normalizedOperation], true, true).newDocument;
|
|
3915
|
+
function coerceNormalizedRuntimeFields(normalized, runtimeContext) {
|
|
3916
|
+
if (!runtimeContext?.fieldRegistry) {
|
|
3917
|
+
return;
|
|
3867
3918
|
}
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
body: document.body ?? ""
|
|
3876
|
-
};
|
|
3919
|
+
const record = normalized;
|
|
3920
|
+
for (const definition of runtimeContext.fieldRegistry.definitions) {
|
|
3921
|
+
const currentValue = record[definition.metadata_key];
|
|
3922
|
+
if (currentValue === void 0) {
|
|
3923
|
+
continue;
|
|
3924
|
+
}
|
|
3925
|
+
record[definition.metadata_key] = coerceRuntimeFieldValue(definition, currentValue, `metadata field "${definition.metadata_key}"`);
|
|
3877
3926
|
}
|
|
3878
|
-
const canonical = canonicalDocument(document);
|
|
3879
|
-
const orderedMetadata = orderObject(toItemRecord(canonical.metadata), ITEM_METADATA_KEY_ORDER);
|
|
3880
|
-
return {
|
|
3881
|
-
front_matter: orderedMetadata,
|
|
3882
|
-
body: canonical.body
|
|
3883
|
-
};
|
|
3884
3927
|
}
|
|
3885
|
-
function
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3928
|
+
function assertNormalizedUnknownFields(normalized, runtimeContext) {
|
|
3929
|
+
if (!runtimeContext || runtimeContext.unknownFieldPolicy === "allow") {
|
|
3930
|
+
return;
|
|
3931
|
+
}
|
|
3932
|
+
const knownKeys = buildKnownItemMetadataKeys(runtimeContext);
|
|
3933
|
+
const record = normalized;
|
|
3934
|
+
const unknownKeys = Object.keys(record).filter((key) => !knownKeys.has(key)).sort((left, right) => left.localeCompare(right));
|
|
3935
|
+
if (unknownKeys.length > 0 && runtimeContext.unknownFieldPolicy === "reject") {
|
|
3936
|
+
validationError(`unknown schema fields are not allowed: ${unknownKeys.join(", ")}`);
|
|
3937
|
+
}
|
|
3938
|
+
if (unknownKeys.length > 0) {
|
|
3939
|
+
runtimeContext.onWarning?.(`item_unknown_schema_fields:${unknownKeys.join(",")}`);
|
|
3892
3940
|
}
|
|
3893
|
-
const canonical = canonicalDocument(document);
|
|
3894
|
-
const orderedMetadata = orderObject(toItemRecord(canonical.metadata), ITEM_METADATA_KEY_ORDER);
|
|
3895
|
-
return {
|
|
3896
|
-
metadata: orderedMetadata,
|
|
3897
|
-
body: canonical.body
|
|
3898
|
-
};
|
|
3899
|
-
}
|
|
3900
|
-
function hashDocument(document) {
|
|
3901
|
-
return sha256Hex(stableStringify(canonicalHashDocument(document)));
|
|
3902
|
-
}
|
|
3903
|
-
function hashEmptyDocument() {
|
|
3904
|
-
return sha256Hex(stableStringify(EMPTY_LEGACY_HASH_DOCUMENT));
|
|
3905
3941
|
}
|
|
3906
|
-
function
|
|
3907
|
-
const
|
|
3908
|
-
const
|
|
3909
|
-
const
|
|
3910
|
-
const
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3942
|
+
function normalizeItemMetadata(itemMetadata, options = {}) {
|
|
3943
|
+
const runtimeContext = resolveRuntimeSchemaValidationContext(options);
|
|
3944
|
+
const normalizedStatus = normalizeStatusInput(itemMetadata.status, runtimeContext?.statusRegistry) ?? itemMetadata.status;
|
|
3945
|
+
const tags = Array.from(new Set(itemMetadata.tags.map((tag) => tag.trim().toLowerCase()).filter(Boolean))).sort((a, b) => a.localeCompare(b));
|
|
3946
|
+
const normalized = {
|
|
3947
|
+
id: itemMetadata.id,
|
|
3948
|
+
title: itemMetadata.title,
|
|
3949
|
+
description: itemMetadata.description,
|
|
3950
|
+
type: itemMetadata.type,
|
|
3951
|
+
pm_format_version: normalizeItemFormatVersion(itemMetadata.pm_format_version),
|
|
3952
|
+
source_type: trimStringOrUndefined(itemMetadata.source_type),
|
|
3953
|
+
type_options: normalizeTypeOptions(itemMetadata.type_options),
|
|
3954
|
+
status: normalizedStatus,
|
|
3955
|
+
priority: itemMetadata.priority,
|
|
3956
|
+
tags,
|
|
3957
|
+
created_at: itemMetadata.created_at,
|
|
3958
|
+
updated_at: itemMetadata.updated_at,
|
|
3959
|
+
dependencies: sortDependencies(itemMetadata.dependencies),
|
|
3960
|
+
comments: sortLogValues(itemMetadata.comments),
|
|
3961
|
+
notes: sortLogValues(itemMetadata.notes),
|
|
3962
|
+
learnings: sortLogValues(itemMetadata.learnings),
|
|
3963
|
+
files: normalizeFiles(itemMetadata.files),
|
|
3964
|
+
tests: sortTests(itemMetadata.tests),
|
|
3965
|
+
test_runs: normalizeTestRunSummaries(itemMetadata.test_runs),
|
|
3966
|
+
docs: sortDocs(itemMetadata.docs),
|
|
3967
|
+
deadline: emptyStringToUndefined(itemMetadata.deadline),
|
|
3968
|
+
reminders: sortReminders(itemMetadata.reminders),
|
|
3969
|
+
events: sortEvents(itemMetadata.events),
|
|
3970
|
+
closed_at: emptyStringToUndefined(itemMetadata.closed_at),
|
|
3971
|
+
assignee: trimStringOrUndefined(itemMetadata.assignee),
|
|
3972
|
+
source_owner: trimStringOrUndefined(itemMetadata.source_owner),
|
|
3973
|
+
author: emptyStringToUndefined(itemMetadata.author),
|
|
3974
|
+
estimated_minutes: itemMetadata.estimated_minutes,
|
|
3975
|
+
acceptance_criteria: itemMetadata.acceptance_criteria ?? void 0,
|
|
3976
|
+
design: itemMetadata.design ?? void 0,
|
|
3977
|
+
external_ref: itemMetadata.external_ref ?? void 0,
|
|
3978
|
+
definition_of_ready: trimStringOrUndefined(itemMetadata.definition_of_ready),
|
|
3979
|
+
order: itemMetadata.order,
|
|
3980
|
+
goal: trimStringOrUndefined(itemMetadata.goal),
|
|
3981
|
+
objective: trimStringOrUndefined(itemMetadata.objective),
|
|
3982
|
+
value: trimStringOrUndefined(itemMetadata.value),
|
|
3983
|
+
impact: trimStringOrUndefined(itemMetadata.impact),
|
|
3984
|
+
outcome: trimStringOrUndefined(itemMetadata.outcome),
|
|
3985
|
+
why_now: trimStringOrUndefined(itemMetadata.why_now),
|
|
3986
|
+
parent: trimStringOrUndefined(itemMetadata.parent),
|
|
3987
|
+
reviewer: trimStringOrUndefined(itemMetadata.reviewer),
|
|
3988
|
+
risk: itemMetadata.risk ?? void 0,
|
|
3989
|
+
confidence: normalizeConfidenceValue(itemMetadata.confidence),
|
|
3990
|
+
sprint: trimStringOrUndefined(itemMetadata.sprint),
|
|
3991
|
+
release: trimStringOrUndefined(itemMetadata.release),
|
|
3992
|
+
blocked_by: trimStringOrUndefined(itemMetadata.blocked_by),
|
|
3993
|
+
blocked_reason: trimStringOrUndefined(itemMetadata.blocked_reason),
|
|
3994
|
+
unblock_note: trimStringOrUndefined(itemMetadata.unblock_note),
|
|
3995
|
+
reporter: trimStringOrUndefined(itemMetadata.reporter),
|
|
3996
|
+
severity: normalizeSeverityValue(itemMetadata.severity),
|
|
3997
|
+
environment: trimStringOrUndefined(itemMetadata.environment),
|
|
3998
|
+
repro_steps: trimStringOrUndefined(itemMetadata.repro_steps),
|
|
3999
|
+
resolution: trimStringOrUndefined(itemMetadata.resolution),
|
|
4000
|
+
expected_result: trimStringOrUndefined(itemMetadata.expected_result),
|
|
4001
|
+
actual_result: trimStringOrUndefined(itemMetadata.actual_result),
|
|
4002
|
+
affected_version: trimStringOrUndefined(itemMetadata.affected_version),
|
|
4003
|
+
fixed_version: trimStringOrUndefined(itemMetadata.fixed_version),
|
|
4004
|
+
component: trimStringOrUndefined(itemMetadata.component),
|
|
4005
|
+
regression: itemMetadata.regression,
|
|
4006
|
+
customer_impact: trimStringOrUndefined(itemMetadata.customer_impact),
|
|
4007
|
+
close_reason: emptyStringToUndefined(itemMetadata.close_reason),
|
|
4008
|
+
plan_mode: trimStringOrUndefined(itemMetadata.plan_mode),
|
|
4009
|
+
plan_scope: trimStringOrUndefined(itemMetadata.plan_scope),
|
|
4010
|
+
plan_harness: trimStringOrUndefined(itemMetadata.plan_harness),
|
|
4011
|
+
plan_resume_context: trimStringOrUndefined(itemMetadata.plan_resume_context),
|
|
4012
|
+
plan_steps: normalizePlanSteps(itemMetadata.plan_steps),
|
|
4013
|
+
plan_decisions: normalizePlanDecisions(itemMetadata.plan_decisions),
|
|
4014
|
+
plan_discoveries: normalizePlanDiscoveries(itemMetadata.plan_discoveries),
|
|
4015
|
+
plan_validation: normalizePlanValidation(itemMetadata.plan_validation)
|
|
3921
4016
|
};
|
|
4017
|
+
copyExtensionItemMetadataFields(normalized, itemMetadata);
|
|
4018
|
+
coerceNormalizedRuntimeFields(normalized, runtimeContext);
|
|
4019
|
+
assertNormalizedUnknownFields(normalized, runtimeContext);
|
|
4020
|
+
deleteUndefinedFields(normalized);
|
|
4021
|
+
return normalized;
|
|
3922
4022
|
}
|
|
3923
|
-
function
|
|
3924
|
-
return
|
|
3925
|
-
}
|
|
3926
|
-
function fallbackHistoryTimestamp(entry) {
|
|
3927
|
-
const ts = entry.ts.trim();
|
|
3928
|
-
return ts.length > 0 ? ts : nowIso();
|
|
3929
|
-
}
|
|
3930
|
-
function withHistoryTimestamp(value, fallbackTs) {
|
|
3931
|
-
const ts = value.ts;
|
|
3932
|
-
if (typeof ts === "string" && ts.trim().length > 0) {
|
|
3933
|
-
return value;
|
|
3934
|
-
}
|
|
3935
|
-
return { ...value, ts: fallbackTs };
|
|
4023
|
+
function orderItemMetadata(itemMetadata) {
|
|
4024
|
+
return orderObject(itemMetadata, ITEM_METADATA_KEY_ORDER);
|
|
3936
4025
|
}
|
|
3937
|
-
function
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
4026
|
+
function findJsonObjectEnd(content) {
|
|
4027
|
+
let depth = 0;
|
|
4028
|
+
let inString = false;
|
|
4029
|
+
let escaped = false;
|
|
4030
|
+
for (let i = 0; i < content.length; i += 1) {
|
|
4031
|
+
const char = content[i];
|
|
4032
|
+
if (inString) {
|
|
4033
|
+
if (escaped) {
|
|
4034
|
+
escaped = false;
|
|
4035
|
+
continue;
|
|
3944
4036
|
}
|
|
3945
|
-
|
|
4037
|
+
if (char === "\\") {
|
|
4038
|
+
escaped = true;
|
|
4039
|
+
continue;
|
|
4040
|
+
}
|
|
4041
|
+
if (char === '"') {
|
|
4042
|
+
inString = false;
|
|
4043
|
+
}
|
|
4044
|
+
continue;
|
|
3946
4045
|
}
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
return JSON.stringify(withHistoryTimestamp(value, fallbackTs));
|
|
3951
|
-
}
|
|
3952
|
-
return JSON.stringify(value);
|
|
3953
|
-
}
|
|
3954
|
-
async function appendHistoryEntry(historyPath, entry) {
|
|
3955
|
-
const override = await runActiveServiceOverride("history_append", {
|
|
3956
|
-
history_path: historyPath,
|
|
3957
|
-
entry
|
|
3958
|
-
});
|
|
3959
|
-
if (override.handled) {
|
|
3960
|
-
if (override.result === false) {
|
|
3961
|
-
return;
|
|
4046
|
+
if (char === '"') {
|
|
4047
|
+
inString = true;
|
|
4048
|
+
continue;
|
|
3962
4049
|
}
|
|
3963
|
-
if (
|
|
3964
|
-
|
|
3965
|
-
|
|
4050
|
+
if (char === "{") {
|
|
4051
|
+
depth += 1;
|
|
4052
|
+
continue;
|
|
3966
4053
|
}
|
|
3967
|
-
if (
|
|
3968
|
-
|
|
3969
|
-
if (
|
|
3970
|
-
return;
|
|
3971
|
-
}
|
|
3972
|
-
const nextHistoryPath = typeof record.history_path === "string" ? record.history_path : historyPath;
|
|
3973
|
-
if (typeof record.line === "string") {
|
|
3974
|
-
await appendLineAtomic(nextHistoryPath, serializeHistoryLine(record.line, entry));
|
|
3975
|
-
return;
|
|
4054
|
+
if (char === "}") {
|
|
4055
|
+
depth -= 1;
|
|
4056
|
+
if (depth === 0) {
|
|
4057
|
+
return i;
|
|
3976
4058
|
}
|
|
3977
|
-
await appendLineAtomic(nextHistoryPath, serializeHistoryLine(record.entry ?? entry, entry));
|
|
3978
|
-
return;
|
|
3979
4059
|
}
|
|
3980
4060
|
}
|
|
3981
|
-
|
|
4061
|
+
return -1;
|
|
3982
4062
|
}
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
import path from "node:path";
|
|
3987
|
-
!(function() {
|
|
3988
|
-
try {
|
|
3989
|
-
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
3990
|
-
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "0e1bb27d-a1ac-57ae-b879-29318d827578");
|
|
3991
|
-
} catch (e2) {
|
|
4063
|
+
function splitFrontMatter(content) {
|
|
4064
|
+
if (!content.startsWith("{")) {
|
|
4065
|
+
return { frontMatter: "", body: content };
|
|
3992
4066
|
}
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
}
|
|
3997
|
-
|
|
3998
|
-
|
|
4067
|
+
const end = findJsonObjectEnd(content);
|
|
4068
|
+
if (end < 0) {
|
|
4069
|
+
return { frontMatter: "", body: content };
|
|
4070
|
+
}
|
|
4071
|
+
const frontMatter = content.slice(0, end + 1);
|
|
4072
|
+
const body = content.slice(end + 1).replace(/^\r?\n+/, "");
|
|
4073
|
+
return { frontMatter, body };
|
|
3999
4074
|
}
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
const
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4075
|
+
function stripLeadingYamlDocument(content) {
|
|
4076
|
+
const normalizedContent = content.charCodeAt(0) === 65279 ? content.slice(1) : content;
|
|
4077
|
+
const opener = normalizedContent.match(/^[ \t]*---[ \t]*(?:\r?\n|$)/);
|
|
4078
|
+
if (!opener) {
|
|
4079
|
+
return { content: normalizedContent, stripped: false };
|
|
4080
|
+
}
|
|
4081
|
+
let cursor = opener[0].length;
|
|
4082
|
+
while (cursor < normalizedContent.length) {
|
|
4083
|
+
const nextNewline = normalizedContent.indexOf("\n", cursor);
|
|
4084
|
+
const lineEnd = nextNewline === -1 ? normalizedContent.length : nextNewline;
|
|
4085
|
+
const line = normalizedContent.slice(cursor, lineEnd).replace(/\r$/, "");
|
|
4086
|
+
const afterLine = nextNewline === -1 ? lineEnd : lineEnd + 1;
|
|
4087
|
+
if (line.trim() === "---") {
|
|
4088
|
+
return {
|
|
4089
|
+
content: normalizedContent.slice(afterLine).replace(/^\s+/, ""),
|
|
4090
|
+
stripped: true
|
|
4091
|
+
};
|
|
4092
|
+
}
|
|
4093
|
+
cursor = afterLine;
|
|
4094
|
+
}
|
|
4095
|
+
return { content: normalizedContent, stripped: false };
|
|
4009
4096
|
}
|
|
4010
|
-
|
|
4011
|
-
return
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
itemIds: [params.itemId],
|
|
4015
|
-
commandLabel: params.commandLabel
|
|
4097
|
+
function normalizeParsedItemMetadata(itemMetadata, options) {
|
|
4098
|
+
return normalizeItemMetadata(itemMetadata, {
|
|
4099
|
+
...options,
|
|
4100
|
+
onWarning: void 0
|
|
4016
4101
|
});
|
|
4017
4102
|
}
|
|
4018
|
-
|
|
4019
|
-
const
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
throw strictMissingStreamError(itemId, params.commandLabel);
|
|
4103
|
+
function parseJsonMarkdownItemDocument(content, runtimeContext, options = {}) {
|
|
4104
|
+
const normalized = stripLeadingYamlDocument(content);
|
|
4105
|
+
if (normalized.stripped) {
|
|
4106
|
+
options.onWarning?.("json_markdown_leading_yaml_frontmatter_ignored");
|
|
4107
|
+
}
|
|
4108
|
+
const { frontMatter, body } = splitFrontMatter(normalized.content);
|
|
4109
|
+
if (!frontMatter) {
|
|
4110
|
+
const trimmed = content.trimStart();
|
|
4111
|
+
if (trimmed.startsWith("{")) {
|
|
4112
|
+
validationError("JSON front matter is not valid JSON");
|
|
4029
4113
|
}
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4114
|
+
validationError("missing JSON front matter");
|
|
4115
|
+
}
|
|
4116
|
+
let parsed;
|
|
4117
|
+
try {
|
|
4118
|
+
parsed = JSON.parse(frontMatter);
|
|
4119
|
+
} catch {
|
|
4120
|
+
validationError("JSON front matter is not valid JSON");
|
|
4033
4121
|
}
|
|
4122
|
+
assertValidItemMetadata(parsed, runtimeContext);
|
|
4034
4123
|
return {
|
|
4035
|
-
|
|
4036
|
-
|
|
4124
|
+
metadata: normalizeParsedItemMetadata(parsed, options),
|
|
4125
|
+
body: normalizeBody(body)
|
|
4037
4126
|
};
|
|
4038
4127
|
}
|
|
4039
|
-
|
|
4040
|
-
// dist/core/lock/lock.js
|
|
4041
|
-
import fs2 from "node:fs/promises";
|
|
4042
|
-
import path2 from "node:path";
|
|
4043
|
-
import { randomUUID } from "node:crypto";
|
|
4044
|
-
!(function() {
|
|
4045
|
-
try {
|
|
4046
|
-
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
4047
|
-
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "d23246e1-c423-5100-bcde-8162e01587f0");
|
|
4048
|
-
} catch (e2) {
|
|
4049
|
-
}
|
|
4050
|
-
})();
|
|
4051
|
-
function parseLockInfo(raw) {
|
|
4128
|
+
function parseToonItemDocument(content, runtimeContext, options = {}) {
|
|
4052
4129
|
let parsed;
|
|
4053
4130
|
try {
|
|
4054
|
-
parsed =
|
|
4131
|
+
parsed = decodeToonItemContent(content).value;
|
|
4055
4132
|
} catch {
|
|
4056
|
-
|
|
4057
|
-
info: null,
|
|
4058
|
-
warnings: ["lock_info_invalid_json"]
|
|
4059
|
-
};
|
|
4060
|
-
}
|
|
4061
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
4062
|
-
return {
|
|
4063
|
-
info: null,
|
|
4064
|
-
warnings: ["lock_info_invalid_shape"]
|
|
4065
|
-
};
|
|
4133
|
+
validationError("TOON item document is not valid TOON");
|
|
4066
4134
|
}
|
|
4067
|
-
|
|
4068
|
-
const
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
const ttlSeconds = candidate.ttl_seconds;
|
|
4073
|
-
if (typeof id !== "string" || typeof pid !== "number" || !Number.isFinite(pid) || typeof owner !== "string" || typeof createdAt !== "string" || typeof ttlSeconds !== "number" || !Number.isFinite(ttlSeconds)) {
|
|
4135
|
+
assertItemMetadataCondition(typeof parsed === "object" && parsed !== null && !Array.isArray(parsed), "TOON item document must be an object");
|
|
4136
|
+
const record = parsed;
|
|
4137
|
+
if (Object.prototype.hasOwnProperty.call(record, "front_matter")) {
|
|
4138
|
+
assertValidItemMetadata(record.front_matter, runtimeContext);
|
|
4139
|
+
assertItemMetadataCondition(record.body === void 0 || typeof record.body === "string", "TOON item document body must be a string");
|
|
4074
4140
|
return {
|
|
4075
|
-
|
|
4076
|
-
|
|
4141
|
+
metadata: normalizeParsedItemMetadata(record.front_matter, options),
|
|
4142
|
+
body: normalizeBody(typeof record.body === "string" ? record.body : "")
|
|
4077
4143
|
};
|
|
4078
4144
|
}
|
|
4145
|
+
const { body, ...itemMetadataRecord } = record;
|
|
4146
|
+
assertItemMetadataCondition(body === void 0 || typeof body === "string", "TOON item document body must be a string");
|
|
4147
|
+
assertValidItemMetadata(itemMetadataRecord, runtimeContext);
|
|
4079
4148
|
return {
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
pid,
|
|
4083
|
-
owner,
|
|
4084
|
-
created_at: createdAt,
|
|
4085
|
-
ttl_seconds: ttlSeconds
|
|
4086
|
-
},
|
|
4087
|
-
warnings: []
|
|
4149
|
+
metadata: normalizeParsedItemMetadata(itemMetadataRecord, options),
|
|
4150
|
+
body: normalizeBody(typeof body === "string" ? body : "")
|
|
4088
4151
|
};
|
|
4089
4152
|
}
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4153
|
+
function serializeJsonMarkdownItemDocument(document, options = {}) {
|
|
4154
|
+
const normalizedMetadata = normalizeItemMetadata(document.metadata, options);
|
|
4155
|
+
const orderedMetadata = orderItemMetadata(normalizedMetadata);
|
|
4156
|
+
const serializedMetadata = JSON.stringify(orderedMetadata, null, 2);
|
|
4157
|
+
const normalizedBody = normalizeBody(document.body ?? "");
|
|
4158
|
+
if (!normalizedBody) {
|
|
4159
|
+
return `${serializedMetadata}
|
|
4160
|
+
`;
|
|
4161
|
+
}
|
|
4162
|
+
return `${serializedMetadata}
|
|
4163
|
+
|
|
4164
|
+
${normalizedBody}
|
|
4165
|
+
`;
|
|
4166
|
+
}
|
|
4167
|
+
function serializeToonItemDocument(document, options = {}) {
|
|
4168
|
+
const normalizedMetadata = normalizeItemMetadata(document.metadata, options);
|
|
4169
|
+
const orderedMetadata = orderItemMetadata(normalizedMetadata);
|
|
4170
|
+
const normalizedBody = normalizeBody(document.body ?? "");
|
|
4171
|
+
return `${encodeToon({ ...orderedMetadata, body: normalizedBody })}
|
|
4172
|
+
`;
|
|
4173
|
+
}
|
|
4174
|
+
function parseItemDocument(content, options = {}) {
|
|
4175
|
+
const conflictMarker = findFirstMergeConflictMarker(content);
|
|
4176
|
+
if (conflictMarker) {
|
|
4177
|
+
throw new PmCliError(`Merge conflict markers detected in item document at line ${conflictMarker.line} (${conflictMarker.marker}). Resolve <<<<<<< ======= >>>>>>> markers and retry.`, EXIT_CODE.GENERIC_FAILURE, {
|
|
4178
|
+
code: "merge_conflict_markers_detected",
|
|
4179
|
+
required: "Resolve merge-conflict markers in the item file before parsing or mutation commands.",
|
|
4180
|
+
why: "Partially merged documents can corrupt item metadata and history integrity.",
|
|
4181
|
+
examples: ["git status", "git add <resolved-file> && git commit"],
|
|
4182
|
+
nextSteps: [
|
|
4183
|
+
"Resolve conflicts, save the file, then rerun the pm command."
|
|
4184
|
+
]
|
|
4096
4185
|
});
|
|
4097
|
-
return parseLockInfo(raw);
|
|
4098
|
-
} catch (error) {
|
|
4099
|
-
if (isErrno(error, "ENOENT")) {
|
|
4100
|
-
return {
|
|
4101
|
-
info: null,
|
|
4102
|
-
warnings: []
|
|
4103
|
-
};
|
|
4104
|
-
}
|
|
4105
|
-
return {
|
|
4106
|
-
info: null,
|
|
4107
|
-
warnings: ["lock_info_read_failed"]
|
|
4108
|
-
};
|
|
4109
4186
|
}
|
|
4187
|
+
const format = options.format ?? "toon";
|
|
4188
|
+
const runtimeContext = resolveRuntimeSchemaValidationContext(options);
|
|
4189
|
+
return format === "toon" ? parseToonItemDocument(content, runtimeContext, options) : parseJsonMarkdownItemDocument(content, runtimeContext, options);
|
|
4110
4190
|
}
|
|
4111
|
-
function
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
async function emitLockWriteHook(lockPath, op) {
|
|
4115
|
-
await runActiveOnWriteHooks({
|
|
4116
|
-
path: lockPath,
|
|
4117
|
-
scope: "project",
|
|
4118
|
-
op
|
|
4119
|
-
});
|
|
4191
|
+
function serializeItemDocument(document, options = {}) {
|
|
4192
|
+
const format = options.format ?? "toon";
|
|
4193
|
+
return format === "toon" ? serializeToonItemDocument(document, options) : serializeJsonMarkdownItemDocument(document, options);
|
|
4120
4194
|
}
|
|
4121
|
-
function
|
|
4195
|
+
function canonicalDocument(document, options = {}) {
|
|
4122
4196
|
return {
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
owner,
|
|
4126
|
-
created_at: nowIso(),
|
|
4127
|
-
ttl_seconds: ttlSeconds
|
|
4197
|
+
metadata: normalizeItemMetadata(document.metadata, options),
|
|
4198
|
+
body: normalizeBody(document.body ?? "")
|
|
4128
4199
|
};
|
|
4129
4200
|
}
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4201
|
+
|
|
4202
|
+
// dist/core/item/item-record.js
|
|
4203
|
+
!(function() {
|
|
4133
4204
|
try {
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
}
|
|
4137
|
-
await handle.close();
|
|
4205
|
+
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
4206
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "30de0e7a-3307-5231-af8c-bae7a2b6374b");
|
|
4207
|
+
} catch (e2) {
|
|
4138
4208
|
}
|
|
4139
|
-
|
|
4209
|
+
})();
|
|
4210
|
+
function toItemRecord(item) {
|
|
4211
|
+
return item;
|
|
4140
4212
|
}
|
|
4141
|
-
|
|
4213
|
+
|
|
4214
|
+
// dist/core/history/history.js
|
|
4215
|
+
import jsonPatch from "fast-json-patch";
|
|
4216
|
+
!(function() {
|
|
4142
4217
|
try {
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
} catch {
|
|
4147
|
-
return false;
|
|
4218
|
+
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
4219
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "45cc07c9-b6f9-5851-9f98-4167976035b1");
|
|
4220
|
+
} catch (e2) {
|
|
4148
4221
|
}
|
|
4149
|
-
}
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
}
|
|
4158
|
-
var LOCK_WAIT_INITIAL_DELAY_MS = 25;
|
|
4159
|
-
var LOCK_WAIT_MAX_DELAY_MS = 200;
|
|
4160
|
-
var LOCK_CONFLICT_RETRY_HINT_MS = 250;
|
|
4161
|
-
var MAX_STALE_LOCK_REMOVALS = 3;
|
|
4162
|
-
var STALE_CLEANUP_GATE_SUFFIX = ".stale-cleanup";
|
|
4163
|
-
var STALE_CLEANUP_GATE_OWNER_FILE = "owner.json";
|
|
4164
|
-
var STALE_CLEANUP_GATE_STALE_MS = 1e4;
|
|
4165
|
-
var STALE_CLEANUP_GATE_MAX_ACTIVE_MS = 5 * 6e4;
|
|
4166
|
-
function parseNonNegativeIntegerWaitMs(value) {
|
|
4167
|
-
if (typeof value === "string") {
|
|
4168
|
-
const trimmed = value.trim();
|
|
4169
|
-
if (!/^\d+$/.test(trimmed)) {
|
|
4170
|
-
return void 0;
|
|
4171
|
-
}
|
|
4172
|
-
const parsed = Number(trimmed);
|
|
4173
|
-
return Number.isSafeInteger(parsed) ? parsed : void 0;
|
|
4222
|
+
})();
|
|
4223
|
+
var EMPTY_LEGACY_HASH_DOCUMENT = {
|
|
4224
|
+
front_matter: {},
|
|
4225
|
+
body: ""
|
|
4226
|
+
};
|
|
4227
|
+
function decodeJsonPointer(path6) {
|
|
4228
|
+
if (!path6 || path6 === "/") {
|
|
4229
|
+
return [];
|
|
4174
4230
|
}
|
|
4175
|
-
if (
|
|
4176
|
-
return
|
|
4231
|
+
if (!path6.startsWith("/")) {
|
|
4232
|
+
return [];
|
|
4177
4233
|
}
|
|
4178
|
-
return
|
|
4234
|
+
return path6.slice(1).split("/").map((segment) => segment.replaceAll("~1", "/").replaceAll("~0", "~"));
|
|
4179
4235
|
}
|
|
4180
|
-
function
|
|
4181
|
-
const
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
return envParsed;
|
|
4185
|
-
}
|
|
4186
|
-
const callerParsed = parseNonNegativeIntegerWaitMs(waitMs);
|
|
4187
|
-
if (callerParsed !== void 0) {
|
|
4188
|
-
return callerParsed;
|
|
4236
|
+
function isDefinedPointerPath(document, path6) {
|
|
4237
|
+
const segments = decodeJsonPointer(path6);
|
|
4238
|
+
if (segments.length === 0) {
|
|
4239
|
+
return true;
|
|
4189
4240
|
}
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
}
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4241
|
+
let cursor = document;
|
|
4242
|
+
for (const segment of segments) {
|
|
4243
|
+
if (Array.isArray(cursor)) {
|
|
4244
|
+
if (segment === "-" || !/^(0|[1-9]\d*)$/.test(segment)) {
|
|
4245
|
+
return false;
|
|
4246
|
+
}
|
|
4247
|
+
const index = Number(segment);
|
|
4248
|
+
if (!Number.isInteger(index) || index < 0 || index >= cursor.length) {
|
|
4249
|
+
return false;
|
|
4250
|
+
}
|
|
4251
|
+
const next2 = cursor[index];
|
|
4252
|
+
if (next2 === void 0) {
|
|
4253
|
+
return false;
|
|
4254
|
+
}
|
|
4255
|
+
cursor = next2;
|
|
4256
|
+
continue;
|
|
4202
4257
|
}
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4258
|
+
if (typeof cursor !== "object" || cursor === null) {
|
|
4259
|
+
return false;
|
|
4260
|
+
}
|
|
4261
|
+
if (!Object.prototype.hasOwnProperty.call(cursor, segment)) {
|
|
4262
|
+
return false;
|
|
4263
|
+
}
|
|
4264
|
+
const next = cursor[segment];
|
|
4265
|
+
if (next === void 0) {
|
|
4266
|
+
return false;
|
|
4267
|
+
}
|
|
4268
|
+
cursor = next;
|
|
4212
4269
|
}
|
|
4213
|
-
return
|
|
4270
|
+
return true;
|
|
4214
4271
|
}
|
|
4215
|
-
function
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4272
|
+
function normalizeHistoryPatchOps(beforeDocument, patch) {
|
|
4273
|
+
const normalized = [];
|
|
4274
|
+
let replayCursor = structuredClone(beforeDocument);
|
|
4275
|
+
for (const operation of patch) {
|
|
4276
|
+
const normalizedOperation = operation.op === "replace" && !isDefinedPointerPath(replayCursor, operation.path) ? { ...operation, op: "add" } : operation;
|
|
4277
|
+
normalized.push(normalizedOperation);
|
|
4278
|
+
replayCursor = jsonPatch.applyPatch(replayCursor, [normalizedOperation], true, true).newDocument;
|
|
4219
4279
|
}
|
|
4280
|
+
return normalized;
|
|
4220
4281
|
}
|
|
4221
|
-
function
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
4229
|
-
return null;
|
|
4230
|
-
}
|
|
4231
|
-
const candidate = parsed;
|
|
4232
|
-
const pid = candidate.pid;
|
|
4233
|
-
const token = candidate.token;
|
|
4234
|
-
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || typeof token !== "string" || token.length === 0) {
|
|
4235
|
-
return null;
|
|
4282
|
+
function canonicalHashDocument(document) {
|
|
4283
|
+
const hasMetadata = document.metadata && Object.keys(document.metadata).length > 0;
|
|
4284
|
+
if (!hasMetadata) {
|
|
4285
|
+
return {
|
|
4286
|
+
front_matter: {},
|
|
4287
|
+
body: document.body ?? ""
|
|
4288
|
+
};
|
|
4236
4289
|
}
|
|
4237
|
-
|
|
4290
|
+
const canonical = canonicalDocument(document);
|
|
4291
|
+
const orderedMetadata = orderObject(toItemRecord(canonical.metadata), ITEM_METADATA_KEY_ORDER);
|
|
4292
|
+
return {
|
|
4293
|
+
front_matter: orderedMetadata,
|
|
4294
|
+
body: canonical.body
|
|
4295
|
+
};
|
|
4238
4296
|
}
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4297
|
+
function canonicalPatchDocument(document) {
|
|
4298
|
+
const hasMetadata = document.metadata && Object.keys(document.metadata).length > 0;
|
|
4299
|
+
if (!hasMetadata) {
|
|
4300
|
+
return {
|
|
4301
|
+
metadata: {},
|
|
4302
|
+
body: document.body ?? ""
|
|
4303
|
+
};
|
|
4244
4304
|
}
|
|
4305
|
+
const canonical = canonicalDocument(document);
|
|
4306
|
+
const orderedMetadata = orderObject(toItemRecord(canonical.metadata), ITEM_METADATA_KEY_ORDER);
|
|
4307
|
+
return {
|
|
4308
|
+
metadata: orderedMetadata,
|
|
4309
|
+
body: canonical.body
|
|
4310
|
+
};
|
|
4245
4311
|
}
|
|
4246
|
-
function
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4312
|
+
function hashDocument(document) {
|
|
4313
|
+
return sha256Hex(stableStringify(canonicalHashDocument(document)));
|
|
4314
|
+
}
|
|
4315
|
+
function hashEmptyDocument() {
|
|
4316
|
+
return sha256Hex(stableStringify(EMPTY_LEGACY_HASH_DOCUMENT));
|
|
4317
|
+
}
|
|
4318
|
+
function createHistoryEntry(params) {
|
|
4319
|
+
const beforeHashCanonical = canonicalHashDocument(params.before);
|
|
4320
|
+
const afterHashCanonical = canonicalHashDocument(params.after);
|
|
4321
|
+
const beforePatchCanonical = canonicalPatchDocument(params.before);
|
|
4322
|
+
const afterPatchCanonical = canonicalPatchDocument(params.after);
|
|
4323
|
+
const rawPatch = jsonPatch.compare(beforePatchCanonical, afterPatchCanonical);
|
|
4324
|
+
const patch = normalizeHistoryPatchOps(beforePatchCanonical, rawPatch);
|
|
4325
|
+
return {
|
|
4326
|
+
ts: params.nowIso,
|
|
4327
|
+
author: params.author,
|
|
4328
|
+
op: params.op,
|
|
4329
|
+
patch,
|
|
4330
|
+
before_hash: sha256Hex(stableStringify(beforeHashCanonical)),
|
|
4331
|
+
after_hash: sha256Hex(stableStringify(afterHashCanonical)),
|
|
4332
|
+
message: params.message === void 0 ? void 0 : params.message
|
|
4333
|
+
};
|
|
4256
4334
|
}
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
await fs2.rm(gatePath, { recursive: true, force: true });
|
|
4260
|
-
return true;
|
|
4261
|
-
} catch {
|
|
4262
|
-
return false;
|
|
4263
|
-
}
|
|
4335
|
+
function isRecord(value) {
|
|
4336
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4264
4337
|
}
|
|
4265
|
-
|
|
4266
|
-
const
|
|
4267
|
-
|
|
4268
|
-
return;
|
|
4269
|
-
}
|
|
4270
|
-
await removeStaleCleanupGateDirectory(gatePath);
|
|
4338
|
+
function fallbackHistoryTimestamp(entry) {
|
|
4339
|
+
const ts = entry.ts.trim();
|
|
4340
|
+
return ts.length > 0 ? ts : nowIso();
|
|
4271
4341
|
}
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
if (isErrno(error, "EEXIST")) {
|
|
4277
|
-
return null;
|
|
4278
|
-
}
|
|
4279
|
-
return null;
|
|
4280
|
-
}
|
|
4281
|
-
const owner = { pid: process.pid, token: randomUUID() };
|
|
4282
|
-
try {
|
|
4283
|
-
await fs2.writeFile(path2.join(gatePath, STALE_CLEANUP_GATE_OWNER_FILE), `${JSON.stringify(owner)}
|
|
4284
|
-
`, "utf8");
|
|
4285
|
-
} catch {
|
|
4286
|
-
await removeStaleCleanupGateDirectory(gatePath);
|
|
4287
|
-
return null;
|
|
4342
|
+
function withHistoryTimestamp(value, fallbackTs) {
|
|
4343
|
+
const ts = value.ts;
|
|
4344
|
+
if (typeof ts === "string" && ts.trim().length > 0) {
|
|
4345
|
+
return value;
|
|
4288
4346
|
}
|
|
4289
|
-
return
|
|
4347
|
+
return { ...value, ts: fallbackTs };
|
|
4290
4348
|
}
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4349
|
+
function serializeHistoryLine(value, fallbackEntry) {
|
|
4350
|
+
const fallbackTs = fallbackHistoryTimestamp(fallbackEntry);
|
|
4351
|
+
if (typeof value === "string") {
|
|
4352
|
+
try {
|
|
4353
|
+
const parsed = JSON.parse(value);
|
|
4354
|
+
if (isRecord(parsed)) {
|
|
4355
|
+
return JSON.stringify(withHistoryTimestamp(parsed, fallbackTs));
|
|
4356
|
+
}
|
|
4357
|
+
} catch {
|
|
4298
4358
|
}
|
|
4299
|
-
|
|
4300
|
-
return isErrno(error, "ENOENT");
|
|
4301
|
-
}
|
|
4302
|
-
const owner = await readStaleCleanupGateOwner(gatePath);
|
|
4303
|
-
if (owner !== null && isProcessAlive(owner.pid) && gateAgeMs <= STALE_CLEANUP_GATE_MAX_ACTIVE_MS) {
|
|
4304
|
-
return false;
|
|
4305
|
-
}
|
|
4306
|
-
return removeStaleCleanupGateDirectory(gatePath);
|
|
4307
|
-
}
|
|
4308
|
-
async function acquireStaleCleanupGate(lockPath, _id) {
|
|
4309
|
-
const gatePath = `${lockPath}${STALE_CLEANUP_GATE_SUFFIX}`;
|
|
4310
|
-
const owner = await tryCreateStaleCleanupGate(gatePath);
|
|
4311
|
-
if (owner !== null) {
|
|
4312
|
-
return async () => releaseStaleCleanupGate(gatePath, owner.token);
|
|
4313
|
-
}
|
|
4314
|
-
if (!await removeExpiredStaleCleanupGate(gatePath)) {
|
|
4315
|
-
return null;
|
|
4359
|
+
return value;
|
|
4316
4360
|
}
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
return null;
|
|
4361
|
+
if (isRecord(value)) {
|
|
4362
|
+
return JSON.stringify(withHistoryTimestamp(value, fallbackTs));
|
|
4320
4363
|
}
|
|
4321
|
-
return
|
|
4364
|
+
return JSON.stringify(value);
|
|
4322
4365
|
}
|
|
4323
|
-
async function
|
|
4324
|
-
const
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
}
|
|
4332
|
-
try {
|
|
4333
|
-
const currentLockInfo = await readLockInfo(params.lockPath);
|
|
4334
|
-
if (currentLockInfo.info === null && currentLockInfo.warnings.length === 0) {
|
|
4335
|
-
return {
|
|
4336
|
-
lockInfo: currentLockInfo,
|
|
4337
|
-
shouldRetryCreate: true,
|
|
4338
|
-
staleRemovalCounted: false
|
|
4339
|
-
};
|
|
4366
|
+
async function appendHistoryEntry(historyPath, entry) {
|
|
4367
|
+
const override = await runActiveServiceOverride("history_append", {
|
|
4368
|
+
history_path: historyPath,
|
|
4369
|
+
entry
|
|
4370
|
+
});
|
|
4371
|
+
if (override.handled) {
|
|
4372
|
+
if (override.result === false) {
|
|
4373
|
+
return;
|
|
4340
4374
|
}
|
|
4341
|
-
if (
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
shouldRetryCreate: false,
|
|
4345
|
-
staleRemovalCounted: false
|
|
4346
|
-
};
|
|
4375
|
+
if (typeof override.result === "string") {
|
|
4376
|
+
await appendLineAtomic(historyPath, serializeHistoryLine(override.result, entry));
|
|
4377
|
+
return;
|
|
4347
4378
|
}
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4379
|
+
if (typeof override.result === "object" && override.result !== null) {
|
|
4380
|
+
const record = override.result;
|
|
4381
|
+
if (record.skip === true) {
|
|
4382
|
+
return;
|
|
4383
|
+
}
|
|
4384
|
+
const nextHistoryPath = typeof record.history_path === "string" ? record.history_path : historyPath;
|
|
4385
|
+
if (typeof record.line === "string") {
|
|
4386
|
+
await appendLineAtomic(nextHistoryPath, serializeHistoryLine(record.line, entry));
|
|
4387
|
+
return;
|
|
4388
|
+
}
|
|
4389
|
+
await appendLineAtomic(nextHistoryPath, serializeHistoryLine(record.entry ?? entry, entry));
|
|
4390
|
+
return;
|
|
4351
4391
|
}
|
|
4352
|
-
return {
|
|
4353
|
-
lockInfo: currentLockInfo,
|
|
4354
|
-
shouldRetryCreate: await unlinkLockWithHook(params.lockPath, "lock:stale_remove"),
|
|
4355
|
-
staleRemovalCounted: true
|
|
4356
|
-
};
|
|
4357
|
-
} finally {
|
|
4358
|
-
await releaseCleanupGate();
|
|
4359
4392
|
}
|
|
4393
|
+
await appendLineAtomic(historyPath, serializeHistoryLine(entry, entry));
|
|
4360
4394
|
}
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4395
|
+
|
|
4396
|
+
// dist/core/history/history-stream-policy.js
|
|
4397
|
+
import fs2 from "node:fs/promises";
|
|
4398
|
+
import path2 from "node:path";
|
|
4399
|
+
!(function() {
|
|
4400
|
+
try {
|
|
4401
|
+
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
4402
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "0e1bb27d-a1ac-57ae-b879-29318d827578");
|
|
4403
|
+
} catch (e2) {
|
|
4404
|
+
}
|
|
4405
|
+
})();
|
|
4406
|
+
function toSortedUniqueItemIds(itemIds) {
|
|
4407
|
+
return [...new Set(itemIds.filter((value) => value.trim().length > 0))].sort((left, right) => left.localeCompare(right));
|
|
4408
|
+
}
|
|
4409
|
+
function strictMissingStreamError(itemId, commandLabel) {
|
|
4410
|
+
return new PmCliError(`Missing history stream for ${itemId}. ${commandLabel} requires history streams when settings.history.missing_stream is strict_error.`, EXIT_CODE.NOT_FOUND);
|
|
4411
|
+
}
|
|
4412
|
+
async function createStream(historyPath, commandLabel) {
|
|
4413
|
+
await ensureDir(path2.dirname(historyPath));
|
|
4414
|
+
const handle = await fs2.open(historyPath, "a");
|
|
4415
|
+
await handle.close();
|
|
4416
|
+
return runActiveOnWriteHooks({
|
|
4417
|
+
path: historyPath,
|
|
4418
|
+
scope: "project",
|
|
4419
|
+
op: `${commandLabel}:history:auto_create`
|
|
4369
4420
|
});
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4421
|
+
}
|
|
4422
|
+
async function enforceHistoryStreamPolicyForItem(params) {
|
|
4423
|
+
return enforceHistoryStreamPolicyForItems({
|
|
4424
|
+
pmRoot: params.pmRoot,
|
|
4425
|
+
settings: params.settings,
|
|
4426
|
+
itemIds: [params.itemId],
|
|
4427
|
+
commandLabel: params.commandLabel
|
|
4428
|
+
});
|
|
4429
|
+
}
|
|
4430
|
+
async function enforceHistoryStreamPolicyForItems(params) {
|
|
4431
|
+
const ids = toSortedUniqueItemIds(params.itemIds);
|
|
4432
|
+
const autoCreated = [];
|
|
4433
|
+
const warnings = [];
|
|
4434
|
+
for (const itemId of ids) {
|
|
4435
|
+
const historyPath = getHistoryPath(params.pmRoot, itemId);
|
|
4436
|
+
if (await pathExists(historyPath)) {
|
|
4437
|
+
continue;
|
|
4381
4438
|
}
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
const waitBudgetMs = resolveLockWaitMs(waitMs);
|
|
4385
|
-
const startedAtMs = Date.now();
|
|
4386
|
-
let staleRemovals = 0;
|
|
4387
|
-
let backoffMs = LOCK_WAIT_INITIAL_DELAY_MS;
|
|
4388
|
-
for (; ; ) {
|
|
4389
|
-
try {
|
|
4390
|
-
await createLockFile(lockPath, id, owner, ttlSeconds);
|
|
4391
|
-
return async () => {
|
|
4392
|
-
await unlinkLockWithHook(lockPath, "lock:release");
|
|
4393
|
-
await runActiveServiceOverride("lock_release", {
|
|
4394
|
-
pm_root: pmRoot,
|
|
4395
|
-
id,
|
|
4396
|
-
owner
|
|
4397
|
-
});
|
|
4398
|
-
};
|
|
4399
|
-
} catch (error) {
|
|
4400
|
-
if (!isErrno(error, "EEXIST")) {
|
|
4401
|
-
throw new PmCliError(`Failed to acquire lock for ${id}: ${toErrorMessage(error)}`, EXIT_CODE.GENERIC_FAILURE);
|
|
4402
|
-
}
|
|
4403
|
-
let lockInfo = await readLockInfo(lockPath);
|
|
4404
|
-
if (isStaleLock(lockInfo.info, ttlSeconds)) {
|
|
4405
|
-
const staleRemoval = await removeConfirmedStaleLock({
|
|
4406
|
-
lockPath,
|
|
4407
|
-
id,
|
|
4408
|
-
ttlSeconds,
|
|
4409
|
-
force,
|
|
4410
|
-
forceRequiredForStaleLock,
|
|
4411
|
-
staleRemovals,
|
|
4412
|
-
waitBudgetMs,
|
|
4413
|
-
startedAtMs,
|
|
4414
|
-
fallbackLockInfo: lockInfo
|
|
4415
|
-
});
|
|
4416
|
-
lockInfo = staleRemoval.lockInfo;
|
|
4417
|
-
if (staleRemoval.staleRemovalCounted) {
|
|
4418
|
-
staleRemovals += 1;
|
|
4419
|
-
}
|
|
4420
|
-
if (staleRemoval.shouldRetryCreate) {
|
|
4421
|
-
continue;
|
|
4422
|
-
}
|
|
4423
|
-
}
|
|
4424
|
-
const elapsedMs = Date.now() - startedAtMs;
|
|
4425
|
-
if (waitBudgetMs === 0 || elapsedMs >= waitBudgetMs) {
|
|
4426
|
-
throw buildLockConflictError(id, lockInfo.info, waitBudgetMs === 0 ? 0 : elapsedMs);
|
|
4427
|
-
}
|
|
4428
|
-
await sleepWithJitter(Math.min(backoffMs, waitBudgetMs - elapsedMs));
|
|
4429
|
-
backoffMs = Math.min(backoffMs * 2, LOCK_WAIT_MAX_DELAY_MS);
|
|
4439
|
+
if (params.settings.history.missing_stream === "strict_error") {
|
|
4440
|
+
throw strictMissingStreamError(itemId, params.commandLabel);
|
|
4430
4441
|
}
|
|
4442
|
+
warnings.push(...await createStream(historyPath, params.commandLabel));
|
|
4443
|
+
warnings.push(`history_stream_auto_created:${itemId}`);
|
|
4444
|
+
autoCreated.push(itemId);
|
|
4431
4445
|
}
|
|
4446
|
+
return {
|
|
4447
|
+
auto_created_ids: autoCreated,
|
|
4448
|
+
warnings
|
|
4449
|
+
};
|
|
4432
4450
|
}
|
|
4433
4451
|
|
|
4434
4452
|
// dist/core/item/id.js
|
|
@@ -5512,6 +5530,7 @@ async function deleteItem(params) {
|
|
|
5512
5530
|
}
|
|
5513
5531
|
|
|
5514
5532
|
export {
|
|
5533
|
+
createCoreCommandHookContext,
|
|
5515
5534
|
createSerialQueue,
|
|
5516
5535
|
setActiveExtensionHooks,
|
|
5517
5536
|
setActiveExtensionCommands,
|
|
@@ -5553,6 +5572,7 @@ export {
|
|
|
5553
5572
|
compareTimestampStrings,
|
|
5554
5573
|
matchesTimestampFilters,
|
|
5555
5574
|
resolveIsoOrRelative,
|
|
5575
|
+
acquireLock,
|
|
5556
5576
|
readRuntimeFieldOptionValue,
|
|
5557
5577
|
coerceRuntimeFieldValue,
|
|
5558
5578
|
collectRuntimeCreateFieldValues,
|
|
@@ -5579,7 +5599,6 @@ export {
|
|
|
5579
5599
|
appendHistoryEntry,
|
|
5580
5600
|
enforceHistoryStreamPolicyForItem,
|
|
5581
5601
|
enforceHistoryStreamPolicyForItems,
|
|
5582
|
-
acquireLock,
|
|
5583
5602
|
normalizePrefix,
|
|
5584
5603
|
normalizeRawItemId,
|
|
5585
5604
|
normalizeItemId,
|
|
@@ -5595,4 +5614,4 @@ export {
|
|
|
5595
5614
|
mutateItem,
|
|
5596
5615
|
deleteItem
|
|
5597
5616
|
};
|
|
5598
|
-
//# sourceMappingURL=chunk-
|
|
5617
|
+
//# sourceMappingURL=chunk-T4BRCB6Z.js.map
|