pm-starter 2026.11.4 → 2026.11.9
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/CHANGELOG.md +15 -0
- package/README.md +67 -0
- package/dist/index.js +1 -1
- package/manifest.json +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026.11.9 - 2026-11-09
|
|
4
|
+
|
|
5
|
+
### Dependencies
|
|
6
|
+
|
|
7
|
+
- Bump the pm-toolchain group with 3 updates ([#199](https://github.com/unbraind/pm-starter/pull/199))
|
|
8
|
+
- Bump unbraind/pm-github/.github/workflows/pm-github-closeout.yml ([#198](https://github.com/unbraind/pm-starter/pull/198))
|
|
9
|
+
- Bump unbraind/pm-github/.github/workflows/pm-github-sync.yml ([#197](https://github.com/unbraind/pm-starter/pull/197))
|
|
10
|
+
- Bump the codeql-action group with 2 updates ([#196](https://github.com/unbraind/pm-starter/pull/196))
|
|
11
|
+
|
|
12
|
+
## 2026.11.5 - 2026-11-05
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- SDK 2026.11.1 upgrade: parent "none" fixture blocks all eight paginated-consumer tests ([pm-starter-toolchain-1104](https://github.com/unbraind/pm-starter/blob/main/.agents/pm/issues/pm-starter-toolchain-1104.toon))
|
|
17
|
+
|
|
3
18
|
## 2026.11.4 - 2026-11-04
|
|
4
19
|
|
|
5
20
|
### Fixed
|
package/README.md
CHANGED
|
@@ -213,6 +213,73 @@ npm run build
|
|
|
213
213
|
pm install ./my-extension --project
|
|
214
214
|
```
|
|
215
215
|
|
|
216
|
+
## Recommended extension tests
|
|
217
|
+
|
|
218
|
+
Use `createExtensionTestHarness` from `@unbrained/pm-cli/sdk/testing` for positive
|
|
219
|
+
registration and handler tests. It activates the real host registration API and
|
|
220
|
+
runs registered handlers through host dispatch. Pair it with an initialized
|
|
221
|
+
`PmClient` tracker in a temporary directory, including a tracker outside Git:
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import assert from "node:assert/strict";
|
|
225
|
+
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
226
|
+
import { tmpdir } from "node:os";
|
|
227
|
+
import { join } from "node:path";
|
|
228
|
+
import test from "node:test";
|
|
229
|
+
import { PmClient } from "@unbrained/pm-cli/sdk";
|
|
230
|
+
import { createExtensionTestHarness } from "@unbrained/pm-cli/sdk/testing";
|
|
231
|
+
import extension from "../index.ts";
|
|
232
|
+
|
|
233
|
+
test("registered command reads a real tracker", async (t) => {
|
|
234
|
+
const directory = mkdtempSync(join(tmpdir(), "extension-test-"));
|
|
235
|
+
t.after(() => rmSync(directory, { recursive: true, force: true }));
|
|
236
|
+
const pmRoot = join(directory, ".agents", "pm"); // Tracker storage, not workspace root.
|
|
237
|
+
const client = new PmClient({ pmRoot, noExtensions: true, author: "test" });
|
|
238
|
+
await client.init("example", { defaults: true, mergeFence: false, agentGuidance: "skip" });
|
|
239
|
+
await client.create({ id: "example", type: "Task", title: "Example" });
|
|
240
|
+
|
|
241
|
+
const manifest: unknown = JSON.parse(readFileSync(new URL("../manifest.json", import.meta.url), "utf8"));
|
|
242
|
+
const harness = await createExtensionTestHarness({ default: extension, manifest });
|
|
243
|
+
t.after(() => harness.deactivate());
|
|
244
|
+
harness.assertCommandContract({ name: "starter greet", flags: ["--name", "--uppercase"] });
|
|
245
|
+
harness.assertFlags({ name: "list", flags: ["--starter-tag"] });
|
|
246
|
+
harness.assertItemField({ name: "starter_origin", type: "string" });
|
|
247
|
+
harness.assertItemType({ name: "StarterNote", folder: "starter-notes" });
|
|
248
|
+
|
|
249
|
+
// A nonempty pmRoot makes the harness inject a real host-bound ctx.sdk.
|
|
250
|
+
const outcome = await harness.runCommand({ command: "starter demo", pmRoot });
|
|
251
|
+
assert.equal(outcome.handled, true);
|
|
252
|
+
assert.deepEqual(outcome.warnings, []);
|
|
253
|
+
assert.equal((outcome.result as { item_count: number }).item_count, 1);
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Keep the manifest's capabilities accurate; this example uses the package's actual
|
|
258
|
+
manifest so missing declarations fail activation. Copy the assertion names and
|
|
259
|
+
expected receipts to match your own extension. The pinned development SDK supplies
|
|
260
|
+
these testing helpers; they do not change the installed extension's host floor.
|
|
261
|
+
|
|
262
|
+
Use `assertHook`, `assertImporter`, `assertExporter` and the other `assert*`
|
|
263
|
+
methods to verify registered surfaces, then `runCommand`, `runRendererOverride`,
|
|
264
|
+
`runImporter`, `runExporter` or `runHook` to exercise behavior. Importers and
|
|
265
|
+
exporters also register command paths, so they appear in the host command registry.
|
|
266
|
+
The harness dispatches one requested surface; it does not run the entire CLI
|
|
267
|
+
parser/preflight/render pipeline or automatically install hooks on a separate
|
|
268
|
+
`PmClient`. Pass parsed command flags in `options`, global host options in `global`,
|
|
269
|
+
and real committed mutation data when invoking an observe-only write hook.
|
|
270
|
+
|
|
271
|
+
Retain package rules as assertions: USAGE errors, inert importer and laboratory
|
|
272
|
+
mutation refusals, renderer ownership, and receipt contents are starter behavior
|
|
273
|
+
the SDK cannot prescribe. Pure option tests and the focused callback/subprocess
|
|
274
|
+
failure doubles in `test/commands.test.ts` stay unit tests; use
|
|
275
|
+
`activateExtensionForTest` directly for deliberate failed-activation or old-host
|
|
276
|
+
compatibility tests. Positive smoke tests must use the supported harness instead
|
|
277
|
+
of a handwritten `ExtensionApi` registration sink. See `test/smoke.test.ts` for
|
|
278
|
+
registration, invocation, output receipt and mutation-context examples.
|
|
279
|
+
|
|
280
|
+
Run `node --test --test-concurrency=2 test/smoke.test.ts` and `npm run build:test`
|
|
281
|
+
when adapting this pattern, then the package's full gate.
|
|
282
|
+
|
|
216
283
|
## License
|
|
217
284
|
|
|
218
285
|
MIT
|
package/dist/index.js
CHANGED
|
@@ -1060,7 +1060,7 @@ function setupFlags(api) {
|
|
|
1060
1060
|
const defineExtension = (module) => module;
|
|
1061
1061
|
export default defineExtension({
|
|
1062
1062
|
name: "pm-starter",
|
|
1063
|
-
version: "2026.11.
|
|
1063
|
+
version: "2026.11.9",
|
|
1064
1064
|
activate(api) {
|
|
1065
1065
|
// Register every capability group. Each helper is defensive enough to be
|
|
1066
1066
|
// safely deleted when you fork this scaffold for a real extension.
|
package/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pm-starter",
|
|
3
|
-
"version": "2026.11.
|
|
3
|
+
"version": "2026.11.9",
|
|
4
4
|
"description": "Complete scaffold showing all 9 capability types: commands, renderers, hooks, schema, importers, search, parser, preflight, services. Includes plan workflow, context, and search integration examples plus guided setup. Use as a starting template for new extensions.",
|
|
5
5
|
"author": "@unbraind",
|
|
6
6
|
"entry": "./dist/index.js",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pm-starter",
|
|
3
|
-
"version": "2026.11.
|
|
3
|
+
"version": "2026.11.9",
|
|
4
4
|
"description": "Complete starter/scaffold extension for pm-cli showing all capability types",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/node": "26.6.6",
|
|
54
|
-
"@unbrained/pm-cli": "2026.
|
|
55
|
-
"pm-changelog": "2026.
|
|
56
|
-
"pm-ops": "2026.
|
|
54
|
+
"@unbrained/pm-cli": "2026.11.5",
|
|
55
|
+
"pm-changelog": "2026.11.5",
|
|
56
|
+
"pm-ops": "2026.11.5",
|
|
57
57
|
"typescript": "7.0.2"
|
|
58
58
|
},
|
|
59
59
|
"keywords": [
|