@unbrained/pm-cli 2026.8.24 → 2026.8.25
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 +13 -0
- package/dist/cli-bundle/bundle-manifest.json +152 -152
- package/dist/cli-bundle/chunks/{chunk-ZAVCS2GH.js → chunk-244MI4GS.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-NXBFO63A.js → chunk-2F3LUFMW.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-DJNJBWAQ.js → chunk-5I5RWIJC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-X7WWQDYQ.js → chunk-65MHLHAA.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-6C7GIMIL.js +13 -0
- package/dist/cli-bundle/chunks/{chunk-IW72J5FW.js → chunk-OWHNAR2B.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-TEQDR5KI.js → chunk-QKGMHGEI.js} +62 -62
- package/dist/cli-bundle/chunks/{chunk-L22NP5MA.js → chunk-QLUORNIB.js} +86 -86
- package/dist/cli-bundle/chunks/{chunk-AGUL3HUT.js → chunk-T2ENPRXF.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-I5Q7QSZX.js → chunk-TPQIBSL2.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-YQMYF3YD.js +35 -0
- package/dist/cli-bundle/chunks/{register-list-query-37A4P6O4.js → register-list-query-XVN2ZLI7.js} +2 -2
- package/dist/cli-bundle/chunks/{register-mutation-TBJDHYIT.js → register-mutation-QCKAEGIJ.js} +3 -3
- package/dist/cli-bundle/chunks/{register-operations-WRZNEBUM.js → register-operations-SDEAXE7E.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-H4PDLACD.js → register-setup-LXVBRCJ3.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-CWCN5RLO.js → chunk-2UIWOP3O.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-42S3GGZ7.js +50 -0
- package/dist/cli-bundle/focused-chunks/{chunk-BFA6KKCI.js → chunk-7I23XGWO.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-6Z24ZMU3.js → chunk-7YCDTCBC.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-O4ZXNJMT.js → chunk-A644DUFQ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-4WP7LNE3.js → chunk-GQR3WH3F.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-RASVBJX5.js → chunk-H5JZEIQV.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-IBZZZGK3.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-LMKG3DFE.js +5 -0
- package/dist/cli-bundle/focused-chunks/{chunk-6MUTDXMP.js → chunk-N7W67YIG.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-IMWTYKII.js → chunk-NOOZGIXP.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-WZLSSGEU.js → chunk-OHIHZ7HS.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-ONYQCALA.js +19 -0
- package/dist/cli-bundle/focused-chunks/{chunk-QBP5FSBX.js → chunk-OVJL6NZE.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-RAFKLNZX.js +16 -0
- package/dist/cli-bundle/focused-chunks/{chunk-GJR6YEMR.js → chunk-VXWATRFL.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-IZNRRCU3.js → chunk-XUQPEKRN.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-MNPECIRL.js → chunk-YO3ZF3FI.js} +2 -2
- package/dist/cli-bundle/main.js +2 -2
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +41 -41
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +32 -33
- 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/diagnostics/remediation.js +17 -2
- package/dist/sdk/cli-contracts/runtime-contracts.d.ts +10 -0
- package/dist/sdk/cli-contracts/runtime-contracts.js +20 -3
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +49 -25
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +26 -2
- package/dist/sdk/governance/health.js +98 -11
- package/dist/sdk/governance/validate.js +15 -9
- package/dist/sdk/history-repair.d.ts +24 -0
- package/dist/sdk/history-repair.js +145 -4
- package/dist/sdk/merge/driver.js +25 -4
- package/dist/sdk/merge/receipt-file-boundary.d.ts +21 -0
- package/dist/sdk/merge/receipt-file-boundary.js +47 -0
- package/dist/sdk/merge/receipts.d.ts +24 -1
- package/dist/sdk/merge/receipts.js +342 -36
- package/dist/sdk/merge/reconcile.js +117 -47
- package/dist/sdk/read-output/continuation.d.ts +15 -2
- package/dist/sdk/read-output/continuation.js +86 -6
- package/dist/sdk/read-output-contracts.d.ts +4 -1
- package/dist/sdk/read-output-contracts.js +9 -6
- package/docs/MERGE_SAFETY.md +34 -5
- package/docs/OUTPUT_PROJECTION_CONTRACTS.md +13 -1
- package/docs/READ_OUTPUT_CONTRACTS.md +25 -2
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +7 -3
- package/marketplace.json +2 -2
- package/package.json +1 -1
- 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 +136 -15
- package/dist/cli-bundle/chunks/chunk-MKE6MD2K.js +0 -36
- package/dist/cli-bundle/chunks/chunk-YOLLRCLY.js +0 -13
- package/dist/cli-bundle/focused-chunks/chunk-FCTT4CZU.js +0 -5
- package/dist/cli-bundle/focused-chunks/chunk-Q63PSLO4.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-QV5UP27O.js +0 -51
- package/dist/cli-bundle/focused-chunks/chunk-RPRLENVA.js +0 -16
- package/dist/cli-bundle/focused-chunks/chunk-TOFVXBWA.js +0 -19
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import type { PmReadOutputCursorEnvelope, PmReadOutputSurface } from "../read-output-contracts.js";
|
|
2
|
-
/**
|
|
3
|
-
export
|
|
2
|
+
/** Stable snapshot policy for a read surface whose probes refresh observation metadata. */
|
|
3
|
+
export interface PmReadOutputContinuationFingerprintPolicy {
|
|
4
|
+
/** Version included in fingerprints so policy changes invalidate older cursors. */
|
|
5
|
+
version: 3;
|
|
6
|
+
/** Declared continuation row paths governed by this policy. */
|
|
7
|
+
paths: readonly string[];
|
|
8
|
+
/** Exact direct detail fields excluded for each named dynamic row. */
|
|
9
|
+
ignored_detail_field_names_by_row: Readonly<Record<string, readonly string[]>>;
|
|
10
|
+
/** Promise that verdicts, stable configuration, and nonvolatile evidence remain bound. */
|
|
11
|
+
guarantee: "nonvolatile_snapshot_and_stable_configuration";
|
|
12
|
+
}
|
|
13
|
+
/** Command-specific exceptions to complete-row continuation fingerprinting. */
|
|
14
|
+
export declare const PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES: Readonly<Partial<Record<PmReadOutputSurface, PmReadOutputContinuationFingerprintPolicy>>>;
|
|
15
|
+
/** Fingerprint the policy-normalized row snapshot so stable evidence changes fail closed. */
|
|
16
|
+
export declare function readOutputCollectionFingerprint(path: string, value: unknown[] | Record<string, unknown>, command?: PmReadOutputSurface): string;
|
|
4
17
|
/** Encode one stable declared-row continuation for CLI, SDK, and MCP callers. */
|
|
5
18
|
export declare function encodeReadOutputContinuationCursor(cursor: Omit<PmReadOutputCursorEnvelope, "version">): string;
|
|
6
19
|
/** Decode and validate one universal declared-row continuation cursor. */
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* resolution and budget policy.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
!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]="
|
|
9
|
+
!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]="9e63b4b0-09a5-50bf-9f56-5f239c75ffe5")}catch(e){}}();
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
11
|
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
12
12
|
import { PmCliError } from "../../core/shared/errors.js";
|
|
@@ -14,13 +14,93 @@ import { stableStringify } from "../../core/shared/serialization.js";
|
|
|
14
14
|
import { resolveReadOutputSurface } from "../read-output-contracts.js";
|
|
15
15
|
import { readOutputContinuationRowCollections, sliceReadOutputRowCollection, } from "../read-output-rows.js";
|
|
16
16
|
const MAX_READ_OUTPUT_CURSOR_LENGTH = 4096;
|
|
17
|
+
const HEALTH_TELEMETRY_VOLATILE_DETAIL_FIELDS = Object.freeze([
|
|
18
|
+
"queue_draining",
|
|
19
|
+
"queue_entries",
|
|
20
|
+
"queue_exists",
|
|
21
|
+
"queue_high_retry_entries",
|
|
22
|
+
"queue_invalid_rows",
|
|
23
|
+
"queue_max_attempts",
|
|
24
|
+
"queue_rows_total",
|
|
25
|
+
"queue_size_bytes",
|
|
26
|
+
"pending_otel_spans",
|
|
27
|
+
"last_attempted_flush_at",
|
|
28
|
+
"last_failed_flush_at",
|
|
29
|
+
"last_otel_attempt_at",
|
|
30
|
+
"last_otel_failure_at",
|
|
31
|
+
"last_otel_success_at",
|
|
32
|
+
"last_successful_flush_at",
|
|
33
|
+
]);
|
|
34
|
+
/** Command-specific exceptions to complete-row continuation fingerprinting. */
|
|
35
|
+
export const PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES = Object.freeze({
|
|
36
|
+
health: Object.freeze({
|
|
37
|
+
version: 3,
|
|
38
|
+
paths: Object.freeze(["checks"]),
|
|
39
|
+
ignored_detail_field_names_by_row: Object.freeze({
|
|
40
|
+
telemetry: HEALTH_TELEMETRY_VOLATILE_DETAIL_FIELDS,
|
|
41
|
+
}),
|
|
42
|
+
guarantee: "nonvolatile_snapshot_and_stable_configuration",
|
|
43
|
+
}),
|
|
44
|
+
});
|
|
17
45
|
function isRecord(value) {
|
|
18
46
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
19
47
|
}
|
|
20
|
-
|
|
21
|
-
|
|
48
|
+
function normalizeReadOutputFingerprintValue(value) {
|
|
49
|
+
if (Array.isArray(value)) {
|
|
50
|
+
return value.map(normalizeReadOutputFingerprintValue);
|
|
51
|
+
}
|
|
52
|
+
if (!isRecord(value))
|
|
53
|
+
return value;
|
|
54
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [
|
|
55
|
+
key,
|
|
56
|
+
normalizeReadOutputFingerprintValue(entry),
|
|
57
|
+
]));
|
|
58
|
+
}
|
|
59
|
+
function normalizeReadOutputFingerprintRow(value, policy) {
|
|
60
|
+
if (!isRecord(value))
|
|
61
|
+
return normalizeReadOutputFingerprintValue(value);
|
|
62
|
+
const rowName = typeof value.name === "string" ? value.name : undefined;
|
|
63
|
+
const ignoredDetailFields = rowName !== undefined &&
|
|
64
|
+
Object.hasOwn(policy.ignored_detail_field_names_by_row, rowName)
|
|
65
|
+
? policy.ignored_detail_field_names_by_row[rowName]
|
|
66
|
+
: undefined;
|
|
67
|
+
return Object.fromEntries(Object.entries(value)
|
|
68
|
+
.map(([key, entry]) => {
|
|
69
|
+
if (key !== "details" || !ignoredDetailFields || !isRecord(entry)) {
|
|
70
|
+
return [key, normalizeReadOutputFingerprintValue(entry)];
|
|
71
|
+
}
|
|
72
|
+
return [
|
|
73
|
+
key,
|
|
74
|
+
Object.fromEntries(Object.entries(entry)
|
|
75
|
+
.filter(([detailKey]) => !ignoredDetailFields.includes(detailKey))
|
|
76
|
+
.map(([detailKey, detailValue]) => [
|
|
77
|
+
detailKey,
|
|
78
|
+
normalizeReadOutputFingerprintValue(detailValue),
|
|
79
|
+
])),
|
|
80
|
+
];
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
function normalizeReadOutputFingerprintSnapshot(value, policy) {
|
|
84
|
+
return Array.isArray(value)
|
|
85
|
+
? value.map((row) => normalizeReadOutputFingerprintRow(row, policy))
|
|
86
|
+
: normalizeReadOutputFingerprintRow(value, policy);
|
|
87
|
+
}
|
|
88
|
+
/** Fingerprint the policy-normalized row snapshot so stable evidence changes fail closed. */
|
|
89
|
+
export function readOutputCollectionFingerprint(path, value, command) {
|
|
90
|
+
const policy = command
|
|
91
|
+
? PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES[command]
|
|
92
|
+
: undefined;
|
|
93
|
+
const policyApplies = policy?.paths.includes(path) === true;
|
|
22
94
|
return createHash("sha256")
|
|
23
|
-
.update(stableStringify({
|
|
95
|
+
.update(stableStringify({
|
|
96
|
+
path,
|
|
97
|
+
value: policyApplies
|
|
98
|
+
? normalizeReadOutputFingerprintSnapshot(value, policy)
|
|
99
|
+
: value,
|
|
100
|
+
...(policyApplies
|
|
101
|
+
? { fingerprint_policy_version: policy.version }
|
|
102
|
+
: {}),
|
|
103
|
+
}))
|
|
24
104
|
.digest("base64url")
|
|
25
105
|
.slice(0, 16);
|
|
26
106
|
}
|
|
@@ -105,11 +185,11 @@ export function applyReadOutputContinuation(result, command, cursor) {
|
|
|
105
185
|
if (!collection ||
|
|
106
186
|
totalRows !== cursor.total_rows ||
|
|
107
187
|
cursor.offset > totalRows ||
|
|
108
|
-
readOutputCollectionFingerprint(cursor.path, collection.value) !==
|
|
188
|
+
readOutputCollectionFingerprint(cursor.path, collection.value, command) !==
|
|
109
189
|
cursor.fingerprint) {
|
|
110
190
|
throw new PmCliError("The read-output continuation no longer matches the declared row collection; restart the bounded read.", EXIT_CODE.USAGE, { code: "read_output_cursor_stale" });
|
|
111
191
|
}
|
|
112
192
|
return sliceReadOutputRowCollection(result, cursor.path, cursor.offset);
|
|
113
193
|
}
|
|
114
194
|
//# sourceMappingURL=continuation.js.map
|
|
115
|
-
//# debugId=
|
|
195
|
+
//# debugId=9e63b4b0-09a5-50bf-9f56-5f239c75ffe5
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { resolveReadOutputRecoveryBudget } from "./read-output-budget.js";
|
|
2
2
|
export type { PmReadOutputRecoveryBudget, PmReadOutputRecoveryBudgetInput, } from "./read-output-budget.js";
|
|
3
|
-
export { decodeReadOutputContinuationCursor, encodeReadOutputContinuationCursor, } from "./read-output/continuation.js";
|
|
3
|
+
export { decodeReadOutputContinuationCursor, encodeReadOutputContinuationCursor, PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES, readOutputCollectionFingerprint, } from "./read-output/continuation.js";
|
|
4
|
+
export type { PmReadOutputContinuationFingerprintPolicy } from "./read-output/continuation.js";
|
|
4
5
|
import { type PmReadOutputSessionReceipt, type PmReadOutputSessionState } from "./read-output-session.js";
|
|
5
6
|
/** Stable output dimensions shared by every read surface. */
|
|
6
7
|
export declare const PM_READ_OUTPUT_DIMENSIONS: readonly ["include", "amount", "cost", "encoding"];
|
|
@@ -61,6 +62,8 @@ export interface PmReadOutputSurfaceContract {
|
|
|
61
62
|
precedence: readonly ["canonical", "legacy", "intent", "default"];
|
|
62
63
|
/** Stable policy used before budget compaction selects retained rows. */
|
|
63
64
|
budget_retention_policy: "ordered_prefix" | "verdict_priority";
|
|
65
|
+
/** Exact command-local whole-result modes accepted by `outputInclude`. */
|
|
66
|
+
projection_modes?: readonly string[];
|
|
64
67
|
}
|
|
65
68
|
/** Source that selected an effective output dimension. */
|
|
66
69
|
export type PmReadOutputDimensionSource = "canonical" | "legacy" | "intent" | "default";
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* surface without coupling package authors to command-specific option names.
|
|
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]="d084da05-c967-58f1-afe4-069f09838e6f")}catch(e){}}();
|
|
9
9
|
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
10
10
|
import { PmCliError } from "../core/shared/errors.js";
|
|
11
11
|
import { compactReadOutputToBudget, estimateReadOutputTokens, resolveReadOutputRecoveryBudget, updateReadOutputReceiptEstimate, } from "./read-output-budget.js";
|
|
@@ -13,7 +13,7 @@ export { resolveReadOutputRecoveryBudget } from "./read-output-budget.js";
|
|
|
13
13
|
import { resolvePmCommandOutputBudget } from "./cli-contracts/agent-output-contracts.js";
|
|
14
14
|
import { boundReadOutputRows, countReadOutputRows, mapReadOutputRows, readOutputBudgetCollections, readOutputContinuationRowCollections, readOutputRowPaths, } from "./read-output-rows.js";
|
|
15
15
|
import { applyReadOutputContinuation, decodeReadOutputContinuationCursor, encodeReadOutputContinuationCursor, prioritizeAssuranceAssertions, readOutputCollectionFingerprint, } from "./read-output/continuation.js";
|
|
16
|
-
export { decodeReadOutputContinuationCursor, encodeReadOutputContinuationCursor, } from "./read-output/continuation.js";
|
|
16
|
+
export { decodeReadOutputContinuationCursor, encodeReadOutputContinuationCursor, PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES, readOutputCollectionFingerprint, } from "./read-output/continuation.js";
|
|
17
17
|
import { applyReadOutputSessionReferences, attachReadOutputSessionReceipt, parseReadOutputSession, readOutputSessionRemainingTokens, } from "./read-output-session.js";
|
|
18
18
|
import { decodeQueryCursorEnvelope, encodeQueryCursor } from "./pagination.js";
|
|
19
19
|
/** Stable output dimensions shared by every read surface. */
|
|
@@ -205,6 +205,9 @@ function buildSurfaceContract(command) {
|
|
|
205
205
|
dimensions,
|
|
206
206
|
precedence: READ_OUTPUT_PRECEDENCE,
|
|
207
207
|
budget_retention_policy: command === "assurance" ? "verdict_priority" : "ordered_prefix",
|
|
208
|
+
projection_modes: Object.freeze([
|
|
209
|
+
...readOutputIncludeModeOptions(command).keys(),
|
|
210
|
+
]),
|
|
208
211
|
});
|
|
209
212
|
}
|
|
210
213
|
/** Universal output contract for every built-in read surface. */
|
|
@@ -1092,7 +1095,7 @@ function rebaseBudgetCompactedCursor(projected, originalItemCount, cursorSource,
|
|
|
1092
1095
|
}
|
|
1093
1096
|
return true;
|
|
1094
1097
|
}
|
|
1095
|
-
function captureReadOutputContinuationState(projected, cursor, options) {
|
|
1098
|
+
function captureReadOutputContinuationState(projected, command, cursor, options) {
|
|
1096
1099
|
const collectionsBeforeBudget = new Map(readOutputContinuationRowCollections(projected).map((collection) => {
|
|
1097
1100
|
const rows = Array.isArray(collection.value)
|
|
1098
1101
|
? collection.value.length
|
|
@@ -1106,7 +1109,7 @@ function captureReadOutputContinuationState(projected, cursor, options) {
|
|
|
1106
1109
|
baseOffset: continued ? cursor.offset : 0,
|
|
1107
1110
|
fingerprint: continued
|
|
1108
1111
|
? cursor.fingerprint
|
|
1109
|
-
: readOutputCollectionFingerprint(collection.path, collection.value),
|
|
1112
|
+
: readOutputCollectionFingerprint(collection.path, collection.value, command),
|
|
1110
1113
|
},
|
|
1111
1114
|
];
|
|
1112
1115
|
}));
|
|
@@ -1154,7 +1157,7 @@ export function applyReadOutputDimensions(command, options, result) {
|
|
|
1154
1157
|
const continuationReadyResult = attachValidateDiagnosticRowContract(resolved.command, result);
|
|
1155
1158
|
const bindingBudget = resolveBindingReadOutputBudget(resolved, session);
|
|
1156
1159
|
let projected = projectReadOutputRows(continuationReadyResult, resolved, session, cursor);
|
|
1157
|
-
const continuationState = captureReadOutputContinuationState(projected, cursor, options);
|
|
1160
|
+
const continuationState = captureReadOutputContinuationState(projected, resolved.command, cursor, options);
|
|
1158
1161
|
const receipt = {
|
|
1159
1162
|
contract_version: 1,
|
|
1160
1163
|
command: resolved.command,
|
|
@@ -1207,4 +1210,4 @@ export function resolveReadOutputEncoding(command, options) {
|
|
|
1207
1210
|
: undefined;
|
|
1208
1211
|
}
|
|
1209
1212
|
//# sourceMappingURL=read-output-contracts.js.map
|
|
1210
|
-
//# debugId=
|
|
1213
|
+
//# debugId=d084da05-c967-58f1-afe4-069f09838e6f
|
package/docs/MERGE_SAFETY.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Tracked by [pm-wc1r](../.agents/pm/features/pm-wc1r.toon), with the integrity and concurrency fixes [pm-9q2t](../.agents/pm/issues/pm-9q2t.toon), [pm-cxyv](../.agents/pm/issues/pm-cxyv.toon), [pm-gpo7](../.agents/pm/issues/pm-gpo7.toon), [pm-m3nl](../.agents/pm/issues/pm-m3nl.toon), [pm-wwfd](../.agents/pm/issues/pm-wwfd.toon), and [pm-xdn6](../.agents/pm/issues/pm-xdn6.toon). Fresh-init fence ownership is tracked by [pm-1w3ljt](../.agents/pm/issues/pm-1w3ljt.toon); runtime-cache index governance by [pm-hous](../.agents/pm/issues/pm-hous.toon); local allocation safety by [pm-khdq](../.agents/pm/issues/pm-khdq.toon); fence-coverage completeness and drift detection by [pm-i4fx](../.agents/pm/issues/pm-i4fx.toon); package-defined item coverage by [pm-5rexki](../.agents/pm/issues/pm-5rexki.toon); non-item JSON coverage by [pm-gjicmx](../.agents/pm/issues/pm-gjicmx.toon); portable driver identity by [pm-w91mvg](../.agents/pm/issues/pm-w91mvg.toon); pending receipt validation by [pm-ysqb6n](../.agents/pm/issues/pm-ysqb6n.toon); receipt classification by [pm-jtwsct](../.agents/pm/issues/pm-jtwsct.toon); direction-independent item conflict selection by [pm-dlx7v7](../.agents/pm/issues/pm-dlx7v7.toon); corrected reconciliation guidance by [pm-lwmstb](../.agents/pm/issues/pm-lwmstb.toon); cross-branch id collision safety by [pm-pibw](../.agents/pm/issues/pm-pibw.toon); auditable merge history by [pm-9j2r3b](../.agents/pm/tasks/pm-9j2r3b.toon); durable conflict decisions by [pm-rh98vo](../.agents/pm/issues/pm-rh98vo.toon); continuous conformance by [pm-76dnfg](../.agents/pm/tasks/pm-76dnfg.toon); workspace-wide CI enforcement by [pm-pdr8t1](../.agents/pm/tasks/pm-pdr8t1.toon); post-merge reconciliation by [pm-mfkv92](../.agents/pm/issues/pm-mfkv92.toon); linked-command execution trust by [pm-ed28wi](../.agents/pm/issues/pm-ed28wi.toon); this repository's own adoption by [pm-iwsj](../.agents/pm/chores/pm-iwsj.toon).
|
|
4
4
|
|
|
5
|
+
Lossless receipt health gating is tracked by
|
|
6
|
+
[pm-baksix](../.agents/pm/issues/pm-baksix.toon).
|
|
7
|
+
|
|
5
8
|
pm stores project context as reviewable repository files. Concurrent agents can therefore use ordinary branches and worktrees, but tracker artifacts need semantic merge behavior: raw line merging cannot preserve TOON collection counts, JSON object structure, or append-only history hash chains.
|
|
6
9
|
|
|
7
10
|
## Install the repository merge contract
|
|
@@ -118,11 +121,37 @@ pm merge reconcile --force --message "Accept reviewed merge decisions" --json
|
|
|
118
121
|
```
|
|
119
122
|
|
|
120
123
|
The preview reports every drifted stream and pending receipt without mutation.
|
|
121
|
-
Lossless receipts
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
Lossless receipts do not become discarded-value decisions and reconcile without
|
|
125
|
+
`--force`, but `pm health` reports `merge_receipts_pending:<n>` and remains
|
|
126
|
+
non-green until the apply pass settles them. `pm history-repair` cannot clear
|
|
127
|
+
that receipt finding. When a drifted item also has a pending receipt, the
|
|
128
|
+
`history_drift` remediation map prioritizes `pm merge reconcile --dry-run` only
|
|
129
|
+
when canonical item path, changed-field, and merged-value hash evidence all
|
|
130
|
+
attribute that finding to one or more receipts loaded from the clone-local Git
|
|
131
|
+
evidence store. Every field declared by each receipt must match its current merged-value
|
|
132
|
+
hash, even when only a subset appears in the history reconciliation diff.
|
|
133
|
+
Disjoint valid receipts may collectively cover a multi-field reconciliation;
|
|
134
|
+
the audit and settlement then retain every individually proven receipt id.
|
|
135
|
+
Serialized source claims are ignored. Receipt readers validate the complete
|
|
136
|
+
bounded schema, safe identifiers, filename and item-path identity, timestamps,
|
|
137
|
+
and bounded decision structure before a sidecar enters health or
|
|
138
|
+
reconciliation. Reads use size-preflighted, no-follow regular-file descriptors;
|
|
139
|
+
durable decisions must retain hash-only values. Legacy or durable-only receipts,
|
|
140
|
+
receipts whose declared fields disagree with their hashes, same-item tampering,
|
|
141
|
+
and drift on unrelated items fail closed to the normal `pm history-repair`
|
|
142
|
+
guidance. Health indexes clone-local evidence once by item and reconciliation
|
|
143
|
+
uses the same per-item groups with a fixed receipt-only worker pool, so committed
|
|
144
|
+
sidecars cannot amplify drift scans into unbounded parallel repair work.
|
|
145
|
+
Apply-mode reconciliation repeats the same proof against the exact
|
|
146
|
+
item snapshot used by the audited history rewrite. The audit event and
|
|
147
|
+
settlement include only the individually proven receipt id, so one valid receipt
|
|
148
|
+
cannot authorize an untrusted same-item sibling. Failed or unproven receipts
|
|
149
|
+
remain pending unless the coordinator explicitly reviews and supplies `--force`.
|
|
150
|
+
Receipts with discarded scalar values retain the distinct
|
|
151
|
+
`merge_decisions_unreviewed:<n>` finding, and the apply pass refuses them unless
|
|
152
|
+
the coordinator explicitly supplies `--force` after review. This prevents a
|
|
153
|
+
routine history repair from hiding unfinished reconciliation or silently
|
|
154
|
+
accepting data loss.
|
|
126
155
|
It exits nonzero while either merge-critical validation check is non-green, so
|
|
127
156
|
CI and explicit post-merge hooks cannot approve unresolved receipts or drift.
|
|
128
157
|
The apply pass uses the audited history rewrite boundary to append a
|
|
@@ -16,7 +16,10 @@ selectors are tracked by
|
|
|
16
16
|
and canonical TOON tables are tracked by
|
|
17
17
|
[pm-gjjurs](../.agents/pm/issues/pm-gjjurs.toon) and
|
|
18
18
|
[pm-5y05kq](../.agents/pm/issues/pm-5y05kq.toon). Nested evidence continuation
|
|
19
|
-
is tracked by [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon)
|
|
19
|
+
is tracked by [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon) and
|
|
20
|
+
[pm-oahhyc](../.agents/pm/issues/pm-oahhyc.toon). Exact command-local
|
|
21
|
+
projection discovery is tracked by
|
|
22
|
+
[pm-q4isdq](../.agents/pm/issues/pm-q4isdq.toon).
|
|
20
23
|
|
|
21
24
|
## Agent Quick Context
|
|
22
25
|
|
|
@@ -112,6 +115,15 @@ machine-iterable without a command-specific selector. `fields` is always explici
|
|
|
112
115
|
shape. NDJSON event streams do not carry an envelope and therefore do not
|
|
113
116
|
publish a row contract.
|
|
114
117
|
|
|
118
|
+
Projection mode discovery is command-local even though the compatibility
|
|
119
|
+
degradation ladder is global. Read
|
|
120
|
+
`output_projection_contracts.commands` from a command-scoped contracts call or
|
|
121
|
+
the full contracts matrix before selecting a whole-result mode. The
|
|
122
|
+
contract labels the global ladder `union_not_per_command`, so clients cannot
|
|
123
|
+
infer that `list` accepts `summary` or that `health` accepts `compact`.
|
|
124
|
+
`PM_READ_OUTPUT_SURFACE_CONTRACTS[].projection_modes` provides the identical
|
|
125
|
+
canonical matrix to SDK and package consumers.
|
|
126
|
+
|
|
115
127
|
SDK and package authors can import `PM_READ_ROW_CONTRACTS`,
|
|
116
128
|
`PM_READ_ROW_JQ_SELECTOR`, and `resolveReadRowContract` from
|
|
117
129
|
`@unbrained/pm-cli/sdk`. Existing package declarations are preserved only
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Universal Read Output Contracts
|
|
2
2
|
|
|
3
|
-
Tracker references: [pm-hb7ug8](../.agents/pm/features/pm-hb7ug8.toon), [pm-cxr0jb](../.agents/pm/features/pm-cxr0jb.toon), [pm-hid9g1](../.agents/pm/features/pm-hid9g1.toon), [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon), [pm-5t33or](../.agents/pm/features/pm-5t33or.toon), [pm-srns](../.agents/pm/issues/pm-srns.toon), [pm-sb0tns](../.agents/pm/issues/pm-sb0tns.toon), [pm-gjjurs](../.agents/pm/issues/pm-gjjurs.toon), [pm-eugaqy](../.agents/pm/issues/pm-eugaqy.toon), [pm-jt8aa2](../.agents/pm/issues/pm-jt8aa2.toon), [pm-kyjdne](../.agents/pm/issues/pm-kyjdne.toon), [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon), [pm-e5gl05](../.agents/pm/issues/pm-e5gl05.toon), [pm-cha95z](../.agents/pm/tasks/pm-cha95z.toon), [pm-2qvq7a](../.agents/pm/issues/pm-2qvq7a.toon), and [pm-xam9bt](../.agents/pm/issues/pm-xam9bt.toon).
|
|
3
|
+
Tracker references: [pm-hb7ug8](../.agents/pm/features/pm-hb7ug8.toon), [pm-cxr0jb](../.agents/pm/features/pm-cxr0jb.toon), [pm-hid9g1](../.agents/pm/features/pm-hid9g1.toon), [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon), [pm-5t33or](../.agents/pm/features/pm-5t33or.toon), [pm-srns](../.agents/pm/issues/pm-srns.toon), [pm-sb0tns](../.agents/pm/issues/pm-sb0tns.toon), [pm-gjjurs](../.agents/pm/issues/pm-gjjurs.toon), [pm-eugaqy](../.agents/pm/issues/pm-eugaqy.toon), [pm-jt8aa2](../.agents/pm/issues/pm-jt8aa2.toon), [pm-kyjdne](../.agents/pm/issues/pm-kyjdne.toon), [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon), [pm-oahhyc](../.agents/pm/issues/pm-oahhyc.toon), [pm-q4isdq](../.agents/pm/issues/pm-q4isdq.toon), [pm-e5gl05](../.agents/pm/issues/pm-e5gl05.toon), [pm-cha95z](../.agents/pm/tasks/pm-cha95z.toon), [pm-2qvq7a](../.agents/pm/issues/pm-2qvq7a.toon), and [pm-xam9bt](../.agents/pm/issues/pm-xam9bt.toon).
|
|
4
4
|
|
|
5
5
|
## Agent Quick Context
|
|
6
6
|
|
|
@@ -60,6 +60,17 @@ removing spelling receipts and volatile run metadata. A selector that matches
|
|
|
60
60
|
neither a declared mode nor any field on any returned row is refused with the
|
|
61
61
|
legal domain, rather than returning rows with every field removed.
|
|
62
62
|
|
|
63
|
+
Runtime discovery publishes the same exact vocabulary before invocation.
|
|
64
|
+
`pm contracts --command <command> --summary` returns
|
|
65
|
+
`output_projection_contracts.commands`, while
|
|
66
|
+
`output_projection_contracts.global_ladder_scope: "union_not_per_command"`
|
|
67
|
+
explicitly marks `output_policy.degradation_ladder` as a cross-command union,
|
|
68
|
+
not a promise that every member is accepted by the selected command. For
|
|
69
|
+
example, `list` declares `brief`, `compact`, and `full`; `health` declares
|
|
70
|
+
`brief`, `full`, and `summary`. The full `read_output_dimensions` matrix also
|
|
71
|
+
includes `projection_modes` for every canonical read surface, including an
|
|
72
|
+
explicit empty array when a surface has no whole-result modes.
|
|
73
|
+
|
|
63
74
|
## Cross-Call Context Sessions
|
|
64
75
|
|
|
65
76
|
`--output-session <json>` / `outputSession` composes the four per-call
|
|
@@ -164,6 +175,18 @@ an unbounded multi-megabyte response;
|
|
|
164
175
|
`recovery_budget_multiplier: 1` declares that each next page retains the same
|
|
165
176
|
useful-result ceiling.
|
|
166
177
|
|
|
178
|
+
Health continuation fingerprints use a versioned nonvolatile-snapshot policy
|
|
179
|
+
for the `checks` row. Command-lifecycle telemetry may refresh timestamps, queue
|
|
180
|
+
counters, and pending spans between pages, so the policy excludes only those
|
|
181
|
+
explicit direct fields from the `telemetry` row's `details`. The row identity,
|
|
182
|
+
verdict, enabled state, capture level, endpoint, environment overrides, probe
|
|
183
|
+
result, and failure errors remain fingerprinted. Every other health check also
|
|
184
|
+
remains fully fingerprinted; changing storage, integrity, history, or another
|
|
185
|
+
stable check fails closed. `PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES`
|
|
186
|
+
publishes the exact ignored detail fields per dynamic row. Other commands still
|
|
187
|
+
fingerprint every field, including fields with the same spelling, and any
|
|
188
|
+
policy-version change fails closed against an older cursor.
|
|
189
|
+
|
|
167
190
|
When compaction affects a nested collection that is not declared resumable,
|
|
168
191
|
the recovery budget is derived from the larger of the binding ceiling plus one
|
|
169
192
|
and the measured pre-compaction result. The SDK adds a 25% envelope margin and
|
|
@@ -221,7 +244,7 @@ const result = await pm.list({
|
|
|
221
244
|
});
|
|
222
245
|
```
|
|
223
246
|
|
|
224
|
-
Package authors should use the exported read-output contracts instead of inventing package-local limit or projection vocabularies. `PM_READ_OUTPUT_SURFACE_CONTRACTS` is the machine-readable matrix and `resolveReadOutputDimensions` plus `applyReadOutputDimensions` are the shared execution primitives.
|
|
247
|
+
Package authors should use the exported read-output contracts instead of inventing package-local limit or projection vocabularies. `PM_READ_OUTPUT_SURFACE_CONTRACTS` is the machine-readable matrix, `PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES` declares stable-snapshot exceptions, and `resolveReadOutputDimensions` plus `applyReadOutputDimensions` are the shared execution primitives.
|
|
225
248
|
|
|
226
249
|
## Drift Gates
|
|
227
250
|
|
|
@@ -4,12 +4,12 @@ Tracker: `pm-f05lsg`.
|
|
|
4
4
|
|
|
5
5
|
Every catalog code is listed. An `uncovered` row is an explicit closure obligation, never an omission or implied approval.
|
|
6
6
|
|
|
7
|
-
- Catalog error codes:
|
|
7
|
+
- Catalog error codes: 342
|
|
8
8
|
- Executable error codes: 16
|
|
9
9
|
- Executable-code ratchet floor: 16
|
|
10
10
|
- Required executable canonical codes: `bulk_ids_input_empty`, `bulk_ids_input_missing_path`, `bulk_ids_input_unreadable`, `invalid_argument_value`, `missing_lifecycle_target`, `missing_required_argument`, `projection_options_mutually_exclusive`, `tracker_not_initialized`, `tracker_root_missing`, `tracker_root_not_directory`, `tracker_root_unreadable`, `unknown_context_intent`, `unknown_field_projection`, `unknown_option`, `unknown_subcommand`
|
|
11
|
-
- Uncovered error codes:
|
|
12
|
-
- Coverage fraction: 0.
|
|
11
|
+
- Uncovered error codes: 326
|
|
12
|
+
- Coverage fraction: 0.046784
|
|
13
13
|
- Closed-domain probes: 18
|
|
14
14
|
- Grammar probes: 95
|
|
15
15
|
|
|
@@ -111,6 +111,7 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
|
|
|
111
111
|
| `history_author_acknowledge_target_unreadable` | `history_author_acknowledge_target_unreadable` | uncovered | none | 0 |
|
|
112
112
|
| `history_drift_chain_mismatch` | `history_drift_chain_mismatch` | uncovered | none | 0 |
|
|
113
113
|
| `history_drift_hash_mismatch` | `history_drift_hash_mismatch` | uncovered | none | 0 |
|
|
114
|
+
| `history_drift_merge_receipt` | `history_drift_merge_receipt` | uncovered | none | 0 |
|
|
114
115
|
| `history_drift_missing_stream` | `history_drift_missing_stream` | uncovered | none | 0 |
|
|
115
116
|
| `history_drift_unreadable_stream` | `history_drift_unreadable_stream` | uncovered | none | 0 |
|
|
116
117
|
| `history_merge_conflict_markers_detected` | `merge_conflict_markers_detected` | uncovered | none | 0 |
|
|
@@ -180,7 +181,10 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
|
|
|
180
181
|
| `merge_conflict_markers_detected` | `merge_conflict_markers_detected` | uncovered | none | 0 |
|
|
181
182
|
| `merge_decisions_unreviewed` | `merge_decisions_unreviewed` | uncovered | none | 0 |
|
|
182
183
|
| `merge_git_config_unwritable` | `merge_git_config_unwritable` | uncovered | none | 0 |
|
|
184
|
+
| `merge_receipt_evidence_invalid` | `merge_receipt_evidence_invalid` | uncovered | none | 0 |
|
|
185
|
+
| `merge_receipts_pending` | `merge_receipts_pending` | uncovered | none | 0 |
|
|
183
186
|
| `merge_reconcile_discards_require_acceptance` | `merge_reconcile_discards_require_acceptance` | uncovered | none | 0 |
|
|
187
|
+
| `merge_reconcile_receipt_evidence_untrusted` | `merge_reconcile_receipt_evidence_untrusted` | uncovered | none | 0 |
|
|
184
188
|
| `merge_root_not_found` | `merge_root_not_found` | uncovered | none | 0 |
|
|
185
189
|
| `missing_allowed_values` | `missing_allowed_values` | uncovered | none | 0 |
|
|
186
190
|
| `missing_budget` | `missing_budget` | uncovered | none | 0 |
|
package/marketplace.json
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Official marketplace for pm CLI — native git-based project management for Claude Code and AI coding agents.",
|
|
9
|
-
"version": "2026.8.
|
|
9
|
+
"version": "2026.8.25"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
13
13
|
"name": "pm-claude",
|
|
14
14
|
"source": "./plugins/pm-claude",
|
|
15
15
|
"description": "Native pm CLI integration for Claude Code — 28 MCP tools, 5 workflow skills, 14 slash commands, 4 subagents, hybrid TUI task tracking, session context injection, and coordination subagents for git-based project management without leaving Claude Code.",
|
|
16
|
-
"version": "2026.8.
|
|
16
|
+
"version": "2026.8.25",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "unbrained",
|
|
19
19
|
"url": "https://github.com/unbraind/pm-cli"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unbrained/pm-digital-twin",
|
|
3
|
-
"version": "2026.8.
|
|
3
|
+
"version": "2026.8.25",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Beyond-PM exemplar: a temporal production-facility digital twin built entirely on public pm SDK and extension primitives.",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pm-claude",
|
|
3
3
|
"description": "Native pm CLI integration for Claude Code — 28 MCP tools, 5 workflow skills, 14 slash commands, 4 subagents (coordinator, delivery-chain, triage, verification), hybrid TUI task tracking (pm as persistent store + Claude Code task panel as live view), session context injection, and full git-based project management without leaving Claude Code.",
|
|
4
|
-
"version": "2026.8.
|
|
4
|
+
"version": "2026.8.25",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "unbrained",
|
|
7
7
|
"url": "https://github.com/unbraind/pm-cli"
|