@unbrained/pm-cli 2026.5.6 → 2026.5.11

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 (268) 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 +35 -0
  22. package/.pi/agents/pm-triage-agent.md +19 -0
  23. package/.pi/agents/pm-verification-agent.md +21 -0
  24. package/.pi/chains/pm-native-delivery.chain.md +11 -0
  25. package/.pi/extensions/pm-cli/index.js +387 -0
  26. package/.pi/prompts/pm-workflow.md +5 -0
  27. package/.pi/skills/pm-native/SKILL.md +44 -0
  28. package/.pi/skills/pm-release/SKILL.md +35 -0
  29. package/AGENTS.md +1 -1
  30. package/CHANGELOG.md +13 -0
  31. package/PRD.md +16 -16
  32. package/README.md +30 -4
  33. package/dist/cli/argv-utils.d.ts +5 -0
  34. package/dist/cli/argv-utils.js +34 -0
  35. package/dist/cli/argv-utils.js.map +1 -0
  36. package/dist/cli/bootstrap-args.d.ts +15 -0
  37. package/dist/cli/bootstrap-args.js +211 -0
  38. package/dist/cli/bootstrap-args.js.map +1 -1
  39. package/dist/cli/commander-usage.js +109 -3
  40. package/dist/cli/commander-usage.js.map +1 -1
  41. package/dist/cli/commands/claim.js +6 -6
  42. package/dist/cli/commands/claim.js.map +1 -1
  43. package/dist/cli/commands/close.js +9 -9
  44. package/dist/cli/commands/close.js.map +1 -1
  45. package/dist/cli/commands/comments.d.ts +2 -0
  46. package/dist/cli/commands/comments.js +57 -8
  47. package/dist/cli/commands/comments.js.map +1 -1
  48. package/dist/cli/commands/completion.js +40 -7
  49. package/dist/cli/commands/completion.js.map +1 -1
  50. package/dist/cli/commands/config.js +6 -3
  51. package/dist/cli/commands/config.js.map +1 -1
  52. package/dist/cli/commands/contracts.d.ts +19 -0
  53. package/dist/cli/commands/contracts.js +36 -1
  54. package/dist/cli/commands/contracts.js.map +1 -1
  55. package/dist/cli/commands/create.d.ts +2 -2
  56. package/dist/cli/commands/create.js +116 -55
  57. package/dist/cli/commands/create.js.map +1 -1
  58. package/dist/cli/commands/docs.js +13 -6
  59. package/dist/cli/commands/docs.js.map +1 -1
  60. package/dist/cli/commands/extension.d.ts +3 -1
  61. package/dist/cli/commands/extension.js +174 -2
  62. package/dist/cli/commands/extension.js.map +1 -1
  63. package/dist/cli/commands/files.js +19 -12
  64. package/dist/cli/commands/files.js.map +1 -1
  65. package/dist/cli/commands/get.js +5 -5
  66. package/dist/cli/commands/get.js.map +1 -1
  67. package/dist/cli/commands/guide.d.ts +55 -0
  68. package/dist/cli/commands/guide.js +260 -0
  69. package/dist/cli/commands/guide.js.map +1 -0
  70. package/dist/cli/commands/health.js +1 -1
  71. package/dist/cli/commands/health.js.map +1 -1
  72. package/dist/cli/commands/history.js +30 -10
  73. package/dist/cli/commands/history.js.map +1 -1
  74. package/dist/cli/commands/index.d.ts +1 -0
  75. package/dist/cli/commands/index.js +1 -0
  76. package/dist/cli/commands/index.js.map +1 -1
  77. package/dist/cli/commands/init.d.ts +2 -0
  78. package/dist/cli/commands/init.js +21 -1
  79. package/dist/cli/commands/init.js.map +1 -1
  80. package/dist/cli/commands/learnings.js +3 -3
  81. package/dist/cli/commands/learnings.js.map +1 -1
  82. package/dist/cli/commands/metadata-normalizers.d.ts +4 -0
  83. package/dist/cli/commands/metadata-normalizers.js +37 -0
  84. package/dist/cli/commands/metadata-normalizers.js.map +1 -0
  85. package/dist/cli/commands/notes.js +3 -3
  86. package/dist/cli/commands/notes.js.map +1 -1
  87. package/dist/cli/commands/reindex.js +180 -156
  88. package/dist/cli/commands/reindex.js.map +1 -1
  89. package/dist/cli/commands/restore.d.ts +2 -2
  90. package/dist/cli/commands/restore.js +44 -24
  91. package/dist/cli/commands/restore.js.map +1 -1
  92. package/dist/cli/commands/search.d.ts +2 -0
  93. package/dist/cli/commands/search.js +45 -26
  94. package/dist/cli/commands/search.js.map +1 -1
  95. package/dist/cli/commands/test-all.d.ts +2 -0
  96. package/dist/cli/commands/test-all.js +2 -0
  97. package/dist/cli/commands/test-all.js.map +1 -1
  98. package/dist/cli/commands/test.d.ts +1 -0
  99. package/dist/cli/commands/test.js +13 -5
  100. package/dist/cli/commands/test.js.map +1 -1
  101. package/dist/cli/commands/update.js +188 -157
  102. package/dist/cli/commands/update.js.map +1 -1
  103. package/dist/cli/commands/validate.js +1 -1
  104. package/dist/cli/commands/validate.js.map +1 -1
  105. package/dist/cli/error-guidance.d.ts +9 -1
  106. package/dist/cli/error-guidance.js +147 -6
  107. package/dist/cli/error-guidance.js.map +1 -1
  108. package/dist/cli/guide-topics.d.ts +25 -0
  109. package/dist/cli/guide-topics.js +283 -0
  110. package/dist/cli/guide-topics.js.map +1 -0
  111. package/dist/cli/help-content.js +25 -1
  112. package/dist/cli/help-content.js.map +1 -1
  113. package/dist/cli/help-json-payload.js +11 -1
  114. package/dist/cli/help-json-payload.js.map +1 -1
  115. package/dist/cli/main.js +69 -6
  116. package/dist/cli/main.js.map +1 -1
  117. package/dist/cli/register-list-query.js +38 -1
  118. package/dist/cli/register-list-query.js.map +1 -1
  119. package/dist/cli/register-mutation.js +17 -4
  120. package/dist/cli/register-mutation.js.map +1 -1
  121. package/dist/cli/register-setup.js +15 -1
  122. package/dist/cli/register-setup.js.map +1 -1
  123. package/dist/cli/telemetry-flush.d.ts +2 -0
  124. package/dist/cli/telemetry-flush.js +4 -0
  125. package/dist/cli/telemetry-flush.js.map +1 -0
  126. package/dist/cli.js +1 -2
  127. package/dist/cli.js.map +1 -1
  128. package/dist/core/extensions/extension-types.d.ts +72 -0
  129. package/dist/core/extensions/extension-types.js +24 -0
  130. package/dist/core/extensions/extension-types.js.map +1 -1
  131. package/dist/core/extensions/loader.d.ts +1 -0
  132. package/dist/core/extensions/loader.js +766 -7
  133. package/dist/core/extensions/loader.js.map +1 -1
  134. package/dist/core/history/history.js +32 -11
  135. package/dist/core/history/history.js.map +1 -1
  136. package/dist/core/item/item-format.d.ts +2 -2
  137. package/dist/core/item/item-format.js +16 -16
  138. package/dist/core/item/item-format.js.map +1 -1
  139. package/dist/core/lock/lock.js +2 -0
  140. package/dist/core/lock/lock.js.map +1 -1
  141. package/dist/core/schema/runtime-field-filters.js +1 -1
  142. package/dist/core/schema/runtime-field-filters.js.map +1 -1
  143. package/dist/core/schema/runtime-field-values.js +2 -2
  144. package/dist/core/schema/runtime-field-values.js.map +1 -1
  145. package/dist/core/schema/runtime-schema.d.ts +1 -1
  146. package/dist/core/schema/runtime-schema.js +3 -3
  147. package/dist/core/schema/runtime-schema.js.map +1 -1
  148. package/dist/core/search/cache.js +7 -21
  149. package/dist/core/search/cache.js.map +1 -1
  150. package/dist/core/search/corpus.d.ts +13 -0
  151. package/dist/core/search/corpus.js +74 -0
  152. package/dist/core/search/corpus.js.map +1 -0
  153. package/dist/core/search/embedding-batches.js +90 -30
  154. package/dist/core/search/embedding-batches.js.map +1 -1
  155. package/dist/core/sentry/instrument.d.ts +18 -1
  156. package/dist/core/sentry/instrument.js +128 -12
  157. package/dist/core/sentry/instrument.js.map +1 -1
  158. package/dist/core/shared/constants.d.ts +1 -1
  159. package/dist/core/shared/constants.js +21 -1
  160. package/dist/core/shared/constants.js.map +1 -1
  161. package/dist/core/shared/errors.d.ts +8 -0
  162. package/dist/core/shared/errors.js.map +1 -1
  163. package/dist/core/shared/levenshtein.d.ts +1 -0
  164. package/dist/core/shared/levenshtein.js +37 -0
  165. package/dist/core/shared/levenshtein.js.map +1 -0
  166. package/dist/core/store/front-matter-cache.d.ts +1 -1
  167. package/dist/core/store/front-matter-cache.js +13 -13
  168. package/dist/core/store/front-matter-cache.js.map +1 -1
  169. package/dist/core/store/item-format-migration.js +5 -2
  170. package/dist/core/store/item-format-migration.js.map +1 -1
  171. package/dist/core/store/item-store.js +16 -15
  172. package/dist/core/store/item-store.js.map +1 -1
  173. package/dist/core/store/paths.js +35 -2
  174. package/dist/core/store/paths.js.map +1 -1
  175. package/dist/core/store/settings.js +216 -2
  176. package/dist/core/store/settings.js.map +1 -1
  177. package/dist/core/telemetry/runtime.d.ts +1 -0
  178. package/dist/core/telemetry/runtime.js +102 -3
  179. package/dist/core/telemetry/runtime.js.map +1 -1
  180. package/dist/core/test/item-test-run-tracking.js +2 -2
  181. package/dist/core/test/item-test-run-tracking.js.map +1 -1
  182. package/dist/mcp/server.d.ts +2 -0
  183. package/dist/mcp/server.js +407 -0
  184. package/dist/mcp/server.js.map +1 -0
  185. package/dist/pi/native.d.ts +5 -0
  186. package/dist/pi/native.js +236 -0
  187. package/dist/pi/native.js.map +1 -0
  188. package/dist/sdk/cli-contracts.d.ts +24 -2
  189. package/dist/sdk/cli-contracts.js +317 -2
  190. package/dist/sdk/cli-contracts.js.map +1 -1
  191. package/dist/sdk/index.d.ts +12 -1
  192. package/dist/sdk/index.js +8 -1
  193. package/dist/sdk/index.js.map +1 -1
  194. package/dist/types.d.ts +51 -2
  195. package/dist/types.js.map +1 -1
  196. package/docs/AGENT_GUIDE.md +15 -0
  197. package/docs/ARCHITECTURE.md +2 -2
  198. package/docs/CLAUDE_CODE_PLUGIN.md +225 -0
  199. package/docs/CODEX_PLUGIN.md +33 -0
  200. package/docs/COMMANDS.md +6 -2
  201. package/docs/CONFIGURATION.md +2 -8
  202. package/docs/EXTENSIONS.md +688 -0
  203. package/docs/MIGRATION_CLI_SIMPLIFICATION.md +64 -0
  204. package/docs/PI_PACKAGE.md +141 -0
  205. package/docs/QUICKSTART.md +1 -0
  206. package/docs/README.md +30 -1
  207. package/docs/RELEASING.md +4 -2
  208. package/docs/SDK.md +444 -2
  209. package/docs/examples/ci/github-actions-pm-extension-gate.yml +53 -0
  210. package/docs/examples/ci/gitlab-ci-pm-extension-gate.yml +41 -0
  211. package/docs/examples/ci/jenkins-pm-extension-gate.Jenkinsfile +45 -0
  212. package/docs/examples/policy-restricted-extension/README.md +74 -0
  213. package/docs/examples/policy-restricted-extension/index.js +21 -0
  214. package/docs/examples/policy-restricted-extension/manifest.json +21 -0
  215. package/docs/examples/policy-restricted-extension/package.json +8 -0
  216. package/docs/examples/sdk-app-embedding/README.md +39 -0
  217. package/docs/examples/sdk-app-embedding/package.json +9 -0
  218. package/docs/examples/sdk-app-embedding/run-embedded-pm.mjs +61 -0
  219. package/docs/examples/sdk-contract-consumer/README.md +57 -0
  220. package/docs/examples/sdk-contract-consumer/inspect-contracts.mjs +47 -0
  221. package/docs/examples/sdk-contract-consumer/package.json +10 -0
  222. package/docs/examples/starter-extension/README.md +57 -42
  223. package/docs/examples/starter-extension/manifest.json +15 -0
  224. package/marketplace.json +34 -0
  225. package/package.json +38 -4
  226. package/plugins/pm-cli-claude/.claude-plugin/plugin.json +23 -0
  227. package/plugins/pm-cli-claude/.mcp.json +12 -0
  228. package/plugins/pm-cli-claude/README.md +225 -0
  229. package/plugins/pm-cli-claude/agents/pm-coordinator.md +48 -0
  230. package/plugins/pm-cli-claude/agents/pm-delivery-chain.md +88 -0
  231. package/plugins/pm-cli-claude/agents/pm-triage-agent.md +83 -0
  232. package/plugins/pm-cli-claude/agents/pm-verification-agent.md +88 -0
  233. package/plugins/pm-cli-claude/commands/pm-audit.md +39 -0
  234. package/plugins/pm-cli-claude/commands/pm-calendar.md +41 -0
  235. package/plugins/pm-cli-claude/commands/pm-close-task.md +20 -0
  236. package/plugins/pm-cli-claude/commands/pm-developer.md +38 -0
  237. package/plugins/pm-cli-claude/commands/pm-init.md +44 -0
  238. package/plugins/pm-cli-claude/commands/pm-list.md +39 -0
  239. package/plugins/pm-cli-claude/commands/pm-new.md +36 -0
  240. package/plugins/pm-cli-claude/commands/pm-planner.md +51 -0
  241. package/plugins/pm-cli-claude/commands/pm-release.md +41 -0
  242. package/plugins/pm-cli-claude/commands/pm-search.md +21 -0
  243. package/plugins/pm-cli-claude/commands/pm-start-task.md +27 -0
  244. package/plugins/pm-cli-claude/commands/pm-status.md +15 -0
  245. package/plugins/pm-cli-claude/commands/pm-triage.md +35 -0
  246. package/plugins/pm-cli-claude/commands/pm-workflow.md +49 -0
  247. package/plugins/pm-cli-claude/hooks/hooks.json +17 -0
  248. package/plugins/pm-cli-claude/hooks/session-start.mjs +120 -0
  249. package/plugins/pm-cli-claude/scripts/pm-mcp-server.mjs +60 -0
  250. package/plugins/pm-cli-claude/skills/pm-audit/SKILL.md +88 -0
  251. package/plugins/pm-cli-claude/skills/pm-developer/SKILL.md +116 -0
  252. package/plugins/pm-cli-claude/skills/pm-planner/SKILL.md +118 -0
  253. package/plugins/pm-cli-claude/skills/pm-release/SKILL.md +83 -0
  254. package/plugins/pm-cli-claude/skills/pm-workflow/SKILL.md +148 -0
  255. package/plugins/pm-cli-codex/.codex-plugin/plugin.json +45 -0
  256. package/plugins/pm-cli-codex/.mcp.json +14 -0
  257. package/plugins/pm-cli-codex/README.md +30 -0
  258. package/plugins/pm-cli-codex/assets/pm-cli-small.svg +4 -0
  259. package/plugins/pm-cli-codex/commands/pm-audit.md +8 -0
  260. package/plugins/pm-cli-codex/commands/pm-close-task.md +9 -0
  261. package/plugins/pm-cli-codex/commands/pm-start-task.md +9 -0
  262. package/plugins/pm-cli-codex/scripts/pm-mcp-server.mjs +54 -0
  263. package/plugins/pm-cli-codex/skills/pm-auditor/SKILL.md +21 -0
  264. package/plugins/pm-cli-codex/skills/pm-auditor/agents/openai.yaml +6 -0
  265. package/plugins/pm-cli-codex/skills/pm-native/SKILL.md +57 -0
  266. package/plugins/pm-cli-codex/skills/pm-native/agents/openai.yaml +6 -0
  267. package/plugins/pm-cli-codex/skills/pm-release/SKILL.md +19 -0
  268. package/plugins/pm-cli-codex/skills/pm-release/agents/openai.yaml +6 -0
@@ -1,3 +1,4 @@
1
+ import { readFile } from "node:fs/promises";
1
2
  import { pathExists } from "../../core/fs/fs-utils.js";
2
3
  import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
3
4
  import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
@@ -43,6 +44,53 @@ function parseCommentTextInput(raw) {
43
44
  return trimmed;
44
45
  }
45
46
  }
47
+ function isErrnoError(error) {
48
+ return typeof error === "object" && error !== null && "code" in error;
49
+ }
50
+ async function resolveCommentInput(options, stdinResolver) {
51
+ const hasAdd = options.add !== undefined;
52
+ const hasStdin = options.stdin === true;
53
+ const hasFile = typeof options.file === "string";
54
+ const sourceCount = Number(hasAdd) + Number(hasStdin) + Number(hasFile);
55
+ if (sourceCount === 0) {
56
+ return { mode: "list" };
57
+ }
58
+ if (sourceCount > 1) {
59
+ throw new PmCliError("Specify comment text using only one input source: --add, --stdin, or --file", EXIT_CODE.USAGE);
60
+ }
61
+ if (hasAdd) {
62
+ const addInput = await stdinResolver.resolveValue(options.add, "--add");
63
+ return {
64
+ mode: "add",
65
+ value: addInput ?? "",
66
+ };
67
+ }
68
+ if (hasStdin) {
69
+ const stdinInput = await stdinResolver.resolveValue("-", "--stdin");
70
+ return {
71
+ mode: "stdin",
72
+ value: stdinInput ?? "",
73
+ };
74
+ }
75
+ const filePath = options.file?.trim() ?? "";
76
+ if (!filePath) {
77
+ throw new PmCliError("--file path cannot be empty", EXIT_CODE.USAGE);
78
+ }
79
+ try {
80
+ const fileInput = await readFile(filePath, "utf8");
81
+ return {
82
+ mode: "file",
83
+ value: fileInput,
84
+ };
85
+ }
86
+ catch (error) {
87
+ if (isErrnoError(error) && error.code === "ENOENT") {
88
+ throw new PmCliError(`--file path not found: ${filePath}`, EXIT_CODE.USAGE);
89
+ }
90
+ const detail = error instanceof Error ? error.message : String(error);
91
+ throw new PmCliError(`Failed to read --file path "${filePath}": ${detail}`, EXIT_CODE.USAGE);
92
+ }
93
+ }
46
94
  export async function runComments(id, options, global) {
47
95
  const stdinResolver = createStdinTokenResolver();
48
96
  const pmRoot = resolvePmRoot(process.cwd(), global.path);
@@ -52,13 +100,14 @@ export async function runComments(id, options, global) {
52
100
  const settings = await readSettings(pmRoot);
53
101
  const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());
54
102
  const limit = parseLimit(options.limit);
55
- if (options.add === undefined) {
103
+ const commentInput = await resolveCommentInput(options, stdinResolver);
104
+ if (commentInput.mode === "list") {
56
105
  const located = await locateItem(pmRoot, id, settings.id_prefix, settings.item_format, typeRegistry.type_to_folder);
57
106
  if (!located) {
58
107
  throw new PmCliError(`Item ${id} not found`, EXIT_CODE.NOT_FOUND);
59
108
  }
60
109
  const loaded = await readLocatedItem(located, { schema: settings.schema });
61
- const comments = limitComments(loaded.document.front_matter.comments ?? [], limit);
110
+ const comments = limitComments(loaded.document.metadata.comments ?? [], limit);
62
111
  return {
63
112
  id: located.id,
64
113
  comments,
@@ -66,10 +115,10 @@ export async function runComments(id, options, global) {
66
115
  };
67
116
  }
68
117
  const author = resolveAuthor(options.author, settings.author_default);
69
- const addInput = await stdinResolver.resolveValue(options.add, "--add");
70
- const text = parseCommentTextInput(addInput ?? "");
71
- if (!text) {
72
- throw new PmCliError("--add text cannot be empty", EXIT_CODE.USAGE);
118
+ const text = commentInput.mode === "add" ? parseCommentTextInput(commentInput.value ?? "") : (commentInput.value ?? "");
119
+ if (!text.trim()) {
120
+ const inputFlag = commentInput.mode === "add" ? "--add" : commentInput.mode === "stdin" ? "--stdin" : "--file";
121
+ throw new PmCliError(`${inputFlag} text cannot be empty`, EXIT_CODE.USAGE);
73
122
  }
74
123
  let result;
75
124
  try {
@@ -83,13 +132,13 @@ export async function runComments(id, options, global) {
83
132
  force: options.force,
84
133
  bypassAssigneeConflict: Boolean(options.allowAuditComment),
85
134
  mutate(document) {
86
- const comments = document.front_matter.comments ?? [];
135
+ const comments = document.metadata.comments ?? [];
87
136
  comments.push({
88
137
  created_at: nowIso(),
89
138
  author,
90
139
  text,
91
140
  });
92
- document.front_matter.comments = comments;
141
+ document.metadata.comments = comments;
93
142
  return { changedFields: ["comments"] };
94
143
  },
95
144
  });
@@ -1 +1 @@
1
- {"version":3,"file":"comments.js","sourceRoot":"/","sources":["cli/commands/comments.ts"],"names":[],"mappings":"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","sourcesContent":["import { pathExists } from \"../../core/fs/fs-utils.js\";\nimport { getActiveExtensionRegistrations } from \"../../core/extensions/index.js\";\nimport { resolveItemTypeRegistry } from \"../../core/item/type-registry.js\";\nimport { EXIT_CODE } from \"../../core/shared/constants.js\";\nimport type { GlobalOptions } from \"../../core/shared/command-types.js\";\nimport { PmCliError } from \"../../core/shared/errors.js\";\nimport { nowIso } from \"../../core/shared/time.js\";\nimport { createStdinTokenResolver, parseCsvKv } from \"../../core/item/parse.js\";\nimport { locateItem, mutateItem, readLocatedItem } from \"../../core/store/item-store.js\";\nimport { getSettingsPath, resolvePmRoot } from \"../../core/store/paths.js\";\nimport { readSettings } from \"../../core/store/settings.js\";\nimport { parseLimit } from \"../shared-parsers.js\";\nimport type { Comment } from \"../../types/index.js\";\n\nexport interface CommentsCommandOptions {\n add?: string;\n limit?: string;\n author?: string;\n message?: string;\n force?: boolean;\n allowAuditComment?: boolean;\n}\n\nexport interface CommentsResult {\n id: string;\n comments: Comment[];\n count: number;\n}\n\nfunction resolveAuthor(candidate: string | undefined, fallback: string): string {\n const resolved = candidate ?? process.env.PM_AUTHOR ?? fallback;\n const trimmed = resolved.trim();\n return trimmed || \"unknown\";\n}\n\nfunction limitComments(values: Comment[], limit: number | undefined): Comment[] {\n if (limit === undefined) return values;\n if (limit === 0) return [];\n return values.slice(Math.max(0, values.length - limit));\n}\n\nfunction parseCommentTextInput(raw: string): string {\n const trimmed = raw.trim();\n if (!trimmed) {\n return \"\";\n }\n const looksStructured = /^(?:[-*+]\\s*)?text\\s*[:=]/im.test(trimmed) || trimmed.startsWith(\"```\");\n if (!looksStructured) {\n return trimmed;\n }\n try {\n const kv = parseCsvKv(trimmed, \"--add\");\n const keys = Object.keys(kv).map((key) => key.trim().toLowerCase());\n if (keys.some((key) => key !== \"text\")) {\n return trimmed;\n }\n const text = kv.text?.trim();\n return text || trimmed;\n } catch {\n return trimmed;\n }\n}\n\nexport async function runComments(id: string, options: CommentsCommandOptions, global: GlobalOptions): Promise<CommentsResult> {\n const stdinResolver = createStdinTokenResolver();\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n if (!(await pathExists(getSettingsPath(pmRoot)))) {\n throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);\n }\n const settings = await readSettings(pmRoot);\n const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());\n const limit = parseLimit(options.limit);\n\n if (options.add === undefined) {\n const located = await locateItem(pmRoot, id, settings.id_prefix, settings.item_format, typeRegistry.type_to_folder);\n if (!located) {\n throw new PmCliError(`Item ${id} not found`, EXIT_CODE.NOT_FOUND);\n }\n const loaded = await readLocatedItem(located, { schema: settings.schema });\n const comments = limitComments(loaded.document.front_matter.comments ?? [], limit);\n return {\n id: located.id,\n comments,\n count: comments.length,\n };\n }\n\n const author = resolveAuthor(options.author, settings.author_default);\n const addInput = await stdinResolver.resolveValue(options.add, \"--add\");\n const text = parseCommentTextInput(addInput ?? \"\");\n if (!text) {\n throw new PmCliError(\"--add text cannot be empty\", EXIT_CODE.USAGE);\n }\n\n let result: Awaited<ReturnType<typeof mutateItem>>;\n try {\n result = await mutateItem({\n pmRoot,\n settings,\n id,\n op: \"comment_add\",\n author,\n message: options.message,\n force: options.force,\n bypassAssigneeConflict: Boolean(options.allowAuditComment),\n mutate(document) {\n const comments = document.front_matter.comments ?? [];\n comments.push({\n created_at: nowIso(),\n author,\n text,\n });\n document.front_matter.comments = comments;\n return { changedFields: [\"comments\"] };\n },\n });\n } catch (error: unknown) {\n if (\n error instanceof PmCliError &&\n error.exitCode === EXIT_CODE.CONFLICT &&\n error.message.includes(\"is assigned to\") &&\n error.message.includes(\"Use --force to override\")\n ) {\n throw new PmCliError(error.message, error.exitCode, {\n code: \"ownership_conflict\",\n required:\n \"For append-only comment audits on another owner's item, prefer --allow-audit-comment before considering --force.\",\n examples: ['pm comments pm-a1b2 --add \"audit note\" --author \"reviewer\" --allow-audit-comment'],\n nextSteps: [\n \"Retry with --allow-audit-comment for append-only audits that do not mutate item metadata beyond comments.\",\n \"Use --force only when an ownership override is explicitly approved.\",\n ],\n });\n }\n throw error;\n }\n\n const comments = limitComments(result.item.comments as Comment[], limit);\n return {\n id: result.item.id,\n comments,\n count: comments.length,\n };\n}\n"]}
1
+ {"version":3,"file":"comments.js","sourceRoot":"/","sources":["cli/commands/comments.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { pathExists } from \"../../core/fs/fs-utils.js\";\nimport { getActiveExtensionRegistrations } from \"../../core/extensions/index.js\";\nimport { resolveItemTypeRegistry } from \"../../core/item/type-registry.js\";\nimport { EXIT_CODE } from \"../../core/shared/constants.js\";\nimport type { GlobalOptions } from \"../../core/shared/command-types.js\";\nimport { PmCliError } from \"../../core/shared/errors.js\";\nimport { nowIso } from \"../../core/shared/time.js\";\nimport { createStdinTokenResolver, parseCsvKv } from \"../../core/item/parse.js\";\nimport { locateItem, mutateItem, readLocatedItem } from \"../../core/store/item-store.js\";\nimport { getSettingsPath, resolvePmRoot } from \"../../core/store/paths.js\";\nimport { readSettings } from \"../../core/store/settings.js\";\nimport { parseLimit } from \"../shared-parsers.js\";\nimport type { Comment } from \"../../types/index.js\";\n\nexport interface CommentsCommandOptions {\n add?: string;\n stdin?: boolean;\n file?: string;\n limit?: string;\n author?: string;\n message?: string;\n force?: boolean;\n allowAuditComment?: boolean;\n}\n\nexport interface CommentsResult {\n id: string;\n comments: Comment[];\n count: number;\n}\n\nfunction resolveAuthor(candidate: string | undefined, fallback: string): string {\n const resolved = candidate ?? process.env.PM_AUTHOR ?? fallback;\n const trimmed = resolved.trim();\n return trimmed || \"unknown\";\n}\n\nfunction limitComments(values: Comment[], limit: number | undefined): Comment[] {\n if (limit === undefined) return values;\n if (limit === 0) return [];\n return values.slice(Math.max(0, values.length - limit));\n}\n\nfunction parseCommentTextInput(raw: string): string {\n const trimmed = raw.trim();\n if (!trimmed) {\n return \"\";\n }\n const looksStructured = /^(?:[-*+]\\s*)?text\\s*[:=]/im.test(trimmed) || trimmed.startsWith(\"```\");\n if (!looksStructured) {\n return trimmed;\n }\n try {\n const kv = parseCsvKv(trimmed, \"--add\");\n const keys = Object.keys(kv).map((key) => key.trim().toLowerCase());\n if (keys.some((key) => key !== \"text\")) {\n return trimmed;\n }\n const text = kv.text?.trim();\n return text || trimmed;\n } catch {\n return trimmed;\n }\n}\n\ninterface ResolvedCommentInput {\n mode: \"list\" | \"add\" | \"stdin\" | \"file\";\n value?: string;\n}\n\nfunction isErrnoError(error: unknown): error is NodeJS.ErrnoException {\n return typeof error === \"object\" && error !== null && \"code\" in error;\n}\n\nasync function resolveCommentInput(\n options: CommentsCommandOptions,\n stdinResolver: ReturnType<typeof createStdinTokenResolver>,\n): Promise<ResolvedCommentInput> {\n const hasAdd = options.add !== undefined;\n const hasStdin = options.stdin === true;\n const hasFile = typeof options.file === \"string\";\n const sourceCount = Number(hasAdd) + Number(hasStdin) + Number(hasFile);\n if (sourceCount === 0) {\n return { mode: \"list\" };\n }\n if (sourceCount > 1) {\n throw new PmCliError(\"Specify comment text using only one input source: --add, --stdin, or --file\", EXIT_CODE.USAGE);\n }\n if (hasAdd) {\n const addInput = await stdinResolver.resolveValue(options.add, \"--add\");\n return {\n mode: \"add\",\n value: addInput ?? \"\",\n };\n }\n if (hasStdin) {\n const stdinInput = await stdinResolver.resolveValue(\"-\", \"--stdin\");\n return {\n mode: \"stdin\",\n value: stdinInput ?? \"\",\n };\n }\n const filePath = options.file?.trim() ?? \"\";\n if (!filePath) {\n throw new PmCliError(\"--file path cannot be empty\", EXIT_CODE.USAGE);\n }\n try {\n const fileInput = await readFile(filePath, \"utf8\");\n return {\n mode: \"file\",\n value: fileInput,\n };\n } catch (error: unknown) {\n if (isErrnoError(error) && error.code === \"ENOENT\") {\n throw new PmCliError(`--file path not found: ${filePath}`, EXIT_CODE.USAGE);\n }\n const detail = error instanceof Error ? error.message : String(error);\n throw new PmCliError(`Failed to read --file path \"${filePath}\": ${detail}`, EXIT_CODE.USAGE);\n }\n}\n\nexport async function runComments(id: string, options: CommentsCommandOptions, global: GlobalOptions): Promise<CommentsResult> {\n const stdinResolver = createStdinTokenResolver();\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n if (!(await pathExists(getSettingsPath(pmRoot)))) {\n throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);\n }\n const settings = await readSettings(pmRoot);\n const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());\n const limit = parseLimit(options.limit);\n const commentInput = await resolveCommentInput(options, stdinResolver);\n\n if (commentInput.mode === \"list\") {\n const located = await locateItem(pmRoot, id, settings.id_prefix, settings.item_format, typeRegistry.type_to_folder);\n if (!located) {\n throw new PmCliError(`Item ${id} not found`, EXIT_CODE.NOT_FOUND);\n }\n const loaded = await readLocatedItem(located, { schema: settings.schema });\n const comments = limitComments(loaded.document.metadata.comments ?? [], limit);\n return {\n id: located.id,\n comments,\n count: comments.length,\n };\n }\n\n const author = resolveAuthor(options.author, settings.author_default);\n const text = commentInput.mode === \"add\" ? parseCommentTextInput(commentInput.value ?? \"\") : (commentInput.value ?? \"\");\n if (!text.trim()) {\n const inputFlag = commentInput.mode === \"add\" ? \"--add\" : commentInput.mode === \"stdin\" ? \"--stdin\" : \"--file\";\n throw new PmCliError(`${inputFlag} text cannot be empty`, EXIT_CODE.USAGE);\n }\n\n let result: Awaited<ReturnType<typeof mutateItem>>;\n try {\n result = await mutateItem({\n pmRoot,\n settings,\n id,\n op: \"comment_add\",\n author,\n message: options.message,\n force: options.force,\n bypassAssigneeConflict: Boolean(options.allowAuditComment),\n mutate(document) {\n const comments = document.metadata.comments ?? [];\n comments.push({\n created_at: nowIso(),\n author,\n text,\n });\n document.metadata.comments = comments;\n return { changedFields: [\"comments\"] };\n },\n });\n } catch (error: unknown) {\n if (\n error instanceof PmCliError &&\n error.exitCode === EXIT_CODE.CONFLICT &&\n error.message.includes(\"is assigned to\") &&\n error.message.includes(\"Use --force to override\")\n ) {\n throw new PmCliError(error.message, error.exitCode, {\n code: \"ownership_conflict\",\n required:\n \"For append-only comment audits on another owner's item, prefer --allow-audit-comment before considering --force.\",\n examples: ['pm comments pm-a1b2 --add \"audit note\" --author \"reviewer\" --allow-audit-comment'],\n nextSteps: [\n \"Retry with --allow-audit-comment for append-only audits that do not mutate item metadata beyond comments.\",\n \"Use --force only when an ownership override is explicitly approved.\",\n ],\n });\n }\n throw error;\n }\n\n const comments = limitComments(result.item.comments as Comment[], limit);\n return {\n id: result.item.id,\n comments,\n count: comments.length,\n };\n}\n"]}
@@ -1,7 +1,8 @@
1
1
  import { EXIT_CODE } from "../../core/shared/constants.js";
2
2
  import { PmCliError } from "../../core/shared/errors.js";
3
- import { ACTIVITY_FLAG_CONTRACTS, APPEND_FLAG_CONTRACTS, CALENDAR_FLAG_CONTRACTS, COMPLETION_FLAG_CONTRACTS, CONTRACTS_FLAG_CONTRACTS, CONTEXT_FLAG_CONTRACTS, CREATE_FLAG_CONTRACTS, DEPS_FLAG_CONTRACTS, GLOBAL_FLAG_CONTRACTS, HEALTH_FLAG_CONTRACTS, INIT_FLAG_CONTRACTS, LIST_FILTER_FLAG_CONTRACTS, NORMALIZE_FLAG_CONTRACTS, PM_CORE_COMMAND_NAMES, SEARCH_FLAG_CONTRACTS, UPDATE_FLAG_CONTRACTS, UPDATE_MANY_FLAG_CONTRACTS, toCompletionFlagString, } from "../../sdk/cli-contracts.js";
3
+ import { ACTIVITY_FLAG_CONTRACTS, APPEND_FLAG_CONTRACTS, CALENDAR_FLAG_CONTRACTS, COMPLETION_FLAG_CONTRACTS, CONTRACTS_FLAG_CONTRACTS, CONTEXT_FLAG_CONTRACTS, CREATE_FLAG_CONTRACTS, DEPS_FLAG_CONTRACTS, GUIDE_FLAG_CONTRACTS, GLOBAL_FLAG_CONTRACTS, HEALTH_FLAG_CONTRACTS, INIT_FLAG_CONTRACTS, LIST_FILTER_FLAG_CONTRACTS, NORMALIZE_FLAG_CONTRACTS, PM_CORE_COMMAND_NAMES, SEARCH_FLAG_CONTRACTS, UPDATE_FLAG_CONTRACTS, UPDATE_MANY_FLAG_CONTRACTS, toCompletionFlagString, } from "../../sdk/cli-contracts.js";
4
4
  import { BUILTIN_ITEM_TYPE_VALUES } from "../../types/index.js";
5
+ import { listGuideTopicIds } from "../guide-topics.js";
5
6
  const VALID_SHELLS = ["bash", "zsh", "fish"];
6
7
  const DEFAULT_ITEM_TYPES = [...BUILTIN_ITEM_TYPE_VALUES];
7
8
  const DEFAULT_STATUS_VALUES = ["draft", "open", "in_progress", "blocked", "closed", "canceled"];
@@ -16,12 +17,14 @@ const ACTIVITY_FLAGS = toCompletionFlagString(ACTIVITY_FLAG_CONTRACTS);
16
17
  const CALENDAR_FLAGS = toCompletionFlagString(CALENDAR_FLAG_CONTRACTS);
17
18
  const CONTEXT_FLAGS = toCompletionFlagString(CONTEXT_FLAG_CONTRACTS);
18
19
  const DEPS_FLAGS = toCompletionFlagString(DEPS_FLAG_CONTRACTS);
20
+ const GUIDE_FLAGS = toCompletionFlagString(GUIDE_FLAG_CONTRACTS);
19
21
  const SEARCH_FLAGS = toCompletionFlagString(SEARCH_FLAG_CONTRACTS);
20
22
  const HEALTH_FLAGS = toCompletionFlagString(HEALTH_FLAG_CONTRACTS);
21
23
  const INIT_FLAGS = toCompletionFlagString(INIT_FLAG_CONTRACTS);
22
24
  const CONTRACTS_FLAGS = toCompletionFlagString(CONTRACTS_FLAG_CONTRACTS);
23
25
  const COMPLETION_FLAGS = toCompletionFlagString(COMPLETION_FLAG_CONTRACTS);
24
26
  const COMPLETION_SHELL_CHOICES = `${COMPLETION_FLAGS} bash zsh fish`;
27
+ const GUIDE_TOPIC_CHOICES = joinCompletionValues(listGuideTopicIds());
25
28
  const MUTATION_FLAGS = "--author --message --force --json --quiet --path --no-extensions --no-pager --profile --help";
26
29
  const CLOSE_MUTATION_FLAGS = "--author --message --validate-close --force --json --quiet --path --no-extensions --no-pager --profile --help";
27
30
  const RELEASE_MUTATION_FLAGS = "--allow-audit-release --author --message --force --json --quiet --path --no-extensions --no-pager --profile --help";
@@ -135,6 +138,9 @@ export function generateBashScript(itemTypes = DEFAULT_ITEM_TYPES, tags = [], ea
135
138
  " context|ctx)",
136
139
  ` COMPREPLY=(${compgen(contextFlags)})`,
137
140
  " ;;",
141
+ " guide)",
142
+ ` COMPREPLY=(${compgen(`${GUIDE_FLAGS} ${GUIDE_TOPIC_CHOICES}`)})`,
143
+ " ;;",
138
144
  " search)",
139
145
  ` COMPREPLY=(${compgen(searchFlags)})`,
140
146
  " ;;",
@@ -148,10 +154,10 @@ export function generateBashScript(itemTypes = DEFAULT_ITEM_TYPES, tags = [], ea
148
154
  ` COMPREPLY=(${compgen("--criterion --clear-criteria --format --policy --json --quiet --path --no-extensions --no-pager --profile --help")})`,
149
155
  " ;;",
150
156
  " extension)",
151
- ` COMPREPLY=(${compgen("init scaffold install uninstall explore manage doctor adopt adopt-all activate deactivate --init --scaffold --install --uninstall --explore --manage --doctor --adopt --adopt-all --activate --deactivate --project --local --global --gh --github --ref --detail --trace --runtime-probe --fix-managed-state --strict-exit --fail-on-warn --json --quiet --path --no-extensions --no-pager --profile --help")})`,
157
+ ` COMPREPLY=(${compgen("init scaffold install uninstall explore manage reload doctor adopt adopt-all activate deactivate --init --scaffold --install --uninstall --explore --manage --reload --watch --doctor --adopt --adopt-all --activate --deactivate --project --local --global --gh --github --ref --detail --trace --runtime-probe --fix-managed-state --strict-exit --fail-on-warn --json --quiet --path --no-extensions --no-pager --profile --help")})`,
152
158
  " ;;",
153
159
  " comments)",
154
- ` COMPREPLY=(${compgen("--add --limit --author --message --allow-audit-comment --force --json --quiet --path --no-extensions --no-pager --profile --help")})`,
160
+ ` COMPREPLY=(${compgen("--add --stdin --file --limit --author --message --allow-audit-comment --force --json --quiet --path --no-extensions --no-pager --profile --help")})`,
155
161
  " ;;",
156
162
  " comments-audit)",
157
163
  ` COMPREPLY=(${compgen("--status --type --tag --priority --parent --sprint --release --assignee --assignee-filter --limit-items --limit --full-history --latest --json --quiet --path --no-extensions --no-pager --profile --help")})`,
@@ -229,6 +235,7 @@ export function generateBashScript(itemTypes = DEFAULT_ITEM_TYPES, tags = [], ea
229
235
  export function generateZshScript(itemTypes = DEFAULT_ITEM_TYPES, tags = [], eagerTagExpansion = false) {
230
236
  const cmds = ALL_COMMANDS.map((c) => `'${c}'`).join(" ");
231
237
  const typeChoices = itemTypes.join(" ");
238
+ const guideTopicChoices = GUIDE_TOPIC_CHOICES;
232
239
  const tagChoices = joinCompletionValues(tags);
233
240
  const useEagerTagExpansion = eagerTagExpansion || tags.length > 0;
234
241
  const zshTagChoices = useEagerTagExpansion ? tagChoices : '${(f)"$(_pm_tag_choices)"}';
@@ -270,6 +277,7 @@ _pm_commands() {
270
277
  'list-canceled:List canceled items with optional filters'
271
278
  'aggregate:Aggregate grouped item counts for governance queries'
272
279
  'dedupe-audit:Audit potential duplicate items and emit merge suggestions'
280
+ 'guide:Browse local progressive-disclosure guides'
273
281
  'calendar:Show calendar views for deadlines and reminders'
274
282
  'cal:Alias for calendar'
275
283
  'context:Show a token-efficient project context snapshot'
@@ -615,6 +623,15 @@ _pm() {
615
623
  '--json[Output JSON]' \\
616
624
  '--quiet[Suppress stdout]'
617
625
  ;;
626
+ guide)
627
+ _arguments \\
628
+ '1:topic:(${guideTopicChoices})' \\
629
+ '--list[Show guide topic index]' \\
630
+ '--format[Output override]:(markdown toon json)' \\
631
+ '--depth[Guide detail depth]:(brief standard deep)' \\
632
+ '--json[Output JSON]' \\
633
+ '--quiet[Suppress stdout]'
634
+ ;;
618
635
  search)
619
636
  _arguments \\
620
637
  '--mode[Search mode]:(keyword semantic hybrid)' \\
@@ -675,6 +692,8 @@ _pm() {
675
692
  comments)
676
693
  _arguments \\
677
694
  '--add[Add one entry (plain text, text=<value>, markdown pairs, or - for stdin)]:text' \\
695
+ '--stdin[Read comment text from stdin (supports multiline markdown)]' \\
696
+ '--file[Read comment text from file (supports multiline markdown)]:path' \\
678
697
  '--limit[Return only latest n entries]:number' \\
679
698
  '--author[Entry author (falls back to PM_AUTHOR/settings)]:author' \\
680
699
  '--message[History message]:message' \\
@@ -791,7 +810,7 @@ _pm() {
791
810
  _arguments \\
792
811
  '--criterion[Criteria value for definition-of-done metadata-required-fields or lifecycle pattern keys (repeatable for set)]:criterion' \\
793
812
  '--clear-criteria[Clear config criteria-list key values]' \\
794
- '--format[Item format for item-format key]:format:(toon json_markdown)' \\
813
+ '--format[Item format for item-format key]:format:(toon)' \\
795
814
  '--policy[Policy value for supported policy keys]:policy' \\
796
815
  '--json[Output JSON]' \\
797
816
  '--quiet[Suppress stdout]'
@@ -890,13 +909,15 @@ _pm() {
890
909
  ;;
891
910
  extension)
892
911
  _arguments \\
893
- '1:extension_action:(init scaffold install uninstall explore manage doctor adopt adopt-all activate deactivate)' \\
912
+ '1:extension_action:(init scaffold install uninstall explore manage reload doctor adopt adopt-all activate deactivate)' \\
894
913
  '--init[Generate a starter extension scaffold at target path]' \\
895
914
  '--scaffold[Alias for --init]' \\
896
915
  '--install[Install extension from local path or GitHub source]' \\
897
916
  '--uninstall[Uninstall extension by name]' \\
898
917
  '--explore[List discovered extensions for selected scope]' \\
899
918
  '--manage[List managed extensions with update metadata]' \\
919
+ '--reload[Reload extensions with cache-busted module imports]' \\
920
+ '--watch[Enable watch mode with --reload]' \\
900
921
  '--doctor[Run consolidated extension diagnostics (summary/deep)]' \\
901
922
  '--adopt[Adopt an unmanaged extension into managed metadata]' \\
902
923
  '--adopt-all[Adopt all unmanaged extensions into managed metadata]' \\
@@ -939,6 +960,7 @@ export function generateFishScript(itemTypes = DEFAULT_ITEM_TYPES, tags = [], ea
939
960
  const listCmds = ALL_COMMANDS.filter((command) => command === "list" || command.startsWith("list-")).join(" ");
940
961
  const noSubcommandList = ALL_COMMANDS.join(" ");
941
962
  const typeChoices = itemTypes.join(" ");
963
+ const guideTopicChoices = GUIDE_TOPIC_CHOICES;
942
964
  const tagChoices = joinCompletionValues(tags);
943
965
  const useEagerTagExpansion = eagerTagExpansion || tags.length > 0;
944
966
  const fishTagChoices = useEagerTagExpansion ? `'${tagChoices}'` : "'(__pm_tag_choices)'";
@@ -1004,6 +1026,7 @@ complete -c pm -n __pm_no_subcommand -a list-closed -d 'List closed items with
1004
1026
  complete -c pm -n __pm_no_subcommand -a list-canceled -d 'List canceled items with optional filters'
1005
1027
  complete -c pm -n __pm_no_subcommand -a aggregate -d 'Aggregate grouped item counts for governance queries'
1006
1028
  complete -c pm -n __pm_no_subcommand -a dedupe-audit -d 'Audit potential duplicate items and emit merge suggestions'
1029
+ complete -c pm -n __pm_no_subcommand -a guide -d 'Browse local progressive-disclosure guides'
1007
1030
  complete -c pm -n __pm_no_subcommand -a calendar -d 'Show deadline/reminder calendar views'
1008
1031
  complete -c pm -n __pm_no_subcommand -a cal -d 'Alias for calendar'
1009
1032
  complete -c pm -n __pm_no_subcommand -a context -d 'Show a token-efficient project context snapshot'
@@ -1308,6 +1331,12 @@ complete -c pm -n '__fish_seen_subcommand_from context ctx' -l release -d 'Fil
1308
1331
  complete -c pm -n '__fish_seen_subcommand_from context ctx' -l limit -d 'Limit focus and agenda rows per section' -r
1309
1332
  complete -c pm -n '__fish_seen_subcommand_from context ctx' -l format -d 'Output override' -r -a 'markdown toon json'
1310
1333
 
1334
+ # guide flags
1335
+ complete -c pm -n '__fish_seen_subcommand_from guide' -l list -d 'Show guide topic index'
1336
+ complete -c pm -n '__fish_seen_subcommand_from guide' -l format -d 'Output override' -r -a 'markdown toon json'
1337
+ complete -c pm -n '__fish_seen_subcommand_from guide' -l depth -d 'Guide detail depth' -r -a 'brief standard deep'
1338
+ complete -c pm -n '__fish_seen_subcommand_from guide' -a '${guideTopicChoices}' -d 'Guide topic'
1339
+
1311
1340
  # reindex flags
1312
1341
  complete -c pm -n '__fish_seen_subcommand_from reindex' -l mode -d 'Reindex mode' -r -a 'keyword semantic hybrid'
1313
1342
  complete -c pm -n '__fish_seen_subcommand_from reindex' -l progress -d 'Emit progress updates to stderr'
@@ -1337,6 +1366,8 @@ complete -c pm -n '__fish_seen_subcommand_from deps' -l summary -d 'Return count
1337
1366
 
1338
1367
  # comments / notes / learnings flags
1339
1368
  complete -c pm -n '__fish_seen_subcommand_from comments notes learnings' -l add -d 'Add one entry (text=<value> or plain text)' -r
1369
+ complete -c pm -n '__fish_seen_subcommand_from comments' -l stdin -d 'Read comment text from stdin (supports multiline markdown)'
1370
+ complete -c pm -n '__fish_seen_subcommand_from comments' -l file -d 'Read comment text from file (supports multiline markdown)' -r
1340
1371
  complete -c pm -n '__fish_seen_subcommand_from comments notes learnings' -l limit -d 'Return only latest n entries' -r
1341
1372
  complete -c pm -n '__fish_seen_subcommand_from comments notes learnings' -l author -d 'Entry author' -r
1342
1373
  complete -c pm -n '__fish_seen_subcommand_from comments notes learnings' -l message -d 'History message' -r
@@ -1430,7 +1461,7 @@ complete -c pm -n '__fish_seen_subcommand_from validate' -l check-command-refere
1430
1461
  complete -c pm -n '__fish_seen_subcommand_from init' -l preset -d 'Governance preset for new setups' -r -a 'minimal default strict'
1431
1462
  complete -c pm -n '__fish_seen_subcommand_from config' -l criterion -d 'Criteria value for definition-of-done metadata-required-fields or lifecycle pattern keys (repeatable for set)' -r
1432
1463
  complete -c pm -n '__fish_seen_subcommand_from config' -l clear-criteria -d 'Clear config criteria-list key values'
1433
- complete -c pm -n '__fish_seen_subcommand_from config' -l format -d 'Item format for item-format key' -r -a 'toon json_markdown'
1464
+ complete -c pm -n '__fish_seen_subcommand_from config' -l format -d 'Item format for item-format key' -r -a 'toon'
1434
1465
  complete -c pm -n '__fish_seen_subcommand_from config' -l policy -d 'Policy value for supported policy keys' -r
1435
1466
  complete -c pm -n '__fish_seen_subcommand_from health' -l strict-directories -d 'Treat optional item-type directories as required failures'
1436
1467
  complete -c pm -n '__fish_seen_subcommand_from health' -l check-only -d 'Run read-only health diagnostics without refreshing vectors'
@@ -1461,13 +1492,15 @@ complete -c pm -n '__fish_seen_subcommand_from completion' -a 'bash zsh fish' -d
1461
1492
  complete -c pm -n '__fish_seen_subcommand_from templates' -a 'save list show' -d 'Templates command'
1462
1493
 
1463
1494
  # extension lifecycle flags
1464
- complete -c pm -n '__fish_seen_subcommand_from extension' -a 'init scaffold install uninstall explore manage doctor adopt adopt-all activate deactivate' -d 'Extension action subcommand'
1495
+ complete -c pm -n '__fish_seen_subcommand_from extension' -a 'init scaffold install uninstall explore manage reload doctor adopt adopt-all activate deactivate' -d 'Extension action subcommand'
1465
1496
  complete -c pm -n '__fish_seen_subcommand_from extension' -l init -d 'Generate starter extension scaffold'
1466
1497
  complete -c pm -n '__fish_seen_subcommand_from extension' -l scaffold -d 'Alias for --init'
1467
1498
  complete -c pm -n '__fish_seen_subcommand_from extension' -l install -d 'Install extension from local path or GitHub source'
1468
1499
  complete -c pm -n '__fish_seen_subcommand_from extension' -l uninstall -d 'Uninstall extension by name'
1469
1500
  complete -c pm -n '__fish_seen_subcommand_from extension' -l explore -d 'List discovered extensions for selected scope'
1470
1501
  complete -c pm -n '__fish_seen_subcommand_from extension' -l manage -d 'List managed extensions with update metadata'
1502
+ complete -c pm -n '__fish_seen_subcommand_from extension' -l reload -d 'Reload extensions with cache-busted module imports'
1503
+ complete -c pm -n '__fish_seen_subcommand_from extension' -l watch -d 'Enable watch mode with --reload'
1471
1504
  complete -c pm -n '__fish_seen_subcommand_from extension' -l doctor -d 'Run consolidated extension diagnostics'
1472
1505
  complete -c pm -n '__fish_seen_subcommand_from extension' -l adopt -d 'Adopt an unmanaged extension into managed metadata'
1473
1506
  complete -c pm -n '__fish_seen_subcommand_from extension' -l adopt-all -d 'Adopt all unmanaged extensions into managed metadata'