@unbrained/pm-cli 2026.3.12 → 2026.5.1
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/pm/extensions/.managed-extensions.json +42 -0
- package/.agents/pm/extensions/beads/index.js +109 -0
- package/.agents/pm/extensions/beads/manifest.json +7 -0
- package/{dist/cli/commands/beads.js → .agents/pm/extensions/beads/runtime.js} +31 -21
- package/.agents/pm/extensions/beads/runtime.ts +702 -0
- package/.agents/pm/extensions/todos/index.js +126 -0
- package/.agents/pm/extensions/todos/manifest.json +7 -0
- package/{dist/extensions/builtins/todos/import-export.js → .agents/pm/extensions/todos/runtime.js} +39 -29
- package/.agents/pm/extensions/todos/runtime.ts +568 -0
- package/AGENTS.md +196 -92
- package/CHANGELOG.md +399 -0
- package/CODE_OF_CONDUCT.md +42 -0
- package/CONTRIBUTING.md +144 -0
- package/PRD.md +512 -164
- package/README.md +1053 -2
- package/SECURITY.md +51 -0
- package/dist/cli/commands/activity.d.ts +5 -0
- package/dist/cli/commands/activity.js +66 -3
- package/dist/cli/commands/activity.js.map +1 -1
- package/dist/cli/commands/aggregate.d.ts +54 -0
- package/dist/cli/commands/aggregate.js +181 -0
- package/dist/cli/commands/aggregate.js.map +1 -0
- package/dist/cli/commands/append.js +4 -1
- package/dist/cli/commands/append.js.map +1 -1
- package/dist/cli/commands/calendar.d.ts +109 -0
- package/dist/cli/commands/calendar.js +797 -0
- package/dist/cli/commands/calendar.js.map +1 -0
- package/dist/cli/commands/claim.d.ts +5 -1
- package/dist/cli/commands/claim.js +42 -21
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/close.d.ts +1 -0
- package/dist/cli/commands/close.js +54 -5
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/comments-audit.d.ts +91 -0
- package/dist/cli/commands/comments-audit.js +195 -0
- package/dist/cli/commands/comments-audit.js.map +1 -0
- package/dist/cli/commands/comments.d.ts +1 -0
- package/dist/cli/commands/comments.js +70 -21
- package/dist/cli/commands/comments.js.map +1 -1
- package/dist/cli/commands/completion.d.ts +10 -4
- package/dist/cli/commands/completion.js +1184 -137
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/config.d.ts +35 -3
- package/dist/cli/commands/config.js +968 -13
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/context.d.ts +86 -0
- package/dist/cli/commands/context.js +299 -0
- package/dist/cli/commands/context.js.map +1 -0
- package/dist/cli/commands/contracts.d.ts +78 -0
- package/dist/cli/commands/contracts.js +920 -0
- package/dist/cli/commands/contracts.js.map +1 -0
- package/dist/cli/commands/create.d.ts +48 -14
- package/dist/cli/commands/create.js +1331 -160
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/dedupe-audit.d.ts +81 -0
- package/dist/cli/commands/dedupe-audit.js +330 -0
- package/dist/cli/commands/dedupe-audit.js.map +1 -0
- package/dist/cli/commands/deps.d.ts +52 -0
- package/dist/cli/commands/deps.js +204 -0
- package/dist/cli/commands/deps.js.map +1 -0
- package/dist/cli/commands/docs.d.ts +19 -0
- package/dist/cli/commands/docs.js +212 -13
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/extension.d.ts +122 -0
- package/dist/cli/commands/extension.js +1850 -0
- package/dist/cli/commands/extension.js.map +1 -0
- package/dist/cli/commands/files.d.ts +52 -1
- package/dist/cli/commands/files.js +443 -13
- package/dist/cli/commands/files.js.map +1 -1
- package/dist/cli/commands/gc.d.ts +11 -1
- package/dist/cli/commands/gc.js +89 -11
- package/dist/cli/commands/gc.js.map +1 -1
- package/dist/cli/commands/get.d.ts +13 -0
- package/dist/cli/commands/get.js +35 -3
- package/dist/cli/commands/get.js.map +1 -1
- package/dist/cli/commands/health.d.ts +10 -2
- package/dist/cli/commands/health.js +774 -23
- package/dist/cli/commands/health.js.map +1 -1
- package/dist/cli/commands/history.d.ts +20 -0
- package/dist/cli/commands/history.js +152 -6
- package/dist/cli/commands/history.js.map +1 -1
- package/dist/cli/commands/index.d.ts +16 -3
- package/dist/cli/commands/index.js +16 -3
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +7 -2
- package/dist/cli/commands/init.js +137 -5
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/learnings.d.ts +17 -0
- package/dist/cli/commands/learnings.js +129 -0
- package/dist/cli/commands/learnings.js.map +1 -0
- package/dist/cli/commands/list.d.ts +29 -1
- package/dist/cli/commands/list.js +289 -53
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/normalize.d.ts +51 -0
- package/dist/cli/commands/normalize.js +298 -0
- package/dist/cli/commands/normalize.js.map +1 -0
- package/dist/cli/commands/notes.d.ts +17 -0
- package/dist/cli/commands/notes.js +129 -0
- package/dist/cli/commands/notes.js.map +1 -0
- package/dist/cli/commands/reindex.d.ts +1 -0
- package/dist/cli/commands/reindex.js +208 -32
- package/dist/cli/commands/reindex.js.map +1 -1
- package/dist/cli/commands/restore.js +164 -30
- package/dist/cli/commands/restore.js.map +1 -1
- package/dist/cli/commands/search.d.ts +14 -1
- package/dist/cli/commands/search.js +475 -81
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/stats.js +26 -10
- package/dist/cli/commands/stats.js.map +1 -1
- package/dist/cli/commands/templates.d.ts +26 -0
- package/dist/cli/commands/templates.js +179 -0
- package/dist/cli/commands/templates.js.map +1 -0
- package/dist/cli/commands/test-all.d.ts +19 -1
- package/dist/cli/commands/test-all.js +161 -13
- package/dist/cli/commands/test-all.js.map +1 -1
- package/dist/cli/commands/test-runs.d.ts +63 -0
- package/dist/cli/commands/test-runs.js +179 -0
- package/dist/cli/commands/test-runs.js.map +1 -0
- package/dist/cli/commands/test.d.ts +75 -1
- package/dist/cli/commands/test.js +1360 -41
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update-many.d.ts +57 -0
- package/dist/cli/commands/update-many.js +631 -0
- package/dist/cli/commands/update-many.js.map +1 -0
- package/dist/cli/commands/update.d.ts +30 -0
- package/dist/cli/commands/update.js +1393 -84
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +30 -0
- package/dist/cli/commands/validate.js +1140 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/error-guidance.d.ts +33 -0
- package/dist/cli/error-guidance.js +337 -0
- package/dist/cli/error-guidance.js.map +1 -0
- package/dist/cli/extension-command-options.d.ts +1 -0
- package/dist/cli/extension-command-options.js +92 -0
- package/dist/cli/extension-command-options.js.map +1 -1
- package/dist/cli/help-content.d.ts +20 -0
- package/dist/cli/help-content.js +543 -0
- package/dist/cli/help-content.js.map +1 -0
- package/dist/cli/main.js +3625 -445
- package/dist/cli/main.js.map +1 -1
- package/dist/core/extensions/index.d.ts +13 -1
- package/dist/core/extensions/index.js +108 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/item-fields.d.ts +2 -0
- package/dist/core/extensions/item-fields.js +79 -0
- package/dist/core/extensions/item-fields.js.map +1 -0
- package/dist/core/extensions/loader.d.ts +322 -9
- package/dist/core/extensions/loader.js +911 -20
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runtime-registrations.d.ts +5 -0
- package/dist/core/extensions/runtime-registrations.js +51 -0
- package/dist/core/extensions/runtime-registrations.js.map +1 -0
- package/dist/core/history/history-stream-policy.d.ts +20 -0
- package/dist/core/history/history-stream-policy.js +53 -0
- package/dist/core/history/history-stream-policy.js.map +1 -0
- package/dist/core/history/history.js +90 -1
- package/dist/core/history/history.js.map +1 -1
- package/dist/core/item/id.js +4 -1
- package/dist/core/item/id.js.map +1 -1
- package/dist/core/item/index.d.ts +1 -0
- package/dist/core/item/index.js +1 -0
- package/dist/core/item/index.js.map +1 -1
- package/dist/core/item/item-format.d.ts +11 -5
- package/dist/core/item/item-format.js +507 -24
- package/dist/core/item/item-format.js.map +1 -1
- package/dist/core/item/parent-reference-policy.d.ts +6 -0
- package/dist/core/item/parent-reference-policy.js +32 -0
- package/dist/core/item/parent-reference-policy.js.map +1 -0
- package/dist/core/item/parse.d.ts +5 -0
- package/dist/core/item/parse.js +216 -19
- package/dist/core/item/parse.js.map +1 -1
- package/dist/core/item/sprint-release-format.d.ts +6 -0
- package/dist/core/item/sprint-release-format.js +33 -0
- package/dist/core/item/sprint-release-format.js.map +1 -0
- package/dist/core/item/status.d.ts +3 -0
- package/dist/core/item/status.js +24 -0
- package/dist/core/item/status.js.map +1 -0
- package/dist/core/item/type-registry.d.ts +37 -0
- package/dist/core/item/type-registry.js +706 -0
- package/dist/core/item/type-registry.js.map +1 -0
- package/dist/core/lock/lock.d.ts +1 -1
- package/dist/core/lock/lock.js +101 -12
- package/dist/core/lock/lock.js.map +1 -1
- package/dist/core/output/command-aware.d.ts +1 -0
- package/dist/core/output/command-aware.js +394 -0
- package/dist/core/output/command-aware.js.map +1 -0
- package/dist/core/output/output.d.ts +3 -0
- package/dist/core/output/output.js +124 -6
- package/dist/core/output/output.js.map +1 -1
- package/dist/core/schema/runtime-field-filters.d.ts +3 -0
- package/dist/core/schema/runtime-field-filters.js +39 -0
- package/dist/core/schema/runtime-field-filters.js.map +1 -0
- package/dist/core/schema/runtime-field-values.d.ts +8 -0
- package/dist/core/schema/runtime-field-values.js +154 -0
- package/dist/core/schema/runtime-field-values.js.map +1 -0
- package/dist/core/schema/runtime-schema.d.ts +68 -0
- package/dist/core/schema/runtime-schema.js +554 -0
- package/dist/core/schema/runtime-schema.js.map +1 -0
- package/dist/core/search/cache.d.ts +13 -1
- package/dist/core/search/cache.js +123 -14
- package/dist/core/search/cache.js.map +1 -1
- package/dist/core/search/semantic-defaults.d.ts +6 -0
- package/dist/core/search/semantic-defaults.js +120 -0
- package/dist/core/search/semantic-defaults.js.map +1 -0
- package/dist/core/search/vector-stores.js +3 -1
- package/dist/core/search/vector-stores.js.map +1 -1
- package/dist/core/shared/command-types.d.ts +2 -0
- package/dist/core/shared/conflict-markers.d.ts +7 -0
- package/dist/core/shared/conflict-markers.js +27 -0
- package/dist/core/shared/conflict-markers.js.map +1 -0
- package/dist/core/shared/constants.d.ts +15 -4
- package/dist/core/shared/constants.js +141 -1
- package/dist/core/shared/constants.js.map +1 -1
- package/dist/core/shared/errors.d.ts +10 -1
- package/dist/core/shared/errors.js +3 -1
- package/dist/core/shared/errors.js.map +1 -1
- package/dist/core/shared/text-normalization.d.ts +4 -0
- package/dist/core/shared/text-normalization.js +33 -0
- package/dist/core/shared/text-normalization.js.map +1 -0
- package/dist/core/shared/time.d.ts +1 -2
- package/dist/core/shared/time.js +98 -11
- package/dist/core/shared/time.js.map +1 -1
- package/dist/core/store/index.d.ts +1 -0
- package/dist/core/store/index.js +1 -0
- package/dist/core/store/index.js.map +1 -1
- package/dist/core/store/item-format-migration.d.ts +9 -0
- package/dist/core/store/item-format-migration.js +87 -0
- package/dist/core/store/item-format-migration.js.map +1 -0
- package/dist/core/store/item-store.d.ts +13 -4
- package/dist/core/store/item-store.js +238 -51
- package/dist/core/store/item-store.js.map +1 -1
- package/dist/core/store/paths.d.ts +21 -3
- package/dist/core/store/paths.js +59 -4
- package/dist/core/store/paths.js.map +1 -1
- package/dist/core/store/settings.d.ts +14 -1
- package/dist/core/store/settings.js +463 -7
- package/dist/core/store/settings.js.map +1 -1
- package/dist/core/telemetry/consent.d.ts +2 -0
- package/dist/core/telemetry/consent.js +79 -0
- package/dist/core/telemetry/consent.js.map +1 -0
- package/dist/core/telemetry/runtime.d.ts +38 -0
- package/dist/core/telemetry/runtime.js +733 -0
- package/dist/core/telemetry/runtime.js.map +1 -0
- package/dist/core/test/background-runs.d.ts +117 -0
- package/dist/core/test/background-runs.js +760 -0
- package/dist/core/test/background-runs.js.map +1 -0
- package/dist/core/test/item-test-run-tracking.d.ts +9 -0
- package/dist/core/test/item-test-run-tracking.js +50 -0
- package/dist/core/test/item-test-run-tracking.js.map +1 -0
- package/dist/sdk/cli-contracts.d.ts +92 -0
- package/dist/sdk/cli-contracts.js +2357 -0
- package/dist/sdk/cli-contracts.js.map +1 -0
- package/dist/sdk/index.d.ts +34 -0
- package/dist/sdk/index.js +23 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/types.d.ts +197 -3
- package/dist/types.js +48 -1
- package/dist/types.js.map +1 -1
- package/docs/ARCHITECTURE.md +368 -39
- package/docs/EXTENSIONS.md +454 -49
- package/docs/RELEASING.md +68 -19
- package/docs/SDK.md +123 -0
- package/docs/examples/starter-extension/README.md +48 -0
- package/docs/examples/starter-extension/index.js +191 -0
- package/docs/examples/starter-extension/manifest.json +17 -0
- package/docs/examples/starter-extension/package.json +10 -0
- package/package.json +33 -6
- package/.pi/extensions/pm-cli/index.ts +0 -778
- package/dist/cli/commands/beads.d.ts +0 -16
- package/dist/cli/commands/beads.js.map +0 -1
- package/dist/cli/commands/install.d.ts +0 -18
- package/dist/cli/commands/install.js +0 -87
- package/dist/cli/commands/install.js.map +0 -1
- package/dist/core/extensions/builtins.d.ts +0 -3
- package/dist/core/extensions/builtins.js +0 -47
- package/dist/core/extensions/builtins.js.map +0 -1
- package/dist/extensions/builtins/beads/index.d.ts +0 -8
- package/dist/extensions/builtins/beads/index.js +0 -33
- package/dist/extensions/builtins/beads/index.js.map +0 -1
- package/dist/extensions/builtins/todos/import-export.d.ts +0 -26
- package/dist/extensions/builtins/todos/import-export.js.map +0 -1
- package/dist/extensions/builtins/todos/index.d.ts +0 -8
- package/dist/extensions/builtins/todos/index.js +0 -38
- package/dist/extensions/builtins/todos/index.js.map +0 -1
package/docs/RELEASING.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Releasing `@unbrained/pm-cli`
|
|
2
2
|
|
|
3
|
-
This repository uses a tag-driven GitHub Actions
|
|
3
|
+
This repository uses a tag-driven GitHub Actions pipeline that publishes to npm and creates a GitHub Release. The pipeline uses standard GitHub Actions, repository or environment secrets, artifacts, and npm provenance; it does not require paid GitHub features or paid-only environment protection rules.
|
|
4
4
|
|
|
5
|
-
## Version
|
|
5
|
+
## Version Policy
|
|
6
6
|
|
|
7
7
|
`pm-cli` uses a calendar SemVer-compatible scheme:
|
|
8
8
|
|
|
@@ -14,24 +14,40 @@ Examples:
|
|
|
14
14
|
- First release on 2026-03-09: `2026.3.9`
|
|
15
15
|
- Second release on 2026-03-09: `2026.3.9-2`
|
|
16
16
|
|
|
17
|
-
Use:
|
|
17
|
+
Use this to compute the next expected release version from the npm registry:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
pnpm version:next
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
The release workflow enforces the package version, tag name, calendar date, and npm registry sequencing before publishing.
|
|
24
24
|
|
|
25
|
-
## One-
|
|
25
|
+
## One-Time Setup
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
27
|
+
- Add `NPM_TOKEN` as a GitHub Environment or repository secret named `NPM_TOKEN`.
|
|
28
|
+
- If using an Environment named `release`, keep it free-feature compatible: no paid-only reviewer or deployment-protection requirements.
|
|
29
|
+
- Ensure `GITHUB_TOKEN` has the default workflow permission needed by `permissions: contents: write` for GitHub Release creation.
|
|
30
|
+
- Keep npm two-factor settings compatible with automation tokens and provenance publishing.
|
|
31
|
+
- Keep `package.json` repository, homepage, and bugs URLs aligned with the canonical GitHub source repository (`https://github.com/unbraind/pm-cli`); npm provenance validation rejects mismatched repository metadata.
|
|
29
32
|
|
|
30
|
-
## Release
|
|
33
|
+
## Local Release Checklist
|
|
31
34
|
|
|
32
|
-
1
|
|
35
|
+
1. Confirm the next version:
|
|
33
36
|
|
|
34
|
-
|
|
37
|
+
```bash
|
|
38
|
+
pnpm version:next
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
2. Update `package.json`, `pnpm-lock.yaml`, and `CHANGELOG.md`.
|
|
42
|
+
|
|
43
|
+
3. Generate release notes locally from changelog + pm tracker data:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pnpm build
|
|
47
|
+
pnpm release:notes -- --version "$(node -p 'require("./package.json").version')" --output /tmp/pm-cli-release-notes.md
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
4. Run local release gates:
|
|
35
51
|
|
|
36
52
|
```bash
|
|
37
53
|
pnpm install
|
|
@@ -39,27 +55,60 @@ pnpm build
|
|
|
39
55
|
pnpm typecheck
|
|
40
56
|
pnpm test
|
|
41
57
|
pnpm test:coverage
|
|
58
|
+
node scripts/run-tests.mjs coverage
|
|
42
59
|
pnpm version:check
|
|
43
60
|
pnpm security:scan
|
|
44
61
|
pnpm smoke:npx
|
|
45
62
|
```
|
|
46
63
|
|
|
47
|
-
|
|
64
|
+
5. Verify previous-version tracker compatibility before tagging. Use a temporary project with the previously published package, create representative items, then run the current build against the same sandboxed `PM_PATH` and `PM_GLOBAL_PATH`. Confirm item count, fields, linked files/docs/tests, comments, close metadata, health, and history drift checks remain intact.
|
|
65
|
+
|
|
66
|
+
6. Commit, push, tag, and push the tag:
|
|
48
67
|
|
|
49
68
|
```bash
|
|
50
|
-
git tag v<version>
|
|
51
69
|
git push origin main
|
|
70
|
+
git tag v<version>
|
|
52
71
|
git push origin v<version>
|
|
53
72
|
```
|
|
54
73
|
|
|
55
|
-
|
|
74
|
+
## Release Workflow
|
|
75
|
+
|
|
76
|
+
`.github/workflows/release.yml` runs on `v*.*.*` tags and performs:
|
|
77
|
+
|
|
78
|
+
- full-history checkout for previous-tag and release-note generation
|
|
79
|
+
- pnpm install with frozen lockfile
|
|
80
|
+
- version policy and tag guard
|
|
81
|
+
- secret leak scan
|
|
82
|
+
- build, typecheck, test coverage, and sandboxed pm coverage
|
|
83
|
+
- npm pack dry run and npx tarball smoke test
|
|
84
|
+
- generated release notes from `CHANGELOG.md` plus sanitized `pm` tracker metadata
|
|
85
|
+
- coverage and release-note artifact uploads
|
|
86
|
+
- `npm publish --access public --provenance`
|
|
87
|
+
- GitHub Release creation using the generated release-note body
|
|
88
|
+
|
|
89
|
+
Monitor with:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
gh run list --workflow Release --limit 5
|
|
93
|
+
gh run watch <run-id> --exit-status
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Post-Release Verification
|
|
97
|
+
|
|
98
|
+
After the workflow succeeds, verify all distribution paths:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm view @unbrained/pm-cli@<version> version dist.integrity dist.unpackedSize --json
|
|
102
|
+
npx --yes @unbrained/pm-cli@<version> --version
|
|
103
|
+
bunx @unbrained/pm-cli@<version> --version
|
|
104
|
+
gh release view v<version> --json tagName,name,isDraft,isPrerelease,url
|
|
105
|
+
```
|
|
56
106
|
|
|
57
|
-
|
|
58
|
-
- `Release` workflow passes for tag
|
|
59
|
-
- npm package published at `@unbrained/pm-cli`
|
|
60
|
-
- GitHub Release created with generated notes
|
|
107
|
+
The `pm` executable name remains unchanged even though the npm package is scoped.
|
|
61
108
|
|
|
62
|
-
##
|
|
109
|
+
## Failure Handling
|
|
63
110
|
|
|
64
111
|
- Do not run manual `npm publish`; publishing is owned by `.github/workflows/release.yml`.
|
|
65
|
-
-
|
|
112
|
+
- If local gates fail, fix the code/docs/tests and rerun the checklist before tagging.
|
|
113
|
+
- If the tag workflow fails before npm publish, fix the issue, move the tag only after confirming no package was published, and rerun the workflow.
|
|
114
|
+
- If npm publish succeeds but GitHub Release creation fails, rerun only the release creation after confirming the tag and package are correct.
|
package/docs/SDK.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# pm SDK Guide
|
|
2
|
+
|
|
3
|
+
This guide documents the public SDK surface for extension authors.
|
|
4
|
+
|
|
5
|
+
Primary import:
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { defineExtension } from "@unbrained/pm-cli/sdk";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Use this document for SDK/API contracts. Use `docs/EXTENSIONS.md` for full runtime lifecycle behavior and `pm extension --init ./my-extension` for starter scaffold generation.
|
|
12
|
+
|
|
13
|
+
## Import Surfaces
|
|
14
|
+
|
|
15
|
+
- `@unbrained/pm-cli/sdk`: stable extension authoring API and CLI contract exports.
|
|
16
|
+
- `@unbrained/pm-cli/cli`: runtime CLI module entrypoint. This path is for runtime module resolution, not a typed library API; its declaration file intentionally exports no symbols.
|
|
17
|
+
|
|
18
|
+
## Public SDK Exports
|
|
19
|
+
|
|
20
|
+
Source of truth:
|
|
21
|
+
|
|
22
|
+
- `src/sdk/index.ts`
|
|
23
|
+
- `src/sdk/cli-contracts.ts`
|
|
24
|
+
|
|
25
|
+
### Extension authoring values
|
|
26
|
+
|
|
27
|
+
- `defineExtension(...)`
|
|
28
|
+
- `EXTENSION_CAPABILITIES`
|
|
29
|
+
- `EXTENSION_CAPABILITY_CONTRACT`
|
|
30
|
+
- `EXTENSION_CAPABILITY_CONTRACT_VERSION`
|
|
31
|
+
- `EXTENSION_CAPABILITY_LEGACY_ALIASES`
|
|
32
|
+
|
|
33
|
+
### CLI/action contract values
|
|
34
|
+
|
|
35
|
+
- `PM_CORE_COMMAND_NAMES`
|
|
36
|
+
- `PM_TOOL_ACTIONS`
|
|
37
|
+
- `PM_TOOL_PARAMETERS_SCHEMA`
|
|
38
|
+
- `PM_EXTENSION_CAPABILITY_CONTRACTS`
|
|
39
|
+
- `PM_EXTENSION_SERVICE_NAME_CONTRACTS`
|
|
40
|
+
- all exported `...FLAG_CONTRACTS`, `...OPTION_CONTRACTS`, and `...COMMANDER_*_CONTRACTS` arrays from `src/sdk/cli-contracts.ts`
|
|
41
|
+
|
|
42
|
+
### CLI/action contract helpers
|
|
43
|
+
|
|
44
|
+
- `withFlagAliasMetadata(...)`
|
|
45
|
+
- `toCompletionFlagString(...)`
|
|
46
|
+
- `readFirstStringFromCommanderOptions(...)`
|
|
47
|
+
- `readStringArrayFromCommanderOptions(...)`
|
|
48
|
+
|
|
49
|
+
### Key type exports
|
|
50
|
+
|
|
51
|
+
- extension capability/types: `ExtensionCapability`, `PmToolAction`, `PmExtensionCapabilityContract`, `PmExtensionServiceNameContract`
|
|
52
|
+
- command/flag/type helpers: `CommandDefinition`, `ExtensionCommandArgumentDefinition`, `FlagDefinition`, `SchemaFieldDefinition`, `SchemaItemTypeDefinition`
|
|
53
|
+
- runtime extension API types: `ExtensionApi`, `ExtensionManifest`, lifecycle hook context types, importer/exporter contexts, search provider types, vector adapter types
|
|
54
|
+
- shared command/settings types: `GlobalOptions`, `PmSettings`
|
|
55
|
+
|
|
56
|
+
## Capability Requirements (Quick Reference)
|
|
57
|
+
|
|
58
|
+
Declare capabilities in `manifest.json`; runtime gating is strict.
|
|
59
|
+
|
|
60
|
+
- `registerCommand(...)`: requires `commands`
|
|
61
|
+
- `registerCommand({ flags: [...] })` and `registerFlags(...)`: require `schema`
|
|
62
|
+
- `registerItemFields(...)`, `registerItemTypes(...)`, `registerMigration(...)`: require `schema`
|
|
63
|
+
- `registerImporter(...)` and `registerExporter(...)`: require `importers`
|
|
64
|
+
- `registerParser(...)`: requires `parser`
|
|
65
|
+
- `registerPreflight(...)`: requires `preflight`
|
|
66
|
+
- `registerService(...)`: requires `services`
|
|
67
|
+
- `registerRenderer(...)`: requires `renderers`
|
|
68
|
+
- lifecycle hooks (`beforeCommand`, `afterCommand`, `onWrite`, `onRead`, `onIndex`): require `hooks`
|
|
69
|
+
- `registerSearchProvider(...)` and `registerVectorStoreAdapter(...)`: require `search`
|
|
70
|
+
|
|
71
|
+
## Minimal Extension
|
|
72
|
+
|
|
73
|
+
`manifest.json`:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"name": "hello-extension",
|
|
78
|
+
"version": "0.1.0",
|
|
79
|
+
"entry": "./index.js",
|
|
80
|
+
"capabilities": ["commands"]
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`index.js`:
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
import { defineExtension } from "@unbrained/pm-cli/sdk";
|
|
88
|
+
|
|
89
|
+
export default defineExtension({
|
|
90
|
+
activate(api) {
|
|
91
|
+
api.registerCommand({
|
|
92
|
+
name: "hello",
|
|
93
|
+
run: async () => ({ ok: true, message: "hello from sdk extension" }),
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Typed Authoring Highlights
|
|
100
|
+
|
|
101
|
+
The SDK provides explicit interfaces for key surfaces including:
|
|
102
|
+
|
|
103
|
+
- `CommandDefinition` and `ExtensionCommandArgumentDefinition`
|
|
104
|
+
- `FlagDefinition`
|
|
105
|
+
- `SchemaFieldDefinition`, `SchemaItemTypeDefinition`, `SchemaMigrationDefinition`
|
|
106
|
+
- `ImportExportContext`
|
|
107
|
+
- `SearchProviderDefinition`, `SearchProviderQueryContext`, `SearchProviderHit`
|
|
108
|
+
- `VectorStoreAdapterDefinition`, `VectorStoreQueryContext`, `VectorStoreUpsertContext`
|
|
109
|
+
|
|
110
|
+
These interfaces intentionally allow additive metadata (`[key: string]: unknown`) where extension-defined metadata is expected.
|
|
111
|
+
|
|
112
|
+
## Recommended Authoring Pattern
|
|
113
|
+
|
|
114
|
+
- keep command handlers deterministic and JSON-like
|
|
115
|
+
- keep renderer/service overrides narrow to specific command paths
|
|
116
|
+
- prefer additive hooks and schema fields over global behavior changes
|
|
117
|
+
- ship one extension folder with `manifest.json`, an entry module, and package metadata/dependencies
|
|
118
|
+
|
|
119
|
+
## Related Docs
|
|
120
|
+
|
|
121
|
+
- full extension lifecycle/runtime reference: `docs/EXTENSIONS.md`
|
|
122
|
+
- architecture internals: `docs/ARCHITECTURE.md`
|
|
123
|
+
- complete starter scaffold: `docs/examples/starter-extension/`
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Starter Extension (All 9 Capabilities)
|
|
2
|
+
|
|
3
|
+
This example demonstrates a single extension that uses the public SDK only:
|
|
4
|
+
`@unbrained/pm-cli/sdk`.
|
|
5
|
+
|
|
6
|
+
It is intentionally small and "feature complete" as a reference scaffold.
|
|
7
|
+
|
|
8
|
+
## Files
|
|
9
|
+
|
|
10
|
+
- `manifest.json` declares all 9 capabilities.
|
|
11
|
+
- `package.json` declares the SDK dependency.
|
|
12
|
+
- `index.js` registers one or more examples for each capability.
|
|
13
|
+
|
|
14
|
+
## Capability Coverage
|
|
15
|
+
|
|
16
|
+
1. `commands` - `api.registerCommand(...)` + `api.registerFlags(...)`
|
|
17
|
+
2. `parser` - `api.registerParser(...)`
|
|
18
|
+
3. `preflight` - `api.registerPreflight(...)`
|
|
19
|
+
4. `services` - `api.registerService(...)`
|
|
20
|
+
5. `renderers` - `api.registerRenderer(...)`
|
|
21
|
+
6. `hooks` - `api.hooks.beforeCommand/afterCommand/onWrite/onRead/onIndex`
|
|
22
|
+
7. `schema` - `api.registerItemFields/registerItemTypes/registerMigration`
|
|
23
|
+
8. `importers` - `api.registerImporter/registerExporter`
|
|
24
|
+
9. `search` - `api.registerSearchProvider/registerVectorStoreAdapter`
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
1. Copy this folder into an extension root:
|
|
29
|
+
- project: `.agents/pm/extensions/starter-extension`
|
|
30
|
+
- global: `~/.pm-cli/extensions/starter-extension`
|
|
31
|
+
2. Install dependencies in that copied folder:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
3. Activate and test:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pm extension --activate --project starter-extension
|
|
41
|
+
pm starter ping --name "agent"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Notes
|
|
45
|
+
|
|
46
|
+
- This starter is for learning and scaffolding, not production behavior.
|
|
47
|
+
- Keep service/renderer overrides narrowly scoped in real extensions.
|
|
48
|
+
- Prefer returning deterministic JSON-like objects from handlers.
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { defineExtension } from "@unbrained/pm-cli/sdk";
|
|
2
|
+
|
|
3
|
+
const runtimeState = {
|
|
4
|
+
beforeCommandCount: 0,
|
|
5
|
+
afterCommandCount: 0,
|
|
6
|
+
onWriteCount: 0,
|
|
7
|
+
onReadCount: 0,
|
|
8
|
+
onIndexCount: 0,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function asRecord(value) {
|
|
12
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function asString(value, fallback = "") {
|
|
19
|
+
return typeof value === "string" ? value : fallback;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function stableJson(value) {
|
|
23
|
+
try {
|
|
24
|
+
return JSON.stringify(value, null, 2);
|
|
25
|
+
} catch {
|
|
26
|
+
return JSON.stringify({ error: "non_serializable_payload" }, null, 2);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default defineExtension({
|
|
31
|
+
activate(api) {
|
|
32
|
+
// commands
|
|
33
|
+
api.registerCommand({
|
|
34
|
+
name: "starter ping",
|
|
35
|
+
description: "Return a deterministic starter-extension response.",
|
|
36
|
+
intent: "Verify extension activation and show SDK registration patterns.",
|
|
37
|
+
examples: ["pm starter ping --name agent --uppercase"],
|
|
38
|
+
run: async (context) => {
|
|
39
|
+
const options = asRecord(context.options);
|
|
40
|
+
const rawName = asString(options.name, "agent").trim();
|
|
41
|
+
return {
|
|
42
|
+
ok: true,
|
|
43
|
+
source: "starter-extension",
|
|
44
|
+
command: context.command,
|
|
45
|
+
hello: rawName.length > 0 ? rawName : "agent",
|
|
46
|
+
hook_counts: {
|
|
47
|
+
before: runtimeState.beforeCommandCount,
|
|
48
|
+
after: runtimeState.afterCommandCount,
|
|
49
|
+
write: runtimeState.onWriteCount,
|
|
50
|
+
read: runtimeState.onReadCount,
|
|
51
|
+
index: runtimeState.onIndexCount,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// schema (registerFlags currently routes through schema capability)
|
|
58
|
+
api.registerFlags("starter ping", [
|
|
59
|
+
{ long: "--name", value_name: "text", description: "Name to include in the response." },
|
|
60
|
+
{ long: "--uppercase", description: "Render hello in uppercase via output_format service override." },
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
// parser
|
|
64
|
+
api.registerParser("starter ping", async (context) => {
|
|
65
|
+
const options = { ...asRecord(context.options) };
|
|
66
|
+
if (typeof options.name === "string") {
|
|
67
|
+
options.name = options.name.trim();
|
|
68
|
+
}
|
|
69
|
+
return { options };
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// preflight
|
|
73
|
+
api.registerPreflight((context) => {
|
|
74
|
+
if (context.command !== "starter ping") {
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
run_extension_migrations: false,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// services
|
|
83
|
+
api.registerService("output_format", (context) => {
|
|
84
|
+
if (context.command !== "starter ping") {
|
|
85
|
+
return context.payload;
|
|
86
|
+
}
|
|
87
|
+
const payload = asRecord(context.payload);
|
|
88
|
+
const result = asRecord(payload.result);
|
|
89
|
+
const options = asRecord(context.options);
|
|
90
|
+
const uppercase = options.uppercase === true;
|
|
91
|
+
const helloRaw = asString(result.hello, "agent");
|
|
92
|
+
const hello = uppercase ? helloRaw.toUpperCase() : helloRaw;
|
|
93
|
+
return `starter_service_output hello=${hello} command=${asString(context.command, "")}`;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// renderers
|
|
97
|
+
api.registerRenderer("json", (context) => stableJson(context.result));
|
|
98
|
+
api.registerRenderer("toon", (context) => {
|
|
99
|
+
const result = asRecord(context.result);
|
|
100
|
+
const hooks = asRecord(result.hook_counts);
|
|
101
|
+
return [
|
|
102
|
+
"starter_ping",
|
|
103
|
+
`hello: ${asString(result.hello, "agent")}`,
|
|
104
|
+
`command: ${asString(result.command, "")}`,
|
|
105
|
+
`hooks.before: ${String(hooks.before ?? 0)}`,
|
|
106
|
+
`hooks.after: ${String(hooks.after ?? 0)}`,
|
|
107
|
+
].join("\n");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// hooks
|
|
111
|
+
api.hooks.beforeCommand(() => {
|
|
112
|
+
runtimeState.beforeCommandCount += 1;
|
|
113
|
+
});
|
|
114
|
+
api.hooks.afterCommand(() => {
|
|
115
|
+
runtimeState.afterCommandCount += 1;
|
|
116
|
+
});
|
|
117
|
+
api.hooks.onWrite(() => {
|
|
118
|
+
runtimeState.onWriteCount += 1;
|
|
119
|
+
});
|
|
120
|
+
api.hooks.onRead(() => {
|
|
121
|
+
runtimeState.onReadCount += 1;
|
|
122
|
+
});
|
|
123
|
+
api.hooks.onIndex(() => {
|
|
124
|
+
runtimeState.onIndexCount += 1;
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// schema
|
|
128
|
+
api.registerItemFields([
|
|
129
|
+
{
|
|
130
|
+
name: "starter_context",
|
|
131
|
+
type: "string",
|
|
132
|
+
optional: true,
|
|
133
|
+
},
|
|
134
|
+
]);
|
|
135
|
+
api.registerItemTypes([
|
|
136
|
+
{
|
|
137
|
+
name: "Experiment",
|
|
138
|
+
folder: "experiments",
|
|
139
|
+
aliases: ["exp"],
|
|
140
|
+
required_create_fields: ["description"],
|
|
141
|
+
},
|
|
142
|
+
]);
|
|
143
|
+
api.registerMigration({
|
|
144
|
+
id: "starter-extension-noop-migration",
|
|
145
|
+
description: "No-op migration to demonstrate schema migration registration.",
|
|
146
|
+
status: "applied",
|
|
147
|
+
mandatory: false,
|
|
148
|
+
run: async () => ({ applied: true }),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// importers
|
|
152
|
+
api.registerImporter("starter-json", async (context) => ({
|
|
153
|
+
imported: true,
|
|
154
|
+
source: "starter-extension",
|
|
155
|
+
input: asRecord(context),
|
|
156
|
+
}));
|
|
157
|
+
api.registerExporter("starter-json", async (context) => ({
|
|
158
|
+
exported: true,
|
|
159
|
+
source: "starter-extension",
|
|
160
|
+
output: asRecord(context),
|
|
161
|
+
}));
|
|
162
|
+
|
|
163
|
+
// search
|
|
164
|
+
api.registerSearchProvider({
|
|
165
|
+
name: "starter-search",
|
|
166
|
+
kind: "example",
|
|
167
|
+
query: async (context) => {
|
|
168
|
+
const query = asString(asRecord(context).query, "").trim();
|
|
169
|
+
if (!query) {
|
|
170
|
+
return [];
|
|
171
|
+
}
|
|
172
|
+
return [
|
|
173
|
+
{
|
|
174
|
+
id: "starter-result-1",
|
|
175
|
+
score: 1,
|
|
176
|
+
title: "Starter Search Result",
|
|
177
|
+
snippet: `Echo match for: ${query}`,
|
|
178
|
+
source: "starter-extension",
|
|
179
|
+
},
|
|
180
|
+
];
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
api.registerVectorStoreAdapter({
|
|
184
|
+
name: "starter-vector-adapter",
|
|
185
|
+
kind: "example",
|
|
186
|
+
upsert: async () => ({ upserted: 0 }),
|
|
187
|
+
query: async () => [],
|
|
188
|
+
delete: async () => ({ deleted: 0 }),
|
|
189
|
+
});
|
|
190
|
+
},
|
|
191
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "starter-extension",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SDK-first starter extension demonstrating all pm extension capabilities.",
|
|
5
|
+
"entry": "./index.js",
|
|
6
|
+
"capabilities": [
|
|
7
|
+
"commands",
|
|
8
|
+
"parser",
|
|
9
|
+
"preflight",
|
|
10
|
+
"services",
|
|
11
|
+
"renderers",
|
|
12
|
+
"hooks",
|
|
13
|
+
"schema",
|
|
14
|
+
"importers",
|
|
15
|
+
"search"
|
|
16
|
+
]
|
|
17
|
+
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unbrained/pm-cli",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.5.1",
|
|
4
4
|
"description": "Git-native project management CLI for humans and agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "unbrained",
|
|
7
7
|
"homepage": "https://github.com/unbraind/pm-cli#readme",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/unbraind/pm-cli.git"
|
|
10
|
+
"url": "git+https://github.com/unbraind/pm-cli.git"
|
|
11
11
|
},
|
|
12
12
|
"bugs": {
|
|
13
13
|
"url": "https://github.com/unbraind/pm-cli/issues"
|
|
@@ -15,14 +15,37 @@
|
|
|
15
15
|
"bin": {
|
|
16
16
|
"pm": "dist/cli.js"
|
|
17
17
|
},
|
|
18
|
+
"types": "dist/sdk/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/sdk/index.d.ts",
|
|
22
|
+
"import": "./dist/sdk/index.js",
|
|
23
|
+
"default": "./dist/sdk/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./sdk": {
|
|
26
|
+
"types": "./dist/sdk/index.d.ts",
|
|
27
|
+
"import": "./dist/sdk/index.js",
|
|
28
|
+
"default": "./dist/sdk/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./cli": {
|
|
31
|
+
"types": "./dist/cli/main.d.ts",
|
|
32
|
+
"import": "./dist/cli/main.js",
|
|
33
|
+
"default": "./dist/cli/main.js"
|
|
34
|
+
},
|
|
35
|
+
"./package.json": "./package.json"
|
|
36
|
+
},
|
|
18
37
|
"files": [
|
|
19
38
|
"dist/**",
|
|
20
39
|
"README.md",
|
|
40
|
+
"CHANGELOG.md",
|
|
41
|
+
"CONTRIBUTING.md",
|
|
42
|
+
"SECURITY.md",
|
|
43
|
+
"CODE_OF_CONDUCT.md",
|
|
21
44
|
"LICENSE",
|
|
22
45
|
"AGENTS.md",
|
|
23
46
|
"PRD.md",
|
|
24
47
|
"docs/**",
|
|
25
|
-
".
|
|
48
|
+
".agents/pm/extensions/**",
|
|
26
49
|
"scripts/install.sh",
|
|
27
50
|
"scripts/install.ps1"
|
|
28
51
|
],
|
|
@@ -35,6 +58,7 @@
|
|
|
35
58
|
"test:coverage": "pnpm build && vitest run --coverage",
|
|
36
59
|
"version:check": "node scripts/release-version.mjs check",
|
|
37
60
|
"version:next": "node scripts/release-version.mjs next",
|
|
61
|
+
"release:notes": "node scripts/generate-release-notes.mjs",
|
|
38
62
|
"security:scan": "node scripts/check-secrets.mjs",
|
|
39
63
|
"smoke:npx": "node scripts/smoke-npx-from-pack.mjs",
|
|
40
64
|
"prepublishOnly": "pnpm build"
|
|
@@ -59,21 +83,24 @@
|
|
|
59
83
|
"dependencies": {
|
|
60
84
|
"@toon-format/toon": "latest",
|
|
61
85
|
"commander": "latest",
|
|
86
|
+
"fast-glob": "^3.3.3",
|
|
62
87
|
"fast-json-patch": "latest",
|
|
63
88
|
"undici": "latest",
|
|
64
89
|
"zod": "latest"
|
|
65
90
|
},
|
|
66
91
|
"devDependencies": {
|
|
67
92
|
"@types/node": "latest",
|
|
68
|
-
"@vitest/coverage-v8": "^4.
|
|
93
|
+
"@vitest/coverage-v8": "^4.1.5",
|
|
69
94
|
"c8": "^11.0.0",
|
|
70
95
|
"tsx": "latest",
|
|
71
96
|
"typescript": "latest",
|
|
72
|
-
"vitest": "^4.
|
|
97
|
+
"vitest": "^4.1.5"
|
|
73
98
|
},
|
|
74
99
|
"pnpm": {
|
|
75
100
|
"overrides": {
|
|
76
|
-
"rollup": ">=4.59.0"
|
|
101
|
+
"rollup": ">=4.59.0",
|
|
102
|
+
"brace-expansion": ">=5.0.5",
|
|
103
|
+
"vite": "7.3.2"
|
|
77
104
|
}
|
|
78
105
|
}
|
|
79
106
|
}
|