@unbrained/pm-cli 2026.5.6 → 2026.5.10

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 (197) hide show
  1. package/.agents/pm/extensions/.managed-extensions.json +2 -2
  2. package/.agents/pm/extensions/beads/runtime.js +4 -4
  3. package/.agents/pm/extensions/beads/runtime.ts +5 -5
  4. package/.agents/pm/extensions/todos/runtime.js +7 -7
  5. package/.agents/pm/extensions/todos/runtime.ts +10 -10
  6. package/.agents/skills/HARNESS_COMPATIBILITY.md +45 -0
  7. package/.agents/skills/README.md +21 -0
  8. package/.agents/skills/pm-developer/SKILL.md +73 -0
  9. package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +48 -0
  10. package/.agents/skills/pm-developer/references/PROMPTS.md +17 -0
  11. package/.agents/skills/pm-extensions/SKILL.md +57 -0
  12. package/.agents/skills/pm-extensions/references/LIFECYCLE.md +40 -0
  13. package/.agents/skills/pm-extensions/references/TROUBLESHOOTING.md +25 -0
  14. package/.agents/skills/pm-sdk/SKILL.md +50 -0
  15. package/.agents/skills/pm-sdk/references/INTEGRATION_CHECKLIST.md +31 -0
  16. package/.agents/skills/pm-sdk/references/PROMPTS.md +13 -0
  17. package/.agents/skills/pm-user/SKILL.md +59 -0
  18. package/.agents/skills/pm-user/references/PROMPTS.md +17 -0
  19. package/.agents/skills/pm-user/references/WORKFLOWS.md +35 -0
  20. package/.claude-plugin/marketplace.json +38 -0
  21. package/.pi/README.md +26 -0
  22. package/.pi/extensions/pm-cli/index.js +147 -0
  23. package/.pi/prompts/pm-workflow.md +5 -0
  24. package/.pi/skills/pm-native/SKILL.md +40 -0
  25. package/.pi/skills/pm-release/SKILL.md +35 -0
  26. package/AGENTS.md +1 -1
  27. package/CHANGELOG.md +6 -0
  28. package/PRD.md +16 -16
  29. package/README.md +22 -4
  30. package/dist/cli/commands/claim.js +6 -6
  31. package/dist/cli/commands/claim.js.map +1 -1
  32. package/dist/cli/commands/close.js +9 -9
  33. package/dist/cli/commands/close.js.map +1 -1
  34. package/dist/cli/commands/comments.d.ts +2 -0
  35. package/dist/cli/commands/comments.js +57 -8
  36. package/dist/cli/commands/comments.js.map +1 -1
  37. package/dist/cli/commands/completion.js +33 -4
  38. package/dist/cli/commands/completion.js.map +1 -1
  39. package/dist/cli/commands/config.js +6 -3
  40. package/dist/cli/commands/config.js.map +1 -1
  41. package/dist/cli/commands/contracts.js +4 -1
  42. package/dist/cli/commands/contracts.js.map +1 -1
  43. package/dist/cli/commands/create.d.ts +2 -2
  44. package/dist/cli/commands/create.js +4 -4
  45. package/dist/cli/commands/create.js.map +1 -1
  46. package/dist/cli/commands/docs.js +4 -4
  47. package/dist/cli/commands/docs.js.map +1 -1
  48. package/dist/cli/commands/files.js +10 -10
  49. package/dist/cli/commands/files.js.map +1 -1
  50. package/dist/cli/commands/get.js +5 -5
  51. package/dist/cli/commands/get.js.map +1 -1
  52. package/dist/cli/commands/guide.d.ts +55 -0
  53. package/dist/cli/commands/guide.js +260 -0
  54. package/dist/cli/commands/guide.js.map +1 -0
  55. package/dist/cli/commands/health.js +1 -1
  56. package/dist/cli/commands/health.js.map +1 -1
  57. package/dist/cli/commands/history.js +30 -10
  58. package/dist/cli/commands/history.js.map +1 -1
  59. package/dist/cli/commands/index.d.ts +1 -0
  60. package/dist/cli/commands/index.js +1 -0
  61. package/dist/cli/commands/index.js.map +1 -1
  62. package/dist/cli/commands/learnings.js +3 -3
  63. package/dist/cli/commands/learnings.js.map +1 -1
  64. package/dist/cli/commands/notes.js +3 -3
  65. package/dist/cli/commands/notes.js.map +1 -1
  66. package/dist/cli/commands/reindex.js +18 -32
  67. package/dist/cli/commands/reindex.js.map +1 -1
  68. package/dist/cli/commands/restore.d.ts +2 -2
  69. package/dist/cli/commands/restore.js +44 -24
  70. package/dist/cli/commands/restore.js.map +1 -1
  71. package/dist/cli/commands/search.d.ts +2 -0
  72. package/dist/cli/commands/search.js +30 -21
  73. package/dist/cli/commands/search.js.map +1 -1
  74. package/dist/cli/commands/test-all.d.ts +2 -0
  75. package/dist/cli/commands/test-all.js +2 -0
  76. package/dist/cli/commands/test-all.js.map +1 -1
  77. package/dist/cli/commands/test.d.ts +1 -0
  78. package/dist/cli/commands/test.js +4 -3
  79. package/dist/cli/commands/test.js.map +1 -1
  80. package/dist/cli/commands/update.js +118 -118
  81. package/dist/cli/commands/update.js.map +1 -1
  82. package/dist/cli/commands/validate.js +1 -1
  83. package/dist/cli/commands/validate.js.map +1 -1
  84. package/dist/cli/guide-topics.d.ts +25 -0
  85. package/dist/cli/guide-topics.js +283 -0
  86. package/dist/cli/guide-topics.js.map +1 -0
  87. package/dist/cli/help-content.js +25 -1
  88. package/dist/cli/help-content.js.map +1 -1
  89. package/dist/cli/register-list-query.js +38 -1
  90. package/dist/cli/register-list-query.js.map +1 -1
  91. package/dist/cli/register-mutation.js +17 -4
  92. package/dist/cli/register-mutation.js.map +1 -1
  93. package/dist/cli/register-setup.js +1 -1
  94. package/dist/cli/register-setup.js.map +1 -1
  95. package/dist/core/history/history.js +32 -11
  96. package/dist/core/history/history.js.map +1 -1
  97. package/dist/core/item/item-format.d.ts +2 -2
  98. package/dist/core/item/item-format.js +16 -16
  99. package/dist/core/item/item-format.js.map +1 -1
  100. package/dist/core/schema/runtime-field-filters.js +1 -1
  101. package/dist/core/schema/runtime-field-filters.js.map +1 -1
  102. package/dist/core/schema/runtime-field-values.js +2 -2
  103. package/dist/core/schema/runtime-field-values.js.map +1 -1
  104. package/dist/core/schema/runtime-schema.d.ts +1 -1
  105. package/dist/core/schema/runtime-schema.js +3 -3
  106. package/dist/core/schema/runtime-schema.js.map +1 -1
  107. package/dist/core/search/cache.js +7 -21
  108. package/dist/core/search/cache.js.map +1 -1
  109. package/dist/core/search/corpus.d.ts +13 -0
  110. package/dist/core/search/corpus.js +74 -0
  111. package/dist/core/search/corpus.js.map +1 -0
  112. package/dist/core/search/embedding-batches.js +90 -30
  113. package/dist/core/search/embedding-batches.js.map +1 -1
  114. package/dist/core/sentry/instrument.d.ts +3 -1
  115. package/dist/core/sentry/instrument.js +93 -9
  116. package/dist/core/sentry/instrument.js.map +1 -1
  117. package/dist/core/shared/constants.d.ts +1 -1
  118. package/dist/core/shared/constants.js +1 -1
  119. package/dist/core/shared/constants.js.map +1 -1
  120. package/dist/core/store/front-matter-cache.d.ts +1 -1
  121. package/dist/core/store/front-matter-cache.js +13 -13
  122. package/dist/core/store/front-matter-cache.js.map +1 -1
  123. package/dist/core/store/item-format-migration.js +5 -2
  124. package/dist/core/store/item-format-migration.js.map +1 -1
  125. package/dist/core/store/item-store.js +16 -15
  126. package/dist/core/store/item-store.js.map +1 -1
  127. package/dist/core/store/paths.js +1 -1
  128. package/dist/core/store/paths.js.map +1 -1
  129. package/dist/core/store/settings.js +6 -1
  130. package/dist/core/store/settings.js.map +1 -1
  131. package/dist/core/test/item-test-run-tracking.js +2 -2
  132. package/dist/core/test/item-test-run-tracking.js.map +1 -1
  133. package/dist/mcp/server.d.ts +2 -0
  134. package/dist/mcp/server.js +405 -0
  135. package/dist/mcp/server.js.map +1 -0
  136. package/dist/pi/native.d.ts +5 -0
  137. package/dist/pi/native.js +183 -0
  138. package/dist/pi/native.js.map +1 -0
  139. package/dist/sdk/cli-contracts.d.ts +3 -1
  140. package/dist/sdk/cli-contracts.js +67 -2
  141. package/dist/sdk/cli-contracts.js.map +1 -1
  142. package/dist/types.d.ts +10 -2
  143. package/dist/types.js.map +1 -1
  144. package/docs/AGENT_GUIDE.md +15 -0
  145. package/docs/ARCHITECTURE.md +2 -2
  146. package/docs/CLAUDE_CODE_PLUGIN.md +186 -0
  147. package/docs/CODEX_PLUGIN.md +33 -0
  148. package/docs/COMMANDS.md +6 -2
  149. package/docs/CONFIGURATION.md +2 -8
  150. package/docs/EXTENSIONS.md +1 -0
  151. package/docs/PI_PACKAGE.md +56 -0
  152. package/docs/QUICKSTART.md +1 -0
  153. package/docs/README.md +30 -1
  154. package/docs/RELEASING.md +4 -2
  155. package/docs/SDK.md +3 -2
  156. package/marketplace.json +34 -0
  157. package/package.json +38 -4
  158. package/plugins/pm-cli-claude/.claude-plugin/plugin.json +23 -0
  159. package/plugins/pm-cli-claude/.mcp.json +12 -0
  160. package/plugins/pm-cli-claude/README.md +184 -0
  161. package/plugins/pm-cli-claude/agents/pm-coordinator.md +48 -0
  162. package/plugins/pm-cli-claude/commands/pm-audit.md +39 -0
  163. package/plugins/pm-cli-claude/commands/pm-calendar.md +41 -0
  164. package/plugins/pm-cli-claude/commands/pm-close-task.md +20 -0
  165. package/plugins/pm-cli-claude/commands/pm-developer.md +38 -0
  166. package/plugins/pm-cli-claude/commands/pm-init.md +44 -0
  167. package/plugins/pm-cli-claude/commands/pm-list.md +39 -0
  168. package/plugins/pm-cli-claude/commands/pm-new.md +36 -0
  169. package/plugins/pm-cli-claude/commands/pm-planner.md +51 -0
  170. package/plugins/pm-cli-claude/commands/pm-release.md +41 -0
  171. package/plugins/pm-cli-claude/commands/pm-search.md +21 -0
  172. package/plugins/pm-cli-claude/commands/pm-start-task.md +27 -0
  173. package/plugins/pm-cli-claude/commands/pm-status.md +15 -0
  174. package/plugins/pm-cli-claude/commands/pm-triage.md +35 -0
  175. package/plugins/pm-cli-claude/commands/pm-workflow.md +49 -0
  176. package/plugins/pm-cli-claude/hooks/hooks.json +17 -0
  177. package/plugins/pm-cli-claude/hooks/session-start.mjs +55 -0
  178. package/plugins/pm-cli-claude/scripts/pm-mcp-server.mjs +60 -0
  179. package/plugins/pm-cli-claude/skills/pm-audit/SKILL.md +88 -0
  180. package/plugins/pm-cli-claude/skills/pm-developer/SKILL.md +116 -0
  181. package/plugins/pm-cli-claude/skills/pm-planner/SKILL.md +118 -0
  182. package/plugins/pm-cli-claude/skills/pm-release/SKILL.md +83 -0
  183. package/plugins/pm-cli-claude/skills/pm-workflow/SKILL.md +148 -0
  184. package/plugins/pm-cli-codex/.codex-plugin/plugin.json +45 -0
  185. package/plugins/pm-cli-codex/.mcp.json +14 -0
  186. package/plugins/pm-cli-codex/README.md +30 -0
  187. package/plugins/pm-cli-codex/assets/pm-cli-small.svg +4 -0
  188. package/plugins/pm-cli-codex/commands/pm-audit.md +8 -0
  189. package/plugins/pm-cli-codex/commands/pm-close-task.md +9 -0
  190. package/plugins/pm-cli-codex/commands/pm-start-task.md +9 -0
  191. package/plugins/pm-cli-codex/scripts/pm-mcp-server.mjs +54 -0
  192. package/plugins/pm-cli-codex/skills/pm-auditor/SKILL.md +21 -0
  193. package/plugins/pm-cli-codex/skills/pm-auditor/agents/openai.yaml +6 -0
  194. package/plugins/pm-cli-codex/skills/pm-native/SKILL.md +57 -0
  195. package/plugins/pm-cli-codex/skills/pm-native/agents/openai.yaml +6 -0
  196. package/plugins/pm-cli-codex/skills/pm-release/SKILL.md +19 -0
  197. package/plugins/pm-cli-codex/skills/pm-release/agents/openai.yaml +6 -0
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: pm-user
3
+ description: Guides user- and operator-facing pm-cli workflows for planning, triage, prioritization, and task lifecycle management with minimal token usage. Use when routing requests into pm items without implementing code changes.
4
+ license: MIT
5
+ compatibility: Works in terminal-based agent harnesses that execute pm CLI commands.
6
+ metadata:
7
+ owner: unbrained
8
+ domain: pm-cli
9
+ scope: operator-workflow
10
+ ---
11
+
12
+ # pm User Skill
13
+
14
+ Use this skill for planning and coordination work where the main output is clean tracker state.
15
+
16
+ ## Quick Start
17
+
18
+ ```bash
19
+ pm guide quickstart
20
+ pm context --limit 10
21
+ pm search "<request keywords>" --limit 10
22
+ pm list-open --limit 20
23
+ pm list-in-progress --limit 20
24
+ ```
25
+
26
+ ## Primary Use Cases
27
+
28
+ - Intake a new request and decide whether an item already exists.
29
+ - Create parent lineage (`Epic` -> `Feature` -> `Task`) for net-new scope.
30
+ - Prioritize and schedule work with deterministic metadata.
31
+ - Maintain clear ownership and handoff notes.
32
+
33
+ ## Workflow Prompts
34
+
35
+ ### Prompt: New Request Triage
36
+
37
+ `Triage this request using pm only. Reuse an existing item if relevant; otherwise create canonical parent lineage and a scoped child item with duplicate-check evidence.`
38
+
39
+ ### Prompt: Prioritization Sweep
40
+
41
+ `Review open and in-progress items, normalize priority/status metadata, and leave append-only notes explaining why any prioritization changed.`
42
+
43
+ ### Prompt: Handoff Preparation
44
+
45
+ `Prepare handoff for <ID>: summarize state in comments, ensure linked files/tests/docs are complete, and release claim when ready.`
46
+
47
+ ## Deterministic Metadata Commands
48
+
49
+ ```bash
50
+ pm update <ID> --description "..." --ac "..." --estimate 60
51
+ pm update <ID> --deadline +2d --priority 1 --status open
52
+ pm comments <ID> "Decision log: <why this status/priority>"
53
+ pm notes <ID> --add "Context for next owner."
54
+ ```
55
+
56
+ ## Progressive Disclosure References
57
+
58
+ - [Triage and planning workflows](references/WORKFLOWS.md)
59
+ - [Operator prompt templates](references/PROMPTS.md)
@@ -0,0 +1,17 @@
1
+ # Operator Prompt Templates
2
+
3
+ ## Triage
4
+
5
+ `Find the canonical pm item for this request. Show duplicate-check commands, then either reuse and update the item or create parent lineage + child item with explicit rationale.`
6
+
7
+ ## Schedule
8
+
9
+ `Apply deterministic scheduling metadata (status, priority, estimate, deadline) to <ID> and leave a comment explaining the prioritization decision.`
10
+
11
+ ## Handoff
12
+
13
+ `Prepare <ID> for handoff: append current state, blockers, and next actions; release the claim when handoff is complete.`
14
+
15
+ ## Closure Readiness
16
+
17
+ `Validate whether <ID> is close-ready by checking acceptance criteria, linked files/tests/docs, and latest verification evidence.`
@@ -0,0 +1,35 @@
1
+ # User and Operator Workflows
2
+
3
+ ## Intake Workflow
4
+
5
+ 1. Query current context:
6
+
7
+ ```bash
8
+ pm context --limit 10
9
+ pm search "<keywords>" --limit 10
10
+ pm list-open --limit 20
11
+ pm list-in-progress --limit 20
12
+ ```
13
+
14
+ 2. If existing item matches, reuse and update it.
15
+ 3. If no match exists, create parent lineage then child item.
16
+ 4. Add duplicate-check evidence in comments at creation time.
17
+
18
+ ## Claim and Ownership Workflow
19
+
20
+ ```bash
21
+ pm claim <ID>
22
+ pm update <ID> --status in_progress --message "Start work"
23
+ pm comments <ID> "Owner update: <state>"
24
+ pm release <ID>
25
+ ```
26
+
27
+ ## Audit-Friendly Collaboration
28
+
29
+ For non-owner append-only collaboration:
30
+
31
+ ```bash
32
+ pm comments <ID> --add "audit comment" --allow-audit-comment
33
+ pm notes <ID> --add "audit note" --allow-audit-comment
34
+ pm update <ID> --dep "id=<id>,kind=related,author=<author>,created_at=now" --allow-audit-dep-update
35
+ ```
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "pm-cli",
3
+ "owner": {
4
+ "name": "unbrained",
5
+ "url": "https://github.com/unbraind/pm-cli"
6
+ },
7
+ "metadata": {
8
+ "description": "Official marketplace for pm CLI — native git-based project management for Claude Code and AI coding agents.",
9
+ "version": "1.0.0"
10
+ },
11
+ "plugins": [
12
+ {
13
+ "name": "pm-cli",
14
+ "source": "./plugins/pm-cli-claude",
15
+ "description": "Native pm CLI integration for Claude Code — 18 MCP tools, workflow skills, slash commands, session context injection, and a coordination subagent for git-based project management without leaving Claude Code.",
16
+ "version": "1.0.0",
17
+ "author": {
18
+ "name": "unbrained",
19
+ "url": "https://github.com/unbraind/pm-cli"
20
+ },
21
+ "homepage": "https://github.com/unbraind/pm-cli",
22
+ "repository": "https://github.com/unbraind/pm-cli",
23
+ "license": "MIT",
24
+ "keywords": [
25
+ "pm-cli",
26
+ "project-management",
27
+ "mcp",
28
+ "tasks",
29
+ "agents",
30
+ "workflows",
31
+ "git-native",
32
+ "task-tracker",
33
+ "ai"
34
+ ],
35
+ "category": "productivity"
36
+ }
37
+ ]
38
+ }
package/.pi/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # pm CLI Pi Package
2
+
3
+ This directory is the installable Pi package payload for `@unbrained/pm-cli`.
4
+
5
+ Install from npm after publish:
6
+
7
+ ```bash
8
+ pi install npm:@unbrained/pm-cli
9
+ ```
10
+
11
+ For local development from a checkout:
12
+
13
+ ```bash
14
+ pnpm build
15
+ pi install -l .
16
+ # or one-shot
17
+ pi -e .
18
+ ```
19
+
20
+ Resources exposed by `package.json`:
21
+
22
+ - `.pi/extensions/pm-cli/index.js` — native Pi extension registering the `pm` tool and slash commands.
23
+ - `.pi/skills/*` — Pi skills for native pm workflows and release validation.
24
+ - `.pi/prompts/*` — prompt templates for pm-tracked work.
25
+
26
+ The extension imports the built package from `dist/`, so run `pnpm build` before local install or before publishing.
@@ -0,0 +1,147 @@
1
+ import { PM_TOOL_ACTIONS } from "../../../dist/sdk/cli-contracts.js";
2
+ import { runNativePmAction } from "../../../dist/pi/native.js";
3
+
4
+ const PM_PI_TOOL_PARAMETERS_SCHEMA = {
5
+ type: "object",
6
+ additionalProperties: true,
7
+ required: ["action"],
8
+ description: "Parameters for the native pm Pi tool. Extra properties are forwarded to the selected pm action.",
9
+ properties: {
10
+ action: {
11
+ type: "string",
12
+ description: "pm action to execute, for example context, search, get, create, update, files, docs, test, validate, or close-task.",
13
+ },
14
+ id: { type: "string", description: "pm item id for item-scoped actions." },
15
+ text: { type: "string", description: "Text payload for comment-like actions or close reasons." },
16
+ title: { type: "string", description: "Title for create actions." },
17
+ description: { type: "string", description: "Description for create/update actions." },
18
+ query: { type: "string", description: "Search query text." },
19
+ limit: { type: "string", description: "Result limit. Numeric strings are accepted." },
20
+ author: { type: "string", description: "Explicit pm author for mutations." },
21
+ path: { type: "string", description: "pm data path override or linked file path, depending on action." },
22
+ scope: { type: "string", description: "Link scope such as project." },
23
+ command: { type: "string", description: "Linked test command or shell completion target, depending on action." },
24
+ options: {
25
+ type: "object",
26
+ additionalProperties: true,
27
+ description: "Advanced command options object forwarded to the selected pm action.",
28
+ },
29
+ },
30
+ };
31
+
32
+ function contentText(result) {
33
+ if (typeof result === "string") return result;
34
+ return JSON.stringify(result, null, 2);
35
+ }
36
+
37
+ function errorDetails(error) {
38
+ return {
39
+ message: error instanceof Error ? error.message : String(error),
40
+ code: typeof error?.exitCode === "number" ? error.exitCode : 1,
41
+ };
42
+ }
43
+
44
+ export function createPmToolDefinition() {
45
+ return {
46
+ name: "pm",
47
+ label: "pm",
48
+ description:
49
+ "Use pm natively from Pi without shelling out to the pm CLI. Supports pm project context, search, lifecycle mutations, links, tests, validation, extension management, templates, calendar, and audit workflows.",
50
+ promptSnippet: "Run native pm project-management operations without bash or the pm CLI.",
51
+ promptGuidelines: [
52
+ "Use the pm tool instead of bash pm commands for project-management operations when this tool is available.",
53
+ "Use pm action=context/list-open/list-in-progress/search before creating new work items.",
54
+ "For mutations, set author explicitly and link changed files/tests/docs through pm actions before closing work.",
55
+ ],
56
+ parameters: PM_PI_TOOL_PARAMETERS_SCHEMA,
57
+ async execute(_toolCallId, params, _signal, onUpdate, ctx) {
58
+ onUpdate?.({ content: [{ type: "text", text: `Running native pm action: ${params.action}` }] });
59
+ try {
60
+ const result = await runNativePmAction({ cwd: ctx?.cwd, ...params });
61
+ return {
62
+ content: [{ type: "text", text: contentText(result) }],
63
+ details: { ok: true, action: params.action, result, native: true },
64
+ };
65
+ } catch (error) {
66
+ const details = errorDetails(error);
67
+ throw new Error(`pm ${params.action ?? "action"} failed: ${details.message}`);
68
+ }
69
+ },
70
+ };
71
+ }
72
+
73
+ export function registerPmCommands(pi) {
74
+ pi.registerCommand("pm-context", {
75
+ description: "Show pm context snapshot using the native pm integration",
76
+ handler: async (args, ctx) => {
77
+ const limit = args?.trim() || "10";
78
+ const result = await runNativePmAction({ cwd: ctx.cwd, action: "context", limit, json: false });
79
+ ctx.ui.notify(contentText(result), "info");
80
+ },
81
+ });
82
+
83
+ pi.registerCommand("pm-start", {
84
+ description: "Start/claim a pm item: /pm-start <id>",
85
+ handler: async (args, ctx) => {
86
+ const id = args?.trim();
87
+ if (!id) return ctx.ui.notify("Usage: /pm-start <id>", "error");
88
+ const result = await runNativePmAction({ cwd: ctx.cwd, action: "start-task", id, author: "pi-agent" });
89
+ ctx.ui.notify(contentText(result), "success");
90
+ },
91
+ });
92
+
93
+ pi.registerCommand("pm-close", {
94
+ description: "Close and release a pm item: /pm-close <id> <reason>",
95
+ handler: async (args, ctx) => {
96
+ const [id, ...reasonParts] = (args ?? "").trim().split(/\s+/);
97
+ const reason = reasonParts.join(" ");
98
+ if (!id || !reason) return ctx.ui.notify("Usage: /pm-close <id> <reason>", "error");
99
+ const result = await runNativePmAction({ cwd: ctx.cwd, action: "close-task", id, text: reason, author: "pi-agent", validateClose: "warn" });
100
+ ctx.ui.notify(contentText(result), "success");
101
+ },
102
+ });
103
+
104
+ pi.registerCommand("pm-actions", {
105
+ description: "List native pm tool actions",
106
+ handler: async (_args, ctx) => {
107
+ ctx.ui.notify(PM_TOOL_ACTIONS.join(", "), "info");
108
+ },
109
+ });
110
+ }
111
+
112
+ function patchPmToolParametersInProviderPayload(payload) {
113
+ if (!payload || typeof payload !== "object" || !Array.isArray(payload.tools)) {
114
+ return undefined;
115
+ }
116
+ let changed = false;
117
+ const tools = payload.tools.map((tool) => {
118
+ if (!tool || typeof tool !== "object") {
119
+ return tool;
120
+ }
121
+ if (tool.name === "pm") {
122
+ const parameters = tool.parameters;
123
+ if (!parameters || parameters.type !== "object") {
124
+ changed = true;
125
+ return { ...tool, parameters: PM_PI_TOOL_PARAMETERS_SCHEMA };
126
+ }
127
+ }
128
+ if (tool.function?.name === "pm") {
129
+ const parameters = tool.function.parameters;
130
+ if (!parameters || parameters.type !== "object") {
131
+ changed = true;
132
+ return { ...tool, function: { ...tool.function, parameters: PM_PI_TOOL_PARAMETERS_SCHEMA } };
133
+ }
134
+ }
135
+ return tool;
136
+ });
137
+ return changed ? { ...payload, tools } : undefined;
138
+ }
139
+
140
+ export default function pmCliPiExtension(pi) {
141
+ pi.registerTool(createPmToolDefinition());
142
+ pi.on("before_provider_request", (event) => patchPmToolParametersInProviderPayload(event.payload));
143
+ registerPmCommands(pi);
144
+ pi.on("session_start", async (_event, ctx) => {
145
+ ctx.ui.setStatus?.("pm", "pm native");
146
+ });
147
+ }
@@ -0,0 +1,5 @@
1
+ ---
2
+ description: Start a pm-tracked implementation workflow using the native pm Pi tool.
3
+ ---
4
+
5
+ Use the native `pm` tool to orient, find an existing relevant item, claim it, link evidence, verify, and close/release only after acceptance criteria are met. Do not run `pm` via bash when the native tool is available.
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: pm-native
3
+ description: Native pm integration for Pi. Use when planning, claiming, updating, linking files/tests/docs, validating, or closing pm CLI work through the Pi pm tool instead of shelling out to the pm CLI.
4
+ license: MIT
5
+ compatibility: Pi coding-agent with the @unbrained/pm-cli Pi package installed.
6
+ metadata:
7
+ owner: unbrained
8
+ domain: pm-cli
9
+ scope: pi-native
10
+ ---
11
+
12
+ # pm Native for Pi
13
+
14
+ Use the `pm` tool for project-management operations. Do not run `pm ...` through bash when the native tool is available.
15
+
16
+ ## Required Loop
17
+
18
+ 1. Orient before creating work:
19
+ - `pm` action `context` with `limit: 10`
20
+ - `pm` action `search` with relevant keywords
21
+ - `pm` action `list-open` and `list-in-progress`
22
+ 2. Claim work with action `claim` or `start-task`.
23
+ 3. Mutate with explicit `author`.
24
+ 4. Link evidence:
25
+ - action `files` with `add`
26
+ - action `docs` with `add`
27
+ - action `test` with sandbox-safe commands
28
+ 5. Verify with action `test`, `validate`, and project test commands when appropriate.
29
+ 6. Close with action `close-task` or `close`, then release if needed.
30
+
31
+ ## Common Tool Calls
32
+
33
+ - Context: `{ "action": "context", "limit": 10 }`
34
+ - Search: `{ "action": "search", "query": "pi native extension", "limit": 10 }`
35
+ - Claim: `{ "action": "claim", "id": "pm-1234", "author": "pi-agent" }`
36
+ - Link file: `{ "action": "files", "id": "pm-1234", "add": ["path=src/file.ts,scope=project,note=implementation"], "author": "pi-agent" }`
37
+ - Add comment: `{ "action": "comments", "id": "pm-1234", "add": ["Evidence: build and tests passed"], "author": "pi-agent" }`
38
+ - Close: `{ "action": "close-task", "id": "pm-1234", "text": "All acceptance criteria met", "author": "pi-agent", "validateClose": "warn" }`
39
+
40
+ Use `pm guide` topics through action `guide` for deeper command docs.
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: pm-release
3
+ description: Release-readiness workflow for pm projects in Pi. Use when running final validation, coverage, package checks, GitHub checks, and closure evidence through the native pm integration.
4
+ license: MIT
5
+ compatibility: Pi coding-agent with the @unbrained/pm-cli Pi package installed.
6
+ metadata:
7
+ owner: unbrained
8
+ domain: pm-cli
9
+ scope: release
10
+ ---
11
+
12
+ # pm Release Workflow for Pi
13
+
14
+ Use the native `pm` tool for tracker state and linked evidence. Use shell only for non-pm project build/test commands.
15
+
16
+ ## Release Checklist
17
+
18
+ 1. `pm` action `context` with `depth: "standard"`.
19
+ 2. Run linked tests with `pm` action `test` and `run: true` for active work items.
20
+ 3. Run validation with `pm` action `validate`, usually `checkResolution: true`, `checkHistoryDrift: true`, and relevant file checks.
21
+ 4. Run package install/discovery smoke for Pi packages:
22
+ - local: `pi install -l .` or `pi -e .`
23
+ - npm after publish: `pi install npm:@unbrained/pm-cli`
24
+ 5. Use `gh` only to inspect GitHub checks after pushing.
25
+ 6. Add a `comments` evidence entry with exact command summaries.
26
+ 7. Close/release the pm item with `close-task` once acceptance criteria are met.
27
+
28
+ ## Evidence Format
29
+
30
+ Record:
31
+ - Changed package resources (`pi.extensions`, `pi.skills`, `pi.prompts`)
32
+ - Native pm tool smoke result
33
+ - Build/test/coverage result
34
+ - Pi install smoke result
35
+ - GitHub checks status
package/AGENTS.md CHANGED
@@ -7,7 +7,7 @@ This document defines how coding agents must use `pm` for planning, execution, a
7
7
  - Use `pm` as the system of record for project work.
8
8
  - Prefer deterministic, script-friendly command usage (`--json` when strict parsing is needed).
9
9
  - Default to TOON output when human + model readability and low token use are desired (calendar command is the intentional exception and defaults to markdown unless overridden).
10
- - Treat TOON as the canonical item-document format in this repo; `front_matter` is an internal model key, while TOON item metadata is stored as top-level object fields.
10
+ - Treat TOON as the canonical item-document format in this repo; item metadata is modeled as `metadata` internally and stored as top-level object fields in TOON.
11
11
  - Never make destructive item changes outside `pm` mutations.
12
12
  - Every mutation must produce a history entry.
13
13
 
package/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2026.5.10] - 2026-05-10
11
+
12
+ ### Changed
13
+ - Added top-level `ok` fields to `pm test --run --json` and `pm test-all --json` so agents can gate linked-test execution without parsing every result row.
14
+ - Capped and truncated semantic reindex embedding payloads for local Ollama providers, with adaptive timeout splitting, to avoid full-corpus reindex failures on large item bodies.
15
+
10
16
  ## [2026.5.6] - 2026-05-06
11
17
 
12
18
  ### Changed
package/PRD.md CHANGED
@@ -73,7 +73,7 @@ Existing trackers either rely on hosted backends, store state in non-diff-friend
73
73
 
74
74
  From `todos.ts`:
75
75
 
76
- - Item file format = JSON front-matter at file start, blank line, then markdown body.
76
+ - Legacy import format = JSON front-matter at file start, blank line, then markdown body.
77
77
  - ID normalization accepts optional `#` and optional prefix.
78
78
  - Claim/release is represented in-record (`assignee`).
79
79
  - Locking model:
@@ -246,16 +246,16 @@ Constraints:
246
246
 
247
247
  ## 7) Item File Format
248
248
 
249
- Each item is one document at `<type-folder>/<id>.toon` (default) or `<type-folder>/<id>.md` (JSON+Markdown alternative).
249
+ Each item is one TOON document at `<type-folder>/<id>.toon`. Legacy `<type-folder>/<id>.md` files are read only for migration.
250
250
 
251
251
  Format:
252
252
 
253
- 1. TOON root-object metadata keys (default) or JSON object metadata block (markdown format).
254
- 2. Optional `body` field / markdown body.
253
+ 1. TOON root-object metadata keys.
254
+ 2. Optional `body` field.
255
255
 
256
256
  ### 7.1 Canonical item-metadata schema
257
257
 
258
- `front_matter` remains the internal field name in TypeScript (`ItemDocument.front_matter`), but TOON documents store the same metadata as top-level keys.
258
+ `metadata` is the internal TypeScript field name (`ItemDocument.metadata`), and TOON documents store the same metadata as top-level keys.
259
259
 
260
260
  Required fields:
261
261
 
@@ -500,7 +500,7 @@ Canonical patch document shape:
500
500
 
501
501
  ```json
502
502
  {
503
- "front_matter": { "...": "..." },
503
+ "metadata": { "...": "..." },
504
504
  "body": "markdown text"
505
505
  }
506
506
  ```
@@ -517,7 +517,7 @@ Canonical patch document shape:
517
517
 
518
518
  1. Resolve item or matching history stream for ID and load full history.
519
519
  2. Replay patches from initial create through target version/timestamp.
520
- 3. Rebuild exact canonical document (`front_matter` + `body`).
520
+ 3. Rebuild exact canonical document (`metadata` + `body`).
521
521
  4. Write item atomically.
522
522
  5. Append a `restore` history event with patch from pre-restore state to restored state.
523
523
 
@@ -717,7 +717,7 @@ Help and error UX note:
717
717
  - `pm restore <ID> <TIMESTAMP|VERSION>`
718
718
  - `pm config <project|global> set definition-of-done --criterion <text>`
719
719
  - `pm config <project|global> get definition-of-done`
720
- - `pm config <project|global> set item-format --format toon|json_markdown`
720
+ - `pm config <project|global> set item-format --format toon`
721
721
  - `pm config <project|global> get item-format`
722
722
  - `pm config <project|global> set history-missing-stream-policy --policy auto_create|strict_error`
723
723
  - `pm config <project|global> get history-missing-stream-policy`
@@ -970,7 +970,7 @@ Contract compatibility policy keeps command names/flags/aliases stable while all
970
970
  | `pm calendar` / `pm cal` | `--view agenda|day|week|month`, `--date`, `--from`/`--to` (agenda), `--past`, `--full-period` (day/week/month only), list-like filters (`type`, `tag`, `priority`, `status`, `assignee`, `sprint`, `release`, `limit`), source controls (`--include`), and recurrence bounds (`--recurrence-lookahead-days`, `--recurrence-lookback-days`, `--occurrence-limit`) | `{ view, output_default, now, anchor, range, filters, summary, events, days }` where `range` includes period metadata (`period_start`, `period_end`, `full_period`), `summary` includes deterministic aggregate breakdown fields (`by_kind`, `by_type`, `by_status`, `recurring_events`), and markdown output includes rich event detail tokens by default |
971
971
  | `pm context` / `pm ctx` | `--date`, `--from`/`--to`, `--past`, list-like filters (`type`, `tag`, `priority`, `assignee`, `sprint`, `release`, `limit`), `--format` | `{ output_default, now, window, filters, summary, high_level, low_level, blocked_fallback, agenda }` (defaults to TOON unless `--format` or `--json` override) |
972
972
  | `pm beads import [--file <path\|->] [--preserve-source-ids]` | optional Beads JSONL source path (`.beads/issues.jsonl` auto-discovered first, then `issues.jsonl`; implicit `sync_base.jsonl` fallback is refused as unsafe; `--file -` requires piped stdin and fails fast on interactive TTY stdin) | `{ ok, source, imported, skipped, ids, warnings }` |
973
- | `pm todos import --folder <path?>` | optional todos markdown source folder (defaults to `.pi/todos`); preserves canonical optional `ItemFrontMatter` metadata when present and applies deterministic defaults for missing PM fields | `{ ok, folder, imported, skipped, ids, warnings }` |
973
+ | `pm todos import --folder <path?>` | optional todos markdown source folder (defaults to `.pi/todos`); preserves canonical optional `ItemMetadata` fields when present and applies deterministic defaults for missing PM fields | `{ ok, folder, imported, skipped, ids, warnings }` |
974
974
  | `pm todos export --folder <path?>` | optional todos markdown destination folder (defaults to `.pi/todos`) | `{ ok, folder, exported, ids, warnings }` |
975
975
  | `pm create ...` | required `--title` + `--description` + `--type`; strict mode is default (`--create-mode strict`) and enforces type-governed required options; progressive mode (`--create-mode progressive`) supports staged omission of type-level required create fields/repeatables; optional `--template` reusable defaults | `{ item, changed_fields, warnings }` |
976
976
  | `pm templates save <NAME> ...` | template name + create-compatible option payload (subset of create flags, including repeatable entries) | `{ name, path, template, saved_at }` |
@@ -986,7 +986,7 @@ Contract compatibility policy keeps command names/flags/aliases stable while all
986
986
  | `pm start-task <ID>` | lifecycle alias command (`claim` + `update --status in_progress`) with optional `--author`, `--message`, `--force` | `{ id, action: "start_task", claim, update }` |
987
987
  | `pm pause-task <ID>` | lifecycle alias command (`update --status open` + `release`) with optional `--author`, `--message`, `--force` | `{ id, action: "pause_task", update, release }` |
988
988
  | `pm close-task <ID> <TEXT>` | lifecycle alias command (`close` + `release`) with optional `--author`, `--message`, `--validate-close`, `--force` | `{ id, action: "close_task", close, release }` |
989
- | `pm comments <ID> [TEXT] --add/--limit` | id + optional positional comment text shorthand + comment text/limit (`--add` accepts plain text, `text=<value>`, markdown `text: <value>`, or stdin token `-`; positional `TEXT` is shorthand for `--add <TEXT>`; ambiguous CSV-like key fragments such as `text=hello,scope:project` remain plain text unless `text` is explicit); optional mutation metadata flags `--author`/`--message`/`--force`; additive ownership-safe audit path `--allow-audit-comment` for non-owner append-only comments | `{ id, comments, count }` |
989
+ | `pm comments <ID> [TEXT] --add/--stdin/--file/--limit` | id + optional positional comment text shorthand + comment text/limit (`--add` accepts plain text, `text=<value>`, markdown `text: <value>`, or stdin token `-`; `--stdin` reads multiline markdown from piped stdin; `--file <path>` reads multiline markdown from a file; positional `TEXT` is shorthand for `--add <TEXT>`; ambiguous CSV-like key fragments such as `text=hello,scope:project` remain plain text unless `text` is explicit); exactly one comment source must be provided per mutation invocation (`[TEXT]`, `--add`, `--stdin`, or `--file`); optional mutation metadata flags `--author`/`--message`/`--force`; additive ownership-safe audit path `--allow-audit-comment` for non-owner append-only comments | `{ id, comments, count }` |
990
990
  | `pm comments-audit` | optional governance filters (`--status`, `--type`, `--assignee`, `--assignee-filter`, `--parent`, `--tag`, `--sprint`, `--release`, `--priority`, `--limit-items`) plus latest/full-history export mode controls (`--latest`, `--full-history`; mutually exclusive, `--latest 0` allowed for summary-only rows) | `{ items, count, summary, filters, export, now, warnings? }` where `summary` includes additive totals/coverage/by-type metrics, `filters.full_history` and `export.mode` indicate latest vs full-history behavior, and `export.row_count` is deterministic (`0` in summary-only latest mode); in full-history mode, `rows[]` includes flat per-comment export entries for NDJSON-friendly downstream processing |
991
991
  | `pm notes <ID> [TEXT] --add/--limit` | id + optional positional note text shorthand + note text/limit (`--add` accepts plain text, `text=<value>`, markdown `text: <value>`, or stdin token `-`; positional `TEXT` is shorthand for `--add <TEXT>`; ambiguous CSV-like key fragments such as `text=hello,scope:project` remain plain text unless `text` is explicit); optional mutation metadata flags `--author`/`--message`/`--force`; additive ownership-safe audit path `--allow-audit-comment` for non-owner append-only notes | `{ id, notes, count }` |
992
992
  | `pm learnings <ID> [TEXT] --add/--limit` | id + optional positional learning text shorthand + learning text/limit (`--add` accepts plain text, `text=<value>`, markdown `text: <value>`, or stdin token `-`; positional `TEXT` is shorthand for `--add <TEXT>`; ambiguous CSV-like key fragments such as `text=hello,scope:project` remain plain text unless `text` is explicit); optional mutation metadata flags `--author`/`--message`/`--force`; additive ownership-safe audit path `--allow-audit-comment` for non-owner append-only learnings | `{ id, learnings, count }` |
@@ -1010,7 +1010,7 @@ Contract compatibility policy keeps command names/flags/aliases stable while all
1010
1010
 
1011
1011
  List command row projection:
1012
1012
 
1013
- - Default `list*` rows contain `ItemFrontMatter` fields only.
1013
+ - Default `list*` rows contain `ItemMetadata` fields only.
1014
1014
  - `--compact` projects deterministic compact fields (`id`, `title`, `status`, `type`, `priority`, `parent`, `updated_at`).
1015
1015
  - `--fields <csv>` projects caller-selected list fields.
1016
1016
  - With `--include-body`, each row additionally includes `body` and `filters.include_body` is `true` (`null` when omitted in JSON; omitted in sparse TOON).
@@ -1027,8 +1027,8 @@ Examples:
1027
1027
 
1028
1028
  - `list*`:
1029
1029
  - `{ items, count, filters, now }`
1030
- - default rows: `ItemFrontMatter`
1031
- - with `--include-body`: `ItemFrontMatter + body`
1030
+ - default rows: `ItemMetadata`
1031
+ - with `--include-body`: `ItemMetadata + body`
1032
1032
  - `search`:
1033
1033
  - `{ query, mode, items, count, filters, now }`
1034
1034
  - `get`:
@@ -1369,7 +1369,7 @@ Behavior:
1369
1369
  - `title -> title`
1370
1370
  - `body -> body`
1371
1371
  - imported IDs, including hierarchical suffixes such as `pm-legacy.1.2`, are preserved verbatim when provided in todos front matter
1372
- - canonical PM front-matter fields round-trip when present, including planning/workflow metadata (`definition_of_ready`, `order`, `goal`, `objective`, `value`, `impact`, `outcome`, `why_now`, `reviewer`, `risk`, `confidence`, `sprint`, `release`, `blocked_by`, `blocked_reason`, `unblock_note`) and issue metadata (`reporter`, `severity`, `environment`, `repro_steps`, `resolution`, `expected_result`, `actual_result`, `affected_version`, `fixed_version`, `component`, `regression`, `customer_impact`)
1372
+ - canonical PM metadata fields round-trip when present, including planning/workflow metadata (`definition_of_ready`, `order`, `goal`, `objective`, `value`, `impact`, `outcome`, `why_now`, `reviewer`, `risk`, `confidence`, `sprint`, `release`, `blocked_by`, `blocked_reason`, `unblock_note`) and issue metadata (`reporter`, `severity`, `environment`, `repro_steps`, `resolution`, `expected_result`, `actual_result`, `affected_version`, `fixed_version`, `component`, `regression`, `customer_impact`)
1373
1373
  - `confidence`, `risk`, and `severity` text aliases normalize deterministically (`med -> medium`)
1374
1374
  - Missing PM fields get deterministic defaults:
1375
1375
  - `description = ""`
@@ -1653,7 +1653,7 @@ Definition of Done:
1653
1653
  Checklist:
1654
1654
 
1655
1655
  - [x] Item schema model + validation
1656
- - [x] Parser/serializer for markdown item files
1656
+ - [x] Parser/serializer for TOON item files plus legacy markdown migration reader
1657
1657
  - [x] ID generation + normalization
1658
1658
  - [x] Lock acquire/release with TTL and conflict handling
1659
1659
  - [x] Core commands: init/create/get/update/append/claim/release/close/delete complete
@@ -1750,6 +1750,6 @@ Definition of Done:
1750
1750
  - unknown values retained in import metadata notes if lossy mapping is required
1751
1751
  - Hierarchical IDs from imports are preserved verbatim; new IDs generated by core default to flat `prefix-token`.
1752
1752
  - TOON formatting follows deterministic encoding with stable object keys; internal serializer may use a thin compatibility layer to ensure strict consistency across Node versions.
1753
- - For `create`, `before_hash` is computed from canonical empty document: `{ "front_matter": {}, "body": "" }`.
1753
+ - For `create`, `before_hash` is computed from the legacy-compatible canonical empty hash document: `{ "front_matter": {}, "body": "" }` (history patch payloads use `metadata` paths).
1754
1754
  - If create item write succeeds but history append fails, implementation MUST rollback the new item file before returning failure.
1755
1755
  - ID normalization helper behavior (`#` prefix, missing configured prefix, case-insensitive input) is required in core utilities even before all commands expose it.
package/README.md CHANGED
@@ -17,11 +17,22 @@
17
17
  | Settings, storage, search, and output | [Configuration](docs/CONFIGURATION.md) |
18
18
  | Safe test execution and linked tests | [Testing](docs/TESTING.md) |
19
19
  | Extension authoring | [Extensions](docs/EXTENSIONS.md) and [SDK](docs/SDK.md) |
20
+ | Pi native package | [Pi Package](docs/PI_PACKAGE.md) |
21
+ | Codex native integration | [Codex Plugin](docs/CODEX_PLUGIN.md) |
20
22
  | Maintainer release process (daily auto-release + local parity) | [Releasing](docs/RELEASING.md) |
21
23
  | Contributor internals | [Architecture](docs/ARCHITECTURE.md) |
22
24
 
23
25
  Full documentation starts at [docs/README.md](docs/README.md).
24
26
 
27
+ Use local in-CLI routing when an agent should stay inside terminal context:
28
+
29
+ ```bash
30
+ pm guide
31
+ pm guide quickstart
32
+ pm guide commands --depth standard
33
+ pm guide skills --depth deep --format markdown
34
+ ```
35
+
25
36
  ## Install
26
37
 
27
38
  `pm-cli` requires Node.js 20 or newer.
@@ -40,6 +51,14 @@ Project-local invocation also works:
40
51
  npx @unbrained/pm-cli --help
41
52
  ```
42
53
 
54
+ For Pi, install the native package integration after publish:
55
+
56
+ ```bash
57
+ pi install npm:@unbrained/pm-cli
58
+ ```
59
+
60
+ This registers a native `pm` tool, Pi skills, and prompt templates without requiring Pi to run the `pm` shell command.
61
+
43
62
  ## 60 Second Example
44
63
 
45
64
  ```bash
@@ -78,6 +97,8 @@ pm list-in-progress --limit 20
78
97
 
79
98
  If no relevant item exists, create a parent lineage before child work, claim the child item, link changed files/docs/tests, and leave evidence comments before closing. The full workflow is in the [Agent Guide](docs/AGENT_GUIDE.md).
80
99
 
100
+ For token-aware local routing, use `pm guide workflows` and then drill into related topics (`commands`, `skills`, `release`) only when needed.
101
+
81
102
  ## Release Automation
82
103
 
83
104
  - Daily release preparation runs in `.github/workflows/auto-release.yml`.
@@ -94,6 +115,7 @@ If no relevant item exists, create a parent lineage before child work, claim the
94
115
  - Built-in types include `Epic`, `Feature`, `Task`, `Chore`, `Issue`, `Decision`, `Event`, `Reminder`, `Milestone`, and `Meeting`.
95
116
  - Output defaults to sparse TOON. Use `--json` for strict parsing.
96
117
  - `pm contracts` is the machine-readable command and schema contract surface for agents.
118
+ - `pm guide` is the local progressive-disclosure docs and skills index for agents.
97
119
 
98
120
  ## Tracker References
99
121
 
@@ -105,10 +127,6 @@ This documentation refresh is tracked through `pm`:
105
127
 
106
128
  Docs should link to relevant `pm` items, and `pm` items should link back to changed docs through `pm docs`.
107
129
 
108
- ## Privacy Boundary
109
-
110
- Private production operations material is local-only, gitignored, and intentionally not linked from public documentation or packaged release files. Keep public docs focused on user-facing CLI behavior and safe contribution workflows.
111
-
112
130
  ## License
113
131
 
114
132
  [MIT](LICENSE)
@@ -28,11 +28,11 @@ export async function runClaim(id, force, global, options = {}) {
28
28
  message: options.message,
29
29
  force,
30
30
  mutate(document) {
31
- previousAssignee = document.front_matter.assignee ?? null;
32
- if (statusIsTerminal(document.front_matter.status, statusRegistry) && !force) {
33
- throw new PmCliError(`Cannot claim terminal item ${document.front_matter.id} without --force`, EXIT_CODE.CONFLICT);
31
+ previousAssignee = document.metadata.assignee ?? null;
32
+ if (statusIsTerminal(document.metadata.status, statusRegistry) && !force) {
33
+ throw new PmCliError(`Cannot claim terminal item ${document.metadata.id} without --force`, EXIT_CODE.CONFLICT);
34
34
  }
35
- document.front_matter.assignee = author;
35
+ document.metadata.assignee = author;
36
36
  return { changedFields: ["assignee"] };
37
37
  },
38
38
  });
@@ -63,11 +63,11 @@ export async function runRelease(id, force, global, options = {}) {
63
63
  force,
64
64
  bypassAssigneeConflict: Boolean(options.allowAuditRelease),
65
65
  mutate(document) {
66
- previousAssignee = document.front_matter.assignee ?? null;
66
+ previousAssignee = document.metadata.assignee ?? null;
67
67
  if (!previousAssignee) {
68
68
  return { changedFields: [] };
69
69
  }
70
- delete document.front_matter.assignee;
70
+ delete document.metadata.assignee;
71
71
  return { changedFields: ["assignee"] };
72
72
  },
73
73
  });