@unbrained/pm-cli 2026.8.7 → 2026.8.8

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 (226) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +35 -0
  3. package/dist/cli/main.js +4 -3
  4. package/dist/cli/register-annotations.d.ts +11 -0
  5. package/dist/cli/register-annotations.js +195 -0
  6. package/dist/cli/register-history-author.js +7 -30
  7. package/dist/cli/register-mutation.js +25 -206
  8. package/dist/cli/runtime-compatibility-boundary.d.ts +17 -0
  9. package/dist/cli/runtime-compatibility-boundary.js +43 -0
  10. package/dist/cli-bundle/bundle-manifest.json +155 -691
  11. package/dist/cli-bundle/chunks/chunk-2ZMXX3Q6.js +2068 -0
  12. package/dist/cli-bundle/chunks/chunk-ALDHXLPS.js +3 -0
  13. package/dist/cli-bundle/chunks/chunk-CBLA33YK.js +8 -0
  14. package/dist/cli-bundle/chunks/chunk-GKA54IJM.js +5 -0
  15. package/dist/cli-bundle/chunks/chunk-KRY7SRUO.js +2 -0
  16. package/dist/cli-bundle/chunks/chunk-MNJ4NNSY.js +26 -0
  17. package/dist/cli-bundle/chunks/chunk-NUXRRNAB.js +77 -0
  18. package/dist/cli-bundle/chunks/chunk-OJPCFDDY.js +13 -0
  19. package/dist/cli-bundle/chunks/chunk-PFSD3DAN.js +194 -0
  20. package/dist/cli-bundle/chunks/chunk-QWRRFYK3.js +2 -0
  21. package/dist/cli-bundle/chunks/chunk-SQ7QZFQ6.js +2 -0
  22. package/dist/cli-bundle/chunks/{register-list-query-FJZCJ67O.js → register-list-query-WFZAMJHZ.js} +8 -8
  23. package/dist/cli-bundle/chunks/register-mutation-SOKKOTHQ.js +20 -0
  24. package/dist/cli-bundle/chunks/register-operations-5XQETS6E.js +2 -0
  25. package/dist/cli-bundle/chunks/register-setup-2HL5ZHMK.js +2 -0
  26. package/dist/cli-bundle/focused-chunks/chunk-54EU2UVO.js +2 -0
  27. package/dist/cli-bundle/focused-chunks/{chunk-VZFU2R4M.js → chunk-5FLBTZJQ.js} +2 -2
  28. package/dist/cli-bundle/focused-chunks/chunk-5GJ57YKN.js +2 -0
  29. package/dist/cli-bundle/focused-chunks/{chunk-HNL6IFGS.js → chunk-ANTMGYLI.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/chunk-CMDS3KYT.js +14 -0
  31. package/dist/cli-bundle/focused-chunks/{chunk-NBJKQP4S.js → chunk-DMKOMTTY.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/{chunk-CIXVQPB7.js → chunk-F5B3HBEZ.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/{chunk-R2LEMEV5.js → chunk-FI6DWU2M.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/{chunk-3K4XV2BF.js → chunk-FNOKJG6N.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/{chunk-RW5IYD4J.js → chunk-FPDYXZBK.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/{chunk-QHRTT7WT.js → chunk-GWI6YIKJ.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/{chunk-MHMTKV5V.js → chunk-HCUC62AB.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/{chunk-MOTJFQ3F.js → chunk-HGNKPSCB.js} +12 -12
  39. package/dist/cli-bundle/focused-chunks/{chunk-4VJQTS3P.js → chunk-IAS7PMLG.js} +2 -2
  40. package/dist/cli-bundle/focused-chunks/{chunk-TIKDBG4D.js → chunk-PL2EYDJK.js} +27 -27
  41. package/dist/cli-bundle/focused-chunks/chunk-SM2PJGP3.js +2 -0
  42. package/dist/cli-bundle/focused-chunks/{chunk-RPNYG5MO.js → chunk-TCSAPH33.js} +2 -2
  43. package/dist/cli-bundle/focused-chunks/chunk-U646T7Z6.js +18 -0
  44. package/dist/cli-bundle/focused-chunks/chunk-YKPE4PPY.js +2 -0
  45. package/dist/cli-bundle/focused-chunks/{chunk-YZEZAPJK.js → chunk-YSAHYUXX.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/{chunk-73JUDYXT.js → chunk-ZOLDTUU7.js} +2 -2
  47. package/dist/cli-bundle/main.js +13 -13
  48. package/dist/cli-bundle/sdk-authoring.js +1 -1
  49. package/dist/cli-bundle/sdk-contracts.js +1 -1
  50. package/dist/cli-bundle/sdk-core.js +38 -38
  51. package/dist/cli-bundle/sdk-governance.js +1 -1
  52. package/dist/cli-bundle/sdk-graph.js +1 -1
  53. package/dist/cli-bundle/sdk-merge.js +1 -1
  54. package/dist/cli-bundle/sdk-query.js +1 -1
  55. package/dist/cli-bundle/sdk-runtime.js +1 -1
  56. package/dist/cli-bundle/sdk-testing.js +1 -1
  57. package/dist/cli-bundle/sdk.js +2 -1
  58. package/dist/cli.js +14 -4
  59. package/dist/core/output/output.js +9 -2
  60. package/dist/core/sentry/helpers.d.ts +10 -0
  61. package/dist/core/sentry/helpers.js +59 -4
  62. package/dist/core/shared/constants.d.ts +2 -0
  63. package/dist/core/shared/constants.js +4 -2
  64. package/dist/sdk/annotations.d.ts +40 -0
  65. package/dist/sdk/annotations.js +61 -9
  66. package/dist/sdk/author-attribution.d.ts +12 -0
  67. package/dist/sdk/author-attribution.js +73 -11
  68. package/dist/sdk/cli-contracts/command-exit-contracts.d.ts +118 -0
  69. package/dist/sdk/cli-contracts/command-exit-contracts.js +152 -0
  70. package/dist/sdk/cli-contracts/completeness.js +5 -3
  71. package/dist/sdk/cli-contracts/flag-contracts.js +5 -2
  72. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +11 -0
  73. package/dist/sdk/cli-contracts/runtime-contracts.js +29 -2
  74. package/dist/sdk/cli-contracts/tool-parameter-tables.js +15 -2
  75. package/dist/sdk/cli-contracts/tool-schema.d.ts +1 -1
  76. package/dist/sdk/cli-contracts/tool-schema.js +6 -3
  77. package/dist/sdk/comments.d.ts +7 -0
  78. package/dist/sdk/comments.js +2 -2
  79. package/dist/sdk/completion.js +9 -5
  80. package/dist/sdk/contracts.d.ts +1 -0
  81. package/dist/sdk/contracts.js +3 -2
  82. package/dist/sdk/environment/host-environment-errors.d.ts +27 -0
  83. package/dist/sdk/environment/host-environment-errors.js +124 -0
  84. package/dist/sdk/environment/project-runtime-compatibility.d.ts +65 -0
  85. package/dist/sdk/environment/project-runtime-compatibility.js +385 -0
  86. package/dist/sdk/environment/source-context.d.ts +23 -0
  87. package/dist/sdk/environment/source-context.js +29 -0
  88. package/dist/sdk/error-code-catalog.d.ts +6 -0
  89. package/dist/sdk/error-code-catalog.js +62 -8
  90. package/dist/sdk/generated-error-code-catalog.js +629 -3
  91. package/dist/sdk/governance/health.d.ts +11 -3
  92. package/dist/sdk/governance/health.js +5 -5
  93. package/dist/sdk/index.d.ts +7 -3
  94. package/dist/sdk/index.js +9 -5
  95. package/dist/sdk/learnings.d.ts +15 -0
  96. package/dist/sdk/learnings.js +2 -2
  97. package/dist/sdk/lifecycle/close-many.d.ts +6 -1
  98. package/dist/sdk/lifecycle/close-many.js +43 -5
  99. package/dist/sdk/lifecycle/update-many.d.ts +2 -1
  100. package/dist/sdk/lifecycle/update-many.js +29 -5
  101. package/dist/sdk/merge/index.d.ts +1 -1
  102. package/dist/sdk/merge/index.js +3 -3
  103. package/dist/sdk/merge/install.d.ts +21 -0
  104. package/dist/sdk/merge/install.js +50 -20
  105. package/dist/sdk/notes.d.ts +7 -0
  106. package/dist/sdk/notes.js +2 -2
  107. package/dist/sdk/read-output-contracts.js +83 -4
  108. package/dist/sdk/runtime.d.ts +1 -1
  109. package/dist/sdk/runtime.js +9 -25
  110. package/dist/sdk/test/execution.js +4 -2
  111. package/dist/sdk/test/parsers.js +5 -2
  112. package/dist/sdk/workspace-snapshot.d.ts +9 -0
  113. package/dist/sdk/workspace-snapshot.js +48 -16
  114. package/docs/AGENT_RUNTIME_PRIMITIVES.md +11 -4
  115. package/docs/README.md +1 -0
  116. package/docs/RELEASING.md +27 -2
  117. package/docs/SCRIPTING.md +27 -1
  118. package/docs/SDK_CONTEXT_INTEGRITY.md +66 -0
  119. package/docs/SDK_RUNTIME_BOUNDARIES.md +58 -0
  120. package/docs/SELF_DESCRIBING_CONTEXT_CONTRACTS.md +13 -0
  121. package/docs/TESTING.md +17 -0
  122. package/marketplace.json +2 -2
  123. package/package.json +5 -3
  124. package/packages/pm-beads/package.json +1 -1
  125. package/packages/pm-calendar/package.json +1 -1
  126. package/packages/pm-command-kit/package.json +1 -1
  127. package/packages/pm-digital-twin/package.json +1 -1
  128. package/packages/pm-governance-audit/package.json +1 -1
  129. package/packages/pm-guide-shell/package.json +1 -1
  130. package/packages/pm-kanban/package.json +1 -1
  131. package/packages/pm-lifecycle-hooks/package.json +1 -1
  132. package/packages/pm-linked-test-adapters/package.json +1 -1
  133. package/packages/pm-search-advanced/package.json +1 -1
  134. package/packages/pm-templates/package.json +1 -1
  135. package/packages/pm-todos/package.json +1 -1
  136. package/packages/pm-vcs/package.json +1 -1
  137. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  138. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  139. package/sdk/public-surface.json +529 -34
  140. package/dist/cli-bundle/chunks/append-7BXBFDGD.js +0 -2
  141. package/dist/cli-bundle/chunks/chunk-2AXF3VSK.js +0 -2
  142. package/dist/cli-bundle/chunks/chunk-2XS43CCV.js +0 -2
  143. package/dist/cli-bundle/chunks/chunk-3A6KWB72.js +0 -8
  144. package/dist/cli-bundle/chunks/chunk-3ISTDB42.js +0 -8
  145. package/dist/cli-bundle/chunks/chunk-4MTI7XOV.js +0 -5
  146. package/dist/cli-bundle/chunks/chunk-6BX5UDCN.js +0 -3
  147. package/dist/cli-bundle/chunks/chunk-6QPO7KLR.js +0 -2
  148. package/dist/cli-bundle/chunks/chunk-7MXHZHSQ.js +0 -5
  149. package/dist/cli-bundle/chunks/chunk-7ZPMJW4U.js +0 -2
  150. package/dist/cli-bundle/chunks/chunk-A6KGKEWT.js +0 -2
  151. package/dist/cli-bundle/chunks/chunk-AGYNSNCI.js +0 -2
  152. package/dist/cli-bundle/chunks/chunk-B4H7FEFH.js +0 -5
  153. package/dist/cli-bundle/chunks/chunk-B4KLBBMN.js +0 -2
  154. package/dist/cli-bundle/chunks/chunk-BXCSXK4J.js +0 -2
  155. package/dist/cli-bundle/chunks/chunk-CALJHNBL.js +0 -23
  156. package/dist/cli-bundle/chunks/chunk-CFIGP5LY.js +0 -2
  157. package/dist/cli-bundle/chunks/chunk-CHOQ2VAW.js +0 -2
  158. package/dist/cli-bundle/chunks/chunk-CS6MRHG7.js +0 -2
  159. package/dist/cli-bundle/chunks/chunk-CUGNQQKH.js +0 -2
  160. package/dist/cli-bundle/chunks/chunk-D4FPS43D.js +0 -164
  161. package/dist/cli-bundle/chunks/chunk-E2ZSLTOP.js +0 -2
  162. package/dist/cli-bundle/chunks/chunk-FB7G2HY2.js +0 -2
  163. package/dist/cli-bundle/chunks/chunk-H5Y5YE6A.js +0 -2
  164. package/dist/cli-bundle/chunks/chunk-H5Y6UV6E.js +0 -2
  165. package/dist/cli-bundle/chunks/chunk-H7KGWPDF.js +0 -2
  166. package/dist/cli-bundle/chunks/chunk-HFSD77TQ.js +0 -2
  167. package/dist/cli-bundle/chunks/chunk-HX2GTA6L.js +0 -2
  168. package/dist/cli-bundle/chunks/chunk-J2IEKAVR.js +0 -2
  169. package/dist/cli-bundle/chunks/chunk-JC6FKIFM.js +0 -2
  170. package/dist/cli-bundle/chunks/chunk-K44PYFXH.js +0 -2
  171. package/dist/cli-bundle/chunks/chunk-K4KGEEBT.js +0 -2
  172. package/dist/cli-bundle/chunks/chunk-KFLK5TRH.js +0 -21
  173. package/dist/cli-bundle/chunks/chunk-KL6IEBV2.js +0 -2
  174. package/dist/cli-bundle/chunks/chunk-KWQZDZSS.js +0 -2
  175. package/dist/cli-bundle/chunks/chunk-KZ4X3DGU.js +0 -3
  176. package/dist/cli-bundle/chunks/chunk-LD77HJMQ.js +0 -13
  177. package/dist/cli-bundle/chunks/chunk-LEPJJ6QC.js +0 -2
  178. package/dist/cli-bundle/chunks/chunk-ME2JJ4LA.js +0 -3
  179. package/dist/cli-bundle/chunks/chunk-NE5VRDAI.js +0 -2
  180. package/dist/cli-bundle/chunks/chunk-NFLJ3FHD.js +0 -2
  181. package/dist/cli-bundle/chunks/chunk-NG6OXIBR.js +0 -19
  182. package/dist/cli-bundle/chunks/chunk-NYIGHWQY.js +0 -8
  183. package/dist/cli-bundle/chunks/chunk-NZ75GNSA.js +0 -2
  184. package/dist/cli-bundle/chunks/chunk-PCJWJNC2.js +0 -2
  185. package/dist/cli-bundle/chunks/chunk-PD3225AM.js +0 -2
  186. package/dist/cli-bundle/chunks/chunk-PDEGKG7P.js +0 -2
  187. package/dist/cli-bundle/chunks/chunk-PIE5HBNA.js +0 -2
  188. package/dist/cli-bundle/chunks/chunk-PW2H7YJR.js +0 -56
  189. package/dist/cli-bundle/chunks/chunk-RSIC5OPE.js +0 -2
  190. package/dist/cli-bundle/chunks/chunk-TPKN3S7S.js +0 -2
  191. package/dist/cli-bundle/chunks/chunk-TPXAXTCO.js +0 -2
  192. package/dist/cli-bundle/chunks/chunk-UFWUJO4V.js +0 -2
  193. package/dist/cli-bundle/chunks/chunk-UQLZQVFW.js +0 -55
  194. package/dist/cli-bundle/chunks/chunk-VT3Z5G7D.js +0 -2
  195. package/dist/cli-bundle/chunks/chunk-WOD3WWUN.js +0 -2
  196. package/dist/cli-bundle/chunks/chunk-WSJEIGJF.js +0 -3
  197. package/dist/cli-bundle/chunks/chunk-WYNUU7ZW.js +0 -2008
  198. package/dist/cli-bundle/chunks/chunk-YGPNCCXZ.js +0 -2
  199. package/dist/cli-bundle/chunks/close-CMY3BAUG.js +0 -2
  200. package/dist/cli-bundle/chunks/close-many-SA4XZCTK.js +0 -2
  201. package/dist/cli-bundle/chunks/comments-EZ556ZD3.js +0 -2
  202. package/dist/cli-bundle/chunks/copy-ZSGPA52X.js +0 -2
  203. package/dist/cli-bundle/chunks/create-I5DVV4YG.js +0 -2
  204. package/dist/cli-bundle/chunks/delete-RL3JACSW.js +0 -2
  205. package/dist/cli-bundle/chunks/deps-S7UBCECS.js +0 -2
  206. package/dist/cli-bundle/chunks/docs-ZZNVBBYO.js +0 -2
  207. package/dist/cli-bundle/chunks/files-27C337VT.js +0 -2
  208. package/dist/cli-bundle/chunks/focus-5Z2SG7LU.js +0 -2
  209. package/dist/cli-bundle/chunks/history-compact-HJQK67CZ.js +0 -2
  210. package/dist/cli-bundle/chunks/history-redact-PWC6PDWA.js +0 -2
  211. package/dist/cli-bundle/chunks/history-repair-N3CY4WBF.js +0 -2
  212. package/dist/cli-bundle/chunks/learnings-4FH23XDT.js +0 -2
  213. package/dist/cli-bundle/chunks/profile-5Y5XXH5N.js +0 -2
  214. package/dist/cli-bundle/chunks/register-mutation-YGYPW3BL.js +0 -20
  215. package/dist/cli-bundle/chunks/register-operations-WMDSUMQF.js +0 -2
  216. package/dist/cli-bundle/chunks/register-setup-DL7FFABC.js +0 -2
  217. package/dist/cli-bundle/chunks/restore-6KYBV5BY.js +0 -2
  218. package/dist/cli-bundle/chunks/schema-EQGKBYXJ.js +0 -2
  219. package/dist/cli-bundle/chunks/update-QVTYOD6I.js +0 -2
  220. package/dist/cli-bundle/chunks/update-many-DJSBU525.js +0 -2
  221. package/dist/cli-bundle/focused-chunks/chunk-2ECLECMK.js +0 -12
  222. package/dist/cli-bundle/focused-chunks/chunk-4EX25PXM.js +0 -8
  223. package/dist/cli-bundle/focused-chunks/chunk-DLTS3IHM.js +0 -2
  224. package/dist/cli-bundle/focused-chunks/chunk-DQ6FKGL3.js +0 -14
  225. package/dist/cli-bundle/focused-chunks/chunk-JLG2C4EQ.js +0 -2
  226. package/dist/cli-bundle/focused-chunks/chunk-ZJIMJHDB.js +0 -2
@@ -0,0 +1,385 @@
1
+ /**
2
+ * @module sdk/project-runtime-compatibility
3
+ *
4
+ * Protects project mutations from an older PATH-resolved pm executable while
5
+ * leaving diagnosis reads available.
6
+ */
7
+
8
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="962636b0-ed3b-5ad0-ae0c-904435025986")}catch(e){}}();
9
+ import fs from "node:fs";
10
+ import path from "node:path";
11
+ import { EXIT_CODE } from "../../core/shared/constants.js";
12
+ import { PmCliError } from "../../core/shared/errors.js";
13
+ export { PmCliError };
14
+ const PACKAGE_NAME = "@unbrained/pm-cli";
15
+ const MUTATING_COMMANDS = new Set([
16
+ "append",
17
+ "claim",
18
+ "changelog",
19
+ "close",
20
+ "close-many",
21
+ "close-task",
22
+ "comments",
23
+ "config",
24
+ "copy",
25
+ "create",
26
+ "dedupe-merge",
27
+ "delete",
28
+ "deps",
29
+ "docs",
30
+ "extension",
31
+ "event",
32
+ "events",
33
+ "files",
34
+ "focus",
35
+ "gc",
36
+ "history-author-acknowledge",
37
+ "history-compact",
38
+ "history-redact",
39
+ "history-repair",
40
+ "init",
41
+ "install",
42
+ "item",
43
+ "learnings",
44
+ "meet",
45
+ "merge",
46
+ "normalize",
47
+ "notes",
48
+ "package",
49
+ "packages",
50
+ "pause-task",
51
+ "plan",
52
+ "profile",
53
+ "reindex",
54
+ "release",
55
+ "remind",
56
+ "restore",
57
+ "schema",
58
+ "start-task",
59
+ "test",
60
+ "test-all",
61
+ "test-runs",
62
+ "test-runs-worker",
63
+ "telemetry",
64
+ "templates",
65
+ "twin",
66
+ "update",
67
+ "update-many",
68
+ "upgrade",
69
+ "vcs",
70
+ "workspace",
71
+ ]);
72
+ const GLOBAL_VALUE_FLAGS = new Set([
73
+ "--author",
74
+ "--output-budget",
75
+ "--output-format",
76
+ "--output-include",
77
+ "--output-limit",
78
+ "--output-session",
79
+ "--path",
80
+ "--pm-path",
81
+ ]);
82
+ const VERSION_PATTERN = /\b(\d{4})\.(\d{1,2})\.(\d{1,2})(?:-(\d+))?\b/u;
83
+ /** Return whether an invocation includes one of the exact mutation switches. */
84
+ function hasAnyToken(argv, tokens) {
85
+ return argv.some((token) => tokens.includes(token.split("=", 1)[0]));
86
+ }
87
+ /** Classify package/extension compatibility aliases from subcommands and legacy flags. */
88
+ function isPackageMutation(argv, positionals) {
89
+ return ([
90
+ "activate",
91
+ "adopt",
92
+ "adopt-all",
93
+ "deactivate",
94
+ "init",
95
+ "install",
96
+ "migrate",
97
+ "reload",
98
+ "uninstall",
99
+ ].includes(positionals[0] ?? "") ||
100
+ hasAnyToken(argv, [
101
+ "--activate",
102
+ "--adopt",
103
+ "--adopt-all",
104
+ "--deactivate",
105
+ "--fix-managed-state",
106
+ "--init",
107
+ "--install",
108
+ "--output",
109
+ "--reload",
110
+ "--scaffold",
111
+ "--uninstall",
112
+ ]));
113
+ }
114
+ const MIXED_COMMAND_CLASSIFIERS = {
115
+ changelog: (argv, positionals) => {
116
+ if (positionals[0] === "generate")
117
+ return !hasAnyToken(argv, ["--check"]);
118
+ const exportIndex = argv.indexOf("export");
119
+ return (positionals[0] === "export" &&
120
+ (hasAnyToken(argv, ["--output"]) ||
121
+ (exportIndex >= 0 &&
122
+ argv[exportIndex + 1] !== undefined &&
123
+ !argv[exportIndex + 1].startsWith("-"))));
124
+ },
125
+ comments: (argv) => hasAnyToken(argv, ["--add", "--delete", "--edit", "--file", "--stdin"]),
126
+ config: (_argv, positionals) => (positionals[0] === "project" || positionals[0] === "global"
127
+ ? positionals[1]
128
+ : positionals[0]) === "set",
129
+ deps: () => false,
130
+ docs: (argv) => hasAnyToken(argv, ["--add", "--add-glob", "--migrate", "--remove"]),
131
+ duplicates: () => false,
132
+ events: () => false,
133
+ extension: isPackageMutation,
134
+ files: (argv, positionals) => hasAnyToken(argv, ["--add", "--add-glob", "--migrate", "--remove"]) ||
135
+ (positionals[0] === "discover" && hasAnyToken(argv, ["--apply"])),
136
+ health: (argv) => !hasAnyToken(argv, ["--check-only", "--no-refresh", "--skip-vectors"]),
137
+ learnings: (argv) => hasAnyToken(argv, ["--add", "--delete", "--edit", "--file", "--stdin"]),
138
+ merge: (_argv, positionals) => positionals[0] !== "report",
139
+ notes: (argv) => hasAnyToken(argv, ["--add", "--delete", "--edit", "--file", "--stdin"]),
140
+ package: isPackageMutation,
141
+ packages: isPackageMutation,
142
+ profile: (_argv, positionals) => positionals[0] === "apply",
143
+ schema: (argv, positionals) => [
144
+ "add-field",
145
+ "add-status",
146
+ "add-type",
147
+ "remove-field",
148
+ "remove-status",
149
+ "remove-type",
150
+ "remap-status",
151
+ "rename-field",
152
+ "rename-type",
153
+ ].includes(positionals[0] ?? "") &&
154
+ !(hasAnyToken(argv, ["--infer"]) && !hasAnyToken(argv, ["--apply"])),
155
+ telemetry: (_argv, positionals) => positionals.slice(0, 2).some((token) => ["clear", "flush"].includes(token)),
156
+ templates: (_argv, positionals) => positionals[0] === "save",
157
+ test: (argv) => hasAnyToken(argv, [
158
+ "--add",
159
+ "--add-json",
160
+ "--background",
161
+ "--measure",
162
+ "--remove",
163
+ "--resume",
164
+ "--run",
165
+ "--stop",
166
+ ]),
167
+ validate: (argv) => hasAnyToken(argv, ["--auto-fix", "--prune-missing"]),
168
+ vcs: (_argv, positionals) => ["abandon", "create", "merge", "propose", "ref-create"].includes(positionals[0] ?? ""),
169
+ workspace: (_argv, positionals) => positionals[0] === "snapshot" &&
170
+ ["create", "delete", "restore"].includes(positionals[1] ?? ""),
171
+ };
172
+ /** Parse the supported date-version coordinates used by pm releases. */
173
+ function parseDateVersion(value) {
174
+ const match = value.match(VERSION_PATTERN);
175
+ return match
176
+ ? [
177
+ Number(match[1]),
178
+ Number(match[2]),
179
+ Number(match[3]),
180
+ Number(match[4] ?? 0),
181
+ ]
182
+ : null;
183
+ }
184
+ /** Compare pm date versions without accepting arbitrary semver-like prose. */
185
+ export function comparePmDateVersions(left, right) {
186
+ const leftParts = parseDateVersion(left);
187
+ const rightParts = parseDateVersion(right);
188
+ if (!leftParts || !rightParts)
189
+ return null;
190
+ for (let index = 0; index < leftParts.length; index += 1) {
191
+ const delta = leftParts[index] - rightParts[index];
192
+ if (delta !== 0)
193
+ return Math.sign(delta);
194
+ }
195
+ return 0;
196
+ }
197
+ /** Read one optional JSON object without turning absence or corruption into startup failure. */
198
+ function readJsonRecord(filePath) {
199
+ try {
200
+ const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
201
+ return typeof parsed === "object" &&
202
+ parsed !== null &&
203
+ !Array.isArray(parsed)
204
+ ? parsed
205
+ : null;
206
+ }
207
+ catch {
208
+ return null;
209
+ }
210
+ }
211
+ /** Extract the highest explicit lower-bound pm date version from dependency declarations. */
212
+ function dependencyPin(packageJson) {
213
+ const versions = [];
214
+ for (const field of [
215
+ "dependencies",
216
+ "devDependencies",
217
+ "optionalDependencies",
218
+ "peerDependencies",
219
+ ]) {
220
+ const dependencies = packageJson[field];
221
+ if (typeof dependencies !== "object" || dependencies === null)
222
+ continue;
223
+ const value = dependencies[PACKAGE_NAME];
224
+ const specification = typeof value === "string" ? value.trim() : "";
225
+ const version = /^[<!]/u.test(specification)
226
+ ? undefined
227
+ : specification.match(VERSION_PATTERN)?.[0];
228
+ if (version)
229
+ versions.push(version);
230
+ }
231
+ return versions.sort((left, right) => comparePmDateVersions(right, left))[0];
232
+ }
233
+ /** Read npm's exact installed package coordinate from package-lock.json. */
234
+ function packageLockPin(projectRoot) {
235
+ const lock = readJsonRecord(path.join(projectRoot, "package-lock.json"));
236
+ const packages = lock?.packages;
237
+ if (typeof packages !== "object" || packages === null)
238
+ return undefined;
239
+ const installed = packages["node_modules/@unbrained/pm-cli"];
240
+ if (typeof installed !== "object" || installed === null)
241
+ return undefined;
242
+ const version = installed.version;
243
+ return typeof version === "string" ? version : undefined;
244
+ }
245
+ /** Read the exact coordinate from the matching text lockfile package block. */
246
+ function textLockPin(projectRoot, file) {
247
+ try {
248
+ const lines = fs
249
+ .readFileSync(path.join(projectRoot, file), "utf8")
250
+ .split(/\r?\n/u);
251
+ const packageLineIndex = lines.findIndex((line) => line.includes(PACKAGE_NAME));
252
+ if (packageLineIndex < 0)
253
+ return undefined;
254
+ const packageIndent = lines[packageLineIndex].match(/^\s*/u)[0].length;
255
+ const entry = [lines[packageLineIndex]];
256
+ for (let index = packageLineIndex + 1; index < lines.length; index += 1) {
257
+ const line = lines[index];
258
+ const trimmed = line.trim();
259
+ const indent = line.match(/^\s*/u)[0].length;
260
+ if (trimmed.length > 0 && indent <= packageIndent)
261
+ break;
262
+ entry.push(line);
263
+ }
264
+ const entrySource = entry.join("\n");
265
+ const explicitVersion = entrySource.match(/^\s*version(?::\s*|\s+)["']?(\d{4}\.\d{1,2}\.\d{1,2}(?:-\d+)?)/mu)?.[1];
266
+ return explicitVersion ?? entry[0].match(VERSION_PATTERN)?.[0];
267
+ }
268
+ catch {
269
+ return undefined;
270
+ }
271
+ }
272
+ /** Discover declared, installed, and lock-resolved versions without network I/O. */
273
+ export function discoverProjectRuntimeVersionPins(projectRoot) {
274
+ const pins = [];
275
+ const projectPackage = readJsonRecord(path.join(projectRoot, "package.json"));
276
+ const declared = projectPackage ? dependencyPin(projectPackage) : undefined;
277
+ if (declared)
278
+ pins.push({ version: declared, source: "package.json" });
279
+ const installedPackage = readJsonRecord(path.join(projectRoot, "node_modules", "@unbrained", "pm-cli", "package.json"));
280
+ const installedVersion = installedPackage?.version;
281
+ if (typeof installedVersion === "string" &&
282
+ parseDateVersion(installedVersion)) {
283
+ pins.push({ version: installedVersion, source: "installed-package" });
284
+ }
285
+ const packageLockVersion = packageLockPin(projectRoot);
286
+ if (packageLockVersion && parseDateVersion(packageLockVersion)) {
287
+ pins.push({ version: packageLockVersion, source: "package-lock.json" });
288
+ }
289
+ for (const file of ["pnpm-lock.yaml", "yarn.lock"]) {
290
+ const version = textLockPin(projectRoot, file);
291
+ if (version)
292
+ pins.push({ version, source: file });
293
+ }
294
+ return pins;
295
+ }
296
+ /** Resolve the first command token and index while preserving global option values. */
297
+ function commandTokenFromArgv(argv) {
298
+ for (let index = 0; index < argv.length; index += 1) {
299
+ const token = argv[index];
300
+ if (GLOBAL_VALUE_FLAGS.has(token)) {
301
+ index += 1;
302
+ continue;
303
+ }
304
+ if (!token.startsWith("-"))
305
+ return { command: token.toLowerCase(), index };
306
+ }
307
+ return undefined;
308
+ }
309
+ /** Classify mutation-capable invocations while preserving explicit read modes. */
310
+ export function isProjectMutatingInvocation(argv) {
311
+ const commandToken = commandTokenFromArgv(argv);
312
+ if (!commandToken)
313
+ return false;
314
+ if (hasAnyToken(argv, ["--help", "-h", "--dry-run"]))
315
+ return false;
316
+ const { command, index: commandIndex } = commandToken;
317
+ const positionals = [];
318
+ for (let index = commandIndex + 1; index < argv.length; index += 1) {
319
+ const token = argv[index];
320
+ if (GLOBAL_VALUE_FLAGS.has(token)) {
321
+ index += 1;
322
+ continue;
323
+ }
324
+ if (!token.startsWith("-"))
325
+ positionals.push(token.toLowerCase());
326
+ }
327
+ const mixedClassifier = MIXED_COMMAND_CLASSIFIERS[command];
328
+ return mixedClassifier
329
+ ? mixedClassifier(argv, positionals)
330
+ : MUTATING_COMMANDS.has(command);
331
+ }
332
+ /** Inspect whether one invocation is compatible with the project's newest pin. */
333
+ export function inspectProjectRuntimeCompatibility(options) {
334
+ const command = commandTokenFromArgv(options.argv)?.command;
335
+ const mutating = isProjectMutatingInvocation(options.argv);
336
+ const pins = discoverProjectRuntimeVersionPins(options.projectRoot)
337
+ .filter((pin) => comparePmDateVersions(pin.version, options.executingVersion) !== null)
338
+ .sort((left, right) => comparePmDateVersions(right.version, left.version));
339
+ const newest = pins[0];
340
+ const stale = newest !== undefined &&
341
+ comparePmDateVersions(options.executingVersion, newest.version) === -1;
342
+ const warning = stale && !mutating
343
+ ? {
344
+ code: "project_runtime_stale_read",
345
+ executing_version: options.executingVersion,
346
+ project_version: newest.version,
347
+ source: newest.source,
348
+ message: "This read is using an older pm runtime than the project requires.",
349
+ next_steps: [
350
+ `Run the command through the project's installed ${PACKAGE_NAME} ${newest.version}.`,
351
+ "Install the project dependencies with its declared package manager if the local executable is missing.",
352
+ ],
353
+ }
354
+ : undefined;
355
+ return {
356
+ compatible: !mutating || !stale || options.allowStale === true,
357
+ executing_version: options.executingVersion,
358
+ ...(newest
359
+ ? { project_version: newest.version, source: newest.source }
360
+ : {}),
361
+ ...(command ? { command } : {}),
362
+ mutating,
363
+ stale,
364
+ ...(warning ? { warning } : {}),
365
+ override_applied: stale && mutating && options.allowStale === true,
366
+ };
367
+ }
368
+ /** Refuse stale mutations with a stable SDK error and package-neutral recovery. */
369
+ export function assertProjectRuntimeCompatibility(options) {
370
+ const result = inspectProjectRuntimeCompatibility(options);
371
+ if (result.compatible)
372
+ return result;
373
+ throw new PmCliError(`pm ${result.executing_version} cannot mutate a project pinned to newer pm ${result.project_version}.`, EXIT_CODE.CONFLICT, {
374
+ code: "project_runtime_stale_mutation",
375
+ reason: result.source,
376
+ why: "An older runtime can write storage, history, and merge contracts it does not understand.",
377
+ nextSteps: [
378
+ `Run this command through the project's installed ${PACKAGE_NAME} ${result.project_version}.`,
379
+ "For an intentional recovery only, set PM_ALLOW_STALE_CLI=1 for this invocation and record why.",
380
+ "Read-only commands remain available without an override.",
381
+ ],
382
+ });
383
+ }
384
+ //# sourceMappingURL=project-runtime-compatibility.js.map
385
+ //# debugId=962636b0-ed3b-5ad0-ae0c-904435025986
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @module sdk/environment/source-context
3
+ *
4
+ * Defines the inherited source-workspace access contract used by sandboxed
5
+ * commands that retain read-only project identity.
6
+ */
7
+ /** Environment key declaring how a child may use inherited source coordinates. */
8
+ export declare const SOURCE_CONTEXT_ACCESS_ENV = "PM_SOURCE_CONTEXT_ACCESS";
9
+ /** Environment key permitting one explicit source-context write invocation. */
10
+ export declare const SOURCE_CONTEXT_WRITE_OVERRIDE_ENV = "PM_ALLOW_SOURCE_CONTEXT_WRITES";
11
+ /** Supported inherited source-context access modes. */
12
+ export type SourceContextAccessMode = "read_only" | "write";
13
+ /** Structured policy used by SDK adapters before selecting source coordinates. */
14
+ export interface SourceContextWritePolicy {
15
+ /** Declared access mode, with absent legacy context retaining write behavior. */
16
+ access: SourceContextAccessMode;
17
+ /** Whether the one-invocation write override was accepted. */
18
+ write_override_applied: boolean;
19
+ /** Whether a mutation may select inherited source coordinates. */
20
+ source_writes_allowed: boolean;
21
+ }
22
+ /** Resolve inherited source-coordinate write policy without reading filesystem state. */
23
+ export declare function resolveSourceContextWritePolicy(environment: Readonly<Record<string, string | undefined>>): SourceContextWritePolicy;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @module sdk/environment/source-context
3
+ *
4
+ * Defines the inherited source-workspace access contract used by sandboxed
5
+ * commands that retain read-only project identity.
6
+ */
7
+ /** Environment key declaring how a child may use inherited source coordinates. */
8
+
9
+ !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]="f97516b2-f75c-5ce0-82dc-f850466284c7")}catch(e){}}();
10
+ export const SOURCE_CONTEXT_ACCESS_ENV = "PM_SOURCE_CONTEXT_ACCESS";
11
+ /** Environment key permitting one explicit source-context write invocation. */
12
+ export const SOURCE_CONTEXT_WRITE_OVERRIDE_ENV = "PM_ALLOW_SOURCE_CONTEXT_WRITES";
13
+ /** Resolve inherited source-coordinate write policy without reading filesystem state. */
14
+ export function resolveSourceContextWritePolicy(environment) {
15
+ const declaredAccess = environment[SOURCE_CONTEXT_ACCESS_ENV];
16
+ const access = declaredAccess === undefined ||
17
+ declaredAccess.trim().toLowerCase() === "write"
18
+ ? "write"
19
+ : "read_only";
20
+ const writeOverrideApplied = access === "read_only" &&
21
+ environment[SOURCE_CONTEXT_WRITE_OVERRIDE_ENV]?.trim() === "1";
22
+ return {
23
+ access,
24
+ write_override_applied: writeOverrideApplied,
25
+ source_writes_allowed: access === "write" || writeOverrideApplied,
26
+ };
27
+ }
28
+ //# sourceMappingURL=source-context.js.map
29
+ //# debugId=f97516b2-f75c-5ce0-82dc-f850466284c7
@@ -43,8 +43,14 @@ export interface PmErrorCodeContract {
43
43
  sources: string[];
44
44
  /** CLI command roots inferred from executable declaration ownership. */
45
45
  emitting_commands: string[];
46
+ /** Canonical machine identifier for this compatibility group. */
47
+ canonical_code?: string;
48
+ /** Stable compatibility spellings that resolve to this canonical code. */
49
+ aliases?: string[];
46
50
  }
47
51
  /** Validate, normalize, sort, and freeze an error-code catalog. */
48
52
  export declare function definePmErrorCodeCatalog(declarations: readonly PmErrorCodeContract[]): readonly PmErrorCodeContract[];
53
+ /** Resolve an emitted code through its stable compatibility alias group. */
54
+ export declare function resolveCanonicalPmErrorCodeContract(code: string, catalog: readonly PmErrorCodeContract[]): PmErrorCodeContract;
49
55
  /** Resolve one declared error contract and fail closed for unknown vocabulary. */
50
56
  export declare function resolvePmErrorCodeContract(code: string, catalog: readonly PmErrorCodeContract[]): PmErrorCodeContract;
@@ -6,7 +6,7 @@
6
6
  */
7
7
  /** Stable shell exit-code taxonomy shared by every structured error. */
8
8
 
9
- !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]="479dd590-7f54-54ae-bbaf-8f183fd6b6b4")}catch(e){}}();
9
+ !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]="393243a5-dd90-52c1-a9c1-588fd33f8b6a")}catch(e){}}();
10
10
  export const PM_ERROR_CODE_EXIT_CLASS_CONTRACTS = [
11
11
  { exit_code: 1, class: "generic_failure" },
12
12
  { exit_code: 2, class: "usage" },
@@ -21,6 +21,55 @@ function normalizeContractList(values) {
21
21
  ...new Set(values.map((value) => value.trim()).filter(Boolean)),
22
22
  ].sort();
23
23
  }
24
+ function isValidNormalizedErrorCodeContract(declaration, sources, emittingCommands, canonicalCode, aliases) {
25
+ return ![
26
+ [1, 2, 3, 4, 5].includes(declaration.exit_code),
27
+ declaration.meaning.trim().length > 0,
28
+ declaration.recovery.trim().length > 0,
29
+ sources.length > 0,
30
+ emittingCommands.length > 0,
31
+ /^[a-z][a-z0-9_]*$/.test(canonicalCode),
32
+ aliases.every((alias) => /^[a-z][a-z0-9_]*$/.test(alias)),
33
+ ERROR_CLASS_BY_EXIT_CODE.get(declaration.exit_code) === declaration.class,
34
+ ].includes(false);
35
+ }
36
+ function resolveCanonicalErrorCodeDeclaration(declaration, byCode) {
37
+ let current = declaration;
38
+ const path = new Set();
39
+ while (current.canonical_code !== current.code) {
40
+ if (path.has(current.code)) {
41
+ throw new TypeError(`Alias cycle in pm error code catalog: ${declaration.code}`);
42
+ }
43
+ path.add(current.code);
44
+ const target = byCode.get(current.canonical_code);
45
+ if (!target) {
46
+ throw new TypeError(`Invalid pm error code contract: ${declaration.code}`);
47
+ }
48
+ current = target;
49
+ }
50
+ return current;
51
+ }
52
+ function validateErrorCodeAliases(declarations) {
53
+ const byCode = new Map(declarations.map((entry) => [entry.code, entry]));
54
+ for (const declaration of declarations) {
55
+ const canonical = resolveCanonicalErrorCodeDeclaration(declaration, byCode);
56
+ if (canonical.exit_code !== declaration.exit_code ||
57
+ canonical.class !== declaration.class) {
58
+ throw new TypeError(`Alias transport mismatch for pm error code: ${declaration.code}`);
59
+ }
60
+ const expectedAliases = declarations
61
+ .filter((candidate) => candidate.code !== canonical.code &&
62
+ candidate.canonical_code === canonical.code)
63
+ .map((candidate) => candidate.code)
64
+ .sort();
65
+ if (declaration.code === canonical.code
66
+ ? JSON.stringify(declaration.aliases) !==
67
+ JSON.stringify(expectedAliases)
68
+ : declaration.aliases.length > 0) {
69
+ throw new TypeError(`Invalid pm error code contract: ${declaration.code}`);
70
+ }
71
+ }
72
+ }
24
73
  /** Validate, normalize, sort, and freeze an error-code catalog. */
25
74
  export function definePmErrorCodeCatalog(declarations) {
26
75
  const seen = new Set();
@@ -35,12 +84,9 @@ export function definePmErrorCodeCatalog(declarations) {
35
84
  seen.add(code);
36
85
  const sources = normalizeContractList(declaration.sources);
37
86
  const emittingCommands = normalizeContractList(declaration.emitting_commands);
38
- if (![1, 2, 3, 4, 5].includes(declaration.exit_code) ||
39
- declaration.meaning.trim().length === 0 ||
40
- declaration.recovery.trim().length === 0 ||
41
- sources.length === 0 ||
42
- emittingCommands.length === 0 ||
43
- ERROR_CLASS_BY_EXIT_CODE.get(declaration.exit_code) !== declaration.class) {
87
+ const canonicalCode = (declaration.canonical_code ?? code).trim();
88
+ const aliases = normalizeContractList(declaration.aliases ?? []);
89
+ if (!isValidNormalizedErrorCodeContract(declaration, sources, emittingCommands, canonicalCode, aliases)) {
44
90
  throw new TypeError(`Invalid pm error code contract: ${code}`);
45
91
  }
46
92
  return Object.freeze({
@@ -50,10 +96,18 @@ export function definePmErrorCodeCatalog(declarations) {
50
96
  recovery: declaration.recovery.trim(),
51
97
  sources,
52
98
  emitting_commands: emittingCommands,
99
+ canonical_code: canonicalCode,
100
+ aliases,
53
101
  });
54
102
  });
103
+ validateErrorCodeAliases(normalized);
55
104
  return Object.freeze(normalized.sort((left, right) => left.code.localeCompare(right.code)));
56
105
  }
106
+ /** Resolve an emitted code through its stable compatibility alias group. */
107
+ export function resolveCanonicalPmErrorCodeContract(code, catalog) {
108
+ const emitted = resolvePmErrorCodeContract(code, catalog);
109
+ return resolvePmErrorCodeContract(emitted.canonical_code ?? emitted.code, catalog);
110
+ }
57
111
  /** Resolve one declared error contract and fail closed for unknown vocabulary. */
58
112
  export function resolvePmErrorCodeContract(code, catalog) {
59
113
  const normalized = code.trim();
@@ -64,4 +118,4 @@ export function resolvePmErrorCodeContract(code, catalog) {
64
118
  return contract;
65
119
  }
66
120
  //# sourceMappingURL=error-code-catalog.js.map
67
- //# debugId=479dd590-7f54-54ae-bbaf-8f183fd6b6b4
121
+ //# debugId=393243a5-dd90-52c1-a9c1-588fd33f8b6a