@unbrained/pm-cli 2026.5.10 → 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.
- package/.claude-plugin/marketplace.json +4 -4
- package/.pi/README.md +10 -1
- package/.pi/agents/pm-triage-agent.md +19 -0
- package/.pi/agents/pm-verification-agent.md +21 -0
- package/.pi/chains/pm-native-delivery.chain.md +11 -0
- package/.pi/extensions/pm-cli/index.js +276 -36
- package/.pi/skills/pm-native/SKILL.md +6 -2
- package/CHANGELOG.md +7 -0
- package/README.md +9 -1
- package/dist/cli/argv-utils.d.ts +5 -0
- package/dist/cli/argv-utils.js +34 -0
- package/dist/cli/argv-utils.js.map +1 -0
- package/dist/cli/bootstrap-args.d.ts +15 -0
- package/dist/cli/bootstrap-args.js +211 -0
- package/dist/cli/bootstrap-args.js.map +1 -1
- package/dist/cli/commander-usage.js +109 -3
- package/dist/cli/commander-usage.js.map +1 -1
- package/dist/cli/commands/completion.js +7 -3
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/contracts.d.ts +19 -0
- package/dist/cli/commands/contracts.js +33 -1
- package/dist/cli/commands/contracts.js.map +1 -1
- package/dist/cli/commands/create.js +112 -51
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/docs.js +9 -2
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/extension.d.ts +3 -1
- package/dist/cli/commands/extension.js +174 -2
- package/dist/cli/commands/extension.js.map +1 -1
- package/dist/cli/commands/files.js +9 -2
- package/dist/cli/commands/files.js.map +1 -1
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.js +21 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/metadata-normalizers.d.ts +4 -0
- package/dist/cli/commands/metadata-normalizers.js +37 -0
- package/dist/cli/commands/metadata-normalizers.js.map +1 -0
- package/dist/cli/commands/reindex.js +173 -135
- package/dist/cli/commands/reindex.js.map +1 -1
- package/dist/cli/commands/search.js +16 -6
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/test.js +9 -2
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update.js +70 -39
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/error-guidance.d.ts +9 -1
- package/dist/cli/error-guidance.js +147 -6
- package/dist/cli/error-guidance.js.map +1 -1
- package/dist/cli/help-json-payload.js +11 -1
- package/dist/cli/help-json-payload.js.map +1 -1
- package/dist/cli/main.js +69 -6
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/register-setup.js +14 -0
- package/dist/cli/register-setup.js.map +1 -1
- package/dist/cli/telemetry-flush.d.ts +2 -0
- package/dist/cli/telemetry-flush.js +4 -0
- package/dist/cli/telemetry-flush.js.map +1 -0
- package/dist/cli.js +1 -2
- package/dist/cli.js.map +1 -1
- package/dist/core/extensions/extension-types.d.ts +72 -0
- package/dist/core/extensions/extension-types.js +24 -0
- package/dist/core/extensions/extension-types.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -0
- package/dist/core/extensions/loader.js +766 -7
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/lock/lock.js +2 -0
- package/dist/core/lock/lock.js.map +1 -1
- package/dist/core/sentry/instrument.d.ts +15 -0
- package/dist/core/sentry/instrument.js +35 -3
- package/dist/core/sentry/instrument.js.map +1 -1
- package/dist/core/shared/constants.js +20 -0
- package/dist/core/shared/constants.js.map +1 -1
- package/dist/core/shared/errors.d.ts +8 -0
- package/dist/core/shared/errors.js.map +1 -1
- package/dist/core/shared/levenshtein.d.ts +1 -0
- package/dist/core/shared/levenshtein.js +37 -0
- package/dist/core/shared/levenshtein.js.map +1 -0
- package/dist/core/store/paths.js +34 -1
- package/dist/core/store/paths.js.map +1 -1
- package/dist/core/store/settings.js +210 -1
- package/dist/core/store/settings.js.map +1 -1
- package/dist/core/telemetry/runtime.d.ts +1 -0
- package/dist/core/telemetry/runtime.js +102 -3
- package/dist/core/telemetry/runtime.js.map +1 -1
- package/dist/mcp/server.js +3 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/pi/native.js +57 -4
- package/dist/pi/native.js.map +1 -1
- package/dist/sdk/cli-contracts.d.ts +21 -1
- package/dist/sdk/cli-contracts.js +250 -0
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/sdk/index.d.ts +12 -1
- package/dist/sdk/index.js +8 -1
- package/dist/sdk/index.js.map +1 -1
- package/dist/types.d.ts +41 -0
- package/dist/types.js.map +1 -1
- package/docs/CLAUDE_CODE_PLUGIN.md +39 -0
- package/docs/EXTENSIONS.md +687 -0
- package/docs/MIGRATION_CLI_SIMPLIFICATION.md +64 -0
- package/docs/PI_PACKAGE.md +95 -10
- package/docs/SDK.md +441 -0
- package/docs/examples/ci/github-actions-pm-extension-gate.yml +53 -0
- package/docs/examples/ci/gitlab-ci-pm-extension-gate.yml +41 -0
- package/docs/examples/ci/jenkins-pm-extension-gate.Jenkinsfile +45 -0
- package/docs/examples/policy-restricted-extension/README.md +74 -0
- package/docs/examples/policy-restricted-extension/index.js +21 -0
- package/docs/examples/policy-restricted-extension/manifest.json +21 -0
- package/docs/examples/policy-restricted-extension/package.json +8 -0
- package/docs/examples/sdk-app-embedding/README.md +39 -0
- package/docs/examples/sdk-app-embedding/package.json +9 -0
- package/docs/examples/sdk-app-embedding/run-embedded-pm.mjs +61 -0
- package/docs/examples/sdk-contract-consumer/README.md +57 -0
- package/docs/examples/sdk-contract-consumer/inspect-contracts.mjs +47 -0
- package/docs/examples/sdk-contract-consumer/package.json +10 -0
- package/docs/examples/starter-extension/README.md +57 -42
- package/docs/examples/starter-extension/manifest.json +15 -0
- package/marketplace.json +3 -3
- package/package.json +1 -1
- package/plugins/pm-cli-claude/.claude-plugin/plugin.json +2 -2
- package/plugins/pm-cli-claude/README.md +55 -14
- package/plugins/pm-cli-claude/agents/pm-delivery-chain.md +88 -0
- package/plugins/pm-cli-claude/agents/pm-triage-agent.md +83 -0
- package/plugins/pm-cli-claude/agents/pm-verification-agent.md +88 -0
- package/plugins/pm-cli-claude/hooks/session-start.mjs +87 -22
package/docs/EXTENSIONS.md
CHANGED
|
@@ -1,5 +1,692 @@
|
|
|
1
1
|
# Extensions
|
|
2
2
|
|
|
3
|
+
Extensions let you add or override `pm` runtime behavior without modifying core `pm-cli` sources.
|
|
4
|
+
|
|
5
|
+
This document is the canonical extension reference for manifest contracts, governance policy, trust and sandbox controls, reload workflows, and diagnostics.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# 1) Scaffold an extension
|
|
11
|
+
pm extension --init ./my-extension
|
|
12
|
+
|
|
13
|
+
# 2) Install in project scope
|
|
14
|
+
pm extension --install --project ./my-extension
|
|
15
|
+
|
|
16
|
+
# 3) Run diagnostics
|
|
17
|
+
pm extension --doctor --project --detail summary
|
|
18
|
+
|
|
19
|
+
# 4) Reload runtime modules after local edits
|
|
20
|
+
pm extension --reload --project
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Extension Locations
|
|
24
|
+
|
|
25
|
+
- project scope: `.agents/pm/extensions/<name>/`
|
|
26
|
+
- global scope: `~/.pm-cli/extensions/<name>/`
|
|
27
|
+
- project entries override global entries for matching command paths
|
|
28
|
+
|
|
29
|
+
Runtime path overrides:
|
|
30
|
+
|
|
31
|
+
- `PM_PATH`: project tracker root override
|
|
32
|
+
- `PM_GLOBAL_PATH`: global profile root override
|
|
33
|
+
|
|
34
|
+
## Manifest Contract
|
|
35
|
+
|
|
36
|
+
### Manifest v1 (supported)
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"name": "my-ext",
|
|
41
|
+
"version": "0.1.0",
|
|
42
|
+
"entry": "./index.js",
|
|
43
|
+
"priority": 100,
|
|
44
|
+
"capabilities": ["commands"]
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Manifest v2 (recommended)
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"name": "my-ext",
|
|
53
|
+
"version": "0.2.0",
|
|
54
|
+
"entry": "./index.js",
|
|
55
|
+
"priority": 100,
|
|
56
|
+
"manifest_version": 2,
|
|
57
|
+
"trusted": true,
|
|
58
|
+
"provenance": {
|
|
59
|
+
"source": "github://org/repo/path",
|
|
60
|
+
"verified": true
|
|
61
|
+
},
|
|
62
|
+
"sandbox_profile": "restricted",
|
|
63
|
+
"permissions": {
|
|
64
|
+
"fs_read": true,
|
|
65
|
+
"fs_write": false,
|
|
66
|
+
"network": false,
|
|
67
|
+
"env_read": true,
|
|
68
|
+
"env_write": false,
|
|
69
|
+
"process_spawn": false
|
|
70
|
+
},
|
|
71
|
+
"capabilities": ["commands", "hooks"]
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Capability values
|
|
76
|
+
|
|
77
|
+
- `commands`
|
|
78
|
+
- `parser`
|
|
79
|
+
- `preflight`
|
|
80
|
+
- `services`
|
|
81
|
+
- `renderers`
|
|
82
|
+
- `hooks`
|
|
83
|
+
- `schema`
|
|
84
|
+
- `importers`
|
|
85
|
+
- `search`
|
|
86
|
+
|
|
87
|
+
## Governance Policy (`extensions.policy`)
|
|
88
|
+
|
|
89
|
+
Policy is configured in `settings.json` under `extensions.policy`.
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"extensions": {
|
|
94
|
+
"policy": {
|
|
95
|
+
"mode": "enforce",
|
|
96
|
+
"trust_mode": "warn",
|
|
97
|
+
"require_provenance": true,
|
|
98
|
+
"default_sandbox_profile": "restricted",
|
|
99
|
+
"allowed_extensions": [],
|
|
100
|
+
"blocked_extensions": [],
|
|
101
|
+
"allowed_capabilities": [],
|
|
102
|
+
"blocked_capabilities": ["services"],
|
|
103
|
+
"allowed_surfaces": [],
|
|
104
|
+
"blocked_surfaces": ["commands.override"],
|
|
105
|
+
"allowed_commands": [],
|
|
106
|
+
"blocked_commands": ["dangerous command"],
|
|
107
|
+
"allowed_actions": [],
|
|
108
|
+
"blocked_actions": ["dangerous-command"],
|
|
109
|
+
"allowed_services": [],
|
|
110
|
+
"blocked_services": ["output_format"]
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Mode semantics:
|
|
117
|
+
|
|
118
|
+
- `mode`: `off|warn|enforce` for extension/capability/surface/command/action/service checks
|
|
119
|
+
- `trust_mode`: `off|warn|enforce` for trust checks
|
|
120
|
+
- `default_sandbox_profile`: `none|restricted|strict`
|
|
121
|
+
|
|
122
|
+
Sandbox profiles:
|
|
123
|
+
|
|
124
|
+
- `none`: no sandbox permission gating
|
|
125
|
+
- `restricted`: blocks sensitive writes and spawn (`process_spawn`, `env_write`)
|
|
126
|
+
- `strict`: blocks spawn/network/write style permissions (`process_spawn`, `network`, `fs_write`, `env_write`)
|
|
127
|
+
|
|
128
|
+
If profile is non-`none` and manifest permissions are missing, policy emits a deterministic warning or block.
|
|
129
|
+
|
|
130
|
+
## Supported Surface Tokens
|
|
131
|
+
|
|
132
|
+
Use these values with `allowed_surfaces` and `blocked_surfaces`:
|
|
133
|
+
|
|
134
|
+
- `commands.override`
|
|
135
|
+
- `commands.handler`
|
|
136
|
+
- `hooks.beforecommand`
|
|
137
|
+
- `hooks.aftercommand`
|
|
138
|
+
- `hooks.onwrite`
|
|
139
|
+
- `hooks.onread`
|
|
140
|
+
- `hooks.onindex`
|
|
141
|
+
- `schema.flags`
|
|
142
|
+
- `schema.itemfields`
|
|
143
|
+
- `schema.itemtypes`
|
|
144
|
+
- `schema.migrations`
|
|
145
|
+
- `parser.override`
|
|
146
|
+
- `preflight.override`
|
|
147
|
+
- `services.override`
|
|
148
|
+
- `renderers.override`
|
|
149
|
+
- `importers.importer`
|
|
150
|
+
- `importers.exporter`
|
|
151
|
+
- `search.provider`
|
|
152
|
+
- `search.vectorstore`
|
|
153
|
+
|
|
154
|
+
## Reload and Watch Workflows
|
|
155
|
+
|
|
156
|
+
Manual reload:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
pm extension --reload --project
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Watch-mode semantics:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
pm extension --reload --project --watch
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
In non-interactive automation, `--watch` performs a deterministic single-pass reload and emits a watch-hint warning.
|
|
169
|
+
|
|
170
|
+
## Diagnostics and Management
|
|
171
|
+
|
|
172
|
+
Basic diagnostics:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
pm extension --doctor --project --detail summary
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Deep diagnostics:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
pm extension --doctor --project --detail deep --trace
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Management commands:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
pm extension --explore
|
|
188
|
+
pm extension --manage --project
|
|
189
|
+
pm extension --manage --project --probe-runtime
|
|
190
|
+
pm extension --manage --project --adopt-unmanaged
|
|
191
|
+
pm extension --activate my-extension --project
|
|
192
|
+
pm extension --deactivate my-extension --project
|
|
193
|
+
pm extension --uninstall my-extension --project
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Common warning prefixes:
|
|
197
|
+
|
|
198
|
+
- `extension_policy_violation_extension`
|
|
199
|
+
- `extension_policy_violation_capability`
|
|
200
|
+
- `extension_policy_violation_registration`
|
|
201
|
+
- `extension_policy_violation_trust`
|
|
202
|
+
- `extension_policy_blocked_extension`
|
|
203
|
+
- `extension_policy_blocked_capability`
|
|
204
|
+
- `extension_policy_blocked_registration`
|
|
205
|
+
- `extension_policy_blocked_trust`
|
|
206
|
+
|
|
207
|
+
## Migration Checklist (v1 -> v2)
|
|
208
|
+
|
|
209
|
+
1. Keep existing manifest fields.
|
|
210
|
+
2. Add `manifest_version: 2`.
|
|
211
|
+
3. Add `trusted`, `provenance`, `sandbox_profile`, and `permissions`.
|
|
212
|
+
4. Extend `extensions.policy` with trust/sandbox and command/action/service controls.
|
|
213
|
+
5. Run:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
pm contracts --json
|
|
217
|
+
pm extension --doctor --project --detail summary --strict-exit
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
6. Resolve warnings before enforcing `mode=enforce` and `trust_mode=enforce`.
|
|
221
|
+
|
|
222
|
+
## Runnable Examples
|
|
223
|
+
|
|
224
|
+
- `docs/examples/starter-extension/`
|
|
225
|
+
- `docs/examples/policy-restricted-extension/`
|
|
226
|
+
- `docs/examples/sdk-contract-consumer/`
|
|
227
|
+
- `docs/examples/sdk-app-embedding/`
|
|
228
|
+
- `docs/examples/ci/github-actions-pm-extension-gate.yml`
|
|
229
|
+
- `docs/examples/ci/gitlab-ci-pm-extension-gate.yml`
|
|
230
|
+
- `docs/examples/ci/jenkins-pm-extension-gate.Jenkinsfile`
|
|
231
|
+
# Extensions
|
|
232
|
+
|
|
233
|
+
Extensions let you add or override `pm` runtime behavior without modifying core `pm-cli`.
|
|
234
|
+
|
|
235
|
+
This guide is the authoritative reference for:
|
|
236
|
+
|
|
237
|
+
- manifest `v1` and `v2` contracts
|
|
238
|
+
- governance policy (`extensions.policy`) controls
|
|
239
|
+
- trust/provenance and sandbox restrictions
|
|
240
|
+
- manual reload and watch-mode workflows
|
|
241
|
+
- migration from policy-only setups to enterprise controls
|
|
242
|
+
|
|
243
|
+
## Quick Start
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
# 1) Scaffold an extension
|
|
247
|
+
pm extension --init ./my-extension
|
|
248
|
+
|
|
249
|
+
# 2) Install in project scope
|
|
250
|
+
pm extension --install --project ./my-extension
|
|
251
|
+
|
|
252
|
+
# 3) Run diagnostics
|
|
253
|
+
pm extension --doctor --project --detail summary
|
|
254
|
+
|
|
255
|
+
# 4) Reload runtime modules after local edits
|
|
256
|
+
pm extension --reload --project
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Delta From Previous Scope
|
|
260
|
+
|
|
261
|
+
Compared to the previous policy-only extension surface, this release adds:
|
|
262
|
+
|
|
263
|
+
- **Manifest v2 metadata** for trust, provenance, sandbox profile, and runtime permission declarations.
|
|
264
|
+
- **Policy v2 controls** for trust mode, provenance requirement, sandbox defaults, and command/action/service allow/block maps.
|
|
265
|
+
- **Registration enforcement upgrades** so command/action/service restrictions are evaluated at registration boundaries.
|
|
266
|
+
- **Hot reload controls** via cache-busted extension reload (`pm extension --reload`) with watch-mode semantics (`--watch`).
|
|
267
|
+
- **Contracts metadata upgrades** for trust/sandbox compatibility information in `pm contracts`.
|
|
268
|
+
|
|
269
|
+
## Extension Locations
|
|
270
|
+
|
|
271
|
+
- Project scope: `.agents/pm/extensions/<name>/`
|
|
272
|
+
- Global scope: `~/.pm-cli/extensions/<name>/`
|
|
273
|
+
- Project entries override global entries when command paths collide.
|
|
274
|
+
|
|
275
|
+
Overrides:
|
|
276
|
+
|
|
277
|
+
- `PM_PATH`: project tracker root override
|
|
278
|
+
- `PM_GLOBAL_PATH`: global profile root override
|
|
279
|
+
|
|
280
|
+
## Manifest Contract
|
|
281
|
+
|
|
282
|
+
### Manifest v1 (still supported)
|
|
283
|
+
|
|
284
|
+
```json
|
|
285
|
+
{
|
|
286
|
+
"name": "my-ext",
|
|
287
|
+
"version": "0.1.0",
|
|
288
|
+
"entry": "./index.js",
|
|
289
|
+
"priority": 100,
|
|
290
|
+
"capabilities": ["commands"]
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Manifest v2 (recommended)
|
|
295
|
+
|
|
296
|
+
```json
|
|
297
|
+
{
|
|
298
|
+
"name": "my-ext",
|
|
299
|
+
"version": "0.2.0",
|
|
300
|
+
"entry": "./index.js",
|
|
301
|
+
"priority": 100,
|
|
302
|
+
"manifest_version": 2,
|
|
303
|
+
"trusted": true,
|
|
304
|
+
"provenance": {
|
|
305
|
+
"source": "github://org/repo/path",
|
|
306
|
+
"verified": true
|
|
307
|
+
},
|
|
308
|
+
"sandbox_profile": "restricted",
|
|
309
|
+
"permissions": {
|
|
310
|
+
"fs_read": true,
|
|
311
|
+
"fs_write": false,
|
|
312
|
+
"network": false,
|
|
313
|
+
"env_read": true,
|
|
314
|
+
"env_write": false,
|
|
315
|
+
"process_spawn": false
|
|
316
|
+
},
|
|
317
|
+
"capabilities": ["commands", "hooks"]
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Capability Values
|
|
322
|
+
|
|
323
|
+
- `commands`
|
|
324
|
+
- `parser`
|
|
325
|
+
- `preflight`
|
|
326
|
+
- `services`
|
|
327
|
+
- `renderers`
|
|
328
|
+
- `hooks`
|
|
329
|
+
- `schema`
|
|
330
|
+
- `importers`
|
|
331
|
+
- `search`
|
|
332
|
+
|
|
333
|
+
## Governance Policy v2
|
|
334
|
+
|
|
335
|
+
Policy is configured under `settings.json` -> `extensions.policy`.
|
|
336
|
+
|
|
337
|
+
```json
|
|
338
|
+
{
|
|
339
|
+
"extensions": {
|
|
340
|
+
"policy": {
|
|
341
|
+
"mode": "enforce",
|
|
342
|
+
"trust_mode": "warn",
|
|
343
|
+
"require_provenance": true,
|
|
344
|
+
"trusted_extensions": ["policy-restricted-extension"],
|
|
345
|
+
"default_sandbox_profile": "restricted",
|
|
346
|
+
"allowed_extensions": [],
|
|
347
|
+
"blocked_extensions": [],
|
|
348
|
+
"allowed_capabilities": [],
|
|
349
|
+
"blocked_capabilities": ["services"],
|
|
350
|
+
"allowed_surfaces": [],
|
|
351
|
+
"blocked_surfaces": ["commands.override"],
|
|
352
|
+
"allowed_commands": [],
|
|
353
|
+
"blocked_commands": ["dangerous command"],
|
|
354
|
+
"allowed_actions": [],
|
|
355
|
+
"blocked_actions": ["dangerous-command"],
|
|
356
|
+
"allowed_services": [],
|
|
357
|
+
"blocked_services": ["output_format"],
|
|
358
|
+
"extension_overrides": [
|
|
359
|
+
{
|
|
360
|
+
"name": "policy-restricted-extension",
|
|
361
|
+
"require_trusted": true,
|
|
362
|
+
"require_provenance": true,
|
|
363
|
+
"sandbox_profile": "strict",
|
|
364
|
+
"allowed_surfaces": ["commands.handler", "hooks.beforecommand"],
|
|
365
|
+
"blocked_surfaces": ["services.override"]
|
|
366
|
+
}
|
|
367
|
+
]
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Mode Semantics
|
|
374
|
+
|
|
375
|
+
- `mode`: `off|warn|enforce` for extension/capability/surface/command/action/service restrictions
|
|
376
|
+
- `trust_mode`: `off|warn|enforce` for trust checks
|
|
377
|
+
- `default_sandbox_profile`: `none|restricted|strict`
|
|
378
|
+
|
|
379
|
+
### Sandbox Profiles
|
|
380
|
+
|
|
381
|
+
Sandbox profiles are policy-driven gates evaluated against manifest permission declarations:
|
|
382
|
+
|
|
383
|
+
- `none`: no sandbox permission gating
|
|
384
|
+
- `restricted`: blocks sensitive writes/spawn (`process_spawn`, `env_write`)
|
|
385
|
+
- `strict`: blocks spawn/network/write-style permissions (`process_spawn`, `network`, `fs_write`, `env_write`)
|
|
386
|
+
|
|
387
|
+
If a non-`none` profile is active and manifest permissions are missing, a deterministic policy warning/block is emitted.
|
|
388
|
+
|
|
389
|
+
### Surface Tokens
|
|
390
|
+
|
|
391
|
+
Supported `allowed_surfaces` / `blocked_surfaces` values:
|
|
392
|
+
|
|
393
|
+
- `commands.override`
|
|
394
|
+
- `commands.handler`
|
|
395
|
+
- `hooks.beforecommand`
|
|
396
|
+
- `hooks.aftercommand`
|
|
397
|
+
- `hooks.onwrite`
|
|
398
|
+
- `hooks.onread`
|
|
399
|
+
- `hooks.onindex`
|
|
400
|
+
- `schema.flags`
|
|
401
|
+
- `schema.itemfields`
|
|
402
|
+
- `schema.itemtypes`
|
|
403
|
+
- `schema.migrations`
|
|
404
|
+
- `parser.override`
|
|
405
|
+
- `preflight.override`
|
|
406
|
+
- `services.override`
|
|
407
|
+
- `renderers.override`
|
|
408
|
+
- `importers.importer`
|
|
409
|
+
- `importers.exporter`
|
|
410
|
+
- `search.provider`
|
|
411
|
+
- `search.vectorstore`
|
|
412
|
+
|
|
413
|
+
## Hot Reload
|
|
414
|
+
|
|
415
|
+
### Manual reload
|
|
416
|
+
|
|
417
|
+
```bash
|
|
418
|
+
pm extension --reload --project
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
This runs extension discovery/load with cache-busted import URLs and returns deterministic load/activation diagnostics.
|
|
422
|
+
|
|
423
|
+
### Watch mode
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
pm extension --reload --project --watch
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
`--watch` enables watch-mode semantics for reload workflows. In non-interactive automation, it executes a deterministic single-pass reload and emits a watch hint warning.
|
|
430
|
+
|
|
431
|
+
## Diagnostics and Warning Codes
|
|
432
|
+
|
|
433
|
+
Common warning prefixes:
|
|
434
|
+
|
|
435
|
+
- `extension_policy_violation_extension`
|
|
436
|
+
- `extension_policy_violation_capability`
|
|
437
|
+
- `extension_policy_violation_registration`
|
|
438
|
+
- `extension_policy_violation_trust`
|
|
439
|
+
- `extension_policy_blocked_extension`
|
|
440
|
+
- `extension_policy_blocked_capability`
|
|
441
|
+
- `extension_policy_blocked_registration`
|
|
442
|
+
- `extension_policy_blocked_trust`
|
|
443
|
+
|
|
444
|
+
Use:
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
pm extension --doctor --project --detail deep --trace
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
for full activation traces.
|
|
451
|
+
|
|
452
|
+
## Migration (v1 -> v2)
|
|
453
|
+
|
|
454
|
+
1. Keep existing manifest fields unchanged.
|
|
455
|
+
2. Add `manifest_version: 2`.
|
|
456
|
+
3. Add `trusted`, `provenance`, `sandbox_profile`, and `permissions`.
|
|
457
|
+
4. Extend `extensions.policy` with trust/sandbox/command-action-service fields.
|
|
458
|
+
5. Run:
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
pm contracts --json
|
|
462
|
+
pm extension --doctor --project --detail summary --strict-exit
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
6. Fix any policy warnings before enforcing (`mode=enforce`, `trust_mode=enforce`).
|
|
466
|
+
|
|
467
|
+
## Runnable Examples
|
|
468
|
+
|
|
469
|
+
- `docs/examples/starter-extension/`
|
|
470
|
+
- `docs/examples/policy-restricted-extension/`
|
|
471
|
+
- `docs/examples/sdk-contract-consumer/`
|
|
472
|
+
- `docs/examples/sdk-app-embedding/`
|
|
473
|
+
- `docs/examples/ci/github-actions-pm-extension-gate.yml`
|
|
474
|
+
- `docs/examples/ci/gitlab-ci-pm-extension-gate.yml`
|
|
475
|
+
- `docs/examples/ci/jenkins-pm-extension-gate.Jenkinsfile`
|
|
476
|
+
# Extensions
|
|
477
|
+
|
|
478
|
+
Extensions let you add or override `pm` runtime behavior without editing core `pm-cli` sources. They are loaded at runtime, gated by manifest capabilities, and now support granular governance policies for capability/surface allow/block controls.
|
|
479
|
+
|
|
480
|
+
## Quick Start
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
# 1) Scaffold a new extension
|
|
484
|
+
pm extension --init ./my-extension
|
|
485
|
+
|
|
486
|
+
# 2) Install into project scope
|
|
487
|
+
pm extension --install --project ./my-extension
|
|
488
|
+
|
|
489
|
+
# 3) Run extension diagnostics
|
|
490
|
+
pm extension --doctor --project --detail summary
|
|
491
|
+
|
|
492
|
+
# 4) Deep diagnostics with traces
|
|
493
|
+
pm extension --doctor --project --detail deep --trace
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Expected summary signals from `extension --doctor`:
|
|
497
|
+
|
|
498
|
+
- `details.summary.status`: `ok` or `warn`
|
|
499
|
+
- `details.summary.warning_codes`: deterministic warning code list
|
|
500
|
+
- `details.summary.policy`: active policy mode and configured counts
|
|
501
|
+
- `details.triage.remediation`: actionable follow-up guidance
|
|
502
|
+
|
|
503
|
+
## Extension Locations and Precedence
|
|
504
|
+
|
|
505
|
+
- Project extensions: `.agents/pm/extensions/<name>/`
|
|
506
|
+
- Global extensions: `~/.pm-cli/extensions/<name>/`
|
|
507
|
+
- Project takes precedence when both scopes register the same command/surface.
|
|
508
|
+
- Discovery and activation remain deterministic across runs.
|
|
509
|
+
|
|
510
|
+
Environment overrides:
|
|
511
|
+
|
|
512
|
+
- `PM_PATH`: project tracker root override
|
|
513
|
+
- `PM_GLOBAL_PATH`: global profile root override
|
|
514
|
+
|
|
515
|
+
## Manifest and Capabilities
|
|
516
|
+
|
|
517
|
+
Minimal `manifest.json`:
|
|
518
|
+
|
|
519
|
+
```json
|
|
520
|
+
{
|
|
521
|
+
"name": "pm-ext-example",
|
|
522
|
+
"version": "0.1.0",
|
|
523
|
+
"entry": "./index.js",
|
|
524
|
+
"priority": 100,
|
|
525
|
+
"capabilities": ["commands"]
|
|
526
|
+
}
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
Rules:
|
|
530
|
+
|
|
531
|
+
- `entry` must resolve inside extension directory (symlink-safe canonical checks apply).
|
|
532
|
+
- Declare only capabilities actually used.
|
|
533
|
+
- Unknown capabilities produce deterministic warnings with guidance.
|
|
534
|
+
- Legacy aliases (`migration`, `validation`) are remapped to `schema` with guidance warnings.
|
|
535
|
+
|
|
536
|
+
Supported capabilities:
|
|
537
|
+
|
|
538
|
+
- `commands`
|
|
539
|
+
- `parser`
|
|
540
|
+
- `preflight`
|
|
541
|
+
- `services`
|
|
542
|
+
- `renderers`
|
|
543
|
+
- `hooks`
|
|
544
|
+
- `schema`
|
|
545
|
+
- `importers`
|
|
546
|
+
- `search`
|
|
547
|
+
|
|
548
|
+
## Governance Policy (Granular Controls)
|
|
549
|
+
|
|
550
|
+
Extension governance policy is configured in `settings.json` under `extensions.policy`.
|
|
551
|
+
|
|
552
|
+
Policy modes:
|
|
553
|
+
|
|
554
|
+
- `off`: no policy enforcement/warnings
|
|
555
|
+
- `warn`: allow registrations but emit policy violation warnings
|
|
556
|
+
- `enforce`: block disallowed extensions/capabilities/surfaces
|
|
557
|
+
|
|
558
|
+
Example policy:
|
|
559
|
+
|
|
560
|
+
```json
|
|
561
|
+
{
|
|
562
|
+
"extensions": {
|
|
563
|
+
"policy": {
|
|
564
|
+
"mode": "enforce",
|
|
565
|
+
"allowed_extensions": ["release-audit-ext"],
|
|
566
|
+
"blocked_extensions": [],
|
|
567
|
+
"allowed_capabilities": [],
|
|
568
|
+
"blocked_capabilities": ["services"],
|
|
569
|
+
"allowed_surfaces": [],
|
|
570
|
+
"blocked_surfaces": ["commands.override"],
|
|
571
|
+
"extension_overrides": [
|
|
572
|
+
{
|
|
573
|
+
"name": "release-audit-ext",
|
|
574
|
+
"allowed_surfaces": ["commands.handler", "hooks.beforecommand"],
|
|
575
|
+
"blocked_surfaces": ["services.override"]
|
|
576
|
+
}
|
|
577
|
+
]
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### Surface Tokens
|
|
584
|
+
|
|
585
|
+
Use these exact values for `allowed_surfaces` / `blocked_surfaces`:
|
|
586
|
+
|
|
587
|
+
- `commands.override`
|
|
588
|
+
- `commands.handler`
|
|
589
|
+
- `hooks.beforecommand`
|
|
590
|
+
- `hooks.aftercommand`
|
|
591
|
+
- `hooks.onwrite`
|
|
592
|
+
- `hooks.onread`
|
|
593
|
+
- `hooks.onindex`
|
|
594
|
+
- `schema.flags`
|
|
595
|
+
- `schema.itemfields`
|
|
596
|
+
- `schema.itemtypes`
|
|
597
|
+
- `schema.migrations`
|
|
598
|
+
- `parser.override`
|
|
599
|
+
- `preflight.override`
|
|
600
|
+
- `services.override`
|
|
601
|
+
- `renderers.override`
|
|
602
|
+
- `importers.importer`
|
|
603
|
+
- `importers.exporter`
|
|
604
|
+
- `search.provider`
|
|
605
|
+
- `search.vectorstore`
|
|
606
|
+
|
|
607
|
+
Policy diagnostics use deterministic warning codes:
|
|
608
|
+
|
|
609
|
+
- `extension_policy_violation_extension`
|
|
610
|
+
- `extension_policy_violation_capability`
|
|
611
|
+
- `extension_policy_violation_registration`
|
|
612
|
+
- `extension_policy_blocked_extension`
|
|
613
|
+
- `extension_policy_blocked_capability`
|
|
614
|
+
- `extension_policy_blocked_registration`
|
|
615
|
+
|
|
616
|
+
## Runtime APIs (Public SDK)
|
|
617
|
+
|
|
618
|
+
Use `@unbrained/pm-cli/sdk` only (no internal imports).
|
|
619
|
+
|
|
620
|
+
- `api.registerCommand(def)` -> `commands`
|
|
621
|
+
- `api.registerParser(command, fn)` -> `parser`
|
|
622
|
+
- `api.registerPreflight(fn)` -> `preflight`
|
|
623
|
+
- `api.registerService(name, fn)` -> `services`
|
|
624
|
+
- `api.registerRenderer(format, fn)` -> `renderers`
|
|
625
|
+
- `api.registerFlags(command, flags)` -> `schema`
|
|
626
|
+
- `api.registerItemFields(fields)` -> `schema`
|
|
627
|
+
- `api.registerItemTypes(types)` -> `schema`
|
|
628
|
+
- `api.registerMigration(def)` -> `schema`
|
|
629
|
+
- `api.registerImporter(name, fn)` -> `importers`
|
|
630
|
+
- `api.registerExporter(name, fn)` -> `importers`
|
|
631
|
+
- `api.registerSearchProvider(provider)` -> `search`
|
|
632
|
+
- `api.registerVectorStoreAdapter(adapter)` -> `search`
|
|
633
|
+
- `api.hooks.beforeCommand/afterCommand/onWrite/onRead/onIndex(fn)` -> `hooks`
|
|
634
|
+
|
|
635
|
+
## Lifecycle Commands
|
|
636
|
+
|
|
637
|
+
```bash
|
|
638
|
+
# Explore
|
|
639
|
+
pm extension --explore --project
|
|
640
|
+
|
|
641
|
+
# Manage (update checks + managed state diagnostics)
|
|
642
|
+
pm extension --manage --project
|
|
643
|
+
|
|
644
|
+
# Optional runtime probe parity in manage mode
|
|
645
|
+
pm extension --manage --project --runtime-probe
|
|
646
|
+
|
|
647
|
+
# Auto-adopt unmanaged extensions into managed state
|
|
648
|
+
pm extension --manage --project --fix-managed-state
|
|
649
|
+
|
|
650
|
+
# Activation/deactivation
|
|
651
|
+
pm extension --activate my-extension --project
|
|
652
|
+
pm extension --deactivate my-extension --project
|
|
653
|
+
|
|
654
|
+
# Uninstall
|
|
655
|
+
pm extension --uninstall my-extension --project
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
## Non-Interactive Automation Patterns
|
|
659
|
+
|
|
660
|
+
For CI/CD and agents:
|
|
661
|
+
|
|
662
|
+
- Prefer `--json` outputs.
|
|
663
|
+
- Use `pm contracts --schema-only --json` before invoking action payloads.
|
|
664
|
+
- Run `pm extension --doctor --detail summary --strict-exit` as a gate.
|
|
665
|
+
- Add `--detail deep --trace` on failure paths for remediation payloads.
|
|
666
|
+
- Use `--no-extensions` as a deterministic fallback for core-only triage.
|
|
667
|
+
|
|
668
|
+
## Runnable Examples
|
|
669
|
+
|
|
670
|
+
- Full starter extension: `docs/examples/starter-extension/`
|
|
671
|
+
- Capability-restricted policy example: `docs/examples/policy-restricted-extension/`
|
|
672
|
+
- Programmatic contracts consumer: `docs/examples/sdk-contract-consumer/`
|
|
673
|
+
- CI gating workflow: `docs/examples/ci/github-actions-pm-extension-gate.yml`
|
|
674
|
+
|
|
675
|
+
## Troubleshooting
|
|
676
|
+
|
|
677
|
+
- Manifest/entry failures: run `pm extension --explore --project`
|
|
678
|
+
- Activation failures: run `pm extension --doctor --detail deep --trace`
|
|
679
|
+
- Policy blocks: review `settings.extensions.policy` and `details.summary.policy`
|
|
680
|
+
- Runtime drift suspicion: compare with `pm --no-extensions <command>`
|
|
681
|
+
- Managed-state update-check gaps: run `pm extension --manage --fix-managed-state`
|
|
682
|
+
|
|
683
|
+
## Related Docs
|
|
684
|
+
|
|
685
|
+
- `docs/SDK.md`
|
|
686
|
+
- `docs/examples/starter-extension/README.md`
|
|
687
|
+
- `docs/CLAUDE_CODE_PLUGIN.md`
|
|
688
|
+
# Extensions
|
|
689
|
+
|
|
3
690
|
Extensions add commands, schema, renderers, importers/exporters, search adapters, lifecycle hooks, and selected runtime overrides without modifying core `pm-cli`.
|
|
4
691
|
|
|
5
692
|
## Agent Quick Context
|