@unbrained/pm-cli 2026.8.25 → 2026.8.27

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 (206) hide show
  1. package/.agents/skills/HARNESS_COMPATIBILITY.md +32 -0
  2. package/.agents/skills/README.md +47 -0
  3. package/.agents/skills/pm-developer/SKILL.md +117 -0
  4. package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +49 -0
  5. package/.agents/skills/pm-developer/references/GRAPH_AND_RELATIONSHIPS.md +91 -0
  6. package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +72 -0
  7. package/.agents/skills/pm-developer/references/PROMPTS.md +17 -0
  8. package/.agents/skills/pm-developer/references/SCRIPTING_COMPOSITION.md +82 -0
  9. package/.agents/skills/pm-developer/references/TOKEN_BUDGETS.md +85 -0
  10. package/.agents/skills/pm-extensions/SKILL.md +106 -0
  11. package/.agents/skills/pm-extensions/references/AUTHORING.md +95 -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 +107 -0
  15. package/.agents/skills/pm-sdk/references/DOMAIN_MODELING.md +78 -0
  16. package/.agents/skills/pm-sdk/references/INTEGRATION_CHECKLIST.md +31 -0
  17. package/.agents/skills/pm-sdk/references/PROMPTS.md +13 -0
  18. package/.agents/skills/pm-sdk/references/SURFACE_MAP.md +82 -0
  19. package/.agents/skills/pm-user/SKILL.md +111 -0
  20. package/.agents/skills/pm-user/references/BACKLOG_SHAPING.md +105 -0
  21. package/.agents/skills/pm-user/references/PROMPTS.md +17 -0
  22. package/.agents/skills/pm-user/references/WORKFLOWS.md +35 -0
  23. package/.claude-plugin/marketplace.json +2 -2
  24. package/CHANGELOG.md +58 -3
  25. package/README.md +8 -5
  26. package/dist/cli/commander-usage.js +11 -7
  27. package/dist/cli/error-guidance.js +3 -3
  28. package/dist/cli/help-content.d.ts +2 -0
  29. package/dist/cli/help-content.js +53 -17
  30. package/dist/cli/help-json-payload.d.ts +8 -2
  31. package/dist/cli/help-json-payload.js +46 -12
  32. package/dist/cli/main.js +52 -74
  33. package/dist/cli/register-annotations.js +27 -21
  34. package/dist/cli/register-setup.js +98 -57
  35. package/dist/cli-bundle/bundle-manifest.json +156 -156
  36. package/dist/cli-bundle/chunks/chunk-3OO3W6FW.js +202 -0
  37. package/dist/cli-bundle/chunks/chunk-52EKTW6V.js +3 -0
  38. package/dist/cli-bundle/chunks/{chunk-QLUORNIB.js → chunk-CVBBGWW5.js} +62 -44
  39. package/dist/cli-bundle/chunks/chunk-MFNTKMTI.js +13 -0
  40. package/dist/cli-bundle/chunks/chunk-OS27HHBN.js +35 -0
  41. package/dist/cli-bundle/chunks/chunk-QTO7USTH.js +2 -0
  42. package/dist/cli-bundle/chunks/{chunk-5I5RWIJC.js → chunk-R4ETAOJC.js} +2 -2
  43. package/dist/cli-bundle/chunks/{chunk-OWHNAR2B.js → chunk-SH6P7FXI.js} +2 -2
  44. package/dist/cli-bundle/chunks/chunk-SHMDY36D.js +8 -0
  45. package/dist/cli-bundle/chunks/{chunk-244MI4GS.js → chunk-SKXLJIEK.js} +60 -60
  46. package/dist/cli-bundle/chunks/chunk-TNX6HC54.js +3 -0
  47. package/dist/cli-bundle/chunks/{register-list-query-XVN2ZLI7.js → register-list-query-EUWM6VII.js} +2 -2
  48. package/dist/cli-bundle/chunks/{register-mutation-QCKAEGIJ.js → register-mutation-FD4HSAVU.js} +4 -4
  49. package/dist/cli-bundle/chunks/{register-operations-SDEAXE7E.js → register-operations-HRMNFEC3.js} +2 -2
  50. package/dist/cli-bundle/chunks/register-setup-33GNICLX.js +2 -0
  51. package/dist/cli-bundle/focused-chunks/{chunk-IBZZZGK3.js → chunk-2AGZ5BRT.js} +2 -2
  52. package/dist/cli-bundle/focused-chunks/chunk-4BR5UU52.js +50 -0
  53. package/dist/cli-bundle/focused-chunks/{chunk-OHIHZ7HS.js → chunk-6GCRSLPG.js} +2 -2
  54. package/dist/cli-bundle/focused-chunks/{chunk-OVJL6NZE.js → chunk-AD6ULRAF.js} +4 -4
  55. package/dist/cli-bundle/focused-chunks/{chunk-7YCDTCBC.js → chunk-AQ5IYEZZ.js} +2 -2
  56. package/dist/cli-bundle/focused-chunks/{chunk-YO3ZF3FI.js → chunk-EKX37ZHA.js} +2 -2
  57. package/dist/cli-bundle/focused-chunks/{chunk-N7W67YIG.js → chunk-FC2AXLB5.js} +2 -2
  58. package/dist/cli-bundle/focused-chunks/{chunk-H5JZEIQV.js → chunk-HC7ODMH3.js} +2 -2
  59. package/dist/cli-bundle/focused-chunks/{chunk-NOOZGIXP.js → chunk-HVQ22RC4.js} +2 -2
  60. package/dist/cli-bundle/focused-chunks/{chunk-A644DUFQ.js → chunk-MEASX544.js} +2 -2
  61. package/dist/cli-bundle/focused-chunks/{chunk-RAFKLNZX.js → chunk-MXTYGECH.js} +2 -2
  62. package/dist/cli-bundle/focused-chunks/{chunk-2UIWOP3O.js → chunk-SUBSWYW3.js} +2 -2
  63. package/dist/cli-bundle/focused-chunks/{chunk-VXWATRFL.js → chunk-XDPYBQCF.js} +9 -9
  64. package/dist/cli-bundle/focused-chunks/{chunk-XUQPEKRN.js → chunk-Y3JJXRVK.js} +2 -2
  65. package/dist/cli-bundle/focused-chunks/{chunk-GQR3WH3F.js → chunk-Y5A7SJJ7.js} +2 -2
  66. package/dist/cli-bundle/focused-chunks/chunk-YHWHX6YY.js +2 -0
  67. package/dist/cli-bundle/focused-chunks/{chunk-ONYQCALA.js → chunk-YVVZ3LQ6.js} +6 -6
  68. package/dist/cli-bundle/focused-chunks/chunk-Z2USIBR2.js +5 -0
  69. package/dist/cli-bundle/main.js +15 -14
  70. package/dist/cli-bundle/sdk-authoring.js +1 -1
  71. package/dist/cli-bundle/sdk-contracts.js +2 -2
  72. package/dist/cli-bundle/sdk-core.js +31 -31
  73. package/dist/cli-bundle/sdk-governance.js +1 -1
  74. package/dist/cli-bundle/sdk-graph.js +1 -1
  75. package/dist/cli-bundle/sdk-merge.js +31 -31
  76. package/dist/cli-bundle/sdk-query.js +1 -1
  77. package/dist/cli-bundle/sdk-runtime.js +1 -1
  78. package/dist/cli-bundle/sdk-testing.js +1 -1
  79. package/dist/cli-bundle/sdk.js +32 -6
  80. package/dist/core/extensions/manifest-schema.d.ts +20 -0
  81. package/dist/core/extensions/manifest-schema.js +28 -10
  82. package/dist/core/governance/issue-codes.d.ts +11 -2
  83. package/dist/core/governance/issue-codes.js +29 -10
  84. package/dist/core/item/item-format.js +3 -3
  85. package/dist/core/store/item-store.js +12 -5
  86. package/dist/mcp/http-server.d.ts +60 -0
  87. package/dist/mcp/http-server.js +451 -0
  88. package/dist/mcp/legacy-adapter.d.ts +50 -0
  89. package/dist/mcp/legacy-adapter.js +64 -0
  90. package/dist/mcp/server.d.ts +42 -9
  91. package/dist/mcp/server.js +572 -59
  92. package/dist/mcp/tool-definitions.d.ts +2 -0
  93. package/dist/mcp/tool-definitions.js +2 -2
  94. package/dist/sdk/agent/closed-domain-contracts.d.ts +1 -1
  95. package/dist/sdk/agent/closed-domain-contracts.js +24 -2
  96. package/dist/sdk/agent/refusal-closure-census.d.ts +6 -2
  97. package/dist/sdk/agent/refusal-closure-census.js +16 -8
  98. package/dist/sdk/agent-capability-contracts.js +6 -2
  99. package/dist/sdk/cli-bootstrap.js +3 -2
  100. package/dist/sdk/cli-contracts/command-aliases.js +15 -2
  101. package/dist/sdk/cli-contracts/enum-contracts.d.ts +4 -1
  102. package/dist/sdk/cli-contracts/enum-contracts.js +7 -2
  103. package/dist/sdk/cli-contracts/flag-contracts.js +9 -5
  104. package/dist/sdk/cli-contracts/grammar-contracts.d.ts +3 -3
  105. package/dist/sdk/cli-contracts/grammar-contracts.js +24 -17
  106. package/dist/sdk/cli-contracts/runtime-contracts.js +13 -11
  107. package/dist/sdk/cli-contracts/tool-schema.js +18 -15
  108. package/dist/sdk/cli-contracts.d.ts +1 -1
  109. package/dist/sdk/cli-contracts.js +3 -3
  110. package/dist/sdk/cli-program.js +3 -2
  111. package/dist/sdk/completion.js +40 -13
  112. package/dist/sdk/compose.d.ts +4 -1
  113. package/dist/sdk/compose.js +23 -36
  114. package/dist/sdk/extension/author-manifest.d.ts +22 -0
  115. package/dist/sdk/extension/author-manifest.js +93 -0
  116. package/dist/sdk/extension.js +6 -3
  117. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +20 -5
  118. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +18 -3
  119. package/dist/sdk/governance/health.js +7 -2
  120. package/dist/sdk/governance/upgrade.d.ts +2 -0
  121. package/dist/sdk/governance/upgrade.js +30 -8
  122. package/dist/sdk/governance/validate.js +8 -6
  123. package/dist/sdk/guide-topics.js +6 -6
  124. package/dist/sdk/index.d.ts +10 -2
  125. package/dist/sdk/index.js +11 -3
  126. package/dist/sdk/mcp/apps.d.ts +70 -0
  127. package/dist/sdk/mcp/apps.js +154 -0
  128. package/dist/sdk/mcp/authorization.d.ts +134 -0
  129. package/dist/sdk/mcp/authorization.js +405 -0
  130. package/dist/sdk/mcp/interactions.d.ts +118 -0
  131. package/dist/sdk/mcp/interactions.js +337 -0
  132. package/dist/sdk/mcp/protocol.d.ts +142 -0
  133. package/dist/sdk/mcp/protocol.js +174 -0
  134. package/dist/sdk/mcp/skills.d.ts +127 -0
  135. package/dist/sdk/mcp/skills.js +390 -0
  136. package/dist/sdk/mcp/subscriptions.d.ts +65 -0
  137. package/dist/sdk/mcp/subscriptions.js +212 -0
  138. package/dist/sdk/mcp/tasks.d.ts +107 -0
  139. package/dist/sdk/mcp/tasks.js +431 -0
  140. package/dist/sdk/mcp/transport.d.ts +30 -0
  141. package/dist/sdk/mcp/transport.js +261 -0
  142. package/dist/sdk/merge/receipts.d.ts +16 -0
  143. package/dist/sdk/merge/receipts.js +9 -8
  144. package/dist/sdk/read-output-contracts.js +16 -3
  145. package/dist/sdk/runtime-action-aliases.js +7 -3
  146. package/dist/sdk/runtime-input.js +12 -4
  147. package/dist/sdk/runtime-primitives.d.ts +2 -2
  148. package/dist/sdk/runtime-primitives.js +4 -4
  149. package/dist/sdk/test/execution.d.ts +6 -0
  150. package/dist/sdk/test/execution.js +32 -3
  151. package/docs/AGENT_PROVENANCE_ADR.md +6 -4
  152. package/docs/AGENT_RUNTIME_PRIMITIVES.md +6 -5
  153. package/docs/CLAUDE_CODE_PLUGIN.md +12 -5
  154. package/docs/CLI_GRAMMAR.md +7 -1
  155. package/docs/COMMANDS.md +2 -2
  156. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +8 -0
  157. package/docs/EXTENSIONS.md +36 -36
  158. package/docs/MCP_2026_07_28.md +160 -0
  159. package/docs/MCP_2026_07_28_CONFORMANCE.md +30 -0
  160. package/docs/MCP_REMOTE_TRANSPORT_SECURITY.md +180 -0
  161. package/docs/MCP_SKILLS_AND_APPS.md +107 -0
  162. package/docs/QUICKSTART.md +15 -15
  163. package/docs/README.md +5 -0
  164. package/docs/RELEASING.md +12 -3
  165. package/docs/SDK.md +22 -1
  166. package/docs/SDK_AGENT_SESSION_CONTEXT.md +18 -13
  167. package/docs/SDK_CONTEXT_INTEGRITY.md +6 -0
  168. package/docs/SDK_EVIDENCE_TRACEABILITY.md +9 -1
  169. package/docs/SDK_MCP_INTERACTIONS.md +227 -0
  170. package/docs/TESTING.md +4 -0
  171. package/docs/generated/AGENT_CAPABILITY_ROUTING.md +1 -1
  172. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +13 -11
  173. package/marketplace.json +2 -2
  174. package/package.json +15 -11
  175. package/packages/pm-beads/README.md +12 -6
  176. package/packages/pm-beads/docs/MIGRATION.md +53 -0
  177. package/packages/pm-beads/extensions/beads/index.ts +8 -0
  178. package/packages/pm-beads/extensions/beads/runtime.ts +671 -112
  179. package/packages/pm-beads/package.json +1 -1
  180. package/packages/pm-calendar/package.json +1 -1
  181. package/packages/pm-command-kit/package.json +1 -1
  182. package/packages/pm-digital-twin/package.json +1 -1
  183. package/packages/pm-governance-audit/package.json +1 -1
  184. package/packages/pm-guide-shell/package.json +1 -1
  185. package/packages/pm-kanban/package.json +1 -1
  186. package/packages/pm-lifecycle-hooks/package.json +1 -1
  187. package/packages/pm-linked-test-adapters/package.json +1 -1
  188. package/packages/pm-search-advanced/package.json +1 -1
  189. package/packages/pm-templates/package.json +1 -1
  190. package/packages/pm-todos/package.json +1 -1
  191. package/packages/pm-vcs/package.json +1 -1
  192. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  193. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  194. package/scripts/finalize-build.mjs +1 -0
  195. package/sdk/public-surface.json +902 -54
  196. package/dist/cli-bundle/chunks/chunk-2F3LUFMW.js +0 -8
  197. package/dist/cli-bundle/chunks/chunk-65MHLHAA.js +0 -2
  198. package/dist/cli-bundle/chunks/chunk-6C7GIMIL.js +0 -13
  199. package/dist/cli-bundle/chunks/chunk-QKGMHGEI.js +0 -202
  200. package/dist/cli-bundle/chunks/chunk-T2ENPRXF.js +0 -3
  201. package/dist/cli-bundle/chunks/chunk-TPQIBSL2.js +0 -3
  202. package/dist/cli-bundle/chunks/chunk-YQMYF3YD.js +0 -35
  203. package/dist/cli-bundle/chunks/register-setup-LXVBRCJ3.js +0 -2
  204. package/dist/cli-bundle/focused-chunks/chunk-42S3GGZ7.js +0 -50
  205. package/dist/cli-bundle/focused-chunks/chunk-7I23XGWO.js +0 -2
  206. package/dist/cli-bundle/focused-chunks/chunk-LMKG3DFE.js +0 -5
@@ -14,7 +14,27 @@ export interface ExtensionManifestSchemaInspection {
14
14
  /** Whether neither canonical pm compatibility bound is present. */
15
15
  missingVersionBounds: boolean;
16
16
  }
17
+ /** Stable machine-readable schema finding emitted by author-time lint. */
18
+ export interface ExtensionManifestSchemaFinding {
19
+ /** Schema condition an author must review. */
20
+ code: "manifest_unknown_key" | "no_version_bounds_declared";
21
+ /** JSON-style manifest location responsible for the finding. */
22
+ path: string;
23
+ /** Canonical key to use when the mistaken or missing field has one. */
24
+ suggested_key?: "pm_min_version" | "pm_max_version";
25
+ /** Actionable explanation of the ignored or missing declaration. */
26
+ message: string;
27
+ }
28
+ /** Pure schema-lint result for one raw extension manifest. */
29
+ export interface ExtensionManifestSchemaLintResult {
30
+ /** False when at least one author-facing schema finding is present. */
31
+ ok: boolean;
32
+ /** Deterministically ordered schema findings. */
33
+ findings: ExtensionManifestSchemaFinding[];
34
+ }
17
35
  /** Inspect raw manifest keys without parsing, loading, or mutating an extension. */
18
36
  export declare function inspectExtensionManifestSchema(manifest: Readonly<Record<string, unknown>>): ExtensionManifestSchemaInspection;
37
+ /** Lint raw extension-manifest keys without loading code or evaluating versions. */
38
+ export declare function lintExtensionManifestSchema(manifest: Readonly<Record<string, unknown>>): ExtensionManifestSchemaLintResult;
19
39
  /** Format runtime discovery warnings for unknown keys and absent canonical compatibility bounds. */
20
40
  export declare function formatExtensionManifestSchemaWarnings(layer: ExtensionLayer, manifest: ExtensionManifest, rawManifest: Readonly<Record<string, unknown>>): string[];
@@ -6,7 +6,7 @@
6
6
  */
7
7
  /** Canonical top-level keys accepted by an extension `manifest.json`. */
8
8
 
9
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7d9d8924-3186-5aab-ac36-164fb08624a8")}catch(e){}}();
9
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="49cea84c-1d1b-523b-8c98-7ac16c69ae82")}catch(e){}}();
10
10
  export const KNOWN_EXTENSION_MANIFEST_KEYS = new Set([
11
11
  "name",
12
12
  "version",
@@ -37,16 +37,34 @@ export function inspectExtensionManifestSchema(manifest) {
37
37
  manifest.pm_max_version === undefined,
38
38
  };
39
39
  }
40
- /** Format runtime discovery warnings for unknown keys and absent canonical compatibility bounds. */
41
- export function formatExtensionManifestSchemaWarnings(layer, manifest, rawManifest) {
42
- const inspection = inspectExtensionManifestSchema(rawManifest);
43
- const warnings = inspection.unknownKeys.map((key) => key === "compatibility"
44
- ? `extension_manifest_unknown_key:${layer}:${manifest.name}:key=compatibility:suggested=pm_min_version`
45
- : `extension_manifest_unknown_key:${layer}:${manifest.name}:key=${key}`);
40
+ /** Lint raw extension-manifest keys without loading code or evaluating versions. */
41
+ export function lintExtensionManifestSchema(manifest) {
42
+ const inspection = inspectExtensionManifestSchema(manifest);
43
+ const findings = inspection.unknownKeys.map((key) => ({
44
+ code: "manifest_unknown_key",
45
+ path: key,
46
+ ...(key === "compatibility"
47
+ ? { suggested_key: "pm_min_version" }
48
+ : {}),
49
+ message: key === "compatibility"
50
+ ? 'Manifest key "compatibility" is ignored; declare the canonical pm_min_version and optional pm_max_version fields instead.'
51
+ : `Manifest key "${key}" is not part of the extension manifest contract and will be ignored.`,
52
+ }));
46
53
  if (inspection.missingVersionBounds) {
47
- warnings.push(`extension_manifest_no_version_bounds:${layer}:${manifest.name}:suggested=pm_min_version`);
54
+ findings.push({
55
+ code: "no_version_bounds_declared",
56
+ path: "$",
57
+ suggested_key: "pm_min_version",
58
+ message: "No canonical pm version bounds are declared; add pm_min_version so compatibility intent is explicit.",
59
+ });
48
60
  }
49
- return warnings;
61
+ return { ok: findings.length === 0, findings };
62
+ }
63
+ /** Format runtime discovery warnings for unknown keys and absent canonical compatibility bounds. */
64
+ export function formatExtensionManifestSchemaWarnings(layer, manifest, rawManifest) {
65
+ return lintExtensionManifestSchema(rawManifest).findings.map((finding) => finding.code === "manifest_unknown_key"
66
+ ? `extension_manifest_unknown_key:${layer}:${manifest.name}:key=${finding.path}${finding.suggested_key ? `:suggested=${finding.suggested_key}` : ""}`
67
+ : `extension_manifest_no_version_bounds:${layer}:${manifest.name}:suggested=pm_min_version`);
50
68
  }
51
69
  //# sourceMappingURL=manifest-schema.js.map
52
- //# debugId=7d9d8924-3186-5aab-ac36-164fb08624a8
70
+ //# debugId=49cea84c-1d1b-523b-8c98-7ac16c69ae82
@@ -21,6 +21,15 @@ export interface IssueCodeItem {
21
21
  parent?: string | null;
22
22
  /** The id of the canonical item this one was closed as a duplicate of, when set. A closed-as-duplicate item has already been adjudicated, so it is excluded from collision detection entirely (GH-278) — re-flagging a resolved duplicate is permanent noise that erodes trust in `validate`. */
23
23
  duplicate_of?: string | null;
24
+ /** Optional body evidence used to disambiguate mixed-case prose compounds. */
25
+ body?: string | null;
26
+ }
27
+ /** Explicit classifier inputs for repository-specific issue-code formats. */
28
+ export interface IssueCodeDetectionOptions {
29
+ /** Prefixes configured by the repository, compared case-insensitively. */
30
+ configuredPrefixes?: readonly string[];
31
+ /** Item body used only for explicit code markers or backtick references. */
32
+ evidenceText?: string | null;
24
33
  }
25
34
  /** A logical issue code shared by two or more items. */
26
35
  export interface DuplicateIssueCode {
@@ -42,7 +51,7 @@ export interface DuplicateIssueCode {
42
51
  * Accepts unknown-ish input defensively (exported helper SDK consumers may call
43
52
  * from untyped JS): a non-string or empty title resolves to `null`.
44
53
  */
45
- export declare function extractIssueCode(title: string | null | undefined): string | null;
54
+ export declare function extractIssueCode(title: string | null | undefined, options?: IssueCodeDetectionOptions): string | null;
46
55
  /**
47
56
  * Find logical issue codes used by 2+ items. Any item whose title begins with a
48
57
  * conventional issue code contributes; codes used by a single item are not
@@ -67,4 +76,4 @@ export declare function extractIssueCode(title: string | null | undefined): stri
67
76
  * given (id) is used; duplicate ids (should not occur for a valid corpus) are
68
77
  * de-duplicated so an item never inflates its own code's count.
69
78
  */
70
- export declare function findDuplicateIssueCodes(items: readonly IssueCodeItem[]): DuplicateIssueCode[];
79
+ export declare function findDuplicateIssueCodes(items: readonly IssueCodeItem[], options?: Omit<IssueCodeDetectionOptions, "evidenceText">): DuplicateIssueCode[];
@@ -22,8 +22,8 @@
22
22
  * (digit immediately followed by a letter — no boundary) does not match.
23
23
  */
24
24
 
25
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="087bac58-e32d-5cb8-8fda-0e09075c3f35")}catch(e){}}();
26
- const ISSUE_CODE_PATTERN = /^([A-Z][A-Z0-9]*-\d+)\b/;
25
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="8a7fbaf1-917f-5067-b9b6-a9f27c80e291")}catch(e){}}();
26
+ const ISSUE_CODE_PATTERN = /^([A-Z][A-Z0-9]*-\d+)\b/iu;
27
27
  /**
28
28
  * Extract the leading logical issue code from a title, or `null` when the title
29
29
  * does not begin with one. The title is trimmed and upper-cased before matching
@@ -33,16 +33,32 @@ const ISSUE_CODE_PATTERN = /^([A-Z][A-Z0-9]*-\d+)\b/;
33
33
  * Accepts unknown-ish input defensively (exported helper SDK consumers may call
34
34
  * from untyped JS): a non-string or empty title resolves to `null`.
35
35
  */
36
- export function extractIssueCode(title) {
36
+ export function extractIssueCode(title, options = {}) {
37
37
  if (typeof title !== "string") {
38
38
  return null;
39
39
  }
40
- const normalized = title.trim().toUpperCase();
41
- if (normalized.length === 0) {
40
+ const trimmed = title.trim();
41
+ if (trimmed.length === 0) {
42
42
  return null;
43
43
  }
44
- const match = ISSUE_CODE_PATTERN.exec(normalized);
45
- return match ? match[1] : null;
44
+ const match = ISSUE_CODE_PATTERN.exec(trimmed);
45
+ if (!match)
46
+ return null;
47
+ const rawCode = match[1];
48
+ const normalized = rawCode.toUpperCase();
49
+ const rawPrefix = rawCode.slice(0, rawCode.lastIndexOf("-"));
50
+ const configured = new Set((options.configuredPrefixes ?? []).map((prefix) => prefix.trim().replace(/-+$/u, "").toUpperCase()));
51
+ const remainder = trimmed.slice(rawCode.length);
52
+ const evidence = options.evidenceText?.toUpperCase() ?? "";
53
+ const hasExplicitBodyEvidence = evidence.includes(`ISSUE CODE: ${normalized}`) ||
54
+ evidence.includes(`ISSUE CODE \`${normalized}\``) ||
55
+ evidence.includes(`\`${normalized}\``) ||
56
+ evidence.includes(`[${normalized}]`);
57
+ const structurallyQualified = rawPrefix === rawPrefix.toUpperCase() ||
58
+ /^\s*(?::|—|–|\])/u.test(remainder) ||
59
+ configured.has(rawPrefix.toUpperCase()) ||
60
+ hasExplicitBodyEvidence;
61
+ return structurallyQualified ? normalized : null;
46
62
  }
47
63
  /** Test whether a value is a usable (non-empty after trim) item-id reference. */
48
64
  function isNonEmptyIdReference(value) {
@@ -72,7 +88,7 @@ function isNonEmptyIdReference(value) {
72
88
  * given (id) is used; duplicate ids (should not occur for a valid corpus) are
73
89
  * de-duplicated so an item never inflates its own code's count.
74
90
  */
75
- export function findDuplicateIssueCodes(items) {
91
+ export function findDuplicateIssueCodes(items, options = {}) {
76
92
  const byCode = new Map();
77
93
  for (const item of items) {
78
94
  // A non-string title can never carry a code, so skip it before extraction;
@@ -84,7 +100,10 @@ export function findDuplicateIssueCodes(items) {
84
100
  if (isNonEmptyIdReference(item.duplicate_of)) {
85
101
  continue;
86
102
  }
87
- const code = extractIssueCode(item.title);
103
+ const code = extractIssueCode(item.title, {
104
+ ...options,
105
+ evidenceText: item.body,
106
+ });
88
107
  if (code === null) {
89
108
  continue;
90
109
  }
@@ -130,4 +149,4 @@ export function findDuplicateIssueCodes(items) {
130
149
  return duplicates.sort((left, right) => left.code.localeCompare(right.code));
131
150
  }
132
151
  //# sourceMappingURL=issue-codes.js.map
133
- //# debugId=087bac58-e32d-5cb8-8fda-0e09075c3f35
152
+ //# debugId=8a7fbaf1-917f-5067-b9b6-a9f27c80e291
@@ -4,7 +4,7 @@
4
4
  * Defines item parsing, formatting, and lifecycle helpers for Item Format.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="65a90a42-eecb-57d3-9f78-3a5f1bc3abd3")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="051655a4-8ba7-5118-9758-d9ca377fa7e4")}catch(e){}}();
8
8
  import { encode as encodeToon } from "@toon-format/toon";
9
9
  import { isDeepStrictEqual } from "node:util";
10
10
  import { CONFIDENCE_TEXT_VALUES, ISSUE_SEVERITY_VALUES, PLAN_STEP_STATUS_VALUES, RECURRENCE_FREQUENCY_VALUES, RECURRENCE_WEEKDAY_VALUES, STATUS_VALUES, weekdayOrderIndex, } from "../../types/index.js";
@@ -422,7 +422,7 @@ function sortDependencies(values) {
422
422
  return undefined;
423
423
  return [...values]
424
424
  .map((value) => ({
425
- id: value.id.trim().toLowerCase(),
425
+ id: value.id.trim(),
426
426
  kind: value.kind,
427
427
  created_at: value.created_at,
428
428
  author: value.author?.trim() || undefined,
@@ -1472,4 +1472,4 @@ export const _testOnlyItemFormat = {
1472
1472
  sortTests,
1473
1473
  };
1474
1474
  //# sourceMappingURL=item-format.js.map
1475
- //# debugId=65a90a42-eecb-57d3-9f78-3a5f1bc3abd3
1475
+ //# debugId=051655a4-8ba7-5118-9758-d9ca377fa7e4
@@ -4,7 +4,7 @@
4
4
  * Reads and writes tracker storage with format-aware helpers for Item Store.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f49b5141-f348-5954-a87e-8fd957593113")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="bffd3114-3e85-58ae-90c7-eea5069cdb89")}catch(e){}}();
8
8
  import fs from "node:fs/promises";
9
9
  import path from "node:path";
10
10
  import { getActiveExtensionRegistrations, projectAfterCommandItemSnapshot, recordAfterCommandAffectedItem, runActiveOnReadHooks, runActiveBeforeMutationHooks, runActiveOnWriteHooks, runActiveServiceOverride, } from "../extensions/index.js";
@@ -63,11 +63,18 @@ function resolveItemFormatSearchOrder(preferredFormat) {
63
63
  }
64
64
  /** Implements locate item for the public runtime surface of this module. */
65
65
  export async function locateItem(pmRoot, rawId, idPrefix = "pm-", preferredFormat, typeToFolder = TYPE_TO_FOLDER) {
66
+ const trimmedRawId = rawId.trim();
67
+ const exactRawId = trimmedRawId.startsWith("#")
68
+ ? trimmedRawId.slice(1)
69
+ : trimmedRawId;
70
+ if (exactRawId.length === 0) {
71
+ return null;
72
+ }
66
73
  const normalizedId = normalizeItemId(rawId, idPrefix);
67
74
  const rawNormalizedId = normalizeRawItemId(rawId);
68
- const candidateIds = normalizedId === rawNormalizedId
69
- ? [normalizedId]
70
- : [normalizedId, rawNormalizedId];
75
+ const candidateIds = [
76
+ ...new Set([exactRawId, normalizedId, rawNormalizedId]),
77
+ ].filter((candidateId) => candidateId.length > 0);
71
78
  const entries = Object.entries(typeToFolder);
72
79
  const searchOrder = resolveItemFormatSearchOrder(preferredFormat);
73
80
  for (const candidateId of candidateIds) {
@@ -642,4 +649,4 @@ export async function deleteItem(params) {
642
649
  }
643
650
  }
644
651
  //# sourceMappingURL=item-store.js.map
645
- //# debugId=f49b5141-f348-5954-a87e-8fd957593113
652
+ //# debugId=bffd3114-3e85-58ae-90c7-eea5069cdb89
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @module mcp/http-server
4
+ *
5
+ * Serves the pm MCP dispatcher through the sessionless 2026-07-28 Streamable
6
+ * HTTP POST binding with request-scoped JSON/SSE responses.
7
+ */
8
+ import { type IncomingMessage, type Server, type ServerResponse } from "node:http";
9
+ import { type PmMcpHttpAuthorizationPolicy, type PmMcpProtectedResourceMetadata } from "../sdk/mcp/authorization.js";
10
+ import { type JsonRpcRequest } from "./server.js";
11
+ /** Runtime options for one real Streamable HTTP server. */
12
+ export interface PmMcpHttpServerOptions {
13
+ /** Local bind host. Defaults to the DNS-rebinding-safe loopback address. */
14
+ host?: string;
15
+ /** TCP port. Zero requests an ephemeral port. */
16
+ port?: number;
17
+ /** Single modern MCP POST endpoint. */
18
+ endpointPath?: string;
19
+ /** Exact browser origins permitted when an Origin header is present. */
20
+ allowedOrigins?: readonly string[];
21
+ /** Optional RFC 9728/OAuth resource-server policy. */
22
+ authorization?: PmMcpHttpAuthorizationPolicy;
23
+ /** Metadata served at RFC 9728 well-known paths. */
24
+ protectedResourceMetadata?: PmMcpProtectedResourceMetadata;
25
+ /** Maximum accepted JSON request bytes. */
26
+ maximumBodyBytes?: number;
27
+ /** SSE comment interval; zero disables keep-alives. */
28
+ keepAliveMs?: number;
29
+ /** Optional embedding dispatcher; defaults to the canonical pm MCP handler. */
30
+ requestHandler?: (request: JsonRpcRequest) => unknown | Promise<unknown>;
31
+ }
32
+ /** Write one SSE event and wait for transport backpressure to clear. */
33
+ export declare function writePmMcpSseEvent(response: ServerResponse, payload: unknown): Promise<void>;
34
+ declare function writeMcpHttpDispatchError(response: ServerResponse, rpcRequest: JsonRpcRequest | undefined, error: unknown): void;
35
+ declare function destroyFailedMcpHttpResponse(response: ServerResponse, error: unknown): void;
36
+ /** Create a configured HTTP server without binding it. */
37
+ export declare function createPmMcpHttpServer(options?: PmMcpHttpServerOptions): Server<typeof IncomingMessage, typeof ServerResponse>;
38
+ /** Gracefully close subscriptions before stopping a Streamable HTTP server. */
39
+ export declare function closePmMcpHttpServer(server: Server): Promise<void>;
40
+ /** Bind the configured Streamable HTTP server and return its actual address. */
41
+ export declare function startPmMcpHttpServer(options?: PmMcpHttpServerOptions): Promise<ReturnType<typeof createPmMcpHttpServer>>;
42
+ /** Resolve loopback-safe bind defaults without opening a socket. */
43
+ export declare function resolvePmMcpHttpListenAddress(options?: Pick<PmMcpHttpServerOptions, "host" | "port">): {
44
+ host: string;
45
+ port: number;
46
+ };
47
+ /** Resolve and harden executable HTTP options from an environment map. */
48
+ export declare function resolvePmMcpHttpServerOptionsFromEnvironment(processEnvironment?: NodeJS.ProcessEnv): PmMcpHttpServerOptions;
49
+ /** Internal HTTP transport seams used only by direct integration tests. */
50
+ export declare const _testOnly: {
51
+ /** Return the first active request-scoped transport key for one server. */
52
+ activeSubscriptionKey: (server: Server) => symbol | undefined;
53
+ /** Open a stream against one server runtime without a network socket. */
54
+ openHttpSubscription: (server: Server, request: JsonRpcRequest, response: ServerResponse) => Promise<void>;
55
+ /** Exercise committed-response handling without a network race. */
56
+ writeMcpHttpDispatchError: typeof writeMcpHttpDispatchError;
57
+ /** Exercise the terminal request rejection handler without a live socket. */
58
+ destroyFailedMcpHttpResponse: typeof destroyFailedMcpHttpResponse;
59
+ };
60
+ export {};