@unbrained/pm-cli 2026.5.11 → 2026.5.14

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 (171) hide show
  1. package/AGENTS.md +3 -116
  2. package/CHANGELOG.md +18 -0
  3. package/PRD.md +18 -39
  4. package/README.md +8 -5
  5. package/dist/cli/commander-usage.js +27 -0
  6. package/dist/cli/commander-usage.js.map +1 -1
  7. package/dist/cli/commands/activity.js +19 -4
  8. package/dist/cli/commands/activity.js.map +1 -1
  9. package/dist/cli/commands/calendar.js +5 -2
  10. package/dist/cli/commands/calendar.js.map +1 -1
  11. package/dist/cli/commands/contracts.js +63 -19
  12. package/dist/cli/commands/contracts.js.map +1 -1
  13. package/dist/cli/commands/create.js +58 -3
  14. package/dist/cli/commands/create.js.map +1 -1
  15. package/dist/cli/commands/extension.d.ts +14 -3
  16. package/dist/cli/commands/extension.js +481 -95
  17. package/dist/cli/commands/extension.js.map +1 -1
  18. package/dist/cli/commands/index.d.ts +1 -8
  19. package/dist/cli/commands/index.js +1 -8
  20. package/dist/cli/commands/index.js.map +1 -1
  21. package/dist/cli/commands/reindex.d.ts +8 -0
  22. package/dist/cli/commands/reindex.js +96 -23
  23. package/dist/cli/commands/reindex.js.map +1 -1
  24. package/dist/cli/commands/search.js +51 -25
  25. package/dist/cli/commands/search.js.map +1 -1
  26. package/dist/cli/commands/test.js +14 -6
  27. package/dist/cli/commands/test.js.map +1 -1
  28. package/dist/cli/commands/upgrade.d.ts +63 -0
  29. package/dist/cli/commands/upgrade.js +260 -0
  30. package/dist/cli/commands/upgrade.js.map +1 -0
  31. package/dist/cli/guide-topics.js +18 -16
  32. package/dist/cli/guide-topics.js.map +1 -1
  33. package/dist/cli/help-content.js +57 -18
  34. package/dist/cli/help-content.js.map +1 -1
  35. package/dist/cli/main.js +73 -7
  36. package/dist/cli/main.js.map +1 -1
  37. package/dist/cli/register-list-query.js +24 -142
  38. package/dist/cli/register-list-query.js.map +1 -1
  39. package/dist/cli/register-mutation.js +49 -257
  40. package/dist/cli/register-mutation.js.map +1 -1
  41. package/dist/cli/register-operations.js +29 -198
  42. package/dist/cli/register-operations.js.map +1 -1
  43. package/dist/cli/register-setup.js +181 -204
  44. package/dist/cli/register-setup.js.map +1 -1
  45. package/dist/cli/registration-helpers.d.ts +2 -2
  46. package/dist/cli/registration-helpers.js +1 -19
  47. package/dist/cli/registration-helpers.js.map +1 -1
  48. package/dist/core/extensions/loader.js +7 -1
  49. package/dist/core/extensions/loader.js.map +1 -1
  50. package/dist/core/packages/manifest.d.ts +38 -0
  51. package/dist/core/packages/manifest.js +221 -0
  52. package/dist/core/packages/manifest.js.map +1 -0
  53. package/dist/core/search/embedding-batches.d.ts +13 -1
  54. package/dist/core/search/embedding-batches.js +19 -1
  55. package/dist/core/search/embedding-batches.js.map +1 -1
  56. package/dist/core/store/front-matter-cache.d.ts +8 -1
  57. package/dist/core/store/front-matter-cache.js +20 -11
  58. package/dist/core/store/front-matter-cache.js.map +1 -1
  59. package/dist/mcp/server.d.ts +8 -0
  60. package/dist/mcp/server.js +100 -43
  61. package/dist/mcp/server.js.map +1 -1
  62. package/dist/sdk/cli-contracts/commander-mutation-options.d.ts +7 -0
  63. package/dist/sdk/cli-contracts/commander-mutation-options.js +477 -0
  64. package/dist/sdk/cli-contracts/commander-mutation-options.js.map +1 -0
  65. package/dist/sdk/cli-contracts/commander-types.d.ts +21 -0
  66. package/dist/sdk/cli-contracts/commander-types.js +92 -0
  67. package/dist/sdk/cli-contracts/commander-types.js.map +1 -0
  68. package/dist/sdk/cli-contracts.d.ts +22 -32
  69. package/dist/sdk/cli-contracts.js +155 -296
  70. package/dist/sdk/cli-contracts.js.map +1 -1
  71. package/dist/sdk/index.d.ts +2 -0
  72. package/dist/sdk/index.js +2 -0
  73. package/dist/sdk/index.js.map +1 -1
  74. package/dist/sdk/runtime.d.ts +29 -0
  75. package/dist/sdk/runtime.js +28 -0
  76. package/dist/sdk/runtime.js.map +1 -0
  77. package/docs/ARCHITECTURE.md +1 -1
  78. package/docs/COMMANDS.md +17 -1
  79. package/docs/EXTENSIONS.md +169 -61
  80. package/docs/QUICKSTART.md +11 -2
  81. package/docs/README.md +4 -6
  82. package/docs/RELEASING.md +4 -2
  83. package/docs/SDK.md +79 -438
  84. package/package.json +6 -23
  85. package/packages/pm-beads/README.md +10 -0
  86. package/packages/pm-beads/extensions/beads/index.js +113 -0
  87. package/{.agents/pm/extensions/beads/index.js → packages/pm-beads/extensions/beads/index.ts} +42 -20
  88. package/{.agents/pm → packages/pm-beads}/extensions/beads/runtime.js +2 -17
  89. package/{.agents/pm → packages/pm-beads}/extensions/beads/runtime.ts +41 -18
  90. package/packages/pm-beads/package.json +50 -0
  91. package/packages/pm-calendar/README.md +13 -0
  92. package/packages/pm-calendar/extensions/calendar/index.js +56 -0
  93. package/packages/pm-calendar/extensions/calendar/index.ts +62 -0
  94. package/packages/pm-calendar/extensions/calendar/manifest.json +7 -0
  95. package/packages/pm-calendar/extensions/calendar/runtime.js +95 -0
  96. package/packages/pm-calendar/extensions/calendar/runtime.ts +104 -0
  97. package/packages/pm-calendar/package.json +51 -0
  98. package/packages/pm-governance-audit/README.md +23 -0
  99. package/packages/pm-governance-audit/extensions/governance-audit/index.js +117 -0
  100. package/packages/pm-governance-audit/extensions/governance-audit/index.ts +118 -0
  101. package/packages/pm-governance-audit/extensions/governance-audit/manifest.json +7 -0
  102. package/packages/pm-governance-audit/extensions/governance-audit/runtime.js +159 -0
  103. package/packages/pm-governance-audit/extensions/governance-audit/runtime.ts +176 -0
  104. package/packages/pm-governance-audit/package.json +52 -0
  105. package/packages/pm-guide-shell/README.md +23 -0
  106. package/packages/pm-guide-shell/extensions/guide-shell/index.js +76 -0
  107. package/packages/pm-guide-shell/extensions/guide-shell/index.ts +81 -0
  108. package/packages/pm-guide-shell/extensions/guide-shell/manifest.json +7 -0
  109. package/packages/pm-guide-shell/extensions/guide-shell/runtime.js +263 -0
  110. package/packages/pm-guide-shell/extensions/guide-shell/runtime.ts +327 -0
  111. package/packages/pm-guide-shell/package.json +52 -0
  112. package/packages/pm-linked-test-adapters/README.md +24 -0
  113. package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/index.js +101 -0
  114. package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/index.ts +102 -0
  115. package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/manifest.json +7 -0
  116. package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.js +142 -0
  117. package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.ts +173 -0
  118. package/packages/pm-linked-test-adapters/package.json +53 -0
  119. package/packages/pm-search-advanced/README.md +27 -0
  120. package/packages/pm-search-advanced/extensions/search-advanced/index.js +93 -0
  121. package/packages/pm-search-advanced/extensions/search-advanced/index.ts +94 -0
  122. package/packages/pm-search-advanced/extensions/search-advanced/manifest.json +7 -0
  123. package/packages/pm-search-advanced/extensions/search-advanced/runtime.js +120 -0
  124. package/packages/pm-search-advanced/extensions/search-advanced/runtime.ts +144 -0
  125. package/packages/pm-search-advanced/package.json +54 -0
  126. package/packages/pm-templates/README.md +20 -0
  127. package/packages/pm-templates/extensions/templates/index.js +101 -0
  128. package/packages/pm-templates/extensions/templates/index.ts +109 -0
  129. package/packages/pm-templates/extensions/templates/manifest.json +7 -0
  130. package/packages/pm-templates/extensions/templates/runtime.js +226 -0
  131. package/packages/pm-templates/extensions/templates/runtime.ts +283 -0
  132. package/packages/pm-templates/package.json +50 -0
  133. package/packages/pm-todos/README.md +11 -0
  134. package/packages/pm-todos/extensions/todos/index.js +130 -0
  135. package/{.agents/pm/extensions/todos/index.js → packages/pm-todos/extensions/todos/index.ts} +47 -23
  136. package/{.agents/pm → packages/pm-todos}/extensions/todos/runtime.js +3 -18
  137. package/{.agents/pm → packages/pm-todos}/extensions/todos/runtime.ts +42 -20
  138. package/packages/pm-todos/package.json +51 -0
  139. package/plugins/pm-cli-claude/README.md +1 -2
  140. package/plugins/pm-cli-claude/hooks/session-start.mjs +4 -55
  141. package/plugins/pm-cli-claude/scripts/pm-mcp-server.mjs +4 -2
  142. package/plugins/pm-cli-codex/scripts/pm-mcp-server.mjs +4 -2
  143. package/.agents/pm/extensions/.managed-extensions.json +0 -42
  144. package/.agents/skills/HARNESS_COMPATIBILITY.md +0 -45
  145. package/.agents/skills/README.md +0 -21
  146. package/.agents/skills/pm-developer/SKILL.md +0 -73
  147. package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +0 -48
  148. package/.agents/skills/pm-developer/references/PROMPTS.md +0 -17
  149. package/.agents/skills/pm-extensions/SKILL.md +0 -57
  150. package/.agents/skills/pm-extensions/references/LIFECYCLE.md +0 -40
  151. package/.agents/skills/pm-extensions/references/TROUBLESHOOTING.md +0 -25
  152. package/.agents/skills/pm-sdk/SKILL.md +0 -50
  153. package/.agents/skills/pm-sdk/references/INTEGRATION_CHECKLIST.md +0 -31
  154. package/.agents/skills/pm-sdk/references/PROMPTS.md +0 -13
  155. package/.agents/skills/pm-user/SKILL.md +0 -59
  156. package/.agents/skills/pm-user/references/PROMPTS.md +0 -17
  157. package/.agents/skills/pm-user/references/WORKFLOWS.md +0 -35
  158. package/.pi/README.md +0 -35
  159. package/.pi/agents/pm-triage-agent.md +0 -19
  160. package/.pi/agents/pm-verification-agent.md +0 -21
  161. package/.pi/chains/pm-native-delivery.chain.md +0 -11
  162. package/.pi/extensions/pm-cli/index.js +0 -387
  163. package/.pi/prompts/pm-workflow.md +0 -5
  164. package/.pi/skills/pm-native/SKILL.md +0 -44
  165. package/.pi/skills/pm-release/SKILL.md +0 -35
  166. package/dist/pi/native.d.ts +0 -5
  167. package/dist/pi/native.js +0 -236
  168. package/dist/pi/native.js.map +0 -1
  169. package/docs/PI_PACKAGE.md +0 -141
  170. /package/{.agents/pm → packages/pm-beads}/extensions/beads/manifest.json +0 -0
  171. /package/{.agents/pm → packages/pm-todos}/extensions/todos/manifest.json +0 -0
@@ -0,0 +1,130 @@
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));
5
+ export const manifest = {
6
+ name: "builtin-todos-import-export",
7
+ version: "0.1.0",
8
+ entry: "./index.js",
9
+ priority: 0,
10
+ capabilities: ["commands", "schema"],
11
+ };
12
+ function asOptionalString(value) {
13
+ return typeof value === "string" ? value : undefined;
14
+ }
15
+ function toImportOptions(options) {
16
+ return {
17
+ folder: asOptionalString(options.folder),
18
+ author: asOptionalString(options.author),
19
+ message: asOptionalString(options.message),
20
+ };
21
+ }
22
+ function toExportOptions(options) {
23
+ return {
24
+ folder: asOptionalString(options.folder),
25
+ };
26
+ }
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
+ async function runTodosImportFromRuntime(options, global) {
72
+ const runtime = await loadRuntimeModule();
73
+ if (typeof runtime.runTodosImport !== "function") {
74
+ throw new Error("Bundled todos runtime module is missing runTodosImport().");
75
+ }
76
+ return runtime.runTodosImport(options, global);
77
+ }
78
+ async function runTodosExportFromRuntime(options, global) {
79
+ const runtime = await loadRuntimeModule();
80
+ if (typeof runtime.runTodosExport !== "function") {
81
+ throw new Error("Bundled todos runtime module is missing runTodosExport().");
82
+ }
83
+ return runtime.runTodosExport(options, global);
84
+ }
85
+ export function activate(api) {
86
+ api.registerCommand({
87
+ name: "todos import",
88
+ action: "todos-import",
89
+ description: "Import Todo markdown files into pm items.",
90
+ flags: [
91
+ {
92
+ long: "--folder",
93
+ value_name: "path",
94
+ value_type: "string",
95
+ description: "Source folder containing Todo markdown files.",
96
+ },
97
+ {
98
+ long: "--author",
99
+ value_name: "author",
100
+ value_type: "string",
101
+ description: "Override import mutation author.",
102
+ },
103
+ {
104
+ long: "--message",
105
+ value_name: "text",
106
+ value_type: "string",
107
+ description: "Override import history message.",
108
+ },
109
+ ],
110
+ run: async (context) => runTodosImportFromRuntime(toImportOptions(context.options), context.global),
111
+ });
112
+ api.registerCommand({
113
+ name: "todos export",
114
+ action: "todos-export",
115
+ description: "Export pm items into Todo markdown files.",
116
+ flags: [
117
+ {
118
+ long: "--folder",
119
+ value_name: "path",
120
+ value_type: "string",
121
+ description: "Destination folder for exported Todo markdown files.",
122
+ },
123
+ ],
124
+ run: async (context) => runTodosExportFromRuntime(toExportOptions(context.options), context.global),
125
+ });
126
+ }
127
+ export default {
128
+ manifest,
129
+ activate,
130
+ };
@@ -1,7 +1,10 @@
1
1
  import path from "node:path";
2
- import { pathToFileURL } from "node:url";
2
+ import { fileURLToPath, pathToFileURL } from "node:url";
3
+ import type { CommandDefinition, ExtensionApi, GlobalOptions } from "../../../../src/sdk/index.js";
4
+ import type { TodosExportOptions, TodosExportResult, TodosImportOptions, TodosImportResult } from "./runtime.js";
3
5
 
4
6
  const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
7
+ const CURRENT_EXTENSION_ROOT = path.dirname(fileURLToPath(import.meta.url));
5
8
 
6
9
  export const manifest = {
7
10
  name: "builtin-todos-import-export",
@@ -11,11 +14,16 @@ export const manifest = {
11
14
  capabilities: ["commands", "schema"],
12
15
  };
13
16
 
14
- function asOptionalString(value) {
17
+ type RuntimeModule = {
18
+ runTodosImport?: (options: TodosImportOptions, global: GlobalOptions) => Promise<TodosImportResult>;
19
+ runTodosExport?: (options: TodosExportOptions, global: GlobalOptions) => Promise<TodosExportResult>;
20
+ };
21
+
22
+ function asOptionalString(value: unknown): string | undefined {
15
23
  return typeof value === "string" ? value : undefined;
16
24
  }
17
25
 
18
- function toImportOptions(options) {
26
+ function toImportOptions(options: Record<string, unknown>): TodosImportOptions {
19
27
  return {
20
28
  folder: asOptionalString(options.folder),
21
29
  author: asOptionalString(options.author),
@@ -23,14 +31,14 @@ function toImportOptions(options) {
23
31
  };
24
32
  }
25
33
 
26
- function toExportOptions(options) {
34
+ function toExportOptions(options: Record<string, unknown>): TodosExportOptions {
27
35
  return {
28
36
  folder: asOptionalString(options.folder),
29
37
  };
30
38
  }
31
39
 
32
- function resolvePackageRootCandidates() {
33
- const candidates = [];
40
+ function resolvePackageRootCandidates(): string[] {
41
+ const candidates: string[] = [];
34
42
  const envRoot = process.env[PM_PACKAGE_ROOT_ENV];
35
43
  if (typeof envRoot === "string" && envRoot.trim().length > 0) {
36
44
  candidates.push(path.resolve(envRoot.trim()));
@@ -46,42 +54,57 @@ function resolvePackageRootCandidates() {
46
54
  return [...new Set(candidates)];
47
55
  }
48
56
 
49
- async function loadRuntimeModule() {
50
- const attempted = [];
57
+ async function loadRuntimeModule(): Promise<RuntimeModule> {
58
+ const attempted: string[] = [];
51
59
  for (const packageRoot of resolvePackageRootCandidates()) {
52
- const modulePath = path.join(packageRoot, ".agents", "pm", "extensions", "todos", "runtime.js");
53
- attempted.push(modulePath);
54
- try {
55
- return await import(pathToFileURL(modulePath).href);
56
- } catch {
57
- // Try the next package-root candidate.
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
+ }
58
71
  }
59
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
+
60
82
  throw new Error(
61
- "Unable to resolve bundled todos extension runtime module. " +
62
- `Tried: ${attempted.join(", ")}. Ensure PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
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.`,
63
85
  );
64
86
  }
65
87
 
66
- async function runTodosImportFromRuntime(options, global) {
88
+ async function runTodosImportFromRuntime(options: TodosImportOptions, global: GlobalOptions): Promise<TodosImportResult> {
67
89
  const runtime = await loadRuntimeModule();
68
90
  if (typeof runtime.runTodosImport !== "function") {
69
- throw new Error('Bundled todos runtime module is missing runTodosImport().');
91
+ throw new Error("Bundled todos runtime module is missing runTodosImport().");
70
92
  }
71
93
  return runtime.runTodosImport(options, global);
72
94
  }
73
95
 
74
- async function runTodosExportFromRuntime(options, global) {
96
+ async function runTodosExportFromRuntime(options: TodosExportOptions, global: GlobalOptions): Promise<TodosExportResult> {
75
97
  const runtime = await loadRuntimeModule();
76
98
  if (typeof runtime.runTodosExport !== "function") {
77
- throw new Error('Bundled todos runtime module is missing runTodosExport().');
99
+ throw new Error("Bundled todos runtime module is missing runTodosExport().");
78
100
  }
79
101
  return runtime.runTodosExport(options, global);
80
102
  }
81
103
 
82
- export function activate(api) {
104
+ export function activate(api: ExtensionApi): void {
83
105
  api.registerCommand({
84
106
  name: "todos import",
107
+ action: "todos-import",
85
108
  description: "Import Todo markdown files into pm items.",
86
109
  flags: [
87
110
  {
@@ -104,9 +127,10 @@ export function activate(api) {
104
127
  },
105
128
  ],
106
129
  run: async (context) => runTodosImportFromRuntime(toImportOptions(context.options), context.global),
107
- });
130
+ } satisfies CommandDefinition);
108
131
  api.registerCommand({
109
132
  name: "todos export",
133
+ action: "todos-export",
110
134
  description: "Export pm items into Todo markdown files.",
111
135
  flags: [
112
136
  {
@@ -117,7 +141,7 @@ export function activate(api) {
117
141
  },
118
142
  ],
119
143
  run: async (context) => runTodosExportFromRuntime(toExportOptions(context.options), context.global),
120
- });
144
+ } satisfies CommandDefinition);
121
145
  }
122
146
 
123
147
  export default {
@@ -1,22 +1,7 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { getActiveExtensionRegistrations, runActiveOnReadHooks, runActiveOnWriteHooks } from "../../../../dist/core/extensions/index.js";
4
- import { pathExists, removeFileIfExists, writeFileAtomic } from "../../../../dist/core/fs/fs-utils.js";
5
- import { appendHistoryEntry, createHistoryEntry } from "../../../../dist/core/history/history.js";
6
- import { generateItemId, normalizeItemId } from "../../../../dist/core/item/id.js";
7
- import { canonicalDocument, normalizeFrontMatter, serializeItemDocument, splitFrontMatter } from "../../../../dist/core/item/item-format.js";
8
- import { normalizeStatusInput } from "../../../../dist/core/item/status.js";
9
- import { resolveItemTypeRegistry } from "../../../../dist/core/item/type-registry.js";
10
- import { parseTags } from "../../../../dist/core/item/parse.js";
11
- import { acquireLock } from "../../../../dist/core/lock/lock.js";
12
- import { EXIT_CODE } from "../../../../dist/core/shared/constants.js";
13
- import { PmCliError } from "../../../../dist/core/shared/errors.js";
14
- import { nowIso } from "../../../../dist/core/shared/time.js";
15
- import { listAllFrontMatter, locateItem, readLocatedItem } from "../../../../dist/core/store/item-store.js";
16
- import { getHistoryPath, getItemPath, getSettingsPath, resolvePmRoot } from "../../../../dist/core/store/paths.js";
17
- import { readSettings } from "../../../../dist/core/store/settings.js";
18
- import { CONFIDENCE_TEXT_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES } from "../../../../dist/types/index.js";
19
- const DEFAULT_TODOS_FOLDER = ".pi/todos";
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";
4
+ const DEFAULT_TODOS_FOLDER = ".pm/todos";
20
5
  function isRecord(value) {
21
6
  return typeof value === "object" && value !== null && !Array.isArray(value);
22
7
  }
@@ -467,4 +452,4 @@ export async function runTodosExport(options, global) {
467
452
  ids,
468
453
  warnings,
469
454
  };
470
- }
455
+ }
@@ -1,26 +1,48 @@
1
1
  import fs from "node:fs/promises";
2
2
  import type { Dirent } from "node:fs";
3
3
  import path from "node:path";
4
- import { getActiveExtensionRegistrations, runActiveOnReadHooks, runActiveOnWriteHooks } from "../../../../src/core/extensions/index.js";
5
- import { pathExists, removeFileIfExists, writeFileAtomic } from "../../../../src/core/fs/fs-utils.js";
6
- import { appendHistoryEntry, createHistoryEntry } from "../../../../src/core/history/history.js";
7
- import { generateItemId, normalizeItemId } from "../../../../src/core/item/id.js";
8
- import { canonicalDocument, normalizeFrontMatter, serializeItemDocument, splitFrontMatter } from "../../../../src/core/item/item-format.js";
9
- import { normalizeStatusInput } from "../../../../src/core/item/status.js";
10
- import { resolveItemTypeRegistry } from "../../../../src/core/item/type-registry.js";
11
- import { parseTags } from "../../../../src/core/item/parse.js";
12
- import { acquireLock } from "../../../../src/core/lock/lock.js";
13
- import { EXIT_CODE } from "../../../../src/core/shared/constants.js";
14
- import type { GlobalOptions } from "../../../../src/core/shared/command-types.js";
15
- import { PmCliError } from "../../../../src/core/shared/errors.js";
16
- import { nowIso } from "../../../../src/core/shared/time.js";
17
- import { listAllFrontMatter, locateItem, readLocatedItem } from "../../../../src/core/store/item-store.js";
18
- import { getHistoryPath, getItemPath, getSettingsPath, resolvePmRoot } from "../../../../src/core/store/paths.js";
19
- import { readSettings } from "../../../../src/core/store/settings.js";
20
- import { CONFIDENCE_TEXT_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES } from "../../../../src/types/index.js";
21
- import type { ItemDocument, ItemMetadata, ItemStatus, ItemType, PmSettings } from "../../../../src/types/index.js";
22
-
23
- const DEFAULT_TODOS_FOLDER = ".pi/todos";
4
+ import {
5
+ CONFIDENCE_TEXT_VALUES,
6
+ EXIT_CODE,
7
+ ISSUE_SEVERITY_VALUES,
8
+ PmCliError,
9
+ RISK_VALUES,
10
+ acquireLock,
11
+ appendHistoryEntry,
12
+ canonicalDocument,
13
+ createHistoryEntry,
14
+ generateItemId,
15
+ getActiveExtensionRegistrations,
16
+ getHistoryPath,
17
+ getItemPath,
18
+ getSettingsPath,
19
+ listAllFrontMatter,
20
+ locateItem,
21
+ normalizeFrontMatter,
22
+ normalizeItemId,
23
+ normalizeStatusInput,
24
+ nowIso,
25
+ parseTags,
26
+ pathExists,
27
+ readLocatedItem,
28
+ readSettings,
29
+ removeFileIfExists,
30
+ resolveItemTypeRegistry,
31
+ resolvePmRoot,
32
+ runActiveOnReadHooks,
33
+ runActiveOnWriteHooks,
34
+ serializeItemDocument,
35
+ splitFrontMatter,
36
+ writeFileAtomic,
37
+ type GlobalOptions,
38
+ type ItemDocument,
39
+ type ItemMetadata,
40
+ type ItemStatus,
41
+ type ItemType,
42
+ type PmSettings,
43
+ } from "../../../../src/sdk/index.js";
44
+
45
+ const DEFAULT_TODOS_FOLDER = ".pm/todos";
24
46
 
25
47
  export interface TodosImportOptions {
26
48
  folder?: string;
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@unbrained/pm-package-todos",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "description": "First-party pm package for Todo markdown import and export.",
7
+ "homepage": "https://github.com/unbraind/pm-cli/tree/main/packages/pm-todos#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/unbraind/pm-cli.git",
11
+ "directory": "packages/pm-todos"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/unbraind/pm-cli/issues"
15
+ },
16
+ "keywords": [
17
+ "pm-package",
18
+ "project-management",
19
+ "todos"
20
+ ],
21
+ "pm": {
22
+ "aliases": [
23
+ "todos"
24
+ ],
25
+ "extensions": [
26
+ "extensions/todos"
27
+ ],
28
+ "catalog": {
29
+ "display_name": "Todos Import/Export",
30
+ "category": "migration",
31
+ "summary": "Import and export Todo markdown tasks through pm package commands.",
32
+ "tags": [
33
+ "migration",
34
+ "todos",
35
+ "import",
36
+ "export"
37
+ ],
38
+ "links": {
39
+ "docs": "https://github.com/unbraind/pm-cli/tree/main/packages/pm-todos#readme",
40
+ "repository": "https://github.com/unbraind/pm-cli/tree/main/packages/pm-todos",
41
+ "report": "https://github.com/unbraind/pm-cli/issues"
42
+ }
43
+ },
44
+ "docs": [
45
+ "README.md"
46
+ ],
47
+ "examples": [
48
+ "README.md"
49
+ ]
50
+ }
51
+ }
@@ -191,8 +191,7 @@ All skills and commands implement this pattern for every claimed item:
191
191
  ## Session Context Injection
192
192
 
193
193
  At session start, the hook runs natively (no `pm` CLI required):
194
- - Walks up directories to find `dist/pi/native.js` in the repo checkout
195
- - Falls back to `npx @unbrained/pm-cli` if no local dist is found
194
+ - Uses `npx @unbrained/pm-cli` without requiring a global install
196
195
  - Injects a compact summary of in-progress/open/blocked items
197
196
 
198
197
  Example output:
@@ -3,14 +3,11 @@
3
3
  * pm-cli Claude Code session-start hook.
4
4
  *
5
5
  * Injects a brief pm context summary into the session when pm is initialized
6
- * in the current workspace. Uses native pm modules when available (repo checkout
7
- * or dist/); falls back to npx @unbrained/pm-cli without requiring the CLI to
8
- * be installed globally. Exits silently if pm is not set up.
6
+ * in the current workspace. Uses the published pm CLI through npx without
7
+ * requiring a global install. Exits silently if pm is not set up.
9
8
  */
10
- import { access } from "node:fs/promises";
11
9
  import { existsSync } from "node:fs";
12
- import { join, resolve, dirname } from "node:path";
13
- import { fileURLToPath, pathToFileURL } from "node:url";
10
+ import { join } from "node:path";
14
11
  import { execSync } from "node:child_process";
15
12
 
16
13
  const workspace = process.cwd();
@@ -20,31 +17,6 @@ if (!existsSync(pmSettingsPath)) {
20
17
  process.exit(0);
21
18
  }
22
19
 
23
- const here = dirname(fileURLToPath(import.meta.url));
24
-
25
- async function pathExists(target) {
26
- try {
27
- await access(target);
28
- return true;
29
- } catch {
30
- return false;
31
- }
32
- }
33
-
34
- async function findNativeModule() {
35
- let cursor = here;
36
- for (let depth = 0; depth < 10; depth += 1) {
37
- const candidate = join(cursor, "dist", "pi", "native.js");
38
- if (await pathExists(candidate)) {
39
- return candidate;
40
- }
41
- const parent = dirname(cursor);
42
- if (parent === cursor) break;
43
- cursor = parent;
44
- }
45
- return null;
46
- }
47
-
48
20
  function formatSummary(ctx) {
49
21
  const { summary } = ctx;
50
22
  if (!summary) return null;
@@ -68,29 +40,6 @@ function formatSummary(ctx) {
68
40
  );
69
41
  }
70
42
 
71
- async function tryNativeContext() {
72
- const nativePath = await findNativeModule();
73
- if (!nativePath) return null;
74
-
75
- try {
76
- const { runNativePmAction } = await import(pathToFileURL(nativePath).href);
77
- const result = await runNativePmAction({
78
- action: "context",
79
- cwd: workspace,
80
- json: true,
81
- options: { limit: "5" },
82
- });
83
- const text = Array.isArray(result?.content)
84
- ? result.content.find((p) => p?.type === "text")?.text ?? ""
85
- : typeof result === "string"
86
- ? result
87
- : JSON.stringify(result);
88
- return JSON.parse(text);
89
- } catch {
90
- return null;
91
- }
92
- }
93
-
94
43
  function tryNpxContext() {
95
44
  try {
96
45
  const raw = execSync(
@@ -109,7 +58,7 @@ function tryNpxContext() {
109
58
  }
110
59
 
111
60
  try {
112
- const ctx = (await tryNativeContext()) ?? tryNpxContext();
61
+ const ctx = tryNpxContext();
113
62
  if (!ctx) process.exit(0);
114
63
 
115
64
  const message = formatSummary(ctx);
@@ -39,11 +39,13 @@ async function findRepoServer() {
39
39
 
40
40
  const explicitServer = process.env.PM_CLI_MCP_SERVER;
41
41
  if (explicitServer && (await exists(explicitServer))) {
42
- await import(pathToFileURL(explicitServer).href);
42
+ const server = await import(pathToFileURL(explicitServer).href);
43
+ server.startMcpServer();
43
44
  } else {
44
45
  const repoServer = await findRepoServer();
45
46
  if (repoServer) {
46
- await import(pathToFileURL(repoServer).href);
47
+ const server = await import(pathToFileURL(repoServer).href);
48
+ server.startMcpServer();
47
49
  } else {
48
50
  const child = spawn("npx", ["-y", "--package=@unbrained/pm-cli@latest", "pm-mcp"], {
49
51
  stdio: "inherit",
@@ -33,11 +33,13 @@ async function findRepoServer() {
33
33
 
34
34
  const explicitServer = process.env.PM_CLI_MCP_SERVER;
35
35
  if (explicitServer && await exists(explicitServer)) {
36
- await import(pathToFileURL(explicitServer).href);
36
+ const server = await import(pathToFileURL(explicitServer).href);
37
+ server.startMcpServer();
37
38
  } else {
38
39
  const repoServer = await findRepoServer();
39
40
  if (repoServer) {
40
- await import(pathToFileURL(repoServer).href);
41
+ const server = await import(pathToFileURL(repoServer).href);
42
+ server.startMcpServer();
41
43
  } else {
42
44
  const child = spawn("npx", ["-y", "@unbrained/pm-cli@latest", "pm-mcp"], {
43
45
  stdio: "inherit",
@@ -1,42 +0,0 @@
1
- {
2
- "version": 1,
3
- "updated_at": "2026-04-25T17:01:49.273Z",
4
- "entries": [
5
- {
6
- "name": "builtin-beads-import",
7
- "directory": "beads",
8
- "scope": "project",
9
- "manifest_version": "0.1.0",
10
- "manifest_entry": "./index.js",
11
- "capabilities": [
12
- "commands",
13
- "schema"
14
- ],
15
- "installed_at": "2026-04-25T17:01:49.268Z",
16
- "updated_at": "2026-04-25T17:01:49.268Z",
17
- "source": {
18
- "kind": "local",
19
- "input": "builtin-beads-import",
20
- "location": ".agents/pm/extensions/beads"
21
- }
22
- },
23
- {
24
- "name": "builtin-todos-import-export",
25
- "directory": "todos",
26
- "scope": "project",
27
- "manifest_version": "0.1.0",
28
- "manifest_entry": "./index.js",
29
- "capabilities": [
30
- "commands",
31
- "schema"
32
- ],
33
- "installed_at": "2026-04-25T17:01:49.268Z",
34
- "updated_at": "2026-04-25T17:01:49.268Z",
35
- "source": {
36
- "kind": "local",
37
- "input": "builtin-todos-import-export",
38
- "location": ".agents/pm/extensions/todos"
39
- }
40
- }
41
- ]
42
- }
@@ -1,45 +0,0 @@
1
- # Harness Compatibility
2
-
3
- This repository supports the following harnesses through shared docs and `.agents/skills` workflows only (no harness-specific runtime code):
4
-
5
- - Pi coding agent
6
- - OpenClaw
7
- - Claude Code
8
- - Codex CLI
9
- - OpenCode
10
- - Amp
11
- - Droid
12
- - Hermes
13
- - Gemini CLI
14
-
15
- ## Progressive-Disclosure Route
16
-
17
- Use the same low-token route in every harness:
18
-
19
- 1. `pm guide` (topic index)
20
- 2. `pm guide <topic>` (focused route)
21
- 3. `pm guide <topic> --depth standard|deep` (details only when needed)
22
- 4. `pm contracts --command <command> --flags-only --json` (strict machine flags)
23
-
24
- ## Harness Mapping
25
-
26
- | Harness | Preferred prompt/doc entrypoint | Skill route |
27
- |---------|----------------------------------|-------------|
28
- | Pi coding agent | `AGENTS.md` + `pm guide workflows` | `.agents/skills/pm-developer/SKILL.md` |
29
- | OpenClaw | repository docs + `pm guide` | `.agents/skills/pm-user/SKILL.md` |
30
- | Claude Code | repository docs + `pm guide skills` | `.agents/skills/pm-developer/SKILL.md` |
31
- | Codex CLI | repository docs + `pm guide commands` | `.agents/skills/pm-developer/SKILL.md` |
32
- | OpenCode | repository docs + `pm guide quickstart` | `.agents/skills/pm-user/SKILL.md` |
33
- | Amp | repository docs + `pm guide workflows` | `.agents/skills/pm-user/SKILL.md` |
34
- | Droid | repository docs + `pm guide extensions` | `.agents/skills/pm-extensions/SKILL.md` |
35
- | Hermes | repository docs + `pm guide sdk` | `.agents/skills/pm-sdk/SKILL.md` |
36
- | Gemini CLI | repository docs + `pm guide commands` | `.agents/skills/pm-user/SKILL.md` |
37
-
38
- ## Verification
39
-
40
- Before release, run:
41
-
42
- ```bash
43
- pm guide skills --depth standard
44
- node scripts/release/docs-skills-gate.mjs
45
- ```
@@ -1,21 +0,0 @@
1
- # pm Agent Skills
2
-
3
- This directory contains `agentskills.io`-style skills for `pm` workflows.
4
-
5
- Start with:
6
-
7
- ```bash
8
- pm guide skills
9
- pm guide harnesses --depth standard
10
- ```
11
-
12
- Skill bundles:
13
-
14
- - `pm-developer` - implementation loop for coding agents.
15
- - `pm-user` - operator workflow for planning and task routing.
16
- - `pm-extensions` - extension lifecycle, diagnostics, and release-safe updates.
17
- - `pm-sdk` - SDK and integration workflows.
18
-
19
- Compatibility routing:
20
-
21
- - [Harness compatibility matrix](HARNESS_COMPATIBILITY.md)