@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutation-advisory.js","sources":["sdk/graph/mutation-advisory.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module sdk/graph/mutation-advisory\n *\n * Detects newly introduced execution-order cycles across immutable workspace\n * snapshots so mutation clients can warn without rejecting legacy graph debt.\n */\nimport type { ItemMetadata } from \"../../types/index.js\";\nimport { analyzeRelationshipExecution } from \"../relationship-analytics.js\";\nimport type { RelationshipGraph } from \"../relationships.js\";\nimport { assembleWorkspaceRelationshipGraph } from \"./assembly.js\";\n\nfunction cycleKey(component: readonly string[]): string {\n return [...component]\n .sort((left, right) => left.localeCompare(right))\n .join(\"\\u0000\");\n}\n\nfunction buildOrderingAdjacency(graph: RelationshipGraph): Map<string, string[]> {\n const adjacency = new Map(graph.nodes().map((node) => [node, [] as string[]]));\n for (const edge of graph.edges()) {\n const definition = graph.registry().require(edge.kind);\n if (!definition.ordering) continue;\n const sourceFirst =\n (definition.precedence ?? \"source_before_target\") ===\n \"source_before_target\";\n adjacency\n .get(sourceFirst ? edge.source : edge.target)\n ?.push(sourceFirst ? edge.target : edge.source);\n }\n for (const neighbors of adjacency.values()) {\n neighbors.sort((left, right) => left.localeCompare(right));\n }\n return adjacency;\n}\n\nfunction findCyclePath(\n graph: RelationshipGraph,\n component: readonly string[],\n changedItemId: string,\n): string[] {\n const members = new Set(component);\n const start = members.has(changedItemId) ? changedItemId : component[0]!;\n const adjacency = buildOrderingAdjacency(graph);\n if (adjacency.get(start)?.includes(start)) return [start, start];\n for (const first of adjacency.get(start) ?? []) {\n if (!members.has(first)) continue;\n const path = findPathBackToStart(adjacency, members, start, first);\n if (path) return path;\n }\n return [...component, component[0]!];\n}\n\nfunction findPathBackToStart(\n adjacency: ReadonlyMap<string, readonly string[]>,\n members: ReadonlySet<string>,\n start: string,\n first: string,\n): string[] | undefined {\n const queue = [[first]];\n const visited = new Set([start, first]);\n while (queue.length > 0) {\n const path = queue.shift()!;\n const tail = path.at(-1)!;\n for (const next of adjacency.get(tail) ?? []) {\n if (next === start) return [start, ...path, start];\n if (!members.has(next) || visited.has(next)) continue;\n visited.add(next);\n queue.push([...path, next]);\n }\n }\n return undefined;\n}\n\n/** Return actionable warnings only for ordering cycles created by the later snapshot and containing the changed item. */\nexport function collectNewOrderingCycleWarnings(\n beforeItems: readonly ItemMetadata[],\n afterItems: readonly ItemMetadata[],\n changedItemId: string,\n): string[] {\n const beforeGraph = assembleWorkspaceRelationshipGraph(beforeItems).graph;\n const afterGraph = assembleWorkspaceRelationshipGraph(afterItems).graph;\n const beforeCycles = new Set(\n analyzeRelationshipExecution(beforeGraph, {\n registry: beforeGraph.registry(),\n }).cycles.map(cycleKey),\n );\n return analyzeRelationshipExecution(afterGraph, {\n registry: afterGraph.registry(),\n }).cycles\n .filter(\n (component) =>\n component.includes(changedItemId) &&\n !beforeCycles.has(cycleKey(component)),\n )\n .map(\n (component) =>\n `ordering_cycle_created:${findCyclePath(afterGraph, component, changedItemId).join(\" -> \")}:items_will_not_be_ready:run_pm_graph_audit`,\n );\n}\n\n/** White-box graph-path helpers for exhaustive SDK primitive verification. */\nexport const mutationAdvisoryTestOnly = {\n buildOrderingAdjacency,\n findCyclePath,\n findPathBackToStart,\n};\n"],"names":[],"mappings":"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","debugId":"b116c910-3783-5ebc-8b6a-e9a64573107e"}
|
|
1
|
+
{"version":3,"file":"mutation-advisory.js","sources":["sdk/graph/mutation-advisory.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module sdk/graph/mutation-advisory\n *\n * Detects newly introduced execution-order cycles across immutable workspace\n * snapshots so mutation clients can warn without rejecting legacy graph debt.\n * Detection is incremental: instead of assembling the full workspace\n * relationship graph and running whole-graph cycle analysis twice per\n * mutation, both snapshots build only a lightweight ordering digraph and scope\n * cycle enumeration to the changed item's weakly connected ordering component\n * — a cycle containing the changed item can never span nodes outside it.\n */\nimport type { ItemMetadata } from \"../../types/index.js\";\nimport type { RelationshipKindRegistry } from \"../relationships.js\";\nimport {\n normalizeDependencyGraphTarget,\n resolveWorkspaceRelationshipKindRegistry,\n} from \"./assembly.js\";\nimport { collectOrderingCycles } from \"./governance.js\";\n\n/** Lightweight ordering digraph over one immutable item snapshot. */\ninterface OrderingDigraph {\n /** Sorted successor adjacency oriented predecessor -> successor. */\n successors: Map<string, string[]>;\n /** Sorted predecessor adjacency, the reverse orientation of successors. */\n predecessors: Map<string, string[]>;\n /** Canonical original-case ids keyed by their lowercase spelling. */\n canonicalIds: Map<string, string>;\n}\n\nfunction cycleKey(component: readonly string[]): string {\n return [...component].sort().join(\"\\u0000\");\n}\n\n/** Append one oriented ordering edge to both adjacency orientations. */\nfunction addOrderingEdge(\n digraph: OrderingDigraph,\n predecessor: string,\n successor: string,\n): void {\n const forward = digraph.successors.get(predecessor);\n if (forward) forward.push(successor);\n else digraph.successors.set(predecessor, [successor]);\n const backward = digraph.predecessors.get(successor);\n if (backward) backward.push(predecessor);\n else digraph.predecessors.set(successor, [predecessor]);\n}\n\n/**\n * Orient one candidate reference into the digraph when its kind is a\n * registry-known order-bearing kind and its target resolves to a real item.\n * Associative kinds, unknown kinds, retired sentinels, and references to\n * absent items are skipped because none of them can create an\n * execution-order cycle — a referenced-but-absent item has no stored\n * out-edges.\n */\nfunction orientOrderingEdge(\n digraph: OrderingDigraph,\n registry: RelationshipKindRegistry,\n source: string,\n target: unknown,\n kind: string,\n): void {\n const definition = registry.resolve(kind);\n if (definition?.ordering !== true) return;\n const normalized = normalizeDependencyGraphTarget(target);\n const canonicalTarget =\n normalized === undefined\n ? undefined\n : digraph.canonicalIds.get(normalized.toLowerCase());\n if (canonicalTarget === undefined) return;\n const sourceFirst =\n (definition.precedence ?? \"source_before_target\") ===\n \"source_before_target\";\n addOrderingEdge(\n digraph,\n sourceFirst ? source : canonicalTarget,\n sourceFirst ? canonicalTarget : source,\n );\n}\n\n/**\n * Build the ordering-only digraph for one item snapshot without assembling a\n * full relationship graph: one linear pass over the legacy scalar blocker and\n * structured dependency rows of every item.\n */\nfunction buildOrderingDigraph(\n items: readonly ItemMetadata[],\n registry: RelationshipKindRegistry,\n): OrderingDigraph {\n const digraph: OrderingDigraph = {\n successors: new Map(),\n predecessors: new Map(),\n canonicalIds: new Map(),\n };\n const safeItems = items.filter(\n (item) => typeof item?.id === \"string\" && item.id.trim().length > 0,\n );\n for (const item of safeItems) {\n const id = item.id.trim();\n digraph.canonicalIds.set(id.toLowerCase(), id);\n }\n for (const item of safeItems) {\n const id = item.id.trim();\n orientOrderingEdge(digraph, registry, id, item.blocked_by, \"blocked_by\");\n for (const dependency of item.dependencies ?? []) {\n if (typeof dependency !== \"object\" || dependency === null) continue;\n orientOrderingEdge(\n digraph,\n registry,\n id,\n dependency.id,\n typeof dependency.kind === \"string\" ? dependency.kind : \"related\",\n );\n }\n }\n for (const adjacency of [digraph.successors, digraph.predecessors])\n for (const neighbors of adjacency.values()) neighbors.sort();\n return digraph;\n}\n\n/**\n * Collect the changed item's weakly connected ordering component: every node\n * reachable through ordering edges in either orientation. Cycle enumeration\n * restricted to this member set is exact for cycles containing the changed\n * item, because a strongly connected component is always contained in a\n * weakly connected one.\n */\nfunction collectWeakComponent(\n digraph: OrderingDigraph,\n start: string,\n): Set<string> {\n const members = new Set([start]);\n const queue = [start];\n while (queue.length > 0) {\n const node = queue.pop()!;\n for (const adjacency of [digraph.successors, digraph.predecessors]) {\n for (const neighbor of adjacency.get(node) ?? []) {\n if (members.has(neighbor)) continue;\n members.add(neighbor);\n queue.push(neighbor);\n }\n }\n }\n return members;\n}\n\n/** Restrict a successor adjacency to edges whose endpoints are both members. */\nfunction induceSuccessors(\n digraph: OrderingDigraph,\n members: ReadonlySet<string>,\n): Map<string, string[]> {\n const induced = new Map<string, string[]>();\n for (const member of members) {\n const neighbors = (digraph.successors.get(member) ?? []).filter((node) =>\n members.has(node),\n );\n if (neighbors.length > 0) induced.set(member, neighbors);\n }\n return induced;\n}\n\n/** Enumerate component-scoped ordering cycles around one canonical item id. */\nfunction collectScopedCycles(\n items: readonly ItemMetadata[],\n registry: RelationshipKindRegistry,\n changedItemId: string,\n): {\n cycles: string[][];\n successors: Map<string, string[]>;\n canonical: string;\n} {\n const digraph = buildOrderingDigraph(items, registry);\n const canonical = digraph.canonicalIds.get(\n changedItemId.trim().toLowerCase(),\n );\n if (canonical === undefined)\n return { cycles: [], successors: new Map(), canonical: changedItemId };\n const successors = induceSuccessors(\n digraph,\n collectWeakComponent(digraph, canonical),\n );\n return {\n cycles: collectOrderingCycles(successors).filter((component) =>\n component.includes(canonical),\n ),\n successors,\n canonical,\n };\n}\n\nfunction findCyclePath(\n adjacency: ReadonlyMap<string, readonly string[]>,\n component: readonly string[],\n changedItemId: string,\n): string[] {\n const members = new Set(component);\n const start = members.has(changedItemId) ? changedItemId : component[0]!;\n if (adjacency.get(start)?.includes(start)) return [start, start];\n for (const first of adjacency.get(start) ?? []) {\n if (!members.has(first)) continue;\n const path = findPathBackToStart(adjacency, members, start, first);\n if (path) return path;\n }\n return [...component, component[0]!];\n}\n\nfunction findPathBackToStart(\n adjacency: ReadonlyMap<string, readonly string[]>,\n members: ReadonlySet<string>,\n start: string,\n first: string,\n): string[] | undefined {\n const queue = [[first]];\n const visited = new Set([start, first]);\n while (queue.length > 0) {\n const path = queue.shift()!;\n const tail = path.at(-1)!;\n for (const next of adjacency.get(tail) ?? []) {\n if (next === start) return [start, ...path, start];\n if (!members.has(next) || visited.has(next)) continue;\n visited.add(next);\n queue.push([...path, next]);\n }\n }\n return undefined;\n}\n\n/** Return actionable warnings only for ordering cycles created by the later snapshot and containing the changed item. */\nexport function collectNewOrderingCycleWarnings(\n beforeItems: readonly ItemMetadata[],\n afterItems: readonly ItemMetadata[],\n changedItemId: string,\n): string[] {\n const registry = resolveWorkspaceRelationshipKindRegistry();\n const before = collectScopedCycles(beforeItems, registry, changedItemId);\n const after = collectScopedCycles(afterItems, registry, changedItemId);\n const beforeCycles = new Set(before.cycles.map(cycleKey));\n return after.cycles\n .filter((component) => !beforeCycles.has(cycleKey(component)))\n .map(\n (component) =>\n `ordering_cycle_created:${findCyclePath(after.successors, component, after.canonical).join(\" -> \")}:items_will_not_be_ready:run_pm_graph_audit`,\n );\n}\n\n/** White-box graph-path helpers for exhaustive SDK primitive verification. */\nexport const mutationAdvisoryTestOnly = {\n buildOrderingDigraph,\n collectWeakComponent,\n induceSuccessors,\n findCyclePath,\n findPathBackToStart,\n};\n"],"names":[],"mappings":"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","debugId":"9dcd2523-3a8a-5667-bd6b-d51c385be111"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ebb01d6f-d876-5196-9937-24528a66b160")}catch(e){}}();
|
|
3
3
|
import { findRedundantRelationshipEdges } from "./analytics.js";
|
|
4
4
|
import { auditWorkspaceRelationshipGraph, collectDuplicateRelationshipEdgeGroups, formatDuplicateEdgeGroup, } from "./governance.js";
|
|
5
5
|
/** Per-finding-code operation template applied to every sampled subject. */
|
|
@@ -42,6 +42,16 @@ const FINDING_STEP_TEMPLATES = {
|
|
|
42
42
|
confidence: "high",
|
|
43
43
|
rationale: "Duplicated spellings between terminal items are historical noise; waive or batch changelog-safe cleanup.",
|
|
44
44
|
},
|
|
45
|
+
duplicate_dependency_row: {
|
|
46
|
+
op: "remove",
|
|
47
|
+
confidence: "high",
|
|
48
|
+
rationale: "The identical dependency row is stored more than once on the holder; drop the repeats so the row exists exactly once — graph semantics are unchanged.",
|
|
49
|
+
},
|
|
50
|
+
legacy_duplicate_dependency_row: {
|
|
51
|
+
op: "waive",
|
|
52
|
+
confidence: "high",
|
|
53
|
+
rationale: "Repeated identical rows on terminal holders are storage noise; waive or clean up only in a changelog-safe closed-item batch.",
|
|
54
|
+
},
|
|
45
55
|
stale_lifecycle_block: {
|
|
46
56
|
op: "investigate",
|
|
47
57
|
confidence: "medium",
|
|
@@ -145,4 +155,4 @@ export function planRelationshipRemediation(assembly, options = {}) {
|
|
|
145
155
|
};
|
|
146
156
|
}
|
|
147
157
|
//# sourceMappingURL=remediation.js.map
|
|
148
|
-
//# debugId=
|
|
158
|
+
//# debugId=ebb01d6f-d876-5196-9937-24528a66b160
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remediation.js","sources":["sdk/graph/remediation.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module sdk/graph/remediation\n *\n * Dry-run remediation planning over the relationship governance audit. The\n * planner turns bounded audit findings and transitive-redundancy evidence into\n * exact, machine-readable proposed operations — remove, retype, supersede,\n * waive, or investigate — each carrying its policy code, evidence, confidence,\n * and rationale. Planning never mutates the workspace and never invents an\n * edge: proposals with structural proof (duplicates, retired sentinels,\n * witnessed shortcuts) get actionable operations, while judgment calls stay\n * explicit `investigate` steps for a human or agent to resolve.\n */\nimport type { RelationshipEdge } from \"../relationships.js\";\nimport { findRedundantRelationshipEdges } from \"./analytics.js\";\nimport type { WorkspaceRelationshipAssembly } from \"./assembly.js\";\nimport {\n auditWorkspaceRelationshipGraph,\n collectDuplicateRelationshipEdgeGroups,\n formatDuplicateEdgeGroup,\n type DuplicateRelationshipEdgeGroup,\n type RelationshipAuditFinding,\n type RelationshipAuditFindingCode,\n type RelationshipAuditOptions,\n type RelationshipAuditReport,\n} from \"./governance.js\";\n\n/** Exact operation family a remediation step proposes; audits never auto-apply. */\nexport type RelationshipRemediationOperation =\n | \"add\"\n | \"remove\"\n | \"retype\"\n | \"supersede\"\n | \"waive\"\n | \"investigate\";\n\n/** Planner confidence that applying the proposed operation is safe and correct. */\nexport type RelationshipRemediationConfidence = \"high\" | \"medium\" | \"low\";\n\n/** Policy source a remediation step was derived from. */\nexport type RelationshipRemediationCode =\n | RelationshipAuditFindingCode\n | \"redundant_edge\";\n\n/** One exact dry-run remediation proposal with evidence and confidence. */\nexport interface RelationshipRemediationStep {\n /** Proposed operation family. */\n op: RelationshipRemediationOperation;\n /** Audit finding code or `redundant_edge` for witnessed transitive shortcuts. */\n code: RelationshipRemediationCode;\n /** Compact deterministic subject — the edge, reference, or node to act on. */\n subject: string;\n /** Why this operation is proposed and what applying it means. */\n rationale: string;\n /** Deterministic evidence strings backing the proposal. */\n evidence: string[];\n /** Planner confidence in the proposal. */\n confidence: RelationshipRemediationConfidence;\n}\n\n/** Tuning inputs accepted by dry-run remediation planning. */\nexport interface RelationshipRemediationPlanOptions\n extends RelationshipAuditOptions {\n /** Maximum witnessed redundant edges scanned into proposals; defaults to the audit sample bound. */\n redundancyLimit?: number;\n}\n\n/** Complete deterministic result of one dry-run remediation planning pass. */\nexport interface RelationshipRemediationPlan {\n /** Proposed steps in audit severity order, redundancy proposals last. */\n steps: RelationshipRemediationStep[];\n /** The governance-audit report the plan was derived from. */\n report: RelationshipAuditReport;\n /** Whether bounded samples or scan limits omitted derivable proposals. */\n truncated: boolean;\n /** Nodes visited and edges inspected by the redundancy witness scan. */\n cost: { visitedNodes: number; inspectedEdges: number };\n}\n\n/** Per-finding-code operation template applied to every sampled subject. */\nconst FINDING_STEP_TEMPLATES: Record<\n RelationshipAuditFindingCode,\n {\n op: RelationshipRemediationOperation;\n confidence: RelationshipRemediationConfidence;\n rationale: string;\n }\n> = {\n missing_reference_active: {\n op: \"investigate\",\n confidence: \"medium\",\n rationale:\n \"Restore or re-create the referenced item, or remove/retype the reference on the active holder; the correct fix depends on why the target is absent.\",\n },\n missing_reference_terminal: {\n op: \"waive\",\n confidence: \"high\",\n rationale:\n \"Terminal-holder reference to an absent item is historical debt; waive it or clean it up only in a dedicated changelog-safe closed-item batch.\",\n },\n legacy_no_blocker_sentinel: {\n op: \"remove\",\n confidence: \"high\",\n rationale:\n \"The pre-structured-dependency no-active-blocker sentinel is retired and carries no information; blocker state derives from blocked_by edges.\",\n },\n ordering_cycle: {\n op: \"investigate\",\n confidence: \"low\",\n rationale:\n \"Every cycle member is unschedulable until one ordering edge is removed or retyped; the planner never chooses which edge to cut.\",\n },\n legacy_ordering_cycle: {\n op: \"waive\",\n confidence: \"high\",\n rationale:\n \"Terminal-only ordering cycles have no scheduling effect; repairing them would mutate closed history (changelog drag).\",\n },\n // duplicate_edge findings are expanded into per-stored-edge remove steps by\n // the planner itself (see stepsFromDuplicateGroup); this template documents\n // the family for exhaustiveness and backs any future sample-only fallback.\n duplicate_edge: {\n op: \"remove\",\n confidence: \"high\",\n rationale:\n \"Parallel same-family spellings state one relationship twice; remove all but one stored spelling, keeping the holder's canonical direction.\",\n },\n legacy_duplicate_edge: {\n op: \"waive\",\n confidence: \"high\",\n rationale:\n \"Duplicated spellings between terminal items are historical noise; waive or batch changelog-safe cleanup.\",\n },\n stale_lifecycle_block: {\n op: \"investigate\",\n confidence: \"medium\",\n rationale:\n \"Re-open the missing prerequisite as an ordering edge, or move the item back to an active status; only the holder's owner knows which is true.\",\n },\n isolated_active_node: {\n op: \"investigate\",\n confidence: \"medium\",\n rationale:\n \"Link the item to its parent, prerequisite, or origin — or register it as an explicitly exempt isolate; the audit never fabricates an edge.\",\n },\n sparse_active_node: {\n op: \"investigate\",\n confidence: \"low\",\n rationale:\n \"Investigate for an honest second edge (story-to-task, defect family, cross-epic complement); sparse is not automatically defective.\",\n },\n};\n\n/** Format one stored edge as a concrete removable identity. */\nfunction formatStoredEdge(edge: RelationshipEdge): string {\n return `${edge.source} -${edge.kind}-> ${edge.target}`;\n}\n\n/**\n * Expand one active duplicate group into concrete per-stored-edge removals.\n * The deterministic keeper is the group's first sorted edge; every other\n * stored spelling gets its own remove proposal naming the exact edge to drop,\n * so the plan stays machine-executable instead of pointing at a display\n * string that spans several stored rows.\n */\nfunction stepsFromDuplicateGroup(\n group: DuplicateRelationshipEdgeGroup,\n): RelationshipRemediationStep[] {\n const [keeper, ...extras] = group.edges;\n return extras.map((edge) => ({\n op: \"remove\" as const,\n code: \"duplicate_edge\" as const,\n subject: formatStoredEdge(edge),\n rationale:\n \"This stored spelling restates the kept canonical edge of the same semantic family; removing it leaves the relationship stated exactly once.\",\n evidence: [\n `keep: ${formatStoredEdge(keeper!)}`,\n `group: ${formatDuplicateEdgeGroup(group)}`,\n ],\n confidence: \"high\" as const,\n }));\n}\n\n/** Derive one proposal per bounded sample subject of an audit finding. */\nfunction stepsFromFinding(\n finding: RelationshipAuditFinding,\n duplicateGroups: Map<string, DuplicateRelationshipEdgeGroup>,\n): RelationshipRemediationStep[] {\n if (finding.code === \"duplicate_edge\") {\n // Sample subjects are the deterministic group format strings, so each one\n // resolves to its concrete stored-edge group for exact removal targeting.\n return finding.sample.flatMap((subject) =>\n stepsFromDuplicateGroup(duplicateGroups.get(subject)!),\n );\n }\n const template = FINDING_STEP_TEMPLATES[finding.code];\n return finding.sample.map((subject) => ({\n op: template.op,\n code: finding.code,\n subject,\n rationale: template.rationale,\n evidence: [finding.policy],\n confidence: template.confidence,\n }));\n}\n\n/**\n * Build one deterministic dry-run remediation plan over an assembled workspace\n * relationship graph. The plan runs the shared governance audit, derives one\n * exact proposal per bounded finding subject, then appends witnessed\n * transitive-shortcut removal proposals from the redundancy scan (medium\n * confidence, because shortcut edges are sometimes deliberate emphasis).\n * `truncated` reports whether sample or scan bounds omitted derivable steps;\n * nothing is ever applied automatically.\n */\nexport function planRelationshipRemediation(\n assembly: WorkspaceRelationshipAssembly,\n options: RelationshipRemediationPlanOptions = {},\n): RelationshipRemediationPlan {\n const { redundancyLimit, ...auditOptions } = options;\n const report = auditWorkspaceRelationshipGraph(assembly, auditOptions);\n const duplicateGroups = new Map(\n collectDuplicateRelationshipEdgeGroups(assembly).map((group) => [\n formatDuplicateEdgeGroup(group),\n group,\n ]),\n );\n const steps = report.findings.flatMap((finding) =>\n stepsFromFinding(finding, duplicateGroups),\n );\n let truncated = report.findings.some((finding) => finding.sample_truncated);\n options.signal?.throwIfAborted();\n const redundancy = findRedundantRelationshipEdges(assembly.graph, {\n limit: redundancyLimit ?? options.maxSampleSize ?? 25,\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n });\n for (const row of redundancy.value) {\n steps.push({\n op: \"remove\",\n code: \"redundant_edge\",\n subject: `${row.edge.source} -> ${row.edge.target} (${row.edge.kind})`,\n rationale:\n \"The stored edge is implied by a longer same-family witness path; shortcut edges are sometimes deliberate emphasis, so confirm intent before removing.\",\n evidence: [`witness: ${row.witness.join(\" -> \")}`],\n confidence: \"medium\",\n });\n }\n truncated = truncated || redundancy.meta.truncated;\n return {\n steps,\n report,\n truncated,\n cost: {\n visitedNodes: redundancy.meta.visitedNodes,\n inspectedEdges: redundancy.meta.inspectedEdges,\n },\n };\n}\n"],"names":[],"mappings":"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","debugId":"662a9796-dbb3-5fd5-bc23-22dba9adde9e"}
|
|
1
|
+
{"version":3,"file":"remediation.js","sources":["sdk/graph/remediation.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module sdk/graph/remediation\n *\n * Dry-run remediation planning over the relationship governance audit. The\n * planner turns bounded audit findings and transitive-redundancy evidence into\n * exact, machine-readable proposed operations — remove, retype, supersede,\n * waive, or investigate — each carrying its policy code, evidence, confidence,\n * and rationale. Planning never mutates the workspace and never invents an\n * edge: proposals with structural proof (duplicates, retired sentinels,\n * witnessed shortcuts) get actionable operations, while judgment calls stay\n * explicit `investigate` steps for a human or agent to resolve.\n */\nimport type { RelationshipEdge } from \"../relationships.js\";\nimport { findRedundantRelationshipEdges } from \"./analytics.js\";\nimport type { WorkspaceRelationshipAssembly } from \"./assembly.js\";\nimport {\n auditWorkspaceRelationshipGraph,\n collectDuplicateRelationshipEdgeGroups,\n formatDuplicateEdgeGroup,\n type DuplicateRelationshipEdgeGroup,\n type RelationshipAuditFinding,\n type RelationshipAuditFindingCode,\n type RelationshipAuditOptions,\n type RelationshipAuditReport,\n} from \"./governance.js\";\n\n/** Exact operation family a remediation step proposes; audits never auto-apply. */\nexport type RelationshipRemediationOperation =\n | \"add\"\n | \"remove\"\n | \"retype\"\n | \"supersede\"\n | \"waive\"\n | \"investigate\";\n\n/** Planner confidence that applying the proposed operation is safe and correct. */\nexport type RelationshipRemediationConfidence = \"high\" | \"medium\" | \"low\";\n\n/** Policy source a remediation step was derived from. */\nexport type RelationshipRemediationCode =\n | RelationshipAuditFindingCode\n | \"redundant_edge\";\n\n/** One exact dry-run remediation proposal with evidence and confidence. */\nexport interface RelationshipRemediationStep {\n /** Proposed operation family. */\n op: RelationshipRemediationOperation;\n /** Audit finding code or `redundant_edge` for witnessed transitive shortcuts. */\n code: RelationshipRemediationCode;\n /** Compact deterministic subject — the edge, reference, or node to act on. */\n subject: string;\n /** Why this operation is proposed and what applying it means. */\n rationale: string;\n /** Deterministic evidence strings backing the proposal. */\n evidence: string[];\n /** Planner confidence in the proposal. */\n confidence: RelationshipRemediationConfidence;\n}\n\n/** Tuning inputs accepted by dry-run remediation planning. */\nexport interface RelationshipRemediationPlanOptions\n extends RelationshipAuditOptions {\n /** Maximum witnessed redundant edges scanned into proposals; defaults to the audit sample bound. */\n redundancyLimit?: number;\n}\n\n/** Complete deterministic result of one dry-run remediation planning pass. */\nexport interface RelationshipRemediationPlan {\n /** Proposed steps in audit severity order, redundancy proposals last. */\n steps: RelationshipRemediationStep[];\n /** The governance-audit report the plan was derived from. */\n report: RelationshipAuditReport;\n /** Whether bounded samples or scan limits omitted derivable proposals. */\n truncated: boolean;\n /** Nodes visited and edges inspected by the redundancy witness scan. */\n cost: { visitedNodes: number; inspectedEdges: number };\n}\n\n/** Per-finding-code operation template applied to every sampled subject. */\nconst FINDING_STEP_TEMPLATES: Record<\n RelationshipAuditFindingCode,\n {\n op: RelationshipRemediationOperation;\n confidence: RelationshipRemediationConfidence;\n rationale: string;\n }\n> = {\n missing_reference_active: {\n op: \"investigate\",\n confidence: \"medium\",\n rationale:\n \"Restore or re-create the referenced item, or remove/retype the reference on the active holder; the correct fix depends on why the target is absent.\",\n },\n missing_reference_terminal: {\n op: \"waive\",\n confidence: \"high\",\n rationale:\n \"Terminal-holder reference to an absent item is historical debt; waive it or clean it up only in a dedicated changelog-safe closed-item batch.\",\n },\n legacy_no_blocker_sentinel: {\n op: \"remove\",\n confidence: \"high\",\n rationale:\n \"The pre-structured-dependency no-active-blocker sentinel is retired and carries no information; blocker state derives from blocked_by edges.\",\n },\n ordering_cycle: {\n op: \"investigate\",\n confidence: \"low\",\n rationale:\n \"Every cycle member is unschedulable until one ordering edge is removed or retyped; the planner never chooses which edge to cut.\",\n },\n legacy_ordering_cycle: {\n op: \"waive\",\n confidence: \"high\",\n rationale:\n \"Terminal-only ordering cycles have no scheduling effect; repairing them would mutate closed history (changelog drag).\",\n },\n // duplicate_edge findings are expanded into per-stored-edge remove steps by\n // the planner itself (see stepsFromDuplicateGroup); this template documents\n // the family for exhaustiveness and backs any future sample-only fallback.\n duplicate_edge: {\n op: \"remove\",\n confidence: \"high\",\n rationale:\n \"Parallel same-family spellings state one relationship twice; remove all but one stored spelling, keeping the holder's canonical direction.\",\n },\n legacy_duplicate_edge: {\n op: \"waive\",\n confidence: \"high\",\n rationale:\n \"Duplicated spellings between terminal items are historical noise; waive or batch changelog-safe cleanup.\",\n },\n duplicate_dependency_row: {\n op: \"remove\",\n confidence: \"high\",\n rationale:\n \"The identical dependency row is stored more than once on the holder; drop the repeats so the row exists exactly once — graph semantics are unchanged.\",\n },\n legacy_duplicate_dependency_row: {\n op: \"waive\",\n confidence: \"high\",\n rationale:\n \"Repeated identical rows on terminal holders are storage noise; waive or clean up only in a changelog-safe closed-item batch.\",\n },\n stale_lifecycle_block: {\n op: \"investigate\",\n confidence: \"medium\",\n rationale:\n \"Re-open the missing prerequisite as an ordering edge, or move the item back to an active status; only the holder's owner knows which is true.\",\n },\n isolated_active_node: {\n op: \"investigate\",\n confidence: \"medium\",\n rationale:\n \"Link the item to its parent, prerequisite, or origin — or register it as an explicitly exempt isolate; the audit never fabricates an edge.\",\n },\n sparse_active_node: {\n op: \"investigate\",\n confidence: \"low\",\n rationale:\n \"Investigate for an honest second edge (story-to-task, defect family, cross-epic complement); sparse is not automatically defective.\",\n },\n};\n\n/** Format one stored edge as a concrete removable identity. */\nfunction formatStoredEdge(edge: RelationshipEdge): string {\n return `${edge.source} -${edge.kind}-> ${edge.target}`;\n}\n\n/**\n * Expand one active duplicate group into concrete per-stored-edge removals.\n * The deterministic keeper is the group's first sorted edge; every other\n * stored spelling gets its own remove proposal naming the exact edge to drop,\n * so the plan stays machine-executable instead of pointing at a display\n * string that spans several stored rows.\n */\nfunction stepsFromDuplicateGroup(\n group: DuplicateRelationshipEdgeGroup,\n): RelationshipRemediationStep[] {\n const [keeper, ...extras] = group.edges;\n return extras.map((edge) => ({\n op: \"remove\" as const,\n code: \"duplicate_edge\" as const,\n subject: formatStoredEdge(edge),\n rationale:\n \"This stored spelling restates the kept canonical edge of the same semantic family; removing it leaves the relationship stated exactly once.\",\n evidence: [\n `keep: ${formatStoredEdge(keeper!)}`,\n `group: ${formatDuplicateEdgeGroup(group)}`,\n ],\n confidence: \"high\" as const,\n }));\n}\n\n/** Derive one proposal per bounded sample subject of an audit finding. */\nfunction stepsFromFinding(\n finding: RelationshipAuditFinding,\n duplicateGroups: Map<string, DuplicateRelationshipEdgeGroup>,\n): RelationshipRemediationStep[] {\n if (finding.code === \"duplicate_edge\") {\n // Sample subjects are the deterministic group format strings, so each one\n // resolves to its concrete stored-edge group for exact removal targeting.\n return finding.sample.flatMap((subject) =>\n stepsFromDuplicateGroup(duplicateGroups.get(subject)!),\n );\n }\n const template = FINDING_STEP_TEMPLATES[finding.code];\n return finding.sample.map((subject) => ({\n op: template.op,\n code: finding.code,\n subject,\n rationale: template.rationale,\n evidence: [finding.policy],\n confidence: template.confidence,\n }));\n}\n\n/**\n * Build one deterministic dry-run remediation plan over an assembled workspace\n * relationship graph. The plan runs the shared governance audit, derives one\n * exact proposal per bounded finding subject, then appends witnessed\n * transitive-shortcut removal proposals from the redundancy scan (medium\n * confidence, because shortcut edges are sometimes deliberate emphasis).\n * `truncated` reports whether sample or scan bounds omitted derivable steps;\n * nothing is ever applied automatically.\n */\nexport function planRelationshipRemediation(\n assembly: WorkspaceRelationshipAssembly,\n options: RelationshipRemediationPlanOptions = {},\n): RelationshipRemediationPlan {\n const { redundancyLimit, ...auditOptions } = options;\n const report = auditWorkspaceRelationshipGraph(assembly, auditOptions);\n const duplicateGroups = new Map(\n collectDuplicateRelationshipEdgeGroups(assembly).map((group) => [\n formatDuplicateEdgeGroup(group),\n group,\n ]),\n );\n const steps = report.findings.flatMap((finding) =>\n stepsFromFinding(finding, duplicateGroups),\n );\n let truncated = report.findings.some((finding) => finding.sample_truncated);\n options.signal?.throwIfAborted();\n const redundancy = findRedundantRelationshipEdges(assembly.graph, {\n limit: redundancyLimit ?? options.maxSampleSize ?? 25,\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n });\n for (const row of redundancy.value) {\n steps.push({\n op: \"remove\",\n code: \"redundant_edge\",\n subject: `${row.edge.source} -> ${row.edge.target} (${row.edge.kind})`,\n rationale:\n \"The stored edge is implied by a longer same-family witness path; shortcut edges are sometimes deliberate emphasis, so confirm intent before removing.\",\n evidence: [`witness: ${row.witness.join(\" -> \")}`],\n confidence: \"medium\",\n });\n }\n truncated = truncated || redundancy.meta.truncated;\n return {\n steps,\n report,\n truncated,\n cost: {\n visitedNodes: redundancy.meta.visitedNodes,\n inspectedEdges: redundancy.meta.inspectedEdges,\n },\n };\n}\n"],"names":[],"mappings":"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","debugId":"ebb01d6f-d876-5196-9937-24528a66b160"}
|
package/dist/sdk/graph/run.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { GlobalOptions } from "../../core/shared/command-types.js";
|
|
2
2
|
import { type GraphCacheMetadata } from "./cache.js";
|
|
3
|
-
import { type RelationshipAuditReport } from "./governance.js";
|
|
3
|
+
import { type RelationshipAuditDelta, type RelationshipAuditReport } from "./governance.js";
|
|
4
4
|
import { type RelationshipRemediationStep } from "./remediation.js";
|
|
5
5
|
import { GRAPH_SUBCOMMAND_VALUES, type GraphSubcommand } from "../cli-contracts/enum-contracts.js";
|
|
6
6
|
export { GRAPH_SUBCOMMAND_VALUES, type GraphSubcommand };
|
|
@@ -22,6 +22,14 @@ export interface GraphCommandOptions {
|
|
|
22
22
|
sample?: string | number;
|
|
23
23
|
/** Item ids treated as explicitly valid isolates by the audit. */
|
|
24
24
|
exemptIsolate?: string | string[];
|
|
25
|
+
/** Item types whose active nodes are policy-valid isolates for the audit (repeatable or comma-separated). */
|
|
26
|
+
exemptIsolateType?: string | string[];
|
|
27
|
+
/** Persist the audit census as the change-since-baseline comparison point (audit only). */
|
|
28
|
+
saveBaseline?: boolean;
|
|
29
|
+
/** Rebuild and warm the durable graph index (index only). */
|
|
30
|
+
rebuild?: boolean;
|
|
31
|
+
/** Delete the durable graph index (index only). */
|
|
32
|
+
clear?: boolean;
|
|
25
33
|
/** Return counts-first envelopes without row collections. */
|
|
26
34
|
summary?: boolean;
|
|
27
35
|
}
|
|
@@ -181,9 +189,36 @@ export interface GraphAuditResult {
|
|
|
181
189
|
profile: RelationshipAuditReport["profile"];
|
|
182
190
|
/** Ordered findings with bounded evidence samples; absent with summary. */
|
|
183
191
|
findings?: RelationshipAuditReport["findings"];
|
|
192
|
+
/** Signed change since the persisted census baseline; absent when no baseline exists. */
|
|
193
|
+
baseline?: RelationshipAuditDelta;
|
|
184
194
|
/** Cache observability for this invocation. */
|
|
185
195
|
cache?: GraphCacheMetadata;
|
|
186
196
|
}
|
|
197
|
+
/** Result envelope for the durable-index maintenance subcommand. */
|
|
198
|
+
export interface GraphIndexResult {
|
|
199
|
+
/** Executed graph subcommand. */
|
|
200
|
+
subcommand: "index";
|
|
201
|
+
/** Maintenance action performed by this invocation. */
|
|
202
|
+
action: "status" | "rebuilt" | "cleared";
|
|
203
|
+
/** Durable index disposition against the current workspace snapshot. */
|
|
204
|
+
state: "fresh" | "stale" | "absent";
|
|
205
|
+
/** Persisted deterministic query results in the envelope. */
|
|
206
|
+
entry_count: number;
|
|
207
|
+
/** Items in the current workspace snapshot. */
|
|
208
|
+
item_count: number;
|
|
209
|
+
/** Item threshold above which implicit persistence activates. */
|
|
210
|
+
min_items_threshold: number;
|
|
211
|
+
/** Whether queries on this workspace will persist results right now. */
|
|
212
|
+
persist_enabled: boolean;
|
|
213
|
+
/** Truncated fingerprint of the current workspace snapshot. */
|
|
214
|
+
current_fingerprint: string;
|
|
215
|
+
/** ISO timestamp of the last persisted write, absent without an envelope. */
|
|
216
|
+
saved_at?: string;
|
|
217
|
+
/** Envelope size in bytes, absent without an envelope. */
|
|
218
|
+
bytes?: number;
|
|
219
|
+
/** Cache observability; maintenance invocations never populate it. */
|
|
220
|
+
cache?: GraphCacheMetadata;
|
|
221
|
+
}
|
|
187
222
|
/** One bounded community row projected by the communities subcommand. */
|
|
188
223
|
export interface GraphCommunityRow {
|
|
189
224
|
/** Lexicographically smallest member id, naming the community. */
|
|
@@ -270,6 +305,102 @@ export interface GraphDominatorsResult {
|
|
|
270
305
|
/** Cache observability for this invocation. */
|
|
271
306
|
cache?: GraphCacheMetadata;
|
|
272
307
|
}
|
|
308
|
+
/** One scheduled task row projected by the slack subcommand. */
|
|
309
|
+
export interface GraphScheduleRow {
|
|
310
|
+
/** Scheduled task id. */
|
|
311
|
+
id: string;
|
|
312
|
+
/** Earliest start (longest prerequisite distance). */
|
|
313
|
+
earliest_start: number;
|
|
314
|
+
/** Latest start preserving the makespan. */
|
|
315
|
+
latest_start: number;
|
|
316
|
+
/** Total float: latest start minus earliest start. */
|
|
317
|
+
slack: number;
|
|
318
|
+
/** Whether the task lies on a critical path. */
|
|
319
|
+
critical: boolean;
|
|
320
|
+
}
|
|
321
|
+
/** Result envelope for the critical-path slack subcommand. */
|
|
322
|
+
export interface GraphSlackResult {
|
|
323
|
+
/** Executed graph subcommand. */
|
|
324
|
+
subcommand: "slack";
|
|
325
|
+
/** Whether the order-bearing graph is acyclic. */
|
|
326
|
+
acyclic: boolean;
|
|
327
|
+
/** Total makespan in unit task durations. */
|
|
328
|
+
makespan: number;
|
|
329
|
+
/** Tasks participating in the order-bearing DAG. */
|
|
330
|
+
scheduled_count: number;
|
|
331
|
+
/** Tasks with zero slack. */
|
|
332
|
+
critical_count: number;
|
|
333
|
+
/** Edge count of the longest execution path. */
|
|
334
|
+
critical_path_length: number;
|
|
335
|
+
/** Genuine ordering cycles excluded from scheduling. */
|
|
336
|
+
cycle_count: number;
|
|
337
|
+
/** Whether the row limit omitted scheduled tasks. */
|
|
338
|
+
truncated: boolean;
|
|
339
|
+
/** Longest deterministic execution path; absent with summary. */
|
|
340
|
+
critical_path?: string[];
|
|
341
|
+
/** Bounded scheduled rows, lowest slack first; absent with summary. */
|
|
342
|
+
rows?: GraphScheduleRow[];
|
|
343
|
+
/** Cache observability for this invocation. */
|
|
344
|
+
cache?: GraphCacheMetadata;
|
|
345
|
+
}
|
|
346
|
+
/** One node ranked by structural centrality with directed fan-in/fan-out. */
|
|
347
|
+
export interface GraphCentralityRow {
|
|
348
|
+
/** Node id. */
|
|
349
|
+
id: string;
|
|
350
|
+
/** Undirected unique-neighbor degree. */
|
|
351
|
+
degree: number;
|
|
352
|
+
/** Distinct ordering predecessors that gate this node (dependency fan-in). */
|
|
353
|
+
in_degree: number;
|
|
354
|
+
/** Distinct ordering successors this node gates (dependency fan-out). */
|
|
355
|
+
out_degree: number;
|
|
356
|
+
/** Shortest-path betweenness centrality. */
|
|
357
|
+
betweenness: number;
|
|
358
|
+
/** Wasserman–Faust closeness centrality. */
|
|
359
|
+
closeness: number;
|
|
360
|
+
}
|
|
361
|
+
/** Result envelope for the centrality subcommand. */
|
|
362
|
+
export interface GraphCentralityResult {
|
|
363
|
+
/** Executed graph subcommand. */
|
|
364
|
+
subcommand: "centrality";
|
|
365
|
+
/** Total indexed graph nodes. */
|
|
366
|
+
node_count: number;
|
|
367
|
+
/** Simple undirected edge count over selected kinds. */
|
|
368
|
+
edge_count: number;
|
|
369
|
+
/** Whether the row limit omitted ranked nodes. */
|
|
370
|
+
truncated: boolean;
|
|
371
|
+
/** Query cost metadata. */
|
|
372
|
+
cost: GraphQueryCost;
|
|
373
|
+
/** Bounded ranked node rows, highest betweenness first; absent with summary. */
|
|
374
|
+
rows?: GraphCentralityRow[];
|
|
375
|
+
/** Cache observability for this invocation. */
|
|
376
|
+
cache?: GraphCacheMetadata;
|
|
377
|
+
}
|
|
378
|
+
/** One bridge edge projected by the articulation subcommand. */
|
|
379
|
+
export interface GraphBridgeRow {
|
|
380
|
+
/** Lexicographically smaller endpoint. */
|
|
381
|
+
source: string;
|
|
382
|
+
/** Lexicographically larger endpoint. */
|
|
383
|
+
target: string;
|
|
384
|
+
}
|
|
385
|
+
/** Result envelope for the articulation subcommand. */
|
|
386
|
+
export interface GraphArticulationResult {
|
|
387
|
+
/** Executed graph subcommand. */
|
|
388
|
+
subcommand: "articulation";
|
|
389
|
+
/** Total articulation points (cut vertices). */
|
|
390
|
+
articulation_count: number;
|
|
391
|
+
/** Total bridge edges (cut edges). */
|
|
392
|
+
bridge_count: number;
|
|
393
|
+
/** Whether the row limit omitted articulation points or bridges. */
|
|
394
|
+
truncated: boolean;
|
|
395
|
+
/** Query cost metadata. */
|
|
396
|
+
cost: GraphQueryCost;
|
|
397
|
+
/** Bounded sorted articulation-point ids; absent with summary. */
|
|
398
|
+
articulation_points?: string[];
|
|
399
|
+
/** Bounded sorted bridge edges; absent with summary. */
|
|
400
|
+
bridges?: GraphBridgeRow[];
|
|
401
|
+
/** Cache observability for this invocation. */
|
|
402
|
+
cache?: GraphCacheMetadata;
|
|
403
|
+
}
|
|
273
404
|
/** Result envelope for the dry-run remediation planning subcommand. */
|
|
274
405
|
export interface GraphPlanResult {
|
|
275
406
|
/** Executed graph subcommand. */
|
|
@@ -292,7 +423,7 @@ export interface GraphPlanResult {
|
|
|
292
423
|
cache?: GraphCacheMetadata;
|
|
293
424
|
}
|
|
294
425
|
/** Union of every graph subcommand result envelope. */
|
|
295
|
-
export type GraphResult = GraphTraversalResult | GraphPathsResult | GraphImpactResult | GraphAnalyzeResult | GraphAuditResult | GraphCommunitiesResult | GraphRedundancyResult | GraphDominatorsResult | GraphPlanResult;
|
|
426
|
+
export type GraphResult = GraphTraversalResult | GraphPathsResult | GraphImpactResult | GraphAnalyzeResult | GraphAuditResult | GraphCommunitiesResult | GraphRedundancyResult | GraphDominatorsResult | GraphSlackResult | GraphCentralityResult | GraphArticulationResult | GraphPlanResult | GraphIndexResult;
|
|
296
427
|
/** Validate the graph subcommand and its positional-id requirements. */
|
|
297
428
|
export declare function parseGraphSubcommand(raw: string, id: string | undefined, target: string | undefined): GraphSubcommand;
|
|
298
429
|
/** Implements run graph for the public runtime surface of this module. */
|
package/dist/sdk/graph/run.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* queries in long-lived hosts are answered from the memoized snapshot.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
!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]="
|
|
14
|
+
!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]="7f767038-30c6-555b-b9ac-adaf98b154e2")}catch(e){}}();
|
|
15
15
|
import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
|
|
16
16
|
import { pathExists } from "../../core/fs/fs-utils.js";
|
|
17
17
|
import { isTerminalStatus } from "../../core/item/status.js";
|
|
@@ -25,9 +25,12 @@ import { readSettings } from "../../core/store/settings.js";
|
|
|
25
25
|
import { parseDirection, parseKinds, parseMaxDepth, parsePositiveInteger, } from "../dependencies.js";
|
|
26
26
|
import { analyzeGraphImpact, analyzeKnowledgeGraph, analyzeRelationshipExecution, } from "../relationship-analytics.js";
|
|
27
27
|
import { computeRelationshipDominators, detectRelationshipCommunities, findRedundantRelationshipEdges, } from "./analytics.js";
|
|
28
|
-
import {
|
|
28
|
+
import { computeRelationshipCentrality, findRelationshipCutStructure, } from "./centrality.js";
|
|
29
|
+
import { analyzeRelationshipSchedule } from "./scheduling.js";
|
|
30
|
+
import { assembleWorkspaceRelationshipGraph, resolveWorkspaceRelationshipKindRegistry, } from "./assembly.js";
|
|
29
31
|
import { computeWorkspaceGraphFingerprint, workspaceGraphCache, } from "./cache.js";
|
|
30
|
-
import {
|
|
32
|
+
import { clearDurableGraphCache, durableGraphCacheStatus, loadGraphAuditBaseline, openDurableGraphCache, persistDurableGraphResult, saveGraphAuditBaseline, shouldPersistDurableGraphCache, GRAPH_DURABLE_CACHE_MIN_ITEMS, } from "./durable-cache.js";
|
|
33
|
+
import { auditWorkspaceRelationshipGraph, diffRelationshipAuditSnapshots, } from "./governance.js";
|
|
31
34
|
import { planRelationshipRemediation, } from "./remediation.js";
|
|
32
35
|
import { enumerateRelationshipPaths, hierarchyAncestors, hierarchyDescendants, orderingPredecessors, orderingSuccessors, } from "./traversal.js";
|
|
33
36
|
import { GRAPH_SUBCOMMAND_VALUES, } from "../cli-contracts/enum-contracts.js";
|
|
@@ -237,6 +240,9 @@ function runGraphAudit(invocation, isTerminal) {
|
|
|
237
240
|
...(invocation.exemptIsolates.length === 0
|
|
238
241
|
? {}
|
|
239
242
|
: { exemptIsolates: invocation.exemptIsolates }),
|
|
243
|
+
...(invocation.exemptIsolateTypes.length === 0
|
|
244
|
+
? {}
|
|
245
|
+
: { isolateExemptTypes: invocation.exemptIsolateTypes }),
|
|
240
246
|
});
|
|
241
247
|
const bySeverity = {};
|
|
242
248
|
const byCode = {};
|
|
@@ -356,6 +362,90 @@ function runGraphDominators(root, invocation) {
|
|
|
356
362
|
}),
|
|
357
363
|
};
|
|
358
364
|
}
|
|
365
|
+
/** Execute the critical-path slack (float) analysis subcommand. */
|
|
366
|
+
function runGraphSlack(invocation) {
|
|
367
|
+
const limit = invocation.limit ?? DEFAULT_SAMPLE_LIMIT;
|
|
368
|
+
// Scheduling spans every ordering kind; --kind is rejected upstream by
|
|
369
|
+
// assertGraphFlagScope, so no kind filter reaches the analysis here.
|
|
370
|
+
const analysis = analyzeRelationshipSchedule(invocation.assembly.graph);
|
|
371
|
+
const criticalCount = analysis.rows.filter((row) => row.critical).length;
|
|
372
|
+
return {
|
|
373
|
+
subcommand: "slack",
|
|
374
|
+
acyclic: analysis.acyclic,
|
|
375
|
+
makespan: analysis.makespan,
|
|
376
|
+
scheduled_count: analysis.scheduledCount,
|
|
377
|
+
critical_count: criticalCount,
|
|
378
|
+
critical_path_length: analysis.criticalPathLength,
|
|
379
|
+
cycle_count: analysis.cycles.length,
|
|
380
|
+
truncated: analysis.rows.length > limit,
|
|
381
|
+
...(invocation.summary
|
|
382
|
+
? {}
|
|
383
|
+
: {
|
|
384
|
+
critical_path: analysis.criticalPath,
|
|
385
|
+
rows: analysis.rows.slice(0, limit).map((row) => ({
|
|
386
|
+
id: row.id,
|
|
387
|
+
earliest_start: row.earliestStart,
|
|
388
|
+
latest_start: row.latestStart,
|
|
389
|
+
slack: row.slack,
|
|
390
|
+
critical: row.critical,
|
|
391
|
+
})),
|
|
392
|
+
}),
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
/** Execute the structural-centrality ranking subcommand. */
|
|
396
|
+
function runGraphCentrality(invocation) {
|
|
397
|
+
const limit = invocation.limit ?? DEFAULT_SAMPLE_LIMIT;
|
|
398
|
+
const result = computeRelationshipCentrality(invocation.assembly.graph, {
|
|
399
|
+
...(invocation.kinds === undefined ? {} : { kinds: invocation.kinds }),
|
|
400
|
+
});
|
|
401
|
+
const analysis = result.value;
|
|
402
|
+
return {
|
|
403
|
+
subcommand: "centrality",
|
|
404
|
+
node_count: analysis.nodeCount,
|
|
405
|
+
edge_count: analysis.edgeCount,
|
|
406
|
+
truncated: analysis.rows.length > limit,
|
|
407
|
+
cost: {
|
|
408
|
+
visited_nodes: result.meta.visitedNodes,
|
|
409
|
+
inspected_edges: result.meta.inspectedEdges,
|
|
410
|
+
},
|
|
411
|
+
...(invocation.summary
|
|
412
|
+
? {}
|
|
413
|
+
: {
|
|
414
|
+
rows: analysis.rows.slice(0, limit).map((row) => ({
|
|
415
|
+
id: row.id,
|
|
416
|
+
degree: row.degree,
|
|
417
|
+
in_degree: row.inDegree,
|
|
418
|
+
out_degree: row.outDegree,
|
|
419
|
+
betweenness: row.betweenness,
|
|
420
|
+
closeness: row.closeness,
|
|
421
|
+
})),
|
|
422
|
+
}),
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
/** Execute the articulation-point and bridge (cut-structure) subcommand. */
|
|
426
|
+
function runGraphArticulation(invocation) {
|
|
427
|
+
const limit = invocation.limit ?? DEFAULT_SAMPLE_LIMIT;
|
|
428
|
+
const result = findRelationshipCutStructure(invocation.assembly.graph, {
|
|
429
|
+
...(invocation.kinds === undefined ? {} : { kinds: invocation.kinds }),
|
|
430
|
+
});
|
|
431
|
+
const { articulationPoints, bridges } = result.value;
|
|
432
|
+
return {
|
|
433
|
+
subcommand: "articulation",
|
|
434
|
+
articulation_count: articulationPoints.length,
|
|
435
|
+
bridge_count: bridges.length,
|
|
436
|
+
truncated: articulationPoints.length > limit || bridges.length > limit,
|
|
437
|
+
cost: {
|
|
438
|
+
visited_nodes: result.meta.visitedNodes,
|
|
439
|
+
inspected_edges: result.meta.inspectedEdges,
|
|
440
|
+
},
|
|
441
|
+
...(invocation.summary
|
|
442
|
+
? {}
|
|
443
|
+
: {
|
|
444
|
+
articulation_points: articulationPoints.slice(0, limit),
|
|
445
|
+
bridges: bridges.slice(0, limit),
|
|
446
|
+
}),
|
|
447
|
+
};
|
|
448
|
+
}
|
|
359
449
|
/** Execute the dry-run remediation planning subcommand. */
|
|
360
450
|
function runGraphPlan(invocation, isTerminal) {
|
|
361
451
|
const limit = invocation.limit ?? DEFAULT_SAMPLE_LIMIT;
|
|
@@ -368,6 +458,9 @@ function runGraphPlan(invocation, isTerminal) {
|
|
|
368
458
|
...(invocation.exemptIsolates.length === 0
|
|
369
459
|
? {}
|
|
370
460
|
: { exemptIsolates: invocation.exemptIsolates }),
|
|
461
|
+
...(invocation.exemptIsolateTypes.length === 0
|
|
462
|
+
? {}
|
|
463
|
+
: { isolateExemptTypes: invocation.exemptIsolateTypes }),
|
|
371
464
|
});
|
|
372
465
|
const byOp = {};
|
|
373
466
|
const byCode = {};
|
|
@@ -407,6 +500,9 @@ function buildGraphQueryKey(subcommand, root, pathsTarget, invocation) {
|
|
|
407
500
|
exemptIsolates: [
|
|
408
501
|
...new Set(invocation.exemptIsolates.map((id) => id.toLowerCase())),
|
|
409
502
|
].sort(),
|
|
503
|
+
exemptIsolateTypes: [
|
|
504
|
+
...new Set(invocation.exemptIsolateTypes.map((type) => type.toLowerCase())),
|
|
505
|
+
].sort(),
|
|
410
506
|
summary: invocation.summary,
|
|
411
507
|
});
|
|
412
508
|
}
|
|
@@ -424,12 +520,105 @@ function executeGraphSubcommand(subcommand, root, pathsTarget, invocation, isTer
|
|
|
424
520
|
return runGraphRedundancy(invocation);
|
|
425
521
|
if (subcommand === "dominators")
|
|
426
522
|
return runGraphDominators(root, invocation);
|
|
523
|
+
if (subcommand === "slack")
|
|
524
|
+
return runGraphSlack(invocation);
|
|
525
|
+
if (subcommand === "centrality")
|
|
526
|
+
return runGraphCentrality(invocation);
|
|
527
|
+
if (subcommand === "articulation")
|
|
528
|
+
return runGraphArticulation(invocation);
|
|
427
529
|
if (subcommand === "paths")
|
|
428
530
|
return runGraphPaths(root, pathsTarget, invocation);
|
|
429
531
|
if (subcommand === "impact")
|
|
430
532
|
return runGraphImpact(root, invocation);
|
|
431
533
|
return runGraphTraversal(subcommand, root, invocation);
|
|
432
534
|
}
|
|
535
|
+
/** Reject maintenance or baseline flags outside their owning subcommand. */
|
|
536
|
+
function assertGraphFlagScope(subcommand, options) {
|
|
537
|
+
if (subcommand !== "index" &&
|
|
538
|
+
(options.rebuild === true || options.clear === true))
|
|
539
|
+
throw new PmCliError("--rebuild and --clear apply only to graph index.", EXIT_CODE.USAGE);
|
|
540
|
+
if (subcommand !== "audit" && options.saveBaseline === true)
|
|
541
|
+
throw new PmCliError("--save-baseline applies only to graph audit.", EXIT_CODE.USAGE);
|
|
542
|
+
// Slack schedules the whole ordering DAG (reusing the exact execution
|
|
543
|
+
// analysis, which has no kind filter), so reject --kind instead of silently
|
|
544
|
+
// ignoring it and letting the cache key diverge on an inert option.
|
|
545
|
+
if (subcommand === "slack" && options.kind !== undefined)
|
|
546
|
+
throw new PmCliError("graph slack analyzes every ordering kind; --kind is not supported.", EXIT_CODE.USAGE);
|
|
547
|
+
if (options.rebuild === true && options.clear === true)
|
|
548
|
+
throw new PmCliError("graph index accepts either --rebuild or --clear, not both.", EXIT_CODE.USAGE);
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Execute the durable-index maintenance subcommand: report status, delete the
|
|
552
|
+
* envelope, or rebuild it and warm the counts-first analyze and audit census
|
|
553
|
+
* queries so follow-up summary invocations answer from the persisted index.
|
|
554
|
+
* A rebuild is also the explicit opt-in that enables persistence on
|
|
555
|
+
* workspaces below the implicit item threshold.
|
|
556
|
+
*/
|
|
557
|
+
async function runGraphIndex(pmRoot, fingerprint, invocation, itemCount, isTerminal, options) {
|
|
558
|
+
let action = "status";
|
|
559
|
+
if (options.clear === true) {
|
|
560
|
+
await clearDurableGraphCache(pmRoot);
|
|
561
|
+
action = "cleared";
|
|
562
|
+
}
|
|
563
|
+
if (options.rebuild === true) {
|
|
564
|
+
await clearDurableGraphCache(pmRoot);
|
|
565
|
+
const view = await openDurableGraphCache(pmRoot, fingerprint);
|
|
566
|
+
const warmInvocation = {
|
|
567
|
+
assembly: invocation.assembly,
|
|
568
|
+
direction: "both",
|
|
569
|
+
exemptIsolates: [],
|
|
570
|
+
exemptIsolateTypes: [],
|
|
571
|
+
saveBaseline: false,
|
|
572
|
+
summary: true,
|
|
573
|
+
};
|
|
574
|
+
for (const warm of ["analyze", "audit"]) {
|
|
575
|
+
await persistDurableGraphResult(pmRoot, fingerprint, view, buildGraphQueryKey(warm, undefined, undefined, warmInvocation), executeGraphSubcommand(warm, undefined, undefined, warmInvocation, isTerminal));
|
|
576
|
+
}
|
|
577
|
+
action = "rebuilt";
|
|
578
|
+
}
|
|
579
|
+
const status = await durableGraphCacheStatus(pmRoot, fingerprint);
|
|
580
|
+
return {
|
|
581
|
+
subcommand: "index",
|
|
582
|
+
action,
|
|
583
|
+
state: status.exists ? (status.fresh ? "fresh" : "stale") : "absent",
|
|
584
|
+
entry_count: status.entry_count,
|
|
585
|
+
item_count: itemCount,
|
|
586
|
+
min_items_threshold: GRAPH_DURABLE_CACHE_MIN_ITEMS,
|
|
587
|
+
persist_enabled: shouldPersistDurableGraphCache(itemCount, status.exists),
|
|
588
|
+
current_fingerprint: fingerprint.slice(0, 12),
|
|
589
|
+
...(status.saved_at === undefined ? {} : { saved_at: status.saved_at }),
|
|
590
|
+
...(status.bytes === undefined ? {} : { bytes: status.bytes }),
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Attach the change-since-baseline census delta to one audit envelope and
|
|
595
|
+
* persist the current census when the caller requested a new baseline. The
|
|
596
|
+
* delta always compares against the baseline as it existed before this
|
|
597
|
+
* invocation, so `--save-baseline` reports drift once and then resets it.
|
|
598
|
+
*/
|
|
599
|
+
async function applyAuditBaseline(pmRoot, fingerprint, audit, saveBaseline) {
|
|
600
|
+
const current = {
|
|
601
|
+
saved_at: new Date().toISOString(),
|
|
602
|
+
fingerprint,
|
|
603
|
+
affected_subjects_by_code: audit.affected_subjects_by_code,
|
|
604
|
+
profile: audit.profile,
|
|
605
|
+
};
|
|
606
|
+
const stored = await loadGraphAuditBaseline(pmRoot);
|
|
607
|
+
if (saveBaseline)
|
|
608
|
+
await saveGraphAuditBaseline(pmRoot, current);
|
|
609
|
+
return stored === undefined
|
|
610
|
+
? audit
|
|
611
|
+
: { ...audit, baseline: diffRelationshipAuditSnapshots(stored, current) };
|
|
612
|
+
}
|
|
613
|
+
/** Persist a rebuildable query result without allowing storage failure to reject the query. */
|
|
614
|
+
async function persistDurableGraphResultBestEffort(pmRoot, fingerprint, view, queryKey, result) {
|
|
615
|
+
try {
|
|
616
|
+
await persistDurableGraphResult(pmRoot, fingerprint, view, queryKey, result);
|
|
617
|
+
}
|
|
618
|
+
catch {
|
|
619
|
+
// The in-memory result remains authoritative; the next invocation can rebuild the cache.
|
|
620
|
+
}
|
|
621
|
+
}
|
|
433
622
|
/** Implements run graph for the public runtime surface of this module. */
|
|
434
623
|
export async function runGraph(subcommandRaw, id, target, options, global) {
|
|
435
624
|
const subcommand = parseGraphSubcommand(subcommandRaw, id, target);
|
|
@@ -442,8 +631,10 @@ export async function runGraph(subcommandRaw, id, target, options, global) {
|
|
|
442
631
|
const items = await listAllItemMetadataLight(pmRoot, settings.item_format, typeRegistry.type_to_folder, undefined, settings.schema);
|
|
443
632
|
const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);
|
|
444
633
|
const isTerminal = (status) => isTerminalStatus(status, statusRegistry);
|
|
445
|
-
|
|
446
|
-
const
|
|
634
|
+
assertGraphFlagScope(subcommand, options);
|
|
635
|
+
const relationshipRegistry = resolveWorkspaceRelationshipKindRegistry();
|
|
636
|
+
const kinds = parseKinds(options.kind, relationshipRegistry);
|
|
637
|
+
const lookup = workspaceGraphCache().lookup(pmRoot, computeWorkspaceGraphFingerprint(items, isTerminal, relationshipRegistry), () => assembleWorkspaceRelationshipGraph(items, isTerminal, relationshipRegistry));
|
|
447
638
|
const invocation = {
|
|
448
639
|
assembly: lookup.assembly,
|
|
449
640
|
...(kinds === undefined ? {} : { kinds }),
|
|
@@ -454,23 +645,41 @@ export async function runGraph(subcommandRaw, id, target, options, global) {
|
|
|
454
645
|
maxPaths: parsePositiveInteger(options.maxPaths, "max-paths"),
|
|
455
646
|
sample: parsePositiveInteger(options.sample, "sample"),
|
|
456
647
|
exemptIsolates: normalizeIdList(options.exemptIsolate),
|
|
648
|
+
exemptIsolateTypes: normalizeIdList(options.exemptIsolateType),
|
|
649
|
+
saveBaseline: options.saveBaseline === true,
|
|
457
650
|
summary: options.summary === true,
|
|
458
651
|
};
|
|
652
|
+
if (subcommand === "index") {
|
|
653
|
+
return runGraphIndex(pmRoot, lookup.fingerprint, invocation, items.length, isTerminal, options);
|
|
654
|
+
}
|
|
459
655
|
const root = ROOTED_SUBCOMMANDS.has(subcommand)
|
|
460
656
|
? canonicalizeGraphId(invocation.assembly, id)
|
|
461
657
|
: undefined;
|
|
462
658
|
const pathsTarget = subcommand === "paths"
|
|
463
659
|
? canonicalizeGraphId(invocation.assembly, target)
|
|
464
660
|
: undefined;
|
|
465
|
-
const
|
|
661
|
+
const queryKey = buildGraphQueryKey(subcommand, root, pathsTarget, invocation);
|
|
662
|
+
const durableView = await openDurableGraphCache(pmRoot, lookup.fingerprint);
|
|
663
|
+
const durableValue = durableView.results[queryKey];
|
|
664
|
+
const memo = lookup.memoize(queryKey, () => durableValue !== undefined
|
|
665
|
+
? structuredClone(durableValue)
|
|
666
|
+
: executeGraphSubcommand(subcommand, root, pathsTarget, invocation, isTerminal));
|
|
667
|
+
const persistEnabled = shouldPersistDurableGraphCache(items.length, durableView.exists);
|
|
668
|
+
if (!memo.reused && durableValue === undefined && persistEnabled) {
|
|
669
|
+
await persistDurableGraphResultBestEffort(pmRoot, lookup.fingerprint, durableView, queryKey, memo.value);
|
|
670
|
+
}
|
|
671
|
+
const value = memo.value.subcommand === "audit"
|
|
672
|
+
? await applyAuditBaseline(pmRoot, lookup.fingerprint, memo.value, invocation.saveBaseline)
|
|
673
|
+
: memo.value;
|
|
466
674
|
return {
|
|
467
|
-
...
|
|
675
|
+
...value,
|
|
468
676
|
cache: {
|
|
469
677
|
fingerprint: lookup.fingerprint.slice(0, 12),
|
|
470
678
|
assembly: lookup.assemblyReused ? "hit" : "miss",
|
|
471
679
|
result: memo.reused ? "hit" : "miss",
|
|
680
|
+
durable: durableValue !== undefined ? "hit" : persistEnabled ? "miss" : "off",
|
|
472
681
|
},
|
|
473
682
|
};
|
|
474
683
|
}
|
|
475
684
|
//# sourceMappingURL=run.js.map
|
|
476
|
-
//# debugId=
|
|
685
|
+
//# debugId=7f767038-30c6-555b-b9ac-adaf98b154e2
|