@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.
Files changed (421) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +11 -0
  3. package/dist/cli/commander-usage.d.ts +1 -1
  4. package/dist/cli/commander-usage.js +5 -5
  5. package/dist/cli/commander-usage.js.map +1 -1
  6. package/dist/cli/commands/completion.js +13 -5
  7. package/dist/cli/commands/completion.js.map +1 -1
  8. package/dist/cli/commands/contracts.js +4 -3
  9. package/dist/cli/commands/contracts.js.map +1 -1
  10. package/dist/cli/error-guidance.d.ts +2 -0
  11. package/dist/cli/error-guidance.js +7 -2
  12. package/dist/cli/error-guidance.js.map +1 -1
  13. package/dist/cli/main.d.ts +1 -5
  14. package/dist/cli/main.js +12 -50
  15. package/dist/cli/main.js.map +1 -1
  16. package/dist/cli/register-list-query.js +13 -3
  17. package/dist/cli/register-list-query.js.map +1 -1
  18. package/dist/cli/register-mutation.js +45 -3
  19. package/dist/cli/register-mutation.js.map +1 -1
  20. package/dist/cli/register-structured-mutation.d.ts +14 -0
  21. package/dist/cli/register-structured-mutation.js +62 -0
  22. package/dist/cli/register-structured-mutation.js.map +1 -0
  23. package/dist/cli/registration-helpers.js +5 -3
  24. package/dist/cli/registration-helpers.js.map +1 -1
  25. package/dist/cli-bundle/bundle-manifest.json +280 -296
  26. package/dist/cli-bundle/chunks/{append-E6V54WOQ.js → append-7OVFYR3C.js} +3 -3
  27. package/dist/cli-bundle/chunks/{append-NNJ3EFIT.js → append-DFETHAZL.js} +3 -3
  28. package/dist/cli-bundle/chunks/{chunk-C3KD7U3T.js → chunk-2L6ZP22J.js} +241 -10
  29. package/dist/cli-bundle/chunks/chunk-2L6ZP22J.js.map +7 -0
  30. package/dist/cli-bundle/chunks/{chunk-KZEANWJS.js → chunk-4PUUNQDV.js} +98 -30
  31. package/dist/cli-bundle/chunks/chunk-4PUUNQDV.js.map +7 -0
  32. package/dist/cli-bundle/chunks/{chunk-RDV4ZFYS.js → chunk-4QOB7L7I.js} +7 -9
  33. package/dist/cli-bundle/chunks/{chunk-RDV4ZFYS.js.map → chunk-4QOB7L7I.js.map} +1 -1
  34. package/dist/cli-bundle/chunks/{chunk-3LPFHE3P.js → chunk-4QSQ6XDK.js} +62 -20
  35. package/dist/cli-bundle/chunks/chunk-4QSQ6XDK.js.map +1 -0
  36. package/dist/cli-bundle/chunks/{chunk-QJKL5PHS.js → chunk-7656MAUL.js} +2 -2
  37. package/dist/cli-bundle/chunks/{chunk-3AO5VSDR.js → chunk-7RW4JCU2.js} +328 -6
  38. package/dist/cli-bundle/chunks/chunk-7RW4JCU2.js.map +7 -0
  39. package/dist/cli-bundle/chunks/{chunk-X6K5XTTN.js → chunk-7W2UAXXT.js} +5 -5
  40. package/dist/cli-bundle/chunks/{chunk-SSKOQNMS.js → chunk-ABWCF646.js} +9 -11
  41. package/dist/cli-bundle/chunks/{chunk-SSKOQNMS.js.map → chunk-ABWCF646.js.map} +1 -1
  42. package/dist/cli-bundle/chunks/{chunk-WVA4DVNV.js → chunk-ADBTSVGK.js} +71 -33
  43. package/dist/cli-bundle/chunks/chunk-ADBTSVGK.js.map +7 -0
  44. package/dist/cli-bundle/chunks/{chunk-J4FBIFU6.js → chunk-AELMUANP.js} +12 -6
  45. package/dist/cli-bundle/chunks/chunk-AELMUANP.js.map +1 -0
  46. package/dist/cli-bundle/chunks/{chunk-4F6BWJ4J.js → chunk-AMJPSANK.js} +57 -36
  47. package/dist/cli-bundle/chunks/chunk-AMJPSANK.js.map +7 -0
  48. package/dist/cli-bundle/chunks/{chunk-6VIJ7UA5.js → chunk-AS4SAZ5R.js} +850 -819
  49. package/dist/cli-bundle/chunks/chunk-AS4SAZ5R.js.map +7 -0
  50. package/dist/cli-bundle/chunks/{chunk-SG74J6MV.js → chunk-ATBCUC7Y.js} +574 -5
  51. package/dist/cli-bundle/chunks/chunk-ATBCUC7Y.js.map +1 -0
  52. package/dist/cli-bundle/chunks/{chunk-5OK4UGFV.js → chunk-BXNDKOR2.js} +3 -3
  53. package/dist/cli-bundle/chunks/{chunk-KSPWRNVP.js → chunk-CPX275C6.js} +2 -2
  54. package/dist/cli-bundle/chunks/{chunk-JH2ZSLO3.js → chunk-DZRV2OPA.js} +2 -2
  55. package/dist/cli-bundle/chunks/{chunk-L7BH7IWU.js → chunk-E5XMKOSB.js} +2 -2
  56. package/dist/cli-bundle/chunks/{chunk-CQTQKUUV.js → chunk-EWJWSNRU.js} +3 -3
  57. package/dist/cli-bundle/chunks/{chunk-DAQ45GCS.js → chunk-F2LBF7XJ.js} +22 -15
  58. package/dist/cli-bundle/chunks/chunk-F2LBF7XJ.js.map +7 -0
  59. package/dist/cli-bundle/chunks/{chunk-6XMUURSS.js → chunk-FJIFFBJX.js} +64 -33
  60. package/dist/cli-bundle/chunks/chunk-FJIFFBJX.js.map +1 -0
  61. package/dist/cli-bundle/chunks/{chunk-E7ICD63T.js → chunk-FO6OSVEN.js} +4 -6
  62. package/dist/cli-bundle/chunks/{chunk-E7ICD63T.js.map → chunk-FO6OSVEN.js.map} +1 -1
  63. package/dist/cli-bundle/chunks/{chunk-3MCTMJXI.js → chunk-FPBMLYPI.js} +2 -2
  64. package/dist/cli-bundle/chunks/{chunk-UZDQXNUB.js → chunk-FSE2IKJQ.js} +46 -5
  65. package/dist/cli-bundle/chunks/chunk-FSE2IKJQ.js.map +1 -0
  66. package/dist/cli-bundle/chunks/{chunk-IX677TRO.js → chunk-GKX4NJ7U.js} +8 -10
  67. package/dist/cli-bundle/chunks/{chunk-IX677TRO.js.map → chunk-GKX4NJ7U.js.map} +1 -1
  68. package/dist/cli-bundle/chunks/{chunk-DVDBQA3B.js → chunk-GTK4DTEW.js} +5 -5
  69. package/dist/cli-bundle/chunks/chunk-H7EAER5L.js +974 -0
  70. package/dist/cli-bundle/chunks/chunk-H7EAER5L.js.map +1 -0
  71. package/dist/cli-bundle/chunks/{chunk-5UX66S6U.js → chunk-ICDAQ4TD.js} +316 -8
  72. package/dist/cli-bundle/chunks/chunk-ICDAQ4TD.js.map +1 -0
  73. package/dist/cli-bundle/chunks/{chunk-YQQNAKW3.js → chunk-JFD5LPMI.js} +6 -8
  74. package/dist/cli-bundle/chunks/{chunk-YQQNAKW3.js.map → chunk-JFD5LPMI.js.map} +1 -1
  75. package/dist/cli-bundle/chunks/{chunk-QANSTTC7.js → chunk-JXCW2TI2.js} +6 -8
  76. package/dist/cli-bundle/chunks/{chunk-QANSTTC7.js.map → chunk-JXCW2TI2.js.map} +1 -1
  77. package/dist/cli-bundle/chunks/{chunk-GSJSM5BJ.js → chunk-K36WV5J6.js} +76 -13
  78. package/dist/cli-bundle/chunks/chunk-K36WV5J6.js.map +1 -0
  79. package/dist/cli-bundle/chunks/{chunk-GVI6FAFG.js → chunk-K55VMLSS.js} +7 -5
  80. package/dist/cli-bundle/chunks/chunk-K55VMLSS.js.map +7 -0
  81. package/dist/cli-bundle/chunks/{chunk-GIQSU6S2.js → chunk-KBLZ3AA5.js} +2 -2
  82. package/dist/cli-bundle/chunks/{chunk-XJF7CDNH.js → chunk-KH44WBAT.js} +2 -2
  83. package/dist/cli-bundle/chunks/{chunk-GV2262OF.js → chunk-LAV26CQG.js} +2 -2
  84. package/dist/cli-bundle/chunks/{chunk-VDO2JMD4.js → chunk-LVC72YRD.js} +2 -2
  85. package/dist/cli-bundle/chunks/{chunk-3VY6MIEO.js → chunk-LZYP423P.js} +35 -6
  86. package/dist/cli-bundle/chunks/chunk-LZYP423P.js.map +7 -0
  87. package/dist/cli-bundle/chunks/{chunk-ZYPFOO3L.js → chunk-MATHDCGG.js} +3 -3
  88. package/dist/cli-bundle/chunks/{chunk-OV7MSW3I.js → chunk-MWQ2HC2A.js} +99 -31
  89. package/dist/cli-bundle/chunks/chunk-MWQ2HC2A.js.map +1 -0
  90. package/dist/cli-bundle/chunks/{chunk-NHT3F4WZ.js → chunk-NUF7ROFH.js} +840 -816
  91. package/dist/cli-bundle/chunks/chunk-NUF7ROFH.js.map +1 -0
  92. package/dist/cli-bundle/chunks/{chunk-AOEOYL3S.js → chunk-O4BCOJTZ.js} +3 -3
  93. package/dist/cli-bundle/chunks/{chunk-RJO3YAFM.js → chunk-OCUBRA6D.js} +2 -2
  94. package/dist/cli-bundle/chunks/{chunk-5IZJWSDB.js → chunk-OG5DVFMA.js} +22 -15
  95. package/dist/cli-bundle/chunks/chunk-OG5DVFMA.js.map +1 -0
  96. package/dist/cli-bundle/chunks/{chunk-I577UHC7.js → chunk-OR42SO64.js} +2 -2
  97. package/dist/cli-bundle/chunks/{chunk-ZOJ3LR7O.js → chunk-OY7DMU5P.js} +2 -2
  98. package/dist/cli-bundle/chunks/{chunk-HEWM6CEN.js → chunk-P7MTHPJQ.js} +50 -9
  99. package/dist/cli-bundle/chunks/chunk-P7MTHPJQ.js.map +7 -0
  100. package/dist/cli-bundle/chunks/{chunk-2BO4CA46.js → chunk-PFNHX655.js} +236 -12
  101. package/dist/cli-bundle/chunks/{chunk-2BO4CA46.js.map → chunk-PFNHX655.js.map} +1 -1
  102. package/dist/cli-bundle/chunks/{chunk-ZV2NTVMJ.js → chunk-PONKZPCJ.js} +2 -2
  103. package/dist/cli-bundle/chunks/{chunk-THAOZG4U.js → chunk-PQSEQD6E.js} +8 -6
  104. package/dist/cli-bundle/chunks/chunk-PQSEQD6E.js.map +1 -0
  105. package/dist/cli-bundle/chunks/chunk-PWDEHT3L.js +991 -0
  106. package/dist/cli-bundle/chunks/chunk-PWDEHT3L.js.map +7 -0
  107. package/dist/cli-bundle/chunks/{chunk-UX6SSO2I.js → chunk-PZC2FUOQ.js} +2 -2
  108. package/dist/cli-bundle/chunks/{chunk-WUVEBQW6.js → chunk-QG4GFLQ6.js} +3 -5
  109. package/dist/cli-bundle/chunks/{chunk-WUVEBQW6.js.map → chunk-QG4GFLQ6.js.map} +1 -1
  110. package/dist/cli-bundle/chunks/{chunk-VQIHNHMJ.js → chunk-QIH77CAG.js} +2 -2
  111. package/dist/cli-bundle/chunks/{chunk-R3EWPG4A.js → chunk-QJIKE24M.js} +2 -2
  112. package/dist/cli-bundle/chunks/{chunk-QLZ643FM.js → chunk-QOOTOD3W.js} +10 -12
  113. package/dist/cli-bundle/chunks/{chunk-QLZ643FM.js.map → chunk-QOOTOD3W.js.map} +1 -1
  114. package/dist/cli-bundle/chunks/{chunk-MYSS5H2A.js → chunk-R3P6FZJW.js} +5 -7
  115. package/dist/cli-bundle/chunks/{chunk-MYSS5H2A.js.map → chunk-R3P6FZJW.js.map} +1 -1
  116. package/dist/cli-bundle/chunks/{chunk-G3COA6GS.js → chunk-RNPZYNHS.js} +56 -35
  117. package/dist/cli-bundle/chunks/chunk-RNPZYNHS.js.map +1 -0
  118. package/dist/cli-bundle/chunks/{chunk-T44FMVRL.js → chunk-RPESLSO5.js} +62 -20
  119. package/dist/cli-bundle/chunks/chunk-RPESLSO5.js.map +7 -0
  120. package/dist/cli-bundle/chunks/{chunk-INSTSQNZ.js → chunk-SY4SFZSD.js} +595 -3
  121. package/dist/cli-bundle/chunks/chunk-SY4SFZSD.js.map +7 -0
  122. package/dist/cli-bundle/chunks/{chunk-HB3P4M52.js → chunk-TRSHFPRZ.js} +2 -2
  123. package/dist/cli-bundle/chunks/{chunk-HRW7GF6T.js → chunk-UCBDQI5E.js} +2 -2
  124. package/dist/cli-bundle/chunks/{chunk-4U4Z6AHI.js → chunk-V22ZPOKN.js} +2 -2
  125. package/dist/cli-bundle/chunks/{chunk-JM6YAXTR.js → chunk-VHXHVTUU.js} +2 -2
  126. package/dist/cli-bundle/chunks/{chunk-LPEYZRUR.js → chunk-VJQG4BIM.js} +35 -6
  127. package/dist/cli-bundle/chunks/chunk-VJQG4BIM.js.map +1 -0
  128. package/dist/cli-bundle/chunks/{chunk-D6NXDNP3.js → chunk-VLRGDBLY.js} +2 -2
  129. package/dist/cli-bundle/chunks/{chunk-JAPE62Y5.js → chunk-VNTCM3VW.js} +3 -3
  130. package/dist/cli-bundle/chunks/{chunk-FDHPAVVB.js → chunk-VXOOB6YX.js} +2 -2
  131. package/dist/cli-bundle/chunks/{chunk-GFQP7HAZ.js → chunk-VZIZB6QH.js} +3 -5
  132. package/dist/cli-bundle/chunks/{chunk-GFQP7HAZ.js.map → chunk-VZIZB6QH.js.map} +1 -1
  133. package/dist/cli-bundle/chunks/{chunk-HQ3SB4CN.js → chunk-X3W65QK3.js} +2 -2
  134. package/dist/cli-bundle/chunks/{chunk-RZJLNXFG.js → chunk-XJTABV3X.js} +3 -3
  135. package/dist/cli-bundle/chunks/{chunk-GVT754PX.js → chunk-YCIUJJOD.js} +11 -5
  136. package/dist/cli-bundle/chunks/chunk-YCIUJJOD.js.map +7 -0
  137. package/dist/cli-bundle/chunks/{chunk-IJNK6WW2.js → chunk-Z75ONV25.js} +75 -12
  138. package/dist/cli-bundle/chunks/chunk-Z75ONV25.js.map +7 -0
  139. package/dist/cli-bundle/chunks/{chunk-4L23AGQ7.js → chunk-Z7VWXXJM.js} +5 -7
  140. package/dist/cli-bundle/chunks/{chunk-4L23AGQ7.js.map → chunk-Z7VWXXJM.js.map} +1 -1
  141. package/dist/cli-bundle/chunks/{chunk-YBT7O4KT.js → chunk-ZTVA4KLN.js} +4 -6
  142. package/dist/cli-bundle/chunks/{chunk-YBT7O4KT.js.map → chunk-ZTVA4KLN.js.map} +1 -1
  143. package/dist/cli-bundle/chunks/{chunk-TYHJDFYW.js → chunk-ZVZGXPQ5.js} +2 -2
  144. package/dist/cli-bundle/chunks/{close-many-SDA426VT.js → close-many-5RZXVN4J.js} +5 -6
  145. package/dist/cli-bundle/chunks/{close-many-UTZANOCQ.js → close-many-RZVTUGBG.js} +5 -6
  146. package/dist/cli-bundle/chunks/{comments-LZN6FXXC.js → comments-TPU7QRBL.js} +4 -4
  147. package/dist/cli-bundle/chunks/{comments-VBQ345ND.js → comments-Z4KV6FU3.js} +4 -4
  148. package/dist/cli-bundle/chunks/{create-GG4RBCGC.js → create-EIFBIVNQ.js} +6 -6
  149. package/dist/cli-bundle/chunks/{create-JBC5KUW6.js → create-RGSPN5GD.js} +6 -6
  150. package/dist/cli-bundle/chunks/{deps-FI4O6NQS.js → deps-UH5EQQUY.js} +3 -3
  151. package/dist/cli-bundle/chunks/{deps-DELOO4TL.js → deps-YG7UF3VR.js} +3 -3
  152. package/dist/cli-bundle/chunks/{docs-6Z2MP526.js → docs-G32TK6XS.js} +4 -4
  153. package/dist/cli-bundle/chunks/{docs-2UYBP5D6.js → docs-JWWNRC27.js} +4 -4
  154. package/dist/cli-bundle/chunks/{files-HKEAN5MA.js → files-3H32UQ4K.js} +4 -4
  155. package/dist/cli-bundle/chunks/{files-HEUGSJZL.js → files-4ALMCSKB.js} +4 -4
  156. package/dist/cli-bundle/chunks/{history-compact-7NDVP3PT.js → history-compact-77BT2LUB.js} +3 -4
  157. package/dist/cli-bundle/chunks/{history-compact-65YVN5DB.js → history-compact-VCKGTX64.js} +3 -4
  158. package/dist/cli-bundle/chunks/{history-redact-7YBL4XSG.js → history-redact-LJPZPNFA.js} +2 -3
  159. package/dist/cli-bundle/chunks/{history-redact-IZGNJBU4.js → history-redact-PWTTJ3XS.js} +2 -3
  160. package/dist/cli-bundle/chunks/{history-repair-7M4PYQUH.js → history-repair-I7CBNCV3.js} +5 -6
  161. package/dist/cli-bundle/chunks/{history-repair-GNGETJLI.js → history-repair-YTDZRK5E.js} +5 -6
  162. package/dist/cli-bundle/chunks/{learnings-3YXDRWFT.js → learnings-CYNOICKR.js} +4 -4
  163. package/dist/cli-bundle/chunks/{learnings-ALC6IMNL.js → learnings-KTYW3AL7.js} +4 -4
  164. package/dist/cli-bundle/chunks/{notes-7JMLQ447.js → notes-FGO63FXL.js} +4 -4
  165. package/dist/cli-bundle/chunks/{notes-JFCLTC5C.js → notes-ZERD3KB2.js} +4 -4
  166. package/dist/cli-bundle/chunks/{plan-T3XB3WTK.js → plan-OFJUBIM5.js} +7 -7
  167. package/dist/cli-bundle/chunks/{plan-KOIPWVOZ.js → plan-SGCDDTYR.js} +7 -7
  168. package/dist/cli-bundle/chunks/{profile-OILJHKUW.js → profile-3THJPIQY.js} +4 -5
  169. package/dist/cli-bundle/chunks/{profile-RJXA7PGS.js → profile-XEZAMMBW.js} +4 -5
  170. package/dist/cli-bundle/chunks/{register-list-query-CFVG75P3.js → register-list-query-BR435Q2H.js} +19 -16
  171. package/dist/cli-bundle/chunks/register-list-query-BR435Q2H.js.map +1 -0
  172. package/dist/cli-bundle/chunks/{register-list-query-E7UVY4TN.js → register-list-query-RWTWLOBE.js} +18 -15
  173. package/dist/cli-bundle/chunks/register-list-query-RWTWLOBE.js.map +7 -0
  174. package/dist/cli-bundle/chunks/{register-mutation-IQ55E25C.js → register-mutation-HLWC2WNP.js} +167 -31
  175. package/dist/cli-bundle/chunks/register-mutation-HLWC2WNP.js.map +1 -0
  176. package/dist/cli-bundle/chunks/{register-mutation-4VJTXBZW.js → register-mutation-ZJX5AZM5.js} +173 -30
  177. package/dist/cli-bundle/chunks/register-mutation-ZJX5AZM5.js.map +7 -0
  178. package/dist/cli-bundle/chunks/{register-operations-AR7RMX4W.js → register-operations-744YBJMV.js} +23 -25
  179. package/dist/cli-bundle/chunks/{register-operations-AR7RMX4W.js.map → register-operations-744YBJMV.js.map} +1 -1
  180. package/dist/cli-bundle/chunks/{register-operations-NOLZGORC.js → register-operations-UEBJH6AN.js} +21 -23
  181. package/dist/cli-bundle/chunks/{register-operations-NOLZGORC.js.map → register-operations-UEBJH6AN.js.map} +1 -1
  182. package/dist/cli-bundle/chunks/{register-setup-EYZ7VTPZ.js → register-setup-5DA4UZXI.js} +7 -8
  183. package/dist/cli-bundle/chunks/{register-setup-EYZ7VTPZ.js.map → register-setup-5DA4UZXI.js.map} +1 -1
  184. package/dist/cli-bundle/chunks/{register-setup-BB77VUEE.js → register-setup-6H25M3BH.js} +9 -10
  185. package/dist/cli-bundle/chunks/{register-setup-BB77VUEE.js.map → register-setup-6H25M3BH.js.map} +1 -1
  186. package/dist/cli-bundle/chunks/{restore-ZH65GZFB.js → restore-6TDVSATY.js} +4 -5
  187. package/dist/cli-bundle/chunks/{restore-L6IAGOD7.js → restore-RSL7C7LO.js} +4 -5
  188. package/dist/cli-bundle/chunks/{schema-4ERWM5QJ.js → schema-HFXFSGPG.js} +2 -3
  189. package/dist/cli-bundle/chunks/{schema-55DL3Q52.js → schema-TPVTIJPO.js} +2 -3
  190. package/dist/cli-bundle/chunks/{update-FW6FKDOP.js → update-LJZCL5SI.js} +7 -7
  191. package/dist/cli-bundle/chunks/{update-TJHSPRPT.js → update-SIA7LH5Y.js} +7 -7
  192. package/dist/cli-bundle/chunks/{update-many-PWXX5WHO.js → update-many-BDBZVGQL.js} +11 -12
  193. package/dist/cli-bundle/chunks/{update-many-NNALYQCN.js → update-many-MOY3A5B3.js} +11 -12
  194. package/dist/cli-bundle/main.js +60 -85
  195. package/dist/cli-bundle/main.js.map +2 -2
  196. package/dist/cli-bundle/sdk-runtime.js +37 -37
  197. package/dist/cli-bundle/sdk.js +126 -291
  198. package/dist/cli-bundle/sdk.js.map +4 -4
  199. package/dist/core/item/parse.d.ts +1 -1
  200. package/dist/core/item/parse.js +13 -7
  201. package/dist/core/item/parse.js.map +1 -1
  202. package/dist/core/output/mutation-projection.d.ts +2 -0
  203. package/dist/core/output/mutation-projection.js +33 -2
  204. package/dist/core/output/mutation-projection.js.map +1 -1
  205. package/dist/core/output/output.d.ts +4 -0
  206. package/dist/core/output/output.js +18 -13
  207. package/dist/core/output/output.js.map +1 -1
  208. package/dist/core/shared/command-types.d.ts +4 -0
  209. package/dist/core/shared/command-types.js +2 -2
  210. package/dist/core/shared/command-types.js.map +1 -1
  211. package/dist/mcp/server.js +39 -4
  212. package/dist/mcp/server.js.map +1 -1
  213. package/dist/mcp/tool-definitions.js +45 -4
  214. package/dist/mcp/tool-definitions.js.map +1 -1
  215. package/dist/sdk/cli-bootstrap.d.ts +2 -0
  216. package/dist/sdk/cli-bootstrap.js +20 -27
  217. package/dist/sdk/cli-bootstrap.js.map +1 -1
  218. package/dist/sdk/cli-contracts/enum-contracts.d.ts +2 -2
  219. package/dist/sdk/cli-contracts/enum-contracts.js +7 -2
  220. package/dist/sdk/cli-contracts/enum-contracts.js.map +1 -1
  221. package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
  222. package/dist/sdk/cli-contracts/flag-contracts.js +21 -2
  223. package/dist/sdk/cli-contracts/flag-contracts.js.map +1 -1
  224. package/dist/sdk/cli-contracts/tool-option-contracts.js +10 -2
  225. package/dist/sdk/cli-contracts/tool-option-contracts.js.map +1 -1
  226. package/dist/sdk/cli-contracts/tool-parameter-tables.js +16 -3
  227. package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -1
  228. package/dist/sdk/cli-contracts/tool-schema.js +6 -2
  229. package/dist/sdk/cli-contracts/tool-schema.js.map +1 -1
  230. package/dist/sdk/cli-contracts.d.ts +1 -1
  231. package/dist/sdk/cli-contracts.js +3 -3
  232. package/dist/sdk/cli-contracts.js.map +1 -1
  233. package/dist/sdk/cli-program.js +4 -2
  234. package/dist/sdk/cli-program.js.map +1 -1
  235. package/dist/sdk/dependencies.d.ts +3 -2
  236. package/dist/sdk/dependencies.js +13 -12
  237. package/dist/sdk/dependencies.js.map +1 -1
  238. package/dist/sdk/error-runtime.d.ts +10 -0
  239. package/dist/sdk/error-runtime.js +59 -0
  240. package/dist/sdk/error-runtime.js.map +1 -0
  241. package/dist/sdk/graph/analytics.d.ts +9 -0
  242. package/dist/sdk/graph/analytics.js +24 -13
  243. package/dist/sdk/graph/analytics.js.map +1 -1
  244. package/dist/sdk/graph/assembly.d.ts +39 -0
  245. package/dist/sdk/graph/assembly.js +92 -12
  246. package/dist/sdk/graph/assembly.js.map +1 -1
  247. package/dist/sdk/graph/cache.d.ts +4 -1
  248. package/dist/sdk/graph/cache.js +17 -4
  249. package/dist/sdk/graph/cache.js.map +1 -1
  250. package/dist/sdk/graph/centrality.d.ts +82 -0
  251. package/dist/sdk/graph/centrality.js +259 -0
  252. package/dist/sdk/graph/centrality.js.map +1 -0
  253. package/dist/sdk/graph/durable-cache.d.ts +71 -0
  254. package/dist/sdk/graph/durable-cache.js +205 -0
  255. package/dist/sdk/graph/durable-cache.js.map +1 -0
  256. package/dist/sdk/graph/governance.d.ts +69 -1
  257. package/dist/sdk/graph/governance.js +143 -35
  258. package/dist/sdk/graph/governance.js.map +1 -1
  259. package/dist/sdk/graph/index.d.ts +7 -4
  260. package/dist/sdk/graph/index.js +8 -5
  261. package/dist/sdk/graph/index.js.map +1 -1
  262. package/dist/sdk/graph/mutation-advisory.d.ts +35 -4
  263. package/dist/sdk/graph/mutation-advisory.js +124 -35
  264. package/dist/sdk/graph/mutation-advisory.js.map +1 -1
  265. package/dist/sdk/graph/remediation.js +12 -2
  266. package/dist/sdk/graph/remediation.js.map +1 -1
  267. package/dist/sdk/graph/run.d.ts +133 -2
  268. package/dist/sdk/graph/run.js +217 -8
  269. package/dist/sdk/graph/run.js.map +1 -1
  270. package/dist/sdk/graph/scheduling.d.ts +59 -0
  271. package/dist/sdk/graph/scheduling.js +125 -0
  272. package/dist/sdk/graph/scheduling.js.map +1 -0
  273. package/dist/sdk/graph/traversal.d.ts +11 -0
  274. package/dist/sdk/graph/traversal.js +16 -2
  275. package/dist/sdk/graph/traversal.js.map +1 -1
  276. package/dist/sdk/index.d.ts +4 -0
  277. package/dist/sdk/index.js +6 -2
  278. package/dist/sdk/index.js.map +1 -1
  279. package/dist/sdk/runtime-input.js +7 -2
  280. package/dist/sdk/runtime-input.js.map +1 -1
  281. package/dist/sdk/runtime-primitives.d.ts +10 -0
  282. package/dist/sdk/runtime-primitives.js +14 -0
  283. package/dist/sdk/runtime-primitives.js.map +1 -0
  284. package/dist/sdk/runtime.d.ts +15 -0
  285. package/dist/sdk/runtime.js +16 -3
  286. package/dist/sdk/runtime.js.map +1 -1
  287. package/dist/sdk/structured-mutations.d.ts +21 -0
  288. package/dist/sdk/structured-mutations.js +375 -0
  289. package/dist/sdk/structured-mutations.js.map +1 -0
  290. package/docs/COMMANDS.md +85 -5
  291. package/docs/RELATIONSHIP_GRAPH.md +48 -7
  292. package/docs/SDK.md +78 -3
  293. package/marketplace.json +2 -2
  294. package/package.json +1 -1
  295. package/packages/pm-beads/package.json +1 -1
  296. package/packages/pm-calendar/package.json +1 -1
  297. package/packages/pm-command-kit/package.json +1 -1
  298. package/packages/pm-governance-audit/package.json +1 -1
  299. package/packages/pm-guide-shell/package.json +1 -1
  300. package/packages/pm-kanban/package.json +1 -1
  301. package/packages/pm-lifecycle-hooks/package.json +1 -1
  302. package/packages/pm-linked-test-adapters/package.json +1 -1
  303. package/packages/pm-search-advanced/package.json +1 -1
  304. package/packages/pm-templates/package.json +1 -1
  305. package/packages/pm-todos/package.json +1 -1
  306. package/packages/pm-vcs/package.json +1 -1
  307. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  308. package/plugins/pm-claude/README.md +5 -3
  309. package/plugins/pm-claude/commands/pm-init.md +1 -1
  310. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  311. package/dist/cli-bundle/chunks/chunk-3AO5VSDR.js.map +0 -7
  312. package/dist/cli-bundle/chunks/chunk-3LPFHE3P.js.map +0 -1
  313. package/dist/cli-bundle/chunks/chunk-3VY6MIEO.js.map +0 -7
  314. package/dist/cli-bundle/chunks/chunk-4F6BWJ4J.js.map +0 -7
  315. package/dist/cli-bundle/chunks/chunk-5IZJWSDB.js.map +0 -1
  316. package/dist/cli-bundle/chunks/chunk-5UX66S6U.js.map +0 -1
  317. package/dist/cli-bundle/chunks/chunk-6C2ZZX5Z.js +0 -286
  318. package/dist/cli-bundle/chunks/chunk-6C2ZZX5Z.js.map +0 -1
  319. package/dist/cli-bundle/chunks/chunk-6VIJ7UA5.js.map +0 -7
  320. package/dist/cli-bundle/chunks/chunk-6XMUURSS.js.map +0 -1
  321. package/dist/cli-bundle/chunks/chunk-C3KD7U3T.js.map +0 -7
  322. package/dist/cli-bundle/chunks/chunk-CFHAODHQ.js +0 -334
  323. package/dist/cli-bundle/chunks/chunk-CFHAODHQ.js.map +0 -1
  324. package/dist/cli-bundle/chunks/chunk-DAQ45GCS.js.map +0 -7
  325. package/dist/cli-bundle/chunks/chunk-E6LEMURX.js +0 -249
  326. package/dist/cli-bundle/chunks/chunk-E6LEMURX.js.map +0 -7
  327. package/dist/cli-bundle/chunks/chunk-G3COA6GS.js.map +0 -1
  328. package/dist/cli-bundle/chunks/chunk-GSJSM5BJ.js.map +0 -1
  329. package/dist/cli-bundle/chunks/chunk-GVI6FAFG.js.map +0 -7
  330. package/dist/cli-bundle/chunks/chunk-GVT754PX.js.map +0 -7
  331. package/dist/cli-bundle/chunks/chunk-HEWM6CEN.js.map +0 -7
  332. package/dist/cli-bundle/chunks/chunk-IJNK6WW2.js.map +0 -7
  333. package/dist/cli-bundle/chunks/chunk-INSTSQNZ.js.map +0 -7
  334. package/dist/cli-bundle/chunks/chunk-J4FBIFU6.js.map +0 -1
  335. package/dist/cli-bundle/chunks/chunk-KZEANWJS.js.map +0 -7
  336. package/dist/cli-bundle/chunks/chunk-LPEYZRUR.js.map +0 -1
  337. package/dist/cli-bundle/chunks/chunk-NHT3F4WZ.js.map +0 -1
  338. package/dist/cli-bundle/chunks/chunk-OV7MSW3I.js.map +0 -1
  339. package/dist/cli-bundle/chunks/chunk-P7JTWYLH.js +0 -246
  340. package/dist/cli-bundle/chunks/chunk-P7JTWYLH.js.map +0 -1
  341. package/dist/cli-bundle/chunks/chunk-R5U2VZ3K.js +0 -344
  342. package/dist/cli-bundle/chunks/chunk-R5U2VZ3K.js.map +0 -7
  343. package/dist/cli-bundle/chunks/chunk-SG74J6MV.js.map +0 -1
  344. package/dist/cli-bundle/chunks/chunk-T44FMVRL.js.map +0 -7
  345. package/dist/cli-bundle/chunks/chunk-THAOZG4U.js.map +0 -1
  346. package/dist/cli-bundle/chunks/chunk-UQLXSG72.js +0 -289
  347. package/dist/cli-bundle/chunks/chunk-UQLXSG72.js.map +0 -7
  348. package/dist/cli-bundle/chunks/chunk-UZDQXNUB.js.map +0 -1
  349. package/dist/cli-bundle/chunks/chunk-WVA4DVNV.js.map +0 -7
  350. package/dist/cli-bundle/chunks/register-list-query-CFVG75P3.js.map +0 -1
  351. package/dist/cli-bundle/chunks/register-list-query-E7UVY4TN.js.map +0 -7
  352. package/dist/cli-bundle/chunks/register-mutation-4VJTXBZW.js.map +0 -7
  353. package/dist/cli-bundle/chunks/register-mutation-IQ55E25C.js.map +0 -1
  354. /package/dist/cli-bundle/chunks/{append-E6V54WOQ.js.map → append-7OVFYR3C.js.map} +0 -0
  355. /package/dist/cli-bundle/chunks/{append-NNJ3EFIT.js.map → append-DFETHAZL.js.map} +0 -0
  356. /package/dist/cli-bundle/chunks/{chunk-QJKL5PHS.js.map → chunk-7656MAUL.js.map} +0 -0
  357. /package/dist/cli-bundle/chunks/{chunk-X6K5XTTN.js.map → chunk-7W2UAXXT.js.map} +0 -0
  358. /package/dist/cli-bundle/chunks/{chunk-5OK4UGFV.js.map → chunk-BXNDKOR2.js.map} +0 -0
  359. /package/dist/cli-bundle/chunks/{chunk-KSPWRNVP.js.map → chunk-CPX275C6.js.map} +0 -0
  360. /package/dist/cli-bundle/chunks/{chunk-JH2ZSLO3.js.map → chunk-DZRV2OPA.js.map} +0 -0
  361. /package/dist/cli-bundle/chunks/{chunk-L7BH7IWU.js.map → chunk-E5XMKOSB.js.map} +0 -0
  362. /package/dist/cli-bundle/chunks/{chunk-CQTQKUUV.js.map → chunk-EWJWSNRU.js.map} +0 -0
  363. /package/dist/cli-bundle/chunks/{chunk-3MCTMJXI.js.map → chunk-FPBMLYPI.js.map} +0 -0
  364. /package/dist/cli-bundle/chunks/{chunk-DVDBQA3B.js.map → chunk-GTK4DTEW.js.map} +0 -0
  365. /package/dist/cli-bundle/chunks/{chunk-GIQSU6S2.js.map → chunk-KBLZ3AA5.js.map} +0 -0
  366. /package/dist/cli-bundle/chunks/{chunk-XJF7CDNH.js.map → chunk-KH44WBAT.js.map} +0 -0
  367. /package/dist/cli-bundle/chunks/{chunk-GV2262OF.js.map → chunk-LAV26CQG.js.map} +0 -0
  368. /package/dist/cli-bundle/chunks/{chunk-VDO2JMD4.js.map → chunk-LVC72YRD.js.map} +0 -0
  369. /package/dist/cli-bundle/chunks/{chunk-ZYPFOO3L.js.map → chunk-MATHDCGG.js.map} +0 -0
  370. /package/dist/cli-bundle/chunks/{chunk-AOEOYL3S.js.map → chunk-O4BCOJTZ.js.map} +0 -0
  371. /package/dist/cli-bundle/chunks/{chunk-RJO3YAFM.js.map → chunk-OCUBRA6D.js.map} +0 -0
  372. /package/dist/cli-bundle/chunks/{chunk-I577UHC7.js.map → chunk-OR42SO64.js.map} +0 -0
  373. /package/dist/cli-bundle/chunks/{chunk-ZOJ3LR7O.js.map → chunk-OY7DMU5P.js.map} +0 -0
  374. /package/dist/cli-bundle/chunks/{chunk-ZV2NTVMJ.js.map → chunk-PONKZPCJ.js.map} +0 -0
  375. /package/dist/cli-bundle/chunks/{chunk-UX6SSO2I.js.map → chunk-PZC2FUOQ.js.map} +0 -0
  376. /package/dist/cli-bundle/chunks/{chunk-VQIHNHMJ.js.map → chunk-QIH77CAG.js.map} +0 -0
  377. /package/dist/cli-bundle/chunks/{chunk-R3EWPG4A.js.map → chunk-QJIKE24M.js.map} +0 -0
  378. /package/dist/cli-bundle/chunks/{chunk-HB3P4M52.js.map → chunk-TRSHFPRZ.js.map} +0 -0
  379. /package/dist/cli-bundle/chunks/{chunk-HRW7GF6T.js.map → chunk-UCBDQI5E.js.map} +0 -0
  380. /package/dist/cli-bundle/chunks/{chunk-4U4Z6AHI.js.map → chunk-V22ZPOKN.js.map} +0 -0
  381. /package/dist/cli-bundle/chunks/{chunk-JM6YAXTR.js.map → chunk-VHXHVTUU.js.map} +0 -0
  382. /package/dist/cli-bundle/chunks/{chunk-D6NXDNP3.js.map → chunk-VLRGDBLY.js.map} +0 -0
  383. /package/dist/cli-bundle/chunks/{chunk-JAPE62Y5.js.map → chunk-VNTCM3VW.js.map} +0 -0
  384. /package/dist/cli-bundle/chunks/{chunk-FDHPAVVB.js.map → chunk-VXOOB6YX.js.map} +0 -0
  385. /package/dist/cli-bundle/chunks/{chunk-HQ3SB4CN.js.map → chunk-X3W65QK3.js.map} +0 -0
  386. /package/dist/cli-bundle/chunks/{chunk-RZJLNXFG.js.map → chunk-XJTABV3X.js.map} +0 -0
  387. /package/dist/cli-bundle/chunks/{chunk-TYHJDFYW.js.map → chunk-ZVZGXPQ5.js.map} +0 -0
  388. /package/dist/cli-bundle/chunks/{close-many-SDA426VT.js.map → close-many-5RZXVN4J.js.map} +0 -0
  389. /package/dist/cli-bundle/chunks/{close-many-UTZANOCQ.js.map → close-many-RZVTUGBG.js.map} +0 -0
  390. /package/dist/cli-bundle/chunks/{comments-LZN6FXXC.js.map → comments-TPU7QRBL.js.map} +0 -0
  391. /package/dist/cli-bundle/chunks/{comments-VBQ345ND.js.map → comments-Z4KV6FU3.js.map} +0 -0
  392. /package/dist/cli-bundle/chunks/{create-GG4RBCGC.js.map → create-EIFBIVNQ.js.map} +0 -0
  393. /package/dist/cli-bundle/chunks/{create-JBC5KUW6.js.map → create-RGSPN5GD.js.map} +0 -0
  394. /package/dist/cli-bundle/chunks/{deps-FI4O6NQS.js.map → deps-UH5EQQUY.js.map} +0 -0
  395. /package/dist/cli-bundle/chunks/{deps-DELOO4TL.js.map → deps-YG7UF3VR.js.map} +0 -0
  396. /package/dist/cli-bundle/chunks/{docs-6Z2MP526.js.map → docs-G32TK6XS.js.map} +0 -0
  397. /package/dist/cli-bundle/chunks/{docs-2UYBP5D6.js.map → docs-JWWNRC27.js.map} +0 -0
  398. /package/dist/cli-bundle/chunks/{files-HKEAN5MA.js.map → files-3H32UQ4K.js.map} +0 -0
  399. /package/dist/cli-bundle/chunks/{files-HEUGSJZL.js.map → files-4ALMCSKB.js.map} +0 -0
  400. /package/dist/cli-bundle/chunks/{history-compact-7NDVP3PT.js.map → history-compact-77BT2LUB.js.map} +0 -0
  401. /package/dist/cli-bundle/chunks/{history-compact-65YVN5DB.js.map → history-compact-VCKGTX64.js.map} +0 -0
  402. /package/dist/cli-bundle/chunks/{history-redact-7YBL4XSG.js.map → history-redact-LJPZPNFA.js.map} +0 -0
  403. /package/dist/cli-bundle/chunks/{history-redact-IZGNJBU4.js.map → history-redact-PWTTJ3XS.js.map} +0 -0
  404. /package/dist/cli-bundle/chunks/{history-repair-7M4PYQUH.js.map → history-repair-I7CBNCV3.js.map} +0 -0
  405. /package/dist/cli-bundle/chunks/{history-repair-GNGETJLI.js.map → history-repair-YTDZRK5E.js.map} +0 -0
  406. /package/dist/cli-bundle/chunks/{learnings-3YXDRWFT.js.map → learnings-CYNOICKR.js.map} +0 -0
  407. /package/dist/cli-bundle/chunks/{learnings-ALC6IMNL.js.map → learnings-KTYW3AL7.js.map} +0 -0
  408. /package/dist/cli-bundle/chunks/{notes-7JMLQ447.js.map → notes-FGO63FXL.js.map} +0 -0
  409. /package/dist/cli-bundle/chunks/{notes-JFCLTC5C.js.map → notes-ZERD3KB2.js.map} +0 -0
  410. /package/dist/cli-bundle/chunks/{plan-T3XB3WTK.js.map → plan-OFJUBIM5.js.map} +0 -0
  411. /package/dist/cli-bundle/chunks/{plan-KOIPWVOZ.js.map → plan-SGCDDTYR.js.map} +0 -0
  412. /package/dist/cli-bundle/chunks/{profile-OILJHKUW.js.map → profile-3THJPIQY.js.map} +0 -0
  413. /package/dist/cli-bundle/chunks/{profile-RJXA7PGS.js.map → profile-XEZAMMBW.js.map} +0 -0
  414. /package/dist/cli-bundle/chunks/{restore-ZH65GZFB.js.map → restore-6TDVSATY.js.map} +0 -0
  415. /package/dist/cli-bundle/chunks/{restore-L6IAGOD7.js.map → restore-RSL7C7LO.js.map} +0 -0
  416. /package/dist/cli-bundle/chunks/{schema-4ERWM5QJ.js.map → schema-HFXFSGPG.js.map} +0 -0
  417. /package/dist/cli-bundle/chunks/{schema-55DL3Q52.js.map → schema-TPVTIJPO.js.map} +0 -0
  418. /package/dist/cli-bundle/chunks/{update-FW6FKDOP.js.map → update-LJZCL5SI.js.map} +0 -0
  419. /package/dist/cli-bundle/chunks/{update-TJHSPRPT.js.map → update-SIA7LH5Y.js.map} +0 -0
  420. /package/dist/cli-bundle/chunks/{update-many-PWXX5WHO.js.map → update-many-BDBZVGQL.js.map} +0 -0
  421. /package/dist/cli-bundle/chunks/{update-many-NNALYQCN.js.map → update-many-MOY3A5B3.js.map} +0 -0
@@ -1,9 +1,9 @@
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]="4c8b3841-40b8-5707-9154-ff020ed23bfd")}catch(e){}}();
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]="405abecd-c7c4-543d-be2a-eb3e5168def7")}catch(e){}}();
3
3
  import {
4
4
  collectStaleVectorizationIds,
5
5
  recordContextUsageTouches
6
- } from "./chunk-YQQNAKW3.js";
6
+ } from "./chunk-JFD5LPMI.js";
7
7
  import {
8
8
  buildEventCorpus,
9
9
  buildPlanFlatCorpus,
@@ -16,15 +16,26 @@ import {
16
16
  resolveSearchCorpusFields,
17
17
  resolveSettingsWithSemanticRuntimeDefaults,
18
18
  resolveVectorStores
19
- } from "./chunk-THAOZG4U.js";
19
+ } from "./chunk-PQSEQD6E.js";
20
20
  import {
21
21
  GRAPH_SUBCOMMAND_VALUES
22
- } from "./chunk-UZDQXNUB.js";
22
+ } from "./chunk-FSE2IKJQ.js";
23
23
  import {
24
- analyzeGraphImpact,
25
- analyzeKnowledgeGraph,
26
- analyzeRelationshipExecution
27
- } from "./chunk-6C2ZZX5Z.js";
24
+ auditWorkspaceRelationshipGraph,
25
+ collectDuplicateRelationshipEdgeGroups,
26
+ computeRelationshipDominators,
27
+ detectRelationshipCommunities,
28
+ diffRelationshipAuditSnapshots,
29
+ enumerateRelationshipPaths,
30
+ findRedundantRelationshipEdges,
31
+ forEachMatchedRelationshipEdge,
32
+ formatDuplicateEdgeGroup,
33
+ hierarchyAncestors,
34
+ hierarchyDescendants,
35
+ orderingPredecessors,
36
+ orderingSuccessors,
37
+ orientOrderingEdge
38
+ } from "./chunk-H7EAER5L.js";
28
39
  import {
29
40
  computeWorkspaceGraphFingerprint,
30
41
  parseDirection,
@@ -32,10 +43,11 @@ import {
32
43
  parseMaxDepth,
33
44
  parsePositiveInteger,
34
45
  workspaceGraphCache
35
- } from "./chunk-5IZJWSDB.js";
46
+ } from "./chunk-OG5DVFMA.js";
36
47
  import {
37
- assembleWorkspaceRelationshipGraph
38
- } from "./chunk-GSJSM5BJ.js";
48
+ assembleWorkspaceRelationshipGraph,
49
+ resolveWorkspaceRelationshipKindRegistry
50
+ } from "./chunk-K36WV5J6.js";
39
51
  import {
40
52
  splitCommaList
41
53
  } from "./chunk-NETP4DY4.js";
@@ -76,11 +88,12 @@ import {
76
88
  } from "./chunk-4XGJLADW.js";
77
89
  import {
78
90
  getItemAt
79
- } from "./chunk-4L23AGQ7.js";
91
+ } from "./chunk-Z7VWXXJM.js";
80
92
  import {
81
93
  readHistoryEntries
82
- } from "./chunk-2BO4CA46.js";
94
+ } from "./chunk-PFNHX655.js";
83
95
  import {
96
+ acquireLock,
84
97
  buildItemNotFoundError,
85
98
  compareTimestampStrings,
86
99
  getActiveExtensionRegistrations,
@@ -107,18 +120,22 @@ import {
107
120
  coerceNumberInRange,
108
121
  coercePositiveInteger,
109
122
  collectRegisteredItemFieldNames,
123
+ createRelationshipKindRegistry,
110
124
  getHistoryPath,
111
125
  getItemPath,
112
126
  getSettingsPath,
113
127
  isPathWithinDirectory,
114
128
  pathExists,
129
+ readFileIfExists,
130
+ removeFileIfExists,
115
131
  resolveGlobalPmRoot,
116
132
  resolveItemTypeRegistry,
117
133
  resolvePmRoot,
118
134
  resolveRuntimeFieldRegistry,
119
135
  resolveRuntimeStatusRegistry,
120
136
  toNonEmptyString,
121
- toNonEmptyStringOrUndefined
137
+ toNonEmptyStringOrUndefined,
138
+ writeFileAtomic
122
139
  } from "./chunk-HYW67VJ5.js";
123
140
 
124
141
  // dist/cli/commands/aggregate.js
@@ -463,866 +480,692 @@ async function runAggregate(options, global) {
463
480
  };
464
481
  }
465
482
 
466
- // dist/sdk/graph/traversal.js
467
- var DEFAULT_MAX_PATHS = 5;
468
- var DEFAULT_MAX_VISITED_PATHS = 1e4;
469
- var DEFAULT_PATH_MAX_DEPTH = 8;
470
- function assertPathBound(name, value) {
471
- if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0)
472
- throw new TypeError(`Invalid path ${name} bound: ${String(value)}`);
473
- }
474
- function hierarchyParentEndpoint(edge, definition) {
475
- return definition.hierarchyDirection === "target_parent" ? edge.target : edge.source;
476
- }
477
- function orderingPredecessorEndpoint(edge, definition) {
478
- return (definition.precedence ?? "source_before_target") === "target_before_source" ? edge.target : edge.source;
479
- }
480
- function resolveFamilyKinds(graph, kinds, family) {
481
- if (kinds === void 0)
482
- return void 0;
483
- const registry = graph.registry();
484
- const resolved = /* @__PURE__ */ new Set();
485
- for (const kind of kinds) {
486
- const definition = registry.require(kind);
487
- if (!definition[family])
488
- throw new TypeError(`Relationship kind ${definition.kind} is not a ${family} kind`);
489
- resolved.add(definition.kind);
490
- }
491
- return resolved;
492
- }
493
- function expandSemanticNeighbors(graph, nodeId, familyKinds, family, matches) {
494
- const registry = graph.registry();
495
- const rows = graph.neighborEdges(nodeId, {
496
- direction: "both",
497
- ...familyKinds === void 0 ? {} : { kinds: [...familyKinds] }
498
- });
499
- const neighbors = [];
500
- const seen = /* @__PURE__ */ new Set();
501
- for (const row of rows.value) {
502
- const definition = registry.require(row.edge.kind);
503
- if (!definition[family])
504
- continue;
505
- if (!matches(row, definition, nodeId))
483
+ // dist/sdk/relationship-analytics.js
484
+ function appendNeighbor(adjacency, source, target) {
485
+ adjacency.get(source).add(target);
486
+ }
487
+ function createAdjacency(nodes) {
488
+ return new Map(nodes.map((node) => [node, /* @__PURE__ */ new Set()]));
489
+ }
490
+ function sortComponents(components) {
491
+ for (const component of components)
492
+ component.sort();
493
+ return components.sort((left, right) => right.length - left.length || left[0].localeCompare(right[0]));
494
+ }
495
+ function stableJsonValue(value) {
496
+ if (Array.isArray(value))
497
+ return value.map((entry) => stableJsonValue(entry));
498
+ if (value === null || typeof value !== "object")
499
+ return value;
500
+ const toJSON = value.toJSON;
501
+ if (typeof toJSON === "function")
502
+ return stableJsonValue(toJSON.call(value));
503
+ return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, stableJsonValue(entry)]));
504
+ }
505
+ function relationshipEdgeKey(edge) {
506
+ return JSON.stringify(stableJsonValue(edge));
507
+ }
508
+ function appendFinishingOrder(start, adjacency, visited, order) {
509
+ const stack = [{ id: start, expanded: false }];
510
+ while (stack.length > 0) {
511
+ const current = stack.pop();
512
+ if (current.expanded) {
513
+ order.push(current.id);
506
514
  continue;
507
- if (seen.has(row.id))
515
+ }
516
+ if (visited.has(current.id))
508
517
  continue;
509
- seen.add(row.id);
510
- neighbors.push(row.id);
518
+ visited.add(current.id);
519
+ stack.push({ id: current.id, expanded: true });
520
+ const neighbors = [...adjacency.get(current.id)].sort().reverse();
521
+ for (const neighbor of neighbors)
522
+ if (!visited.has(neighbor))
523
+ stack.push({ id: neighbor, expanded: false });
511
524
  }
512
- return { neighbors, inspectedEdges: rows.meta.inspectedEdges };
513
525
  }
514
- function appendSemanticExpansion(expansion, currentDepth, maxDepth, limit, after, state) {
515
- if (currentDepth >= maxDepth) {
516
- if (expansion.neighbors.some((neighbor) => !state.seen.has(neighbor)))
517
- state.truncated = true;
518
- return false;
519
- }
520
- for (const neighbor of expansion.neighbors) {
521
- if (state.seen.has(neighbor))
522
- continue;
523
- state.seen.add(neighbor);
524
- state.queue.push({ id: neighbor, depth: currentDepth + 1 });
525
- if (!state.resumed) {
526
- if (neighbor === after)
527
- state.resumed = true;
526
+ function computeFinishingOrder(nodes, adjacency) {
527
+ const visited = /* @__PURE__ */ new Set();
528
+ const order = [];
529
+ for (const start of nodes)
530
+ if (!visited.has(start))
531
+ appendFinishingOrder(start, adjacency, visited, order);
532
+ return order;
533
+ }
534
+ function collectReverseComponents(order, reverse) {
535
+ const visited = /* @__PURE__ */ new Set();
536
+ const components = [];
537
+ for (const start of [...order].reverse()) {
538
+ if (visited.has(start))
528
539
  continue;
540
+ const component = [];
541
+ const stack = [start];
542
+ visited.add(start);
543
+ while (stack.length > 0) {
544
+ const current = stack.pop();
545
+ component.push(current);
546
+ for (const neighbor of reverse.get(current)) {
547
+ if (visited.has(neighbor))
548
+ continue;
549
+ visited.add(neighbor);
550
+ stack.push(neighbor);
551
+ }
529
552
  }
530
- if (state.value.length >= limit) {
531
- state.truncated = true;
532
- return true;
533
- }
534
- state.value.push(neighbor);
553
+ components.push(component);
535
554
  }
536
- return false;
555
+ return sortComponents(components);
537
556
  }
538
- function boundedSemanticWalk(graph, start, options, family, matches) {
539
- if (!graph.hasNode(start))
540
- throw new TypeError(`Relationship node not found: ${start}`);
541
- const familyKinds = resolveFamilyKinds(graph, options.kinds, family);
542
- const limit = options.limit ?? Number.POSITIVE_INFINITY;
543
- const maxDepth = options.maxDepth ?? Number.POSITIVE_INFINITY;
544
- const after = options.after;
545
- const state = {
546
- seen: /* @__PURE__ */ new Set([start]),
547
- value: [],
548
- queue: [{ id: start, depth: 0 }],
549
- resumed: after === void 0,
550
- truncated: false
551
- };
552
- let visitedNodes = 0;
553
- let inspectedEdges = 0;
554
- for (let index = 0; index < state.queue.length; index += 1) {
555
- options.signal?.throwIfAborted();
556
- const current = state.queue[index];
557
- visitedNodes += 1;
558
- const expansion = expandSemanticNeighbors(graph, current.id, familyKinds, family, matches);
559
- inspectedEdges += expansion.inspectedEdges;
560
- if (appendSemanticExpansion(expansion, current.depth, maxDepth, limit, after, state))
561
- break;
562
- }
563
- if (!state.resumed)
564
- throw new TypeError(`Traversal cursor not found in sequence: ${after}`);
565
- return {
566
- value: state.value,
567
- meta: {
568
- visitedNodes,
569
- inspectedEdges,
570
- truncated: state.truncated,
571
- nextCursor: state.value.at(-1)
572
- }
573
- };
557
+ function stronglyConnectedComponents(nodes, adjacency) {
558
+ const reverse = createAdjacency(nodes);
559
+ for (const [source, targets] of adjacency)
560
+ for (const target of targets)
561
+ appendNeighbor(reverse, target, source);
562
+ return collectReverseComponents(computeFinishingOrder(nodes, adjacency), reverse);
574
563
  }
575
- function assertPathEndpoint(graph, id) {
576
- if (!graph.hasNode(id))
577
- throw new TypeError(`Relationship node not found: ${id}`);
564
+ function buildExecutionAdjacency(graph, registry) {
565
+ const adjacency = createAdjacency(graph.nodes());
566
+ for (const edge of graph.edges()) {
567
+ const definition = registry.require(edge.kind);
568
+ if (!definition.ordering)
569
+ continue;
570
+ const sourceFirst = (definition.precedence ?? "source_before_target") === "source_before_target";
571
+ appendNeighbor(adjacency, sourceFirst ? edge.source : edge.target, sourceFirst ? edge.target : edge.source);
572
+ }
573
+ return adjacency;
578
574
  }
579
- function readPathContinuations(graph, partial, options, direction, state) {
580
- const rows = graph.neighborEdges(partial.nodes.at(-1), {
581
- direction,
582
- ...options.kinds === void 0 ? {} : { kinds: options.kinds }
583
- });
584
- state.inspectedEdges += rows.meta.inspectedEdges;
585
- return rows.value.filter((row) => !partial.nodeSet.has(row.id));
586
- }
587
- function expandPartialPath(graph, partial, target, options, direction, probeLimit, state) {
588
- for (const row of readPathContinuations(graph, partial, options, direction, state)) {
589
- const nodes = [...partial.nodes, row.id];
590
- const nodeSet = new Set(partial.nodeSet).add(row.id);
591
- const edges = [...partial.edges, row.edge];
592
- if (row.id === target) {
593
- state.value.push({ nodes, edges, length: edges.length });
594
- if (state.value.length >= probeLimit)
595
- return true;
596
- } else {
597
- state.queue.push({ nodes, nodeSet, edges });
575
+ function topologicalLayers(nodes, adjacency) {
576
+ const indegree = new Map(nodes.map((node) => [node, 0]));
577
+ for (const targets of adjacency.values())
578
+ for (const target of targets)
579
+ indegree.set(target, indegree.get(target) + 1);
580
+ let frontier = nodes.filter((node) => indegree.get(node) === 0).sort();
581
+ const layers = [];
582
+ while (frontier.length > 0) {
583
+ layers.push(frontier);
584
+ const next = [];
585
+ for (const source of frontier) {
586
+ for (const target of adjacency.get(source)) {
587
+ const remaining = indegree.get(target) - 1;
588
+ indegree.set(target, remaining);
589
+ if (remaining === 0)
590
+ next.push(target);
591
+ }
598
592
  }
593
+ frontier = next.sort();
599
594
  }
600
- return false;
601
- }
602
- function hierarchyAncestors(graph, id, options = {}) {
603
- return boundedSemanticWalk(graph, id, options, "hierarchy", (row, definition) => hierarchyParentEndpoint(row.edge, definition) === row.id);
604
- }
605
- function hierarchyDescendants(graph, id, options = {}) {
606
- return boundedSemanticWalk(graph, id, options, "hierarchy", (row, definition, nodeId) => hierarchyParentEndpoint(row.edge, definition) === nodeId);
607
- }
608
- function orderingPredecessors(graph, id, options = {}) {
609
- return boundedSemanticWalk(graph, id, options, "ordering", (row, definition) => orderingPredecessorEndpoint(row.edge, definition) === row.id);
610
- }
611
- function orderingSuccessors(graph, id, options = {}) {
612
- return boundedSemanticWalk(graph, id, options, "ordering", (row, definition, nodeId) => orderingPredecessorEndpoint(row.edge, definition) === nodeId);
595
+ return layers;
613
596
  }
614
- function enumerateNonZeroRelationshipPaths(graph, source, target, options, maxPaths, maxVisitedPaths, maxDepth, direction) {
615
- const state = {
616
- value: [],
617
- queue: [{ nodes: [source], nodeSet: /* @__PURE__ */ new Set([source]), edges: [] }],
618
- inspectedEdges: 0
597
+ function longestPath(order, adjacency) {
598
+ const depth = new Map(order.map((node) => [node, 0]));
599
+ const parent = /* @__PURE__ */ new Map();
600
+ for (const source of order) {
601
+ for (const target of adjacency.get(source)) {
602
+ if (!depth.has(target))
603
+ continue;
604
+ const candidate = depth.get(source) + 1;
605
+ const currentParent = parent.get(target);
606
+ if (candidate > depth.get(target) || candidate === depth.get(target) && (currentParent === void 0 || source.localeCompare(currentParent) < 0)) {
607
+ depth.set(target, candidate);
608
+ parent.set(target, source);
609
+ }
610
+ }
611
+ }
612
+ const end = [...order].sort((left, right) => depth.get(right) - depth.get(left) || left.localeCompare(right))[0];
613
+ const path4 = end === void 0 ? [] : [end];
614
+ while (path4[0] !== void 0 && parent.has(path4[0]))
615
+ path4.unshift(parent.get(path4[0]));
616
+ return { depth: Object.fromEntries(depth), path: path4 };
617
+ }
618
+ function reconstructImpactPath(root, target, parents) {
619
+ const path4 = [target];
620
+ let cursor = target;
621
+ while (cursor !== root) {
622
+ cursor = parents.get(cursor);
623
+ path4.push(cursor);
624
+ }
625
+ return path4.reverse();
626
+ }
627
+ function analyzeRelationshipExecution(graph, options = {}) {
628
+ const registry = options.registry ?? createRelationshipKindRegistry();
629
+ const nodes = [...graph.nodes()];
630
+ const adjacency = buildExecutionAdjacency(graph, registry);
631
+ const layers = topologicalLayers(nodes, adjacency);
632
+ const order = layers.flat();
633
+ const acyclic = order.length === nodes.length;
634
+ const cycles = acyclic ? [] : stronglyConnectedComponents(nodes, adjacency).filter((component) => component.length > 1 || adjacency.get(component[0]).has(component[0]));
635
+ const longest = longestPath(order, adjacency);
636
+ return {
637
+ exact: true,
638
+ acyclic,
639
+ order,
640
+ layers,
641
+ frontier: layers[0] ?? [],
642
+ depth: longest.depth,
643
+ criticalPath: longest.path,
644
+ criticalPathLength: Math.max(0, longest.path.length - 1),
645
+ cycles,
646
+ provenance: { algorithm: "kahn-longest-path", edgeFamily: "ordering" }
619
647
  };
648
+ }
649
+ function analyzeGraphImpact(graph, root, options = {}) {
650
+ const direction = options.direction ?? "outgoing";
651
+ const maxDepth = options.maxDepth ?? Number.POSITIVE_INFINITY;
652
+ const limit = options.limit ?? Number.POSITIVE_INFINITY;
653
+ const queue = [{ id: root, depth: 0 }];
654
+ const seen = /* @__PURE__ */ new Set([root]);
655
+ const parents = /* @__PURE__ */ new Map();
656
+ const affected = [];
620
657
  let visitedNodes = 0;
658
+ let inspectedEdges = 0;
621
659
  let truncated = false;
622
- const probeLimit = maxPaths + 1;
623
- for (let index = 0; index < state.queue.length; index += 1) {
660
+ traversal: for (let index = 0; index < queue.length; index += 1) {
624
661
  options.signal?.throwIfAborted();
625
- if (state.value.length >= probeLimit || visitedNodes >= maxVisitedPaths) {
626
- truncated = true;
627
- break;
628
- }
629
- const partial = state.queue[index];
662
+ const current = queue[index];
630
663
  visitedNodes += 1;
631
- if (partial.edges.length >= maxDepth) {
632
- if (readPathContinuations(graph, partial, options, direction, state).length > 0)
664
+ const adjacent = graph.adjacency(current.id, {
665
+ direction,
666
+ kinds: options.kinds,
667
+ signal: options.signal
668
+ });
669
+ inspectedEdges += adjacent.meta.inspectedEdges;
670
+ if (current.depth >= maxDepth) {
671
+ if (adjacent.value.some((id) => !seen.has(id)))
633
672
  truncated = true;
634
673
  continue;
635
674
  }
636
- if (expandPartialPath(graph, partial, target, options, direction, probeLimit, state)) {
637
- truncated = true;
638
- break;
675
+ for (const id of adjacent.value) {
676
+ if (seen.has(id))
677
+ continue;
678
+ if (affected.length >= limit) {
679
+ truncated = true;
680
+ break traversal;
681
+ }
682
+ seen.add(id);
683
+ parents.set(id, current.id);
684
+ const depth = current.depth + 1;
685
+ affected.push({
686
+ id,
687
+ distance: depth,
688
+ path: reconstructImpactPath(root, id, parents)
689
+ });
690
+ queue.push({ id, depth });
639
691
  }
640
692
  }
641
693
  return {
642
- value: state.value.slice(0, maxPaths),
643
- meta: { visitedNodes, inspectedEdges: state.inspectedEdges, truncated }
694
+ root,
695
+ affected,
696
+ exact: true,
697
+ truncated,
698
+ cost: { visitedNodes, inspectedEdges }
644
699
  };
645
700
  }
646
- function enumerateRelationshipPaths(graph, source, target, options = {}) {
647
- assertPathEndpoint(graph, source);
648
- assertPathEndpoint(graph, target);
649
- const maxPaths = options.maxPaths ?? DEFAULT_MAX_PATHS;
650
- const maxVisitedPaths = options.maxVisitedPaths ?? DEFAULT_MAX_VISITED_PATHS;
651
- const maxDepth = options.maxDepth ?? DEFAULT_PATH_MAX_DEPTH;
652
- assertPathBound("maxPaths", maxPaths);
653
- assertPathBound("maxVisitedPaths", maxVisitedPaths);
654
- assertPathBound("maxDepth", maxDepth);
655
- const direction = options.direction ?? "outgoing";
656
- options.signal?.throwIfAborted();
657
- for (const kind of options.kinds ?? [])
658
- graph.registry().require(kind);
659
- if (source === target) {
660
- if (maxPaths === 0) {
661
- return {
662
- value: [],
663
- meta: { visitedNodes: 1, inspectedEdges: 0, truncated: true }
664
- };
665
- }
666
- return {
667
- value: [{ nodes: [source], edges: [], length: 0 }],
668
- meta: { visitedNodes: 1, inspectedEdges: 0, truncated: false }
669
- };
670
- }
671
- return enumerateNonZeroRelationshipPaths(graph, source, target, options, maxPaths, maxVisitedPaths, maxDepth, direction);
672
- }
673
-
674
- // dist/sdk/graph/analytics.js
675
- var DEFAULT_MAX_ITERATIONS = 16;
676
- var DEFAULT_MIN_COMMUNITY_SIZE = 2;
677
- var DEFAULT_REDUNDANCY_MAX_DEPTH = 8;
678
- function assertPositiveBound(name, value) {
679
- if (!Number.isInteger(value) || value < 1)
680
- throw new TypeError(`Invalid ${name} bound: ${String(value)}`);
681
- }
682
- function buildUndirectedAdjacency(graph, kinds) {
683
- const registry = graph.registry();
684
- const wanted = kinds === void 0 ? void 0 : new Set(kinds.map((kind) => registry.require(kind).kind));
685
- const adjacency = /* @__PURE__ */ new Map();
701
+ function analyzeKnowledgeGraph(graph) {
702
+ const nodes = [...graph.nodes()];
703
+ const weak = createAdjacency(nodes);
704
+ const directed = createAdjacency(nodes);
686
705
  for (const edge of graph.edges()) {
687
- if (edge.source === edge.target)
688
- continue;
689
- if (wanted !== void 0) {
690
- const definition = registry.require(edge.kind);
691
- const matches = wanted.has(definition.kind) || definition.inverse !== void 0 && wanted.has(definition.inverse);
692
- if (!matches)
693
- continue;
694
- }
695
- appendAdjacency(adjacency, edge.source, edge.target);
696
- appendAdjacency(adjacency, edge.target, edge.source);
697
- }
698
- for (const neighbors of adjacency.values())
699
- neighbors.sort();
700
- return adjacency;
701
- }
702
- function appendAdjacency(adjacency, from, to) {
703
- const neighbors = adjacency.get(from);
704
- if (neighbors === void 0)
705
- adjacency.set(from, [to]);
706
- else
707
- neighbors.push(to);
708
- }
709
- function dominantNeighborLabel(neighbors, labels) {
710
- const counts = /* @__PURE__ */ new Map();
711
- for (const neighbor of neighbors) {
712
- const label = labels.get(neighbor);
713
- counts.set(label, (counts.get(label) ?? 0) + 1);
714
- }
715
- let best;
716
- let bestCount = 0;
717
- for (const [label, count] of counts) {
718
- if (count > bestCount || count === bestCount && label < best) {
719
- best = label;
720
- bestCount = count;
721
- }
722
- }
723
- return best;
724
- }
725
- function collectCommunities(labels, minSize) {
726
- const groups = /* @__PURE__ */ new Map();
727
- for (const [id, label] of labels) {
728
- const members = groups.get(label);
729
- if (members === void 0)
730
- groups.set(label, [id]);
731
- else
732
- members.push(id);
733
- }
734
- const communities = [];
735
- for (const members of groups.values()) {
736
- if (members.length < minSize)
706
+ appendNeighbor(weak, edge.source, edge.target);
707
+ appendNeighbor(weak, edge.target, edge.source);
708
+ appendNeighbor(directed, edge.source, edge.target);
709
+ }
710
+ const components = [];
711
+ const visited = /* @__PURE__ */ new Set();
712
+ for (const start of nodes) {
713
+ if (visited.has(start))
737
714
  continue;
738
- members.sort();
739
- communities.push({
740
- representative: members[0],
741
- size: members.length,
742
- members
743
- });
744
- }
745
- return communities.sort((left, right) => right.size - left.size || left.representative.localeCompare(right.representative));
746
- }
747
- function detectRelationshipCommunities(graph, options = {}) {
748
- const maxIterations = options.maxIterations ?? DEFAULT_MAX_ITERATIONS;
749
- const minSize = options.minSize ?? DEFAULT_MIN_COMMUNITY_SIZE;
750
- assertPositiveBound("maxIterations", maxIterations);
751
- assertPositiveBound("minSize", minSize);
752
- const adjacency = buildUndirectedAdjacency(graph, options.kinds);
753
- const nodes = graph.nodes();
754
- const labels = new Map(nodes.map((id) => [id, id]));
755
- let iterations = 0;
756
- let converged = false;
757
- let visitedNodes = 0;
758
- let inspectedEdges = 0;
759
- while (iterations < maxIterations && !converged) {
760
- options.signal?.throwIfAborted();
761
- iterations += 1;
762
- converged = true;
763
- for (const id of nodes) {
764
- visitedNodes += 1;
765
- const neighbors = adjacency.get(id);
766
- if (neighbors === void 0)
767
- continue;
768
- inspectedEdges += neighbors.length;
769
- const dominant = dominantNeighborLabel(neighbors, labels);
770
- if (dominant !== labels.get(id)) {
771
- labels.set(id, dominant);
772
- converged = false;
715
+ const component = [];
716
+ const stack = [start];
717
+ visited.add(start);
718
+ while (stack.length > 0) {
719
+ const current = stack.pop();
720
+ component.push(current);
721
+ for (const neighbor of weak.get(current)) {
722
+ if (visited.has(neighbor))
723
+ continue;
724
+ visited.add(neighbor);
725
+ stack.push(neighbor);
773
726
  }
774
727
  }
728
+ components.push(component);
775
729
  }
730
+ const degrees = nodes.map((id) => ({ id, degree: weak.get(id).size }));
731
+ const maximum = Math.max(0, ...degrees.map(({ degree }) => degree));
776
732
  return {
777
- value: {
778
- communities: collectCommunities(labels, minSize),
779
- iterations,
780
- converged
781
- },
782
- meta: { visitedNodes, inspectedEdges, truncated: !converged }
733
+ components: sortComponents(components),
734
+ stronglyConnected: stronglyConnectedComponents(nodes, directed),
735
+ orphans: degrees.filter(({ degree }) => degree === 0).map(({ id }) => id),
736
+ hubs: degrees.filter(({ degree }) => degree > 0 && degree === maximum),
737
+ exact: true,
738
+ provenance: { algorithm: "component-degree", edgeFamily: "all" }
783
739
  };
784
740
  }
785
- function isTransitiveKind(definition) {
786
- return definition.direction === "directed" && (definition.ordering || definition.hierarchy);
741
+ function compareRelationshipSnapshots(before, after) {
742
+ const earlier = new Map(before.edges.map((edge) => [relationshipEdgeKey(edge), edge]));
743
+ const later = new Map(after.edges.map((edge) => [relationshipEdgeKey(edge), edge]));
744
+ return {
745
+ fromVersion: before.version,
746
+ toVersion: after.version,
747
+ added: [...later].filter(([key]) => !earlier.has(key)).map(([, edge]) => edge),
748
+ removed: [...earlier].filter(([key]) => !later.has(key)).map(([, edge]) => edge),
749
+ unchangedCount: [...earlier.keys()].filter((key) => later.has(key)).length,
750
+ exact: true
751
+ };
787
752
  }
788
- function transitiveFamilyKey(definition) {
789
- return definition.inverse !== void 0 && definition.inverse < definition.kind ? definition.inverse : definition.kind;
753
+
754
+ // dist/sdk/graph/centrality.js
755
+ function roundScore(value) {
756
+ return Math.round(value * 1e6) / 1e6;
757
+ }
758
+ function addToSetMap(map, key, value) {
759
+ const set = map.get(key);
760
+ if (set === void 0)
761
+ map.set(key, /* @__PURE__ */ new Set([value]));
762
+ else
763
+ set.add(value);
790
764
  }
791
- function orientTransitiveEdge(edge, definition) {
792
- const head = definition.hierarchy ? hierarchyParentEndpoint(edge, definition) : edge.source === orderingPredecessorEndpoint(edge, definition) ? edge.target : edge.source;
793
- return head === edge.target ? { from: edge.source, to: edge.target } : { from: edge.target, to: edge.source };
765
+ function buildSimpleUndirectedAdjacency(graph, kinds) {
766
+ const sets = new Map(graph.nodes().map((id) => [id, /* @__PURE__ */ new Set()]));
767
+ forEachMatchedRelationshipEdge(graph, kinds, (edge) => {
768
+ sets.get(edge.source).add(edge.target);
769
+ sets.get(edge.target).add(edge.source);
770
+ });
771
+ const adjacency = /* @__PURE__ */ new Map();
772
+ for (const [id, neighbors] of sets)
773
+ adjacency.set(id, [...neighbors].sort());
774
+ return adjacency;
794
775
  }
795
- function resolveRedundancyFamilies(graph, kinds) {
796
- if (kinds === void 0)
797
- return void 0;
798
- const registry = graph.registry();
799
- const families = /* @__PURE__ */ new Set();
800
- for (const kind of kinds) {
801
- const definition = registry.require(kind);
802
- if (!isTransitiveKind(definition))
803
- throw new TypeError(`Relationship kind ${definition.kind} is not a directed ordering or hierarchy kind`);
804
- families.add(transitiveFamilyKey(definition));
776
+ function collectOrderingDegrees(graph, kinds) {
777
+ const incoming = /* @__PURE__ */ new Map();
778
+ const outgoing = /* @__PURE__ */ new Map();
779
+ forEachMatchedRelationshipEdge(graph, kinds, (edge, definition) => {
780
+ if (!definition.ordering)
781
+ return;
782
+ const { predecessor, successor } = orientOrderingEdge(edge, definition);
783
+ addToSetMap(outgoing, predecessor, successor);
784
+ addToSetMap(incoming, successor, predecessor);
785
+ });
786
+ return { incoming, outgoing };
787
+ }
788
+ function brandesShortestPaths(source, adjacency, cost) {
789
+ const distance = /* @__PURE__ */ new Map([[source, 0]]);
790
+ const sigma = /* @__PURE__ */ new Map([[source, 1]]);
791
+ const predecessors = /* @__PURE__ */ new Map();
792
+ const stack = [];
793
+ const queue = [source];
794
+ let reachableCount = 0;
795
+ let distanceSum = 0;
796
+ for (let index = 0; index < queue.length; index += 1) {
797
+ const node = queue[index];
798
+ cost.visitedNodes += 1;
799
+ stack.push(node);
800
+ const nodeDistance = distance.get(node);
801
+ if (node !== source) {
802
+ reachableCount += 1;
803
+ distanceSum += nodeDistance;
804
+ }
805
+ for (const neighbor of adjacency.get(node)) {
806
+ cost.inspectedEdges += 1;
807
+ if (!distance.has(neighbor)) {
808
+ distance.set(neighbor, nodeDistance + 1);
809
+ queue.push(neighbor);
810
+ }
811
+ if (distance.get(neighbor) === nodeDistance + 1) {
812
+ sigma.set(neighbor, (sigma.get(neighbor) ?? 0) + sigma.get(node));
813
+ const predecessorList = predecessors.get(neighbor);
814
+ if (predecessorList === void 0)
815
+ predecessors.set(neighbor, [node]);
816
+ else
817
+ predecessorList.push(node);
818
+ }
819
+ }
805
820
  }
806
- return families;
821
+ return { stack, sigma, predecessors, reachableCount, distanceSum };
807
822
  }
808
- function collectTransitiveFamilies(graph, wanted) {
809
- const registry = graph.registry();
810
- const families = /* @__PURE__ */ new Map();
811
- for (const edge of graph.edges()) {
812
- const definition = registry.require(edge.kind);
813
- if (!isTransitiveKind(definition))
814
- continue;
815
- const key = transitiveFamilyKey(definition);
816
- if (wanted !== void 0 && !wanted.has(key))
817
- continue;
818
- const oriented = orientTransitiveEdge(edge, definition);
819
- if (oriented.from === oriented.to)
820
- continue;
821
- let family = families.get(key);
822
- if (family === void 0) {
823
- family = { adjacency: /* @__PURE__ */ new Map(), records: [] };
824
- families.set(key, family);
823
+ function accumulateBetweenness(sweep, source, betweenness) {
824
+ const dependency = /* @__PURE__ */ new Map();
825
+ for (let index = sweep.stack.length - 1; index >= 0; index -= 1) {
826
+ const node = sweep.stack[index];
827
+ const share = (1 + (dependency.get(node) ?? 0)) / sweep.sigma.get(node);
828
+ for (const predecessor of sweep.predecessors.get(node) ?? []) {
829
+ dependency.set(predecessor, (dependency.get(predecessor) ?? 0) + sweep.sigma.get(predecessor) * share);
825
830
  }
826
- const targets = family.adjacency.get(oriented.from);
827
- if (targets === void 0)
828
- family.adjacency.set(oriented.from, /* @__PURE__ */ new Set([oriented.to]));
829
- else
830
- targets.add(oriented.to);
831
- family.records.push({ ...oriented, edge });
832
- }
833
- return families;
834
- }
835
- function sortedFamilyAdjacency(family) {
836
- const sorted = /* @__PURE__ */ new Map();
837
- for (const [from, targets] of family.adjacency)
838
- sorted.set(from, [...targets].sort());
839
- return sorted;
840
- }
841
- function reconstructWitness(parents, from, tail, head) {
842
- const witness = [head];
843
- for (let node = tail; node !== from; node = parents.get(node))
844
- witness.push(node);
845
- witness.push(from);
846
- return witness.reverse();
847
- }
848
- function expandWitnessFrontier(adjacency, record, current, parents, queue, cost) {
849
- for (const next of adjacency.get(current.id) ?? []) {
850
- cost.inspectedEdges += 1;
851
- if (current.depth === 0 && next === record.to)
852
- continue;
853
- if (parents.has(next))
854
- continue;
855
- parents.set(next, current.id);
856
- if (next === record.to)
857
- return reconstructWitness(parents, record.from, current.id, next);
858
- queue.push({ id: next, depth: current.depth + 1 });
831
+ if (node !== source)
832
+ betweenness.set(node, (betweenness.get(node) ?? 0) + (dependency.get(node) ?? 0));
859
833
  }
860
- return void 0;
861
834
  }
862
- function findWitnessPath(adjacency, record, maxDepth, cost) {
863
- const parents = /* @__PURE__ */ new Map([[record.from, record.from]]);
864
- const queue = [{ id: record.from, depth: 0 }];
865
- for (let index = 0; index < queue.length; index += 1) {
866
- const current = queue[index];
867
- cost.visitedNodes += 1;
868
- if (current.depth >= maxDepth)
869
- continue;
870
- const witness = expandWitnessFrontier(adjacency, record, current, parents, queue, cost);
871
- if (witness !== void 0)
872
- return witness;
873
- }
874
- return void 0;
835
+ function wassermanFaustCloseness(sweep, nodeCount) {
836
+ if (nodeCount <= 1 || sweep.reachableCount === 0)
837
+ return 0;
838
+ return sweep.reachableCount / (nodeCount - 1) * (sweep.reachableCount / sweep.distanceSum);
875
839
  }
876
- function findRedundantRelationshipEdges(graph, options = {}) {
877
- const maxDepth = options.maxDepth ?? DEFAULT_REDUNDANCY_MAX_DEPTH;
878
- assertPositiveBound("maxDepth", maxDepth);
879
- if (options.limit !== void 0)
880
- assertPositiveBound("limit", options.limit);
881
- const limit = options.limit ?? Number.POSITIVE_INFINITY;
882
- const wanted = resolveRedundancyFamilies(graph, options.kinds);
883
- const families = collectTransitiveFamilies(graph, wanted);
884
- const value = [];
840
+ function centralityRow(id, adjacency, directed, betweenness, closeness) {
841
+ return {
842
+ id,
843
+ degree: adjacency.get(id).length,
844
+ inDegree: directed.incoming.get(id)?.size ?? 0,
845
+ outDegree: directed.outgoing.get(id)?.size ?? 0,
846
+ // Undirected betweenness double-counts each ordered pair; halve it.
847
+ betweenness: roundScore((betweenness.get(id) ?? 0) / 2),
848
+ // Every node is a sweep source, so closeness is always populated.
849
+ closeness: roundScore(closeness.get(id))
850
+ };
851
+ }
852
+ function computeRelationshipCentrality(graph, options = {}) {
853
+ const adjacency = buildSimpleUndirectedAdjacency(graph, options.kinds);
854
+ const directed = collectOrderingDegrees(graph, options.kinds);
855
+ const nodes = graph.nodes();
856
+ const betweenness = /* @__PURE__ */ new Map();
857
+ const closeness = /* @__PURE__ */ new Map();
885
858
  const cost = { visitedNodes: 0, inspectedEdges: 0 };
886
- let truncated = false;
887
- scan: for (const key of [...families.keys()].sort()) {
888
- const family = families.get(key);
889
- const adjacency = sortedFamilyAdjacency(family);
890
- for (const record of family.records) {
891
- options.signal?.throwIfAborted();
892
- const witness = findWitnessPath(adjacency, record, maxDepth, cost);
893
- if (witness === void 0)
894
- continue;
895
- if (value.length >= limit) {
896
- truncated = true;
897
- break scan;
898
- }
899
- value.push({ edge: record.edge, witness });
900
- }
859
+ for (const source of nodes) {
860
+ options.signal?.throwIfAborted();
861
+ const sweep = brandesShortestPaths(source, adjacency, cost);
862
+ closeness.set(source, wassermanFaustCloseness(sweep, nodes.length));
863
+ accumulateBetweenness(sweep, source, betweenness);
901
864
  }
865
+ let degreeSum = 0;
866
+ for (const neighbors of adjacency.values())
867
+ degreeSum += neighbors.length;
868
+ const rows = nodes.map((id) => centralityRow(id, adjacency, directed, betweenness, closeness)).sort((left, right) => right.betweenness - left.betweenness || right.degree - left.degree || left.id.localeCompare(right.id));
902
869
  return {
903
- value,
870
+ value: { nodeCount: nodes.length, edgeCount: degreeSum / 2, rows },
904
871
  meta: {
905
872
  visitedNodes: cost.visitedNodes,
906
873
  inspectedEdges: cost.inspectedEdges,
907
- truncated
874
+ truncated: false
908
875
  }
909
876
  };
910
877
  }
911
- function expandReachableNode(id, depth, rows, maxDepth, state) {
912
- const nextSet = /* @__PURE__ */ new Set();
913
- const nexts = [];
914
- for (const row of rows) {
915
- if (row.id === id || nextSet.has(row.id))
916
- continue;
917
- if (!state.seen.has(row.id)) {
918
- if (depth >= maxDepth) {
919
- state.truncated = true;
920
- continue;
921
- }
922
- state.seen.add(row.id);
923
- state.queue.push({ id: row.id, depth: depth + 1 });
924
- }
925
- nextSet.add(row.id);
926
- nexts.push(row.id);
927
- let incoming = state.predecessors.get(row.id);
928
- if (incoming === void 0) {
929
- incoming = /* @__PURE__ */ new Set();
930
- state.predecessors.set(row.id, incoming);
931
- }
932
- incoming.add(id);
933
- }
934
- return nexts;
878
+ function orderedBridge(left, right) {
879
+ return left <= right ? { source: left, target: right } : { source: right, target: left };
935
880
  }
936
- function indexReachableSubgraph(graph, root, options) {
937
- const direction = options.direction ?? "outgoing";
938
- const maxDepth = options.maxDepth ?? Number.POSITIVE_INFINITY;
939
- const order = [];
940
- const successors = /* @__PURE__ */ new Map();
941
- const state = {
942
- seen: /* @__PURE__ */ new Set([root]),
943
- queue: [{ id: root, depth: 0 }],
944
- predecessors: /* @__PURE__ */ new Map(),
945
- truncated: false
946
- };
947
- let inspectedEdges = 0;
948
- for (let index = 0; index < state.queue.length; index += 1) {
949
- options.signal?.throwIfAborted();
950
- const { id, depth } = state.queue[index];
951
- order.push(id);
952
- const rows = graph.neighborEdges(id, {
953
- direction,
954
- ...options.kinds === void 0 ? {} : { kinds: options.kinds }
955
- });
956
- inspectedEdges += rows.meta.inspectedEdges;
957
- successors.set(id, expandReachableNode(id, depth, rows.value, maxDepth, state));
881
+ function advanceCutFrame(frame, adjacency, state) {
882
+ const neighbors = adjacency.get(frame.node);
883
+ const neighbor = neighbors[frame.neighborIndex];
884
+ frame.neighborIndex += 1;
885
+ state.inspectedEdges += 1;
886
+ if (neighbor === frame.parent)
887
+ return void 0;
888
+ if (state.discovery.has(neighbor)) {
889
+ state.low.set(frame.node, Math.min(state.low.get(frame.node), state.discovery.get(neighbor)));
890
+ return void 0;
958
891
  }
959
- return {
960
- order,
961
- successors,
962
- predecessors: state.predecessors,
963
- inspectedEdges,
964
- truncated: state.truncated
965
- };
892
+ frame.children += 1;
893
+ state.discovery.set(neighbor, state.timer);
894
+ state.low.set(neighbor, state.timer);
895
+ state.timer += 1;
896
+ return { node: neighbor, parent: frame.node, neighborIndex: 0, children: 0 };
966
897
  }
967
- function reversePostorder(subgraph, root) {
968
- const postorder = [];
969
- const visited = /* @__PURE__ */ new Set([root]);
970
- const stack = [{ id: root, index: 0 }];
898
+ function retreatCutFrame(frame, root, state) {
899
+ if (frame.parent === null) {
900
+ if (frame.children > 1)
901
+ state.articulation.add(frame.node);
902
+ return;
903
+ }
904
+ const parent = frame.parent;
905
+ const childLow = state.low.get(frame.node);
906
+ state.low.set(parent, Math.min(state.low.get(parent), childLow));
907
+ if (parent !== root && childLow >= state.discovery.get(parent))
908
+ state.articulation.add(parent);
909
+ if (childLow > state.discovery.get(parent))
910
+ state.bridges.push(orderedBridge(parent, frame.node));
911
+ }
912
+ function searchComponentCuts(root, adjacency, state, signal) {
913
+ state.discovery.set(root, state.timer);
914
+ state.low.set(root, state.timer);
915
+ state.timer += 1;
916
+ const stack = [
917
+ { node: root, parent: null, neighborIndex: 0, children: 0 }
918
+ ];
971
919
  while (stack.length > 0) {
920
+ signal?.throwIfAborted();
972
921
  const frame = stack.at(-1);
973
- const nexts = subgraph.successors.get(frame.id);
974
- if (frame.index < nexts.length) {
975
- const next = nexts[frame.index];
976
- frame.index += 1;
977
- if (!visited.has(next)) {
978
- visited.add(next);
979
- stack.push({ id: next, index: 0 });
980
- }
922
+ if (frame.neighborIndex < adjacency.get(frame.node).length) {
923
+ const child = advanceCutFrame(frame, adjacency, state);
924
+ if (child !== void 0)
925
+ stack.push(child);
981
926
  } else {
982
- postorder.push(frame.id);
927
+ retreatCutFrame(frame, root, state);
983
928
  stack.pop();
984
929
  }
985
930
  }
986
- return postorder.reverse();
987
931
  }
988
- function intersectDominators(left, right, idom, ordinal) {
989
- let first = left;
990
- let second = right;
991
- while (first !== second) {
992
- while (ordinal.get(first) > ordinal.get(second))
993
- first = idom.get(first);
994
- while (ordinal.get(second) > ordinal.get(first))
995
- second = idom.get(second);
996
- }
997
- return first;
998
- }
999
- function dominatorCandidate(predecessors, idom, ordinal) {
1000
- let candidate;
1001
- for (const pred of [...predecessors].sort()) {
1002
- if (!idom.has(pred))
1003
- continue;
1004
- candidate = candidate === void 0 ? pred : intersectDominators(candidate, pred, idom, ordinal);
1005
- }
1006
- return candidate;
1007
- }
1008
- function solveImmediateDominators(subgraph, root, order, ordinal, signal) {
1009
- const idom = /* @__PURE__ */ new Map([[root, root]]);
1010
- let changed = true;
1011
- while (changed) {
1012
- changed = false;
1013
- for (const id of order) {
1014
- signal?.throwIfAborted();
1015
- if (id === root)
1016
- continue;
1017
- const candidate = dominatorCandidate(subgraph.predecessors.get(id), idom, ordinal);
1018
- if (candidate !== void 0 && idom.get(id) !== candidate) {
1019
- idom.set(id, candidate);
1020
- changed = true;
1021
- }
1022
- }
1023
- }
1024
- return idom;
1025
- }
1026
- function computeRelationshipDominators(graph, root, options = {}) {
1027
- if (!graph.hasNode(root))
1028
- throw new TypeError(`Relationship node not found: ${root}`);
1029
- if (options.maxDepth !== void 0 && (!Number.isInteger(options.maxDepth) || options.maxDepth < 0))
1030
- throw new TypeError(`Invalid maxDepth bound: ${String(options.maxDepth)}`);
1031
- const subgraph = indexReachableSubgraph(graph, root, options);
1032
- const order = reversePostorder(subgraph, root);
1033
- const ordinal = new Map(order.map((id, index) => [id, index]));
1034
- const idom = solveImmediateDominators(subgraph, root, order, ordinal, options.signal);
1035
- const subtreeSizes = new Map(order.map((id) => [id, 1]));
1036
- for (let index = order.length - 1; index >= 0; index -= 1) {
1037
- const id = order[index];
1038
- if (id === root)
932
+ function findRelationshipCutStructure(graph, options = {}) {
933
+ const adjacency = buildSimpleUndirectedAdjacency(graph, options.kinds);
934
+ const state = {
935
+ discovery: /* @__PURE__ */ new Map(),
936
+ low: /* @__PURE__ */ new Map(),
937
+ timer: 0,
938
+ articulation: /* @__PURE__ */ new Set(),
939
+ bridges: [],
940
+ inspectedEdges: 0
941
+ };
942
+ for (const root of graph.nodes()) {
943
+ if (state.discovery.has(root))
1039
944
  continue;
1040
- const parent = idom.get(id);
1041
- subtreeSizes.set(parent, subtreeSizes.get(parent) + subtreeSizes.get(id));
945
+ searchComponentCuts(root, adjacency, state, options.signal);
1042
946
  }
1043
- const rows = order.filter((id) => id !== root).map((id) => ({
1044
- id,
1045
- idom: idom.get(id),
1046
- dominatedCount: subtreeSizes.get(id) - 1
1047
- })).sort((left, right) => right.dominatedCount - left.dominatedCount || left.id.localeCompare(right.id));
1048
947
  return {
1049
- value: { root, reachableCount: subgraph.order.length, rows },
948
+ value: {
949
+ articulationPoints: [...state.articulation].sort(),
950
+ bridges: state.bridges.sort((left, right) => left.source.localeCompare(right.source) || left.target.localeCompare(right.target))
951
+ },
1050
952
  meta: {
1051
- visitedNodes: subgraph.order.length,
1052
- inspectedEdges: subgraph.inspectedEdges,
1053
- truncated: subgraph.truncated
953
+ visitedNodes: state.discovery.size,
954
+ inspectedEdges: state.inspectedEdges,
955
+ truncated: false
1054
956
  }
1055
957
  };
1056
958
  }
1057
959
 
1058
- // dist/sdk/graph/governance.js
1059
- var DEFAULT_MAX_SAMPLE_SIZE = 25;
1060
- var SEVERITY_RANK = {
1061
- error: 0,
1062
- warning: 1,
1063
- info: 2
1064
- };
1065
- function buildFinding(code, severity, policy, describe, subjects, maxSampleSize, remediation) {
1066
- const sorted = [...subjects].sort((left, right) => left.localeCompare(right));
1067
- return {
1068
- code,
1069
- severity,
1070
- policy,
1071
- message: describe(sorted.length),
1072
- count: sorted.length,
1073
- sample: sorted.slice(0, maxSampleSize),
1074
- sample_truncated: sorted.length > maxSampleSize,
1075
- remediation
1076
- };
1077
- }
1078
- function buildOrderingAdjacency(assembly) {
1079
- const registry = assembly.graph.registry();
1080
- const successors = /* @__PURE__ */ new Map();
1081
- for (const edge of assembly.graph.edges()) {
960
+ // dist/sdk/graph/scheduling.js
961
+ function collectOrderingParticipation(graph) {
962
+ const registry = graph.registry();
963
+ const forward = /* @__PURE__ */ new Map();
964
+ const participants = /* @__PURE__ */ new Set();
965
+ for (const edge of graph.edges()) {
1082
966
  const definition = registry.require(edge.kind);
1083
967
  if (!definition.ordering)
1084
968
  continue;
1085
- const [predecessor, successor] = (definition.precedence ?? "source_before_target") === "target_before_source" ? [edge.target, edge.source] : [edge.source, edge.target];
1086
- const adjacent = successors.get(predecessor);
1087
- if (adjacent)
1088
- adjacent.push(successor);
969
+ const { predecessor, successor } = orientOrderingEdge(edge, definition);
970
+ participants.add(predecessor);
971
+ participants.add(successor);
972
+ if (predecessor === successor)
973
+ continue;
974
+ const targets = forward.get(predecessor);
975
+ if (targets === void 0)
976
+ forward.set(predecessor, /* @__PURE__ */ new Set([successor]));
1089
977
  else
1090
- successors.set(predecessor, [successor]);
1091
- }
1092
- for (const adjacent of successors.values())
1093
- adjacent.sort((left, right) => left.localeCompare(right));
1094
- return successors;
1095
- }
1096
- function registerTarjanNode(node, state) {
1097
- state.indexes.set(node, state.nextIndex);
1098
- state.lowLinks.set(node, state.nextIndex);
1099
- state.nextIndex += 1;
1100
- state.stack.push(node);
1101
- state.onStack.add(node);
1102
- }
1103
- function visitNextTarjanNeighbor(frame, frames, successors, state) {
1104
- const neighbors = successors.get(frame.node) ?? [];
1105
- if (frame.neighborIndex >= neighbors.length)
1106
- return false;
1107
- const neighbor = neighbors[frame.neighborIndex];
1108
- frame.neighborIndex += 1;
1109
- if (!state.indexes.has(neighbor)) {
1110
- registerTarjanNode(neighbor, state);
1111
- frames.push({ node: neighbor, neighborIndex: 0 });
1112
- } else if (state.onStack.has(neighbor)) {
1113
- state.lowLinks.set(frame.node, Math.min(state.lowLinks.get(frame.node), state.indexes.get(neighbor)));
978
+ targets.add(successor);
1114
979
  }
1115
- return true;
980
+ return { forward, participants };
1116
981
  }
1117
- function completeTarjanFrame(frame, frames, successors, state) {
1118
- frames.pop();
1119
- const parent = frames.at(-1);
1120
- if (parent)
1121
- state.lowLinks.set(parent.node, Math.min(state.lowLinks.get(parent.node), state.lowLinks.get(frame.node)));
1122
- if (state.lowLinks.get(frame.node) !== state.indexes.get(frame.node))
1123
- return;
1124
- const component = [];
1125
- while (true) {
1126
- const member = state.stack.pop();
1127
- state.onStack.delete(member);
1128
- component.push(member);
1129
- if (member === frame.node)
1130
- break;
982
+ function latestFinishFor(successors, acyclic, latestStart, makespan) {
983
+ if (successors === void 0)
984
+ return makespan;
985
+ let bound = makespan;
986
+ for (const successor of successors) {
987
+ if (!acyclic.has(successor))
988
+ continue;
989
+ bound = Math.min(bound, latestStart.get(successor));
1131
990
  }
1132
- if (component.length > 1 || component.length === 1 && successors.get(component[0])?.includes(component[0]))
1133
- state.components.push(component.sort((left, right) => left.localeCompare(right)));
991
+ return bound;
1134
992
  }
1135
- function collectOrderingCycles(successors) {
1136
- const state = {
1137
- indexes: /* @__PURE__ */ new Map(),
1138
- lowLinks: /* @__PURE__ */ new Map(),
1139
- onStack: /* @__PURE__ */ new Set(),
1140
- stack: [],
1141
- components: [],
1142
- nextIndex: 0
993
+ function scheduleRow(id, earliestStart, latestStart) {
994
+ const slack = latestStart - earliestStart;
995
+ return {
996
+ id,
997
+ earliestStart,
998
+ earliestFinish: earliestStart + 1,
999
+ latestStart,
1000
+ latestFinish: latestStart + 1,
1001
+ slack,
1002
+ critical: slack === 0
1143
1003
  };
1144
- const roots = [...successors.keys()].sort((left, right) => left.localeCompare(right));
1145
- for (const root of roots) {
1146
- if (state.indexes.has(root))
1147
- continue;
1148
- const frames = [{ node: root, neighborIndex: 0 }];
1149
- registerTarjanNode(root, state);
1150
- while (frames.length > 0) {
1151
- const frame = frames.at(-1);
1152
- if (visitNextTarjanNeighbor(frame, frames, successors, state))
1153
- continue;
1154
- completeTarjanFrame(frame, frames, successors, state);
1155
- }
1156
- }
1157
- return state.components.sort((left, right) => left[0].localeCompare(right[0]));
1158
1004
  }
1159
- function formatDanglingReference(reference) {
1160
- return `${reference.holder_id} -> ${reference.target_id} (${reference.kind})`;
1005
+ function computeScheduleRows(topoParticipants, participation, depth, acyclic, makespan) {
1006
+ const latestStart = /* @__PURE__ */ new Map();
1007
+ for (let index = topoParticipants.length - 1; index >= 0; index -= 1) {
1008
+ const id = topoParticipants[index];
1009
+ const finish = latestFinishFor(participation.forward.get(id), acyclic, latestStart, makespan);
1010
+ latestStart.set(id, finish - 1);
1011
+ }
1012
+ return topoParticipants.map((id) => scheduleRow(id, depth[id], latestStart.get(id))).sort((left, right) => left.slack - right.slack || left.earliestStart - right.earliestStart || left.id.localeCompare(right.id));
1161
1013
  }
1162
- function appendFinding(findings, subjects, maxSampleSize, code, severity, policy, describe, remediation) {
1163
- if (subjects.length === 0)
1164
- return;
1165
- findings.push(buildFinding(code, severity, policy, describe, subjects, maxSampleSize, remediation));
1166
- }
1167
- function collectIntegrityFindings(assembly, isTerminal, maxSampleSize) {
1168
- const findings = [];
1169
- const references = [
1170
- ...assembly.dangling.active,
1171
- ...assembly.dangling.legacy_terminal
1172
- ].filter((reference) => !reference.no_active_blocker_sentinel);
1173
- appendFinding(findings, references.filter((reference) => !isTerminal(reference.holder_status)).map(formatDanglingReference), maxSampleSize, "missing_reference_active", "error", "Active items must not reference absent targets; missing prerequisites distort scheduling.", (count) => `${count} active dangling reference(s) to absent items`, "Restore or re-create the referenced item, or remove/retype the reference on the holder.");
1174
- appendFinding(findings, references.filter((reference) => isTerminal(reference.holder_status)).map(formatDanglingReference), maxSampleSize, "missing_reference_terminal", "info", "Terminal items may retain historical references, but absent targets remain unexplainable context.", (count) => `${count} terminal dangling reference(s) to absent items`, "Leave as history debt or clean up in a dedicated changelog-safe closed-item batch.");
1175
- appendFinding(findings, assembly.dangling.no_active_blocker_sentinels.map(formatDanglingReference), maxSampleSize, "legacy_no_blocker_sentinel", "info", "The pre-structured-dependency no-active-blocker sentinel is retired; real edges carry blocker state.", (count) => `${count} legacy no-active-blocker sentinel reference(s)`, "Delete the sentinel reference; blocker state is derived from blocked_by edges.");
1176
- return findings;
1177
- }
1178
- function isActiveAuditMember(member, nodeStates) {
1179
- const state = nodeStates.get(member);
1180
- if (!state)
1181
- return true;
1182
- return !state.terminal;
1183
- }
1184
- function collectOrderingFindings(assembly, nodeStates, isBlocked, maxSampleSize) {
1185
- const findings = [];
1186
- const orderingAdjacency = buildOrderingAdjacency(assembly);
1187
- for (const cycle of collectOrderingCycles(orderingAdjacency)) {
1188
- const active = cycle.some((member) => isActiveAuditMember(member, nodeStates));
1189
- findings.push(active ? buildFinding("ordering_cycle", "error", "Order-bearing relationship kinds must stay acyclic; a cycle makes every member unschedulable.", (count) => `execution-order cycle across ${count} item(s)`, cycle, maxSampleSize, "Remove or retype one ordering edge inside the cycle, or split the work so precedence is linear.") : buildFinding("legacy_ordering_cycle", "info", "Ordering cycles between exclusively terminal items are historical contradictions with no scheduling effect.", (count) => `terminal-only execution-order cycle across ${count} item(s)`, cycle, maxSampleSize, "Leave as history debt, or clean up in a dedicated changelog-safe closed-item batch; never repair closed items ad hoc."));
1190
- }
1191
- const predecessorsByNode = /* @__PURE__ */ new Map();
1192
- for (const [predecessor, adjacent] of orderingAdjacency)
1193
- for (const successor of adjacent) {
1194
- const predecessors = predecessorsByNode.get(successor);
1195
- if (predecessors)
1196
- predecessors.push(predecessor);
1197
- else
1198
- predecessorsByNode.set(successor, [predecessor]);
1199
- }
1200
- const staleLifecycleBlocks = [...nodeStates.values()].filter((state) => !state.missing && !state.terminal && isBlocked(state.status) && !(predecessorsByNode.get(state.id) ?? []).some((predecessor) => {
1201
- const predecessorState = nodeStates.get(predecessor);
1202
- return predecessorState === void 0 || !predecessorState.terminal;
1203
- })).map((state) => state.id);
1204
- appendFinding(findings, staleLifecycleBlocks, maxSampleSize, "stale_lifecycle_block", "warning", "A blocked lifecycle status must be backed by at least one open ordering predecessor.", (count) => `${count} status-blocked item(s) with no open blocker edge`, "Re-open the missing prerequisite as an edge, or move the item back to an active status.");
1205
- return findings;
1206
- }
1207
- function formatDuplicateEdgeGroup(group) {
1208
- const kinds = group.edges.map((edge) => edge.kind).sort((left, right) => left.localeCompare(right));
1209
- return `${group.from} -> ${group.to} (${kinds.join(" + ")})`;
1210
- }
1211
- function collectDuplicateRelationshipEdgeGroups(assembly) {
1212
- const registry = assembly.graph.registry();
1213
- const groups = /* @__PURE__ */ new Map();
1214
- for (const edge of assembly.graph.edges()) {
1215
- const definition = registry.require(edge.kind);
1216
- if (!isTransitiveKind(definition))
1217
- continue;
1218
- const oriented = orientTransitiveEdge(edge, definition);
1219
- if (oriented.from === oriented.to)
1220
- continue;
1221
- const key = `${transitiveFamilyKey(definition)}::${oriented.from}::${oriented.to}`;
1222
- const group = groups.get(key);
1223
- if (group)
1224
- group.edges.push(edge);
1225
- else
1226
- groups.set(key, { ...oriented, edges: [edge] });
1227
- }
1228
- const duplicated = [...groups.values()].filter((group) => group.edges.length >= 2);
1229
- for (const group of duplicated)
1230
- group.edges.sort((left, right) => left.kind.localeCompare(right.kind));
1231
- return duplicated.sort((left, right) => left.from.localeCompare(right.from) || left.to.localeCompare(right.to));
1232
- }
1233
- function collectDuplicateEdgeFindings(assembly, nodeStates, maxSampleSize) {
1234
- const active = [];
1235
- const legacy = [];
1236
- for (const group of collectDuplicateRelationshipEdgeGroups(assembly)) {
1237
- const subjects = isActiveAuditMember(group.from, nodeStates) || isActiveAuditMember(group.to, nodeStates) ? active : legacy;
1238
- subjects.push(formatDuplicateEdgeGroup(group));
1239
- }
1240
- const findings = [];
1241
- appendFinding(findings, active, maxSampleSize, "duplicate_edge", "info", "One semantic relationship should be stored once; parallel same-family spellings (reciprocal inverse pairs included) add no information and skew degree metrics.", (count) => `${count} duplicated relationship(s) between active endpoints`, "Remove all but one stored spelling of the relationship; keep the canonical direction the holder declared first.");
1242
- appendFinding(findings, legacy, maxSampleSize, "legacy_duplicate_edge", "info", "Duplicated spellings between exclusively terminal items are historical noise with no scheduling effect.", (count) => `${count} duplicated relationship(s) between terminal endpoints`, "Leave as history debt or clean up in a dedicated changelog-safe closed-item batch.");
1243
- return findings;
1244
- }
1245
- function collectCoverageReport(assembly, nodeStates, exemptIsolates, maxSampleSize, edgesByKind) {
1246
- let activeNodes = 0;
1247
- let missingNodes = 0;
1248
- let isolatedActiveNodes = 0;
1249
- let degreeLeqOneActive = 0;
1250
- const isolates = [];
1251
- const sparse = [];
1252
- for (const id of assembly.graph.nodes()) {
1253
- const state = nodeStates.get(id);
1254
- if (!state)
1255
- continue;
1256
- if (state.missing) {
1257
- missingNodes += 1;
1258
- continue;
1014
+ function analyzeRelationshipSchedule(graph, options = {}) {
1015
+ options.signal?.throwIfAborted();
1016
+ const execution = analyzeRelationshipExecution(graph, { registry: graph.registry() });
1017
+ const participation = collectOrderingParticipation(graph);
1018
+ const acyclic = new Set(execution.order);
1019
+ const topoParticipants = execution.order.filter((id) => participation.participants.has(id));
1020
+ const makespan = topoParticipants.reduce((peak, id) => Math.max(peak, execution.depth[id] + 1), 0);
1021
+ const rows = computeScheduleRows(topoParticipants, participation, execution.depth, acyclic, makespan);
1022
+ const scheduled = rows.length > 0;
1023
+ return {
1024
+ exact: true,
1025
+ acyclic: execution.acyclic,
1026
+ makespan,
1027
+ scheduledCount: rows.length,
1028
+ // A single-node execution "path" over a workspace with no order-bearing
1029
+ // edge is not a real critical path, so report it only when work is scheduled.
1030
+ criticalPath: scheduled ? execution.criticalPath : [],
1031
+ criticalPathLength: scheduled ? execution.criticalPathLength : 0,
1032
+ cycles: execution.cycles,
1033
+ rows,
1034
+ provenance: {
1035
+ algorithm: "critical-path-method",
1036
+ edgeFamily: "ordering",
1037
+ weighting: "unit"
1259
1038
  }
1260
- if (state.terminal)
1261
- continue;
1262
- activeNodes += 1;
1263
- const degree = assembly.graph.incidentEdges(id).length;
1264
- if (degree > 1)
1265
- continue;
1266
- degreeLeqOneActive += 1;
1267
- if (degree === 0)
1268
- isolatedActiveNodes += 1;
1269
- if (exemptIsolates.has(id.toLowerCase()))
1270
- continue;
1271
- if (degree === 0)
1272
- isolates.push(id);
1273
- else
1274
- sparse.push(id);
1039
+ };
1040
+ }
1041
+
1042
+ // dist/sdk/graph/durable-cache.js
1043
+ import path from "node:path";
1044
+ var GRAPH_DURABLE_CACHE_VERSION = 1;
1045
+ var GRAPH_DURABLE_CACHE_MIN_ITEMS = 500;
1046
+ var MAX_DURABLE_RESULTS = 64;
1047
+ var DURABLE_GRAPH_CACHE_LOCK_ID = "graph-durable-cache";
1048
+ function acquireDurableGraphCacheLock(pmRoot) {
1049
+ return acquireLock(pmRoot, DURABLE_GRAPH_CACHE_LOCK_ID, 30, `graph-cache:${process.pid}`, false, false, 3e3);
1050
+ }
1051
+ function durableGraphCachePath(pmRoot) {
1052
+ return path.join(pmRoot, "runtime", "graph-cache.json");
1053
+ }
1054
+ function graphAuditBaselinePath(pmRoot) {
1055
+ return path.join(pmRoot, "runtime", "graph-audit-baseline.json");
1056
+ }
1057
+ function decodeEnvelope(raw) {
1058
+ if (raw === null)
1059
+ return void 0;
1060
+ try {
1061
+ const parsed = JSON.parse(raw);
1062
+ if (typeof parsed !== "object" || parsed === null || parsed.version !== GRAPH_DURABLE_CACHE_VERSION || typeof parsed.fingerprint !== "string" || typeof parsed.saved_at !== "string" || typeof parsed.results !== "object" || parsed.results === null || Array.isArray(parsed.results))
1063
+ return void 0;
1064
+ return parsed;
1065
+ } catch {
1066
+ return void 0;
1275
1067
  }
1276
- const findings = [];
1277
- appendFinding(findings, isolates, maxSampleSize, "isolated_active_node", "warning", "Active work should be reachable from the graph unless explicitly declared a valid isolate.", (count) => `${count} active item(s) with no relationships`, "Link the item to its parent, prerequisite, or origin \u2014 or register it as an exempt isolate.");
1278
- appendFinding(findings, sparse, maxSampleSize, "sparse_active_node", "info", "Active items with a single edge often miss an honest semantic partner; sparse is not automatically defective.", (count) => `${count} active item(s) with exactly one relationship`, "Investigate for an honest second edge (story->task, defect family, cross-epic complement); do not fabricate one.");
1068
+ }
1069
+ async function openDurableGraphCache(pmRoot, fingerprint) {
1070
+ const raw = await readFileIfExists(durableGraphCachePath(pmRoot));
1071
+ const envelope = decodeEnvelope(raw);
1072
+ const fresh = envelope?.fingerprint === fingerprint;
1279
1073
  return {
1280
- findings,
1281
- profile: {
1282
- nodes: assembly.graph.nodes().length,
1283
- edges: assembly.graph.edges().length,
1284
- edges_by_kind: Object.fromEntries(Object.entries(edgesByKind).sort(([left], [right]) => left.localeCompare(right))),
1285
- active_nodes: activeNodes,
1286
- missing_nodes: missingNodes,
1287
- isolated_active_nodes: isolatedActiveNodes,
1288
- degree_leq_one_active_nodes: degreeLeqOneActive
1289
- }
1074
+ exists: raw !== null,
1075
+ fresh,
1076
+ results: fresh ? envelope.results : {}
1290
1077
  };
1291
1078
  }
1292
- function auditWorkspaceRelationshipGraph(assembly, options = {}) {
1293
- const isTerminal = options.isTerminal ?? ((status) => status === "closed" || status === "canceled");
1294
- const isBlocked = options.isBlocked ?? ((status) => status === "blocked");
1295
- const maxSampleSize = options.maxSampleSize ?? DEFAULT_MAX_SAMPLE_SIZE;
1296
- if (!Number.isInteger(maxSampleSize) || maxSampleSize < 1)
1297
- throw new TypeError(`Invalid audit sample bound: ${String(options.maxSampleSize)}`);
1298
- const exemptIsolates = new Set((options.exemptIsolates ?? []).filter((id) => typeof id === "string").map((id) => id.trim().toLowerCase()));
1299
- const nodeStates = new Map(assembly.details.map((detail) => [
1300
- detail.id,
1301
- {
1302
- id: detail.id,
1303
- status: detail.status,
1304
- missing: assembly.missingIdSet.has(detail.id.toLowerCase()),
1305
- terminal: isTerminal(detail.status)
1306
- }
1307
- ]));
1308
- options.signal?.throwIfAborted();
1309
- const edgesByKind = {};
1310
- for (const edge of assembly.graph.edges())
1311
- edgesByKind[edge.kind] = (edgesByKind[edge.kind] ?? 0) + 1;
1312
- const findings = collectIntegrityFindings(assembly, isTerminal, maxSampleSize);
1313
- options.signal?.throwIfAborted();
1314
- findings.push(...collectOrderingFindings(assembly, nodeStates, isBlocked, maxSampleSize));
1315
- options.signal?.throwIfAborted();
1316
- findings.push(...collectDuplicateEdgeFindings(assembly, nodeStates, maxSampleSize));
1317
- options.signal?.throwIfAborted();
1318
- const coverage = collectCoverageReport(assembly, nodeStates, exemptIsolates, maxSampleSize, edgesByKind);
1319
- findings.push(...coverage.findings);
1320
- findings.sort((left, right) => SEVERITY_RANK[left.severity] - SEVERITY_RANK[right.severity] || left.code.localeCompare(right.code) || left.sample[0].localeCompare(right.sample[0]));
1079
+ async function persistDurableGraphResult(pmRoot, fingerprint, view, queryKey, result) {
1080
+ const release = await acquireDurableGraphCacheLock(pmRoot);
1081
+ try {
1082
+ const envelope = decodeEnvelope(await readFileIfExists(durableGraphCachePath(pmRoot)));
1083
+ const results = envelope?.fingerprint === fingerprint ? envelope.results : {};
1084
+ delete results[queryKey];
1085
+ results[queryKey] = result;
1086
+ const keys = Object.keys(results);
1087
+ for (const stale of keys.slice(0, Math.max(0, keys.length - MAX_DURABLE_RESULTS)))
1088
+ delete results[stale];
1089
+ await writeFileAtomic(durableGraphCachePath(pmRoot), JSON.stringify({
1090
+ version: GRAPH_DURABLE_CACHE_VERSION,
1091
+ fingerprint,
1092
+ saved_at: (/* @__PURE__ */ new Date()).toISOString(),
1093
+ results
1094
+ }));
1095
+ view.results = results;
1096
+ } finally {
1097
+ await release();
1098
+ }
1099
+ }
1100
+ async function clearDurableGraphCache(pmRoot) {
1101
+ const release = await acquireDurableGraphCacheLock(pmRoot);
1102
+ try {
1103
+ await removeFileIfExists(durableGraphCachePath(pmRoot));
1104
+ } finally {
1105
+ await release();
1106
+ }
1107
+ }
1108
+ async function durableGraphCacheStatus(pmRoot, fingerprint) {
1109
+ const cachePath = durableGraphCachePath(pmRoot);
1110
+ const raw = await readFileIfExists(cachePath);
1111
+ const envelope = decodeEnvelope(raw);
1112
+ if (envelope === void 0)
1113
+ return { exists: raw !== null, fresh: false, entry_count: 0 };
1321
1114
  return {
1322
- findings,
1323
- profile: coverage.profile
1115
+ exists: true,
1116
+ fresh: envelope.fingerprint === fingerprint,
1117
+ entry_count: Object.keys(envelope.results).length,
1118
+ fingerprint: envelope.fingerprint.slice(0, 12),
1119
+ saved_at: envelope.saved_at,
1120
+ bytes: Buffer.byteLength(raw, "utf8")
1324
1121
  };
1325
1122
  }
1123
+ function shouldPersistDurableGraphCache(itemCount, envelopeExists) {
1124
+ return envelopeExists || itemCount >= GRAPH_DURABLE_CACHE_MIN_ITEMS;
1125
+ }
1126
+ function isNonnegativeCountRecord(value) {
1127
+ return typeof value === "object" && value !== null && !Array.isArray(value) && Object.values(value).every((count) => Number.isInteger(count) && count >= 0);
1128
+ }
1129
+ function isNonnegativeCoverageByTypeRecord(value) {
1130
+ if (typeof value !== "object" || value === null || Array.isArray(value))
1131
+ return false;
1132
+ return Object.values(value).every((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry) && [entry.active, entry.isolated, entry.degree_leq_one].every((count) => Number.isInteger(count) && count >= 0));
1133
+ }
1134
+ function decodeBaseline(raw) {
1135
+ if (raw === null)
1136
+ return void 0;
1137
+ try {
1138
+ const parsed = JSON.parse(raw);
1139
+ if (typeof parsed !== "object" || parsed === null)
1140
+ return void 0;
1141
+ const snapshot = parsed;
1142
+ const profile = snapshot.profile;
1143
+ if (typeof snapshot.saved_at !== "string" || typeof snapshot.fingerprint !== "string" || !isNonnegativeCountRecord(snapshot.affected_subjects_by_code) || typeof profile !== "object" || profile === null || ![
1144
+ profile.nodes,
1145
+ profile.edges,
1146
+ profile.active_nodes,
1147
+ profile.missing_nodes,
1148
+ profile.isolated_active_nodes,
1149
+ profile.degree_leq_one_active_nodes
1150
+ ].every((value) => Number.isInteger(value) && value >= 0) || !isNonnegativeCountRecord(profile.edges_by_kind) || profile.coverage_by_type !== void 0 && !isNonnegativeCoverageByTypeRecord(profile.coverage_by_type))
1151
+ return void 0;
1152
+ return {
1153
+ ...snapshot,
1154
+ profile: {
1155
+ ...profile,
1156
+ coverage_by_type: profile.coverage_by_type ?? {}
1157
+ }
1158
+ };
1159
+ } catch {
1160
+ return void 0;
1161
+ }
1162
+ }
1163
+ async function loadGraphAuditBaseline(pmRoot) {
1164
+ return decodeBaseline(await readFileIfExists(graphAuditBaselinePath(pmRoot)));
1165
+ }
1166
+ async function saveGraphAuditBaseline(pmRoot, snapshot) {
1167
+ await writeFileAtomic(graphAuditBaselinePath(pmRoot), JSON.stringify(snapshot));
1168
+ }
1326
1169
 
1327
1170
  // dist/sdk/graph/remediation.js
1328
1171
  var FINDING_STEP_TEMPLATES = {
@@ -1364,6 +1207,16 @@ var FINDING_STEP_TEMPLATES = {
1364
1207
  confidence: "high",
1365
1208
  rationale: "Duplicated spellings between terminal items are historical noise; waive or batch changelog-safe cleanup."
1366
1209
  },
1210
+ duplicate_dependency_row: {
1211
+ op: "remove",
1212
+ confidence: "high",
1213
+ rationale: "The identical dependency row is stored more than once on the holder; drop the repeats so the row exists exactly once \u2014 graph semantics are unchanged."
1214
+ },
1215
+ legacy_duplicate_dependency_row: {
1216
+ op: "waive",
1217
+ confidence: "high",
1218
+ rationale: "Repeated identical rows on terminal holders are storage noise; waive or clean up only in a changelog-safe closed-item batch."
1219
+ },
1367
1220
  stale_lifecycle_block: {
1368
1221
  op: "investigate",
1369
1222
  confidence: "medium",
@@ -1543,10 +1396,10 @@ function runGraphPaths(root, target, invocation) {
1543
1396
  count: result.value.length,
1544
1397
  ...projectQueryMeta(result.meta),
1545
1398
  ...invocation.summary ? {} : {
1546
- paths: result.value.map((path3) => ({
1547
- nodes: path3.nodes,
1548
- kinds: path3.edges.map((edge) => edge.kind),
1549
- length: path3.length
1399
+ paths: result.value.map((path4) => ({
1400
+ nodes: path4.nodes,
1401
+ kinds: path4.edges.map((edge) => edge.kind),
1402
+ length: path4.length
1550
1403
  }))
1551
1404
  }
1552
1405
  };
@@ -1611,7 +1464,8 @@ function runGraphAudit(invocation, isTerminal) {
1611
1464
  const report = auditWorkspaceRelationshipGraph(invocation.assembly, {
1612
1465
  isTerminal,
1613
1466
  ...invocation.sample === void 0 ? {} : { maxSampleSize: invocation.sample },
1614
- ...invocation.exemptIsolates.length === 0 ? {} : { exemptIsolates: invocation.exemptIsolates }
1467
+ ...invocation.exemptIsolates.length === 0 ? {} : { exemptIsolates: invocation.exemptIsolates },
1468
+ ...invocation.exemptIsolateTypes.length === 0 ? {} : { isolateExemptTypes: invocation.exemptIsolateTypes }
1615
1469
  });
1616
1470
  const bySeverity = {};
1617
1471
  const byCode = {};
@@ -1713,13 +1567,87 @@ function runGraphDominators(root, invocation) {
1713
1567
  }
1714
1568
  };
1715
1569
  }
1570
+ function runGraphSlack(invocation) {
1571
+ const limit = invocation.limit ?? DEFAULT_SAMPLE_LIMIT;
1572
+ const analysis = analyzeRelationshipSchedule(invocation.assembly.graph);
1573
+ const criticalCount = analysis.rows.filter((row) => row.critical).length;
1574
+ return {
1575
+ subcommand: "slack",
1576
+ acyclic: analysis.acyclic,
1577
+ makespan: analysis.makespan,
1578
+ scheduled_count: analysis.scheduledCount,
1579
+ critical_count: criticalCount,
1580
+ critical_path_length: analysis.criticalPathLength,
1581
+ cycle_count: analysis.cycles.length,
1582
+ truncated: analysis.rows.length > limit,
1583
+ ...invocation.summary ? {} : {
1584
+ critical_path: analysis.criticalPath,
1585
+ rows: analysis.rows.slice(0, limit).map((row) => ({
1586
+ id: row.id,
1587
+ earliest_start: row.earliestStart,
1588
+ latest_start: row.latestStart,
1589
+ slack: row.slack,
1590
+ critical: row.critical
1591
+ }))
1592
+ }
1593
+ };
1594
+ }
1595
+ function runGraphCentrality(invocation) {
1596
+ const limit = invocation.limit ?? DEFAULT_SAMPLE_LIMIT;
1597
+ const result = computeRelationshipCentrality(invocation.assembly.graph, {
1598
+ ...invocation.kinds === void 0 ? {} : { kinds: invocation.kinds }
1599
+ });
1600
+ const analysis = result.value;
1601
+ return {
1602
+ subcommand: "centrality",
1603
+ node_count: analysis.nodeCount,
1604
+ edge_count: analysis.edgeCount,
1605
+ truncated: analysis.rows.length > limit,
1606
+ cost: {
1607
+ visited_nodes: result.meta.visitedNodes,
1608
+ inspected_edges: result.meta.inspectedEdges
1609
+ },
1610
+ ...invocation.summary ? {} : {
1611
+ rows: analysis.rows.slice(0, limit).map((row) => ({
1612
+ id: row.id,
1613
+ degree: row.degree,
1614
+ in_degree: row.inDegree,
1615
+ out_degree: row.outDegree,
1616
+ betweenness: row.betweenness,
1617
+ closeness: row.closeness
1618
+ }))
1619
+ }
1620
+ };
1621
+ }
1622
+ function runGraphArticulation(invocation) {
1623
+ const limit = invocation.limit ?? DEFAULT_SAMPLE_LIMIT;
1624
+ const result = findRelationshipCutStructure(invocation.assembly.graph, {
1625
+ ...invocation.kinds === void 0 ? {} : { kinds: invocation.kinds }
1626
+ });
1627
+ const { articulationPoints, bridges } = result.value;
1628
+ return {
1629
+ subcommand: "articulation",
1630
+ articulation_count: articulationPoints.length,
1631
+ bridge_count: bridges.length,
1632
+ truncated: articulationPoints.length > limit || bridges.length > limit,
1633
+ cost: {
1634
+ visited_nodes: result.meta.visitedNodes,
1635
+ inspected_edges: result.meta.inspectedEdges
1636
+ },
1637
+ ...invocation.summary ? {} : {
1638
+ articulation_points: articulationPoints.slice(0, limit),
1639
+ bridges: bridges.slice(0, limit)
1640
+ }
1641
+ };
1642
+ }
1716
1643
  function runGraphPlan(invocation, isTerminal) {
1717
1644
  const limit = invocation.limit ?? DEFAULT_SAMPLE_LIMIT;
1718
1645
  const plan = planRelationshipRemediation(invocation.assembly, {
1719
1646
  isTerminal,
1720
1647
  redundancyLimit: limit,
1721
1648
  ...invocation.sample === void 0 ? {} : { maxSampleSize: invocation.sample },
1722
- ...invocation.exemptIsolates.length === 0 ? {} : { exemptIsolates: invocation.exemptIsolates }
1649
+ ...invocation.exemptIsolates.length === 0 ? {} : { exemptIsolates: invocation.exemptIsolates },
1650
+ ...invocation.exemptIsolateTypes.length === 0 ? {} : { isolateExemptTypes: invocation.exemptIsolateTypes }
1723
1651
  });
1724
1652
  const byOp = {};
1725
1653
  const byCode = {};
@@ -1758,6 +1686,9 @@ function buildGraphQueryKey(subcommand, root, pathsTarget, invocation) {
1758
1686
  exemptIsolates: [
1759
1687
  ...new Set(invocation.exemptIsolates.map((id) => id.toLowerCase()))
1760
1688
  ].sort(),
1689
+ exemptIsolateTypes: [
1690
+ ...new Set(invocation.exemptIsolateTypes.map((type) => type.toLowerCase()))
1691
+ ].sort(),
1761
1692
  summary: invocation.summary
1762
1693
  });
1763
1694
  }
@@ -1774,12 +1705,82 @@ function executeGraphSubcommand(subcommand, root, pathsTarget, invocation, isTer
1774
1705
  return runGraphRedundancy(invocation);
1775
1706
  if (subcommand === "dominators")
1776
1707
  return runGraphDominators(root, invocation);
1708
+ if (subcommand === "slack")
1709
+ return runGraphSlack(invocation);
1710
+ if (subcommand === "centrality")
1711
+ return runGraphCentrality(invocation);
1712
+ if (subcommand === "articulation")
1713
+ return runGraphArticulation(invocation);
1777
1714
  if (subcommand === "paths")
1778
1715
  return runGraphPaths(root, pathsTarget, invocation);
1779
1716
  if (subcommand === "impact")
1780
1717
  return runGraphImpact(root, invocation);
1781
1718
  return runGraphTraversal(subcommand, root, invocation);
1782
1719
  }
1720
+ function assertGraphFlagScope(subcommand, options) {
1721
+ if (subcommand !== "index" && (options.rebuild === true || options.clear === true))
1722
+ throw new PmCliError("--rebuild and --clear apply only to graph index.", EXIT_CODE.USAGE);
1723
+ if (subcommand !== "audit" && options.saveBaseline === true)
1724
+ throw new PmCliError("--save-baseline applies only to graph audit.", EXIT_CODE.USAGE);
1725
+ if (subcommand === "slack" && options.kind !== void 0)
1726
+ throw new PmCliError("graph slack analyzes every ordering kind; --kind is not supported.", EXIT_CODE.USAGE);
1727
+ if (options.rebuild === true && options.clear === true)
1728
+ throw new PmCliError("graph index accepts either --rebuild or --clear, not both.", EXIT_CODE.USAGE);
1729
+ }
1730
+ async function runGraphIndex(pmRoot, fingerprint, invocation, itemCount, isTerminal, options) {
1731
+ let action = "status";
1732
+ if (options.clear === true) {
1733
+ await clearDurableGraphCache(pmRoot);
1734
+ action = "cleared";
1735
+ }
1736
+ if (options.rebuild === true) {
1737
+ await clearDurableGraphCache(pmRoot);
1738
+ const view = await openDurableGraphCache(pmRoot, fingerprint);
1739
+ const warmInvocation = {
1740
+ assembly: invocation.assembly,
1741
+ direction: "both",
1742
+ exemptIsolates: [],
1743
+ exemptIsolateTypes: [],
1744
+ saveBaseline: false,
1745
+ summary: true
1746
+ };
1747
+ for (const warm of ["analyze", "audit"]) {
1748
+ await persistDurableGraphResult(pmRoot, fingerprint, view, buildGraphQueryKey(warm, void 0, void 0, warmInvocation), executeGraphSubcommand(warm, void 0, void 0, warmInvocation, isTerminal));
1749
+ }
1750
+ action = "rebuilt";
1751
+ }
1752
+ const status = await durableGraphCacheStatus(pmRoot, fingerprint);
1753
+ return {
1754
+ subcommand: "index",
1755
+ action,
1756
+ state: status.exists ? status.fresh ? "fresh" : "stale" : "absent",
1757
+ entry_count: status.entry_count,
1758
+ item_count: itemCount,
1759
+ min_items_threshold: GRAPH_DURABLE_CACHE_MIN_ITEMS,
1760
+ persist_enabled: shouldPersistDurableGraphCache(itemCount, status.exists),
1761
+ current_fingerprint: fingerprint.slice(0, 12),
1762
+ ...status.saved_at === void 0 ? {} : { saved_at: status.saved_at },
1763
+ ...status.bytes === void 0 ? {} : { bytes: status.bytes }
1764
+ };
1765
+ }
1766
+ async function applyAuditBaseline(pmRoot, fingerprint, audit, saveBaseline) {
1767
+ const current = {
1768
+ saved_at: (/* @__PURE__ */ new Date()).toISOString(),
1769
+ fingerprint,
1770
+ affected_subjects_by_code: audit.affected_subjects_by_code,
1771
+ profile: audit.profile
1772
+ };
1773
+ const stored = await loadGraphAuditBaseline(pmRoot);
1774
+ if (saveBaseline)
1775
+ await saveGraphAuditBaseline(pmRoot, current);
1776
+ return stored === void 0 ? audit : { ...audit, baseline: diffRelationshipAuditSnapshots(stored, current) };
1777
+ }
1778
+ async function persistDurableGraphResultBestEffort(pmRoot, fingerprint, view, queryKey, result) {
1779
+ try {
1780
+ await persistDurableGraphResult(pmRoot, fingerprint, view, queryKey, result);
1781
+ } catch {
1782
+ }
1783
+ }
1783
1784
  async function runGraph(subcommandRaw, id, target, options, global) {
1784
1785
  const subcommand = parseGraphSubcommand(subcommandRaw, id, target);
1785
1786
  const pmRoot = resolvePmRoot(process.cwd(), global.path);
@@ -1791,8 +1792,10 @@ async function runGraph(subcommandRaw, id, target, options, global) {
1791
1792
  const items = await listAllItemMetadataLight(pmRoot, settings.item_format, typeRegistry.type_to_folder, void 0, settings.schema);
1792
1793
  const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);
1793
1794
  const isTerminal = (status) => isTerminalStatus(status, statusRegistry);
1794
- const kinds = parseKinds(options.kind);
1795
- const lookup = workspaceGraphCache().lookup(pmRoot, computeWorkspaceGraphFingerprint(items, isTerminal), () => assembleWorkspaceRelationshipGraph(items, isTerminal));
1795
+ assertGraphFlagScope(subcommand, options);
1796
+ const relationshipRegistry = resolveWorkspaceRelationshipKindRegistry();
1797
+ const kinds = parseKinds(options.kind, relationshipRegistry);
1798
+ const lookup = workspaceGraphCache().lookup(pmRoot, computeWorkspaceGraphFingerprint(items, isTerminal, relationshipRegistry), () => assembleWorkspaceRelationshipGraph(items, isTerminal, relationshipRegistry));
1796
1799
  const invocation = {
1797
1800
  assembly: lookup.assembly,
1798
1801
  ...kinds === void 0 ? {} : { kinds },
@@ -1803,17 +1806,31 @@ async function runGraph(subcommandRaw, id, target, options, global) {
1803
1806
  maxPaths: parsePositiveInteger(options.maxPaths, "max-paths"),
1804
1807
  sample: parsePositiveInteger(options.sample, "sample"),
1805
1808
  exemptIsolates: normalizeIdList(options.exemptIsolate),
1809
+ exemptIsolateTypes: normalizeIdList(options.exemptIsolateType),
1810
+ saveBaseline: options.saveBaseline === true,
1806
1811
  summary: options.summary === true
1807
1812
  };
1813
+ if (subcommand === "index") {
1814
+ return runGraphIndex(pmRoot, lookup.fingerprint, invocation, items.length, isTerminal, options);
1815
+ }
1808
1816
  const root = ROOTED_SUBCOMMANDS.has(subcommand) ? canonicalizeGraphId(invocation.assembly, id) : void 0;
1809
1817
  const pathsTarget = subcommand === "paths" ? canonicalizeGraphId(invocation.assembly, target) : void 0;
1810
- const memo = lookup.memoize(buildGraphQueryKey(subcommand, root, pathsTarget, invocation), () => executeGraphSubcommand(subcommand, root, pathsTarget, invocation, isTerminal));
1818
+ const queryKey = buildGraphQueryKey(subcommand, root, pathsTarget, invocation);
1819
+ const durableView = await openDurableGraphCache(pmRoot, lookup.fingerprint);
1820
+ const durableValue = durableView.results[queryKey];
1821
+ const memo = lookup.memoize(queryKey, () => durableValue !== void 0 ? structuredClone(durableValue) : executeGraphSubcommand(subcommand, root, pathsTarget, invocation, isTerminal));
1822
+ const persistEnabled = shouldPersistDurableGraphCache(items.length, durableView.exists);
1823
+ if (!memo.reused && durableValue === void 0 && persistEnabled) {
1824
+ await persistDurableGraphResultBestEffort(pmRoot, lookup.fingerprint, durableView, queryKey, memo.value);
1825
+ }
1826
+ const value = memo.value.subcommand === "audit" ? await applyAuditBaseline(pmRoot, lookup.fingerprint, memo.value, invocation.saveBaseline) : memo.value;
1811
1827
  return {
1812
- ...memo.value,
1828
+ ...value,
1813
1829
  cache: {
1814
1830
  fingerprint: lookup.fingerprint.slice(0, 12),
1815
1831
  assembly: lookup.assemblyReused ? "hit" : "miss",
1816
- result: memo.reused ? "hit" : "miss"
1832
+ result: memo.reused ? "hit" : "miss",
1833
+ durable: durableValue !== void 0 ? "hit" : persistEnabled ? "miss" : "off"
1817
1834
  }
1818
1835
  };
1819
1836
  }
@@ -2207,7 +2224,7 @@ async function runGet(id, global, options = {}) {
2207
2224
 
2208
2225
  // dist/sdk/query/search.js
2209
2226
  import fs from "node:fs/promises";
2210
- import path from "node:path";
2227
+ import path2 from "node:path";
2211
2228
 
2212
2229
  // dist/core/shared/text-normalization.js
2213
2230
  function normalizeLowercaseWhitespace(value) {
@@ -3109,7 +3126,7 @@ function collectLinkedPaths(item) {
3109
3126
  return [...deduped.values()];
3110
3127
  }
3111
3128
  async function resolveContainmentRoot(root) {
3112
- const resolved = path.resolve(root);
3129
+ const resolved = path2.resolve(root);
3113
3130
  try {
3114
3131
  const realpathRoot = await fs.realpath(resolved);
3115
3132
  return {
@@ -3138,7 +3155,7 @@ async function loadLinkedCorpus(document, roots) {
3138
3155
  if (!containmentRoot) {
3139
3156
  continue;
3140
3157
  }
3141
- const resolved = path.resolve(containmentRoot.resolved, linkedPath.path);
3158
+ const resolved = path2.resolve(containmentRoot.resolved, linkedPath.path);
3142
3159
  if (!isPathWithinDirectory(containmentRoot.resolved, resolved)) {
3143
3160
  continue;
3144
3161
  }
@@ -3960,7 +3977,7 @@ async function loadDocuments(pmRoot, itemFormat, typeToFolder, schema) {
3960
3977
  try {
3961
3978
  return await tryRead(alternatePath, alternateFormat);
3962
3979
  } catch {
3963
- listWarnings.push(`item_list_item_read_failed:${path.relative(pmRoot, alternatePath)}`);
3980
+ listWarnings.push(`item_list_item_read_failed:${path2.relative(pmRoot, alternatePath)}`);
3964
3981
  return "";
3965
3982
  }
3966
3983
  }
@@ -4465,7 +4482,7 @@ async function runSearch(rawQuery, rawOptions, global) {
4465
4482
 
4466
4483
  // dist/sdk/eval.js
4467
4484
  import fs2 from "node:fs/promises";
4468
- import path2 from "node:path";
4485
+ import path3 from "node:path";
4469
4486
 
4470
4487
  // dist/core/search/eval.js
4471
4488
  var DEFAULT_EVAL_K = 10;
@@ -4604,7 +4621,7 @@ function parseEvalQuerySet(raw) {
4604
4621
  }
4605
4622
 
4606
4623
  // dist/sdk/eval.js
4607
- var DEFAULT_EVAL_QUERIES_RELATIVE_PATH = path2.join("search", "eval-queries.json");
4624
+ var DEFAULT_EVAL_QUERIES_RELATIVE_PATH = path3.join("search", "eval-queries.json");
4608
4625
  var VALID_EVAL_MODES2 = /* @__PURE__ */ new Set([
4609
4626
  "keyword",
4610
4627
  "semantic",
@@ -4685,7 +4702,7 @@ var validateEvalQuerySet = (parsed) => {
4685
4702
  }
4686
4703
  };
4687
4704
  var loadEvalQuerySet = async (queriesPath) => validateEvalQuerySet(parseEvalQuerySetJson(await readEvalQuerySetFile(queriesPath), queriesPath));
4688
- var resolveEvalQueriesPath = (pmRoot, queries) => queries ? path2.resolve(process.cwd(), queries) : path2.join(pmRoot, DEFAULT_EVAL_QUERIES_RELATIVE_PATH);
4705
+ var resolveEvalQueriesPath = (pmRoot, queries) => queries ? path3.resolve(process.cwd(), queries) : path3.join(pmRoot, DEFAULT_EVAL_QUERIES_RELATIVE_PATH);
4689
4706
  var evaluateEvalQuery = async (evalQuery, defaultMode, k, global) => {
4690
4707
  const mode = evalQuery.mode ?? defaultMode;
4691
4708
  const searchResult = await runSearch(evalQuery.query, { mode, limit: String(k), fields: "id" }, global);
@@ -4743,17 +4760,24 @@ var runEval = async (options, global) => {
4743
4760
 
4744
4761
  export {
4745
4762
  runAggregate,
4746
- hierarchyAncestors,
4747
- hierarchyDescendants,
4748
- orderingPredecessors,
4749
- orderingSuccessors,
4750
- enumerateRelationshipPaths,
4751
- detectRelationshipCommunities,
4752
- findRedundantRelationshipEdges,
4753
- computeRelationshipDominators,
4754
- formatDuplicateEdgeGroup,
4755
- collectDuplicateRelationshipEdgeGroups,
4756
- auditWorkspaceRelationshipGraph,
4763
+ analyzeRelationshipExecution,
4764
+ analyzeGraphImpact,
4765
+ analyzeKnowledgeGraph,
4766
+ compareRelationshipSnapshots,
4767
+ computeRelationshipCentrality,
4768
+ findRelationshipCutStructure,
4769
+ analyzeRelationshipSchedule,
4770
+ GRAPH_DURABLE_CACHE_VERSION,
4771
+ GRAPH_DURABLE_CACHE_MIN_ITEMS,
4772
+ durableGraphCachePath,
4773
+ graphAuditBaselinePath,
4774
+ openDurableGraphCache,
4775
+ persistDurableGraphResult,
4776
+ clearDurableGraphCache,
4777
+ durableGraphCacheStatus,
4778
+ shouldPersistDurableGraphCache,
4779
+ loadGraphAuditBaseline,
4780
+ saveGraphAuditBaseline,
4757
4781
  planRelationshipRemediation,
4758
4782
  parseGraphSubcommand,
4759
4783
  runGraph,
@@ -4767,6 +4791,6 @@ export {
4767
4791
  DEFAULT_EVAL_QUERIES_RELATIVE_PATH,
4768
4792
  runEval
4769
4793
  };
4770
- //# sourceMappingURL=chunk-NHT3F4WZ.js.map
4794
+ //# sourceMappingURL=chunk-NUF7ROFH.js.map
4771
4795
 
4772
- //# debugId=4c8b3841-40b8-5707-9154-ff020ed23bfd
4796
+ //# debugId=405abecd-c7c4-543d-be2a-eb3e5168def7