@unbrained/pm-cli 2026.7.20 → 2026.7.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +11 -0
- package/dist/cli/commander-usage.d.ts +1 -1
- package/dist/cli/commander-usage.js +5 -5
- package/dist/cli/commander-usage.js.map +1 -1
- package/dist/cli/commands/completion.js +13 -5
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/contracts.js +4 -3
- package/dist/cli/commands/contracts.js.map +1 -1
- package/dist/cli/error-guidance.d.ts +2 -0
- package/dist/cli/error-guidance.js +7 -2
- package/dist/cli/error-guidance.js.map +1 -1
- package/dist/cli/main.d.ts +1 -5
- package/dist/cli/main.js +12 -50
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/register-list-query.js +13 -3
- package/dist/cli/register-list-query.js.map +1 -1
- package/dist/cli/register-mutation.js +45 -3
- package/dist/cli/register-mutation.js.map +1 -1
- package/dist/cli/register-structured-mutation.d.ts +14 -0
- package/dist/cli/register-structured-mutation.js +62 -0
- package/dist/cli/register-structured-mutation.js.map +1 -0
- package/dist/cli/registration-helpers.js +5 -3
- package/dist/cli/registration-helpers.js.map +1 -1
- package/dist/cli-bundle/bundle-manifest.json +280 -296
- package/dist/cli-bundle/chunks/{append-E6V54WOQ.js → append-7OVFYR3C.js} +3 -3
- package/dist/cli-bundle/chunks/{append-NNJ3EFIT.js → append-DFETHAZL.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-C3KD7U3T.js → chunk-2L6ZP22J.js} +241 -10
- package/dist/cli-bundle/chunks/chunk-2L6ZP22J.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-KZEANWJS.js → chunk-4PUUNQDV.js} +98 -30
- package/dist/cli-bundle/chunks/chunk-4PUUNQDV.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-RDV4ZFYS.js → chunk-4QOB7L7I.js} +7 -9
- package/dist/cli-bundle/chunks/{chunk-RDV4ZFYS.js.map → chunk-4QOB7L7I.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-3LPFHE3P.js → chunk-4QSQ6XDK.js} +62 -20
- package/dist/cli-bundle/chunks/chunk-4QSQ6XDK.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-QJKL5PHS.js → chunk-7656MAUL.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-3AO5VSDR.js → chunk-7RW4JCU2.js} +328 -6
- package/dist/cli-bundle/chunks/chunk-7RW4JCU2.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-X6K5XTTN.js → chunk-7W2UAXXT.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-SSKOQNMS.js → chunk-ABWCF646.js} +9 -11
- package/dist/cli-bundle/chunks/{chunk-SSKOQNMS.js.map → chunk-ABWCF646.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-WVA4DVNV.js → chunk-ADBTSVGK.js} +71 -33
- package/dist/cli-bundle/chunks/chunk-ADBTSVGK.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-J4FBIFU6.js → chunk-AELMUANP.js} +12 -6
- package/dist/cli-bundle/chunks/chunk-AELMUANP.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-4F6BWJ4J.js → chunk-AMJPSANK.js} +57 -36
- package/dist/cli-bundle/chunks/chunk-AMJPSANK.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-6VIJ7UA5.js → chunk-AS4SAZ5R.js} +850 -819
- package/dist/cli-bundle/chunks/chunk-AS4SAZ5R.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-SG74J6MV.js → chunk-ATBCUC7Y.js} +574 -5
- package/dist/cli-bundle/chunks/chunk-ATBCUC7Y.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-5OK4UGFV.js → chunk-BXNDKOR2.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-KSPWRNVP.js → chunk-CPX275C6.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-JH2ZSLO3.js → chunk-DZRV2OPA.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-L7BH7IWU.js → chunk-E5XMKOSB.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-CQTQKUUV.js → chunk-EWJWSNRU.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-DAQ45GCS.js → chunk-F2LBF7XJ.js} +22 -15
- package/dist/cli-bundle/chunks/chunk-F2LBF7XJ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-6XMUURSS.js → chunk-FJIFFBJX.js} +64 -33
- package/dist/cli-bundle/chunks/chunk-FJIFFBJX.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-E7ICD63T.js → chunk-FO6OSVEN.js} +4 -6
- package/dist/cli-bundle/chunks/{chunk-E7ICD63T.js.map → chunk-FO6OSVEN.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-3MCTMJXI.js → chunk-FPBMLYPI.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-UZDQXNUB.js → chunk-FSE2IKJQ.js} +46 -5
- package/dist/cli-bundle/chunks/chunk-FSE2IKJQ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-IX677TRO.js → chunk-GKX4NJ7U.js} +8 -10
- package/dist/cli-bundle/chunks/{chunk-IX677TRO.js.map → chunk-GKX4NJ7U.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-DVDBQA3B.js → chunk-GTK4DTEW.js} +5 -5
- package/dist/cli-bundle/chunks/chunk-H7EAER5L.js +974 -0
- package/dist/cli-bundle/chunks/chunk-H7EAER5L.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-5UX66S6U.js → chunk-ICDAQ4TD.js} +316 -8
- package/dist/cli-bundle/chunks/chunk-ICDAQ4TD.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-YQQNAKW3.js → chunk-JFD5LPMI.js} +6 -8
- package/dist/cli-bundle/chunks/{chunk-YQQNAKW3.js.map → chunk-JFD5LPMI.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-QANSTTC7.js → chunk-JXCW2TI2.js} +6 -8
- package/dist/cli-bundle/chunks/{chunk-QANSTTC7.js.map → chunk-JXCW2TI2.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-GSJSM5BJ.js → chunk-K36WV5J6.js} +76 -13
- package/dist/cli-bundle/chunks/chunk-K36WV5J6.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-GVI6FAFG.js → chunk-K55VMLSS.js} +7 -5
- package/dist/cli-bundle/chunks/chunk-K55VMLSS.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-GIQSU6S2.js → chunk-KBLZ3AA5.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-XJF7CDNH.js → chunk-KH44WBAT.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-GV2262OF.js → chunk-LAV26CQG.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-VDO2JMD4.js → chunk-LVC72YRD.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-3VY6MIEO.js → chunk-LZYP423P.js} +35 -6
- package/dist/cli-bundle/chunks/chunk-LZYP423P.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-ZYPFOO3L.js → chunk-MATHDCGG.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-OV7MSW3I.js → chunk-MWQ2HC2A.js} +99 -31
- package/dist/cli-bundle/chunks/chunk-MWQ2HC2A.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-NHT3F4WZ.js → chunk-NUF7ROFH.js} +840 -816
- package/dist/cli-bundle/chunks/chunk-NUF7ROFH.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-AOEOYL3S.js → chunk-O4BCOJTZ.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-RJO3YAFM.js → chunk-OCUBRA6D.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-5IZJWSDB.js → chunk-OG5DVFMA.js} +22 -15
- package/dist/cli-bundle/chunks/chunk-OG5DVFMA.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-I577UHC7.js → chunk-OR42SO64.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-ZOJ3LR7O.js → chunk-OY7DMU5P.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-HEWM6CEN.js → chunk-P7MTHPJQ.js} +50 -9
- package/dist/cli-bundle/chunks/chunk-P7MTHPJQ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-2BO4CA46.js → chunk-PFNHX655.js} +236 -12
- package/dist/cli-bundle/chunks/{chunk-2BO4CA46.js.map → chunk-PFNHX655.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-ZV2NTVMJ.js → chunk-PONKZPCJ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-THAOZG4U.js → chunk-PQSEQD6E.js} +8 -6
- package/dist/cli-bundle/chunks/chunk-PQSEQD6E.js.map +1 -0
- package/dist/cli-bundle/chunks/chunk-PWDEHT3L.js +991 -0
- package/dist/cli-bundle/chunks/chunk-PWDEHT3L.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-UX6SSO2I.js → chunk-PZC2FUOQ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-WUVEBQW6.js → chunk-QG4GFLQ6.js} +3 -5
- package/dist/cli-bundle/chunks/{chunk-WUVEBQW6.js.map → chunk-QG4GFLQ6.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-VQIHNHMJ.js → chunk-QIH77CAG.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-R3EWPG4A.js → chunk-QJIKE24M.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-QLZ643FM.js → chunk-QOOTOD3W.js} +10 -12
- package/dist/cli-bundle/chunks/{chunk-QLZ643FM.js.map → chunk-QOOTOD3W.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-MYSS5H2A.js → chunk-R3P6FZJW.js} +5 -7
- package/dist/cli-bundle/chunks/{chunk-MYSS5H2A.js.map → chunk-R3P6FZJW.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-G3COA6GS.js → chunk-RNPZYNHS.js} +56 -35
- package/dist/cli-bundle/chunks/chunk-RNPZYNHS.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-T44FMVRL.js → chunk-RPESLSO5.js} +62 -20
- package/dist/cli-bundle/chunks/chunk-RPESLSO5.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-INSTSQNZ.js → chunk-SY4SFZSD.js} +595 -3
- package/dist/cli-bundle/chunks/chunk-SY4SFZSD.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-HB3P4M52.js → chunk-TRSHFPRZ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-HRW7GF6T.js → chunk-UCBDQI5E.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-4U4Z6AHI.js → chunk-V22ZPOKN.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-JM6YAXTR.js → chunk-VHXHVTUU.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-LPEYZRUR.js → chunk-VJQG4BIM.js} +35 -6
- package/dist/cli-bundle/chunks/chunk-VJQG4BIM.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-D6NXDNP3.js → chunk-VLRGDBLY.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-JAPE62Y5.js → chunk-VNTCM3VW.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-FDHPAVVB.js → chunk-VXOOB6YX.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-GFQP7HAZ.js → chunk-VZIZB6QH.js} +3 -5
- package/dist/cli-bundle/chunks/{chunk-GFQP7HAZ.js.map → chunk-VZIZB6QH.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-HQ3SB4CN.js → chunk-X3W65QK3.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-RZJLNXFG.js → chunk-XJTABV3X.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-GVT754PX.js → chunk-YCIUJJOD.js} +11 -5
- package/dist/cli-bundle/chunks/chunk-YCIUJJOD.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-IJNK6WW2.js → chunk-Z75ONV25.js} +75 -12
- package/dist/cli-bundle/chunks/chunk-Z75ONV25.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-4L23AGQ7.js → chunk-Z7VWXXJM.js} +5 -7
- package/dist/cli-bundle/chunks/{chunk-4L23AGQ7.js.map → chunk-Z7VWXXJM.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-YBT7O4KT.js → chunk-ZTVA4KLN.js} +4 -6
- package/dist/cli-bundle/chunks/{chunk-YBT7O4KT.js.map → chunk-ZTVA4KLN.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-TYHJDFYW.js → chunk-ZVZGXPQ5.js} +2 -2
- package/dist/cli-bundle/chunks/{close-many-SDA426VT.js → close-many-5RZXVN4J.js} +5 -6
- package/dist/cli-bundle/chunks/{close-many-UTZANOCQ.js → close-many-RZVTUGBG.js} +5 -6
- package/dist/cli-bundle/chunks/{comments-LZN6FXXC.js → comments-TPU7QRBL.js} +4 -4
- package/dist/cli-bundle/chunks/{comments-VBQ345ND.js → comments-Z4KV6FU3.js} +4 -4
- package/dist/cli-bundle/chunks/{create-GG4RBCGC.js → create-EIFBIVNQ.js} +6 -6
- package/dist/cli-bundle/chunks/{create-JBC5KUW6.js → create-RGSPN5GD.js} +6 -6
- package/dist/cli-bundle/chunks/{deps-FI4O6NQS.js → deps-UH5EQQUY.js} +3 -3
- package/dist/cli-bundle/chunks/{deps-DELOO4TL.js → deps-YG7UF3VR.js} +3 -3
- package/dist/cli-bundle/chunks/{docs-6Z2MP526.js → docs-G32TK6XS.js} +4 -4
- package/dist/cli-bundle/chunks/{docs-2UYBP5D6.js → docs-JWWNRC27.js} +4 -4
- package/dist/cli-bundle/chunks/{files-HKEAN5MA.js → files-3H32UQ4K.js} +4 -4
- package/dist/cli-bundle/chunks/{files-HEUGSJZL.js → files-4ALMCSKB.js} +4 -4
- package/dist/cli-bundle/chunks/{history-compact-7NDVP3PT.js → history-compact-77BT2LUB.js} +3 -4
- package/dist/cli-bundle/chunks/{history-compact-65YVN5DB.js → history-compact-VCKGTX64.js} +3 -4
- package/dist/cli-bundle/chunks/{history-redact-7YBL4XSG.js → history-redact-LJPZPNFA.js} +2 -3
- package/dist/cli-bundle/chunks/{history-redact-IZGNJBU4.js → history-redact-PWTTJ3XS.js} +2 -3
- package/dist/cli-bundle/chunks/{history-repair-7M4PYQUH.js → history-repair-I7CBNCV3.js} +5 -6
- package/dist/cli-bundle/chunks/{history-repair-GNGETJLI.js → history-repair-YTDZRK5E.js} +5 -6
- package/dist/cli-bundle/chunks/{learnings-3YXDRWFT.js → learnings-CYNOICKR.js} +4 -4
- package/dist/cli-bundle/chunks/{learnings-ALC6IMNL.js → learnings-KTYW3AL7.js} +4 -4
- package/dist/cli-bundle/chunks/{notes-7JMLQ447.js → notes-FGO63FXL.js} +4 -4
- package/dist/cli-bundle/chunks/{notes-JFCLTC5C.js → notes-ZERD3KB2.js} +4 -4
- package/dist/cli-bundle/chunks/{plan-T3XB3WTK.js → plan-OFJUBIM5.js} +7 -7
- package/dist/cli-bundle/chunks/{plan-KOIPWVOZ.js → plan-SGCDDTYR.js} +7 -7
- package/dist/cli-bundle/chunks/{profile-OILJHKUW.js → profile-3THJPIQY.js} +4 -5
- package/dist/cli-bundle/chunks/{profile-RJXA7PGS.js → profile-XEZAMMBW.js} +4 -5
- package/dist/cli-bundle/chunks/{register-list-query-CFVG75P3.js → register-list-query-BR435Q2H.js} +19 -16
- package/dist/cli-bundle/chunks/register-list-query-BR435Q2H.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-list-query-E7UVY4TN.js → register-list-query-RWTWLOBE.js} +18 -15
- package/dist/cli-bundle/chunks/register-list-query-RWTWLOBE.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-mutation-IQ55E25C.js → register-mutation-HLWC2WNP.js} +167 -31
- package/dist/cli-bundle/chunks/register-mutation-HLWC2WNP.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-mutation-4VJTXBZW.js → register-mutation-ZJX5AZM5.js} +173 -30
- package/dist/cli-bundle/chunks/register-mutation-ZJX5AZM5.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-operations-AR7RMX4W.js → register-operations-744YBJMV.js} +23 -25
- package/dist/cli-bundle/chunks/{register-operations-AR7RMX4W.js.map → register-operations-744YBJMV.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-operations-NOLZGORC.js → register-operations-UEBJH6AN.js} +21 -23
- package/dist/cli-bundle/chunks/{register-operations-NOLZGORC.js.map → register-operations-UEBJH6AN.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-setup-EYZ7VTPZ.js → register-setup-5DA4UZXI.js} +7 -8
- package/dist/cli-bundle/chunks/{register-setup-EYZ7VTPZ.js.map → register-setup-5DA4UZXI.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-setup-BB77VUEE.js → register-setup-6H25M3BH.js} +9 -10
- package/dist/cli-bundle/chunks/{register-setup-BB77VUEE.js.map → register-setup-6H25M3BH.js.map} +1 -1
- package/dist/cli-bundle/chunks/{restore-ZH65GZFB.js → restore-6TDVSATY.js} +4 -5
- package/dist/cli-bundle/chunks/{restore-L6IAGOD7.js → restore-RSL7C7LO.js} +4 -5
- package/dist/cli-bundle/chunks/{schema-4ERWM5QJ.js → schema-HFXFSGPG.js} +2 -3
- package/dist/cli-bundle/chunks/{schema-55DL3Q52.js → schema-TPVTIJPO.js} +2 -3
- package/dist/cli-bundle/chunks/{update-FW6FKDOP.js → update-LJZCL5SI.js} +7 -7
- package/dist/cli-bundle/chunks/{update-TJHSPRPT.js → update-SIA7LH5Y.js} +7 -7
- package/dist/cli-bundle/chunks/{update-many-PWXX5WHO.js → update-many-BDBZVGQL.js} +11 -12
- package/dist/cli-bundle/chunks/{update-many-NNALYQCN.js → update-many-MOY3A5B3.js} +11 -12
- package/dist/cli-bundle/main.js +60 -85
- package/dist/cli-bundle/main.js.map +2 -2
- package/dist/cli-bundle/sdk-runtime.js +37 -37
- package/dist/cli-bundle/sdk.js +126 -291
- package/dist/cli-bundle/sdk.js.map +4 -4
- package/dist/core/item/parse.d.ts +1 -1
- package/dist/core/item/parse.js +13 -7
- package/dist/core/item/parse.js.map +1 -1
- package/dist/core/output/mutation-projection.d.ts +2 -0
- package/dist/core/output/mutation-projection.js +33 -2
- package/dist/core/output/mutation-projection.js.map +1 -1
- package/dist/core/output/output.d.ts +4 -0
- package/dist/core/output/output.js +18 -13
- package/dist/core/output/output.js.map +1 -1
- package/dist/core/shared/command-types.d.ts +4 -0
- package/dist/core/shared/command-types.js +2 -2
- package/dist/core/shared/command-types.js.map +1 -1
- package/dist/mcp/server.js +39 -4
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tool-definitions.js +45 -4
- package/dist/mcp/tool-definitions.js.map +1 -1
- package/dist/sdk/cli-bootstrap.d.ts +2 -0
- package/dist/sdk/cli-bootstrap.js +20 -27
- package/dist/sdk/cli-bootstrap.js.map +1 -1
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +2 -2
- package/dist/sdk/cli-contracts/enum-contracts.js +7 -2
- package/dist/sdk/cli-contracts/enum-contracts.js.map +1 -1
- package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
- package/dist/sdk/cli-contracts/flag-contracts.js +21 -2
- package/dist/sdk/cli-contracts/flag-contracts.js.map +1 -1
- package/dist/sdk/cli-contracts/tool-option-contracts.js +10 -2
- package/dist/sdk/cli-contracts/tool-option-contracts.js.map +1 -1
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +16 -3
- package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -1
- package/dist/sdk/cli-contracts/tool-schema.js +6 -2
- package/dist/sdk/cli-contracts/tool-schema.js.map +1 -1
- package/dist/sdk/cli-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts.js +3 -3
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/sdk/cli-program.js +4 -2
- package/dist/sdk/cli-program.js.map +1 -1
- package/dist/sdk/dependencies.d.ts +3 -2
- package/dist/sdk/dependencies.js +13 -12
- package/dist/sdk/dependencies.js.map +1 -1
- package/dist/sdk/error-runtime.d.ts +10 -0
- package/dist/sdk/error-runtime.js +59 -0
- package/dist/sdk/error-runtime.js.map +1 -0
- package/dist/sdk/graph/analytics.d.ts +9 -0
- package/dist/sdk/graph/analytics.js +24 -13
- package/dist/sdk/graph/analytics.js.map +1 -1
- package/dist/sdk/graph/assembly.d.ts +39 -0
- package/dist/sdk/graph/assembly.js +92 -12
- package/dist/sdk/graph/assembly.js.map +1 -1
- package/dist/sdk/graph/cache.d.ts +4 -1
- package/dist/sdk/graph/cache.js +17 -4
- package/dist/sdk/graph/cache.js.map +1 -1
- package/dist/sdk/graph/centrality.d.ts +82 -0
- package/dist/sdk/graph/centrality.js +259 -0
- package/dist/sdk/graph/centrality.js.map +1 -0
- package/dist/sdk/graph/durable-cache.d.ts +71 -0
- package/dist/sdk/graph/durable-cache.js +205 -0
- package/dist/sdk/graph/durable-cache.js.map +1 -0
- package/dist/sdk/graph/governance.d.ts +69 -1
- package/dist/sdk/graph/governance.js +143 -35
- package/dist/sdk/graph/governance.js.map +1 -1
- package/dist/sdk/graph/index.d.ts +7 -4
- package/dist/sdk/graph/index.js +8 -5
- package/dist/sdk/graph/index.js.map +1 -1
- package/dist/sdk/graph/mutation-advisory.d.ts +35 -4
- package/dist/sdk/graph/mutation-advisory.js +124 -35
- package/dist/sdk/graph/mutation-advisory.js.map +1 -1
- package/dist/sdk/graph/remediation.js +12 -2
- package/dist/sdk/graph/remediation.js.map +1 -1
- package/dist/sdk/graph/run.d.ts +133 -2
- package/dist/sdk/graph/run.js +217 -8
- package/dist/sdk/graph/run.js.map +1 -1
- package/dist/sdk/graph/scheduling.d.ts +59 -0
- package/dist/sdk/graph/scheduling.js +125 -0
- package/dist/sdk/graph/scheduling.js.map +1 -0
- package/dist/sdk/graph/traversal.d.ts +11 -0
- package/dist/sdk/graph/traversal.js +16 -2
- package/dist/sdk/graph/traversal.js.map +1 -1
- package/dist/sdk/index.d.ts +4 -0
- package/dist/sdk/index.js +6 -2
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/runtime-input.js +7 -2
- package/dist/sdk/runtime-input.js.map +1 -1
- package/dist/sdk/runtime-primitives.d.ts +10 -0
- package/dist/sdk/runtime-primitives.js +14 -0
- package/dist/sdk/runtime-primitives.js.map +1 -0
- package/dist/sdk/runtime.d.ts +15 -0
- package/dist/sdk/runtime.js +16 -3
- package/dist/sdk/runtime.js.map +1 -1
- package/dist/sdk/structured-mutations.d.ts +21 -0
- package/dist/sdk/structured-mutations.js +375 -0
- package/dist/sdk/structured-mutations.js.map +1 -0
- package/docs/COMMANDS.md +85 -5
- package/docs/RELATIONSHIP_GRAPH.md +48 -7
- package/docs/SDK.md +78 -3
- package/marketplace.json +2 -2
- package/package.json +1 -1
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-claude/README.md +5 -3
- package/plugins/pm-claude/commands/pm-init.md +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/dist/cli-bundle/chunks/chunk-3AO5VSDR.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-3LPFHE3P.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-3VY6MIEO.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-4F6BWJ4J.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-5IZJWSDB.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-5UX66S6U.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-6C2ZZX5Z.js +0 -286
- package/dist/cli-bundle/chunks/chunk-6C2ZZX5Z.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-6VIJ7UA5.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-6XMUURSS.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-C3KD7U3T.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-CFHAODHQ.js +0 -334
- package/dist/cli-bundle/chunks/chunk-CFHAODHQ.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-DAQ45GCS.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-E6LEMURX.js +0 -249
- package/dist/cli-bundle/chunks/chunk-E6LEMURX.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-G3COA6GS.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-GSJSM5BJ.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-GVI6FAFG.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-GVT754PX.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-HEWM6CEN.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-IJNK6WW2.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-INSTSQNZ.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-J4FBIFU6.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-KZEANWJS.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-LPEYZRUR.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-NHT3F4WZ.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-OV7MSW3I.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-P7JTWYLH.js +0 -246
- package/dist/cli-bundle/chunks/chunk-P7JTWYLH.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-R5U2VZ3K.js +0 -344
- package/dist/cli-bundle/chunks/chunk-R5U2VZ3K.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-SG74J6MV.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-T44FMVRL.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-THAOZG4U.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-UQLXSG72.js +0 -289
- package/dist/cli-bundle/chunks/chunk-UQLXSG72.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-UZDQXNUB.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-WVA4DVNV.js.map +0 -7
- package/dist/cli-bundle/chunks/register-list-query-CFVG75P3.js.map +0 -1
- package/dist/cli-bundle/chunks/register-list-query-E7UVY4TN.js.map +0 -7
- package/dist/cli-bundle/chunks/register-mutation-4VJTXBZW.js.map +0 -7
- package/dist/cli-bundle/chunks/register-mutation-IQ55E25C.js.map +0 -1
- /package/dist/cli-bundle/chunks/{append-E6V54WOQ.js.map → append-7OVFYR3C.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{append-NNJ3EFIT.js.map → append-DFETHAZL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-QJKL5PHS.js.map → chunk-7656MAUL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-X6K5XTTN.js.map → chunk-7W2UAXXT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-5OK4UGFV.js.map → chunk-BXNDKOR2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-KSPWRNVP.js.map → chunk-CPX275C6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JH2ZSLO3.js.map → chunk-DZRV2OPA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-L7BH7IWU.js.map → chunk-E5XMKOSB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-CQTQKUUV.js.map → chunk-EWJWSNRU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-3MCTMJXI.js.map → chunk-FPBMLYPI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-DVDBQA3B.js.map → chunk-GTK4DTEW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-GIQSU6S2.js.map → chunk-KBLZ3AA5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-XJF7CDNH.js.map → chunk-KH44WBAT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-GV2262OF.js.map → chunk-LAV26CQG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-VDO2JMD4.js.map → chunk-LVC72YRD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZYPFOO3L.js.map → chunk-MATHDCGG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-AOEOYL3S.js.map → chunk-O4BCOJTZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-RJO3YAFM.js.map → chunk-OCUBRA6D.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-I577UHC7.js.map → chunk-OR42SO64.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZOJ3LR7O.js.map → chunk-OY7DMU5P.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZV2NTVMJ.js.map → chunk-PONKZPCJ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-UX6SSO2I.js.map → chunk-PZC2FUOQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-VQIHNHMJ.js.map → chunk-QIH77CAG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-R3EWPG4A.js.map → chunk-QJIKE24M.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HB3P4M52.js.map → chunk-TRSHFPRZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HRW7GF6T.js.map → chunk-UCBDQI5E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-4U4Z6AHI.js.map → chunk-V22ZPOKN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JM6YAXTR.js.map → chunk-VHXHVTUU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-D6NXDNP3.js.map → chunk-VLRGDBLY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JAPE62Y5.js.map → chunk-VNTCM3VW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FDHPAVVB.js.map → chunk-VXOOB6YX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HQ3SB4CN.js.map → chunk-X3W65QK3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-RZJLNXFG.js.map → chunk-XJTABV3X.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-TYHJDFYW.js.map → chunk-ZVZGXPQ5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-many-SDA426VT.js.map → close-many-5RZXVN4J.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-many-UTZANOCQ.js.map → close-many-RZVTUGBG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-LZN6FXXC.js.map → comments-TPU7QRBL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-VBQ345ND.js.map → comments-Z4KV6FU3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-GG4RBCGC.js.map → create-EIFBIVNQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-JBC5KUW6.js.map → create-RGSPN5GD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-FI4O6NQS.js.map → deps-UH5EQQUY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-DELOO4TL.js.map → deps-YG7UF3VR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{docs-6Z2MP526.js.map → docs-G32TK6XS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{docs-2UYBP5D6.js.map → docs-JWWNRC27.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{files-HKEAN5MA.js.map → files-3H32UQ4K.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{files-HEUGSJZL.js.map → files-4ALMCSKB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-compact-7NDVP3PT.js.map → history-compact-77BT2LUB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-compact-65YVN5DB.js.map → history-compact-VCKGTX64.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-7YBL4XSG.js.map → history-redact-LJPZPNFA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-IZGNJBU4.js.map → history-redact-PWTTJ3XS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-repair-7M4PYQUH.js.map → history-repair-I7CBNCV3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-repair-GNGETJLI.js.map → history-repair-YTDZRK5E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-3YXDRWFT.js.map → learnings-CYNOICKR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-ALC6IMNL.js.map → learnings-KTYW3AL7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-7JMLQ447.js.map → notes-FGO63FXL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-JFCLTC5C.js.map → notes-ZERD3KB2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{plan-T3XB3WTK.js.map → plan-OFJUBIM5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{plan-KOIPWVOZ.js.map → plan-SGCDDTYR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{profile-OILJHKUW.js.map → profile-3THJPIQY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{profile-RJXA7PGS.js.map → profile-XEZAMMBW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-ZH65GZFB.js.map → restore-6TDVSATY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-L6IAGOD7.js.map → restore-RSL7C7LO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-4ERWM5QJ.js.map → schema-HFXFSGPG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-55DL3Q52.js.map → schema-TPVTIJPO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-FW6FKDOP.js.map → update-LJZCL5SI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-TJHSPRPT.js.map → update-SIA7LH5Y.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-PWXX5WHO.js.map → update-many-BDBZVGQL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-NNALYQCN.js.map → update-many-MOY3A5B3.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../sdk/graph/traversal.ts","../../../../../../../../sdk/graph/analytics.ts","../../../../../../../../sdk/graph/governance.ts"],"sourcesContent":["/**\n * @module sdk/graph/traversal\n *\n * Registry-semantics graph traversal primitives layered over the bounded\n * relationship kernel: hierarchy walks (ancestors/descendants), execution-order\n * walks (predecessors/successors), and bounded simple-path enumeration. Every\n * query is deterministic, cancellable, resumable via an explicit cursor, and\n * reports exact cost and truncation metadata so agents can budget follow-up\n * calls without re-reading the workspace.\n */\nimport {\n RelationshipGraph,\n type RelationshipEdge,\n type RelationshipKindDefinition,\n type RelationshipNeighborEdge,\n type RelationshipQueryOptions,\n type RelationshipQueryResult,\n} from \"../relationships.js\";\n\n/**\n * Shared bounded-traversal controls extended with deterministic resumption.\n * Semantic hierarchy and ordering orientation comes from the relationship-kind\n * registry, so callers cannot supply the generic graph `direction` option.\n */\nexport interface GraphTraversalOptions extends Omit<\n RelationshipQueryOptions,\n \"direction\"\n> {\n /**\n * Resume emission after this previously returned node identifier. The\n * traversal re-walks the same deterministic sequence and starts emitting\n * after the cursor node; an identifier the sequence never reaches fails fast\n * instead of silently returning an empty page.\n */\n after?: string;\n}\n\n/** One enumerated simple path between two nodes. */\nexport interface RelationshipPath {\n /** Ordered node identifiers from source to target inclusive. */\n nodes: string[];\n /** Edges connecting consecutive path nodes, in traversal order. */\n edges: RelationshipEdge[];\n /** Number of edges in the path. */\n length: number;\n}\n\n/** Bounded-path enumeration controls. */\nexport interface GraphPathOptions extends RelationshipQueryOptions {\n /** Maximum number of returned paths; defaults to 5. */\n maxPaths?: number;\n /** Safety bound on expanded partial paths before truncation; defaults to 10000. */\n maxVisitedPaths?: number;\n}\n\n/** Default number of paths returned by bounded path enumeration. */\nconst DEFAULT_MAX_PATHS = 5;\n/** Default expansion-safety bound for bounded path enumeration. */\nconst DEFAULT_MAX_VISITED_PATHS = 10_000;\n/** Default depth bound applied to bounded path enumeration. */\nconst DEFAULT_PATH_MAX_DEPTH = 8;\n\n/** Require a finite non-negative integer for one path-enumeration bound. */\nfunction assertPathBound(name: string, value: number): void {\n if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0)\n throw new TypeError(`Invalid path ${name} bound: ${String(value)}`);\n}\n\n/** Endpoint of a hierarchy edge that represents the structural parent. */\nexport function hierarchyParentEndpoint(\n edge: RelationshipEdge,\n definition: RelationshipKindDefinition,\n): string {\n // Custom hierarchy kinds may omit the direction; the registry documents the\n // source endpoint as the default parent.\n return definition.hierarchyDirection === \"target_parent\"\n ? edge.target\n : edge.source;\n}\n\n/** Endpoint of an ordering edge that must finish first. */\nexport function orderingPredecessorEndpoint(\n edge: RelationshipEdge,\n definition: RelationshipKindDefinition,\n): string {\n // Ordering kinds registered without explicit precedence default to\n // source-before-target, matching the execution-analytics interpretation.\n return (definition.precedence ?? \"source_before_target\") ===\n \"target_before_source\"\n ? edge.target\n : edge.source;\n}\n\n/**\n * Orient one ordering edge into its execution direction — the predecessor that\n * must finish first and the successor it gates — honoring the kind's declared\n * precedence so inverse spellings (`blocked_by`/`blocks`) agree. This is the\n * single ordering-orientation primitive shared by scheduling and degree\n * analytics.\n */\nexport function orientOrderingEdge(\n edge: RelationshipEdge,\n definition: RelationshipKindDefinition,\n): { predecessor: string; successor: string } {\n const predecessor = orderingPredecessorEndpoint(edge, definition);\n return {\n predecessor,\n successor: predecessor === edge.source ? edge.target : edge.source,\n };\n}\n\n/** Validate optional kind filters against one semantic edge family. */\nfunction resolveFamilyKinds(\n graph: RelationshipGraph,\n kinds: readonly string[] | undefined,\n family: \"hierarchy\" | \"ordering\",\n): Set<string> | undefined {\n if (kinds === undefined) return undefined;\n const registry = graph.registry();\n const resolved = new Set<string>();\n for (const kind of kinds) {\n const definition = registry.require(kind);\n if (!definition[family])\n throw new TypeError(\n `Relationship kind ${definition.kind} is not a ${family} kind`,\n );\n resolved.add(definition.kind);\n }\n return resolved;\n}\n\n/** Predicate deciding whether a neighbor row participates in one semantic walk. */\ntype SemanticNeighborPredicate = (\n row: RelationshipNeighborEdge,\n definition: RelationshipKindDefinition,\n nodeId: string,\n) => boolean;\n\n/** Mutable state for one bounded semantic breadth-first walk. */\ninterface SemanticWalkState {\n /** Nodes already discovered during the walk. */\n seen: Set<string>;\n /** Nodes emitted for the current page. */\n value: string[];\n /** Pending breadth-first nodes and their depths. */\n queue: { id: string; depth: number }[];\n /** Whether the optional cursor has been reached. */\n resumed: boolean;\n /** Whether a configured bound omitted reachable work. */\n truncated: boolean;\n}\n\n/** Mutable state for bounded simple-path enumeration. */\ninterface PathEnumerationState {\n /** Completed source-to-target paths. */\n value: RelationshipPath[];\n /** Partial simple paths pending expansion. */\n queue: { nodes: string[]; nodeSet: Set<string>; edges: RelationshipEdge[] }[];\n /** Total graph edges inspected by neighbor queries. */\n inspectedEdges: number;\n}\n\n/** Expand one node into its deterministic semantic neighbors. */\nfunction expandSemanticNeighbors(\n graph: RelationshipGraph,\n nodeId: string,\n familyKinds: Set<string> | undefined,\n family: \"hierarchy\" | \"ordering\",\n matches: SemanticNeighborPredicate,\n): { neighbors: string[]; inspectedEdges: number } {\n const registry = graph.registry();\n const rows = graph.neighborEdges(nodeId, {\n direction: \"both\",\n ...(familyKinds === undefined ? {} : { kinds: [...familyKinds] }),\n });\n const neighbors: string[] = [];\n const seen = new Set<string>();\n for (const row of rows.value) {\n const definition = registry.require(row.edge.kind);\n if (!definition[family]) continue;\n if (!matches(row, definition, nodeId)) continue;\n if (seen.has(row.id)) continue;\n seen.add(row.id);\n neighbors.push(row.id);\n }\n return { neighbors, inspectedEdges: rows.meta.inspectedEdges };\n}\n\n/** Append one semantic expansion and report whether the page limit was reached. */\nfunction appendSemanticExpansion(\n expansion: { neighbors: string[] },\n currentDepth: number,\n maxDepth: number,\n limit: number,\n after: string | undefined,\n state: SemanticWalkState,\n): boolean {\n if (currentDepth >= maxDepth) {\n if (expansion.neighbors.some((neighbor) => !state.seen.has(neighbor)))\n state.truncated = true;\n return false;\n }\n for (const neighbor of expansion.neighbors) {\n if (state.seen.has(neighbor)) continue;\n state.seen.add(neighbor);\n state.queue.push({ id: neighbor, depth: currentDepth + 1 });\n if (!state.resumed) {\n if (neighbor === after) state.resumed = true;\n continue;\n }\n if (state.value.length >= limit) {\n state.truncated = true;\n return true;\n }\n state.value.push(neighbor);\n }\n return false;\n}\n\n/** Run one deterministic bounded breadth-first semantic walk. */\nfunction boundedSemanticWalk(\n graph: RelationshipGraph,\n start: string,\n options: GraphTraversalOptions,\n family: \"hierarchy\" | \"ordering\",\n matches: SemanticNeighborPredicate,\n): RelationshipQueryResult<string[]> {\n if (!graph.hasNode(start))\n throw new TypeError(`Relationship node not found: ${start}`);\n const familyKinds = resolveFamilyKinds(graph, options.kinds, family);\n const limit = options.limit ?? Number.POSITIVE_INFINITY;\n const maxDepth = options.maxDepth ?? Number.POSITIVE_INFINITY;\n const after = options.after;\n const state: SemanticWalkState = {\n seen: new Set([start]),\n value: [],\n queue: [{ id: start, depth: 0 }],\n resumed: after === undefined,\n truncated: false,\n };\n let visitedNodes = 0;\n let inspectedEdges = 0;\n for (let index = 0; index < state.queue.length; index += 1) {\n options.signal?.throwIfAborted();\n const current = state.queue[index]!;\n visitedNodes += 1;\n const expansion = expandSemanticNeighbors(\n graph,\n current.id,\n familyKinds,\n family,\n matches,\n );\n inspectedEdges += expansion.inspectedEdges;\n if (\n appendSemanticExpansion(\n expansion,\n current.depth,\n maxDepth,\n limit,\n after,\n state,\n )\n )\n break;\n }\n if (!state.resumed)\n throw new TypeError(`Traversal cursor not found in sequence: ${after}`);\n return {\n value: state.value,\n meta: {\n visitedNodes,\n inspectedEdges,\n truncated: state.truncated,\n nextCursor: state.value.at(-1),\n },\n };\n}\n/** Validate one path endpoint against the indexed graph. */\nfunction assertPathEndpoint(graph: RelationshipGraph, id: string): void {\n if (!graph.hasNode(id))\n throw new TypeError(`Relationship node not found: ${id}`);\n}\n\n/** Return eligible simple-path continuations and account for inspected edges. */\nfunction readPathContinuations(\n graph: RelationshipGraph,\n partial: { nodes: string[]; nodeSet: Set<string>; edges: RelationshipEdge[] },\n options: GraphPathOptions,\n direction: \"outgoing\" | \"incoming\" | \"both\",\n state: PathEnumerationState,\n): ReturnType<RelationshipGraph[\"neighborEdges\"]>[\"value\"] {\n const rows = graph.neighborEdges(partial.nodes.at(-1)!, {\n direction,\n ...(options.kinds === undefined ? {} : { kinds: options.kinds }),\n });\n state.inspectedEdges += rows.meta.inspectedEdges;\n return rows.value.filter((row) => !partial.nodeSet.has(row.id));\n}\n\n/** Expand one partial simple path and report whether the probe cap was reached. */\nfunction expandPartialPath(\n graph: RelationshipGraph,\n partial: { nodes: string[]; nodeSet: Set<string>; edges: RelationshipEdge[] },\n target: string,\n options: GraphPathOptions,\n direction: \"outgoing\" | \"incoming\" | \"both\",\n probeLimit: number,\n state: PathEnumerationState,\n): boolean {\n for (const row of readPathContinuations(\n graph,\n partial,\n options,\n direction,\n state,\n )) {\n const nodes = [...partial.nodes, row.id];\n const nodeSet = new Set(partial.nodeSet).add(row.id);\n const edges = [...partial.edges, row.edge];\n if (row.id === target) {\n state.value.push({ nodes, edges, length: edges.length });\n if (state.value.length >= probeLimit) return true;\n } else {\n state.queue.push({ nodes, nodeSet, edges });\n }\n }\n return false;\n}\n\n/**\n * Return the bounded transitive hierarchy ancestors of one node in\n * breadth-first discovery order, honoring each hierarchy kind's declared\n * parent endpoint (so `parent` and inverse `child` spellings agree).\n */\nexport function hierarchyAncestors(\n graph: RelationshipGraph,\n id: string,\n options: GraphTraversalOptions = {},\n): RelationshipQueryResult<string[]> {\n return boundedSemanticWalk(\n graph,\n id,\n options,\n \"hierarchy\",\n (row, definition) =>\n hierarchyParentEndpoint(row.edge, definition) === row.id,\n );\n}\n\n/**\n * Return the bounded transitive hierarchy descendants of one node in\n * breadth-first discovery order, honoring each hierarchy kind's declared\n * parent endpoint.\n */\nexport function hierarchyDescendants(\n graph: RelationshipGraph,\n id: string,\n options: GraphTraversalOptions = {},\n): RelationshipQueryResult<string[]> {\n return boundedSemanticWalk(\n graph,\n id,\n options,\n \"hierarchy\",\n (row, definition, nodeId) =>\n hierarchyParentEndpoint(row.edge, definition) === nodeId,\n );\n}\n\n/**\n * Return the bounded transitive execution predecessors of one node — the work\n * that must finish before it — in breadth-first discovery order, honoring each\n * ordering kind's declared precedence (so `blocked_by` and inverse `blocks`\n * spellings agree).\n */\nexport function orderingPredecessors(\n graph: RelationshipGraph,\n id: string,\n options: GraphTraversalOptions = {},\n): RelationshipQueryResult<string[]> {\n return boundedSemanticWalk(\n graph,\n id,\n options,\n \"ordering\",\n (row, definition) =>\n orderingPredecessorEndpoint(row.edge, definition) === row.id,\n );\n}\n\n/**\n * Return the bounded transitive execution successors of one node — the work\n * this node gates — in breadth-first discovery order, honoring each ordering\n * kind's declared precedence.\n */\nexport function orderingSuccessors(\n graph: RelationshipGraph,\n id: string,\n options: GraphTraversalOptions = {},\n): RelationshipQueryResult<string[]> {\n return boundedSemanticWalk(\n graph,\n id,\n options,\n \"ordering\",\n (row, definition, nodeId) =>\n orderingPredecessorEndpoint(row.edge, definition) === nodeId,\n );\n}\n\n/** Run bounded non-zero path enumeration after public option validation. */\nfunction enumerateNonZeroRelationshipPaths(\n graph: RelationshipGraph,\n source: string,\n target: string,\n options: GraphPathOptions,\n maxPaths: number,\n maxVisitedPaths: number,\n maxDepth: number,\n direction: \"outgoing\" | \"incoming\" | \"both\",\n): RelationshipQueryResult<RelationshipPath[]> {\n const state: PathEnumerationState = {\n value: [],\n queue: [{ nodes: [source], nodeSet: new Set([source]), edges: [] }],\n inspectedEdges: 0,\n };\n let visitedNodes = 0;\n let truncated = false;\n const probeLimit = maxPaths + 1;\n for (let index = 0; index < state.queue.length; index += 1) {\n options.signal?.throwIfAborted();\n if (state.value.length >= probeLimit || visitedNodes >= maxVisitedPaths) {\n truncated = true;\n break;\n }\n const partial = state.queue[index]!;\n visitedNodes += 1;\n if (partial.edges.length >= maxDepth) {\n if (\n readPathContinuations(graph, partial, options, direction, state)\n .length > 0\n )\n truncated = true;\n continue;\n }\n if (\n expandPartialPath(\n graph,\n partial,\n target,\n options,\n direction,\n probeLimit,\n state,\n )\n ) {\n truncated = true;\n break;\n }\n }\n return {\n value: state.value.slice(0, maxPaths),\n meta: { visitedNodes, inspectedEdges: state.inspectedEdges, truncated },\n };\n}\n\n/**\n * Enumerate bounded simple paths between two nodes, shortest first and\n * lexicographic within equal length. Traversal honors direction and kind\n * filters, caps returned paths, and reports truncation when depth, path-count,\n * or the expansion-safety bound stops the search early.\n */\nexport function enumerateRelationshipPaths(\n graph: RelationshipGraph,\n source: string,\n target: string,\n options: GraphPathOptions = {},\n): RelationshipQueryResult<RelationshipPath[]> {\n assertPathEndpoint(graph, source);\n assertPathEndpoint(graph, target);\n const maxPaths = options.maxPaths ?? DEFAULT_MAX_PATHS;\n const maxVisitedPaths = options.maxVisitedPaths ?? DEFAULT_MAX_VISITED_PATHS;\n const maxDepth = options.maxDepth ?? DEFAULT_PATH_MAX_DEPTH;\n assertPathBound(\"maxPaths\", maxPaths);\n assertPathBound(\"maxVisitedPaths\", maxVisitedPaths);\n assertPathBound(\"maxDepth\", maxDepth);\n const direction = options.direction ?? \"outgoing\";\n options.signal?.throwIfAborted();\n for (const kind of options.kinds ?? []) graph.registry().require(kind);\n if (source === target) {\n if (maxPaths === 0) {\n return {\n value: [],\n meta: { visitedNodes: 1, inspectedEdges: 0, truncated: true },\n };\n }\n return {\n value: [{ nodes: [source], edges: [], length: 0 }],\n meta: { visitedNodes: 1, inspectedEdges: 0, truncated: false },\n };\n }\n return enumerateNonZeroRelationshipPaths(\n graph,\n source,\n target,\n options,\n maxPaths,\n maxVisitedPaths,\n maxDepth,\n direction,\n );\n}\n","/**\n * @module sdk/graph/analytics\n *\n * Structural graph analytics beyond exact components: deterministic\n * label-propagation community detection over the undirected relationship\n * structure, transitively redundant edge discovery over ordering and\n * hierarchy families, and dominator (bottleneck) analysis over one node's\n * reachable subgraph. Every analysis is deterministic, cancellable, bounded,\n * and reports exact cost metadata so agents can budget follow-up reads\n * without re-scanning the workspace.\n */\nimport {\n RelationshipGraph,\n type RelationshipEdge,\n type RelationshipKindDefinition,\n type RelationshipNeighborEdge,\n type RelationshipQueryResult,\n type RelationshipTraversalDirection,\n} from \"../relationships.js\";\nimport {\n hierarchyParentEndpoint,\n orderingPredecessorEndpoint,\n} from \"./traversal.js\";\n\n/** Default label-propagation sweeps before reporting non-convergence. */\nconst DEFAULT_MAX_ITERATIONS = 16;\n/** Default minimum member count for a reported community. */\nconst DEFAULT_MIN_COMMUNITY_SIZE = 2;\n/** Default witness-path depth searched per candidate redundant edge. */\nconst DEFAULT_REDUNDANCY_MAX_DEPTH = 8;\n\n/** One detected relationship community. */\nexport interface RelationshipCommunity {\n /** Lexicographically smallest member id, naming the community. */\n representative: string;\n /** Total member count. */\n size: number;\n /** Sorted member node ids. */\n members: string[];\n}\n\n/** Bounded community-detection controls. */\nexport interface GraphCommunityOptions {\n /** Registered relationship kinds whose edges define adjacency. */\n kinds?: readonly string[];\n /** Maximum label-propagation sweeps before reporting non-convergence; defaults to 16. */\n maxIterations?: number;\n /** Minimum member count for a reported community; defaults to 2. */\n minSize?: number;\n /** Abort signal checked once per sweep. */\n signal?: AbortSignal;\n}\n\n/** Deterministic label-propagation community analysis. */\nexport interface RelationshipCommunityAnalysis {\n /** Detected communities, largest first and by representative within equal size. */\n communities: RelationshipCommunity[];\n /** Label-propagation sweeps executed. */\n iterations: number;\n /** Whether labels stabilized before the iteration bound stopped the sweep. */\n converged: boolean;\n}\n\n/** One stored edge implied by a longer same-family witness path. */\nexport interface RedundantRelationshipEdge {\n /** The stored redundant edge in its original spelling. */\n edge: RelationshipEdge;\n /** Semantic-orientation witness node path proving the implication, endpoints inclusive. */\n witness: string[];\n}\n\n/** Bounded redundancy-scan controls. */\nexport interface GraphRedundancyOptions {\n /** Directed ordering or hierarchy kinds to scan; defaults to every eligible registered kind. */\n kinds?: readonly string[];\n /** Maximum witness-path depth searched per edge; defaults to 8. */\n maxDepth?: number;\n /** Maximum reported redundant edges. */\n limit?: number;\n /** Abort signal checked once per scanned edge. */\n signal?: AbortSignal;\n}\n\n/** One reachable node with its immediate dominator and gating weight. */\nexport interface RelationshipDominatorRow {\n /** Reachable node id. */\n id: string;\n /** Immediate dominator appearing on every root-to-node path. */\n idom: string;\n /** Nodes strictly dominated by this node — its dominator-subtree size minus itself. */\n dominatedCount: number;\n}\n\n/** Bounded dominator-analysis controls. */\nexport interface GraphDominatorOptions {\n /** Registered relationship kinds whose edges define reachability. */\n kinds?: readonly string[];\n /** Traversal direction relative to each visited node; defaults to \"outgoing\". */\n direction?: RelationshipTraversalDirection;\n /** Maximum reachability depth from the root as a non-negative integer. */\n maxDepth?: number;\n /** Abort signal checked once per processed node. */\n signal?: AbortSignal;\n}\n\n/** Dominator-tree analysis of one node's reachable subgraph. */\nexport interface RelationshipDominatorAnalysis {\n /** Analyzed root id. */\n root: string;\n /** Reachable node count including the root. */\n reachableCount: number;\n /** Non-root reachable rows sorted by gating weight, then id. */\n rows: RelationshipDominatorRow[];\n}\n\n/** Require a positive integer for one analytics bound. */\nfunction assertPositiveBound(name: string, value: number): void {\n if (!Number.isInteger(value) || value < 1)\n throw new TypeError(`Invalid ${name} bound: ${String(value)}`);\n}\n\n/**\n * Invoke `visit` once per canonical-kind-matched edge, skipping self-loops.\n * Kind filters resolve to canonical spelling and match either the requested\n * kind or its inverse so directed families are selected by either spelling. The\n * resolved definition is passed alongside the edge so callers can distinguish\n * directed and undirected families. This is the single edge-selection primitive\n * shared by community, centrality, cut-structure, and degree builders.\n */\nexport function forEachMatchedRelationshipEdge(\n graph: RelationshipGraph,\n kinds: readonly string[] | undefined,\n visit: (\n edge: RelationshipEdge,\n definition: RelationshipKindDefinition,\n ) => void,\n): void {\n const registry = graph.registry();\n const wanted =\n kinds === undefined\n ? undefined\n : new Set(kinds.map((kind) => registry.require(kind).kind));\n for (const edge of graph.edges()) {\n if (edge.source === edge.target) continue;\n const definition = registry.require(edge.kind);\n if (\n wanted !== undefined &&\n !(\n wanted.has(definition.kind) ||\n (definition.inverse !== undefined && wanted.has(definition.inverse))\n )\n )\n continue;\n visit(edge, definition);\n }\n}\n\n/** Build the deterministic undirected multiset adjacency restricted to canonicalized kinds. */\nfunction buildUndirectedAdjacency(\n graph: RelationshipGraph,\n kinds: readonly string[] | undefined,\n): Map<string, string[]> {\n const adjacency = new Map<string, string[]>();\n forEachMatchedRelationshipEdge(graph, kinds, (edge) => {\n appendAdjacency(adjacency, edge.source, edge.target);\n appendAdjacency(adjacency, edge.target, edge.source);\n });\n for (const neighbors of adjacency.values()) neighbors.sort();\n return adjacency;\n}\n\n/** Append one neighbor to a node's adjacency list, creating the list on demand. */\nfunction appendAdjacency(\n adjacency: Map<string, string[]>,\n from: string,\n to: string,\n): void {\n const neighbors = adjacency.get(from);\n if (neighbors === undefined) adjacency.set(from, [to]);\n else neighbors.push(to);\n}\n\n/** Adopt the most frequent neighbor label with lexicographic tie-breaking. */\nfunction dominantNeighborLabel(\n neighbors: readonly string[],\n labels: Map<string, string>,\n): string {\n const counts = new Map<string, number>();\n for (const neighbor of neighbors) {\n const label = labels.get(neighbor)!;\n counts.set(label, (counts.get(label) ?? 0) + 1);\n }\n let best: string | undefined;\n let bestCount = 0;\n for (const [label, count] of counts) {\n if (count > bestCount || (count === bestCount && label < best!)) {\n best = label;\n bestCount = count;\n }\n }\n return best!;\n}\n\n/** Group stabilized labels into sorted communities meeting the size floor. */\nfunction collectCommunities(\n labels: Map<string, string>,\n minSize: number,\n): RelationshipCommunity[] {\n const groups = new Map<string, string[]>();\n for (const [id, label] of labels) {\n const members = groups.get(label);\n if (members === undefined) groups.set(label, [id]);\n else members.push(id);\n }\n const communities: RelationshipCommunity[] = [];\n for (const members of groups.values()) {\n if (members.length < minSize) continue;\n members.sort();\n communities.push({\n representative: members[0]!,\n size: members.length,\n members,\n });\n }\n return communities.sort(\n (left, right) =>\n right.size - left.size ||\n left.representative.localeCompare(right.representative),\n );\n}\n\n/**\n * Detect communities with deterministic asynchronous label propagation: nodes\n * are swept in sorted order, each adopting the most frequent label among its\n * neighbors with lexicographic tie-breaking, until labels stabilize or the\n * iteration bound stops the sweep. Adjacency is undirected — every\n * participating edge connects both endpoints symmetrically and parallel edges\n * weight their neighbor. `meta.truncated` reports non-convergence.\n */\nexport function detectRelationshipCommunities(\n graph: RelationshipGraph,\n options: GraphCommunityOptions = {},\n): RelationshipQueryResult<RelationshipCommunityAnalysis> {\n const maxIterations = options.maxIterations ?? DEFAULT_MAX_ITERATIONS;\n const minSize = options.minSize ?? DEFAULT_MIN_COMMUNITY_SIZE;\n assertPositiveBound(\"maxIterations\", maxIterations);\n assertPositiveBound(\"minSize\", minSize);\n const adjacency = buildUndirectedAdjacency(graph, options.kinds);\n const nodes = graph.nodes();\n const labels = new Map(nodes.map((id) => [id, id]));\n let iterations = 0;\n let converged = false;\n let visitedNodes = 0;\n let inspectedEdges = 0;\n while (iterations < maxIterations && !converged) {\n options.signal?.throwIfAborted();\n iterations += 1;\n converged = true;\n for (const id of nodes) {\n visitedNodes += 1;\n const neighbors = adjacency.get(id);\n if (neighbors === undefined) continue;\n inspectedEdges += neighbors.length;\n const dominant = dominantNeighborLabel(neighbors, labels);\n if (dominant !== labels.get(id)) {\n labels.set(id, dominant);\n converged = false;\n }\n }\n }\n return {\n value: {\n communities: collectCommunities(labels, minSize),\n iterations,\n converged,\n },\n meta: { visitedNodes, inspectedEdges, truncated: !converged },\n };\n}\n\n/** Decide whether a kind carries transitive semantics eligible for redundancy and duplicate analysis. */\nexport function isTransitiveKind(definition: RelationshipKindDefinition): boolean {\n return (\n definition.direction === \"directed\" &&\n (definition.ordering || definition.hierarchy)\n );\n}\n\n/** Family grouping key joining a directed kind with its inverse spelling. */\nexport function transitiveFamilyKey(definition: RelationshipKindDefinition): string {\n return definition.inverse !== undefined &&\n definition.inverse < definition.kind\n ? definition.inverse\n : definition.kind;\n}\n\n/** Orient one transitive edge into its semantic forward direction. */\nexport function orientTransitiveEdge(\n edge: RelationshipEdge,\n definition: RelationshipKindDefinition,\n): { from: string; to: string } {\n // Hierarchy families flow child -> parent; ordering families flow\n // predecessor -> successor, so inverse spellings land in one relation.\n const head = definition.hierarchy\n ? hierarchyParentEndpoint(edge, definition)\n : edge.source === orderingPredecessorEndpoint(edge, definition)\n ? edge.target\n : edge.source;\n return head === edge.target\n ? { from: edge.source, to: edge.target }\n : { from: edge.target, to: edge.source };\n}\n\n/** One semantically oriented transitive edge retaining its stored spelling. */\ninterface OrientedTransitiveEdge {\n /** Semantic tail node. */\n from: string;\n /** Semantic head node. */\n to: string;\n /** Original stored edge. */\n edge: RelationshipEdge;\n}\n\n/** Per-family oriented edges and their deterministic forward adjacency. */\ninterface TransitiveFamily {\n /** Deduplicated forward adjacency in semantic orientation, sorted after collection. */\n adjacency: Map<string, Set<string>>;\n /** Oriented edges in deterministic stored order. */\n records: OrientedTransitiveEdge[];\n}\n\n/** Resolve explicit redundancy kind filters into their family keys. */\nfunction resolveRedundancyFamilies(\n graph: RelationshipGraph,\n kinds: readonly string[] | undefined,\n): Set<string> | undefined {\n if (kinds === undefined) return undefined;\n const registry = graph.registry();\n const families = new Set<string>();\n for (const kind of kinds) {\n const definition = registry.require(kind);\n if (!isTransitiveKind(definition))\n throw new TypeError(\n `Relationship kind ${definition.kind} is not a directed ordering or hierarchy kind`,\n );\n families.add(transitiveFamilyKey(definition));\n }\n return families;\n}\n\n/** Group eligible stored edges into oriented per-family scan structures. */\nfunction collectTransitiveFamilies(\n graph: RelationshipGraph,\n wanted: Set<string> | undefined,\n): Map<string, TransitiveFamily> {\n const registry = graph.registry();\n const families = new Map<string, TransitiveFamily>();\n for (const edge of graph.edges()) {\n const definition = registry.require(edge.kind);\n if (!isTransitiveKind(definition)) continue;\n const key = transitiveFamilyKey(definition);\n if (wanted !== undefined && !wanted.has(key)) continue;\n const oriented = orientTransitiveEdge(edge, definition);\n if (oriented.from === oriented.to) continue;\n let family = families.get(key);\n if (family === undefined) {\n family = { adjacency: new Map(), records: [] };\n families.set(key, family);\n }\n const targets = family.adjacency.get(oriented.from);\n if (targets === undefined)\n family.adjacency.set(oriented.from, new Set([oriented.to]));\n else targets.add(oriented.to);\n family.records.push({ ...oriented, edge });\n }\n return families;\n}\n\n/** Freeze one family's adjacency sets into deterministic sorted lists. */\nfunction sortedFamilyAdjacency(\n family: TransitiveFamily,\n): Map<string, readonly string[]> {\n const sorted = new Map<string, readonly string[]>();\n for (const [from, targets] of family.adjacency)\n sorted.set(from, [...targets].sort());\n return sorted;\n}\n\n/** Rebuild the witness node path from breadth-first parent pointers. */\nfunction reconstructWitness(\n parents: Map<string, string>,\n from: string,\n tail: string,\n head: string,\n): string[] {\n const witness = [head];\n for (let node = tail; node !== from; node = parents.get(node)!)\n witness.push(node);\n witness.push(from);\n return witness.reverse();\n}\n\n/** Expand one witness frontier node; return the completed witness when the head is reached. */\nfunction expandWitnessFrontier(\n adjacency: Map<string, readonly string[]>,\n record: OrientedTransitiveEdge,\n current: { id: string; depth: number },\n parents: Map<string, string>,\n queue: { id: string; depth: number }[],\n cost: { visitedNodes: number; inspectedEdges: number },\n): string[] | undefined {\n for (const next of adjacency.get(current.id) ?? []) {\n cost.inspectedEdges += 1;\n // Skip the direct edge under test; deeper hops may still reach the head.\n if (current.depth === 0 && next === record.to) continue;\n if (parents.has(next)) continue;\n parents.set(next, current.id);\n if (next === record.to)\n return reconstructWitness(parents, record.from, current.id, next);\n queue.push({ id: next, depth: current.depth + 1 });\n }\n return undefined;\n}\n\n/** Search one bounded same-family witness path that implies a direct edge. */\nfunction findWitnessPath(\n adjacency: Map<string, readonly string[]>,\n record: OrientedTransitiveEdge,\n maxDepth: number,\n cost: { visitedNodes: number; inspectedEdges: number },\n): string[] | undefined {\n const parents = new Map<string, string>([[record.from, record.from]]);\n const queue = [{ id: record.from, depth: 0 }];\n for (let index = 0; index < queue.length; index += 1) {\n const current = queue[index]!;\n cost.visitedNodes += 1;\n if (current.depth >= maxDepth) continue;\n const witness = expandWitnessFrontier(\n adjacency,\n record,\n current,\n parents,\n queue,\n cost,\n );\n if (witness !== undefined) return witness;\n }\n return undefined;\n}\n\n/**\n * Find stored edges implied by a longer path of the same semantic family —\n * the transitive-reduction view of ordering and hierarchy relations. Each\n * family joins a directed kind with its inverse spelling in semantic\n * orientation, so `blocked_by` and `blocks` witness each other. The witness\n * search is breadth-first, shortest and lexicographic first, bounded by\n * `maxDepth` per edge; `meta.truncated` reports only the `limit` bound.\n */\nexport function findRedundantRelationshipEdges(\n graph: RelationshipGraph,\n options: GraphRedundancyOptions = {},\n): RelationshipQueryResult<RedundantRelationshipEdge[]> {\n const maxDepth = options.maxDepth ?? DEFAULT_REDUNDANCY_MAX_DEPTH;\n assertPositiveBound(\"maxDepth\", maxDepth);\n if (options.limit !== undefined) assertPositiveBound(\"limit\", options.limit);\n const limit = options.limit ?? Number.POSITIVE_INFINITY;\n const wanted = resolveRedundancyFamilies(graph, options.kinds);\n const families = collectTransitiveFamilies(graph, wanted);\n const value: RedundantRelationshipEdge[] = [];\n const cost = { visitedNodes: 0, inspectedEdges: 0 };\n let truncated = false;\n scan: for (const key of [...families.keys()].sort()) {\n const family = families.get(key)!;\n const adjacency = sortedFamilyAdjacency(family);\n for (const record of family.records) {\n options.signal?.throwIfAborted();\n const witness = findWitnessPath(adjacency, record, maxDepth, cost);\n if (witness === undefined) continue;\n if (value.length >= limit) {\n truncated = true;\n break scan;\n }\n value.push({ edge: record.edge, witness });\n }\n }\n return {\n value,\n meta: {\n visitedNodes: cost.visitedNodes,\n inspectedEdges: cost.inspectedEdges,\n truncated,\n },\n };\n}\n\n/** Reachability index of one root's directed subgraph. */\ninterface ReachableSubgraph {\n /** Reachable node ids in breadth-first discovery order. */\n order: string[];\n /** Deterministic successor lists per reachable node. */\n successors: Map<string, string[]>;\n /** Reachable predecessor sets per reachable node. */\n predecessors: Map<string, Set<string>>;\n /** Candidate edges inspected while indexing. */\n inspectedEdges: number;\n /** Whether the depth bound excluded reachable nodes. */\n truncated: boolean;\n}\n\n/** Mutable frontier state threaded through bounded reachability expansion. */\ninterface ReachabilityState {\n /** Nodes already discovered. */\n seen: Set<string>;\n /** Pending breadth-first nodes and their depths. */\n queue: { id: string; depth: number }[];\n /** Reachable predecessor sets per discovered node. */\n predecessors: Map<string, Set<string>>;\n /** Whether the depth bound excluded reachable nodes. */\n truncated: boolean;\n}\n\n/** Expand one node's neighbor rows into successors, predecessors, and frontier work. */\nfunction expandReachableNode(\n id: string,\n depth: number,\n rows: readonly RelationshipNeighborEdge[],\n maxDepth: number,\n state: ReachabilityState,\n): string[] {\n const nextSet = new Set<string>();\n const nexts: string[] = [];\n for (const row of rows) {\n if (row.id === id || nextSet.has(row.id)) continue;\n if (!state.seen.has(row.id)) {\n // A depth-boundary node keeps its edges to already-indexed nodes but\n // may not discover new ones; excluded discoveries mark truncation.\n if (depth >= maxDepth) {\n state.truncated = true;\n continue;\n }\n state.seen.add(row.id);\n state.queue.push({ id: row.id, depth: depth + 1 });\n }\n nextSet.add(row.id);\n nexts.push(row.id);\n let incoming = state.predecessors.get(row.id);\n if (incoming === undefined) {\n incoming = new Set();\n state.predecessors.set(row.id, incoming);\n }\n incoming.add(id);\n }\n return nexts;\n}\n\n/** Index the bounded reachable subgraph used by dominator analysis. */\nfunction indexReachableSubgraph(\n graph: RelationshipGraph,\n root: string,\n options: GraphDominatorOptions,\n): ReachableSubgraph {\n const direction = options.direction ?? \"outgoing\";\n const maxDepth = options.maxDepth ?? Number.POSITIVE_INFINITY;\n const order: string[] = [];\n const successors = new Map<string, string[]>();\n const state: ReachabilityState = {\n seen: new Set([root]),\n queue: [{ id: root, depth: 0 }],\n predecessors: new Map(),\n truncated: false,\n };\n let inspectedEdges = 0;\n for (let index = 0; index < state.queue.length; index += 1) {\n options.signal?.throwIfAborted();\n const { id, depth } = state.queue[index]!;\n order.push(id);\n const rows = graph.neighborEdges(id, {\n direction,\n ...(options.kinds === undefined ? {} : { kinds: options.kinds }),\n });\n inspectedEdges += rows.meta.inspectedEdges;\n successors.set(id, expandReachableNode(id, depth, rows.value, maxDepth, state));\n }\n return {\n order,\n successors,\n predecessors: state.predecessors,\n inspectedEdges,\n truncated: state.truncated,\n };\n}\n\n/** Compute the deterministic reverse postorder of one reachable subgraph. */\nfunction reversePostorder(subgraph: ReachableSubgraph, root: string): string[] {\n const postorder: string[] = [];\n const visited = new Set([root]);\n const stack = [{ id: root, index: 0 }];\n while (stack.length > 0) {\n const frame = stack.at(-1)!;\n const nexts = subgraph.successors.get(frame.id)!;\n if (frame.index < nexts.length) {\n const next = nexts[frame.index]!;\n frame.index += 1;\n if (!visited.has(next)) {\n visited.add(next);\n stack.push({ id: next, index: 0 });\n }\n } else {\n postorder.push(frame.id);\n stack.pop();\n }\n }\n return postorder.reverse();\n}\n\n/** Walk two dominator-tree fingers to their common ancestor by reverse-postorder number. */\nfunction intersectDominators(\n left: string,\n right: string,\n idom: Map<string, string>,\n ordinal: Map<string, number>,\n): string {\n let first = left;\n let second = right;\n while (first !== second) {\n while (ordinal.get(first)! > ordinal.get(second)!) first = idom.get(first)!;\n while (ordinal.get(second)! > ordinal.get(first)!) second = idom.get(second)!;\n }\n return first;\n}\n\n/** Fold one node's processed predecessors into its dominator candidate. */\nfunction dominatorCandidate(\n predecessors: ReadonlySet<string>,\n idom: Map<string, string>,\n ordinal: Map<string, number>,\n): string | undefined {\n let candidate: string | undefined;\n for (const pred of [...predecessors].sort()) {\n if (!idom.has(pred)) continue;\n candidate =\n candidate === undefined\n ? pred\n : intersectDominators(candidate, pred, idom, ordinal);\n }\n return candidate;\n}\n\n/** Run the Cooper–Harvey–Kennedy fixed-point over one reverse postorder. */\nfunction solveImmediateDominators(\n subgraph: ReachableSubgraph,\n root: string,\n order: readonly string[],\n ordinal: Map<string, number>,\n signal: AbortSignal | undefined,\n): Map<string, string> {\n const idom = new Map<string, string>([[root, root]]);\n let changed = true;\n while (changed) {\n changed = false;\n for (const id of order) {\n signal?.throwIfAborted();\n if (id === root) continue;\n // Every non-root node in the order was discovered through at least one\n // predecessor, so the set is always present.\n const candidate = dominatorCandidate(\n subgraph.predecessors.get(id)!,\n idom,\n ordinal,\n );\n if (candidate !== undefined && idom.get(id) !== candidate) {\n idom.set(id, candidate);\n changed = true;\n }\n }\n }\n return idom;\n}\n\n/**\n * Compute immediate dominators and gating weights over one node's reachable\n * subgraph using the Cooper–Harvey–Kennedy fixed-point. A node dominates the\n * work that every path from the root must pass through it to reach, so rows\n * with a positive `dominatedCount` are the structural bottlenecks of the\n * root's blast radius. Rows sort by gating weight, then id; `meta.truncated`\n * reports when the `maxDepth` bound excluded reachable nodes.\n */\nexport function computeRelationshipDominators(\n graph: RelationshipGraph,\n root: string,\n options: GraphDominatorOptions = {},\n): RelationshipQueryResult<RelationshipDominatorAnalysis> {\n if (!graph.hasNode(root))\n throw new TypeError(`Relationship node not found: ${root}`);\n if (\n options.maxDepth !== undefined &&\n (!Number.isInteger(options.maxDepth) || options.maxDepth < 0)\n )\n throw new TypeError(`Invalid maxDepth bound: ${String(options.maxDepth)}`);\n const subgraph = indexReachableSubgraph(graph, root, options);\n const order = reversePostorder(subgraph, root);\n const ordinal = new Map(order.map((id, index) => [id, index]));\n const idom = solveImmediateDominators(\n subgraph,\n root,\n order,\n ordinal,\n options.signal,\n );\n const subtreeSizes = new Map(order.map((id) => [id, 1]));\n for (let index = order.length - 1; index >= 0; index -= 1) {\n const id = order[index]!;\n if (id === root) continue;\n const parent = idom.get(id)!;\n subtreeSizes.set(parent, subtreeSizes.get(parent)! + subtreeSizes.get(id)!);\n }\n const rows = order\n .filter((id) => id !== root)\n .map((id) => ({\n id,\n idom: idom.get(id)!,\n dominatedCount: subtreeSizes.get(id)! - 1,\n }))\n .sort(\n (left, right) =>\n right.dominatedCount - left.dominatedCount ||\n left.id.localeCompare(right.id),\n );\n return {\n value: { root, reachableCount: subgraph.order.length, rows },\n meta: {\n visitedNodes: subgraph.order.length,\n inspectedEdges: subgraph.inspectedEdges,\n truncated: subgraph.truncated,\n },\n };\n}\n","/**\n * @module sdk/graph/governance\n *\n * Policy-aware relationship-graph quality audit shared by validation, health,\n * and package governance surfaces. The audit inspects one assembled workspace\n * graph and reports machine-readable findings — integrity gaps, ordering\n * cycles, duplicated edge spellings, stale lifecycle blocks, and coverage\n * outliers — without inventing edges or assuming that sparse connectivity is\n * defective. Findings gate severity on lifecycle: contradictions confined to\n * terminal items downgrade to informational `legacy_*` codes because repairing\n * them would mutate closed history. Every finding names the violated policy,\n * carries a deterministic bounded sample, and proposes a safe next action so\n * agents can plan remediation without re-deriving context.\n */\nimport type { RelationshipEdge } from \"../relationships.js\";\nimport {\n isTransitiveKind,\n orientTransitiveEdge,\n transitiveFamilyKey,\n} from \"./analytics.js\";\nimport type { WorkspaceRelationshipAssembly } from \"./assembly.js\";\n\n/** Severity ladder shared by every relationship audit finding. */\nexport type RelationshipAuditSeverity = \"error\" | \"warning\" | \"info\";\n\n/** Machine-readable identifier for one relationship audit finding family. */\nexport type RelationshipAuditFindingCode =\n | \"missing_reference_active\"\n | \"missing_reference_terminal\"\n | \"legacy_no_blocker_sentinel\"\n | \"ordering_cycle\"\n | \"legacy_ordering_cycle\"\n | \"duplicate_edge\"\n | \"legacy_duplicate_edge\"\n | \"duplicate_dependency_row\"\n | \"legacy_duplicate_dependency_row\"\n | \"stale_lifecycle_block\"\n | \"isolated_active_node\"\n | \"sparse_active_node\";\n\n/** One policy-aware relationship audit finding with bounded evidence. */\nexport interface RelationshipAuditFinding {\n /** Machine-readable finding family identifier. */\n code: RelationshipAuditFindingCode;\n /** Severity of the violated policy. */\n severity: RelationshipAuditSeverity;\n /** Policy statement this finding violates. */\n policy: string;\n /** Human-readable summary including the affected count. */\n message: string;\n /** Total number of affected subjects, independent of sample bounding. */\n count: number;\n /** Deterministic bounded sample of affected subjects. */\n sample: string[];\n /** Whether {@link sample} was truncated by the configured sample bound. */\n sample_truncated: boolean;\n /** Safe machine-actionable next step; audits never invent or auto-apply edges. */\n remediation: string;\n}\n\n/** Per-item-type connectivity coverage inside a coverage profile. */\nexport interface RelationshipCoverageTypeProfile {\n /** Active nodes declaring this item type. */\n active: number;\n /** Active nodes of this type with no incident edges. */\n isolated: number;\n /** Active nodes of this type with at most one incident edge, isolates included. */\n degree_leq_one: number;\n}\n\n/** Aggregate structural coverage metrics for one assembled workspace graph. */\nexport interface RelationshipCoverageProfile {\n /** Total indexed nodes including materialized missing placeholders. */\n nodes: number;\n /** Total deduplicated indexed edges. */\n edges: number;\n /** Deterministic per-kind edge counts. */\n edges_by_kind: Record<string, number>;\n /** Nodes whose lifecycle status is active (non-terminal, non-missing). */\n active_nodes: number;\n /** Materialized placeholder nodes for referenced-but-absent items. */\n missing_nodes: number;\n /** Active nodes with no incident edges at all. */\n isolated_active_nodes: number;\n /** Active nodes with at most one incident edge, isolates included. */\n degree_leq_one_active_nodes: number;\n /** Deterministic per-type connectivity coverage; untyped nodes bucket under `(untyped)`. */\n coverage_by_type: Record<string, RelationshipCoverageTypeProfile>;\n}\n\n/** Tuning and policy inputs accepted by the relationship audit. */\nexport interface RelationshipAuditOptions {\n /** Terminal-lifecycle predicate; defaults to the built-in closed/canceled statuses. */\n isTerminal?: (status: string) => boolean;\n /** Blocked-lifecycle predicate for stale-block detection; defaults to `status === \"blocked\"`. */\n isBlocked?: (status: string) => boolean;\n /** Node identifiers that are explicitly valid isolates (roots, archives, scratch work). */\n exemptIsolates?: readonly string[];\n /** Item types whose active nodes are policy-valid isolates or sparse nodes (case-insensitive); they stay in the coverage profile but raise no coverage finding. */\n isolateExemptTypes?: readonly string[];\n /** Maximum sample entries retained per finding; defaults to 25. */\n maxSampleSize?: number;\n /** Abort signal checked between finding families. */\n signal?: AbortSignal;\n}\n\n/** Complete deterministic result of one relationship-graph audit. */\nexport interface RelationshipAuditReport {\n /** Findings ordered by severity, then code, then first sample subject. */\n findings: RelationshipAuditFinding[];\n /** Structural coverage metrics computed during the audit. */\n profile: RelationshipCoverageProfile;\n}\n\n/** Default bounded sample size applied to every finding family. */\nconst DEFAULT_MAX_SAMPLE_SIZE = 25;\n\n/** Rank used to order findings by decreasing severity. */\nconst SEVERITY_RANK: Record<RelationshipAuditSeverity, number> = {\n error: 0,\n warning: 1,\n info: 2,\n};\n\n/** Internal per-node lifecycle classification resolved once per audit. */\ninterface AuditNodeState {\n /** Original-case node identifier. */\n id: string;\n /** Raw lifecycle status string from assembly details. */\n status: string;\n /** Whether the node is a materialized missing placeholder. */\n missing: boolean;\n /** Whether the node's lifecycle status is terminal. */\n terminal: boolean;\n /** Declared item type, when the assembly carried one. */\n type?: string;\n}\n\n/** Mutable state shared by iterative Tarjan frames. */\ninterface TarjanState {\n /** Discovery index assigned to each visited node. */\n indexes: Map<string, number>;\n /** Lowest reachable discovery index per visited node. */\n lowLinks: Map<string, number>;\n /** Nodes that still belong to an unfinished component. */\n onStack: Set<string>;\n /** Component-membership stack. */\n stack: string[];\n /** Completed cyclic components. */\n components: string[][];\n /** Discovery index assigned to the next unseen node. */\n nextIndex: number;\n}\n\n/** One explicit depth-first frame used by iterative Tarjan traversal. */\ninterface TarjanFrame {\n /** Node currently being expanded. */\n node: string;\n /** Index of the next successor to inspect. */\n neighborIndex: number;\n}\n\n/** Build one finding with deterministic bounded sampling over sorted subjects. */\nfunction buildFinding(\n code: RelationshipAuditFindingCode,\n severity: RelationshipAuditSeverity,\n policy: string,\n describe: (count: number) => string,\n subjects: readonly string[],\n maxSampleSize: number,\n remediation: string,\n): RelationshipAuditFinding {\n const sorted = [...subjects].sort((left, right) => left.localeCompare(right));\n return {\n code,\n severity,\n policy,\n message: describe(sorted.length),\n count: sorted.length,\n sample: sorted.slice(0, maxSampleSize),\n sample_truncated: sorted.length > maxSampleSize,\n remediation,\n };\n}\n/** Resolve the ordering-only successor adjacency for cycle analysis. */\nfunction buildOrderingAdjacency(\n assembly: WorkspaceRelationshipAssembly,\n): Map<string, string[]> {\n const registry = assembly.graph.registry();\n const successors = new Map<string, string[]>();\n for (const edge of assembly.graph.edges()) {\n const definition = registry.require(edge.kind);\n if (!definition.ordering) continue;\n // Orient every ordering edge predecessor -> successor so inverse spellings\n // (blocked_by/blocks) land in one canonical execution-order digraph.\n const [predecessor, successor] =\n (definition.precedence ?? \"source_before_target\") ===\n \"target_before_source\"\n ? [edge.target, edge.source]\n : [edge.source, edge.target];\n const adjacent = successors.get(predecessor);\n if (adjacent) adjacent.push(successor);\n else successors.set(predecessor, [successor]);\n }\n for (const adjacent of successors.values())\n adjacent.sort((left, right) => left.localeCompare(right));\n return successors;\n}\n\n/** Register one newly discovered Tarjan node. */\nfunction registerTarjanNode(node: string, state: TarjanState): void {\n state.indexes.set(node, state.nextIndex);\n state.lowLinks.set(node, state.nextIndex);\n state.nextIndex += 1;\n state.stack.push(node);\n state.onStack.add(node);\n}\n\n/** Visit one pending successor, returning whether the frame had work left. */\nfunction visitNextTarjanNeighbor(\n frame: TarjanFrame,\n frames: TarjanFrame[],\n successors: Map<string, string[]>,\n state: TarjanState,\n): boolean {\n const neighbors = successors.get(frame.node) ?? [];\n if (frame.neighborIndex >= neighbors.length) return false;\n const neighbor = neighbors[frame.neighborIndex]!;\n frame.neighborIndex += 1;\n if (!state.indexes.has(neighbor)) {\n registerTarjanNode(neighbor, state);\n frames.push({ node: neighbor, neighborIndex: 0 });\n } else if (state.onStack.has(neighbor)) {\n state.lowLinks.set(\n frame.node,\n Math.min(state.lowLinks.get(frame.node)!, state.indexes.get(neighbor)!),\n );\n }\n return true;\n}\n\n/** Complete one Tarjan frame and emit its component when it is a root. */\nfunction completeTarjanFrame(\n frame: TarjanFrame,\n frames: TarjanFrame[],\n successors: Map<string, string[]>,\n state: TarjanState,\n): void {\n frames.pop();\n const parent = frames.at(-1);\n if (parent)\n state.lowLinks.set(\n parent.node,\n Math.min(\n state.lowLinks.get(parent.node)!,\n state.lowLinks.get(frame.node)!,\n ),\n );\n if (state.lowLinks.get(frame.node) !== state.indexes.get(frame.node)) return;\n const component: string[] = [];\n while (true) {\n const member = state.stack.pop()!;\n state.onStack.delete(member);\n component.push(member);\n if (member === frame.node) break;\n }\n if (\n component.length > 1 ||\n (component.length === 1 &&\n successors.get(component[0]!)?.includes(component[0]!))\n )\n state.components.push(\n component.sort((left, right) => left.localeCompare(right)),\n );\n}\n\n/**\n * Enumerate strongly connected components with more than one member (or a\n * self-loop) over an ordering-only successor digraph using an iterative Tarjan\n * traversal. Only order-bearing kinds should participate: associative kinds\n * such as `related` cannot create execution-order contradictions and stay out\n * of cycle analysis by policy. Exported so incremental consumers (mutation\n * advisories) share one cycle semantics with the workspace audit.\n */\nexport function collectOrderingCycles(\n successors: Map<string, string[]>,\n): string[][] {\n const state: TarjanState = {\n indexes: new Map(),\n lowLinks: new Map(),\n onStack: new Set(),\n stack: [],\n components: [],\n nextIndex: 0,\n };\n const roots = [...successors.keys()].sort((left, right) =>\n left.localeCompare(right),\n );\n for (const root of roots) {\n if (state.indexes.has(root)) continue;\n // Explicit frame stack keeps the traversal safe on deep dependency chains.\n const frames: TarjanFrame[] = [{ node: root, neighborIndex: 0 }];\n registerTarjanNode(root, state);\n while (frames.length > 0) {\n const frame = frames.at(-1)!;\n if (visitNextTarjanNeighbor(frame, frames, successors, state)) continue;\n completeTarjanFrame(frame, frames, successors, state);\n }\n }\n return state.components.sort((left, right) =>\n left[0]!.localeCompare(right[0]!),\n );\n}\n\n/** Format one dangling reference as a compact deterministic evidence string. */\nfunction formatDanglingReference(reference: {\n holder_id: string;\n target_id: string;\n kind: string;\n}): string {\n return `${reference.holder_id} -> ${reference.target_id} (${reference.kind})`;\n}\n\n/** Append one finding only when its subject collection is non-empty. */\nfunction appendFinding(\n findings: RelationshipAuditFinding[],\n subjects: readonly string[],\n maxSampleSize: number,\n code: RelationshipAuditFindingCode,\n severity: RelationshipAuditSeverity,\n policy: string,\n describe: (count: number) => string,\n remediation: string,\n): void {\n if (subjects.length === 0) return;\n findings.push(\n buildFinding(\n code,\n severity,\n policy,\n describe,\n subjects,\n maxSampleSize,\n remediation,\n ),\n );\n}\n\n/** Collect dangling-reference and retired-sentinel governance findings. */\nfunction collectIntegrityFindings(\n assembly: WorkspaceRelationshipAssembly,\n isTerminal: (status: string) => boolean,\n maxSampleSize: number,\n): RelationshipAuditFinding[] {\n const findings: RelationshipAuditFinding[] = [];\n const references = [\n ...assembly.dangling.active,\n ...assembly.dangling.legacy_terminal,\n ].filter((reference) => !reference.no_active_blocker_sentinel);\n appendFinding(\n findings,\n references\n .filter((reference) => !isTerminal(reference.holder_status))\n .map(formatDanglingReference),\n maxSampleSize,\n \"missing_reference_active\",\n \"error\",\n \"Active items must not reference absent targets; missing prerequisites distort scheduling.\",\n (count) => `${count} active dangling reference(s) to absent items`,\n \"Restore or re-create the referenced item, or remove/retype the reference on the holder.\",\n );\n appendFinding(\n findings,\n references\n .filter((reference) => isTerminal(reference.holder_status))\n .map(formatDanglingReference),\n maxSampleSize,\n \"missing_reference_terminal\",\n \"info\",\n \"Terminal items may retain historical references, but absent targets remain unexplainable context.\",\n (count) => `${count} terminal dangling reference(s) to absent items`,\n \"Leave as history debt or clean up in a dedicated changelog-safe closed-item batch.\",\n );\n appendFinding(\n findings,\n assembly.dangling.no_active_blocker_sentinels.map(formatDanglingReference),\n maxSampleSize,\n \"legacy_no_blocker_sentinel\",\n \"info\",\n \"The pre-structured-dependency no-active-blocker sentinel is retired; real edges carry blocker state.\",\n (count) => `${count} legacy no-active-blocker sentinel reference(s)`,\n \"Delete the sentinel reference; blocker state is derived from blocked_by edges.\",\n );\n return findings;\n}\n\n/** Decide whether one audited node still participates in active scheduling. */\nfunction isActiveAuditMember(\n member: string,\n nodeStates: Map<string, AuditNodeState>,\n): boolean {\n const state = nodeStates.get(member);\n // A trimmed or custom assembly may omit a member's details. Treat that\n // unknown lifecycle conservatively as active so contradictions are never\n // silently downgraded to legacy history debt.\n if (!state) return true;\n return !state.terminal;\n}\n\n/** Collect ordering-cycle and lifecycle-block governance findings. */\nfunction collectOrderingFindings(\n assembly: WorkspaceRelationshipAssembly,\n nodeStates: Map<string, AuditNodeState>,\n isBlocked: (status: string) => boolean,\n maxSampleSize: number,\n): RelationshipAuditFinding[] {\n const findings: RelationshipAuditFinding[] = [];\n const orderingAdjacency = buildOrderingAdjacency(assembly);\n for (const cycle of collectOrderingCycles(orderingAdjacency)) {\n // A cycle whose members are all terminal is a historical contradiction:\n // it cannot make live work unschedulable, and \"repairing\" it would touch\n // closed items (changelog drag), so it downgrades to informational debt.\n const active = cycle.some((member) =>\n isActiveAuditMember(member, nodeStates),\n );\n findings.push(\n active\n ? buildFinding(\n \"ordering_cycle\",\n \"error\",\n \"Order-bearing relationship kinds must stay acyclic; a cycle makes every member unschedulable.\",\n (count) => `execution-order cycle across ${count} item(s)`,\n cycle,\n maxSampleSize,\n \"Remove or retype one ordering edge inside the cycle, or split the work so precedence is linear.\",\n )\n : buildFinding(\n \"legacy_ordering_cycle\",\n \"info\",\n \"Ordering cycles between exclusively terminal items are historical contradictions with no scheduling effect.\",\n (count) =>\n `terminal-only execution-order cycle across ${count} item(s)`,\n cycle,\n maxSampleSize,\n \"Leave as history debt, or clean up in a dedicated changelog-safe closed-item batch; never repair closed items ad hoc.\",\n ),\n );\n }\n const predecessorsByNode = new Map<string, string[]>();\n for (const [predecessor, adjacent] of orderingAdjacency)\n for (const successor of adjacent) {\n const predecessors = predecessorsByNode.get(successor);\n if (predecessors) predecessors.push(predecessor);\n else predecessorsByNode.set(successor, [predecessor]);\n }\n const staleLifecycleBlocks = [...nodeStates.values()]\n .filter(\n (state) =>\n !state.missing &&\n !state.terminal &&\n isBlocked(state.status) &&\n !(predecessorsByNode.get(state.id) ?? []).some((predecessor) => {\n const predecessorState = nodeStates.get(predecessor);\n // A trimmed/custom assembly may omit predecessor details. Treat that\n // unknown state conservatively as potentially open instead of\n // falsely declaring the lifecycle block stale.\n return predecessorState === undefined || !predecessorState.terminal;\n }),\n )\n .map((state) => state.id);\n appendFinding(\n findings,\n staleLifecycleBlocks,\n maxSampleSize,\n \"stale_lifecycle_block\",\n \"warning\",\n \"A blocked lifecycle status must be backed by at least one open ordering predecessor.\",\n (count) => `${count} status-blocked item(s) with no open blocker edge`,\n \"Re-open the missing prerequisite as an edge, or move the item back to an active status.\",\n );\n return findings;\n}\n\n/** One duplicate-edge group in semantic orientation with its stored spellings. */\nexport interface DuplicateRelationshipEdgeGroup {\n /** Semantic tail node shared by every stored spelling. */\n from: string;\n /** Semantic head node shared by every stored spelling. */\n to: string;\n /** Stored parallel edges sorted by kind. */\n edges: RelationshipEdge[];\n}\n\n/** Format one duplicate-edge group as a compact deterministic evidence string. */\nexport function formatDuplicateEdgeGroup(\n group: DuplicateRelationshipEdgeGroup,\n): string {\n const kinds = group.edges\n .map((edge) => edge.kind)\n .sort((left, right) => left.localeCompare(right));\n return `${group.from} -> ${group.to} (${kinds.join(\" + \")})`;\n}\n\n/**\n * Collect the groups of parallel same-family stored edges over the directed\n * ordering and hierarchy families. Each family joins a kind with its inverse\n * spelling in semantic orientation, so a reciprocal pair such as\n * `A blocked_by B` plus `B blocks A` collapses onto one oriented endpoint\n * pair. Only groups holding at least two stored spellings are returned, in\n * deterministic orientation order with per-group edges sorted by kind, source,\n * then target — the exact stored identities remediation planning targets.\n */\nexport function collectDuplicateRelationshipEdgeGroups(\n assembly: WorkspaceRelationshipAssembly,\n): DuplicateRelationshipEdgeGroup[] {\n const registry = assembly.graph.registry();\n const groups = new Map<string, DuplicateRelationshipEdgeGroup>();\n for (const edge of assembly.graph.edges()) {\n const definition = registry.require(edge.kind);\n if (!isTransitiveKind(definition)) continue;\n const oriented = orientTransitiveEdge(edge, definition);\n if (oriented.from === oriented.to) continue;\n const key = `${transitiveFamilyKey(definition)}::${oriented.from}::${oriented.to}`;\n const group = groups.get(key);\n if (group) group.edges.push(edge);\n else groups.set(key, { ...oriented, edges: [edge] });\n }\n const duplicated = [...groups.values()].filter(\n (group) => group.edges.length >= 2,\n );\n // Within one oriented group every stored spelling has a distinct kind: a\n // same-kind restatement of the same oriented pair would carry identical\n // endpoints and is deduplicated by edge identity during graph construction.\n for (const group of duplicated)\n group.edges.sort((left, right) => left.kind.localeCompare(right.kind));\n return duplicated.sort(\n (left, right) =>\n left.from.localeCompare(right.from) || left.to.localeCompare(right.to),\n );\n}\n\n/**\n * Collect duplicate stored-edge findings from the oriented duplicate groups.\n * Transitive-reduction redundancy analysis deliberately skips the direct edge\n * under test, so these exact parallels are invisible there and this is the\n * only surface that reports them.\n */\nfunction collectDuplicateEdgeFindings(\n assembly: WorkspaceRelationshipAssembly,\n nodeStates: Map<string, AuditNodeState>,\n maxSampleSize: number,\n): RelationshipAuditFinding[] {\n const active: string[] = [];\n const legacy: string[] = [];\n for (const group of collectDuplicateRelationshipEdgeGroups(assembly)) {\n const subjects =\n isActiveAuditMember(group.from, nodeStates) ||\n isActiveAuditMember(group.to, nodeStates)\n ? active\n : legacy;\n subjects.push(formatDuplicateEdgeGroup(group));\n }\n const findings: RelationshipAuditFinding[] = [];\n appendFinding(\n findings,\n active,\n maxSampleSize,\n \"duplicate_edge\",\n \"info\",\n \"One semantic relationship should be stored once; parallel same-family spellings (reciprocal inverse pairs included) add no information and skew degree metrics.\",\n (count) => `${count} duplicated relationship(s) between active endpoints`,\n \"Remove all but one stored spelling of the relationship; keep the canonical direction the holder declared first.\",\n );\n appendFinding(\n findings,\n legacy,\n maxSampleSize,\n \"legacy_duplicate_edge\",\n \"info\",\n \"Duplicated spellings between exclusively terminal items are historical noise with no scheduling effect.\",\n (count) => `${count} duplicated relationship(s) between terminal endpoints`,\n \"Leave as history debt or clean up in a dedicated changelog-safe closed-item batch.\",\n );\n return findings;\n}\n\n/**\n * Collect storage-integrity findings for raw dependency rows whose exact\n * identity is stored more than once on one holder. Graph edge-identity dedup\n * hides these from every assembled-graph surface (duplicate_edge only covers\n * cross-spelling parallels), so the audit reports them from the pre-assembly\n * scan carried on the assembly.\n */\nfunction collectDuplicateRowFindings(\n assembly: WorkspaceRelationshipAssembly,\n maxSampleSize: number,\n): RelationshipAuditFinding[] {\n const active: string[] = [];\n const legacy: string[] = [];\n // Public/JSON-parsed assemblies produced before duplicate-row governance may omit this field.\n for (const row of assembly.duplicateRows ?? []) {\n (row.legacy_terminal ? legacy : active).push(\n `${row.holder_id} -> ${row.target_id} (${row.kind} x${row.occurrences})`,\n );\n }\n const findings: RelationshipAuditFinding[] = [];\n appendFinding(\n findings,\n active,\n maxSampleSize,\n \"duplicate_dependency_row\",\n \"warning\",\n \"One dependency row must be stored once per holder; identical repeated rows are a storage-layer defect invisible to the assembled graph.\",\n (count) =>\n `${count} exactly duplicated stored dependency row(s) on active holder(s)`,\n \"Remove the repeated rows so the dependency is stored exactly once; graph semantics are unchanged.\",\n );\n appendFinding(\n findings,\n legacy,\n maxSampleSize,\n \"legacy_duplicate_dependency_row\",\n \"info\",\n \"Identical repeated dependency rows on terminal holders are historical storage noise with no scheduling effect.\",\n (count) =>\n `${count} exactly duplicated stored dependency row(s) on terminal holder(s)`,\n \"Leave as history debt or clean up in a dedicated changelog-safe closed-item batch.\",\n );\n return findings;\n}\n\n/** Compute structural coverage metrics and coverage-policy findings. */\n/** Mutable coverage tallies accumulated across active graph nodes. */\ninterface CoverageTallies {\n /** Active node count. */\n active: number;\n /** Missing placeholder count. */\n missing: number;\n /** Isolated active node count. */\n isolated: number;\n /** Degree-at-most-one active node count, isolates included. */\n degreeLeqOne: number;\n /** Non-exempt isolate finding subjects. */\n isolates: string[];\n /** Non-exempt single-edge finding subjects. */\n sparse: string[];\n /** Per-type connectivity tallies. */\n byType: Map<string, RelationshipCoverageTypeProfile>;\n}\n\n/** Fold one active node's degree into the aggregate and per-type coverage tallies. */\nfunction tallyActiveCoverageNode(\n tallies: CoverageTallies,\n state: AuditNodeState,\n degree: number,\n exemptIsolates: Set<string>,\n isolateExemptTypes: Set<string>,\n): void {\n tallies.active += 1;\n const typeKey = state.type ?? \"(untyped)\";\n let typeProfile = tallies.byType.get(typeKey);\n if (!typeProfile) {\n typeProfile = { active: 0, isolated: 0, degree_leq_one: 0 };\n tallies.byType.set(typeKey, typeProfile);\n }\n typeProfile.active += 1;\n if (degree > 1) return;\n tallies.degreeLeqOne += 1;\n typeProfile.degree_leq_one += 1;\n if (degree === 0) {\n tallies.isolated += 1;\n typeProfile.isolated += 1;\n }\n if (\n exemptIsolates.has(state.id.toLowerCase()) ||\n isolateExemptTypes.has(typeKey.toLowerCase())\n )\n return;\n if (degree === 0) tallies.isolates.push(state.id);\n else tallies.sparse.push(state.id);\n}\n\nfunction collectCoverageReport(\n assembly: WorkspaceRelationshipAssembly,\n nodeStates: Map<string, AuditNodeState>,\n exemptIsolates: Set<string>,\n isolateExemptTypes: Set<string>,\n maxSampleSize: number,\n edgesByKind: Record<string, number>,\n): RelationshipAuditReport {\n const tallies: CoverageTallies = {\n active: 0,\n missing: 0,\n isolated: 0,\n degreeLeqOne: 0,\n isolates: [],\n sparse: [],\n byType: new Map(),\n };\n for (const id of assembly.graph.nodes()) {\n const state = nodeStates.get(id);\n /* c8 ignore next -- every graph node originates from assembly details by construction */\n if (!state) continue;\n if (state.missing) {\n tallies.missing += 1;\n continue;\n }\n if (state.terminal) continue;\n tallyActiveCoverageNode(\n tallies,\n state,\n assembly.graph.incidentEdges(id).length,\n exemptIsolates,\n isolateExemptTypes,\n );\n }\n const { isolates, sparse } = tallies;\n const findings: RelationshipAuditFinding[] = [];\n appendFinding(\n findings,\n isolates,\n maxSampleSize,\n \"isolated_active_node\",\n \"warning\",\n \"Active work should be reachable from the graph unless explicitly declared a valid isolate.\",\n (count) => `${count} active item(s) with no relationships`,\n \"Link the item to its parent, prerequisite, or origin — or register it as an exempt isolate.\",\n );\n appendFinding(\n findings,\n sparse,\n maxSampleSize,\n \"sparse_active_node\",\n \"info\",\n \"Active items with a single edge often miss an honest semantic partner; sparse is not automatically defective.\",\n (count) => `${count} active item(s) with exactly one relationship`,\n \"Investigate for an honest second edge (story->task, defect family, cross-epic complement); do not fabricate one.\",\n );\n return {\n findings,\n profile: {\n nodes: assembly.graph.nodes().length,\n edges: assembly.graph.edges().length,\n edges_by_kind: Object.fromEntries(\n Object.entries(edgesByKind).sort(([left], [right]) =>\n left.localeCompare(right),\n ),\n ),\n active_nodes: tallies.active,\n missing_nodes: tallies.missing,\n isolated_active_nodes: tallies.isolated,\n degree_leq_one_active_nodes: tallies.degreeLeqOne,\n coverage_by_type: Object.fromEntries(\n [...tallies.byType.entries()].sort(([left], [right]) =>\n left < right ? -1 : 1,\n ),\n ),\n },\n };\n}\n\n/**\n * Audit one assembled workspace relationship graph against the shared\n * governance policy and return deterministic machine-readable findings plus a\n * structural coverage profile.\n *\n * The audit is read-only and never proposes inventing an edge: integrity\n * findings report evidence for investigation, coverage findings honor explicit\n * isolate exemptions, and cycle findings enumerate the strongly connected\n * members so callers can decide which edge to retype, remove, or waive.\n */\nexport function auditWorkspaceRelationshipGraph(\n assembly: WorkspaceRelationshipAssembly,\n options: RelationshipAuditOptions = {},\n): RelationshipAuditReport {\n const isTerminal =\n options.isTerminal ??\n ((status: string) => status === \"closed\" || status === \"canceled\");\n const isBlocked =\n options.isBlocked ?? ((status: string) => status === \"blocked\");\n const maxSampleSize = options.maxSampleSize ?? DEFAULT_MAX_SAMPLE_SIZE;\n if (!Number.isInteger(maxSampleSize) || maxSampleSize < 1)\n throw new TypeError(\n `Invalid audit sample bound: ${String(options.maxSampleSize)}`,\n );\n const exemptIsolates = new Set(\n (options.exemptIsolates ?? [])\n .filter((id): id is string => typeof id === \"string\")\n .map((id) => id.trim().toLowerCase()),\n );\n const isolateExemptTypes = new Set(\n (options.isolateExemptTypes ?? [])\n .filter((type): type is string => typeof type === \"string\")\n .map((type) => type.trim().toLowerCase()),\n );\n const nodeStates = new Map<string, AuditNodeState>(\n assembly.details.map((detail) => [\n detail.id,\n {\n id: detail.id,\n status: detail.status,\n missing: assembly.missingIdSet.has(detail.id.toLowerCase()),\n terminal: isTerminal(detail.status),\n ...(detail.type === undefined ? {} : { type: detail.type }),\n },\n ]),\n );\n options.signal?.throwIfAborted();\n\n const edgesByKind: Record<string, number> = {};\n for (const edge of assembly.graph.edges())\n edgesByKind[edge.kind] = (edgesByKind[edge.kind] ?? 0) + 1;\n const findings = collectIntegrityFindings(\n assembly,\n isTerminal,\n maxSampleSize,\n );\n options.signal?.throwIfAborted();\n findings.push(\n ...collectOrderingFindings(assembly, nodeStates, isBlocked, maxSampleSize),\n );\n options.signal?.throwIfAborted();\n findings.push(\n ...collectDuplicateEdgeFindings(assembly, nodeStates, maxSampleSize),\n ...collectDuplicateRowFindings(assembly, maxSampleSize),\n );\n options.signal?.throwIfAborted();\n const coverage = collectCoverageReport(\n assembly,\n nodeStates,\n exemptIsolates,\n isolateExemptTypes,\n maxSampleSize,\n edgesByKind,\n );\n findings.push(...coverage.findings);\n\n findings.sort(\n (left, right) =>\n SEVERITY_RANK[left.severity] - SEVERITY_RANK[right.severity] ||\n left.code.localeCompare(right.code) ||\n left.sample[0]!.localeCompare(right.sample[0]!),\n );\n return {\n findings,\n profile: coverage.profile,\n };\n}\n\n/** One persisted point-in-time audit census used for temporal comparison. */\nexport interface RelationshipAuditSnapshot {\n /** ISO timestamp the snapshot was taken at. */\n saved_at: string;\n /** Workspace graph fingerprint of the audited item snapshot. */\n fingerprint: string;\n /** Affected-subject counts keyed by finding code at snapshot time. */\n affected_subjects_by_code: Record<string, number>;\n /** Structural coverage profile at snapshot time. */\n profile: RelationshipCoverageProfile;\n}\n\n/** Signed change between two audit snapshots; zero-change keys are dropped. */\nexport interface RelationshipAuditDelta {\n /** ISO timestamp of the baseline snapshot the delta is measured against. */\n baseline_saved_at: string;\n /** Whether both snapshots audited the identical workspace fingerprint. */\n same_snapshot: boolean;\n /** Signed affected-subject deltas keyed by finding code. */\n affected_subjects_by_code: Record<string, number>;\n /** Signed structural profile deltas. */\n profile: {\n /** Node-count change including missing placeholders. */\n nodes: number;\n /** Deduplicated edge-count change. */\n edges: number;\n /** Active-node-count change. */\n active_nodes: number;\n /** Missing-placeholder-count change. */\n missing_nodes: number;\n /** Isolated-active-node-count change. */\n isolated_active_nodes: number;\n /** Degree-at-most-one active-node-count change. */\n degree_leq_one_active_nodes: number;\n /** Signed per-kind edge-count deltas; unchanged kinds are dropped. */\n edges_by_kind: Record<string, number>;\n /** Signed per-type coverage deltas; unchanged types are dropped. */\n coverage_by_type: Record<string, RelationshipCoverageTypeProfile>;\n };\n}\n\n/** Subtract two count records, keeping only non-zero signed deltas in sorted key order. */\nfunction diffCountRecords(\n baseline: Record<string, number>,\n current: Record<string, number>,\n): Record<string, number> {\n const keys = [\n ...new Set([...Object.keys(baseline), ...Object.keys(current)]),\n ].sort();\n const deltas: Record<string, number> = {};\n for (const key of keys) {\n const delta = (current[key] ?? 0) - (baseline[key] ?? 0);\n if (delta !== 0) deltas[key] = delta;\n }\n return deltas;\n}\n\n/** Read per-type coverage defensively from current or legacy runtime snapshots. */\nfunction readSnapshotCoverageByType(\n snapshot: RelationshipAuditSnapshot,\n): Record<string, RelationshipCoverageTypeProfile> {\n return snapshot.profile.coverage_by_type ?? {};\n}\n\n/**\n * Compare two point-in-time audit snapshots and return the signed change in\n * findings and structural coverage. This is the temporal primitive behind\n * change-since-baseline audit reporting: agents track census drift across\n * sessions without re-deriving or storing full finding collections.\n */\nexport function diffRelationshipAuditSnapshots(\n baseline: RelationshipAuditSnapshot,\n current: RelationshipAuditSnapshot,\n): RelationshipAuditDelta {\n const coverageByType: Record<string, RelationshipCoverageTypeProfile> = {};\n // Public SDK callers may compare legacy or JSON-decoded snapshots created\n // before per-type coverage was added, even though current typed snapshots\n // always carry this field.\n const baselineCoverageByType = readSnapshotCoverageByType(baseline);\n const currentCoverageByType = readSnapshotCoverageByType(current);\n const typeKeys = [\n ...new Set([\n ...Object.keys(baselineCoverageByType),\n ...Object.keys(currentCoverageByType),\n ]),\n ].sort();\n for (const type of typeKeys) {\n const before = baselineCoverageByType[type];\n const after = currentCoverageByType[type];\n const delta = {\n active: (after?.active ?? 0) - (before?.active ?? 0),\n isolated: (after?.isolated ?? 0) - (before?.isolated ?? 0),\n degree_leq_one:\n (after?.degree_leq_one ?? 0) - (before?.degree_leq_one ?? 0),\n };\n if (Object.values(delta).some((value) => value !== 0))\n coverageByType[type] = delta;\n }\n return {\n baseline_saved_at: baseline.saved_at,\n same_snapshot: baseline.fingerprint === current.fingerprint,\n affected_subjects_by_code: diffCountRecords(\n baseline.affected_subjects_by_code,\n current.affected_subjects_by_code,\n ),\n profile: {\n nodes: current.profile.nodes - baseline.profile.nodes,\n edges: current.profile.edges - baseline.profile.edges,\n active_nodes:\n current.profile.active_nodes - baseline.profile.active_nodes,\n missing_nodes:\n current.profile.missing_nodes - baseline.profile.missing_nodes,\n isolated_active_nodes:\n current.profile.isolated_active_nodes -\n baseline.profile.isolated_active_nodes,\n degree_leq_one_active_nodes:\n current.profile.degree_leq_one_active_nodes -\n baseline.profile.degree_leq_one_active_nodes,\n edges_by_kind: diffCountRecords(\n baseline.profile.edges_by_kind,\n current.profile.edges_by_kind,\n ),\n coverage_by_type: coverageByType,\n },\n };\n}\n"],"names":[],"mappings":"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","debugId":"e233b53a-3a7c-5fb5-a544-a0261aed1192"}
|
|
@@ -1,8 +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]="
|
|
3
|
-
import {
|
|
4
|
-
refreshMergeAttributeFenceIfInstalled
|
|
5
|
-
} from "./chunk-CFHAODHQ.js";
|
|
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]="072ffd55-4bbd-5829-b84e-0747490f43a9")}catch(e){}}();
|
|
6
3
|
import {
|
|
7
4
|
BUILTIN_STATUS_IDS,
|
|
8
5
|
TYPE_PRESET_NAMES,
|
|
@@ -59,8 +56,309 @@ import {
|
|
|
59
56
|
writeFileAtomic
|
|
60
57
|
} from "./chunk-HYW67VJ5.js";
|
|
61
58
|
|
|
62
|
-
// dist/sdk/
|
|
59
|
+
// dist/sdk/workspace.js
|
|
60
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
63
61
|
import path from "node:path";
|
|
62
|
+
var PM_GITIGNORE_START = "# pm-cli:runtime-cache:start";
|
|
63
|
+
var PM_GITIGNORE_END = "# pm-cli:runtime-cache:end";
|
|
64
|
+
var PM_GITIGNORE_DEFAULT_TRACKER_ROOT = ".agents/pm";
|
|
65
|
+
var PM_GITIGNORE_RUNTIME_DIRECTORIES = [
|
|
66
|
+
"runtime/",
|
|
67
|
+
"search/",
|
|
68
|
+
"locks/",
|
|
69
|
+
"transactions/",
|
|
70
|
+
"checkpoints/"
|
|
71
|
+
];
|
|
72
|
+
function normalizeTrackerRelativeRoot(trackerRelativeRoot) {
|
|
73
|
+
return trackerRelativeRoot.replaceAll("\\", "/").replace(/^\.\/+/, "").replace(/\/+$/, "");
|
|
74
|
+
}
|
|
75
|
+
function isPathOutsideRoot(relativePath) {
|
|
76
|
+
const normalized = relativePath.replaceAll("\\", "/");
|
|
77
|
+
return path.isAbsolute(relativePath) || normalized === ".." || normalized.startsWith("../");
|
|
78
|
+
}
|
|
79
|
+
function getPmGitignoreBlock(trackerRelativeRoot = PM_GITIGNORE_DEFAULT_TRACKER_ROOT) {
|
|
80
|
+
const root = normalizeTrackerRelativeRoot(trackerRelativeRoot);
|
|
81
|
+
return [
|
|
82
|
+
PM_GITIGNORE_START,
|
|
83
|
+
...PM_GITIGNORE_RUNTIME_DIRECTORIES.map((directory) => `${root}/${directory}`),
|
|
84
|
+
PM_GITIGNORE_END
|
|
85
|
+
].join("\n");
|
|
86
|
+
}
|
|
87
|
+
async function ensurePmGitignore(workspaceRoot, options = {}) {
|
|
88
|
+
const gitignorePath = path.join(workspaceRoot, ".gitignore");
|
|
89
|
+
let trackerRelativeRoot = PM_GITIGNORE_DEFAULT_TRACKER_ROOT;
|
|
90
|
+
if (options.pmRoot !== void 0) {
|
|
91
|
+
const relative = normalizeTrackerRelativeRoot(path.relative(path.resolve(workspaceRoot), path.resolve(options.pmRoot)));
|
|
92
|
+
if (isPathOutsideRoot(relative)) {
|
|
93
|
+
return { path: gitignorePath, changed: false };
|
|
94
|
+
}
|
|
95
|
+
if (relative.length > 0) {
|
|
96
|
+
trackerRelativeRoot = relative;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
let current = "";
|
|
100
|
+
try {
|
|
101
|
+
current = await readFile(gitignorePath, "utf8");
|
|
102
|
+
} catch (error) {
|
|
103
|
+
if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const start = current.indexOf(PM_GITIGNORE_START);
|
|
108
|
+
const end = current.indexOf(PM_GITIGNORE_END);
|
|
109
|
+
const withoutManagedBlock = start >= 0 && end >= start ? `${current.slice(0, start)}${current.slice(end + PM_GITIGNORE_END.length)}` : current;
|
|
110
|
+
const prefix = withoutManagedBlock.trimEnd();
|
|
111
|
+
const next = `${prefix.length > 0 ? `${prefix}
|
|
112
|
+
|
|
113
|
+
` : ""}${getPmGitignoreBlock(trackerRelativeRoot)}
|
|
114
|
+
`;
|
|
115
|
+
if (next === current) {
|
|
116
|
+
return { path: gitignorePath, changed: false };
|
|
117
|
+
}
|
|
118
|
+
await writeFile(gitignorePath, next, "utf8");
|
|
119
|
+
return { path: gitignorePath, changed: true };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// dist/sdk/merge/install.js
|
|
123
|
+
import { readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
124
|
+
import { execFile } from "node:child_process";
|
|
125
|
+
import path2 from "node:path";
|
|
126
|
+
import { promisify } from "node:util";
|
|
127
|
+
var execFileAsync = promisify(execFile);
|
|
128
|
+
var PM_GITATTRIBUTES_START = "# pm-cli:merge-drivers:start";
|
|
129
|
+
var PM_GITATTRIBUTES_END = "# pm-cli:merge-drivers:end";
|
|
130
|
+
var MERGE_FENCE_LOCK_ID = "merge-fence";
|
|
131
|
+
var MERGE_DRIVER_DEFINITIONS = [
|
|
132
|
+
{
|
|
133
|
+
key: "pm-item-toon",
|
|
134
|
+
name: "pm field-aware TOON item document merge",
|
|
135
|
+
artifact: "item",
|
|
136
|
+
itemPath: "item.toon"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
key: "pm-item-markdown",
|
|
140
|
+
name: "pm field-aware JSON-markdown item document merge",
|
|
141
|
+
artifact: "item",
|
|
142
|
+
itemPath: "item.md"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
key: "pm-history",
|
|
146
|
+
name: "pm append-only history stream merge",
|
|
147
|
+
artifact: "history",
|
|
148
|
+
itemPath: void 0
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
key: "pm-relationship",
|
|
152
|
+
name: "pm append-only relationship event store merge",
|
|
153
|
+
artifact: "relationship",
|
|
154
|
+
itemPath: void 0
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
key: "pm-json",
|
|
158
|
+
name: "pm key-level JSON config merge",
|
|
159
|
+
artifact: "json",
|
|
160
|
+
itemPath: void 0
|
|
161
|
+
}
|
|
162
|
+
];
|
|
163
|
+
async function resolveGitWorkspaceRoot(cwd) {
|
|
164
|
+
try {
|
|
165
|
+
const { stdout } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], { cwd, encoding: "utf8", windowsHide: true, timeout: 1e4 });
|
|
166
|
+
return stdout.trim();
|
|
167
|
+
} catch {
|
|
168
|
+
throw new PmCliError("pm merge install requires a git repository (merge drivers are git configuration).", EXIT_CODE.USAGE);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function toPosixRelative(fromPath, toPath) {
|
|
172
|
+
return path2.relative(fromPath, toPath).replaceAll("\\", "/");
|
|
173
|
+
}
|
|
174
|
+
function quoteGitAttributePattern(value) {
|
|
175
|
+
return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
|
|
176
|
+
}
|
|
177
|
+
function buildMergeAttributePatterns(trackerRelativeRoot, typeFolders) {
|
|
178
|
+
const prefix = trackerRelativeRoot.length > 0 ? `${trackerRelativeRoot}/` : "";
|
|
179
|
+
const patterns = [];
|
|
180
|
+
for (const folder of typeFolders) {
|
|
181
|
+
patterns.push(`${quoteGitAttributePattern(`${prefix}${folder}/*.toon`)} merge=pm-item-toon`);
|
|
182
|
+
patterns.push(`${quoteGitAttributePattern(`${prefix}${folder}/*.md`)} merge=pm-item-markdown`);
|
|
183
|
+
}
|
|
184
|
+
patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.jsonl`)} merge=pm-relationship`);
|
|
185
|
+
patterns.push(`${quoteGitAttributePattern(`${prefix}history/*.jsonl`)} merge=pm-history`);
|
|
186
|
+
patterns.push(`${quoteGitAttributePattern(`${prefix}settings.json`)} merge=pm-json`);
|
|
187
|
+
patterns.push(`${quoteGitAttributePattern(`${prefix}schema/*.json`)} merge=pm-json`);
|
|
188
|
+
return patterns;
|
|
189
|
+
}
|
|
190
|
+
async function reconcileGitattributesBlock(workspaceRoot, patterns, dryRun) {
|
|
191
|
+
const gitattributesPath = path2.join(workspaceRoot, ".gitattributes");
|
|
192
|
+
let current = "";
|
|
193
|
+
try {
|
|
194
|
+
current = await readFile2(gitattributesPath, "utf8");
|
|
195
|
+
} catch (error) {
|
|
196
|
+
if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const block = [
|
|
201
|
+
PM_GITATTRIBUTES_START,
|
|
202
|
+
...patterns,
|
|
203
|
+
PM_GITATTRIBUTES_END
|
|
204
|
+
].join("\n");
|
|
205
|
+
const start = current.indexOf(PM_GITATTRIBUTES_START);
|
|
206
|
+
const end = current.indexOf(PM_GITATTRIBUTES_END);
|
|
207
|
+
const withoutManagedBlock = start >= 0 && end > start ? `${current.slice(0, start)}${current.slice(end + PM_GITATTRIBUTES_END.length)}` : current.replace(PM_GITATTRIBUTES_START, "").replace(PM_GITATTRIBUTES_END, "");
|
|
208
|
+
const prefix = withoutManagedBlock.trimEnd();
|
|
209
|
+
const next = `${prefix.length > 0 ? `${prefix}
|
|
210
|
+
|
|
211
|
+
` : ""}${block}
|
|
212
|
+
`;
|
|
213
|
+
if (next === current) {
|
|
214
|
+
return { path: gitattributesPath, changed: false };
|
|
215
|
+
}
|
|
216
|
+
if (!dryRun) {
|
|
217
|
+
await writeFile2(gitattributesPath, next, "utf8");
|
|
218
|
+
}
|
|
219
|
+
return { path: gitattributesPath, changed: true };
|
|
220
|
+
}
|
|
221
|
+
async function auditMergeAttributeFence(pmRoot, typeFolders) {
|
|
222
|
+
const resolvedRoot = path2.resolve(pmRoot);
|
|
223
|
+
let fenceDirectory = null;
|
|
224
|
+
let fenceContent = "";
|
|
225
|
+
let directory = resolvedRoot;
|
|
226
|
+
for (let depth = 0; depth < 8; depth += 1) {
|
|
227
|
+
const candidate = path2.join(directory, ".gitattributes");
|
|
228
|
+
try {
|
|
229
|
+
const raw = await readFile2(candidate, "utf8");
|
|
230
|
+
if (raw.includes(PM_GITATTRIBUTES_START)) {
|
|
231
|
+
fenceDirectory = directory;
|
|
232
|
+
fenceContent = raw;
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
} catch {
|
|
236
|
+
}
|
|
237
|
+
const parent = path2.dirname(directory);
|
|
238
|
+
if (parent === directory) {
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
directory = parent;
|
|
242
|
+
}
|
|
243
|
+
if (fenceDirectory === null) {
|
|
244
|
+
return { status: "not_installed", missing_patterns: [], stale_patterns: [] };
|
|
245
|
+
}
|
|
246
|
+
const fencePath = path2.join(fenceDirectory, ".gitattributes");
|
|
247
|
+
const start = fenceContent.indexOf(PM_GITATTRIBUTES_START);
|
|
248
|
+
const end = fenceContent.indexOf(PM_GITATTRIBUTES_END);
|
|
249
|
+
const committed = end > start ? fenceContent.slice(start + PM_GITATTRIBUTES_START.length, end).split("\n").map((line) => line.trim()).filter((line) => line.length > 0) : [];
|
|
250
|
+
const expected = buildMergeAttributePatterns(toPosixRelative(fenceDirectory, resolvedRoot), typeFolders);
|
|
251
|
+
const committedSet = new Set(committed);
|
|
252
|
+
const expectedSet = new Set(expected);
|
|
253
|
+
const missing = expected.filter((line) => !committedSet.has(line));
|
|
254
|
+
const stale = committed.filter((line) => !expectedSet.has(line));
|
|
255
|
+
return {
|
|
256
|
+
status: missing.length > 0 || stale.length > 0 ? "drift" : "ok",
|
|
257
|
+
path: fencePath,
|
|
258
|
+
missing_patterns: missing,
|
|
259
|
+
stale_patterns: stale
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
async function refreshMergeAttributeFenceIfInstalled(pmRoot) {
|
|
263
|
+
let workspaceRoot;
|
|
264
|
+
try {
|
|
265
|
+
workspaceRoot = await resolveGitWorkspaceRoot(path2.resolve(pmRoot));
|
|
266
|
+
} catch {
|
|
267
|
+
return { status: "no_git" };
|
|
268
|
+
}
|
|
269
|
+
const trackerRelativeRoot = toPosixRelative(workspaceRoot, path2.resolve(pmRoot));
|
|
270
|
+
const lockSettings = await readSettings(pmRoot);
|
|
271
|
+
const owner = (process.env.PM_AUTHOR ?? lockSettings.author_default).trim();
|
|
272
|
+
const releaseLock = await acquireLock(pmRoot, MERGE_FENCE_LOCK_ID, lockSettings.locks.ttl_seconds, owner.length > 0 ? owner : "unknown", false, resolveGovernanceKnobs(lockSettings).force_required_for_stale_lock, lockSettings.locks.wait_ms);
|
|
273
|
+
try {
|
|
274
|
+
const gitattributesPath = path2.join(workspaceRoot, ".gitattributes");
|
|
275
|
+
let current;
|
|
276
|
+
try {
|
|
277
|
+
current = await readFile2(gitattributesPath, "utf8");
|
|
278
|
+
} catch (error) {
|
|
279
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
280
|
+
return { status: "not_installed", path: gitattributesPath };
|
|
281
|
+
}
|
|
282
|
+
throw error;
|
|
283
|
+
}
|
|
284
|
+
if (!current.includes(PM_GITATTRIBUTES_START)) {
|
|
285
|
+
return { status: "not_installed", path: gitattributesPath };
|
|
286
|
+
}
|
|
287
|
+
const settings = await readSettings(pmRoot);
|
|
288
|
+
const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());
|
|
289
|
+
const typeFolders = [
|
|
290
|
+
...new Set(Object.values(typeRegistry.type_to_folder))
|
|
291
|
+
].sort((left, right) => left.localeCompare(right));
|
|
292
|
+
const outcome = await reconcileGitattributesBlock(workspaceRoot, buildMergeAttributePatterns(trackerRelativeRoot, typeFolders), false);
|
|
293
|
+
return {
|
|
294
|
+
status: outcome.changed ? "refreshed" : "unchanged",
|
|
295
|
+
path: outcome.path
|
|
296
|
+
};
|
|
297
|
+
} finally {
|
|
298
|
+
await releaseLock();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
async function runMergeInstall(options, global) {
|
|
302
|
+
const pmRoot = resolvePmRoot(process.cwd(), global.path);
|
|
303
|
+
if (!await pathExists(getSettingsPath(pmRoot))) {
|
|
304
|
+
throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
|
|
305
|
+
}
|
|
306
|
+
const dryRun = options.dryRun === true;
|
|
307
|
+
const workspaceRoot = await resolveGitWorkspaceRoot(process.cwd());
|
|
308
|
+
const trackerRelativeRoot = toPosixRelative(workspaceRoot, path2.resolve(pmRoot));
|
|
309
|
+
if (isPathOutsideRoot(trackerRelativeRoot)) {
|
|
310
|
+
throw new PmCliError(`Tracker root ${pmRoot} is outside the git repository ${workspaceRoot}; there is nothing to configure for this repository.`, EXIT_CODE.USAGE);
|
|
311
|
+
}
|
|
312
|
+
const settings = await readSettings(pmRoot);
|
|
313
|
+
const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());
|
|
314
|
+
const typeFolders = [
|
|
315
|
+
...new Set(Object.values(typeRegistry.type_to_folder))
|
|
316
|
+
].sort((left, right) => left.localeCompare(right));
|
|
317
|
+
const patterns = buildMergeAttributePatterns(trackerRelativeRoot, typeFolders);
|
|
318
|
+
const gitattributes = await reconcileGitattributesBlock(workspaceRoot, patterns, dryRun);
|
|
319
|
+
const gitConfigEntries = [];
|
|
320
|
+
for (const definition of MERGE_DRIVER_DEFINITIONS) {
|
|
321
|
+
gitConfigEntries.push({
|
|
322
|
+
key: `merge.${definition.key}.name`,
|
|
323
|
+
value: definition.name
|
|
324
|
+
});
|
|
325
|
+
gitConfigEntries.push({
|
|
326
|
+
key: `merge.${definition.key}.driver`,
|
|
327
|
+
value: `pm merge driver ${definition.artifact} "%O" "%A" "%B"${definition.itemPath === void 0 ? "" : ` --item-path ${definition.itemPath}`}`
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
if (!dryRun) {
|
|
331
|
+
for (const entry of gitConfigEntries) {
|
|
332
|
+
await execFileAsync("git", ["config", entry.key, entry.value], {
|
|
333
|
+
cwd: workspaceRoot,
|
|
334
|
+
encoding: "utf8",
|
|
335
|
+
windowsHide: true,
|
|
336
|
+
timeout: 1e4
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return {
|
|
341
|
+
ok: true,
|
|
342
|
+
dry_run: dryRun,
|
|
343
|
+
workspace_root: workspaceRoot,
|
|
344
|
+
gitattributes: {
|
|
345
|
+
path: gitattributes.path,
|
|
346
|
+
changed: gitattributes.changed,
|
|
347
|
+
patterns
|
|
348
|
+
},
|
|
349
|
+
git_config: gitConfigEntries,
|
|
350
|
+
guidance: [
|
|
351
|
+
"Commit .gitattributes so every branch and collaborator shares the merge mapping.",
|
|
352
|
+
'git config is per-clone: each collaborator (and each fresh worktree/clone) runs "pm merge install" once.',
|
|
353
|
+
'After merging branches, run "pm validate" and, if history drift is reported, "pm history-repair --all" to reconcile item state with merged history.',
|
|
354
|
+
"Custom item types registered later refresh this fence automatically (pm schema add-type/remove-type); rerun pm merge install only after out-of-band type-folder edits."
|
|
355
|
+
],
|
|
356
|
+
generated_at: nowIso()
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// dist/sdk/schema.js
|
|
361
|
+
import path3 from "node:path";
|
|
64
362
|
import { mkdir } from "node:fs/promises";
|
|
65
363
|
|
|
66
364
|
// dist/core/schema/type-inference.js
|
|
@@ -346,7 +644,7 @@ function typesPathFor(pmRoot, schema) {
|
|
|
346
644
|
async function ensureTypeFolderScaffold(pmRoot, definitions, warnings, op) {
|
|
347
645
|
for (const definition of definitions) {
|
|
348
646
|
const folder = definition.folder ?? toDefaultFolder(definition.name);
|
|
349
|
-
const target =
|
|
647
|
+
const target = path3.join(pmRoot, folder);
|
|
350
648
|
if (await pathExists(target)) {
|
|
351
649
|
continue;
|
|
352
650
|
}
|
|
@@ -1229,6 +1527,16 @@ var _testOnlySchemaCommand = {
|
|
|
1229
1527
|
};
|
|
1230
1528
|
|
|
1231
1529
|
export {
|
|
1530
|
+
PM_GITIGNORE_START,
|
|
1531
|
+
PM_GITIGNORE_END,
|
|
1532
|
+
getPmGitignoreBlock,
|
|
1533
|
+
ensurePmGitignore,
|
|
1534
|
+
PM_GITATTRIBUTES_START,
|
|
1535
|
+
PM_GITATTRIBUTES_END,
|
|
1536
|
+
buildMergeAttributePatterns,
|
|
1537
|
+
auditMergeAttributeFence,
|
|
1538
|
+
refreshMergeAttributeFenceIfInstalled,
|
|
1539
|
+
runMergeInstall,
|
|
1232
1540
|
SCHEMA_SUBCOMMANDS,
|
|
1233
1541
|
runSchemaAddType,
|
|
1234
1542
|
runSchemaRemoveType,
|
|
@@ -1259,6 +1567,6 @@ export {
|
|
|
1259
1567
|
formatSchemaInferTypesHuman,
|
|
1260
1568
|
_testOnlySchemaCommand
|
|
1261
1569
|
};
|
|
1262
|
-
//# sourceMappingURL=chunk-
|
|
1570
|
+
//# sourceMappingURL=chunk-ICDAQ4TD.js.map
|
|
1263
1571
|
|
|
1264
|
-
//# debugId=
|
|
1572
|
+
//# debugId=072ffd55-4bbd-5829-b84e-0747490f43a9
|