@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.
- package/.agents/skills/HARNESS_COMPATIBILITY.md +32 -0
- package/.agents/skills/README.md +47 -0
- package/.agents/skills/pm-developer/SKILL.md +117 -0
- package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +49 -0
- package/.agents/skills/pm-developer/references/GRAPH_AND_RELATIONSHIPS.md +91 -0
- package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +72 -0
- package/.agents/skills/pm-developer/references/PROMPTS.md +17 -0
- package/.agents/skills/pm-developer/references/SCRIPTING_COMPOSITION.md +82 -0
- package/.agents/skills/pm-developer/references/TOKEN_BUDGETS.md +85 -0
- package/.agents/skills/pm-extensions/SKILL.md +106 -0
- package/.agents/skills/pm-extensions/references/AUTHORING.md +95 -0
- package/.agents/skills/pm-extensions/references/LIFECYCLE.md +40 -0
- package/.agents/skills/pm-extensions/references/TROUBLESHOOTING.md +25 -0
- package/.agents/skills/pm-sdk/SKILL.md +107 -0
- package/.agents/skills/pm-sdk/references/DOMAIN_MODELING.md +78 -0
- package/.agents/skills/pm-sdk/references/INTEGRATION_CHECKLIST.md +31 -0
- package/.agents/skills/pm-sdk/references/PROMPTS.md +13 -0
- package/.agents/skills/pm-sdk/references/SURFACE_MAP.md +82 -0
- package/.agents/skills/pm-user/SKILL.md +111 -0
- package/.agents/skills/pm-user/references/BACKLOG_SHAPING.md +105 -0
- package/.agents/skills/pm-user/references/PROMPTS.md +17 -0
- package/.agents/skills/pm-user/references/WORKFLOWS.md +35 -0
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +58 -3
- package/README.md +8 -5
- package/dist/cli/commander-usage.js +11 -7
- package/dist/cli/error-guidance.js +3 -3
- package/dist/cli/help-content.d.ts +2 -0
- package/dist/cli/help-content.js +53 -17
- package/dist/cli/help-json-payload.d.ts +8 -2
- package/dist/cli/help-json-payload.js +46 -12
- package/dist/cli/main.js +52 -74
- package/dist/cli/register-annotations.js +27 -21
- package/dist/cli/register-setup.js +98 -57
- package/dist/cli-bundle/bundle-manifest.json +156 -156
- package/dist/cli-bundle/chunks/chunk-3OO3W6FW.js +202 -0
- package/dist/cli-bundle/chunks/chunk-52EKTW6V.js +3 -0
- package/dist/cli-bundle/chunks/{chunk-QLUORNIB.js → chunk-CVBBGWW5.js} +62 -44
- package/dist/cli-bundle/chunks/chunk-MFNTKMTI.js +13 -0
- package/dist/cli-bundle/chunks/chunk-OS27HHBN.js +35 -0
- package/dist/cli-bundle/chunks/chunk-QTO7USTH.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-5I5RWIJC.js → chunk-R4ETAOJC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-OWHNAR2B.js → chunk-SH6P7FXI.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-SHMDY36D.js +8 -0
- package/dist/cli-bundle/chunks/{chunk-244MI4GS.js → chunk-SKXLJIEK.js} +60 -60
- package/dist/cli-bundle/chunks/chunk-TNX6HC54.js +3 -0
- package/dist/cli-bundle/chunks/{register-list-query-XVN2ZLI7.js → register-list-query-EUWM6VII.js} +2 -2
- package/dist/cli-bundle/chunks/{register-mutation-QCKAEGIJ.js → register-mutation-FD4HSAVU.js} +4 -4
- package/dist/cli-bundle/chunks/{register-operations-SDEAXE7E.js → register-operations-HRMNFEC3.js} +2 -2
- package/dist/cli-bundle/chunks/register-setup-33GNICLX.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-IBZZZGK3.js → chunk-2AGZ5BRT.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-4BR5UU52.js +50 -0
- package/dist/cli-bundle/focused-chunks/{chunk-OHIHZ7HS.js → chunk-6GCRSLPG.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-OVJL6NZE.js → chunk-AD6ULRAF.js} +4 -4
- package/dist/cli-bundle/focused-chunks/{chunk-7YCDTCBC.js → chunk-AQ5IYEZZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-YO3ZF3FI.js → chunk-EKX37ZHA.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-N7W67YIG.js → chunk-FC2AXLB5.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-H5JZEIQV.js → chunk-HC7ODMH3.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-NOOZGIXP.js → chunk-HVQ22RC4.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-A644DUFQ.js → chunk-MEASX544.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-RAFKLNZX.js → chunk-MXTYGECH.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-2UIWOP3O.js → chunk-SUBSWYW3.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-VXWATRFL.js → chunk-XDPYBQCF.js} +9 -9
- package/dist/cli-bundle/focused-chunks/{chunk-XUQPEKRN.js → chunk-Y3JJXRVK.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-GQR3WH3F.js → chunk-Y5A7SJJ7.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-YHWHX6YY.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-ONYQCALA.js → chunk-YVVZ3LQ6.js} +6 -6
- package/dist/cli-bundle/focused-chunks/chunk-Z2USIBR2.js +5 -0
- package/dist/cli-bundle/main.js +15 -14
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +31 -31
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +31 -31
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +32 -6
- package/dist/core/extensions/manifest-schema.d.ts +20 -0
- package/dist/core/extensions/manifest-schema.js +28 -10
- package/dist/core/governance/issue-codes.d.ts +11 -2
- package/dist/core/governance/issue-codes.js +29 -10
- package/dist/core/item/item-format.js +3 -3
- package/dist/core/store/item-store.js +12 -5
- package/dist/mcp/http-server.d.ts +60 -0
- package/dist/mcp/http-server.js +451 -0
- package/dist/mcp/legacy-adapter.d.ts +50 -0
- package/dist/mcp/legacy-adapter.js +64 -0
- package/dist/mcp/server.d.ts +42 -9
- package/dist/mcp/server.js +572 -59
- package/dist/mcp/tool-definitions.d.ts +2 -0
- package/dist/mcp/tool-definitions.js +2 -2
- package/dist/sdk/agent/closed-domain-contracts.d.ts +1 -1
- package/dist/sdk/agent/closed-domain-contracts.js +24 -2
- package/dist/sdk/agent/refusal-closure-census.d.ts +6 -2
- package/dist/sdk/agent/refusal-closure-census.js +16 -8
- package/dist/sdk/agent-capability-contracts.js +6 -2
- package/dist/sdk/cli-bootstrap.js +3 -2
- package/dist/sdk/cli-contracts/command-aliases.js +15 -2
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +4 -1
- package/dist/sdk/cli-contracts/enum-contracts.js +7 -2
- package/dist/sdk/cli-contracts/flag-contracts.js +9 -5
- package/dist/sdk/cli-contracts/grammar-contracts.d.ts +3 -3
- package/dist/sdk/cli-contracts/grammar-contracts.js +24 -17
- package/dist/sdk/cli-contracts/runtime-contracts.js +13 -11
- package/dist/sdk/cli-contracts/tool-schema.js +18 -15
- package/dist/sdk/cli-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts.js +3 -3
- package/dist/sdk/cli-program.js +3 -2
- package/dist/sdk/completion.js +40 -13
- package/dist/sdk/compose.d.ts +4 -1
- package/dist/sdk/compose.js +23 -36
- package/dist/sdk/extension/author-manifest.d.ts +22 -0
- package/dist/sdk/extension/author-manifest.js +93 -0
- package/dist/sdk/extension.js +6 -3
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +20 -5
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +18 -3
- package/dist/sdk/governance/health.js +7 -2
- package/dist/sdk/governance/upgrade.d.ts +2 -0
- package/dist/sdk/governance/upgrade.js +30 -8
- package/dist/sdk/governance/validate.js +8 -6
- package/dist/sdk/guide-topics.js +6 -6
- package/dist/sdk/index.d.ts +10 -2
- package/dist/sdk/index.js +11 -3
- package/dist/sdk/mcp/apps.d.ts +70 -0
- package/dist/sdk/mcp/apps.js +154 -0
- package/dist/sdk/mcp/authorization.d.ts +134 -0
- package/dist/sdk/mcp/authorization.js +405 -0
- package/dist/sdk/mcp/interactions.d.ts +118 -0
- package/dist/sdk/mcp/interactions.js +337 -0
- package/dist/sdk/mcp/protocol.d.ts +142 -0
- package/dist/sdk/mcp/protocol.js +174 -0
- package/dist/sdk/mcp/skills.d.ts +127 -0
- package/dist/sdk/mcp/skills.js +390 -0
- package/dist/sdk/mcp/subscriptions.d.ts +65 -0
- package/dist/sdk/mcp/subscriptions.js +212 -0
- package/dist/sdk/mcp/tasks.d.ts +107 -0
- package/dist/sdk/mcp/tasks.js +431 -0
- package/dist/sdk/mcp/transport.d.ts +30 -0
- package/dist/sdk/mcp/transport.js +261 -0
- package/dist/sdk/merge/receipts.d.ts +16 -0
- package/dist/sdk/merge/receipts.js +9 -8
- package/dist/sdk/read-output-contracts.js +16 -3
- package/dist/sdk/runtime-action-aliases.js +7 -3
- package/dist/sdk/runtime-input.js +12 -4
- package/dist/sdk/runtime-primitives.d.ts +2 -2
- package/dist/sdk/runtime-primitives.js +4 -4
- package/dist/sdk/test/execution.d.ts +6 -0
- package/dist/sdk/test/execution.js +32 -3
- package/docs/AGENT_PROVENANCE_ADR.md +6 -4
- package/docs/AGENT_RUNTIME_PRIMITIVES.md +6 -5
- package/docs/CLAUDE_CODE_PLUGIN.md +12 -5
- package/docs/CLI_GRAMMAR.md +7 -1
- package/docs/COMMANDS.md +2 -2
- package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +8 -0
- package/docs/EXTENSIONS.md +36 -36
- package/docs/MCP_2026_07_28.md +160 -0
- package/docs/MCP_2026_07_28_CONFORMANCE.md +30 -0
- package/docs/MCP_REMOTE_TRANSPORT_SECURITY.md +180 -0
- package/docs/MCP_SKILLS_AND_APPS.md +107 -0
- package/docs/QUICKSTART.md +15 -15
- package/docs/README.md +5 -0
- package/docs/RELEASING.md +12 -3
- package/docs/SDK.md +22 -1
- package/docs/SDK_AGENT_SESSION_CONTEXT.md +18 -13
- package/docs/SDK_CONTEXT_INTEGRITY.md +6 -0
- package/docs/SDK_EVIDENCE_TRACEABILITY.md +9 -1
- package/docs/SDK_MCP_INTERACTIONS.md +227 -0
- package/docs/TESTING.md +4 -0
- package/docs/generated/AGENT_CAPABILITY_ROUTING.md +1 -1
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +13 -11
- package/marketplace.json +2 -2
- package/package.json +15 -11
- package/packages/pm-beads/README.md +12 -6
- package/packages/pm-beads/docs/MIGRATION.md +53 -0
- package/packages/pm-beads/extensions/beads/index.ts +8 -0
- package/packages/pm-beads/extensions/beads/runtime.ts +671 -112
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/scripts/finalize-build.mjs +1 -0
- package/sdk/public-surface.json +902 -54
- package/dist/cli-bundle/chunks/chunk-2F3LUFMW.js +0 -8
- package/dist/cli-bundle/chunks/chunk-65MHLHAA.js +0 -2
- package/dist/cli-bundle/chunks/chunk-6C7GIMIL.js +0 -13
- package/dist/cli-bundle/chunks/chunk-QKGMHGEI.js +0 -202
- package/dist/cli-bundle/chunks/chunk-T2ENPRXF.js +0 -3
- package/dist/cli-bundle/chunks/chunk-TPQIBSL2.js +0 -3
- package/dist/cli-bundle/chunks/chunk-YQMYF3YD.js +0 -35
- package/dist/cli-bundle/chunks/register-setup-LXVBRCJ3.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-42S3GGZ7.js +0 -50
- package/dist/cli-bundle/focused-chunks/chunk-7I23XGWO.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-LMKG3DFE.js +0 -5
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# MCP Interaction and Task SDK
|
|
2
|
+
|
|
3
|
+
Tracker references: [pm-rz9gep](../.agents/pm/features/pm-rz9gep.toon),
|
|
4
|
+
[pm-rzs24j](../.agents/pm/features/pm-rzs24j.toon), and
|
|
5
|
+
[pm-hv1x1x](../.agents/pm/features/pm-hv1x1x.toon). Transport and remote
|
|
6
|
+
trust primitives are tracked by
|
|
7
|
+
[pm-v7e337](../.agents/pm/features/pm-v7e337.toon) and
|
|
8
|
+
[pm-3zh9s4](../.agents/pm/features/pm-3zh9s4.toon).
|
|
9
|
+
|
|
10
|
+
The aggregate `@unbrained/pm-cli/sdk` entrypoint exposes transport-neutral
|
|
11
|
+
contracts for MCP 2026-07-28 multi round-trip requests (MRTR), explicit cache
|
|
12
|
+
policy, bounded JSON Schema 2020-12 validation, and the official durable tasks
|
|
13
|
+
extension. A custom stdio or HTTP host can reuse these primitives without
|
|
14
|
+
importing pm's executable server.
|
|
15
|
+
|
|
16
|
+
## Request more host input
|
|
17
|
+
|
|
18
|
+
Throw `PmMcpInputRequiredError` from domain code. The host adapter converts the
|
|
19
|
+
signal into an `input_required` result after validating request method,
|
|
20
|
+
payload bounds, and the request-local client capability.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import {
|
|
24
|
+
PmMcpInputRequiredError,
|
|
25
|
+
digestMcpRequestParameters,
|
|
26
|
+
sealMcpRequestState,
|
|
27
|
+
} from "@unbrained/pm-cli/sdk";
|
|
28
|
+
|
|
29
|
+
const requestState = sealMcpRequestState(
|
|
30
|
+
{
|
|
31
|
+
expiresAt: Date.now() + 5 * 60_000,
|
|
32
|
+
method: "tools/call",
|
|
33
|
+
parameterDigest: digestMcpRequestParameters({ name: "pm_mutate" }),
|
|
34
|
+
principal: "host-user-42",
|
|
35
|
+
state: { phase: "confirm" },
|
|
36
|
+
},
|
|
37
|
+
process.env.MCP_REQUEST_STATE_KEY!, // at least 32 bytes
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
throw new PmMcpInputRequiredError({
|
|
41
|
+
requestState,
|
|
42
|
+
inputRequests: {
|
|
43
|
+
confirmation: {
|
|
44
|
+
method: "elicitation/create",
|
|
45
|
+
params: {
|
|
46
|
+
mode: "form",
|
|
47
|
+
message: "Apply the proposed PM mutations?",
|
|
48
|
+
requestedSchema: {
|
|
49
|
+
type: "object",
|
|
50
|
+
properties: { approved: { type: "boolean" } },
|
|
51
|
+
required: ["approved"],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Use `openMcpRequestState()` on retry to verify signature, expiry, original
|
|
60
|
+
method, parameter digest, and principal. Call
|
|
61
|
+
`PmMcpRequestStateReplayGuard.consume()` only after successful verification.
|
|
62
|
+
The bundled guard provides bounded single-process replay detection; a
|
|
63
|
+
multi-process host should persist the consumed state digest in its shared
|
|
64
|
+
store. `parseMcpInputResponses()` validates and clones retry responses.
|
|
65
|
+
|
|
66
|
+
The permitted input request methods are
|
|
67
|
+
`elicitation/create`, `roots/list`, and `sampling/createMessage`. The client
|
|
68
|
+
must advertise the corresponding capability on that same request.
|
|
69
|
+
|
|
70
|
+
## Validate schemas and attach cache policy
|
|
71
|
+
|
|
72
|
+
`validateMcpJsonSchema()` accepts object and boolean JSON Schema 2020-12 roots,
|
|
73
|
+
resolves local JSON Pointer references, and applies byte, depth, and node work
|
|
74
|
+
bounds. It returns a clone so callers cannot mutate the validated input by
|
|
75
|
+
alias. External references remain identifiers; this validator does not perform
|
|
76
|
+
network retrieval.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import {
|
|
80
|
+
validateMcpJsonSchema,
|
|
81
|
+
withMcpCachePolicy,
|
|
82
|
+
} from "@unbrained/pm-cli/sdk";
|
|
83
|
+
|
|
84
|
+
const inputSchema = validateMcpJsonSchema({
|
|
85
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
86
|
+
type: "object",
|
|
87
|
+
properties: { id: { type: "string" } },
|
|
88
|
+
required: ["id"],
|
|
89
|
+
additionalProperties: false,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const result = withMcpCachePolicy(
|
|
93
|
+
{ tools: [{ name: "get_item", inputSchema }] },
|
|
94
|
+
{ ttlMs: 30_000, cacheScope: "private" },
|
|
95
|
+
);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Use `cacheScope: "private"` whenever a result depends on a workspace,
|
|
99
|
+
principal, authorization decision, or user data. A `public` result must be
|
|
100
|
+
safe for shared intermediaries and all principals for its full TTL.
|
|
101
|
+
|
|
102
|
+
## Run durable extension tasks
|
|
103
|
+
|
|
104
|
+
`createMcpTaskStore()` persists task records below the supplied tracker root's
|
|
105
|
+
ignored `runtime/mcp-tasks` directory. It creates the durable record before
|
|
106
|
+
returning a handle and serializes mutations with pm's cross-process lock.
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { createMcpTaskStore } from "@unbrained/pm-cli/sdk";
|
|
110
|
+
|
|
111
|
+
const tasks = createMcpTaskStore({
|
|
112
|
+
pmRoot: "/workspace/project/.agents/pm",
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const handle = await tasks.create({
|
|
116
|
+
principal: "host-user-42",
|
|
117
|
+
ttlMs: 60 * 60_000,
|
|
118
|
+
statusMessage: "Validating the workspace.",
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const result = await validateWorkspace();
|
|
123
|
+
await tasks.complete(handle.taskId, "host-user-42", result);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
await tasks.fail(handle.taskId, "host-user-42", {
|
|
126
|
+
code: -32603,
|
|
127
|
+
message: error instanceof Error ? error.message : "Validation failed",
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The lifecycle is `working` to `input_required`, `completed`, `failed`, or
|
|
133
|
+
`cancelled`. `get()` applies retention expiry and restart recovery;
|
|
134
|
+
`requireInput()` records MRTR requests; `update()` accepts matching responses;
|
|
135
|
+
`takeInputResponses()` transfers them to a resumed worker; and `cancel()` is a
|
|
136
|
+
cooperative state transition. Completed, failed, and cancelled records are
|
|
137
|
+
immutable. Task ids and principal mismatches intentionally return the same
|
|
138
|
+
not-found refusal to avoid disclosing another principal's work.
|
|
139
|
+
|
|
140
|
+
The bundled `pm-mcp` server negotiates the extension through
|
|
141
|
+
`io.modelcontextprotocol/tasks`. Eligible validation, health, graph, import,
|
|
142
|
+
reindex, and test operations may return a task handle when the client requests
|
|
143
|
+
asynchronous execution. Clients retrieve state with `tasks/get`, provide MRTR
|
|
144
|
+
answers with `tasks/update`, and request cancellation with `tasks/cancel`.
|
|
145
|
+
|
|
146
|
+
Task progress notifications and cross-transport request-scoped streams are a
|
|
147
|
+
separate concern from change subscriptions. A client polls at `pollIntervalMs`
|
|
148
|
+
for task state; `subscriptions/listen` carries only explicitly acknowledged
|
|
149
|
+
tool, prompt, and resource changes.
|
|
150
|
+
|
|
151
|
+
## Open change subscriptions
|
|
152
|
+
|
|
153
|
+
`PmMcpSubscriptionRegistry` is transport-neutral. A stdio or HTTP adapter
|
|
154
|
+
opens a record with the `subscriptions/listen` JSON-RPC id, requested filter,
|
|
155
|
+
and an asynchronous sink. The registry sends the acknowledgment before any
|
|
156
|
+
other notification, intersects filters with advertised server capabilities,
|
|
157
|
+
tags every notification with the subscription id, and awaits each sink so
|
|
158
|
+
transport backpressure is visible.
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
import { PmMcpSubscriptionRegistry } from "@unbrained/pm-cli/sdk";
|
|
162
|
+
|
|
163
|
+
const subscriptions = new PmMcpSubscriptionRegistry({
|
|
164
|
+
capabilities: { resources: { listChanged: true, subscribe: true } },
|
|
165
|
+
serverInfo: { name: "custom-pm-host", version: "1.0.0" },
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
await subscriptions.open({
|
|
169
|
+
id: "workspace-changes",
|
|
170
|
+
notifications: {
|
|
171
|
+
resourcesListChanged: true,
|
|
172
|
+
resourceSubscriptions: ["pm://workspace/context"],
|
|
173
|
+
},
|
|
174
|
+
sink: async (notification) => sendOnTransport(notification),
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
await subscriptions.emitResourceUpdated("pm://workspace/context");
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Closing returns the final modern result envelope. Abrupt disconnects should
|
|
181
|
+
delete the record without fabricating a replay cursor or redelivery promise.
|
|
182
|
+
|
|
183
|
+
## Project and validate HTTP headers
|
|
184
|
+
|
|
185
|
+
`buildMcpHttpRequestHeaders()` constructs the required protocol, method, and
|
|
186
|
+
name headers from a request. `validateMcpHttpRequestHeaders()` checks the
|
|
187
|
+
received headers against both the JSON-RPC body and a tool's input schema.
|
|
188
|
+
`collectMcpHeaderAnnotations()` exposes the validated `x-mcp-header` mapping
|
|
189
|
+
when a custom adapter needs to inspect it.
|
|
190
|
+
|
|
191
|
+
Header values are strings, numbers, or booleans. The SDK Base64-encodes values
|
|
192
|
+
that cannot be represented unambiguously and rejects control bytes, reserved
|
|
193
|
+
MCP names, duplicate mappings, undeclared arguments, and body/header
|
|
194
|
+
mismatches. Never copy arbitrary client headers into tool arguments.
|
|
195
|
+
|
|
196
|
+
## Compose remote authorization
|
|
197
|
+
|
|
198
|
+
Use `buildMcpProtectedResourceMetadata()` for RFC 9728 metadata,
|
|
199
|
+
`buildMcpAuthorizationDiscoveryUrls()` and
|
|
200
|
+
`validateMcpAuthorizationServerMetadata()` for exact issuer discovery, and
|
|
201
|
+
`selectMcpClientRegistrationMode()` to prefer Client ID Metadata Documents
|
|
202
|
+
over deprecated Dynamic Client Registration. Store credentials with
|
|
203
|
+
`PmMcpIssuerCredentialStore`; its exact issuer key prevents cross-issuer
|
|
204
|
+
reuse and its cloned values prevent alias mutation.
|
|
205
|
+
|
|
206
|
+
At the resource boundary, `authorizeMcpHttpRequest()` accepts bearer tokens
|
|
207
|
+
only in the Authorization header and verifies issuer, audience, and required
|
|
208
|
+
scopes through a host-provided verifier. `extractMcpTraceContext()` validates
|
|
209
|
+
W3C trace fields and retains only allowlisted baggage before
|
|
210
|
+
`runWithMcpTraceContext()` creates a concurrent-request-local scope.
|
|
211
|
+
|
|
212
|
+
See [MCP remote transport, authorization, and migration](MCP_REMOTE_TRANSPORT_SECURITY.md)
|
|
213
|
+
for executable configuration, lifecycle policy, and the threat model.
|
|
214
|
+
|
|
215
|
+
## Failure and trust boundaries
|
|
216
|
+
|
|
217
|
+
- Keep signing keys outside request data and logs; rotate them using a bounded
|
|
218
|
+
overlap strategy owned by the host.
|
|
219
|
+
- Bind continuation state and tasks to an authenticated principal chosen by
|
|
220
|
+
the host, never to a caller-supplied display name.
|
|
221
|
+
- Treat `ttlMs` as retention/freshness policy, not proof that underlying data
|
|
222
|
+
is unchanged.
|
|
223
|
+
- A worker lost across process restart becomes a terminal, non-recoverable task
|
|
224
|
+
result. Create a new task instead of replaying side effects implicitly.
|
|
225
|
+
- The task store is durable local coordination, not a distributed queue. A
|
|
226
|
+
multi-host deployment should implement the same public lifecycle on a
|
|
227
|
+
shared transactional backend.
|
package/docs/TESTING.md
CHANGED
|
@@ -443,6 +443,10 @@ context. This preserves source isolation without copying an unrelated tracker
|
|
|
443
443
|
into constrained temporary storage.
|
|
444
444
|
Capacity, permission, and resource failures while seeding a required tracker
|
|
445
445
|
surface as typed, path-redacted host-environment refusals with recovery steps.
|
|
446
|
+
When a legacy source tracker has settings but no `_workspace` history, tracker
|
|
447
|
+
mode creates the sandbox's initial audited settings snapshot from the exact
|
|
448
|
+
source bytes. Existing source workspace history is copied unchanged, including
|
|
449
|
+
real drift, so linked validation never masks a source integrity failure.
|
|
446
450
|
|
|
447
451
|
## Source Workspace Modes
|
|
448
452
|
|
|
@@ -14,4 +14,4 @@ This file is generated from `PM_COMMAND_CAPABILITY_CONTRACTS`. Do not edit it ma
|
|
|
14
14
|
| graph | `graph`, `deps`, `plan` |
|
|
15
15
|
| quality | `test`, `test-all`, `validate`, `assurance`, `contracts` |
|
|
16
16
|
| automation | `meet`, `event`, `remind` |
|
|
17
|
-
| extensions | `
|
|
17
|
+
| extensions | `package` |
|
|
@@ -4,14 +4,14 @@ Tracker: `pm-f05lsg`.
|
|
|
4
4
|
|
|
5
5
|
Every catalog code is listed. An `uncovered` row is an explicit closure obligation, never an omission or implied approval.
|
|
6
6
|
|
|
7
|
-
- Catalog error codes:
|
|
8
|
-
- Executable error codes:
|
|
9
|
-
- Executable-code ratchet floor:
|
|
10
|
-
- Required executable canonical codes: `bulk_ids_input_empty`, `bulk_ids_input_missing_path`, `bulk_ids_input_unreadable`, `invalid_argument_value`, `missing_lifecycle_target`, `missing_required_argument`, `projection_options_mutually_exclusive`, `tracker_not_initialized`, `tracker_root_missing`, `tracker_root_not_directory`, `tracker_root_unreadable`, `unknown_context_intent`, `unknown_field_projection`, `unknown_option`, `unknown_subcommand`
|
|
11
|
-
- Uncovered error codes:
|
|
12
|
-
- Coverage fraction: 0.
|
|
13
|
-
- Closed-domain probes:
|
|
14
|
-
- Grammar probes:
|
|
7
|
+
- Catalog error codes: 344
|
|
8
|
+
- Executable error codes: 19
|
|
9
|
+
- Executable-code ratchet floor: 18
|
|
10
|
+
- Required executable canonical codes: `bulk_ids_input_empty`, `bulk_ids_input_missing_path`, `bulk_ids_input_unreadable`, `invalid_argument_value`, `manifest_unknown_key`, `missing_lifecycle_target`, `missing_required_argument`, `no_version_bounds_declared`, `projection_options_mutually_exclusive`, `tracker_not_initialized`, `tracker_root_missing`, `tracker_root_not_directory`, `tracker_root_unreadable`, `unknown_context_intent`, `unknown_field_projection`, `unknown_option`, `unknown_subcommand`
|
|
11
|
+
- Uncovered error codes: 325
|
|
12
|
+
- Coverage fraction: 0.055233
|
|
13
|
+
- Closed-domain probes: 19
|
|
14
|
+
- Grammar probes: 94
|
|
15
15
|
|
|
16
16
|
| Error code | Canonical code | Disposition | Evidence kinds | Probe count |
|
|
17
17
|
| --- | --- | --- | --- | --- |
|
|
@@ -175,9 +175,10 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
|
|
|
175
175
|
| `locks_unreadable` | `locks_unreadable` | uncovered | none | 0 |
|
|
176
176
|
| `malformed_plan_step_evidence` | `malformed_plan_step_evidence` | uncovered | none | 0 |
|
|
177
177
|
| `manifest_capabilities_absent` | `manifest_capabilities_absent` | uncovered | none | 0 |
|
|
178
|
-
| `manifest_unknown_key` | `manifest_unknown_key` |
|
|
178
|
+
| `manifest_unknown_key` | `manifest_unknown_key` | executable | owned_state | 1 |
|
|
179
179
|
| `mcp_annotation_file_unavailable` | `mcp_annotation_file_unavailable` | uncovered | none | 0 |
|
|
180
180
|
| `mcp_stdin_unavailable` | `mcp_stdin_unavailable` | uncovered | none | 0 |
|
|
181
|
+
| `mcp_task_not_found_or_not_authorized` | `mcp_task_not_found_or_not_authorized` | uncovered | none | 0 |
|
|
181
182
|
| `merge_conflict_markers_detected` | `merge_conflict_markers_detected` | uncovered | none | 0 |
|
|
182
183
|
| `merge_decisions_unreviewed` | `merge_decisions_unreviewed` | uncovered | none | 0 |
|
|
183
184
|
| `merge_git_config_unwritable` | `merge_git_config_unwritable` | uncovered | none | 0 |
|
|
@@ -197,7 +198,7 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
|
|
|
197
198
|
| `missing_observed_signature` | `missing_observed_signature` | uncovered | none | 0 |
|
|
198
199
|
| `missing_parameter_alias` | `missing_parameter_alias` | uncovered | none | 0 |
|
|
199
200
|
| `missing_probe` | `missing_probe` | uncovered | none | 0 |
|
|
200
|
-
| `missing_required_argument` | `missing_required_argument` | executable | grammar |
|
|
201
|
+
| `missing_required_argument` | `missing_required_argument` | executable | grammar | 57 |
|
|
201
202
|
| `missing_required_option` | `missing_required_option` | uncovered | none | 0 |
|
|
202
203
|
| `missing_suggested_retry` | `missing_suggested_retry` | uncovered | none | 0 |
|
|
203
204
|
| `missing_suggested_retry_args` | `missing_suggested_retry_args` | uncovered | none | 0 |
|
|
@@ -210,13 +211,14 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
|
|
|
210
211
|
| `no_test_files_found` | `no_test_files_found` | uncovered | none | 0 |
|
|
211
212
|
| `no_tests_found` | `no_tests_found` | uncovered | none | 0 |
|
|
212
213
|
| `no_update_fields` | `no_update_fields` | uncovered | none | 0 |
|
|
213
|
-
| `no_version_bounds_declared` | `no_version_bounds_declared` |
|
|
214
|
+
| `no_version_bounds_declared` | `no_version_bounds_declared` | executable | owned_state | 1 |
|
|
214
215
|
| `non_refusal_exit` | `non_refusal_exit` | uncovered | none | 0 |
|
|
215
216
|
| `npm_package_not_found` | `npm_package_not_found` | uncovered | none | 0 |
|
|
216
217
|
| `ownership_conflict` | `ownership_conflict` | uncovered | none | 0 |
|
|
217
218
|
| `ownership_dependency_bypass_restricted_options` | `ownership_dependency_bypass_restricted_options` | uncovered | none | 0 |
|
|
218
219
|
| `ownership_metadata_bypass_restricted_options` | `ownership_metadata_bypass_restricted_options` | uncovered | none | 0 |
|
|
219
220
|
| `package_spec_empty` | `package_spec_empty` | uncovered | none | 0 |
|
|
221
|
+
| `package_upgrade_modes_mutually_exclusive` | `package_upgrade_modes_mutually_exclusive` | executable | closed_domain | 1 |
|
|
220
222
|
| `positional_shape_budget_exceeded` | `positional_shape_budget_exceeded` | uncovered | none | 0 |
|
|
221
223
|
| `positional_signature_mismatch` | `positional_signature_mismatch` | uncovered | none | 0 |
|
|
222
224
|
| `profile_name_empty` | `profile_name_empty` | uncovered | none | 0 |
|
package/marketplace.json
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Official marketplace for pm CLI — native git-based project management for Claude Code and AI coding agents.",
|
|
9
|
-
"version": "2026.8.
|
|
9
|
+
"version": "2026.8.27"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
13
13
|
"name": "pm-claude",
|
|
14
14
|
"source": "./plugins/pm-claude",
|
|
15
15
|
"description": "Native pm CLI integration for Claude Code — 28 MCP tools, 5 workflow skills, 14 slash commands, 4 subagents, hybrid TUI task tracking, session context injection, and coordination subagents for git-based project management without leaving Claude Code.",
|
|
16
|
-
"version": "2026.8.
|
|
16
|
+
"version": "2026.8.27",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "unbrained",
|
|
19
19
|
"url": "https://github.com/unbraind/pm-cli"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unbrained/pm-cli",
|
|
3
|
-
"version": "2026.8.
|
|
3
|
+
"version": "2026.8.27",
|
|
4
4
|
"description": "Git-native project management CLI for humans and agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@11.10.0",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"bin": {
|
|
17
17
|
"pm-cli": "dist/cli.js",
|
|
18
18
|
"pm": "dist/cli.js",
|
|
19
|
-
"pm-mcp": "dist/mcp/server.js"
|
|
19
|
+
"pm-mcp": "dist/mcp/server.js",
|
|
20
|
+
"pm-mcp-http": "dist/mcp/http-server.js"
|
|
20
21
|
},
|
|
21
22
|
"types": "dist/sdk/index.d.ts",
|
|
22
23
|
"exports": {
|
|
@@ -103,6 +104,7 @@
|
|
|
103
104
|
"scripts/finalize-build.mjs",
|
|
104
105
|
"scripts/install.sh",
|
|
105
106
|
"scripts/install.ps1",
|
|
107
|
+
".agents/skills/**",
|
|
106
108
|
"scripts/prepare-build-cache.mjs",
|
|
107
109
|
"marketplace.json"
|
|
108
110
|
],
|
|
@@ -120,7 +122,7 @@
|
|
|
120
122
|
"lint:complexity:baseline": "eslint . --suppress-rule complexity --suppress-rule sonarjs/cognitive-complexity",
|
|
121
123
|
"lint:duplicates": "jscpd --config .jscpd.json",
|
|
122
124
|
"lint:codefactor": "pnpm quality:static",
|
|
123
|
-
"quality:static": "pnpm build && node scripts/contracts-snapshot.mjs --check && node scripts/generate-agent-capability-surfaces.mjs --check && node scripts/generate-error-code-catalog.mjs --check && node scripts/release/repository-assurance.mjs repository-static-quality --trigger ci --json && node scripts/release/audit-package-boundary.mjs && node scripts/release/package-sdk-contract-parity.mjs && node scripts/release/surface-replication-gate.mjs && node scripts/release/command-grammar-gate.mjs && node scripts/release/flag-invocation-parity.mjs && node scripts/release/flag-lexicon-gate.mjs && node scripts/release/refusal-closure-gate.mjs && node dist/cli.js assurance run tracker-context-quality --trigger ci --dry-run --json --output-budget unbounded && node scripts/release/gate-registry.mjs && node scripts/sdk-surface-snapshot.mjs --check && node scripts/bench/sdk-entrypoint-costs.mjs --check && node scripts/bench/cli-transport-floor.mjs --check && node dist/cli.js assurance run graph-composition --trigger ci --dry-run --json --output-budget unbounded && node dist/cli.js assurance run record-integrity --trigger ci --dry-run --json --output-budget unbounded",
|
|
125
|
+
"quality:static": "pnpm build && node scripts/contracts-snapshot.mjs --check && node scripts/generate-agent-capability-surfaces.mjs --check && node scripts/generate-error-code-catalog.mjs --check && node scripts/release/repository-assurance.mjs repository-static-quality --trigger ci --json && node scripts/release/audit-package-boundary.mjs && node scripts/release/package-sdk-contract-parity.mjs && node scripts/release/surface-replication-gate.mjs && node scripts/release/command-grammar-gate.mjs && node scripts/release/flag-invocation-parity.mjs && node scripts/release/flag-lexicon-gate.mjs && node scripts/release/refusal-closure-gate.mjs && pnpm quality:mcp-deprecations && node dist/cli.js assurance run tracker-context-quality --trigger ci --dry-run --json --output-budget unbounded && node scripts/release/gate-registry.mjs && node scripts/sdk-surface-snapshot.mjs --check && node scripts/bench/sdk-entrypoint-costs.mjs --check && node scripts/bench/cli-transport-floor.mjs --check && node dist/cli.js assurance run graph-composition --trigger ci --dry-run --json --output-budget unbounded && node dist/cli.js assurance run record-integrity --trigger ci --dry-run --json --output-budget unbounded",
|
|
124
126
|
"quality:command-grammar": "pnpm build && node scripts/release/command-grammar-gate.mjs && node scripts/release/flag-invocation-parity.mjs && node scripts/release/flag-lexicon-gate.mjs",
|
|
125
127
|
"quality:recovery-closure": "pnpm build && node scripts/release/refusal-closure-gate.mjs",
|
|
126
128
|
"quality:token-budget": "node scripts/release/token-budget-gate.mjs",
|
|
@@ -139,6 +141,7 @@
|
|
|
139
141
|
"quality:absence-tolerance": "node scripts/release/absence-tolerance-gate.mjs",
|
|
140
142
|
"quality:docs-skills": "node scripts/release/docs-skills-gate.mjs",
|
|
141
143
|
"quality:docs-links": "node scripts/release/docs-skills-gate.mjs --links-only",
|
|
144
|
+
"quality:mcp-deprecations": "node --input-type=module --eval 'import { main } from \"./scripts/release/mcp-deprecation-inventory.mjs\"; await main()'",
|
|
142
145
|
"quality:defect-evidence": "pnpm build && node scripts/release/defect-evidence-gate.mjs",
|
|
143
146
|
"quality:hosted-analysis": "node scripts/release/hosted-analysis-gate.mjs",
|
|
144
147
|
"benchmark:scale:generate": "node scripts/bench/scale-workspace.mjs",
|
|
@@ -165,7 +168,7 @@
|
|
|
165
168
|
"version:check": "node scripts/release-version.mjs check && node scripts/sync-versions.mjs check",
|
|
166
169
|
"version:next": "node scripts/release-version.mjs next",
|
|
167
170
|
"version:sync": "node scripts/sync-versions.mjs apply",
|
|
168
|
-
"changelog:pm:install": "node dist/cli.js install npm:pm-changelog --project",
|
|
171
|
+
"changelog:pm:install": "node dist/cli.js package install npm:pm-changelog --project",
|
|
169
172
|
"changelog:pm": "pnpm changelog:pm:install && node dist/cli.js changelog generate --output CHANGELOG.md --title \"Changelog\" --mode replace --all-release-tags --status closed --exclude-tag changelog-exclude --item-url-base https://github.com/unbraind/pm-cli/blob/main/.agents/pm",
|
|
170
173
|
"changelog:pm:check": "pnpm changelog:pm:install && node dist/cli.js changelog generate --output CHANGELOG.md --title \"Changelog\" --mode replace --all-release-tags --status closed --exclude-tag changelog-exclude --item-url-base https://github.com/unbraind/pm-cli/blob/main/.agents/pm --check",
|
|
171
174
|
"release:notes": "node scripts/generate-release-notes.mjs",
|
|
@@ -203,24 +206,26 @@
|
|
|
203
206
|
"node": ">=22.18.0"
|
|
204
207
|
},
|
|
205
208
|
"dependencies": {
|
|
206
|
-
"@sentry/node": "10.
|
|
209
|
+
"@sentry/node": "10.71.0",
|
|
207
210
|
"@toon-format/toon": "^4.1.1",
|
|
208
211
|
"@types/node": ">=22",
|
|
209
212
|
"commander": "^15.0.0",
|
|
210
213
|
"fast-glob": "^3.3.3",
|
|
211
214
|
"fast-json-patch": "^3.1.1",
|
|
212
215
|
"npm-package-arg": "^13.0.2",
|
|
213
|
-
"tar": "7.5.22"
|
|
216
|
+
"tar": "7.5.22",
|
|
217
|
+
"yaml": "^2.9.0"
|
|
214
218
|
},
|
|
215
219
|
"devDependencies": {
|
|
220
|
+
"@modelcontextprotocol/ext-apps": "1.7.5",
|
|
216
221
|
"@codspeed/vitest-plugin": "^5.7.1",
|
|
217
222
|
"@eslint/js": "^10.0.1",
|
|
218
223
|
"@sentry/cli": "^3.6.2",
|
|
219
|
-
"@types/node": "^26.
|
|
224
|
+
"@types/node": "^26.3.0",
|
|
220
225
|
"@types/npm-package-arg": "^6.1.4",
|
|
221
226
|
"@vitest/coverage-v8": "^4.1.11",
|
|
222
227
|
"esbuild": "0.28.2",
|
|
223
|
-
"eslint": "^10.9.
|
|
228
|
+
"eslint": "^10.9.1",
|
|
224
229
|
"eslint-plugin-sonarjs": "^4.2.0",
|
|
225
230
|
"eslint-plugin-unicorn": "^73.0.0",
|
|
226
231
|
"fast-check": "^4.9.0",
|
|
@@ -228,8 +233,7 @@
|
|
|
228
233
|
"jscpd": "^5.0.16",
|
|
229
234
|
"tsx": "^4.23.12",
|
|
230
235
|
"typescript": "^6.0.3",
|
|
231
|
-
"typescript-eslint": "^8.
|
|
232
|
-
"vitest": "^4.1.11"
|
|
233
|
-
"yaml": "^2.9.0"
|
|
236
|
+
"typescript-eslint": "^8.68.0",
|
|
237
|
+
"vitest": "^4.1.11"
|
|
234
238
|
}
|
|
235
239
|
}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
# pm Beads Package
|
|
2
2
|
|
|
3
|
-
First-party pm package for
|
|
3
|
+
First-party pm package for lossless Beads migration through public pm SDK
|
|
4
|
+
contracts. The importer preserves issue identity, comments, structured events,
|
|
5
|
+
relationships, labels, and terminal closure evidence before reporting a
|
|
6
|
+
complete count-parity receipt.
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
pm install ./packages/pm-beads --project
|
|
7
|
-
pm beads import --file .beads/issues.jsonl
|
|
8
|
-
```
|
|
8
|
+
## Migration
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Use a current portable backup for lossless relational migration. The focused
|
|
11
|
+
[migration guide](docs/MIGRATION.md) covers installation, source validation,
|
|
12
|
+
ID preservation, legacy exports, parity receipts, and post-import checks.
|
|
13
|
+
|
|
14
|
+
The package exposes the `beads import` extension command through the
|
|
15
|
+
`pm.extensions` package manifest. Runtime sources are TypeScript and use only
|
|
16
|
+
the published `@unbrained/pm-cli/sdk` surface.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Beads Migration
|
|
2
|
+
|
|
3
|
+
Tracker: [pm-tpwde6](../../../.agents/pm/issues/pm-tpwde6.toon)
|
|
4
|
+
|
|
5
|
+
## Lossless portable-backup migration
|
|
6
|
+
|
|
7
|
+
Install the package, create a current Beads portable backup, and import the
|
|
8
|
+
backup directory without modifying the source project:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pm package install ./packages/pm-beads --project
|
|
12
|
+
bd backup --force
|
|
13
|
+
pm beads import --backup-dir .beads/backup --preserve-source-ids
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Current Beads backups contain relational `issues.jsonl`, `comments.jsonl`,
|
|
17
|
+
`events.jsonl`, `dependencies.jsonl`, and `labels.jsonl` files plus
|
|
18
|
+
`backup_state.json`. The importer validates those files, their foreign keys,
|
|
19
|
+
the backup counts, source-ID collisions, and every issue before the first pm
|
|
20
|
+
write. Structural source failures therefore cannot leave a partially imported
|
|
21
|
+
tracker; each later item commit also retains pm's normal lock and rollback
|
|
22
|
+
guarantees.
|
|
23
|
+
|
|
24
|
+
Successful output includes `complete: true`, source and imported counts for
|
|
25
|
+
each relation, and an exact `id_mapping`. Source IDs are preserved only when
|
|
26
|
+
they are safe path identifiers and do not collide case-insensitively with one
|
|
27
|
+
another or with the target tracker. Comments remain comments, Beads events are
|
|
28
|
+
stored as structured JSON notes, dependencies retain their source identity,
|
|
29
|
+
label text is normalized to canonical lowercase pm tags, and a
|
|
30
|
+
terminal Beads close reason becomes the pm resolution when no explicit source
|
|
31
|
+
resolution exists.
|
|
32
|
+
|
|
33
|
+
Verify representative records and the final tracker after import:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pm get Tokenwerk-A1
|
|
37
|
+
pm comments Tokenwerk-A1
|
|
38
|
+
pm validate --check-resolution --check-history-drift
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Legacy single-file import
|
|
42
|
+
|
|
43
|
+
Older JSON/JSONL exports with embedded `comments`, `events`, `dependencies`,
|
|
44
|
+
and `labels` remain supported:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pm beads import --file .beads/issues.jsonl
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
A current plain `bd export` that advertises `comment_count` but omits comment
|
|
51
|
+
bodies is intentionally rejected before any write. Run `bd backup --force` and
|
|
52
|
+
use `--backup-dir` instead so the migration cannot silently lose discussion or
|
|
53
|
+
event history.
|
|
@@ -37,6 +37,7 @@ function toBeadsImportOptions(
|
|
|
37
37
|
): BeadsImportOptions {
|
|
38
38
|
return {
|
|
39
39
|
file: asOptionalString(options.file),
|
|
40
|
+
backupDir: asOptionalString(options.backupDir),
|
|
40
41
|
author: global.author,
|
|
41
42
|
message: asOptionalString(options.message),
|
|
42
43
|
preserveSourceIds: asBoolean(options.preserveSourceIds),
|
|
@@ -69,6 +70,13 @@ export function activate(api: ExtensionApi): void {
|
|
|
69
70
|
value_type: "string",
|
|
70
71
|
description: "Path to the Beads JSONL source file.",
|
|
71
72
|
},
|
|
73
|
+
{
|
|
74
|
+
long: "--backup-dir",
|
|
75
|
+
value_name: "path",
|
|
76
|
+
value_type: "string",
|
|
77
|
+
description:
|
|
78
|
+
"Path to a complete bd portable-backup directory with issue, event, comment, dependency, label, and count files.",
|
|
79
|
+
},
|
|
72
80
|
{
|
|
73
81
|
long: "--message",
|
|
74
82
|
value_name: "text",
|