@unbrained/pm-cli 2026.8.14 → 2026.8.15

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 (145) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +25 -2
  3. package/dist/cli/commander-usage.js +17 -4
  4. package/dist/cli/error-guidance.d.ts +2 -0
  5. package/dist/cli/error-guidance.js +52 -25
  6. package/dist/cli/main.js +3 -2
  7. package/dist/cli/register-mutation.js +4 -2
  8. package/dist/cli/register-operations.js +5 -5
  9. package/dist/cli-bundle/bundle-manifest.json +150 -150
  10. package/dist/cli-bundle/chunks/{chunk-TXMEUUUY.js → chunk-24GAV7XL.js} +2 -2
  11. package/dist/cli-bundle/chunks/{chunk-TMJ7URWS.js → chunk-AIM6VT2N.js} +9 -9
  12. package/dist/cli-bundle/chunks/chunk-DSWDLTDR.js +197 -0
  13. package/dist/cli-bundle/chunks/{chunk-FIW4P64F.js → chunk-J42EGKDK.js} +2 -2
  14. package/dist/cli-bundle/chunks/chunk-KIEGUBYQ.js +2 -0
  15. package/dist/cli-bundle/chunks/{chunk-SBRKH6OR.js → chunk-KLKYLSDX.js} +2 -2
  16. package/dist/cli-bundle/chunks/{chunk-G5JUB66K.js → chunk-LJHOAVGI.js} +59 -59
  17. package/dist/cli-bundle/chunks/{chunk-BFALV3YP.js → chunk-MEM2ZS3O.js} +2 -2
  18. package/dist/cli-bundle/chunks/chunk-QHPCJWEJ.js +35 -0
  19. package/dist/cli-bundle/chunks/{chunk-XAVMOK6B.js → chunk-WLPDLNEZ.js} +2 -2
  20. package/dist/cli-bundle/chunks/{register-list-query-T3EHHNNV.js → register-list-query-CT3LFDDN.js} +2 -2
  21. package/dist/cli-bundle/chunks/{register-mutation-E27WCLSZ.js → register-mutation-NWEVA5YS.js} +3 -3
  22. package/dist/cli-bundle/chunks/register-operations-AHIAG5KM.js +2 -0
  23. package/dist/cli-bundle/chunks/{register-setup-3YXZ444E.js → register-setup-ZJZFVAKE.js} +2 -2
  24. package/dist/cli-bundle/focused-chunks/chunk-4X57RE4U.js +2 -0
  25. package/dist/cli-bundle/focused-chunks/{chunk-XDNAW5OI.js → chunk-6XKF3PGV.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/chunk-7NJ4QYQ2.js +2 -0
  27. package/dist/cli-bundle/focused-chunks/{chunk-WCVE2NIG.js → chunk-EXZA4257.js} +2 -2
  28. package/dist/cli-bundle/focused-chunks/chunk-ITAUHSO6.js +50 -0
  29. package/dist/cli-bundle/focused-chunks/{chunk-4DQ2YERC.js → chunk-KLVUMNXJ.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/{chunk-K7RWWOAG.js → chunk-KT5XMYSX.js} +2 -2
  31. package/dist/cli-bundle/focused-chunks/{chunk-PPFGQDSI.js → chunk-KTKH4IMG.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/chunk-M67F5AIN.js +8 -0
  33. package/dist/cli-bundle/focused-chunks/{chunk-KSEDUWVZ.js → chunk-NSPYTG6G.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/chunk-OKA6ELTL.js +2 -0
  35. package/dist/cli-bundle/focused-chunks/chunk-PUISBOPP.js +2 -0
  36. package/dist/cli-bundle/focused-chunks/chunk-QLNMCESQ.js +155 -0
  37. package/dist/cli-bundle/focused-chunks/{chunk-LZ4MV3RH.js → chunk-SLKC6QLJ.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/chunk-U65UC4G3.js +2 -0
  39. package/dist/cli-bundle/focused-chunks/{chunk-KFSZ3BP6.js → chunk-WTSER4WJ.js} +6 -6
  40. package/dist/cli-bundle/focused-chunks/{chunk-YOOI3UZX.js → chunk-ZMFXQ7VF.js} +2 -2
  41. package/dist/cli-bundle/main.js +13 -13
  42. package/dist/cli-bundle/sdk-authoring.js +1 -1
  43. package/dist/cli-bundle/sdk-contracts.js +1 -1
  44. package/dist/cli-bundle/sdk-core.js +32 -35
  45. package/dist/cli-bundle/sdk-governance.js +1 -1
  46. package/dist/cli-bundle/sdk-graph.js +1 -1
  47. package/dist/cli-bundle/sdk-merge.js +32 -31
  48. package/dist/cli-bundle/sdk-query.js +1 -1
  49. package/dist/cli-bundle/sdk-runtime.js +1 -1
  50. package/dist/cli-bundle/sdk-testing.js +1 -1
  51. package/dist/cli-bundle/sdk.js +2 -2
  52. package/dist/core/diagnostics/remediation.js +7 -2
  53. package/dist/core/extensions/reserved-host-flags.js +3 -2
  54. package/dist/core/history/replay.d.ts +14 -1
  55. package/dist/core/history/replay.js +45 -8
  56. package/dist/core/output/output.d.ts +2 -0
  57. package/dist/core/output/output.js +3 -2
  58. package/dist/core/shared/command-types.d.ts +2 -0
  59. package/dist/core/shared/command-types.js +2 -2
  60. package/dist/core/shared/errors.d.ts +12 -0
  61. package/dist/core/shared/errors.js +2 -2
  62. package/dist/mcp/tool-definitions.js +9 -5
  63. package/dist/sdk/agent/refusal-reachability.d.ts +61 -0
  64. package/dist/sdk/agent/refusal-reachability.js +91 -3
  65. package/dist/sdk/cli-bootstrap.d.ts +2 -0
  66. package/dist/sdk/cli-bootstrap.js +7 -2
  67. package/dist/sdk/cli-contracts/completeness.js +3 -2
  68. package/dist/sdk/cli-contracts/flag-contracts.js +3 -2
  69. package/dist/sdk/cli-contracts/registration-helpers.js +3 -2
  70. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +5 -0
  71. package/dist/sdk/cli-contracts/runtime-contracts.js +23 -7
  72. package/dist/sdk/cli-contracts/tool-parameter-tables.js +15 -5
  73. package/dist/sdk/cli-contracts/tool-schema.js +10 -3
  74. package/dist/sdk/cli-program.js +3 -2
  75. package/dist/sdk/core.d.ts +2 -2
  76. package/dist/sdk/core.js +3 -3
  77. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +26 -2
  78. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +50 -26
  79. package/dist/sdk/governance/assurance-action.d.ts +7 -1
  80. package/dist/sdk/governance/assurance-action.js +7 -6
  81. package/dist/sdk/governance/assurance-mutation-error.d.ts +42 -1
  82. package/dist/sdk/governance/assurance-mutation-error.js +27 -3
  83. package/dist/sdk/governance/assurance-runtime.js +12 -11
  84. package/dist/sdk/governance/assurance.d.ts +9 -0
  85. package/dist/sdk/governance/assurance.js +80 -14
  86. package/dist/sdk/governance/extension-host-version.d.ts +25 -0
  87. package/dist/sdk/governance/extension-host-version.js +105 -0
  88. package/dist/sdk/governance/health.d.ts +32 -1
  89. package/dist/sdk/governance/health.js +119 -27
  90. package/dist/sdk/governance/provenance-health.d.ts +27 -0
  91. package/dist/sdk/governance/provenance-health.js +95 -3
  92. package/dist/sdk/governance/validate.js +7 -8
  93. package/dist/sdk/governance.d.ts +6 -0
  94. package/dist/sdk/governance.js +8 -2
  95. package/dist/sdk/history-repair.d.ts +13 -1
  96. package/dist/sdk/history-repair.js +62 -18
  97. package/dist/sdk/linked-artifacts.js +16 -5
  98. package/dist/sdk/pagination.d.ts +15 -0
  99. package/dist/sdk/pagination.js +9 -5
  100. package/dist/sdk/query/context.d.ts +5 -1
  101. package/dist/sdk/query/context.js +14 -5
  102. package/dist/sdk/read-output/continuation.d.ts +11 -0
  103. package/dist/sdk/read-output/continuation.js +132 -0
  104. package/dist/sdk/read-output-budget.d.ts +1 -1
  105. package/dist/sdk/read-output-budget.js +14 -10
  106. package/dist/sdk/read-output-contracts.d.ts +66 -2
  107. package/dist/sdk/read-output-contracts.js +183 -19
  108. package/dist/sdk/read-output-rows.d.ts +2 -0
  109. package/dist/sdk/read-output-rows.js +15 -2
  110. package/dist/sdk/runtime-input.js +4 -2
  111. package/docs/ASSURANCE.md +59 -2
  112. package/docs/COMMANDS.md +8 -2
  113. package/docs/READ_OUTPUT_CONTRACTS.md +49 -8
  114. package/docs/RELEASING.md +42 -5
  115. package/docs/SDK_CONTEXT_INTEGRITY.md +64 -2
  116. package/marketplace.json +2 -2
  117. package/package.json +3 -3
  118. package/packages/pm-beads/package.json +1 -1
  119. package/packages/pm-calendar/package.json +1 -1
  120. package/packages/pm-command-kit/package.json +1 -1
  121. package/packages/pm-digital-twin/package.json +1 -1
  122. package/packages/pm-governance-audit/package.json +1 -1
  123. package/packages/pm-guide-shell/package.json +1 -1
  124. package/packages/pm-kanban/package.json +1 -1
  125. package/packages/pm-lifecycle-hooks/package.json +1 -1
  126. package/packages/pm-linked-test-adapters/package.json +1 -1
  127. package/packages/pm-search-advanced/package.json +1 -1
  128. package/packages/pm-templates/package.json +1 -1
  129. package/packages/pm-todos/package.json +1 -1
  130. package/packages/pm-vcs/package.json +1 -1
  131. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  132. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  133. package/sdk/public-surface.json +1133 -187
  134. package/dist/cli-bundle/chunks/chunk-BBOFSVAK.js +0 -197
  135. package/dist/cli-bundle/chunks/chunk-YAMTJL6Y.js +0 -34
  136. package/dist/cli-bundle/chunks/chunk-YSVSMJ2B.js +0 -2
  137. package/dist/cli-bundle/chunks/register-operations-4R6I7CPY.js +0 -2
  138. package/dist/cli-bundle/focused-chunks/chunk-F43TT2QQ.js +0 -8
  139. package/dist/cli-bundle/focused-chunks/chunk-KYUQGTSB.js +0 -2
  140. package/dist/cli-bundle/focused-chunks/chunk-PGXJQLCT.js +0 -155
  141. package/dist/cli-bundle/focused-chunks/chunk-Q4YY3XNF.js +0 -2
  142. package/dist/cli-bundle/focused-chunks/chunk-QK753U3U.js +0 -46
  143. package/dist/cli-bundle/focused-chunks/chunk-QUMB2J27.js +0 -2
  144. package/dist/cli-bundle/focused-chunks/chunk-SM7MTG27.js +0 -2
  145. package/dist/cli-bundle/focused-chunks/chunk-ZM6TZVHC.js +0 -2
@@ -1,3 +1,4 @@
1
+ import type { HistoryEntry } from "../../types/index.js";
1
2
  /** Aggregated resolver attempts for one harness provenance dimension. */
2
3
  export interface ProvenanceResolverHealthOutcome {
3
4
  /** Detected harness namespace. */
@@ -35,5 +36,31 @@ export interface ProvenanceResolverHealthScan {
35
36
  /** Whether an event or byte ceiling omitted history input. */
36
37
  truncated: boolean;
37
38
  }
39
+ /** Privacy-safe receipt for an explicit provenance normalization pass. */
40
+ export interface ProvenanceNormalizationReceipt {
41
+ /** Whether at least one immutable event required normalization. */
42
+ changed: boolean;
43
+ /** Immutable events whose invalid provenance observations were removed. */
44
+ events_changed: number;
45
+ /** Total invalid observations removed without retaining their values. */
46
+ observations_removed: number;
47
+ /** Aggregate invalid-value classes removed by the pass. */
48
+ invalid_values: ProvenanceValueHealthFinding[];
49
+ }
50
+ /** Normalized entries plus the privacy-safe mutation receipt. */
51
+ export interface ProvenanceNormalizationResult {
52
+ /** History entries with invalid bounded observations removed. */
53
+ entries: HistoryEntry[];
54
+ /** Aggregate mutation receipt; never includes an observed value. */
55
+ receipt: ProvenanceNormalizationReceipt;
56
+ }
57
+ /**
58
+ * Remove only provenance observations whose values violate the bounded domain.
59
+ * History operations, patches, timestamps, authors, and hashes are retained;
60
+ * the receipt exposes aggregate classes and counts but never the removed value.
61
+ */
62
+ export declare function normalizeInvalidHistoryProvenance(entries: HistoryEntry[]): ProvenanceNormalizationResult;
63
+ /** Find every history stream requiring provenance normalization without returning raw values. */
64
+ export declare function listInvalidProvenanceHistoryStreamIds(pmRoot: string): Promise<string[]>;
38
65
  /** Scan immutable history without failing over malformed streams owned by integrity checks. */
39
66
  export declare function scanProvenanceResolverHealth(pmRoot: string, eventLimit?: number): Promise<ProvenanceResolverHealthScan>;
@@ -4,7 +4,7 @@
4
4
  * Reads bounded, privacy-safe provenance resolver outcomes for health checks.
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]="60154e1b-8348-5b6b-badf-e76bba43bef8")}catch(e){}}();
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]="6efed404-acd2-5c3a-a008-856df67c8b77")}catch(e){}}();
8
8
  import fs from "node:fs/promises";
9
9
  import path from "node:path";
10
10
  const DEFAULT_PROVENANCE_HISTORY_BYTE_LIMIT = 8_388_608;
@@ -27,6 +27,98 @@ const INVALID_PROVENANCE_VALUE_CLASSIFIERS = [
27
27
  function isRecord(value) {
28
28
  return typeof value === "object" && value !== null && !Array.isArray(value);
29
29
  }
30
+ function invalidProvenanceValueKind(value) {
31
+ return INVALID_PROVENANCE_VALUE_CLASSIFIERS.find((classifier) => classifier.matches(value))?.kind;
32
+ }
33
+ /**
34
+ * Remove only provenance observations whose values violate the bounded domain.
35
+ * History operations, patches, timestamps, authors, and hashes are retained;
36
+ * the receipt exposes aggregate classes and counts but never the removed value.
37
+ */
38
+ export function normalizeInvalidHistoryProvenance(entries) {
39
+ const invalidValues = new Map();
40
+ let eventsChanged = 0;
41
+ let observationsRemoved = 0;
42
+ const normalized = entries.map((entry) => {
43
+ const provenance = isRecord(entry.agent_provenance)
44
+ ? entry.agent_provenance
45
+ : undefined;
46
+ if (provenance === undefined)
47
+ return entry;
48
+ const retained = {};
49
+ let eventChanged = false;
50
+ for (const [dimension, observation] of Object.entries(provenance)) {
51
+ const kind = isRecord(observation)
52
+ ? invalidProvenanceValueKind(observation.value)
53
+ : undefined;
54
+ if (kind === undefined) {
55
+ retained[dimension] = observation;
56
+ continue;
57
+ }
58
+ eventChanged = true;
59
+ observationsRemoved += 1;
60
+ const harness = entry.agent_harness ?? "unknown";
61
+ const key = `${harness}\0${dimension}\0${kind}`;
62
+ const aggregate = invalidValues.get(key) ?? {
63
+ harness,
64
+ dimension,
65
+ kind,
66
+ count: 0,
67
+ };
68
+ aggregate.count += 1;
69
+ invalidValues.set(key, aggregate);
70
+ }
71
+ if (!eventChanged)
72
+ return entry;
73
+ eventsChanged += 1;
74
+ const next = { ...entry };
75
+ if (Object.keys(retained).length === 0) {
76
+ delete next.agent_provenance;
77
+ }
78
+ else {
79
+ next.agent_provenance = retained;
80
+ }
81
+ return next;
82
+ });
83
+ return {
84
+ entries: normalized,
85
+ receipt: {
86
+ changed: eventsChanged > 0,
87
+ events_changed: eventsChanged,
88
+ observations_removed: observationsRemoved,
89
+ invalid_values: [...invalidValues.values()].sort((left, right) => left.harness.localeCompare(right.harness) ||
90
+ left.dimension.localeCompare(right.dimension) ||
91
+ left.kind.localeCompare(right.kind)),
92
+ },
93
+ };
94
+ }
95
+ /** Find every history stream requiring provenance normalization without returning raw values. */
96
+ export async function listInvalidProvenanceHistoryStreamIds(pmRoot) {
97
+ const ids = [];
98
+ for (const file of await listHistoryFiles(pmRoot)) {
99
+ try {
100
+ const content = await fs.readFile(path.join(pmRoot, "history", file), "utf8");
101
+ for (const line of content.split("\n")) {
102
+ if (line.trim().length === 0)
103
+ continue;
104
+ const entry = parseHistoryEntry(line);
105
+ if (entry === null || !isRecord(entry.agent_provenance))
106
+ continue;
107
+ const invalid = Object.values(entry.agent_provenance).some((observation) => isRecord(observation) &&
108
+ invalidProvenanceValueKind(observation.value) !== undefined);
109
+ if (invalid) {
110
+ ids.push(file.slice(0, -".jsonl".length));
111
+ break;
112
+ }
113
+ }
114
+ }
115
+ catch {
116
+ // Integrity diagnostics own unreadable or malformed streams. This census
117
+ // only selects safely parseable streams for the explicit normalizer.
118
+ }
119
+ }
120
+ return ids;
121
+ }
30
122
  async function listHistoryFiles(pmRoot) {
31
123
  try {
32
124
  return (await fs.readdir(path.join(pmRoot, "history")))
@@ -84,7 +176,7 @@ function collectResolverOutcomes(entry, aggregates, invalidValues) {
84
176
  Object.entries(provenance).forEach(([dimension, observation]) => {
85
177
  if (!isRecord(observation))
86
178
  return;
87
- const kind = INVALID_PROVENANCE_VALUE_CLASSIFIERS.find((classifier) => classifier.matches(observation.value))?.kind;
179
+ const kind = invalidProvenanceValueKind(observation.value);
88
180
  if (!kind)
89
181
  return;
90
182
  const key = `${harness}\0${dimension}\0${kind}`;
@@ -182,4 +274,4 @@ export async function scanProvenanceResolverHealth(pmRoot, eventLimit = 10_000)
182
274
  };
183
275
  }
184
276
  //# sourceMappingURL=provenance-health.js.map
185
- //# debugId=60154e1b-8348-5b6b-badf-e76bba43bef8
277
+ //# debugId=6efed404-acd2-5c3a-a008-856df67c8b77
@@ -4,7 +4,7 @@
4
4
  * Implements the pm validate 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]="7b47a375-e72c-5108-bd93-75dd8cf93218")}catch(e){}}();
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]="b8c4707f-5445-5079-96e5-dc0dbd649b34")}catch(e){}}();
8
8
  import fs from "node:fs/promises";
9
9
  import { realpathSync } from "node:fs";
10
10
  import { execFile } from "node:child_process";
@@ -778,9 +778,7 @@ function buildMetadataCounts(metadataPolicy, missingByField) {
778
778
  const missing = missingByField[field];
779
779
  const value = missing ? missing.length : 0;
780
780
  const countKey = METADATA_COUNT_KEY_BY_FIELD[field];
781
- if (value > 0 && countKey) {
782
- counts[countKey] = value;
783
- }
781
+ counts[countKey] = value;
784
782
  }
785
783
  return counts;
786
784
  }
@@ -858,9 +856,10 @@ function buildMetadataCheck(items, metadataPolicy, statusRegistry, verboseDiagno
858
856
  const duplicateIssueCodes = findDuplicateIssueCodes(items);
859
857
  const duplicateIssueCodeSummary = summarizeDuplicateIssueCodes(duplicateIssueCodes, verboseDiagnostics);
860
858
  const warningTokens = buildMetadataWarningTokens(metadataPolicy, missingByField, duplicateIssueCodeSummary.warnings);
861
- // Zero-suppress counts to reduce agent token cost (telemetry pm-tylj).
862
- // Only emit counts for the ACTIVE required fields of the resolved profile so a
863
- // looser profile (e.g. core) never reports missing reviewer/risk/sprint/etc.
859
+ // Emit an explicit numeric predicate for every ACTIVE required field. Stable
860
+ // zeroes let assurance consumers distinguish a passing metric from an absent
861
+ // contract key without exposing any per-item diagnostic rows.
862
+ // A looser profile (e.g. core) still never reports reviewer/risk/sprint/etc.
864
863
  // Defensive guards (Gemini high #1, PR #78 follow-up): a future settings
865
864
  // shape could include an unsupported field in required_fields — fall back
866
865
  // to 0 instead of throwing TypeError, and skip writing when the count-key
@@ -2314,4 +2313,4 @@ export async function runValidate(options, global, services = {}) {
2314
2313
  }
2315
2314
  /* c8 ignore stop */
2316
2315
  //# sourceMappingURL=validate.js.map
2317
- //# debugId=7b47a375-e72c-5108-bd93-75dd8cf93218
2316
+ //# debugId=b8c4707f-5445-5079-96e5-dc0dbd649b34
@@ -5,6 +5,12 @@
5
5
  */
6
6
  export * from "./governance/gc.js";
7
7
  export * from "./governance/health.js";
8
+ export * from "./governance/extension-host-version.js";
9
+ export * from "./governance/assurance.js";
10
+ export * from "./governance/assurance-action.js";
11
+ export * from "./governance/assurance-mutation-error.js";
12
+ export * from "./governance/assurance-presets.js";
13
+ export * from "./governance/assurance-runtime.js";
8
14
  export { runReindex, type ReindexOptions, type ReindexResult, } from "./governance/reindex.js";
9
15
  export * from "./governance/stale-work.js";
10
16
  export * from "./governance/storage-integrity.js";
@@ -4,9 +4,15 @@
4
4
  * Provides validation, health, integrity, and mutation-policy primitives.
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]="8e8c2de1-7bff-57c6-8e71-9c27e9e76eaa")}catch(e){}}();
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]="0baaaf38-2a32-5d6e-92bc-9919d2393f86")}catch(e){}}();
8
8
  export * from "./governance/gc.js";
9
9
  export * from "./governance/health.js";
10
+ export * from "./governance/extension-host-version.js";
11
+ export * from "./governance/assurance.js";
12
+ export * from "./governance/assurance-action.js";
13
+ export * from "./governance/assurance-mutation-error.js";
14
+ export * from "./governance/assurance-presets.js";
15
+ export * from "./governance/assurance-runtime.js";
10
16
  export { runReindex, } from "./governance/reindex.js";
11
17
  export * from "./governance/stale-work.js";
12
18
  export * from "./governance/storage-integrity.js";
@@ -17,4 +23,4 @@ export * from "./mutation-guard.js";
17
23
  export * from "./governance/provenance-health.js";
18
24
  export * from "./similarity.js";
19
25
  //# sourceMappingURL=governance.js.map
20
- //# debugId=8e8c2de1-7bff-57c6-8e71-9c27e9e76eaa
26
+ //# debugId=0baaaf38-2a32-5d6e-92bc-9919d2393f86
@@ -1,6 +1,7 @@
1
1
  import { type ReplayDocument } from "../core/history/replay.js";
2
2
  import type { GlobalOptions } from "../core/shared/command-types.js";
3
3
  import type { HistoryEntry } from "../types/index.js";
4
+ import { type ProvenanceNormalizationReceipt } from "./governance/provenance-health.js";
4
5
  /** Documents the history repair command options payload exchanged by command, SDK, and package integrations. */
5
6
  export interface HistoryRepairCommandOptions {
6
7
  /** Value that configures or reports dry run for this contract. */
@@ -19,6 +20,8 @@ export interface HistoryRepairCommandOptions {
19
20
  auditContextById?: Record<string, Record<string, unknown>>;
20
21
  /** Add an audit event even when replay and the current item already match. */
21
22
  forceAuditEntry?: boolean;
23
+ /** Remove bounded-domain-invalid provenance observations and record an aggregate privacy-safe audit receipt. */
24
+ normalizeProvenance?: boolean;
22
25
  }
23
26
  /** Documents the history repair result payload exchanged by command, SDK, and package integrations. */
24
27
  export interface HistoryRepairResult {
@@ -41,6 +44,9 @@ export interface HistoryRepairResult {
41
44
  audit_entry_added: boolean;
42
45
  verify_ok: boolean;
43
46
  verify_errors: string[];
47
+ item_hash_version_before: number | null;
48
+ item_hash_version_after: number;
49
+ version_disposition: "preserved" | "selected_for_ambiguous_stream";
44
50
  };
45
51
  /** Value that configures or reports item for this contract. */
46
52
  item: {
@@ -48,6 +54,10 @@ export interface HistoryRepairResult {
48
54
  path: string | null;
49
55
  matched_chain_before: boolean | null;
50
56
  };
57
+ /** Privacy-safe receipt for the explicitly requested provenance normalization mode. */
58
+ provenance_normalization: ProvenanceNormalizationReceipt & {
59
+ requested: boolean;
60
+ };
51
61
  /** Present when reconciling the chain with the on-disk item discards the replayed effect of earlier history events (GH-603): names the reverted fields and the authors whose mutations the reconciliation overwrites, so cross-author data loss after a lossy merge is loud instead of silent. */
52
62
  reconciliation?: HistoryRepairReconciliationReport;
53
63
  /** Value that configures or reports warnings for this contract. */
@@ -126,7 +136,9 @@ export interface HistoryRepairAllResult {
126
136
  scanned_streams: number;
127
137
  /** Value that configures or reports drifted streams for this contract. */
128
138
  drifted_streams: number;
129
- /** One compact row per drifted stream (clean streams are summarized by the counts only). */
139
+ /** Streams selected only because invalid provenance required normalization. */
140
+ provenance_invalid_streams: number;
141
+ /** One compact row per drifted or provenance-normalization target. */
130
142
  streams: HistoryRepairAllStreamResult[];
131
143
  /** Value that configures or reports totals for this contract. */
132
144
  totals: {
@@ -4,12 +4,12 @@
4
4
  * Implements the pm history repair 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]="dd5ab9c3-bc6f-59f1-be89-ad0ab2abe7b5")}catch(e){}}();
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]="de9b7f82-0f51-599d-b1fa-2d54e3acbdbc")}catch(e){}}();
8
8
  import jsonPatch from "fast-json-patch";
9
9
  import { patchPathToChangedField } from "../core/history/history-diff.js";
10
10
  import { pathExists, readFileIfExists } from "../core/fs/fs-utils.js";
11
11
  import { executeHistoryRewrite, writeHistoryRawWithRollback, } from "../core/history/history-rewrite.js";
12
- import { historyEntriesToRaw, normalizeReplayPatchOps, reanchorHistoryEntries, replayHash, toReplayDocument, verifyHistoryChain, } from "../core/history/replay.js";
12
+ import { historyEntriesToRaw, normalizeReplayPatchOps, reanchorHistoryEntries, replayHash, resolveHistoryRepairItemHashVersion, toReplayDocument, verifyHistoryChain, verifyHistoryChainWithVersion, } from "../core/history/replay.js";
13
13
  import { scanHistoryDrift } from "../core/history/drift-scan.js";
14
14
  import { invalidateHistoryDriftCache } from "../core/history/drift-cache.js";
15
15
  import { readHistoryEntries } from "../core/history/read.js";
@@ -23,6 +23,7 @@ import { listAllItemMetadataWithBody, readLocatedItem, } from "../core/store/ite
23
23
  import { getSettingsPath, resolvePmRoot } from "../core/store/paths.js";
24
24
  import { readSettings } from "../core/store/settings.js";
25
25
  import { resolveHistorySubject } from "./history-redact.js";
26
+ import { listInvalidProvenanceHistoryStreamIds, normalizeInvalidHistoryProvenance, } from "./governance/provenance-health.js";
26
27
  function replayFieldValue(document, field) {
27
28
  return field === "body"
28
29
  ? document.body
@@ -133,7 +134,7 @@ export function analyzeReconciliationDiscard(entries, finalReplay, currentItemRe
133
134
  : null,
134
135
  };
135
136
  }
136
- async function loadHistoryRepairItemReplay(subject, settings, historyEntries) {
137
+ async function loadHistoryRepairItemReplay(subject, settings, historyEntries, itemHashVersion) {
137
138
  const currentItemPath = subject.located?.itemPath ?? null;
138
139
  const loadedItem = subject.located
139
140
  ? await readLocatedItem(subject.located, { schema: settings.schema })
@@ -152,7 +153,7 @@ async function loadHistoryRepairItemReplay(subject, settings, historyEntries) {
152
153
  return {
153
154
  currentItemReplay,
154
155
  currentItemPath,
155
- matchedChainBefore: replayHash(currentItemReplay) === lastOriginalAfterHash,
156
+ matchedChainBefore: replayHash(currentItemReplay, itemHashVersion) === lastOriginalAfterHash,
156
157
  currentItemRawBeforeLock: loadedItem.raw,
157
158
  loadedItem,
158
159
  };
@@ -180,16 +181,19 @@ function buildHistoryRepairEntries(params) {
180
181
  patch: params.reconcileNeeded && params.currentItemReplay
181
182
  ? jsonPatch.compare(params.finalReplay, params.currentItemReplay)
182
183
  : [],
183
- before_hash: replayHash(params.finalReplay),
184
- after_hash: replayHash(afterReplay),
184
+ before_hash: replayHash(params.finalReplay, params.itemHashVersion),
185
+ after_hash: replayHash(afterReplay, params.itemHashVersion),
185
186
  message: params.message,
187
+ ...(params.explicitItemHashVersion
188
+ ? { item_hash_version: params.itemHashVersion }
189
+ : {}),
186
190
  ...(params.auditContext === undefined
187
191
  ? {}
188
192
  : { context: params.auditContext }),
189
193
  });
190
194
  return { rewrittenEntries, auditEntryAdded: true };
191
195
  }
192
- function collectHistoryRepairWarnings(changed, skippedOps) {
196
+ function collectHistoryRepairWarnings(changed, skippedOps, reconciliation) {
193
197
  const warnings = [];
194
198
  if (!changed) {
195
199
  warnings.push("history_repair_no_changes");
@@ -197,6 +201,9 @@ function collectHistoryRepairWarnings(changed, skippedOps) {
197
201
  if (skippedOps > 0) {
198
202
  warnings.push(`history_repair_skipped_unresolvable_ops:${skippedOps}`);
199
203
  }
204
+ if (reconciliation && reconciliation.discarded_events.length > 0) {
205
+ warnings.push(`history_repair_reconcile_discards_events:${reconciliation.discarded_events.length}`, `history_repair_discarded_authors:${reconciliation.discarded_authors.join(",")}`);
206
+ }
200
207
  return warnings;
201
208
  }
202
209
  async function applyHistoryRepairRewrite(params) {
@@ -241,11 +248,28 @@ export async function runHistoryRepair(id, options, global) {
241
248
  throw new PmCliError(`No history entries exist for ${subject.id}; nothing to repair.`, EXIT_CODE.USAGE);
242
249
  }
243
250
  const chainBefore = verifyHistoryChain(historyEntries);
244
- const reanchor = reanchorHistoryEntries(historyEntries);
245
- const itemReplayContext = await loadHistoryRepairItemReplay(subject, settings, historyEntries);
251
+ const chainVersionBefore = verifyHistoryChainWithVersion(historyEntries);
252
+ const provenanceNormalization = options.normalizeProvenance
253
+ ? normalizeInvalidHistoryProvenance(historyEntries)
254
+ : {
255
+ entries: historyEntries,
256
+ receipt: {
257
+ changed: false,
258
+ events_changed: 0,
259
+ observations_removed: 0,
260
+ invalid_values: [],
261
+ },
262
+ };
263
+ const itemHashVersion = resolveHistoryRepairItemHashVersion(provenanceNormalization.entries);
264
+ const explicitVersionsBefore = new Set(provenanceNormalization.entries
265
+ .map((entry) => entry.item_hash_version)
266
+ .filter((version) => version !== undefined));
267
+ const reanchor = reanchorHistoryEntries(provenanceNormalization.entries, itemHashVersion);
268
+ const itemReplayContext = await loadHistoryRepairItemReplay(subject, settings, historyEntries, itemHashVersion);
246
269
  const finalReplay = reanchor.finalDocument;
247
270
  const reconcileNeeded = itemReplayContext.currentItemReplay !== null &&
248
- replayHash(finalReplay) !== replayHash(itemReplayContext.currentItemReplay);
271
+ replayHash(finalReplay, itemHashVersion) !==
272
+ replayHash(itemReplayContext.currentItemReplay, itemHashVersion);
249
273
  // GH-603: reconciling toward the on-disk item can silently overwrite the
250
274
  // replayed effect of other authors' events (classic after a lossy merge).
251
275
  // Surface exactly what is being discarded before any write happens.
@@ -257,6 +281,7 @@ export async function runHistoryRepair(id, options, global) {
257
281
  reanchor.entriesPatchRepaired > 0,
258
282
  reconcileNeeded,
259
283
  options.forceAuditEntry === true,
284
+ provenanceNormalization.receipt.changed,
260
285
  ].some(Boolean);
261
286
  const author = resolveAuthor(options.author, settings.author_default);
262
287
  const dryRun = Boolean(options.dryRun);
@@ -275,17 +300,20 @@ export async function runHistoryRepair(id, options, global) {
275
300
  author,
276
301
  message: repairMessage,
277
302
  auditOperation: options.auditOperation ?? "history_repair",
278
- auditContext: options.auditContext,
303
+ auditContext: provenanceNormalization.receipt.changed
304
+ ? {
305
+ ...options.auditContext,
306
+ provenance_normalization: provenanceNormalization.receipt,
307
+ }
308
+ : options.auditContext,
309
+ itemHashVersion,
310
+ explicitItemHashVersion: reanchor.explicitItemHashVersion,
279
311
  });
280
312
  const historyVerify = verifyHistoryChain(rewrittenEntries);
281
313
  if (!historyVerify.ok) {
282
314
  throw new PmCliError(`history-repair produced an invalid rewritten chain (${historyVerify.errors.join(", ")}).`, EXIT_CODE.GENERIC_FAILURE);
283
315
  }
284
- const warnings = collectHistoryRepairWarnings(changed, reanchor.skippedOps);
285
- if (reconciliation && reconciliation.discarded_events.length > 0) {
286
- warnings.push(`history_repair_reconcile_discards_events:${reconciliation.discarded_events.length}`);
287
- warnings.push(`history_repair_discarded_authors:${reconciliation.discarded_authors.join(",")}`);
288
- }
316
+ const warnings = collectHistoryRepairWarnings(changed, reanchor.skippedOps, reconciliation);
289
317
  if (changed && !dryRun) {
290
318
  warnings.push(...(await applyHistoryRepairRewrite({
291
319
  pmRoot,
@@ -317,12 +345,21 @@ export async function runHistoryRepair(id, options, global) {
317
345
  audit_entry_added: auditEntryAdded,
318
346
  verify_ok: historyVerify.ok,
319
347
  verify_errors: historyVerify.errors,
348
+ item_hash_version_before: chainVersionBefore.item_hash_version ?? null,
349
+ item_hash_version_after: itemHashVersion,
350
+ version_disposition: explicitVersionsBefore.size > 1
351
+ ? "selected_for_ambiguous_stream"
352
+ : "preserved",
320
353
  },
321
354
  item: {
322
355
  exists: itemReplayContext.currentItemPath !== null,
323
356
  path: itemReplayContext.currentItemPath,
324
357
  matched_chain_before: itemReplayContext.matchedChainBefore,
325
358
  },
359
+ provenance_normalization: {
360
+ requested: options.normalizeProvenance === true,
361
+ ...provenanceNormalization.receipt,
362
+ },
326
363
  ...(reconciliation ? { reconciliation } : {}),
327
364
  warnings: [...new Set(warnings)].sort((left, right) => left.localeCompare(right)),
328
365
  generated_at: nowIso(),
@@ -348,10 +385,16 @@ export async function runHistoryRepairAll(options, global) {
348
385
  const itemReadWarnings = [];
349
386
  const items = await listAllItemMetadataWithBody(pmRoot, settings.item_format, typeRegistry.type_to_folder, itemReadWarnings, settings.schema, { forceSourceScan: true });
350
387
  const drift = await scanHistoryDrift(pmRoot, items);
388
+ const invalidProvenanceIds = options.normalizeProvenance
389
+ ? await listInvalidProvenanceHistoryStreamIds(pmRoot)
390
+ : [];
391
+ const targetedIds = [
392
+ ...new Set([...drift.driftedItems, ...invalidProvenanceIds]),
393
+ ].sort((left, right) => left.localeCompare(right));
351
394
  const streams = [];
352
395
  const repairWarnings = [];
353
396
  const totals = { repaired: 0, skipped_clean: 0, failed: 0 };
354
- for (const driftedId of drift.driftedItems) {
397
+ for (const driftedId of targetedIds) {
355
398
  try {
356
399
  const result = await runHistoryRepair(driftedId, {
357
400
  ...options,
@@ -392,6 +435,7 @@ export async function runHistoryRepairAll(options, global) {
392
435
  dry_run: Boolean(options.dryRun),
393
436
  scanned_streams: items.length,
394
437
  drifted_streams: drift.driftedItems.length,
438
+ provenance_invalid_streams: invalidProvenanceIds.length,
395
439
  streams,
396
440
  totals,
397
441
  warnings: [...new Set([...itemReadWarnings, ...repairWarnings])].sort((left, right) => left.localeCompare(right)),
@@ -399,4 +443,4 @@ export async function runHistoryRepairAll(options, global) {
399
443
  };
400
444
  }
401
445
  //# sourceMappingURL=history-repair.js.map
402
- //# debugId=dd5ab9c3-bc6f-59f1-be89-ad0ab2abe7b5
446
+ //# debugId=de9b7f82-0f51-599d-b1fa-2d54e3acbdbc
@@ -4,7 +4,7 @@
4
4
  * Implements the pm linked artifacts 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]="585364aa-e5ff-56b6-8276-8f741fbd6be4")}catch(e){}}();
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]="256b39b7-882e-553c-9dea-813bfd363dd7")}catch(e){}}();
8
8
  import fs from "node:fs/promises";
9
9
  import path from "node:path";
10
10
  import fg from "fast-glob";
@@ -57,9 +57,20 @@ export function looksLikeStructuredPathEntry(raw) {
57
57
  if (/^(?:[-*+]\s+)?(?:path|scope|note)\s*[:=]/i.test(raw)) {
58
58
  return true;
59
59
  }
60
- // A first-key typo (e.g. `lable=main,path=…`) must still be parsed so the
61
- // unknown key is rejected rather than swallowed as a bare path (GH-258).
62
- return looksLikeGenericKeyValueEntry(raw);
60
+ // An equals sign is valid inside filesystem paths and URL query strings.
61
+ // Preserve unmistakable whitespace-free path/URL shapes while routing
62
+ // leading assignment syntax through the structured-key allowlist so typos
63
+ // and malformed URL-plus-note input remain atomic failures (GH-258,
64
+ // GH-1000).
65
+ const equalsIndex = raw.indexOf("=");
66
+ if (equalsIndex >= 0 &&
67
+ !/\s/u.test(raw) &&
68
+ (/^[A-Za-z][A-Za-z0-9+.-]*:\/\//u.test(raw) ||
69
+ /^(?:[A-Za-z]:[\\/]|[\\/]{1,2}|\.\.?(?:[\\/]))/u.test(raw) ||
70
+ [raw.indexOf("/"), raw.indexOf("\\")].some((separatorIndex) => separatorIndex >= 0 && separatorIndex < equalsIndex))) {
71
+ return false;
72
+ }
73
+ return raw.includes("=") || looksLikeGenericKeyValueEntry(raw);
63
74
  }
64
75
  function expandBareCommaSeparatedAddEntries(raw) {
65
76
  return raw.flatMap((entry) => {
@@ -479,4 +490,4 @@ export function renameArtifactsResultKey(result, key) {
479
490
  return out;
480
491
  }
481
492
  //# sourceMappingURL=linked-artifacts.js.map
482
- //# debugId=585364aa-e5ff-56b6-8276-8f741fbd6be4
493
+ //# debugId=256b39b7-882e-553c-9dea-813bfd363dd7
@@ -1,4 +1,17 @@
1
1
  import type { CliFlagContract } from "./cli-contracts/flag-contracts.js";
2
+ /** Validated transport envelope carried by an opaque query cursor. */
3
+ export interface QueryCursorEnvelope {
4
+ /** Serialized cursor contract version. */
5
+ version: number;
6
+ /** Stable fingerprint of the query semantics that produced the cursor. */
7
+ fingerprint: string;
8
+ /** Stable id of the last row emitted by the producer. */
9
+ after_id: string;
10
+ /** Zero-based position of the last emitted row when available. */
11
+ after_index?: number;
12
+ /** Opaque producer-defined snapshot token for stable continuation. */
13
+ snapshot?: string;
14
+ }
2
15
  /** Decoded cursor state for advanced package and retrieval-window integrations. */
3
16
  export interface QueryCursorState {
4
17
  /** Stable id of the last row emitted by the previous page. */
@@ -27,6 +40,8 @@ export declare function selectCursorSemanticOptions(options: Readonly<Record<str
27
40
  export declare function createQueryFingerprint(command: string, contract: unknown): string;
28
41
  /** Encode the last emitted item id into a versioned opaque base64url cursor. */
29
42
  export declare function encodeQueryCursor(fingerprint: string, afterId: string, afterIndex?: number, snapshot?: string): string;
43
+ /** Decode and validate an opaque cursor without imposing caller query identity. */
44
+ export declare function decodeQueryCursorEnvelope(cursor: unknown): QueryCursorEnvelope;
30
45
  /** Decode and validate complete cursor state against a query fingerprint. */
31
46
  export declare function decodeQueryCursorState(cursor: unknown, expectedFingerprint: string): QueryCursorState;
32
47
  /** Decode and validate a cursor against the normalized query fingerprint. */
@@ -5,7 +5,7 @@
5
5
  * package-authored query surfaces.
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]="83fe180b-9d95-5d19-9d3b-ba3821700e61")}catch(e){}}();
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]="d3329fac-693d-566c-a30a-43f8fb37938f")}catch(e){}}();
9
9
  import { createHash } from "node:crypto";
10
10
  import { PmCliError } from "../core/shared/errors.js";
11
11
  import { EXIT_CODE } from "../core/shared/constants.js";
@@ -78,8 +78,8 @@ function isQueryCursorEnvelope(value) {
78
78
  (envelope.snapshot === undefined ||
79
79
  (typeof envelope.snapshot === "string" && envelope.snapshot.length > 0)));
80
80
  }
81
- /** Decode and validate complete cursor state against a query fingerprint. */
82
- export function decodeQueryCursorState(cursor, expectedFingerprint) {
81
+ /** Decode and validate an opaque cursor without imposing caller query identity. */
82
+ export function decodeQueryCursorEnvelope(cursor) {
83
83
  if (typeof cursor !== "string") {
84
84
  throw invalidCursor("Query cursor is malformed.");
85
85
  }
@@ -99,7 +99,11 @@ export function decodeQueryCursorState(cursor, expectedFingerprint) {
99
99
  if (!isQueryCursorEnvelope(parsed)) {
100
100
  throw invalidCursor("Query cursor version or payload is unsupported.");
101
101
  }
102
- const envelope = parsed;
102
+ return parsed;
103
+ }
104
+ /** Decode and validate complete cursor state against a query fingerprint. */
105
+ export function decodeQueryCursorState(cursor, expectedFingerprint) {
106
+ const envelope = decodeQueryCursorEnvelope(cursor);
103
107
  if (envelope.fingerprint !== expectedFingerprint) {
104
108
  throw invalidCursor(`Query cursor does not match the current filters, sort, or query (${envelope.fingerprint} != ${expectedFingerprint}).`);
105
109
  }
@@ -156,4 +160,4 @@ export const QUERY_CURSOR_CONTRACT = Object.freeze({
156
160
  max_length: MAX_CURSOR_LENGTH,
157
161
  });
158
162
  //# sourceMappingURL=pagination.js.map
159
- //# debugId=83fe180b-9d95-5d19-9d3b-ba3821700e61
163
+ //# debugId=d3329fac-693d-566c-a30a-43f8fb37938f
@@ -399,6 +399,10 @@ export interface ContextRankingSummary {
399
399
  score: number;
400
400
  contributions: ContextRelevanceContributions;
401
401
  }>;
402
+ /** Number of candidates considered before answer-sized projection. */
403
+ candidate_count: number;
404
+ /** Number of candidate explanations omitted because their rows were not served. */
405
+ omitted_count: number;
402
406
  /** Rebuildable feature-store freshness and provenance. */
403
407
  feature_store?: {
404
408
  source: "derived_index" | "scan_fallback";
@@ -462,7 +466,7 @@ export declare function packRankedContextItems(report: ContextRelevanceReport<It
462
466
  /** Projects the SDK packer report onto the stable low-token command envelope. */
463
467
  export declare function toContextPackingSummary(report: ContextPackingReport<ItemMetadata>): ContextPackingSummary;
464
468
  /** Project a full scorer report onto the low-token command explanation shape. */
465
- export declare function toContextRankingSummary<TItem>(report: ContextRelevanceReport<TItem>, featureStore?: ContextSignalStoreReadResult): ContextRankingSummary;
469
+ export declare function toContextRankingSummary<TItem>(report: ContextRelevanceReport<TItem>, featureStore?: ContextSignalStoreReadResult, servedItemIds?: ReadonlySet<string>): ContextRankingSummary;
466
470
  declare function completionPct(closed: number, total: number): number;
467
471
  /** Indexes items by their parent id, yielding a parent→direct-children map used by the hierarchy/progress rollups and by focus-row child completion. Items without a parent are skipped. Exported so sibling read commands reuse the same index. */
468
472
  export declare function buildChildrenByParent(allItems: ItemMetadata[]): Map<string, ItemMetadata[]>;