@unbrained/pm-cli 2026.8.19 → 2026.8.20
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 +2 -2
- package/CHANGELOG.md +19 -0
- package/dist/cli/register-list-query.js +12 -10
- package/dist/cli/register-structured-mutation.d.ts +2 -0
- package/dist/cli/register-structured-mutation.js +29 -6
- package/dist/cli-bundle/bundle-manifest.json +151 -143
- package/dist/cli-bundle/chunks/{chunk-4THEB6PD.js → chunk-2RDVGYWE.js} +12 -12
- package/dist/cli-bundle/chunks/{chunk-BHYMXLAE.js → chunk-4GB2LTOQ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-TOXJM4WA.js → chunk-7BRF2BX2.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-BLVQHFSY.js +35 -0
- package/dist/cli-bundle/chunks/chunk-CU25EQVV.js +5 -0
- package/dist/cli-bundle/chunks/{chunk-4NRRH7AM.js → chunk-K3EN3LK2.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-OIOKV6NO.js → chunk-L4LGPBJU.js} +49 -49
- package/dist/cli-bundle/chunks/chunk-RS3IV2R6.js +197 -0
- package/dist/cli-bundle/chunks/chunk-TSMWLCHS.js +3 -0
- package/dist/cli-bundle/chunks/chunk-US2ZQW2M.js +77 -0
- package/dist/cli-bundle/chunks/{chunk-QXSH7BLM.js → chunk-XYDDWBZN.js} +2 -2
- package/dist/cli-bundle/chunks/register-list-query-JSAQCVOC.js +11 -0
- package/dist/cli-bundle/chunks/{register-mutation-AUWVCW4M.js → register-mutation-XJPAW63D.js} +20 -20
- package/dist/cli-bundle/chunks/{register-operations-PZQPHXW5.js → register-operations-DSOSB2XQ.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-I4LUHGVW.js → register-setup-QUR6QL2C.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-DKPLYW3L.js → chunk-325UXIO7.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-5L7M4AI7.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-EF6ZS5GH.js → chunk-6AHG2YW7.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-MCZXYZAF.js → chunk-AZBACT5T.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-VXDSU5MC.js → chunk-BLJCGGID.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-FUREQLQN.js +18 -0
- package/dist/cli-bundle/focused-chunks/{chunk-US7VEYZG.js → chunk-G3C5ERXG.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-ZBIQQYMI.js → chunk-GXWQBE3T.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-JDOMQ7VQ.js → chunk-JWKEDZJI.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-KYZ6JGPL.js +155 -0
- package/dist/cli-bundle/focused-chunks/{chunk-ESISGDAY.js → chunk-M32HFIQB.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-EXBCLIBU.js → chunk-OM65KHGF.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-Q47EX4DI.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-BJRYFVSH.js → chunk-RIHDMCUM.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-T4ZFY7ZJ.js +16 -0
- package/dist/cli-bundle/focused-chunks/chunk-TDR5OGG3.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-ODHQEECS.js → chunk-UGSS4F5X.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-Z3PLWSGM.js +2 -0
- package/dist/cli-bundle/main.js +2 -2
- 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 +41 -41
- 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 +5 -5
- package/dist/core/output/mutation-projection.js +26 -2
- package/dist/core/shared/constants.d.ts +1 -5
- package/dist/core/shared/constants.js +3 -81
- package/dist/core/shared/item-metadata-contract.d.ts +14 -0
- package/dist/core/shared/item-metadata-contract.js +90 -0
- package/dist/core/store/item-store.d.ts +60 -0
- package/dist/core/store/item-store.js +22 -5
- package/dist/sdk/agent/closed-domain-contracts.d.ts +25 -0
- package/dist/sdk/agent/closed-domain-contracts.js +140 -0
- package/dist/sdk/agent/refusal-closure.d.ts +13 -1
- package/dist/sdk/agent/refusal-closure.js +45 -3
- package/dist/sdk/agent/refusal-reachability.d.ts +26 -0
- package/dist/sdk/agent/refusal-reachability.js +26 -2
- package/dist/sdk/agent-capability-contracts.js +6 -11
- package/dist/sdk/cli-contracts/completeness.js +8 -2
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +4 -2
- package/dist/sdk/cli-contracts/enum-contracts.js +16 -6
- package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
- package/dist/sdk/cli-contracts/flag-contracts.js +11 -2
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.d.ts +19 -2
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +105 -5
- package/dist/sdk/cli-contracts/grammar-contracts.d.ts +2 -2
- package/dist/sdk/cli-contracts/grammar-contracts.js +5 -2
- package/dist/sdk/cli-contracts/runtime-contracts.js +7 -3
- package/dist/sdk/cli-contracts/tool-schema.js +7 -2
- package/dist/sdk/cli-contracts.d.ts +2 -2
- package/dist/sdk/cli-contracts.js +4 -4
- package/dist/sdk/contracts.d.ts +1 -0
- package/dist/sdk/contracts.js +3 -2
- package/dist/sdk/core.d.ts +1 -1
- package/dist/sdk/core.js +3 -3
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +74 -2
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +112 -40
- package/dist/sdk/index.d.ts +5 -3
- package/dist/sdk/index.js +6 -4
- package/dist/sdk/init-agent-guidance.d.ts +5 -3
- package/dist/sdk/init-agent-guidance.js +69 -9
- package/dist/sdk/lifecycle/mcp-actions.d.ts +18 -0
- package/dist/sdk/lifecycle/mcp-actions.js +52 -0
- package/dist/sdk/lifecycle/reopen.d.ts +44 -0
- package/dist/sdk/lifecycle/reopen.js +69 -0
- package/dist/sdk/lifecycle/update.d.ts +31 -0
- package/dist/sdk/lifecycle/update.js +95 -13
- package/dist/sdk/query/get.d.ts +1 -1
- package/dist/sdk/query/get.js +18 -52
- package/dist/sdk/query/list.d.ts +7 -21
- package/dist/sdk/query/list.js +35 -49
- package/dist/sdk/query/projection-contracts.d.ts +33 -0
- package/dist/sdk/query/projection-contracts.js +185 -0
- package/dist/sdk/query/search-contracts.d.ts +2 -1
- package/dist/sdk/query/search-contracts.js +18 -87
- package/dist/sdk/query/search.d.ts +15 -0
- package/dist/sdk/query/search.js +31 -5
- package/dist/sdk/runtime-primitives.d.ts +1 -1
- package/dist/sdk/runtime-primitives.js +3 -3
- package/dist/sdk/runtime.d.ts +6 -0
- package/dist/sdk/runtime.js +18 -14
- package/dist/sdk/similarity.d.ts +13 -0
- package/dist/sdk/similarity.js +32 -6
- package/docs/COMMANDS.md +13 -1
- package/docs/README.md +1 -0
- package/docs/RECURRENCE_RECOVERY_CONTRACTS.md +114 -0
- package/docs/SDK.md +10 -2
- package/docs/SDK_CONTEXT_INTEGRITY.md +45 -0
- package/docs/generated/AGENT_COMMAND_SURFACE.md +1 -1
- package/docs/performance/sdk-entrypoint-import-costs.md +14 -21
- package/marketplace.json +2 -2
- package/package.json +5 -5
- 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/sdk/public-surface.json +387 -25
- package/dist/cli-bundle/chunks/chunk-GWMXAQOD.js +0 -197
- package/dist/cli-bundle/chunks/chunk-HVFQTLYM.js +0 -35
- package/dist/cli-bundle/chunks/chunk-OI4XI562.js +0 -5
- package/dist/cli-bundle/chunks/chunk-SARFF5H5.js +0 -3
- package/dist/cli-bundle/chunks/chunk-YBMRWW4E.js +0 -77
- package/dist/cli-bundle/chunks/register-list-query-Y56KINDU.js +0 -11
- package/dist/cli-bundle/focused-chunks/chunk-34QBIYZI.js +0 -155
- package/dist/cli-bundle/focused-chunks/chunk-L623ZPNK.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-PRHY2IMX.js +0 -18
- package/dist/cli-bundle/focused-chunks/chunk-RZU5U6Q7.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-YBMGXBFV.js +0 -16
- package/dist/cli-bundle/focused-chunks/chunk-YLVBJ6GF.js +0 -2
package/dist/sdk/similarity.js
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
* governance and package-owned duplicate analysis.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
8
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="33a43890-abcf-58fc-bf9d-bf2619d4cf35")}catch(e){}}();
|
|
9
9
|
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
10
10
|
import { PmCliError } from "../core/shared/errors.js";
|
|
11
11
|
import { resolveItemTypeRegistry } from "../core/item/type-registry.js";
|
|
12
|
-
import { normalizeStatusInput } from "../core/item/status.js";
|
|
12
|
+
import { isTerminalStatus, normalizeStatusInput } from "../core/item/status.js";
|
|
13
13
|
import { resolveRuntimeStatusRegistry } from "../core/schema/runtime-schema.js";
|
|
14
14
|
import { listAllItemMetadataLight } from "../core/store/item-store.js";
|
|
15
15
|
import { resolvePmRoot } from "../core/store/paths.js";
|
|
@@ -32,8 +32,28 @@ export function similarityAdvisoryWarnings(advisory) {
|
|
|
32
32
|
`likely_duplicates:${advisory.result.items
|
|
33
33
|
.map((item) => item.id)
|
|
34
34
|
.join(",")}`,
|
|
35
|
+
`likely_duplicate_recovery:${advisory.recovery.action}:${advisory.recovery.item_id}`,
|
|
35
36
|
];
|
|
36
37
|
}
|
|
38
|
+
async function resolveSimilarityRecovery(result, options) {
|
|
39
|
+
const strongest = result.items[0];
|
|
40
|
+
const pmRoot = resolvePmRoot(options.cwd ?? process.cwd(), options.pmRoot);
|
|
41
|
+
const statusRegistry = resolveRuntimeStatusRegistry((await readSettings(pmRoot)).schema);
|
|
42
|
+
if (isTerminalStatus(strongest.status, statusRegistry)) {
|
|
43
|
+
return {
|
|
44
|
+
action: "reopen",
|
|
45
|
+
item_id: strongest.id,
|
|
46
|
+
command: `pm item reopen ${strongest.id} "<recurrence reason>"`,
|
|
47
|
+
args: ["item", "reopen", strongest.id, "<recurrence reason>"],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
action: "reuse",
|
|
52
|
+
item_id: strongest.id,
|
|
53
|
+
command: `pm get ${strongest.id} --full`,
|
|
54
|
+
args: ["get", strongest.id, "--full"],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
37
57
|
function validateSimilarityOptions(options) {
|
|
38
58
|
const limit = options.limit ?? DEFAULT_SIMILARITY_LIMIT;
|
|
39
59
|
const threshold = options.threshold ?? DEFAULT_SIMILARITY_THRESHOLD;
|
|
@@ -287,20 +307,26 @@ export async function evaluateSimilarityGovernance(candidate, options) {
|
|
|
287
307
|
const result = await findSimilarItems(candidate, options);
|
|
288
308
|
if (result.count === 0)
|
|
289
309
|
return undefined;
|
|
310
|
+
const recovery = await resolveSimilarityRecovery(result, options);
|
|
290
311
|
const bypassed = options.mode === "strict" && options.allowDuplicate === true;
|
|
291
312
|
if (options.mode === "strict" && !bypassed) {
|
|
292
313
|
const candidates = result.items
|
|
293
314
|
.map((item) => `${item.id} (${item.status}): ${item.title}`)
|
|
294
315
|
.join("; ");
|
|
295
|
-
|
|
316
|
+
const recoveryInstruction = recovery.action === "reopen"
|
|
317
|
+
? "Reopen the canonical item"
|
|
318
|
+
: "Reuse the canonical item";
|
|
319
|
+
throw new PmCliError(`Likely duplicate item(s) found: ${candidates}. ${recoveryInstruction} or pass --allow-duplicate with explicit intent.`, EXIT_CODE.CONFLICT, {
|
|
296
320
|
code: "likely_duplicate",
|
|
297
|
-
required:
|
|
321
|
+
required: `${recoveryInstruction}, or explicitly acknowledge the duplicate with --allow-duplicate.`,
|
|
298
322
|
recovery: {
|
|
299
323
|
suggested_flags: ["--allow-duplicate"],
|
|
324
|
+
suggested_retry: recovery.command,
|
|
325
|
+
suggested_retry_args: recovery.args,
|
|
300
326
|
},
|
|
301
327
|
});
|
|
302
328
|
}
|
|
303
|
-
return { mode: options.mode, bypassed, result };
|
|
329
|
+
return { mode: options.mode, bypassed, result, recovery };
|
|
304
330
|
}
|
|
305
331
|
//# sourceMappingURL=similarity.js.map
|
|
306
|
-
//# debugId=
|
|
332
|
+
//# debugId=33a43890-abcf-58fc-bf9d-bf2619d4cf35
|
package/docs/COMMANDS.md
CHANGED
|
@@ -52,7 +52,7 @@ JSON ceiling; TOON uses the smaller default agent ceiling.
|
|
|
52
52
|
| Family | Commands | Purpose |
|
|
53
53
|
| ------------ | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
54
54
|
| Bootstrap | `init`, `config`, `health`, `telemetry` | create and inspect tracker setup |
|
|
55
|
-
| Lifecycle | `create`, `copy`, `focus`, `claim`, `update`, `append`, `close`, `release`, `delete`, `start-task`, `pause-task`, `close-task` | mutate item state
|
|
55
|
+
| Lifecycle | `create`, `copy`, `focus`, `claim`, `update`, `item reopen`, `append`, `close`, `release`, `delete`, `start-task`, `pause-task`, `close-task` | mutate item state, including terminal-work recurrence without duplicate creation |
|
|
56
56
|
| Bulk | `item mutate`, `item complete`, `update-many`, `close-many` | atomically commit heterogeneous SDK mutation batches or evidence-backed completion, or apply one change across a matched, dry-run-previewed set with a rollback checkpoint |
|
|
57
57
|
| Scheduling | `meet`, `event`, `remind` | low-friction Meeting/Event/Reminder creation |
|
|
58
58
|
| Planning | `plan create`, `plan add-step`, `plan update-step`, `plan complete-step`, `plan link`, `plan approve`, `plan materialize` | agent-optimized living plans with ordered steps, evidence, decisions, validation, and materialization |
|
|
@@ -165,6 +165,18 @@ custom statuses are normalized through the runtime status registry and an
|
|
|
165
165
|
unknown status fails instead of returning a false-clean result.
|
|
166
166
|
Use `pm get <id>` to read a single item by ID — the single-item read primitive used throughout the agent loop. It accepts `--fields <list>` and `--depth brief|standard|deep|full` for token-minimal projections, and `--tree`/`--tree-depth <n>` to include descendants. Standard/deep reads expose a normalized `schedule` facet (`deadline`, `start_at`, `end_at`, `location`, reminders, and events) when scheduling metadata exists. Container-oriented built-ins (Epic, Feature, Milestone, and Plan) plus custom types automatically expose type-agnostic child counts and continuation metadata. Standard depth keeps that rollup counts-only; `--depth deep|full` or an explicit `--fields id,children` request adds the deterministic bounded child sample. Built-in leaf reads avoid a workspace scan unless children are explicitly requested. `pm get <id> --json` returns the `body` inside the `item` object (`.item.body`); see [Full results, totals, and bodies](#full-results-totals-and-bodies). To duplicate an existing item as a starting point, `pm copy <id> --title "New title"` clones it into a fresh id with lifecycle fields reset.
|
|
167
167
|
|
|
168
|
+
When the strongest duplicate match is terminal because the same work recurred,
|
|
169
|
+
reuse its lineage instead of creating or copying another item:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
pm item reopen pm-a1b2 "The production failure recurred" --status in_progress
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The command appends a structured `reopen` history event, preserves the earlier
|
|
176
|
+
closure in immutable history, clears stale terminal metadata through the normal
|
|
177
|
+
update path, and refuses an already-active item. See
|
|
178
|
+
[Recurrence and Executable Recovery Contracts](RECURRENCE_RECOVERY_CONTRACTS.md).
|
|
179
|
+
|
|
168
180
|
Add `--at <version|ISO-timestamp>` for a verified point-in-time read. It replays the same hash-checked history kernel used by restore but never acquires a lock, writes the item, or appends history. The result always includes `reconstructed: true`, `as_of_version`, and `as_of_timestamp`. Future/out-of-range targets fail with structured `valid_range` metadata. `--at` cannot be combined with `--tree`; workspace-wide historical graph projections require a future indexed primitive.
|
|
169
181
|
`context` standard/deep views include high-level child completion counters plus `recently_created` and `unparented` sections, so agents can spot new orphan work before creating duplicates.
|
|
170
182
|
Use `pm aggregate --completion` when you need per-group `open`, `in_progress`, `closed`, `other`, and `completion_pct` progress context.
|
package/docs/README.md
CHANGED
|
@@ -57,6 +57,7 @@ pm guide release --json
|
|
|
57
57
|
- [Improvement Ledger and History Analytics](IMPROVEMENT_ANALYTICS.md) - audited quantitative observations, live provenance coverage, and bounded observational fleet outcomes.
|
|
58
58
|
- [Project Assurance Primitives](ASSURANCE.md) - SDK-owned measurements, assertions, lifecycle gates, cost receipts, and durable verdict history shared by CLI and MCP.
|
|
59
59
|
- [Defect Recurrence and Boundary Evidence](DEFECT_RECURRENCE.md) - captured external samples, structured defect-escape evidence, incremental change-risk indexing, and executable recovery-producer census.
|
|
60
|
+
- [Recurrence and Executable Recovery Contracts](RECURRENCE_RECOVERY_CONTRACTS.md) - terminal-item recurrence, duplicate-intake routing, capability-aware reindex recovery, and target-aware generated test guidance.
|
|
60
61
|
- [Trustworthy Context and Evidence Contracts](TRUSTWORTHY_CONTEXT_EVIDENCE.md) - full-record assurance, graph composition, boolean health rows, lossless linked-test removal, and role-labelled recovery.
|
|
61
62
|
- [Context Integrity Contracts](CONTEXT_INTEGRITY_CONTRACTS.md) - sparse-read identity, closed extension manifests, lossless remote docs, direction-locked graph impact, and cross-version history epochs.
|
|
62
63
|
- [SDK Evidence Traceability and Integrity](SDK_EVIDENCE_TRACEABILITY.md) - reverse source-to-item lookup, atomic evidence replacement, no-op history, linked-test collision classification, and telemetry drain receipts.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Recurrence and Executable Recovery Contracts
|
|
2
|
+
|
|
3
|
+
Tracked by [pm-83cz0o](../.agents/pm/features/pm-83cz0o.toon),
|
|
4
|
+
[pm-qljv](../.agents/pm/issues/pm-qljv.toon),
|
|
5
|
+
[pm-surv](../.agents/pm/issues/pm-surv.toon),
|
|
6
|
+
[pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon), and
|
|
7
|
+
[pm-f05lsg](../.agents/pm/features/pm-f05lsg.toon).
|
|
8
|
+
|
|
9
|
+
## Agent Quick Context
|
|
10
|
+
|
|
11
|
+
- Reuse an active matching item; reopen a terminal matching item.
|
|
12
|
+
- `pm item reopen` is the noun-first recurrence command. It never creates a
|
|
13
|
+
second item and never rewrites the earlier close event.
|
|
14
|
+
- Recovery guidance is capability-aware: it names an executable command on the
|
|
15
|
+
current surface, or installs the package that owns the command first.
|
|
16
|
+
- Generated `AGENTS.md` guidance detects the target repository's test command.
|
|
17
|
+
When no executable test contract exists, it prints an explicit placeholder
|
|
18
|
+
instead of naming a pm-cli repository script that the target does not have.
|
|
19
|
+
|
|
20
|
+
## Reopen Terminal Work
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pm item reopen pm-a1b2 "The production failure recurred after deployment"
|
|
24
|
+
pm item reopen pm-a1b2 "The customer reproduced the issue" --status in_progress
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The command accepts only the workspace open or in-progress status. While
|
|
28
|
+
holding the item lock it verifies that the current status is terminal, records
|
|
29
|
+
one `reopen` history event with structured recurrence context, and delegates the
|
|
30
|
+
state change to the normal update pipeline. Active metadata drops stale
|
|
31
|
+
`closed_at`, `completed_at`, `close_reason`, `resolution`, `expected_result`,
|
|
32
|
+
`actual_result`, and `fixed_version` values. Earlier history retains the exact
|
|
33
|
+
closure values.
|
|
34
|
+
|
|
35
|
+
Compact output keeps the recurrence receipt because the prior and next status,
|
|
36
|
+
reason, and terminal evidence are the proof that this was a recurrence rather
|
|
37
|
+
than a generic edit. An already-active item fails with
|
|
38
|
+
`item_already_active` and points to `pm get <id> --full`; continue that item with
|
|
39
|
+
`pm update` instead of manufacturing another recurrence event.
|
|
40
|
+
|
|
41
|
+
## SDK and MCP
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { PmClient, reopen } from "@unbrained/pm-cli/sdk";
|
|
45
|
+
|
|
46
|
+
const pm = new PmClient({ pmRoot: "/workspace/.agents/pm" });
|
|
47
|
+
const viaClient = await pm.reopen(
|
|
48
|
+
"pm-a1b2",
|
|
49
|
+
"The production failure recurred",
|
|
50
|
+
{ status: "in_progress" },
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const viaFunction = await reopen(
|
|
54
|
+
"pm-c3d4",
|
|
55
|
+
"The customer reproduced the issue",
|
|
56
|
+
{},
|
|
57
|
+
{ pmRoot: "/workspace/.agents/pm" },
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
console.log(viaClient.recurrence.previous_terminal);
|
|
61
|
+
console.log(viaFunction.recurrence.from_status);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Generic action hosts use `item-reopen` with required `id` and `reason` fields.
|
|
65
|
+
The action participates in the generated action schema, SDK dispatch coverage,
|
|
66
|
+
CLI/SDK parameter parity, command grammar, and MCP `pm_run` surface.
|
|
67
|
+
|
|
68
|
+
## Duplicate Intake
|
|
69
|
+
|
|
70
|
+
Create and copy similarity governance inspect all lifecycle statuses. The
|
|
71
|
+
strongest active match returns a `pm get <id> --full` reuse path. The strongest
|
|
72
|
+
terminal match returns:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pm item reopen <id> "<recurrence reason>"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Strict duplicate refusal exposes the same command and tokenized arguments in
|
|
79
|
+
its structured recovery envelope. Advisory mode adds a compact
|
|
80
|
+
`likely_duplicate_recovery:<reuse|reopen>:<id>` warning so agents can select the
|
|
81
|
+
correct lifecycle action without reparsing prose.
|
|
82
|
+
|
|
83
|
+
## Capability-Aware Reindex Recovery
|
|
84
|
+
|
|
85
|
+
When semantic search detects stale vectors, it inspects the active extension
|
|
86
|
+
command registry. If `reindex` is active, the direct recovery is:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pm reindex --mode hybrid
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
If the command is absent, recovery is a two-step executable sequence:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pm install search-advanced --project
|
|
96
|
+
pm reindex --mode hybrid
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The human warning and structured `vector_index_recovery` tokens come from the
|
|
100
|
+
same resolution. This prevents a base installation from suggesting an
|
|
101
|
+
unavailable command.
|
|
102
|
+
|
|
103
|
+
## Target-Aware Generated Test Guidance
|
|
104
|
+
|
|
105
|
+
`pm init --agent-guidance add` resolves the linked-test command in this order:
|
|
106
|
+
|
|
107
|
+
1. `node scripts/run-tests.mjs test` when that repository script exists.
|
|
108
|
+
2. The declared package manager's `test` script (`pnpm test`, `bun run test`,
|
|
109
|
+
`yarn test`, or `npm test`).
|
|
110
|
+
3. `<your project test command>` when the target does not declare an executable
|
|
111
|
+
test contract.
|
|
112
|
+
|
|
113
|
+
The managed guidance block is versioned, so a later init can replace an older
|
|
114
|
+
pm-managed block without changing surrounding repository instructions.
|
package/docs/SDK.md
CHANGED
|
@@ -54,6 +54,11 @@ Positional command signatures, action-scoped discovery, and MCP/CLI option
|
|
|
54
54
|
parity are tracked by [pm-ya7x55](../.agents/pm/tasks/pm-ya7x55.toon),
|
|
55
55
|
[pm-2tan](../.agents/pm/issues/pm-2tan.toon), and
|
|
56
56
|
[pm-y0htkd](../.agents/pm/issues/pm-y0htkd.toon).
|
|
57
|
+
Terminal recurrence and executable recovery are tracked by
|
|
58
|
+
[pm-83cz0o](../.agents/pm/features/pm-83cz0o.toon),
|
|
59
|
+
[pm-qljv](../.agents/pm/issues/pm-qljv.toon), and
|
|
60
|
+
[pm-surv](../.agents/pm/issues/pm-surv.toon); see
|
|
61
|
+
[Recurrence and Executable Recovery Contracts](RECURRENCE_RECOVERY_CONTRACTS.md).
|
|
57
62
|
|
|
58
63
|
Use it for extension authoring, package authoring, command/action contract discovery, and deterministic app or CI automation. Do not import private `src/core/...` modules from external integrations or packages.
|
|
59
64
|
|
|
@@ -1127,10 +1132,13 @@ filters, and bound the race-loss candidate walk with `maxAttempts` (1 through
|
|
|
1127
1132
|
tools do not need to reproduce CLI concurrency policy.
|
|
1128
1133
|
|
|
1129
1134
|
Lifecycle convenience methods and the matching top-level functions (`create`,
|
|
1130
|
-
`update`, `close`, `claim`, `release`, `copy`, `deleteItem`, `restore`,
|
|
1135
|
+
`update`, `reopen`, `close`, `claim`, `release`, `copy`, `deleteItem`, `restore`,
|
|
1131
1136
|
`focus`, `startTask`, `pauseTask`, and `closeTask`) use the same mutation paths
|
|
1132
1137
|
as the CLI and MCP dispatcher. They are the baseline primitives for custom PM
|
|
1133
|
-
tools that need to own item state without spawning `pm`.
|
|
1138
|
+
tools that need to own item state without spawning `pm`. `reopen` requires a
|
|
1139
|
+
recurrence reason, accepts only the workspace open or in-progress target, and
|
|
1140
|
+
returns the terminal evidence captured atomically before the update path clears
|
|
1141
|
+
it from active metadata.
|
|
1134
1142
|
|
|
1135
1143
|
### Atomic workspace transactions
|
|
1136
1144
|
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Tracker: [pm-0k19l7](../.agents/pm/issues/pm-0k19l7.toon), [pm-9stazf](../.agents/pm/issues/pm-9stazf.toon), [pm-tu71](../.agents/pm/issues/pm-tu71.toon), [pm-0xmajx](../.agents/pm/issues/pm-0xmajx.toon), [pm-7rrqsk](../.agents/pm/issues/pm-7rrqsk.toon), [pm-ety1qc](../.agents/pm/issues/pm-ety1qc.toon), [pm-lu6sca](../.agents/pm/features/pm-lu6sca.toon), [pm-5y05kq](../.agents/pm/issues/pm-5y05kq.toon), [pm-gjjurs](../.agents/pm/issues/pm-gjjurs.toon), [pm-h97qxd](../.agents/pm/issues/pm-h97qxd.toon), [pm-h06944](../.agents/pm/issues/pm-h06944.toon), [pm-5t33or](../.agents/pm/features/pm-5t33or.toon), [pm-in23qu](../.agents/pm/issues/pm-in23qu.toon), [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon), [pm-okgxwa](../.agents/pm/issues/pm-okgxwa.toon), [pm-22rzjp](../.agents/pm/issues/pm-22rzjp.toon), [pm-76fkpp](../.agents/pm/issues/pm-76fkpp.toon), [pm-igdvfq](../.agents/pm/issues/pm-igdvfq.toon), [pm-643e0k](../.agents/pm/issues/pm-643e0k.toon), [pm-larv4r](../.agents/pm/issues/pm-larv4r.toon), [pm-mcxk8v](../.agents/pm/issues/pm-mcxk8v.toon), and [pm-2zkvxm](../.agents/pm/issues/pm-2zkvxm.toon).
|
|
4
4
|
|
|
5
|
+
Current closure tranche: [pm-fs8q9x](../.agents/pm/tasks/pm-fs8q9x.toon), [pm-gy885b](../.agents/pm/issues/pm-gy885b.toon), and [pm-f05lsg](../.agents/pm/features/pm-f05lsg.toon).
|
|
6
|
+
|
|
5
7
|
## Agent Quick Context
|
|
6
8
|
|
|
7
9
|
These contracts keep project management equal to context management: reads say what they omit, writes return only newly useful context, diagnostics do not unexpectedly call remote providers, and every transport delegates domain validation to the same SDK primitive. Package authors can use the same primitives without reproducing CLI parsing rules.
|
|
@@ -74,6 +76,39 @@ The structured `option_scope` is `declared_on_path`, `declared_elsewhere`, or
|
|
|
74
76
|
case, while the third names the nearest current-path spellings and explicitly
|
|
75
77
|
terminates the otherwise-unbounded command search.
|
|
76
78
|
|
|
79
|
+
## Semantic flag and spelling contracts
|
|
80
|
+
|
|
81
|
+
`listPmFlagLexicon()` classifies flags by meaning rather than spelling alone.
|
|
82
|
+
For example, `--limit` is the shared `result-row-limit` concept, while
|
|
83
|
+
`--node-limit`, `--edge-limit`, `--output-limit`, `--output-budget`, and
|
|
84
|
+
`--token-budget` retain distinct graph, serialization, and intent-budget
|
|
85
|
+
semantics. Command-local overloads such as `--file` are explicitly separated
|
|
86
|
+
into linked-file, annotation-input, and plan-definition concepts.
|
|
87
|
+
|
|
88
|
+
`listPmFlagSpellingInventory()` publishes every canonical spelling and every
|
|
89
|
+
accepted compatibility alias. The repository gate compares it with
|
|
90
|
+
`scripts/release/flag-spelling-baseline.json`; removing either a canonical flag
|
|
91
|
+
or an established alias fails closed. A separate generated help baseline
|
|
92
|
+
records UTF-8 size, estimated tokens, and per-command deltas, so a vocabulary
|
|
93
|
+
change cannot silently expand the agent discovery surface. Refreshing either
|
|
94
|
+
baseline is an explicit reviewed operation through
|
|
95
|
+
`node scripts/release/flag-lexicon-gate.mjs --update-inventory`.
|
|
96
|
+
|
|
97
|
+
## Closed-domain refusal contracts
|
|
98
|
+
|
|
99
|
+
`listCoreClosedDomainContracts()` is the SDK-owned registry for every built-in
|
|
100
|
+
`--for` intent and `--fields` projection refusal. It derives projection values
|
|
101
|
+
from the list, get, and search query modules and covers all eight list-family
|
|
102
|
+
entrypoints. CLI help uses the same registry, representing `item.<field>` and
|
|
103
|
+
runtime-schema extensions with compact generative notation instead of
|
|
104
|
+
repeating every alias.
|
|
105
|
+
|
|
106
|
+
The executable gate derives its refusal corpus from this registry, requires
|
|
107
|
+
the exact error code, complete `allowed_values`, shell-free
|
|
108
|
+
`suggested_retry_args`, and a successful retry, then compares probe identities
|
|
109
|
+
with `scripts/release/refusal-closure-baseline.json`. Adding a new core domain
|
|
110
|
+
without a probe or removing historical coverage therefore fails CI.
|
|
111
|
+
|
|
77
112
|
## Executable recovery-reference coverage
|
|
78
113
|
|
|
79
114
|
Structured refusal guidance is a forward-reference contract, not decorative
|
|
@@ -89,6 +124,16 @@ family. Each obligation declares `recovery`, `replacement`, or
|
|
|
89
124
|
`behavior_preserving` semantics and its proof must demonstrate the same
|
|
90
125
|
promise.
|
|
91
126
|
|
|
127
|
+
`verifyPmRecoveryKindRuntimeCoverage` joins the syntax-aware complete source
|
|
128
|
+
census to distinct emitted values for every typed kind. Its receipt retains
|
|
129
|
+
both denominators and fails when a kind has source producers but no runtime
|
|
130
|
+
evidence, preventing a representative recovery example from masking an
|
|
131
|
+
entirely unexecuted producer family. This is explicitly kind-level assurance:
|
|
132
|
+
it does not claim that every individual source location or every distinct value
|
|
133
|
+
was executed. The former `verifyPmRecoveryProducerRuntimeCoverage` export
|
|
134
|
+
remains as a deprecated compatibility alias with those same kind-level
|
|
135
|
+
semantics.
|
|
136
|
+
|
|
92
137
|
The repository integration corpus drives real CLI refusals, executes the
|
|
93
138
|
emitted retry in a temporary tracker, compares candidate commands with the
|
|
94
139
|
unbounded runtime contract enumeration, and binds examples and next steps to
|
|
@@ -12,7 +12,7 @@ This file is generated from `PM_COMMAND_CAPABILITY_CONTRACTS`. Do not edit it ma
|
|
|
12
12
|
| `install` | full | extensions |
|
|
13
13
|
| `upgrade` | full | extensions |
|
|
14
14
|
| `create` | core | intake |
|
|
15
|
-
| `item` | full |
|
|
15
|
+
| `item-reopen` | full | lifecycle |
|
|
16
16
|
| `copy` | full | intake |
|
|
17
17
|
| `focus` | standard | intake |
|
|
18
18
|
| `list` | core | context |
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
# SDK entrypoint import costs
|
|
2
2
|
|
|
3
3
|
Tracked by [pm-38bskj](../../.agents/pm/tasks/pm-38bskj.toon) and
|
|
4
|
-
[pm-cg1sjb](../../.agents/pm/issues/pm-cg1sjb.toon).
|
|
5
|
-
topology is tracked by
|
|
6
|
-
[pm-m9gu9r](../../.agents/pm/chores/pm-m9gu9r.toon).
|
|
4
|
+
[pm-cg1sjb](../../.agents/pm/issues/pm-cg1sjb.toon).
|
|
7
5
|
|
|
8
6
|
This table measures fresh-process ESM import and module evaluation. The bare
|
|
9
7
|
Node v26.5.0 process floor on linux/x64
|
|
10
|
-
was
|
|
8
|
+
was 44 ms p50 (56 ms p95) across
|
|
11
9
|
5 measured runs after one warm-up. Focused entrypoints are
|
|
12
10
|
compared with the compatibility aggregate; negative reduction means the focused
|
|
13
11
|
entrypoint was slower in this sample. The gate admits the median measured run
|
|
@@ -15,25 +13,20 @@ against the unchanged upper-bound budget and 30 ms scheduler margin. A single
|
|
|
15
13
|
cold or descheduled process therefore cannot fail the gate, while a majority of
|
|
16
14
|
over-budget samples still does; p95 remains visible as diagnostic evidence.
|
|
17
15
|
|
|
18
|
-
| Package export
|
|
19
|
-
|
|
20
|
-
| `./sdk`
|
|
21
|
-
| `./sdk/authoring`
|
|
22
|
-
| `./sdk/contracts`
|
|
23
|
-
| `./sdk/core`
|
|
24
|
-
| `./sdk/governance` |
|
|
25
|
-
| `./sdk/graph`
|
|
26
|
-
| `./sdk/merge`
|
|
27
|
-
| `./sdk/query`
|
|
28
|
-
| `./sdk/runtime`
|
|
29
|
-
| `./sdk/testing`
|
|
16
|
+
| Package export | p50 | p95 | p50 above Node | Reduction vs aggregate overhead |
|
|
17
|
+
|---|---:|---:|---:|---:|
|
|
18
|
+
| `./sdk` | 320 ms | 348 ms | 276 ms | 0% |
|
|
19
|
+
| `./sdk/authoring` | 91 ms | 99 ms | 47 ms | 83% |
|
|
20
|
+
| `./sdk/contracts` | 152 ms | 156 ms | 108 ms | 60.9% |
|
|
21
|
+
| `./sdk/core` | 285 ms | 291 ms | 241 ms | 12.7% |
|
|
22
|
+
| `./sdk/governance` | 211 ms | 220 ms | 167 ms | 39.5% |
|
|
23
|
+
| `./sdk/graph` | 92 ms | 105 ms | 48 ms | 82.6% |
|
|
24
|
+
| `./sdk/merge` | 130 ms | 145 ms | 86 ms | 68.8% |
|
|
25
|
+
| `./sdk/query` | 132 ms | 156 ms | 88 ms | 68.1% |
|
|
26
|
+
| `./sdk/runtime` | 283 ms | 312 ms | 239 ms | 13.4% |
|
|
27
|
+
| `./sdk/testing` | 274 ms | 319 ms | 230 ms | 16.7% |
|
|
30
28
|
|
|
31
29
|
The aggregate `@unbrained/pm-cli/sdk` remains supported for compatibility.
|
|
32
30
|
New packages should import the narrowest subpath that owns their capability.
|
|
33
|
-
The build emits `./sdk/merge` as a standalone no-splitting bundle because its
|
|
34
|
-
dependency closure overlaps with several broader focused entrypoints. Keeping
|
|
35
|
-
that surface in the shared focused chunk graph made a merge-only import traverse
|
|
36
|
-
unrelated chunks; the isolated output preserves the same public exports while
|
|
37
|
-
keeping its runtime loading cost proportional to the capability requested.
|
|
38
31
|
The committed budget file is an upper-bound ratchet and must not be weakened to
|
|
39
32
|
hide a regression.
|
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.20"
|
|
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.20",
|
|
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.20",
|
|
4
4
|
"description": "Git-native project management CLI for humans and agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@11.10.0",
|
|
@@ -218,18 +218,18 @@
|
|
|
218
218
|
"@sentry/cli": "^3.6.2",
|
|
219
219
|
"@types/node": "^26.2.0",
|
|
220
220
|
"@types/npm-package-arg": "^6.1.4",
|
|
221
|
-
"@vitest/coverage-v8": "^4.1.
|
|
221
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
222
222
|
"esbuild": "0.28.2",
|
|
223
223
|
"eslint": "^10.8.1",
|
|
224
224
|
"eslint-plugin-sonarjs": "^4.2.0",
|
|
225
225
|
"eslint-plugin-unicorn": "^73.0.0",
|
|
226
226
|
"fast-check": "^4.9.0",
|
|
227
|
-
"greptile": "^3.4.
|
|
228
|
-
"jscpd": "^5.0.
|
|
227
|
+
"greptile": "^3.4.1",
|
|
228
|
+
"jscpd": "^5.0.16",
|
|
229
229
|
"tsx": "^4.23.12",
|
|
230
230
|
"typescript": "^6.0.3",
|
|
231
231
|
"typescript-eslint": "^8.67.0",
|
|
232
|
-
"vitest": "^4.1.
|
|
232
|
+
"vitest": "^4.1.11",
|
|
233
233
|
"yaml": "^2.9.0"
|
|
234
234
|
}
|
|
235
235
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unbrained/pm-digital-twin",
|
|
3
|
-
"version": "2026.8.
|
|
3
|
+
"version": "2026.8.20",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Beyond-PM exemplar: a temporal production-facility digital twin built entirely on public pm SDK and extension primitives.",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pm-claude",
|
|
3
3
|
"description": "Native pm CLI integration for Claude Code — 28 MCP tools, 5 workflow skills, 14 slash commands, 4 subagents (coordinator, delivery-chain, triage, verification), hybrid TUI task tracking (pm as persistent store + Claude Code task panel as live view), session context injection, and full git-based project management without leaving Claude Code.",
|
|
4
|
-
"version": "2026.8.
|
|
4
|
+
"version": "2026.8.20",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "unbrained",
|
|
7
7
|
"url": "https://github.com/unbraind/pm-cli"
|