@unbrained/pm-cli 2026.5.11 → 2026.5.12
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.
- package/AGENTS.md +3 -116
- package/CHANGELOG.md +7 -0
- package/PRD.md +11 -11
- package/README.md +11 -1
- package/dist/cli/commands/contracts.js +8 -2
- package/dist/cli/commands/contracts.js.map +1 -1
- package/dist/cli/commands/extension.d.ts +9 -2
- package/dist/cli/commands/extension.js +247 -67
- package/dist/cli/commands/extension.js.map +1 -1
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/test.js +14 -6
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/upgrade.d.ts +63 -0
- package/dist/cli/commands/upgrade.js +260 -0
- package/dist/cli/commands/upgrade.js.map +1 -0
- package/dist/cli/guide-topics.js +18 -16
- package/dist/cli/guide-topics.js.map +1 -1
- package/dist/cli/help-content.js +42 -2
- package/dist/cli/help-content.js.map +1 -1
- package/dist/cli/register-setup.js +168 -90
- package/dist/cli/register-setup.js.map +1 -1
- package/dist/core/packages/manifest.d.ts +13 -0
- package/dist/core/packages/manifest.js +139 -0
- package/dist/core/packages/manifest.js.map +1 -0
- package/dist/mcp/server.js +9 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/sdk/cli-contracts.d.ts +18 -17
- package/dist/sdk/cli-contracts.js +137 -35
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/sdk/index.d.ts +1 -0
- package/dist/sdk/index.js +1 -0
- package/dist/sdk/index.js.map +1 -1
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/COMMANDS.md +14 -1
- package/docs/EXTENSIONS.md +112 -29
- package/docs/QUICKSTART.md +10 -2
- package/docs/README.md +4 -6
- package/docs/SDK.md +16 -12
- package/package.json +5 -23
- package/packages/pm-beads/README.md +10 -0
- package/{.agents/pm → packages/pm-beads}/extensions/beads/index.js +24 -9
- package/packages/pm-beads/extensions/beads/index.ts +131 -0
- package/packages/pm-beads/package.json +17 -0
- package/packages/pm-todos/README.md +11 -0
- package/{.agents/pm → packages/pm-todos}/extensions/todos/index.js +24 -9
- package/packages/pm-todos/extensions/todos/index.ts +149 -0
- package/{.agents/pm → packages/pm-todos}/extensions/todos/runtime.js +1 -1
- package/{.agents/pm → packages/pm-todos}/extensions/todos/runtime.ts +1 -1
- package/packages/pm-todos/package.json +17 -0
- package/plugins/pm-cli-claude/README.md +1 -2
- package/plugins/pm-cli-claude/hooks/session-start.mjs +4 -55
- package/.agents/pm/extensions/.managed-extensions.json +0 -42
- package/.agents/skills/HARNESS_COMPATIBILITY.md +0 -45
- package/.agents/skills/README.md +0 -21
- package/.agents/skills/pm-developer/SKILL.md +0 -73
- package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +0 -48
- package/.agents/skills/pm-developer/references/PROMPTS.md +0 -17
- package/.agents/skills/pm-extensions/SKILL.md +0 -57
- package/.agents/skills/pm-extensions/references/LIFECYCLE.md +0 -40
- package/.agents/skills/pm-extensions/references/TROUBLESHOOTING.md +0 -25
- package/.agents/skills/pm-sdk/SKILL.md +0 -50
- package/.agents/skills/pm-sdk/references/INTEGRATION_CHECKLIST.md +0 -31
- package/.agents/skills/pm-sdk/references/PROMPTS.md +0 -13
- package/.agents/skills/pm-user/SKILL.md +0 -59
- package/.agents/skills/pm-user/references/PROMPTS.md +0 -17
- package/.agents/skills/pm-user/references/WORKFLOWS.md +0 -35
- package/.pi/README.md +0 -35
- package/.pi/agents/pm-triage-agent.md +0 -19
- package/.pi/agents/pm-verification-agent.md +0 -21
- package/.pi/chains/pm-native-delivery.chain.md +0 -11
- package/.pi/extensions/pm-cli/index.js +0 -387
- package/.pi/prompts/pm-workflow.md +0 -5
- package/.pi/skills/pm-native/SKILL.md +0 -44
- package/.pi/skills/pm-release/SKILL.md +0 -35
- package/dist/pi/native.d.ts +0 -5
- package/dist/pi/native.js +0 -236
- package/dist/pi/native.js.map +0 -1
- package/docs/PI_PACKAGE.md +0 -141
- /package/{.agents/pm → packages/pm-beads}/extensions/beads/manifest.json +0 -0
- /package/{.agents/pm → packages/pm-beads}/extensions/beads/runtime.js +0 -0
- /package/{.agents/pm → packages/pm-beads}/extensions/beads/runtime.ts +0 -0
- /package/{.agents/pm → packages/pm-todos}/extensions/todos/manifest.json +0 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
|
+
import type { CommandDefinition, ExtensionApi } from "../../../../src/core/extensions/loader.js";
|
|
4
|
+
import type { GlobalOptions } from "../../../../src/core/shared/command-types.js";
|
|
5
|
+
import type { BeadsImportOptions, BeadsImportResult } from "./runtime.js";
|
|
6
|
+
|
|
7
|
+
const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
|
|
8
|
+
const CURRENT_EXTENSION_ROOT = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
export const manifest = {
|
|
11
|
+
name: "builtin-beads-import",
|
|
12
|
+
version: "0.1.0",
|
|
13
|
+
entry: "./index.js",
|
|
14
|
+
priority: 0,
|
|
15
|
+
capabilities: ["commands", "schema"],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type RuntimeModule = {
|
|
19
|
+
runBeadsImport?: (options: BeadsImportOptions, global: GlobalOptions) => Promise<BeadsImportResult>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function asOptionalString(value: unknown): string | undefined {
|
|
23
|
+
return typeof value === "string" ? value : undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function asBoolean(value: unknown): boolean | undefined {
|
|
27
|
+
return typeof value === "boolean" ? value : undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function toBeadsImportOptions(options: Record<string, unknown>): BeadsImportOptions {
|
|
31
|
+
return {
|
|
32
|
+
file: asOptionalString(options.file),
|
|
33
|
+
author: asOptionalString(options.author),
|
|
34
|
+
message: asOptionalString(options.message),
|
|
35
|
+
preserveSourceIds: asBoolean(options.preserveSourceIds),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function resolvePackageRootCandidates(): string[] {
|
|
40
|
+
const candidates: string[] = [];
|
|
41
|
+
const envRoot = process.env[PM_PACKAGE_ROOT_ENV];
|
|
42
|
+
if (typeof envRoot === "string" && envRoot.trim().length > 0) {
|
|
43
|
+
candidates.push(path.resolve(envRoot.trim()));
|
|
44
|
+
}
|
|
45
|
+
const argvEntry = typeof process.argv[1] === "string" ? process.argv[1].trim() : "";
|
|
46
|
+
if (argvEntry.length > 0) {
|
|
47
|
+
const resolvedEntry = path.resolve(argvEntry);
|
|
48
|
+
const entryDir = path.dirname(resolvedEntry);
|
|
49
|
+
candidates.push(path.resolve(entryDir, ".."));
|
|
50
|
+
candidates.push(path.resolve(entryDir, "../.."));
|
|
51
|
+
candidates.push(path.resolve(entryDir, "../../.."));
|
|
52
|
+
}
|
|
53
|
+
return [...new Set(candidates)];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function loadRuntimeModule(): Promise<RuntimeModule> {
|
|
57
|
+
const attempted: string[] = [];
|
|
58
|
+
for (const packageRoot of resolvePackageRootCandidates()) {
|
|
59
|
+
const modulePaths = [
|
|
60
|
+
path.join(packageRoot, ".agents", "pm", "extensions", "beads", "runtime.js"),
|
|
61
|
+
path.join(packageRoot, "packages", "pm-beads", "extensions", "beads", "runtime.js"),
|
|
62
|
+
];
|
|
63
|
+
for (const modulePath of modulePaths) {
|
|
64
|
+
attempted.push(modulePath);
|
|
65
|
+
try {
|
|
66
|
+
return await import(pathToFileURL(modulePath).href) as RuntimeModule;
|
|
67
|
+
} catch {
|
|
68
|
+
// Try the next package-root candidate.
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const localRuntimePath = path.join(CURRENT_EXTENSION_ROOT, "runtime.js");
|
|
74
|
+
attempted.push(localRuntimePath);
|
|
75
|
+
try {
|
|
76
|
+
return await import(pathToFileURL(localRuntimePath).href) as RuntimeModule;
|
|
77
|
+
} catch {
|
|
78
|
+
// Fall through to the diagnostic below.
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
throw new Error(
|
|
82
|
+
"Unable to resolve packaged beads extension runtime module. " +
|
|
83
|
+
`Tried: ${attempted.join(", ")}. Ensure the installed extension includes runtime.js or PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function runBeadsImportFromRuntime(options: BeadsImportOptions, global: GlobalOptions): Promise<BeadsImportResult> {
|
|
88
|
+
const runtime = await loadRuntimeModule();
|
|
89
|
+
if (typeof runtime.runBeadsImport !== "function") {
|
|
90
|
+
throw new Error("Bundled beads runtime module is missing runBeadsImport().");
|
|
91
|
+
}
|
|
92
|
+
return runtime.runBeadsImport(options, global);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function activate(api: ExtensionApi): void {
|
|
96
|
+
api.registerCommand({
|
|
97
|
+
name: "beads import",
|
|
98
|
+
description: "Import Beads JSONL records into pm items.",
|
|
99
|
+
flags: [
|
|
100
|
+
{
|
|
101
|
+
long: "--file",
|
|
102
|
+
value_name: "path",
|
|
103
|
+
value_type: "string",
|
|
104
|
+
description: "Path to the Beads JSONL source file.",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
long: "--author",
|
|
108
|
+
value_name: "author",
|
|
109
|
+
value_type: "string",
|
|
110
|
+
description: "Override import mutation author.",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
long: "--message",
|
|
114
|
+
value_name: "text",
|
|
115
|
+
value_type: "string",
|
|
116
|
+
description: "Override import history message.",
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
long: "--preserve-source-ids",
|
|
120
|
+
value_type: "boolean",
|
|
121
|
+
description: "Preserve source IDs from Beads payload records when possible.",
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
run: async (context) => runBeadsImportFromRuntime(toBeadsImportOptions(context.options), context.global),
|
|
125
|
+
} satisfies CommandDefinition);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export default {
|
|
129
|
+
manifest,
|
|
130
|
+
activate,
|
|
131
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@unbrained/pm-package-beads",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "First-party pm package for importing Beads JSONL records.",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"pm-package",
|
|
9
|
+
"project-management",
|
|
10
|
+
"beads"
|
|
11
|
+
],
|
|
12
|
+
"pm": {
|
|
13
|
+
"extensions": [
|
|
14
|
+
"extensions/beads"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# pm Todos Package
|
|
2
|
+
|
|
3
|
+
First-party pm package for Todo markdown import and export.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pm install ./packages/pm-todos --project
|
|
7
|
+
pm todos import --folder .pm/todos
|
|
8
|
+
pm todos export --folder .pm/todos
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The package exposes the `todos import` and `todos export` extension commands through the `pm.extensions` package manifest. Runtime sources are authored in TypeScript and shipped with JavaScript entry artifacts for Node extension loading.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { pathToFileURL } from "node:url";
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
3
|
|
|
4
4
|
const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
|
|
5
|
+
const CURRENT_EXTENSION_ROOT = path.dirname(fileURLToPath(import.meta.url));
|
|
5
6
|
|
|
6
7
|
export const manifest = {
|
|
7
8
|
name: "builtin-todos-import-export",
|
|
@@ -49,17 +50,31 @@ function resolvePackageRootCandidates() {
|
|
|
49
50
|
async function loadRuntimeModule() {
|
|
50
51
|
const attempted = [];
|
|
51
52
|
for (const packageRoot of resolvePackageRootCandidates()) {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
const modulePaths = [
|
|
54
|
+
path.join(packageRoot, ".agents", "pm", "extensions", "todos", "runtime.js"),
|
|
55
|
+
path.join(packageRoot, "packages", "pm-todos", "extensions", "todos", "runtime.js"),
|
|
56
|
+
];
|
|
57
|
+
for (const modulePath of modulePaths) {
|
|
58
|
+
attempted.push(modulePath);
|
|
59
|
+
try {
|
|
60
|
+
return await import(pathToFileURL(modulePath).href);
|
|
61
|
+
} catch {
|
|
62
|
+
// Try the next package-root candidate.
|
|
63
|
+
}
|
|
58
64
|
}
|
|
59
65
|
}
|
|
66
|
+
|
|
67
|
+
const localRuntimePath = path.join(CURRENT_EXTENSION_ROOT, "runtime.js");
|
|
68
|
+
attempted.push(localRuntimePath);
|
|
69
|
+
try {
|
|
70
|
+
return await import(pathToFileURL(localRuntimePath).href);
|
|
71
|
+
} catch {
|
|
72
|
+
// Fall through to the diagnostic below.
|
|
73
|
+
}
|
|
74
|
+
|
|
60
75
|
throw new Error(
|
|
61
|
-
"Unable to resolve
|
|
62
|
-
`Tried: ${attempted.join(", ")}. Ensure PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
|
|
76
|
+
"Unable to resolve packaged todos extension runtime module. " +
|
|
77
|
+
`Tried: ${attempted.join(", ")}. Ensure the installed extension includes runtime.js or PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
|
|
63
78
|
);
|
|
64
79
|
}
|
|
65
80
|
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
|
+
import type { CommandDefinition, ExtensionApi } from "../../../../src/core/extensions/loader.js";
|
|
4
|
+
import type { GlobalOptions } from "../../../../src/core/shared/command-types.js";
|
|
5
|
+
import type { TodosExportOptions, TodosExportResult, TodosImportOptions, TodosImportResult } from "./runtime.js";
|
|
6
|
+
|
|
7
|
+
const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
|
|
8
|
+
const CURRENT_EXTENSION_ROOT = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
export const manifest = {
|
|
11
|
+
name: "builtin-todos-import-export",
|
|
12
|
+
version: "0.1.0",
|
|
13
|
+
entry: "./index.js",
|
|
14
|
+
priority: 0,
|
|
15
|
+
capabilities: ["commands", "schema"],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type RuntimeModule = {
|
|
19
|
+
runTodosImport?: (options: TodosImportOptions, global: GlobalOptions) => Promise<TodosImportResult>;
|
|
20
|
+
runTodosExport?: (options: TodosExportOptions, global: GlobalOptions) => Promise<TodosExportResult>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function asOptionalString(value: unknown): string | undefined {
|
|
24
|
+
return typeof value === "string" ? value : undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function toImportOptions(options: Record<string, unknown>): TodosImportOptions {
|
|
28
|
+
return {
|
|
29
|
+
folder: asOptionalString(options.folder),
|
|
30
|
+
author: asOptionalString(options.author),
|
|
31
|
+
message: asOptionalString(options.message),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function toExportOptions(options: Record<string, unknown>): TodosExportOptions {
|
|
36
|
+
return {
|
|
37
|
+
folder: asOptionalString(options.folder),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function resolvePackageRootCandidates(): string[] {
|
|
42
|
+
const candidates: string[] = [];
|
|
43
|
+
const envRoot = process.env[PM_PACKAGE_ROOT_ENV];
|
|
44
|
+
if (typeof envRoot === "string" && envRoot.trim().length > 0) {
|
|
45
|
+
candidates.push(path.resolve(envRoot.trim()));
|
|
46
|
+
}
|
|
47
|
+
const argvEntry = typeof process.argv[1] === "string" ? process.argv[1].trim() : "";
|
|
48
|
+
if (argvEntry.length > 0) {
|
|
49
|
+
const resolvedEntry = path.resolve(argvEntry);
|
|
50
|
+
const entryDir = path.dirname(resolvedEntry);
|
|
51
|
+
candidates.push(path.resolve(entryDir, ".."));
|
|
52
|
+
candidates.push(path.resolve(entryDir, "../.."));
|
|
53
|
+
candidates.push(path.resolve(entryDir, "../../.."));
|
|
54
|
+
}
|
|
55
|
+
return [...new Set(candidates)];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function loadRuntimeModule(): Promise<RuntimeModule> {
|
|
59
|
+
const attempted: string[] = [];
|
|
60
|
+
for (const packageRoot of resolvePackageRootCandidates()) {
|
|
61
|
+
const modulePaths = [
|
|
62
|
+
path.join(packageRoot, ".agents", "pm", "extensions", "todos", "runtime.js"),
|
|
63
|
+
path.join(packageRoot, "packages", "pm-todos", "extensions", "todos", "runtime.js"),
|
|
64
|
+
];
|
|
65
|
+
for (const modulePath of modulePaths) {
|
|
66
|
+
attempted.push(modulePath);
|
|
67
|
+
try {
|
|
68
|
+
return await import(pathToFileURL(modulePath).href) as RuntimeModule;
|
|
69
|
+
} catch {
|
|
70
|
+
// Try the next package-root candidate.
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const localRuntimePath = path.join(CURRENT_EXTENSION_ROOT, "runtime.js");
|
|
76
|
+
attempted.push(localRuntimePath);
|
|
77
|
+
try {
|
|
78
|
+
return await import(pathToFileURL(localRuntimePath).href) as RuntimeModule;
|
|
79
|
+
} catch {
|
|
80
|
+
// Fall through to the diagnostic below.
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
throw new Error(
|
|
84
|
+
"Unable to resolve packaged todos extension runtime module. " +
|
|
85
|
+
`Tried: ${attempted.join(", ")}. Ensure the installed extension includes runtime.js or PM_CLI_PACKAGE_ROOT points to an installed pm package root.`,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function runTodosImportFromRuntime(options: TodosImportOptions, global: GlobalOptions): Promise<TodosImportResult> {
|
|
90
|
+
const runtime = await loadRuntimeModule();
|
|
91
|
+
if (typeof runtime.runTodosImport !== "function") {
|
|
92
|
+
throw new Error("Bundled todos runtime module is missing runTodosImport().");
|
|
93
|
+
}
|
|
94
|
+
return runtime.runTodosImport(options, global);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function runTodosExportFromRuntime(options: TodosExportOptions, global: GlobalOptions): Promise<TodosExportResult> {
|
|
98
|
+
const runtime = await loadRuntimeModule();
|
|
99
|
+
if (typeof runtime.runTodosExport !== "function") {
|
|
100
|
+
throw new Error("Bundled todos runtime module is missing runTodosExport().");
|
|
101
|
+
}
|
|
102
|
+
return runtime.runTodosExport(options, global);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function activate(api: ExtensionApi): void {
|
|
106
|
+
api.registerCommand({
|
|
107
|
+
name: "todos import",
|
|
108
|
+
description: "Import Todo markdown files into pm items.",
|
|
109
|
+
flags: [
|
|
110
|
+
{
|
|
111
|
+
long: "--folder",
|
|
112
|
+
value_name: "path",
|
|
113
|
+
value_type: "string",
|
|
114
|
+
description: "Source folder containing Todo markdown files.",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
long: "--author",
|
|
118
|
+
value_name: "author",
|
|
119
|
+
value_type: "string",
|
|
120
|
+
description: "Override import mutation author.",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
long: "--message",
|
|
124
|
+
value_name: "text",
|
|
125
|
+
value_type: "string",
|
|
126
|
+
description: "Override import history message.",
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
run: async (context) => runTodosImportFromRuntime(toImportOptions(context.options), context.global),
|
|
130
|
+
} satisfies CommandDefinition);
|
|
131
|
+
api.registerCommand({
|
|
132
|
+
name: "todos export",
|
|
133
|
+
description: "Export pm items into Todo markdown files.",
|
|
134
|
+
flags: [
|
|
135
|
+
{
|
|
136
|
+
long: "--folder",
|
|
137
|
+
value_name: "path",
|
|
138
|
+
value_type: "string",
|
|
139
|
+
description: "Destination folder for exported Todo markdown files.",
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
run: async (context) => runTodosExportFromRuntime(toExportOptions(context.options), context.global),
|
|
143
|
+
} satisfies CommandDefinition);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export default {
|
|
147
|
+
manifest,
|
|
148
|
+
activate,
|
|
149
|
+
};
|
|
@@ -16,7 +16,7 @@ import { listAllFrontMatter, locateItem, readLocatedItem } from "../../../../dis
|
|
|
16
16
|
import { getHistoryPath, getItemPath, getSettingsPath, resolvePmRoot } from "../../../../dist/core/store/paths.js";
|
|
17
17
|
import { readSettings } from "../../../../dist/core/store/settings.js";
|
|
18
18
|
import { CONFIDENCE_TEXT_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES } from "../../../../dist/types/index.js";
|
|
19
|
-
const DEFAULT_TODOS_FOLDER = ".
|
|
19
|
+
const DEFAULT_TODOS_FOLDER = ".pm/todos";
|
|
20
20
|
function isRecord(value) {
|
|
21
21
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22
22
|
}
|
|
@@ -20,7 +20,7 @@ import { readSettings } from "../../../../src/core/store/settings.js";
|
|
|
20
20
|
import { CONFIDENCE_TEXT_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES } from "../../../../src/types/index.js";
|
|
21
21
|
import type { ItemDocument, ItemMetadata, ItemStatus, ItemType, PmSettings } from "../../../../src/types/index.js";
|
|
22
22
|
|
|
23
|
-
const DEFAULT_TODOS_FOLDER = ".
|
|
23
|
+
const DEFAULT_TODOS_FOLDER = ".pm/todos";
|
|
24
24
|
|
|
25
25
|
export interface TodosImportOptions {
|
|
26
26
|
folder?: string;
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
"keywords": [
|
|
8
|
+
"pm-package",
|
|
9
|
+
"project-management",
|
|
10
|
+
"todos"
|
|
11
|
+
],
|
|
12
|
+
"pm": {
|
|
13
|
+
"extensions": [
|
|
14
|
+
"extensions/todos"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -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
|
-
-
|
|
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
|
|
7
|
-
*
|
|
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
|
|
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 =
|
|
61
|
+
const ctx = tryNpxContext();
|
|
113
62
|
if (!ctx) process.exit(0);
|
|
114
63
|
|
|
115
64
|
const message = formatSummary(ctx);
|
|
@@ -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
|
-
```
|
package/.agents/skills/README.md
DELETED
|
@@ -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)
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pm-developer
|
|
3
|
-
description: Runs the pm-cli developer execution loop (orient, claim, implement, verify, close) with linked files/tests/docs evidence. Use when coding, debugging, refactoring, or shipping repository changes tracked in pm items.
|
|
4
|
-
license: MIT
|
|
5
|
-
compatibility: Works in terminal-based coding agents with bash, Node.js, and pnpm.
|
|
6
|
-
metadata:
|
|
7
|
-
owner: unbrained
|
|
8
|
-
domain: pm-cli
|
|
9
|
-
scope: developer-workflow
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# pm Developer Skill
|
|
13
|
-
|
|
14
|
-
Use this skill for implementation work that changes code, docs, tests, or release gates.
|
|
15
|
-
|
|
16
|
-
## Quick Start
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
pm context --limit 10
|
|
20
|
-
pm search "<task keywords>" --limit 10
|
|
21
|
-
pm list-open --limit 20
|
|
22
|
-
pm claim <ID>
|
|
23
|
-
pm update <ID> --status in_progress
|
|
24
|
-
pm guide workflows
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Canonical Workflow
|
|
28
|
-
|
|
29
|
-
1. **Orient**: pick an existing item when possible.
|
|
30
|
-
2. **Claim**: claim before substantial edits.
|
|
31
|
-
3. **Link context**: attach changed files/tests/docs while implementing.
|
|
32
|
-
4. **Verify**: run linked tests plus local quality gates.
|
|
33
|
-
5. **Close with evidence**: append what changed and what passed.
|
|
34
|
-
6. **Release claim**: release when paused, handed off, or closed.
|
|
35
|
-
|
|
36
|
-
## Workflow Prompts
|
|
37
|
-
|
|
38
|
-
Use one prompt template, then execute only the minimum required commands.
|
|
39
|
-
|
|
40
|
-
### Prompt: Implement Scoped Change
|
|
41
|
-
|
|
42
|
-
`Implement the requested change on <ID>. Keep edits scoped, link files/tests/docs, run targeted verification, and record closure evidence before releasing claim.`
|
|
43
|
-
|
|
44
|
-
### Prompt: Debug Regression
|
|
45
|
-
|
|
46
|
-
`Investigate failing behavior for <ID>. Reproduce first, add or update regression tests, patch root cause, and append evidence with exact command outputs.`
|
|
47
|
-
|
|
48
|
-
### Prompt: Documentation + Code Sync
|
|
49
|
-
|
|
50
|
-
`Update implementation and docs together for <ID>. Ensure docs route through pm guide topics and verify command examples still match pm contracts output.`
|
|
51
|
-
|
|
52
|
-
## Required Evidence Commands
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
pm files <ID> --add path=<path>,scope=project,note="<reason>"
|
|
56
|
-
pm test <ID> --add command="node scripts/run-tests.mjs test -- <target>",scope=project,timeout_seconds=240
|
|
57
|
-
pm docs <ID> --add path=<doc>,scope=project,note="<reason>"
|
|
58
|
-
pm comments <ID> "Evidence: <what changed + tests run>"
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Verification Defaults
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
pnpm build
|
|
65
|
-
node scripts/run-tests.mjs test -- <targets>
|
|
66
|
-
node scripts/run-tests.mjs coverage
|
|
67
|
-
pm validate --check-resolution --check-history-drift
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Progressive Disclosure References
|
|
71
|
-
|
|
72
|
-
- [Developer command playbook](references/COMMAND_PLAYBOOK.md)
|
|
73
|
-
- [Prompt templates and examples](references/PROMPTS.md)
|