@unbrained/pm-cli 2026.8.30 → 2026.9.1

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.
Files changed (176) hide show
  1. package/.agents/skills/HARNESS_COMPATIBILITY.md +1 -1
  2. package/.agents/skills/README.md +1 -1
  3. package/.agents/skills/pm-developer/SKILL.md +1 -1
  4. package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +2 -2
  5. package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +1 -1
  6. package/.agents/skills/pm-developer/references/TOKEN_BUDGETS.md +1 -1
  7. package/.agents/skills/pm-extensions/SKILL.md +2 -2
  8. package/.agents/skills/pm-extensions/references/AUTHORING.md +1 -1
  9. package/.agents/skills/pm-extensions/references/LIFECYCLE.md +1 -1
  10. package/.agents/skills/pm-sdk/SKILL.md +1 -1
  11. package/.agents/skills/pm-user/SKILL.md +2 -2
  12. package/.agents/skills/pm-user/references/WORKFLOWS.md +2 -2
  13. package/.claude-plugin/marketplace.json +2 -2
  14. package/AGENTS.md +16 -14
  15. package/CHANGELOG.md +41 -6
  16. package/README.md +3 -3
  17. package/dist/cli/commands/merge.d.ts +1 -1
  18. package/dist/cli/commands/merge.js +3 -3
  19. package/dist/cli/register-list-query.js +32 -17
  20. package/dist/cli/register-mutation.js +8 -5
  21. package/dist/cli/register-operations.d.ts +2 -0
  22. package/dist/cli/register-operations.js +20 -9
  23. package/dist/cli-bundle/bundle-manifest.json +144 -144
  24. package/dist/cli-bundle/chunks/{chunk-CMIEDWAY.js → chunk-2MC2LCXZ.js} +41 -41
  25. package/dist/cli-bundle/chunks/{chunk-WS2GJQVG.js → chunk-3WICXLVT.js} +2 -2
  26. package/dist/cli-bundle/chunks/{chunk-7SKMLSMX.js → chunk-6XIIGE7U.js} +2 -2
  27. package/dist/cli-bundle/chunks/chunk-ALKKAUFN.js +35 -0
  28. package/dist/cli-bundle/chunks/{chunk-MTTKAUBX.js → chunk-DTGWEL23.js} +2 -2
  29. package/dist/cli-bundle/chunks/chunk-GOACULJW.js +13 -0
  30. package/dist/cli-bundle/chunks/chunk-NOPL37X4.js +205 -0
  31. package/dist/cli-bundle/chunks/{chunk-2UETTHY6.js → chunk-TAG4VC22.js} +30 -30
  32. package/dist/cli-bundle/chunks/{chunk-3TEF3HM5.js → chunk-U45JXJCC.js} +2 -2
  33. package/dist/cli-bundle/chunks/{chunk-TGNAA66W.js → chunk-X4RCGLTX.js} +2 -2
  34. package/dist/cli-bundle/chunks/{chunk-2MKLQL2E.js → chunk-Y7VOMSZT.js} +2 -2
  35. package/dist/cli-bundle/chunks/{register-list-query-OMKJ5ONN.js → register-list-query-XYNX4ASQ.js} +11 -11
  36. package/dist/cli-bundle/chunks/register-mutation-2MVLRS3J.js +20 -0
  37. package/dist/cli-bundle/chunks/register-operations-WCIDXBU3.js +2 -0
  38. package/dist/cli-bundle/chunks/{register-setup-GLQ5SYV3.js → register-setup-KVNC5KPL.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/{chunk-HVQ22RC4.js → chunk-2FEZ5SKM.js} +2 -2
  40. package/dist/cli-bundle/focused-chunks/{chunk-Y3JJXRVK.js → chunk-4O4CJAR6.js} +5 -5
  41. package/dist/cli-bundle/focused-chunks/chunk-7VATS5QY.js +16 -0
  42. package/dist/cli-bundle/focused-chunks/{chunk-LYFWQMVC.js → chunk-BEVHCEWG.js} +2 -2
  43. package/dist/cli-bundle/focused-chunks/{chunk-TDK3OCX3.js → chunk-FWPLDEXF.js} +2 -2
  44. package/dist/cli-bundle/focused-chunks/chunk-JEFKLWMM.js +2 -0
  45. package/dist/cli-bundle/focused-chunks/{chunk-JZYPPMXF.js → chunk-KB5OFSFD.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/{chunk-73EDXGYE.js → chunk-MKHG3T76.js} +2 -2
  47. package/dist/cli-bundle/focused-chunks/{chunk-3AVAWVZA.js → chunk-PF3E6Q36.js} +2 -2
  48. package/dist/cli-bundle/focused-chunks/{chunk-AD6ULRAF.js → chunk-QDFJIRKN.js} +4 -4
  49. package/dist/cli-bundle/focused-chunks/{chunk-RKOKG43G.js → chunk-RMRCQPWU.js} +2 -2
  50. package/dist/cli-bundle/focused-chunks/{chunk-XXOWRJZ5.js → chunk-S4U5CN5Q.js} +2 -2
  51. package/dist/cli-bundle/focused-chunks/{chunk-THEPQMLX.js → chunk-SVXJYD6G.js} +2 -2
  52. package/dist/cli-bundle/focused-chunks/chunk-T2LXXSOD.js +158 -0
  53. package/dist/cli-bundle/focused-chunks/chunk-Y6JJIX6I.js +51 -0
  54. package/dist/cli-bundle/main.js +2 -2
  55. package/dist/cli-bundle/sdk-authoring.js +1 -1
  56. package/dist/cli-bundle/sdk-contracts.js +1 -1
  57. package/dist/cli-bundle/sdk-core.js +27 -27
  58. package/dist/cli-bundle/sdk-governance.js +1 -1
  59. package/dist/cli-bundle/sdk-graph.js +1 -1
  60. package/dist/cli-bundle/sdk-merge.js +33 -33
  61. package/dist/cli-bundle/sdk-query.js +1 -1
  62. package/dist/cli-bundle/sdk-runtime.js +1 -1
  63. package/dist/cli-bundle/sdk-testing.js +1 -1
  64. package/dist/cli-bundle/sdk.js +10 -10
  65. package/dist/core/history/drift-scan.js +6 -6
  66. package/dist/core/history/history.d.ts +6 -0
  67. package/dist/core/history/history.js +47 -5
  68. package/dist/core/history/replay.d.ts +12 -1
  69. package/dist/core/history/replay.js +60 -39
  70. package/dist/core/schema/runtime-schema.d.ts +4 -0
  71. package/dist/core/schema/runtime-schema.js +60 -48
  72. package/dist/core/schema/status-defs-file.js +5 -2
  73. package/dist/mcp/legacy-adapter.d.ts +11 -2
  74. package/dist/mcp/legacy-adapter.js +26 -12
  75. package/dist/mcp/server.d.ts +2 -2
  76. package/dist/mcp/server.js +78 -15
  77. package/dist/mcp/tool-definitions.js +56 -2
  78. package/dist/sdk/agent-capability-contracts.js +4 -2
  79. package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
  80. package/dist/sdk/cli-contracts/flag-contracts.js +6 -2
  81. package/dist/sdk/cli-contracts/grammar-contracts.d.ts +1 -1
  82. package/dist/sdk/cli-contracts/grammar-contracts.js +12 -2
  83. package/dist/sdk/cli-contracts/runtime-contracts.js +3 -2
  84. package/dist/sdk/cli-contracts/tool-schema.js +11 -3
  85. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +14 -2
  86. package/dist/sdk/governance/health.js +17 -6
  87. package/dist/sdk/governance/status-role-diagnostics.d.ts +27 -0
  88. package/dist/sdk/governance/status-role-diagnostics.js +36 -0
  89. package/dist/sdk/governance/validate-normalization.d.ts +6 -0
  90. package/dist/sdk/governance/validate-normalization.js +37 -0
  91. package/dist/sdk/governance/validate.d.ts +1 -1
  92. package/dist/sdk/governance/validate.js +20 -35
  93. package/dist/sdk/governance/workspace-position.d.ts +69 -0
  94. package/dist/sdk/governance/workspace-position.js +164 -0
  95. package/dist/sdk/governance.d.ts +2 -0
  96. package/dist/sdk/governance.js +4 -2
  97. package/dist/sdk/history-read.js +14 -6
  98. package/dist/sdk/history-repair.js +17 -10
  99. package/dist/sdk/index.d.ts +2 -1
  100. package/dist/sdk/index.js +4 -3
  101. package/dist/sdk/init-agent-guidance.js +4 -4
  102. package/dist/sdk/lifecycle/update.js +23 -10
  103. package/dist/sdk/mcp/discovery.d.ts +152 -0
  104. package/dist/sdk/mcp/discovery.js +495 -0
  105. package/dist/sdk/mcp/protocol.d.ts +10 -2
  106. package/dist/sdk/mcp/protocol.js +15 -4
  107. package/dist/sdk/merge/index.d.ts +1 -1
  108. package/dist/sdk/merge/index.js +3 -3
  109. package/dist/sdk/merge/receipts.d.ts +27 -1
  110. package/dist/sdk/merge/receipts.js +27 -8
  111. package/dist/sdk/merge/three-way.d.ts +3 -1
  112. package/dist/sdk/merge/three-way.js +9 -7
  113. package/dist/sdk/query/context.js +11 -14
  114. package/dist/sdk/query/list.d.ts +2 -0
  115. package/dist/sdk/query/list.js +33 -12
  116. package/dist/sdk/runtime-extended-actions.js +10 -6
  117. package/dist/sdk/schema.js +12 -2
  118. package/dist/sdk/test/execution.d.ts +15 -0
  119. package/dist/sdk/test/execution.js +35 -27
  120. package/docs/AGENT_GUIDE.md +12 -4
  121. package/docs/AGENT_PROVENANCE_ADR.md +1 -1
  122. package/docs/AGENT_RUNTIME_PRIMITIVES.md +2 -2
  123. package/docs/ARCHITECTURE.md +5 -0
  124. package/docs/CLAUDE_CODE_PLUGIN.md +5 -5
  125. package/docs/COMMANDS.md +12 -12
  126. package/docs/CONFIGURATION.md +1 -1
  127. package/docs/CONTEXT_RECOVERY_PRIMITIVES.md +14 -5
  128. package/docs/DEFECT_RECURRENCE.md +2 -0
  129. package/docs/MCP_2026_07_28.md +33 -9
  130. package/docs/MCP_2026_07_28_CONFORMANCE.md +1 -0
  131. package/docs/MCP_CAPABILITY_SURFACES.md +7 -1
  132. package/docs/MCP_REMOTE_TRANSPORT_SECURITY.md +15 -3
  133. package/docs/MERGE_SAFETY.md +30 -2
  134. package/docs/ONBOARDING.md +1 -1
  135. package/docs/OUTPUT_TOKEN_ACCOUNTING.md +5 -3
  136. package/docs/PROGRESSIVE_TOOL_DISCOVERY.md +42 -0
  137. package/docs/README.md +3 -1
  138. package/docs/READ_OUTPUT_CONTRACTS.md +1 -1
  139. package/docs/RECURRENCE_RECOVERY_CONTRACTS.md +1 -1
  140. package/docs/SDK.md +3 -3
  141. package/docs/TESTING.md +23 -14
  142. package/docs/WORKSPACE_POSITION_AND_LIFECYCLE.md +113 -0
  143. package/docs/agent-task-token-baseline.json +157 -3
  144. package/docs/agent-task-transcripts.json +143 -0
  145. package/docs/examples/policy-restricted-extension/README.md +2 -2
  146. package/docs/examples/starter-extension/README.md +1 -1
  147. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +4 -3
  148. package/docs/performance/cli-transport-overhead.md +8 -6
  149. package/marketplace.json +2 -2
  150. package/package.json +4 -4
  151. package/packages/pm-beads/package.json +1 -1
  152. package/packages/pm-calendar/package.json +1 -1
  153. package/packages/pm-command-kit/package.json +1 -1
  154. package/packages/pm-digital-twin/package.json +1 -1
  155. package/packages/pm-governance-audit/package.json +1 -1
  156. package/packages/pm-guide-shell/package.json +1 -1
  157. package/packages/pm-kanban/package.json +1 -1
  158. package/packages/pm-lifecycle-hooks/package.json +1 -1
  159. package/packages/pm-linked-test-adapters/package.json +1 -1
  160. package/packages/pm-search-advanced/package.json +1 -1
  161. package/packages/pm-templates/package.json +1 -1
  162. package/packages/pm-todos/package.json +1 -1
  163. package/packages/pm-vcs/package.json +1 -1
  164. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  165. package/plugins/pm-claude/README.md +4 -3
  166. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  167. package/sdk/public-surface.json +314 -10
  168. package/dist/cli-bundle/chunks/chunk-7X6OZEIV.js +0 -34
  169. package/dist/cli-bundle/chunks/chunk-GNWPTEBW.js +0 -205
  170. package/dist/cli-bundle/chunks/chunk-N6OR6FAR.js +0 -13
  171. package/dist/cli-bundle/chunks/register-mutation-QBSNCOY3.js +0 -20
  172. package/dist/cli-bundle/chunks/register-operations-UC77FQZC.js +0 -2
  173. package/dist/cli-bundle/focused-chunks/chunk-3UMBF26I.js +0 -158
  174. package/dist/cli-bundle/focused-chunks/chunk-AXZ5AJAF.js +0 -50
  175. package/dist/cli-bundle/focused-chunks/chunk-G6PATS5E.js +0 -16
  176. package/dist/cli-bundle/focused-chunks/chunk-LLNTHF5X.js +0 -2
@@ -0,0 +1,495 @@
1
+ /**
2
+ * @module sdk/mcp/discovery
3
+ *
4
+ * Provides the deterministic, token-bounded progressive tool discovery
5
+ * contract shared by MCP servers, embedded hosts, and agent integrations.
6
+ */
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]="4853ebbf-f28a-55f1-b306-aa75cb9355ae")}catch(e){}}();
9
+ import { createHash, createHmac, randomBytes, timingSafeEqual, } from "node:crypto";
10
+ import { PM_COMMAND_CAPABILITY_CONTRACTS, PM_MCP_TOOL_COMMAND_CONTRACTS, resolvePmCommandCapabilityFamily, resolvePmCommandVisibilityTier, } from "../agent-capability-contracts.js";
11
+ import { PmCliError } from "../runtime-primitives.js";
12
+ /** Namespaced MCP extension that opts a client into progressive tool discovery. */
13
+ export const PM_MCP_PROGRESSIVE_DISCOVERY_EXTENSION = "dev.unbrained.pm/progressive-tool-discovery";
14
+ /** Versioned server capability advertised for progressive tool discovery. */
15
+ export const PM_MCP_PROGRESSIVE_DISCOVERY_SERVER_CAPABILITY = Object.freeze({
16
+ version: 1,
17
+ discoveryTool: "pm_discover",
18
+ canonicalResult: "structuredContent.result",
19
+ compatibilityText: "pointer",
20
+ });
21
+ /** Small stable tool catalog returned to clients that negotiate the extension. */
22
+ export const PM_MCP_ENTRY_TOOL_NAMES = Object.freeze([
23
+ "pm_discover",
24
+ "pm_next",
25
+ "pm_context",
26
+ "pm_search",
27
+ "pm_get",
28
+ ]);
29
+ const DISCOVERY_WEIGHTS = Object.freeze({
30
+ lexical: 0.4,
31
+ semantic: 0.2,
32
+ graph: 0.1,
33
+ permission: 0.15,
34
+ freshness: 0.05,
35
+ usage: 0.1,
36
+ });
37
+ const DISCOVERY_CACHE_INVALIDATIONS = Object.freeze([
38
+ "profile_changed",
39
+ "tool_contract_changed",
40
+ "workspace_extension_changed",
41
+ "authorization_changed",
42
+ "ranking_signal_changed",
43
+ "cursor_integrity_key_rotated",
44
+ ]);
45
+ const TIER_RANK = {
46
+ core: 0,
47
+ standard: 1,
48
+ full: 2,
49
+ internal: 3,
50
+ };
51
+ const SELECTABLE_TIERS = Object.freeze([
52
+ "core",
53
+ "standard",
54
+ "full",
55
+ ]);
56
+ const MCP_TOOL_PROFILES = new Set([
57
+ "core",
58
+ "standard",
59
+ "full",
60
+ "custom",
61
+ ]);
62
+ const CAPABILITY_FAMILIES = new Set(PM_COMMAND_CAPABILITY_CONTRACTS.map(({ family }) => family));
63
+ const PROCESS_CURSOR_INTEGRITY_KEY = randomBytes(32);
64
+ /** Validate a discovery string with the Unicode code-point semantics used by JSON Schema. */
65
+ function boundedDiscoveryString(value, field) {
66
+ if (typeof value !== "string") {
67
+ throw new PmCliError(`pm tool discovery ${field} must be a string of at most 4096 Unicode characters.`, 64);
68
+ }
69
+ const iterator = value[Symbol.iterator]();
70
+ let count = 0;
71
+ for (let next = iterator.next(); !next.done; next = iterator.next()) {
72
+ count += 1;
73
+ if (count > 4_096) {
74
+ throw new PmCliError(`pm tool discovery ${field} must be a string of at most 4096 Unicode characters.`, 64);
75
+ }
76
+ }
77
+ return value;
78
+ }
79
+ function discoveryLimit(value) {
80
+ if (!Number.isInteger(value) || Number(value) < 1 || Number(value) > 100) {
81
+ throw new PmCliError("pm tool discovery limit must be from 1 through 100.", 64);
82
+ }
83
+ return Number(value);
84
+ }
85
+ function discoveryOutputBudget(value) {
86
+ if (value !== "unbounded" &&
87
+ (!Number.isInteger(value) || Number(value) < 128)) {
88
+ throw new PmCliError("pm tool discovery outputBudget must be unbounded or an integer of at least 128.", 64);
89
+ }
90
+ return value === "unbounded" ? value : Number(value);
91
+ }
92
+ function discoveryIncludeSchema(value) {
93
+ if (value !== undefined && typeof value !== "boolean") {
94
+ throw new PmCliError("pm tool discovery includeSchema must be a boolean.", 64);
95
+ }
96
+ return value === true;
97
+ }
98
+ function validateDiscoveryOptionsContainer(value) {
99
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
100
+ throw new PmCliError("pm tool discovery options must be an object.", 64);
101
+ }
102
+ }
103
+ /** Reject malformed candidate catalogs supplied by untyped SDK consumers. */
104
+ function validateDiscoveryCandidates(candidates) {
105
+ if (!Array.isArray(candidates)) {
106
+ throw new PmCliError("pm tool discovery candidates must be an array.", 64);
107
+ }
108
+ for (const [index, candidate] of candidates.entries()) {
109
+ if (candidate === null ||
110
+ typeof candidate !== "object" ||
111
+ Array.isArray(candidate)) {
112
+ throw new PmCliError(`pm tool discovery candidate ${index} must be an object.`, 64);
113
+ }
114
+ if (typeof candidate.name !== "string" ||
115
+ candidate.name.trim().length === 0) {
116
+ throw new PmCliError(`pm tool discovery candidate ${index} name must be a non-empty string.`, 64);
117
+ }
118
+ if (typeof candidate.description !== "string" ||
119
+ candidate.description.trim().length === 0) {
120
+ throw new PmCliError(`pm tool discovery candidate ${index} description must be a non-empty string.`, 64);
121
+ }
122
+ if (candidate.inputSchema === null ||
123
+ typeof candidate.inputSchema !== "object" ||
124
+ Array.isArray(candidate.inputSchema)) {
125
+ throw new PmCliError(`pm tool discovery candidate ${index} inputSchema must be an object.`, 64);
126
+ }
127
+ if (candidate.authorized !== undefined &&
128
+ typeof candidate.authorized !== "boolean") {
129
+ throw new PmCliError(`pm tool discovery candidate ${index} authorized must be a boolean.`, 64);
130
+ }
131
+ }
132
+ }
133
+ /** Parse untrusted adapter input without discarding malformed discovery values. */
134
+ export function parsePmToolDiscoveryOptions(input) {
135
+ validateDiscoveryOptionsContainer(input);
136
+ if (input.family !== undefined &&
137
+ (typeof input.family !== "string" || !CAPABILITY_FAMILIES.has(input.family))) {
138
+ throw new PmCliError("pm tool discovery family must be a declared capability family.", 64);
139
+ }
140
+ if (input.tier !== undefined &&
141
+ (typeof input.tier !== "string" || !SELECTABLE_TIERS.includes(input.tier))) {
142
+ throw new PmCliError("pm tool discovery tier must be core, standard, or full.", 64);
143
+ }
144
+ return {
145
+ ...(input.query !== undefined
146
+ ? { query: boundedDiscoveryString(input.query, "query") }
147
+ : {}),
148
+ ...(input.family !== undefined
149
+ ? { family: input.family }
150
+ : {}),
151
+ ...(input.tier !== undefined
152
+ ? {
153
+ tier: input.tier,
154
+ }
155
+ : {}),
156
+ ...(input.limit !== undefined
157
+ ? { limit: discoveryLimit(input.limit) }
158
+ : {}),
159
+ ...(input.cursor !== undefined
160
+ ? { cursor: boundedDiscoveryString(input.cursor, "cursor") }
161
+ : {}),
162
+ ...(input.includeSchema !== undefined
163
+ ? { includeSchema: discoveryIncludeSchema(input.includeSchema) }
164
+ : {}),
165
+ ...(input.outputBudget !== undefined
166
+ ? { outputBudget: discoveryOutputBudget(input.outputBudget) }
167
+ : {}),
168
+ };
169
+ }
170
+ function normalizedUnitInterval(value) {
171
+ if (value === undefined || !Number.isFinite(value))
172
+ return 0;
173
+ return Math.min(1, Math.max(0, value));
174
+ }
175
+ function normalizedSearchTokens(value) {
176
+ return [...new Set(value.toLowerCase().match(/[a-z0-9]+/gu) ?? [])].sort();
177
+ }
178
+ function lexicalRelevance(query, text) {
179
+ const queryTokens = normalizedSearchTokens(query);
180
+ if (queryTokens.length === 0)
181
+ return 0;
182
+ const targetTokens = new Set(normalizedSearchTokens(text));
183
+ const matched = queryTokens.filter((token) => targetTokens.has(token)).length;
184
+ const exactBonus = text.toLowerCase().includes(query.toLowerCase())
185
+ ? 0.25
186
+ : 0;
187
+ return Math.min(1, matched / queryTokens.length + exactBonus);
188
+ }
189
+ function semanticRelevance(query, text) {
190
+ const queryTokens = normalizedSearchTokens(query);
191
+ if (queryTokens.length === 0)
192
+ return 0;
193
+ const target = text.toLowerCase();
194
+ const targetTokens = normalizedSearchTokens(text);
195
+ const related = queryTokens.filter((queryToken) => targetTokens.some((targetToken) => targetToken.startsWith(queryToken) ||
196
+ queryToken.startsWith(targetToken))).length;
197
+ const phraseBonus = target.includes(query.toLowerCase()) ? 0.2 : 0;
198
+ return Math.min(1, related / queryTokens.length + phraseBonus);
199
+ }
200
+ function hashDiscoveryValue(value) {
201
+ return createHash("sha256")
202
+ .update(JSON.stringify(value))
203
+ .digest("hex")
204
+ .slice(0, 24);
205
+ }
206
+ function cursorSignature(fingerprint, offset, integrityKey) {
207
+ return createHmac("sha256", integrityKey)
208
+ .update(JSON.stringify({ version: 1, fingerprint, offset }))
209
+ .digest("base64url");
210
+ }
211
+ function encodeDiscoveryCursor(fingerprint, offset, integrityKey) {
212
+ const cursor = {
213
+ version: 1,
214
+ offset,
215
+ signature: cursorSignature(fingerprint, offset, integrityKey),
216
+ };
217
+ return Buffer.from(JSON.stringify(cursor), "utf8").toString("base64url");
218
+ }
219
+ function decodeDiscoveryCursor(value, fingerprint, total, integrityKey) {
220
+ if (value === undefined)
221
+ return 0;
222
+ try {
223
+ const decoded = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
224
+ if (decoded.version !== 1 ||
225
+ !Number.isInteger(decoded.offset) ||
226
+ (decoded.offset ?? -1) < 0 ||
227
+ Number(decoded.offset) > total ||
228
+ typeof decoded.signature !== "string") {
229
+ throw new Error("cursor fields do not match the request");
230
+ }
231
+ const expectedSignature = Buffer.from(cursorSignature(fingerprint, decoded.offset, integrityKey), "base64url");
232
+ const suppliedSignature = Buffer.from(decoded.signature, "base64url");
233
+ if (suppliedSignature.length !== expectedSignature.length ||
234
+ !timingSafeEqual(suppliedSignature, expectedSignature)) {
235
+ throw new Error("cursor signature does not match the request");
236
+ }
237
+ return decoded.offset;
238
+ }
239
+ catch (error) {
240
+ throw new PmCliError("Invalid or stale pm tool discovery cursor; restart discovery without cursor.", 64, { reason: String(error) });
241
+ }
242
+ }
243
+ function appliedSignal(value, weight, source) {
244
+ return {
245
+ value: normalizedUnitInterval(value),
246
+ weight,
247
+ available: source !== "unavailable",
248
+ source,
249
+ };
250
+ }
251
+ function hostOrComputedSignal(hostValue, computedValue, weight) {
252
+ return appliedSignal(hostValue ?? computedValue, weight, hostValue === undefined ? "computed" : "host");
253
+ }
254
+ function buildRankedRow(candidate, query, includeSchema) {
255
+ const command = Object.hasOwn(PM_MCP_TOOL_COMMAND_CONTRACTS, candidate.name)
256
+ ? PM_MCP_TOOL_COMMAND_CONTRACTS[candidate.name]
257
+ : "help";
258
+ const family = resolvePmCommandCapabilityFamily(command);
259
+ const searchableText = `${candidate.name} ${candidate.description} ${command} ${family}`;
260
+ const lexical = lexicalRelevance(query, searchableText);
261
+ const queryTokens = new Set(normalizedSearchTokens(query));
262
+ const signals = {
263
+ lexical: appliedSignal(lexical, DISCOVERY_WEIGHTS.lexical, "computed"),
264
+ semantic: hostOrComputedSignal(candidate.signals?.semantic, semanticRelevance(query, searchableText), DISCOVERY_WEIGHTS.semantic),
265
+ graph: hostOrComputedSignal(candidate.signals?.graph, queryTokens.has(family) || queryTokens.has(command) ? 1 : 0, DISCOVERY_WEIGHTS.graph),
266
+ permission: appliedSignal(1, DISCOVERY_WEIGHTS.permission, "authorization"),
267
+ freshness: hostOrComputedSignal(candidate.signals?.freshness, 1, DISCOVERY_WEIGHTS.freshness),
268
+ usage: hostOrComputedSignal(candidate.signals?.usage, PM_MCP_ENTRY_TOOL_NAMES.includes(candidate.name) ? 1 : 0, DISCOVERY_WEIGHTS.usage),
269
+ };
270
+ const score = Object.values(signals).reduce((total, signal) => total + signal.value * signal.weight, 0);
271
+ return {
272
+ name: candidate.name,
273
+ description: candidate.description,
274
+ command,
275
+ tier: resolvePmCommandVisibilityTier(command),
276
+ family,
277
+ score: Number(score.toFixed(6)),
278
+ signals,
279
+ ...(includeSchema
280
+ ? { input_schema: structuredClone(candidate.inputSchema) }
281
+ : {}),
282
+ };
283
+ }
284
+ /** Reject runtime filter values that bypass the public TypeScript unions. */
285
+ function validateDiscoveryFilters(options) {
286
+ if (options.cursorIntegrityKey !== undefined &&
287
+ (!(options.cursorIntegrityKey instanceof Uint8Array) ||
288
+ options.cursorIntegrityKey.byteLength < 32)) {
289
+ throw new PmCliError("pm tool discovery cursorIntegrityKey must contain at least 32 bytes.", 64);
290
+ }
291
+ if (options.tier !== undefined &&
292
+ (typeof options.tier !== "string" ||
293
+ !SELECTABLE_TIERS.includes(options.tier))) {
294
+ throw new PmCliError("pm tool discovery tier must be core, standard, or full.", 64);
295
+ }
296
+ if (options.family !== undefined &&
297
+ (typeof options.family !== "string" ||
298
+ !CAPABILITY_FAMILIES.has(options.family))) {
299
+ throw new PmCliError("pm tool discovery family must be a declared capability family.", 64);
300
+ }
301
+ if (options.profile !== undefined &&
302
+ (typeof options.profile !== "string" ||
303
+ !MCP_TOOL_PROFILES.has(options.profile))) {
304
+ throw new PmCliError("pm tool discovery profile must be core, standard, full, or custom.", 64);
305
+ }
306
+ }
307
+ function resolveDiscoveryRequest(options) {
308
+ const rawQuery = boundedDiscoveryString(options.query === undefined ? "" : options.query, "query");
309
+ const query = rawQuery.trim().replace(/\s+/gu, " ");
310
+ boundedDiscoveryString(options.cursor === undefined ? "" : options.cursor, "cursor");
311
+ const limit = discoveryLimit(options.limit === undefined ? 10 : options.limit);
312
+ const budget = discoveryOutputBudget(options.outputBudget === undefined ? 1_200 : options.outputBudget);
313
+ validateDiscoveryFilters(options);
314
+ return {
315
+ query,
316
+ includeSchema: discoveryIncludeSchema(options.includeSchema),
317
+ limit,
318
+ budget,
319
+ maximumTier: TIER_RANK[options.tier ?? "full"],
320
+ profile: options.profile === undefined ? "core" : options.profile,
321
+ };
322
+ }
323
+ /**
324
+ * Measure one result exactly while allowing callers to supply pre-serialized
325
+ * array contents, so budget selection stays linear in the returned row bytes.
326
+ */
327
+ function estimateDiscoveryResultTokens(resultWithoutCost, budget, serializedToolRowsBytes) {
328
+ const toolRowsBytes = serializedToolRowsBytes ??
329
+ resultWithoutCost.tools.reduce((total, row, index) => total +
330
+ (index === 0 ? 0 : 1) +
331
+ Buffer.byteLength(JSON.stringify(row), "utf8"), 0);
332
+ const emptyToolsResult = { ...resultWithoutCost, tools: [] };
333
+ let estimatedTokens = 0;
334
+ for (let iteration = 0; iteration < 4; iteration += 1) {
335
+ const envelopeBytes = Buffer.byteLength(JSON.stringify({
336
+ ...emptyToolsResult,
337
+ token_cost: {
338
+ estimated_tokens: estimatedTokens,
339
+ budget,
340
+ within_budget: true,
341
+ },
342
+ }), "utf8");
343
+ const nextEstimate = Math.ceil((envelopeBytes + toolRowsBytes) / 4);
344
+ if (nextEstimate === estimatedTokens)
345
+ break;
346
+ estimatedTokens = nextEstimate;
347
+ }
348
+ return estimatedTokens;
349
+ }
350
+ function rankedDiscoveryRows(candidates, options, request) {
351
+ return candidates
352
+ .filter((candidate) => candidate.authorized !== false)
353
+ .map((candidate) => buildRankedRow(candidate, request.query, request.includeSchema))
354
+ .filter((row) => row.tier !== "internal" &&
355
+ TIER_RANK[row.tier] <= request.maximumTier &&
356
+ (options.family === undefined || row.family === options.family))
357
+ .sort((left, right) => right.score - left.score ||
358
+ (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));
359
+ }
360
+ function rowsWithinDiscoveryBudget(candidates, budget, buildResultWithoutCost) {
361
+ if (budget === "unbounded")
362
+ return [...candidates];
363
+ const selected = [];
364
+ let serializedToolRowsBytes = 0;
365
+ for (const [index, row] of candidates.entries()) {
366
+ const candidateRowsBytes = serializedToolRowsBytes +
367
+ (index === 0 ? 0 : 1) +
368
+ Buffer.byteLength(JSON.stringify(row), "utf8");
369
+ const estimatedTokens = estimateDiscoveryResultTokens(buildResultWithoutCost(index + 1), budget, candidateRowsBytes);
370
+ if (estimatedTokens > budget)
371
+ break;
372
+ selected.push(row);
373
+ serializedToolRowsBytes = candidateRowsBytes;
374
+ }
375
+ return selected;
376
+ }
377
+ /**
378
+ * Rank and page an authorized MCP tool catalog under an explicit token budget.
379
+ *
380
+ * Cursors fail closed when the query, filters, schemas, authorization-filtered
381
+ * catalog, or ranking inputs change. Host signals override documented local
382
+ * fallbacks without changing the public formula or hiding signal provenance.
383
+ */
384
+ export function discoverPmTools(candidates, options = {}) {
385
+ validateDiscoveryCandidates(candidates);
386
+ validateDiscoveryOptionsContainer(options);
387
+ const request = resolveDiscoveryRequest(options);
388
+ const cursorIntegrityKey = options.cursorIntegrityKey ?? PROCESS_CURSOR_INTEGRITY_KEY;
389
+ const ranked = rankedDiscoveryRows(candidates, options, request);
390
+ const fingerprint = hashDiscoveryValue({
391
+ query: request.query,
392
+ family: options.family ?? null,
393
+ tier: options.tier ?? "full",
394
+ includeSchema: request.includeSchema,
395
+ profile: request.profile,
396
+ ranked,
397
+ });
398
+ const offset = decodeDiscoveryCursor(options.cursor, fingerprint, ranked.length, cursorIntegrityKey);
399
+ const pageCandidates = ranked.slice(offset, offset + request.limit);
400
+ const omitted = [];
401
+ if (!request.includeSchema) {
402
+ omitted.push({
403
+ name: "input_schema",
404
+ reason: "compact_projection",
405
+ restore_with: "Set includeSchema=true.",
406
+ });
407
+ }
408
+ if (offset + request.limit < ranked.length) {
409
+ omitted.push({
410
+ name: "tools",
411
+ reason: "limit",
412
+ restore_with: "Continue with next_cursor or increase limit.",
413
+ });
414
+ }
415
+ const base = {
416
+ result_type: "pm_tool_discovery",
417
+ contract_version: 1,
418
+ query: request.query,
419
+ profile: request.profile,
420
+ total: ranked.length,
421
+ ranking_policy: {
422
+ version: 1,
423
+ formula: "weighted_sum_then_name",
424
+ weights: DISCOVERY_WEIGHTS,
425
+ },
426
+ cache: {
427
+ key: hashDiscoveryValue({
428
+ fingerprint,
429
+ cursorIntegrityKey: createHash("sha256")
430
+ .update(cursorIntegrityKey)
431
+ .digest("hex"),
432
+ limit: request.limit,
433
+ offset,
434
+ budget: request.budget,
435
+ }),
436
+ ttl_ms: 30_000,
437
+ scope: "private",
438
+ invalidates_on: DISCOVERY_CACHE_INVALIDATIONS,
439
+ },
440
+ };
441
+ const buildResultWithoutCost = (selected, selectedCount = selected.length) => {
442
+ const endOffset = offset + selectedCount;
443
+ const hasMore = endOffset < ranked.length;
444
+ const resultOmissions = [...omitted];
445
+ if (selectedCount < pageCandidates.length) {
446
+ resultOmissions.push({
447
+ name: "tools",
448
+ reason: "token_budget",
449
+ restore_with: "Continue with next_cursor or increase outputBudget.",
450
+ });
451
+ }
452
+ const resultWithoutCost = {
453
+ ...base,
454
+ tools: [...selected],
455
+ returned: selectedCount,
456
+ has_more: hasMore,
457
+ ...(hasMore
458
+ ? {
459
+ next_cursor: encodeDiscoveryCursor(fingerprint, endOffset, cursorIntegrityKey),
460
+ }
461
+ : {}),
462
+ omission_receipt: {
463
+ has_omissions: resultOmissions.length > 0,
464
+ omitted: resultOmissions,
465
+ },
466
+ };
467
+ return resultWithoutCost;
468
+ };
469
+ const buildResult = (selected) => {
470
+ const resultWithoutCost = buildResultWithoutCost(selected);
471
+ const estimatedTokens = estimateDiscoveryResultTokens(resultWithoutCost, request.budget);
472
+ return {
473
+ ...resultWithoutCost,
474
+ token_cost: {
475
+ estimated_tokens: estimatedTokens,
476
+ budget: request.budget,
477
+ within_budget: request.budget === "unbounded" || estimatedTokens <= request.budget,
478
+ },
479
+ };
480
+ };
481
+ const selected = rowsWithinDiscoveryBudget(pageCandidates, request.budget, (selectedCount) => buildResultWithoutCost([], selectedCount));
482
+ const result = buildResult(selected);
483
+ if (pageCandidates.length > 0 && selected.length === 0) {
484
+ const oneRowCost = buildResult([pageCandidates[0]]).token_cost
485
+ .estimated_tokens;
486
+ throw new PmCliError(`pm tool discovery outputBudget is too small to return a tool; increase it to at least ${oneRowCost}.`, 64, { required: String(oneRowCost) });
487
+ }
488
+ if (request.budget !== "unbounded" &&
489
+ result.token_cost.estimated_tokens > request.budget) {
490
+ throw new PmCliError(`pm tool discovery outputBudget is too small; at least ${result.token_cost.estimated_tokens} estimated tokens are required for this page.`, 64, { required: String(result.token_cost.estimated_tokens) });
491
+ }
492
+ return result;
493
+ }
494
+ //# sourceMappingURL=discovery.js.map
495
+ //# debugId=4853ebbf-f28a-55f1-b306-aa75cb9355ae
@@ -6,8 +6,16 @@
6
6
  */
7
7
  /** Canonical stateless MCP revision implemented by pm. */
8
8
  export declare const PM_MCP_PROTOCOL_VERSION: "2026-07-28";
9
- /** Legacy initialize-era revisions accepted only by the bounded stdio adapter. */
10
- export declare const PM_MCP_LEGACY_PROTOCOL_VERSIONS: readonly ["2025-06-18"];
9
+ /**
10
+ * Legacy initialize-era revisions accepted only by the bounded stdio adapter.
11
+ *
12
+ * The canonical revision defines legacy as every version that establishes a
13
+ * session with the handshake method, which is `2025-11-25` and earlier, so this
14
+ * set tracks that boundary rather than a single historical revision.
15
+ * Ordered newest first: element zero is the revision offered to a client that
16
+ * omits `protocolVersion`.
17
+ */
18
+ export declare const PM_MCP_LEGACY_PROTOCOL_VERSIONS: readonly ["2025-11-25", "2025-06-18"];
11
19
  /** Modern per-request protocol versions accepted by the stateless core. */
12
20
  export declare const PM_MCP_SUPPORTED_PROTOCOL_VERSIONS: readonly ["2026-07-28"];
13
21
  /** Allocated MCP 2026-07-28 protocol error codes. */
@@ -6,10 +6,21 @@
6
6
  */
7
7
  /** Canonical stateless MCP revision implemented by pm. */
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]="9cb05a78-f95d-5211-a35a-03756f66c812")}catch(e){}}();
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]="0ec82581-c626-544c-9deb-ec5e810fd7e9")}catch(e){}}();
10
10
  export const PM_MCP_PROTOCOL_VERSION = "2026-07-28";
11
- /** Legacy initialize-era revisions accepted only by the bounded stdio adapter. */
12
- export const PM_MCP_LEGACY_PROTOCOL_VERSIONS = ["2025-06-18"];
11
+ /**
12
+ * Legacy initialize-era revisions accepted only by the bounded stdio adapter.
13
+ *
14
+ * The canonical revision defines legacy as every version that establishes a
15
+ * session with the handshake method, which is `2025-11-25` and earlier, so this
16
+ * set tracks that boundary rather than a single historical revision.
17
+ * Ordered newest first: element zero is the revision offered to a client that
18
+ * omits `protocolVersion`.
19
+ */
20
+ export const PM_MCP_LEGACY_PROTOCOL_VERSIONS = [
21
+ "2025-11-25",
22
+ "2025-06-18",
23
+ ];
13
24
  /** Modern per-request protocol versions accepted by the stateless core. */
14
25
  export const PM_MCP_SUPPORTED_PROTOCOL_VERSIONS = [
15
26
  PM_MCP_PROTOCOL_VERSION,
@@ -171,4 +182,4 @@ export function interpretMcpResultType(result, era) {
171
182
  throw new PmMcpProtocolError("Modern MCP result is missing resultType", PM_MCP_ERROR_CODES.invalidParams, { required: "resultType" });
172
183
  }
173
184
  //# sourceMappingURL=protocol.js.map
174
- //# debugId=9cb05a78-f95d-5211-a35a-03756f66c812
185
+ //# debugId=0ec82581-c626-544c-9deb-ec5e810fd7e9
@@ -7,7 +7,7 @@
7
7
  * this module so packages and hosts can reuse the same merge behavior.
8
8
  */
9
9
  export { ITEM_LATEST_TIMESTAMP_FIELDS, ITEM_UNION_COLLECTION_FIELDS, mergeHistoryStreams, mergeItemDocuments, mergeJsonDocuments, mergeRelationshipEventStreams, type HistoryMergeResult, type HistoryMergeStrategy, type ItemDocumentMergeResult, type JsonDocumentMergeResult, type ItemMergeConflictDecision, type MergePreferredSide, type RelationshipStreamMergeResult, } from "./three-way.js";
10
- export { listMergeReceipts, markMergeReceiptReconciled, runMergeReceiptReport, summarizeMergeReceipt, type MergeDecisionReceipt, type MergeDecisionReceiptSummary, type MergeReceiptReport, } from "./receipts.js";
10
+ export { inspectMergeReceiptEvidence, listMergeReceipts, markMergeReceiptReconciled, runMergeReceiptEvidenceReport, runMergeReceiptReport, summarizeMergeReceipt, type MergeDecisionReceipt, type MergeDecisionReceiptSummary, type MergeReceiptEvidenceReport, type MergeReceiptEvidenceScan, type MergeReceiptReport, } from "./receipts.js";
11
11
  export { MERGE_DRIVER_ARTIFACT_VALUES, runMergeDriver, type MergeDriverArtifact, type MergeDriverOptions, type MergeDriverResult, } from "./driver.js";
12
12
  export { auditMergeAttributeFence, auditMergeDriverConfiguration, buildMergeAttributePatterns, findGitWorkspaceRoot, PM_GITATTRIBUTES_END, PM_GITATTRIBUTES_START, PM_GITATTRIBUTES_V2_END, PM_GITATTRIBUTES_V2_START, refreshMergeAttributeFenceIfInstalled, resolveMergeInstallContext, runMergeInstall, type MergeFenceAuditResult, type MergeDriverConfigurationAuditResult, type MergeFenceRefreshOutcome, type MergeInstallOptions, type MergeInstallContextResolution, type MergeInstallResult, } from "./install.js";
13
13
  export { runMergeReconcile, type MergeReconcileOptions, type MergeReconcileResult, } from "./reconcile.js";
@@ -7,11 +7,11 @@
7
7
  * this module so packages and hosts can reuse the same merge behavior.
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]="687855bf-7432-5691-a809-1f0406b5d8a8")}catch(e){}}();
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]="a26f1126-3c87-5b0d-8712-2846fc9dcbb3")}catch(e){}}();
11
11
  export { ITEM_LATEST_TIMESTAMP_FIELDS, ITEM_UNION_COLLECTION_FIELDS, mergeHistoryStreams, mergeItemDocuments, mergeJsonDocuments, mergeRelationshipEventStreams, } from "./three-way.js";
12
- export { listMergeReceipts, markMergeReceiptReconciled, runMergeReceiptReport, summarizeMergeReceipt, } from "./receipts.js";
12
+ export { inspectMergeReceiptEvidence, listMergeReceipts, markMergeReceiptReconciled, runMergeReceiptEvidenceReport, runMergeReceiptReport, summarizeMergeReceipt, } from "./receipts.js";
13
13
  export { MERGE_DRIVER_ARTIFACT_VALUES, runMergeDriver, } from "./driver.js";
14
14
  export { auditMergeAttributeFence, auditMergeDriverConfiguration, buildMergeAttributePatterns, findGitWorkspaceRoot, PM_GITATTRIBUTES_END, PM_GITATTRIBUTES_START, PM_GITATTRIBUTES_V2_END, PM_GITATTRIBUTES_V2_START, refreshMergeAttributeFenceIfInstalled, resolveMergeInstallContext, runMergeInstall, } from "./install.js";
15
15
  export { runMergeReconcile, } from "./reconcile.js";
16
16
  //# sourceMappingURL=index.js.map
17
- //# debugId=687855bf-7432-5691-a809-1f0406b5d8a8
17
+ //# debugId=a26f1126-3c87-5b0d-8712-2846fc9dcbb3
@@ -70,12 +70,31 @@ export interface MergeReceiptReport {
70
70
  /** ISO timestamp for the report. */
71
71
  generated_at: string;
72
72
  }
73
- /** Internal integrity scan result used by health without exposing malformed receipt contents. */
73
+ /** Loss-aware merge receipt report for integrity gates and diagnostic adapters. */
74
+ export interface MergeReceiptEvidenceReport {
75
+ /** Whether clone-local evidence resolved and every candidate was read and validated successfully. */
76
+ ok: boolean;
77
+ /** Whether clone-local evidence resolved and every discovered JSON candidate was read and validated successfully. */
78
+ complete: boolean;
79
+ /** Number of valid receipts returned. */
80
+ count: number;
81
+ /** Number of candidates rejected by bounded-file, schema, identity, or copy-consistency validation. */
82
+ invalid_evidence_count: number;
83
+ /** Whether the clone-local Git receipt directory was resolved successfully; always emitted by current implementations and optional for structural compatibility. */
84
+ clone_local_evidence_resolved?: boolean;
85
+ /** Receipts including recoverable values from the local clone only. */
86
+ receipts: MergeDecisionReceipt[];
87
+ /** ISO timestamp for the report. */
88
+ generated_at: string;
89
+ }
90
+ /** Loss-aware receipt inspection result that never exposes malformed file contents. */
74
91
  export interface MergeReceiptEvidenceScan {
75
92
  /** Valid receipts that passed bounded-file, schema, and identity validation. */
76
93
  receipts: MergeDecisionReceipt[];
77
94
  /** Number of JSON receipt candidates that could not be validated safely. */
78
95
  invalid_evidence_count: number;
96
+ /** Whether the clone-local Git receipt directory was resolved successfully; always emitted by current implementations and optional for structural compatibility. */
97
+ clone_local_evidence_resolved?: boolean;
79
98
  }
80
99
  declare function prepareReceiptSettlement(params: {
81
100
  receiptPath: string;
@@ -134,6 +153,13 @@ export declare function runMergeReceiptReport(options: {
134
153
  /** Repository directory to inspect; defaults to the process working directory. */
135
154
  cwd?: string;
136
155
  }): Promise<MergeReceiptReport>;
156
+ /** Inspect every receipt candidate and retain completeness diagnostics without exposing rejected file contents. */
157
+ export declare function runMergeReceiptEvidenceReport(options: {
158
+ /** Include receipts already represented by merge history events. */
159
+ includeReconciled?: boolean;
160
+ /** Repository directory to inspect; defaults to the process working directory. */
161
+ cwd?: string;
162
+ }): Promise<MergeReceiptEvidenceReport>;
137
163
  /** Test-only seams for deterministic receipt-boundary fault coverage. */
138
164
  export declare const _testOnlyMergeReceipts: {
139
165
  prepareReceiptSettlement: typeof prepareReceiptSettlement;