@unbrained/pm-cli 2026.7.20 → 2026.7.21
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 +11 -0
- package/dist/cli/commander-usage.d.ts +1 -1
- package/dist/cli/commander-usage.js +5 -5
- package/dist/cli/commander-usage.js.map +1 -1
- package/dist/cli/commands/completion.js +13 -5
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/contracts.js +4 -3
- package/dist/cli/commands/contracts.js.map +1 -1
- package/dist/cli/error-guidance.d.ts +2 -0
- package/dist/cli/error-guidance.js +7 -2
- package/dist/cli/error-guidance.js.map +1 -1
- package/dist/cli/main.d.ts +1 -5
- package/dist/cli/main.js +12 -50
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/register-list-query.js +13 -3
- package/dist/cli/register-list-query.js.map +1 -1
- package/dist/cli/register-mutation.js +45 -3
- package/dist/cli/register-mutation.js.map +1 -1
- package/dist/cli/register-structured-mutation.d.ts +14 -0
- package/dist/cli/register-structured-mutation.js +62 -0
- package/dist/cli/register-structured-mutation.js.map +1 -0
- package/dist/cli/registration-helpers.js +5 -3
- package/dist/cli/registration-helpers.js.map +1 -1
- package/dist/cli-bundle/bundle-manifest.json +280 -296
- package/dist/cli-bundle/chunks/{append-E6V54WOQ.js → append-7OVFYR3C.js} +3 -3
- package/dist/cli-bundle/chunks/{append-NNJ3EFIT.js → append-DFETHAZL.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-C3KD7U3T.js → chunk-2L6ZP22J.js} +241 -10
- package/dist/cli-bundle/chunks/chunk-2L6ZP22J.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-KZEANWJS.js → chunk-4PUUNQDV.js} +98 -30
- package/dist/cli-bundle/chunks/chunk-4PUUNQDV.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-RDV4ZFYS.js → chunk-4QOB7L7I.js} +7 -9
- package/dist/cli-bundle/chunks/{chunk-RDV4ZFYS.js.map → chunk-4QOB7L7I.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-3LPFHE3P.js → chunk-4QSQ6XDK.js} +62 -20
- package/dist/cli-bundle/chunks/chunk-4QSQ6XDK.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-QJKL5PHS.js → chunk-7656MAUL.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-3AO5VSDR.js → chunk-7RW4JCU2.js} +328 -6
- package/dist/cli-bundle/chunks/chunk-7RW4JCU2.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-X6K5XTTN.js → chunk-7W2UAXXT.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-SSKOQNMS.js → chunk-ABWCF646.js} +9 -11
- package/dist/cli-bundle/chunks/{chunk-SSKOQNMS.js.map → chunk-ABWCF646.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-WVA4DVNV.js → chunk-ADBTSVGK.js} +71 -33
- package/dist/cli-bundle/chunks/chunk-ADBTSVGK.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-J4FBIFU6.js → chunk-AELMUANP.js} +12 -6
- package/dist/cli-bundle/chunks/chunk-AELMUANP.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-4F6BWJ4J.js → chunk-AMJPSANK.js} +57 -36
- package/dist/cli-bundle/chunks/chunk-AMJPSANK.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-6VIJ7UA5.js → chunk-AS4SAZ5R.js} +850 -819
- package/dist/cli-bundle/chunks/chunk-AS4SAZ5R.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-SG74J6MV.js → chunk-ATBCUC7Y.js} +574 -5
- package/dist/cli-bundle/chunks/chunk-ATBCUC7Y.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-5OK4UGFV.js → chunk-BXNDKOR2.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-KSPWRNVP.js → chunk-CPX275C6.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-JH2ZSLO3.js → chunk-DZRV2OPA.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-L7BH7IWU.js → chunk-E5XMKOSB.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-CQTQKUUV.js → chunk-EWJWSNRU.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-DAQ45GCS.js → chunk-F2LBF7XJ.js} +22 -15
- package/dist/cli-bundle/chunks/chunk-F2LBF7XJ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-6XMUURSS.js → chunk-FJIFFBJX.js} +64 -33
- package/dist/cli-bundle/chunks/chunk-FJIFFBJX.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-E7ICD63T.js → chunk-FO6OSVEN.js} +4 -6
- package/dist/cli-bundle/chunks/{chunk-E7ICD63T.js.map → chunk-FO6OSVEN.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-3MCTMJXI.js → chunk-FPBMLYPI.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-UZDQXNUB.js → chunk-FSE2IKJQ.js} +46 -5
- package/dist/cli-bundle/chunks/chunk-FSE2IKJQ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-IX677TRO.js → chunk-GKX4NJ7U.js} +8 -10
- package/dist/cli-bundle/chunks/{chunk-IX677TRO.js.map → chunk-GKX4NJ7U.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-DVDBQA3B.js → chunk-GTK4DTEW.js} +5 -5
- package/dist/cli-bundle/chunks/chunk-H7EAER5L.js +974 -0
- package/dist/cli-bundle/chunks/chunk-H7EAER5L.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-5UX66S6U.js → chunk-ICDAQ4TD.js} +316 -8
- package/dist/cli-bundle/chunks/chunk-ICDAQ4TD.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-YQQNAKW3.js → chunk-JFD5LPMI.js} +6 -8
- package/dist/cli-bundle/chunks/{chunk-YQQNAKW3.js.map → chunk-JFD5LPMI.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-QANSTTC7.js → chunk-JXCW2TI2.js} +6 -8
- package/dist/cli-bundle/chunks/{chunk-QANSTTC7.js.map → chunk-JXCW2TI2.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-GSJSM5BJ.js → chunk-K36WV5J6.js} +76 -13
- package/dist/cli-bundle/chunks/chunk-K36WV5J6.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-GVI6FAFG.js → chunk-K55VMLSS.js} +7 -5
- package/dist/cli-bundle/chunks/chunk-K55VMLSS.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-GIQSU6S2.js → chunk-KBLZ3AA5.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-XJF7CDNH.js → chunk-KH44WBAT.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-GV2262OF.js → chunk-LAV26CQG.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-VDO2JMD4.js → chunk-LVC72YRD.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-3VY6MIEO.js → chunk-LZYP423P.js} +35 -6
- package/dist/cli-bundle/chunks/chunk-LZYP423P.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-ZYPFOO3L.js → chunk-MATHDCGG.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-OV7MSW3I.js → chunk-MWQ2HC2A.js} +99 -31
- package/dist/cli-bundle/chunks/chunk-MWQ2HC2A.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-NHT3F4WZ.js → chunk-NUF7ROFH.js} +840 -816
- package/dist/cli-bundle/chunks/chunk-NUF7ROFH.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-AOEOYL3S.js → chunk-O4BCOJTZ.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-RJO3YAFM.js → chunk-OCUBRA6D.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-5IZJWSDB.js → chunk-OG5DVFMA.js} +22 -15
- package/dist/cli-bundle/chunks/chunk-OG5DVFMA.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-I577UHC7.js → chunk-OR42SO64.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-ZOJ3LR7O.js → chunk-OY7DMU5P.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-HEWM6CEN.js → chunk-P7MTHPJQ.js} +50 -9
- package/dist/cli-bundle/chunks/chunk-P7MTHPJQ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-2BO4CA46.js → chunk-PFNHX655.js} +236 -12
- package/dist/cli-bundle/chunks/{chunk-2BO4CA46.js.map → chunk-PFNHX655.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-ZV2NTVMJ.js → chunk-PONKZPCJ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-THAOZG4U.js → chunk-PQSEQD6E.js} +8 -6
- package/dist/cli-bundle/chunks/chunk-PQSEQD6E.js.map +1 -0
- package/dist/cli-bundle/chunks/chunk-PWDEHT3L.js +991 -0
- package/dist/cli-bundle/chunks/chunk-PWDEHT3L.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-UX6SSO2I.js → chunk-PZC2FUOQ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-WUVEBQW6.js → chunk-QG4GFLQ6.js} +3 -5
- package/dist/cli-bundle/chunks/{chunk-WUVEBQW6.js.map → chunk-QG4GFLQ6.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-VQIHNHMJ.js → chunk-QIH77CAG.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-R3EWPG4A.js → chunk-QJIKE24M.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-QLZ643FM.js → chunk-QOOTOD3W.js} +10 -12
- package/dist/cli-bundle/chunks/{chunk-QLZ643FM.js.map → chunk-QOOTOD3W.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-MYSS5H2A.js → chunk-R3P6FZJW.js} +5 -7
- package/dist/cli-bundle/chunks/{chunk-MYSS5H2A.js.map → chunk-R3P6FZJW.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-G3COA6GS.js → chunk-RNPZYNHS.js} +56 -35
- package/dist/cli-bundle/chunks/chunk-RNPZYNHS.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-T44FMVRL.js → chunk-RPESLSO5.js} +62 -20
- package/dist/cli-bundle/chunks/chunk-RPESLSO5.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-INSTSQNZ.js → chunk-SY4SFZSD.js} +595 -3
- package/dist/cli-bundle/chunks/chunk-SY4SFZSD.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-HB3P4M52.js → chunk-TRSHFPRZ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-HRW7GF6T.js → chunk-UCBDQI5E.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-4U4Z6AHI.js → chunk-V22ZPOKN.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-JM6YAXTR.js → chunk-VHXHVTUU.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-LPEYZRUR.js → chunk-VJQG4BIM.js} +35 -6
- package/dist/cli-bundle/chunks/chunk-VJQG4BIM.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-D6NXDNP3.js → chunk-VLRGDBLY.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-JAPE62Y5.js → chunk-VNTCM3VW.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-FDHPAVVB.js → chunk-VXOOB6YX.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-GFQP7HAZ.js → chunk-VZIZB6QH.js} +3 -5
- package/dist/cli-bundle/chunks/{chunk-GFQP7HAZ.js.map → chunk-VZIZB6QH.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-HQ3SB4CN.js → chunk-X3W65QK3.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-RZJLNXFG.js → chunk-XJTABV3X.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-GVT754PX.js → chunk-YCIUJJOD.js} +11 -5
- package/dist/cli-bundle/chunks/chunk-YCIUJJOD.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-IJNK6WW2.js → chunk-Z75ONV25.js} +75 -12
- package/dist/cli-bundle/chunks/chunk-Z75ONV25.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-4L23AGQ7.js → chunk-Z7VWXXJM.js} +5 -7
- package/dist/cli-bundle/chunks/{chunk-4L23AGQ7.js.map → chunk-Z7VWXXJM.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-YBT7O4KT.js → chunk-ZTVA4KLN.js} +4 -6
- package/dist/cli-bundle/chunks/{chunk-YBT7O4KT.js.map → chunk-ZTVA4KLN.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-TYHJDFYW.js → chunk-ZVZGXPQ5.js} +2 -2
- package/dist/cli-bundle/chunks/{close-many-SDA426VT.js → close-many-5RZXVN4J.js} +5 -6
- package/dist/cli-bundle/chunks/{close-many-UTZANOCQ.js → close-many-RZVTUGBG.js} +5 -6
- package/dist/cli-bundle/chunks/{comments-LZN6FXXC.js → comments-TPU7QRBL.js} +4 -4
- package/dist/cli-bundle/chunks/{comments-VBQ345ND.js → comments-Z4KV6FU3.js} +4 -4
- package/dist/cli-bundle/chunks/{create-GG4RBCGC.js → create-EIFBIVNQ.js} +6 -6
- package/dist/cli-bundle/chunks/{create-JBC5KUW6.js → create-RGSPN5GD.js} +6 -6
- package/dist/cli-bundle/chunks/{deps-FI4O6NQS.js → deps-UH5EQQUY.js} +3 -3
- package/dist/cli-bundle/chunks/{deps-DELOO4TL.js → deps-YG7UF3VR.js} +3 -3
- package/dist/cli-bundle/chunks/{docs-6Z2MP526.js → docs-G32TK6XS.js} +4 -4
- package/dist/cli-bundle/chunks/{docs-2UYBP5D6.js → docs-JWWNRC27.js} +4 -4
- package/dist/cli-bundle/chunks/{files-HKEAN5MA.js → files-3H32UQ4K.js} +4 -4
- package/dist/cli-bundle/chunks/{files-HEUGSJZL.js → files-4ALMCSKB.js} +4 -4
- package/dist/cli-bundle/chunks/{history-compact-7NDVP3PT.js → history-compact-77BT2LUB.js} +3 -4
- package/dist/cli-bundle/chunks/{history-compact-65YVN5DB.js → history-compact-VCKGTX64.js} +3 -4
- package/dist/cli-bundle/chunks/{history-redact-7YBL4XSG.js → history-redact-LJPZPNFA.js} +2 -3
- package/dist/cli-bundle/chunks/{history-redact-IZGNJBU4.js → history-redact-PWTTJ3XS.js} +2 -3
- package/dist/cli-bundle/chunks/{history-repair-7M4PYQUH.js → history-repair-I7CBNCV3.js} +5 -6
- package/dist/cli-bundle/chunks/{history-repair-GNGETJLI.js → history-repair-YTDZRK5E.js} +5 -6
- package/dist/cli-bundle/chunks/{learnings-3YXDRWFT.js → learnings-CYNOICKR.js} +4 -4
- package/dist/cli-bundle/chunks/{learnings-ALC6IMNL.js → learnings-KTYW3AL7.js} +4 -4
- package/dist/cli-bundle/chunks/{notes-7JMLQ447.js → notes-FGO63FXL.js} +4 -4
- package/dist/cli-bundle/chunks/{notes-JFCLTC5C.js → notes-ZERD3KB2.js} +4 -4
- package/dist/cli-bundle/chunks/{plan-T3XB3WTK.js → plan-OFJUBIM5.js} +7 -7
- package/dist/cli-bundle/chunks/{plan-KOIPWVOZ.js → plan-SGCDDTYR.js} +7 -7
- package/dist/cli-bundle/chunks/{profile-OILJHKUW.js → profile-3THJPIQY.js} +4 -5
- package/dist/cli-bundle/chunks/{profile-RJXA7PGS.js → profile-XEZAMMBW.js} +4 -5
- package/dist/cli-bundle/chunks/{register-list-query-CFVG75P3.js → register-list-query-BR435Q2H.js} +19 -16
- package/dist/cli-bundle/chunks/register-list-query-BR435Q2H.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-list-query-E7UVY4TN.js → register-list-query-RWTWLOBE.js} +18 -15
- package/dist/cli-bundle/chunks/register-list-query-RWTWLOBE.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-mutation-IQ55E25C.js → register-mutation-HLWC2WNP.js} +167 -31
- package/dist/cli-bundle/chunks/register-mutation-HLWC2WNP.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-mutation-4VJTXBZW.js → register-mutation-ZJX5AZM5.js} +173 -30
- package/dist/cli-bundle/chunks/register-mutation-ZJX5AZM5.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-operations-AR7RMX4W.js → register-operations-744YBJMV.js} +23 -25
- package/dist/cli-bundle/chunks/{register-operations-AR7RMX4W.js.map → register-operations-744YBJMV.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-operations-NOLZGORC.js → register-operations-UEBJH6AN.js} +21 -23
- package/dist/cli-bundle/chunks/{register-operations-NOLZGORC.js.map → register-operations-UEBJH6AN.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-setup-EYZ7VTPZ.js → register-setup-5DA4UZXI.js} +7 -8
- package/dist/cli-bundle/chunks/{register-setup-EYZ7VTPZ.js.map → register-setup-5DA4UZXI.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-setup-BB77VUEE.js → register-setup-6H25M3BH.js} +9 -10
- package/dist/cli-bundle/chunks/{register-setup-BB77VUEE.js.map → register-setup-6H25M3BH.js.map} +1 -1
- package/dist/cli-bundle/chunks/{restore-ZH65GZFB.js → restore-6TDVSATY.js} +4 -5
- package/dist/cli-bundle/chunks/{restore-L6IAGOD7.js → restore-RSL7C7LO.js} +4 -5
- package/dist/cli-bundle/chunks/{schema-4ERWM5QJ.js → schema-HFXFSGPG.js} +2 -3
- package/dist/cli-bundle/chunks/{schema-55DL3Q52.js → schema-TPVTIJPO.js} +2 -3
- package/dist/cli-bundle/chunks/{update-FW6FKDOP.js → update-LJZCL5SI.js} +7 -7
- package/dist/cli-bundle/chunks/{update-TJHSPRPT.js → update-SIA7LH5Y.js} +7 -7
- package/dist/cli-bundle/chunks/{update-many-PWXX5WHO.js → update-many-BDBZVGQL.js} +11 -12
- package/dist/cli-bundle/chunks/{update-many-NNALYQCN.js → update-many-MOY3A5B3.js} +11 -12
- package/dist/cli-bundle/main.js +60 -85
- package/dist/cli-bundle/main.js.map +2 -2
- package/dist/cli-bundle/sdk-runtime.js +37 -37
- package/dist/cli-bundle/sdk.js +126 -291
- package/dist/cli-bundle/sdk.js.map +4 -4
- package/dist/core/item/parse.d.ts +1 -1
- package/dist/core/item/parse.js +13 -7
- package/dist/core/item/parse.js.map +1 -1
- package/dist/core/output/mutation-projection.d.ts +2 -0
- package/dist/core/output/mutation-projection.js +33 -2
- package/dist/core/output/mutation-projection.js.map +1 -1
- package/dist/core/output/output.d.ts +4 -0
- package/dist/core/output/output.js +18 -13
- package/dist/core/output/output.js.map +1 -1
- package/dist/core/shared/command-types.d.ts +4 -0
- package/dist/core/shared/command-types.js +2 -2
- package/dist/core/shared/command-types.js.map +1 -1
- package/dist/mcp/server.js +39 -4
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tool-definitions.js +45 -4
- package/dist/mcp/tool-definitions.js.map +1 -1
- package/dist/sdk/cli-bootstrap.d.ts +2 -0
- package/dist/sdk/cli-bootstrap.js +20 -27
- package/dist/sdk/cli-bootstrap.js.map +1 -1
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +2 -2
- package/dist/sdk/cli-contracts/enum-contracts.js +7 -2
- package/dist/sdk/cli-contracts/enum-contracts.js.map +1 -1
- package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
- package/dist/sdk/cli-contracts/flag-contracts.js +21 -2
- package/dist/sdk/cli-contracts/flag-contracts.js.map +1 -1
- package/dist/sdk/cli-contracts/tool-option-contracts.js +10 -2
- package/dist/sdk/cli-contracts/tool-option-contracts.js.map +1 -1
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +16 -3
- package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -1
- package/dist/sdk/cli-contracts/tool-schema.js +6 -2
- package/dist/sdk/cli-contracts/tool-schema.js.map +1 -1
- package/dist/sdk/cli-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts.js +3 -3
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/sdk/cli-program.js +4 -2
- package/dist/sdk/cli-program.js.map +1 -1
- package/dist/sdk/dependencies.d.ts +3 -2
- package/dist/sdk/dependencies.js +13 -12
- package/dist/sdk/dependencies.js.map +1 -1
- package/dist/sdk/error-runtime.d.ts +10 -0
- package/dist/sdk/error-runtime.js +59 -0
- package/dist/sdk/error-runtime.js.map +1 -0
- package/dist/sdk/graph/analytics.d.ts +9 -0
- package/dist/sdk/graph/analytics.js +24 -13
- package/dist/sdk/graph/analytics.js.map +1 -1
- package/dist/sdk/graph/assembly.d.ts +39 -0
- package/dist/sdk/graph/assembly.js +92 -12
- package/dist/sdk/graph/assembly.js.map +1 -1
- package/dist/sdk/graph/cache.d.ts +4 -1
- package/dist/sdk/graph/cache.js +17 -4
- package/dist/sdk/graph/cache.js.map +1 -1
- package/dist/sdk/graph/centrality.d.ts +82 -0
- package/dist/sdk/graph/centrality.js +259 -0
- package/dist/sdk/graph/centrality.js.map +1 -0
- package/dist/sdk/graph/durable-cache.d.ts +71 -0
- package/dist/sdk/graph/durable-cache.js +205 -0
- package/dist/sdk/graph/durable-cache.js.map +1 -0
- package/dist/sdk/graph/governance.d.ts +69 -1
- package/dist/sdk/graph/governance.js +143 -35
- package/dist/sdk/graph/governance.js.map +1 -1
- package/dist/sdk/graph/index.d.ts +7 -4
- package/dist/sdk/graph/index.js +8 -5
- package/dist/sdk/graph/index.js.map +1 -1
- package/dist/sdk/graph/mutation-advisory.d.ts +35 -4
- package/dist/sdk/graph/mutation-advisory.js +124 -35
- package/dist/sdk/graph/mutation-advisory.js.map +1 -1
- package/dist/sdk/graph/remediation.js +12 -2
- package/dist/sdk/graph/remediation.js.map +1 -1
- package/dist/sdk/graph/run.d.ts +133 -2
- package/dist/sdk/graph/run.js +217 -8
- package/dist/sdk/graph/run.js.map +1 -1
- package/dist/sdk/graph/scheduling.d.ts +59 -0
- package/dist/sdk/graph/scheduling.js +125 -0
- package/dist/sdk/graph/scheduling.js.map +1 -0
- package/dist/sdk/graph/traversal.d.ts +11 -0
- package/dist/sdk/graph/traversal.js +16 -2
- package/dist/sdk/graph/traversal.js.map +1 -1
- package/dist/sdk/index.d.ts +4 -0
- package/dist/sdk/index.js +6 -2
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/runtime-input.js +7 -2
- package/dist/sdk/runtime-input.js.map +1 -1
- package/dist/sdk/runtime-primitives.d.ts +10 -0
- package/dist/sdk/runtime-primitives.js +14 -0
- package/dist/sdk/runtime-primitives.js.map +1 -0
- package/dist/sdk/runtime.d.ts +15 -0
- package/dist/sdk/runtime.js +16 -3
- package/dist/sdk/runtime.js.map +1 -1
- package/dist/sdk/structured-mutations.d.ts +21 -0
- package/dist/sdk/structured-mutations.js +375 -0
- package/dist/sdk/structured-mutations.js.map +1 -0
- package/docs/COMMANDS.md +85 -5
- package/docs/RELATIONSHIP_GRAPH.md +48 -7
- package/docs/SDK.md +78 -3
- 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/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-claude/README.md +5 -3
- package/plugins/pm-claude/commands/pm-init.md +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/dist/cli-bundle/chunks/chunk-3AO5VSDR.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-3LPFHE3P.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-3VY6MIEO.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-4F6BWJ4J.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-5IZJWSDB.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-5UX66S6U.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-6C2ZZX5Z.js +0 -286
- package/dist/cli-bundle/chunks/chunk-6C2ZZX5Z.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-6VIJ7UA5.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-6XMUURSS.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-C3KD7U3T.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-CFHAODHQ.js +0 -334
- package/dist/cli-bundle/chunks/chunk-CFHAODHQ.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-DAQ45GCS.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-E6LEMURX.js +0 -249
- package/dist/cli-bundle/chunks/chunk-E6LEMURX.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-G3COA6GS.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-GSJSM5BJ.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-GVI6FAFG.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-GVT754PX.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-HEWM6CEN.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-IJNK6WW2.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-INSTSQNZ.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-J4FBIFU6.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-KZEANWJS.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-LPEYZRUR.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-NHT3F4WZ.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-OV7MSW3I.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-P7JTWYLH.js +0 -246
- package/dist/cli-bundle/chunks/chunk-P7JTWYLH.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-R5U2VZ3K.js +0 -344
- package/dist/cli-bundle/chunks/chunk-R5U2VZ3K.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-SG74J6MV.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-T44FMVRL.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-THAOZG4U.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-UQLXSG72.js +0 -289
- package/dist/cli-bundle/chunks/chunk-UQLXSG72.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-UZDQXNUB.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-WVA4DVNV.js.map +0 -7
- package/dist/cli-bundle/chunks/register-list-query-CFVG75P3.js.map +0 -1
- package/dist/cli-bundle/chunks/register-list-query-E7UVY4TN.js.map +0 -7
- package/dist/cli-bundle/chunks/register-mutation-4VJTXBZW.js.map +0 -7
- package/dist/cli-bundle/chunks/register-mutation-IQ55E25C.js.map +0 -1
- /package/dist/cli-bundle/chunks/{append-E6V54WOQ.js.map → append-7OVFYR3C.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{append-NNJ3EFIT.js.map → append-DFETHAZL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-QJKL5PHS.js.map → chunk-7656MAUL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-X6K5XTTN.js.map → chunk-7W2UAXXT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-5OK4UGFV.js.map → chunk-BXNDKOR2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-KSPWRNVP.js.map → chunk-CPX275C6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JH2ZSLO3.js.map → chunk-DZRV2OPA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-L7BH7IWU.js.map → chunk-E5XMKOSB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-CQTQKUUV.js.map → chunk-EWJWSNRU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-3MCTMJXI.js.map → chunk-FPBMLYPI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-DVDBQA3B.js.map → chunk-GTK4DTEW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-GIQSU6S2.js.map → chunk-KBLZ3AA5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-XJF7CDNH.js.map → chunk-KH44WBAT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-GV2262OF.js.map → chunk-LAV26CQG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-VDO2JMD4.js.map → chunk-LVC72YRD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZYPFOO3L.js.map → chunk-MATHDCGG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-AOEOYL3S.js.map → chunk-O4BCOJTZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-RJO3YAFM.js.map → chunk-OCUBRA6D.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-I577UHC7.js.map → chunk-OR42SO64.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZOJ3LR7O.js.map → chunk-OY7DMU5P.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZV2NTVMJ.js.map → chunk-PONKZPCJ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-UX6SSO2I.js.map → chunk-PZC2FUOQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-VQIHNHMJ.js.map → chunk-QIH77CAG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-R3EWPG4A.js.map → chunk-QJIKE24M.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HB3P4M52.js.map → chunk-TRSHFPRZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HRW7GF6T.js.map → chunk-UCBDQI5E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-4U4Z6AHI.js.map → chunk-V22ZPOKN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JM6YAXTR.js.map → chunk-VHXHVTUU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-D6NXDNP3.js.map → chunk-VLRGDBLY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JAPE62Y5.js.map → chunk-VNTCM3VW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FDHPAVVB.js.map → chunk-VXOOB6YX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HQ3SB4CN.js.map → chunk-X3W65QK3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-RZJLNXFG.js.map → chunk-XJTABV3X.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-TYHJDFYW.js.map → chunk-ZVZGXPQ5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-many-SDA426VT.js.map → close-many-5RZXVN4J.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-many-UTZANOCQ.js.map → close-many-RZVTUGBG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-LZN6FXXC.js.map → comments-TPU7QRBL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-VBQ345ND.js.map → comments-Z4KV6FU3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-GG4RBCGC.js.map → create-EIFBIVNQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-JBC5KUW6.js.map → create-RGSPN5GD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-FI4O6NQS.js.map → deps-UH5EQQUY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-DELOO4TL.js.map → deps-YG7UF3VR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{docs-6Z2MP526.js.map → docs-G32TK6XS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{docs-2UYBP5D6.js.map → docs-JWWNRC27.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{files-HKEAN5MA.js.map → files-3H32UQ4K.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{files-HEUGSJZL.js.map → files-4ALMCSKB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-compact-7NDVP3PT.js.map → history-compact-77BT2LUB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-compact-65YVN5DB.js.map → history-compact-VCKGTX64.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-7YBL4XSG.js.map → history-redact-LJPZPNFA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-IZGNJBU4.js.map → history-redact-PWTTJ3XS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-repair-7M4PYQUH.js.map → history-repair-I7CBNCV3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-repair-GNGETJLI.js.map → history-repair-YTDZRK5E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-3YXDRWFT.js.map → learnings-CYNOICKR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-ALC6IMNL.js.map → learnings-KTYW3AL7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-7JMLQ447.js.map → notes-FGO63FXL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-JFCLTC5C.js.map → notes-ZERD3KB2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{plan-T3XB3WTK.js.map → plan-OFJUBIM5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{plan-KOIPWVOZ.js.map → plan-SGCDDTYR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{profile-OILJHKUW.js.map → profile-3THJPIQY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{profile-RJXA7PGS.js.map → profile-XEZAMMBW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-ZH65GZFB.js.map → restore-6TDVSATY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-L6IAGOD7.js.map → restore-RSL7C7LO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-4ERWM5QJ.js.map → schema-HFXFSGPG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-55DL3Q52.js.map → schema-TPVTIJPO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-FW6FKDOP.js.map → update-LJZCL5SI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-TJHSPRPT.js.map → update-SIA7LH5Y.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-PWXX5WHO.js.map → update-many-BDBZVGQL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-NNALYQCN.js.map → update-many-MOY3A5B3.js.map} +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BulkItemMutation } from "./item-transaction.js";
|
|
2
|
+
/** Validated transaction controls shared by atomic CLI and MCP adapters. */
|
|
3
|
+
export interface AtomicMutationControls {
|
|
4
|
+
/** Compensation policy applied to created items when a later step fails. */
|
|
5
|
+
createCompensation?: "close" | "delete";
|
|
6
|
+
/** Workspace transaction lock lifetime in seconds. */
|
|
7
|
+
lockTtlSeconds?: number;
|
|
8
|
+
/** Maximum time to wait for the workspace transaction lock. */
|
|
9
|
+
lockWaitMs?: number;
|
|
10
|
+
}
|
|
11
|
+
/** Validate and normalize atomic transaction controls at every transport boundary. */
|
|
12
|
+
export declare function parseAtomicMutationControls(value: Record<string, unknown>): AtomicMutationControls;
|
|
13
|
+
/** Parse a JSON array, or an object containing `mutations`, into an atomic mutation batch. */
|
|
14
|
+
export declare function parseItemMutationBatch(input: string): BulkItemMutation[];
|
|
15
|
+
/**
|
|
16
|
+
* Convert a direct item JSON document or `pm get --json` envelope into the
|
|
17
|
+
* create/update option shape. Explicit CLI flags override document values.
|
|
18
|
+
*/
|
|
19
|
+
export declare function itemDocumentToMutationOptions(input: string, mode: "create" | "update", explicitOptions?: Record<string, unknown>): Record<string, unknown>;
|
|
20
|
+
/** Validate an already-decoded MCP mutation array through the same strict parser as CLI stdin. */
|
|
21
|
+
export declare function validateItemMutationRows(value: unknown): BulkItemMutation[];
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/structured-mutations
|
|
3
|
+
*
|
|
4
|
+
* Parses agent-authored JSON mutation payloads into the public atomic item
|
|
5
|
+
* transaction contract and normalizes full item documents for CLI round trips.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
!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]="916a227a-1ec9-5af6-9b71-e871af2d7f0c")}catch(e){}}();
|
|
9
|
+
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
10
|
+
import { PmCliError } from "../core/shared/errors.js";
|
|
11
|
+
import { levenshteinDistanceWithinLimit } from "../core/shared/levenshtein.js";
|
|
12
|
+
import { CLOSE_FLAG_CONTRACTS } from "./cli-contracts/flag-contracts.js";
|
|
13
|
+
import { CREATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS, UPDATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS, } from "./cli-contracts/commander-mutation-options.js";
|
|
14
|
+
const MUTATION_ROW_KEYS = ["op", "id", "reason", "options"];
|
|
15
|
+
const ITEM_ENVELOPE_KEYS = [
|
|
16
|
+
"item",
|
|
17
|
+
"linked",
|
|
18
|
+
"schedule",
|
|
19
|
+
"claim_state",
|
|
20
|
+
"children",
|
|
21
|
+
];
|
|
22
|
+
const READ_ONLY_ITEM_KEYS = new Set([
|
|
23
|
+
"created_at",
|
|
24
|
+
"updated_at",
|
|
25
|
+
"closed_at",
|
|
26
|
+
"version",
|
|
27
|
+
"format_version",
|
|
28
|
+
"path",
|
|
29
|
+
"author",
|
|
30
|
+
]);
|
|
31
|
+
const UPDATE_READ_ONLY_ITEM_KEYS = new Set([...READ_ONLY_ITEM_KEYS, "id"]);
|
|
32
|
+
const ITEM_FIELD_KEYS = new Set([
|
|
33
|
+
"id",
|
|
34
|
+
"title",
|
|
35
|
+
"description",
|
|
36
|
+
"type",
|
|
37
|
+
"status",
|
|
38
|
+
"priority",
|
|
39
|
+
"tags",
|
|
40
|
+
"body",
|
|
41
|
+
"deadline",
|
|
42
|
+
"estimated_minutes",
|
|
43
|
+
"acceptance_criteria",
|
|
44
|
+
"definition_of_ready",
|
|
45
|
+
"order",
|
|
46
|
+
"rank",
|
|
47
|
+
"goal",
|
|
48
|
+
"objective",
|
|
49
|
+
"value",
|
|
50
|
+
"impact",
|
|
51
|
+
"outcome",
|
|
52
|
+
"why_now",
|
|
53
|
+
"assignee",
|
|
54
|
+
"parent",
|
|
55
|
+
"reviewer",
|
|
56
|
+
"risk",
|
|
57
|
+
"confidence",
|
|
58
|
+
"sprint",
|
|
59
|
+
"release",
|
|
60
|
+
"blocked_by",
|
|
61
|
+
"blocked_reason",
|
|
62
|
+
"unblock_note",
|
|
63
|
+
"reporter",
|
|
64
|
+
"severity",
|
|
65
|
+
"environment",
|
|
66
|
+
"repro_steps",
|
|
67
|
+
"resolution",
|
|
68
|
+
"expected_result",
|
|
69
|
+
"actual_result",
|
|
70
|
+
"affected_version",
|
|
71
|
+
"fixed_version",
|
|
72
|
+
"component",
|
|
73
|
+
"regression",
|
|
74
|
+
"customer_impact",
|
|
75
|
+
"close_reason",
|
|
76
|
+
"dependencies",
|
|
77
|
+
"comments",
|
|
78
|
+
"notes",
|
|
79
|
+
"learnings",
|
|
80
|
+
"files",
|
|
81
|
+
"tests",
|
|
82
|
+
"docs",
|
|
83
|
+
"reminders",
|
|
84
|
+
"events",
|
|
85
|
+
"type_options",
|
|
86
|
+
]);
|
|
87
|
+
const MUTATION_OPTION_KEYS = {
|
|
88
|
+
create: CREATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS.map((contract) => contract.target),
|
|
89
|
+
update: UPDATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS.map((contract) => contract.target),
|
|
90
|
+
close: CLOSE_FLAG_CONTRACTS.map((contract) => contract.flag
|
|
91
|
+
.slice(2)
|
|
92
|
+
.replaceAll(/-([a-z])/gu, (_match, letter) => letter.toUpperCase())).filter((key) => key !== "reason"),
|
|
93
|
+
};
|
|
94
|
+
/** Validate and normalize atomic transaction controls at every transport boundary. */
|
|
95
|
+
export function parseAtomicMutationControls(value) {
|
|
96
|
+
const controls = {};
|
|
97
|
+
const compensation = value.createCompensation;
|
|
98
|
+
if (compensation !== undefined) {
|
|
99
|
+
if (compensation !== "close" && compensation !== "delete") {
|
|
100
|
+
throw new PmCliError("createCompensation must be close or delete.", EXIT_CODE.USAGE);
|
|
101
|
+
}
|
|
102
|
+
controls.createCompensation = compensation;
|
|
103
|
+
}
|
|
104
|
+
for (const key of ["lockTtlSeconds", "lockWaitMs"]) {
|
|
105
|
+
const raw = value[key];
|
|
106
|
+
if (raw === undefined)
|
|
107
|
+
continue;
|
|
108
|
+
const parsed = typeof raw === "number" ||
|
|
109
|
+
(typeof raw === "string" && raw.trim().length > 0)
|
|
110
|
+
? Number(raw)
|
|
111
|
+
: Number.NaN;
|
|
112
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
|
|
113
|
+
throw new PmCliError(`${key} must be a positive safe integer.`, EXIT_CODE.USAGE);
|
|
114
|
+
}
|
|
115
|
+
controls[key] = parsed;
|
|
116
|
+
}
|
|
117
|
+
return controls;
|
|
118
|
+
}
|
|
119
|
+
function isPlainObject(value) {
|
|
120
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
const prototype = Object.getPrototypeOf(value);
|
|
124
|
+
return prototype === Object.prototype || prototype === null;
|
|
125
|
+
}
|
|
126
|
+
function nearestKey(key, candidates) {
|
|
127
|
+
const limit = Math.max(1, Math.min(3, Math.floor(key.length / 4) + 1));
|
|
128
|
+
let best;
|
|
129
|
+
for (const candidate of candidates) {
|
|
130
|
+
const distance = levenshteinDistanceWithinLimit(key, candidate, limit);
|
|
131
|
+
if (distance !== null && (best === undefined || distance < best.distance)) {
|
|
132
|
+
best = { key: candidate, distance };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return best?.key;
|
|
136
|
+
}
|
|
137
|
+
function unknownKeyError(scope, key, candidates) {
|
|
138
|
+
const suggestion = nearestKey(key, candidates);
|
|
139
|
+
return new PmCliError(suggestion === undefined
|
|
140
|
+
? `${scope} does not recognize key "${key}". Allowed keys: ${candidates.join(", ")}.`
|
|
141
|
+
: `${scope} does not recognize key "${key}". Did you mean "${suggestion}"?`, EXIT_CODE.USAGE, {
|
|
142
|
+
code: "stdin_json_unknown_key",
|
|
143
|
+
required: `Use documented ${scope} keys only.`,
|
|
144
|
+
why: "Strict structured input prevents silent typos from creating incomplete or unintended mutations.",
|
|
145
|
+
nextSteps: [
|
|
146
|
+
suggestion === undefined
|
|
147
|
+
? `Remove or correct "${key}".`
|
|
148
|
+
: `Replace "${key}" with "${suggestion}".`,
|
|
149
|
+
],
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function parseJsonValue(input, label) {
|
|
153
|
+
try {
|
|
154
|
+
return JSON.parse(input);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
158
|
+
throw new PmCliError(`${label} must be valid JSON: ${detail}`, EXIT_CODE.USAGE, {
|
|
159
|
+
code: "stdin_json_invalid",
|
|
160
|
+
required: `Pipe one valid JSON ${label.toLowerCase()} into stdin.`,
|
|
161
|
+
why: "Structured mutation input must parse deterministically before any tracker write begins.",
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function validateMutationObject(value, index) {
|
|
166
|
+
if (!isPlainObject(value)) {
|
|
167
|
+
throw new PmCliError(`Mutation ${index + 1} must be an object.`, EXIT_CODE.USAGE);
|
|
168
|
+
}
|
|
169
|
+
for (const key of Object.keys(value)) {
|
|
170
|
+
if (!MUTATION_ROW_KEYS.includes(key)) {
|
|
171
|
+
throw unknownKeyError(`mutation ${index + 1}`, key, MUTATION_ROW_KEYS);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return value;
|
|
175
|
+
}
|
|
176
|
+
function validateMutationOptions(options, op, index) {
|
|
177
|
+
if (options === undefined)
|
|
178
|
+
return undefined;
|
|
179
|
+
if (!isPlainObject(options)) {
|
|
180
|
+
throw new PmCliError(`Mutation ${index + 1} options must be an object.`, EXIT_CODE.USAGE);
|
|
181
|
+
}
|
|
182
|
+
for (const key of Object.keys(options)) {
|
|
183
|
+
if (!MUTATION_OPTION_KEYS[op].includes(key)) {
|
|
184
|
+
throw unknownKeyError(`mutation ${index + 1} ${op} options`, key, MUTATION_OPTION_KEYS[op]);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return options;
|
|
188
|
+
}
|
|
189
|
+
function validateMutationRow(value, index) {
|
|
190
|
+
const mutation = validateMutationObject(value, index);
|
|
191
|
+
const { op, id, reason } = mutation;
|
|
192
|
+
if (op !== "create" && op !== "update" && op !== "close") {
|
|
193
|
+
throw new PmCliError(`Mutation ${index + 1} op must be create, update, or close.`, EXIT_CODE.USAGE);
|
|
194
|
+
}
|
|
195
|
+
const options = validateMutationOptions(mutation.options, op, index);
|
|
196
|
+
if (typeof id !== "string" || id.trim().length === 0) {
|
|
197
|
+
throw new PmCliError(`Mutation ${index + 1} requires a non-empty id.`, EXIT_CODE.USAGE);
|
|
198
|
+
}
|
|
199
|
+
const normalizedId = id.trim();
|
|
200
|
+
if (op === "close") {
|
|
201
|
+
if (typeof reason !== "string" || reason.trim().length === 0) {
|
|
202
|
+
throw new PmCliError(`Mutation ${index + 1} close requires a non-empty reason.`, EXIT_CODE.USAGE);
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
op,
|
|
206
|
+
id: normalizedId,
|
|
207
|
+
reason: reason.trim(),
|
|
208
|
+
...(options === undefined
|
|
209
|
+
? {}
|
|
210
|
+
: { options: options }),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
if (!isPlainObject(options)) {
|
|
214
|
+
throw new PmCliError(`Mutation ${index + 1} ${op} requires an options object.`, EXIT_CODE.USAGE);
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
op,
|
|
218
|
+
id: normalizedId,
|
|
219
|
+
options: options,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
/** Parse a JSON array, or an object containing `mutations`, into an atomic mutation batch. */
|
|
223
|
+
export function parseItemMutationBatch(input) {
|
|
224
|
+
const parsed = parseJsonValue(input, "Mutation batch");
|
|
225
|
+
const rows = Array.isArray(parsed)
|
|
226
|
+
? parsed
|
|
227
|
+
: isPlainObject(parsed) && Array.isArray(parsed.mutations)
|
|
228
|
+
? parsed.mutations
|
|
229
|
+
: undefined;
|
|
230
|
+
if (rows === undefined || rows.length === 0) {
|
|
231
|
+
throw new PmCliError("Mutation batch must be a non-empty JSON array or an object with a non-empty mutations array.", EXIT_CODE.USAGE);
|
|
232
|
+
}
|
|
233
|
+
return rows.map((row, index) => validateMutationRow(row, index));
|
|
234
|
+
}
|
|
235
|
+
function serializePairs(value, keys) {
|
|
236
|
+
return keys
|
|
237
|
+
.filter((key) => value[key] !== undefined && value[key] !== null)
|
|
238
|
+
.map((key) => {
|
|
239
|
+
const rendered = String(value[key]);
|
|
240
|
+
return `${key}=${/[",\n\r\\]/u.test(rendered) ? JSON.stringify(rendered) : rendered}`;
|
|
241
|
+
})
|
|
242
|
+
.join(",");
|
|
243
|
+
}
|
|
244
|
+
function serializeObjectArray(value, keys, label) {
|
|
245
|
+
if (value === undefined)
|
|
246
|
+
return undefined;
|
|
247
|
+
if (!Array.isArray(value) || !value.every(isPlainObject)) {
|
|
248
|
+
throw new PmCliError(`${label} must be an array of objects.`, EXIT_CODE.USAGE);
|
|
249
|
+
}
|
|
250
|
+
return value.map((entry) => serializePairs(entry, keys));
|
|
251
|
+
}
|
|
252
|
+
function scalarItemOption(key, value) {
|
|
253
|
+
if (key === "tags" &&
|
|
254
|
+
Array.isArray(value) &&
|
|
255
|
+
value.every((entry) => typeof entry === "string")) {
|
|
256
|
+
return JSON.stringify(value);
|
|
257
|
+
}
|
|
258
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
259
|
+
return String(value);
|
|
260
|
+
}
|
|
261
|
+
return value;
|
|
262
|
+
}
|
|
263
|
+
function appendFacetOptions(target, source, skipPersistedAnnotations = false) {
|
|
264
|
+
const mappings = [
|
|
265
|
+
["dependencies", "dep", ["id", "kind", "created_at", "author"]],
|
|
266
|
+
["comments", "comment", ["text", "created_at", "author"]],
|
|
267
|
+
["notes", "note", ["text", "created_at", "author"]],
|
|
268
|
+
["learnings", "learning", ["text", "created_at", "author"]],
|
|
269
|
+
["files", "file", ["path", "scope", "note"]],
|
|
270
|
+
["tests", "test", ["command", "scope", "timeout_seconds"]],
|
|
271
|
+
["docs", "doc", ["path", "scope", "note"]],
|
|
272
|
+
["reminders", "reminder", ["at", "text", "created_at"]],
|
|
273
|
+
["events", "event", ["start_at", "end_at", "title", "location"]],
|
|
274
|
+
["type_options", "typeOption", ["key", "value"]],
|
|
275
|
+
];
|
|
276
|
+
for (const [sourceKey, targetKey, keys] of mappings) {
|
|
277
|
+
const sourceValue = source[sourceKey];
|
|
278
|
+
const serialized = serializeObjectArray(skipPersistedAnnotations &&
|
|
279
|
+
["comments", "notes", "learnings"].includes(sourceKey) &&
|
|
280
|
+
Array.isArray(sourceValue)
|
|
281
|
+
? sourceValue.filter((entry) => !isPlainObject(entry) || entry.created_at === undefined)
|
|
282
|
+
: sourceValue, keys, sourceKey);
|
|
283
|
+
if (serialized !== undefined && serialized.length > 0)
|
|
284
|
+
target[targetKey] = serialized;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function validateItemDocumentKeys(parsed, envelope) {
|
|
288
|
+
for (const key of Object.keys(parsed)) {
|
|
289
|
+
if (envelope) {
|
|
290
|
+
if (!ITEM_ENVELOPE_KEYS.includes(key))
|
|
291
|
+
throw unknownKeyError("item envelope", key, ITEM_ENVELOPE_KEYS);
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
if (!ITEM_FIELD_KEYS.has(key) &&
|
|
295
|
+
nearestKey(key, [...ITEM_FIELD_KEYS]) === undefined &&
|
|
296
|
+
nearestKey(key, ITEM_ENVELOPE_KEYS) === "item")
|
|
297
|
+
throw unknownKeyError("item envelope", key, ITEM_ENVELOPE_KEYS);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function resolveItemDocument(parsed) {
|
|
301
|
+
const envelope = Object.hasOwn(parsed, "item");
|
|
302
|
+
validateItemDocumentKeys(parsed, envelope);
|
|
303
|
+
const item = envelope ? parsed.item : parsed;
|
|
304
|
+
if (!isPlainObject(item)) {
|
|
305
|
+
throw new PmCliError("Item document item must be an object.", EXIT_CODE.USAGE);
|
|
306
|
+
}
|
|
307
|
+
return {
|
|
308
|
+
item,
|
|
309
|
+
...(envelope && isPlainObject(parsed.linked)
|
|
310
|
+
? { linked: parsed.linked }
|
|
311
|
+
: {}),
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
function appendItemDocumentEntry(documentOptions, key, value, mode) {
|
|
315
|
+
const readOnlyKeys = mode === "update" ? UPDATE_READ_ONLY_ITEM_KEYS : READ_ONLY_ITEM_KEYS;
|
|
316
|
+
if (readOnlyKeys.has(key))
|
|
317
|
+
return;
|
|
318
|
+
if (!ITEM_FIELD_KEYS.has(key)) {
|
|
319
|
+
const suggestion = nearestKey(key, [...ITEM_FIELD_KEYS]);
|
|
320
|
+
if (suggestion !== undefined)
|
|
321
|
+
throw unknownKeyError("item document", key, [...ITEM_FIELD_KEYS]);
|
|
322
|
+
const fields = Array.isArray(documentOptions.field)
|
|
323
|
+
? documentOptions.field
|
|
324
|
+
: [];
|
|
325
|
+
fields.push(serializePairs({
|
|
326
|
+
key,
|
|
327
|
+
value: typeof value === "string" ? value : JSON.stringify(value),
|
|
328
|
+
}, ["key", "value"]));
|
|
329
|
+
documentOptions.field = fields;
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
if ([
|
|
333
|
+
"dependencies",
|
|
334
|
+
"comments",
|
|
335
|
+
"notes",
|
|
336
|
+
"learnings",
|
|
337
|
+
"files",
|
|
338
|
+
"tests",
|
|
339
|
+
"docs",
|
|
340
|
+
"reminders",
|
|
341
|
+
"events",
|
|
342
|
+
"type_options",
|
|
343
|
+
].includes(key))
|
|
344
|
+
return;
|
|
345
|
+
documentOptions[key.replaceAll(/_([a-z])/gu, (_match, letter) => letter.toUpperCase())] = scalarItemOption(key, value);
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Convert a direct item JSON document or `pm get --json` envelope into the
|
|
349
|
+
* create/update option shape. Explicit CLI flags override document values.
|
|
350
|
+
*/
|
|
351
|
+
export function itemDocumentToMutationOptions(input, mode, explicitOptions = {}) {
|
|
352
|
+
const parsed = parseJsonValue(input, "Item document");
|
|
353
|
+
if (!isPlainObject(parsed)) {
|
|
354
|
+
throw new PmCliError("Item document must be a JSON object.", EXIT_CODE.USAGE);
|
|
355
|
+
}
|
|
356
|
+
const { item, linked } = resolveItemDocument(parsed);
|
|
357
|
+
const documentOptions = {};
|
|
358
|
+
for (const [key, value] of Object.entries(item)) {
|
|
359
|
+
appendItemDocumentEntry(documentOptions, key, value, mode);
|
|
360
|
+
}
|
|
361
|
+
appendFacetOptions(documentOptions, item, mode === "update");
|
|
362
|
+
if (linked !== undefined)
|
|
363
|
+
appendFacetOptions(documentOptions, linked);
|
|
364
|
+
return {
|
|
365
|
+
...documentOptions,
|
|
366
|
+
...Object.fromEntries(Object.entries(explicitOptions).filter(([, value]) => value !== undefined)),
|
|
367
|
+
stdinJson: undefined,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
/** Validate an already-decoded MCP mutation array through the same strict parser as CLI stdin. */
|
|
371
|
+
export function validateItemMutationRows(value) {
|
|
372
|
+
return parseItemMutationBatch(JSON.stringify(value));
|
|
373
|
+
}
|
|
374
|
+
//# sourceMappingURL=structured-mutations.js.map
|
|
375
|
+
//# debugId=916a227a-1ec9-5af6-9b71-e871af2d7f0c
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-mutations.js","sources":["sdk/structured-mutations.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module sdk/structured-mutations\n *\n * Parses agent-authored JSON mutation payloads into the public atomic item\n * transaction contract and normalizes full item documents for CLI round trips.\n */\nimport { EXIT_CODE } from \"../core/shared/constants.js\";\nimport { PmCliError } from \"../core/shared/errors.js\";\nimport { levenshteinDistanceWithinLimit } from \"../core/shared/levenshtein.js\";\nimport { CLOSE_FLAG_CONTRACTS } from \"./cli-contracts/flag-contracts.js\";\nimport {\n CREATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS,\n UPDATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS,\n} from \"./cli-contracts/commander-mutation-options.js\";\nimport type { PmClientFullMutationOptions } from \"./runtime.js\";\nimport type { BulkItemMutation } from \"./item-transaction.js\";\n\nconst MUTATION_ROW_KEYS = [\"op\", \"id\", \"reason\", \"options\"] as const;\nconst ITEM_ENVELOPE_KEYS = [\n \"item\",\n \"linked\",\n \"schedule\",\n \"claim_state\",\n \"children\",\n] as const;\nconst READ_ONLY_ITEM_KEYS = new Set([\n \"created_at\",\n \"updated_at\",\n \"closed_at\",\n \"version\",\n \"format_version\",\n \"path\",\n \"author\",\n]);\nconst UPDATE_READ_ONLY_ITEM_KEYS = new Set([...READ_ONLY_ITEM_KEYS, \"id\"]);\nconst ITEM_FIELD_KEYS = new Set([\n \"id\",\n \"title\",\n \"description\",\n \"type\",\n \"status\",\n \"priority\",\n \"tags\",\n \"body\",\n \"deadline\",\n \"estimated_minutes\",\n \"acceptance_criteria\",\n \"definition_of_ready\",\n \"order\",\n \"rank\",\n \"goal\",\n \"objective\",\n \"value\",\n \"impact\",\n \"outcome\",\n \"why_now\",\n \"assignee\",\n \"parent\",\n \"reviewer\",\n \"risk\",\n \"confidence\",\n \"sprint\",\n \"release\",\n \"blocked_by\",\n \"blocked_reason\",\n \"unblock_note\",\n \"reporter\",\n \"severity\",\n \"environment\",\n \"repro_steps\",\n \"resolution\",\n \"expected_result\",\n \"actual_result\",\n \"affected_version\",\n \"fixed_version\",\n \"component\",\n \"regression\",\n \"customer_impact\",\n \"close_reason\",\n \"dependencies\",\n \"comments\",\n \"notes\",\n \"learnings\",\n \"files\",\n \"tests\",\n \"docs\",\n \"reminders\",\n \"events\",\n \"type_options\",\n]);\nconst MUTATION_OPTION_KEYS: Readonly<\n Record<BulkItemMutation[\"op\"], readonly string[]>\n> = {\n create: CREATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS.map(\n (contract) => contract.target,\n ),\n update: UPDATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS.map(\n (contract) => contract.target,\n ),\n close: CLOSE_FLAG_CONTRACTS.map((contract) =>\n contract.flag\n .slice(2)\n .replaceAll(/-([a-z])/gu, (_match, letter: string) =>\n letter.toUpperCase(),\n ),\n ).filter((key) => key !== \"reason\"),\n};\n\n/** Validated transaction controls shared by atomic CLI and MCP adapters. */\nexport interface AtomicMutationControls {\n /** Compensation policy applied to created items when a later step fails. */\n createCompensation?: \"close\" | \"delete\";\n /** Workspace transaction lock lifetime in seconds. */\n lockTtlSeconds?: number;\n /** Maximum time to wait for the workspace transaction lock. */\n lockWaitMs?: number;\n}\n\n/** Validate and normalize atomic transaction controls at every transport boundary. */\nexport function parseAtomicMutationControls(\n value: Record<string, unknown>,\n): AtomicMutationControls {\n const controls: AtomicMutationControls = {};\n const compensation = value.createCompensation;\n if (compensation !== undefined) {\n if (compensation !== \"close\" && compensation !== \"delete\") {\n throw new PmCliError(\n \"createCompensation must be close or delete.\",\n EXIT_CODE.USAGE,\n );\n }\n controls.createCompensation = compensation;\n }\n for (const key of [\"lockTtlSeconds\", \"lockWaitMs\"] as const) {\n const raw = value[key];\n if (raw === undefined) continue;\n const parsed =\n typeof raw === \"number\" ||\n (typeof raw === \"string\" && raw.trim().length > 0)\n ? Number(raw)\n : Number.NaN;\n if (!Number.isSafeInteger(parsed) || parsed <= 0) {\n throw new PmCliError(\n `${key} must be a positive safe integer.`,\n EXIT_CODE.USAGE,\n );\n }\n controls[key] = parsed;\n }\n return controls;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false;\n }\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction nearestKey(\n key: string,\n candidates: readonly string[],\n): string | undefined {\n const limit = Math.max(1, Math.min(3, Math.floor(key.length / 4) + 1));\n let best: { key: string; distance: number } | undefined;\n for (const candidate of candidates) {\n const distance = levenshteinDistanceWithinLimit(key, candidate, limit);\n if (distance !== null && (best === undefined || distance < best.distance)) {\n best = { key: candidate, distance };\n }\n }\n return best?.key;\n}\n\nfunction unknownKeyError(\n scope: string,\n key: string,\n candidates: readonly string[],\n): PmCliError {\n const suggestion = nearestKey(key, candidates);\n return new PmCliError(\n suggestion === undefined\n ? `${scope} does not recognize key \"${key}\". Allowed keys: ${candidates.join(\", \")}.`\n : `${scope} does not recognize key \"${key}\". Did you mean \"${suggestion}\"?`,\n EXIT_CODE.USAGE,\n {\n code: \"stdin_json_unknown_key\",\n required: `Use documented ${scope} keys only.`,\n why: \"Strict structured input prevents silent typos from creating incomplete or unintended mutations.\",\n nextSteps: [\n suggestion === undefined\n ? `Remove or correct \"${key}\".`\n : `Replace \"${key}\" with \"${suggestion}\".`,\n ],\n },\n );\n}\n\nfunction parseJsonValue(input: string, label: string): unknown {\n try {\n return JSON.parse(input) as unknown;\n } catch (error: unknown) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new PmCliError(\n `${label} must be valid JSON: ${detail}`,\n EXIT_CODE.USAGE,\n {\n code: \"stdin_json_invalid\",\n required: `Pipe one valid JSON ${label.toLowerCase()} into stdin.`,\n why: \"Structured mutation input must parse deterministically before any tracker write begins.\",\n },\n );\n }\n}\n\nfunction validateMutationObject(\n value: unknown,\n index: number,\n): Record<string, unknown> {\n if (!isPlainObject(value)) {\n throw new PmCliError(\n `Mutation ${index + 1} must be an object.`,\n EXIT_CODE.USAGE,\n );\n }\n for (const key of Object.keys(value)) {\n if (\n !MUTATION_ROW_KEYS.includes(key as (typeof MUTATION_ROW_KEYS)[number])\n ) {\n throw unknownKeyError(`mutation ${index + 1}`, key, MUTATION_ROW_KEYS);\n }\n }\n return value;\n}\n\nfunction validateMutationOptions(\n options: unknown,\n op: BulkItemMutation[\"op\"],\n index: number,\n): Record<string, unknown> | undefined {\n if (options === undefined) return undefined;\n if (!isPlainObject(options)) {\n throw new PmCliError(\n `Mutation ${index + 1} options must be an object.`,\n EXIT_CODE.USAGE,\n );\n }\n for (const key of Object.keys(options)) {\n if (!MUTATION_OPTION_KEYS[op].includes(key)) {\n throw unknownKeyError(\n `mutation ${index + 1} ${op} options`,\n key,\n MUTATION_OPTION_KEYS[op],\n );\n }\n }\n return options;\n}\n\nfunction validateMutationRow(value: unknown, index: number): BulkItemMutation {\n const mutation = validateMutationObject(value, index);\n const { op, id, reason } = mutation;\n if (op !== \"create\" && op !== \"update\" && op !== \"close\") {\n throw new PmCliError(\n `Mutation ${index + 1} op must be create, update, or close.`,\n EXIT_CODE.USAGE,\n );\n }\n const options = validateMutationOptions(mutation.options, op, index);\n if (typeof id !== \"string\" || id.trim().length === 0) {\n throw new PmCliError(\n `Mutation ${index + 1} requires a non-empty id.`,\n EXIT_CODE.USAGE,\n );\n }\n const normalizedId = id.trim();\n if (op === \"close\") {\n if (typeof reason !== \"string\" || reason.trim().length === 0) {\n throw new PmCliError(\n `Mutation ${index + 1} close requires a non-empty reason.`,\n EXIT_CODE.USAGE,\n );\n }\n return {\n op,\n id: normalizedId,\n reason: reason.trim(),\n ...(options === undefined\n ? {}\n : { options: options as PmClientFullMutationOptions }),\n };\n }\n if (!isPlainObject(options)) {\n throw new PmCliError(\n `Mutation ${index + 1} ${op} requires an options object.`,\n EXIT_CODE.USAGE,\n );\n }\n return {\n op,\n id: normalizedId,\n options: options as PmClientFullMutationOptions,\n };\n}\n\n/** Parse a JSON array, or an object containing `mutations`, into an atomic mutation batch. */\nexport function parseItemMutationBatch(input: string): BulkItemMutation[] {\n const parsed = parseJsonValue(input, \"Mutation batch\");\n const rows = Array.isArray(parsed)\n ? parsed\n : isPlainObject(parsed) && Array.isArray(parsed.mutations)\n ? parsed.mutations\n : undefined;\n if (rows === undefined || rows.length === 0) {\n throw new PmCliError(\n \"Mutation batch must be a non-empty JSON array or an object with a non-empty mutations array.\",\n EXIT_CODE.USAGE,\n );\n }\n return rows.map((row, index) => validateMutationRow(row, index));\n}\n\nfunction serializePairs(\n value: Record<string, unknown>,\n keys: readonly string[],\n): string {\n return keys\n .filter((key) => value[key] !== undefined && value[key] !== null)\n .map((key) => {\n const rendered = String(value[key]);\n return `${key}=${/[\",\\n\\r\\\\]/u.test(rendered) ? JSON.stringify(rendered) : rendered}`;\n })\n .join(\",\");\n}\n\nfunction serializeObjectArray(\n value: unknown,\n keys: readonly string[],\n label: string,\n): string[] | undefined {\n if (value === undefined) return undefined;\n if (!Array.isArray(value) || !value.every(isPlainObject)) {\n throw new PmCliError(\n `${label} must be an array of objects.`,\n EXIT_CODE.USAGE,\n );\n }\n return value.map((entry) => serializePairs(entry, keys));\n}\n\nfunction scalarItemOption(key: string, value: unknown): unknown {\n if (\n key === \"tags\" &&\n Array.isArray(value) &&\n value.every((entry) => typeof entry === \"string\")\n ) {\n return JSON.stringify(value);\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n return value;\n}\n\nfunction appendFacetOptions(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n skipPersistedAnnotations = false,\n): void {\n const mappings: ReadonlyArray<readonly [string, string, readonly string[]]> =\n [\n [\"dependencies\", \"dep\", [\"id\", \"kind\", \"created_at\", \"author\"]],\n [\"comments\", \"comment\", [\"text\", \"created_at\", \"author\"]],\n [\"notes\", \"note\", [\"text\", \"created_at\", \"author\"]],\n [\"learnings\", \"learning\", [\"text\", \"created_at\", \"author\"]],\n [\"files\", \"file\", [\"path\", \"scope\", \"note\"]],\n [\"tests\", \"test\", [\"command\", \"scope\", \"timeout_seconds\"]],\n [\"docs\", \"doc\", [\"path\", \"scope\", \"note\"]],\n [\"reminders\", \"reminder\", [\"at\", \"text\", \"created_at\"]],\n [\"events\", \"event\", [\"start_at\", \"end_at\", \"title\", \"location\"]],\n [\"type_options\", \"typeOption\", [\"key\", \"value\"]],\n ];\n for (const [sourceKey, targetKey, keys] of mappings) {\n const sourceValue = source[sourceKey];\n const serialized = serializeObjectArray(\n skipPersistedAnnotations &&\n [\"comments\", \"notes\", \"learnings\"].includes(sourceKey) &&\n Array.isArray(sourceValue)\n ? sourceValue.filter(\n (entry) =>\n !isPlainObject(entry) || entry.created_at === undefined,\n )\n : sourceValue,\n keys,\n sourceKey,\n );\n if (serialized !== undefined && serialized.length > 0)\n target[targetKey] = serialized;\n }\n}\n\nfunction validateItemDocumentKeys(\n parsed: Record<string, unknown>,\n envelope: boolean,\n): void {\n for (const key of Object.keys(parsed)) {\n if (envelope) {\n if (\n !ITEM_ENVELOPE_KEYS.includes(key as (typeof ITEM_ENVELOPE_KEYS)[number])\n )\n throw unknownKeyError(\"item envelope\", key, ITEM_ENVELOPE_KEYS);\n continue;\n }\n if (\n !ITEM_FIELD_KEYS.has(key) &&\n nearestKey(key, [...ITEM_FIELD_KEYS]) === undefined &&\n nearestKey(key, ITEM_ENVELOPE_KEYS) === \"item\"\n )\n throw unknownKeyError(\"item envelope\", key, ITEM_ENVELOPE_KEYS);\n }\n}\n\nfunction resolveItemDocument(parsed: Record<string, unknown>): {\n item: Record<string, unknown>;\n linked?: Record<string, unknown>;\n} {\n const envelope = Object.hasOwn(parsed, \"item\");\n validateItemDocumentKeys(parsed, envelope);\n const item = envelope ? parsed.item : parsed;\n if (!isPlainObject(item)) {\n throw new PmCliError(\n \"Item document item must be an object.\",\n EXIT_CODE.USAGE,\n );\n }\n return {\n item,\n ...(envelope && isPlainObject(parsed.linked)\n ? { linked: parsed.linked }\n : {}),\n };\n}\n\nfunction appendItemDocumentEntry(\n documentOptions: Record<string, unknown>,\n key: string,\n value: unknown,\n mode: \"create\" | \"update\",\n): void {\n const readOnlyKeys =\n mode === \"update\" ? UPDATE_READ_ONLY_ITEM_KEYS : READ_ONLY_ITEM_KEYS;\n if (readOnlyKeys.has(key)) return;\n if (!ITEM_FIELD_KEYS.has(key)) {\n const suggestion = nearestKey(key, [...ITEM_FIELD_KEYS]);\n if (suggestion !== undefined)\n throw unknownKeyError(\"item document\", key, [...ITEM_FIELD_KEYS]);\n const fields = Array.isArray(documentOptions.field)\n ? (documentOptions.field as string[])\n : [];\n fields.push(\n serializePairs(\n {\n key,\n value: typeof value === \"string\" ? value : JSON.stringify(value),\n },\n [\"key\", \"value\"],\n ),\n );\n documentOptions.field = fields;\n return;\n }\n if (\n [\n \"dependencies\",\n \"comments\",\n \"notes\",\n \"learnings\",\n \"files\",\n \"tests\",\n \"docs\",\n \"reminders\",\n \"events\",\n \"type_options\",\n ].includes(key)\n )\n return;\n documentOptions[\n key.replaceAll(/_([a-z])/gu, (_match, letter: string) =>\n letter.toUpperCase(),\n )\n ] = scalarItemOption(key, value);\n}\n\n/**\n * Convert a direct item JSON document or `pm get --json` envelope into the\n * create/update option shape. Explicit CLI flags override document values.\n */\nexport function itemDocumentToMutationOptions(\n input: string,\n mode: \"create\" | \"update\",\n explicitOptions: Record<string, unknown> = {},\n): Record<string, unknown> {\n const parsed = parseJsonValue(input, \"Item document\");\n if (!isPlainObject(parsed)) {\n throw new PmCliError(\n \"Item document must be a JSON object.\",\n EXIT_CODE.USAGE,\n );\n }\n const { item, linked } = resolveItemDocument(parsed);\n const documentOptions: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(item)) {\n appendItemDocumentEntry(documentOptions, key, value, mode);\n }\n appendFacetOptions(documentOptions, item, mode === \"update\");\n if (linked !== undefined) appendFacetOptions(documentOptions, linked);\n return {\n ...documentOptions,\n ...Object.fromEntries(\n Object.entries(explicitOptions).filter(\n ([, value]) => value !== undefined,\n ),\n ),\n stdinJson: undefined,\n };\n}\n\n/** Validate an already-decoded MCP mutation array through the same strict parser as CLI stdin. */\nexport function validateItemMutationRows(value: unknown): BulkItemMutation[] {\n return parseItemMutationBatch(JSON.stringify(value));\n}\n"],"names":[],"mappings":"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","debugId":"916a227a-1ec9-5af6-9b71-e871af2d7f0c"}
|
package/docs/COMMANDS.md
CHANGED
|
@@ -27,7 +27,7 @@ Tracked documentation work: [pm-u9d0](../.agents/pm/epics/pm-u9d0.toon).
|
|
|
27
27
|
| ------------ | ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
28
28
|
| Bootstrap | `init`, `config`, `health`, `telemetry` | create and inspect tracker setup |
|
|
29
29
|
| Lifecycle | `create`, `copy`, `focus`, `claim`, `update`, `append`, `close`, `release`, `delete`, `start-task`, `pause-task`, `close-task` | mutate item state |
|
|
30
|
-
| Bulk | `update-many`, `close-many`
|
|
30
|
+
| Bulk | `item mutate`, `update-many`, `close-many` | atomically commit heterogeneous SDK mutation batches, or apply one change across a matched, dry-run-previewed set with a rollback checkpoint |
|
|
31
31
|
| Scheduling | `meet`, `event`, `remind` | low-friction Meeting/Event/Reminder creation |
|
|
32
32
|
| Planning | `plan create`, `plan add-step`, `plan update-step`, `plan complete-step`, `plan link`, `plan approve`, `plan materialize` | agent-optimized living plans with ordered steps, evidence, decisions, validation, and materialization |
|
|
33
33
|
| Links | `files`, `docs`, `test`, `deps` | connect items to artifacts, tests, and relationships |
|
|
@@ -327,6 +327,13 @@ When a flag is rejected with `Unknown option`, the error guidance now suggests t
|
|
|
327
327
|
|
|
328
328
|
## Create and Update
|
|
329
329
|
|
|
330
|
+
Tracked structured-input and compact-output work:
|
|
331
|
+
[pm-xm7c](../.agents/pm/features/pm-xm7c.toon),
|
|
332
|
+
[pm-kipd](../.agents/pm/features/pm-kipd.toon),
|
|
333
|
+
[pm-nilh](../.agents/pm/features/pm-nilh.toon),
|
|
334
|
+
[pm-cfed](../.agents/pm/features/pm-cfed.toon), and
|
|
335
|
+
[pm-g9xk](../.agents/pm/features/pm-g9xk.toon).
|
|
336
|
+
|
|
330
337
|
Shortest agent-friendly create (positional title + defaults to `Task` type):
|
|
331
338
|
|
|
332
339
|
```bash
|
|
@@ -376,6 +383,25 @@ pm update pm-a1b2 --body-file ./specs/updated-spec.md
|
|
|
376
383
|
|
|
377
384
|
`--body-file` is mutually exclusive with `--body` (passing both errors). Use `--body -` to read the body from piped stdin.
|
|
378
385
|
|
|
386
|
+
For whole-item automation, `--stdin-json` on create/update accepts either a
|
|
387
|
+
direct item object or the envelope emitted by `pm get <id> --json`. Read-only
|
|
388
|
+
fields are ignored, linked facets are normalized through their audited mutation
|
|
389
|
+
inputs, and explicit CLI flags override document values:
|
|
390
|
+
|
|
391
|
+
```bash
|
|
392
|
+
# Create from a complete document.
|
|
393
|
+
printf '%s' '{"title":"Imported incident","type":"Issue","tags":["imported"]}' \
|
|
394
|
+
| pm create --stdin-json --json
|
|
395
|
+
|
|
396
|
+
# Lossless get -> edit -> update round trip.
|
|
397
|
+
pm get pm-a1b2 --json > item.json
|
|
398
|
+
# edit item.json with an ordinary JSON-aware tool
|
|
399
|
+
pm update pm-a1b2 --stdin-json < item.json
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Input is strict: a near-miss such as `acceptance_criterai` fails with a
|
|
403
|
+
did-you-mean diagnostic instead of becoming an accidental custom field.
|
|
404
|
+
|
|
379
405
|
Repeated singular/plural list flags now accumulate, so `--tag a --tag b` is equivalent to `--tags a,b` (the same holds for `--status`, `--ids`, and `--fields` on read commands). Earlier versions silently kept only the last value. `list`/`search` also accept `--tags` as a never-block alias for the canonical read filter `--tag`.
|
|
380
406
|
|
|
381
407
|
`--tags` REPLACES the whole tag list. To edit tags without restating the full set, use the additive/subtractive flags on `create`/`update`/`update-many`:
|
|
@@ -389,7 +415,7 @@ pm update pm-abc1 --remove-tags stale # drops "stale", keeps the rest
|
|
|
389
415
|
pm create "New backend task" --add-tags backend,p1
|
|
390
416
|
```
|
|
391
417
|
|
|
392
|
-
Acceptance criteria get the same additive treatment on `update`/`update-many`: `--acceptance-criteria`/`--ac` REPLACES the whole value, while `--add-ac <text>` appends one criterion (repeatable; deduped on exact text) and `--remove-ac <text>` removes one criterion by exact text match (repeatable; a non-matching selector adds a `remove_ac_unmatched:<text>` warning instead of silently no-oping). Criteria are stored
|
|
418
|
+
Acceptance criteria get the same additive treatment on `update`/`update-many`: `--acceptance-criteria`/`--ac` REPLACES the whole value, while `--add-ac <text>` appends one criterion (repeatable; deduped on exact text) and `--remove-ac <text>` removes one criterion by exact text match (repeatable; a non-matching selector adds a `remove_ac_unmatched:<text>` warning instead of silently no-oping). Criteria are stored with semicolon-space separators, so one criterion cannot contain a semicolon. Disjoint `--add-ac` edits from concurrent agents/branches merge cleanly instead of clobbering each other.
|
|
393
419
|
|
|
394
420
|
```bash
|
|
395
421
|
pm update pm-abc1 --add-ac "error path covered by a regression test"
|
|
@@ -426,13 +452,29 @@ pm update <id> --expected "Retry succeeds after backoff" --actual "Retry threw o
|
|
|
426
452
|
|
|
427
453
|
Repeat `--ac`/`--acceptance-criteria` to build multi-part criteria; values are stored in order joined by `; `. Dependency inputs accept either a bare existing item id or the explicit `id=<id>,kind=<kind>` form, and malformed shorthand such as `related:pm-abcd` fails before it can create a dangling graph edge.
|
|
428
454
|
|
|
429
|
-
Mutation commands (`create`/`update`/`close`/`append`/...)
|
|
455
|
+
Mutation commands (`create`/`update`/`close`/`append`/...) default to an
|
|
456
|
+
agent-efficient `id`/`status`/`changed_field_count` envelope. Use
|
|
457
|
+
`--no-changed-fields` for the full item echo without the redundant delta array,
|
|
458
|
+
or `--full-changed-fields` to restore the legacy complete envelope:
|
|
430
459
|
|
|
431
460
|
```bash
|
|
432
|
-
pm
|
|
461
|
+
pm create "Probe item" # id + status + changed_field_count
|
|
462
|
+
pm --no-changed-fields create "Probe item" # item echo + changed_field_count
|
|
463
|
+
pm --full-changed-fields create "Probe item" # item echo + changed_fields array
|
|
433
464
|
pm --id-only create "Probe item" # output is only id + status
|
|
434
465
|
```
|
|
435
466
|
|
|
467
|
+
For strict JSON consumers, the global `--lean` flag recursively omits null,
|
|
468
|
+
undefined, empty-array, and empty-object noise while preserving meaningful
|
|
469
|
+
false/zero/empty-string values. On usage failures it keeps only actionable
|
|
470
|
+
error fields (`type`, `code`, `detail`, `exit_code`, examples, next steps, and
|
|
471
|
+
recovery), reducing retry context without hiding the deterministic fix:
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
pm --json --lean get pm-a1b2
|
|
475
|
+
pm --json --lean create --unknown-option
|
|
476
|
+
```
|
|
477
|
+
|
|
436
478
|
Use `pm create --allow-missing-parent --parent <id>` only for deliberate imports or staged backlog reconstruction. Normal `pm create --parent <id>` fails fast when the parent id cannot be resolved.
|
|
437
479
|
|
|
438
480
|
Use `pm close <duplicate-id> --duplicate-of <canonical-id>` to close duplicates. The command validates the canonical target exists, records `duplicate_of`, auto-fills the close reason as `Duplicate of <canonical-id>` when no reason text was supplied, and fills the resolution/expected/actual closure fields when they were not provided explicitly.
|
|
@@ -447,6 +489,32 @@ When closing a blocker, `pm close` scans reverse `blocked_by` edges and auto-unb
|
|
|
447
489
|
|
|
448
490
|
Over MCP the mutation tools (`pm_create`/`pm_update`/`pm_close`/`pm_run` append/update-many) are compact by default; pass `fullChangedFields=true` to restore the full `changed_fields` delta, or `idOnly=true` for single-item id/status output.
|
|
449
491
|
|
|
492
|
+
### Atomic heterogeneous mutation batches
|
|
493
|
+
|
|
494
|
+
`pm item mutate` is the noun-first CLI adapter over the public SDK
|
|
495
|
+
`commitItemMutations` primitive. Pipe a non-empty JSON array (or an object with a
|
|
496
|
+
`mutations` array), provide one stable transaction id, and mix create/update/
|
|
497
|
+
close operations in order:
|
|
498
|
+
|
|
499
|
+
```bash
|
|
500
|
+
pm item mutate \
|
|
501
|
+
--transaction-id sync-2026-07-20-001 \
|
|
502
|
+
--stdin-json <<'JSON'
|
|
503
|
+
[
|
|
504
|
+
{"op":"create","id":"ext-1042","options":{"title":"Imported issue","type":"Issue"}},
|
|
505
|
+
{"op":"update","id":"pm-a1b2","options":{"priority":"1","addTags":["synced"]}},
|
|
506
|
+
{"op":"close","id":"pm-c3d4","reason":"Resolved upstream"}
|
|
507
|
+
]
|
|
508
|
+
JSON
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
Use `--dry-run` to validate and preview without acquiring a writer lock. Reuse
|
|
512
|
+
the exact transaction id and deterministic batch after interruption: the SDK
|
|
513
|
+
journal resumes pending steps and never duplicates a successfully applied
|
|
514
|
+
step. `--create-compensation close|delete`, `--lock-ttl-seconds`, and
|
|
515
|
+
`--lock-wait-ms` expose the transaction safety controls. The equivalent MCP
|
|
516
|
+
surface is `pm_mutate`.
|
|
517
|
+
|
|
450
518
|
## Focus (session default parent)
|
|
451
519
|
|
|
452
520
|
`pm focus` sets a session "focused" item so subsequent `pm create` calls default their `--parent` to it — project management is context management, and focus keeps new work attached to the active parent without restating `--parent` every time.
|
|
@@ -574,10 +642,22 @@ pm graph audit --sample 5 --exempt-isolate pm-root
|
|
|
574
642
|
pm graph communities --kind blocked_by --limit 5
|
|
575
643
|
pm graph redundancy --max-depth 6 --limit 20
|
|
576
644
|
pm graph dominators <id> --direction outgoing --limit 10
|
|
645
|
+
pm graph slack --limit 20
|
|
646
|
+
pm graph centrality --kind blocked_by --limit 10
|
|
647
|
+
pm graph articulation --limit 20
|
|
577
648
|
pm graph plan --sample 5 --limit 20
|
|
649
|
+
pm graph audit --save-baseline
|
|
650
|
+
pm graph audit --exempt-isolate-type Reminder,Event
|
|
651
|
+
pm graph index
|
|
652
|
+
pm graph index --rebuild
|
|
653
|
+
pm graph index --clear
|
|
578
654
|
```
|
|
579
655
|
|
|
580
|
-
`graph` is read-only and answers workspace-wide relationship questions through the public SDK graph toolkit. `ancestors`/`descendants` walk registered hierarchy kinds, `predecessors`/`successors` walk order-bearing kinds, `paths` enumerates bounded simple paths between two items with per-edge kinds, and `impact` reports the bounded blast radius with an explaining path per affected item. `analyze` returns workspace execution analytics (topological layers, prerequisite frontier, critical path, genuine ordering cycles) plus knowledge-graph structure (components, orphans, hubs), and `audit` runs the policy-aware governance audit with counts-first findings, severities, and bounded evidence samples. Audit severity gates on lifecycle: ordering cycles and duplicated edge spellings confined to closed/canceled items downgrade to informational `legacy_ordering_cycle`/`legacy_duplicate_edge` findings (history debt, never repaired ad hoc), while `ordering_cycle` errors and `duplicate_edge` findings are reserved for subjects touching at least one active item; `duplicate_edge` reports parallel same-family spellings — including reciprocal inverse pairs such as `A blocked_by B` plus `B blocks A` — that transitive-reduction redundancy deliberately cannot see. `communities` clusters the undirected structure with deterministic label propagation (reporting `iterations` and `converged`), `redundancy` finds stored edges implied by a longer path of the same semantic family (`blocked_by`/`blocks` and hierarchy spellings witness each other, each row carrying its witness path), and `dominators` reports the structural bottlenecks of one item's reachable subgraph — nodes every path from the root must pass through, ranked by how much work they gate (`dominated_count`). `plan` derives a dry-run remediation plan from the audit plus the redundancy scan: exact `remove`/`retype`/`supersede`/`waive`/`investigate` proposals with per-step policy code, evidence, rationale, and confidence — nothing is ever applied automatically and no proposal invents an edge. Every envelope is counts-first with explicit `truncated`, `cost` (visited nodes, inspected edges), and `cache` (workspace fingerprint plus assembly/result hit-or-miss) metadata; repeated identical queries in long-lived hosts such as the MCP server are answered from a fingerprint-keyed snapshot cache that invalidates on any relationship-relevant item change. `--summary` suppresses row collections entirely. `--kind` accepts registered relationship kinds (repeatable or comma-separated) and fails fast on unknown values (`redundancy` additionally requires directed ordering or hierarchy kinds); `--after` resumes hierarchy/ordering walks after a previously returned node id (see [Relationship Graph](RELATIONSHIP_GRAPH.md)).
|
|
656
|
+
`graph` is read-only and answers workspace-wide relationship questions through the public SDK graph toolkit. `ancestors`/`descendants` walk registered hierarchy kinds, `predecessors`/`successors` walk order-bearing kinds, `paths` enumerates bounded simple paths between two items with per-edge kinds, and `impact` reports the bounded blast radius with an explaining path per affected item. `analyze` returns workspace execution analytics (topological layers, prerequisite frontier, critical path, genuine ordering cycles) plus knowledge-graph structure (components, orphans, hubs), and `audit` runs the policy-aware governance audit with counts-first findings, severities, and bounded evidence samples. Audit severity gates on lifecycle: ordering cycles and duplicated edge spellings confined to closed/canceled items downgrade to informational `legacy_ordering_cycle`/`legacy_duplicate_edge` findings (history debt, never repaired ad hoc), while `ordering_cycle` errors and `duplicate_edge` findings are reserved for subjects touching at least one active item; `duplicate_edge` reports parallel same-family spellings — including reciprocal inverse pairs such as `A blocked_by B` plus `B blocks A` — that transitive-reduction redundancy deliberately cannot see. `communities` clusters the undirected structure with deterministic label propagation (reporting `iterations` and `converged`), `redundancy` finds stored edges implied by a longer path of the same semantic family (`blocked_by`/`blocks` and hierarchy spellings witness each other, each row carrying its witness path), and `dominators` reports the structural bottlenecks of one item's reachable subgraph — nodes every path from the root must pass through, ranked by how much work they gate (`dominated_count`). Three planning and structural analytics complete the surface: `slack` runs the Critical Path Method over the order-bearing DAG and reports each task's earliest start, latest start, total float (`slack`), and whether it is `critical` (zero slack), plus the overall `makespan` and critical path — unit task durations keep it deterministic and metadata-independent, and genuine cycles are reported apart from the schedule; `centrality` ranks nodes by exact shortest-path `betweenness` (Brandes) with Wasserman–Faust `closeness`, undirected `degree`, and dependency fan-in/fan-out (`in_degree`/`out_degree`, ordering predecessors/successors oriented by precedence) over the simple undirected graph; and `articulation` reports the graph's articulation points and bridges — the cut vertices and cut edges whose removal fragments the knowledge graph into more components (single points of failure). `plan` derives a dry-run remediation plan from the audit plus the redundancy scan: exact `remove`/`retype`/`supersede`/`waive`/`investigate` proposals with per-step policy code, evidence, rationale, and confidence — nothing is ever applied automatically and no proposal invents an edge. Every envelope is counts-first with explicit `truncated`, `cost` (visited nodes, inspected edges), and `cache` (workspace fingerprint plus assembly/result hit-or-miss) metadata; repeated identical queries in long-lived hosts such as the MCP server are answered from a fingerprint-keyed snapshot cache that invalidates on any relationship-relevant item change. `--summary` suppresses row collections entirely. `--kind` accepts registered relationship kinds (repeatable or comma-separated) and fails fast on unknown values (`redundancy` additionally requires directed ordering or hierarchy kinds); `--after` resumes hierarchy/ordering walks after a previously returned node id (see [Relationship Graph](RELATIONSHIP_GRAPH.md)).
|
|
657
|
+
|
|
658
|
+
The audit also reports storage-layer integrity and per-type coverage. `duplicate_dependency_row` (warning on active holders, informational `legacy_duplicate_dependency_row` on terminal ones) catches raw dependency rows whose exact identity — holder, kind, and case-insensitive target — is stored more than once on one item; graph edge-identity dedup hides these from every assembled-graph projection, so the pre-assembly scan is the only surface that can see them. The audit `profile` gains `coverage_by_type`, a per-item-type breakdown of active, isolated, and degree-at-most-one nodes (untyped items bucket under `(untyped)`), and `--exempt-isolate-type <type>` (repeatable or comma-separated, case-insensitive) suppresses isolate/sparse coverage findings for types whose disconnection is policy-valid (reminders, calendar events) while keeping them counted in the profile. `--save-baseline` persists the audit census (`affected_subjects_by_code` plus the profile) as the machine-local comparison point under `.agents/pm/runtime/graph-audit-baseline.json`; every later audit automatically attaches a `baseline` block with the signed drift since that census (`same_snapshot`, per-code deltas, profile deltas including per-kind edge counts) — the temporal primitive for tracking relationship-graph health across sessions without storing full finding collections.
|
|
659
|
+
|
|
660
|
+
`index` maintains the durable cross-process graph index at `.agents/pm/runtime/graph-cache.json` (gitignored, machine-local): a fingerprint-keyed, atomically written, crash-safe envelope of deterministic query results that lets one-shot CLI invocations reuse analysis computed by earlier processes. Every non-index graph envelope reports `cache.durable` (`hit`, `miss`, or `off`). Persistence is automatic at ≥500 items and otherwise opt-in: `pm graph index` reports status (`fresh`/`stale`/`absent`, entry count, size, thresholds), `pm graph index --rebuild` clears, re-creates, and warms the envelope with the counts-first `analyze`/`audit` census queries (and enables persistence on small workspaces), and `pm graph index --clear` deletes it. The index is never authoritative — any relationship-relevant item change invalidates the fingerprint and queries transparently recompute from item storage.
|
|
581
661
|
|
|
582
662
|
## Linked Tests
|
|
583
663
|
|