@unbrained/pm-cli 2026.3.12 → 2026.5.1-2

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 (285) hide show
  1. package/.agents/pm/extensions/.managed-extensions.json +42 -0
  2. package/.agents/pm/extensions/beads/index.js +109 -0
  3. package/.agents/pm/extensions/beads/manifest.json +7 -0
  4. package/{dist/cli/commands/beads.js → .agents/pm/extensions/beads/runtime.js} +31 -21
  5. package/.agents/pm/extensions/beads/runtime.ts +702 -0
  6. package/.agents/pm/extensions/todos/index.js +126 -0
  7. package/.agents/pm/extensions/todos/manifest.json +7 -0
  8. package/{dist/extensions/builtins/todos/import-export.js → .agents/pm/extensions/todos/runtime.js} +39 -29
  9. package/.agents/pm/extensions/todos/runtime.ts +568 -0
  10. package/AGENTS.md +196 -92
  11. package/CHANGELOG.md +404 -0
  12. package/CODE_OF_CONDUCT.md +42 -0
  13. package/CONTRIBUTING.md +144 -0
  14. package/PRD.md +512 -164
  15. package/README.md +1053 -2
  16. package/SECURITY.md +51 -0
  17. package/dist/cli/commands/activity.d.ts +5 -0
  18. package/dist/cli/commands/activity.js +66 -3
  19. package/dist/cli/commands/activity.js.map +1 -1
  20. package/dist/cli/commands/aggregate.d.ts +54 -0
  21. package/dist/cli/commands/aggregate.js +181 -0
  22. package/dist/cli/commands/aggregate.js.map +1 -0
  23. package/dist/cli/commands/append.js +4 -1
  24. package/dist/cli/commands/append.js.map +1 -1
  25. package/dist/cli/commands/calendar.d.ts +109 -0
  26. package/dist/cli/commands/calendar.js +797 -0
  27. package/dist/cli/commands/calendar.js.map +1 -0
  28. package/dist/cli/commands/claim.d.ts +5 -1
  29. package/dist/cli/commands/claim.js +42 -21
  30. package/dist/cli/commands/claim.js.map +1 -1
  31. package/dist/cli/commands/close.d.ts +1 -0
  32. package/dist/cli/commands/close.js +54 -5
  33. package/dist/cli/commands/close.js.map +1 -1
  34. package/dist/cli/commands/comments-audit.d.ts +91 -0
  35. package/dist/cli/commands/comments-audit.js +195 -0
  36. package/dist/cli/commands/comments-audit.js.map +1 -0
  37. package/dist/cli/commands/comments.d.ts +1 -0
  38. package/dist/cli/commands/comments.js +70 -21
  39. package/dist/cli/commands/comments.js.map +1 -1
  40. package/dist/cli/commands/completion.d.ts +10 -4
  41. package/dist/cli/commands/completion.js +1184 -137
  42. package/dist/cli/commands/completion.js.map +1 -1
  43. package/dist/cli/commands/config.d.ts +35 -3
  44. package/dist/cli/commands/config.js +968 -13
  45. package/dist/cli/commands/config.js.map +1 -1
  46. package/dist/cli/commands/context.d.ts +86 -0
  47. package/dist/cli/commands/context.js +299 -0
  48. package/dist/cli/commands/context.js.map +1 -0
  49. package/dist/cli/commands/contracts.d.ts +78 -0
  50. package/dist/cli/commands/contracts.js +920 -0
  51. package/dist/cli/commands/contracts.js.map +1 -0
  52. package/dist/cli/commands/create.d.ts +48 -14
  53. package/dist/cli/commands/create.js +1331 -160
  54. package/dist/cli/commands/create.js.map +1 -1
  55. package/dist/cli/commands/dedupe-audit.d.ts +81 -0
  56. package/dist/cli/commands/dedupe-audit.js +330 -0
  57. package/dist/cli/commands/dedupe-audit.js.map +1 -0
  58. package/dist/cli/commands/deps.d.ts +52 -0
  59. package/dist/cli/commands/deps.js +204 -0
  60. package/dist/cli/commands/deps.js.map +1 -0
  61. package/dist/cli/commands/docs.d.ts +19 -0
  62. package/dist/cli/commands/docs.js +212 -13
  63. package/dist/cli/commands/docs.js.map +1 -1
  64. package/dist/cli/commands/extension.d.ts +122 -0
  65. package/dist/cli/commands/extension.js +1850 -0
  66. package/dist/cli/commands/extension.js.map +1 -0
  67. package/dist/cli/commands/files.d.ts +52 -1
  68. package/dist/cli/commands/files.js +455 -13
  69. package/dist/cli/commands/files.js.map +1 -1
  70. package/dist/cli/commands/gc.d.ts +11 -1
  71. package/dist/cli/commands/gc.js +89 -11
  72. package/dist/cli/commands/gc.js.map +1 -1
  73. package/dist/cli/commands/get.d.ts +13 -0
  74. package/dist/cli/commands/get.js +35 -3
  75. package/dist/cli/commands/get.js.map +1 -1
  76. package/dist/cli/commands/health.d.ts +10 -2
  77. package/dist/cli/commands/health.js +774 -23
  78. package/dist/cli/commands/health.js.map +1 -1
  79. package/dist/cli/commands/history.d.ts +20 -0
  80. package/dist/cli/commands/history.js +152 -6
  81. package/dist/cli/commands/history.js.map +1 -1
  82. package/dist/cli/commands/index.d.ts +16 -3
  83. package/dist/cli/commands/index.js +16 -3
  84. package/dist/cli/commands/index.js.map +1 -1
  85. package/dist/cli/commands/init.d.ts +7 -2
  86. package/dist/cli/commands/init.js +137 -5
  87. package/dist/cli/commands/init.js.map +1 -1
  88. package/dist/cli/commands/learnings.d.ts +17 -0
  89. package/dist/cli/commands/learnings.js +129 -0
  90. package/dist/cli/commands/learnings.js.map +1 -0
  91. package/dist/cli/commands/list.d.ts +29 -1
  92. package/dist/cli/commands/list.js +289 -53
  93. package/dist/cli/commands/list.js.map +1 -1
  94. package/dist/cli/commands/normalize.d.ts +51 -0
  95. package/dist/cli/commands/normalize.js +298 -0
  96. package/dist/cli/commands/normalize.js.map +1 -0
  97. package/dist/cli/commands/notes.d.ts +17 -0
  98. package/dist/cli/commands/notes.js +129 -0
  99. package/dist/cli/commands/notes.js.map +1 -0
  100. package/dist/cli/commands/reindex.d.ts +1 -0
  101. package/dist/cli/commands/reindex.js +208 -32
  102. package/dist/cli/commands/reindex.js.map +1 -1
  103. package/dist/cli/commands/restore.js +164 -30
  104. package/dist/cli/commands/restore.js.map +1 -1
  105. package/dist/cli/commands/search.d.ts +14 -1
  106. package/dist/cli/commands/search.js +475 -81
  107. package/dist/cli/commands/search.js.map +1 -1
  108. package/dist/cli/commands/stats.js +26 -10
  109. package/dist/cli/commands/stats.js.map +1 -1
  110. package/dist/cli/commands/templates.d.ts +26 -0
  111. package/dist/cli/commands/templates.js +179 -0
  112. package/dist/cli/commands/templates.js.map +1 -0
  113. package/dist/cli/commands/test-all.d.ts +19 -1
  114. package/dist/cli/commands/test-all.js +161 -13
  115. package/dist/cli/commands/test-all.js.map +1 -1
  116. package/dist/cli/commands/test-runs.d.ts +63 -0
  117. package/dist/cli/commands/test-runs.js +179 -0
  118. package/dist/cli/commands/test-runs.js.map +1 -0
  119. package/dist/cli/commands/test.d.ts +75 -1
  120. package/dist/cli/commands/test.js +1360 -41
  121. package/dist/cli/commands/test.js.map +1 -1
  122. package/dist/cli/commands/update-many.d.ts +57 -0
  123. package/dist/cli/commands/update-many.js +631 -0
  124. package/dist/cli/commands/update-many.js.map +1 -0
  125. package/dist/cli/commands/update.d.ts +30 -0
  126. package/dist/cli/commands/update.js +1393 -84
  127. package/dist/cli/commands/update.js.map +1 -1
  128. package/dist/cli/commands/validate.d.ts +30 -0
  129. package/dist/cli/commands/validate.js +1151 -0
  130. package/dist/cli/commands/validate.js.map +1 -0
  131. package/dist/cli/error-guidance.d.ts +33 -0
  132. package/dist/cli/error-guidance.js +337 -0
  133. package/dist/cli/error-guidance.js.map +1 -0
  134. package/dist/cli/extension-command-options.d.ts +1 -0
  135. package/dist/cli/extension-command-options.js +92 -0
  136. package/dist/cli/extension-command-options.js.map +1 -1
  137. package/dist/cli/help-content.d.ts +20 -0
  138. package/dist/cli/help-content.js +543 -0
  139. package/dist/cli/help-content.js.map +1 -0
  140. package/dist/cli/main.js +3625 -445
  141. package/dist/cli/main.js.map +1 -1
  142. package/dist/core/extensions/index.d.ts +13 -1
  143. package/dist/core/extensions/index.js +108 -1
  144. package/dist/core/extensions/index.js.map +1 -1
  145. package/dist/core/extensions/item-fields.d.ts +2 -0
  146. package/dist/core/extensions/item-fields.js +79 -0
  147. package/dist/core/extensions/item-fields.js.map +1 -0
  148. package/dist/core/extensions/loader.d.ts +322 -9
  149. package/dist/core/extensions/loader.js +911 -20
  150. package/dist/core/extensions/loader.js.map +1 -1
  151. package/dist/core/extensions/runtime-registrations.d.ts +5 -0
  152. package/dist/core/extensions/runtime-registrations.js +51 -0
  153. package/dist/core/extensions/runtime-registrations.js.map +1 -0
  154. package/dist/core/history/history-stream-policy.d.ts +20 -0
  155. package/dist/core/history/history-stream-policy.js +53 -0
  156. package/dist/core/history/history-stream-policy.js.map +1 -0
  157. package/dist/core/history/history.js +90 -1
  158. package/dist/core/history/history.js.map +1 -1
  159. package/dist/core/item/id.js +4 -1
  160. package/dist/core/item/id.js.map +1 -1
  161. package/dist/core/item/index.d.ts +1 -0
  162. package/dist/core/item/index.js +1 -0
  163. package/dist/core/item/index.js.map +1 -1
  164. package/dist/core/item/item-format.d.ts +11 -5
  165. package/dist/core/item/item-format.js +507 -24
  166. package/dist/core/item/item-format.js.map +1 -1
  167. package/dist/core/item/parent-reference-policy.d.ts +6 -0
  168. package/dist/core/item/parent-reference-policy.js +32 -0
  169. package/dist/core/item/parent-reference-policy.js.map +1 -0
  170. package/dist/core/item/parse.d.ts +5 -0
  171. package/dist/core/item/parse.js +216 -19
  172. package/dist/core/item/parse.js.map +1 -1
  173. package/dist/core/item/sprint-release-format.d.ts +6 -0
  174. package/dist/core/item/sprint-release-format.js +33 -0
  175. package/dist/core/item/sprint-release-format.js.map +1 -0
  176. package/dist/core/item/status.d.ts +3 -0
  177. package/dist/core/item/status.js +24 -0
  178. package/dist/core/item/status.js.map +1 -0
  179. package/dist/core/item/type-registry.d.ts +37 -0
  180. package/dist/core/item/type-registry.js +706 -0
  181. package/dist/core/item/type-registry.js.map +1 -0
  182. package/dist/core/lock/lock.d.ts +1 -1
  183. package/dist/core/lock/lock.js +101 -12
  184. package/dist/core/lock/lock.js.map +1 -1
  185. package/dist/core/output/command-aware.d.ts +1 -0
  186. package/dist/core/output/command-aware.js +394 -0
  187. package/dist/core/output/command-aware.js.map +1 -0
  188. package/dist/core/output/output.d.ts +3 -0
  189. package/dist/core/output/output.js +124 -6
  190. package/dist/core/output/output.js.map +1 -1
  191. package/dist/core/schema/runtime-field-filters.d.ts +3 -0
  192. package/dist/core/schema/runtime-field-filters.js +39 -0
  193. package/dist/core/schema/runtime-field-filters.js.map +1 -0
  194. package/dist/core/schema/runtime-field-values.d.ts +8 -0
  195. package/dist/core/schema/runtime-field-values.js +154 -0
  196. package/dist/core/schema/runtime-field-values.js.map +1 -0
  197. package/dist/core/schema/runtime-schema.d.ts +68 -0
  198. package/dist/core/schema/runtime-schema.js +554 -0
  199. package/dist/core/schema/runtime-schema.js.map +1 -0
  200. package/dist/core/search/cache.d.ts +13 -1
  201. package/dist/core/search/cache.js +123 -14
  202. package/dist/core/search/cache.js.map +1 -1
  203. package/dist/core/search/semantic-defaults.d.ts +6 -0
  204. package/dist/core/search/semantic-defaults.js +120 -0
  205. package/dist/core/search/semantic-defaults.js.map +1 -0
  206. package/dist/core/search/vector-stores.js +3 -1
  207. package/dist/core/search/vector-stores.js.map +1 -1
  208. package/dist/core/shared/command-types.d.ts +2 -0
  209. package/dist/core/shared/conflict-markers.d.ts +7 -0
  210. package/dist/core/shared/conflict-markers.js +27 -0
  211. package/dist/core/shared/conflict-markers.js.map +1 -0
  212. package/dist/core/shared/constants.d.ts +15 -4
  213. package/dist/core/shared/constants.js +141 -1
  214. package/dist/core/shared/constants.js.map +1 -1
  215. package/dist/core/shared/errors.d.ts +10 -1
  216. package/dist/core/shared/errors.js +3 -1
  217. package/dist/core/shared/errors.js.map +1 -1
  218. package/dist/core/shared/text-normalization.d.ts +4 -0
  219. package/dist/core/shared/text-normalization.js +33 -0
  220. package/dist/core/shared/text-normalization.js.map +1 -0
  221. package/dist/core/shared/time.d.ts +1 -2
  222. package/dist/core/shared/time.js +98 -11
  223. package/dist/core/shared/time.js.map +1 -1
  224. package/dist/core/store/index.d.ts +1 -0
  225. package/dist/core/store/index.js +1 -0
  226. package/dist/core/store/index.js.map +1 -1
  227. package/dist/core/store/item-format-migration.d.ts +9 -0
  228. package/dist/core/store/item-format-migration.js +87 -0
  229. package/dist/core/store/item-format-migration.js.map +1 -0
  230. package/dist/core/store/item-store.d.ts +13 -4
  231. package/dist/core/store/item-store.js +238 -51
  232. package/dist/core/store/item-store.js.map +1 -1
  233. package/dist/core/store/paths.d.ts +21 -3
  234. package/dist/core/store/paths.js +59 -4
  235. package/dist/core/store/paths.js.map +1 -1
  236. package/dist/core/store/settings.d.ts +14 -1
  237. package/dist/core/store/settings.js +463 -7
  238. package/dist/core/store/settings.js.map +1 -1
  239. package/dist/core/telemetry/consent.d.ts +2 -0
  240. package/dist/core/telemetry/consent.js +79 -0
  241. package/dist/core/telemetry/consent.js.map +1 -0
  242. package/dist/core/telemetry/runtime.d.ts +38 -0
  243. package/dist/core/telemetry/runtime.js +733 -0
  244. package/dist/core/telemetry/runtime.js.map +1 -0
  245. package/dist/core/test/background-runs.d.ts +117 -0
  246. package/dist/core/test/background-runs.js +760 -0
  247. package/dist/core/test/background-runs.js.map +1 -0
  248. package/dist/core/test/item-test-run-tracking.d.ts +9 -0
  249. package/dist/core/test/item-test-run-tracking.js +50 -0
  250. package/dist/core/test/item-test-run-tracking.js.map +1 -0
  251. package/dist/sdk/cli-contracts.d.ts +92 -0
  252. package/dist/sdk/cli-contracts.js +2357 -0
  253. package/dist/sdk/cli-contracts.js.map +1 -0
  254. package/dist/sdk/index.d.ts +34 -0
  255. package/dist/sdk/index.js +23 -0
  256. package/dist/sdk/index.js.map +1 -0
  257. package/dist/types.d.ts +197 -3
  258. package/dist/types.js +48 -1
  259. package/dist/types.js.map +1 -1
  260. package/docs/ARCHITECTURE.md +368 -39
  261. package/docs/EXTENSIONS.md +454 -49
  262. package/docs/RELEASING.md +70 -19
  263. package/docs/SDK.md +123 -0
  264. package/docs/examples/starter-extension/README.md +48 -0
  265. package/docs/examples/starter-extension/index.js +191 -0
  266. package/docs/examples/starter-extension/manifest.json +17 -0
  267. package/docs/examples/starter-extension/package.json +10 -0
  268. package/package.json +41 -14
  269. package/.pi/extensions/pm-cli/index.ts +0 -778
  270. package/dist/cli/commands/beads.d.ts +0 -16
  271. package/dist/cli/commands/beads.js.map +0 -1
  272. package/dist/cli/commands/install.d.ts +0 -18
  273. package/dist/cli/commands/install.js +0 -87
  274. package/dist/cli/commands/install.js.map +0 -1
  275. package/dist/core/extensions/builtins.d.ts +0 -3
  276. package/dist/core/extensions/builtins.js +0 -47
  277. package/dist/core/extensions/builtins.js.map +0 -1
  278. package/dist/extensions/builtins/beads/index.d.ts +0 -8
  279. package/dist/extensions/builtins/beads/index.js +0 -33
  280. package/dist/extensions/builtins/beads/index.js.map +0 -1
  281. package/dist/extensions/builtins/todos/import-export.d.ts +0 -26
  282. package/dist/extensions/builtins/todos/import-export.js.map +0 -1
  283. package/dist/extensions/builtins/todos/index.d.ts +0 -8
  284. package/dist/extensions/builtins/todos/index.js +0 -38
  285. package/dist/extensions/builtins/todos/index.js.map +0 -1
@@ -1,10 +1,130 @@
1
1
  import { pathExists } from "../../core/fs/fs-utils.js";
2
+ import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
3
+ import { normalizeParentReferencePolicy } from "../../core/item/parent-reference-policy.js";
4
+ import { normalizeSprintReleaseFormatPolicy } from "../../core/item/sprint-release-format.js";
5
+ import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
2
6
  import { EXIT_CODE } from "../../core/shared/constants.js";
3
7
  import { PmCliError } from "../../core/shared/errors.js";
8
+ import { migrateItemFilesToFormat } from "../../core/store/item-format-migration.js";
4
9
  import { getSettingsPath, resolveGlobalPmRoot, resolvePmRoot, } from "../../core/store/paths.js";
5
- import { readSettings, writeSettings } from "../../core/store/settings.js";
10
+ import { readSettingsWithMetadata, writeSettings } from "../../core/store/settings.js";
6
11
  const CONFIG_SCOPE_VALUES = ["project", "global"];
7
- const CONFIG_KEY_VALUES = ["definition-of-done", "definition_of_done"];
12
+ const CONFIG_KEY_VALUES = [
13
+ "definition-of-done",
14
+ "definition_of_done",
15
+ "item-format",
16
+ "item_format",
17
+ "history-missing-stream-policy",
18
+ "history_missing_stream_policy",
19
+ "sprint-release-format-policy",
20
+ "sprint_release_format_policy",
21
+ "parent-reference-policy",
22
+ "parent_reference_policy",
23
+ "metadata-validation-profile",
24
+ "metadata_validation_profile",
25
+ "metadata-required-fields",
26
+ "metadata_required_fields",
27
+ "lifecycle-stale-blocker-reason-patterns",
28
+ "lifecycle_stale_blocker_reason_patterns",
29
+ "lifecycle-closure-like-blocked-reason-patterns",
30
+ "lifecycle_closure_like_blocked_reason_patterns",
31
+ "lifecycle-closure-like-resolution-patterns",
32
+ "lifecycle_closure_like_resolution_patterns",
33
+ "lifecycle-closure-like-actual-result-patterns",
34
+ "lifecycle_closure_like_actual_result_patterns",
35
+ "governance-preset",
36
+ "governance_preset",
37
+ "governance-ownership-enforcement",
38
+ "governance_ownership_enforcement",
39
+ "governance-create-mode-default",
40
+ "governance_create_mode_default",
41
+ "governance-close-validation-default",
42
+ "governance_close_validation_default",
43
+ "governance-parent-reference-policy",
44
+ "governance_parent_reference_policy",
45
+ "governance-metadata-validation-profile",
46
+ "governance_metadata_validation_profile",
47
+ "governance-force-required-for-stale-lock",
48
+ "governance_force_required_for_stale_lock",
49
+ "test-result-tracking",
50
+ "test_result_tracking",
51
+ "telemetry-tracking",
52
+ "telemetry_tracking",
53
+ ];
54
+ const CONFIG_KEY_ALIASES = {
55
+ definition_of_done: ["definition-of-done", "definition_of_done"],
56
+ item_format: ["item-format", "item_format"],
57
+ history_missing_stream_policy: ["history-missing-stream-policy", "history_missing_stream_policy"],
58
+ sprint_release_format_policy: ["sprint-release-format-policy", "sprint_release_format_policy"],
59
+ parent_reference_policy: ["parent-reference-policy", "parent_reference_policy"],
60
+ metadata_validation_profile: ["metadata-validation-profile", "metadata_validation_profile"],
61
+ metadata_required_fields: ["metadata-required-fields", "metadata_required_fields"],
62
+ lifecycle_stale_blocker_reason_patterns: [
63
+ "lifecycle-stale-blocker-reason-patterns",
64
+ "lifecycle_stale_blocker_reason_patterns",
65
+ ],
66
+ lifecycle_closure_like_blocked_reason_patterns: [
67
+ "lifecycle-closure-like-blocked-reason-patterns",
68
+ "lifecycle_closure_like_blocked_reason_patterns",
69
+ ],
70
+ lifecycle_closure_like_resolution_patterns: [
71
+ "lifecycle-closure-like-resolution-patterns",
72
+ "lifecycle_closure_like_resolution_patterns",
73
+ ],
74
+ lifecycle_closure_like_actual_result_patterns: [
75
+ "lifecycle-closure-like-actual-result-patterns",
76
+ "lifecycle_closure_like_actual_result_patterns",
77
+ ],
78
+ governance_preset: ["governance-preset", "governance_preset"],
79
+ governance_ownership_enforcement: ["governance-ownership-enforcement", "governance_ownership_enforcement"],
80
+ governance_create_mode_default: ["governance-create-mode-default", "governance_create_mode_default"],
81
+ governance_close_validation_default: [
82
+ "governance-close-validation-default",
83
+ "governance_close_validation_default",
84
+ ],
85
+ governance_parent_reference_policy: ["governance-parent-reference-policy", "governance_parent_reference_policy"],
86
+ governance_metadata_validation_profile: [
87
+ "governance-metadata-validation-profile",
88
+ "governance_metadata_validation_profile",
89
+ ],
90
+ governance_force_required_for_stale_lock: [
91
+ "governance-force-required-for-stale-lock",
92
+ "governance_force_required_for_stale_lock",
93
+ ],
94
+ test_result_tracking: ["test-result-tracking", "test_result_tracking"],
95
+ telemetry_tracking: ["telemetry-tracking", "telemetry_tracking"],
96
+ };
97
+ const CONFIG_KEY_SUMMARIES = {
98
+ definition_of_done: "Definition of Done criteria list.",
99
+ item_format: "Default item file format.",
100
+ history_missing_stream_policy: "Missing history stream handling policy.",
101
+ sprint_release_format_policy: "Sprint/release format validation policy.",
102
+ parent_reference_policy: "Parent reference validation policy.",
103
+ metadata_validation_profile: "Validate metadata profile policy (core|strict|custom).",
104
+ metadata_required_fields: "Validate custom metadata required-fields list.",
105
+ lifecycle_stale_blocker_reason_patterns: "Validate lifecycle stale-blocker reason substring patterns (criteria list).",
106
+ lifecycle_closure_like_blocked_reason_patterns: "Validate lifecycle closure-like blocked_reason substring patterns (criteria list).",
107
+ lifecycle_closure_like_resolution_patterns: "Validate lifecycle closure-like resolution substring patterns (criteria list).",
108
+ lifecycle_closure_like_actual_result_patterns: "Validate lifecycle closure-like actual_result substring patterns (criteria list).",
109
+ governance_preset: "Governance preset policy (minimal|default|strict|custom).",
110
+ governance_ownership_enforcement: "Governance ownership enforcement policy (none|warn|strict).",
111
+ governance_create_mode_default: "Governance default create mode (progressive|strict).",
112
+ governance_close_validation_default: "Governance default close validation mode (off|warn|strict).",
113
+ governance_parent_reference_policy: "Governance parent reference policy (warn|strict_error).",
114
+ governance_metadata_validation_profile: "Governance metadata validation profile (core|strict|custom).",
115
+ governance_force_required_for_stale_lock: "Governance stale-lock force policy (enabled|disabled).",
116
+ test_result_tracking: "Item-level linked test result persistence policy.",
117
+ telemetry_tracking: "Telemetry usage reporting policy.",
118
+ };
119
+ const LIFECYCLE_PATTERN_CONFIG_KEYS = [
120
+ "lifecycle_stale_blocker_reason_patterns",
121
+ "lifecycle_closure_like_blocked_reason_patterns",
122
+ "lifecycle_closure_like_resolution_patterns",
123
+ "lifecycle_closure_like_actual_result_patterns",
124
+ ];
125
+ function isCriteriaConfigKey(key) {
126
+ return key === "definition_of_done" || key === "metadata_required_fields" || LIFECYCLE_PATTERN_CONFIG_KEYS.includes(key);
127
+ }
8
128
  function normalizeScope(value) {
9
129
  if (CONFIG_SCOPE_VALUES.includes(value)) {
10
130
  return value;
@@ -12,24 +132,308 @@ function normalizeScope(value) {
12
132
  throw new PmCliError(`Invalid config scope "${value}". Allowed: ${CONFIG_SCOPE_VALUES.join(", ")}`, EXIT_CODE.USAGE);
13
133
  }
14
134
  function normalizeAction(value) {
15
- if (value === "get" || value === "set") {
135
+ if (value === "get" || value === "set" || value === "list" || value === "export") {
16
136
  return value;
17
137
  }
18
- throw new PmCliError(`Invalid config action "${value}". Allowed: get, set`, EXIT_CODE.USAGE);
138
+ throw new PmCliError(`Invalid config action "${value}". Allowed: get, set, list, export`, EXIT_CODE.USAGE);
19
139
  }
20
140
  function normalizeKey(value) {
21
141
  if (CONFIG_KEY_VALUES.includes(value)) {
142
+ if (value === "item-format" || value === "item_format") {
143
+ return "item_format";
144
+ }
145
+ if (value === "history-missing-stream-policy" || value === "history_missing_stream_policy") {
146
+ return "history_missing_stream_policy";
147
+ }
148
+ if (value === "sprint-release-format-policy" || value === "sprint_release_format_policy") {
149
+ return "sprint_release_format_policy";
150
+ }
151
+ if (value === "parent-reference-policy" || value === "parent_reference_policy") {
152
+ return "parent_reference_policy";
153
+ }
154
+ if (value === "metadata-validation-profile" || value === "metadata_validation_profile") {
155
+ return "metadata_validation_profile";
156
+ }
157
+ if (value === "metadata-required-fields" || value === "metadata_required_fields") {
158
+ return "metadata_required_fields";
159
+ }
160
+ if (value === "lifecycle-stale-blocker-reason-patterns" ||
161
+ value === "lifecycle_stale_blocker_reason_patterns") {
162
+ return "lifecycle_stale_blocker_reason_patterns";
163
+ }
164
+ if (value === "lifecycle-closure-like-blocked-reason-patterns" ||
165
+ value === "lifecycle_closure_like_blocked_reason_patterns") {
166
+ return "lifecycle_closure_like_blocked_reason_patterns";
167
+ }
168
+ if (value === "lifecycle-closure-like-resolution-patterns" ||
169
+ value === "lifecycle_closure_like_resolution_patterns") {
170
+ return "lifecycle_closure_like_resolution_patterns";
171
+ }
172
+ if (value === "lifecycle-closure-like-actual-result-patterns" ||
173
+ value === "lifecycle_closure_like_actual_result_patterns") {
174
+ return "lifecycle_closure_like_actual_result_patterns";
175
+ }
176
+ if (value === "governance-preset" || value === "governance_preset") {
177
+ return "governance_preset";
178
+ }
179
+ if (value === "governance-ownership-enforcement" || value === "governance_ownership_enforcement") {
180
+ return "governance_ownership_enforcement";
181
+ }
182
+ if (value === "governance-create-mode-default" || value === "governance_create_mode_default") {
183
+ return "governance_create_mode_default";
184
+ }
185
+ if (value === "governance-close-validation-default" || value === "governance_close_validation_default") {
186
+ return "governance_close_validation_default";
187
+ }
188
+ if (value === "governance-parent-reference-policy" || value === "governance_parent_reference_policy") {
189
+ return "governance_parent_reference_policy";
190
+ }
191
+ if (value === "governance-metadata-validation-profile" ||
192
+ value === "governance_metadata_validation_profile") {
193
+ return "governance_metadata_validation_profile";
194
+ }
195
+ if (value === "governance-force-required-for-stale-lock" ||
196
+ value === "governance_force_required_for_stale_lock") {
197
+ return "governance_force_required_for_stale_lock";
198
+ }
199
+ if (value === "test-result-tracking" || value === "test_result_tracking") {
200
+ return "test_result_tracking";
201
+ }
202
+ if (value === "telemetry-tracking" || value === "telemetry_tracking") {
203
+ return "telemetry_tracking";
204
+ }
22
205
  return "definition_of_done";
23
206
  }
24
207
  throw new PmCliError(`Invalid config key "${value}". Supported: ${CONFIG_KEY_VALUES.join(", ")}`, EXIT_CODE.USAGE);
25
208
  }
26
- function normalizeCriteria(values) {
209
+ function normalizeCriteria(values, clearCriteria) {
27
210
  const normalized = [...new Set((values ?? []).map((value) => value.trim()).filter((value) => value.length > 0))].sort((left, right) => left.localeCompare(right));
211
+ if (clearCriteria) {
212
+ if (normalized.length > 0) {
213
+ throw new PmCliError("Config set definition-of-done cannot combine --clear-criteria with --criterion values", EXIT_CODE.USAGE);
214
+ }
215
+ return [];
216
+ }
217
+ if (normalized.length === 0) {
218
+ throw new PmCliError("Config set definition-of-done requires at least one non-empty --criterion value (or --clear-criteria to clear)", EXIT_CODE.USAGE);
219
+ }
220
+ return normalized;
221
+ }
222
+ function normalizeItemFormat(value) {
223
+ const normalized = value?.trim().toLowerCase();
224
+ if (normalized === "toon" || normalized === "json_markdown") {
225
+ return normalized;
226
+ }
227
+ throw new PmCliError('Config set item-format requires --format with one of: toon, json_markdown', EXIT_CODE.USAGE);
228
+ }
229
+ function normalizeHistoryMissingStreamPolicy(value) {
230
+ const normalized = value?.trim().toLowerCase().replaceAll("-", "_");
231
+ if (normalized === "auto_create" || normalized === "strict_error") {
232
+ return normalized;
233
+ }
234
+ throw new PmCliError("Config set history-missing-stream-policy requires --policy with one of: auto_create, strict_error", EXIT_CODE.USAGE);
235
+ }
236
+ function normalizeTestResultTrackingPolicy(value) {
237
+ const normalized = value?.trim().toLowerCase().replaceAll("-", "_");
238
+ if (normalized === "enabled" || normalized === "disabled") {
239
+ return normalized;
240
+ }
241
+ throw new PmCliError("Config set test-result-tracking requires --policy with one of: enabled, disabled", EXIT_CODE.USAGE);
242
+ }
243
+ function normalizeTelemetryTrackingPolicy(value) {
244
+ const normalized = value?.trim().toLowerCase().replaceAll("-", "_");
245
+ if (normalized === "enabled" || normalized === "disabled") {
246
+ return normalized;
247
+ }
248
+ throw new PmCliError("Config set telemetry-tracking requires --policy with one of: enabled, disabled", EXIT_CODE.USAGE);
249
+ }
250
+ function normalizeValidateMetadataProfile(value) {
251
+ const normalized = value?.trim().toLowerCase().replaceAll("-", "_");
252
+ if (normalized === "core" || normalized === "strict" || normalized === "custom") {
253
+ return normalized;
254
+ }
255
+ throw new PmCliError("Config set metadata-validation-profile requires --policy with one of: core, strict, custom", EXIT_CODE.USAGE);
256
+ }
257
+ function normalizeGovernancePreset(value) {
258
+ const normalized = value?.trim().toLowerCase().replaceAll("-", "_");
259
+ if (normalized === "minimal" || normalized === "default" || normalized === "strict" || normalized === "custom") {
260
+ return normalized;
261
+ }
262
+ throw new PmCliError("Config set governance-preset requires --policy with one of: minimal, default, strict, custom", EXIT_CODE.USAGE);
263
+ }
264
+ function normalizeGovernanceOwnershipEnforcement(value) {
265
+ const normalized = value?.trim().toLowerCase().replaceAll("-", "_");
266
+ if (normalized === "none" || normalized === "warn" || normalized === "strict") {
267
+ return normalized;
268
+ }
269
+ throw new PmCliError("Config set governance-ownership-enforcement requires --policy with one of: none, warn, strict", EXIT_CODE.USAGE);
270
+ }
271
+ function normalizeGovernanceCreateModeDefault(value) {
272
+ const normalized = value?.trim().toLowerCase().replaceAll("-", "_");
273
+ if (normalized === "progressive" || normalized === "strict") {
274
+ return normalized;
275
+ }
276
+ throw new PmCliError("Config set governance-create-mode-default requires --policy with one of: progressive, strict", EXIT_CODE.USAGE);
277
+ }
278
+ function normalizeGovernanceCloseValidationDefault(value) {
279
+ const normalized = value?.trim().toLowerCase().replaceAll("-", "_");
280
+ if (normalized === "off" || normalized === "warn" || normalized === "strict") {
281
+ return normalized;
282
+ }
283
+ if (normalized === "none" || normalized === "disabled") {
284
+ return "off";
285
+ }
286
+ throw new PmCliError("Config set governance-close-validation-default requires --policy with one of: off, warn, strict", EXIT_CODE.USAGE);
287
+ }
288
+ function normalizeGovernanceForceRequiredForStaleLockPolicy(value) {
289
+ const normalized = value?.trim().toLowerCase().replaceAll("-", "_");
290
+ if (normalized === "enabled" || normalized === "disabled") {
291
+ return normalized;
292
+ }
293
+ throw new PmCliError("Config set governance-force-required-for-stale-lock requires --policy with one of: enabled, disabled", EXIT_CODE.USAGE);
294
+ }
295
+ const METADATA_REQUIRED_FIELD_ALIAS_MAP = {
296
+ author: "author",
297
+ acceptance_criteria: "acceptance_criteria",
298
+ "acceptance-criteria": "acceptance_criteria",
299
+ estimated_minutes: "estimated_minutes",
300
+ "estimated-minutes": "estimated_minutes",
301
+ estimate: "estimated_minutes",
302
+ close_reason: "close_reason",
303
+ "close-reason": "close_reason",
304
+ reviewer: "reviewer",
305
+ risk: "risk",
306
+ confidence: "confidence",
307
+ sprint: "sprint",
308
+ release: "release",
309
+ };
310
+ const METADATA_REQUIRED_FIELD_OPTIONS = [
311
+ "author",
312
+ "acceptance_criteria",
313
+ "estimated_minutes",
314
+ "close_reason",
315
+ "reviewer",
316
+ "risk",
317
+ "confidence",
318
+ "sprint",
319
+ "release",
320
+ ];
321
+ function normalizeMetadataRequiredFields(values, clearCriteria) {
322
+ const normalized = [...new Set((values ?? []).map((value) => value.trim()).filter((value) => value.length > 0))];
323
+ if (clearCriteria) {
324
+ if (normalized.length > 0) {
325
+ throw new PmCliError("Config set metadata-required-fields cannot combine --clear-criteria with --criterion values", EXIT_CODE.USAGE);
326
+ }
327
+ return [];
328
+ }
28
329
  if (normalized.length === 0) {
29
- throw new PmCliError("Config set definition-of-done requires at least one non-empty --criterion value", EXIT_CODE.USAGE);
330
+ throw new PmCliError("Config set metadata-required-fields requires at least one --criterion value (or --clear-criteria to clear)", EXIT_CODE.USAGE);
331
+ }
332
+ const lowered = normalized.map((value) => value.toLowerCase().replaceAll("-", "_"));
333
+ const unsupported = lowered.filter((value) => METADATA_REQUIRED_FIELD_ALIAS_MAP[value] === undefined);
334
+ if (unsupported.length > 0) {
335
+ throw new PmCliError(`Config set metadata-required-fields received unsupported values: ${unsupported.join(", ")}. ` +
336
+ `Supported values: ${METADATA_REQUIRED_FIELD_OPTIONS.join(", ")}`, EXIT_CODE.USAGE);
337
+ }
338
+ return [...new Set(lowered.map((value) => METADATA_REQUIRED_FIELD_ALIAS_MAP[value]))].sort((left, right) => left.localeCompare(right));
339
+ }
340
+ function normalizeLifecyclePatternCriteria(key, values, clearCriteria) {
341
+ const normalized = [...new Set((values ?? []).map((value) => value.trim().toLowerCase()).filter((value) => value.length > 0))].sort((left, right) => left.localeCompare(right));
342
+ if (clearCriteria) {
343
+ if (normalized.length > 0) {
344
+ throw new PmCliError(`Config set ${CONFIG_KEY_ALIASES[key][0]} cannot combine --clear-criteria with --criterion values`, EXIT_CODE.USAGE);
345
+ }
346
+ return [];
347
+ }
348
+ if (normalized.length === 0) {
349
+ throw new PmCliError(`Config set ${CONFIG_KEY_ALIASES[key][0]} requires at least one --criterion value (or --clear-criteria to clear)`, EXIT_CODE.USAGE);
30
350
  }
31
351
  return normalized;
32
352
  }
353
+ function normalizeWarnings(values) {
354
+ return [...new Set(values)].sort((left, right) => left.localeCompare(right));
355
+ }
356
+ function normalizeKeyForAction(action, value) {
357
+ if (action === "list" || action === "export") {
358
+ if (typeof value === "string" && value.trim().length > 0) {
359
+ throw new PmCliError(`Config action "${action}" does not accept <key>`, EXIT_CODE.USAGE);
360
+ }
361
+ return undefined;
362
+ }
363
+ if (typeof value !== "string" || value.trim().length === 0) {
364
+ throw new PmCliError(`Config action "${action}" requires <key>`, EXIT_CODE.USAGE);
365
+ }
366
+ return normalizeKey(value);
367
+ }
368
+ function readConfigValue(settings, key) {
369
+ if (key === "item_format") {
370
+ return settings.item_format;
371
+ }
372
+ if (key === "history_missing_stream_policy") {
373
+ return settings.history.missing_stream;
374
+ }
375
+ if (key === "sprint_release_format_policy") {
376
+ return settings.validation.sprint_release_format;
377
+ }
378
+ if (key === "parent_reference_policy") {
379
+ return settings.validation.parent_reference;
380
+ }
381
+ if (key === "metadata_validation_profile") {
382
+ return settings.validation.metadata_profile;
383
+ }
384
+ if (key === "metadata_required_fields") {
385
+ return [...settings.validation.metadata_required_fields];
386
+ }
387
+ if (key === "lifecycle_stale_blocker_reason_patterns") {
388
+ return [...settings.validation.lifecycle_stale_blocker_reason_patterns];
389
+ }
390
+ if (key === "lifecycle_closure_like_blocked_reason_patterns") {
391
+ return [...settings.validation.lifecycle_closure_like_blocked_reason_patterns];
392
+ }
393
+ if (key === "lifecycle_closure_like_resolution_patterns") {
394
+ return [...settings.validation.lifecycle_closure_like_resolution_patterns];
395
+ }
396
+ if (key === "lifecycle_closure_like_actual_result_patterns") {
397
+ return [...settings.validation.lifecycle_closure_like_actual_result_patterns];
398
+ }
399
+ if (key === "governance_preset") {
400
+ return settings.governance.preset;
401
+ }
402
+ if (key === "governance_ownership_enforcement") {
403
+ return settings.governance.ownership_enforcement;
404
+ }
405
+ if (key === "governance_create_mode_default") {
406
+ return settings.governance.create_mode_default;
407
+ }
408
+ if (key === "governance_close_validation_default") {
409
+ return settings.governance.close_validation_default;
410
+ }
411
+ if (key === "governance_parent_reference_policy") {
412
+ return settings.governance.parent_reference;
413
+ }
414
+ if (key === "governance_metadata_validation_profile") {
415
+ return settings.governance.metadata_profile;
416
+ }
417
+ if (key === "governance_force_required_for_stale_lock") {
418
+ return settings.governance.force_required_for_stale_lock ? "enabled" : "disabled";
419
+ }
420
+ if (key === "test_result_tracking") {
421
+ return settings.testing.record_results_to_items ? "enabled" : "disabled";
422
+ }
423
+ if (key === "telemetry_tracking") {
424
+ return settings.telemetry.enabled ? "enabled" : "disabled";
425
+ }
426
+ return [...settings.workflow.definition_of_done];
427
+ }
428
+ function withWarnings(result, warnings) {
429
+ if (warnings.length === 0) {
430
+ return result;
431
+ }
432
+ return {
433
+ ...result,
434
+ warnings,
435
+ };
436
+ }
33
437
  async function resolveSettingsTarget(scope, global) {
34
438
  const cwd = process.cwd();
35
439
  const pmRoot = scope === "project" ? resolvePmRoot(cwd, global.path) : resolveGlobalPmRoot(cwd);
@@ -42,31 +446,582 @@ async function resolveSettingsTarget(scope, global) {
42
446
  export async function runConfig(scopeValue, actionValue, keyValue, options, global) {
43
447
  const scope = normalizeScope(scopeValue);
44
448
  const action = normalizeAction(actionValue);
45
- const key = normalizeKey(keyValue);
449
+ const key = normalizeKeyForAction(action, keyValue);
46
450
  const target = await resolveSettingsTarget(scope, global);
47
- const settings = await readSettings(target.pmRoot);
451
+ const { settings, metadata, warnings: settingsReadWarnings } = await readSettingsWithMetadata(target.pmRoot);
452
+ const warnings = normalizeWarnings(settingsReadWarnings);
453
+ if (action === "list") {
454
+ const keys = Object.keys(CONFIG_KEY_ALIASES).map((candidate) => ({
455
+ key: candidate,
456
+ aliases: CONFIG_KEY_ALIASES[candidate],
457
+ value_kind: isCriteriaConfigKey(candidate) ? "string_array" : "enum",
458
+ set_flags: isCriteriaConfigKey(candidate) ? ["--criterion", "--clear-criteria"] : candidate === "item_format" ? ["--format"] : ["--policy"],
459
+ summary: CONFIG_KEY_SUMMARIES[candidate],
460
+ value: readConfigValue(settings, candidate),
461
+ }));
462
+ return withWarnings({
463
+ scope,
464
+ keys,
465
+ count: keys.length,
466
+ settings_path: target.settingsPath,
467
+ changed: false,
468
+ }, warnings);
469
+ }
470
+ if (action === "export") {
471
+ const values = {
472
+ definition_of_done: readConfigValue(settings, "definition_of_done"),
473
+ item_format: readConfigValue(settings, "item_format"),
474
+ history_missing_stream_policy: readConfigValue(settings, "history_missing_stream_policy"),
475
+ sprint_release_format_policy: readConfigValue(settings, "sprint_release_format_policy"),
476
+ parent_reference_policy: readConfigValue(settings, "parent_reference_policy"),
477
+ metadata_validation_profile: readConfigValue(settings, "metadata_validation_profile"),
478
+ metadata_required_fields: readConfigValue(settings, "metadata_required_fields"),
479
+ lifecycle_stale_blocker_reason_patterns: readConfigValue(settings, "lifecycle_stale_blocker_reason_patterns"),
480
+ lifecycle_closure_like_blocked_reason_patterns: readConfigValue(settings, "lifecycle_closure_like_blocked_reason_patterns"),
481
+ lifecycle_closure_like_resolution_patterns: readConfigValue(settings, "lifecycle_closure_like_resolution_patterns"),
482
+ lifecycle_closure_like_actual_result_patterns: readConfigValue(settings, "lifecycle_closure_like_actual_result_patterns"),
483
+ governance_preset: readConfigValue(settings, "governance_preset"),
484
+ governance_ownership_enforcement: readConfigValue(settings, "governance_ownership_enforcement"),
485
+ governance_create_mode_default: readConfigValue(settings, "governance_create_mode_default"),
486
+ governance_close_validation_default: readConfigValue(settings, "governance_close_validation_default"),
487
+ governance_parent_reference_policy: readConfigValue(settings, "governance_parent_reference_policy"),
488
+ governance_metadata_validation_profile: readConfigValue(settings, "governance_metadata_validation_profile"),
489
+ governance_force_required_for_stale_lock: readConfigValue(settings, "governance_force_required_for_stale_lock"),
490
+ test_result_tracking: readConfigValue(settings, "test_result_tracking"),
491
+ telemetry_tracking: readConfigValue(settings, "telemetry_tracking"),
492
+ };
493
+ return withWarnings({
494
+ scope,
495
+ values,
496
+ settings_path: target.settingsPath,
497
+ changed: false,
498
+ }, warnings);
499
+ }
48
500
  if (action === "get") {
49
- return {
501
+ if (!key) {
502
+ throw new PmCliError('Config action "get" requires <key>', EXIT_CODE.USAGE);
503
+ }
504
+ if (key === "item_format") {
505
+ return withWarnings({
506
+ scope,
507
+ key,
508
+ format: settings.item_format,
509
+ has_explicit_item_format: metadata.has_explicit_item_format,
510
+ settings_path: target.settingsPath,
511
+ changed: false,
512
+ }, warnings);
513
+ }
514
+ if (key === "history_missing_stream_policy") {
515
+ return withWarnings({
516
+ scope,
517
+ key,
518
+ policy: settings.history.missing_stream,
519
+ settings_path: target.settingsPath,
520
+ changed: false,
521
+ }, warnings);
522
+ }
523
+ if (key === "sprint_release_format_policy") {
524
+ return withWarnings({
525
+ scope,
526
+ key,
527
+ policy: settings.validation.sprint_release_format,
528
+ settings_path: target.settingsPath,
529
+ changed: false,
530
+ }, warnings);
531
+ }
532
+ if (key === "parent_reference_policy") {
533
+ return withWarnings({
534
+ scope,
535
+ key,
536
+ policy: settings.validation.parent_reference,
537
+ settings_path: target.settingsPath,
538
+ changed: false,
539
+ }, warnings);
540
+ }
541
+ if (key === "metadata_validation_profile") {
542
+ return withWarnings({
543
+ scope,
544
+ key,
545
+ policy: settings.validation.metadata_profile,
546
+ settings_path: target.settingsPath,
547
+ changed: false,
548
+ }, warnings);
549
+ }
550
+ if (key === "metadata_required_fields") {
551
+ return withWarnings({
552
+ scope,
553
+ key,
554
+ criteria: [...settings.validation.metadata_required_fields],
555
+ settings_path: target.settingsPath,
556
+ changed: false,
557
+ }, warnings);
558
+ }
559
+ if (key === "lifecycle_stale_blocker_reason_patterns") {
560
+ return withWarnings({
561
+ scope,
562
+ key,
563
+ criteria: [...settings.validation.lifecycle_stale_blocker_reason_patterns],
564
+ settings_path: target.settingsPath,
565
+ changed: false,
566
+ }, warnings);
567
+ }
568
+ if (key === "lifecycle_closure_like_blocked_reason_patterns") {
569
+ return withWarnings({
570
+ scope,
571
+ key,
572
+ criteria: [...settings.validation.lifecycle_closure_like_blocked_reason_patterns],
573
+ settings_path: target.settingsPath,
574
+ changed: false,
575
+ }, warnings);
576
+ }
577
+ if (key === "lifecycle_closure_like_resolution_patterns") {
578
+ return withWarnings({
579
+ scope,
580
+ key,
581
+ criteria: [...settings.validation.lifecycle_closure_like_resolution_patterns],
582
+ settings_path: target.settingsPath,
583
+ changed: false,
584
+ }, warnings);
585
+ }
586
+ if (key === "lifecycle_closure_like_actual_result_patterns") {
587
+ return withWarnings({
588
+ scope,
589
+ key,
590
+ criteria: [...settings.validation.lifecycle_closure_like_actual_result_patterns],
591
+ settings_path: target.settingsPath,
592
+ changed: false,
593
+ }, warnings);
594
+ }
595
+ if (key === "governance_preset") {
596
+ return withWarnings({
597
+ scope,
598
+ key,
599
+ policy: settings.governance.preset,
600
+ settings_path: target.settingsPath,
601
+ changed: false,
602
+ }, warnings);
603
+ }
604
+ if (key === "governance_ownership_enforcement") {
605
+ return withWarnings({
606
+ scope,
607
+ key,
608
+ policy: settings.governance.ownership_enforcement,
609
+ settings_path: target.settingsPath,
610
+ changed: false,
611
+ }, warnings);
612
+ }
613
+ if (key === "governance_create_mode_default") {
614
+ return withWarnings({
615
+ scope,
616
+ key,
617
+ policy: settings.governance.create_mode_default,
618
+ settings_path: target.settingsPath,
619
+ changed: false,
620
+ }, warnings);
621
+ }
622
+ if (key === "governance_close_validation_default") {
623
+ return withWarnings({
624
+ scope,
625
+ key,
626
+ policy: settings.governance.close_validation_default,
627
+ settings_path: target.settingsPath,
628
+ changed: false,
629
+ }, warnings);
630
+ }
631
+ if (key === "governance_parent_reference_policy") {
632
+ return withWarnings({
633
+ scope,
634
+ key,
635
+ policy: settings.governance.parent_reference,
636
+ settings_path: target.settingsPath,
637
+ changed: false,
638
+ }, warnings);
639
+ }
640
+ if (key === "governance_metadata_validation_profile") {
641
+ return withWarnings({
642
+ scope,
643
+ key,
644
+ policy: settings.governance.metadata_profile,
645
+ settings_path: target.settingsPath,
646
+ changed: false,
647
+ }, warnings);
648
+ }
649
+ if (key === "governance_force_required_for_stale_lock") {
650
+ return withWarnings({
651
+ scope,
652
+ key,
653
+ policy: settings.governance.force_required_for_stale_lock ? "enabled" : "disabled",
654
+ settings_path: target.settingsPath,
655
+ changed: false,
656
+ }, warnings);
657
+ }
658
+ if (key === "test_result_tracking") {
659
+ return withWarnings({
660
+ scope,
661
+ key,
662
+ policy: settings.testing.record_results_to_items ? "enabled" : "disabled",
663
+ settings_path: target.settingsPath,
664
+ changed: false,
665
+ }, warnings);
666
+ }
667
+ if (key === "telemetry_tracking") {
668
+ return withWarnings({
669
+ scope,
670
+ key,
671
+ policy: settings.telemetry.enabled ? "enabled" : "disabled",
672
+ settings_path: target.settingsPath,
673
+ changed: false,
674
+ }, warnings);
675
+ }
676
+ return withWarnings({
50
677
  scope,
51
678
  key,
52
679
  criteria: [...settings.workflow.definition_of_done],
53
680
  settings_path: target.settingsPath,
54
681
  changed: false,
55
- };
682
+ }, warnings);
683
+ }
684
+ if (!key) {
685
+ throw new PmCliError('Config action "set" requires <key>', EXIT_CODE.USAGE);
56
686
  }
57
- const nextCriteria = normalizeCriteria(options.criterion);
687
+ if (options.clearCriteria === true && !isCriteriaConfigKey(key)) {
688
+ throw new PmCliError("--clear-criteria is only supported with config set criteria-list keys", EXIT_CODE.USAGE);
689
+ }
690
+ if (key === "item_format") {
691
+ const nextFormat = normalizeItemFormat(options.format);
692
+ const changed = settings.item_format !== nextFormat || !metadata.has_explicit_item_format;
693
+ let migration = undefined;
694
+ settings.item_format = nextFormat;
695
+ if (changed) {
696
+ await writeSettings(target.pmRoot, settings, "config:set:item_format");
697
+ const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());
698
+ const migrated = await migrateItemFilesToFormat(target.pmRoot, nextFormat, "config:set:item_format:migrate", typeRegistry.type_to_folder, settings.schema);
699
+ migration = {
700
+ target_format: migrated.target_format,
701
+ scanned: migrated.scanned,
702
+ migrated: migrated.migrated,
703
+ removed: migrated.removed,
704
+ warnings: migrated.warnings,
705
+ };
706
+ }
707
+ return withWarnings({
708
+ scope,
709
+ key,
710
+ format: settings.item_format,
711
+ has_explicit_item_format: true,
712
+ migration,
713
+ settings_path: target.settingsPath,
714
+ changed,
715
+ }, warnings);
716
+ }
717
+ if (key === "history_missing_stream_policy") {
718
+ const nextPolicy = normalizeHistoryMissingStreamPolicy(options.policy);
719
+ const changed = settings.history.missing_stream !== nextPolicy;
720
+ settings.history.missing_stream = nextPolicy;
721
+ if (changed) {
722
+ await writeSettings(target.pmRoot, settings, "config:set:history_missing_stream_policy");
723
+ }
724
+ return withWarnings({
725
+ scope,
726
+ key,
727
+ policy: settings.history.missing_stream,
728
+ settings_path: target.settingsPath,
729
+ changed,
730
+ }, warnings);
731
+ }
732
+ if (key === "sprint_release_format_policy") {
733
+ const nextPolicy = normalizeSprintReleaseFormatPolicy(options.policy);
734
+ const changed = settings.validation.sprint_release_format !== nextPolicy;
735
+ settings.validation.sprint_release_format = nextPolicy;
736
+ if (changed) {
737
+ await writeSettings(target.pmRoot, settings, "config:set:sprint_release_format_policy");
738
+ }
739
+ return withWarnings({
740
+ scope,
741
+ key,
742
+ policy: settings.validation.sprint_release_format,
743
+ settings_path: target.settingsPath,
744
+ changed,
745
+ }, warnings);
746
+ }
747
+ if (key === "parent_reference_policy") {
748
+ const nextPolicy = normalizeParentReferencePolicy(options.policy);
749
+ const changed = settings.validation.parent_reference !== nextPolicy ||
750
+ settings.governance.preset !== "custom" ||
751
+ settings.governance.parent_reference !== nextPolicy;
752
+ settings.validation.parent_reference = nextPolicy;
753
+ settings.governance.preset = "custom";
754
+ settings.governance.parent_reference = nextPolicy;
755
+ if (changed) {
756
+ await writeSettings(target.pmRoot, settings, "config:set:parent_reference_policy");
757
+ }
758
+ return withWarnings({
759
+ scope,
760
+ key,
761
+ policy: settings.validation.parent_reference,
762
+ settings_path: target.settingsPath,
763
+ changed,
764
+ }, warnings);
765
+ }
766
+ if (key === "metadata_validation_profile") {
767
+ const nextPolicy = normalizeValidateMetadataProfile(options.policy);
768
+ const changed = settings.validation.metadata_profile !== nextPolicy ||
769
+ settings.governance.preset !== "custom" ||
770
+ settings.governance.metadata_profile !== nextPolicy;
771
+ settings.validation.metadata_profile = nextPolicy;
772
+ settings.governance.preset = "custom";
773
+ settings.governance.metadata_profile = nextPolicy;
774
+ if (changed) {
775
+ await writeSettings(target.pmRoot, settings, "config:set:metadata_validation_profile");
776
+ }
777
+ return withWarnings({
778
+ scope,
779
+ key,
780
+ policy: settings.validation.metadata_profile,
781
+ settings_path: target.settingsPath,
782
+ changed,
783
+ }, warnings);
784
+ }
785
+ if (key === "metadata_required_fields") {
786
+ const nextCriteria = normalizeMetadataRequiredFields(options.criterion, options.clearCriteria);
787
+ const changed = nextCriteria.length !== settings.validation.metadata_required_fields.length ||
788
+ nextCriteria.some((value, index) => value !== settings.validation.metadata_required_fields[index]);
789
+ settings.validation.metadata_required_fields = nextCriteria;
790
+ if (changed) {
791
+ await writeSettings(target.pmRoot, settings, "config:set:metadata_required_fields");
792
+ }
793
+ return withWarnings({
794
+ scope,
795
+ key,
796
+ criteria: [...settings.validation.metadata_required_fields],
797
+ settings_path: target.settingsPath,
798
+ changed,
799
+ }, warnings);
800
+ }
801
+ if (key === "lifecycle_stale_blocker_reason_patterns") {
802
+ const nextCriteria = normalizeLifecyclePatternCriteria(key, options.criterion, options.clearCriteria);
803
+ const changed = nextCriteria.length !== settings.validation.lifecycle_stale_blocker_reason_patterns.length ||
804
+ nextCriteria.some((value, index) => value !== settings.validation.lifecycle_stale_blocker_reason_patterns[index]);
805
+ settings.validation.lifecycle_stale_blocker_reason_patterns = nextCriteria;
806
+ if (changed) {
807
+ await writeSettings(target.pmRoot, settings, "config:set:lifecycle_stale_blocker_reason_patterns");
808
+ }
809
+ return withWarnings({
810
+ scope,
811
+ key,
812
+ criteria: [...settings.validation.lifecycle_stale_blocker_reason_patterns],
813
+ settings_path: target.settingsPath,
814
+ changed,
815
+ }, warnings);
816
+ }
817
+ if (key === "lifecycle_closure_like_blocked_reason_patterns") {
818
+ const nextCriteria = normalizeLifecyclePatternCriteria(key, options.criterion, options.clearCriteria);
819
+ const changed = nextCriteria.length !== settings.validation.lifecycle_closure_like_blocked_reason_patterns.length ||
820
+ nextCriteria.some((value, index) => value !== settings.validation.lifecycle_closure_like_blocked_reason_patterns[index]);
821
+ settings.validation.lifecycle_closure_like_blocked_reason_patterns = nextCriteria;
822
+ if (changed) {
823
+ await writeSettings(target.pmRoot, settings, "config:set:lifecycle_closure_like_blocked_reason_patterns");
824
+ }
825
+ return withWarnings({
826
+ scope,
827
+ key,
828
+ criteria: [...settings.validation.lifecycle_closure_like_blocked_reason_patterns],
829
+ settings_path: target.settingsPath,
830
+ changed,
831
+ }, warnings);
832
+ }
833
+ if (key === "lifecycle_closure_like_resolution_patterns") {
834
+ const nextCriteria = normalizeLifecyclePatternCriteria(key, options.criterion, options.clearCriteria);
835
+ const changed = nextCriteria.length !== settings.validation.lifecycle_closure_like_resolution_patterns.length ||
836
+ nextCriteria.some((value, index) => value !== settings.validation.lifecycle_closure_like_resolution_patterns[index]);
837
+ settings.validation.lifecycle_closure_like_resolution_patterns = nextCriteria;
838
+ if (changed) {
839
+ await writeSettings(target.pmRoot, settings, "config:set:lifecycle_closure_like_resolution_patterns");
840
+ }
841
+ return withWarnings({
842
+ scope,
843
+ key,
844
+ criteria: [...settings.validation.lifecycle_closure_like_resolution_patterns],
845
+ settings_path: target.settingsPath,
846
+ changed,
847
+ }, warnings);
848
+ }
849
+ if (key === "lifecycle_closure_like_actual_result_patterns") {
850
+ const nextCriteria = normalizeLifecyclePatternCriteria(key, options.criterion, options.clearCriteria);
851
+ const changed = nextCriteria.length !== settings.validation.lifecycle_closure_like_actual_result_patterns.length ||
852
+ nextCriteria.some((value, index) => value !== settings.validation.lifecycle_closure_like_actual_result_patterns[index]);
853
+ settings.validation.lifecycle_closure_like_actual_result_patterns = nextCriteria;
854
+ if (changed) {
855
+ await writeSettings(target.pmRoot, settings, "config:set:lifecycle_closure_like_actual_result_patterns");
856
+ }
857
+ return withWarnings({
858
+ scope,
859
+ key,
860
+ criteria: [...settings.validation.lifecycle_closure_like_actual_result_patterns],
861
+ settings_path: target.settingsPath,
862
+ changed,
863
+ }, warnings);
864
+ }
865
+ if (key === "governance_preset") {
866
+ const nextPolicy = normalizeGovernancePreset(options.policy);
867
+ const changed = settings.governance.preset !== nextPolicy;
868
+ settings.governance.preset = nextPolicy;
869
+ if (changed) {
870
+ await writeSettings(target.pmRoot, settings, "config:set:governance_preset");
871
+ }
872
+ return withWarnings({
873
+ scope,
874
+ key,
875
+ policy: settings.governance.preset,
876
+ settings_path: target.settingsPath,
877
+ changed,
878
+ }, warnings);
879
+ }
880
+ if (key === "governance_ownership_enforcement") {
881
+ const nextPolicy = normalizeGovernanceOwnershipEnforcement(options.policy);
882
+ const changed = settings.governance.preset !== "custom" || settings.governance.ownership_enforcement !== nextPolicy;
883
+ settings.governance.preset = "custom";
884
+ settings.governance.ownership_enforcement = nextPolicy;
885
+ if (changed) {
886
+ await writeSettings(target.pmRoot, settings, "config:set:governance_ownership_enforcement");
887
+ }
888
+ return withWarnings({
889
+ scope,
890
+ key,
891
+ policy: settings.governance.ownership_enforcement,
892
+ settings_path: target.settingsPath,
893
+ changed,
894
+ }, warnings);
895
+ }
896
+ if (key === "governance_create_mode_default") {
897
+ const nextPolicy = normalizeGovernanceCreateModeDefault(options.policy);
898
+ const changed = settings.governance.preset !== "custom" || settings.governance.create_mode_default !== nextPolicy;
899
+ settings.governance.preset = "custom";
900
+ settings.governance.create_mode_default = nextPolicy;
901
+ if (changed) {
902
+ await writeSettings(target.pmRoot, settings, "config:set:governance_create_mode_default");
903
+ }
904
+ return withWarnings({
905
+ scope,
906
+ key,
907
+ policy: settings.governance.create_mode_default,
908
+ settings_path: target.settingsPath,
909
+ changed,
910
+ }, warnings);
911
+ }
912
+ if (key === "governance_close_validation_default") {
913
+ const nextPolicy = normalizeGovernanceCloseValidationDefault(options.policy);
914
+ const changed = settings.governance.preset !== "custom" || settings.governance.close_validation_default !== nextPolicy;
915
+ settings.governance.preset = "custom";
916
+ settings.governance.close_validation_default = nextPolicy;
917
+ if (changed) {
918
+ await writeSettings(target.pmRoot, settings, "config:set:governance_close_validation_default");
919
+ }
920
+ return withWarnings({
921
+ scope,
922
+ key,
923
+ policy: settings.governance.close_validation_default,
924
+ settings_path: target.settingsPath,
925
+ changed,
926
+ }, warnings);
927
+ }
928
+ if (key === "governance_parent_reference_policy") {
929
+ const nextPolicy = normalizeParentReferencePolicy(options.policy);
930
+ const changed = settings.governance.preset !== "custom" || settings.governance.parent_reference !== nextPolicy;
931
+ settings.governance.preset = "custom";
932
+ settings.governance.parent_reference = nextPolicy;
933
+ settings.validation.parent_reference = nextPolicy;
934
+ if (changed) {
935
+ await writeSettings(target.pmRoot, settings, "config:set:governance_parent_reference_policy");
936
+ }
937
+ return withWarnings({
938
+ scope,
939
+ key,
940
+ policy: settings.governance.parent_reference,
941
+ settings_path: target.settingsPath,
942
+ changed,
943
+ }, warnings);
944
+ }
945
+ if (key === "governance_metadata_validation_profile") {
946
+ const nextPolicy = normalizeValidateMetadataProfile(options.policy);
947
+ const changed = settings.governance.preset !== "custom" || settings.governance.metadata_profile !== nextPolicy;
948
+ settings.governance.preset = "custom";
949
+ settings.governance.metadata_profile = nextPolicy;
950
+ settings.validation.metadata_profile = nextPolicy;
951
+ if (changed) {
952
+ await writeSettings(target.pmRoot, settings, "config:set:governance_metadata_validation_profile");
953
+ }
954
+ return withWarnings({
955
+ scope,
956
+ key,
957
+ policy: settings.governance.metadata_profile,
958
+ settings_path: target.settingsPath,
959
+ changed,
960
+ }, warnings);
961
+ }
962
+ if (key === "governance_force_required_for_stale_lock") {
963
+ const nextPolicy = normalizeGovernanceForceRequiredForStaleLockPolicy(options.policy);
964
+ const nextEnabled = nextPolicy === "enabled";
965
+ const changed = settings.governance.preset !== "custom" || settings.governance.force_required_for_stale_lock !== nextEnabled;
966
+ settings.governance.preset = "custom";
967
+ settings.governance.force_required_for_stale_lock = nextEnabled;
968
+ if (changed) {
969
+ await writeSettings(target.pmRoot, settings, "config:set:governance_force_required_for_stale_lock");
970
+ }
971
+ return withWarnings({
972
+ scope,
973
+ key,
974
+ policy: settings.governance.force_required_for_stale_lock ? "enabled" : "disabled",
975
+ settings_path: target.settingsPath,
976
+ changed,
977
+ }, warnings);
978
+ }
979
+ if (key === "test_result_tracking") {
980
+ const nextPolicy = normalizeTestResultTrackingPolicy(options.policy);
981
+ const nextEnabled = nextPolicy === "enabled";
982
+ const changed = settings.testing.record_results_to_items !== nextEnabled;
983
+ settings.testing.record_results_to_items = nextEnabled;
984
+ if (changed) {
985
+ await writeSettings(target.pmRoot, settings, "config:set:test_result_tracking");
986
+ }
987
+ return withWarnings({
988
+ scope,
989
+ key,
990
+ policy: settings.testing.record_results_to_items ? "enabled" : "disabled",
991
+ settings_path: target.settingsPath,
992
+ changed,
993
+ }, warnings);
994
+ }
995
+ if (key === "telemetry_tracking") {
996
+ const nextPolicy = normalizeTelemetryTrackingPolicy(options.policy);
997
+ const nextEnabled = nextPolicy === "enabled";
998
+ const changed = settings.telemetry.enabled !== nextEnabled || !settings.telemetry.first_run_prompt_completed;
999
+ settings.telemetry.enabled = nextEnabled;
1000
+ settings.telemetry.first_run_prompt_completed = true;
1001
+ if (changed) {
1002
+ await writeSettings(target.pmRoot, settings, "config:set:telemetry_tracking");
1003
+ }
1004
+ return withWarnings({
1005
+ scope,
1006
+ key,
1007
+ policy: settings.telemetry.enabled ? "enabled" : "disabled",
1008
+ settings_path: target.settingsPath,
1009
+ changed,
1010
+ }, warnings);
1011
+ }
1012
+ const nextCriteria = normalizeCriteria(options.criterion, options.clearCriteria);
58
1013
  const changed = nextCriteria.length !== settings.workflow.definition_of_done.length ||
59
1014
  nextCriteria.some((value, index) => value !== settings.workflow.definition_of_done[index]);
60
1015
  settings.workflow.definition_of_done = nextCriteria;
61
1016
  if (changed) {
62
1017
  await writeSettings(target.pmRoot, settings, "config:set:definition_of_done");
63
1018
  }
64
- return {
1019
+ return withWarnings({
65
1020
  scope,
66
1021
  key,
67
1022
  criteria: [...settings.workflow.definition_of_done],
68
1023
  settings_path: target.settingsPath,
69
1024
  changed,
70
- };
1025
+ }, warnings);
71
1026
  }
72
1027
  //# sourceMappingURL=config.js.map