@unbrained/pm-cli 2026.8.18 → 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 +35 -2
- package/dist/cli/error-guidance.js +3 -2
- package/dist/cli/help-content.js +32 -13
- package/dist/cli/help-json-payload.d.ts +15 -0
- package/dist/cli/help-json-payload.js +101 -23
- package/dist/cli/main.js +6 -2
- package/dist/cli/register-list-query.js +18 -13
- package/dist/cli/register-mutation.js +8 -8
- package/dist/cli/register-operations.js +6 -6
- 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-UYCLQVL2.js → chunk-2RDVGYWE.js} +12 -12
- package/dist/cli-bundle/chunks/{chunk-BSK2IN3C.js → chunk-4GB2LTOQ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-RZQTVMRQ.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-K3EN3LK2.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-YRGOLZA7.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-5UZZAJKR.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-XJPAW63D.js +20 -0
- package/dist/cli-bundle/chunks/register-operations-DSOSB2XQ.js +2 -0
- package/dist/cli-bundle/chunks/{register-setup-PPPEF3SN.js → register-setup-QUR6QL2C.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-325UXIO7.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-5L7M4AI7.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-ODOVCP45.js → chunk-6AHG2YW7.js} +44 -44
- package/dist/cli-bundle/focused-chunks/chunk-AZBACT5T.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-TN4AE665.js → chunk-BLJCGGID.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-FUREQLQN.js +18 -0
- package/dist/cli-bundle/focused-chunks/{chunk-M62NO7EI.js → chunk-G3C5ERXG.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-K43KKAFS.js → chunk-GXWQBE3T.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-UI6AJ5TD.js → chunk-JWKEDZJI.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-KYZ6JGPL.js +155 -0
- package/dist/cli-bundle/focused-chunks/{chunk-EX6MKP2X.js → chunk-M32HFIQB.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-EUEGXZ2A.js → chunk-OM65KHGF.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-Q47EX4DI.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-V5XTGLK7.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-UGSS4F5X.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-Z3PLWSGM.js +2 -0
- package/dist/cli-bundle/main.js +13 -13
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -1
- 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 +32 -32
- 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 -4
- 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/errors.d.ts +2 -0
- package/dist/core/shared/errors.js +2 -2
- 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 +53 -0
- package/dist/sdk/agent/refusal-closure.js +134 -0
- package/dist/sdk/agent/refusal-reachability.d.ts +27 -1
- package/dist/sdk/agent/refusal-reachability.js +26 -2
- package/dist/sdk/agent-capability-contracts.d.ts +13 -0
- package/dist/sdk/agent-capability-contracts.js +101 -9
- package/dist/sdk/cli-contracts/command-aliases.js +18 -2
- package/dist/sdk/cli-contracts/commander-mutation-options.js +30 -6
- package/dist/sdk/cli-contracts/commander-types.js +5 -4
- 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 +7 -0
- package/dist/sdk/cli-contracts/flag-contracts.js +84 -8
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.d.ts +72 -0
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +340 -0
- package/dist/sdk/cli-contracts/grammar-contracts.d.ts +83 -2
- package/dist/sdk/cli-contracts/grammar-contracts.js +618 -2
- package/dist/sdk/cli-contracts/runtime-contracts.d.ts +15 -4
- package/dist/sdk/cli-contracts/runtime-contracts.js +47 -13
- package/dist/sdk/cli-contracts/tool-option-contracts.d.ts +28 -1
- package/dist/sdk/cli-contracts/tool-option-contracts.js +38 -3
- package/dist/sdk/cli-contracts/tool-schema.js +7 -2
- package/dist/sdk/cli-contracts.d.ts +4 -3
- package/dist/sdk/cli-contracts.js +6 -5
- package/dist/sdk/context-intent-contracts.d.ts +2 -2
- package/dist/sdk/context-intent-contracts.js +22 -7
- package/dist/sdk/contracts.d.ts +3 -0
- package/dist/sdk/contracts.js +5 -2
- package/dist/sdk/core.d.ts +1 -1
- package/dist/sdk/core.js +3 -3
- package/dist/sdk/flag-invocation-contracts.d.ts +37 -0
- package/dist/sdk/flag-invocation-contracts.js +218 -9
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +206 -2
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +244 -40
- package/dist/sdk/index.d.ts +11 -7
- package/dist/sdk/index.js +10 -6
- 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/output-projection.d.ts +2 -0
- package/dist/sdk/output-projection.js +11 -5
- package/dist/sdk/query/get.d.ts +1 -1
- package/dist/sdk/query/get.js +34 -49
- package/dist/sdk/query/list.d.ts +7 -21
- package/dist/sdk/query/list.js +44 -44
- 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 +3 -2
- package/dist/sdk/query/search-contracts.js +30 -85
- package/dist/sdk/query/search.d.ts +15 -0
- package/dist/sdk/query/search.js +32 -6
- package/dist/sdk/read-output/continuation.d.ts +1 -1
- package/dist/sdk/read-output/continuation.js +7 -24
- package/dist/sdk/read-output-contracts.js +55 -6
- package/dist/sdk/read-output-rows.d.ts +4 -0
- package/dist/sdk/read-output-rows.js +47 -18
- 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 +25 -17
- package/dist/sdk/similarity.d.ts +13 -0
- package/dist/sdk/similarity.js +32 -6
- package/dist/sdk/workspace-snapshot.d.ts +2 -0
- package/dist/sdk/workspace-snapshot.js +10 -2
- package/docs/COMMANDS.md +29 -5
- package/docs/OUTPUT_PROJECTION_CONTRACTS.md +11 -2
- package/docs/README.md +1 -0
- package/docs/READ_OUTPUT_CONTRACTS.md +10 -6
- package/docs/RECURRENCE_RECOVERY_CONTRACTS.md +114 -0
- package/docs/SDK.md +16 -2
- package/docs/SDK_CONTEXT_INTEGRITY.md +45 -0
- package/docs/TESTING.md +14 -1
- package/docs/generated/AGENT_COMMAND_SURFACE.md +78 -78
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +76 -0
- package/docs/performance/sdk-entrypoint-import-costs.md +14 -21
- package/marketplace.json +2 -2
- package/package.json +9 -7
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/scripts/generate-agent-capability-surfaces.mjs +20 -14
- package/sdk/public-surface.json +950 -24
- package/dist/cli-bundle/chunks/chunk-ALDJGKAK.js +0 -2
- package/dist/cli-bundle/chunks/chunk-DY4DMUMC.js +0 -197
- package/dist/cli-bundle/chunks/chunk-GNFAFIJI.js +0 -77
- package/dist/cli-bundle/chunks/chunk-L5Q2CLPE.js +0 -35
- package/dist/cli-bundle/chunks/chunk-PVRUN5ZS.js +0 -5
- package/dist/cli-bundle/chunks/chunk-SARFF5H5.js +0 -3
- package/dist/cli-bundle/chunks/register-list-query-I23LALEE.js +0 -11
- package/dist/cli-bundle/chunks/register-mutation-6YGU3GPH.js +0 -20
- package/dist/cli-bundle/chunks/register-operations-4HTFC6J7.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-2PN4TJXH.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-3TKWMNKF.js +0 -18
- package/dist/cli-bundle/focused-chunks/chunk-5AF3ZBNB.js +0 -155
- package/dist/cli-bundle/focused-chunks/chunk-C5IW2NDA.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-RNDNMARJ.js +0 -16
- package/dist/cli-bundle/focused-chunks/chunk-TVV2DONO.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-WGHQVU6P.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-XYNBXTDQ.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-Z56ECT7I.js +0 -2
package/dist/sdk/runtime.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Defines public SDK APIs and package-author helpers for Runtime.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!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]="
|
|
7
|
+
!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]="c770afea-3eb6-5476-ba07-8ec1c5d9c699")}catch(e){}}();
|
|
8
8
|
export { PM_GITIGNORE_END, PM_GITIGNORE_START, ensurePmGitignore, getPmGitignoreBlock, } from "./workspace.js";
|
|
9
9
|
export { SEARCH_EXTENSION_FLAG_DEFINITIONS } from "./extension-contracts.js";
|
|
10
10
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -70,6 +70,7 @@ import { acknowledgeUnknownAuthorHistoryEventsFromTransport, } from "./author-at
|
|
|
70
70
|
import { PROFILE_SUBCOMMANDS, runProfileApply, runProfileLint, runProfileList, runProfileShow, } from "./profile.js";
|
|
71
71
|
import { runHistoryRedact, } from "./history-redact.js";
|
|
72
72
|
import { runMcpHistoryCompactAction, runMcpHistoryRepairAction, } from "./history-mcp.js";
|
|
73
|
+
import { runMcpCloseAction, runMcpReopenAction } from "./lifecycle/mcp-actions.js";
|
|
73
74
|
import { actionGlobalOptions as globalOptions, closeManyOptionsFromFlat, extensionOptionsFromArgs, graphOptionsFromFlat, mutationListOptions, normalizeActionName, normalizeCommandPath, normalizeMcpOptionsArrays, normalizeMcpUpdateOptions, optionsWithAuthor, parseRuntimeInteger as parseMcpInteger, readRuntimeScalarString as readScalarString, readRuntimeScalarStringAllowBlank as readScalarStringAllowBlank, readRuntimeString as readString, readRuntimeStringArray as readStringArray, resolveRuntimeLimit, updateManyOptionsFromFlat, withAddNoteOption, withFilesDiscoveryOptions, withMutationCompaction, } from "./runtime-input.js";
|
|
74
75
|
import { runDeps } from "./dependencies.js";
|
|
75
76
|
import { runDocs } from "./docs.js";
|
|
@@ -119,6 +120,7 @@ export { runFocus, } from "./lifecycle/focus.js";
|
|
|
119
120
|
export { runRestore, } from "./lifecycle/restore.js";
|
|
120
121
|
export { DEFAULT_TERMINAL_TRANSITION_POLICY, applyTerminalOrderingPolicy, requireTerminalReason, resolveTerminalReason, } from "./lifecycle-policy.js";
|
|
121
122
|
export { runUpdate } from "./lifecycle/update.js";
|
|
123
|
+
export { runReopen } from "./lifecycle/reopen.js";
|
|
122
124
|
export { NEXT_OUTPUT_VALUES, runNext, } from "./query/next.js";
|
|
123
125
|
export { runSearch, } from "./query/search.js";
|
|
124
126
|
export { runStats, } from "./stats.js";
|
|
@@ -536,6 +538,15 @@ export class PmClient {
|
|
|
536
538
|
...splitFullClientMutationOptions(options),
|
|
537
539
|
});
|
|
538
540
|
}
|
|
541
|
+
/** Reopen terminal work as a recurrence through the canonical update path. */
|
|
542
|
+
reopen(id, reason, options = {}) {
|
|
543
|
+
return this.runTyped("item-reopen", {
|
|
544
|
+
id,
|
|
545
|
+
reason,
|
|
546
|
+
fullChangedFields: true,
|
|
547
|
+
options,
|
|
548
|
+
});
|
|
549
|
+
}
|
|
539
550
|
/** Close an item using the same mutation path as `pm close`. Options are contract-typed (pm-x29o); the close reason is the positional parameter, so the option bag omits `reason`/`text`. */
|
|
540
551
|
close(id, reason, options = {}) {
|
|
541
552
|
return this.runTyped("close", {
|
|
@@ -908,6 +919,10 @@ export function create(options = {}, clientOptions = {}) {
|
|
|
908
919
|
export function update(id, options = {}, clientOptions = {}) {
|
|
909
920
|
return new PmClient(clientOptions).update(id, options);
|
|
910
921
|
}
|
|
922
|
+
/** Reopen terminal work as a recurrence without constructing a reusable client. */
|
|
923
|
+
export function reopen(id, reason, options = {}, clientOptions = {}) {
|
|
924
|
+
return new PmClient(clientOptions).reopen(id, reason, options);
|
|
925
|
+
}
|
|
911
926
|
/** Close an item without constructing a reusable client. */
|
|
912
927
|
export function close(id, reason, options = {}, clientOptions = {}) {
|
|
913
928
|
return new PmClient(clientOptions).close(id, reason, options);
|
|
@@ -1349,13 +1364,14 @@ async function runMcpListAction(ctx) {
|
|
|
1349
1364
|
return withQuerySummary((await runList(readString(ctx.args, "status") ?? readString(listOptions, "status"), listOptions, ctx.global)), listOptions);
|
|
1350
1365
|
}
|
|
1351
1366
|
async function runMcpSearchAction(ctx) {
|
|
1352
|
-
const
|
|
1367
|
+
const query = readRequiredString(ctx.args, "query");
|
|
1368
|
+
const searchOptions = applyContextIntentProjection("search", ctx.options, [query]);
|
|
1353
1369
|
if (searchOptions.compact === undefined &&
|
|
1354
1370
|
searchOptions.full === undefined &&
|
|
1355
1371
|
searchOptions.fields === undefined) {
|
|
1356
1372
|
searchOptions.compact = true;
|
|
1357
1373
|
}
|
|
1358
|
-
return withQuerySummary((await runSearch(
|
|
1374
|
+
return withQuerySummary((await runSearch(query, searchOptions, ctx.global)), searchOptions);
|
|
1359
1375
|
}
|
|
1360
1376
|
async function runMcpCreateAction(ctx) {
|
|
1361
1377
|
const { changedFields, idOnly, runnerOptions } = withMutationCompaction(ctx.args, ctx.options);
|
|
@@ -1391,18 +1407,6 @@ async function runMcpUpdateAction(ctx) {
|
|
|
1391
1407
|
idOnly,
|
|
1392
1408
|
});
|
|
1393
1409
|
}
|
|
1394
|
-
async function runMcpCloseAction(ctx) {
|
|
1395
|
-
const { changedFields, idOnly, runnerOptions } = withMutationCompaction(ctx.args, ctx.options);
|
|
1396
|
-
const closeReason = readString(ctx.args, "reason") ??
|
|
1397
|
-
readString(ctx.args, "text") ??
|
|
1398
|
-
readString(runnerOptions, "reason") ??
|
|
1399
|
-
readString(runnerOptions, "text");
|
|
1400
|
-
return projectMutationResult(await runClose(requireMcpItemId(ctx, runnerOptions), closeReason, runnerOptions, ctx.global), {
|
|
1401
|
-
changedFields,
|
|
1402
|
-
compactEnvelope: changedFields === "compact" && !idOnly,
|
|
1403
|
-
idOnly,
|
|
1404
|
-
});
|
|
1405
|
-
}
|
|
1406
1410
|
function runMcpCommentsAction(ctx) {
|
|
1407
1411
|
const commentOptions = normalizeAnnotationTransportOptions(ctx.options);
|
|
1408
1412
|
const isListing = commentOptions.add === undefined &&
|
|
@@ -1783,7 +1787,10 @@ const SDK_ACTION_HANDLERS = {
|
|
|
1783
1787
|
event: runRuntimeSchedulingAction,
|
|
1784
1788
|
remind: runRuntimeSchedulingAction,
|
|
1785
1789
|
list: runMcpListAction,
|
|
1786
|
-
get: (ctx) =>
|
|
1790
|
+
get: (ctx) => {
|
|
1791
|
+
const id = requireMcpItemId(ctx);
|
|
1792
|
+
return runGet(id, ctx.global, applyContextIntentProjection("get", ctx.options, [id]));
|
|
1793
|
+
},
|
|
1787
1794
|
search: runMcpSearchAction,
|
|
1788
1795
|
duplicates: (ctx) => {
|
|
1789
1796
|
const status = typeof ctx.options.status === "string"
|
|
@@ -1804,6 +1811,7 @@ const SDK_ACTION_HANDLERS = {
|
|
|
1804
1811
|
copy: runMcpCopyAction,
|
|
1805
1812
|
focus: (ctx) => runFocus(ctx.id, { clear: ctx.options.clear === true || ctx.args.clear === true }, ctx.global),
|
|
1806
1813
|
update: runMcpUpdateAction,
|
|
1814
|
+
"item-reopen": runMcpReopenAction,
|
|
1807
1815
|
restore: runMcpRestoreAction,
|
|
1808
1816
|
claim: (ctx) => ctx.options.next === true || ctx.args.next === true
|
|
1809
1817
|
? runClaimNext(ctx.force, ctx.global, { ...ctx.options, ...ctx.args }, { ...ctx.options, ...ctx.args })
|
|
@@ -1936,4 +1944,4 @@ async function loadWorkspaceExtensionRegistrations(pmRoot, settings, cwd) {
|
|
|
1936
1944
|
}
|
|
1937
1945
|
}
|
|
1938
1946
|
//# sourceMappingURL=runtime.js.map
|
|
1939
|
-
//# debugId=
|
|
1947
|
+
//# debugId=c770afea-3eb6-5476-ba07-8ec1c5d9c699
|
package/dist/sdk/similarity.d.ts
CHANGED
|
@@ -115,6 +115,19 @@ export interface SimilarityAdvisory {
|
|
|
115
115
|
bypassed: boolean;
|
|
116
116
|
/** Shared similarity query result. */
|
|
117
117
|
result: SimilarItemsResult;
|
|
118
|
+
/** Executable next action selected from the strongest matching item's lifecycle state. */
|
|
119
|
+
recovery: SimilarityRecovery;
|
|
120
|
+
}
|
|
121
|
+
/** Executable duplicate-intake recovery selected from the strongest match. */
|
|
122
|
+
export interface SimilarityRecovery {
|
|
123
|
+
/** Whether to continue existing active work or reopen terminal work as a recurrence. */
|
|
124
|
+
action: "reuse" | "reopen";
|
|
125
|
+
/** Strongest matching canonical item. */
|
|
126
|
+
item_id: string;
|
|
127
|
+
/** Shell-form recovery command. */
|
|
128
|
+
command: string;
|
|
129
|
+
/** Tokenized recovery command for direct execution. */
|
|
130
|
+
args: string[];
|
|
118
131
|
}
|
|
119
132
|
/** Render compact warning tokens shared by create and copy results. */
|
|
120
133
|
export declare function similarityAdvisoryWarnings(advisory: SimilarityAdvisory | undefined): string[];
|
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
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** Current content-addressed workspace snapshot manifest schema identifier. */
|
|
2
2
|
export declare const SNAPSHOT_SCHEMA = "https://schema.unbrained.dev/pm/workspace-snapshot/v1";
|
|
3
|
+
/** Workspace snapshot action tokens accepted by the SDK and CLI dispatcher. */
|
|
4
|
+
export declare const WORKSPACE_SNAPSHOT_ACTIONS: readonly ["create", "list", "inspect", "restore", "delete"];
|
|
3
5
|
/** Filesystem operations required by atomic snapshot publish and restore swaps. */
|
|
4
6
|
export interface WorkspaceSnapshotAtomicOperations {
|
|
5
7
|
/** Rename one filesystem entry atomically. */
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* state while excluding clone-local caches, locks, and recovery journals.
|
|
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]="2580e043-8675-5070-b57e-30cae333228c")}catch(e){}}();
|
|
9
9
|
import crypto from "node:crypto";
|
|
10
10
|
import { cp, lstat, mkdir, readFile, readdir, rename, rm, writeFile, } from "node:fs/promises";
|
|
11
11
|
import path from "node:path";
|
|
@@ -18,6 +18,14 @@ import { PmCliError } from "../core/shared/errors.js";
|
|
|
18
18
|
import { withHostEnvironmentBoundary } from "./environment/host-environment-errors.js";
|
|
19
19
|
/** Current content-addressed workspace snapshot manifest schema identifier. */
|
|
20
20
|
export const SNAPSHOT_SCHEMA = "https://schema.unbrained.dev/pm/workspace-snapshot/v1";
|
|
21
|
+
/** Workspace snapshot action tokens accepted by the SDK and CLI dispatcher. */
|
|
22
|
+
export const WORKSPACE_SNAPSHOT_ACTIONS = [
|
|
23
|
+
"create",
|
|
24
|
+
"list",
|
|
25
|
+
"inspect",
|
|
26
|
+
"restore",
|
|
27
|
+
"delete",
|
|
28
|
+
];
|
|
21
29
|
const SNAPSHOT_RUNTIME_PATH = path.join("runtime", "workspace-snapshots");
|
|
22
30
|
const EXCLUDED_ROOT_NAMES = new Set([
|
|
23
31
|
"checkpoints",
|
|
@@ -603,4 +611,4 @@ export async function deleteWorkspaceSnapshot(pmRoot, target) {
|
|
|
603
611
|
return { deleted: "object", target };
|
|
604
612
|
}
|
|
605
613
|
//# sourceMappingURL=workspace-snapshot.js.map
|
|
606
|
-
//# debugId=
|
|
614
|
+
//# debugId=2580e043-8675-5070-b57e-30cae333228c
|
package/docs/COMMANDS.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This is a task-oriented command guide. For exact flags, use runtime help because extensions and settings can change the active surface:
|
|
4
4
|
|
|
5
|
-
Tracked implementation updates: [pm-52eh](../.agents/pm/features/pm-52eh.toon), [pm-mcxr](../.agents/pm/issues/pm-mcxr.toon), [pm-qd3woa](../.agents/pm/issues/pm-qd3woa.toon), [pm-ypuc39](../.agents/pm/issues/pm-ypuc39.toon), [pm-tz2ikr](../.agents/pm/issues/pm-tz2ikr.toon), the schema-migration recovery contract [pm-s79kel](../.agents/pm/issues/pm-s79kel.toon), the lossless mutation contracts [pm-x3dq0l](../.agents/pm/issues/pm-x3dq0l.toon), [pm-lppm6y](../.agents/pm/issues/pm-lppm6y.toon), and [pm-embm6t](../.agents/pm/issues/pm-embm6t.toon), and the SDK-first agent grammar tranche [pm-p316vn](../.agents/pm/issues/pm-p316vn.toon), [pm-st7wgu](../.agents/pm/issues/pm-st7wgu.toon), [pm-mkinft](../.agents/pm/issues/pm-mkinft.toon), [pm-ulqu](../.agents/pm/issues/pm-ulqu.toon), [pm-qmjx](../.agents/pm/issues/pm-qmjx.toon), [pm-4bzq](../.agents/pm/features/pm-4bzq.toon), [pm-x2vx](../.agents/pm/issues/pm-x2vx.toon), and [pm-g543](../.agents/pm/issues/pm-g543.toon).
|
|
5
|
+
Tracked implementation updates: [pm-52eh](../.agents/pm/features/pm-52eh.toon), [pm-mcxr](../.agents/pm/issues/pm-mcxr.toon), [pm-qd3woa](../.agents/pm/issues/pm-qd3woa.toon), [pm-ypuc39](../.agents/pm/issues/pm-ypuc39.toon), [pm-tz2ikr](../.agents/pm/issues/pm-tz2ikr.toon), the schema-migration recovery contract [pm-s79kel](../.agents/pm/issues/pm-s79kel.toon), the lossless mutation contracts [pm-x3dq0l](../.agents/pm/issues/pm-x3dq0l.toon), [pm-lppm6y](../.agents/pm/issues/pm-lppm6y.toon), and [pm-embm6t](../.agents/pm/issues/pm-embm6t.toon), positional action discovery [pm-2tan](../.agents/pm/issues/pm-2tan.toon), and the SDK-first agent grammar tranche [pm-p316vn](../.agents/pm/issues/pm-p316vn.toon), [pm-st7wgu](../.agents/pm/issues/pm-st7wgu.toon), [pm-mkinft](../.agents/pm/issues/pm-mkinft.toon), [pm-ulqu](../.agents/pm/issues/pm-ulqu.toon), [pm-qmjx](../.agents/pm/issues/pm-qmjx.toon), [pm-4bzq](../.agents/pm/features/pm-4bzq.toon), [pm-x2vx](../.agents/pm/issues/pm-x2vx.toon), and [pm-g543](../.agents/pm/issues/pm-g543.toon).
|
|
6
6
|
|
|
7
7
|
Workspace-integrity contracts are tracked by [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), and [pm-larv4r](../.agents/pm/issues/pm-larv4r.toon).
|
|
8
8
|
|
|
@@ -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.
|
|
@@ -1120,6 +1132,13 @@ Profiles are extensible: a package can ship its own archetype with `api.register
|
|
|
1120
1132
|
|
|
1121
1133
|
Plan creation shares the normal create contract. Governance fields such as `--status`, `--deadline`, `--estimate`, `--acceptance-criteria`, `--assignee`, review/risk fields, comments, notes, learnings, reminders, events, and linked resources are accepted directly and pass through the same strict/progressive schema validation as `pm create`.
|
|
1122
1134
|
|
|
1135
|
+
Every positional plan action is also a discoverable virtual command path. Use
|
|
1136
|
+
`pm plan create --help --json` or `pm help plan create --json` for its exact
|
|
1137
|
+
arguments and effective flags, and use `pm contracts --command "plan create"
|
|
1138
|
+
--flags-only --json` for the matching machine contract. Root `pm plan --help
|
|
1139
|
+
--json` publishes the same action inventory under `subcommands`; omitting the
|
|
1140
|
+
required action fails as `missing_required_argument` before mutation dispatch.
|
|
1141
|
+
|
|
1123
1142
|
```bash
|
|
1124
1143
|
pm plan create --title "Refactor lock retry" --scope "Improve retry semantics" --harness claude-code --parent pm-epic1 --related pm-rel1,pm-rel2 --claim
|
|
1125
1144
|
pm plan create --title "Fix flaky retry test" --step "Read lock.ts" --step "Write the fix" --step "Run the tests"
|
|
@@ -1190,9 +1209,14 @@ Project-governance setters use the separate `governance_contracts` value
|
|
|
1190
1209
|
domains; in particular, workflow enforcement is `off|warn|strict`, not the
|
|
1191
1210
|
extension policy token `enforce`.
|
|
1192
1211
|
Use `pm contracts --summary --json` first when bootstrapping in a tight context
|
|
1193
|
-
window. `command_summaries` contains
|
|
1194
|
-
|
|
1195
|
-
`default_max_estimated_tokens
|
|
1212
|
+
window. `command_summaries` contains one row per registered command path,
|
|
1213
|
+
including aliases and namespace children, with a meaningful intent plus
|
|
1214
|
+
`default_max_estimated_tokens`. The low-token summary intentionally does not
|
|
1215
|
+
repeat the 32 virtual positional Plan, Assurance, and workspace-snapshot action rows;
|
|
1216
|
+
`grammar_contracts.positional_action_count` and `positional_action_parents`
|
|
1217
|
+
retain their complete discoverability and route callers to root help. A
|
|
1218
|
+
command-scoped contract for an exact action restores its typed positional
|
|
1219
|
+
signature, exact flags, provenance, and format-specific TOON/JSON ceilings.
|
|
1196
1220
|
Package commands contribute their intent through command registration (falling
|
|
1197
1221
|
back to the registered description), so agents never need a generic
|
|
1198
1222
|
`Inspect flags.` placeholder. Request heavier command-specific flags or schemas
|
|
@@ -15,7 +15,8 @@ selectors are tracked by
|
|
|
15
15
|
[pm-x710qm](../.agents/pm/issues/pm-x710qm.toon). Default contract suppression
|
|
16
16
|
and canonical TOON tables are tracked by
|
|
17
17
|
[pm-gjjurs](../.agents/pm/issues/pm-gjjurs.toon) and
|
|
18
|
-
[pm-5y05kq](../.agents/pm/issues/pm-5y05kq.toon).
|
|
18
|
+
[pm-5y05kq](../.agents/pm/issues/pm-5y05kq.toon). Nested evidence continuation
|
|
19
|
+
is tracked by [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon).
|
|
19
20
|
|
|
20
21
|
## Agent Quick Context
|
|
21
22
|
|
|
@@ -73,6 +74,7 @@ or not the current page has rows:
|
|
|
73
74
|
"command": "list",
|
|
74
75
|
"row_kind": "collection",
|
|
75
76
|
"row_keys": ["items"],
|
|
77
|
+
"continuation_row_keys": ["items"],
|
|
76
78
|
"fields": "supported",
|
|
77
79
|
"jq_selector": ".row_contract.row_keys[] as $key | getpath($key | split(\".\")) | if type == \"array\" then .[] else if type == \"object\" then to_entries[] else empty end end",
|
|
78
80
|
"toon_encoding": "tabular_when_uniform"
|
|
@@ -89,6 +91,12 @@ nested dependency graph and relationship-context rows addressable as
|
|
|
89
91
|
`graph.nodes`, `graph.edges`, `context.nodes`, and `context.edges` without
|
|
90
92
|
duplicating them at the envelope root. Array collections produce their
|
|
91
93
|
elements; object maps produce jq `to_entries` rows.
|
|
94
|
+
`continuation_row_keys` is optional and defaults to `row_keys`. A command uses
|
|
95
|
+
it only when independently resumable nested evidence differs from its primary
|
|
96
|
+
amount-bounded rows. Validate, for example, keeps `checks` and `warnings` as
|
|
97
|
+
primary rows while a rich result can name
|
|
98
|
+
`checks.0.details.missing_resolution_rows` as a continuation row. This prevents
|
|
99
|
+
an inner diagnostic array from disabling `--output-limit` on the outer checks.
|
|
92
100
|
`toon_encoding: "tabular_when_uniform"` declares that an array of flat objects
|
|
93
101
|
with one shared key set renders as a length-marked TOON table; mixed, nested,
|
|
94
102
|
or heterogeneous arrays retain the expanded representation. Quoted,
|
|
@@ -107,7 +115,8 @@ publish a row contract.
|
|
|
107
115
|
SDK and package authors can import `PM_READ_ROW_CONTRACTS`,
|
|
108
116
|
`PM_READ_ROW_JQ_SELECTOR`, and `resolveReadRowContract` from
|
|
109
117
|
`@unbrained/pm-cli/sdk`. Existing package declarations are preserved only
|
|
110
|
-
when `command`, `row_kind`, `row_keys`,
|
|
118
|
+
when `command`, `row_kind`, `row_keys`, optional unique non-empty
|
|
119
|
+
`continuation_row_keys`, `fields`, the conditional
|
|
111
120
|
`jq_selector`, and any supplied `toon_encoding` form a structurally valid row contract; malformed declarations
|
|
112
121
|
are replaced by the canonical built-in contract when one applies.
|
|
113
122
|
|
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.
|
|
@@ -15,10 +15,13 @@ Every built-in read surface uses four output dimensions: what to include, how mu
|
|
|
15
15
|
|
|
16
16
|
The contract covers `list`, `context`, `search`, `get`, `next`, `health`, `deps`, `graph`, `history`, `activity`, `validate`, `events`, `contracts`, `comments`, `notes`, `files`, `docs`, `stats`, and `aggregate`, including list aliases and `ctx`.
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
dot-delimited
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
Primary row shaping follows each envelope's `row_contract.row_keys`, including
|
|
19
|
+
dot-delimited arrays and object maps such as `graph.nodes`. Include, amount, and
|
|
20
|
+
repeat suppression therefore remain bound to the rows the command says it
|
|
21
|
+
returns. A result may additionally declare `continuation_row_keys` when a
|
|
22
|
+
nested evidence collection must resume independently without redefining the
|
|
23
|
+
primary rows that `--output-limit` bounds. Cost compaction may inspect both
|
|
24
|
+
primary and nested collections; it does not rely on command-specific keys.
|
|
22
25
|
The runtime uses that declaration internally on every read but omits the
|
|
23
26
|
repeated metadata from results by default. Request
|
|
24
27
|
`--output-row-contract` / `outputRowContract: true` when a consumer needs the
|
|
@@ -153,8 +156,9 @@ producer cursor, a universal output cursor, and a terminal page;
|
|
|
153
156
|
`next_cursor` mirrors the first universal entry for ordinary one-path
|
|
154
157
|
consumers. Replay the same query and budget
|
|
155
158
|
with `--output-cursor <cursor>` / `outputCursor`. The cursor validates the
|
|
156
|
-
command, declared
|
|
157
|
-
|
|
159
|
+
command, declared continuation path, total, and canonical content fingerprint
|
|
160
|
+
before slicing, so same-cardinality content changes and other stale replays
|
|
161
|
+
fail closed instead of skipping evidence. A
|
|
158
162
|
bounded recovery therefore does not require replacing a 600-token request with
|
|
159
163
|
an unbounded multi-megabyte response;
|
|
160
164
|
`recovery_budget_multiplier: 1` declares that each next page retains the same
|
|
@@ -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
|
@@ -50,6 +50,15 @@ first-class recurrence relationships are tracked by
|
|
|
50
50
|
Fail-closed whole-corpus reads and package-catalog output controls are tracked by
|
|
51
51
|
[pm-y4aaol](../.agents/pm/issues/pm-y4aaol.toon) and
|
|
52
52
|
[pm-2firut](../.agents/pm/issues/pm-2firut.toon).
|
|
53
|
+
Positional command signatures, action-scoped discovery, and MCP/CLI option
|
|
54
|
+
parity are tracked by [pm-ya7x55](../.agents/pm/tasks/pm-ya7x55.toon),
|
|
55
|
+
[pm-2tan](../.agents/pm/issues/pm-2tan.toon), and
|
|
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).
|
|
53
62
|
|
|
54
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.
|
|
55
64
|
|
|
@@ -340,6 +349,8 @@ Command/action contract exports:
|
|
|
340
349
|
- Execution and diagnostics contracts: `TestCommandOptions` / `TestResult` / `TestRunResult`, `TestAllCommandOptions` / `TestAllResult`, `StartBackgroundRunCommandOptions` / `StartBackgroundRunResult`, `TestRuns*CommandOptions`, `EvalOptions` / `EvalResult`, `TelemetryCommandOptions` / `TelemetrySubcommand`, and `StatsCommandOptions` / `StatsResult`.
|
|
341
350
|
- Linked-test authoring primitives: `parseLinkedTestJsonEntries`, the `parseLinkedTest*` field parsers, `LINKED_TEST_PM_CONTEXT_MODE_VALUES`, `LINKED_TEST_PROTECTED_ENV_KEYS`, `classifyLinkedTestFailure`, `countFailureCategories`, and `summarizeContextPreflight` let custom hosts validate, execute, classify, and report linked tests without duplicating CLI policy.
|
|
342
351
|
- Agent command primitives: `normalizeItemAddressInvocation` and `supportsItemIdAlias` project one item-id grammar across CLI adapters; `renderMissingOptionRetry`, `resolveMissingOptionPlaceholder`, and `resolveRecoveryCommandName` preserve attempted argv, derive enum/boolean/scalar recovery arity from flag contracts, and identify the actual command without mistaking a global option value for one; `createUnknownSubcommandError` provides one typed positional refusal with complete allowed values and deterministic nearest retry; `rankCommandPaths` and `scoreCommandPathMatch` provide deterministic synonym/edit-distance/substring ranking; `resolveCreateExplicitEmptyFlag` and `supportsCreateExplicitEmpty` model a considered-but-empty strict repeatable input without inventing metadata or graph edges.
|
|
352
|
+
- Positional grammar primitives: `PM_COMMAND_POSITIONAL_CONTRACTS` declares every core and known-package command signature as ordered, typed slots; `PM_POSITIONAL_ACTION_CONTRACTS` promotes positional plan and assurance actions into discoverable virtual command paths with action-scoped flags, examples, and intent. `resolvePmCommandPositionalContract`, `resolvePmPositionalActionContract`, and `verifyPmCommandPositionalContracts` let custom hosts resolve or fail-closed compare the same signatures emitted by runtime contracts. The grammar receipt ratchets distinct semantic shapes through `positional_shape_budget` so a new arity cannot silently expand agent context.
|
|
353
|
+
- MCP/CLI option parity primitive: `verifyToolOptionCliParity` compares one `ToolOptionFlagContract` table with its executable `CliFlagContract` table. It fails when the transport-selected canonical flag is absent or when a parameter such as `linkedFile` cannot be invoked using its kebab-case CLI spelling (`--linked-file`) canonically or through a registered alias. Core create/update parity is part of the required command-grammar gate.
|
|
343
354
|
- Refusal reachability primitives: generated `PmErrorCodeContract.owned_states` declarations bind stable codes to concrete states, probe ids, entrypoints, and exit classes; `verifyPmRefusalReachability` compares those declarations with real CLI, SDK, MCP, or package observations and fails closed for missing, duplicate, wrong-entrypoint, mismatched, or undeclared probes.
|
|
344
355
|
- Typed plan workflow primitives on `PmClient`: `plan`, `planCreate`, `planShow`, `planAddStep`, `planUpdateStep`, `planCompleteStep`, `planBlockStep`, `planReorderStep`, `planRemoveStep`, `planLink`, `planUnlink`, `planDecision`, `planDiscovery`, `planValidation`, `planResume`, `planApprove`, and `planMaterialize`
|
|
345
356
|
- Plan contracts: `PlanSubcommand`, `PlanCommandOptions`, `PlanCommandResult`, `PlanResultPlan`, `PlanStepSummary`, `PlanShowDepth`, and `PlanTemplateName`
|
|
@@ -1121,10 +1132,13 @@ filters, and bound the race-loss candidate walk with `maxAttempts` (1 through
|
|
|
1121
1132
|
tools do not need to reproduce CLI concurrency policy.
|
|
1122
1133
|
|
|
1123
1134
|
Lifecycle convenience methods and the matching top-level functions (`create`,
|
|
1124
|
-
`update`, `close`, `claim`, `release`, `copy`, `deleteItem`, `restore`,
|
|
1135
|
+
`update`, `reopen`, `close`, `claim`, `release`, `copy`, `deleteItem`, `restore`,
|
|
1125
1136
|
`focus`, `startTask`, `pauseTask`, and `closeTask`) use the same mutation paths
|
|
1126
1137
|
as the CLI and MCP dispatcher. They are the baseline primitives for custom PM
|
|
1127
|
-
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.
|
|
1128
1142
|
|
|
1129
1143
|
### Atomic workspace transactions
|
|
1130
1144
|
|