@unbrained/pm-cli 2026.8.9 → 2026.8.10
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 +40 -0
- package/dist/cli/commander-usage.js +17 -12
- package/dist/cli/help-json-payload.js +51 -16
- package/dist/cli/main.js +7 -6
- package/dist/cli-bundle/bundle-manifest.json +165 -165
- package/dist/cli-bundle/chunks/chunk-2QYH4QMI.js +30 -0
- package/dist/cli-bundle/chunks/{chunk-YC3UF2IO.js → chunk-EBO7OUUE.js} +57 -57
- package/dist/cli-bundle/chunks/{chunk-GMX5YOI3.js → chunk-ETML5C6H.js} +48 -48
- package/dist/cli-bundle/chunks/chunk-JUDU4RO4.js +194 -0
- package/dist/cli-bundle/chunks/{chunk-PYO5GZU6.js → chunk-JZSNADRR.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-EF43KODO.js → chunk-MENWVGJW.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-5JO6R4BS.js → chunk-S4EITGLA.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-2DTCZXSD.js → chunk-TIGKWVLA.js} +9 -9
- package/dist/cli-bundle/chunks/{chunk-RJC7TPF4.js → chunk-TRWXF476.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-TSLDTJLQ.js +2 -0
- package/dist/cli-bundle/chunks/{register-list-query-BUE7PTCU.js → register-list-query-OJ6ZXKV4.js} +2 -2
- package/dist/cli-bundle/chunks/{register-mutation-FC3XLVIK.js → register-mutation-DKI7QC7O.js} +2 -2
- package/dist/cli-bundle/chunks/register-operations-P5OGMT6I.js +2 -0
- package/dist/cli-bundle/chunks/{register-setup-UQDTNTLJ.js → register-setup-S3KT2LTH.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-6DO4YQWZ.js → chunk-2COZ67XT.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-2EXI2DKR.js +4 -0
- package/dist/cli-bundle/focused-chunks/{chunk-KNEHLPBF.js → chunk-34SX654S.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-36FTZ2NT.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-3CQECMKR.js +16 -0
- package/dist/cli-bundle/focused-chunks/chunk-75774JWP.js +6 -0
- package/dist/cli-bundle/focused-chunks/{chunk-MRWVJ3ZG.js → chunk-7UN6BHHO.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-VRXJSGIT.js → chunk-CHIBMEZR.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-DZGAHZZV.js +3 -0
- package/dist/cli-bundle/focused-chunks/chunk-FF4MNAYB.js +153 -0
- package/dist/cli-bundle/focused-chunks/{chunk-ZG54B4XG.js → chunk-GHTN2ILR.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-I4YM2I7S.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-IMDTEN7K.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-IW43E4XL.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-3WVHTUAW.js → chunk-JMVA4HKR.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-C3GCHDSQ.js → chunk-KR5RVXLQ.js} +31 -31
- package/dist/cli-bundle/focused-chunks/chunk-KSNJG4KI.js +16 -0
- package/dist/cli-bundle/focused-chunks/{chunk-73FIJONU.js → chunk-M6RPIXKC.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-MXYSIQ56.js +18 -0
- package/dist/cli-bundle/focused-chunks/chunk-RIIN5V4N.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-U46GQJNY.js → chunk-RKWSCYYN.js} +2 -2
- package/dist/cli-bundle/main.js +13 -13
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +1 -1
- package/dist/cli-bundle/sdk-core.js +38 -38
- 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 +1 -1
- 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 +2 -2
- package/dist/core/diagnostics/remediation.js +9 -9
- package/dist/core/fs/fs-utils.d.ts +10 -0
- package/dist/core/fs/fs-utils.js +16 -4
- package/dist/core/item/item-format.js +3 -32
- package/dist/core/schema/fields-file.d.ts +1 -2
- package/dist/core/schema/fields-file.js +4 -11
- package/dist/core/schema/runtime-schema.js +3 -10
- package/dist/core/schema/status-defs-file.d.ts +1 -2
- package/dist/core/schema/status-defs-file.js +4 -32
- package/dist/core/schema/status-token.d.ts +2 -0
- package/dist/core/schema/status-token.js +32 -0
- package/dist/core/schema/type-workflows.d.ts +1 -2
- package/dist/core/schema/type-workflows.js +4 -11
- package/dist/core/shared/author.d.ts +1 -1
- package/dist/core/shared/author.js +21 -8
- package/dist/core/shared/errors.d.ts +4 -0
- package/dist/core/shared/errors.js +2 -2
- package/dist/core/shared/text-normalization.d.ts +1 -1
- package/dist/core/shared/text-normalization.js +2 -2
- package/dist/sdk/agent/command-recovery.d.ts +4 -0
- package/dist/sdk/agent/command-recovery.js +52 -0
- package/dist/sdk/agent/command-suggestions.d.ts +4 -0
- package/dist/sdk/agent/command-suggestions.js +67 -0
- package/dist/sdk/agent/create-option-policy.d.ts +12 -0
- package/dist/sdk/agent/create-option-policy.js +32 -0
- package/dist/sdk/agent/item-addressing.d.ts +19 -0
- package/dist/sdk/agent/item-addressing.js +208 -0
- package/dist/sdk/cli-bootstrap.d.ts +1 -1
- package/dist/sdk/cli-bootstrap.js +20 -5
- package/dist/sdk/cli-contracts/commander-mutation-options.js +16 -4
- package/dist/sdk/cli-contracts/flag-contracts.js +62 -21
- package/dist/sdk/cli-contracts/registration-helpers.js +10 -2
- package/dist/sdk/cli-contracts/runtime-contracts.js +5 -3
- package/dist/sdk/cli-contracts/tool-option-contracts.d.ts +6 -0
- package/dist/sdk/cli-contracts/tool-option-contracts.js +4 -2
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +19 -4
- package/dist/sdk/cli-contracts/tool-schema.js +17 -4
- package/dist/sdk/context-intent-runtime.js +8 -5
- package/dist/sdk/context-signal-store.d.ts +34 -0
- package/dist/sdk/context-signal-store.js +24 -2
- package/dist/sdk/dependency-flag-validation.d.ts +15 -1
- package/dist/sdk/dependency-flag-validation.js +54 -2
- package/dist/sdk/generated-error-code-catalog.js +74 -2
- package/dist/sdk/governance/health.js +14 -7
- package/dist/sdk/governance/provenance-health.d.ts +13 -0
- package/dist/sdk/governance/provenance-health.js +63 -17
- package/dist/sdk/governance/validate-item-reader.d.ts +13 -0
- package/dist/sdk/governance/validate-item-reader.js +18 -0
- package/dist/sdk/governance/validate.d.ts +2 -2
- package/dist/sdk/governance/validate.js +15 -6
- package/dist/sdk/index.d.ts +4 -0
- package/dist/sdk/index.js +6 -2
- package/dist/sdk/lifecycle/close.js +17 -14
- package/dist/sdk/lifecycle/create.d.ts +2 -0
- package/dist/sdk/lifecycle/create.js +62 -9
- package/dist/sdk/lifecycle/update-many.js +39 -27
- package/dist/sdk/lifecycle/update.d.ts +6 -1
- package/dist/sdk/lifecycle/update.js +47 -10
- package/dist/sdk/merge/index.d.ts +1 -1
- package/dist/sdk/merge/index.js +3 -3
- package/dist/sdk/merge/install.d.ts +4 -0
- package/dist/sdk/merge/install.js +28 -16
- package/dist/sdk/merge/receipts.d.ts +3 -0
- package/dist/sdk/merge/receipts.js +81 -17
- package/dist/sdk/output-projection.js +24 -4
- package/dist/sdk/query/context.d.ts +2 -0
- package/dist/sdk/query/context.js +7 -4
- package/dist/sdk/query/light-metadata.d.ts +3 -0
- package/dist/sdk/query/light-metadata.js +19 -0
- package/dist/sdk/runtime.d.ts +4 -1
- package/dist/sdk/runtime.js +8 -3
- package/dist/sdk/schema-migration.js +7 -9
- package/dist/sdk/similarity-scoring.d.ts +1 -2
- package/dist/sdk/similarity-scoring.js +4 -16
- package/dist/sdk/workspace-snapshot.d.ts +4 -0
- package/dist/sdk/workspace-snapshot.js +24 -11
- package/docs/AGENT_GUIDE.md +3 -1
- package/docs/COMMANDS.md +8 -5
- package/docs/MERGE_SAFETY.md +7 -5
- package/docs/README.md +2 -5
- package/docs/READ_OUTPUT_CONTRACTS.md +2 -2
- package/docs/SDK.md +33 -8
- package/docs/SDK_AGENT_SESSION_CONTEXT.md +3 -2
- package/docs/SDK_CONTEXT.md +97 -0
- package/docs/SDK_CONTEXT_INTEGRITY.md +18 -3
- package/docs/agent-task-token-baseline.json +2 -2
- package/marketplace.json +2 -2
- package/package.json +5 -4
- 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 +194 -26
- package/dist/cli-bundle/chunks/chunk-5KN4DZYV.js +0 -194
- package/dist/cli-bundle/chunks/chunk-HUV2Z7IS.js +0 -28
- package/dist/cli-bundle/chunks/chunk-MHBVCUF2.js +0 -2
- package/dist/cli-bundle/chunks/register-operations-YH2WAOXU.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-2VVP5RAA.js +0 -153
- package/dist/cli-bundle/focused-chunks/chunk-3GSFUDAI.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-4H6MVCK3.js +0 -16
- package/dist/cli-bundle/focused-chunks/chunk-54TZJ4BM.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-5NK5TJ5D.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-JGRSQZJT.js +0 -18
- package/dist/cli-bundle/focused-chunks/chunk-NL57J7BZ.js +0 -4
- package/dist/cli-bundle/focused-chunks/chunk-P6BBIQRG.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-PZAGVQNN.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-QDAO3XEK.js +0 -14
- package/dist/cli-bundle/focused-chunks/chunk-T4IGQCSY.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-XC2ZW3CJ.js +0 -2
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* value for the coordinator that performed the merge.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
!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]="
|
|
10
|
+
!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]="59863597-bf57-5d96-9cba-983443e5b209")}catch(e){}}();
|
|
11
11
|
import { execFile } from "node:child_process";
|
|
12
12
|
import { randomUUID } from "node:crypto";
|
|
13
13
|
import { readdir, readFile } from "node:fs/promises";
|
|
@@ -31,6 +31,21 @@ async function resolveReceiptDirectory(cwd) {
|
|
|
31
31
|
return null;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
+
async function resolveTrackerRootFromItemPath(cwd, itemPath) {
|
|
35
|
+
let directory = path.dirname(path.resolve(cwd, itemPath));
|
|
36
|
+
for (let depth = 0; depth < 12; depth += 1) {
|
|
37
|
+
if (await pathExists(path.join(directory, "settings.json")))
|
|
38
|
+
return directory;
|
|
39
|
+
const parent = path.dirname(directory);
|
|
40
|
+
if (parent === directory)
|
|
41
|
+
break;
|
|
42
|
+
directory = parent;
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
function durableReceiptDirectory(pmRoot) {
|
|
47
|
+
return path.join(pmRoot, "merge-receipts");
|
|
48
|
+
}
|
|
34
49
|
function receiptFileName(id) {
|
|
35
50
|
return `${id}.json`;
|
|
36
51
|
}
|
|
@@ -47,11 +62,25 @@ export function summarizeMergeReceipt(receipt) {
|
|
|
47
62
|
conflict_resolution: receipt.conflict_resolution,
|
|
48
63
|
decisions: receipt.decisions.map((decision) => ({
|
|
49
64
|
field: decision.field,
|
|
50
|
-
retained_hash:
|
|
51
|
-
|
|
65
|
+
retained_hash: isPrehashedValue(decision.retained) ??
|
|
66
|
+
sha256Hex(stableStringify(decision.retained)),
|
|
67
|
+
discarded_hash: isPrehashedValue(decision.discarded) ??
|
|
68
|
+
sha256Hex(stableStringify(decision.discarded)),
|
|
52
69
|
})),
|
|
53
70
|
};
|
|
54
71
|
}
|
|
72
|
+
function isPrehashedValue(value) {
|
|
73
|
+
if (typeof value !== "object" ||
|
|
74
|
+
value === null ||
|
|
75
|
+
Array.isArray(value) ||
|
|
76
|
+
!("pm_value_hash" in value)) {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
const hash = value.pm_value_hash;
|
|
80
|
+
return typeof hash === "string" && /^[a-f0-9]{64}$/u.test(hash)
|
|
81
|
+
? hash
|
|
82
|
+
: undefined;
|
|
83
|
+
}
|
|
55
84
|
/** Persist one item-driver outcome in the clone-local Git directory. */
|
|
56
85
|
export async function writeMergeReceipt(params) {
|
|
57
86
|
const directory = await resolveReceiptDirectory(params.cwd);
|
|
@@ -77,18 +106,34 @@ export async function writeMergeReceipt(params) {
|
|
|
77
106
|
decisions: structuredClone(params.decisions),
|
|
78
107
|
state: "pending",
|
|
79
108
|
created_at: nowIso(),
|
|
109
|
+
value_availability: "clone_local",
|
|
80
110
|
};
|
|
81
111
|
await ensureDir(directory);
|
|
82
112
|
await writeFileAtomic(path.join(directory, receiptFileName(receipt.id)), `${JSON.stringify(receipt, null, 2)}\n`);
|
|
113
|
+
const trackerRoot = await resolveTrackerRootFromItemPath(params.cwd, receipt.item_path);
|
|
114
|
+
if (trackerRoot !== null) {
|
|
115
|
+
const durableDirectory = durableReceiptDirectory(trackerRoot);
|
|
116
|
+
const summary = summarizeMergeReceipt(receipt);
|
|
117
|
+
const durableReceipt = {
|
|
118
|
+
...receipt,
|
|
119
|
+
decisions: summary.decisions.map((decision) => ({
|
|
120
|
+
field: decision.field,
|
|
121
|
+
base: null,
|
|
122
|
+
ours: null,
|
|
123
|
+
theirs: null,
|
|
124
|
+
retained: { pm_value_hash: decision.retained_hash },
|
|
125
|
+
discarded: { pm_value_hash: decision.discarded_hash },
|
|
126
|
+
})),
|
|
127
|
+
value_availability: "hash_only",
|
|
128
|
+
};
|
|
129
|
+
await ensureDir(durableDirectory);
|
|
130
|
+
await writeFileAtomic(path.join(durableDirectory, receiptFileName(receipt.id)), `${JSON.stringify(durableReceipt, null, 2)}\n`);
|
|
131
|
+
}
|
|
83
132
|
return receipt;
|
|
84
133
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const directory = await resolveReceiptDirectory(cwd);
|
|
88
|
-
if (directory === null || !(await pathExists(directory))) {
|
|
134
|
+
async function readReceiptsFromDirectory(directory, options) {
|
|
135
|
+
if (!(await pathExists(directory)))
|
|
89
136
|
return [];
|
|
90
|
-
}
|
|
91
|
-
const receipts = [];
|
|
92
137
|
let names;
|
|
93
138
|
try {
|
|
94
139
|
names = await readdir(directory);
|
|
@@ -96,10 +141,10 @@ export async function listMergeReceipts(cwd, options = {}) {
|
|
|
96
141
|
catch {
|
|
97
142
|
return [];
|
|
98
143
|
}
|
|
144
|
+
const receipts = [];
|
|
99
145
|
for (const name of names.sort((left, right) => left.localeCompare(right))) {
|
|
100
|
-
if (!name.endsWith(".json"))
|
|
146
|
+
if (!name.endsWith(".json"))
|
|
101
147
|
continue;
|
|
102
|
-
}
|
|
103
148
|
try {
|
|
104
149
|
const parsed = JSON.parse(await readFile(path.join(directory, name), "utf8"));
|
|
105
150
|
const normalizedReceipt = {
|
|
@@ -109,17 +154,28 @@ export async function listMergeReceipts(cwd, options = {}) {
|
|
|
109
154
|
if (normalizedReceipt.version === 1 &&
|
|
110
155
|
(options.includeReconciled || normalizedReceipt.state === "pending") &&
|
|
111
156
|
(options.includeLossless !== false ||
|
|
112
|
-
|
|
113
|
-
normalizedReceipt.decisions.length > 0))) {
|
|
157
|
+
normalizedReceipt.decisions.length > 0)) {
|
|
114
158
|
receipts.push(normalizedReceipt);
|
|
115
159
|
}
|
|
116
160
|
}
|
|
117
161
|
catch {
|
|
118
|
-
//
|
|
119
|
-
// omitted count once a future schema version adds richer diagnostics.
|
|
162
|
+
// Malformed evidence remains an integrity concern for a future schema.
|
|
120
163
|
}
|
|
121
164
|
}
|
|
122
|
-
return receipts
|
|
165
|
+
return receipts;
|
|
166
|
+
}
|
|
167
|
+
/** Read clone-local receipts with explicit reconciled/lossless classification controls. */
|
|
168
|
+
export async function listMergeReceipts(cwd, options = {}) {
|
|
169
|
+
const directory = await resolveReceiptDirectory(cwd);
|
|
170
|
+
const local = directory === null
|
|
171
|
+
? []
|
|
172
|
+
: await readReceiptsFromDirectory(directory, options);
|
|
173
|
+
const trackerRoot = options.pmRoot ?? path.join(cwd, ".agents", "pm");
|
|
174
|
+
const durable = await readReceiptsFromDirectory(durableReceiptDirectory(trackerRoot), options);
|
|
175
|
+
const receipts = new Map(durable.map((receipt) => [receipt.id, receipt]));
|
|
176
|
+
for (const receipt of local)
|
|
177
|
+
receipts.set(receipt.id, receipt);
|
|
178
|
+
return [...receipts.values()].sort((left, right) => left.created_at.localeCompare(right.created_at));
|
|
123
179
|
}
|
|
124
180
|
/** Split merge provenance into receipts with discarded values and receipts whose composition was lossless. */
|
|
125
181
|
export function partitionMergeReceipts(receipts) {
|
|
@@ -139,6 +195,14 @@ export async function markMergeReceiptReconciled(cwd, receipt) {
|
|
|
139
195
|
return;
|
|
140
196
|
}
|
|
141
197
|
await writeFileAtomic(path.join(directory, receiptFileName(receipt.id)), `${JSON.stringify({ ...receipt, state: "reconciled", reconciled_at: nowIso() }, null, 2)}\n`);
|
|
198
|
+
const trackerRoot = await resolveTrackerRootFromItemPath(cwd, receipt.item_path);
|
|
199
|
+
if (trackerRoot !== null) {
|
|
200
|
+
const durablePath = path.join(durableReceiptDirectory(trackerRoot), receiptFileName(receipt.id));
|
|
201
|
+
if (await pathExists(durablePath)) {
|
|
202
|
+
const durable = JSON.parse(await readFile(durablePath, "utf8"));
|
|
203
|
+
await writeFileAtomic(durablePath, `${JSON.stringify({ ...durable, state: "reconciled", reconciled_at: nowIso() }, null, 2)}\n`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
142
206
|
}
|
|
143
207
|
/** Report pending or historical clone-local merge decisions. */
|
|
144
208
|
export async function runMergeReceiptReport(options) {
|
|
@@ -154,4 +218,4 @@ export async function runMergeReceiptReport(options) {
|
|
|
154
218
|
};
|
|
155
219
|
}
|
|
156
220
|
//# sourceMappingURL=receipts.js.map
|
|
157
|
-
//# debugId=
|
|
221
|
+
//# debugId=59863597-bf57-5d96-9cba-983443e5b209
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Declares machine-readable field-group omissions for bounded command results.
|
|
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]="630b48a7-aa38-529c-a272-14b7c748101c")}catch(e){}}();
|
|
8
8
|
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
9
9
|
import { PmCliError } from "../core/shared/errors.js";
|
|
10
10
|
/** Universal selector for results carrying a {@link ReadRowContract}. */
|
|
@@ -283,11 +283,31 @@ function resolveContextReceipt(result) {
|
|
|
283
283
|
function resolveGetReceipt(result) {
|
|
284
284
|
if (!isRecord(result.item))
|
|
285
285
|
return undefined;
|
|
286
|
-
const
|
|
286
|
+
const item = result.item;
|
|
287
|
+
const itemGroups = [
|
|
288
|
+
"comments",
|
|
289
|
+
"notes",
|
|
290
|
+
"learnings",
|
|
291
|
+
"files",
|
|
292
|
+
"tests",
|
|
293
|
+
"docs",
|
|
294
|
+
"reminders",
|
|
295
|
+
"events",
|
|
296
|
+
];
|
|
297
|
+
const resultGroups = [
|
|
298
|
+
"body",
|
|
299
|
+
"children",
|
|
300
|
+
"claim_state",
|
|
301
|
+
"linked",
|
|
302
|
+
"schedule",
|
|
303
|
+
];
|
|
304
|
+
const groups = ["body", ...itemGroups, ...resultGroups.slice(1)].map((name) => ({
|
|
287
305
|
name,
|
|
288
306
|
restore_with: `--fields ${name}`,
|
|
289
307
|
}));
|
|
290
|
-
return createOutputOmissionReceipt(groups, new Set(groups.flatMap(({ name }) => (
|
|
308
|
+
return createOutputOmissionReceipt(groups, new Set(groups.flatMap(({ name }) => !Object.hasOwn(itemGroups.includes(name) ? item : result, name)
|
|
309
|
+
? []
|
|
310
|
+
: [name])));
|
|
291
311
|
}
|
|
292
312
|
function resolveListOrSearchReceipt(result) {
|
|
293
313
|
if (!isRecord(result.projection))
|
|
@@ -358,4 +378,4 @@ export function attachOutputOmissionReceipt(command, result) {
|
|
|
358
378
|
: { ...disclosedResult, omission_receipt: receipt };
|
|
359
379
|
}
|
|
360
380
|
//# sourceMappingURL=output-projection.js.map
|
|
361
|
-
//# debugId=
|
|
381
|
+
//# debugId=630b48a7-aa38-529c-a272-14b7c748101c
|
|
@@ -362,6 +362,8 @@ export interface ContextResult {
|
|
|
362
362
|
focus_fields?: string[];
|
|
363
363
|
/** Value that configures or reports warnings for this contract. */
|
|
364
364
|
warnings?: string[];
|
|
365
|
+
/** Actionable recovery contracts for context signal-store warnings. */
|
|
366
|
+
warning_details?: ContextSignalStoreReadResult["warning_details"];
|
|
365
367
|
/** Value that configures or reports ranking for this contract. */
|
|
366
368
|
ranking?: ContextRankingSummary;
|
|
367
369
|
/** Token-budget selection and projection accounting for ranked focus rows. */
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Implements the pm context 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]="161507f0-b1a7-59a6-9a60-d8f09806ed3f")}catch(e){}}();
|
|
8
8
|
import { SETTINGS_DEFAULTS, EXIT_CODE, PmCliError, compareTimestampStrings, nowIso, isTerminalStatus, normalizeStatusForRegistry, normalizeStatusInput, resolveRuntimeStatusRegistry, resolvePmRoot, readSettings, resolveAuthor, discoverExtensions, } from "../runtime-primitives.js";
|
|
9
9
|
import { collectDependencyBlockedIds, resolveItemBlockers, } from "../actionability.js";
|
|
10
10
|
import { CONTEXT_DEPTH_VALUES, CONTEXT_SECTION_VALUES, } from "../../types/index.js";
|
|
@@ -1412,7 +1412,7 @@ function buildContextSummaryExtras(needsAllItems, allItems, statusRegistry) {
|
|
|
1412
1412
|
canceledStatus).length,
|
|
1413
1413
|
};
|
|
1414
1414
|
}
|
|
1415
|
-
function attachOptionalContextSections(result, sections) {
|
|
1415
|
+
function attachOptionalContextSections(result, sections, warningDetails) {
|
|
1416
1416
|
if (sections.hierarchy)
|
|
1417
1417
|
result.hierarchy = sections.hierarchy;
|
|
1418
1418
|
if (sections.activity)
|
|
@@ -1433,6 +1433,9 @@ function attachOptionalContextSections(result, sections) {
|
|
|
1433
1433
|
result.staleness = sections.staleness;
|
|
1434
1434
|
if (sections.tests)
|
|
1435
1435
|
result.tests = sections.tests;
|
|
1436
|
+
if (warningDetails !== undefined && warningDetails.length > 0) {
|
|
1437
|
+
result.warning_details = warningDetails;
|
|
1438
|
+
}
|
|
1436
1439
|
}
|
|
1437
1440
|
function applyContextFocusProjection(result, focusFields) {
|
|
1438
1441
|
if (!focusFields) {
|
|
@@ -1642,7 +1645,7 @@ export async function runContext(options, global) {
|
|
|
1642
1645
|
};
|
|
1643
1646
|
result.workspace_memory = selectWorkspaceMemory(workspaceMemory, Math.min(800, Math.floor(runtime.tokenBudget * 0.2)));
|
|
1644
1647
|
Object.assign(result, await extensionHealthPromise);
|
|
1645
|
-
attachOptionalContextSections(result, sections);
|
|
1648
|
+
attachOptionalContextSections(result, sections, focusGroups.featureStore.warning_details);
|
|
1646
1649
|
applyContextTagProjection(result, options.noTags === true);
|
|
1647
1650
|
if (options.explainRanking === true) {
|
|
1648
1651
|
result.ranking = toContextRankingSummary(focusGroups.ranking, focusGroups.featureStore);
|
|
@@ -1656,4 +1659,4 @@ export async function runContext(options, global) {
|
|
|
1656
1659
|
return result;
|
|
1657
1660
|
}
|
|
1658
1661
|
//# sourceMappingURL=context.js.map
|
|
1659
|
-
//# debugId=
|
|
1662
|
+
//# debugId=161507f0-b1a7-59a6-9a60-d8f09806ed3f
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ItemMetadata } from "../../types/index.js";
|
|
2
|
+
/** Read scalar-only metadata using client workspace defaults and custom type folders. */
|
|
3
|
+
export declare function listClientItemMetadataLight(pmRootOverride: string | undefined, cwdOverride: string | undefined): Promise<ItemMetadata[]>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/query/light-metadata
|
|
3
|
+
*
|
|
4
|
+
* Resolves workspace settings for the host-bound lightweight metadata reader.
|
|
5
|
+
*/
|
|
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]="6ede8efb-54ec-5b13-a1bf-216b525acc12")}catch(e){}}();
|
|
8
|
+
import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
|
|
9
|
+
import { listAllItemMetadataLight } from "../../core/store/item-store.js";
|
|
10
|
+
import { resolvePmRoot } from "../../core/store/paths.js";
|
|
11
|
+
import { readSettings } from "../../core/store/settings.js";
|
|
12
|
+
/** Read scalar-only metadata using client workspace defaults and custom type folders. */
|
|
13
|
+
export async function listClientItemMetadataLight(pmRootOverride, cwdOverride) {
|
|
14
|
+
const pmRoot = resolvePmRoot(cwdOverride ?? process.cwd(), pmRootOverride);
|
|
15
|
+
const settings = await readSettings(pmRoot);
|
|
16
|
+
return listAllItemMetadataLight(pmRoot, settings.item_format, resolveItemTypeRegistry(settings, null).type_to_folder, undefined, settings.schema);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=light-metadata.js.map
|
|
19
|
+
//# debugId=6ede8efb-54ec-5b13-a1bf-216b525acc12
|
package/dist/sdk/runtime.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { PM_GITIGNORE_END, PM_GITIGNORE_START, ensurePmGitignore, getPmGitignore
|
|
|
7
7
|
export { SEARCH_EXTENSION_FLAG_DEFINITIONS } from "./extension-contracts.js";
|
|
8
8
|
export type { FlagDefinition } from "../core/extensions/loader.js";
|
|
9
9
|
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
10
|
+
import type { ItemMetadata } from "../types/index.js";
|
|
10
11
|
export type { WorkspaceExtensionCommandContract, WorkspaceFieldContract, } from "./workspace-contracts.js";
|
|
11
12
|
import { type PmReadOutputOptions, type PmReadOutputResultFor } from "./read-output-contracts.js";
|
|
12
13
|
export type { PmReadOutputBudgetExceeded, PmReadOutputOptions, PmReadOutputResult, PmReadOutputResultFor, PmReadOutputSurfaceContract, } from "./read-output-contracts.js";
|
|
@@ -74,7 +75,7 @@ export { EXIT_CODE };
|
|
|
74
75
|
export { PmCliError } from "../core/shared/errors.js";
|
|
75
76
|
export { isTimestampLiteral, nowIso } from "../core/shared/time.js";
|
|
76
77
|
export { jaccardSimilarity, normalizeSimilarityText, scoreItemSimilarity, tokenizeSimilarityText, type ItemSimilarityScore, } from "./similarity-scoring.js";
|
|
77
|
-
export { listAllItemMetadata, locateItem, readLocatedItem, } from "../core/store/item-store.js";
|
|
78
|
+
export { listAllItemMetadata, listAllItemMetadataLight, locateItem, readLocatedItem, } from "../core/store/item-store.js";
|
|
78
79
|
export { getHistoryPath, getItemPath, getSettingsPath, resolveImplicitPmRoot, resolvePmRoot, } from "../core/store/paths.js";
|
|
79
80
|
export { readSettings } from "../core/store/settings.js";
|
|
80
81
|
export { runAggregate, type AggregateOptions, type AggregateResult, type AggregateRow, } from "./query/aggregate.js";
|
|
@@ -131,6 +132,8 @@ export declare class PmClient {
|
|
|
131
132
|
private runTyped;
|
|
132
133
|
/** Return the same context snapshot produced by `pm context`. */
|
|
133
134
|
context<Options extends ReadOptions<ContextOptions> = ContextOptions>(options?: Options): ReadPromise<ContextResult, Options>;
|
|
135
|
+
/** Read every item through the scalar-only metadata cache without materializing heavy collections or bodies. */
|
|
136
|
+
listAllItemMetadataLight(): Promise<ItemMetadata[]>;
|
|
134
137
|
/** List items with the MCP/agent compact defaults. */
|
|
135
138
|
list<Options extends ReadOptions<ListOptions> = ListOptions>(options?: Options): ReadPromise<ListResult, Options>;
|
|
136
139
|
/** Search items with the MCP/agent compact defaults. */
|
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]="70ce3cab-35f0-508b-9348-2f8479495946")}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";
|
|
@@ -22,6 +22,7 @@ import { createAsyncReadWriteGate } from "../core/shared/serial-queue.js";
|
|
|
22
22
|
import { resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, } from "../core/schema/runtime-schema.js";
|
|
23
23
|
import { getSettingsPath, resolvePmRoot } from "../core/store/paths.js";
|
|
24
24
|
import { readSettings } from "../core/store/settings.js";
|
|
25
|
+
import { listClientItemMetadataLight } from "./query/light-metadata.js";
|
|
25
26
|
import { buildWorkspaceExtensionCommandContracts, buildWorkspaceFieldContracts, } from "./workspace-contracts.js";
|
|
26
27
|
import { PM_TOOL_ACTIONS } from "./cli-contracts/enum-contracts.js";
|
|
27
28
|
import { clearWorkspaceContractsCache, memoizeWorkspaceExtensionRegistrations, } from "./workspace-contracts-cache.js";
|
|
@@ -99,7 +100,7 @@ export { EXIT_CODE };
|
|
|
99
100
|
export { PmCliError } from "../core/shared/errors.js";
|
|
100
101
|
export { isTimestampLiteral, nowIso } from "../core/shared/time.js";
|
|
101
102
|
export { jaccardSimilarity, normalizeSimilarityText, scoreItemSimilarity, tokenizeSimilarityText, } from "./similarity-scoring.js";
|
|
102
|
-
export { listAllItemMetadata, locateItem, readLocatedItem, } from "../core/store/item-store.js";
|
|
103
|
+
export { listAllItemMetadata, listAllItemMetadataLight, locateItem, readLocatedItem, } from "../core/store/item-store.js";
|
|
103
104
|
export { getHistoryPath, getItemPath, getSettingsPath, resolveImplicitPmRoot, resolvePmRoot, } from "../core/store/paths.js";
|
|
104
105
|
export { readSettings } from "../core/store/settings.js";
|
|
105
106
|
export { runAggregate, } from "./query/aggregate.js";
|
|
@@ -169,6 +170,10 @@ export class PmClient {
|
|
|
169
170
|
context(options = {}) {
|
|
170
171
|
return this.runTyped("context", { options });
|
|
171
172
|
}
|
|
173
|
+
/** Read every item through the scalar-only metadata cache without materializing heavy collections or bodies. */
|
|
174
|
+
listAllItemMetadataLight() {
|
|
175
|
+
return listClientItemMetadataLight(this.defaults.path, this.defaults.cwd);
|
|
176
|
+
}
|
|
172
177
|
/** List items with the MCP/agent compact defaults. */
|
|
173
178
|
list(options = {}) {
|
|
174
179
|
return this.runTyped("list", { options });
|
|
@@ -1925,4 +1930,4 @@ async function loadWorkspaceExtensionRegistrations(pmRoot, settings, cwd) {
|
|
|
1925
1930
|
}
|
|
1926
1931
|
}
|
|
1927
1932
|
//# sourceMappingURL=runtime.js.map
|
|
1928
|
-
//# debugId=
|
|
1933
|
+
//# debugId=70ce3cab-35f0-508b-9348-2f8479495946
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* guarantees.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
!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]="
|
|
10
|
+
!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]="7d175791-016d-59b6-a44d-a70371f36751")}catch(e){}}();
|
|
11
11
|
import { createHash } from "node:crypto";
|
|
12
12
|
import fs from "node:fs/promises";
|
|
13
13
|
import path from "node:path";
|
|
@@ -18,6 +18,7 @@ import { parseFieldsFile, serializeFieldsFile, } from "../core/schema/fields-fil
|
|
|
18
18
|
import { parseItemTypesFile, serializeItemTypesFile, } from "../core/schema/item-types-file.js";
|
|
19
19
|
import { DEFAULT_RUNTIME_SCHEMA_FILE_PATHS, filePathForSchemaSection, normalizeRuntimeSchemaSettings, } from "../core/schema/runtime-schema.js";
|
|
20
20
|
import { parseStatusDefsFile, serializeStatusDefsFile, } from "../core/schema/status-defs-file.js";
|
|
21
|
+
import { normalizeStatusToken } from "../core/schema/status-token.js";
|
|
21
22
|
import { getActiveExtensionRegistrations } from "../core/extensions/index.js";
|
|
22
23
|
import { listAllItemMetadataLight, locateItem, mutateItem, readLocatedItem, } from "../core/store/item-store.js";
|
|
23
24
|
import { getSettingsPath, resolvePmRoot } from "../core/store/paths.js";
|
|
@@ -55,9 +56,6 @@ export function deriveSchemaEvolutionMigrationId(requestInput, migrationScope) {
|
|
|
55
56
|
.slice(0, 20)}`;
|
|
56
57
|
}
|
|
57
58
|
function normalizedRequest(request) {
|
|
58
|
-
const normalizeToken = (value) => requiredText(value, "source or target")
|
|
59
|
-
.toLowerCase()
|
|
60
|
-
.replaceAll(/[\s-]+/g, "_");
|
|
61
59
|
const normalized = request.kind === "rename-type"
|
|
62
60
|
? {
|
|
63
61
|
kind: request.kind,
|
|
@@ -67,16 +65,16 @@ function normalizedRequest(request) {
|
|
|
67
65
|
: request.kind === "rename-field"
|
|
68
66
|
? {
|
|
69
67
|
kind: request.kind,
|
|
70
|
-
from:
|
|
71
|
-
to:
|
|
68
|
+
from: normalizeStatusToken(requiredText(request.from, "source")),
|
|
69
|
+
to: normalizeStatusToken(requiredText(request.to, "target")),
|
|
72
70
|
...(request.type === undefined
|
|
73
71
|
? {}
|
|
74
72
|
: { type: requiredText(request.type, "type") }),
|
|
75
73
|
}
|
|
76
74
|
: {
|
|
77
75
|
kind: request.kind,
|
|
78
|
-
from:
|
|
79
|
-
to:
|
|
76
|
+
from: normalizeStatusToken(requiredText(request.from, "source")),
|
|
77
|
+
to: normalizeStatusToken(requiredText(request.to, "target")),
|
|
80
78
|
};
|
|
81
79
|
if (normalized.from.toLowerCase() === normalized.to.toLowerCase()) {
|
|
82
80
|
throw new TypeError("Schema migration source and target must differ");
|
|
@@ -857,4 +855,4 @@ export const schemaMigrationTestOnly = {
|
|
|
857
855
|
validateAndStoreMigrationPlan,
|
|
858
856
|
};
|
|
859
857
|
//# sourceMappingURL=schema-migration.js.map
|
|
860
|
-
//# debugId=
|
|
858
|
+
//# debugId=7d175791-016d-59b6-a44d-a70371f36751
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { jaccardSimilarity } from "../core/shared/text-normalization.js";
|
|
1
2
|
/** Precomputed title signals reused by bounded batch similarity operations. */
|
|
2
3
|
export interface PreparedSimilarityText {
|
|
3
4
|
/** Canonical title used for exact comparison. */
|
|
@@ -20,8 +21,6 @@ export declare function normalizeSimilarityText(value: string): string;
|
|
|
20
21
|
export declare function tokenizeSimilarityText(value: string): string[];
|
|
21
22
|
/** Precompute every deterministic title signal exactly once for repeated comparisons. */
|
|
22
23
|
export declare function prepareSimilarityText(value: string): PreparedSimilarityText;
|
|
23
|
-
/** Measure set overlap between two token collections. */
|
|
24
|
-
export declare function jaccardSimilarity(leftTokens: readonly string[], rightTokens: readonly string[]): number;
|
|
25
24
|
/** Score two titles through the canonical exact, issue-code, and token signals. */
|
|
26
25
|
export declare function scoreItemSimilarity(leftTitle: string, rightTitle: string): ItemSimilarityScore;
|
|
27
26
|
/** Score two precomputed title representations without repeating normalization or tokenization. */
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* extension packages without loading tracker query infrastructure.
|
|
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]="dff9b113-2b29-5154-afbf-f191f2f556a6")}catch(e){}}();
|
|
9
|
+
import { jaccardSimilarity } from "../core/shared/text-normalization.js";
|
|
10
|
+
export { jaccardSimilarity } from "../core/shared/text-normalization.js";
|
|
9
11
|
const ISSUE_CODE_PATTERN = /\b[a-z][a-z0-9]*-\d+(?:-[a-z0-9]+)*\b/giu;
|
|
10
12
|
/** Normalize title text for exact comparisons and tokenization. */
|
|
11
13
|
export function normalizeSimilarityText(value) {
|
|
@@ -30,20 +32,6 @@ export function prepareSimilarityText(value) {
|
|
|
30
32
|
],
|
|
31
33
|
};
|
|
32
34
|
}
|
|
33
|
-
/** Measure set overlap between two token collections. */
|
|
34
|
-
export function jaccardSimilarity(leftTokens, rightTokens) {
|
|
35
|
-
const left = new Set(leftTokens);
|
|
36
|
-
const right = new Set(rightTokens);
|
|
37
|
-
const union = new Set([...left, ...right]);
|
|
38
|
-
if (union.size === 0)
|
|
39
|
-
return 1;
|
|
40
|
-
let intersection = 0;
|
|
41
|
-
for (const token of left) {
|
|
42
|
-
if (right.has(token))
|
|
43
|
-
intersection += 1;
|
|
44
|
-
}
|
|
45
|
-
return intersection / union.size;
|
|
46
|
-
}
|
|
47
35
|
/** Score two titles through the canonical exact, issue-code, and token signals. */
|
|
48
36
|
export function scoreItemSimilarity(leftTitle, rightTitle) {
|
|
49
37
|
return scorePreparedItemSimilarity(prepareSimilarityText(leftTitle), prepareSimilarityText(rightTitle));
|
|
@@ -63,4 +51,4 @@ export function scorePreparedItemSimilarity(left, right) {
|
|
|
63
51
|
};
|
|
64
52
|
}
|
|
65
53
|
//# sourceMappingURL=similarity-scoring.js.map
|
|
66
|
-
//# debugId=
|
|
54
|
+
//# debugId=dff9b113-2b29-5154-afbf-f191f2f556a6
|
|
@@ -19,10 +19,14 @@ declare class WorkspaceLockHeartbeat {
|
|
|
19
19
|
constructor(lockPath: string, owner: string, ttlSeconds: number);
|
|
20
20
|
/** Begin renewing the lock without keeping the process alive on its own. */
|
|
21
21
|
start(): void;
|
|
22
|
+
/** Force and await one owned renewal so callers can establish a fresh lease boundary. */
|
|
23
|
+
refreshNow(): Promise<void>;
|
|
22
24
|
/** Fail the restore before activation when lease ownership was lost. */
|
|
23
25
|
assertHealthy(): void;
|
|
24
26
|
/** Stop future renewals and await the last in-flight atomic write. */
|
|
25
27
|
stop(): Promise<void>;
|
|
28
|
+
/** Serialize renewal attempts and retain the first ownership failure. */
|
|
29
|
+
private scheduleRenewal;
|
|
26
30
|
/** Atomically refresh only the lock still owned by this process and actor. */
|
|
27
31
|
private renew;
|
|
28
32
|
}
|
|
@@ -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]="470bb466-4619-5c54-a154-186b7ef4a049")}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";
|
|
@@ -55,19 +55,18 @@ class WorkspaceLockHeartbeat {
|
|
|
55
55
|
}
|
|
56
56
|
/** Begin renewing the lock without keeping the process alive on its own. */
|
|
57
57
|
start() {
|
|
58
|
+
this.scheduleRenewal();
|
|
58
59
|
this.timer = setInterval(() => {
|
|
59
|
-
|
|
60
|
-
return;
|
|
61
|
-
this.refresh = this.renew()
|
|
62
|
-
.catch((error) => {
|
|
63
|
-
this.failure = error;
|
|
64
|
-
})
|
|
65
|
-
.finally(() => {
|
|
66
|
-
this.refresh = undefined;
|
|
67
|
-
});
|
|
60
|
+
this.scheduleRenewal();
|
|
68
61
|
}, this.intervalMs);
|
|
69
62
|
this.timer.unref();
|
|
70
63
|
}
|
|
64
|
+
/** Force and await one owned renewal so callers can establish a fresh lease boundary. */
|
|
65
|
+
async refreshNow() {
|
|
66
|
+
this.scheduleRenewal();
|
|
67
|
+
await this.refresh;
|
|
68
|
+
this.assertHealthy();
|
|
69
|
+
}
|
|
71
70
|
/** Fail the restore before activation when lease ownership was lost. */
|
|
72
71
|
assertHealthy() {
|
|
73
72
|
if (this.failure !== undefined) {
|
|
@@ -83,6 +82,18 @@ class WorkspaceLockHeartbeat {
|
|
|
83
82
|
await this.refresh;
|
|
84
83
|
this.assertHealthy();
|
|
85
84
|
}
|
|
85
|
+
/** Serialize renewal attempts and retain the first ownership failure. */
|
|
86
|
+
scheduleRenewal() {
|
|
87
|
+
if (this.refresh !== undefined || this.failure !== undefined)
|
|
88
|
+
return;
|
|
89
|
+
this.refresh = this.renew()
|
|
90
|
+
.catch((error) => {
|
|
91
|
+
this.failure = error;
|
|
92
|
+
})
|
|
93
|
+
.finally(() => {
|
|
94
|
+
this.refresh = undefined;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
86
97
|
/** Atomically refresh only the lock still owned by this process and actor. */
|
|
87
98
|
async renew() {
|
|
88
99
|
const parsed = JSON.parse(await readFile(this.lockPath, "utf8"));
|
|
@@ -483,6 +494,7 @@ export async function restoreWorkspaceSnapshotWithRecovery(pmRoot, target, optio
|
|
|
483
494
|
const releaseWorkspaceLock = await acquireLock(pmRoot, WORKSPACE_WRITER_LOCK_ID, lockTtlSeconds, author, false, false, lockWaitMs);
|
|
484
495
|
const heartbeat = new WorkspaceLockHeartbeat(getLockPath(pmRoot, WORKSPACE_WRITER_LOCK_ID), author, lockTtlSeconds);
|
|
485
496
|
heartbeat.start();
|
|
497
|
+
await heartbeat.refreshNow();
|
|
486
498
|
let staging;
|
|
487
499
|
let swapStarted = false;
|
|
488
500
|
let heartbeatStopped = false;
|
|
@@ -536,6 +548,7 @@ export async function restoreWorkspaceSnapshotWithRecovery(pmRoot, target, optio
|
|
|
536
548
|
await swapWorkspaceSnapshotRootWithActivation(staging, pmRoot, backup, DEFAULT_ATOMIC_OPERATIONS, async () => {
|
|
537
549
|
heartbeat.start();
|
|
538
550
|
heartbeatStopped = false;
|
|
551
|
+
await heartbeat.refreshNow();
|
|
539
552
|
});
|
|
540
553
|
await heartbeat.stop();
|
|
541
554
|
heartbeatStopped = true;
|
|
@@ -596,4 +609,4 @@ export async function deleteWorkspaceSnapshot(pmRoot, target) {
|
|
|
596
609
|
return { deleted: "object", target };
|
|
597
610
|
}
|
|
598
611
|
//# sourceMappingURL=workspace-snapshot.js.map
|
|
599
|
-
//# debugId=
|
|
612
|
+
//# debugId=470bb466-4619-5c54-a154-186b7ef4a049
|
package/docs/AGENT_GUIDE.md
CHANGED
|
@@ -50,7 +50,9 @@ Repeated singular/plural list flags accumulate, so `--tag a --tag b` is equivale
|
|
|
50
50
|
|
|
51
51
|
`--tags` REPLACES the whole tag list. To edit tags without restating the full set, prefer `--add-tags <value>` (adds without replacing) and `--remove-tags <value>` (prunes) on `create`/`update`/`update-many` (both repeatable; CSV or JSON-array). `--remove-tags` is `update`/`update-many` only. Also note `--expected`/`--actual` are short aliases for `--expected-result`/`--actual-result` on these commands, matching `pm close`.
|
|
52
52
|
|
|
53
|
-
`--acceptance-criteria`/`--ac` likewise REPLACES the whole criteria value
|
|
53
|
+
`--acceptance-criteria`/`--ac` likewise explicitly REPLACES the whole criteria value and cannot be combined with `--add-ac` or `--remove-ac`. Prefer `--add-ac <text>` (appends one criterion; deduped on exact text) and `--remove-ac <text>` (removes one criterion by exact text) on `update`/`update-many` so concurrent branch edits with disjoint additions merge instead of clobbering. Every removal must match or the complete mutation fails atomically with structured unmatched-selector recovery. Acceptance criteria use semicolons as storage boundaries, so one criterion cannot itself contain a semicolon.
|
|
54
|
+
|
|
55
|
+
Local dependency targets supplied to `create`, `update`, or `update-many` must already exist. Mark cross-workspace targets with `source_kind=external`; reserve `--allow-unresolved-deps` for deliberate staged imports and retain its structured warning as evidence.
|
|
54
56
|
|
|
55
57
|
```bash
|
|
56
58
|
pm update <item-id> --add-tags urgent,backend # keep existing tags, add two
|