@unbrained/pm-cli 2026.5.24 → 2026.5.28

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 (246) hide show
  1. package/CHANGELOG.md +953 -522
  2. package/README.md +2 -10
  3. package/dist/cli/bootstrap-args.d.ts +18 -1
  4. package/dist/cli/bootstrap-args.js +143 -3
  5. package/dist/cli/bootstrap-args.js.map +1 -1
  6. package/dist/cli/commander-usage.js +134 -11
  7. package/dist/cli/commander-usage.js.map +1 -1
  8. package/dist/cli/commands/append.js +4 -3
  9. package/dist/cli/commands/append.js.map +1 -1
  10. package/dist/cli/commands/claim.js +5 -4
  11. package/dist/cli/commands/claim.js.map +1 -1
  12. package/dist/cli/commands/close.d.ts +3 -0
  13. package/dist/cli/commands/close.js +26 -3
  14. package/dist/cli/commands/close.js.map +1 -1
  15. package/dist/cli/commands/completion.d.ts +2 -2
  16. package/dist/cli/commands/completion.js +109 -56
  17. package/dist/cli/commands/completion.js.map +1 -1
  18. package/dist/cli/commands/config.d.ts +1 -1
  19. package/dist/cli/commands/config.js +82 -4
  20. package/dist/cli/commands/config.js.map +1 -1
  21. package/dist/cli/commands/create.js +7 -272
  22. package/dist/cli/commands/create.js.map +1 -1
  23. package/dist/cli/commands/delete.js +4 -3
  24. package/dist/cli/commands/delete.js.map +1 -1
  25. package/dist/cli/commands/docs.d.ts +1 -12
  26. package/dist/cli/commands/docs.js +8 -312
  27. package/dist/cli/commands/docs.js.map +1 -1
  28. package/dist/cli/commands/extension/bundled-catalog.d.ts +14 -0
  29. package/dist/cli/commands/extension/bundled-catalog.js +268 -0
  30. package/dist/cli/commands/extension/bundled-catalog.js.map +1 -0
  31. package/dist/cli/commands/extension/doctor.d.ts +31 -0
  32. package/dist/cli/commands/extension/doctor.js +345 -0
  33. package/dist/cli/commands/extension/doctor.js.map +1 -0
  34. package/dist/cli/commands/extension/install-sources.d.ts +37 -0
  35. package/dist/cli/commands/extension/install-sources.js +384 -0
  36. package/dist/cli/commands/extension/install-sources.js.map +1 -0
  37. package/dist/cli/commands/extension/managed-state.d.ts +48 -0
  38. package/dist/cli/commands/extension/managed-state.js +172 -0
  39. package/dist/cli/commands/extension/managed-state.js.map +1 -0
  40. package/dist/cli/commands/extension/scaffold.d.ts +14 -0
  41. package/dist/cli/commands/extension/scaffold.js +202 -0
  42. package/dist/cli/commands/extension/scaffold.js.map +1 -0
  43. package/dist/cli/commands/extension/shared.d.ts +14 -0
  44. package/dist/cli/commands/extension/shared.js +106 -0
  45. package/dist/cli/commands/extension/shared.js.map +1 -0
  46. package/dist/cli/commands/extension.d.ts +36 -68
  47. package/dist/cli/commands/extension.js +143 -1422
  48. package/dist/cli/commands/extension.js.map +1 -1
  49. package/dist/cli/commands/files.d.ts +1 -12
  50. package/dist/cli/commands/files.js +11 -308
  51. package/dist/cli/commands/files.js.map +1 -1
  52. package/dist/cli/commands/get.js +4 -3
  53. package/dist/cli/commands/get.js.map +1 -1
  54. package/dist/cli/commands/health.js +17 -3
  55. package/dist/cli/commands/health.js.map +1 -1
  56. package/dist/cli/commands/history-redact.js +23 -18
  57. package/dist/cli/commands/history-redact.js.map +1 -1
  58. package/dist/cli/commands/history-repair.js +24 -18
  59. package/dist/cli/commands/history-repair.js.map +1 -1
  60. package/dist/cli/commands/legacy-none-tokens.d.ts +3 -0
  61. package/dist/cli/commands/legacy-none-tokens.js +39 -0
  62. package/dist/cli/commands/legacy-none-tokens.js.map +1 -0
  63. package/dist/cli/commands/linked-artifacts.d.ts +96 -0
  64. package/dist/cli/commands/linked-artifacts.js +335 -0
  65. package/dist/cli/commands/linked-artifacts.js.map +1 -0
  66. package/dist/cli/commands/linked-test-parsers.d.ts +28 -0
  67. package/dist/cli/commands/linked-test-parsers.js +192 -0
  68. package/dist/cli/commands/linked-test-parsers.js.map +1 -0
  69. package/dist/cli/commands/list.js +19 -5
  70. package/dist/cli/commands/list.js.map +1 -1
  71. package/dist/cli/commands/normalize.js +4 -3
  72. package/dist/cli/commands/normalize.js.map +1 -1
  73. package/dist/cli/commands/plan.d.ts +5 -0
  74. package/dist/cli/commands/plan.js +56 -8
  75. package/dist/cli/commands/plan.js.map +1 -1
  76. package/dist/cli/commands/recurrence-parsers.d.ts +26 -0
  77. package/dist/cli/commands/recurrence-parsers.js +98 -0
  78. package/dist/cli/commands/recurrence-parsers.js.map +1 -0
  79. package/dist/cli/commands/restore.js +19 -8
  80. package/dist/cli/commands/restore.js.map +1 -1
  81. package/dist/cli/commands/search.js +5 -8
  82. package/dist/cli/commands/search.js.map +1 -1
  83. package/dist/cli/commands/test/linked-command-detection.d.ts +37 -0
  84. package/dist/cli/commands/test/linked-command-detection.js +200 -0
  85. package/dist/cli/commands/test/linked-command-detection.js.map +1 -0
  86. package/dist/cli/commands/test.d.ts +1 -2
  87. package/dist/cli/commands/test.js +8 -350
  88. package/dist/cli/commands/test.js.map +1 -1
  89. package/dist/cli/commands/update-many.js +4 -3
  90. package/dist/cli/commands/update-many.js.map +1 -1
  91. package/dist/cli/commands/update.js +83 -356
  92. package/dist/cli/commands/update.js.map +1 -1
  93. package/dist/cli/commands/validate.js +32 -12
  94. package/dist/cli/commands/validate.js.map +1 -1
  95. package/dist/cli/error-guidance.d.ts +1 -0
  96. package/dist/cli/error-guidance.js +6 -2
  97. package/dist/cli/error-guidance.js.map +1 -1
  98. package/dist/cli/main.d.ts +11 -0
  99. package/dist/cli/main.js +76 -28
  100. package/dist/cli/main.js.map +1 -1
  101. package/dist/cli/register-list-query.d.ts +4 -1
  102. package/dist/cli/register-list-query.js +242 -203
  103. package/dist/cli/register-list-query.js.map +1 -1
  104. package/dist/cli/register-mutation.js +73 -11
  105. package/dist/cli/register-mutation.js.map +1 -1
  106. package/dist/cli/register-operations.js +3 -3
  107. package/dist/cli/register-operations.js.map +1 -1
  108. package/dist/cli/register-setup.js +12 -7
  109. package/dist/cli/register-setup.js.map +1 -1
  110. package/dist/cli/registration-helpers.js +3 -2
  111. package/dist/cli/registration-helpers.js.map +1 -1
  112. package/dist/cli.js +4 -3
  113. package/dist/cli.js.map +1 -1
  114. package/dist/core/config/positional-value.d.ts +44 -0
  115. package/dist/core/config/positional-value.js +109 -0
  116. package/dist/core/config/positional-value.js.map +1 -0
  117. package/dist/core/extensions/extension-capability-aliases.d.ts +14 -0
  118. package/dist/core/extensions/extension-capability-aliases.js +159 -0
  119. package/dist/core/extensions/extension-capability-aliases.js.map +1 -0
  120. package/dist/core/extensions/extension-hook-runtime.d.ts +13 -0
  121. package/dist/core/extensions/extension-hook-runtime.js +414 -0
  122. package/dist/core/extensions/extension-hook-runtime.js.map +1 -0
  123. package/dist/core/extensions/extension-policy.d.ts +69 -0
  124. package/dist/core/extensions/extension-policy.js +481 -0
  125. package/dist/core/extensions/extension-policy.js.map +1 -0
  126. package/dist/core/extensions/extension-registries.d.ts +8 -0
  127. package/dist/core/extensions/extension-registries.js +52 -0
  128. package/dist/core/extensions/extension-registries.js.map +1 -0
  129. package/dist/core/extensions/extension-runtime-helpers.d.ts +6 -0
  130. package/dist/core/extensions/extension-runtime-helpers.js +29 -0
  131. package/dist/core/extensions/extension-runtime-helpers.js.map +1 -0
  132. package/dist/core/extensions/extension-types.d.ts +13 -39
  133. package/dist/core/extensions/extension-types.js +34 -2
  134. package/dist/core/extensions/extension-types.js.map +1 -1
  135. package/dist/core/extensions/index.d.ts +7 -0
  136. package/dist/core/extensions/index.js +11 -2
  137. package/dist/core/extensions/index.js.map +1 -1
  138. package/dist/core/extensions/loader.d.ts +4 -22
  139. package/dist/core/extensions/loader.js +22 -1139
  140. package/dist/core/extensions/loader.js.map +1 -1
  141. package/dist/core/history/drift-scan.d.ts +11 -0
  142. package/dist/core/history/drift-scan.js +114 -32
  143. package/dist/core/history/drift-scan.js.map +1 -1
  144. package/dist/core/history/history-rewrite.d.ts +43 -0
  145. package/dist/core/history/history-rewrite.js +48 -0
  146. package/dist/core/history/history-rewrite.js.map +1 -0
  147. package/dist/core/history/history.js +5 -4
  148. package/dist/core/history/history.js.map +1 -1
  149. package/dist/core/history/replay.js +4 -3
  150. package/dist/core/history/replay.js.map +1 -1
  151. package/dist/core/item/item-record.d.ts +19 -0
  152. package/dist/core/item/item-record.js +24 -0
  153. package/dist/core/item/item-record.js.map +1 -0
  154. package/dist/core/output/mutation-projection.d.ts +31 -0
  155. package/dist/core/output/mutation-projection.js +103 -0
  156. package/dist/core/output/mutation-projection.js.map +1 -0
  157. package/dist/core/output/output.d.ts +2 -0
  158. package/dist/core/output/output.js +5 -3
  159. package/dist/core/output/output.js.map +1 -1
  160. package/dist/core/schema/runtime-schema.js +8 -38
  161. package/dist/core/schema/runtime-schema.js.map +1 -1
  162. package/dist/core/search/vector-stores.js +46 -9
  163. package/dist/core/search/vector-stores.js.map +1 -1
  164. package/dist/core/sentry/helpers.d.ts +1 -1
  165. package/dist/core/sentry/helpers.js +20 -3
  166. package/dist/core/sentry/helpers.js.map +1 -1
  167. package/dist/core/shared/command-types.d.ts +1 -0
  168. package/dist/core/shared/command-types.js +2 -2
  169. package/dist/core/shared/command-types.js.map +1 -1
  170. package/dist/core/shared/constants.d.ts +10 -1
  171. package/dist/core/shared/constants.js +56 -58
  172. package/dist/core/shared/constants.js.map +1 -1
  173. package/dist/core/shared/levenshtein.js +23 -7
  174. package/dist/core/shared/levenshtein.js.map +1 -1
  175. package/dist/core/shared/primitives.d.ts +23 -0
  176. package/dist/core/shared/primitives.js +39 -2
  177. package/dist/core/shared/primitives.js.map +1 -1
  178. package/dist/core/store/front-matter-cache.d.ts +16 -2
  179. package/dist/core/store/front-matter-cache.js +99 -33
  180. package/dist/core/store/front-matter-cache.js.map +1 -1
  181. package/dist/core/store/item-store.js +8 -73
  182. package/dist/core/store/item-store.js.map +1 -1
  183. package/dist/mcp/server.js +76 -28
  184. package/dist/mcp/server.js.map +1 -1
  185. package/dist/sdk/cli-contracts/enum-contracts.d.ts +20 -0
  186. package/dist/sdk/cli-contracts/enum-contracts.js +156 -0
  187. package/dist/sdk/cli-contracts/enum-contracts.js.map +1 -0
  188. package/dist/sdk/cli-contracts/tool-option-contracts.d.ts +14 -0
  189. package/dist/sdk/cli-contracts/tool-option-contracts.js +243 -0
  190. package/dist/sdk/cli-contracts/tool-option-contracts.js.map +1 -0
  191. package/dist/sdk/cli-contracts/tool-parameter-tables.d.ts +11 -0
  192. package/dist/sdk/cli-contracts/tool-parameter-tables.js +901 -0
  193. package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -0
  194. package/dist/sdk/cli-contracts.d.ts +11 -33
  195. package/dist/sdk/cli-contracts.js +30 -1356
  196. package/dist/sdk/cli-contracts.js.map +1 -1
  197. package/dist/sdk/package-import-adapters.d.ts +74 -0
  198. package/dist/sdk/package-import-adapters.js +186 -0
  199. package/dist/sdk/package-import-adapters.js.map +1 -0
  200. package/dist/sdk/package-runtime-options.d.ts +26 -0
  201. package/dist/sdk/package-runtime-options.js +71 -0
  202. package/dist/sdk/package-runtime-options.js.map +1 -0
  203. package/dist/sdk/runtime.d.ts +2 -0
  204. package/dist/sdk/runtime.js +4 -2
  205. package/dist/sdk/runtime.js.map +1 -1
  206. package/docs/AGENT_GUIDE.md +6 -10
  207. package/docs/CLAUDE_CODE_PLUGIN.md +5 -28
  208. package/docs/CODEX_PLUGIN.md +5 -5
  209. package/docs/COMMANDS.md +19 -3
  210. package/docs/CONFIGURATION.md +15 -0
  211. package/docs/EXTENSIONS.md +4 -63
  212. package/docs/RELEASING.md +4 -4
  213. package/marketplace.json +7 -3
  214. package/package.json +9 -6
  215. package/packages/pm-beads/extensions/beads/index.js +2 -49
  216. package/packages/pm-beads/extensions/beads/index.ts +2 -54
  217. package/packages/pm-beads/extensions/beads/runtime-loader.js +86 -0
  218. package/packages/pm-beads/extensions/beads/runtime-loader.ts +88 -0
  219. package/packages/pm-beads/extensions/beads/runtime.js +26 -115
  220. package/packages/pm-beads/extensions/beads/runtime.ts +33 -132
  221. package/packages/pm-calendar/extensions/calendar/index.js +47 -2
  222. package/packages/pm-calendar/extensions/calendar/index.ts +52 -2
  223. package/packages/pm-calendar/extensions/calendar/runtime.js +1 -0
  224. package/packages/pm-calendar/extensions/calendar/runtime.ts +1 -0
  225. package/packages/pm-governance-audit/extensions/governance-audit/runtime.js +14 -41
  226. package/packages/pm-governance-audit/extensions/governance-audit/runtime.ts +25 -41
  227. package/packages/pm-guide-shell/extensions/guide-shell/runtime.js +10 -50
  228. package/packages/pm-guide-shell/extensions/guide-shell/runtime.ts +17 -50
  229. package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.js +8 -40
  230. package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.ts +10 -40
  231. package/packages/pm-search-advanced/extensions/search-advanced/index.js +1 -1
  232. package/packages/pm-search-advanced/extensions/search-advanced/runtime.js +4 -37
  233. package/packages/pm-search-advanced/extensions/search-advanced/runtime.ts +6 -37
  234. package/packages/pm-todos/extensions/todos/index.js +3 -50
  235. package/packages/pm-todos/extensions/todos/index.ts +3 -55
  236. package/packages/pm-todos/extensions/todos/runtime-loader.js +86 -0
  237. package/packages/pm-todos/extensions/todos/runtime-loader.ts +88 -0
  238. package/packages/pm-todos/extensions/todos/runtime.js +24 -117
  239. package/packages/pm-todos/extensions/todos/runtime.ts +32 -129
  240. package/plugins/pm-claude/README.md +2 -2
  241. package/plugins/pm-claude/commands/pm-planner.md +1 -15
  242. package/plugins/pm-claude/scripts/pm-mcp-server.mjs +5 -2
  243. package/plugins/pm-claude/skills/pm-planner/SKILL.md +3 -21
  244. package/plugins/pm-codex/scripts/pm-mcp-server.mjs +15 -6
  245. package/plugins/pm-codex/skills/pm-native/SKILL.md +1 -13
  246. package/PRD.md +0 -1734
@@ -8,6 +8,8 @@ interface GovernanceRuntimeSdkModule {
8
8
  runDedupeAudit: (options: Record<string, unknown>, global: GlobalOptions) => Promise<unknown>;
9
9
  runCommentsAudit: (options: Record<string, unknown>, global: GlobalOptions) => Promise<unknown>;
10
10
  runNormalize: (options: Record<string, unknown>, global: GlobalOptions) => Promise<unknown>;
11
+ readStringOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => string | undefined;
12
+ readBooleanOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => boolean | undefined;
11
13
  }
12
14
 
13
15
  let governanceModule: GovernanceRuntimeSdkModule | null = null;
@@ -37,7 +39,9 @@ async function loadGovernanceModule(): Promise<GovernanceRuntimeSdkModule> {
37
39
  if (
38
40
  typeof loaded.runDedupeAudit === "function" &&
39
41
  typeof loaded.runCommentsAudit === "function" &&
40
- typeof loaded.runNormalize === "function"
42
+ typeof loaded.runNormalize === "function" &&
43
+ typeof loaded.readStringOption === "function" &&
44
+ typeof loaded.readBooleanOption === "function"
41
45
  ) {
42
46
  return loaded as GovernanceRuntimeSdkModule;
43
47
  }
@@ -49,41 +53,11 @@ async function loadGovernanceModule(): Promise<GovernanceRuntimeSdkModule> {
49
53
  );
50
54
  }
51
55
 
52
- function readStringOption(options: Record<string, unknown>, key: string, aliases: string[] = []): string | undefined {
53
- const keys = [key, ...aliases];
54
- for (const candidate of keys) {
55
- const value = options[candidate];
56
- if (typeof value === "string" && value.trim().length > 0) {
57
- return value;
58
- }
59
- }
60
- return undefined;
61
- }
62
-
63
- function readBooleanOption(options: Record<string, unknown>, key: string, aliases: string[] = []): boolean | undefined {
64
- const keys = [key, ...aliases];
65
- for (const candidate of keys) {
66
- const value = options[candidate];
67
- if (value === undefined) {
68
- continue;
69
- }
70
- if (typeof value === "boolean") {
71
- return value;
72
- }
73
- if (typeof value === "string") {
74
- const normalized = value.trim().toLowerCase();
75
- if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on") {
76
- return true;
77
- }
78
- if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "off") {
79
- return false;
80
- }
81
- }
82
- }
83
- return undefined;
84
- }
85
-
86
- function normalizeDedupeAuditOptions(raw: Record<string, unknown>): Record<string, unknown> {
56
+ function normalizeDedupeAuditOptions(
57
+ sdk: GovernanceRuntimeSdkModule,
58
+ raw: Record<string, unknown>,
59
+ ): Record<string, unknown> {
60
+ const readStringOption = sdk.readStringOption;
87
61
  return {
88
62
  mode: readStringOption(raw, "mode"),
89
63
  status: readStringOption(raw, "status"),
@@ -102,7 +76,12 @@ function normalizeDedupeAuditOptions(raw: Record<string, unknown>): Record<strin
102
76
  };
103
77
  }
104
78
 
105
- function normalizeCommentsAuditOptions(raw: Record<string, unknown>): Record<string, unknown> {
79
+ function normalizeCommentsAuditOptions(
80
+ sdk: GovernanceRuntimeSdkModule,
81
+ raw: Record<string, unknown>,
82
+ ): Record<string, unknown> {
83
+ const readStringOption = sdk.readStringOption;
84
+ const readBooleanOption = sdk.readBooleanOption;
106
85
  return {
107
86
  status: readStringOption(raw, "status"),
108
87
  type: readStringOption(raw, "type"),
@@ -120,7 +99,12 @@ function normalizeCommentsAuditOptions(raw: Record<string, unknown>): Record<str
120
99
  };
121
100
  }
122
101
 
123
- function normalizeNormalizeOptions(raw: Record<string, unknown>): Record<string, unknown> {
102
+ function normalizeNormalizeOptions(
103
+ sdk: GovernanceRuntimeSdkModule,
104
+ raw: Record<string, unknown>,
105
+ ): Record<string, unknown> {
106
+ const readStringOption = sdk.readStringOption;
107
+ const readBooleanOption = sdk.readBooleanOption;
124
108
  return {
125
109
  status: readStringOption(raw, "filterStatus", ["filter_status", "status"]),
126
110
  list: {
@@ -156,7 +140,7 @@ export async function runDedupeAuditPackage(
156
140
  global: GlobalOptions,
157
141
  ): Promise<unknown> {
158
142
  const module = await ensureGovernanceModule();
159
- return module.runDedupeAudit(normalizeDedupeAuditOptions(options), global);
143
+ return module.runDedupeAudit(normalizeDedupeAuditOptions(module, options), global);
160
144
  }
161
145
 
162
146
  export async function runCommentsAuditPackage(
@@ -164,7 +148,7 @@ export async function runCommentsAuditPackage(
164
148
  global: GlobalOptions,
165
149
  ): Promise<unknown> {
166
150
  const module = await ensureGovernanceModule();
167
- return module.runCommentsAudit(normalizeCommentsAuditOptions(options), global);
151
+ return module.runCommentsAudit(normalizeCommentsAuditOptions(module, options), global);
168
152
  }
169
153
 
170
154
  export async function runNormalizePackage(
@@ -172,5 +156,5 @@ export async function runNormalizePackage(
172
156
  global: GlobalOptions,
173
157
  ): Promise<unknown> {
174
158
  const module = await ensureGovernanceModule();
175
- return module.runNormalize(normalizeNormalizeOptions(options), global);
159
+ return module.runNormalize(normalizeNormalizeOptions(module, options), global);
176
160
  }
@@ -39,7 +39,10 @@ async function loadRuntimeBundle() {
39
39
  typeof sdkLoaded.resolveRuntimeStatusRegistry === "function" &&
40
40
  typeof sdkLoaded.resolveRuntimeFieldRegistry === "function" &&
41
41
  typeof sdkLoaded.listAllFrontMatter === "function" &&
42
- typeof sdkLoaded.getActiveExtensionRegistrations === "function"
42
+ typeof sdkLoaded.getActiveExtensionRegistrations === "function" &&
43
+ typeof sdkLoaded.readStringOption === "function" &&
44
+ typeof sdkLoaded.readBooleanOption === "function" &&
45
+ typeof sdkLoaded.readCsvListOption === "function"
43
46
  ) {
44
47
  return {
45
48
  sdk: sdkLoaded,
@@ -53,52 +56,8 @@ async function loadRuntimeBundle() {
53
56
  );
54
57
  }
55
58
 
56
- function readStringOption(options, key, aliases = []) {
57
- const keys = [key, ...aliases];
58
- for (const candidate of keys) {
59
- const value = options[candidate];
60
- if (typeof value === "string" && value.trim().length > 0) {
61
- return value;
62
- }
63
- }
64
- return undefined;
65
- }
66
-
67
- function readBooleanOption(options, key, aliases = []) {
68
- const keys = [key, ...aliases];
69
- for (const candidate of keys) {
70
- const value = options[candidate];
71
- if (value === undefined) {
72
- continue;
73
- }
74
- if (typeof value === "boolean") {
75
- return value;
76
- }
77
- if (typeof value === "string") {
78
- const normalized = value.trim().toLowerCase();
79
- if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on") {
80
- return true;
81
- }
82
- if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "off") {
83
- return false;
84
- }
85
- }
86
- }
87
- return undefined;
88
- }
89
-
90
- function readCsvListOption(options, key, aliases = []) {
91
- const value = readStringOption(options, key, aliases);
92
- if (!value) {
93
- return [];
94
- }
95
- return value
96
- .split(",")
97
- .map((entry) => entry.trim())
98
- .filter((entry) => entry.length > 0);
99
- }
100
-
101
- function normalizeGuideOptions(args, options) {
59
+ function normalizeGuideOptions(bundle, args, options) {
60
+ const { readStringOption, readBooleanOption } = bundle.sdk;
102
61
  const topicFromArgs = args[0];
103
62
  return {
104
63
  topic: readStringOption(options, "topic") ?? (typeof topicFromArgs === "string" && topicFromArgs.trim().length > 0 ? topicFromArgs : undefined),
@@ -108,7 +67,8 @@ function normalizeGuideOptions(args, options) {
108
67
  };
109
68
  }
110
69
 
111
- function normalizeCompletionOptions(args, options) {
70
+ function normalizeCompletionOptions(bundle, args, options) {
71
+ const { readStringOption, readBooleanOption, readCsvListOption } = bundle.sdk;
112
72
  const shellFromOptions = readStringOption(options, "shell");
113
73
  const shellFromArgs = typeof args[0] === "string" && args[0].trim().length > 0 ? args[0].trim() : undefined;
114
74
  return {
@@ -185,12 +145,12 @@ function collectTagsFromItems(items) {
185
145
 
186
146
  export async function runGuidePackage(args, options, global) {
187
147
  const bundle = await ensureRuntimeBundle();
188
- return bundle.sdk.runGuide(normalizeGuideOptions(args, options), global);
148
+ return bundle.sdk.runGuide(normalizeGuideOptions(bundle, args, options), global);
189
149
  }
190
150
 
191
151
  export async function runCompletionPackage(args, options, global) {
192
152
  const bundle = await ensureRuntimeBundle();
193
- const normalized = normalizeCompletionOptions(args, options);
153
+ const normalized = normalizeCompletionOptions(bundle, args, options);
194
154
  const runtimeConfig = await buildCompletionRuntimeConfig(bundle, global);
195
155
  return bundle.sdk.runCompletion(
196
156
  normalized.shell,
@@ -39,6 +39,9 @@ interface RuntimeSdkModule {
39
39
  schema?: unknown,
40
40
  ) => Promise<Array<{ metadata: { tags?: string[] } }>>;
41
41
  getActiveExtensionRegistrations: () => unknown;
42
+ readStringOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => string | undefined;
43
+ readBooleanOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => boolean | undefined;
44
+ readCsvListOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => string[];
42
45
  }
43
46
 
44
47
  interface RuntimeBundle {
@@ -82,7 +85,10 @@ async function loadRuntimeBundle(): Promise<RuntimeBundle> {
82
85
  typeof sdkLoaded.resolveRuntimeStatusRegistry === "function" &&
83
86
  typeof sdkLoaded.resolveRuntimeFieldRegistry === "function" &&
84
87
  typeof sdkLoaded.listAllFrontMatter === "function" &&
85
- typeof sdkLoaded.getActiveExtensionRegistrations === "function"
88
+ typeof sdkLoaded.getActiveExtensionRegistrations === "function" &&
89
+ typeof sdkLoaded.readStringOption === "function" &&
90
+ typeof sdkLoaded.readBooleanOption === "function" &&
91
+ typeof sdkLoaded.readCsvListOption === "function"
86
92
  ) {
87
93
  return {
88
94
  sdk: sdkLoaded as RuntimeSdkModule,
@@ -96,52 +102,12 @@ async function loadRuntimeBundle(): Promise<RuntimeBundle> {
96
102
  );
97
103
  }
98
104
 
99
- function readStringOption(options: Record<string, unknown>, key: string, aliases: string[] = []): string | undefined {
100
- const keys = [key, ...aliases];
101
- for (const candidate of keys) {
102
- const value = options[candidate];
103
- if (typeof value === "string" && value.trim().length > 0) {
104
- return value;
105
- }
106
- }
107
- return undefined;
108
- }
109
-
110
- function readBooleanOption(options: Record<string, unknown>, key: string, aliases: string[] = []): boolean | undefined {
111
- const keys = [key, ...aliases];
112
- for (const candidate of keys) {
113
- const value = options[candidate];
114
- if (value === undefined) {
115
- continue;
116
- }
117
- if (typeof value === "boolean") {
118
- return value;
119
- }
120
- if (typeof value === "string") {
121
- const normalized = value.trim().toLowerCase();
122
- if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on") {
123
- return true;
124
- }
125
- if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "off") {
126
- return false;
127
- }
128
- }
129
- }
130
- return undefined;
131
- }
132
-
133
- function readCsvListOption(options: Record<string, unknown>, key: string, aliases: string[] = []): string[] {
134
- const value = readStringOption(options, key, aliases);
135
- if (!value) {
136
- return [];
137
- }
138
- return value
139
- .split(",")
140
- .map((entry) => entry.trim())
141
- .filter((entry) => entry.length > 0);
142
- }
143
-
144
- function normalizeGuideOptions(args: string[], options: Record<string, unknown>): Record<string, unknown> {
105
+ function normalizeGuideOptions(
106
+ bundle: RuntimeBundle,
107
+ args: string[],
108
+ options: Record<string, unknown>,
109
+ ): Record<string, unknown> {
110
+ const { readStringOption, readBooleanOption } = bundle.sdk;
145
111
  const topicFromArgs = args[0];
146
112
  return {
147
113
  topic: readStringOption(options, "topic") ?? (typeof topicFromArgs === "string" && topicFromArgs.trim().length > 0 ? topicFromArgs : undefined),
@@ -151,12 +117,13 @@ function normalizeGuideOptions(args: string[], options: Record<string, unknown>)
151
117
  };
152
118
  }
153
119
 
154
- function normalizeCompletionOptions(args: string[], options: Record<string, unknown>): {
120
+ function normalizeCompletionOptions(bundle: RuntimeBundle, args: string[], options: Record<string, unknown>): {
155
121
  shell: string;
156
122
  itemTypes: string[];
157
123
  tags: string[];
158
124
  eagerTags: boolean;
159
125
  } {
126
+ const { readStringOption, readBooleanOption, readCsvListOption } = bundle.sdk;
160
127
  const shellFromOptions = readStringOption(options, "shell");
161
128
  const shellFromArgs = typeof args[0] === "string" && args[0].trim().length > 0 ? args[0].trim() : undefined;
162
129
  return {
@@ -243,7 +210,7 @@ export async function runGuidePackage(
243
210
  global: GlobalOptions,
244
211
  ): Promise<unknown> {
245
212
  const bundle = await ensureRuntimeBundle();
246
- return bundle.sdk.runGuide(normalizeGuideOptions(args, options), global);
213
+ return bundle.sdk.runGuide(normalizeGuideOptions(bundle, args, options), global);
247
214
  }
248
215
 
249
216
  export async function runCompletionPackage(
@@ -252,7 +219,7 @@ export async function runCompletionPackage(
252
219
  global: GlobalOptions,
253
220
  ): Promise<unknown> {
254
221
  const bundle = await ensureRuntimeBundle();
255
- const normalized = normalizeCompletionOptions(args, options);
222
+ const normalized = normalizeCompletionOptions(bundle, args, options);
256
223
  const runtimeConfig = await buildCompletionRuntimeConfig(bundle, global);
257
224
  return bundle.sdk.runCompletion(
258
225
  normalized.shell,
@@ -33,6 +33,8 @@ async function loadRuntimeBundle() {
33
33
  typeof sdkLoaded.runTestRunsStop === "function" &&
34
34
  typeof sdkLoaded.runTestRunsResume === "function" &&
35
35
  typeof sdkLoaded.PmCliError === "function" &&
36
+ typeof sdkLoaded.readStringOption === "function" &&
37
+ typeof sdkLoaded.readBooleanOption === "function" &&
36
38
  typeof sdkLoaded.EXIT_CODE === "object" &&
37
39
  sdkLoaded.EXIT_CODE !== null
38
40
  ) {
@@ -48,40 +50,6 @@ async function loadRuntimeBundle() {
48
50
  );
49
51
  }
50
52
 
51
- function readStringOption(options, key, aliases = []) {
52
- const keys = [key, ...aliases];
53
- for (const candidate of keys) {
54
- const value = options[candidate];
55
- if (typeof value === "string" && value.trim().length > 0) {
56
- return value;
57
- }
58
- }
59
- return undefined;
60
- }
61
-
62
- function readBooleanOption(options, key, aliases = []) {
63
- const keys = [key, ...aliases];
64
- for (const candidate of keys) {
65
- const value = options[candidate];
66
- if (value === undefined) {
67
- continue;
68
- }
69
- if (typeof value === "boolean") {
70
- return value;
71
- }
72
- if (typeof value === "string") {
73
- const normalized = value.trim().toLowerCase();
74
- if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on") {
75
- return true;
76
- }
77
- if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "off") {
78
- return false;
79
- }
80
- }
81
- }
82
- return undefined;
83
- }
84
-
85
53
  function requireRunId(bundle, commandName, args) {
86
54
  const runId = args[0];
87
55
  if (typeof runId === "string" && runId.trim().length > 0) {
@@ -94,8 +62,8 @@ export async function runTestRunsListPackage(options, global) {
94
62
  const bundle = await ensureRuntimeBundle();
95
63
  return bundle.sdk.runTestRunsList(
96
64
  {
97
- status: readStringOption(options, "status"),
98
- limit: readStringOption(options, "limit"),
65
+ status: bundle.sdk.readStringOption(options, "status"),
66
+ limit: bundle.sdk.readStringOption(options, "limit"),
99
67
  },
100
68
  global,
101
69
  );
@@ -111,8 +79,8 @@ export async function runTestRunsLogsPackage(args, options, global) {
111
79
  return bundle.sdk.runTestRunsLogs(
112
80
  requireRunId(bundle, "test-runs logs", args),
113
81
  {
114
- stream: readStringOption(options, "stream"),
115
- tail: readStringOption(options, "tail"),
82
+ stream: bundle.sdk.readStringOption(options, "stream"),
83
+ tail: bundle.sdk.readStringOption(options, "tail"),
116
84
  },
117
85
  global,
118
86
  );
@@ -123,7 +91,7 @@ export async function runTestRunsStopPackage(args, options, global) {
123
91
  return bundle.sdk.runTestRunsStop(
124
92
  requireRunId(bundle, "test-runs stop", args),
125
93
  {
126
- force: readBooleanOption(options, "force") === true,
94
+ force: bundle.sdk.readBooleanOption(options, "force") === true,
127
95
  },
128
96
  global,
129
97
  );
@@ -134,7 +102,7 @@ export async function runTestRunsResumePackage(args, options, global) {
134
102
  return bundle.sdk.runTestRunsResume(
135
103
  requireRunId(bundle, "test-runs resume", args),
136
104
  {
137
- author: readStringOption(options, "author"),
105
+ author: bundle.sdk.readStringOption(options, "author"),
138
106
  noExtensions: global.noExtensions === true,
139
107
  },
140
108
  global,
@@ -12,6 +12,8 @@ interface RuntimeSdkModule {
12
12
  runTestRunsLogs: (runId: string, options: Record<string, unknown>, global: GlobalOptions) => Promise<unknown>;
13
13
  runTestRunsStop: (runId: string, options: Record<string, unknown>, global: GlobalOptions) => Promise<unknown>;
14
14
  runTestRunsResume: (runId: string, options: Record<string, unknown>, global: GlobalOptions) => Promise<unknown>;
15
+ readStringOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => string | undefined;
16
+ readBooleanOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => boolean | undefined;
15
17
  }
16
18
 
17
19
  interface RuntimeBundle {
@@ -49,6 +51,8 @@ async function loadRuntimeBundle(): Promise<RuntimeBundle> {
49
51
  typeof sdkLoaded.runTestRunsStop === "function" &&
50
52
  typeof sdkLoaded.runTestRunsResume === "function" &&
51
53
  typeof sdkLoaded.PmCliError === "function" &&
54
+ typeof sdkLoaded.readStringOption === "function" &&
55
+ typeof sdkLoaded.readBooleanOption === "function" &&
52
56
  typeof sdkLoaded.EXIT_CODE === "object" &&
53
57
  sdkLoaded.EXIT_CODE !== null
54
58
  ) {
@@ -64,40 +68,6 @@ async function loadRuntimeBundle(): Promise<RuntimeBundle> {
64
68
  );
65
69
  }
66
70
 
67
- function readStringOption(options: Record<string, unknown>, key: string, aliases: string[] = []): string | undefined {
68
- const keys = [key, ...aliases];
69
- for (const candidate of keys) {
70
- const value = options[candidate];
71
- if (typeof value === "string" && value.trim().length > 0) {
72
- return value;
73
- }
74
- }
75
- return undefined;
76
- }
77
-
78
- function readBooleanOption(options: Record<string, unknown>, key: string, aliases: string[] = []): boolean | undefined {
79
- const keys = [key, ...aliases];
80
- for (const candidate of keys) {
81
- const value = options[candidate];
82
- if (value === undefined) {
83
- continue;
84
- }
85
- if (typeof value === "boolean") {
86
- return value;
87
- }
88
- if (typeof value === "string") {
89
- const normalized = value.trim().toLowerCase();
90
- if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on") {
91
- return true;
92
- }
93
- if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "off") {
94
- return false;
95
- }
96
- }
97
- }
98
- return undefined;
99
- }
100
-
101
71
  function requireRunId(bundle: RuntimeBundle, commandName: string, args: string[]): string {
102
72
  const runId = args[0];
103
73
  if (typeof runId === "string" && runId.trim().length > 0) {
@@ -113,8 +83,8 @@ export async function runTestRunsListPackage(
113
83
  const bundle = await ensureRuntimeBundle();
114
84
  return bundle.sdk.runTestRunsList(
115
85
  {
116
- status: readStringOption(options, "status"),
117
- limit: readStringOption(options, "limit"),
86
+ status: bundle.sdk.readStringOption(options, "status"),
87
+ limit: bundle.sdk.readStringOption(options, "limit"),
118
88
  },
119
89
  global,
120
90
  );
@@ -134,8 +104,8 @@ export async function runTestRunsLogsPackage(
134
104
  return bundle.sdk.runTestRunsLogs(
135
105
  requireRunId(bundle, "test-runs logs", args),
136
106
  {
137
- stream: readStringOption(options, "stream"),
138
- tail: readStringOption(options, "tail"),
107
+ stream: bundle.sdk.readStringOption(options, "stream"),
108
+ tail: bundle.sdk.readStringOption(options, "tail"),
139
109
  },
140
110
  global,
141
111
  );
@@ -150,7 +120,7 @@ export async function runTestRunsStopPackage(
150
120
  return bundle.sdk.runTestRunsStop(
151
121
  requireRunId(bundle, "test-runs stop", args),
152
122
  {
153
- force: readBooleanOption(options, "force") === true,
123
+ force: bundle.sdk.readBooleanOption(options, "force") === true,
154
124
  },
155
125
  global,
156
126
  );
@@ -165,7 +135,7 @@ export async function runTestRunsResumePackage(
165
135
  return bundle.sdk.runTestRunsResume(
166
136
  requireRunId(bundle, "test-runs resume", args),
167
137
  {
168
- author: readStringOption(options, "author"),
138
+ author: bundle.sdk.readStringOption(options, "author"),
169
139
  noExtensions: global.noExtensions === true,
170
140
  },
171
141
  global,
@@ -5,7 +5,7 @@ export const manifest = {
5
5
  version: "0.1.0",
6
6
  entry: "./index.js",
7
7
  priority: 0,
8
- capabilities: ["commands"],
8
+ capabilities: ["commands", "schema"],
9
9
  };
10
10
 
11
11
  const searchAdvancedFlags = [
@@ -8,6 +8,8 @@ const {
8
8
  PmCliError,
9
9
  runSearch,
10
10
  runReindex,
11
+ readStringOption,
12
+ readBooleanOption,
11
13
  } = sdk;
12
14
 
13
15
  async function loadSearchSdkModule() {
@@ -24,6 +26,8 @@ async function loadSearchSdkModule() {
24
26
  typeof loaded.runSearch === "function" &&
25
27
  typeof loaded.runReindex === "function" &&
26
28
  typeof loaded.PmCliError === "function" &&
29
+ typeof loaded.readStringOption === "function" &&
30
+ typeof loaded.readBooleanOption === "function" &&
27
31
  typeof loaded.EXIT_CODE === "object" &&
28
32
  loaded.EXIT_CODE !== null
29
33
  ) {
@@ -37,43 +41,6 @@ async function loadSearchSdkModule() {
37
41
  );
38
42
  }
39
43
 
40
- function readStringOption(options, key, aliases = []) {
41
- const keys = [key, ...aliases];
42
- for (const candidate of keys) {
43
- const value = options[candidate];
44
- if (typeof value === "string" && value.trim().length > 0) {
45
- return value;
46
- }
47
- }
48
- return undefined;
49
- }
50
-
51
- const BOOLEAN_TRUE_VALUES = new Set(["true", "1", "yes", "on"]);
52
- const BOOLEAN_FALSE_VALUES = new Set(["false", "0", "no", "off"]);
53
-
54
- function readBooleanOption(options, key, aliases = []) {
55
- const keys = [key, ...aliases];
56
- for (const candidate of keys) {
57
- const value = options[candidate];
58
- if (value === undefined) {
59
- continue;
60
- }
61
- if (typeof value === "boolean") {
62
- return value;
63
- }
64
- if (typeof value === "string") {
65
- const normalized = value.trim().toLowerCase();
66
- if (BOOLEAN_TRUE_VALUES.has(normalized)) {
67
- return true;
68
- }
69
- if (BOOLEAN_FALSE_VALUES.has(normalized)) {
70
- return false;
71
- }
72
- }
73
- }
74
- return undefined;
75
- }
76
-
77
44
  const SEARCH_VALUE_FLAGS = new Set([
78
45
  "--mode",
79
46
  "--type",
@@ -17,6 +17,8 @@ interface SearchRuntimeSdkModule {
17
17
  PmCliError: new (message: string, exitCode?: number) => Error;
18
18
  runSearch: (query: string, options: SearchOptions, global: GlobalOptions) => Promise<SearchResult>;
19
19
  runReindex: (options: ReindexOptions, global: GlobalOptions) => Promise<ReindexResult>;
20
+ readStringOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => string | undefined;
21
+ readBooleanOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => boolean | undefined;
20
22
  }
21
23
 
22
24
  const sdk = await loadSearchSdkModule();
@@ -25,6 +27,8 @@ const {
25
27
  PmCliError,
26
28
  runSearch,
27
29
  runReindex,
30
+ readStringOption,
31
+ readBooleanOption,
28
32
  } = sdk;
29
33
 
30
34
  async function loadSearchSdkModule(): Promise<SearchRuntimeSdkModule> {
@@ -41,6 +45,8 @@ async function loadSearchSdkModule(): Promise<SearchRuntimeSdkModule> {
41
45
  typeof loaded.runSearch === "function" &&
42
46
  typeof loaded.runReindex === "function" &&
43
47
  typeof loaded.PmCliError === "function" &&
48
+ typeof loaded.readStringOption === "function" &&
49
+ typeof loaded.readBooleanOption === "function" &&
44
50
  typeof loaded.EXIT_CODE === "object" &&
45
51
  loaded.EXIT_CODE !== null
46
52
  ) {
@@ -54,43 +60,6 @@ async function loadSearchSdkModule(): Promise<SearchRuntimeSdkModule> {
54
60
  );
55
61
  }
56
62
 
57
- function readStringOption(options: Record<string, unknown>, key: string, aliases: string[] = []): string | undefined {
58
- const keys = [key, ...aliases];
59
- for (const candidate of keys) {
60
- const value = options[candidate];
61
- if (typeof value === "string" && value.trim().length > 0) {
62
- return value;
63
- }
64
- }
65
- return undefined;
66
- }
67
-
68
- const BOOLEAN_TRUE_VALUES = new Set(["true", "1", "yes", "on"]);
69
- const BOOLEAN_FALSE_VALUES = new Set(["false", "0", "no", "off"]);
70
-
71
- function readBooleanOption(options: Record<string, unknown>, key: string, aliases: string[] = []): boolean | undefined {
72
- const keys = [key, ...aliases];
73
- for (const candidate of keys) {
74
- const value = options[candidate];
75
- if (value === undefined) {
76
- continue;
77
- }
78
- if (typeof value === "boolean") {
79
- return value;
80
- }
81
- if (typeof value === "string") {
82
- const normalized = value.trim().toLowerCase();
83
- if (BOOLEAN_TRUE_VALUES.has(normalized)) {
84
- return true;
85
- }
86
- if (BOOLEAN_FALSE_VALUES.has(normalized)) {
87
- return false;
88
- }
89
- }
90
- }
91
- return undefined;
92
- }
93
-
94
63
  const SEARCH_VALUE_FLAGS = new Set([
95
64
  "--mode",
96
65
  "--type",