@unbrained/pm-cli 2026.7.1 → 2026.7.3
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 +3 -3
- package/CHANGELOG.md +25 -0
- package/CONTRIBUTING.md +2 -2
- package/README.md +1 -1
- package/dist/cli/commander-usage.d.ts +2 -0
- package/dist/cli/commander-usage.js +110 -86
- package/dist/cli/commander-usage.js.map +1 -1
- package/dist/cli/commands/activity.js +79 -57
- package/dist/cli/commands/activity.js.map +1 -1
- package/dist/cli/commands/aggregate.js +102 -79
- package/dist/cli/commands/aggregate.js.map +1 -1
- package/dist/cli/commands/calendar.js +278 -243
- package/dist/cli/commands/calendar.js.map +1 -1
- package/dist/cli/commands/close-many.js +176 -114
- package/dist/cli/commands/close-many.js.map +1 -1
- package/dist/cli/commands/close.js +157 -129
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/comments-audit.js +50 -42
- package/dist/cli/commands/comments-audit.js.map +1 -1
- package/dist/cli/commands/config.d.ts +2 -0
- package/dist/cli/commands/config.js +443 -879
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/context.js +365 -287
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/contracts.js +352 -238
- package/dist/cli/commands/contracts.js.map +1 -1
- package/dist/cli/commands/create.js +32 -17
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/dedupe-audit.js +46 -39
- package/dist/cli/commands/dedupe-audit.js.map +1 -1
- package/dist/cli/commands/dedupe-merge.js +88 -69
- package/dist/cli/commands/dedupe-merge.js.map +1 -1
- package/dist/cli/commands/extension/doctor.js +56 -67
- package/dist/cli/commands/extension/doctor.js.map +1 -1
- package/dist/cli/commands/extension/shared.js +21 -15
- package/dist/cli/commands/extension/shared.js.map +1 -1
- package/dist/cli/commands/get.js +114 -81
- package/dist/cli/commands/get.js.map +1 -1
- package/dist/cli/commands/health.d.ts +17 -0
- package/dist/cli/commands/health.js +545 -417
- package/dist/cli/commands/health.js.map +1 -1
- package/dist/cli/commands/history-compact.js +209 -140
- package/dist/cli/commands/history-compact.js.map +1 -1
- package/dist/cli/commands/history-redact.js +162 -119
- package/dist/cli/commands/history-redact.js.map +1 -1
- package/dist/cli/commands/history-repair.js +120 -85
- package/dist/cli/commands/history-repair.js.map +1 -1
- package/dist/cli/commands/init-agent-guidance.js +32 -19
- package/dist/cli/commands/init-agent-guidance.js.map +1 -1
- package/dist/cli/commands/init.d.ts +8 -2
- package/dist/cli/commands/init.js +263 -162
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/list.js +152 -102
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/next.js +60 -40
- package/dist/cli/commands/next.js.map +1 -1
- package/dist/cli/commands/plan.js +373 -298
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/profile.js +23 -15
- package/dist/cli/commands/profile.js.map +1 -1
- package/dist/cli/commands/recurrence-parsers.js +43 -25
- package/dist/cli/commands/recurrence-parsers.js.map +1 -1
- package/dist/cli/commands/reindex.d.ts +21 -5
- package/dist/cli/commands/reindex.js +345 -205
- package/dist/cli/commands/reindex.js.map +1 -1
- package/dist/cli/commands/restore.d.ts +8 -7
- package/dist/cli/commands/restore.js +105 -69
- package/dist/cli/commands/restore.js.map +1 -1
- package/dist/cli/commands/schema.js +33 -30
- package/dist/cli/commands/schema.js.map +1 -1
- package/dist/cli/commands/search.d.ts +10 -2
- package/dist/cli/commands/search.js +503 -470
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/telemetry.js +98 -87
- package/dist/cli/commands/telemetry.js.map +1 -1
- package/dist/cli/commands/test-all.js +237 -168
- package/dist/cli/commands/test-all.js.map +1 -1
- package/dist/cli/commands/test.d.ts +6 -5
- package/dist/cli/commands/test.js +424 -344
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update-many.js +57 -42
- package/dist/cli/commands/update-many.js.map +1 -1
- package/dist/cli/commands/update.d.ts +1 -1
- package/dist/cli/commands/update.js +738 -671
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +20 -1
- package/dist/cli/commands/validate.js +478 -343
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/error-guidance.js +406 -361
- package/dist/cli/error-guidance.js.map +1 -1
- package/dist/cli/extension-command-help.js +27 -19
- package/dist/cli/extension-command-help.js.map +1 -1
- package/dist/cli/help-json-payload.js +57 -49
- package/dist/cli/help-json-payload.js.map +1 -1
- package/dist/cli/main.d.ts +47 -0
- package/dist/cli/main.js +474 -371
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/migration-gates.js +22 -45
- package/dist/cli/migration-gates.js.map +1 -1
- package/dist/cli/register-list-query.js +299 -310
- package/dist/cli/register-list-query.js.map +1 -1
- package/dist/cli/register-mutation.js +763 -779
- package/dist/cli/register-mutation.js.map +1 -1
- package/dist/cli/register-operations.js +386 -362
- package/dist/cli/register-operations.js.map +1 -1
- package/dist/cli/register-setup.js +120 -101
- package/dist/cli/register-setup.js.map +1 -1
- package/dist/cli/registration-helpers.d.ts +4 -0
- package/dist/cli/registration-helpers.js +45 -56
- package/dist/cli/registration-helpers.js.map +1 -1
- package/dist/cli-bundle/chunks/{activity-DBLQVIP6.js → activity-5YWLSPGE.js} +9 -9
- package/dist/cli-bundle/chunks/activity-BIML7K2D.js +16 -0
- package/dist/cli-bundle/chunks/{aggregate-SDF7DUOD.js → aggregate-2V2M3JZU.js} +107 -83
- package/dist/cli-bundle/chunks/{aggregate-SDF7DUOD.js.map → aggregate-2V2M3JZU.js.map} +2 -2
- package/dist/cli-bundle/chunks/{aggregate-JTEF4BP7.js → aggregate-EK7DXML7.js} +108 -84
- package/dist/cli-bundle/chunks/aggregate-EK7DXML7.js.map +1 -0
- package/dist/cli-bundle/chunks/{append-LOVPGVPT.js → append-EZESUVJT.js} +8 -8
- package/dist/cli-bundle/chunks/{append-QCFJSDFL.js → append-JFG4WQMG.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-TP5Q5ZD3.js → chunk-32IUNTG4.js} +158 -119
- package/dist/cli-bundle/chunks/chunk-32IUNTG4.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-BHO33VBQ.js → chunk-3W2HJKJX.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-VARHOHYV.js → chunk-4EXFFP7T.js} +86 -52
- package/dist/cli-bundle/chunks/chunk-4EXFFP7T.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-4DUVCVLZ.js → chunk-4PFVUUYV.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-JSU5P7VS.js → chunk-4WB6S4YX.js} +308 -184
- package/dist/cli-bundle/chunks/chunk-4WB6S4YX.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-HXTQJXWT.js → chunk-572FKBRL.js} +61 -102
- package/dist/cli-bundle/chunks/chunk-572FKBRL.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-IJYK2T43.js → chunk-5E7N4T2Z.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-NKZAN7BD.js → chunk-5IZUBZBR.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-NOLPZMSV.js → chunk-5JIWFWOZ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-FFMQB7WR.js → chunk-67LARBDL.js} +493 -404
- package/dist/cli-bundle/chunks/chunk-67LARBDL.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-6AQZPVHQ.js → chunk-6CDCWKSX.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-3K2M5OYU.js → chunk-6KRFL33E.js} +308 -184
- package/dist/cli-bundle/chunks/chunk-6KRFL33E.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-LB6TP6MC.js → chunk-6NYJGMTY.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-SLMUGTK3.js → chunk-7CLLC75T.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-2466X6E4.js → chunk-7LYO6S5A.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-W4ULYO7Z.js → chunk-A3OQ7TFW.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-5CGRF3L5.js → chunk-AIKU3IIL.js} +153 -90
- package/dist/cli-bundle/chunks/chunk-AIKU3IIL.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-WYDHYJPO.js → chunk-AJHYQCBJ.js} +39 -5
- package/dist/cli-bundle/chunks/chunk-AJHYQCBJ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-VZDBVEZR.js → chunk-B4O5S7I3.js} +79 -57
- package/dist/cli-bundle/chunks/{chunk-VZDBVEZR.js.map → chunk-B4O5S7I3.js.map} +2 -2
- package/dist/cli-bundle/chunks/{chunk-OTUHB4HS.js → chunk-BE2SR6QL.js} +92 -77
- package/dist/cli-bundle/chunks/chunk-BE2SR6QL.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-JLM7BHI7.js → chunk-BI4R7HI2.js} +75 -53
- package/dist/cli-bundle/chunks/chunk-BI4R7HI2.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-AXIDKKAT.js → chunk-CXR3CMBQ.js} +33 -6
- package/dist/cli-bundle/chunks/chunk-CXR3CMBQ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-ZETXE4SE.js → chunk-ECU6MMTQ.js} +713 -613
- package/dist/cli-bundle/chunks/chunk-ECU6MMTQ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-2D4HATP2.js → chunk-EJ2OCBHF.js} +54 -30
- package/dist/cli-bundle/chunks/chunk-EJ2OCBHF.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-BDTISOSD.js → chunk-EQURFOMH.js} +41 -26
- package/dist/cli-bundle/chunks/chunk-EQURFOMH.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-GJ326ZKX.js → chunk-ER4ME5U2.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-HZZEHPRG.js → chunk-ERG65A2L.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-IZBR4NRW.js → chunk-F6WNBITZ.js} +157 -113
- package/dist/cli-bundle/chunks/chunk-F6WNBITZ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-L5OEFZQG.js → chunk-FH2H3CBD.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-JPECA746.js → chunk-FUFFPIYA.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-CF7RL6FR.js → chunk-FZJM2TXF.js} +110 -73
- package/dist/cli-bundle/chunks/chunk-FZJM2TXF.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-27BXPBAY.js → chunk-GUYNUXQT.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-MAUKX7JC.js → chunk-GVJE5T7Q.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-3J6JRJ3I.js → chunk-HB4FAT3O.js} +42 -60
- package/dist/cli-bundle/chunks/chunk-HB4FAT3O.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-55SNVXRQ.js → chunk-HQAF23Q2.js} +626 -484
- package/dist/cli-bundle/chunks/chunk-HQAF23Q2.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-ZRP4VG5U.js → chunk-JBZ2NTKX.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-RMMQ74TG.js → chunk-JPATY4SE.js} +54 -30
- package/dist/cli-bundle/chunks/chunk-JPATY4SE.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-IPYBJWTE.js → chunk-K5DT2YKM.js} +109 -72
- package/dist/cli-bundle/chunks/chunk-K5DT2YKM.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-EJUDVUYZ.js → chunk-KEZOIPCR.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-RVUALSJF.js → chunk-KHVGM5CS.js} +466 -365
- package/dist/cli-bundle/chunks/chunk-KHVGM5CS.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-YITK2PJ6.js → chunk-KS6ATO47.js} +288 -175
- package/dist/cli-bundle/chunks/chunk-KS6ATO47.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-7R4QEMZZ.js → chunk-L4SLHV6G.js} +463 -362
- package/dist/cli-bundle/chunks/chunk-L4SLHV6G.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-RLDHZHQS.js → chunk-LBE5QFMZ.js} +158 -114
- package/dist/cli-bundle/chunks/chunk-LBE5QFMZ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-22WKIL3H.js → chunk-LCWQP6NM.js} +76 -54
- package/dist/cli-bundle/chunks/chunk-LCWQP6NM.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-KNPEF7QG.js → chunk-LOWVNZBZ.js} +91 -76
- package/dist/cli-bundle/chunks/chunk-LOWVNZBZ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-HYTGA6GI.js → chunk-MDHWWBNZ.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-N74UMG5H.js → chunk-MEZZZBYX.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-V3NOKJF2.js → chunk-MHRS5FUX.js} +288 -175
- package/dist/cli-bundle/chunks/chunk-MHRS5FUX.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-3XZCOZ5J.js → chunk-NOIEVOK5.js} +391 -313
- package/dist/cli-bundle/chunks/chunk-NOIEVOK5.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-SDR5J34Q.js → chunk-NZ7QIUP5.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-UYUYDGIB.js → chunk-OGLGI22K.js} +115 -67
- package/dist/cli-bundle/chunks/{chunk-UYUYDGIB.js.map → chunk-OGLGI22K.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-DDPTYJIM.js → chunk-P5L7Z2O6.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-BZCEN4JA.js → chunk-PULUSQAV.js} +492 -403
- package/dist/cli-bundle/chunks/chunk-PULUSQAV.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-3VGN2UWE.js → chunk-QCDTQCMW.js} +22 -30
- package/dist/cli-bundle/chunks/chunk-QCDTQCMW.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-4A3BJ675.js → chunk-QNNQAAZ5.js} +24 -18
- package/dist/cli-bundle/chunks/{chunk-4A3BJ675.js.map → chunk-QNNQAAZ5.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-MDPEOIGN.js → chunk-RAHINBVP.js} +60 -101
- package/dist/cli-bundle/chunks/chunk-RAHINBVP.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-CWFNTKQJ.js → chunk-RJH5VQHW.js} +43 -61
- package/dist/cli-bundle/chunks/chunk-RJH5VQHW.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-OGXLACHC.js → chunk-SU2E4AWU.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-HPPFYYOV.js → chunk-SU3TB4NS.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-JWXRETDF.js → chunk-SYE6WMV6.js} +626 -484
- package/dist/cli-bundle/chunks/chunk-SYE6WMV6.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-NWMZWYYB.js → chunk-T3P7PMZP.js} +42 -27
- package/dist/cli-bundle/chunks/chunk-T3P7PMZP.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-G7I7DEZA.js → chunk-T4XBKJ3F.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-RH5ZBYFD.js → chunk-T6AXEBOP.js} +23 -17
- package/dist/cli-bundle/chunks/{chunk-RH5ZBYFD.js.map → chunk-T6AXEBOP.js.map} +2 -2
- package/dist/cli-bundle/chunks/{chunk-5QFDBI4F.js → chunk-TQ6AX5SQ.js} +58 -69
- package/dist/cli-bundle/chunks/{chunk-5QFDBI4F.js.map → chunk-TQ6AX5SQ.js.map} +2 -2
- package/dist/cli-bundle/chunks/{chunk-4XOIEKSD.js → chunk-U3S2B7TA.js} +86 -52
- package/dist/cli-bundle/chunks/chunk-U3S2B7TA.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-VICZWYGZ.js → chunk-U5TR4N7J.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-EVMTBV6V.js → chunk-UMNQZS4H.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-A7FPBAQS.js → chunk-WJA3PXW7.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-RGEMWD6Q.js → chunk-WRYERRZX.js} +157 -118
- package/dist/cli-bundle/chunks/chunk-WRYERRZX.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-NUHHPVVS.js → chunk-WYOIIFSE.js} +712 -612
- package/dist/cli-bundle/chunks/chunk-WYOIIFSE.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-4DSGXSBL.js → chunk-XRYSCRZR.js} +116 -68
- package/dist/cli-bundle/chunks/{chunk-4DSGXSBL.js.map → chunk-XRYSCRZR.js.map} +3 -3
- package/dist/cli-bundle/chunks/{chunk-NU2UEROZ.js → chunk-YF746GTH.js} +59 -70
- package/dist/cli-bundle/chunks/{chunk-NU2UEROZ.js.map → chunk-YF746GTH.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-JMP4E6D7.js → chunk-YPWUSH72.js} +390 -312
- package/dist/cli-bundle/chunks/{chunk-JMP4E6D7.js.map → chunk-YPWUSH72.js.map} +2 -2
- package/dist/cli-bundle/chunks/{chunk-QCWF6IYD.js → chunk-YSDFIY7N.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-UZIWVBE6.js → chunk-YSGTMDWC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-NFDPYAIP.js → chunk-YVKZ3ANP.js} +21 -29
- package/dist/cli-bundle/chunks/chunk-YVKZ3ANP.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-OKQ22KTH.js → chunk-Z4DGFQDH.js} +80 -58
- package/dist/cli-bundle/chunks/{chunk-OKQ22KTH.js.map → chunk-Z4DGFQDH.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-64HNBBFQ.js → chunk-Z5F6XZXE.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-AVEE5EHK.js → chunk-Z7RPDF2Y.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-3S2KT7NG.js → chunk-ZFTKYWIF.js} +152 -89
- package/dist/cli-bundle/chunks/chunk-ZFTKYWIF.js.map +7 -0
- package/dist/cli-bundle/chunks/{claim-T3GCKV7C.js → claim-2BGBGSVI.js} +8 -8
- package/dist/cli-bundle/chunks/{claim-EMQLYPRW.js → claim-5GU7OE67.js} +8 -8
- package/dist/cli-bundle/chunks/close-6YODBUIV.js +14 -0
- package/dist/cli-bundle/chunks/{close-TQYAAFJP.js → close-AFVKPR57.js} +7 -7
- package/dist/cli-bundle/chunks/{close-many-BG5QQIDQ.js → close-many-7KLOSYLP.js} +186 -122
- package/dist/cli-bundle/chunks/close-many-7KLOSYLP.js.map +7 -0
- package/dist/cli-bundle/chunks/{close-many-LDRVEQY2.js → close-many-JKUJMHLG.js} +187 -123
- package/dist/cli-bundle/chunks/close-many-JKUJMHLG.js.map +1 -0
- package/dist/cli-bundle/chunks/{comments-YUXJRZPQ.js → comments-DNWHEBOS.js} +9 -9
- package/dist/cli-bundle/chunks/{comments-QCKR2YY2.js → comments-RW23R3VE.js} +9 -9
- package/dist/cli-bundle/chunks/config-AUM5WBYA.js +1072 -0
- package/dist/cli-bundle/chunks/config-AUM5WBYA.js.map +7 -0
- package/dist/cli-bundle/chunks/config-OZWSA2NP.js +1062 -0
- package/dist/cli-bundle/chunks/config-OZWSA2NP.js.map +1 -0
- package/dist/cli-bundle/chunks/{context-B6275WPX.js → context-OYXRGY7S.js} +12 -12
- package/dist/cli-bundle/chunks/{context-OCZ3FJ4Z.js → context-PKCEHQY3.js} +12 -12
- package/dist/cli-bundle/chunks/{contracts-HN7ABKLP.js → contracts-L6ODXNUM.js} +320 -199
- package/dist/cli-bundle/chunks/contracts-L6ODXNUM.js.map +7 -0
- package/dist/cli-bundle/chunks/{contracts-W4FZVVD6.js → contracts-X74F2GSM.js} +321 -200
- package/dist/cli-bundle/chunks/contracts-X74F2GSM.js.map +1 -0
- package/dist/cli-bundle/chunks/{copy-DEM4DATS.js → copy-6XOR3HKN.js} +5 -5
- package/dist/cli-bundle/chunks/{copy-BTJOSKKT.js → copy-I4NCLBR4.js} +5 -5
- package/dist/cli-bundle/chunks/{create-RLRJMRTM.js → create-PM45M6PE.js} +12 -12
- package/dist/cli-bundle/chunks/create-Z7YCH3BE.js +28 -0
- package/dist/cli-bundle/chunks/{delete-BHK7VB2Z.js → delete-7YXHYG67.js} +5 -5
- package/dist/cli-bundle/chunks/{delete-LSVHAB4Y.js → delete-LPISP43T.js} +5 -5
- package/dist/cli-bundle/chunks/{deps-XHYXWEPT.js → deps-N2T26FME.js} +5 -5
- package/dist/cli-bundle/chunks/{deps-4UDFJRUA.js → deps-WATKQDE3.js} +5 -5
- package/dist/cli-bundle/chunks/{docs-GYZNVS26.js → docs-6LQ3GLM7.js} +7 -7
- package/dist/cli-bundle/chunks/{docs-26S44RXU.js → docs-Z3X6JZLT.js} +7 -7
- package/dist/cli-bundle/chunks/{eval-UYF3ZPVO.js → eval-6DCLG52D.js} +10 -10
- package/dist/cli-bundle/chunks/{eval-PGRVIJQU.js → eval-Y3ZCUTHK.js} +10 -10
- package/dist/cli-bundle/chunks/{extension-CPSLJQVE.js → extension-BNINIMT7.js} +11 -11
- package/dist/cli-bundle/chunks/{extension-CXJ6RELI.js → extension-QWE4YYK5.js} +11 -11
- package/dist/cli-bundle/chunks/{files-NQHEXUZD.js → files-6SGKHS6O.js} +7 -7
- package/dist/cli-bundle/chunks/{files-MBNICQFM.js → files-FUYPSOFJ.js} +7 -7
- package/dist/cli-bundle/chunks/{focus-DWYIG7GU.js → focus-2Q3K76G2.js} +6 -6
- package/dist/cli-bundle/chunks/{focus-XZW5423D.js → focus-ATLBWXXD.js} +6 -6
- package/dist/cli-bundle/chunks/{gc-LPVMKJQJ.js → gc-RUYEMNRF.js} +3 -3
- package/dist/cli-bundle/chunks/{gc-7GQYOS2G.js → gc-TDWSDR66.js} +3 -3
- package/dist/cli-bundle/chunks/{get-A7MAOHCU.js → get-2WGLX74N.js} +120 -80
- package/dist/cli-bundle/chunks/get-2WGLX74N.js.map +7 -0
- package/dist/cli-bundle/chunks/{get-DSDEKJ3L.js → get-LY6M2JIM.js} +121 -81
- package/dist/cli-bundle/chunks/get-LY6M2JIM.js.map +1 -0
- package/dist/cli-bundle/chunks/{health-3IPFLKXB.js → health-4RKHYS3T.js} +535 -371
- package/dist/cli-bundle/chunks/health-4RKHYS3T.js.map +1 -0
- package/dist/cli-bundle/chunks/{health-GZXGBZ36.js → health-TMFVNYRA.js} +534 -370
- package/dist/cli-bundle/chunks/health-TMFVNYRA.js.map +7 -0
- package/dist/cli-bundle/chunks/history-CGNQJXFE.js +18 -0
- package/dist/cli-bundle/chunks/{history-NERDJNUB.js → history-SGRRS72R.js} +8 -8
- package/dist/cli-bundle/chunks/{history-compact-2WRZ2WK4.js → history-compact-LOED43R3.js} +213 -134
- package/dist/cli-bundle/chunks/history-compact-LOED43R3.js.map +7 -0
- package/dist/cli-bundle/chunks/{history-compact-HR7BB4LR.js → history-compact-V5DNAQHH.js} +214 -135
- package/dist/cli-bundle/chunks/history-compact-V5DNAQHH.js.map +1 -0
- package/dist/cli-bundle/chunks/{history-redact-O3NBCNWC.js → history-redact-IRL7WJ3E.js} +9 -9
- package/dist/cli-bundle/chunks/history-redact-N3JK7VBW.js +19 -0
- package/dist/cli-bundle/chunks/{history-repair-XA3LC4GA.js → history-repair-4WVBVHFR.js} +124 -84
- package/dist/cli-bundle/chunks/history-repair-4WVBVHFR.js.map +1 -0
- package/dist/cli-bundle/chunks/{history-repair-LCMOS45X.js → history-repair-PGYQJMGD.js} +123 -83
- package/dist/cli-bundle/chunks/history-repair-PGYQJMGD.js.map +7 -0
- package/dist/cli-bundle/chunks/{init-64XDLQJB.js → init-4GESW7RM.js} +12 -12
- package/dist/cli-bundle/chunks/init-XIDPABA4.js +22 -0
- package/dist/cli-bundle/chunks/{learnings-LPKCSJX7.js → learnings-4BHWFFUV.js} +9 -9
- package/dist/cli-bundle/chunks/{learnings-JR6MA5TI.js → learnings-4FJY7WIW.js} +9 -9
- package/dist/cli-bundle/chunks/{list-G5Y65VF6.js → list-472TIOVK.js} +8 -8
- package/dist/cli-bundle/chunks/{list-DNBJVO3E.js → list-D7BF5CL2.js} +8 -8
- package/dist/cli-bundle/chunks/{next-FYTQF6HG.js → next-D5STGWI2.js} +71 -46
- package/dist/cli-bundle/chunks/next-D5STGWI2.js.map +1 -0
- package/dist/cli-bundle/chunks/{next-BCERKDUR.js → next-SFQZVX2B.js} +70 -45
- package/dist/cli-bundle/chunks/next-SFQZVX2B.js.map +7 -0
- package/dist/cli-bundle/chunks/{notes-2BMU3VVQ.js → notes-6KNOSLIT.js} +9 -9
- package/dist/cli-bundle/chunks/{notes-6KTGO2OJ.js → notes-W4UEICGF.js} +9 -9
- package/dist/cli-bundle/chunks/{plan-RKZHQVXR.js → plan-JO6V7BXO.js} +373 -279
- package/dist/cli-bundle/chunks/plan-JO6V7BXO.js.map +1 -0
- package/dist/cli-bundle/chunks/{plan-4WXEQCTN.js → plan-MJQW5XK3.js} +372 -278
- package/dist/cli-bundle/chunks/plan-MJQW5XK3.js.map +7 -0
- package/dist/cli-bundle/chunks/{profile-4OMM32CD.js → profile-3TOTMUR4.js} +27 -19
- package/dist/cli-bundle/chunks/profile-3TOTMUR4.js.map +7 -0
- package/dist/cli-bundle/chunks/{profile-QLER5ENE.js → profile-WIQY2KCV.js} +28 -20
- package/dist/cli-bundle/chunks/profile-WIQY2KCV.js.map +1 -0
- package/dist/cli-bundle/chunks/register-list-query-ELBHCCFI.js +416 -0
- package/dist/cli-bundle/chunks/register-list-query-ELBHCCFI.js.map +7 -0
- package/dist/cli-bundle/chunks/register-list-query-GAPQ6DM3.js +406 -0
- package/dist/cli-bundle/chunks/register-list-query-GAPQ6DM3.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-mutation-KK7PHYYU.js → register-mutation-ROFE2YPC.js} +729 -702
- package/dist/cli-bundle/chunks/register-mutation-ROFE2YPC.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-mutation-ENNDUAZG.js → register-mutation-SJWMVIJ2.js} +730 -703
- package/dist/cli-bundle/chunks/register-mutation-SJWMVIJ2.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-operations-HZ6XERQG.js → register-operations-IADFVH53.js} +389 -365
- package/dist/cli-bundle/chunks/register-operations-IADFVH53.js.map +7 -0
- package/dist/cli-bundle/chunks/register-operations-MEKU3AKC.js +510 -0
- package/dist/cli-bundle/chunks/register-operations-MEKU3AKC.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-setup-ZKJ53RS7.js → register-setup-3QJY43CY.js} +128 -103
- package/dist/cli-bundle/chunks/register-setup-3QJY43CY.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-setup-P67EMBDJ.js → register-setup-AJWUSSQX.js} +129 -104
- package/dist/cli-bundle/chunks/register-setup-AJWUSSQX.js.map +1 -0
- package/dist/cli-bundle/chunks/{restore-4MHZFJ2E.js → restore-44IHMMZZ.js} +9 -9
- package/dist/cli-bundle/chunks/restore-EXHU34EU.js +17 -0
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-LB6DOLRL.js → scheduling-shortcuts-OLHNLAZY.js} +12 -12
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-UTOYKLXQ.js → scheduling-shortcuts-TSBK4AY5.js} +12 -12
- package/dist/cli-bundle/chunks/{schema-73HR2OJW.js → schema-IB2NZZWD.js} +7 -7
- package/dist/cli-bundle/chunks/{schema-U6LJKSIR.js → schema-VBCELP5G.js} +7 -7
- package/dist/cli-bundle/chunks/{search-AXPXKZER.js → search-7UBETML4.js} +10 -10
- package/dist/cli-bundle/chunks/{search-KILGT37L.js → search-R227JOL6.js} +10 -10
- package/dist/cli-bundle/chunks/{stats-W5KNVJWQ.js → stats-FAG7COEH.js} +6 -6
- package/dist/cli-bundle/chunks/{stats-PSYVVTNZ.js → stats-MCK7PLYS.js} +6 -6
- package/dist/cli-bundle/chunks/{telemetry-GAHHQTOS.js → telemetry-DRPDZMAO.js} +84 -70
- package/dist/cli-bundle/chunks/telemetry-DRPDZMAO.js.map +7 -0
- package/dist/cli-bundle/chunks/{telemetry-BZUF6H7G.js → telemetry-GVVUQSJQ.js} +85 -71
- package/dist/cli-bundle/chunks/telemetry-GVVUQSJQ.js.map +1 -0
- package/dist/cli-bundle/chunks/{test-PWDIZ255.js → test-QY44WAMR.js} +15 -15
- package/dist/cli-bundle/chunks/{test-ACD52Z3S.js → test-SY76DZTO.js} +15 -15
- package/dist/cli-bundle/chunks/test-all-QD6QAEG7.js +430 -0
- package/dist/cli-bundle/chunks/test-all-QD6QAEG7.js.map +7 -0
- package/dist/cli-bundle/chunks/test-all-USPJHXFR.js +427 -0
- package/dist/cli-bundle/chunks/test-all-USPJHXFR.js.map +1 -0
- package/dist/cli-bundle/chunks/{test-runs-UXIXPDKU.js → test-runs-MG5VIGSK.js} +185 -147
- package/dist/cli-bundle/chunks/test-runs-MG5VIGSK.js.map +1 -0
- package/dist/cli-bundle/chunks/{test-runs-PLRAZEFW.js → test-runs-QIR5MJPL.js} +184 -146
- package/dist/cli-bundle/chunks/test-runs-QIR5MJPL.js.map +7 -0
- package/dist/cli-bundle/chunks/update-A7EICML6.js +24 -0
- package/dist/cli-bundle/chunks/{update-KFX2SIAC.js → update-IKJZWLQC.js} +15 -15
- package/dist/cli-bundle/chunks/{update-many-RNSBX2TA.js → update-many-BEMTDA2X.js} +84 -69
- package/dist/cli-bundle/chunks/{update-many-RNSBX2TA.js.map → update-many-BEMTDA2X.js.map} +1 -1
- package/dist/cli-bundle/chunks/{update-many-Z5GJS5LC.js → update-many-RATAARHU.js} +83 -68
- package/dist/cli-bundle/chunks/{update-many-Z5GJS5LC.js.map → update-many-RATAARHU.js.map} +2 -2
- package/dist/cli-bundle/chunks/{upgrade-BRL6KCOJ.js → upgrade-NWMR3VQL.js} +11 -11
- package/dist/cli-bundle/chunks/{upgrade-HAK6JG2O.js → upgrade-VU46BLJZ.js} +11 -11
- package/dist/cli-bundle/chunks/{validate-X5W76YJL.js → validate-GAJ6FUSI.js} +451 -321
- package/dist/cli-bundle/chunks/validate-GAJ6FUSI.js.map +1 -0
- package/dist/cli-bundle/chunks/{validate-MTUVL5VC.js → validate-NRY6MFXN.js} +450 -320
- package/dist/cli-bundle/chunks/validate-NRY6MFXN.js.map +7 -0
- package/dist/cli-bundle/main.js +1107 -916
- package/dist/cli-bundle/main.js.map +3 -3
- package/dist/core/config/nested-settings.js +89 -67
- package/dist/core/config/nested-settings.js.map +1 -1
- package/dist/core/governance/metadata-coverage.js +20 -28
- package/dist/core/governance/metadata-coverage.js.map +1 -1
- package/dist/core/history/drift-scan.js +93 -81
- package/dist/core/history/drift-scan.js.map +1 -1
- package/dist/core/item/item-type-definition.js +14 -14
- package/dist/core/item/item-type-definition.js.map +1 -1
- package/dist/core/item/type-registry.js +114 -99
- package/dist/core/item/type-registry.js.map +1 -1
- package/dist/core/output/mutation-projection.js +42 -26
- package/dist/core/output/mutation-projection.js.map +1 -1
- package/dist/core/schema/runtime-schema.js +97 -80
- package/dist/core/schema/runtime-schema.js.map +1 -1
- package/dist/core/schema/status-defs-file.js +26 -3
- package/dist/core/schema/status-defs-file.js.map +1 -1
- package/dist/core/search/corpus.js +25 -19
- package/dist/core/search/corpus.js.map +1 -1
- package/dist/core/search/semantic-defaults.js +64 -37
- package/dist/core/search/semantic-defaults.js.map +1 -1
- package/dist/core/search/vector-stores.js +32 -17
- package/dist/core/search/vector-stores.js.map +1 -1
- package/dist/core/sentry/helpers.js +31 -28
- package/dist/core/sentry/helpers.js.map +1 -1
- package/dist/core/sentry/instrument.js +54 -43
- package/dist/core/sentry/instrument.js.map +1 -1
- package/dist/core/shared/memo.d.ts +12 -0
- package/dist/core/shared/memo.js +25 -0
- package/dist/core/shared/memo.js.map +1 -0
- package/dist/core/shared/serialization.js +24 -14
- package/dist/core/shared/serialization.js.map +1 -1
- package/dist/core/shared/time.js +26 -4
- package/dist/core/shared/time.js.map +1 -1
- package/dist/core/store/front-matter-cache.d.ts +5 -0
- package/dist/core/store/front-matter-cache.js +316 -171
- package/dist/core/store/front-matter-cache.js.map +1 -1
- package/dist/core/store/item-store.js +33 -26
- package/dist/core/store/item-store.js.map +1 -1
- package/dist/core/store/settings.js +247 -203
- package/dist/core/store/settings.js.map +1 -1
- package/dist/core/test/background-runs.js +189 -160
- package/dist/core/test/background-runs.js.map +1 -1
- package/dist/sdk/cli-contracts/flag-contracts.js +71 -99
- package/dist/sdk/cli-contracts/flag-contracts.js.map +1 -1
- package/dist/sdk/compose.js +51 -42
- package/dist/sdk/compose.js.map +1 -1
- package/docs/AGENT_GUIDE.md +2 -2
- package/docs/ARCHITECTURE.md +2 -2
- package/docs/COMMANDS.md +8 -4
- package/docs/CONFIGURATION.md +1 -1
- package/docs/EXTENSIONS.md +12 -12
- package/docs/ONBOARDING.md +4 -2
- package/docs/README.md +2 -0
- package/docs/examples/starter-extension/README.md +11 -10
- package/marketplace.json +3 -3
- package/package.json +2 -2
- package/packages/pm-beads/extensions/beads/runtime.ts +240 -167
- package/packages/pm-guide-shell/extensions/guide-shell/runtime.ts +65 -58
- package/packages/pm-todos/extensions/todos/runtime.ts +65 -42
- package/plugins/pm-claude/.claude-plugin/plugin.json +2 -2
- package/plugins/pm-claude/README.md +6 -3
- package/plugins/pm-claude/commands/pm-init.md +1 -1
- package/dist/cli-bundle/chunks/activity-AW6XVFH6.js +0 -16
- package/dist/cli-bundle/chunks/aggregate-JTEF4BP7.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-22WKIL3H.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-2D4HATP2.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-3J6JRJ3I.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-3K2M5OYU.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-3S2KT7NG.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-3VGN2UWE.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-3XZCOZ5J.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-4XOIEKSD.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-55SNVXRQ.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-5CGRF3L5.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-7R4QEMZZ.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-AXIDKKAT.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-BDTISOSD.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-BZCEN4JA.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-CF7RL6FR.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-CWFNTKQJ.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-FFMQB7WR.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-HXTQJXWT.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-IPYBJWTE.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-IZBR4NRW.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-JLM7BHI7.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-JSU5P7VS.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-JWXRETDF.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-KNPEF7QG.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-MDPEOIGN.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-NFDPYAIP.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-NUHHPVVS.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-NWMZWYYB.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-OTUHB4HS.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-RGEMWD6Q.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-RLDHZHQS.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-RMMQ74TG.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-RVUALSJF.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-TP5Q5ZD3.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-V3NOKJF2.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-VARHOHYV.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-WYDHYJPO.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-YITK2PJ6.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-ZETXE4SE.js.map +0 -1
- package/dist/cli-bundle/chunks/close-E6ZZGCJY.js +0 -14
- package/dist/cli-bundle/chunks/close-many-BG5QQIDQ.js.map +0 -7
- package/dist/cli-bundle/chunks/close-many-LDRVEQY2.js.map +0 -1
- package/dist/cli-bundle/chunks/config-DMSU64QO.js +0 -1541
- package/dist/cli-bundle/chunks/config-DMSU64QO.js.map +0 -7
- package/dist/cli-bundle/chunks/config-QH2DICD6.js +0 -1531
- package/dist/cli-bundle/chunks/config-QH2DICD6.js.map +0 -1
- package/dist/cli-bundle/chunks/contracts-HN7ABKLP.js.map +0 -7
- package/dist/cli-bundle/chunks/contracts-W4FZVVD6.js.map +0 -1
- package/dist/cli-bundle/chunks/create-OH3BDGBB.js +0 -28
- package/dist/cli-bundle/chunks/get-A7MAOHCU.js.map +0 -7
- package/dist/cli-bundle/chunks/get-DSDEKJ3L.js.map +0 -1
- package/dist/cli-bundle/chunks/health-3IPFLKXB.js.map +0 -1
- package/dist/cli-bundle/chunks/health-GZXGBZ36.js.map +0 -7
- package/dist/cli-bundle/chunks/history-WSZHY3PN.js +0 -18
- package/dist/cli-bundle/chunks/history-compact-2WRZ2WK4.js.map +0 -7
- package/dist/cli-bundle/chunks/history-compact-HR7BB4LR.js.map +0 -1
- package/dist/cli-bundle/chunks/history-redact-MP6CH7U5.js +0 -19
- package/dist/cli-bundle/chunks/history-repair-LCMOS45X.js.map +0 -7
- package/dist/cli-bundle/chunks/history-repair-XA3LC4GA.js.map +0 -1
- package/dist/cli-bundle/chunks/init-PAX32BJA.js +0 -22
- package/dist/cli-bundle/chunks/next-BCERKDUR.js.map +0 -7
- package/dist/cli-bundle/chunks/next-FYTQF6HG.js.map +0 -1
- package/dist/cli-bundle/chunks/plan-4WXEQCTN.js.map +0 -7
- package/dist/cli-bundle/chunks/plan-RKZHQVXR.js.map +0 -1
- package/dist/cli-bundle/chunks/profile-4OMM32CD.js.map +0 -7
- package/dist/cli-bundle/chunks/profile-QLER5ENE.js.map +0 -1
- package/dist/cli-bundle/chunks/register-list-query-7LV46VAU.js +0 -400
- package/dist/cli-bundle/chunks/register-list-query-7LV46VAU.js.map +0 -1
- package/dist/cli-bundle/chunks/register-list-query-SNG5PGA4.js +0 -410
- package/dist/cli-bundle/chunks/register-list-query-SNG5PGA4.js.map +0 -7
- package/dist/cli-bundle/chunks/register-mutation-ENNDUAZG.js.map +0 -1
- package/dist/cli-bundle/chunks/register-mutation-KK7PHYYU.js.map +0 -7
- package/dist/cli-bundle/chunks/register-operations-C6OWLDSH.js +0 -486
- package/dist/cli-bundle/chunks/register-operations-C6OWLDSH.js.map +0 -1
- package/dist/cli-bundle/chunks/register-operations-HZ6XERQG.js.map +0 -7
- package/dist/cli-bundle/chunks/register-setup-P67EMBDJ.js.map +0 -1
- package/dist/cli-bundle/chunks/register-setup-ZKJ53RS7.js.map +0 -7
- package/dist/cli-bundle/chunks/restore-YALDGTQR.js +0 -17
- package/dist/cli-bundle/chunks/telemetry-BZUF6H7G.js.map +0 -1
- package/dist/cli-bundle/chunks/telemetry-GAHHQTOS.js.map +0 -7
- package/dist/cli-bundle/chunks/test-all-L2MDDUCA.js +0 -358
- package/dist/cli-bundle/chunks/test-all-L2MDDUCA.js.map +0 -1
- package/dist/cli-bundle/chunks/test-all-RBZ6DLU2.js +0 -361
- package/dist/cli-bundle/chunks/test-all-RBZ6DLU2.js.map +0 -7
- package/dist/cli-bundle/chunks/test-runs-PLRAZEFW.js.map +0 -7
- package/dist/cli-bundle/chunks/test-runs-UXIXPDKU.js.map +0 -1
- package/dist/cli-bundle/chunks/update-AMRSOIWP.js +0 -24
- package/dist/cli-bundle/chunks/validate-MTUVL5VC.js.map +0 -7
- package/dist/cli-bundle/chunks/validate-X5W76YJL.js.map +0 -1
- /package/dist/cli-bundle/chunks/{activity-DBLQVIP6.js.map → activity-5YWLSPGE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{activity-AW6XVFH6.js.map → activity-BIML7K2D.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{append-LOVPGVPT.js.map → append-EZESUVJT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{append-QCFJSDFL.js.map → append-JFG4WQMG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-BHO33VBQ.js.map → chunk-3W2HJKJX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-4DUVCVLZ.js.map → chunk-4PFVUUYV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-IJYK2T43.js.map → chunk-5E7N4T2Z.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-NKZAN7BD.js.map → chunk-5IZUBZBR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-NOLPZMSV.js.map → chunk-5JIWFWOZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-6AQZPVHQ.js.map → chunk-6CDCWKSX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-LB6TP6MC.js.map → chunk-6NYJGMTY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-SLMUGTK3.js.map → chunk-7CLLC75T.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2466X6E4.js.map → chunk-7LYO6S5A.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-W4ULYO7Z.js.map → chunk-A3OQ7TFW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-GJ326ZKX.js.map → chunk-ER4ME5U2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HZZEHPRG.js.map → chunk-ERG65A2L.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-L5OEFZQG.js.map → chunk-FH2H3CBD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JPECA746.js.map → chunk-FUFFPIYA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-27BXPBAY.js.map → chunk-GUYNUXQT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-MAUKX7JC.js.map → chunk-GVJE5T7Q.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZRP4VG5U.js.map → chunk-JBZ2NTKX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-EJUDVUYZ.js.map → chunk-KEZOIPCR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HYTGA6GI.js.map → chunk-MDHWWBNZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-N74UMG5H.js.map → chunk-MEZZZBYX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-SDR5J34Q.js.map → chunk-NZ7QIUP5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-DDPTYJIM.js.map → chunk-P5L7Z2O6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-OGXLACHC.js.map → chunk-SU2E4AWU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HPPFYYOV.js.map → chunk-SU3TB4NS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-G7I7DEZA.js.map → chunk-T4XBKJ3F.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-VICZWYGZ.js.map → chunk-U5TR4N7J.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-EVMTBV6V.js.map → chunk-UMNQZS4H.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-A7FPBAQS.js.map → chunk-WJA3PXW7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-QCWF6IYD.js.map → chunk-YSDFIY7N.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-UZIWVBE6.js.map → chunk-YSGTMDWC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-64HNBBFQ.js.map → chunk-Z5F6XZXE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-AVEE5EHK.js.map → chunk-Z7RPDF2Y.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{claim-T3GCKV7C.js.map → claim-2BGBGSVI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{claim-EMQLYPRW.js.map → claim-5GU7OE67.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-E6ZZGCJY.js.map → close-6YODBUIV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-TQYAAFJP.js.map → close-AFVKPR57.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-YUXJRZPQ.js.map → comments-DNWHEBOS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-QCKR2YY2.js.map → comments-RW23R3VE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{context-B6275WPX.js.map → context-OYXRGY7S.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{context-OCZ3FJ4Z.js.map → context-PKCEHQY3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{copy-DEM4DATS.js.map → copy-6XOR3HKN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{copy-BTJOSKKT.js.map → copy-I4NCLBR4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-RLRJMRTM.js.map → create-PM45M6PE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-OH3BDGBB.js.map → create-Z7YCH3BE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{delete-BHK7VB2Z.js.map → delete-7YXHYG67.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{delete-LSVHAB4Y.js.map → delete-LPISP43T.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-XHYXWEPT.js.map → deps-N2T26FME.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-4UDFJRUA.js.map → deps-WATKQDE3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{docs-GYZNVS26.js.map → docs-6LQ3GLM7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{docs-26S44RXU.js.map → docs-Z3X6JZLT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{eval-UYF3ZPVO.js.map → eval-6DCLG52D.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{eval-PGRVIJQU.js.map → eval-Y3ZCUTHK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{extension-CPSLJQVE.js.map → extension-BNINIMT7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{extension-CXJ6RELI.js.map → extension-QWE4YYK5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{files-NQHEXUZD.js.map → files-6SGKHS6O.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{files-MBNICQFM.js.map → files-FUYPSOFJ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{focus-DWYIG7GU.js.map → focus-2Q3K76G2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{focus-XZW5423D.js.map → focus-ATLBWXXD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{gc-LPVMKJQJ.js.map → gc-RUYEMNRF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{gc-7GQYOS2G.js.map → gc-TDWSDR66.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-WSZHY3PN.js.map → history-CGNQJXFE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-NERDJNUB.js.map → history-SGRRS72R.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-O3NBCNWC.js.map → history-redact-IRL7WJ3E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-MP6CH7U5.js.map → history-redact-N3JK7VBW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{init-64XDLQJB.js.map → init-4GESW7RM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{init-PAX32BJA.js.map → init-XIDPABA4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-LPKCSJX7.js.map → learnings-4BHWFFUV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-JR6MA5TI.js.map → learnings-4FJY7WIW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{list-G5Y65VF6.js.map → list-472TIOVK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{list-DNBJVO3E.js.map → list-D7BF5CL2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-2BMU3VVQ.js.map → notes-6KNOSLIT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-6KTGO2OJ.js.map → notes-W4UEICGF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-4MHZFJ2E.js.map → restore-44IHMMZZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-YALDGTQR.js.map → restore-EXHU34EU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{scheduling-shortcuts-LB6DOLRL.js.map → scheduling-shortcuts-OLHNLAZY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{scheduling-shortcuts-UTOYKLXQ.js.map → scheduling-shortcuts-TSBK4AY5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-73HR2OJW.js.map → schema-IB2NZZWD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-U6LJKSIR.js.map → schema-VBCELP5G.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{search-AXPXKZER.js.map → search-7UBETML4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{search-KILGT37L.js.map → search-R227JOL6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{stats-W5KNVJWQ.js.map → stats-FAG7COEH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{stats-PSYVVTNZ.js.map → stats-MCK7PLYS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-PWDIZ255.js.map → test-QY44WAMR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-ACD52Z3S.js.map → test-SY76DZTO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-AMRSOIWP.js.map → update-A7EICML6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-KFX2SIAC.js.map → update-IKJZWLQC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{upgrade-BRL6KCOJ.js.map → upgrade-NWMR3VQL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{upgrade-HAK6JG2O.js.map → upgrade-VU46BLJZ.js.map} +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Implements append-only history and replay behavior for Drift Scan.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!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]="
|
|
7
|
+
!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]="91c6995a-7219-5402-b2d4-e50227bf0149")}catch(e){}}();
|
|
8
8
|
import fs from "fs/promises";
|
|
9
9
|
import { createHash } from "node:crypto";
|
|
10
10
|
import path from "node:path";
|
|
@@ -75,6 +75,62 @@ async function verifyHistoryStream(historyPath) {
|
|
|
75
75
|
contentHash,
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
|
+
function cacheMetadataMatches(cached, stat) {
|
|
79
|
+
return cached !== undefined && cached.mtime_ms === stat.mtimeMs && cached.ctime_ms === stat.ctimeMs && cached.size === stat.size;
|
|
80
|
+
}
|
|
81
|
+
async function loadFreshStreamVerification(itemId, historyPath, accumulator) {
|
|
82
|
+
try {
|
|
83
|
+
const loaded = await verifyHistoryStream(historyPath);
|
|
84
|
+
if (!loaded) {
|
|
85
|
+
accumulator.missingStreams.push(itemId);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
return loaded;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
accumulator.unreadableStreams.push(itemId);
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function resolveStreamVerification(params) {
|
|
96
|
+
const cachedContentHash = typeof params.cached?.content_hash === "string" && params.cached.content_hash.length > 0
|
|
97
|
+
? params.cached.content_hash
|
|
98
|
+
: undefined;
|
|
99
|
+
const canUseCache = cacheMetadataMatches(params.cached, params.stat) && cachedContentHash !== undefined && params.cached !== undefined;
|
|
100
|
+
if (!canUseCache || !params.cached) {
|
|
101
|
+
return {
|
|
102
|
+
verification: await loadFreshStreamVerification(params.itemId, params.historyPath, params.accumulator),
|
|
103
|
+
cacheDirty: true,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
let currentContentHash;
|
|
107
|
+
if (params.verifyCacheHitByContent) {
|
|
108
|
+
try {
|
|
109
|
+
currentContentHash = await readHistoryContentHash(params.historyPath);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
params.accumulator.unreadableStreams.push(params.itemId);
|
|
113
|
+
return { verification: null, cacheDirty: false };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
currentContentHash = cachedContentHash;
|
|
118
|
+
}
|
|
119
|
+
if (!params.verifyCacheHitByContent || currentContentHash === cachedContentHash) {
|
|
120
|
+
return {
|
|
121
|
+
verification: {
|
|
122
|
+
latestAfterHash: params.cached.latest_after_hash,
|
|
123
|
+
chainOk: params.cached.chain_ok,
|
|
124
|
+
contentHash: currentContentHash,
|
|
125
|
+
},
|
|
126
|
+
cacheDirty: false,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
verification: await loadFreshStreamVerification(params.itemId, params.historyPath, params.accumulator),
|
|
131
|
+
cacheDirty: true,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
78
134
|
/**
|
|
79
135
|
* Scan every item's history stream for drift (missing/unreadable streams, broken
|
|
80
136
|
* hash chains, and item/history hash mismatches).
|
|
@@ -86,10 +142,12 @@ async function verifyHistoryStream(historyPath) {
|
|
|
86
142
|
* trusting the stat tuple and skip rereading unchanged streams.
|
|
87
143
|
*/
|
|
88
144
|
export async function scanHistoryDrift(pmRoot, items, options = {}) {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
145
|
+
const accumulator = {
|
|
146
|
+
missingStreams: [],
|
|
147
|
+
unreadableStreams: [],
|
|
148
|
+
hashMismatches: [],
|
|
149
|
+
chainMismatches: [],
|
|
150
|
+
};
|
|
93
151
|
const cache = await loadDriftCache(pmRoot);
|
|
94
152
|
const previousEntries = cache?.entries ?? {};
|
|
95
153
|
const nextEntries = {};
|
|
@@ -105,97 +163,44 @@ export async function scanHistoryDrift(pmRoot, items, options = {}) {
|
|
|
105
163
|
}
|
|
106
164
|
catch (error) {
|
|
107
165
|
if (isErrno(error, "ENOENT")) {
|
|
108
|
-
missingStreams.push(item.id);
|
|
166
|
+
accumulator.missingStreams.push(item.id);
|
|
109
167
|
}
|
|
110
168
|
else {
|
|
111
|
-
unreadableStreams.push(item.id);
|
|
169
|
+
accumulator.unreadableStreams.push(item.id);
|
|
112
170
|
}
|
|
113
171
|
continue;
|
|
114
172
|
}
|
|
115
|
-
const loadStreamVerification = async () => {
|
|
116
|
-
try {
|
|
117
|
-
return await verifyHistoryStream(historyPath);
|
|
118
|
-
}
|
|
119
|
-
catch {
|
|
120
|
-
return "unreadable";
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
const loadFreshVerification = async () => {
|
|
124
|
-
const loaded = await loadStreamVerification();
|
|
125
|
-
if (loaded === "unreadable") {
|
|
126
|
-
unreadableStreams.push(item.id);
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
if (!loaded) {
|
|
130
|
-
missingStreams.push(item.id);
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
return loaded;
|
|
134
|
-
};
|
|
135
173
|
const cached = previousEntries[item.id];
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
cached
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
currentContentHash = await readHistoryContentHash(historyPath);
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
unreadableStreams.push(item.id);
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
currentContentHash = cachedContentHash;
|
|
156
|
-
}
|
|
157
|
-
if (!verifyCacheHitByContent || currentContentHash === cachedContentHash) {
|
|
158
|
-
verification = {
|
|
159
|
-
latestAfterHash: cached.latest_after_hash,
|
|
160
|
-
chainOk: cached.chain_ok,
|
|
161
|
-
contentHash: currentContentHash,
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
cacheDirty = true;
|
|
166
|
-
const refreshed = await loadFreshVerification();
|
|
167
|
-
if (!refreshed) {
|
|
168
|
-
continue;
|
|
169
|
-
}
|
|
170
|
-
verification = refreshed;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
cacheDirty = true;
|
|
175
|
-
const refreshed = await loadFreshVerification();
|
|
176
|
-
if (!refreshed) {
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
verification = refreshed;
|
|
174
|
+
const resolved = await resolveStreamVerification({
|
|
175
|
+
itemId: item.id,
|
|
176
|
+
historyPath,
|
|
177
|
+
stat,
|
|
178
|
+
cached,
|
|
179
|
+
verifyCacheHitByContent,
|
|
180
|
+
accumulator,
|
|
181
|
+
});
|
|
182
|
+
cacheDirty ||= resolved.cacheDirty;
|
|
183
|
+
if (!resolved.verification) {
|
|
184
|
+
continue;
|
|
180
185
|
}
|
|
181
|
-
if (!verification.chainOk) {
|
|
182
|
-
chainMismatches.push(item.id);
|
|
186
|
+
if (!resolved.verification.chainOk) {
|
|
187
|
+
accumulator.chainMismatches.push(item.id);
|
|
183
188
|
}
|
|
184
189
|
nextEntries[item.id] = {
|
|
185
190
|
mtime_ms: stat.mtimeMs,
|
|
186
191
|
ctime_ms: stat.ctimeMs,
|
|
187
192
|
size: stat.size,
|
|
188
|
-
content_hash: verification.contentHash,
|
|
189
|
-
latest_after_hash: verification.latestAfterHash,
|
|
190
|
-
chain_ok: verification.chainOk,
|
|
193
|
+
content_hash: resolved.verification.contentHash,
|
|
194
|
+
latest_after_hash: resolved.verification.latestAfterHash,
|
|
195
|
+
chain_ok: resolved.verification.chainOk,
|
|
191
196
|
};
|
|
192
197
|
const { body, ...frontMatter } = item;
|
|
193
198
|
const currentHash = hashDocument({
|
|
194
199
|
metadata: frontMatter,
|
|
195
200
|
body,
|
|
196
201
|
});
|
|
197
|
-
if (currentHash !== verification.latestAfterHash) {
|
|
198
|
-
hashMismatches.push(item.id);
|
|
202
|
+
if (currentHash !== resolved.verification.latestAfterHash) {
|
|
203
|
+
accumulator.hashMismatches.push(item.id);
|
|
199
204
|
}
|
|
200
205
|
}
|
|
201
206
|
if (cacheDirty || Object.keys(previousEntries).length !== Object.keys(nextEntries).length) {
|
|
@@ -208,8 +213,15 @@ export async function scanHistoryDrift(pmRoot, items, options = {}) {
|
|
|
208
213
|
// Best-effort cache write: a failed persist must never fail a health scan.
|
|
209
214
|
}
|
|
210
215
|
}
|
|
211
|
-
const driftedItems = [
|
|
212
|
-
|
|
216
|
+
const driftedItems = [
|
|
217
|
+
...new Set([
|
|
218
|
+
...accumulator.missingStreams,
|
|
219
|
+
...accumulator.unreadableStreams,
|
|
220
|
+
...accumulator.hashMismatches,
|
|
221
|
+
...accumulator.chainMismatches,
|
|
222
|
+
]),
|
|
223
|
+
].sort((a, b) => a.localeCompare(b));
|
|
224
|
+
return { ...accumulator, driftedItems };
|
|
213
225
|
}
|
|
214
226
|
//# sourceMappingURL=drift-scan.js.map
|
|
215
|
-
//# debugId=
|
|
227
|
+
//# debugId=91c6995a-7219-5402-b2d4-e50227bf0149
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drift-scan.js","sources":["core/history/drift-scan.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module core/history/drift-scan\n *\n * Implements append-only history and replay behavior for Drift Scan.\n */\nimport fs from \"fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport { getHistoryPath } from \"../store/paths.js\";\nimport { writeFileAtomic } from \"../fs/fs-utils.js\";\nimport { hashDocument } from \"./history.js\";\nimport { verifyHistoryChain } from \"./replay.js\";\nimport type { HistoryEntry, ItemMetadata } from \"../../types/index.js\";\n\n/**\n * Documents the drift scan result payload exchanged by command, SDK, and package integrations.\n */\nexport interface DriftScanResult {\n missingStreams: string[];\n unreadableStreams: string[];\n hashMismatches: string[];\n chainMismatches: string[];\n driftedItems: string[];\n}\n\nconst DRIFT_CACHE_VERSION = 3;\nconst DRIFT_CACHE_FILENAME = \"history-drift-cache.json\";\n\n/**\n * Controls how cached history stream verification is trusted when the file stat\n * tuple still matches a previous scan.\n */\nexport type DriftCacheHitVerification = \"content_hash\" | \"metadata\";\n\n/**\n * Documents the history drift scan options shared by health, validate, and\n * repair callers.\n */\nexport interface DriftScanOptions {\n cacheHitVerification?: DriftCacheHitVerification;\n}\n\ninterface DriftCacheEntry {\n mtime_ms: number;\n ctime_ms: number;\n size: number;\n content_hash: string;\n latest_after_hash: string;\n chain_ok: boolean;\n}\n\ninterface DriftCacheEnvelope {\n version: number;\n entries: Record<string, DriftCacheEntry>;\n}\n\nfunction getDriftCachePath(pmRoot: string): string {\n return path.join(pmRoot, \"runtime\", DRIFT_CACHE_FILENAME);\n}\n\nasync function loadDriftCache(pmRoot: string): Promise<DriftCacheEnvelope | null> {\n try {\n const raw = await fs.readFile(getDriftCachePath(pmRoot), \"utf8\");\n const parsed = JSON.parse(raw) as DriftCacheEnvelope;\n if (parsed.version !== DRIFT_CACHE_VERSION || typeof parsed.entries !== \"object\" || parsed.entries === null) {\n return null;\n }\n return parsed;\n } catch {\n return null;\n }\n}\n\nfunction isErrno(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && (error as { code?: string }).code === code;\n}\n\ninterface StreamVerification {\n latestAfterHash: string;\n chainOk: boolean;\n contentHash: string;\n}\n\nfunction hashContent(raw: string): string {\n return createHash(\"sha256\").update(raw).digest(\"hex\");\n}\n\nasync function readHistoryContentHash(historyPath: string): Promise<string> {\n const raw = await fs.readFile(historyPath, \"utf8\");\n return hashContent(raw);\n}\n\n/**\n * Read and fully verify one history stream's hash chain. Returns null for an\n * empty/missing stream (caller records it as a missing stream).\n */\nasync function verifyHistoryStream(historyPath: string): Promise<StreamVerification | null> {\n const raw = await fs.readFile(historyPath, \"utf8\");\n const contentHash = hashContent(raw);\n if (raw.trim().length === 0) {\n return null;\n }\n const entries: HistoryEntry[] = [];\n let latestAfterHash: string | null = null;\n for (const line of raw.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (trimmed.length === 0) {\n continue;\n }\n const parsed = JSON.parse(trimmed) as HistoryEntry;\n if (typeof parsed.after_hash !== \"string\" || parsed.after_hash.trim().length === 0) {\n throw new Error(\"missing after_hash\");\n }\n entries.push(parsed);\n latestAfterHash = parsed.after_hash;\n }\n /* c8 ignore start -- defensive guard for future history schema changes. */\n if (!latestAfterHash) {\n return null;\n }\n /* c8 ignore stop */\n return {\n latestAfterHash,\n chainOk: verifyHistoryChain(entries).ok,\n contentHash,\n };\n}\n\n/**\n * Scan every item's history stream for drift (missing/unreadable streams, broken\n * hash chains, and item/history hash mismatches).\n *\n * Full chain re-verification of a large history tree is the dominant cost of\n * `pm health`. We cache the per-stream verification keyed by the history file's\n * mtime/ctime/size plus content hash. Strict callers keep recomputing the\n * content hash on metadata hits; latency-sensitive health checks can opt into\n * trusting the stat tuple and skip rereading unchanged streams.\n */\nexport async function scanHistoryDrift(\n pmRoot: string,\n items: Array<ItemMetadata & { body: string }>,\n options: DriftScanOptions = {},\n): Promise<DriftScanResult> {\n const missingStreams: string[] = [];\n const unreadableStreams: string[] = [];\n const hashMismatches: string[] = [];\n const chainMismatches: string[] = [];\n\n const cache = await loadDriftCache(pmRoot);\n const previousEntries: Record<string, DriftCacheEntry> = cache?.entries ?? {};\n const nextEntries: Record<string, DriftCacheEntry> = {};\n let cacheDirty = false;\n // Metadata mode does not open a stat-matched stream, so unreadable-after-stat\n // failures are intentionally deferred to strict validate/history-repair scans.\n const verifyCacheHitByContent = options.cacheHitVerification !== \"metadata\";\n\n for (const item of items) {\n const historyPath = getHistoryPath(pmRoot, item.id);\n\n let stat: Awaited<ReturnType<typeof fs.stat>>;\n try {\n stat = await fs.stat(historyPath);\n } catch (error: unknown) {\n if (isErrno(error, \"ENOENT\")) {\n missingStreams.push(item.id);\n } else {\n unreadableStreams.push(item.id);\n }\n continue;\n }\n\n const loadStreamVerification = async (): Promise<StreamVerification | null | \"unreadable\"> => {\n try {\n return await verifyHistoryStream(historyPath);\n } catch {\n return \"unreadable\";\n }\n };\n\n const loadFreshVerification = async (): Promise<StreamVerification | null> => {\n const loaded = await loadStreamVerification();\n if (loaded === \"unreadable\") {\n unreadableStreams.push(item.id);\n return null;\n }\n if (!loaded) {\n missingStreams.push(item.id);\n return null;\n }\n return loaded;\n };\n\n const cached = previousEntries[item.id];\n let verification: StreamVerification;\n const metadataMatchesCache =\n cached !== undefined &&\n cached.mtime_ms === stat.mtimeMs &&\n cached.ctime_ms === stat.ctimeMs &&\n cached.size === stat.size;\n const cachedContentHash =\n typeof cached?.content_hash === \"string\" && cached.content_hash.length > 0 ? cached.content_hash : undefined;\n const canUseCache = metadataMatchesCache && cachedContentHash !== undefined;\n if (canUseCache && cached) {\n let currentContentHash: string;\n if (verifyCacheHitByContent) {\n try {\n currentContentHash = await readHistoryContentHash(historyPath);\n } catch {\n unreadableStreams.push(item.id);\n continue;\n }\n } else {\n currentContentHash = cachedContentHash;\n }\n if (!verifyCacheHitByContent || currentContentHash === cachedContentHash) {\n verification = {\n latestAfterHash: cached.latest_after_hash,\n chainOk: cached.chain_ok,\n contentHash: currentContentHash,\n };\n } else {\n cacheDirty = true;\n const refreshed = await loadFreshVerification();\n if (!refreshed) {\n continue;\n }\n verification = refreshed;\n }\n } else {\n cacheDirty = true;\n const refreshed = await loadFreshVerification();\n if (!refreshed) {\n continue;\n }\n verification = refreshed;\n }\n\n if (!verification.chainOk) {\n chainMismatches.push(item.id);\n }\n nextEntries[item.id] = {\n mtime_ms: stat.mtimeMs,\n ctime_ms: stat.ctimeMs,\n size: stat.size,\n content_hash: verification.contentHash,\n latest_after_hash: verification.latestAfterHash,\n chain_ok: verification.chainOk,\n };\n\n const { body, ...frontMatter } = item;\n const currentHash = hashDocument({\n metadata: frontMatter as ItemMetadata,\n body,\n });\n if (currentHash !== verification.latestAfterHash) {\n hashMismatches.push(item.id);\n }\n }\n\n if (cacheDirty || Object.keys(previousEntries).length !== Object.keys(nextEntries).length) {\n const cachePath = getDriftCachePath(pmRoot);\n try {\n await fs.mkdir(path.dirname(cachePath), { recursive: true });\n await writeFileAtomic(cachePath, JSON.stringify({ version: DRIFT_CACHE_VERSION, entries: nextEntries }));\n } catch {\n // Best-effort cache write: a failed persist must never fail a health scan.\n }\n }\n\n const driftedItems = [...new Set([...missingStreams, ...unreadableStreams, ...hashMismatches, ...chainMismatches])].sort((a, b) =>\n a.localeCompare(b),\n );\n return { missingStreams, unreadableStreams, hashMismatches, chainMismatches, driftedItems };\n}\n"],"names":[],"mappings":"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","debugId":"a928aad0-855f-5c7f-aa00-77d698ddca80"}
|
|
1
|
+
{"version":3,"file":"drift-scan.js","sources":["core/history/drift-scan.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module core/history/drift-scan\n *\n * Implements append-only history and replay behavior for Drift Scan.\n */\nimport fs from \"fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport { getHistoryPath } from \"../store/paths.js\";\nimport { writeFileAtomic } from \"../fs/fs-utils.js\";\nimport { hashDocument } from \"./history.js\";\nimport { verifyHistoryChain } from \"./replay.js\";\nimport type { HistoryEntry, ItemMetadata } from \"../../types/index.js\";\n\n/**\n * Documents the drift scan result payload exchanged by command, SDK, and package integrations.\n */\nexport interface DriftScanResult {\n missingStreams: string[];\n unreadableStreams: string[];\n hashMismatches: string[];\n chainMismatches: string[];\n driftedItems: string[];\n}\n\nconst DRIFT_CACHE_VERSION = 3;\nconst DRIFT_CACHE_FILENAME = \"history-drift-cache.json\";\n\n/**\n * Controls how cached history stream verification is trusted when the file stat\n * tuple still matches a previous scan.\n */\nexport type DriftCacheHitVerification = \"content_hash\" | \"metadata\";\n\n/**\n * Documents the history drift scan options shared by health, validate, and\n * repair callers.\n */\nexport interface DriftScanOptions {\n cacheHitVerification?: DriftCacheHitVerification;\n}\n\ninterface DriftCacheEntry {\n mtime_ms: number;\n ctime_ms: number;\n size: number;\n content_hash: string;\n latest_after_hash: string;\n chain_ok: boolean;\n}\n\ninterface DriftCacheEnvelope {\n version: number;\n entries: Record<string, DriftCacheEntry>;\n}\n\nfunction getDriftCachePath(pmRoot: string): string {\n return path.join(pmRoot, \"runtime\", DRIFT_CACHE_FILENAME);\n}\n\nasync function loadDriftCache(pmRoot: string): Promise<DriftCacheEnvelope | null> {\n try {\n const raw = await fs.readFile(getDriftCachePath(pmRoot), \"utf8\");\n const parsed = JSON.parse(raw) as DriftCacheEnvelope;\n if (parsed.version !== DRIFT_CACHE_VERSION || typeof parsed.entries !== \"object\" || parsed.entries === null) {\n return null;\n }\n return parsed;\n } catch {\n return null;\n }\n}\n\nfunction isErrno(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && (error as { code?: string }).code === code;\n}\n\ninterface StreamVerification {\n latestAfterHash: string;\n chainOk: boolean;\n contentHash: string;\n}\n\ninterface DriftScanAccumulator {\n missingStreams: string[];\n unreadableStreams: string[];\n hashMismatches: string[];\n chainMismatches: string[];\n}\n\nfunction hashContent(raw: string): string {\n return createHash(\"sha256\").update(raw).digest(\"hex\");\n}\n\nasync function readHistoryContentHash(historyPath: string): Promise<string> {\n const raw = await fs.readFile(historyPath, \"utf8\");\n return hashContent(raw);\n}\n\n/**\n * Read and fully verify one history stream's hash chain. Returns null for an\n * empty/missing stream (caller records it as a missing stream).\n */\nasync function verifyHistoryStream(historyPath: string): Promise<StreamVerification | null> {\n const raw = await fs.readFile(historyPath, \"utf8\");\n const contentHash = hashContent(raw);\n if (raw.trim().length === 0) {\n return null;\n }\n const entries: HistoryEntry[] = [];\n let latestAfterHash: string | null = null;\n for (const line of raw.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (trimmed.length === 0) {\n continue;\n }\n const parsed = JSON.parse(trimmed) as HistoryEntry;\n if (typeof parsed.after_hash !== \"string\" || parsed.after_hash.trim().length === 0) {\n throw new Error(\"missing after_hash\");\n }\n entries.push(parsed);\n latestAfterHash = parsed.after_hash;\n }\n /* c8 ignore start -- defensive guard for future history schema changes. */\n if (!latestAfterHash) {\n return null;\n }\n /* c8 ignore stop */\n return {\n latestAfterHash,\n chainOk: verifyHistoryChain(entries).ok,\n contentHash,\n };\n}\n\nfunction cacheMetadataMatches(cached: DriftCacheEntry | undefined, stat: Awaited<ReturnType<typeof fs.stat>>): boolean {\n return cached !== undefined && cached.mtime_ms === stat.mtimeMs && cached.ctime_ms === stat.ctimeMs && cached.size === stat.size;\n}\n\nasync function loadFreshStreamVerification(\n itemId: string,\n historyPath: string,\n accumulator: DriftScanAccumulator,\n): Promise<StreamVerification | null> {\n try {\n const loaded = await verifyHistoryStream(historyPath);\n if (!loaded) {\n accumulator.missingStreams.push(itemId);\n return null;\n }\n return loaded;\n } catch {\n accumulator.unreadableStreams.push(itemId);\n return null;\n }\n}\n\nasync function resolveStreamVerification(params: {\n itemId: string;\n historyPath: string;\n stat: Awaited<ReturnType<typeof fs.stat>>;\n cached: DriftCacheEntry | undefined;\n verifyCacheHitByContent: boolean;\n accumulator: DriftScanAccumulator;\n}): Promise<{ verification: StreamVerification | null; cacheDirty: boolean }> {\n const cachedContentHash =\n typeof params.cached?.content_hash === \"string\" && params.cached.content_hash.length > 0\n ? params.cached.content_hash\n : undefined;\n const canUseCache = cacheMetadataMatches(params.cached, params.stat) && cachedContentHash !== undefined && params.cached !== undefined;\n if (!canUseCache || !params.cached) {\n return {\n verification: await loadFreshStreamVerification(params.itemId, params.historyPath, params.accumulator),\n cacheDirty: true,\n };\n }\n let currentContentHash: string;\n if (params.verifyCacheHitByContent) {\n try {\n currentContentHash = await readHistoryContentHash(params.historyPath);\n } catch {\n params.accumulator.unreadableStreams.push(params.itemId);\n return { verification: null, cacheDirty: false };\n }\n } else {\n currentContentHash = cachedContentHash;\n }\n if (!params.verifyCacheHitByContent || currentContentHash === cachedContentHash) {\n return {\n verification: {\n latestAfterHash: params.cached.latest_after_hash,\n chainOk: params.cached.chain_ok,\n contentHash: currentContentHash,\n },\n cacheDirty: false,\n };\n }\n return {\n verification: await loadFreshStreamVerification(params.itemId, params.historyPath, params.accumulator),\n cacheDirty: true,\n };\n}\n\n/**\n * Scan every item's history stream for drift (missing/unreadable streams, broken\n * hash chains, and item/history hash mismatches).\n *\n * Full chain re-verification of a large history tree is the dominant cost of\n * `pm health`. We cache the per-stream verification keyed by the history file's\n * mtime/ctime/size plus content hash. Strict callers keep recomputing the\n * content hash on metadata hits; latency-sensitive health checks can opt into\n * trusting the stat tuple and skip rereading unchanged streams.\n */\nexport async function scanHistoryDrift(\n pmRoot: string,\n items: Array<ItemMetadata & { body: string }>,\n options: DriftScanOptions = {},\n): Promise<DriftScanResult> {\n const accumulator: DriftScanAccumulator = {\n missingStreams: [],\n unreadableStreams: [],\n hashMismatches: [],\n chainMismatches: [],\n };\n\n const cache = await loadDriftCache(pmRoot);\n const previousEntries: Record<string, DriftCacheEntry> = cache?.entries ?? {};\n const nextEntries: Record<string, DriftCacheEntry> = {};\n let cacheDirty = false;\n // Metadata mode does not open a stat-matched stream, so unreadable-after-stat\n // failures are intentionally deferred to strict validate/history-repair scans.\n const verifyCacheHitByContent = options.cacheHitVerification !== \"metadata\";\n\n for (const item of items) {\n const historyPath = getHistoryPath(pmRoot, item.id);\n\n let stat: Awaited<ReturnType<typeof fs.stat>>;\n try {\n stat = await fs.stat(historyPath);\n } catch (error: unknown) {\n if (isErrno(error, \"ENOENT\")) {\n accumulator.missingStreams.push(item.id);\n } else {\n accumulator.unreadableStreams.push(item.id);\n }\n continue;\n }\n\n const cached = previousEntries[item.id];\n const resolved = await resolveStreamVerification({\n itemId: item.id,\n historyPath,\n stat,\n cached,\n verifyCacheHitByContent,\n accumulator,\n });\n cacheDirty ||= resolved.cacheDirty;\n if (!resolved.verification) {\n continue;\n }\n\n if (!resolved.verification.chainOk) {\n accumulator.chainMismatches.push(item.id);\n }\n nextEntries[item.id] = {\n mtime_ms: stat.mtimeMs,\n ctime_ms: stat.ctimeMs,\n size: stat.size,\n content_hash: resolved.verification.contentHash,\n latest_after_hash: resolved.verification.latestAfterHash,\n chain_ok: resolved.verification.chainOk,\n };\n\n const { body, ...frontMatter } = item;\n const currentHash = hashDocument({\n metadata: frontMatter as ItemMetadata,\n body,\n });\n if (currentHash !== resolved.verification.latestAfterHash) {\n accumulator.hashMismatches.push(item.id);\n }\n }\n\n if (cacheDirty || Object.keys(previousEntries).length !== Object.keys(nextEntries).length) {\n const cachePath = getDriftCachePath(pmRoot);\n try {\n await fs.mkdir(path.dirname(cachePath), { recursive: true });\n await writeFileAtomic(cachePath, JSON.stringify({ version: DRIFT_CACHE_VERSION, entries: nextEntries }));\n } catch {\n // Best-effort cache write: a failed persist must never fail a health scan.\n }\n }\n\n const driftedItems = [\n ...new Set([\n ...accumulator.missingStreams,\n ...accumulator.unreadableStreams,\n ...accumulator.hashMismatches,\n ...accumulator.chainMismatches,\n ]),\n ].sort((a, b) => a.localeCompare(b));\n return { ...accumulator, driftedItems };\n}\n"],"names":[],"mappings":"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","debugId":"91c6995a-7219-5402-b2d4-e50227bf0149"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
/** Dedupe + sort a string list: trim, drop blanks, unique, locale-sorted. */
|
|
17
17
|
|
|
18
|
-
!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]="
|
|
18
|
+
!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]="a5621ca3-a40f-59d1-9bce-02c10afcc247")}catch(e){}}();
|
|
19
19
|
export function normalizeItemTypeStringList(values) {
|
|
20
20
|
return [...new Set((values ?? []).map((value) => value.trim()).filter((value) => value.length > 0))].sort((left, right) => left.localeCompare(right));
|
|
21
21
|
}
|
|
@@ -80,6 +80,13 @@ export function normalizeItemTypeCommandOptionPolicies(policies, resolvePolicyCo
|
|
|
80
80
|
? left.option.localeCompare(right.option)
|
|
81
81
|
: left.command.localeCompare(right.command));
|
|
82
82
|
}
|
|
83
|
+
function normalizeOptionalStringList(values, preservePresence) {
|
|
84
|
+
return preservePresence ? normalizeItemTypeStringList(values) : undefined;
|
|
85
|
+
}
|
|
86
|
+
function optionalNonEmptyString(value) {
|
|
87
|
+
const normalized = value?.trim();
|
|
88
|
+
return normalized && normalized.length > 0 ? normalized : undefined;
|
|
89
|
+
}
|
|
83
90
|
/**
|
|
84
91
|
* Normalize a full {@link ItemTypeDefinition}, returning null when the name is blank.
|
|
85
92
|
*
|
|
@@ -98,9 +105,6 @@ export function normalizeItemTypeDefinition(definition, options = {}) {
|
|
|
98
105
|
const hasRequiredCreateRepeatables = definition.required_create_repeatables !== undefined;
|
|
99
106
|
const hasOptions = definition.options !== undefined;
|
|
100
107
|
const hasCommandOptionPolicies = definition.command_option_policies !== undefined;
|
|
101
|
-
const folder = definition.folder?.trim();
|
|
102
|
-
const description = definition.description?.trim();
|
|
103
|
-
const defaultStatus = definition.default_status?.trim();
|
|
104
108
|
const aliases = normalizeItemTypeStringList(definition.aliases);
|
|
105
109
|
const normalizedOptions = (definition.options ?? [])
|
|
106
110
|
.map((option) => normalizeItemTypeOption(option))
|
|
@@ -109,19 +113,15 @@ export function normalizeItemTypeDefinition(definition, options = {}) {
|
|
|
109
113
|
const commandOptionPolicies = normalizeItemTypeCommandOptionPolicies(definition.command_option_policies, resolvePolicyCommand);
|
|
110
114
|
return {
|
|
111
115
|
name,
|
|
112
|
-
description:
|
|
113
|
-
default_status:
|
|
114
|
-
folder:
|
|
116
|
+
description: optionalNonEmptyString(definition.description),
|
|
117
|
+
default_status: optionalNonEmptyString(definition.default_status),
|
|
118
|
+
folder: optionalNonEmptyString(definition.folder),
|
|
115
119
|
aliases: aliases.length > 0 ? aliases : undefined,
|
|
116
|
-
required_create_fields: hasRequiredCreateFields
|
|
117
|
-
|
|
118
|
-
: undefined,
|
|
119
|
-
required_create_repeatables: hasRequiredCreateRepeatables
|
|
120
|
-
? normalizeItemTypeStringList(definition.required_create_repeatables)
|
|
121
|
-
: undefined,
|
|
120
|
+
required_create_fields: normalizeOptionalStringList(definition.required_create_fields, hasRequiredCreateFields),
|
|
121
|
+
required_create_repeatables: normalizeOptionalStringList(definition.required_create_repeatables, hasRequiredCreateRepeatables),
|
|
122
122
|
options: hasOptions ? normalizedOptions : undefined,
|
|
123
123
|
command_option_policies: hasCommandOptionPolicies ? commandOptionPolicies : undefined,
|
|
124
124
|
};
|
|
125
125
|
}
|
|
126
126
|
//# sourceMappingURL=item-type-definition.js.map
|
|
127
|
-
//# debugId=
|
|
127
|
+
//# debugId=a5621ca3-a40f-59d1-9bce-02c10afcc247
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"item-type-definition.js","sources":["core/item/item-type-definition.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module core/item/item-type-definition\n *\n * Defines item parsing, formatting, and lifecycle helpers for Item Type Definition.\n */\nimport type {\n ItemTypeCommandOptionPolicy,\n ItemTypeDefinition,\n ItemTypeOptionDefinition,\n} from \"../../types/index.js\";\n\n/**\n * Shared, pure normalization for {@link ItemTypeDefinition} objects, single-sourced\n * across the runtime item-type registry and settings persistence (pm-v798).\n *\n * The only genuine difference between the two callers is how a command-option\n * policy's `command` field is resolved:\n * - the runtime registry consumes untrusted extension/file definitions, so it\n * must trim+lowercase and reject anything that is not \"create\"/\"update\";\n * - settings persistence operates on already-validated definitions, so it keeps\n * the typed `command` value verbatim.\n *\n * That single difference is injected via {@link NormalizeItemTypeDefinitionOptions.resolvePolicyCommand};\n * everything else (name trim, optional folder, aliases, required_create_* fields,\n * options normalization, policy dedupe key + stable sort) is shared.\n */\n\n/** Dedupe + sort a string list: trim, drop blanks, unique, locale-sorted. */\nexport function normalizeItemTypeStringList(values: string[] | undefined): string[] {\n return [...new Set((values ?? []).map((value) => value.trim()).filter((value) => value.length > 0))].sort(\n (left, right) => left.localeCompare(right),\n );\n}\n\n/** Normalize one type-option definition, or null when its key is blank. */\nexport function normalizeItemTypeOption(option: ItemTypeOptionDefinition): ItemTypeOptionDefinition | null {\n const key = option.key.trim();\n if (key.length === 0) {\n return null;\n }\n const aliases = normalizeItemTypeStringList(option.aliases);\n const description = option.description?.trim();\n return {\n key,\n values: normalizeItemTypeStringList(option.values),\n required: option.required === true ? true : undefined,\n aliases: aliases.length > 0 ? aliases : undefined,\n description: description && description.length > 0 ? description : undefined,\n };\n}\n\n/**\n * Resolves a raw policy `command` value to the canonical \"create\"/\"update\" type,\n * or null to drop the policy. Lets each layer plug in its own strictness.\n */\nexport type ResolvePolicyCommand = (command: string) => ItemTypeCommandOptionPolicy[\"command\"] | null;\n\n/**\n * Pass-through resolver used by settings persistence: the value is already typed\n * \"create\" | \"update\" by the settings validator, so it is kept verbatim.\n */\nexport const keepPolicyCommand: ResolvePolicyCommand = (command) =>\n command as ItemTypeCommandOptionPolicy[\"command\"];\n\n/**\n * Strict resolver used by the runtime registry: trims + lowercases and rejects\n * anything other than \"create\"/\"update\".\n */\nexport const strictPolicyCommand: ResolvePolicyCommand = (command) => {\n const normalized = command.trim().toLowerCase();\n return normalized === \"create\" || normalized === \"update\" ? normalized : null;\n};\n\n/** Normalize one command-option policy, or null when invalid (blank option / rejected command). */\nexport function normalizeItemTypeCommandOptionPolicy(\n policy: ItemTypeCommandOptionPolicy,\n resolvePolicyCommand: ResolvePolicyCommand,\n): ItemTypeCommandOptionPolicy | null {\n const command = resolvePolicyCommand(policy.command);\n if (command === null) {\n return null;\n }\n const option = policy.option.trim();\n if (option.length === 0) {\n return null;\n }\n return {\n command,\n option,\n required: policy.required,\n visible: policy.visible,\n enabled: policy.enabled,\n };\n}\n\n/** Dedupe by `${command}:${option-lowercased}` and stable-sort by command then option. */\nexport function normalizeItemTypeCommandOptionPolicies(\n policies: ItemTypeCommandOptionPolicy[] | undefined,\n resolvePolicyCommand: ResolvePolicyCommand,\n): ItemTypeCommandOptionPolicy[] {\n const dedupedByKey = new Map<string, ItemTypeCommandOptionPolicy>();\n for (const policy of policies ?? []) {\n const normalized = normalizeItemTypeCommandOptionPolicy(policy, resolvePolicyCommand);\n if (!normalized) {\n continue;\n }\n dedupedByKey.set(`${normalized.command}:${normalized.option.toLowerCase()}`, normalized);\n }\n return [...dedupedByKey.values()].sort((left, right) =>\n left.command === right.command\n ? left.option.localeCompare(right.option)\n : left.command.localeCompare(right.command),\n );\n}\n\n/**\n * Documents the normalize item type definition options payload exchanged by command, SDK, and package integrations.\n */\nexport interface NormalizeItemTypeDefinitionOptions {\n /** How to resolve a raw policy `command` value (defaults to {@link keepPolicyCommand}). */\n resolvePolicyCommand?: ResolvePolicyCommand;\n}\n\n/**\n * Normalize a full {@link ItemTypeDefinition}, returning null when the name is blank.\n *\n * Optional collection fields (`folder`, `aliases`, `required_create_fields`,\n * `required_create_repeatables`, `options`, `command_option_policies`) are only\n * emitted when present on the input (presence-preserving) so the distinction\n * between \"unset\" and \"set-but-empty\" survives the round-trip.\n */\nexport function normalizeItemTypeDefinition(\n definition: ItemTypeDefinition,\n options: NormalizeItemTypeDefinitionOptions = {},\n): ItemTypeDefinition | null {\n const resolvePolicyCommand = options.resolvePolicyCommand ?? keepPolicyCommand;\n const name = definition.name.trim();\n if (name.length === 0) {\n return null;\n }\n\n const hasRequiredCreateFields = definition.required_create_fields !== undefined;\n const hasRequiredCreateRepeatables = definition.required_create_repeatables !== undefined;\n const hasOptions = definition.options !== undefined;\n const hasCommandOptionPolicies = definition.command_option_policies !== undefined;\n\n const folder = definition.folder?.trim();\n const description = definition.description?.trim();\n const defaultStatus = definition.default_status?.trim();\n const aliases = normalizeItemTypeStringList(definition.aliases);\n const normalizedOptions = (definition.options ?? [])\n .map((option) => normalizeItemTypeOption(option))\n .filter((option): option is ItemTypeOptionDefinition => option !== null)\n .sort((left, right) => left.key.localeCompare(right.key));\n const commandOptionPolicies = normalizeItemTypeCommandOptionPolicies(\n definition.command_option_policies,\n resolvePolicyCommand,\n );\n\n return {\n name,\n description: description && description.length > 0 ? description : undefined,\n default_status: defaultStatus && defaultStatus.length > 0 ? defaultStatus : undefined,\n folder: folder && folder.length > 0 ? folder : undefined,\n aliases: aliases.length > 0 ? aliases : undefined,\n required_create_fields: hasRequiredCreateFields\n ? normalizeItemTypeStringList(definition.required_create_fields)\n : undefined,\n required_create_repeatables: hasRequiredCreateRepeatables\n ? normalizeItemTypeStringList(definition.required_create_repeatables)\n : undefined,\n options: hasOptions ? normalizedOptions : undefined,\n command_option_policies: hasCommandOptionPolicies ? commandOptionPolicies : undefined,\n };\n}\n"],"names":[],"mappings":"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","debugId":"257435ee-2ef3-5736-a403-57d6265cf280"}
|
|
1
|
+
{"version":3,"file":"item-type-definition.js","sources":["core/item/item-type-definition.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module core/item/item-type-definition\n *\n * Defines item parsing, formatting, and lifecycle helpers for Item Type Definition.\n */\nimport type {\n ItemTypeCommandOptionPolicy,\n ItemTypeDefinition,\n ItemTypeOptionDefinition,\n} from \"../../types/index.js\";\n\n/**\n * Shared, pure normalization for {@link ItemTypeDefinition} objects, single-sourced\n * across the runtime item-type registry and settings persistence (pm-v798).\n *\n * The only genuine difference between the two callers is how a command-option\n * policy's `command` field is resolved:\n * - the runtime registry consumes untrusted extension/file definitions, so it\n * must trim+lowercase and reject anything that is not \"create\"/\"update\";\n * - settings persistence operates on already-validated definitions, so it keeps\n * the typed `command` value verbatim.\n *\n * That single difference is injected via {@link NormalizeItemTypeDefinitionOptions.resolvePolicyCommand};\n * everything else (name trim, optional folder, aliases, required_create_* fields,\n * options normalization, policy dedupe key + stable sort) is shared.\n */\n\n/** Dedupe + sort a string list: trim, drop blanks, unique, locale-sorted. */\nexport function normalizeItemTypeStringList(values: string[] | undefined): string[] {\n return [...new Set((values ?? []).map((value) => value.trim()).filter((value) => value.length > 0))].sort(\n (left, right) => left.localeCompare(right),\n );\n}\n\n/** Normalize one type-option definition, or null when its key is blank. */\nexport function normalizeItemTypeOption(option: ItemTypeOptionDefinition): ItemTypeOptionDefinition | null {\n const key = option.key.trim();\n if (key.length === 0) {\n return null;\n }\n const aliases = normalizeItemTypeStringList(option.aliases);\n const description = option.description?.trim();\n return {\n key,\n values: normalizeItemTypeStringList(option.values),\n required: option.required === true ? true : undefined,\n aliases: aliases.length > 0 ? aliases : undefined,\n description: description && description.length > 0 ? description : undefined,\n };\n}\n\n/**\n * Resolves a raw policy `command` value to the canonical \"create\"/\"update\" type,\n * or null to drop the policy. Lets each layer plug in its own strictness.\n */\nexport type ResolvePolicyCommand = (command: string) => ItemTypeCommandOptionPolicy[\"command\"] | null;\n\n/**\n * Pass-through resolver used by settings persistence: the value is already typed\n * \"create\" | \"update\" by the settings validator, so it is kept verbatim.\n */\nexport const keepPolicyCommand: ResolvePolicyCommand = (command) =>\n command as ItemTypeCommandOptionPolicy[\"command\"];\n\n/**\n * Strict resolver used by the runtime registry: trims + lowercases and rejects\n * anything other than \"create\"/\"update\".\n */\nexport const strictPolicyCommand: ResolvePolicyCommand = (command) => {\n const normalized = command.trim().toLowerCase();\n return normalized === \"create\" || normalized === \"update\" ? normalized : null;\n};\n\n/** Normalize one command-option policy, or null when invalid (blank option / rejected command). */\nexport function normalizeItemTypeCommandOptionPolicy(\n policy: ItemTypeCommandOptionPolicy,\n resolvePolicyCommand: ResolvePolicyCommand,\n): ItemTypeCommandOptionPolicy | null {\n const command = resolvePolicyCommand(policy.command);\n if (command === null) {\n return null;\n }\n const option = policy.option.trim();\n if (option.length === 0) {\n return null;\n }\n return {\n command,\n option,\n required: policy.required,\n visible: policy.visible,\n enabled: policy.enabled,\n };\n}\n\n/** Dedupe by `${command}:${option-lowercased}` and stable-sort by command then option. */\nexport function normalizeItemTypeCommandOptionPolicies(\n policies: ItemTypeCommandOptionPolicy[] | undefined,\n resolvePolicyCommand: ResolvePolicyCommand,\n): ItemTypeCommandOptionPolicy[] {\n const dedupedByKey = new Map<string, ItemTypeCommandOptionPolicy>();\n for (const policy of policies ?? []) {\n const normalized = normalizeItemTypeCommandOptionPolicy(policy, resolvePolicyCommand);\n if (!normalized) {\n continue;\n }\n dedupedByKey.set(`${normalized.command}:${normalized.option.toLowerCase()}`, normalized);\n }\n return [...dedupedByKey.values()].sort((left, right) =>\n left.command === right.command\n ? left.option.localeCompare(right.option)\n : left.command.localeCompare(right.command),\n );\n}\n\n/**\n * Documents the normalize item type definition options payload exchanged by command, SDK, and package integrations.\n */\nexport interface NormalizeItemTypeDefinitionOptions {\n /** How to resolve a raw policy `command` value (defaults to {@link keepPolicyCommand}). */\n resolvePolicyCommand?: ResolvePolicyCommand;\n}\n\nfunction normalizeOptionalStringList(\n values: string[] | undefined,\n preservePresence: boolean,\n): string[] | undefined {\n return preservePresence ? normalizeItemTypeStringList(values) : undefined;\n}\n\nfunction optionalNonEmptyString(value: string | undefined): string | undefined {\n const normalized = value?.trim();\n return normalized && normalized.length > 0 ? normalized : undefined;\n}\n\n/**\n * Normalize a full {@link ItemTypeDefinition}, returning null when the name is blank.\n *\n * Optional collection fields (`folder`, `aliases`, `required_create_fields`,\n * `required_create_repeatables`, `options`, `command_option_policies`) are only\n * emitted when present on the input (presence-preserving) so the distinction\n * between \"unset\" and \"set-but-empty\" survives the round-trip.\n */\nexport function normalizeItemTypeDefinition(\n definition: ItemTypeDefinition,\n options: NormalizeItemTypeDefinitionOptions = {},\n): ItemTypeDefinition | null {\n const resolvePolicyCommand = options.resolvePolicyCommand ?? keepPolicyCommand;\n const name = definition.name.trim();\n if (name.length === 0) {\n return null;\n }\n\n const hasRequiredCreateFields = definition.required_create_fields !== undefined;\n const hasRequiredCreateRepeatables = definition.required_create_repeatables !== undefined;\n const hasOptions = definition.options !== undefined;\n const hasCommandOptionPolicies = definition.command_option_policies !== undefined;\n\n const aliases = normalizeItemTypeStringList(definition.aliases);\n const normalizedOptions = (definition.options ?? [])\n .map((option) => normalizeItemTypeOption(option))\n .filter((option): option is ItemTypeOptionDefinition => option !== null)\n .sort((left, right) => left.key.localeCompare(right.key));\n const commandOptionPolicies = normalizeItemTypeCommandOptionPolicies(\n definition.command_option_policies,\n resolvePolicyCommand,\n );\n\n return {\n name,\n description: optionalNonEmptyString(definition.description),\n default_status: optionalNonEmptyString(definition.default_status),\n folder: optionalNonEmptyString(definition.folder),\n aliases: aliases.length > 0 ? aliases : undefined,\n required_create_fields: normalizeOptionalStringList(definition.required_create_fields, hasRequiredCreateFields),\n required_create_repeatables: normalizeOptionalStringList(\n definition.required_create_repeatables,\n hasRequiredCreateRepeatables,\n ),\n options: hasOptions ? normalizedOptions : undefined,\n command_option_policies: hasCommandOptionPolicies ? commandOptionPolicies : undefined,\n };\n}\n"],"names":[],"mappings":"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","debugId":"a5621ca3-a40f-59d1-9bce-02c10afcc247"}
|