@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
@@ -1,7 +1,4 @@
1
- import path from "node:path";
2
- import { fileURLToPath, pathToFileURL } from "node:url";
3
- const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
4
- const CURRENT_EXTENSION_ROOT = path.dirname(fileURLToPath(import.meta.url));
1
+ import { loadPackageRuntimeModule } from "./runtime-loader.js";
5
2
  export const manifest = {
6
3
  name: "builtin-todos-import-export",
7
4
  version: "0.1.0",
@@ -24,59 +21,15 @@ function toExportOptions(options) {
24
21
  folder: asOptionalString(options.folder),
25
22
  };
26
23
  }
27
- function resolvePackageRootCandidates() {
28
- const candidates = [];
29
- const envRoot = process.env[PM_PACKAGE_ROOT_ENV];
30
- if (typeof envRoot === "string" && envRoot.trim().length > 0) {
31
- candidates.push(path.resolve(envRoot.trim()));
32
- }
33
- const argvEntry = typeof process.argv[1] === "string" ? process.argv[1].trim() : "";
34
- if (argvEntry.length > 0) {
35
- const resolvedEntry = path.resolve(argvEntry);
36
- const entryDir = path.dirname(resolvedEntry);
37
- candidates.push(path.resolve(entryDir, ".."));
38
- candidates.push(path.resolve(entryDir, "../.."));
39
- candidates.push(path.resolve(entryDir, "../../.."));
40
- }
41
- return [...new Set(candidates)];
42
- }
43
- async function loadRuntimeModule() {
44
- const attempted = [];
45
- for (const packageRoot of resolvePackageRootCandidates()) {
46
- const modulePaths = [
47
- path.join(packageRoot, ".agents", "pm", "extensions", "todos", "runtime.js"),
48
- path.join(packageRoot, "packages", "pm-todos", "extensions", "todos", "runtime.js"),
49
- ];
50
- for (const modulePath of modulePaths) {
51
- attempted.push(modulePath);
52
- try {
53
- return await import(pathToFileURL(modulePath).href);
54
- }
55
- catch {
56
- // Try the next package-root candidate.
57
- }
58
- }
59
- }
60
- const localRuntimePath = path.join(CURRENT_EXTENSION_ROOT, "runtime.js");
61
- attempted.push(localRuntimePath);
62
- try {
63
- return await import(pathToFileURL(localRuntimePath).href);
64
- }
65
- catch {
66
- // Fall through to the diagnostic below.
67
- }
68
- throw new Error("Unable to resolve packaged todos extension runtime module. " +
69
- `Tried: ${attempted.join(", ")}. Ensure the installed extension includes runtime.js or PM_CLI_PACKAGE_ROOT points to an installed pm package root.`);
70
- }
71
24
  async function runTodosImportFromRuntime(options, global) {
72
- const runtime = await loadRuntimeModule();
25
+ const runtime = await loadPackageRuntimeModule();
73
26
  if (typeof runtime.runTodosImport !== "function") {
74
27
  throw new Error("Bundled todos runtime module is missing runTodosImport().");
75
28
  }
76
29
  return runtime.runTodosImport(options, global);
77
30
  }
78
31
  async function runTodosExportFromRuntime(options, global) {
79
- const runtime = await loadRuntimeModule();
32
+ const runtime = await loadPackageRuntimeModule();
80
33
  if (typeof runtime.runTodosExport !== "function") {
81
34
  throw new Error("Bundled todos runtime module is missing runTodosExport().");
82
35
  }
@@ -1,10 +1,6 @@
1
- import path from "node:path";
2
- import { fileURLToPath, pathToFileURL } from "node:url";
3
1
  import type { CommandDefinition, ExtensionApi, GlobalOptions } from "../../../../src/sdk/index.js";
4
2
  import type { TodosExportOptions, TodosExportResult, TodosImportOptions, TodosImportResult } from "./runtime.js";
5
-
6
- const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
7
- const CURRENT_EXTENSION_ROOT = path.dirname(fileURLToPath(import.meta.url));
3
+ import { loadPackageRuntimeModule } from "./runtime-loader.js";
8
4
 
9
5
  export const manifest = {
10
6
  name: "builtin-todos-import-export",
@@ -37,56 +33,8 @@ function toExportOptions(options: Record<string, unknown>): TodosExportOptions {
37
33
  };
38
34
  }
39
35
 
40
- function resolvePackageRootCandidates(): string[] {
41
- const candidates: string[] = [];
42
- const envRoot = process.env[PM_PACKAGE_ROOT_ENV];
43
- if (typeof envRoot === "string" && envRoot.trim().length > 0) {
44
- candidates.push(path.resolve(envRoot.trim()));
45
- }
46
- const argvEntry = typeof process.argv[1] === "string" ? process.argv[1].trim() : "";
47
- if (argvEntry.length > 0) {
48
- const resolvedEntry = path.resolve(argvEntry);
49
- const entryDir = path.dirname(resolvedEntry);
50
- candidates.push(path.resolve(entryDir, ".."));
51
- candidates.push(path.resolve(entryDir, "../.."));
52
- candidates.push(path.resolve(entryDir, "../../.."));
53
- }
54
- return [...new Set(candidates)];
55
- }
56
-
57
- async function loadRuntimeModule(): Promise<RuntimeModule> {
58
- const attempted: string[] = [];
59
- for (const packageRoot of resolvePackageRootCandidates()) {
60
- const modulePaths = [
61
- path.join(packageRoot, ".agents", "pm", "extensions", "todos", "runtime.js"),
62
- path.join(packageRoot, "packages", "pm-todos", "extensions", "todos", "runtime.js"),
63
- ];
64
- for (const modulePath of modulePaths) {
65
- attempted.push(modulePath);
66
- try {
67
- return await import(pathToFileURL(modulePath).href) as RuntimeModule;
68
- } catch {
69
- // Try the next package-root candidate.
70
- }
71
- }
72
- }
73
-
74
- const localRuntimePath = path.join(CURRENT_EXTENSION_ROOT, "runtime.js");
75
- attempted.push(localRuntimePath);
76
- try {
77
- return await import(pathToFileURL(localRuntimePath).href) as RuntimeModule;
78
- } catch {
79
- // Fall through to the diagnostic below.
80
- }
81
-
82
- throw new Error(
83
- "Unable to resolve packaged todos extension runtime module. " +
84
- `Tried: ${attempted.join(", ")}. Ensure the installed extension includes runtime.js or PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
85
- );
86
- }
87
-
88
36
  async function runTodosImportFromRuntime(options: TodosImportOptions, global: GlobalOptions): Promise<TodosImportResult> {
89
- const runtime = await loadRuntimeModule();
37
+ const runtime = await loadPackageRuntimeModule() as RuntimeModule;
90
38
  if (typeof runtime.runTodosImport !== "function") {
91
39
  throw new Error("Bundled todos runtime module is missing runTodosImport().");
92
40
  }
@@ -94,7 +42,7 @@ async function runTodosImportFromRuntime(options: TodosImportOptions, global: Gl
94
42
  }
95
43
 
96
44
  async function runTodosExportFromRuntime(options: TodosExportOptions, global: GlobalOptions): Promise<TodosExportResult> {
97
- const runtime = await loadRuntimeModule();
45
+ const runtime = await loadPackageRuntimeModule() as RuntimeModule;
98
46
  if (typeof runtime.runTodosExport !== "function") {
99
47
  throw new Error("Bundled todos runtime module is missing runTodosExport().");
100
48
  }
@@ -0,0 +1,86 @@
1
+ import { existsSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath, pathToFileURL } from "node:url";
4
+
5
+ /**
6
+ * GENERATED by scripts/gen-package-runtime-loaders.mjs - do not edit directly.
7
+ * This file is shipped with the package extension and intentionally avoids
8
+ * static SDK imports so project-local installed extensions can load it.
9
+ */
10
+
11
+ const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
12
+ const CURRENT_EXTENSION_ROOT = path.dirname(fileURLToPath(import.meta.url));
13
+ const EXTENSION_NAME = "todos";
14
+ const PACKAGE_NAME = "pm-todos";
15
+ const DIAGNOSTIC_NAME = "todos";
16
+
17
+ function isRecord(value) {
18
+ return typeof value === "object" && value !== null;
19
+ }
20
+
21
+ function isMissingRuntimeModuleError(error, modulePath) {
22
+ if (!isRecord(error) || error.code !== "ERR_MODULE_NOT_FOUND") {
23
+ return false;
24
+ }
25
+ const message = typeof error.message === "string" ? error.message : "";
26
+ const moduleUrl = pathToFileURL(modulePath).href;
27
+ return message.includes(modulePath) || message.includes(moduleUrl);
28
+ }
29
+
30
+ function resolvePackageRootCandidates() {
31
+ const candidates = [];
32
+ const envRoot = process.env[PM_PACKAGE_ROOT_ENV];
33
+ if (typeof envRoot === "string" && envRoot.trim().length > 0) {
34
+ candidates.push(path.resolve(envRoot.trim()));
35
+ }
36
+ const argvEntry = typeof process.argv[1] === "string" ? process.argv[1].trim() : "";
37
+ if (argvEntry.length > 0) {
38
+ const resolvedEntry = path.resolve(argvEntry);
39
+ const entryDir = path.dirname(resolvedEntry);
40
+ candidates.push(path.resolve(entryDir, ".."));
41
+ candidates.push(path.resolve(entryDir, "../.."));
42
+ candidates.push(path.resolve(entryDir, "../../.."));
43
+ }
44
+ return [...new Set(candidates)];
45
+ }
46
+
47
+ export async function loadPackageRuntimeModule() {
48
+ const attempted = [];
49
+ for (const packageRoot of resolvePackageRootCandidates()) {
50
+ const modulePaths = [
51
+ path.join(packageRoot, ".agents", "pm", "extensions", EXTENSION_NAME, "runtime.js"),
52
+ path.join(packageRoot, "packages", PACKAGE_NAME, "extensions", EXTENSION_NAME, "runtime.js"),
53
+ ];
54
+ for (const modulePath of modulePaths) {
55
+ attempted.push(modulePath);
56
+ if (!existsSync(modulePath)) {
57
+ continue;
58
+ }
59
+ try {
60
+ return await import(pathToFileURL(modulePath).href);
61
+ } catch (error) {
62
+ if (isMissingRuntimeModuleError(error, modulePath)) {
63
+ continue;
64
+ }
65
+ throw error;
66
+ }
67
+ }
68
+ }
69
+
70
+ const localRuntimePath = path.join(CURRENT_EXTENSION_ROOT, "runtime.js");
71
+ attempted.push(localRuntimePath);
72
+ if (existsSync(localRuntimePath)) {
73
+ try {
74
+ return await import(pathToFileURL(localRuntimePath).href);
75
+ } catch (error) {
76
+ if (!isMissingRuntimeModuleError(error, localRuntimePath)) {
77
+ throw error;
78
+ }
79
+ }
80
+ }
81
+
82
+ throw new Error(
83
+ `Unable to resolve packaged ${DIAGNOSTIC_NAME} extension runtime module. ` +
84
+ `Tried: ${attempted.join(", ")}. Ensure the installed extension includes runtime.js or PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
85
+ );
86
+ }
@@ -0,0 +1,88 @@
1
+ import { existsSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath, pathToFileURL } from "node:url";
4
+
5
+ /**
6
+ * GENERATED by scripts/gen-package-runtime-loaders.mjs - do not edit directly.
7
+ * This file is shipped with the package extension and intentionally avoids
8
+ * static SDK imports so project-local installed extensions can load it.
9
+ */
10
+
11
+ const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
12
+ const CURRENT_EXTENSION_ROOT = path.dirname(fileURLToPath(import.meta.url));
13
+ const EXTENSION_NAME = "todos";
14
+ const PACKAGE_NAME = "pm-todos";
15
+ const DIAGNOSTIC_NAME = "todos";
16
+
17
+ export type PackageRuntimeModule = Record<string, unknown>;
18
+
19
+ function isRecord(value: unknown): value is Record<string, unknown> {
20
+ return typeof value === "object" && value !== null;
21
+ }
22
+
23
+ function isMissingRuntimeModuleError(error: unknown, modulePath: string): boolean {
24
+ if (!isRecord(error) || error.code !== "ERR_MODULE_NOT_FOUND") {
25
+ return false;
26
+ }
27
+ const message = typeof error.message === "string" ? error.message : "";
28
+ const moduleUrl = pathToFileURL(modulePath).href;
29
+ return message.includes(modulePath) || message.includes(moduleUrl);
30
+ }
31
+
32
+ function resolvePackageRootCandidates(): string[] {
33
+ const candidates: string[] = [];
34
+ const envRoot = process.env[PM_PACKAGE_ROOT_ENV];
35
+ if (typeof envRoot === "string" && envRoot.trim().length > 0) {
36
+ candidates.push(path.resolve(envRoot.trim()));
37
+ }
38
+ const argvEntry = typeof process.argv[1] === "string" ? process.argv[1].trim() : "";
39
+ if (argvEntry.length > 0) {
40
+ const resolvedEntry = path.resolve(argvEntry);
41
+ const entryDir = path.dirname(resolvedEntry);
42
+ candidates.push(path.resolve(entryDir, ".."));
43
+ candidates.push(path.resolve(entryDir, "../.."));
44
+ candidates.push(path.resolve(entryDir, "../../.."));
45
+ }
46
+ return [...new Set(candidates)];
47
+ }
48
+
49
+ export async function loadPackageRuntimeModule(): Promise<PackageRuntimeModule> {
50
+ const attempted: string[] = [];
51
+ for (const packageRoot of resolvePackageRootCandidates()) {
52
+ const modulePaths = [
53
+ path.join(packageRoot, ".agents", "pm", "extensions", EXTENSION_NAME, "runtime.js"),
54
+ path.join(packageRoot, "packages", PACKAGE_NAME, "extensions", EXTENSION_NAME, "runtime.js"),
55
+ ];
56
+ for (const modulePath of modulePaths) {
57
+ attempted.push(modulePath);
58
+ if (!existsSync(modulePath)) {
59
+ continue;
60
+ }
61
+ try {
62
+ return await import(pathToFileURL(modulePath).href) as PackageRuntimeModule;
63
+ } catch (error: unknown) {
64
+ if (isMissingRuntimeModuleError(error, modulePath)) {
65
+ continue;
66
+ }
67
+ throw error;
68
+ }
69
+ }
70
+ }
71
+
72
+ const localRuntimePath = path.join(CURRENT_EXTENSION_ROOT, "runtime.js");
73
+ attempted.push(localRuntimePath);
74
+ if (existsSync(localRuntimePath)) {
75
+ try {
76
+ return await import(pathToFileURL(localRuntimePath).href) as PackageRuntimeModule;
77
+ } catch (error: unknown) {
78
+ if (!isMissingRuntimeModuleError(error, localRuntimePath)) {
79
+ throw error;
80
+ }
81
+ }
82
+ }
83
+
84
+ throw new Error(
85
+ `Unable to resolve packaged ${DIAGNOSTIC_NAME} extension runtime module. ` +
86
+ `Tried: ${attempted.join(", ")}. Ensure the installed extension includes runtime.js or PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
87
+ );
88
+ }
@@ -1,17 +1,15 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { CONFIDENCE_TEXT_VALUES, EXIT_CODE, ISSUE_SEVERITY_VALUES, PmCliError, RISK_VALUES, acquireLock, appendHistoryEntry, canonicalDocument, createHistoryEntry, generateItemId, getActiveExtensionRegistrations, getHistoryPath, getItemPath, getSettingsPath, listAllFrontMatter, locateItem, normalizeFrontMatter, normalizeItemId, normalizeStatusInput, nowIso, parseTags, pathExists, readLocatedItem, readSettings, removeFileIfExists, resolveItemTypeRegistry, resolvePmRoot, runActiveOnReadHooks, runActiveOnWriteHooks, serializeItemDocument, splitFrontMatter, writeFileAtomic, } from "../../../../dist/sdk/index.js";
3
+ import { CONFIDENCE_TEXT_VALUES, EXIT_CODE, ISSUE_SEVERITY_VALUES, PmCliError, RISK_VALUES, canonicalDocument, commitImportedItem, generateItemId, getActiveExtensionRegistrations, getItemPath, listAllFrontMatter, locateItem, normalizeFrontMatter, normalizeItemId, nowIso, readLocatedItem, readSettings, resolveItemTypeRegistry, resolvePmRoot, runActiveOnReadHooks, runActiveOnWriteHooks, selectImportAuthor, splitFrontMatter, ensureTrackerInitialized, toEstimatedMinutesValue, toImportPriority, toImportStatus, toImportTags, toNonEmptyImportString, writeFileAtomic, } from "../../../../dist/sdk/index.js";
4
4
  const DEFAULT_TODOS_FOLDER = ".pm/todos";
5
+ // Shared, behavior-identical value coercers are sourced from the SDK adapter
6
+ // surface; package-specific mappings (lenient timestamps, type-name resolution,
7
+ // confidence/enum coercion) stay local below.
8
+ const toNonEmptyString = toNonEmptyImportString;
9
+ const toEstimatedMinutes = toEstimatedMinutesValue;
5
10
  function isRecord(value) {
6
11
  return typeof value === "object" && value !== null && !Array.isArray(value);
7
12
  }
8
- function toNonEmptyString(value) {
9
- if (typeof value !== "string") {
10
- return undefined;
11
- }
12
- const trimmed = value.trim();
13
- return trimmed.length > 0 ? trimmed : undefined;
14
- }
15
13
  function toIsoString(value) {
16
14
  const raw = toNonEmptyString(value);
17
15
  if (!raw) {
@@ -23,18 +21,6 @@ function toIsoString(value) {
23
21
  }
24
22
  return new Date(timestamp).toISOString();
25
23
  }
26
- function toEstimatedMinutes(value) {
27
- if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
28
- return value;
29
- }
30
- if (typeof value === "string" && value.trim().length > 0) {
31
- const parsed = Number(value);
32
- if (Number.isFinite(parsed) && parsed >= 0) {
33
- return parsed;
34
- }
35
- }
36
- return undefined;
37
- }
38
24
  function toInteger(value) {
39
25
  if (typeof value === "number" && Number.isInteger(value)) {
40
26
  return value;
@@ -47,18 +33,7 @@ function toInteger(value) {
47
33
  }
48
34
  return undefined;
49
35
  }
50
- function toPriority(value) {
51
- if (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 4) {
52
- return value;
53
- }
54
- if (typeof value === "string" && value.trim().length > 0) {
55
- const parsed = Number(value);
56
- if (Number.isInteger(parsed) && parsed >= 0 && parsed <= 4) {
57
- return parsed;
58
- }
59
- }
60
- return 2;
61
- }
36
+ const toPriority = toImportPriority;
62
37
  function toConfidence(value) {
63
38
  if (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 100) {
64
39
  return value;
@@ -119,19 +94,7 @@ function toBoolean(value) {
119
94
  }
120
95
  return undefined;
121
96
  }
122
- function toTags(value) {
123
- if (Array.isArray(value)) {
124
- const tags = value
125
- .filter((entry) => typeof entry === "string")
126
- .map((entry) => entry.trim().toLowerCase())
127
- .filter((entry) => entry.length > 0);
128
- return Array.from(new Set(tags)).sort((left, right) => left.localeCompare(right));
129
- }
130
- if (typeof value === "string") {
131
- return parseTags(value);
132
- }
133
- return [];
134
- }
97
+ const toTags = toImportTags;
135
98
  function toItemType(value, typeNames) {
136
99
  const normalized = toNonEmptyString(value)?.toLowerCase();
137
100
  const fallbackType = typeNames.find((entry) => entry.toLowerCase() === "task") ?? typeNames[0] ?? "Task";
@@ -145,37 +108,12 @@ function toItemType(value, typeNames) {
145
108
  }
146
109
  return fallbackType;
147
110
  }
148
- function toStatus(value) {
149
- const normalized = toNonEmptyString(value);
150
- if (normalized) {
151
- const canonical = normalizeStatusInput(normalized);
152
- if (canonical) {
153
- return canonical;
154
- }
155
- }
156
- return "open";
157
- }
158
- function selectAuthor(explicitAuthor, settingsAuthor) {
159
- const candidate = explicitAuthor ?? process.env.PM_AUTHOR ?? settingsAuthor;
160
- const trimmed = candidate.trim();
161
- return trimmed.length > 0 ? trimmed : "unknown";
162
- }
163
- function ensureInitHasRun(pmRoot) {
164
- return pathExists(getSettingsPath(pmRoot)).then((exists) => {
165
- if (!exists) {
166
- throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
167
- }
168
- });
169
- }
111
+ const toStatus = toImportStatus;
112
+ const selectAuthor = selectImportAuthor;
113
+ const ensureInitHasRun = ensureTrackerInitialized;
170
114
  function normalizeBody(body) {
171
115
  return body.replace(/^\n+/, "").replace(/\s+$/, "");
172
116
  }
173
- function emptyDocument() {
174
- return {
175
- metadata: {},
176
- body: "",
177
- };
178
- }
179
117
  function resolveFolderPath(rawPath) {
180
118
  return path.isAbsolute(rawPath) ? rawPath : path.resolve(process.cwd(), rawPath);
181
119
  }
@@ -296,51 +234,20 @@ async function importTodoCandidate(candidate, runtime) {
296
234
  }),
297
235
  body: candidate.body,
298
236
  });
299
- const historyPath = getHistoryPath(runtime.pmRoot, id);
300
- let writeWarnings = [];
301
- try {
302
- const releaseLock = await acquireLock(runtime.pmRoot, id, runtime.settings.locks.ttl_seconds, runtime.author);
303
- try {
304
- await writeFileAtomic(itemPath, serializeItemDocument(afterDocument, { format: "toon" }));
305
- try {
306
- const historyEntry = createHistoryEntry({
307
- nowIso: nowIso(),
308
- author: runtime.author,
309
- op: "import",
310
- before: emptyDocument(),
311
- after: afterDocument,
312
- message: runtime.message,
313
- });
314
- await appendHistoryEntry(historyPath, historyEntry);
315
- writeWarnings = [
316
- ...(await runActiveOnWriteHooks({
317
- path: itemPath,
318
- scope: "project",
319
- op: "import",
320
- })),
321
- ...(await runActiveOnWriteHooks({
322
- path: historyPath,
323
- scope: "project",
324
- op: "import:history",
325
- })),
326
- ];
327
- }
328
- catch (error) {
329
- await removeFileIfExists(itemPath);
330
- throw error;
331
- }
332
- }
333
- finally {
334
- await releaseLock();
335
- }
336
- }
337
- catch (error) {
338
- if (error instanceof PmCliError && error.exitCode === EXIT_CODE.CONFLICT) {
339
- return { warning: `todos_import_lock_conflict:${id}` };
340
- }
341
- throw error;
237
+ const commit = await commitImportedItem({
238
+ pmRoot: runtime.pmRoot,
239
+ id,
240
+ itemPath,
241
+ document: afterDocument,
242
+ author: runtime.author,
243
+ message: runtime.message,
244
+ settings: runtime.settings,
245
+ conflictWarningPrefix: "todos_import_lock_conflict",
246
+ });
247
+ if (!commit.committed) {
248
+ return { warning: commit.conflictWarning };
342
249
  }
343
- return { id, writeWarnings };
250
+ return { id, writeWarnings: commit.writeWarnings };
344
251
  }
345
252
  export async function runTodosImport(options, global) {
346
253
  const pmRoot = resolvePmRoot(process.cwd(), global.path);