@unbrained/pm-cli 2026.8.19 → 2026.8.21
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 +41 -0
- package/dist/cli/error-guidance.d.ts +20 -0
- package/dist/cli/error-guidance.js +29 -30
- 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 +156 -148
- package/dist/cli-bundle/chunks/chunk-2MA6ZQVZ.js +197 -0
- package/dist/cli-bundle/chunks/{chunk-4NRRH7AM.js → chunk-3AFAUHUE.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-7VHZS727.js +5 -0
- package/dist/cli-bundle/chunks/chunk-BKYB45NQ.js +2092 -0
- package/dist/cli-bundle/chunks/{chunk-BHYMXLAE.js → chunk-BUNIEJNE.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-QXSH7BLM.js → chunk-JSLOFXGA.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-LARJJ3RK.js +3 -0
- package/dist/cli-bundle/chunks/{chunk-TOXJM4WA.js → chunk-LOVTQ52Z.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-N3DSV4CH.js +77 -0
- package/dist/cli-bundle/chunks/chunk-OCLPLFAY.js +35 -0
- package/dist/cli-bundle/chunks/chunk-S4IRYKBU.js +13 -0
- package/dist/cli-bundle/chunks/register-list-query-F57EWDEF.js +11 -0
- package/dist/cli-bundle/chunks/{register-mutation-AUWVCW4M.js → register-mutation-7IY2D5KO.js} +20 -20
- package/dist/cli-bundle/chunks/{register-operations-PZQPHXW5.js → register-operations-FALL3YTU.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-I4LUHGVW.js → register-setup-HXU7IZZD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-2NIY5NKG.js +18 -0
- package/dist/cli-bundle/focused-chunks/{chunk-US7VEYZG.js → chunk-4ERLO7QD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-7WZRLCYF.js +50 -0
- package/dist/cli-bundle/focused-chunks/{chunk-MCZXYZAF.js → chunk-CKKQSJNN.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-EEFKYMDR.js +16 -0
- package/dist/cli-bundle/focused-chunks/{chunk-ZBIQQYMI.js → chunk-F2A56DHV.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-ESISGDAY.js → chunk-F4YEW5I2.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-ODHQEECS.js → chunk-FH6DYED3.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-FJ22HNRP.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-FV5ACOK7.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-JEAVFOWM.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-EXBCLIBU.js → chunk-KDNG7TKQ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-NJ63LOP6.js +155 -0
- package/dist/cli-bundle/focused-chunks/chunk-NXRTQ7HI.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-JDOMQ7VQ.js → chunk-TJ7EMJ46.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-UZE7XUZK.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-DKPLYW3L.js → chunk-YKBKIEAJ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-VXDSU5MC.js → chunk-ZOSEELYJ.js} +2 -2
- package/dist/cli-bundle/main.js +12 -12
- 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 +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 -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/errors.d.ts +16 -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 +26 -94
- package/dist/core/store/tracker-preflight.d.ts +7 -0
- package/dist/core/store/tracker-preflight.js +142 -0
- 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/tracker-preflight-contracts.d.ts +63 -0
- package/dist/sdk/agent/tracker-preflight-contracts.js +127 -0
- package/dist/sdk/agent-capability-contracts.js +6 -11
- package/dist/sdk/annotations.js +6 -7
- 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/config.d.ts +5 -0
- package/dist/sdk/config.js +5 -5
- package/dist/sdk/context-intent-runtime.js +7 -4
- package/dist/sdk/contracts.d.ts +2 -0
- package/dist/sdk/contracts.js +4 -2
- package/dist/sdk/core.d.ts +1 -1
- package/dist/sdk/core.js +3 -3
- package/dist/sdk/dependencies.js +5 -7
- package/dist/sdk/dependency-flag-validation.d.ts +1 -1
- package/dist/sdk/dependency-flag-validation.js +10 -4
- package/dist/sdk/environment/tracker-preflight.d.ts +6 -0
- package/dist/sdk/environment/tracker-preflight.js +10 -0
- package/dist/sdk/eval.js +5 -7
- package/dist/sdk/files.js +6 -10
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +110 -2
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +179 -46
- package/dist/sdk/governance/assurance.d.ts +36 -2
- package/dist/sdk/governance/assurance.js +184 -10
- package/dist/sdk/governance/gc.js +5 -6
- package/dist/sdk/governance/health.js +5 -6
- package/dist/sdk/governance/reindex.js +5 -6
- package/dist/sdk/governance/validate.d.ts +1 -2
- package/dist/sdk/governance/validate.js +6 -12
- package/dist/sdk/graph/governance.d.ts +7 -5
- package/dist/sdk/graph/governance.js +32 -16
- package/dist/sdk/graph/run.js +5 -7
- package/dist/sdk/graph/traversal.js +14 -5
- package/dist/sdk/history-compact.js +6 -9
- package/dist/sdk/history-read.js +5 -7
- package/dist/sdk/history-redact.js +5 -6
- package/dist/sdk/history-repair.js +6 -9
- package/dist/sdk/improvement-ledger.js +7 -10
- package/dist/sdk/index.d.ts +7 -3
- package/dist/sdk/index.js +8 -4
- package/dist/sdk/init-agent-guidance.d.ts +5 -3
- package/dist/sdk/init-agent-guidance.js +69 -9
- package/dist/sdk/lifecycle/append.d.ts +0 -5
- package/dist/sdk/lifecycle/append.js +5 -6
- package/dist/sdk/lifecycle/claim.d.ts +0 -5
- package/dist/sdk/lifecycle/claim.js +6 -9
- package/dist/sdk/lifecycle/close-many.d.ts +0 -5
- package/dist/sdk/lifecycle/close-many.js +5 -6
- package/dist/sdk/lifecycle/close.d.ts +0 -5
- package/dist/sdk/lifecycle/close.js +5 -6
- package/dist/sdk/lifecycle/copy.d.ts +0 -5
- package/dist/sdk/lifecycle/copy.js +5 -6
- package/dist/sdk/lifecycle/create.d.ts +0 -5
- package/dist/sdk/lifecycle/create.js +5 -9
- package/dist/sdk/lifecycle/delete.js +5 -6
- package/dist/sdk/lifecycle/focus.d.ts +0 -5
- package/dist/sdk/lifecycle/focus.js +5 -6
- package/dist/sdk/lifecycle/mcp-actions.d.ts +18 -0
- package/dist/sdk/lifecycle/mcp-actions.js +52 -0
- package/dist/sdk/lifecycle/plan.d.ts +0 -5
- package/dist/sdk/lifecycle/plan.js +5 -6
- package/dist/sdk/lifecycle/reopen.d.ts +44 -0
- package/dist/sdk/lifecycle/reopen.js +69 -0
- package/dist/sdk/lifecycle/restore.js +5 -6
- package/dist/sdk/lifecycle/update-many.d.ts +0 -5
- package/dist/sdk/lifecycle/update-many.js +5 -6
- package/dist/sdk/lifecycle/update.d.ts +31 -5
- package/dist/sdk/lifecycle/update.js +140 -19
- package/dist/sdk/linked-artifacts.js +6 -7
- package/dist/sdk/merge/install.js +5 -6
- package/dist/sdk/mutation-events.js +5 -7
- package/dist/sdk/package-import-adapters.js +6 -8
- package/dist/sdk/profile.js +6 -7
- package/dist/sdk/query/activity.js +5 -6
- package/dist/sdk/query/calendar.js +5 -6
- package/dist/sdk/query/get.d.ts +1 -6
- package/dist/sdk/query/get.js +20 -55
- package/dist/sdk/query/history.d.ts +0 -5
- package/dist/sdk/query/history.js +5 -6
- package/dist/sdk/query/list.d.ts +7 -21
- package/dist/sdk/query/list.js +38 -54
- 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 +34 -10
- package/dist/sdk/relationship-kinds/contract.d.ts +8 -0
- package/dist/sdk/relationship-kinds/contract.js +13 -13
- package/dist/sdk/relationships.d.ts +1 -1
- package/dist/sdk/relationships.js +20 -2
- 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/schema-migration.js +6 -7
- package/dist/sdk/schema.js +5 -6
- package/dist/sdk/similarity.d.ts +13 -0
- package/dist/sdk/similarity.js +32 -6
- package/dist/sdk/stats.js +5 -8
- package/dist/sdk/templates.js +5 -6
- package/dist/sdk/test/batch.js +5 -7
- package/dist/sdk/test/execution.js +4 -5
- package/dist/sdk/test/runs.js +5 -7
- package/docs/AGENT_UX_CONTRACTS.md +8 -1
- package/docs/COMMANDS.md +13 -1
- package/docs/DEPENDENCY_KIND_CONTRACT.md +12 -1
- package/docs/README.md +1 -0
- package/docs/RECURRENCE_RECOVERY_CONTRACTS.md +151 -0
- package/docs/RELATIONSHIP_GRAPH.md +92 -10
- package/docs/SDK.md +10 -2
- package/docs/SDK_CONTEXT_INTEGRITY.md +45 -0
- package/docs/SDK_PRIMITIVE_INVENTORY.md +15 -1
- 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 +640 -44
- package/dist/cli-bundle/chunks/chunk-4THEB6PD.js +0 -13
- 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-OIOKV6NO.js +0 -2092
- 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-BJRYFVSH.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-EF6ZS5GH.js +0 -50
- 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/schema.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Owns typed schema customization primitives shared by SDK, CLI, and MCP consumers.
|
|
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]="6112923d-5e06-5839-b452-a32818c6398d")}catch(e){}}();
|
|
8
|
+
import { assertInitializedTracker } from "./environment/tracker-preflight.js";
|
|
8
9
|
import path from "node:path";
|
|
9
10
|
import { mkdir } from "node:fs/promises";
|
|
10
11
|
import { resolveAuthor } from "../core/shared/author.js";
|
|
@@ -24,7 +25,7 @@ import { EXIT_CODE } from "../core/shared/constants.js";
|
|
|
24
25
|
import { PmCliError } from "../core/shared/errors.js";
|
|
25
26
|
import { nowIso } from "../core/shared/time.js";
|
|
26
27
|
import { getActiveExtensionRegistrations, runActiveOnWriteHooks, } from "../core/extensions/index.js";
|
|
27
|
-
import {
|
|
28
|
+
import { resolvePmRoot } from "../core/store/paths.js";
|
|
28
29
|
import { readSettings, resolveGovernanceKnobs, } from "../core/store/settings.js";
|
|
29
30
|
import { resolvePmToolCustomFieldCollision } from "./cli-contracts/tool-schema.js";
|
|
30
31
|
/** Public contract for schema subcommands, shared by SDK and presentation-layer consumers. */
|
|
@@ -160,9 +161,7 @@ export async function runSchemaAddType(name, options, global) {
|
|
|
160
161
|
};
|
|
161
162
|
}
|
|
162
163
|
async function ensureInitialized(pmRoot) {
|
|
163
|
-
|
|
164
|
-
throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
|
|
165
|
-
}
|
|
164
|
+
await assertInitializedTracker(pmRoot);
|
|
166
165
|
}
|
|
167
166
|
/**
|
|
168
167
|
* Reconcile the committed merge-driver fence with the type folders that exist
|
|
@@ -1365,4 +1364,4 @@ export const _testOnlySchemaCommand = {
|
|
|
1365
1364
|
workflowSlotsReferencing,
|
|
1366
1365
|
};
|
|
1367
1366
|
//# sourceMappingURL=schema.js.map
|
|
1368
|
-
//# debugId=
|
|
1367
|
+
//# debugId=6112923d-5e06-5839-b452-a32818c6398d
|
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
|
package/dist/sdk/stats.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Implements the pm stats command surface and its agent-facing runtime behavior.
|
|
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]="b56db1fc-d989-5d18-8b29-336a03f1e525")}catch(e){}}();
|
|
8
|
+
import { assertInitializedTracker } from "./environment/tracker-preflight.js";
|
|
8
9
|
import fs from "node:fs/promises";
|
|
9
10
|
import path from "node:path";
|
|
10
11
|
import { getActiveExtensionRegistrations, runActiveOnReadHooks, } from "../core/extensions/index.js";
|
|
@@ -15,11 +16,9 @@ import { enforceHistoryStreamPolicyForItems } from "../core/history/history-stre
|
|
|
15
16
|
import { computeHistoryStorageStats, } from "../core/history/history-storage-stats.js";
|
|
16
17
|
import { resolveItemTypeRegistry } from "../core/item/type-registry.js";
|
|
17
18
|
import { resolveRuntimeStatusRegistry } from "../core/schema/runtime-schema.js";
|
|
18
|
-
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
19
|
-
import { PmCliError } from "../core/shared/errors.js";
|
|
20
19
|
import { nowIso } from "../core/shared/time.js";
|
|
21
20
|
import { listAllItemMetadataLight, listAllItemMetadataWithBody, } from "../core/store/item-store.js";
|
|
22
|
-
import {
|
|
21
|
+
import { resolvePmRoot } from "../core/store/paths.js";
|
|
23
22
|
import { readSettings } from "../core/store/settings.js";
|
|
24
23
|
import { recordImprovementObservation, readImprovementLedger, } from "./improvement-ledger.js";
|
|
25
24
|
import { projectFleetAttributionAnalytics, projectProvenanceCoverageAnalytics, readHistoryAnalyticsWindow, } from "./history-analytics.js";
|
|
@@ -210,9 +209,7 @@ function assembleStatsResult(totals, byType, byStatus, omittedZeroBuckets, optio
|
|
|
210
209
|
/** Implements run stats for the public runtime surface of this module. */
|
|
211
210
|
export async function runStats(global, options = {}) {
|
|
212
211
|
const pmRoot = resolvePmRoot(process.cwd(), global.path);
|
|
213
|
-
|
|
214
|
-
throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
|
|
215
|
-
}
|
|
212
|
+
await assertInitializedTracker(pmRoot);
|
|
216
213
|
const settings = await readSettings(pmRoot);
|
|
217
214
|
const recordedObservations = await recordStatsObservations(global, options);
|
|
218
215
|
const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());
|
|
@@ -271,4 +268,4 @@ export async function runStats(global, options = {}) {
|
|
|
271
268
|
});
|
|
272
269
|
}
|
|
273
270
|
//# sourceMappingURL=stats.js.map
|
|
274
|
-
//# debugId=
|
|
271
|
+
//# debugId=b56db1fc-d989-5d18-8b29-336a03f1e525
|
package/dist/sdk/templates.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Implements the pm templates command surface and its agent-facing runtime behavior.
|
|
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]="5c70da27-21f6-5d31-b506-96e1818996d6")}catch(e){}}();
|
|
8
|
+
import { assertInitializedTracker } from "./environment/tracker-preflight.js";
|
|
8
9
|
import fs from "node:fs/promises";
|
|
9
10
|
import path from "node:path";
|
|
10
11
|
import { pathExists, readFileIfExists, } from "../core/fs/fs-utils.js";
|
|
@@ -13,7 +14,7 @@ import { resolveAuthor } from "../core/shared/author.js";
|
|
|
13
14
|
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
14
15
|
import { PmCliError } from "../core/shared/errors.js";
|
|
15
16
|
import { nowIso } from "../core/shared/time.js";
|
|
16
|
-
import {
|
|
17
|
+
import { resolvePmRoot } from "../core/store/paths.js";
|
|
17
18
|
import { readSettings } from "../core/store/settings.js";
|
|
18
19
|
import { CREATE_COMMANDER_REPEATABLE_OPTION_CONTRACTS } from "./cli-contracts.js";
|
|
19
20
|
const TEMPLATE_DIRECTORY_NAME = "templates";
|
|
@@ -78,9 +79,7 @@ function templatePath(pmRoot, normalizedName) {
|
|
|
78
79
|
return path.join(templatesDirectory(pmRoot), `${normalizedName}${TEMPLATE_FILE_EXTENSION}`);
|
|
79
80
|
}
|
|
80
81
|
async function ensureTrackerInitialized(pmRoot) {
|
|
81
|
-
|
|
82
|
-
throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
|
|
83
|
-
}
|
|
82
|
+
await assertInitializedTracker(pmRoot);
|
|
84
83
|
}
|
|
85
84
|
function sortTemplateOptions(options) {
|
|
86
85
|
return Object.fromEntries(Object.entries(options).sort(([left], [right]) => left.localeCompare(right)));
|
|
@@ -291,4 +290,4 @@ export async function runTemplatesShow(rawTemplateName, global) {
|
|
|
291
290
|
};
|
|
292
291
|
}
|
|
293
292
|
//# sourceMappingURL=templates.js.map
|
|
294
|
-
//# debugId=
|
|
293
|
+
//# debugId=5c70da27-21f6-5d31-b506-96e1818996d6
|
package/dist/sdk/test/batch.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Implements the pm test all command surface and its agent-facing runtime behavior.
|
|
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]="
|
|
8
|
-
import {
|
|
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]="aeb0a1a7-bc73-5c56-bbed-9472c651b5f6")}catch(e){}}();
|
|
8
|
+
import { assertInitializedTracker } from "../environment/tracker-preflight.js";
|
|
9
9
|
import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
|
|
10
10
|
import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
|
|
11
11
|
import { parseOptionalNumber } from "../../core/item/parse.js";
|
|
@@ -15,7 +15,7 @@ import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
|
15
15
|
import { PmCliError } from "../../core/shared/errors.js";
|
|
16
16
|
import { nowIso } from "../../core/shared/time.js";
|
|
17
17
|
import { listAllItemMetadataLight } from "../../core/store/item-store.js";
|
|
18
|
-
import {
|
|
18
|
+
import { resolveGlobalPmRoot, resolvePmRoot, } from "../../core/store/paths.js";
|
|
19
19
|
import { readSettings } from "../../core/store/settings.js";
|
|
20
20
|
import { appendTrackedTestRunSummary } from "../../core/test/item-test-run-tracking.js";
|
|
21
21
|
import { resolveAuthor } from "../../core/shared/author.js";
|
|
@@ -421,9 +421,7 @@ const buildTestAllSelectionProgress = (params) => [
|
|
|
421
421
|
/** Loads the tracker selection and linked tests for one test-all run. */
|
|
422
422
|
const prepareTestAllRun = async (options, global) => {
|
|
423
423
|
const pmRoot = resolvePmRoot(process.cwd(), global.path);
|
|
424
|
-
|
|
425
|
-
throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
|
|
426
|
-
}
|
|
424
|
+
await assertInitializedTracker(pmRoot);
|
|
427
425
|
const settings = await readSettings(pmRoot);
|
|
428
426
|
const selection = await selectTestAllItems({ pmRoot, settings, options });
|
|
429
427
|
const defaultTimeoutSeconds = parseTimeout(options.timeout);
|
|
@@ -489,4 +487,4 @@ export const _testOnlyTestAll = {
|
|
|
489
487
|
formatTrackingError,
|
|
490
488
|
};
|
|
491
489
|
//# sourceMappingURL=batch.js.map
|
|
492
|
-
//# debugId=
|
|
490
|
+
//# debugId=aeb0a1a7-bc73-5c56-bbed-9472c651b5f6
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Implements the pm test command surface and its agent-facing runtime behavior.
|
|
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]="2354c553-3a81-59d8-9c0a-3d19cd3cedd2")}catch(e){}}();
|
|
8
|
+
import { assertInitializedTracker } from "../environment/tracker-preflight.js";
|
|
8
9
|
import { spawn } from "node:child_process";
|
|
9
10
|
import { cp, mkdir, mkdtemp, open, readdir, rm } from "node:fs/promises";
|
|
10
11
|
import { tmpdir } from "node:os";
|
|
@@ -1849,9 +1850,7 @@ function buildTestMeasurementProjection(options, runs, recordedRun) {
|
|
|
1849
1850
|
export async function runTest(id, options, global) {
|
|
1850
1851
|
const stdinResolver = createStdinTokenResolver();
|
|
1851
1852
|
const pmRoot = resolvePmRoot(process.cwd(), global.path);
|
|
1852
|
-
|
|
1853
|
-
throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
|
|
1854
|
-
}
|
|
1853
|
+
await assertInitializedTracker(pmRoot);
|
|
1855
1854
|
const settings = await readSettings(pmRoot);
|
|
1856
1855
|
if ((options.measure?.length ?? 0) > 0 && options.run !== true) {
|
|
1857
1856
|
throw new PmCliError("--measure requires --run", EXIT_CODE.USAGE);
|
|
@@ -1965,4 +1964,4 @@ export const _testOnlyTestCommand = {
|
|
|
1965
1964
|
summarizeRunResultStatuses,
|
|
1966
1965
|
};
|
|
1967
1966
|
//# sourceMappingURL=execution.js.map
|
|
1968
|
-
//# debugId=
|
|
1967
|
+
//# debugId=2354c553-3a81-59d8-9c0a-3d19cd3cedd2
|
package/dist/sdk/test/runs.js
CHANGED
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
* Implements the pm test runs command surface and its agent-facing runtime behavior.
|
|
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]="1cbb3565-26d8-5657-b724-602658bec852")}catch(e){}}();
|
|
8
|
+
import { assertInitializedTracker } from "../environment/tracker-preflight.js";
|
|
8
9
|
import os from "node:os";
|
|
9
|
-
import { pathExists } from "../../core/fs/fs-utils.js";
|
|
10
10
|
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
11
11
|
import { PmCliError } from "../../core/shared/errors.js";
|
|
12
12
|
import { readAuthorEnvironment } from "../../core/shared/author.js";
|
|
13
13
|
import { getBackgroundTestRunStatus, listBackgroundTestRuns, readBackgroundTestRunLogs, resumeBackgroundTestRun, runBackgroundTestRunWorker, spawnBackgroundTestRunWorker, startBackgroundTestRun, stopBackgroundTestRun, } from "../../core/test/background-runs.js";
|
|
14
|
-
import {
|
|
14
|
+
import { resolveGlobalPmRoot, resolvePmRoot, } from "../../core/store/paths.js";
|
|
15
15
|
import { readSettings } from "../../core/store/settings.js";
|
|
16
16
|
import { parseLimit } from "../../core/shared/numeric-parsers.js";
|
|
17
17
|
const BACKGROUND_STATUS_VALUES = [
|
|
@@ -81,9 +81,7 @@ function resolveRequestedBy(author, fallback) {
|
|
|
81
81
|
return "unknown";
|
|
82
82
|
}
|
|
83
83
|
async function ensureInitialized(pmRoot) {
|
|
84
|
-
|
|
85
|
-
throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
|
|
86
|
-
}
|
|
84
|
+
await assertInitializedTracker(pmRoot);
|
|
87
85
|
}
|
|
88
86
|
/** Implements run start background run for the public runtime surface of this module. */
|
|
89
87
|
export async function runStartBackgroundRun(options, global) {
|
|
@@ -193,4 +191,4 @@ export async function runTestRunsWorker(runId, global) {
|
|
|
193
191
|
};
|
|
194
192
|
}
|
|
195
193
|
//# sourceMappingURL=runs.js.map
|
|
196
|
-
//# debugId=
|
|
194
|
+
//# debugId=1cbb3565-26d8-5657-b724-602658bec852
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Agent UX Contracts
|
|
2
2
|
|
|
3
|
-
Tracker references: [pm-v1yo](../.agents/pm/issues/pm-v1yo.toon), [pm-i6pi](../.agents/pm/issues/pm-i6pi.toon), [pm-um4g](../.agents/pm/issues/pm-um4g.toon), [pm-tmhs](../.agents/pm/issues/pm-tmhs.toon), [pm-6m1i](../.agents/pm/issues/pm-6m1i.toon), [pm-cj9v](../.agents/pm/issues/pm-cj9v.toon), [pm-yp56](../.agents/pm/issues/pm-yp56.toon).
|
|
3
|
+
Tracker references: [pm-v1yo](../.agents/pm/issues/pm-v1yo.toon), [pm-i6pi](../.agents/pm/issues/pm-i6pi.toon), [pm-um4g](../.agents/pm/issues/pm-um4g.toon), [pm-tmhs](../.agents/pm/issues/pm-tmhs.toon), [pm-6m1i](../.agents/pm/issues/pm-6m1i.toon), [pm-cj9v](../.agents/pm/issues/pm-cj9v.toon), [pm-yp56](../.agents/pm/issues/pm-yp56.toon), [pm-gos426](../.agents/pm/issues/pm-gos426.toon), and [pm-flnefm](../.agents/pm/issues/pm-flnefm.toon).
|
|
4
4
|
|
|
5
5
|
These contracts keep common agent loops deterministic, token-efficient, and recoverable. Runtime contracts and `--help --json` remain the exact source for available flags.
|
|
6
6
|
|
|
@@ -10,6 +10,13 @@ These contracts keep common agent loops deterministic, token-efficient, and reco
|
|
|
10
10
|
|
|
11
11
|
The public SDK exports `collectNewOrderingCycleWarnings(beforeItems, afterItems, changedItemId)` from `@unbrained/pm-cli/sdk`. Package authors can apply the same immutable-snapshot advisory to custom mutation workflows; activated custom relationship kinds participate through the shared registry.
|
|
12
12
|
|
|
13
|
+
Dependency removal is lossless. `--dep-remove` rejects the same malformed
|
|
14
|
+
shorthand as `--dep`, and a selector that matches nothing returns the typed
|
|
15
|
+
`dependency_remove_no_match` refusal instead of a successful no-op. Exact
|
|
16
|
+
duplicate rows can be normalized without delete-then-add risk by re-adding the
|
|
17
|
+
same `id`, `kind`, and `source_kind`; the mutation keeps one canonical row and
|
|
18
|
+
never removes the logical edge.
|
|
19
|
+
|
|
13
20
|
`pm graph audit` uses two explicit units:
|
|
14
21
|
|
|
15
22
|
- `finding_count`, `findings_by_severity`, and `findings_by_code` count finding rows.
|
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.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Dependency-kind contract
|
|
2
2
|
|
|
3
|
-
Tracker: [pm-4020c5](../.agents/pm/issues/pm-4020c5.toon), [pm-jkbqt8](../.agents/pm/issues/pm-jkbqt8.toon), [pm-q6n8sj](../.agents/pm/issues/pm-q6n8sj.toon), [pm-ouyq3n](../.agents/pm/issues/pm-ouyq3n.toon)
|
|
3
|
+
Tracker: [pm-4020c5](../.agents/pm/issues/pm-4020c5.toon), [pm-jkbqt8](../.agents/pm/issues/pm-jkbqt8.toon), [pm-q6n8sj](../.agents/pm/issues/pm-q6n8sj.toon), [pm-ouyq3n](../.agents/pm/issues/pm-ouyq3n.toon), [pm-gos426](../.agents/pm/issues/pm-gos426.toon), and [pm-flnefm](../.agents/pm/issues/pm-flnefm.toon).
|
|
4
4
|
|
|
5
5
|
Dependency rows have one canonical stored spelling per relationship meaning. Command inputs remain compatibility-friendly: hyphens normalize to underscores and the aliases below are accepted, but `pm create` and `pm update` persist the canonical kind. Existing historical rows are never rewritten implicitly.
|
|
6
6
|
|
|
@@ -15,6 +15,17 @@ Dependency rows have one canonical stored spelling per relationship meaning. Com
|
|
|
15
15
|
|
|
16
16
|
The SDK relationship registry is authoritative. `canonicalizeRelationshipKind()` rejects unknown spellings, while `resolveCanonicalRelationshipKind()` supports validation flows that need an undefined result. `pm contracts` publishes `relationship_kind_contracts` with canonical names, aliases, inverses, and ordering/hierarchy semantics.
|
|
17
17
|
|
|
18
|
+
Dependency additions and removals share the same lossless input grammar. A
|
|
19
|
+
bare value is an item id; structured input uses `id=<id>` plus an optional
|
|
20
|
+
canonical `kind`/`type` and `source_kind`. Punctuation-shaped shorthand such as
|
|
21
|
+
`OTHER,related` is rejected with `dependency_flag_value_invalid` on both
|
|
22
|
+
`--dep` and `--dep-remove`, before prefix normalization can turn it into a
|
|
23
|
+
dangling id. A removal selector that matches no stored row fails with
|
|
24
|
+
`dependency_remove_no_match` and returns the unmatched selectors plus compact
|
|
25
|
+
available identities. Re-adding a stored dependency identity is idempotent; if
|
|
26
|
+
legacy storage contains that exact identity more than once, the same mutation
|
|
27
|
+
collapses the touched copies to one without creating an edge-absence window.
|
|
28
|
+
|
|
18
29
|
`recurs_from` has no alias: a later occurrence points to an earlier occurrence.
|
|
19
30
|
It is persistent after both items become terminal and carries temporal identity,
|
|
20
31
|
not execution precedence. `supersedes` keeps replacement semantics, while
|
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,151 @@
|
|
|
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
|
+
## Tracker Preflight Recovery
|
|
69
|
+
|
|
70
|
+
Every SDK command that requires project state now enters through one shared
|
|
71
|
+
filesystem preflight instead of maintaining a command-local settings check.
|
|
72
|
+
The public aggregate SDK exposes the same primitive for packages and embedded
|
|
73
|
+
hosts:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import {
|
|
77
|
+
assertInitializedTracker,
|
|
78
|
+
assertReadableTrackerRoot,
|
|
79
|
+
} from "@unbrained/pm-cli/sdk";
|
|
80
|
+
|
|
81
|
+
await assertReadableTrackerRoot(candidateRoot); // an empty directory is valid
|
|
82
|
+
await assertInitializedTracker(projectRoot); // settings.json is required
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The refusal contract distinguishes four states before any command-specific
|
|
86
|
+
read or mutation begins:
|
|
87
|
+
|
|
88
|
+
| Selected root state | Code | Exit | Recovery |
|
|
89
|
+
| --- | --- | ---: | --- |
|
|
90
|
+
| Path does not exist | `tracker_root_missing` | 3 | Tokenized, non-interactive `pm --pm-path <path> init --defaults --agent-guidance skip` |
|
|
91
|
+
| Directory exists but `settings.json` does not | `tracker_not_initialized` | 3 | The same initialization retry |
|
|
92
|
+
| Path or ancestor is a regular file | `tracker_root_not_directory` | 2 | Select a directory; never suggest `pm init` against the file |
|
|
93
|
+
| Directory cannot be read or searched | `tracker_root_unreadable` | 1 | Repair permissions, then retry the same selected root |
|
|
94
|
+
|
|
95
|
+
`listTrackerPreflightRecoveryContracts` publishes this four-state corpus from
|
|
96
|
+
`@unbrained/pm-cli/sdk/contracts`.
|
|
97
|
+
`scoreTrackerPreflightRecoveryClosure` verifies code, exit class, recovery kind,
|
|
98
|
+
and executable retry evidence. The repository recovery gate runs these probes
|
|
99
|
+
beside the 18 closed-domain probes, so its ratcheted corpus is 22 and a removed
|
|
100
|
+
state, failed retry, or unsafe file-path initialization suggestion blocks the
|
|
101
|
+
release. The surface-replication gate separately requires at least 50 shared
|
|
102
|
+
preflight invocations across the 45 migrated SDK modules and forbids the former
|
|
103
|
+
inline error body from returning.
|
|
104
|
+
|
|
105
|
+
## Duplicate Intake
|
|
106
|
+
|
|
107
|
+
Create and copy similarity governance inspect all lifecycle statuses. The
|
|
108
|
+
strongest active match returns a `pm get <id> --full` reuse path. The strongest
|
|
109
|
+
terminal match returns:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
pm item reopen <id> "<recurrence reason>"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Strict duplicate refusal exposes the same command and tokenized arguments in
|
|
116
|
+
its structured recovery envelope. Advisory mode adds a compact
|
|
117
|
+
`likely_duplicate_recovery:<reuse|reopen>:<id>` warning so agents can select the
|
|
118
|
+
correct lifecycle action without reparsing prose.
|
|
119
|
+
|
|
120
|
+
## Capability-Aware Reindex Recovery
|
|
121
|
+
|
|
122
|
+
When semantic search detects stale vectors, it inspects the active extension
|
|
123
|
+
command registry. If `reindex` is active, the direct recovery is:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
pm reindex --mode hybrid
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
If the command is absent, recovery is a two-step executable sequence:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
pm install search-advanced --project
|
|
133
|
+
pm reindex --mode hybrid
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The human warning and structured `vector_index_recovery` tokens come from the
|
|
137
|
+
same resolution. This prevents a base installation from suggesting an
|
|
138
|
+
unavailable command.
|
|
139
|
+
|
|
140
|
+
## Target-Aware Generated Test Guidance
|
|
141
|
+
|
|
142
|
+
`pm init --agent-guidance add` resolves the linked-test command in this order:
|
|
143
|
+
|
|
144
|
+
1. `node scripts/run-tests.mjs test` when that repository script exists.
|
|
145
|
+
2. The declared package manager's `test` script (`pnpm test`, `bun run test`,
|
|
146
|
+
`yarn test`, or `npm test`).
|
|
147
|
+
3. `<your project test command>` when the target does not declare an executable
|
|
148
|
+
test contract.
|
|
149
|
+
|
|
150
|
+
The managed guidance block is versioned, so a later init can replace an older
|
|
151
|
+
pm-managed block without changing surrounding repository instructions.
|