@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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e468cc5b-3706-5898-8d97-4deeb3bc0835")}catch(e){}}();
|
|
3
3
|
import {
|
|
4
4
|
CONFIDENCE_TEXT_VALUES,
|
|
5
5
|
DEFAULT_RUNTIME_SCHEMA_FILE_PATHS,
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
appendLineAtomic,
|
|
25
25
|
coerceFiniteNumber,
|
|
26
26
|
collectRegisteredItemFieldNames,
|
|
27
|
+
createEmptyExtensionHookRegistry,
|
|
27
28
|
ensureDir,
|
|
28
29
|
ensureRuntimeSchemaFileScaffold,
|
|
29
30
|
evictOldestMemoEntries,
|
|
@@ -57,7 +58,17 @@ import {
|
|
|
57
58
|
toErrorMessage,
|
|
58
59
|
weekdayOrderIndex,
|
|
59
60
|
writeFileAtomic
|
|
60
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-GXXC7QSK.js";
|
|
62
|
+
|
|
63
|
+
// dist/core/extensions/command-hook-context.js
|
|
64
|
+
function createCoreCommandHookContext(options) {
|
|
65
|
+
return {
|
|
66
|
+
...options,
|
|
67
|
+
hooks: createEmptyExtensionHookRegistry(),
|
|
68
|
+
profileEnabled: Boolean(options.globalOptions.profile),
|
|
69
|
+
migrationBlockers: []
|
|
70
|
+
};
|
|
71
|
+
}
|
|
61
72
|
|
|
62
73
|
// dist/core/shared/serial-queue.js
|
|
63
74
|
function createSerialQueue() {
|
|
@@ -158,7 +169,7 @@ function getActiveCommandResult() {
|
|
|
158
169
|
return activeCommandResult;
|
|
159
170
|
}
|
|
160
171
|
function recordAfterCommandAffectedItem(item) {
|
|
161
|
-
if (!item
|
|
172
|
+
if (!item) {
|
|
162
173
|
return;
|
|
163
174
|
}
|
|
164
175
|
activeAfterCommandAffectedItems.push(item);
|
|
@@ -2208,2103 +2219,2103 @@ function resolveIsoOrRelative(input, now = /* @__PURE__ */ new Date(), fieldLabe
|
|
|
2208
2219
|
return new Date(timestamp).toISOString();
|
|
2209
2220
|
}
|
|
2210
2221
|
|
|
2211
|
-
// dist/core/
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2222
|
+
// dist/core/lock/lock.js
|
|
2223
|
+
import fs from "node:fs/promises";
|
|
2224
|
+
import path from "node:path";
|
|
2225
|
+
import { randomUUID } from "node:crypto";
|
|
2226
|
+
function parseLockInfo(raw) {
|
|
2227
|
+
let parsed;
|
|
2228
|
+
try {
|
|
2229
|
+
parsed = JSON.parse(raw);
|
|
2230
|
+
} catch {
|
|
2231
|
+
return {
|
|
2232
|
+
info: null,
|
|
2233
|
+
warnings: ["lock_info_invalid_json"]
|
|
2234
|
+
};
|
|
2216
2235
|
}
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2236
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
2237
|
+
return {
|
|
2238
|
+
info: null,
|
|
2239
|
+
warnings: ["lock_info_invalid_shape"]
|
|
2240
|
+
};
|
|
2241
|
+
}
|
|
2242
|
+
const candidate = parsed;
|
|
2243
|
+
const id = candidate.id;
|
|
2244
|
+
const pid = candidate.pid;
|
|
2245
|
+
const owner = candidate.owner;
|
|
2246
|
+
const createdAt = candidate.created_at;
|
|
2247
|
+
const ttlSeconds = candidate.ttl_seconds;
|
|
2248
|
+
if (typeof id !== "string" || typeof pid !== "number" || !Number.isFinite(pid) || typeof owner !== "string" || typeof createdAt !== "string" || typeof ttlSeconds !== "number" || !Number.isFinite(ttlSeconds)) {
|
|
2249
|
+
return {
|
|
2250
|
+
info: null,
|
|
2251
|
+
warnings: ["lock_info_invalid_shape"]
|
|
2252
|
+
};
|
|
2253
|
+
}
|
|
2254
|
+
return {
|
|
2255
|
+
info: {
|
|
2256
|
+
id,
|
|
2257
|
+
pid,
|
|
2258
|
+
owner,
|
|
2259
|
+
created_at: createdAt,
|
|
2260
|
+
ttl_seconds: ttlSeconds
|
|
2261
|
+
},
|
|
2262
|
+
warnings: []
|
|
2263
|
+
};
|
|
2229
2264
|
}
|
|
2230
|
-
function
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2265
|
+
async function readLockInfo(lockPath) {
|
|
2266
|
+
try {
|
|
2267
|
+
const raw = await fs.readFile(lockPath, "utf8");
|
|
2268
|
+
await runActiveOnReadHooks({
|
|
2269
|
+
path: lockPath,
|
|
2270
|
+
scope: "project"
|
|
2271
|
+
});
|
|
2272
|
+
return parseLockInfo(raw);
|
|
2273
|
+
} catch (error) {
|
|
2274
|
+
if (isErrno(error, "ENOENT")) {
|
|
2275
|
+
return {
|
|
2276
|
+
info: null,
|
|
2277
|
+
warnings: []
|
|
2278
|
+
};
|
|
2238
2279
|
}
|
|
2280
|
+
return {
|
|
2281
|
+
info: null,
|
|
2282
|
+
warnings: ["lock_info_read_failed"]
|
|
2283
|
+
};
|
|
2239
2284
|
}
|
|
2240
|
-
return void 0;
|
|
2241
2285
|
}
|
|
2242
|
-
function
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2286
|
+
function isErrno(error, code) {
|
|
2287
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
2288
|
+
}
|
|
2289
|
+
async function emitLockWriteHook(lockPath, op) {
|
|
2290
|
+
await runActiveOnWriteHooks({
|
|
2291
|
+
path: lockPath,
|
|
2292
|
+
scope: "project",
|
|
2293
|
+
op
|
|
2294
|
+
});
|
|
2295
|
+
}
|
|
2296
|
+
function buildLockPayload(id, owner, ttlSeconds) {
|
|
2297
|
+
return {
|
|
2298
|
+
id,
|
|
2299
|
+
pid: process.pid,
|
|
2300
|
+
owner,
|
|
2301
|
+
created_at: nowIso(),
|
|
2302
|
+
ttl_seconds: ttlSeconds
|
|
2303
|
+
};
|
|
2304
|
+
}
|
|
2305
|
+
async function createLockFile(lockPath, id, owner, ttlSeconds) {
|
|
2306
|
+
await fs.mkdir(path.dirname(lockPath), { recursive: true });
|
|
2307
|
+
const handle = await fs.open(lockPath, "wx");
|
|
2308
|
+
try {
|
|
2309
|
+
await handle.writeFile(`${JSON.stringify(buildLockPayload(id, owner, ttlSeconds), null, 2)}
|
|
2310
|
+
`, "utf8");
|
|
2311
|
+
} finally {
|
|
2312
|
+
await handle.close();
|
|
2251
2313
|
}
|
|
2252
|
-
|
|
2314
|
+
await emitLockWriteHook(lockPath, "lock:create");
|
|
2253
2315
|
}
|
|
2254
|
-
function
|
|
2255
|
-
|
|
2256
|
-
|
|
2316
|
+
async function unlinkLockWithHook(lockPath, op) {
|
|
2317
|
+
try {
|
|
2318
|
+
await fs.unlink(lockPath);
|
|
2319
|
+
await emitLockWriteHook(lockPath, op);
|
|
2320
|
+
return true;
|
|
2321
|
+
} catch {
|
|
2322
|
+
return false;
|
|
2257
2323
|
}
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2324
|
+
}
|
|
2325
|
+
function isStaleLock(info, ttlSeconds) {
|
|
2326
|
+
const createdAtMs = info?.created_at ? Date.parse(info.created_at) : Number.NaN;
|
|
2327
|
+
const ageMs = Number.isFinite(createdAtMs) ? Date.now() - createdAtMs : Number.POSITIVE_INFINITY;
|
|
2328
|
+
return ageMs > ttlSeconds * 1e3;
|
|
2329
|
+
}
|
|
2330
|
+
function lockOwnerSuffix(info) {
|
|
2331
|
+
return info?.owner ? ` (owner ${info.owner})` : "";
|
|
2332
|
+
}
|
|
2333
|
+
var LOCK_WAIT_INITIAL_DELAY_MS = 25;
|
|
2334
|
+
var LOCK_WAIT_MAX_DELAY_MS = 200;
|
|
2335
|
+
var LOCK_CONFLICT_RETRY_HINT_MS = 250;
|
|
2336
|
+
var MAX_STALE_LOCK_REMOVALS = 3;
|
|
2337
|
+
var STALE_CLEANUP_GATE_SUFFIX = ".stale-cleanup";
|
|
2338
|
+
var STALE_CLEANUP_GATE_OWNER_FILE = "owner.json";
|
|
2339
|
+
var STALE_CLEANUP_GATE_STALE_MS = 1e4;
|
|
2340
|
+
var STALE_CLEANUP_GATE_MAX_ACTIVE_MS = 5 * 6e4;
|
|
2341
|
+
function parseNonNegativeIntegerWaitMs(value) {
|
|
2342
|
+
if (typeof value === "string") {
|
|
2343
|
+
const trimmed = value.trim();
|
|
2344
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
2345
|
+
return void 0;
|
|
2264
2346
|
}
|
|
2347
|
+
const parsed = Number(trimmed);
|
|
2348
|
+
return Number.isSafeInteger(parsed) ? parsed : void 0;
|
|
2265
2349
|
}
|
|
2266
|
-
if (typeof
|
|
2267
|
-
|
|
2268
|
-
if (normalized === "true" || normalized === "1" || normalized === "yes") {
|
|
2269
|
-
return true;
|
|
2270
|
-
}
|
|
2271
|
-
if (normalized === "false" || normalized === "0" || normalized === "no") {
|
|
2272
|
-
return false;
|
|
2273
|
-
}
|
|
2350
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
2351
|
+
return Math.trunc(value);
|
|
2274
2352
|
}
|
|
2275
|
-
|
|
2353
|
+
return void 0;
|
|
2276
2354
|
}
|
|
2277
|
-
function
|
|
2278
|
-
|
|
2279
|
-
|
|
2355
|
+
function resolveLockWaitMs(waitMs) {
|
|
2356
|
+
const envRaw = process.env.PM_LOCK_WAIT_MS;
|
|
2357
|
+
const envParsed = parseNonNegativeIntegerWaitMs(envRaw);
|
|
2358
|
+
if (envParsed !== void 0) {
|
|
2359
|
+
return envParsed;
|
|
2280
2360
|
}
|
|
2281
|
-
const
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
throw new PmCliError(`${label} must be a number`, EXIT_CODE.USAGE);
|
|
2361
|
+
const callerParsed = parseNonNegativeIntegerWaitMs(waitMs);
|
|
2362
|
+
if (callerParsed !== void 0) {
|
|
2363
|
+
return callerParsed;
|
|
2285
2364
|
}
|
|
2286
|
-
return
|
|
2365
|
+
return 0;
|
|
2287
2366
|
}
|
|
2288
|
-
function
|
|
2289
|
-
const
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2367
|
+
function sleepWithJitter(baseDelayMs) {
|
|
2368
|
+
const jitteredMs = Math.max(1, Math.round(baseDelayMs * (0.5 + Math.random())));
|
|
2369
|
+
return new Promise((resolve) => setTimeout(resolve, jitteredMs));
|
|
2370
|
+
}
|
|
2371
|
+
function buildLockConflictError(id, info, waitedMs) {
|
|
2372
|
+
const waitedSuffix = waitedMs > 0 ? ` after waiting ${waitedMs}ms` : "";
|
|
2373
|
+
return new PmCliError(`Item ${id} is locked${lockOwnerSuffix(info)}${waitedSuffix}`, EXIT_CODE.CONFLICT, {
|
|
2374
|
+
code: "lock_conflict",
|
|
2375
|
+
recovery: {
|
|
2376
|
+
retry_after_ms: LOCK_CONFLICT_RETRY_HINT_MS
|
|
2297
2377
|
}
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
if (
|
|
2302
|
-
return
|
|
2378
|
+
});
|
|
2379
|
+
}
|
|
2380
|
+
function resolveLockOverrideRelease(result) {
|
|
2381
|
+
if (typeof result === "function") {
|
|
2382
|
+
return result;
|
|
2303
2383
|
}
|
|
2304
|
-
if (
|
|
2305
|
-
|
|
2384
|
+
if (typeof result === "object" && result !== null && "release" in result) {
|
|
2385
|
+
const release = result.release;
|
|
2386
|
+
return typeof release === "function" ? release : null;
|
|
2306
2387
|
}
|
|
2307
|
-
|
|
2308
|
-
|
|
2388
|
+
return null;
|
|
2389
|
+
}
|
|
2390
|
+
function throwIfStaleLockNeedsForce(id, lockInfo, force, forceRequired) {
|
|
2391
|
+
if (!force && forceRequired) {
|
|
2392
|
+
const warningSuffix = lockInfo.warnings.length > 0 ? ` (${lockInfo.warnings.join(",")})` : "";
|
|
2393
|
+
throw new PmCliError(`Item ${id} lock is stale${warningSuffix}; rerun with --force when supported for this command`, EXIT_CODE.CONFLICT);
|
|
2309
2394
|
}
|
|
2310
|
-
return typeof scalarRaw === "string" ? scalarRaw : String(scalarRaw);
|
|
2311
2395
|
}
|
|
2312
|
-
function
|
|
2313
|
-
|
|
2314
|
-
|
|
2396
|
+
function parseStaleCleanupGateOwner(raw) {
|
|
2397
|
+
let parsed;
|
|
2398
|
+
try {
|
|
2399
|
+
parsed = JSON.parse(raw);
|
|
2400
|
+
} catch {
|
|
2401
|
+
return null;
|
|
2315
2402
|
}
|
|
2316
|
-
if (
|
|
2317
|
-
return
|
|
2403
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
2404
|
+
return null;
|
|
2318
2405
|
}
|
|
2319
|
-
|
|
2320
|
-
|
|
2406
|
+
const candidate = parsed;
|
|
2407
|
+
const pid = candidate.pid;
|
|
2408
|
+
const token = candidate.token;
|
|
2409
|
+
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || typeof token !== "string" || token.length === 0) {
|
|
2410
|
+
return null;
|
|
2321
2411
|
}
|
|
2322
|
-
return
|
|
2412
|
+
return { pid, token };
|
|
2323
2413
|
}
|
|
2324
|
-
function
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
if (rawValue === void 0) {
|
|
2330
|
-
if (shouldRequireFieldOnCreate(definition, itemTypeName)) {
|
|
2331
|
-
missingRequiredFlags.push(`--${definition.cli_flag}`);
|
|
2332
|
-
}
|
|
2333
|
-
continue;
|
|
2334
|
-
}
|
|
2335
|
-
values[definition.metadata_key] = coerceRuntimeFieldValue(definition, rawValue);
|
|
2414
|
+
async function readStaleCleanupGateOwner(gatePath) {
|
|
2415
|
+
try {
|
|
2416
|
+
return parseStaleCleanupGateOwner(await fs.readFile(path.join(gatePath, STALE_CLEANUP_GATE_OWNER_FILE), "utf8"));
|
|
2417
|
+
} catch {
|
|
2418
|
+
return null;
|
|
2336
2419
|
}
|
|
2337
|
-
return {
|
|
2338
|
-
values,
|
|
2339
|
-
missing_required_flags: [...new Set(missingRequiredFlags)].sort((left, right) => left.localeCompare(right))
|
|
2340
|
-
};
|
|
2341
2420
|
}
|
|
2342
|
-
function
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
continue;
|
|
2350
|
-
}
|
|
2351
|
-
if (seen.has(definition.metadata_key)) {
|
|
2352
|
-
continue;
|
|
2421
|
+
function isProcessAlive(pid) {
|
|
2422
|
+
try {
|
|
2423
|
+
process.kill(pid, 0);
|
|
2424
|
+
return true;
|
|
2425
|
+
} catch (error) {
|
|
2426
|
+
if (isErrno(error, "ESRCH")) {
|
|
2427
|
+
return false;
|
|
2353
2428
|
}
|
|
2354
|
-
|
|
2355
|
-
values[definition.metadata_key] = coerceRuntimeFieldValue(definition, rawValue);
|
|
2429
|
+
return true;
|
|
2356
2430
|
}
|
|
2357
|
-
return values;
|
|
2358
2431
|
}
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
if (typeof raw === "number" && Number.isInteger(raw) && raw >= BASELINE_ITEM_FORMAT_VERSION) {
|
|
2366
|
-
return raw;
|
|
2432
|
+
async function removeStaleCleanupGateDirectory(gatePath) {
|
|
2433
|
+
try {
|
|
2434
|
+
await fs.rm(gatePath, { recursive: true, force: true });
|
|
2435
|
+
return true;
|
|
2436
|
+
} catch {
|
|
2437
|
+
return false;
|
|
2367
2438
|
}
|
|
2368
|
-
return BASELINE_ITEM_FORMAT_VERSION;
|
|
2369
2439
|
}
|
|
2370
|
-
function
|
|
2371
|
-
|
|
2372
|
-
|
|
2440
|
+
async function releaseStaleCleanupGate(gatePath, token) {
|
|
2441
|
+
const owner = await readStaleCleanupGateOwner(gatePath);
|
|
2442
|
+
if (owner === null || owner.token !== token) {
|
|
2443
|
+
return;
|
|
2373
2444
|
}
|
|
2374
|
-
|
|
2445
|
+
await removeStaleCleanupGateDirectory(gatePath);
|
|
2375
2446
|
}
|
|
2376
|
-
function
|
|
2377
|
-
|
|
2378
|
-
|
|
2447
|
+
async function tryCreateStaleCleanupGate(gatePath) {
|
|
2448
|
+
try {
|
|
2449
|
+
await fs.mkdir(gatePath);
|
|
2450
|
+
} catch (error) {
|
|
2451
|
+
if (isErrno(error, "EEXIST")) {
|
|
2452
|
+
return null;
|
|
2453
|
+
}
|
|
2454
|
+
return null;
|
|
2379
2455
|
}
|
|
2380
|
-
|
|
2381
|
-
|
|
2456
|
+
const owner = { pid: process.pid, token: randomUUID() };
|
|
2457
|
+
try {
|
|
2458
|
+
await fs.writeFile(path.join(gatePath, STALE_CLEANUP_GATE_OWNER_FILE), `${JSON.stringify(owner)}
|
|
2459
|
+
`, "utf8");
|
|
2460
|
+
} catch {
|
|
2461
|
+
await removeStaleCleanupGateDirectory(gatePath);
|
|
2462
|
+
return null;
|
|
2382
2463
|
}
|
|
2383
|
-
return
|
|
2464
|
+
return owner;
|
|
2384
2465
|
}
|
|
2385
|
-
function
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
if (
|
|
2391
|
-
|
|
2392
|
-
} else if (status === "ahead") {
|
|
2393
|
-
ahead.push(entry.ref);
|
|
2466
|
+
async function removeExpiredStaleCleanupGate(gatePath) {
|
|
2467
|
+
let gateAgeMs;
|
|
2468
|
+
try {
|
|
2469
|
+
const stats = await fs.stat(gatePath);
|
|
2470
|
+
gateAgeMs = Date.now() - stats.mtimeMs;
|
|
2471
|
+
if (gateAgeMs <= STALE_CLEANUP_GATE_STALE_MS) {
|
|
2472
|
+
return false;
|
|
2394
2473
|
}
|
|
2474
|
+
} catch (error) {
|
|
2475
|
+
return isErrno(error, "ENOENT");
|
|
2395
2476
|
}
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
};
|
|
2400
|
-
}
|
|
2401
|
-
|
|
2402
|
-
// dist/core/item/status.js
|
|
2403
|
-
var STATUS_ALIAS_MAP = {
|
|
2404
|
-
"in-progress": "in_progress",
|
|
2405
|
-
cancelled: "canceled"
|
|
2406
|
-
};
|
|
2407
|
-
function normalizeStatusInput(value, registry) {
|
|
2408
|
-
if (registry) {
|
|
2409
|
-
const normalizedFromRegistry = normalizeStatusInputWithRegistry(value, registry);
|
|
2410
|
-
if (normalizedFromRegistry) {
|
|
2411
|
-
return normalizedFromRegistry;
|
|
2412
|
-
}
|
|
2477
|
+
const owner = await readStaleCleanupGateOwner(gatePath);
|
|
2478
|
+
if (owner !== null && isProcessAlive(owner.pid) && gateAgeMs <= STALE_CLEANUP_GATE_MAX_ACTIVE_MS) {
|
|
2479
|
+
return false;
|
|
2413
2480
|
}
|
|
2414
|
-
|
|
2415
|
-
|
|
2481
|
+
return removeStaleCleanupGateDirectory(gatePath);
|
|
2482
|
+
}
|
|
2483
|
+
async function acquireStaleCleanupGate(lockPath, _id) {
|
|
2484
|
+
const gatePath = `${lockPath}${STALE_CLEANUP_GATE_SUFFIX}`;
|
|
2485
|
+
const owner = await tryCreateStaleCleanupGate(gatePath);
|
|
2486
|
+
if (owner !== null) {
|
|
2487
|
+
return async () => releaseStaleCleanupGate(gatePath, owner.token);
|
|
2416
2488
|
}
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
return void 0;
|
|
2489
|
+
if (!await removeExpiredStaleCleanupGate(gatePath)) {
|
|
2490
|
+
return null;
|
|
2420
2491
|
}
|
|
2421
|
-
const
|
|
2422
|
-
if (
|
|
2423
|
-
return
|
|
2492
|
+
const recoveredOwner = await tryCreateStaleCleanupGate(gatePath);
|
|
2493
|
+
if (recoveredOwner === null) {
|
|
2494
|
+
return null;
|
|
2424
2495
|
}
|
|
2425
|
-
return
|
|
2426
|
-
}
|
|
2427
|
-
function normalizeStatusForRegistry(status, registry) {
|
|
2428
|
-
return normalizeStatusInput(status, registry) ?? status;
|
|
2429
|
-
}
|
|
2430
|
-
function isTerminalStatus(status, registry) {
|
|
2431
|
-
return registry.terminal_statuses.has(normalizeStatusForRegistry(status, registry));
|
|
2496
|
+
return async () => releaseStaleCleanupGate(gatePath, recoveredOwner.token);
|
|
2432
2497
|
}
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2498
|
+
async function removeConfirmedStaleLock(params) {
|
|
2499
|
+
const releaseCleanupGate = await acquireStaleCleanupGate(params.lockPath, params.id);
|
|
2500
|
+
if (releaseCleanupGate === null) {
|
|
2501
|
+
return {
|
|
2502
|
+
lockInfo: params.fallbackLockInfo,
|
|
2503
|
+
shouldRetryCreate: false,
|
|
2504
|
+
staleRemovalCounted: false
|
|
2505
|
+
};
|
|
2506
|
+
}
|
|
2507
|
+
try {
|
|
2508
|
+
const currentLockInfo = await readLockInfo(params.lockPath);
|
|
2509
|
+
if (currentLockInfo.info === null && currentLockInfo.warnings.length === 0) {
|
|
2510
|
+
return {
|
|
2511
|
+
lockInfo: currentLockInfo,
|
|
2512
|
+
shouldRetryCreate: true,
|
|
2513
|
+
staleRemovalCounted: false
|
|
2514
|
+
};
|
|
2445
2515
|
}
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2516
|
+
if (!isStaleLock(currentLockInfo.info, params.ttlSeconds)) {
|
|
2517
|
+
return {
|
|
2518
|
+
lockInfo: currentLockInfo,
|
|
2519
|
+
shouldRetryCreate: false,
|
|
2520
|
+
staleRemovalCounted: false
|
|
2521
|
+
};
|
|
2450
2522
|
}
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
function decodeToonItemContent(content) {
|
|
2455
|
-
try {
|
|
2456
|
-
return { value: decodeToon(content), usedScalarBracketEscape: false };
|
|
2457
|
-
} catch (strictError) {
|
|
2458
|
-
const escaped = escapeBracketsInQuotedScalars(content);
|
|
2459
|
-
if (escaped === content) {
|
|
2460
|
-
throw strictError;
|
|
2523
|
+
throwIfStaleLockNeedsForce(params.id, currentLockInfo, params.force, params.forceRequiredForStaleLock);
|
|
2524
|
+
if (params.staleRemovals >= MAX_STALE_LOCK_REMOVALS) {
|
|
2525
|
+
throw buildLockConflictError(params.id, currentLockInfo.info, Date.now() - params.startedAtMs);
|
|
2461
2526
|
}
|
|
2462
|
-
return {
|
|
2527
|
+
return {
|
|
2528
|
+
lockInfo: currentLockInfo,
|
|
2529
|
+
shouldRetryCreate: await unlinkLockWithHook(params.lockPath, "lock:stale_remove"),
|
|
2530
|
+
staleRemovalCounted: true
|
|
2531
|
+
};
|
|
2532
|
+
} finally {
|
|
2533
|
+
await releaseCleanupGate();
|
|
2463
2534
|
}
|
|
2464
2535
|
}
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
const
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2536
|
+
async function acquireLock(pmRoot, id, ttlSeconds, owner, force = false, forceRequiredForStaleLock = true, waitMs) {
|
|
2537
|
+
const lockOverride = await runActiveServiceOverride("lock_acquire", {
|
|
2538
|
+
pm_root: pmRoot,
|
|
2539
|
+
id,
|
|
2540
|
+
ttl_seconds: ttlSeconds,
|
|
2541
|
+
owner,
|
|
2542
|
+
force,
|
|
2543
|
+
force_required_for_stale_lock: forceRequiredForStaleLock
|
|
2544
|
+
});
|
|
2545
|
+
if (lockOverride.handled) {
|
|
2546
|
+
const release = resolveLockOverrideRelease(lockOverride.result);
|
|
2547
|
+
if (release) {
|
|
2548
|
+
return async () => {
|
|
2549
|
+
await Promise.resolve(release());
|
|
2550
|
+
await runActiveServiceOverride("lock_release", {
|
|
2551
|
+
pm_root: pmRoot,
|
|
2552
|
+
id,
|
|
2553
|
+
owner
|
|
2554
|
+
});
|
|
2555
|
+
};
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
const lockPath = getLockPath(pmRoot, id);
|
|
2559
|
+
const waitBudgetMs = resolveLockWaitMs(waitMs);
|
|
2560
|
+
const startedAtMs = Date.now();
|
|
2561
|
+
let staleRemovals = 0;
|
|
2562
|
+
let backoffMs = LOCK_WAIT_INITIAL_DELAY_MS;
|
|
2563
|
+
for (; ; ) {
|
|
2564
|
+
try {
|
|
2565
|
+
await createLockFile(lockPath, id, owner, ttlSeconds);
|
|
2566
|
+
return async () => {
|
|
2567
|
+
await unlinkLockWithHook(lockPath, "lock:release");
|
|
2568
|
+
await runActiveServiceOverride("lock_release", {
|
|
2569
|
+
pm_root: pmRoot,
|
|
2570
|
+
id,
|
|
2571
|
+
owner
|
|
2572
|
+
});
|
|
2573
|
+
};
|
|
2574
|
+
} catch (error) {
|
|
2575
|
+
if (!isErrno(error, "EEXIST")) {
|
|
2576
|
+
throw new PmCliError(`Failed to acquire lock for ${id}: ${toErrorMessage(error)}`, EXIT_CODE.GENERIC_FAILURE);
|
|
2577
|
+
}
|
|
2578
|
+
let lockInfo = await readLockInfo(lockPath);
|
|
2579
|
+
if (isStaleLock(lockInfo.info, ttlSeconds)) {
|
|
2580
|
+
const staleRemoval = await removeConfirmedStaleLock({
|
|
2581
|
+
lockPath,
|
|
2582
|
+
id,
|
|
2583
|
+
ttlSeconds,
|
|
2584
|
+
force,
|
|
2585
|
+
forceRequiredForStaleLock,
|
|
2586
|
+
staleRemovals,
|
|
2587
|
+
waitBudgetMs,
|
|
2588
|
+
startedAtMs,
|
|
2589
|
+
fallbackLockInfo: lockInfo
|
|
2590
|
+
});
|
|
2591
|
+
lockInfo = staleRemoval.lockInfo;
|
|
2592
|
+
if (staleRemoval.staleRemovalCounted) {
|
|
2593
|
+
staleRemovals += 1;
|
|
2594
|
+
}
|
|
2595
|
+
if (staleRemoval.shouldRetryCreate) {
|
|
2596
|
+
continue;
|
|
2597
|
+
}
|
|
2598
|
+
}
|
|
2599
|
+
const elapsedMs = Date.now() - startedAtMs;
|
|
2600
|
+
if (waitBudgetMs === 0 || elapsedMs >= waitBudgetMs) {
|
|
2601
|
+
throw buildLockConflictError(id, lockInfo.info, waitBudgetMs === 0 ? 0 : elapsedMs);
|
|
2602
|
+
}
|
|
2603
|
+
await sleepWithJitter(Math.min(backoffMs, waitBudgetMs - elapsedMs));
|
|
2604
|
+
backoffMs = Math.min(backoffMs * 2, LOCK_WAIT_MAX_DELAY_MS);
|
|
2479
2605
|
}
|
|
2480
|
-
const marker = markerMatch[1];
|
|
2481
|
-
matches.push({
|
|
2482
|
-
line: index + 1,
|
|
2483
|
-
marker,
|
|
2484
|
-
text: line
|
|
2485
|
-
});
|
|
2486
2606
|
}
|
|
2487
|
-
return matches;
|
|
2488
|
-
}
|
|
2489
|
-
function findFirstMergeConflictMarker(content) {
|
|
2490
|
-
const matches = findMergeConflictMarkers(content);
|
|
2491
|
-
return matches[0];
|
|
2492
2607
|
}
|
|
2493
2608
|
|
|
2494
|
-
// dist/core/
|
|
2495
|
-
|
|
2496
|
-
"
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
]);
|
|
2500
|
-
var ITEM_TEST_RUN_STATUS_VALUES = /* @__PURE__ */ new Set([
|
|
2501
|
-
"passed",
|
|
2502
|
-
"failed",
|
|
2503
|
-
"stopped",
|
|
2504
|
-
"canceled"
|
|
2505
|
-
]);
|
|
2506
|
-
var PLAN_STEP_STATUS_SET = new Set(PLAN_STEP_STATUS_VALUES);
|
|
2507
|
-
function normalizePathValue(value) {
|
|
2508
|
-
return value.replaceAll("\\", "/");
|
|
2509
|
-
}
|
|
2510
|
-
function firstNonZeroComparison(comparisons) {
|
|
2511
|
-
for (const comparison of comparisons) {
|
|
2512
|
-
if (comparison !== 0) {
|
|
2513
|
-
return comparison;
|
|
2514
|
-
}
|
|
2609
|
+
// dist/core/schema/runtime-field-values.js
|
|
2610
|
+
function toCamelToken(value) {
|
|
2611
|
+
const segments = value.trim().replaceAll(/[^A-Za-z0-9]+/g, " ").split(/\s+/).filter((segment) => segment.length > 0).map((segment) => segment.toLowerCase());
|
|
2612
|
+
if (segments.length === 0) {
|
|
2613
|
+
return value;
|
|
2515
2614
|
}
|
|
2516
|
-
|
|
2615
|
+
const [first, ...rest] = segments;
|
|
2616
|
+
return `${first}${rest.map((segment) => `${segment.slice(0, 1).toUpperCase()}${segment.slice(1)}`).join("")}`;
|
|
2517
2617
|
}
|
|
2518
|
-
function
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2618
|
+
function resolveCandidateOptionKeys(definition) {
|
|
2619
|
+
return [
|
|
2620
|
+
.../* @__PURE__ */ new Set([
|
|
2621
|
+
runtimeFieldOptionTarget(definition),
|
|
2622
|
+
toCamelToken(definition.key),
|
|
2623
|
+
toCamelToken(definition.cli_flag),
|
|
2624
|
+
...definition.cli_aliases.map((alias) => toCamelToken(alias))
|
|
2625
|
+
])
|
|
2626
|
+
];
|
|
2627
|
+
}
|
|
2628
|
+
function readRuntimeFieldOptionValue(options, definition) {
|
|
2629
|
+
for (const candidateKey of resolveCandidateOptionKeys(definition)) {
|
|
2630
|
+
if (!Object.hasOwn(options, candidateKey)) {
|
|
2631
|
+
continue;
|
|
2632
|
+
}
|
|
2633
|
+
const value = options[candidateKey];
|
|
2634
|
+
if (value !== void 0) {
|
|
2635
|
+
return value;
|
|
2522
2636
|
}
|
|
2523
2637
|
}
|
|
2638
|
+
return void 0;
|
|
2524
2639
|
}
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
"description",
|
|
2529
|
-
"created_at",
|
|
2530
|
-
"updated_at"
|
|
2531
|
-
];
|
|
2532
|
-
var STATIC_ITEM_METADATA_FIELD_SET = new Set(ITEM_METADATA_KEY_ORDER);
|
|
2533
|
-
function resolveRuntimeSchemaValidationContext(options) {
|
|
2534
|
-
if (!options?.schema) {
|
|
2535
|
-
return void 0;
|
|
2640
|
+
function normalizeStringArrayValue(value) {
|
|
2641
|
+
if (Array.isArray(value)) {
|
|
2642
|
+
return value.flatMap((entry) => normalizeStringArrayValue(entry)).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
2536
2643
|
}
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
fieldRegistry: resolveRuntimeFieldRegistry(options.schema),
|
|
2540
|
-
unknownFieldPolicy: options.schema.unknown_field_policy ?? "allow",
|
|
2541
|
-
extensionFieldNames: new Set(options.extensionFieldNames ?? []),
|
|
2542
|
-
onWarning: options.onWarning
|
|
2543
|
-
};
|
|
2544
|
-
}
|
|
2545
|
-
function runtimeFieldRequiredForType(definition, typeName) {
|
|
2546
|
-
if (!definition.required) {
|
|
2547
|
-
return false;
|
|
2644
|
+
if (typeof value === "string") {
|
|
2645
|
+
return value.split(/[,\n|]/).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
2548
2646
|
}
|
|
2549
|
-
if (
|
|
2550
|
-
return
|
|
2647
|
+
if (value === void 0 || value === null) {
|
|
2648
|
+
return [];
|
|
2551
2649
|
}
|
|
2552
|
-
return
|
|
2553
|
-
}
|
|
2554
|
-
function validationError(message) {
|
|
2555
|
-
throw new PmCliError(`Invalid item metadata: ${message}`, EXIT_CODE.GENERIC_FAILURE);
|
|
2650
|
+
return [String(value).trim()].filter((entry) => entry.length > 0);
|
|
2556
2651
|
}
|
|
2557
|
-
function
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
knownKeys.add(definition.metadata_key);
|
|
2652
|
+
function parseBooleanValue(raw, label) {
|
|
2653
|
+
if (typeof raw === "boolean") {
|
|
2654
|
+
return raw;
|
|
2561
2655
|
}
|
|
2562
|
-
|
|
2563
|
-
|
|
2656
|
+
if (typeof raw === "number") {
|
|
2657
|
+
if (raw === 1) {
|
|
2658
|
+
return true;
|
|
2659
|
+
}
|
|
2660
|
+
if (raw === 0) {
|
|
2661
|
+
return false;
|
|
2662
|
+
}
|
|
2564
2663
|
}
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2664
|
+
if (typeof raw === "string") {
|
|
2665
|
+
const normalized = raw.trim().toLowerCase();
|
|
2666
|
+
if (normalized === "true" || normalized === "1" || normalized === "yes") {
|
|
2667
|
+
return true;
|
|
2668
|
+
}
|
|
2669
|
+
if (normalized === "false" || normalized === "0" || normalized === "no") {
|
|
2670
|
+
return false;
|
|
2671
|
+
}
|
|
2570
2672
|
}
|
|
2673
|
+
throw new PmCliError(`${label} must be one of true|false|1|0|yes|no`, EXIT_CODE.USAGE);
|
|
2571
2674
|
}
|
|
2572
|
-
function
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
const timestamp = rawValue;
|
|
2576
|
-
assertItemMetadataCondition(isTimestampLiteral(timestamp), `${fieldName} must be a valid ISO timestamp`);
|
|
2577
|
-
}
|
|
2578
|
-
function assertPositiveIntegerField(record, fieldName, messagePrefix) {
|
|
2579
|
-
const value = record[fieldName];
|
|
2580
|
-
if (value === void 0) {
|
|
2581
|
-
return;
|
|
2675
|
+
function parseNumberValue(raw, label) {
|
|
2676
|
+
if (typeof raw === "number" && Number.isFinite(raw)) {
|
|
2677
|
+
return raw;
|
|
2582
2678
|
}
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
if (value === void 0) {
|
|
2588
|
-
return;
|
|
2679
|
+
const candidate = typeof raw === "string" ? raw.trim() : String(raw);
|
|
2680
|
+
const parsed = Number(candidate);
|
|
2681
|
+
if (!Number.isFinite(parsed)) {
|
|
2682
|
+
throw new PmCliError(`${label} must be a number`, EXIT_CODE.USAGE);
|
|
2589
2683
|
}
|
|
2590
|
-
|
|
2591
|
-
assertItemMetadataCondition(isTimestampLiteral(value), `${messagePrefix} must be a valid ISO timestamp`);
|
|
2684
|
+
return parsed;
|
|
2592
2685
|
}
|
|
2593
|
-
function
|
|
2594
|
-
|
|
2595
|
-
|
|
2686
|
+
function coerceRuntimeFieldValue(definition, rawValue, labelOverride) {
|
|
2687
|
+
const label = labelOverride ?? `--${definition.cli_flag}`;
|
|
2688
|
+
if (definition.repeatable || definition.type === "string_array") {
|
|
2689
|
+
const values = normalizeStringArrayValue(rawValue);
|
|
2690
|
+
if (definition.type === "number") {
|
|
2691
|
+
return values.map((value) => parseNumberValue(value, label));
|
|
2692
|
+
}
|
|
2693
|
+
if (definition.type === "boolean") {
|
|
2694
|
+
return values.map((value) => parseBooleanValue(value, label));
|
|
2695
|
+
}
|
|
2696
|
+
return values;
|
|
2596
2697
|
}
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
const normalizedWeekday = weekday.trim().toLowerCase();
|
|
2601
|
-
assertItemMetadataCondition(RECURRENCE_WEEKDAY_VALUES.includes(normalizedWeekday), `event.recurrence.by_weekday entries must be one of: ${RECURRENCE_WEEKDAY_VALUES.join(", ")}`);
|
|
2698
|
+
const scalarRaw = Array.isArray(rawValue) ? rawValue[rawValue.length - 1] : rawValue;
|
|
2699
|
+
if (scalarRaw === void 0) {
|
|
2700
|
+
return void 0;
|
|
2602
2701
|
}
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
if (value === void 0) {
|
|
2606
|
-
return;
|
|
2702
|
+
if (definition.type === "number") {
|
|
2703
|
+
return parseNumberValue(scalarRaw, label);
|
|
2607
2704
|
}
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
assertItemMetadataCondition(typeof day === "number" && Number.isInteger(day) && day >= 1 && day <= 31, "event.recurrence.by_month_day entries must be integers 1..31");
|
|
2705
|
+
if (definition.type === "boolean") {
|
|
2706
|
+
return parseBooleanValue(scalarRaw, label);
|
|
2611
2707
|
}
|
|
2708
|
+
return typeof scalarRaw === "string" ? scalarRaw : String(scalarRaw);
|
|
2612
2709
|
}
|
|
2613
|
-
function
|
|
2614
|
-
if (
|
|
2615
|
-
return;
|
|
2710
|
+
function shouldRequireFieldOnCreate(definition, itemTypeName) {
|
|
2711
|
+
if (!definition.required && !definition.required_on_create) {
|
|
2712
|
+
return false;
|
|
2616
2713
|
}
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
assertItemMetadataCondition(typeof exdate === "string", "event.recurrence.exdates entries must be strings");
|
|
2620
|
-
assertItemMetadataCondition(isTimestampLiteral(exdate), "event.recurrence.exdates entries must be valid ISO timestamps");
|
|
2714
|
+
if (definition.required_types.length === 0) {
|
|
2715
|
+
return true;
|
|
2621
2716
|
}
|
|
2717
|
+
if (!itemTypeName) {
|
|
2718
|
+
return false;
|
|
2719
|
+
}
|
|
2720
|
+
return definition.required_types.map((value) => value.toLowerCase()).includes(itemTypeName.trim().toLowerCase());
|
|
2622
2721
|
}
|
|
2623
|
-
function
|
|
2624
|
-
|
|
2625
|
-
const
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
}
|
|
2636
|
-
function assertRequiredItemMetadataFields(record) {
|
|
2637
|
-
for (const fieldName of REQUIRED_STRING_FIELDS) {
|
|
2638
|
-
assertItemMetadataCondition(typeof record[fieldName] === "string", `${fieldName} is required and must be a string`);
|
|
2639
|
-
}
|
|
2640
|
-
const itemType = record.type;
|
|
2641
|
-
assertItemMetadataCondition(typeof itemType === "string" && itemType.trim().length > 0, "type must be a non-empty string");
|
|
2642
|
-
const formatVersion = record.pm_format_version;
|
|
2643
|
-
if (formatVersion !== void 0) {
|
|
2644
|
-
assertItemMetadataCondition(typeof formatVersion === "number" && Number.isInteger(formatVersion) && formatVersion >= BASELINE_ITEM_FORMAT_VERSION, `pm_format_version must be an integer >= ${BASELINE_ITEM_FORMAT_VERSION}`);
|
|
2645
|
-
}
|
|
2646
|
-
return itemType;
|
|
2647
|
-
}
|
|
2648
|
-
function assertStatusItemMetadataField(record, runtimeContext) {
|
|
2649
|
-
const status = record.status;
|
|
2650
|
-
assertItemMetadataCondition(typeof status === "string" && status.trim().length > 0, "status must be a non-empty string");
|
|
2651
|
-
const statusRegistry = runtimeContext?.statusRegistry;
|
|
2652
|
-
const normalizedStatus = normalizeStatusInput(status, statusRegistry);
|
|
2653
|
-
const statusDomain = statusRegistry ? statusRegistry.definitions.map((definition) => definition.id) : [...STATUS_VALUES];
|
|
2654
|
-
assertItemMetadataCondition(normalizedStatus !== void 0, `status must be one of: ${statusDomain.join(", ")}`);
|
|
2655
|
-
}
|
|
2656
|
-
function assertPriorityAndTags(record) {
|
|
2657
|
-
const priority = record.priority;
|
|
2658
|
-
assertItemMetadataCondition(typeof priority === "number" && Number.isInteger(priority) && [0, 1, 2, 3, 4].includes(priority), "priority must be an integer 0..4");
|
|
2659
|
-
const tags = record.tags;
|
|
2660
|
-
assertItemMetadataCondition(Array.isArray(tags), "tags must be an array");
|
|
2661
|
-
for (const tag of tags) {
|
|
2662
|
-
assertItemMetadataCondition(typeof tag === "string", "tags entries must be strings");
|
|
2722
|
+
function collectRuntimeCreateFieldValues(options, fieldRegistry, itemTypeName) {
|
|
2723
|
+
const values = {};
|
|
2724
|
+
const missingRequiredFlags = [];
|
|
2725
|
+
for (const definition of fieldRegistry.command_to_fields.get("create") ?? []) {
|
|
2726
|
+
const rawValue = readRuntimeFieldOptionValue(options, definition);
|
|
2727
|
+
if (rawValue === void 0) {
|
|
2728
|
+
if (shouldRequireFieldOnCreate(definition, itemTypeName)) {
|
|
2729
|
+
missingRequiredFlags.push(`--${definition.cli_flag}`);
|
|
2730
|
+
}
|
|
2731
|
+
continue;
|
|
2732
|
+
}
|
|
2733
|
+
values[definition.metadata_key] = coerceRuntimeFieldValue(definition, rawValue);
|
|
2663
2734
|
}
|
|
2735
|
+
return {
|
|
2736
|
+
values,
|
|
2737
|
+
missing_required_flags: [...new Set(missingRequiredFlags)].sort((left, right) => left.localeCompare(right))
|
|
2738
|
+
};
|
|
2664
2739
|
}
|
|
2665
|
-
function
|
|
2666
|
-
const
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2740
|
+
function collectRuntimeUpdateFieldValues(options, fieldRegistry, commands = ["update"]) {
|
|
2741
|
+
const values = {};
|
|
2742
|
+
const definitions = (commands ?? ["update"]).flatMap((command) => fieldRegistry.command_to_fields.get(command) ?? []);
|
|
2743
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2744
|
+
for (const definition of definitions) {
|
|
2745
|
+
const rawValue = readRuntimeFieldOptionValue(options, definition);
|
|
2746
|
+
if (rawValue === void 0) {
|
|
2747
|
+
continue;
|
|
2748
|
+
}
|
|
2749
|
+
if (seen.has(definition.metadata_key)) {
|
|
2750
|
+
continue;
|
|
2751
|
+
}
|
|
2752
|
+
seen.add(definition.metadata_key);
|
|
2753
|
+
values[definition.metadata_key] = coerceRuntimeFieldValue(definition, rawValue);
|
|
2679
2754
|
}
|
|
2680
|
-
|
|
2755
|
+
return values;
|
|
2681
2756
|
}
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2757
|
+
|
|
2758
|
+
// dist/core/item/item-format-version.js
|
|
2759
|
+
var BASELINE_ITEM_FORMAT_VERSION = 1;
|
|
2760
|
+
var CURRENT_ITEM_FORMAT_VERSION = 1;
|
|
2761
|
+
function effectiveItemFormatVersion(metadata) {
|
|
2762
|
+
const raw = metadata.pm_format_version;
|
|
2763
|
+
if (typeof raw === "number" && Number.isInteger(raw) && raw >= BASELINE_ITEM_FORMAT_VERSION) {
|
|
2764
|
+
return raw;
|
|
2689
2765
|
}
|
|
2690
|
-
|
|
2691
|
-
const isKnownSeverity = normalizedSeverity === "med" || ISSUE_SEVERITY_VALUES.includes(normalizedSeverity);
|
|
2692
|
-
assertItemMetadataCondition(isKnownSeverity, `severity value must be one of: ${[...ISSUE_SEVERITY_VALUES, "med"].join(", ")}`);
|
|
2766
|
+
return BASELINE_ITEM_FORMAT_VERSION;
|
|
2693
2767
|
}
|
|
2694
|
-
function
|
|
2695
|
-
if (
|
|
2696
|
-
|
|
2768
|
+
function normalizeItemFormatVersion(value) {
|
|
2769
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value <= BASELINE_ITEM_FORMAT_VERSION) {
|
|
2770
|
+
return void 0;
|
|
2697
2771
|
}
|
|
2772
|
+
return value;
|
|
2698
2773
|
}
|
|
2699
|
-
function
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
return;
|
|
2774
|
+
function classifyItemFormatVersion(version, current = CURRENT_ITEM_FORMAT_VERSION) {
|
|
2775
|
+
if (version < current) {
|
|
2776
|
+
return "outdated";
|
|
2703
2777
|
}
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
assertItemMetadataCondition(typeof reminder === "object" && reminder !== null && !Array.isArray(reminder), "reminders entries must be objects");
|
|
2707
|
-
const reminderRecord = reminder;
|
|
2708
|
-
assertItemMetadataCondition(typeof reminderRecord.at === "string", "reminder.at must be a string");
|
|
2709
|
-
assertItemMetadataCondition(isTimestampLiteral(reminderRecord.at), "reminder.at must be a valid ISO timestamp");
|
|
2710
|
-
assertItemMetadataCondition(typeof reminderRecord.text === "string", "reminder.text must be a string");
|
|
2711
|
-
assertItemMetadataCondition(reminderRecord.text.trim().length > 0, "reminder.text must not be empty");
|
|
2778
|
+
if (version > current) {
|
|
2779
|
+
return "ahead";
|
|
2712
2780
|
}
|
|
2781
|
+
return "current";
|
|
2713
2782
|
}
|
|
2714
|
-
function
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
"
|
|
2720
|
-
|
|
2721
|
-
if (
|
|
2722
|
-
|
|
2723
|
-
assertItemMetadataCondition(eventRecord[stringField].trim().length > 0, `event.${stringField} must not be empty`);
|
|
2783
|
+
function scanItemFormatVersions(entries, current = CURRENT_ITEM_FORMAT_VERSION) {
|
|
2784
|
+
const outdated = [];
|
|
2785
|
+
const ahead = [];
|
|
2786
|
+
for (const entry of entries) {
|
|
2787
|
+
const status = classifyItemFormatVersion(entry.version, current);
|
|
2788
|
+
if (status === "outdated") {
|
|
2789
|
+
outdated.push(entry.ref);
|
|
2790
|
+
} else if (status === "ahead") {
|
|
2791
|
+
ahead.push(entry.ref);
|
|
2724
2792
|
}
|
|
2725
2793
|
}
|
|
2794
|
+
return {
|
|
2795
|
+
outdated: outdated.sort((left, right) => left.localeCompare(right)),
|
|
2796
|
+
ahead: ahead.sort((left, right) => left.localeCompare(right))
|
|
2797
|
+
};
|
|
2726
2798
|
}
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2799
|
+
|
|
2800
|
+
// dist/core/item/status.js
|
|
2801
|
+
var STATUS_ALIAS_MAP = {
|
|
2802
|
+
"in-progress": "in_progress",
|
|
2803
|
+
cancelled: "canceled"
|
|
2804
|
+
};
|
|
2805
|
+
function normalizeStatusInput(value, registry) {
|
|
2806
|
+
if (registry) {
|
|
2807
|
+
const normalizedFromRegistry = normalizeStatusInputWithRegistry(value, registry);
|
|
2808
|
+
if (normalizedFromRegistry) {
|
|
2809
|
+
return normalizedFromRegistry;
|
|
2810
|
+
}
|
|
2730
2811
|
}
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
assertItemMetadataCondition(compareTimestampStrings(eventRecord.recurrence.until, eventRecord.start_at) >= 0, "event.recurrence.until must be at or after event.start_at");
|
|
2812
|
+
if (typeof value !== "string") {
|
|
2813
|
+
return void 0;
|
|
2734
2814
|
}
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
const eventRecord = event;
|
|
2739
|
-
assertItemMetadataCondition(typeof eventRecord.start_at === "string", "event.start_at must be a string");
|
|
2740
|
-
assertItemMetadataCondition(isTimestampLiteral(eventRecord.start_at), "event.start_at must be a valid ISO timestamp");
|
|
2741
|
-
if (eventRecord.end_at !== void 0) {
|
|
2742
|
-
assertItemMetadataCondition(typeof eventRecord.end_at === "string", "event.end_at must be a string");
|
|
2743
|
-
assertItemMetadataCondition(isTimestampLiteral(eventRecord.end_at), "event.end_at must be a valid ISO timestamp");
|
|
2744
|
-
assertItemMetadataCondition(compareTimestampStrings(eventRecord.end_at, eventRecord.start_at) > 0, "event.end_at must be after event.start_at");
|
|
2815
|
+
const normalized = value.trim().toLowerCase();
|
|
2816
|
+
if (!normalized) {
|
|
2817
|
+
return void 0;
|
|
2745
2818
|
}
|
|
2746
|
-
|
|
2747
|
-
if (
|
|
2748
|
-
|
|
2819
|
+
const canonical = STATUS_ALIAS_MAP[normalized] ?? normalized;
|
|
2820
|
+
if (!STATUS_VALUES.includes(canonical)) {
|
|
2821
|
+
return void 0;
|
|
2749
2822
|
}
|
|
2750
|
-
|
|
2823
|
+
return canonical;
|
|
2751
2824
|
}
|
|
2752
|
-
function
|
|
2753
|
-
|
|
2754
|
-
if (events === void 0) {
|
|
2755
|
-
return;
|
|
2756
|
-
}
|
|
2757
|
-
assertItemMetadataCondition(Array.isArray(events), "events must be an array");
|
|
2758
|
-
for (const event of events) {
|
|
2759
|
-
assertCalendarEventEntry(event);
|
|
2760
|
-
}
|
|
2825
|
+
function normalizeStatusForRegistry(status, registry) {
|
|
2826
|
+
return normalizeStatusInput(status, registry) ?? status;
|
|
2761
2827
|
}
|
|
2762
|
-
function
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2828
|
+
function isTerminalStatus(status, registry) {
|
|
2829
|
+
return registry.terminal_statuses.has(normalizeStatusForRegistry(status, registry));
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
// dist/core/item/item-format.js
|
|
2833
|
+
import { encode as encodeToon } from "@toon-format/toon";
|
|
2834
|
+
|
|
2835
|
+
// dist/core/item/toon-decode.js
|
|
2836
|
+
import { decode as decodeToon } from "@toon-format/toon";
|
|
2837
|
+
function escapeBracketsInQuotedScalars(content) {
|
|
2838
|
+
return content.split("\n").map((line) => {
|
|
2839
|
+
const separatorIndex = line.indexOf(": ");
|
|
2840
|
+
const bracketIndex = line.indexOf("[");
|
|
2841
|
+
if (separatorIndex === -1 || bracketIndex === -1 || bracketIndex < separatorIndex) {
|
|
2842
|
+
return line;
|
|
2772
2843
|
}
|
|
2773
|
-
|
|
2844
|
+
const key = line.slice(0, separatorIndex + 2);
|
|
2845
|
+
const value = line.slice(separatorIndex + 2);
|
|
2846
|
+
if (!value.startsWith('"')) {
|
|
2847
|
+
return line;
|
|
2848
|
+
}
|
|
2849
|
+
return key + value.replaceAll("[", "\\u005b");
|
|
2850
|
+
}).join("\n");
|
|
2774
2851
|
}
|
|
2775
|
-
function
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
const optionText = optionValue;
|
|
2785
|
-
assertItemMetadataCondition(optionText.trim().length > 0, "type_options values must be non-empty strings");
|
|
2852
|
+
function decodeToonItemContent(content) {
|
|
2853
|
+
try {
|
|
2854
|
+
return { value: decodeToon(content), usedScalarBracketEscape: false };
|
|
2855
|
+
} catch (strictError) {
|
|
2856
|
+
const escaped = escapeBracketsInQuotedScalars(content);
|
|
2857
|
+
if (escaped === content) {
|
|
2858
|
+
throw strictError;
|
|
2859
|
+
}
|
|
2860
|
+
return { value: decodeToon(escaped), usedScalarBracketEscape: true };
|
|
2786
2861
|
}
|
|
2787
2862
|
}
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2863
|
+
|
|
2864
|
+
// dist/core/shared/conflict-markers.js
|
|
2865
|
+
var CONFLICT_MARKER_PATTERN = /^\s*(<<<<<<<|=======|>>>>>>>)(?:\s.*)?$/;
|
|
2866
|
+
function findMergeConflictMarkers(content) {
|
|
2867
|
+
if (content.length === 0) {
|
|
2868
|
+
return [];
|
|
2791
2869
|
}
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2870
|
+
const lines = content.split(/\r?\n/);
|
|
2871
|
+
const matches = [];
|
|
2872
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
2873
|
+
const line = lines[index] ?? "";
|
|
2874
|
+
const markerMatch = line.match(CONFLICT_MARKER_PATTERN);
|
|
2875
|
+
if (!markerMatch) {
|
|
2798
2876
|
continue;
|
|
2799
2877
|
}
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2878
|
+
const marker = markerMatch[1];
|
|
2879
|
+
matches.push({
|
|
2880
|
+
line: index + 1,
|
|
2881
|
+
marker,
|
|
2882
|
+
text: line
|
|
2883
|
+
});
|
|
2805
2884
|
}
|
|
2885
|
+
return matches;
|
|
2806
2886
|
}
|
|
2807
|
-
function
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2887
|
+
function findFirstMergeConflictMarker(content) {
|
|
2888
|
+
const matches = findMergeConflictMarkers(content);
|
|
2889
|
+
return matches[0];
|
|
2890
|
+
}
|
|
2891
|
+
|
|
2892
|
+
// dist/core/item/item-format.js
|
|
2893
|
+
var LINKED_TEST_PM_CONTEXT_MODE_VALUES = /* @__PURE__ */ new Set([
|
|
2894
|
+
"schema",
|
|
2895
|
+
"tracker",
|
|
2896
|
+
"auto"
|
|
2897
|
+
]);
|
|
2898
|
+
var ITEM_TEST_RUN_STATUS_VALUES = /* @__PURE__ */ new Set([
|
|
2899
|
+
"passed",
|
|
2900
|
+
"failed",
|
|
2901
|
+
"stopped",
|
|
2902
|
+
"canceled"
|
|
2903
|
+
]);
|
|
2904
|
+
var PLAN_STEP_STATUS_SET = new Set(PLAN_STEP_STATUS_VALUES);
|
|
2905
|
+
function normalizePathValue(value) {
|
|
2906
|
+
return value.replaceAll("\\", "/");
|
|
2907
|
+
}
|
|
2908
|
+
function firstNonZeroComparison(comparisons) {
|
|
2909
|
+
for (const comparison of comparisons) {
|
|
2910
|
+
if (comparison !== 0) {
|
|
2911
|
+
return comparison;
|
|
2912
|
+
}
|
|
2820
2913
|
}
|
|
2914
|
+
return 0;
|
|
2821
2915
|
}
|
|
2822
|
-
function
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
assertPriorityAndTags(record);
|
|
2828
|
-
assertConfidenceItemMetadataField(record);
|
|
2829
|
-
assertSeverityItemMetadataField(record);
|
|
2830
|
-
assertRegressionItemMetadataField(record);
|
|
2831
|
-
assertTimestampField(record, "created_at");
|
|
2832
|
-
assertTimestampField(record, "updated_at");
|
|
2833
|
-
if (record.deadline !== void 0) {
|
|
2834
|
-
assertTimestampField(record, "deadline");
|
|
2916
|
+
function deleteUndefinedFields(record) {
|
|
2917
|
+
for (const [key, value] of Object.entries(record)) {
|
|
2918
|
+
if (value === void 0) {
|
|
2919
|
+
delete record[key];
|
|
2920
|
+
}
|
|
2835
2921
|
}
|
|
2836
|
-
assertReminderEntries(record);
|
|
2837
|
-
assertCalendarEvents(record);
|
|
2838
|
-
assertOptionalTimestampString(record, "closed_at", "closed_at");
|
|
2839
|
-
assertOptionalStringFields(record);
|
|
2840
|
-
assertTypeOptionsField(record);
|
|
2841
|
-
coerceRuntimeItemMetadataFields(record, itemType, runtimeContext);
|
|
2842
|
-
assertRuntimeUnknownItemMetadataFields(record, runtimeContext);
|
|
2843
2922
|
}
|
|
2844
|
-
|
|
2845
|
-
|
|
2923
|
+
var REQUIRED_STRING_FIELDS = [
|
|
2924
|
+
"id",
|
|
2925
|
+
"title",
|
|
2926
|
+
"description",
|
|
2927
|
+
"created_at",
|
|
2928
|
+
"updated_at"
|
|
2929
|
+
];
|
|
2930
|
+
var STATIC_ITEM_METADATA_FIELD_SET = new Set(ITEM_METADATA_KEY_ORDER);
|
|
2931
|
+
function resolveRuntimeSchemaValidationContext(options) {
|
|
2932
|
+
if (!options?.schema) {
|
|
2846
2933
|
return void 0;
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
if (byCreated !== 0)
|
|
2856
|
-
return byCreated;
|
|
2857
|
-
const byId = a.id.localeCompare(b.id);
|
|
2858
|
-
if (byId !== 0)
|
|
2859
|
-
return byId;
|
|
2860
|
-
const byKind = a.kind.localeCompare(b.kind);
|
|
2861
|
-
if (byKind !== 0)
|
|
2862
|
-
return byKind;
|
|
2863
|
-
return (a.source_kind ?? "").localeCompare(b.source_kind ?? "");
|
|
2864
|
-
});
|
|
2934
|
+
}
|
|
2935
|
+
return {
|
|
2936
|
+
statusRegistry: resolveRuntimeStatusRegistry(options.schema),
|
|
2937
|
+
fieldRegistry: resolveRuntimeFieldRegistry(options.schema),
|
|
2938
|
+
unknownFieldPolicy: options.schema.unknown_field_policy ?? "allow",
|
|
2939
|
+
extensionFieldNames: new Set(options.extensionFieldNames ?? []),
|
|
2940
|
+
onWarning: options.onWarning
|
|
2941
|
+
};
|
|
2865
2942
|
}
|
|
2866
|
-
function
|
|
2867
|
-
if (!
|
|
2868
|
-
return
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
if (byText !== 0)
|
|
2875
|
-
return byText;
|
|
2876
|
-
return a.author.localeCompare(b.author);
|
|
2877
|
-
});
|
|
2943
|
+
function runtimeFieldRequiredForType(definition, typeName) {
|
|
2944
|
+
if (!definition.required) {
|
|
2945
|
+
return false;
|
|
2946
|
+
}
|
|
2947
|
+
if (definition.required_types.length === 0) {
|
|
2948
|
+
return true;
|
|
2949
|
+
}
|
|
2950
|
+
return definition.required_types.map((value) => value.toLowerCase()).includes(typeName.trim().toLowerCase());
|
|
2878
2951
|
}
|
|
2879
|
-
function
|
|
2880
|
-
|
|
2881
|
-
return void 0;
|
|
2882
|
-
const normalized = [...values].map((value) => ({
|
|
2883
|
-
at: value.at,
|
|
2884
|
-
text: value.text.trim()
|
|
2885
|
-
})).filter((value) => value.text.length > 0).sort((a, b) => {
|
|
2886
|
-
const byAt = compareTimestampStrings(a.at, b.at);
|
|
2887
|
-
if (byAt !== 0)
|
|
2888
|
-
return byAt;
|
|
2889
|
-
return a.text.localeCompare(b.text);
|
|
2890
|
-
});
|
|
2891
|
-
return normalized.length === 0 ? void 0 : normalized;
|
|
2952
|
+
function validationError(message) {
|
|
2953
|
+
throw new PmCliError(`Invalid item metadata: ${message}`, EXIT_CODE.GENERIC_FAILURE);
|
|
2892
2954
|
}
|
|
2893
|
-
function
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
const normalizedFrequency = value.freq.trim().toLowerCase();
|
|
2898
|
-
if (!RECURRENCE_FREQUENCY_VALUES.includes(normalizedFrequency)) {
|
|
2899
|
-
return void 0;
|
|
2955
|
+
function buildKnownItemMetadataKeys(runtimeContext) {
|
|
2956
|
+
const knownKeys = new Set(STATIC_ITEM_METADATA_FIELD_SET);
|
|
2957
|
+
for (const definition of runtimeContext.fieldRegistry?.definitions ?? []) {
|
|
2958
|
+
knownKeys.add(definition.metadata_key);
|
|
2900
2959
|
}
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
const exdates = Array.from(new Set((value.exdates ?? []).map((timestamp) => timestamp.trim()).filter((timestamp) => isTimestampLiteral(timestamp)))).sort((a, b) => compareTimestampStrings(a, b));
|
|
2904
|
-
const normalized = {
|
|
2905
|
-
freq: normalizedFrequency,
|
|
2906
|
-
interval: value.interval !== void 0 && value.interval > 1 ? value.interval : void 0,
|
|
2907
|
-
count: value.count,
|
|
2908
|
-
until: value.until?.trim() || void 0,
|
|
2909
|
-
by_weekday: byWeekday.length > 0 ? byWeekday : void 0,
|
|
2910
|
-
by_month_day: byMonthDay.length > 0 ? byMonthDay : void 0,
|
|
2911
|
-
exdates: exdates.length > 0 ? exdates : void 0
|
|
2912
|
-
};
|
|
2913
|
-
for (const [key, fieldValue] of Object.entries(normalized)) {
|
|
2914
|
-
if (fieldValue === void 0) {
|
|
2915
|
-
delete normalized[key];
|
|
2916
|
-
}
|
|
2960
|
+
for (const fieldName of runtimeContext.extensionFieldNames) {
|
|
2961
|
+
knownKeys.add(fieldName);
|
|
2917
2962
|
}
|
|
2918
|
-
return
|
|
2963
|
+
return knownKeys;
|
|
2919
2964
|
}
|
|
2920
|
-
function
|
|
2921
|
-
if (!
|
|
2922
|
-
|
|
2965
|
+
function assertItemMetadataCondition(condition, message) {
|
|
2966
|
+
if (!condition) {
|
|
2967
|
+
validationError(message);
|
|
2923
2968
|
}
|
|
2924
|
-
const normalized = [...values].map(normalizeCalendarEvent).sort(compareCalendarEvents);
|
|
2925
|
-
return normalized;
|
|
2926
2969
|
}
|
|
2927
|
-
function
|
|
2928
|
-
const
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
description: value.description?.trim() || void 0,
|
|
2933
|
-
location: value.location?.trim() || void 0,
|
|
2934
|
-
all_day: value.all_day,
|
|
2935
|
-
timezone: value.timezone?.trim() || void 0,
|
|
2936
|
-
recurrence: normalizeRecurrenceRule(value.recurrence)
|
|
2937
|
-
};
|
|
2938
|
-
deleteUndefinedFields(event);
|
|
2939
|
-
return event;
|
|
2970
|
+
function assertTimestampField(record, fieldName) {
|
|
2971
|
+
const rawValue = record[fieldName];
|
|
2972
|
+
assertItemMetadataCondition(typeof rawValue === "string", `${fieldName} must be a string`);
|
|
2973
|
+
const timestamp = rawValue;
|
|
2974
|
+
assertItemMetadataCondition(isTimestampLiteral(timestamp), `${fieldName} must be a valid ISO timestamp`);
|
|
2940
2975
|
}
|
|
2941
|
-
function
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
(a.timezone ?? "").localeCompare(b.timezone ?? ""),
|
|
2948
|
-
(a.location ?? "").localeCompare(b.location ?? ""),
|
|
2949
|
-
(a.description ?? "").localeCompare(b.description ?? ""),
|
|
2950
|
-
JSON.stringify(a.recurrence ?? {}).localeCompare(JSON.stringify(b.recurrence ?? {}))
|
|
2951
|
-
]);
|
|
2976
|
+
function assertPositiveIntegerField(record, fieldName, messagePrefix) {
|
|
2977
|
+
const value = record[fieldName];
|
|
2978
|
+
if (value === void 0) {
|
|
2979
|
+
return;
|
|
2980
|
+
}
|
|
2981
|
+
assertItemMetadataCondition(typeof value === "number" && Number.isInteger(value) && value >= 1, `${messagePrefix} must be an integer >= 1`);
|
|
2952
2982
|
}
|
|
2953
|
-
function
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
}));
|
|
2983
|
+
function assertOptionalTimestampString(record, fieldName, messagePrefix) {
|
|
2984
|
+
const value = record[fieldName];
|
|
2985
|
+
if (value === void 0) {
|
|
2986
|
+
return;
|
|
2987
|
+
}
|
|
2988
|
+
assertItemMetadataCondition(typeof value === "string", `${messagePrefix} must be a string`);
|
|
2989
|
+
assertItemMetadataCondition(isTimestampLiteral(value), `${messagePrefix} must be a valid ISO timestamp`);
|
|
2961
2990
|
}
|
|
2962
|
-
function
|
|
2963
|
-
if (
|
|
2964
|
-
return
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2991
|
+
function assertRecurrenceWeekdays(value) {
|
|
2992
|
+
if (value === void 0) {
|
|
2993
|
+
return;
|
|
2994
|
+
}
|
|
2995
|
+
assertItemMetadataCondition(Array.isArray(value), "event.recurrence.by_weekday must be an array");
|
|
2996
|
+
for (const weekday of value) {
|
|
2997
|
+
assertItemMetadataCondition(typeof weekday === "string", "event.recurrence.by_weekday entries must be strings");
|
|
2998
|
+
const normalizedWeekday = weekday.trim().toLowerCase();
|
|
2999
|
+
assertItemMetadataCondition(RECURRENCE_WEEKDAY_VALUES.includes(normalizedWeekday), `event.recurrence.by_weekday entries must be one of: ${RECURRENCE_WEEKDAY_VALUES.join(", ")}`);
|
|
3000
|
+
}
|
|
2971
3001
|
}
|
|
2972
|
-
function
|
|
2973
|
-
|
|
3002
|
+
function assertRecurrenceMonthDays(value) {
|
|
3003
|
+
if (value === void 0) {
|
|
3004
|
+
return;
|
|
3005
|
+
}
|
|
3006
|
+
assertItemMetadataCondition(Array.isArray(value), "event.recurrence.by_month_day must be an array");
|
|
3007
|
+
for (const day of value) {
|
|
3008
|
+
assertItemMetadataCondition(typeof day === "number" && Number.isInteger(day) && day >= 1 && day <= 31, "event.recurrence.by_month_day entries must be integers 1..31");
|
|
3009
|
+
}
|
|
2974
3010
|
}
|
|
2975
|
-
function
|
|
2976
|
-
|
|
3011
|
+
function assertRecurrenceExdates(value) {
|
|
3012
|
+
if (value === void 0) {
|
|
3013
|
+
return;
|
|
3014
|
+
}
|
|
3015
|
+
assertItemMetadataCondition(Array.isArray(value), "event.recurrence.exdates must be an array");
|
|
3016
|
+
for (const exdate of value) {
|
|
3017
|
+
assertItemMetadataCondition(typeof exdate === "string", "event.recurrence.exdates entries must be strings");
|
|
3018
|
+
assertItemMetadataCondition(isTimestampLiteral(exdate), "event.recurrence.exdates entries must be valid ISO timestamps");
|
|
3019
|
+
}
|
|
2977
3020
|
}
|
|
2978
|
-
function
|
|
2979
|
-
|
|
3021
|
+
function assertValidRecurrenceRule(recurrence) {
|
|
3022
|
+
assertItemMetadataCondition(typeof recurrence === "object" && recurrence !== null && !Array.isArray(recurrence), "event.recurrence must be an object");
|
|
3023
|
+
const recurrenceRecord = recurrence;
|
|
3024
|
+
assertItemMetadataCondition(typeof recurrenceRecord.freq === "string", "event.recurrence.freq must be a string");
|
|
3025
|
+
const frequency = recurrenceRecord.freq.trim().toLowerCase();
|
|
3026
|
+
assertItemMetadataCondition(RECURRENCE_FREQUENCY_VALUES.includes(frequency), `event.recurrence.freq must be one of: ${RECURRENCE_FREQUENCY_VALUES.join(", ")}`);
|
|
3027
|
+
assertPositiveIntegerField(recurrenceRecord, "interval", "event.recurrence.interval");
|
|
3028
|
+
assertPositiveIntegerField(recurrenceRecord, "count", "event.recurrence.count");
|
|
3029
|
+
assertOptionalTimestampString(recurrenceRecord, "until", "event.recurrence.until");
|
|
3030
|
+
assertRecurrenceWeekdays(recurrenceRecord.by_weekday);
|
|
3031
|
+
assertRecurrenceMonthDays(recurrenceRecord.by_month_day);
|
|
3032
|
+
assertRecurrenceExdates(recurrenceRecord.exdates);
|
|
2980
3033
|
}
|
|
2981
|
-
function
|
|
2982
|
-
const
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
const
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
attempt: normalizePositiveInteger(value.attempt),
|
|
2993
|
-
resumed_from: value.resumed_from?.trim() || void 0,
|
|
2994
|
-
passed: normalizeNonNegativeInteger(value.passed) ?? 0,
|
|
2995
|
-
failed: normalizeNonNegativeInteger(value.failed) ?? 0,
|
|
2996
|
-
skipped: normalizeNonNegativeInteger(value.skipped) ?? 0,
|
|
2997
|
-
items: normalizeNonNegativeInteger(value.items),
|
|
2998
|
-
linked_tests: normalizeNonNegativeInteger(value.linked_tests),
|
|
2999
|
-
fail_on_skipped_triggered: value.fail_on_skipped_triggered === true ? true : void 0
|
|
3000
|
-
};
|
|
3001
|
-
deleteUndefinedFields(summary);
|
|
3002
|
-
return summary;
|
|
3034
|
+
function assertRequiredItemMetadataFields(record) {
|
|
3035
|
+
for (const fieldName of REQUIRED_STRING_FIELDS) {
|
|
3036
|
+
assertItemMetadataCondition(typeof record[fieldName] === "string", `${fieldName} is required and must be a string`);
|
|
3037
|
+
}
|
|
3038
|
+
const itemType = record.type;
|
|
3039
|
+
assertItemMetadataCondition(typeof itemType === "string" && itemType.trim().length > 0, "type must be a non-empty string");
|
|
3040
|
+
const formatVersion = record.pm_format_version;
|
|
3041
|
+
if (formatVersion !== void 0) {
|
|
3042
|
+
assertItemMetadataCondition(typeof formatVersion === "number" && Number.isInteger(formatVersion) && formatVersion >= BASELINE_ITEM_FORMAT_VERSION, `pm_format_version must be an integer >= ${BASELINE_ITEM_FORMAT_VERSION}`);
|
|
3043
|
+
}
|
|
3044
|
+
return itemType;
|
|
3003
3045
|
}
|
|
3004
|
-
function
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3046
|
+
function assertStatusItemMetadataField(record, runtimeContext) {
|
|
3047
|
+
const status = record.status;
|
|
3048
|
+
assertItemMetadataCondition(typeof status === "string" && status.trim().length > 0, "status must be a non-empty string");
|
|
3049
|
+
const statusRegistry = runtimeContext?.statusRegistry;
|
|
3050
|
+
const normalizedStatus = normalizeStatusInput(status, statusRegistry);
|
|
3051
|
+
const statusDomain = statusRegistry ? statusRegistry.definitions.map((definition) => definition.id) : [...STATUS_VALUES];
|
|
3052
|
+
assertItemMetadataCondition(normalizedStatus !== void 0, `status must be one of: ${statusDomain.join(", ")}`);
|
|
3008
3053
|
}
|
|
3009
|
-
function
|
|
3010
|
-
|
|
3011
|
-
|
|
3054
|
+
function assertPriorityAndTags(record) {
|
|
3055
|
+
const priority = record.priority;
|
|
3056
|
+
assertItemMetadataCondition(typeof priority === "number" && Number.isInteger(priority) && [0, 1, 2, 3, 4].includes(priority), "priority must be an integer 0..4");
|
|
3057
|
+
const tags = record.tags;
|
|
3058
|
+
assertItemMetadataCondition(Array.isArray(tags), "tags must be an array");
|
|
3059
|
+
for (const tag of tags) {
|
|
3060
|
+
assertItemMetadataCondition(typeof tag === "string", "tags entries must be strings");
|
|
3012
3061
|
}
|
|
3013
|
-
const normalized = [
|
|
3014
|
-
...new Set(value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter((entry) => entry.length > 0))
|
|
3015
|
-
].sort((a, b) => a.localeCompare(b));
|
|
3016
|
-
return normalized.length > 0 ? normalized : void 0;
|
|
3017
3062
|
}
|
|
3018
|
-
function
|
|
3019
|
-
|
|
3020
|
-
|
|
3063
|
+
function assertConfidenceItemMetadataField(record) {
|
|
3064
|
+
const confidence = record.confidence;
|
|
3065
|
+
if (confidence === void 0) {
|
|
3066
|
+
return;
|
|
3021
3067
|
}
|
|
3022
|
-
|
|
3023
|
-
|
|
3068
|
+
if (typeof confidence === "number") {
|
|
3069
|
+
assertItemMetadataCondition(Number.isInteger(confidence) && confidence >= 0 && confidence <= 100, "confidence number value must be an integer 0..100");
|
|
3070
|
+
return;
|
|
3071
|
+
}
|
|
3072
|
+
if (typeof confidence === "string") {
|
|
3073
|
+
const normalizedConfidence = confidence.trim().toLowerCase();
|
|
3074
|
+
const isKnownTextConfidence = normalizedConfidence === "med" || CONFIDENCE_TEXT_VALUES.includes(normalizedConfidence);
|
|
3075
|
+
assertItemMetadataCondition(isKnownTextConfidence, `confidence string value must be one of: ${[...CONFIDENCE_TEXT_VALUES, "med"].join(", ")}`);
|
|
3076
|
+
return;
|
|
3077
|
+
}
|
|
3078
|
+
assertItemMetadataCondition(false, "confidence must be a number or string");
|
|
3024
3079
|
}
|
|
3025
|
-
function
|
|
3026
|
-
|
|
3080
|
+
function assertSeverityItemMetadataField(record) {
|
|
3081
|
+
const severity = record.severity;
|
|
3082
|
+
if (severity === void 0) {
|
|
3083
|
+
return;
|
|
3084
|
+
}
|
|
3085
|
+
if (typeof severity !== "string") {
|
|
3086
|
+
validationError("severity must be a string");
|
|
3087
|
+
}
|
|
3088
|
+
const normalizedSeverity = severity.trim().toLowerCase();
|
|
3089
|
+
const isKnownSeverity = normalizedSeverity === "med" || ISSUE_SEVERITY_VALUES.includes(normalizedSeverity);
|
|
3090
|
+
assertItemMetadataCondition(isKnownSeverity, `severity value must be one of: ${[...ISSUE_SEVERITY_VALUES, "med"].join(", ")}`);
|
|
3027
3091
|
}
|
|
3028
|
-
function
|
|
3029
|
-
if (
|
|
3030
|
-
|
|
3092
|
+
function assertRegressionItemMetadataField(record) {
|
|
3093
|
+
if (record.regression !== void 0 && typeof record.regression !== "boolean") {
|
|
3094
|
+
validationError("regression must be a boolean");
|
|
3031
3095
|
}
|
|
3032
|
-
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));
|
|
3033
|
-
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
3034
3096
|
}
|
|
3035
|
-
function
|
|
3036
|
-
|
|
3037
|
-
|
|
3097
|
+
function assertReminderEntries(record) {
|
|
3098
|
+
const reminders = record.reminders;
|
|
3099
|
+
if (reminders === void 0) {
|
|
3100
|
+
return;
|
|
3101
|
+
}
|
|
3102
|
+
assertItemMetadataCondition(Array.isArray(reminders), "reminders must be an array");
|
|
3103
|
+
for (const reminder of reminders) {
|
|
3104
|
+
assertItemMetadataCondition(typeof reminder === "object" && reminder !== null && !Array.isArray(reminder), "reminders entries must be objects");
|
|
3105
|
+
const reminderRecord = reminder;
|
|
3106
|
+
assertItemMetadataCondition(typeof reminderRecord.at === "string", "reminder.at must be a string");
|
|
3107
|
+
assertItemMetadataCondition(isTimestampLiteral(reminderRecord.at), "reminder.at must be a valid ISO timestamp");
|
|
3108
|
+
assertItemMetadataCondition(typeof reminderRecord.text === "string", "reminder.text must be a string");
|
|
3109
|
+
assertItemMetadataCondition(reminderRecord.text.trim().length > 0, "reminder.text must not be empty");
|
|
3038
3110
|
}
|
|
3039
|
-
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));
|
|
3040
|
-
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
3041
3111
|
}
|
|
3042
|
-
function
|
|
3043
|
-
const
|
|
3044
|
-
|
|
3045
|
-
|
|
3112
|
+
function assertEventStringFields(eventRecord) {
|
|
3113
|
+
for (const stringField of [
|
|
3114
|
+
"title",
|
|
3115
|
+
"description",
|
|
3116
|
+
"location",
|
|
3117
|
+
"timezone"
|
|
3118
|
+
]) {
|
|
3119
|
+
if (eventRecord[stringField] !== void 0) {
|
|
3120
|
+
assertItemMetadataCondition(typeof eventRecord[stringField] === "string", `event.${stringField} must be a string`);
|
|
3121
|
+
assertItemMetadataCondition(eventRecord[stringField].trim().length > 0, `event.${stringField} must not be empty`);
|
|
3122
|
+
}
|
|
3046
3123
|
}
|
|
3047
|
-
return normalized;
|
|
3048
3124
|
}
|
|
3049
|
-
function
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
env_clear: normalizeTrimmedStringList(value.env_clear),
|
|
3058
|
-
shared_host_safe: value.shared_host_safe === true ? true : void 0,
|
|
3059
|
-
assert_stdout_contains: normalizeTrimmedStringList(value.assert_stdout_contains),
|
|
3060
|
-
assert_stdout_regex: normalizeTrimmedStringList(value.assert_stdout_regex),
|
|
3061
|
-
assert_stderr_contains: normalizeTrimmedStringList(value.assert_stderr_contains),
|
|
3062
|
-
assert_stderr_regex: normalizeTrimmedStringList(value.assert_stderr_regex),
|
|
3063
|
-
assert_stdout_min_lines: normalizeNonNegativeInteger(value.assert_stdout_min_lines),
|
|
3064
|
-
assert_json_field_equals: normalizeStringRecord(value.assert_json_field_equals),
|
|
3065
|
-
assert_json_field_gte: normalizeNumericRecord(value.assert_json_field_gte),
|
|
3066
|
-
note: value.note?.trim() || void 0
|
|
3067
|
-
};
|
|
3068
|
-
deleteUndefinedFields(test);
|
|
3069
|
-
return test;
|
|
3125
|
+
function assertEventRecurrence(eventRecord) {
|
|
3126
|
+
if (eventRecord.recurrence === void 0) {
|
|
3127
|
+
return;
|
|
3128
|
+
}
|
|
3129
|
+
assertValidRecurrenceRule(eventRecord.recurrence);
|
|
3130
|
+
if (eventRecord.recurrence.until !== void 0) {
|
|
3131
|
+
assertItemMetadataCondition(compareTimestampStrings(eventRecord.recurrence.until, eventRecord.start_at) >= 0, "event.recurrence.until must be at or after event.start_at");
|
|
3132
|
+
}
|
|
3070
3133
|
}
|
|
3071
|
-
function
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
compareJsonValues(a.assert_json_field_equals, b.assert_json_field_equals, {}),
|
|
3087
|
-
compareJsonValues(a.assert_json_field_gte, b.assert_json_field_gte, {}),
|
|
3088
|
-
compareOptionalStrings(a.note, b.note)
|
|
3089
|
-
]);
|
|
3134
|
+
function assertCalendarEventEntry(event) {
|
|
3135
|
+
assertItemMetadataCondition(typeof event === "object" && event !== null && !Array.isArray(event), "events entries must be objects");
|
|
3136
|
+
const eventRecord = event;
|
|
3137
|
+
assertItemMetadataCondition(typeof eventRecord.start_at === "string", "event.start_at must be a string");
|
|
3138
|
+
assertItemMetadataCondition(isTimestampLiteral(eventRecord.start_at), "event.start_at must be a valid ISO timestamp");
|
|
3139
|
+
if (eventRecord.end_at !== void 0) {
|
|
3140
|
+
assertItemMetadataCondition(typeof eventRecord.end_at === "string", "event.end_at must be a string");
|
|
3141
|
+
assertItemMetadataCondition(isTimestampLiteral(eventRecord.end_at), "event.end_at must be a valid ISO timestamp");
|
|
3142
|
+
assertItemMetadataCondition(compareTimestampStrings(eventRecord.end_at, eventRecord.start_at) > 0, "event.end_at must be after event.start_at");
|
|
3143
|
+
}
|
|
3144
|
+
assertEventStringFields(eventRecord);
|
|
3145
|
+
if (eventRecord.all_day !== void 0) {
|
|
3146
|
+
assertItemMetadataCondition(typeof eventRecord.all_day === "boolean", "event.all_day must be a boolean");
|
|
3147
|
+
}
|
|
3148
|
+
assertEventRecurrence(eventRecord);
|
|
3090
3149
|
}
|
|
3091
|
-
function
|
|
3092
|
-
|
|
3150
|
+
function assertCalendarEvents(record) {
|
|
3151
|
+
const events = record.events;
|
|
3152
|
+
if (events === void 0) {
|
|
3153
|
+
return;
|
|
3154
|
+
}
|
|
3155
|
+
assertItemMetadataCondition(Array.isArray(events), "events must be an array");
|
|
3156
|
+
for (const event of events) {
|
|
3157
|
+
assertCalendarEventEntry(event);
|
|
3158
|
+
}
|
|
3093
3159
|
}
|
|
3094
|
-
function
|
|
3095
|
-
|
|
3160
|
+
function assertOptionalStringFields(record) {
|
|
3161
|
+
for (const fieldName of [
|
|
3162
|
+
"source_type",
|
|
3163
|
+
"source_owner",
|
|
3164
|
+
"design",
|
|
3165
|
+
"external_ref"
|
|
3166
|
+
]) {
|
|
3167
|
+
const value = record[fieldName];
|
|
3168
|
+
if (value !== void 0) {
|
|
3169
|
+
assertItemMetadataCondition(typeof value === "string", `${fieldName} must be a string`);
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3096
3172
|
}
|
|
3097
|
-
function
|
|
3098
|
-
|
|
3173
|
+
function assertTypeOptionsField(record) {
|
|
3174
|
+
const typeOptions = record.type_options;
|
|
3175
|
+
if (typeOptions === void 0) {
|
|
3176
|
+
return;
|
|
3177
|
+
}
|
|
3178
|
+
assertItemMetadataCondition(typeof typeOptions === "object" && typeOptions !== null && !Array.isArray(typeOptions), "type_options must be an object");
|
|
3179
|
+
for (const [optionKey, optionValue] of Object.entries(typeOptions)) {
|
|
3180
|
+
assertItemMetadataCondition(optionKey.trim().length > 0, "type_options keys must be non-empty");
|
|
3181
|
+
assertItemMetadataCondition(typeof optionValue === "string", "type_options values must be strings");
|
|
3182
|
+
const optionText = optionValue;
|
|
3183
|
+
assertItemMetadataCondition(optionText.trim().length > 0, "type_options values must be non-empty strings");
|
|
3184
|
+
}
|
|
3099
3185
|
}
|
|
3100
|
-
function
|
|
3186
|
+
function coerceRuntimeItemMetadataFields(record, itemType, runtimeContext) {
|
|
3187
|
+
if (!runtimeContext?.fieldRegistry) {
|
|
3188
|
+
return;
|
|
3189
|
+
}
|
|
3190
|
+
for (const definition of runtimeContext.fieldRegistry.definitions) {
|
|
3191
|
+
const fieldValue = record[definition.metadata_key];
|
|
3192
|
+
if (fieldValue === void 0) {
|
|
3193
|
+
if (runtimeFieldRequiredForType(definition, itemType)) {
|
|
3194
|
+
validationError(`missing required schema field: ${definition.metadata_key}`);
|
|
3195
|
+
}
|
|
3196
|
+
continue;
|
|
3197
|
+
}
|
|
3198
|
+
try {
|
|
3199
|
+
record[definition.metadata_key] = coerceRuntimeFieldValue(definition, fieldValue, `metadata field "${definition.metadata_key}"`);
|
|
3200
|
+
} catch (error) {
|
|
3201
|
+
validationError(String(error?.message).replace(/^Invalid\s+/u, ""));
|
|
3202
|
+
}
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
3205
|
+
function assertRuntimeUnknownItemMetadataFields(record, runtimeContext) {
|
|
3206
|
+
if (!runtimeContext || runtimeContext.unknownFieldPolicy === "allow") {
|
|
3207
|
+
return;
|
|
3208
|
+
}
|
|
3209
|
+
const knownKeys = buildKnownItemMetadataKeys(runtimeContext);
|
|
3210
|
+
const unknownKeys = Object.keys(record).filter((key) => !knownKeys.has(key)).sort((left, right) => left.localeCompare(right));
|
|
3211
|
+
if (unknownKeys.length === 0) {
|
|
3212
|
+
return;
|
|
3213
|
+
}
|
|
3214
|
+
if (runtimeContext.unknownFieldPolicy === "reject") {
|
|
3215
|
+
validationError(`unknown schema fields are not allowed: ${unknownKeys.join(", ")}`);
|
|
3216
|
+
} else {
|
|
3217
|
+
runtimeContext.onWarning?.(`item_unknown_schema_fields:${unknownKeys.join(",")}`);
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
function assertValidItemMetadata(itemMetadata, runtimeContext) {
|
|
3221
|
+
assertItemMetadataCondition(typeof itemMetadata === "object" && itemMetadata !== null && !Array.isArray(itemMetadata), "item metadata must be an object");
|
|
3222
|
+
const record = itemMetadata;
|
|
3223
|
+
const itemType = assertRequiredItemMetadataFields(record);
|
|
3224
|
+
assertStatusItemMetadataField(record, runtimeContext);
|
|
3225
|
+
assertPriorityAndTags(record);
|
|
3226
|
+
assertConfidenceItemMetadataField(record);
|
|
3227
|
+
assertSeverityItemMetadataField(record);
|
|
3228
|
+
assertRegressionItemMetadataField(record);
|
|
3229
|
+
assertTimestampField(record, "created_at");
|
|
3230
|
+
assertTimestampField(record, "updated_at");
|
|
3231
|
+
if (record.deadline !== void 0) {
|
|
3232
|
+
assertTimestampField(record, "deadline");
|
|
3233
|
+
}
|
|
3234
|
+
assertReminderEntries(record);
|
|
3235
|
+
assertCalendarEvents(record);
|
|
3236
|
+
assertOptionalTimestampString(record, "closed_at", "closed_at");
|
|
3237
|
+
assertOptionalStringFields(record);
|
|
3238
|
+
assertTypeOptionsField(record);
|
|
3239
|
+
coerceRuntimeItemMetadataFields(record, itemType, runtimeContext);
|
|
3240
|
+
assertRuntimeUnknownItemMetadataFields(record, runtimeContext);
|
|
3241
|
+
}
|
|
3242
|
+
function sortDependencies(values) {
|
|
3101
3243
|
if (!values || values.length === 0)
|
|
3102
3244
|
return void 0;
|
|
3103
3245
|
return [...values].map((value) => ({
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3246
|
+
id: value.id.trim().toLowerCase(),
|
|
3247
|
+
kind: value.kind,
|
|
3248
|
+
created_at: value.created_at,
|
|
3249
|
+
author: value.author?.trim() || void 0,
|
|
3250
|
+
source_kind: value.source_kind?.trim() || void 0
|
|
3107
3251
|
})).sort((a, b) => {
|
|
3108
|
-
const
|
|
3109
|
-
if (
|
|
3110
|
-
return
|
|
3111
|
-
const
|
|
3112
|
-
if (
|
|
3113
|
-
return
|
|
3114
|
-
|
|
3252
|
+
const byCreated = compareTimestampStrings(a.created_at, b.created_at);
|
|
3253
|
+
if (byCreated !== 0)
|
|
3254
|
+
return byCreated;
|
|
3255
|
+
const byId = a.id.localeCompare(b.id);
|
|
3256
|
+
if (byId !== 0)
|
|
3257
|
+
return byId;
|
|
3258
|
+
const byKind = a.kind.localeCompare(b.kind);
|
|
3259
|
+
if (byKind !== 0)
|
|
3260
|
+
return byKind;
|
|
3261
|
+
return (a.source_kind ?? "").localeCompare(b.source_kind ?? "");
|
|
3115
3262
|
});
|
|
3116
3263
|
}
|
|
3117
|
-
function
|
|
3118
|
-
if (
|
|
3264
|
+
function sortLogValues(values) {
|
|
3265
|
+
if (!values || values.length === 0)
|
|
3119
3266
|
return void 0;
|
|
3120
|
-
|
|
3121
|
-
|
|
3267
|
+
return [...values].sort((a, b) => {
|
|
3268
|
+
const byCreated = compareTimestampStrings(a.created_at, b.created_at);
|
|
3269
|
+
if (byCreated !== 0)
|
|
3270
|
+
return byCreated;
|
|
3271
|
+
const byText = a.text.localeCompare(b.text);
|
|
3272
|
+
if (byText !== 0)
|
|
3273
|
+
return byText;
|
|
3274
|
+
return a.author.localeCompare(b.author);
|
|
3275
|
+
});
|
|
3122
3276
|
}
|
|
3123
|
-
function
|
|
3124
|
-
if (!
|
|
3277
|
+
function sortReminders(values) {
|
|
3278
|
+
if (!values || values.length === 0)
|
|
3125
3279
|
return void 0;
|
|
3126
|
-
const
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
const
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
const note = trimStringOrUndefined(record.note);
|
|
3137
|
-
if (note)
|
|
3138
|
-
link.note = note;
|
|
3139
|
-
if (record.required_before_step === true)
|
|
3140
|
-
link.required_before_step = true;
|
|
3141
|
-
out.push(link);
|
|
3142
|
-
}
|
|
3143
|
-
return out.length > 0 ? out : void 0;
|
|
3280
|
+
const normalized = [...values].map((value) => ({
|
|
3281
|
+
at: value.at,
|
|
3282
|
+
text: value.text.trim()
|
|
3283
|
+
})).filter((value) => value.text.length > 0).sort((a, b) => {
|
|
3284
|
+
const byAt = compareTimestampStrings(a.at, b.at);
|
|
3285
|
+
if (byAt !== 0)
|
|
3286
|
+
return byAt;
|
|
3287
|
+
return a.text.localeCompare(b.text);
|
|
3288
|
+
});
|
|
3289
|
+
return normalized.length === 0 ? void 0 : normalized;
|
|
3144
3290
|
}
|
|
3145
|
-
function
|
|
3146
|
-
if (!
|
|
3291
|
+
function normalizeRecurrenceRule(value) {
|
|
3292
|
+
if (!value) {
|
|
3147
3293
|
return void 0;
|
|
3148
|
-
const out = [];
|
|
3149
|
-
for (const entry of value) {
|
|
3150
|
-
if (entry === null || typeof entry !== "object")
|
|
3151
|
-
continue;
|
|
3152
|
-
const record = entry;
|
|
3153
|
-
const path6 = trimStringOrUndefined(record.path);
|
|
3154
|
-
if (!path6)
|
|
3155
|
-
continue;
|
|
3156
|
-
const file = { path: normalizePathValue(path6) };
|
|
3157
|
-
if (record.scope === "project" || record.scope === "global")
|
|
3158
|
-
file.scope = record.scope;
|
|
3159
|
-
const note = trimStringOrUndefined(record.note);
|
|
3160
|
-
if (note)
|
|
3161
|
-
file.note = note;
|
|
3162
|
-
out.push(file);
|
|
3163
3294
|
}
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
function normalizePlanStepTests(value) {
|
|
3167
|
-
if (!Array.isArray(value))
|
|
3295
|
+
const normalizedFrequency = value.freq.trim().toLowerCase();
|
|
3296
|
+
if (!RECURRENCE_FREQUENCY_VALUES.includes(normalizedFrequency)) {
|
|
3168
3297
|
return void 0;
|
|
3169
|
-
const out = [];
|
|
3170
|
-
for (const entry of value) {
|
|
3171
|
-
if (entry === null || typeof entry !== "object")
|
|
3172
|
-
continue;
|
|
3173
|
-
const record = entry;
|
|
3174
|
-
const command = trimStringOrUndefined(record.command);
|
|
3175
|
-
const path6 = trimStringOrUndefined(record.path);
|
|
3176
|
-
if (!command && !path6)
|
|
3177
|
-
continue;
|
|
3178
|
-
const test = {};
|
|
3179
|
-
if (command)
|
|
3180
|
-
test.command = command;
|
|
3181
|
-
if (path6)
|
|
3182
|
-
test.path = normalizePathValue(path6);
|
|
3183
|
-
const note = trimStringOrUndefined(record.note);
|
|
3184
|
-
if (note)
|
|
3185
|
-
test.note = note;
|
|
3186
|
-
out.push(test);
|
|
3187
3298
|
}
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
const note = trimStringOrUndefined(record.note);
|
|
3205
|
-
if (note)
|
|
3206
|
-
doc.note = note;
|
|
3207
|
-
out.push(doc);
|
|
3299
|
+
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));
|
|
3300
|
+
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);
|
|
3301
|
+
const exdates = Array.from(new Set((value.exdates ?? []).map((timestamp) => timestamp.trim()).filter((timestamp) => isTimestampLiteral(timestamp)))).sort((a, b) => compareTimestampStrings(a, b));
|
|
3302
|
+
const normalized = {
|
|
3303
|
+
freq: normalizedFrequency,
|
|
3304
|
+
interval: value.interval !== void 0 && value.interval > 1 ? value.interval : void 0,
|
|
3305
|
+
count: value.count,
|
|
3306
|
+
until: value.until?.trim() || void 0,
|
|
3307
|
+
by_weekday: byWeekday.length > 0 ? byWeekday : void 0,
|
|
3308
|
+
by_month_day: byMonthDay.length > 0 ? byMonthDay : void 0,
|
|
3309
|
+
exdates: exdates.length > 0 ? exdates : void 0
|
|
3310
|
+
};
|
|
3311
|
+
for (const [key, fieldValue] of Object.entries(normalized)) {
|
|
3312
|
+
if (fieldValue === void 0) {
|
|
3313
|
+
delete normalized[key];
|
|
3314
|
+
}
|
|
3208
3315
|
}
|
|
3209
|
-
return
|
|
3316
|
+
return normalized;
|
|
3210
3317
|
}
|
|
3211
|
-
function
|
|
3212
|
-
if (
|
|
3213
|
-
return void 0;
|
|
3214
|
-
}
|
|
3215
|
-
const record = entry;
|
|
3216
|
-
const id = trimStringOrUndefined(record.id);
|
|
3217
|
-
const title = trimStringOrUndefined(record.title);
|
|
3218
|
-
const statusRaw = trimStringOrUndefined(record.status);
|
|
3219
|
-
const status = statusRaw && PLAN_STEP_STATUS_SET.has(statusRaw) ? statusRaw : void 0;
|
|
3220
|
-
const order = coerceFiniteNumber(record.order) ?? Number.NaN;
|
|
3221
|
-
const created_at = typeof record.created_at === "string" ? record.created_at : "";
|
|
3222
|
-
const updated_at = typeof record.updated_at === "string" ? record.updated_at : "";
|
|
3223
|
-
if (!id || !title || !status || !Number.isFinite(order) || !created_at || !updated_at) {
|
|
3318
|
+
function sortEvents(values) {
|
|
3319
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
3224
3320
|
return void 0;
|
|
3225
3321
|
}
|
|
3226
|
-
const
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3322
|
+
const normalized = [...values].map(normalizeCalendarEvent).sort(compareCalendarEvents);
|
|
3323
|
+
return normalized;
|
|
3324
|
+
}
|
|
3325
|
+
function normalizeCalendarEvent(value) {
|
|
3326
|
+
const event = {
|
|
3327
|
+
start_at: value.start_at,
|
|
3328
|
+
end_at: value.end_at || void 0,
|
|
3329
|
+
title: value.title?.trim() || void 0,
|
|
3330
|
+
description: value.description?.trim() || void 0,
|
|
3331
|
+
location: value.location?.trim() || void 0,
|
|
3332
|
+
all_day: value.all_day,
|
|
3333
|
+
timezone: value.timezone?.trim() || void 0,
|
|
3334
|
+
recurrence: normalizeRecurrenceRule(value.recurrence)
|
|
3233
3335
|
};
|
|
3234
|
-
|
|
3235
|
-
return
|
|
3336
|
+
deleteUndefinedFields(event);
|
|
3337
|
+
return event;
|
|
3236
3338
|
}
|
|
3237
|
-
function
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
step[target] = value;
|
|
3249
|
-
}
|
|
3250
|
-
}
|
|
3251
|
-
const completedAt = typeof record.completed_at === "string" ? record.completed_at : void 0;
|
|
3252
|
-
if (completedAt && completedAt.length > 0) {
|
|
3253
|
-
step.completed_at = completedAt;
|
|
3254
|
-
}
|
|
3255
|
-
const collectionFields = [
|
|
3256
|
-
["linked_items", "linked_items", normalizePlanStepLinks],
|
|
3257
|
-
["files", "files", normalizePlanStepFiles],
|
|
3258
|
-
["tests", "tests", normalizePlanStepTests],
|
|
3259
|
-
["docs", "docs", normalizePlanStepDocs]
|
|
3260
|
-
];
|
|
3261
|
-
for (const [target, source, normalize] of collectionFields) {
|
|
3262
|
-
const value = normalize(record[source]);
|
|
3263
|
-
if (value) {
|
|
3264
|
-
step[target] = value;
|
|
3265
|
-
}
|
|
3266
|
-
}
|
|
3339
|
+
function compareCalendarEvents(a, b) {
|
|
3340
|
+
return firstNonZeroComparison([
|
|
3341
|
+
compareTimestampStrings(a.start_at, b.start_at),
|
|
3342
|
+
(a.end_at ?? "").localeCompare(b.end_at ?? ""),
|
|
3343
|
+
(a.title ?? "").localeCompare(b.title ?? ""),
|
|
3344
|
+
Number(Boolean(a.all_day)) - Number(Boolean(b.all_day)),
|
|
3345
|
+
(a.timezone ?? "").localeCompare(b.timezone ?? ""),
|
|
3346
|
+
(a.location ?? "").localeCompare(b.location ?? ""),
|
|
3347
|
+
(a.description ?? "").localeCompare(b.description ?? ""),
|
|
3348
|
+
JSON.stringify(a.recurrence ?? {}).localeCompare(JSON.stringify(b.recurrence ?? {}))
|
|
3349
|
+
]);
|
|
3267
3350
|
}
|
|
3268
|
-
function
|
|
3269
|
-
if (!
|
|
3351
|
+
function normalizeFiles(values) {
|
|
3352
|
+
if (!values || values.length === 0)
|
|
3270
3353
|
return void 0;
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
return out.length > 0 ? out : void 0;
|
|
3354
|
+
return values.map((value) => ({
|
|
3355
|
+
path: normalizePathValue(value.path),
|
|
3356
|
+
scope: value.scope,
|
|
3357
|
+
note: value.note?.trim() || void 0
|
|
3358
|
+
}));
|
|
3277
3359
|
}
|
|
3278
|
-
function
|
|
3279
|
-
if (!
|
|
3360
|
+
function normalizeTestRunSummaries(values) {
|
|
3361
|
+
if (!values || values.length === 0)
|
|
3280
3362
|
return void 0;
|
|
3281
|
-
const
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
const author = typeof record.author === "string" ? record.author : "";
|
|
3288
|
-
const decision = trimStringOrUndefined(record.decision);
|
|
3289
|
-
if (!ts || !author || !decision)
|
|
3290
|
-
continue;
|
|
3291
|
-
const item = { ts, author, decision };
|
|
3292
|
-
const rationale = trimStringOrUndefined(record.rationale);
|
|
3293
|
-
if (rationale)
|
|
3294
|
-
item.rationale = rationale;
|
|
3295
|
-
const evidence = trimStringOrUndefined(record.evidence);
|
|
3296
|
-
if (evidence)
|
|
3297
|
-
item.evidence = evidence;
|
|
3298
|
-
const stepId = trimStringOrUndefined(record.step_id);
|
|
3299
|
-
if (stepId)
|
|
3300
|
-
item.step_id = stepId;
|
|
3301
|
-
out.push(item);
|
|
3302
|
-
}
|
|
3303
|
-
return out.length > 0 ? out : void 0;
|
|
3363
|
+
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([
|
|
3364
|
+
compareTimestampStrings(a.recorded_at, b.recorded_at),
|
|
3365
|
+
a.run_id.localeCompare(b.run_id),
|
|
3366
|
+
a.kind.localeCompare(b.kind)
|
|
3367
|
+
]));
|
|
3368
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
3304
3369
|
}
|
|
3305
|
-
function
|
|
3306
|
-
|
|
3307
|
-
return void 0;
|
|
3308
|
-
const out = [];
|
|
3309
|
-
for (const entry of value) {
|
|
3310
|
-
if (entry === null || typeof entry !== "object")
|
|
3311
|
-
continue;
|
|
3312
|
-
const record = entry;
|
|
3313
|
-
const ts = typeof record.ts === "string" ? record.ts : "";
|
|
3314
|
-
const author = typeof record.author === "string" ? record.author : "";
|
|
3315
|
-
const text = trimStringOrUndefined(record.text);
|
|
3316
|
-
if (!ts || !author || !text)
|
|
3317
|
-
continue;
|
|
3318
|
-
const item = { ts, author, text };
|
|
3319
|
-
const stepId = trimStringOrUndefined(record.step_id);
|
|
3320
|
-
if (stepId)
|
|
3321
|
-
item.step_id = stepId;
|
|
3322
|
-
out.push(item);
|
|
3323
|
-
}
|
|
3324
|
-
return out.length > 0 ? out : void 0;
|
|
3370
|
+
function normalizeNonNegativeInteger(value) {
|
|
3371
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : void 0;
|
|
3325
3372
|
}
|
|
3326
|
-
function
|
|
3327
|
-
|
|
3328
|
-
return void 0;
|
|
3329
|
-
const out = [];
|
|
3330
|
-
for (const entry of value) {
|
|
3331
|
-
if (entry === null || typeof entry !== "object")
|
|
3332
|
-
continue;
|
|
3333
|
-
const record = entry;
|
|
3334
|
-
const text = trimStringOrUndefined(record.text);
|
|
3335
|
-
if (!text)
|
|
3336
|
-
continue;
|
|
3337
|
-
const item = { text };
|
|
3338
|
-
const command = trimStringOrUndefined(record.command);
|
|
3339
|
-
if (command)
|
|
3340
|
-
item.command = command;
|
|
3341
|
-
const expected = trimStringOrUndefined(record.expected);
|
|
3342
|
-
if (expected)
|
|
3343
|
-
item.expected = expected;
|
|
3344
|
-
out.push(item);
|
|
3345
|
-
}
|
|
3346
|
-
return out.length > 0 ? out : void 0;
|
|
3373
|
+
function normalizePositiveInteger(value) {
|
|
3374
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 1 ? Math.floor(value) : void 0;
|
|
3347
3375
|
}
|
|
3348
|
-
function
|
|
3349
|
-
|
|
3376
|
+
function stringOrEmpty(value) {
|
|
3377
|
+
return typeof value === "string" ? value : "";
|
|
3378
|
+
}
|
|
3379
|
+
function normalizeTestRunSummary(value) {
|
|
3380
|
+
const runId = typeof value.run_id === "string" ? value.run_id.trim() : "";
|
|
3381
|
+
const kind = value.kind === "test" || value.kind === "test-all" ? value.kind : "test";
|
|
3382
|
+
const status = ITEM_TEST_RUN_STATUS_VALUES.has(value.status) ? value.status : "failed";
|
|
3383
|
+
const summary = {
|
|
3384
|
+
run_id: runId,
|
|
3385
|
+
kind,
|
|
3386
|
+
status,
|
|
3387
|
+
started_at: stringOrEmpty(value.started_at),
|
|
3388
|
+
finished_at: stringOrEmpty(value.finished_at),
|
|
3389
|
+
recorded_at: stringOrEmpty(value.recorded_at),
|
|
3390
|
+
attempt: normalizePositiveInteger(value.attempt),
|
|
3391
|
+
resumed_from: value.resumed_from?.trim() || void 0,
|
|
3392
|
+
passed: normalizeNonNegativeInteger(value.passed) ?? 0,
|
|
3393
|
+
failed: normalizeNonNegativeInteger(value.failed) ?? 0,
|
|
3394
|
+
skipped: normalizeNonNegativeInteger(value.skipped) ?? 0,
|
|
3395
|
+
items: normalizeNonNegativeInteger(value.items),
|
|
3396
|
+
linked_tests: normalizeNonNegativeInteger(value.linked_tests),
|
|
3397
|
+
fail_on_skipped_triggered: value.fail_on_skipped_triggered === true ? true : void 0
|
|
3398
|
+
};
|
|
3399
|
+
deleteUndefinedFields(summary);
|
|
3400
|
+
return summary;
|
|
3401
|
+
}
|
|
3402
|
+
function sortTests(values) {
|
|
3403
|
+
if (!Array.isArray(values) || values.length === 0)
|
|
3350
3404
|
return void 0;
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3405
|
+
return [...values].map(normalizeLinkedTest).sort(compareLinkedTests);
|
|
3406
|
+
}
|
|
3407
|
+
function normalizeTrimmedStringList(value) {
|
|
3408
|
+
if (!Array.isArray(value)) {
|
|
3354
3409
|
return void 0;
|
|
3355
3410
|
}
|
|
3356
|
-
|
|
3411
|
+
const normalized = [
|
|
3412
|
+
...new Set(value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter((entry) => entry.length > 0))
|
|
3413
|
+
].sort((a, b) => a.localeCompare(b));
|
|
3414
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
3357
3415
|
}
|
|
3358
|
-
function
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
start += 1;
|
|
3416
|
+
function isPlainObjectRecord(value) {
|
|
3417
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3418
|
+
return false;
|
|
3362
3419
|
}
|
|
3363
|
-
|
|
3420
|
+
const prototype = Object.getPrototypeOf(value);
|
|
3421
|
+
return prototype === Object.prototype || prototype === null;
|
|
3364
3422
|
}
|
|
3365
|
-
function
|
|
3366
|
-
|
|
3423
|
+
function isUnsafeObjectKey(key) {
|
|
3424
|
+
return key === "__proto__" || key === "constructor" || key === "prototype";
|
|
3425
|
+
}
|
|
3426
|
+
function normalizeStringRecord(value) {
|
|
3427
|
+
if (!isPlainObjectRecord(value)) {
|
|
3367
3428
|
return void 0;
|
|
3368
3429
|
}
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
}
|
|
3372
|
-
const normalized = value.trim().toLowerCase();
|
|
3373
|
-
if (normalized === "med") {
|
|
3374
|
-
return "medium";
|
|
3375
|
-
}
|
|
3376
|
-
if (CONFIDENCE_TEXT_VALUES.includes(normalized)) {
|
|
3377
|
-
return normalized;
|
|
3378
|
-
}
|
|
3379
|
-
return void 0;
|
|
3430
|
+
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));
|
|
3431
|
+
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
3380
3432
|
}
|
|
3381
|
-
function
|
|
3382
|
-
if (value
|
|
3433
|
+
function normalizeNumericRecord(value) {
|
|
3434
|
+
if (!isPlainObjectRecord(value)) {
|
|
3383
3435
|
return void 0;
|
|
3384
3436
|
}
|
|
3385
|
-
const
|
|
3386
|
-
|
|
3387
|
-
return "medium";
|
|
3388
|
-
}
|
|
3389
|
-
if (ISSUE_SEVERITY_VALUES.includes(normalized)) {
|
|
3390
|
-
return normalized;
|
|
3391
|
-
}
|
|
3392
|
-
return void 0;
|
|
3393
|
-
}
|
|
3394
|
-
function emptyStringToUndefined(value) {
|
|
3395
|
-
return value || void 0;
|
|
3437
|
+
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));
|
|
3438
|
+
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
3396
3439
|
}
|
|
3397
|
-
function
|
|
3398
|
-
const
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
if (isUnsafeObjectKey(key) || Object.prototype.hasOwnProperty.call(targetRecord, key) || value === void 0) {
|
|
3402
|
-
continue;
|
|
3403
|
-
}
|
|
3404
|
-
targetRecord[key] = value;
|
|
3440
|
+
function normalizeLinkedTestContextMode(value) {
|
|
3441
|
+
const normalized = value?.trim().toLowerCase();
|
|
3442
|
+
if (!normalized || !LINKED_TEST_PM_CONTEXT_MODE_VALUES.has(normalized)) {
|
|
3443
|
+
return void 0;
|
|
3405
3444
|
}
|
|
3445
|
+
return normalized;
|
|
3406
3446
|
}
|
|
3407
|
-
function
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3447
|
+
function normalizeLinkedTest(value) {
|
|
3448
|
+
const test = {
|
|
3449
|
+
command: value.command?.trim() || void 0,
|
|
3450
|
+
path: value.path ? normalizePathValue(value.path) : void 0,
|
|
3451
|
+
scope: value.scope,
|
|
3452
|
+
timeout_seconds: typeof value.timeout_seconds === "number" && Number.isFinite(value.timeout_seconds) && value.timeout_seconds > 0 ? value.timeout_seconds : void 0,
|
|
3453
|
+
pm_context_mode: normalizeLinkedTestContextMode(value.pm_context_mode),
|
|
3454
|
+
env_set: normalizeStringRecord(value.env_set),
|
|
3455
|
+
env_clear: normalizeTrimmedStringList(value.env_clear),
|
|
3456
|
+
shared_host_safe: value.shared_host_safe === true ? true : void 0,
|
|
3457
|
+
assert_stdout_contains: normalizeTrimmedStringList(value.assert_stdout_contains),
|
|
3458
|
+
assert_stdout_regex: normalizeTrimmedStringList(value.assert_stdout_regex),
|
|
3459
|
+
assert_stderr_contains: normalizeTrimmedStringList(value.assert_stderr_contains),
|
|
3460
|
+
assert_stderr_regex: normalizeTrimmedStringList(value.assert_stderr_regex),
|
|
3461
|
+
assert_stdout_min_lines: normalizeNonNegativeInteger(value.assert_stdout_min_lines),
|
|
3462
|
+
assert_json_field_equals: normalizeStringRecord(value.assert_json_field_equals),
|
|
3463
|
+
assert_json_field_gte: normalizeNumericRecord(value.assert_json_field_gte),
|
|
3464
|
+
note: value.note?.trim() || void 0
|
|
3465
|
+
};
|
|
3466
|
+
deleteUndefinedFields(test);
|
|
3467
|
+
return test;
|
|
3468
|
+
}
|
|
3469
|
+
function compareLinkedTests(a, b) {
|
|
3470
|
+
return firstNonZeroComparison([
|
|
3471
|
+
a.scope.localeCompare(b.scope),
|
|
3472
|
+
compareOptionalStrings(a.path, b.path),
|
|
3473
|
+
compareOptionalStrings(a.command, b.command),
|
|
3474
|
+
compareOptionalNumbers(a.timeout_seconds, b.timeout_seconds),
|
|
3475
|
+
compareOptionalStrings(a.pm_context_mode, b.pm_context_mode),
|
|
3476
|
+
Number(Boolean(a.shared_host_safe)) - Number(Boolean(b.shared_host_safe)),
|
|
3477
|
+
compareJsonValues(a.env_clear, b.env_clear, []),
|
|
3478
|
+
compareJsonValues(a.env_set, b.env_set, {}),
|
|
3479
|
+
compareJsonValues(a.assert_stdout_contains, b.assert_stdout_contains, []),
|
|
3480
|
+
compareJsonValues(a.assert_stdout_regex, b.assert_stdout_regex, []),
|
|
3481
|
+
compareJsonValues(a.assert_stderr_contains, b.assert_stderr_contains, []),
|
|
3482
|
+
compareJsonValues(a.assert_stderr_regex, b.assert_stderr_regex, []),
|
|
3483
|
+
compareOptionalNumbers(a.assert_stdout_min_lines, b.assert_stdout_min_lines),
|
|
3484
|
+
compareJsonValues(a.assert_json_field_equals, b.assert_json_field_equals, {}),
|
|
3485
|
+
compareJsonValues(a.assert_json_field_gte, b.assert_json_field_gte, {}),
|
|
3486
|
+
compareOptionalStrings(a.note, b.note)
|
|
3487
|
+
]);
|
|
3488
|
+
}
|
|
3489
|
+
function compareOptionalStrings(left, right) {
|
|
3490
|
+
return (left ?? "").localeCompare(right ?? "");
|
|
3491
|
+
}
|
|
3492
|
+
function compareOptionalNumbers(left, right) {
|
|
3493
|
+
return (left ?? 0) - (right ?? 0);
|
|
3494
|
+
}
|
|
3495
|
+
function compareJsonValues(left, right, fallback) {
|
|
3496
|
+
return JSON.stringify(left ?? fallback).localeCompare(JSON.stringify(right ?? fallback));
|
|
3497
|
+
}
|
|
3498
|
+
function sortDocs(values) {
|
|
3499
|
+
if (!values || values.length === 0)
|
|
3500
|
+
return void 0;
|
|
3501
|
+
return [...values].map((value) => ({
|
|
3502
|
+
path: normalizePathValue(value.path),
|
|
3503
|
+
scope: value.scope,
|
|
3504
|
+
note: value.note?.trim() || void 0
|
|
3505
|
+
})).sort((a, b) => {
|
|
3506
|
+
const byScope = a.scope.localeCompare(b.scope);
|
|
3507
|
+
if (byScope !== 0)
|
|
3508
|
+
return byScope;
|
|
3509
|
+
const byPath = a.path.localeCompare(b.path);
|
|
3510
|
+
if (byPath !== 0)
|
|
3511
|
+
return byPath;
|
|
3512
|
+
return (a.note ?? "").localeCompare(b.note ?? "");
|
|
3513
|
+
});
|
|
3514
|
+
}
|
|
3515
|
+
function trimStringOrUndefined(value) {
|
|
3516
|
+
if (typeof value !== "string")
|
|
3517
|
+
return void 0;
|
|
3518
|
+
const trimmed = value.trim();
|
|
3519
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
3520
|
+
}
|
|
3521
|
+
function normalizePlanStepLinks(value) {
|
|
3522
|
+
if (!Array.isArray(value))
|
|
3523
|
+
return void 0;
|
|
3524
|
+
const out = [];
|
|
3525
|
+
for (const entry of value) {
|
|
3526
|
+
if (entry === null || typeof entry !== "object")
|
|
3415
3527
|
continue;
|
|
3416
|
-
|
|
3417
|
-
|
|
3528
|
+
const record = entry;
|
|
3529
|
+
const id = trimStringOrUndefined(record.id);
|
|
3530
|
+
const kind = trimStringOrUndefined(record.kind);
|
|
3531
|
+
if (!id || !kind)
|
|
3532
|
+
continue;
|
|
3533
|
+
const link = { id, kind };
|
|
3534
|
+
const note = trimStringOrUndefined(record.note);
|
|
3535
|
+
if (note)
|
|
3536
|
+
link.note = note;
|
|
3537
|
+
if (record.required_before_step === true)
|
|
3538
|
+
link.required_before_step = true;
|
|
3539
|
+
out.push(link);
|
|
3418
3540
|
}
|
|
3541
|
+
return out.length > 0 ? out : void 0;
|
|
3419
3542
|
}
|
|
3420
|
-
function
|
|
3421
|
-
if (!
|
|
3422
|
-
return;
|
|
3423
|
-
|
|
3424
|
-
const
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3543
|
+
function normalizePlanStepFiles(value) {
|
|
3544
|
+
if (!Array.isArray(value))
|
|
3545
|
+
return void 0;
|
|
3546
|
+
const out = [];
|
|
3547
|
+
for (const entry of value) {
|
|
3548
|
+
if (entry === null || typeof entry !== "object")
|
|
3549
|
+
continue;
|
|
3550
|
+
const record = entry;
|
|
3551
|
+
const path6 = trimStringOrUndefined(record.path);
|
|
3552
|
+
if (!path6)
|
|
3553
|
+
continue;
|
|
3554
|
+
const file = { path: normalizePathValue(path6) };
|
|
3555
|
+
if (record.scope === "project" || record.scope === "global")
|
|
3556
|
+
file.scope = record.scope;
|
|
3557
|
+
const note = trimStringOrUndefined(record.note);
|
|
3558
|
+
if (note)
|
|
3559
|
+
file.note = note;
|
|
3560
|
+
out.push(file);
|
|
3432
3561
|
}
|
|
3562
|
+
return out.length > 0 ? out : void 0;
|
|
3433
3563
|
}
|
|
3434
|
-
function
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
const
|
|
3438
|
-
const
|
|
3439
|
-
|
|
3440
|
-
title: itemMetadata.title,
|
|
3441
|
-
description: itemMetadata.description,
|
|
3442
|
-
type: itemMetadata.type,
|
|
3443
|
-
pm_format_version: normalizeItemFormatVersion(itemMetadata.pm_format_version),
|
|
3444
|
-
source_type: trimStringOrUndefined(itemMetadata.source_type),
|
|
3445
|
-
type_options: normalizeTypeOptions(itemMetadata.type_options),
|
|
3446
|
-
status: normalizedStatus,
|
|
3447
|
-
priority: itemMetadata.priority,
|
|
3448
|
-
tags,
|
|
3449
|
-
created_at: itemMetadata.created_at,
|
|
3450
|
-
updated_at: itemMetadata.updated_at,
|
|
3451
|
-
dependencies: sortDependencies(itemMetadata.dependencies),
|
|
3452
|
-
comments: sortLogValues(itemMetadata.comments),
|
|
3453
|
-
notes: sortLogValues(itemMetadata.notes),
|
|
3454
|
-
learnings: sortLogValues(itemMetadata.learnings),
|
|
3455
|
-
files: normalizeFiles(itemMetadata.files),
|
|
3456
|
-
tests: sortTests(itemMetadata.tests),
|
|
3457
|
-
test_runs: normalizeTestRunSummaries(itemMetadata.test_runs),
|
|
3458
|
-
docs: sortDocs(itemMetadata.docs),
|
|
3459
|
-
deadline: emptyStringToUndefined(itemMetadata.deadline),
|
|
3460
|
-
reminders: sortReminders(itemMetadata.reminders),
|
|
3461
|
-
events: sortEvents(itemMetadata.events),
|
|
3462
|
-
closed_at: emptyStringToUndefined(itemMetadata.closed_at),
|
|
3463
|
-
assignee: trimStringOrUndefined(itemMetadata.assignee),
|
|
3464
|
-
source_owner: trimStringOrUndefined(itemMetadata.source_owner),
|
|
3465
|
-
author: emptyStringToUndefined(itemMetadata.author),
|
|
3466
|
-
estimated_minutes: itemMetadata.estimated_minutes,
|
|
3467
|
-
acceptance_criteria: itemMetadata.acceptance_criteria ?? void 0,
|
|
3468
|
-
design: itemMetadata.design ?? void 0,
|
|
3469
|
-
external_ref: itemMetadata.external_ref ?? void 0,
|
|
3470
|
-
definition_of_ready: trimStringOrUndefined(itemMetadata.definition_of_ready),
|
|
3471
|
-
order: itemMetadata.order,
|
|
3472
|
-
goal: trimStringOrUndefined(itemMetadata.goal),
|
|
3473
|
-
objective: trimStringOrUndefined(itemMetadata.objective),
|
|
3474
|
-
value: trimStringOrUndefined(itemMetadata.value),
|
|
3475
|
-
impact: trimStringOrUndefined(itemMetadata.impact),
|
|
3476
|
-
outcome: trimStringOrUndefined(itemMetadata.outcome),
|
|
3477
|
-
why_now: trimStringOrUndefined(itemMetadata.why_now),
|
|
3478
|
-
parent: trimStringOrUndefined(itemMetadata.parent),
|
|
3479
|
-
reviewer: trimStringOrUndefined(itemMetadata.reviewer),
|
|
3480
|
-
risk: itemMetadata.risk ?? void 0,
|
|
3481
|
-
confidence: normalizeConfidenceValue(itemMetadata.confidence),
|
|
3482
|
-
sprint: trimStringOrUndefined(itemMetadata.sprint),
|
|
3483
|
-
release: trimStringOrUndefined(itemMetadata.release),
|
|
3484
|
-
blocked_by: trimStringOrUndefined(itemMetadata.blocked_by),
|
|
3485
|
-
blocked_reason: trimStringOrUndefined(itemMetadata.blocked_reason),
|
|
3486
|
-
unblock_note: trimStringOrUndefined(itemMetadata.unblock_note),
|
|
3487
|
-
reporter: trimStringOrUndefined(itemMetadata.reporter),
|
|
3488
|
-
severity: normalizeSeverityValue(itemMetadata.severity),
|
|
3489
|
-
environment: trimStringOrUndefined(itemMetadata.environment),
|
|
3490
|
-
repro_steps: trimStringOrUndefined(itemMetadata.repro_steps),
|
|
3491
|
-
resolution: trimStringOrUndefined(itemMetadata.resolution),
|
|
3492
|
-
expected_result: trimStringOrUndefined(itemMetadata.expected_result),
|
|
3493
|
-
actual_result: trimStringOrUndefined(itemMetadata.actual_result),
|
|
3494
|
-
affected_version: trimStringOrUndefined(itemMetadata.affected_version),
|
|
3495
|
-
fixed_version: trimStringOrUndefined(itemMetadata.fixed_version),
|
|
3496
|
-
component: trimStringOrUndefined(itemMetadata.component),
|
|
3497
|
-
regression: itemMetadata.regression,
|
|
3498
|
-
customer_impact: trimStringOrUndefined(itemMetadata.customer_impact),
|
|
3499
|
-
close_reason: emptyStringToUndefined(itemMetadata.close_reason),
|
|
3500
|
-
plan_mode: trimStringOrUndefined(itemMetadata.plan_mode),
|
|
3501
|
-
plan_scope: trimStringOrUndefined(itemMetadata.plan_scope),
|
|
3502
|
-
plan_harness: trimStringOrUndefined(itemMetadata.plan_harness),
|
|
3503
|
-
plan_resume_context: trimStringOrUndefined(itemMetadata.plan_resume_context),
|
|
3504
|
-
plan_steps: normalizePlanSteps(itemMetadata.plan_steps),
|
|
3505
|
-
plan_decisions: normalizePlanDecisions(itemMetadata.plan_decisions),
|
|
3506
|
-
plan_discoveries: normalizePlanDiscoveries(itemMetadata.plan_discoveries),
|
|
3507
|
-
plan_validation: normalizePlanValidation(itemMetadata.plan_validation)
|
|
3508
|
-
};
|
|
3509
|
-
copyExtensionItemMetadataFields(normalized, itemMetadata);
|
|
3510
|
-
coerceNormalizedRuntimeFields(normalized, runtimeContext);
|
|
3511
|
-
assertNormalizedUnknownFields(normalized, runtimeContext);
|
|
3512
|
-
deleteUndefinedFields(normalized);
|
|
3513
|
-
return normalized;
|
|
3514
|
-
}
|
|
3515
|
-
function orderItemMetadata(itemMetadata) {
|
|
3516
|
-
return orderObject(itemMetadata, ITEM_METADATA_KEY_ORDER);
|
|
3517
|
-
}
|
|
3518
|
-
function findJsonObjectEnd(content) {
|
|
3519
|
-
let depth = 0;
|
|
3520
|
-
let inString = false;
|
|
3521
|
-
let escaped = false;
|
|
3522
|
-
for (let i = 0; i < content.length; i += 1) {
|
|
3523
|
-
const char = content[i];
|
|
3524
|
-
if (inString) {
|
|
3525
|
-
if (escaped) {
|
|
3526
|
-
escaped = false;
|
|
3527
|
-
continue;
|
|
3528
|
-
}
|
|
3529
|
-
if (char === "\\") {
|
|
3530
|
-
escaped = true;
|
|
3531
|
-
continue;
|
|
3532
|
-
}
|
|
3533
|
-
if (char === '"') {
|
|
3534
|
-
inString = false;
|
|
3535
|
-
}
|
|
3564
|
+
function normalizePlanStepTests(value) {
|
|
3565
|
+
if (!Array.isArray(value))
|
|
3566
|
+
return void 0;
|
|
3567
|
+
const out = [];
|
|
3568
|
+
for (const entry of value) {
|
|
3569
|
+
if (entry === null || typeof entry !== "object")
|
|
3536
3570
|
continue;
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3571
|
+
const record = entry;
|
|
3572
|
+
const command = trimStringOrUndefined(record.command);
|
|
3573
|
+
const path6 = trimStringOrUndefined(record.path);
|
|
3574
|
+
if (!command && !path6)
|
|
3575
|
+
continue;
|
|
3576
|
+
const test = {};
|
|
3577
|
+
if (command)
|
|
3578
|
+
test.command = command;
|
|
3579
|
+
if (path6)
|
|
3580
|
+
test.path = normalizePathValue(path6);
|
|
3581
|
+
const note = trimStringOrUndefined(record.note);
|
|
3582
|
+
if (note)
|
|
3583
|
+
test.note = note;
|
|
3584
|
+
out.push(test);
|
|
3585
|
+
}
|
|
3586
|
+
return out.length > 0 ? out : void 0;
|
|
3587
|
+
}
|
|
3588
|
+
function normalizePlanStepDocs(value) {
|
|
3589
|
+
if (!Array.isArray(value))
|
|
3590
|
+
return void 0;
|
|
3591
|
+
const out = [];
|
|
3592
|
+
for (const entry of value) {
|
|
3593
|
+
if (entry === null || typeof entry !== "object")
|
|
3540
3594
|
continue;
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3595
|
+
const record = entry;
|
|
3596
|
+
const path6 = trimStringOrUndefined(record.path);
|
|
3597
|
+
if (!path6)
|
|
3544
3598
|
continue;
|
|
3545
|
-
}
|
|
3546
|
-
if (
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3599
|
+
const doc = { path: normalizePathValue(path6) };
|
|
3600
|
+
if (record.scope === "project" || record.scope === "global")
|
|
3601
|
+
doc.scope = record.scope;
|
|
3602
|
+
const note = trimStringOrUndefined(record.note);
|
|
3603
|
+
if (note)
|
|
3604
|
+
doc.note = note;
|
|
3605
|
+
out.push(doc);
|
|
3552
3606
|
}
|
|
3553
|
-
return
|
|
3607
|
+
return out.length > 0 ? out : void 0;
|
|
3554
3608
|
}
|
|
3555
|
-
function
|
|
3556
|
-
if (
|
|
3557
|
-
return
|
|
3609
|
+
function normalizePlanStepEntry(entry) {
|
|
3610
|
+
if (entry === null || typeof entry !== "object") {
|
|
3611
|
+
return void 0;
|
|
3558
3612
|
}
|
|
3559
|
-
const
|
|
3560
|
-
|
|
3561
|
-
|
|
3613
|
+
const record = entry;
|
|
3614
|
+
const id = trimStringOrUndefined(record.id);
|
|
3615
|
+
const title = trimStringOrUndefined(record.title);
|
|
3616
|
+
const statusRaw = trimStringOrUndefined(record.status);
|
|
3617
|
+
const status = statusRaw && PLAN_STEP_STATUS_SET.has(statusRaw) ? statusRaw : void 0;
|
|
3618
|
+
const order = coerceFiniteNumber(record.order) ?? Number.NaN;
|
|
3619
|
+
const created_at = typeof record.created_at === "string" ? record.created_at : "";
|
|
3620
|
+
const updated_at = typeof record.updated_at === "string" ? record.updated_at : "";
|
|
3621
|
+
if (!id || !title || !status || !Number.isFinite(order) || !created_at || !updated_at) {
|
|
3622
|
+
return void 0;
|
|
3562
3623
|
}
|
|
3563
|
-
const
|
|
3564
|
-
|
|
3565
|
-
|
|
3624
|
+
const step = {
|
|
3625
|
+
id,
|
|
3626
|
+
order,
|
|
3627
|
+
title,
|
|
3628
|
+
status,
|
|
3629
|
+
created_at,
|
|
3630
|
+
updated_at
|
|
3631
|
+
};
|
|
3632
|
+
applyPlanStepOptionalFields(step, record);
|
|
3633
|
+
return step;
|
|
3566
3634
|
}
|
|
3567
|
-
function
|
|
3568
|
-
const
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
const
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
if (line.trim() === "---") {
|
|
3580
|
-
return {
|
|
3581
|
-
content: normalizedContent.slice(afterLine).replace(/^\s+/, ""),
|
|
3582
|
-
stripped: true
|
|
3583
|
-
};
|
|
3635
|
+
function applyPlanStepOptionalFields(step, record) {
|
|
3636
|
+
const stringFields = [
|
|
3637
|
+
["body", "body"],
|
|
3638
|
+
["owner", "owner"],
|
|
3639
|
+
["evidence", "evidence"],
|
|
3640
|
+
["blocked_reason", "blocked_reason"],
|
|
3641
|
+
["superseded_by", "superseded_by"]
|
|
3642
|
+
];
|
|
3643
|
+
for (const [target, source] of stringFields) {
|
|
3644
|
+
const value = trimStringOrUndefined(record[source]);
|
|
3645
|
+
if (value) {
|
|
3646
|
+
step[target] = value;
|
|
3584
3647
|
}
|
|
3585
|
-
cursor = afterLine;
|
|
3586
3648
|
}
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
return normalizeItemMetadata(itemMetadata, {
|
|
3591
|
-
...options,
|
|
3592
|
-
onWarning: void 0
|
|
3593
|
-
});
|
|
3594
|
-
}
|
|
3595
|
-
function parseJsonMarkdownItemDocument(content, runtimeContext, options = {}) {
|
|
3596
|
-
const normalized = stripLeadingYamlDocument(content);
|
|
3597
|
-
if (normalized.stripped) {
|
|
3598
|
-
options.onWarning?.("json_markdown_leading_yaml_frontmatter_ignored");
|
|
3649
|
+
const completedAt = typeof record.completed_at === "string" ? record.completed_at : void 0;
|
|
3650
|
+
if (completedAt && completedAt.length > 0) {
|
|
3651
|
+
step.completed_at = completedAt;
|
|
3599
3652
|
}
|
|
3600
|
-
const
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3653
|
+
const collectionFields = [
|
|
3654
|
+
["linked_items", "linked_items", normalizePlanStepLinks],
|
|
3655
|
+
["files", "files", normalizePlanStepFiles],
|
|
3656
|
+
["tests", "tests", normalizePlanStepTests],
|
|
3657
|
+
["docs", "docs", normalizePlanStepDocs]
|
|
3658
|
+
];
|
|
3659
|
+
for (const [target, source, normalize] of collectionFields) {
|
|
3660
|
+
const value = normalize(record[source]);
|
|
3661
|
+
if (value) {
|
|
3662
|
+
step[target] = value;
|
|
3605
3663
|
}
|
|
3606
|
-
validationError("missing JSON front matter");
|
|
3607
|
-
}
|
|
3608
|
-
let parsed;
|
|
3609
|
-
try {
|
|
3610
|
-
parsed = JSON.parse(frontMatter);
|
|
3611
|
-
} catch {
|
|
3612
|
-
validationError("JSON front matter is not valid JSON");
|
|
3613
3664
|
}
|
|
3614
|
-
assertValidItemMetadata(parsed, runtimeContext);
|
|
3615
|
-
return {
|
|
3616
|
-
metadata: normalizeParsedItemMetadata(parsed, options),
|
|
3617
|
-
body: normalizeBody(body)
|
|
3618
|
-
};
|
|
3619
3665
|
}
|
|
3620
|
-
function
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
}
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
if (Object.prototype.hasOwnProperty.call(record, "front_matter")) {
|
|
3630
|
-
assertValidItemMetadata(record.front_matter, runtimeContext);
|
|
3631
|
-
assertItemMetadataCondition(record.body === void 0 || typeof record.body === "string", "TOON item document body must be a string");
|
|
3632
|
-
return {
|
|
3633
|
-
metadata: normalizeParsedItemMetadata(record.front_matter, options),
|
|
3634
|
-
body: normalizeBody(typeof record.body === "string" ? record.body : "")
|
|
3635
|
-
};
|
|
3636
|
-
}
|
|
3637
|
-
const { body, ...itemMetadataRecord } = record;
|
|
3638
|
-
assertItemMetadataCondition(body === void 0 || typeof body === "string", "TOON item document body must be a string");
|
|
3639
|
-
assertValidItemMetadata(itemMetadataRecord, runtimeContext);
|
|
3640
|
-
return {
|
|
3641
|
-
metadata: normalizeParsedItemMetadata(itemMetadataRecord, options),
|
|
3642
|
-
body: normalizeBody(typeof body === "string" ? body : "")
|
|
3643
|
-
};
|
|
3666
|
+
function normalizePlanSteps(value) {
|
|
3667
|
+
if (!Array.isArray(value))
|
|
3668
|
+
return void 0;
|
|
3669
|
+
const out = value.flatMap((entry) => {
|
|
3670
|
+
const step = normalizePlanStepEntry(entry);
|
|
3671
|
+
return step ? [step] : [];
|
|
3672
|
+
});
|
|
3673
|
+
out.sort((left, right) => left.order - right.order);
|
|
3674
|
+
return out.length > 0 ? out : void 0;
|
|
3644
3675
|
}
|
|
3645
|
-
function
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
const
|
|
3649
|
-
const
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3676
|
+
function normalizePlanDecisions(value) {
|
|
3677
|
+
if (!Array.isArray(value))
|
|
3678
|
+
return void 0;
|
|
3679
|
+
const out = [];
|
|
3680
|
+
for (const entry of value) {
|
|
3681
|
+
if (entry === null || typeof entry !== "object")
|
|
3682
|
+
continue;
|
|
3683
|
+
const record = entry;
|
|
3684
|
+
const ts = typeof record.ts === "string" ? record.ts : "";
|
|
3685
|
+
const author = typeof record.author === "string" ? record.author : "";
|
|
3686
|
+
const decision = trimStringOrUndefined(record.decision);
|
|
3687
|
+
if (!ts || !author || !decision)
|
|
3688
|
+
continue;
|
|
3689
|
+
const item = { ts, author, decision };
|
|
3690
|
+
const rationale = trimStringOrUndefined(record.rationale);
|
|
3691
|
+
if (rationale)
|
|
3692
|
+
item.rationale = rationale;
|
|
3693
|
+
const evidence = trimStringOrUndefined(record.evidence);
|
|
3694
|
+
if (evidence)
|
|
3695
|
+
item.evidence = evidence;
|
|
3696
|
+
const stepId = trimStringOrUndefined(record.step_id);
|
|
3697
|
+
if (stepId)
|
|
3698
|
+
item.step_id = stepId;
|
|
3699
|
+
out.push(item);
|
|
3653
3700
|
}
|
|
3654
|
-
return
|
|
3655
|
-
|
|
3656
|
-
${normalizedBody}
|
|
3657
|
-
`;
|
|
3701
|
+
return out.length > 0 ? out : void 0;
|
|
3658
3702
|
}
|
|
3659
|
-
function
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
const
|
|
3663
|
-
|
|
3664
|
-
|
|
3703
|
+
function normalizePlanDiscoveries(value) {
|
|
3704
|
+
if (!Array.isArray(value))
|
|
3705
|
+
return void 0;
|
|
3706
|
+
const out = [];
|
|
3707
|
+
for (const entry of value) {
|
|
3708
|
+
if (entry === null || typeof entry !== "object")
|
|
3709
|
+
continue;
|
|
3710
|
+
const record = entry;
|
|
3711
|
+
const ts = typeof record.ts === "string" ? record.ts : "";
|
|
3712
|
+
const author = typeof record.author === "string" ? record.author : "";
|
|
3713
|
+
const text = trimStringOrUndefined(record.text);
|
|
3714
|
+
if (!ts || !author || !text)
|
|
3715
|
+
continue;
|
|
3716
|
+
const item = { ts, author, text };
|
|
3717
|
+
const stepId = trimStringOrUndefined(record.step_id);
|
|
3718
|
+
if (stepId)
|
|
3719
|
+
item.step_id = stepId;
|
|
3720
|
+
out.push(item);
|
|
3721
|
+
}
|
|
3722
|
+
return out.length > 0 ? out : void 0;
|
|
3665
3723
|
}
|
|
3666
|
-
function
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
}
|
|
3724
|
+
function normalizePlanValidation(value) {
|
|
3725
|
+
if (!Array.isArray(value))
|
|
3726
|
+
return void 0;
|
|
3727
|
+
const out = [];
|
|
3728
|
+
for (const entry of value) {
|
|
3729
|
+
if (entry === null || typeof entry !== "object")
|
|
3730
|
+
continue;
|
|
3731
|
+
const record = entry;
|
|
3732
|
+
const text = trimStringOrUndefined(record.text);
|
|
3733
|
+
if (!text)
|
|
3734
|
+
continue;
|
|
3735
|
+
const item = { text };
|
|
3736
|
+
const command = trimStringOrUndefined(record.command);
|
|
3737
|
+
if (command)
|
|
3738
|
+
item.command = command;
|
|
3739
|
+
const expected = trimStringOrUndefined(record.expected);
|
|
3740
|
+
if (expected)
|
|
3741
|
+
item.expected = expected;
|
|
3742
|
+
out.push(item);
|
|
3678
3743
|
}
|
|
3679
|
-
|
|
3680
|
-
const runtimeContext = resolveRuntimeSchemaValidationContext(options);
|
|
3681
|
-
return format === "toon" ? parseToonItemDocument(content, runtimeContext, options) : parseJsonMarkdownItemDocument(content, runtimeContext, options);
|
|
3682
|
-
}
|
|
3683
|
-
function serializeItemDocument(document, options = {}) {
|
|
3684
|
-
const format = options.format ?? "toon";
|
|
3685
|
-
return format === "toon" ? serializeToonItemDocument(document, options) : serializeJsonMarkdownItemDocument(document, options);
|
|
3744
|
+
return out.length > 0 ? out : void 0;
|
|
3686
3745
|
}
|
|
3687
|
-
function
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3746
|
+
function normalizeTypeOptions(values) {
|
|
3747
|
+
if (!values) {
|
|
3748
|
+
return void 0;
|
|
3749
|
+
}
|
|
3750
|
+
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]));
|
|
3751
|
+
if (normalizedEntries.length === 0) {
|
|
3752
|
+
return void 0;
|
|
3753
|
+
}
|
|
3754
|
+
return Object.fromEntries(normalizedEntries);
|
|
3692
3755
|
}
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3756
|
+
function normalizeBody(body) {
|
|
3757
|
+
let start = 0;
|
|
3758
|
+
while (start < body.length && body[start] === "\n") {
|
|
3759
|
+
start += 1;
|
|
3760
|
+
}
|
|
3761
|
+
return body.slice(start).trimEnd();
|
|
3697
3762
|
}
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
var EMPTY_LEGACY_HASH_DOCUMENT = {
|
|
3702
|
-
front_matter: {},
|
|
3703
|
-
body: ""
|
|
3704
|
-
};
|
|
3705
|
-
function decodeJsonPointer(path6) {
|
|
3706
|
-
if (!path6 || path6 === "/") {
|
|
3707
|
-
return [];
|
|
3763
|
+
function normalizeConfidenceValue(value) {
|
|
3764
|
+
if (value === void 0) {
|
|
3765
|
+
return void 0;
|
|
3708
3766
|
}
|
|
3709
|
-
if (
|
|
3710
|
-
return
|
|
3767
|
+
if (typeof value === "number") {
|
|
3768
|
+
return value;
|
|
3711
3769
|
}
|
|
3712
|
-
|
|
3770
|
+
const normalized = value.trim().toLowerCase();
|
|
3771
|
+
if (normalized === "med") {
|
|
3772
|
+
return "medium";
|
|
3773
|
+
}
|
|
3774
|
+
if (CONFIDENCE_TEXT_VALUES.includes(normalized)) {
|
|
3775
|
+
return normalized;
|
|
3776
|
+
}
|
|
3777
|
+
return void 0;
|
|
3713
3778
|
}
|
|
3714
|
-
function
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
return true;
|
|
3779
|
+
function normalizeSeverityValue(value) {
|
|
3780
|
+
if (value === void 0) {
|
|
3781
|
+
return void 0;
|
|
3718
3782
|
}
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3783
|
+
const normalized = value.trim().toLowerCase();
|
|
3784
|
+
if (normalized === "med") {
|
|
3785
|
+
return "medium";
|
|
3786
|
+
}
|
|
3787
|
+
if (ISSUE_SEVERITY_VALUES.includes(normalized)) {
|
|
3788
|
+
return normalized;
|
|
3789
|
+
}
|
|
3790
|
+
return void 0;
|
|
3791
|
+
}
|
|
3792
|
+
function emptyStringToUndefined(value) {
|
|
3793
|
+
return value || void 0;
|
|
3794
|
+
}
|
|
3795
|
+
function copyExtensionItemMetadataFields(normalized, source) {
|
|
3796
|
+
const targetRecord = normalized;
|
|
3797
|
+
const sourceRecord = source;
|
|
3798
|
+
for (const [key, value] of Object.entries(sourceRecord)) {
|
|
3799
|
+
if (isUnsafeObjectKey(key) || Object.prototype.hasOwnProperty.call(targetRecord, key) || value === void 0) {
|
|
3734
3800
|
continue;
|
|
3735
3801
|
}
|
|
3736
|
-
|
|
3737
|
-
return false;
|
|
3738
|
-
}
|
|
3739
|
-
if (!Object.prototype.hasOwnProperty.call(cursor, segment)) {
|
|
3740
|
-
return false;
|
|
3741
|
-
}
|
|
3742
|
-
const next = cursor[segment];
|
|
3743
|
-
if (next === void 0) {
|
|
3744
|
-
return false;
|
|
3745
|
-
}
|
|
3746
|
-
cursor = next;
|
|
3802
|
+
targetRecord[key] = value;
|
|
3747
3803
|
}
|
|
3748
|
-
return true;
|
|
3749
3804
|
}
|
|
3750
|
-
function
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
for (const operation of patch) {
|
|
3754
|
-
const normalizedOperation = operation.op === "replace" && !isDefinedPointerPath(replayCursor, operation.path) ? { ...operation, op: "add" } : operation;
|
|
3755
|
-
normalized.push(normalizedOperation);
|
|
3756
|
-
replayCursor = jsonPatch.applyPatch(replayCursor, [normalizedOperation], true, true).newDocument;
|
|
3805
|
+
function coerceNormalizedRuntimeFields(normalized, runtimeContext) {
|
|
3806
|
+
if (!runtimeContext?.fieldRegistry) {
|
|
3807
|
+
return;
|
|
3757
3808
|
}
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
body: document.body ?? ""
|
|
3766
|
-
};
|
|
3809
|
+
const record = normalized;
|
|
3810
|
+
for (const definition of runtimeContext.fieldRegistry.definitions) {
|
|
3811
|
+
const currentValue = record[definition.metadata_key];
|
|
3812
|
+
if (currentValue === void 0) {
|
|
3813
|
+
continue;
|
|
3814
|
+
}
|
|
3815
|
+
record[definition.metadata_key] = coerceRuntimeFieldValue(definition, currentValue, `metadata field "${definition.metadata_key}"`);
|
|
3767
3816
|
}
|
|
3768
|
-
const canonical = canonicalDocument(document);
|
|
3769
|
-
const orderedMetadata = orderObject(toItemRecord(canonical.metadata), ITEM_METADATA_KEY_ORDER);
|
|
3770
|
-
return {
|
|
3771
|
-
front_matter: orderedMetadata,
|
|
3772
|
-
body: canonical.body
|
|
3773
|
-
};
|
|
3774
3817
|
}
|
|
3775
|
-
function
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3818
|
+
function assertNormalizedUnknownFields(normalized, runtimeContext) {
|
|
3819
|
+
if (!runtimeContext || runtimeContext.unknownFieldPolicy === "allow") {
|
|
3820
|
+
return;
|
|
3821
|
+
}
|
|
3822
|
+
const knownKeys = buildKnownItemMetadataKeys(runtimeContext);
|
|
3823
|
+
const record = normalized;
|
|
3824
|
+
const unknownKeys = Object.keys(record).filter((key) => !knownKeys.has(key)).sort((left, right) => left.localeCompare(right));
|
|
3825
|
+
if (unknownKeys.length > 0 && runtimeContext.unknownFieldPolicy === "reject") {
|
|
3826
|
+
validationError(`unknown schema fields are not allowed: ${unknownKeys.join(", ")}`);
|
|
3827
|
+
}
|
|
3828
|
+
if (unknownKeys.length > 0) {
|
|
3829
|
+
runtimeContext.onWarning?.(`item_unknown_schema_fields:${unknownKeys.join(",")}`);
|
|
3782
3830
|
}
|
|
3783
|
-
const canonical = canonicalDocument(document);
|
|
3784
|
-
const orderedMetadata = orderObject(toItemRecord(canonical.metadata), ITEM_METADATA_KEY_ORDER);
|
|
3785
|
-
return {
|
|
3786
|
-
metadata: orderedMetadata,
|
|
3787
|
-
body: canonical.body
|
|
3788
|
-
};
|
|
3789
|
-
}
|
|
3790
|
-
function hashDocument(document) {
|
|
3791
|
-
return sha256Hex(stableStringify(canonicalHashDocument(document)));
|
|
3792
|
-
}
|
|
3793
|
-
function hashEmptyDocument() {
|
|
3794
|
-
return sha256Hex(stableStringify(EMPTY_LEGACY_HASH_DOCUMENT));
|
|
3795
3831
|
}
|
|
3796
|
-
function
|
|
3797
|
-
const
|
|
3798
|
-
const
|
|
3799
|
-
const
|
|
3800
|
-
const
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3832
|
+
function normalizeItemMetadata(itemMetadata, options = {}) {
|
|
3833
|
+
const runtimeContext = resolveRuntimeSchemaValidationContext(options);
|
|
3834
|
+
const normalizedStatus = normalizeStatusInput(itemMetadata.status, runtimeContext?.statusRegistry) ?? itemMetadata.status;
|
|
3835
|
+
const tags = Array.from(new Set(itemMetadata.tags.map((tag) => tag.trim().toLowerCase()).filter(Boolean))).sort((a, b) => a.localeCompare(b));
|
|
3836
|
+
const normalized = {
|
|
3837
|
+
id: itemMetadata.id,
|
|
3838
|
+
title: itemMetadata.title,
|
|
3839
|
+
description: itemMetadata.description,
|
|
3840
|
+
type: itemMetadata.type,
|
|
3841
|
+
pm_format_version: normalizeItemFormatVersion(itemMetadata.pm_format_version),
|
|
3842
|
+
source_type: trimStringOrUndefined(itemMetadata.source_type),
|
|
3843
|
+
type_options: normalizeTypeOptions(itemMetadata.type_options),
|
|
3844
|
+
status: normalizedStatus,
|
|
3845
|
+
priority: itemMetadata.priority,
|
|
3846
|
+
tags,
|
|
3847
|
+
created_at: itemMetadata.created_at,
|
|
3848
|
+
updated_at: itemMetadata.updated_at,
|
|
3849
|
+
dependencies: sortDependencies(itemMetadata.dependencies),
|
|
3850
|
+
comments: sortLogValues(itemMetadata.comments),
|
|
3851
|
+
notes: sortLogValues(itemMetadata.notes),
|
|
3852
|
+
learnings: sortLogValues(itemMetadata.learnings),
|
|
3853
|
+
files: normalizeFiles(itemMetadata.files),
|
|
3854
|
+
tests: sortTests(itemMetadata.tests),
|
|
3855
|
+
test_runs: normalizeTestRunSummaries(itemMetadata.test_runs),
|
|
3856
|
+
docs: sortDocs(itemMetadata.docs),
|
|
3857
|
+
deadline: emptyStringToUndefined(itemMetadata.deadline),
|
|
3858
|
+
reminders: sortReminders(itemMetadata.reminders),
|
|
3859
|
+
events: sortEvents(itemMetadata.events),
|
|
3860
|
+
closed_at: emptyStringToUndefined(itemMetadata.closed_at),
|
|
3861
|
+
assignee: trimStringOrUndefined(itemMetadata.assignee),
|
|
3862
|
+
source_owner: trimStringOrUndefined(itemMetadata.source_owner),
|
|
3863
|
+
author: emptyStringToUndefined(itemMetadata.author),
|
|
3864
|
+
estimated_minutes: itemMetadata.estimated_minutes,
|
|
3865
|
+
acceptance_criteria: itemMetadata.acceptance_criteria ?? void 0,
|
|
3866
|
+
design: itemMetadata.design ?? void 0,
|
|
3867
|
+
external_ref: itemMetadata.external_ref ?? void 0,
|
|
3868
|
+
definition_of_ready: trimStringOrUndefined(itemMetadata.definition_of_ready),
|
|
3869
|
+
order: itemMetadata.order,
|
|
3870
|
+
goal: trimStringOrUndefined(itemMetadata.goal),
|
|
3871
|
+
objective: trimStringOrUndefined(itemMetadata.objective),
|
|
3872
|
+
value: trimStringOrUndefined(itemMetadata.value),
|
|
3873
|
+
impact: trimStringOrUndefined(itemMetadata.impact),
|
|
3874
|
+
outcome: trimStringOrUndefined(itemMetadata.outcome),
|
|
3875
|
+
why_now: trimStringOrUndefined(itemMetadata.why_now),
|
|
3876
|
+
parent: trimStringOrUndefined(itemMetadata.parent),
|
|
3877
|
+
reviewer: trimStringOrUndefined(itemMetadata.reviewer),
|
|
3878
|
+
risk: itemMetadata.risk ?? void 0,
|
|
3879
|
+
confidence: normalizeConfidenceValue(itemMetadata.confidence),
|
|
3880
|
+
sprint: trimStringOrUndefined(itemMetadata.sprint),
|
|
3881
|
+
release: trimStringOrUndefined(itemMetadata.release),
|
|
3882
|
+
blocked_by: trimStringOrUndefined(itemMetadata.blocked_by),
|
|
3883
|
+
blocked_reason: trimStringOrUndefined(itemMetadata.blocked_reason),
|
|
3884
|
+
unblock_note: trimStringOrUndefined(itemMetadata.unblock_note),
|
|
3885
|
+
reporter: trimStringOrUndefined(itemMetadata.reporter),
|
|
3886
|
+
severity: normalizeSeverityValue(itemMetadata.severity),
|
|
3887
|
+
environment: trimStringOrUndefined(itemMetadata.environment),
|
|
3888
|
+
repro_steps: trimStringOrUndefined(itemMetadata.repro_steps),
|
|
3889
|
+
resolution: trimStringOrUndefined(itemMetadata.resolution),
|
|
3890
|
+
expected_result: trimStringOrUndefined(itemMetadata.expected_result),
|
|
3891
|
+
actual_result: trimStringOrUndefined(itemMetadata.actual_result),
|
|
3892
|
+
affected_version: trimStringOrUndefined(itemMetadata.affected_version),
|
|
3893
|
+
fixed_version: trimStringOrUndefined(itemMetadata.fixed_version),
|
|
3894
|
+
component: trimStringOrUndefined(itemMetadata.component),
|
|
3895
|
+
regression: itemMetadata.regression,
|
|
3896
|
+
customer_impact: trimStringOrUndefined(itemMetadata.customer_impact),
|
|
3897
|
+
close_reason: emptyStringToUndefined(itemMetadata.close_reason),
|
|
3898
|
+
plan_mode: trimStringOrUndefined(itemMetadata.plan_mode),
|
|
3899
|
+
plan_scope: trimStringOrUndefined(itemMetadata.plan_scope),
|
|
3900
|
+
plan_harness: trimStringOrUndefined(itemMetadata.plan_harness),
|
|
3901
|
+
plan_resume_context: trimStringOrUndefined(itemMetadata.plan_resume_context),
|
|
3902
|
+
plan_steps: normalizePlanSteps(itemMetadata.plan_steps),
|
|
3903
|
+
plan_decisions: normalizePlanDecisions(itemMetadata.plan_decisions),
|
|
3904
|
+
plan_discoveries: normalizePlanDiscoveries(itemMetadata.plan_discoveries),
|
|
3905
|
+
plan_validation: normalizePlanValidation(itemMetadata.plan_validation)
|
|
3811
3906
|
};
|
|
3907
|
+
copyExtensionItemMetadataFields(normalized, itemMetadata);
|
|
3908
|
+
coerceNormalizedRuntimeFields(normalized, runtimeContext);
|
|
3909
|
+
assertNormalizedUnknownFields(normalized, runtimeContext);
|
|
3910
|
+
deleteUndefinedFields(normalized);
|
|
3911
|
+
return normalized;
|
|
3812
3912
|
}
|
|
3813
|
-
function
|
|
3814
|
-
return
|
|
3815
|
-
}
|
|
3816
|
-
function fallbackHistoryTimestamp(entry) {
|
|
3817
|
-
const ts = entry.ts.trim();
|
|
3818
|
-
return ts.length > 0 ? ts : nowIso();
|
|
3819
|
-
}
|
|
3820
|
-
function withHistoryTimestamp(value, fallbackTs) {
|
|
3821
|
-
const ts = value.ts;
|
|
3822
|
-
if (typeof ts === "string" && ts.trim().length > 0) {
|
|
3823
|
-
return value;
|
|
3824
|
-
}
|
|
3825
|
-
return { ...value, ts: fallbackTs };
|
|
3913
|
+
function orderItemMetadata(itemMetadata) {
|
|
3914
|
+
return orderObject(itemMetadata, ITEM_METADATA_KEY_ORDER);
|
|
3826
3915
|
}
|
|
3827
|
-
function
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3916
|
+
function findJsonObjectEnd(content) {
|
|
3917
|
+
let depth = 0;
|
|
3918
|
+
let inString = false;
|
|
3919
|
+
let escaped = false;
|
|
3920
|
+
for (let i = 0; i < content.length; i += 1) {
|
|
3921
|
+
const char = content[i];
|
|
3922
|
+
if (inString) {
|
|
3923
|
+
if (escaped) {
|
|
3924
|
+
escaped = false;
|
|
3925
|
+
continue;
|
|
3834
3926
|
}
|
|
3835
|
-
|
|
3927
|
+
if (char === "\\") {
|
|
3928
|
+
escaped = true;
|
|
3929
|
+
continue;
|
|
3930
|
+
}
|
|
3931
|
+
if (char === '"') {
|
|
3932
|
+
inString = false;
|
|
3933
|
+
}
|
|
3934
|
+
continue;
|
|
3836
3935
|
}
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
return JSON.stringify(withHistoryTimestamp(value, fallbackTs));
|
|
3841
|
-
}
|
|
3842
|
-
return JSON.stringify(value);
|
|
3843
|
-
}
|
|
3844
|
-
async function appendHistoryEntry(historyPath, entry) {
|
|
3845
|
-
const override = await runActiveServiceOverride("history_append", {
|
|
3846
|
-
history_path: historyPath,
|
|
3847
|
-
entry
|
|
3848
|
-
});
|
|
3849
|
-
if (override.handled) {
|
|
3850
|
-
if (override.result === false) {
|
|
3851
|
-
return;
|
|
3936
|
+
if (char === '"') {
|
|
3937
|
+
inString = true;
|
|
3938
|
+
continue;
|
|
3852
3939
|
}
|
|
3853
|
-
if (
|
|
3854
|
-
|
|
3855
|
-
|
|
3940
|
+
if (char === "{") {
|
|
3941
|
+
depth += 1;
|
|
3942
|
+
continue;
|
|
3856
3943
|
}
|
|
3857
|
-
if (
|
|
3858
|
-
|
|
3859
|
-
if (
|
|
3860
|
-
return;
|
|
3861
|
-
}
|
|
3862
|
-
const nextHistoryPath = typeof record.history_path === "string" ? record.history_path : historyPath;
|
|
3863
|
-
if (typeof record.line === "string") {
|
|
3864
|
-
await appendLineAtomic(nextHistoryPath, serializeHistoryLine(record.line, entry));
|
|
3865
|
-
return;
|
|
3944
|
+
if (char === "}") {
|
|
3945
|
+
depth -= 1;
|
|
3946
|
+
if (depth === 0) {
|
|
3947
|
+
return i;
|
|
3866
3948
|
}
|
|
3867
|
-
await appendLineAtomic(nextHistoryPath, serializeHistoryLine(record.entry ?? entry, entry));
|
|
3868
|
-
return;
|
|
3869
3949
|
}
|
|
3870
3950
|
}
|
|
3871
|
-
|
|
3872
|
-
}
|
|
3873
|
-
|
|
3874
|
-
// dist/core/history/history-stream-policy.js
|
|
3875
|
-
import fs from "node:fs/promises";
|
|
3876
|
-
import path from "node:path";
|
|
3877
|
-
function toSortedUniqueItemIds(itemIds) {
|
|
3878
|
-
return [...new Set(itemIds.filter((value) => value.trim().length > 0))].sort((left, right) => left.localeCompare(right));
|
|
3951
|
+
return -1;
|
|
3879
3952
|
}
|
|
3880
|
-
function
|
|
3881
|
-
|
|
3953
|
+
function splitFrontMatter(content) {
|
|
3954
|
+
if (!content.startsWith("{")) {
|
|
3955
|
+
return { frontMatter: "", body: content };
|
|
3956
|
+
}
|
|
3957
|
+
const end = findJsonObjectEnd(content);
|
|
3958
|
+
if (end < 0) {
|
|
3959
|
+
return { frontMatter: "", body: content };
|
|
3960
|
+
}
|
|
3961
|
+
const frontMatter = content.slice(0, end + 1);
|
|
3962
|
+
const body = content.slice(end + 1).replace(/^\r?\n+/, "");
|
|
3963
|
+
return { frontMatter, body };
|
|
3882
3964
|
}
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
const
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3965
|
+
function stripLeadingYamlDocument(content) {
|
|
3966
|
+
const normalizedContent = content.charCodeAt(0) === 65279 ? content.slice(1) : content;
|
|
3967
|
+
const opener = normalizedContent.match(/^[ \t]*---[ \t]*(?:\r?\n|$)/);
|
|
3968
|
+
if (!opener) {
|
|
3969
|
+
return { content: normalizedContent, stripped: false };
|
|
3970
|
+
}
|
|
3971
|
+
let cursor = opener[0].length;
|
|
3972
|
+
while (cursor < normalizedContent.length) {
|
|
3973
|
+
const nextNewline = normalizedContent.indexOf("\n", cursor);
|
|
3974
|
+
const lineEnd = nextNewline === -1 ? normalizedContent.length : nextNewline;
|
|
3975
|
+
const line = normalizedContent.slice(cursor, lineEnd).replace(/\r$/, "");
|
|
3976
|
+
const afterLine = nextNewline === -1 ? lineEnd : lineEnd + 1;
|
|
3977
|
+
if (line.trim() === "---") {
|
|
3978
|
+
return {
|
|
3979
|
+
content: normalizedContent.slice(afterLine).replace(/^\s+/, ""),
|
|
3980
|
+
stripped: true
|
|
3981
|
+
};
|
|
3982
|
+
}
|
|
3983
|
+
cursor = afterLine;
|
|
3984
|
+
}
|
|
3985
|
+
return { content: normalizedContent, stripped: false };
|
|
3892
3986
|
}
|
|
3893
|
-
|
|
3894
|
-
return
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
itemIds: [params.itemId],
|
|
3898
|
-
commandLabel: params.commandLabel
|
|
3987
|
+
function normalizeParsedItemMetadata(itemMetadata, options) {
|
|
3988
|
+
return normalizeItemMetadata(itemMetadata, {
|
|
3989
|
+
...options,
|
|
3990
|
+
onWarning: void 0
|
|
3899
3991
|
});
|
|
3900
3992
|
}
|
|
3901
|
-
|
|
3902
|
-
const
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
throw strictMissingStreamError(itemId, params.commandLabel);
|
|
3993
|
+
function parseJsonMarkdownItemDocument(content, runtimeContext, options = {}) {
|
|
3994
|
+
const normalized = stripLeadingYamlDocument(content);
|
|
3995
|
+
if (normalized.stripped) {
|
|
3996
|
+
options.onWarning?.("json_markdown_leading_yaml_frontmatter_ignored");
|
|
3997
|
+
}
|
|
3998
|
+
const { frontMatter, body } = splitFrontMatter(normalized.content);
|
|
3999
|
+
if (!frontMatter) {
|
|
4000
|
+
const trimmed = content.trimStart();
|
|
4001
|
+
if (trimmed.startsWith("{")) {
|
|
4002
|
+
validationError("JSON front matter is not valid JSON");
|
|
3912
4003
|
}
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
4004
|
+
validationError("missing JSON front matter");
|
|
4005
|
+
}
|
|
4006
|
+
let parsed;
|
|
4007
|
+
try {
|
|
4008
|
+
parsed = JSON.parse(frontMatter);
|
|
4009
|
+
} catch {
|
|
4010
|
+
validationError("JSON front matter is not valid JSON");
|
|
3916
4011
|
}
|
|
4012
|
+
assertValidItemMetadata(parsed, runtimeContext);
|
|
3917
4013
|
return {
|
|
3918
|
-
|
|
3919
|
-
|
|
4014
|
+
metadata: normalizeParsedItemMetadata(parsed, options),
|
|
4015
|
+
body: normalizeBody(body)
|
|
3920
4016
|
};
|
|
3921
4017
|
}
|
|
3922
|
-
|
|
3923
|
-
// dist/core/lock/lock.js
|
|
3924
|
-
import fs2 from "node:fs/promises";
|
|
3925
|
-
import path2 from "node:path";
|
|
3926
|
-
import { randomUUID } from "node:crypto";
|
|
3927
|
-
function parseLockInfo(raw) {
|
|
4018
|
+
function parseToonItemDocument(content, runtimeContext, options = {}) {
|
|
3928
4019
|
let parsed;
|
|
3929
4020
|
try {
|
|
3930
|
-
parsed =
|
|
4021
|
+
parsed = decodeToonItemContent(content).value;
|
|
3931
4022
|
} catch {
|
|
3932
|
-
|
|
3933
|
-
info: null,
|
|
3934
|
-
warnings: ["lock_info_invalid_json"]
|
|
3935
|
-
};
|
|
3936
|
-
}
|
|
3937
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
3938
|
-
return {
|
|
3939
|
-
info: null,
|
|
3940
|
-
warnings: ["lock_info_invalid_shape"]
|
|
3941
|
-
};
|
|
4023
|
+
validationError("TOON item document is not valid TOON");
|
|
3942
4024
|
}
|
|
3943
|
-
|
|
3944
|
-
const
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
const ttlSeconds = candidate.ttl_seconds;
|
|
3949
|
-
if (typeof id !== "string" || typeof pid !== "number" || !Number.isFinite(pid) || typeof owner !== "string" || typeof createdAt !== "string" || typeof ttlSeconds !== "number" || !Number.isFinite(ttlSeconds)) {
|
|
4025
|
+
assertItemMetadataCondition(typeof parsed === "object" && parsed !== null && !Array.isArray(parsed), "TOON item document must be an object");
|
|
4026
|
+
const record = parsed;
|
|
4027
|
+
if (Object.prototype.hasOwnProperty.call(record, "front_matter")) {
|
|
4028
|
+
assertValidItemMetadata(record.front_matter, runtimeContext);
|
|
4029
|
+
assertItemMetadataCondition(record.body === void 0 || typeof record.body === "string", "TOON item document body must be a string");
|
|
3950
4030
|
return {
|
|
3951
|
-
|
|
3952
|
-
|
|
4031
|
+
metadata: normalizeParsedItemMetadata(record.front_matter, options),
|
|
4032
|
+
body: normalizeBody(typeof record.body === "string" ? record.body : "")
|
|
3953
4033
|
};
|
|
3954
4034
|
}
|
|
4035
|
+
const { body, ...itemMetadataRecord } = record;
|
|
4036
|
+
assertItemMetadataCondition(body === void 0 || typeof body === "string", "TOON item document body must be a string");
|
|
4037
|
+
assertValidItemMetadata(itemMetadataRecord, runtimeContext);
|
|
3955
4038
|
return {
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
pid,
|
|
3959
|
-
owner,
|
|
3960
|
-
created_at: createdAt,
|
|
3961
|
-
ttl_seconds: ttlSeconds
|
|
3962
|
-
},
|
|
3963
|
-
warnings: []
|
|
4039
|
+
metadata: normalizeParsedItemMetadata(itemMetadataRecord, options),
|
|
4040
|
+
body: normalizeBody(typeof body === "string" ? body : "")
|
|
3964
4041
|
};
|
|
3965
4042
|
}
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
4043
|
+
function serializeJsonMarkdownItemDocument(document, options = {}) {
|
|
4044
|
+
const normalizedMetadata = normalizeItemMetadata(document.metadata, options);
|
|
4045
|
+
const orderedMetadata = orderItemMetadata(normalizedMetadata);
|
|
4046
|
+
const serializedMetadata = JSON.stringify(orderedMetadata, null, 2);
|
|
4047
|
+
const normalizedBody = normalizeBody(document.body ?? "");
|
|
4048
|
+
if (!normalizedBody) {
|
|
4049
|
+
return `${serializedMetadata}
|
|
4050
|
+
`;
|
|
4051
|
+
}
|
|
4052
|
+
return `${serializedMetadata}
|
|
4053
|
+
|
|
4054
|
+
${normalizedBody}
|
|
4055
|
+
`;
|
|
4056
|
+
}
|
|
4057
|
+
function serializeToonItemDocument(document, options = {}) {
|
|
4058
|
+
const normalizedMetadata = normalizeItemMetadata(document.metadata, options);
|
|
4059
|
+
const orderedMetadata = orderItemMetadata(normalizedMetadata);
|
|
4060
|
+
const normalizedBody = normalizeBody(document.body ?? "");
|
|
4061
|
+
return `${encodeToon({ ...orderedMetadata, body: normalizedBody })}
|
|
4062
|
+
`;
|
|
4063
|
+
}
|
|
4064
|
+
function parseItemDocument(content, options = {}) {
|
|
4065
|
+
const conflictMarker = findFirstMergeConflictMarker(content);
|
|
4066
|
+
if (conflictMarker) {
|
|
4067
|
+
throw new PmCliError(`Merge conflict markers detected in item document at line ${conflictMarker.line} (${conflictMarker.marker}). Resolve <<<<<<< ======= >>>>>>> markers and retry.`, EXIT_CODE.GENERIC_FAILURE, {
|
|
4068
|
+
code: "merge_conflict_markers_detected",
|
|
4069
|
+
required: "Resolve merge-conflict markers in the item file before parsing or mutation commands.",
|
|
4070
|
+
why: "Partially merged documents can corrupt item metadata and history integrity.",
|
|
4071
|
+
examples: ["git status", "git add <resolved-file> && git commit"],
|
|
4072
|
+
nextSteps: [
|
|
4073
|
+
"Resolve conflicts, save the file, then rerun the pm command."
|
|
4074
|
+
]
|
|
3972
4075
|
});
|
|
3973
|
-
return parseLockInfo(raw);
|
|
3974
|
-
} catch (error) {
|
|
3975
|
-
if (isErrno(error, "ENOENT")) {
|
|
3976
|
-
return {
|
|
3977
|
-
info: null,
|
|
3978
|
-
warnings: []
|
|
3979
|
-
};
|
|
3980
|
-
}
|
|
3981
|
-
return {
|
|
3982
|
-
info: null,
|
|
3983
|
-
warnings: ["lock_info_read_failed"]
|
|
3984
|
-
};
|
|
3985
4076
|
}
|
|
4077
|
+
const format = options.format ?? "toon";
|
|
4078
|
+
const runtimeContext = resolveRuntimeSchemaValidationContext(options);
|
|
4079
|
+
return format === "toon" ? parseToonItemDocument(content, runtimeContext, options) : parseJsonMarkdownItemDocument(content, runtimeContext, options);
|
|
3986
4080
|
}
|
|
3987
|
-
function
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
async function emitLockWriteHook(lockPath, op) {
|
|
3991
|
-
await runActiveOnWriteHooks({
|
|
3992
|
-
path: lockPath,
|
|
3993
|
-
scope: "project",
|
|
3994
|
-
op
|
|
3995
|
-
});
|
|
4081
|
+
function serializeItemDocument(document, options = {}) {
|
|
4082
|
+
const format = options.format ?? "toon";
|
|
4083
|
+
return format === "toon" ? serializeToonItemDocument(document, options) : serializeJsonMarkdownItemDocument(document, options);
|
|
3996
4084
|
}
|
|
3997
|
-
function
|
|
4085
|
+
function canonicalDocument(document, options = {}) {
|
|
3998
4086
|
return {
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
owner,
|
|
4002
|
-
created_at: nowIso(),
|
|
4003
|
-
ttl_seconds: ttlSeconds
|
|
4087
|
+
metadata: normalizeItemMetadata(document.metadata, options),
|
|
4088
|
+
body: normalizeBody(document.body ?? "")
|
|
4004
4089
|
};
|
|
4005
4090
|
}
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4091
|
+
|
|
4092
|
+
// dist/core/item/item-record.js
|
|
4093
|
+
function toItemRecord(item) {
|
|
4094
|
+
return item;
|
|
4095
|
+
}
|
|
4096
|
+
|
|
4097
|
+
// dist/core/history/history.js
|
|
4098
|
+
import jsonPatch from "fast-json-patch";
|
|
4099
|
+
var EMPTY_LEGACY_HASH_DOCUMENT = {
|
|
4100
|
+
front_matter: {},
|
|
4101
|
+
body: ""
|
|
4102
|
+
};
|
|
4103
|
+
function decodeJsonPointer(path6) {
|
|
4104
|
+
if (!path6 || path6 === "/") {
|
|
4105
|
+
return [];
|
|
4014
4106
|
}
|
|
4015
|
-
|
|
4107
|
+
if (!path6.startsWith("/")) {
|
|
4108
|
+
return [];
|
|
4109
|
+
}
|
|
4110
|
+
return path6.slice(1).split("/").map((segment) => segment.replaceAll("~1", "/").replaceAll("~0", "~"));
|
|
4016
4111
|
}
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
await emitLockWriteHook(lockPath, op);
|
|
4112
|
+
function isDefinedPointerPath(document, path6) {
|
|
4113
|
+
const segments = decodeJsonPointer(path6);
|
|
4114
|
+
if (segments.length === 0) {
|
|
4021
4115
|
return true;
|
|
4022
|
-
} catch {
|
|
4023
|
-
return false;
|
|
4024
4116
|
}
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
}
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
var STALE_CLEANUP_GATE_MAX_ACTIVE_MS = 5 * 6e4;
|
|
4042
|
-
function parseNonNegativeIntegerWaitMs(value) {
|
|
4043
|
-
if (typeof value === "string") {
|
|
4044
|
-
const trimmed = value.trim();
|
|
4045
|
-
if (!/^\d+$/.test(trimmed)) {
|
|
4046
|
-
return void 0;
|
|
4117
|
+
let cursor = document;
|
|
4118
|
+
for (const segment of segments) {
|
|
4119
|
+
if (Array.isArray(cursor)) {
|
|
4120
|
+
if (segment === "-" || !/^(0|[1-9]\d*)$/.test(segment)) {
|
|
4121
|
+
return false;
|
|
4122
|
+
}
|
|
4123
|
+
const index = Number(segment);
|
|
4124
|
+
if (!Number.isInteger(index) || index < 0 || index >= cursor.length) {
|
|
4125
|
+
return false;
|
|
4126
|
+
}
|
|
4127
|
+
const next2 = cursor[index];
|
|
4128
|
+
if (next2 === void 0) {
|
|
4129
|
+
return false;
|
|
4130
|
+
}
|
|
4131
|
+
cursor = next2;
|
|
4132
|
+
continue;
|
|
4047
4133
|
}
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4134
|
+
if (typeof cursor !== "object" || cursor === null) {
|
|
4135
|
+
return false;
|
|
4136
|
+
}
|
|
4137
|
+
if (!Object.prototype.hasOwnProperty.call(cursor, segment)) {
|
|
4138
|
+
return false;
|
|
4139
|
+
}
|
|
4140
|
+
const next = cursor[segment];
|
|
4141
|
+
if (next === void 0) {
|
|
4142
|
+
return false;
|
|
4143
|
+
}
|
|
4144
|
+
cursor = next;
|
|
4053
4145
|
}
|
|
4054
|
-
return
|
|
4146
|
+
return true;
|
|
4055
4147
|
}
|
|
4056
|
-
function
|
|
4057
|
-
const
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
if (callerParsed !== void 0) {
|
|
4064
|
-
return callerParsed;
|
|
4148
|
+
function normalizeHistoryPatchOps(beforeDocument, patch) {
|
|
4149
|
+
const normalized = [];
|
|
4150
|
+
let replayCursor = structuredClone(beforeDocument);
|
|
4151
|
+
for (const operation of patch) {
|
|
4152
|
+
const normalizedOperation = operation.op === "replace" && !isDefinedPointerPath(replayCursor, operation.path) ? { ...operation, op: "add" } : operation;
|
|
4153
|
+
normalized.push(normalizedOperation);
|
|
4154
|
+
replayCursor = jsonPatch.applyPatch(replayCursor, [normalizedOperation], true, true).newDocument;
|
|
4065
4155
|
}
|
|
4066
|
-
return
|
|
4067
|
-
}
|
|
4068
|
-
function sleepWithJitter(baseDelayMs) {
|
|
4069
|
-
const jitteredMs = Math.max(1, Math.round(baseDelayMs * (0.5 + Math.random())));
|
|
4070
|
-
return new Promise((resolve) => setTimeout(resolve, jitteredMs));
|
|
4071
|
-
}
|
|
4072
|
-
function buildLockConflictError(id, info, waitedMs) {
|
|
4073
|
-
const waitedSuffix = waitedMs > 0 ? ` after waiting ${waitedMs}ms` : "";
|
|
4074
|
-
return new PmCliError(`Item ${id} is locked${lockOwnerSuffix(info)}${waitedSuffix}`, EXIT_CODE.CONFLICT, {
|
|
4075
|
-
code: "lock_conflict",
|
|
4076
|
-
recovery: {
|
|
4077
|
-
retry_after_ms: LOCK_CONFLICT_RETRY_HINT_MS
|
|
4078
|
-
}
|
|
4079
|
-
});
|
|
4156
|
+
return normalized;
|
|
4080
4157
|
}
|
|
4081
|
-
function
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4158
|
+
function canonicalHashDocument(document) {
|
|
4159
|
+
const hasMetadata = document.metadata && Object.keys(document.metadata).length > 0;
|
|
4160
|
+
if (!hasMetadata) {
|
|
4161
|
+
return {
|
|
4162
|
+
front_matter: {},
|
|
4163
|
+
body: document.body ?? ""
|
|
4164
|
+
};
|
|
4088
4165
|
}
|
|
4089
|
-
|
|
4166
|
+
const canonical = canonicalDocument(document);
|
|
4167
|
+
const orderedMetadata = orderObject(toItemRecord(canonical.metadata), ITEM_METADATA_KEY_ORDER);
|
|
4168
|
+
return {
|
|
4169
|
+
front_matter: orderedMetadata,
|
|
4170
|
+
body: canonical.body
|
|
4171
|
+
};
|
|
4090
4172
|
}
|
|
4091
|
-
function
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4173
|
+
function canonicalPatchDocument(document) {
|
|
4174
|
+
const hasMetadata = document.metadata && Object.keys(document.metadata).length > 0;
|
|
4175
|
+
if (!hasMetadata) {
|
|
4176
|
+
return {
|
|
4177
|
+
metadata: {},
|
|
4178
|
+
body: document.body ?? ""
|
|
4179
|
+
};
|
|
4095
4180
|
}
|
|
4181
|
+
const canonical = canonicalDocument(document);
|
|
4182
|
+
const orderedMetadata = orderObject(toItemRecord(canonical.metadata), ITEM_METADATA_KEY_ORDER);
|
|
4183
|
+
return {
|
|
4184
|
+
metadata: orderedMetadata,
|
|
4185
|
+
body: canonical.body
|
|
4186
|
+
};
|
|
4096
4187
|
}
|
|
4097
|
-
function
|
|
4098
|
-
|
|
4099
|
-
try {
|
|
4100
|
-
parsed = JSON.parse(raw);
|
|
4101
|
-
} catch {
|
|
4102
|
-
return null;
|
|
4103
|
-
}
|
|
4104
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
4105
|
-
return null;
|
|
4106
|
-
}
|
|
4107
|
-
const candidate = parsed;
|
|
4108
|
-
const pid = candidate.pid;
|
|
4109
|
-
const token = candidate.token;
|
|
4110
|
-
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || typeof token !== "string" || token.length === 0) {
|
|
4111
|
-
return null;
|
|
4112
|
-
}
|
|
4113
|
-
return { pid, token };
|
|
4188
|
+
function hashDocument(document) {
|
|
4189
|
+
return sha256Hex(stableStringify(canonicalHashDocument(document)));
|
|
4114
4190
|
}
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
return parseStaleCleanupGateOwner(await fs2.readFile(path2.join(gatePath, STALE_CLEANUP_GATE_OWNER_FILE), "utf8"));
|
|
4118
|
-
} catch {
|
|
4119
|
-
return null;
|
|
4120
|
-
}
|
|
4191
|
+
function hashEmptyDocument() {
|
|
4192
|
+
return sha256Hex(stableStringify(EMPTY_LEGACY_HASH_DOCUMENT));
|
|
4121
4193
|
}
|
|
4122
|
-
function
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4194
|
+
function createHistoryEntry(params) {
|
|
4195
|
+
const beforeHashCanonical = canonicalHashDocument(params.before);
|
|
4196
|
+
const afterHashCanonical = canonicalHashDocument(params.after);
|
|
4197
|
+
const beforePatchCanonical = canonicalPatchDocument(params.before);
|
|
4198
|
+
const afterPatchCanonical = canonicalPatchDocument(params.after);
|
|
4199
|
+
const rawPatch = jsonPatch.compare(beforePatchCanonical, afterPatchCanonical);
|
|
4200
|
+
const patch = normalizeHistoryPatchOps(beforePatchCanonical, rawPatch);
|
|
4201
|
+
return {
|
|
4202
|
+
ts: params.nowIso,
|
|
4203
|
+
author: params.author,
|
|
4204
|
+
op: params.op,
|
|
4205
|
+
patch,
|
|
4206
|
+
before_hash: sha256Hex(stableStringify(beforeHashCanonical)),
|
|
4207
|
+
after_hash: sha256Hex(stableStringify(afterHashCanonical)),
|
|
4208
|
+
message: params.message === void 0 ? void 0 : params.message
|
|
4209
|
+
};
|
|
4132
4210
|
}
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
await fs2.rm(gatePath, { recursive: true, force: true });
|
|
4136
|
-
return true;
|
|
4137
|
-
} catch {
|
|
4138
|
-
return false;
|
|
4139
|
-
}
|
|
4211
|
+
function isRecord(value) {
|
|
4212
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4140
4213
|
}
|
|
4141
|
-
|
|
4142
|
-
const
|
|
4143
|
-
|
|
4144
|
-
return;
|
|
4145
|
-
}
|
|
4146
|
-
await removeStaleCleanupGateDirectory(gatePath);
|
|
4214
|
+
function fallbackHistoryTimestamp(entry) {
|
|
4215
|
+
const ts = entry.ts.trim();
|
|
4216
|
+
return ts.length > 0 ? ts : nowIso();
|
|
4147
4217
|
}
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
if (isErrno(error, "EEXIST")) {
|
|
4153
|
-
return null;
|
|
4154
|
-
}
|
|
4155
|
-
return null;
|
|
4156
|
-
}
|
|
4157
|
-
const owner = { pid: process.pid, token: randomUUID() };
|
|
4158
|
-
try {
|
|
4159
|
-
await fs2.writeFile(path2.join(gatePath, STALE_CLEANUP_GATE_OWNER_FILE), `${JSON.stringify(owner)}
|
|
4160
|
-
`, "utf8");
|
|
4161
|
-
} catch {
|
|
4162
|
-
await removeStaleCleanupGateDirectory(gatePath);
|
|
4163
|
-
return null;
|
|
4218
|
+
function withHistoryTimestamp(value, fallbackTs) {
|
|
4219
|
+
const ts = value.ts;
|
|
4220
|
+
if (typeof ts === "string" && ts.trim().length > 0) {
|
|
4221
|
+
return value;
|
|
4164
4222
|
}
|
|
4165
|
-
return
|
|
4223
|
+
return { ...value, ts: fallbackTs };
|
|
4166
4224
|
}
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4225
|
+
function serializeHistoryLine(value, fallbackEntry) {
|
|
4226
|
+
const fallbackTs = fallbackHistoryTimestamp(fallbackEntry);
|
|
4227
|
+
if (typeof value === "string") {
|
|
4228
|
+
try {
|
|
4229
|
+
const parsed = JSON.parse(value);
|
|
4230
|
+
if (isRecord(parsed)) {
|
|
4231
|
+
return JSON.stringify(withHistoryTimestamp(parsed, fallbackTs));
|
|
4232
|
+
}
|
|
4233
|
+
} catch {
|
|
4174
4234
|
}
|
|
4175
|
-
|
|
4176
|
-
return isErrno(error, "ENOENT");
|
|
4177
|
-
}
|
|
4178
|
-
const owner = await readStaleCleanupGateOwner(gatePath);
|
|
4179
|
-
if (owner !== null && isProcessAlive(owner.pid) && gateAgeMs <= STALE_CLEANUP_GATE_MAX_ACTIVE_MS) {
|
|
4180
|
-
return false;
|
|
4181
|
-
}
|
|
4182
|
-
return removeStaleCleanupGateDirectory(gatePath);
|
|
4183
|
-
}
|
|
4184
|
-
async function acquireStaleCleanupGate(lockPath, _id) {
|
|
4185
|
-
const gatePath = `${lockPath}${STALE_CLEANUP_GATE_SUFFIX}`;
|
|
4186
|
-
const owner = await tryCreateStaleCleanupGate(gatePath);
|
|
4187
|
-
if (owner !== null) {
|
|
4188
|
-
return async () => releaseStaleCleanupGate(gatePath, owner.token);
|
|
4189
|
-
}
|
|
4190
|
-
if (!await removeExpiredStaleCleanupGate(gatePath)) {
|
|
4191
|
-
return null;
|
|
4235
|
+
return value;
|
|
4192
4236
|
}
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
return null;
|
|
4237
|
+
if (isRecord(value)) {
|
|
4238
|
+
return JSON.stringify(withHistoryTimestamp(value, fallbackTs));
|
|
4196
4239
|
}
|
|
4197
|
-
return
|
|
4240
|
+
return JSON.stringify(value);
|
|
4198
4241
|
}
|
|
4199
|
-
async function
|
|
4200
|
-
const
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
}
|
|
4208
|
-
try {
|
|
4209
|
-
const currentLockInfo = await readLockInfo(params.lockPath);
|
|
4210
|
-
if (currentLockInfo.info === null && currentLockInfo.warnings.length === 0) {
|
|
4211
|
-
return {
|
|
4212
|
-
lockInfo: currentLockInfo,
|
|
4213
|
-
shouldRetryCreate: true,
|
|
4214
|
-
staleRemovalCounted: false
|
|
4215
|
-
};
|
|
4242
|
+
async function appendHistoryEntry(historyPath, entry) {
|
|
4243
|
+
const override = await runActiveServiceOverride("history_append", {
|
|
4244
|
+
history_path: historyPath,
|
|
4245
|
+
entry
|
|
4246
|
+
});
|
|
4247
|
+
if (override.handled) {
|
|
4248
|
+
if (override.result === false) {
|
|
4249
|
+
return;
|
|
4216
4250
|
}
|
|
4217
|
-
if (
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
shouldRetryCreate: false,
|
|
4221
|
-
staleRemovalCounted: false
|
|
4222
|
-
};
|
|
4251
|
+
if (typeof override.result === "string") {
|
|
4252
|
+
await appendLineAtomic(historyPath, serializeHistoryLine(override.result, entry));
|
|
4253
|
+
return;
|
|
4223
4254
|
}
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4255
|
+
if (typeof override.result === "object" && override.result !== null) {
|
|
4256
|
+
const record = override.result;
|
|
4257
|
+
if (record.skip === true) {
|
|
4258
|
+
return;
|
|
4259
|
+
}
|
|
4260
|
+
const nextHistoryPath = typeof record.history_path === "string" ? record.history_path : historyPath;
|
|
4261
|
+
if (typeof record.line === "string") {
|
|
4262
|
+
await appendLineAtomic(nextHistoryPath, serializeHistoryLine(record.line, entry));
|
|
4263
|
+
return;
|
|
4264
|
+
}
|
|
4265
|
+
await appendLineAtomic(nextHistoryPath, serializeHistoryLine(record.entry ?? entry, entry));
|
|
4266
|
+
return;
|
|
4227
4267
|
}
|
|
4228
|
-
return {
|
|
4229
|
-
lockInfo: currentLockInfo,
|
|
4230
|
-
shouldRetryCreate: await unlinkLockWithHook(params.lockPath, "lock:stale_remove"),
|
|
4231
|
-
staleRemovalCounted: true
|
|
4232
|
-
};
|
|
4233
|
-
} finally {
|
|
4234
|
-
await releaseCleanupGate();
|
|
4235
4268
|
}
|
|
4269
|
+
await appendLineAtomic(historyPath, serializeHistoryLine(entry, entry));
|
|
4236
4270
|
}
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4271
|
+
|
|
4272
|
+
// dist/core/history/history-stream-policy.js
|
|
4273
|
+
import fs2 from "node:fs/promises";
|
|
4274
|
+
import path2 from "node:path";
|
|
4275
|
+
function toSortedUniqueItemIds(itemIds) {
|
|
4276
|
+
return [...new Set(itemIds.filter((value) => value.trim().length > 0))].sort((left, right) => left.localeCompare(right));
|
|
4277
|
+
}
|
|
4278
|
+
function strictMissingStreamError(itemId, commandLabel) {
|
|
4279
|
+
return new PmCliError(`Missing history stream for ${itemId}. ${commandLabel} requires history streams when settings.history.missing_stream is strict_error.`, EXIT_CODE.NOT_FOUND);
|
|
4280
|
+
}
|
|
4281
|
+
async function createStream(historyPath, commandLabel) {
|
|
4282
|
+
await ensureDir(path2.dirname(historyPath));
|
|
4283
|
+
const handle = await fs2.open(historyPath, "a");
|
|
4284
|
+
await handle.close();
|
|
4285
|
+
return runActiveOnWriteHooks({
|
|
4286
|
+
path: historyPath,
|
|
4287
|
+
scope: "project",
|
|
4288
|
+
op: `${commandLabel}:history:auto_create`
|
|
4245
4289
|
});
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4290
|
+
}
|
|
4291
|
+
async function enforceHistoryStreamPolicyForItem(params) {
|
|
4292
|
+
return enforceHistoryStreamPolicyForItems({
|
|
4293
|
+
pmRoot: params.pmRoot,
|
|
4294
|
+
settings: params.settings,
|
|
4295
|
+
itemIds: [params.itemId],
|
|
4296
|
+
commandLabel: params.commandLabel
|
|
4297
|
+
});
|
|
4298
|
+
}
|
|
4299
|
+
async function enforceHistoryStreamPolicyForItems(params) {
|
|
4300
|
+
const ids = toSortedUniqueItemIds(params.itemIds);
|
|
4301
|
+
const autoCreated = [];
|
|
4302
|
+
const warnings = [];
|
|
4303
|
+
for (const itemId of ids) {
|
|
4304
|
+
const historyPath = getHistoryPath(params.pmRoot, itemId);
|
|
4305
|
+
if (await pathExists(historyPath)) {
|
|
4306
|
+
continue;
|
|
4257
4307
|
}
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
const waitBudgetMs = resolveLockWaitMs(waitMs);
|
|
4261
|
-
const startedAtMs = Date.now();
|
|
4262
|
-
let staleRemovals = 0;
|
|
4263
|
-
let backoffMs = LOCK_WAIT_INITIAL_DELAY_MS;
|
|
4264
|
-
for (; ; ) {
|
|
4265
|
-
try {
|
|
4266
|
-
await createLockFile(lockPath, id, owner, ttlSeconds);
|
|
4267
|
-
return async () => {
|
|
4268
|
-
await unlinkLockWithHook(lockPath, "lock:release");
|
|
4269
|
-
await runActiveServiceOverride("lock_release", {
|
|
4270
|
-
pm_root: pmRoot,
|
|
4271
|
-
id,
|
|
4272
|
-
owner
|
|
4273
|
-
});
|
|
4274
|
-
};
|
|
4275
|
-
} catch (error) {
|
|
4276
|
-
if (!isErrno(error, "EEXIST")) {
|
|
4277
|
-
throw new PmCliError(`Failed to acquire lock for ${id}: ${toErrorMessage(error)}`, EXIT_CODE.GENERIC_FAILURE);
|
|
4278
|
-
}
|
|
4279
|
-
let lockInfo = await readLockInfo(lockPath);
|
|
4280
|
-
if (isStaleLock(lockInfo.info, ttlSeconds)) {
|
|
4281
|
-
const staleRemoval = await removeConfirmedStaleLock({
|
|
4282
|
-
lockPath,
|
|
4283
|
-
id,
|
|
4284
|
-
ttlSeconds,
|
|
4285
|
-
force,
|
|
4286
|
-
forceRequiredForStaleLock,
|
|
4287
|
-
staleRemovals,
|
|
4288
|
-
waitBudgetMs,
|
|
4289
|
-
startedAtMs,
|
|
4290
|
-
fallbackLockInfo: lockInfo
|
|
4291
|
-
});
|
|
4292
|
-
lockInfo = staleRemoval.lockInfo;
|
|
4293
|
-
if (staleRemoval.staleRemovalCounted) {
|
|
4294
|
-
staleRemovals += 1;
|
|
4295
|
-
}
|
|
4296
|
-
if (staleRemoval.shouldRetryCreate) {
|
|
4297
|
-
continue;
|
|
4298
|
-
}
|
|
4299
|
-
}
|
|
4300
|
-
const elapsedMs = Date.now() - startedAtMs;
|
|
4301
|
-
if (waitBudgetMs === 0 || elapsedMs >= waitBudgetMs) {
|
|
4302
|
-
throw buildLockConflictError(id, lockInfo.info, waitBudgetMs === 0 ? 0 : elapsedMs);
|
|
4303
|
-
}
|
|
4304
|
-
await sleepWithJitter(Math.min(backoffMs, waitBudgetMs - elapsedMs));
|
|
4305
|
-
backoffMs = Math.min(backoffMs * 2, LOCK_WAIT_MAX_DELAY_MS);
|
|
4308
|
+
if (params.settings.history.missing_stream === "strict_error") {
|
|
4309
|
+
throw strictMissingStreamError(itemId, params.commandLabel);
|
|
4306
4310
|
}
|
|
4311
|
+
warnings.push(...await createStream(historyPath, params.commandLabel));
|
|
4312
|
+
warnings.push(`history_stream_auto_created:${itemId}`);
|
|
4313
|
+
autoCreated.push(itemId);
|
|
4307
4314
|
}
|
|
4315
|
+
return {
|
|
4316
|
+
auto_created_ids: autoCreated,
|
|
4317
|
+
warnings
|
|
4318
|
+
};
|
|
4308
4319
|
}
|
|
4309
4320
|
|
|
4310
4321
|
// dist/core/item/id.js
|
|
@@ -5367,6 +5378,7 @@ async function deleteItem(params) {
|
|
|
5367
5378
|
}
|
|
5368
5379
|
|
|
5369
5380
|
export {
|
|
5381
|
+
createCoreCommandHookContext,
|
|
5370
5382
|
createSerialQueue,
|
|
5371
5383
|
setActiveExtensionHooks,
|
|
5372
5384
|
setActiveExtensionCommands,
|
|
@@ -5408,6 +5420,7 @@ export {
|
|
|
5408
5420
|
compareTimestampStrings,
|
|
5409
5421
|
matchesTimestampFilters,
|
|
5410
5422
|
resolveIsoOrRelative,
|
|
5423
|
+
acquireLock,
|
|
5411
5424
|
readRuntimeFieldOptionValue,
|
|
5412
5425
|
coerceRuntimeFieldValue,
|
|
5413
5426
|
collectRuntimeCreateFieldValues,
|
|
@@ -5434,7 +5447,6 @@ export {
|
|
|
5434
5447
|
appendHistoryEntry,
|
|
5435
5448
|
enforceHistoryStreamPolicyForItem,
|
|
5436
5449
|
enforceHistoryStreamPolicyForItems,
|
|
5437
|
-
acquireLock,
|
|
5438
5450
|
normalizePrefix,
|
|
5439
5451
|
normalizeRawItemId,
|
|
5440
5452
|
normalizeItemId,
|
|
@@ -5450,6 +5462,6 @@ export {
|
|
|
5450
5462
|
mutateItem,
|
|
5451
5463
|
deleteItem
|
|
5452
5464
|
};
|
|
5453
|
-
//# sourceMappingURL=chunk-
|
|
5465
|
+
//# sourceMappingURL=chunk-GSEADLRH.js.map
|
|
5454
5466
|
|
|
5455
|
-
//# debugId=
|
|
5467
|
+
//# debugId=e468cc5b-3706-5898-8d97-4deeb3bc0835
|