@unbrained/pm-cli 2026.9.1 → 2026.9.3

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 (133) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +27 -0
  3. package/dist/cli/after-command-context-usage.js +16 -3
  4. package/dist/cli-bundle/bundle-manifest.json +153 -153
  5. package/dist/cli-bundle/chunks/{chunk-6XIIGE7U.js → chunk-34HASX3S.js} +2 -2
  6. package/dist/cli-bundle/chunks/chunk-AY324UJ5.js +9 -0
  7. package/dist/cli-bundle/chunks/{chunk-TAG4VC22.js → chunk-DKGP3QLE.js} +27 -27
  8. package/dist/cli-bundle/chunks/chunk-E5RBBCXO.js +230 -0
  9. package/dist/cli-bundle/chunks/{chunk-DTGWEL23.js → chunk-EDPIS7EB.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-X4RCGLTX.js → chunk-IEHHE6GA.js} +5 -5
  11. package/dist/cli-bundle/chunks/{chunk-U45JXJCC.js → chunk-L7B7343B.js} +2 -2
  12. package/dist/cli-bundle/chunks/{chunk-2MC2LCXZ.js → chunk-LENC656S.js} +41 -41
  13. package/dist/cli-bundle/chunks/chunk-LISESA7W.js +35 -0
  14. package/dist/cli-bundle/chunks/{chunk-3WICXLVT.js → chunk-UPPM2FOZ.js} +2 -2
  15. package/dist/cli-bundle/chunks/{chunk-Y7VOMSZT.js → chunk-Y4PJ6HPK.js} +2 -2
  16. package/dist/cli-bundle/chunks/{register-list-query-XYNX4ASQ.js → register-list-query-W2ZTOMKP.js} +2 -2
  17. package/dist/cli-bundle/chunks/{register-mutation-2MVLRS3J.js → register-mutation-RVND5NCG.js} +2 -2
  18. package/dist/cli-bundle/chunks/{register-operations-WCIDXBU3.js → register-operations-TTROIVC4.js} +2 -2
  19. package/dist/cli-bundle/chunks/{register-setup-KVNC5KPL.js → register-setup-D3ZFHY3L.js} +2 -2
  20. package/dist/cli-bundle/focused-chunks/chunk-3ZBI35HU.js +176 -0
  21. package/dist/cli-bundle/focused-chunks/{chunk-SVXJYD6G.js → chunk-4HJFY4MB.js} +2 -2
  22. package/dist/cli-bundle/focused-chunks/chunk-4RRHC3S4.js +6 -0
  23. package/dist/cli-bundle/focused-chunks/chunk-4WR46RMG.js +9 -0
  24. package/dist/cli-bundle/focused-chunks/chunk-5RFXUPN5.js +3 -0
  25. package/dist/cli-bundle/focused-chunks/chunk-BWKHEIVF.js +2 -0
  26. package/dist/cli-bundle/focused-chunks/{chunk-4O4CJAR6.js → chunk-D7KXFBXV.js} +2 -2
  27. package/dist/cli-bundle/focused-chunks/{chunk-MKHG3T76.js → chunk-GHCZ3YFR.js} +3 -3
  28. package/dist/cli-bundle/focused-chunks/{chunk-KB5OFSFD.js → chunk-GT7MXDLW.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/chunk-KBLZRU62.js +2 -0
  30. package/dist/cli-bundle/focused-chunks/chunk-KZ2NB3ET.js +2 -0
  31. package/dist/cli-bundle/focused-chunks/chunk-M5M6SVHS.js +3 -0
  32. package/dist/cli-bundle/focused-chunks/{chunk-BEVHCEWG.js → chunk-OL5EH6I3.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/{chunk-MEASX544.js → chunk-Q45NHPF2.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/{chunk-Y6JJIX6I.js → chunk-QKHCSUGJ.js} +48 -48
  35. package/dist/cli-bundle/focused-chunks/chunk-S27XMBIN.js +8 -0
  36. package/dist/cli-bundle/focused-chunks/chunk-TXE4TSHM.js +12 -0
  37. package/dist/cli-bundle/focused-chunks/chunk-UCLO3XDU.js +2 -0
  38. package/dist/cli-bundle/main.js +15 -15
  39. package/dist/cli-bundle/sdk-authoring.js +1 -1
  40. package/dist/cli-bundle/sdk-contracts.js +1 -1
  41. package/dist/cli-bundle/sdk-core.js +28 -28
  42. package/dist/cli-bundle/sdk-governance.js +1 -1
  43. package/dist/cli-bundle/sdk-graph.js +1 -1
  44. package/dist/cli-bundle/sdk-merge.js +35 -33
  45. package/dist/cli-bundle/sdk-query.js +1 -1
  46. package/dist/cli-bundle/sdk-runtime.js +1 -1
  47. package/dist/cli-bundle/sdk-testing.js +1 -1
  48. package/dist/cli-bundle/sdk.js +9 -9
  49. package/dist/core/diagnostics/remediation.js +9 -4
  50. package/dist/core/history/event-classification.d.ts +21 -0
  51. package/dist/core/history/event-classification.js +109 -0
  52. package/dist/core/history/event-index.d.ts +14 -3
  53. package/dist/core/history/event-index.js +543 -88
  54. package/dist/core/history/history.js +47 -18
  55. package/dist/core/history/workspace-history.js +7 -6
  56. package/dist/core/lock/lock.d.ts +22 -2
  57. package/dist/core/lock/lock.js +121 -19
  58. package/dist/core/output/output.js +31 -7
  59. package/dist/core/shared/time.d.ts +2 -0
  60. package/dist/core/shared/time.js +8 -2
  61. package/dist/core/store/item-metadata-query-index.js +5 -5
  62. package/dist/sdk/context/recency.d.ts +9 -0
  63. package/dist/sdk/context/recency.js +34 -0
  64. package/dist/sdk/context/usage-egress.d.ts +9 -0
  65. package/dist/sdk/context/usage-egress.js +30 -0
  66. package/dist/sdk/context-intent-contracts.js +7 -3
  67. package/dist/sdk/context-relevance.d.ts +23 -0
  68. package/dist/sdk/context-relevance.js +94 -23
  69. package/dist/sdk/context-signal-store.d.ts +7 -3
  70. package/dist/sdk/context-signal-store.js +155 -42
  71. package/dist/sdk/context-usage.d.ts +54 -0
  72. package/dist/sdk/context-usage.js +245 -16
  73. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +26 -14
  74. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +14 -2
  75. package/dist/sdk/governance/health.js +77 -11
  76. package/dist/sdk/governance/validate.js +4 -2
  77. package/dist/sdk/index.d.ts +2 -0
  78. package/dist/sdk/index.js +4 -2
  79. package/dist/sdk/init.d.ts +2 -0
  80. package/dist/sdk/init.js +18 -9
  81. package/dist/sdk/merge/index.d.ts +1 -1
  82. package/dist/sdk/merge/index.js +2 -2
  83. package/dist/sdk/merge/receipts.d.ts +24 -0
  84. package/dist/sdk/merge/receipts.js +122 -30
  85. package/dist/sdk/query/context.d.ts +3 -1
  86. package/dist/sdk/query/context.js +21 -9
  87. package/dist/sdk/query/next.js +18 -9
  88. package/dist/sdk/runtime-input.d.ts +2 -0
  89. package/dist/sdk/runtime-input.js +25 -2
  90. package/dist/sdk/runtime.d.ts +1 -0
  91. package/dist/sdk/runtime.js +17 -26
  92. package/dist/types.d.ts +2 -0
  93. package/dist/types.js +2 -2
  94. package/docs/CONTEXT_RECOVERY_PRIMITIVES.md +11 -2
  95. package/docs/CONTEXT_RELEVANCE.md +44 -1
  96. package/docs/MERGE_SAFETY.md +16 -2
  97. package/docs/PERFORMANCE.md +6 -3
  98. package/docs/READ_OUTPUT_CONTRACTS.md +9 -1
  99. package/docs/SDK.md +11 -8
  100. package/docs/SDK_CONTEXT.md +7 -0
  101. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +5 -3
  102. package/marketplace.json +2 -2
  103. package/package.json +4 -4
  104. package/packages/pm-beads/package.json +1 -1
  105. package/packages/pm-calendar/package.json +1 -1
  106. package/packages/pm-command-kit/package.json +1 -1
  107. package/packages/pm-digital-twin/package.json +1 -1
  108. package/packages/pm-governance-audit/package.json +1 -1
  109. package/packages/pm-guide-shell/package.json +1 -1
  110. package/packages/pm-kanban/package.json +1 -1
  111. package/packages/pm-lifecycle-hooks/package.json +1 -1
  112. package/packages/pm-linked-test-adapters/package.json +1 -1
  113. package/packages/pm-search-advanced/package.json +1 -1
  114. package/packages/pm-templates/package.json +1 -1
  115. package/packages/pm-todos/package.json +1 -1
  116. package/packages/pm-vcs/package.json +1 -1
  117. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  118. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  119. package/sdk/public-surface.json +268 -28
  120. package/dist/cli-bundle/chunks/chunk-ALKKAUFN.js +0 -35
  121. package/dist/cli-bundle/chunks/chunk-GOACULJW.js +0 -13
  122. package/dist/cli-bundle/chunks/chunk-NOPL37X4.js +0 -205
  123. package/dist/cli-bundle/focused-chunks/chunk-2FEZ5SKM.js +0 -3
  124. package/dist/cli-bundle/focused-chunks/chunk-6GCRSLPG.js +0 -2
  125. package/dist/cli-bundle/focused-chunks/chunk-7VATS5QY.js +0 -16
  126. package/dist/cli-bundle/focused-chunks/chunk-FWPLDEXF.js +0 -2
  127. package/dist/cli-bundle/focused-chunks/chunk-JEFKLWMM.js +0 -2
  128. package/dist/cli-bundle/focused-chunks/chunk-PF3E6Q36.js +0 -8
  129. package/dist/cli-bundle/focused-chunks/chunk-QDFJIRKN.js +0 -4
  130. package/dist/cli-bundle/focused-chunks/chunk-RMRCQPWU.js +0 -2
  131. package/dist/cli-bundle/focused-chunks/chunk-S4U5CN5Q.js +0 -2
  132. package/dist/cli-bundle/focused-chunks/chunk-T2LXXSOD.js +0 -158
  133. package/dist/cli-bundle/focused-chunks/chunk-Z2USIBR2.js +0 -5
package/dist/sdk/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Defines public SDK APIs and package-author helpers for Index.
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]="8a1a02de-32cb-5714-b950-6041ae8ce229")}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]="62e450f7-9ed9-5855-923a-7b2ffb8b49f4")}catch(e){}}();
8
8
  export { PM_COMMAND_CAPABILITY_CONTRACTS, PM_COMMAND_VISIBILITY_CONTRACTS, PM_MCP_PROMPT_CONTRACTS, PM_MCP_RESOURCE_CONTRACTS, PM_MCP_TOOL_COMMAND_CONTRACTS, listPmCommandsForFamily, listPmCommandsForTier, listPmMcpToolsForProfile, renderPmCommandVisibilityMarkdown, resolvePmCommandCapabilityFamily, resolvePmCommandVisibilityTier, } from "./agent-capability-contracts.js";
9
9
  export * from "./mcp/protocol.js";
10
10
  export * from "./mcp/interactions.js";
@@ -78,6 +78,7 @@ export * from "./environment/source-context.js";
78
78
  export * from "./environment/host-environment-errors.js";
79
79
  export * from "./cli-contracts/command-exit-contracts.js";
80
80
  export * from "./context-relevance.js";
81
+ export * from "./context/recency.js";
81
82
  export * from "./context-intent-contracts.js";
82
83
  export * from "./context-intent-runtime.js";
83
84
  export * from "./context-signal-store.js";
@@ -91,6 +92,7 @@ export * from "./read-output-session.js";
91
92
  export * from "./output-token-accounting.js";
92
93
  export * from "./context-packing.js";
93
94
  export * from "./context-usage.js";
95
+ export { classifyHistoryEvent, HISTORY_EVENT_CLASSIFICATION_VERSION, MAINTENANCE_HISTORY_OPERATIONS, SUBSTANTIVE_HISTORY_OPERATIONS, } from "../core/history/event-classification.js";
94
96
  export * from "./dependency-provenance.js";
95
97
  export * from "./duplicates.js";
96
98
  export * from "./lifecycle/reopen.js";
@@ -177,4 +179,4 @@ export * from "./mcp/discovery.js";
177
179
  export * from "./query.js";
178
180
  export * from "./testing.js";
179
181
  //# sourceMappingURL=index.js.map
180
- //# debugId=8a1a02de-32cb-5714-b950-6041ae8ce229
182
+ //# debugId=62e450f7-9ed9-5855-923a-7b2ffb8b49f4
@@ -5,6 +5,8 @@ import type { GovernancePreset, PmSettings } from "../types/index.js";
5
5
  import { type ExtensionCommandResult } from "./extension.js";
6
6
  import { type InitAgentGuidanceMode, type InitAgentGuidanceSummary } from "./init-agent-guidance.js";
7
7
  import { installMergeFence } from "./merge/install.js";
8
+ /** Symbol key for the captured working directory of an in-process init call. */
9
+ export declare const INIT_INVOCATION_CWD: unique symbol;
8
10
  /** Documents the init installed packages summary payload exchanged by command, SDK, and package integrations. */
9
11
  export interface InitInstalledPackagesSummary {
10
12
  /** Value that configures or reports installed all for this contract. */
package/dist/sdk/init.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Implements the pm init 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]="75c0d2d2-6a89-508f-b7dd-b43d55978b44")}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]="d06d4db7-8ab7-5a9f-84df-508bd305ea23")}catch(e){}}();
8
8
  import fs from "node:fs/promises";
9
9
  import path from "node:path";
10
10
  import readline from "node:readline/promises";
@@ -27,6 +27,8 @@ import { renderPmCommand } from "./command-line.js";
27
27
  import { runExtension } from "./extension.js";
28
28
  import { INIT_AGENT_GUIDANCE_MODE_VALUES, runInitAgentGuidance, } from "./init-agent-guidance.js";
29
29
  import { findGitWorkspaceRoot, installMergeFence } from "./merge/install.js";
30
+ /** Symbol key for the captured working directory of an in-process init call. */
31
+ export const INIT_INVOCATION_CWD = Symbol.for("pm.sdk.init-invocation-cwd");
30
32
  /** Implements summarize init result for the public runtime surface of this module. */
31
33
  export function summarizeInitResult(result) {
32
34
  return {
@@ -709,9 +711,21 @@ async function installInitMergeFence(pmRoot, gitWorkspaceRoot, warnings, install
709
711
  warnings.push(`merge_fence_skipped:install_failed:${error.context.code ?? "pm_error"}:${error.message}:run pm merge install after resolving the Git repository error`);
710
712
  }
711
713
  }
714
+ async function ensureInitWorkspaceGitignore(workspaceRoot, pmRoot, agentGuidanceMode, warnings) {
715
+ if (workspaceRoot === undefined ||
716
+ workspaceRoot === null ||
717
+ agentGuidanceMode === "status") {
718
+ return;
719
+ }
720
+ const gitignore = await ensurePmGitignore(workspaceRoot, { pmRoot });
721
+ if (gitignore.changed) {
722
+ warnings.push(`updated:gitignore:${gitignore.path}`);
723
+ }
724
+ }
712
725
  /** Implements run init for the public runtime surface of this module. */
713
726
  export async function runInit(prefixArg, global, options = {}) {
714
- const cwd = process.cwd();
727
+ const invocationCwd = global[INIT_INVOCATION_CWD];
728
+ const cwd = typeof invocationCwd === "string" ? invocationCwd : process.cwd();
715
729
  const invocation = resolveInitInvocation(cwd, global, prefixArg, options.workspace);
716
730
  const pmRoot = invocation.pmRoot;
717
731
  prefixArg = resolveInitPrefixInput(invocation.prefixArg, options.idPrefix);
@@ -773,12 +787,7 @@ export async function runInit(prefixArg, global, options = {}) {
773
787
  settings = await readSettings(pmRoot);
774
788
  }
775
789
  await ensureInitTypeDirectories({ pmRoot, settings, createdDirs, warnings });
776
- if (workspaceRoot && normalizedOptions.agentGuidanceMode !== "status") {
777
- const gitignore = await ensurePmGitignore(workspaceRoot, { pmRoot });
778
- if (gitignore.changed) {
779
- warnings.push(`updated:gitignore:${gitignore.path}`);
780
- }
781
- }
790
+ await ensureInitWorkspaceGitignore(workspaceRoot, pmRoot, normalizedOptions.agentGuidanceMode, warnings);
782
791
  if (!settingsExists &&
783
792
  options.mergeFence !== false &&
784
793
  normalizedOptions.agentGuidanceMode !== "status") {
@@ -809,4 +818,4 @@ export async function runInit(prefixArg, global, options = {}) {
809
818
  };
810
819
  }
811
820
  //# sourceMappingURL=init.js.map
812
- //# debugId=75c0d2d2-6a89-508f-b7dd-b43d55978b44
821
+ //# debugId=d06d4db7-8ab7-5a9f-84df-508bd305ea23
@@ -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 { inspectMergeReceiptEvidence, listMergeReceipts, markMergeReceiptReconciled, runMergeReceiptEvidenceReport, runMergeReceiptReport, summarizeMergeReceipt, type MergeDecisionReceipt, type MergeDecisionReceiptSummary, type MergeReceiptEvidenceReport, type MergeReceiptEvidenceScan, type MergeReceiptReport, } from "./receipts.js";
10
+ export { inspectMergeReceiptEvidence, listMergeReceipts, markMergeReceiptReconciled, runMergeReceiptEvidenceReport, runMergeReceiptReport, summarizeMergeReceipt, type MergeDecisionReceipt, type MergeDecisionReceiptSummary, type MergeReceiptEvidenceReport, type MergeReceiptEvidenceScan, type MergeReceiptInvalidEvidence, 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]="a26f1126-3c87-5b0d-8712-2846fc9dcbb3")}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]="0a17e896-d54a-5796-8be3-535179c4d6e0")}catch(e){}}();
11
11
  export { ITEM_LATEST_TIMESTAMP_FIELDS, ITEM_UNION_COLLECTION_FIELDS, mergeHistoryStreams, mergeItemDocuments, mergeJsonDocuments, mergeRelationshipEventStreams, } from "./three-way.js";
12
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=a26f1126-3c87-5b0d-8712-2846fc9dcbb3
17
+ //# debugId=0a17e896-d54a-5796-8be3-535179c4d6e0
@@ -1,4 +1,7 @@
1
+ import type { Stats } from "node:fs";
1
2
  import type { ItemMergeConflictDecision, MergePreferredSide } from "./three-way.js";
3
+ /** Return whether a receipt id is safe to expose in cleartext diagnostics. */
4
+ export declare function isSafeReceiptId(value: string): boolean;
2
5
  /** One clone-local merge receipt with recoverable branch values. */
3
6
  export interface MergeDecisionReceipt {
4
7
  /** Receipt schema version. */
@@ -80,6 +83,10 @@ export interface MergeReceiptEvidenceReport {
80
83
  count: number;
81
84
  /** Number of candidates rejected by bounded-file, schema, identity, or copy-consistency validation. */
82
85
  invalid_evidence_count: number;
86
+ /** Bounded privacy-safe identities and reason codes for rejected evidence. */
87
+ invalid_evidence: MergeReceiptInvalidEvidence[];
88
+ /** Whether additional rejected evidence was omitted from the bounded detail list. */
89
+ invalid_evidence_truncated: boolean;
83
90
  /** Whether the clone-local Git receipt directory was resolved successfully; always emitted by current implementations and optional for structural compatibility. */
84
91
  clone_local_evidence_resolved?: boolean;
85
92
  /** Receipts including recoverable values from the local clone only. */
@@ -93,9 +100,24 @@ export interface MergeReceiptEvidenceScan {
93
100
  receipts: MergeDecisionReceipt[];
94
101
  /** Number of JSON receipt candidates that could not be validated safely. */
95
102
  invalid_evidence_count: number;
103
+ /** Bounded privacy-safe identities and reason codes for rejected evidence. */
104
+ invalid_evidence: MergeReceiptInvalidEvidence[];
105
+ /** Whether additional rejected evidence was omitted from the bounded detail list. */
106
+ invalid_evidence_truncated: boolean;
96
107
  /** Whether the clone-local Git receipt directory was resolved successfully; always emitted by current implementations and optional for structural compatibility. */
97
108
  clone_local_evidence_resolved?: boolean;
98
109
  }
110
+ /** Stable privacy-safe classification for one rejected receipt candidate or source. */
111
+ export interface MergeReceiptInvalidEvidence {
112
+ /** Evidence store that produced the rejected candidate. */
113
+ evidence_source: "clone_local" | "durable" | "clone_local_and_durable";
114
+ /** Stable failure class suitable for remediation routing and graph analytics. */
115
+ reason: "directory_unreadable" | "candidate_not_bounded_regular_file" | "candidate_unreadable" | "candidate_invalid_json" | "schema_or_identity_invalid" | "copy_provenance_mismatch";
116
+ /** Receipt identity when the bounded filename itself is a valid receipt id. */
117
+ receipt_id?: string;
118
+ /** SHA-256 locator for an unsafe or malformed candidate filename. */
119
+ candidate_name_hash?: string;
120
+ }
99
121
  declare function prepareReceiptSettlement(params: {
100
122
  receiptPath: string;
101
123
  receiptId: string;
@@ -120,6 +142,7 @@ export declare function writeMergeReceipt(params: {
120
142
  mergedFieldHashes?: Record<string, string>;
121
143
  decisions: ItemMergeConflictDecision[];
122
144
  }): Promise<MergeDecisionReceipt | null>;
145
+ declare function receiptDirectoryFailureMeansAbsent(directory: string, error: unknown, inspectAncestor?: (ancestor: string) => Promise<Pick<Stats, "isDirectory">>): Promise<boolean>;
123
146
  /** Inspect valid receipts and count invalid evidence without returning untrusted file contents. */
124
147
  export declare function inspectMergeReceiptEvidence(cwd: string, options?: {
125
148
  /** Include receipts whose reconciliation state is already settled. */
@@ -163,5 +186,6 @@ export declare function runMergeReceiptEvidenceReport(options: {
163
186
  /** Test-only seams for deterministic receipt-boundary fault coverage. */
164
187
  export declare const _testOnlyMergeReceipts: {
165
188
  prepareReceiptSettlement: typeof prepareReceiptSettlement;
189
+ receiptDirectoryFailureMeansAbsent: typeof receiptDirectoryFailureMeansAbsent;
166
190
  };
167
191
  export {};
@@ -7,10 +7,10 @@
7
7
  * value for the coordinator that performed the merge.
8
8
  */
9
9
 
10
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="624fc190-4c46-5a55-b757-72e621aec35d")}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]="df7d5bd9-8381-5961-bda1-9e8ed335afc9")}catch(e){}}();
11
11
  import { execFile } from "node:child_process";
12
12
  import { randomUUID } from "node:crypto";
13
- import { readdir } from "node:fs/promises";
13
+ import { readdir, stat } from "node:fs/promises";
14
14
  import path from "node:path";
15
15
  import { promisify } from "node:util";
16
16
  import { ensureDir, isFileAbsentError, isFileMissingError, pathExists, writeFileAtomic, } from "../../core/fs/fs-utils.js";
@@ -24,6 +24,7 @@ const RECEIPT_FIELD_MAX = 2_048;
24
24
  const RECEIPT_FILE_MAX_BYTES = 16 * 1024 * 1024;
25
25
  const RECEIPT_VALUE_MAX_DEPTH = 64;
26
26
  const RECEIPT_VALUE_MAX_NODES = 100_000;
27
+ const RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT = 100;
27
28
  const RECEIPT_KEYS = new Set([
28
29
  "version",
29
30
  "id",
@@ -42,6 +43,10 @@ const RECEIPT_KEYS = new Set([
42
43
  "value_availability",
43
44
  "evidence_source",
44
45
  ]);
46
+ /** Return whether a receipt id is safe to expose in cleartext diagnostics. */
47
+ export function isSafeReceiptId(value) {
48
+ return RECEIPT_ID_PATTERN.test(value);
49
+ }
45
50
  const RECEIPT_DECISION_KEYS = new Set([
46
51
  "field",
47
52
  "base",
@@ -163,7 +168,7 @@ function hasValidReceiptIdentity(value) {
163
168
  return !hasOnlyKeys(value, RECEIPT_KEYS) || value.version !== 1
164
169
  ? false
165
170
  : typeof value.id === "string" &&
166
- RECEIPT_ID_PATTERN.test(value.id) &&
171
+ isSafeReceiptId(value.id) &&
167
172
  typeof value.item_id === "string" &&
168
173
  RECEIPT_ITEM_ID_PATTERN.test(value.item_id) &&
169
174
  isSafeReceiptItemPath(value.item_path, value.item_id);
@@ -372,54 +377,115 @@ async function readReceiptsFromDirectory(directory, evidenceSource) {
372
377
  names = await readdir(directory);
373
378
  }
374
379
  catch (error) {
380
+ const absent = await receiptDirectoryFailureMeansAbsent(directory, error);
375
381
  return {
376
382
  receipts: [],
377
- invalid_evidence_count: isFileMissingError(error) ? 0 : 1,
383
+ invalid_evidence_count: absent ? 0 : 1,
384
+ invalid_evidence: absent
385
+ ? []
386
+ : [{ evidence_source: evidenceSource, reason: "directory_unreadable" }],
387
+ invalid_evidence_truncated: false,
378
388
  };
379
389
  }
380
390
  const receipts = [];
381
391
  let invalidEvidenceCount = 0;
392
+ const invalidEvidence = [];
393
+ const recordInvalidEvidence = (name, reason) => {
394
+ invalidEvidenceCount += 1;
395
+ if (invalidEvidence.length >= RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT)
396
+ return;
397
+ const receiptId = name.slice(0, -".json".length);
398
+ invalidEvidence.push({
399
+ evidence_source: evidenceSource,
400
+ reason,
401
+ ...(isSafeReceiptId(receiptId)
402
+ ? { receipt_id: receiptId }
403
+ : { candidate_name_hash: sha256Hex(name) }),
404
+ });
405
+ };
382
406
  for (const name of names.sort((left, right) => left.localeCompare(right))) {
383
407
  if (!name.endsWith(".json"))
384
408
  continue;
409
+ const candidate = await inspectReceiptCandidate(directory, name, evidenceSource);
410
+ if (candidate.receipt !== undefined) {
411
+ receipts.push(candidate.receipt);
412
+ }
413
+ else {
414
+ recordInvalidEvidence(name, candidate.reason);
415
+ }
416
+ }
417
+ return {
418
+ receipts,
419
+ invalid_evidence_count: invalidEvidenceCount,
420
+ invalid_evidence: invalidEvidence,
421
+ invalid_evidence_truncated: invalidEvidenceCount > invalidEvidence.length,
422
+ };
423
+ }
424
+ async function receiptDirectoryFailureMeansAbsent(directory, error, inspectAncestor = stat) {
425
+ if (!isFileMissingError(error))
426
+ return false;
427
+ let ancestor = directory;
428
+ while (true) {
385
429
  try {
386
- const receiptPath = path.join(directory, name);
387
- const raw = await readBoundedRegularReceiptFile(receiptPath);
388
- if (raw === null) {
389
- invalidEvidenceCount += 1;
390
- continue;
391
- }
392
- const parsed = JSON.parse(raw);
393
- if (!isMergeDecisionReceipt(parsed, evidenceSource) ||
394
- name !== receiptFileName(parsed.id)) {
395
- invalidEvidenceCount += 1;
396
- continue;
397
- }
398
- const { preferred: legacyPreference, evidence_source: _serializedEvidenceSource, ...receiptWithoutRuntimeKeys } = parsed;
399
- const normalizedReceipt = {
400
- ...receiptWithoutRuntimeKeys,
401
- requested_preference: parsed.requested_preference ?? legacyPreference ?? "ours",
402
- conflict_resolution: parsed.conflict_resolution ?? "preferred_side",
403
- evidence_source: evidenceSource,
404
- };
405
- receipts.push(normalizedReceipt);
430
+ return (await inspectAncestor(ancestor)).isDirectory();
406
431
  }
407
- catch {
408
- invalidEvidenceCount += 1;
432
+ catch (ancestorError) {
433
+ if (!isFileMissingError(ancestorError))
434
+ return false;
435
+ const parent = path.dirname(ancestor);
436
+ if (parent === ancestor)
437
+ return true;
438
+ ancestor = parent;
409
439
  }
410
440
  }
411
- return { receipts, invalid_evidence_count: invalidEvidenceCount };
441
+ }
442
+ async function inspectReceiptCandidate(directory, name, evidenceSource) {
443
+ let raw;
444
+ try {
445
+ raw = await readBoundedRegularReceiptFile(path.join(directory, name));
446
+ }
447
+ catch {
448
+ return { reason: "candidate_unreadable" };
449
+ }
450
+ if (raw === null)
451
+ return { reason: "candidate_not_bounded_regular_file" };
452
+ let parsed;
453
+ try {
454
+ parsed = JSON.parse(raw);
455
+ }
456
+ catch {
457
+ return { reason: "candidate_invalid_json" };
458
+ }
459
+ if (!isMergeDecisionReceipt(parsed, evidenceSource) ||
460
+ name !== receiptFileName(parsed.id)) {
461
+ return { reason: "schema_or_identity_invalid" };
462
+ }
463
+ const { preferred: legacyPreference, evidence_source: _serializedEvidenceSource, ...receiptWithoutRuntimeKeys } = parsed;
464
+ return {
465
+ receipt: {
466
+ ...receiptWithoutRuntimeKeys,
467
+ requested_preference: parsed.requested_preference ?? legacyPreference ?? "ours",
468
+ conflict_resolution: parsed.conflict_resolution ?? "preferred_side",
469
+ evidence_source: evidenceSource,
470
+ },
471
+ };
412
472
  }
413
473
  /** Inspect valid receipts and count invalid evidence without returning untrusted file contents. */
414
474
  export async function inspectMergeReceiptEvidence(cwd, options = {}) {
415
475
  const directory = await resolveReceiptDirectory(cwd);
416
476
  const local = directory === null
417
- ? { receipts: [], invalid_evidence_count: 0 }
477
+ ? {
478
+ receipts: [],
479
+ invalid_evidence_count: 0,
480
+ invalid_evidence: [],
481
+ invalid_evidence_truncated: false,
482
+ }
418
483
  : await readReceiptsFromDirectory(directory, "clone_local");
419
484
  const trackerRoot = options.pmRoot ?? path.join(cwd, ".agents", "pm");
420
485
  const durable = await readReceiptsFromDirectory(durableReceiptDirectory(trackerRoot), "durable");
421
486
  const receipts = new Map(durable.receipts.map((receipt) => [receipt.id, receipt]));
422
487
  let divergentCopyCount = 0;
488
+ const divergentCopyEvidence = [];
423
489
  for (const receipt of local.receipts) {
424
490
  const durableCopy = receipts.get(receipt.id);
425
491
  if (durableCopy !== undefined &&
@@ -427,6 +493,16 @@ export async function inspectMergeReceiptEvidence(cwd, options = {}) {
427
493
  receiptProvenanceFingerprint(receipt)) {
428
494
  receipts.delete(receipt.id);
429
495
  divergentCopyCount += 1;
496
+ if (local.invalid_evidence.length +
497
+ durable.invalid_evidence.length +
498
+ divergentCopyEvidence.length <
499
+ RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT) {
500
+ divergentCopyEvidence.push({
501
+ evidence_source: "clone_local_and_durable",
502
+ reason: "copy_provenance_mismatch",
503
+ receipt_id: receipt.id,
504
+ });
505
+ }
430
506
  continue;
431
507
  }
432
508
  receipts.set(receipt.id, durableCopy === undefined
@@ -441,6 +517,17 @@ export async function inspectMergeReceiptEvidence(cwd, options = {}) {
441
517
  invalid_evidence_count: local.invalid_evidence_count +
442
518
  durable.invalid_evidence_count +
443
519
  divergentCopyCount,
520
+ invalid_evidence: [
521
+ ...local.invalid_evidence,
522
+ ...durable.invalid_evidence,
523
+ ...divergentCopyEvidence,
524
+ ].slice(0, RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT),
525
+ invalid_evidence_truncated: local.invalid_evidence_truncated ||
526
+ durable.invalid_evidence_truncated ||
527
+ local.invalid_evidence_count +
528
+ durable.invalid_evidence_count +
529
+ divergentCopyCount >
530
+ RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT,
444
531
  clone_local_evidence_resolved: directory !== null,
445
532
  };
446
533
  }
@@ -538,12 +625,17 @@ export async function runMergeReceiptEvidenceReport(options) {
538
625
  complete,
539
626
  count: evidence.receipts.length,
540
627
  invalid_evidence_count: evidence.invalid_evidence_count,
628
+ invalid_evidence: evidence.invalid_evidence,
629
+ invalid_evidence_truncated: evidence.invalid_evidence_truncated,
541
630
  clone_local_evidence_resolved: evidence.clone_local_evidence_resolved,
542
631
  receipts: evidence.receipts,
543
632
  generated_at: nowIso(),
544
633
  };
545
634
  }
546
635
  /** Test-only seams for deterministic receipt-boundary fault coverage. */
547
- export const _testOnlyMergeReceipts = { prepareReceiptSettlement };
636
+ export const _testOnlyMergeReceipts = {
637
+ prepareReceiptSettlement,
638
+ receiptDirectoryFailureMeansAbsent,
639
+ };
548
640
  //# sourceMappingURL=receipts.js.map
549
- //# debugId=624fc190-4c46-5a55-b757-72e621aec35d
641
+ //# debugId=df7d5bd9-8381-5961-bda1-9e8ed335afc9
@@ -7,7 +7,7 @@ import { type GlobalOptions, type RuntimeStatusRegistry } from "../runtime-primi
7
7
  import type { ContextDepth, ContextSectionName, ContextSettings, ItemMetadata, ItemStatus, PmSettings } from "../../types/index.js";
8
8
  import { type CalendarRow } from "./calendar.js";
9
9
  import { type CompactActivityEntry } from "./activity.js";
10
- import { type ContextRelevanceContributions, type ContextRelevanceReport, type ContextRelevanceSignalName } from "../context-relevance.js";
10
+ import { type ContextRelevanceContributions, type ContextRecencyEvidence, type ContextRelevanceReport, type ContextRelevanceSignalName } from "../context-relevance.js";
11
11
  export { buildItemContextRelevanceCandidates } from "../context-relevance.js";
12
12
  import { type ContextPackingReport } from "../context-packing.js";
13
13
  import { type ContextSignalStoreReadResult } from "../context-signal-store.js";
@@ -398,6 +398,8 @@ export interface ContextRankingSummary {
398
398
  baseline_rank: number;
399
399
  score: number;
400
400
  contributions: ContextRelevanceContributions;
401
+ /** Authoritative temporal source used for the recency contribution. */
402
+ recency?: ContextRecencyEvidence;
401
403
  }>;
402
404
  /** Number of candidates considered before answer-sized projection. */
403
405
  candidate_count: number;
@@ -4,7 +4,7 @@
4
4
  * Implements the pm context command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a870e3ac-f731-5cbf-a66e-38d1d5b1d0aa")}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]="56205e5f-fc26-59ab-abdf-45bdcaf1c263")}catch(e){}}();
8
8
  import { SETTINGS_DEFAULTS, EXIT_CODE, PmCliError, compareTimestampStrings, nowIso, isTerminalStatus, normalizeStatusForRegistry, normalizeStatusInput, resolveRuntimeStatusRegistry, resolvePmRoot, readSettings, resolveAuthor, discoverExtensions, } from "../runtime-primitives.js";
9
9
  import { collectDependencyBlockedIds, resolveItemBlockers, } from "../actionability.js";
10
10
  import { CONTEXT_DEPTH_VALUES, CONTEXT_SECTION_VALUES, } from "../../types/index.js";
@@ -17,7 +17,7 @@ export { buildItemContextRelevanceCandidates } from "../context-relevance.js";
17
17
  import { createQueryFingerprint, encodeQueryCursor, resolveQueryCursorStart, selectCursorSemanticOptions, } from "../pagination.js";
18
18
  import { CONTEXT_FLAG_CONTRACTS } from "../cli-contracts/flag-contracts.js";
19
19
  import { packContextCandidates, } from "../context-packing.js";
20
- import { readContextUsageAffinity, recordContextUsageServing, } from "../context-usage.js";
20
+ import { attachContextUsageServingReceipt, collectContextUsageDeliveredItemIds, readContextUsageAffinity, recordContextUsageServing, } from "../context-usage.js";
21
21
  import { readWorkspaceContextSignals, } from "../context-signal-store.js";
22
22
  import { readWorkspaceMemory, selectWorkspaceMemory, } from "../workspace-memory.js";
23
23
  import { detectAgentIdentity } from "../../core/shared/author.js";
@@ -465,6 +465,9 @@ export function toContextRankingSummary(report, featureStore, servedItemIds) {
465
465
  baseline_rank: entry.baseline_rank,
466
466
  score: entry.score,
467
467
  contributions: entry.contributions,
468
+ ...(entry.signal_provenance === undefined
469
+ ? {}
470
+ : { recency: entry.signal_provenance.recency }),
468
471
  })),
469
472
  candidate_count: report.ranked.length,
470
473
  omitted_count: report.ranked.length - ranked.length,
@@ -1512,18 +1515,27 @@ function maybeAttachEmptyContextSuggestions(result, activeItems, blockedItems) {
1512
1515
  async function attachContextUsageFeedback(result, focusGroups, pmRoot, author) {
1513
1516
  try {
1514
1517
  const included = new Set(focusGroups.packing.included.map((entry) => entry.id));
1515
- await recordContextUsageServing({
1518
+ const rows = focusGroups.ranking.ranked.map((entry) => ({
1519
+ id: entry.id,
1520
+ rank: entry.rank,
1521
+ included: included.has(entry.id),
1522
+ }));
1523
+ const rankedIds = new Set(rows.map((row) => row.id));
1524
+ for (const id of collectContextUsageDeliveredItemIds(result, "context")) {
1525
+ if (!rankedIds.has(id)) {
1526
+ rows.push({ id, rank: rows.length + 1, included: false });
1527
+ rankedIds.add(id);
1528
+ }
1529
+ }
1530
+ const receipt = await recordContextUsageServing({
1516
1531
  pmRoot,
1517
1532
  author,
1518
1533
  surface: "context",
1519
1534
  profile: focusGroups.packing.profile,
1520
- rows: focusGroups.ranking.ranked.map((entry) => ({
1521
- id: entry.id,
1522
- rank: entry.rank,
1523
- included: included.has(entry.id),
1524
- })),
1535
+ rows,
1525
1536
  enabled: process.env.PM_CONTEXT_USAGE_DISABLED !== "1",
1526
1537
  });
1538
+ attachContextUsageServingReceipt(result, receipt);
1527
1539
  }
1528
1540
  catch {
1529
1541
  result.warnings = mergeSortedWarnings(result.warnings, [
@@ -1676,4 +1688,4 @@ export async function runContext(options, global) {
1676
1688
  return result;
1677
1689
  }
1678
1690
  //# sourceMappingURL=context.js.map
1679
- //# debugId=a870e3ac-f731-5cbf-a66e-38d1d5b1d0aa
1691
+ //# debugId=56205e5f-fc26-59ab-abdf-45bdcaf1c263
@@ -9,14 +9,14 @@
9
9
  * re-deriving readiness from a full `pm context` snapshot every turn.
10
10
  */
11
11
 
12
- !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]="9b788e0a-f4ac-5c6e-bf52-0ef0519d6925")}catch(e){}}();
12
+ !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]="b0f3d72c-ff0b-59bb-a6bc-8476eb9fb6c1")}catch(e){}}();
13
13
  import { collectBlockedByIds, computeActionabilityReport, } from "../actionability.js";
14
14
  import { resolveRuntimeStatusRegistry, EXIT_CODE, PmCliError, nowIso, normalizeStatusInput, normalizeStatusForRegistry, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
15
15
  import { parseIntegerLimit } from "./parsers.js";
16
16
  import { buildChildrenByParent, collectSubtreeIds, compareCriticalItems, mergeSortedWarnings, packRankedContextItems, resolveContextTokenBudget, toContextPackingSummary, toContextRankingSummary, toContextFocusItem, } from "./context.js";
17
17
  import { runList } from "./list.js";
18
18
  import { scoreContextCandidatesWithActiveExtensions } from "../context-relevance.js";
19
- import { readContextUsageAffinity, recordContextUsageServing, } from "../context-usage.js";
19
+ import { attachContextUsageServingReceipt, collectContextUsageDeliveredItemIds, readContextUsageAffinity, recordContextUsageServing, } from "../context-usage.js";
20
20
  import { readWorkspaceContextSignals, } from "../context-signal-store.js";
21
21
  /** Supported values accepted by the next output contract. */
22
22
  export const NEXT_OUTPUT_VALUES = ["markdown", "toon", "json"];
@@ -228,18 +228,27 @@ function buildNextTruncation(decisionCount, heldCount, limit) {
228
228
  async function attachNextUsageFeedback(params) {
229
229
  try {
230
230
  const included = new Set(params.packing.included.map((entry) => entry.id));
231
- await recordContextUsageServing({
231
+ const rows = params.ranking.ranked.map((entry) => ({
232
+ id: entry.id,
233
+ rank: entry.rank,
234
+ included: included.has(entry.id),
235
+ }));
236
+ const rankedIds = new Set(rows.map((row) => row.id));
237
+ for (const id of collectContextUsageDeliveredItemIds(params.result, "next")) {
238
+ if (!rankedIds.has(id)) {
239
+ rows.push({ id, rank: rows.length + 1, included: false });
240
+ rankedIds.add(id);
241
+ }
242
+ }
243
+ const receipt = await recordContextUsageServing({
232
244
  pmRoot: params.pmRoot,
233
245
  author: params.author,
234
246
  surface: "next",
235
247
  profile: params.packing.profile,
236
- rows: params.ranking.ranked.map((entry) => ({
237
- id: entry.id,
238
- rank: entry.rank,
239
- included: included.has(entry.id),
240
- })),
248
+ rows,
241
249
  enabled: process.env.PM_CONTEXT_USAGE_DISABLED !== "1",
242
250
  });
251
+ attachContextUsageServingReceipt(params.result, receipt);
243
252
  }
244
253
  catch {
245
254
  params.result.warnings = mergeSortedWarnings(params.result.warnings, [
@@ -479,4 +488,4 @@ function formatNextLine(item) {
479
488
  return `${rankToken}${item.id} p${item.priority} ${item.status} ${item.type} deadline:${deadlineToken}${parentToken}${unblocksToken} ${item.title}`;
480
489
  }
481
490
  //# sourceMappingURL=next.js.map
482
- //# debugId=9b788e0a-f4ac-5c6e-bf52-0ef0519d6925
491
+ //# debugId=b0f3d72c-ff0b-59bb-a6bc-8476eb9fb6c1
@@ -31,6 +31,8 @@ export declare function withAddNoteOption(options: Record<string, unknown>): Rec
31
31
  export declare function withFilesDiscoveryOptions(options: Record<string, unknown>): Record<string, unknown>;
32
32
  /** Canonicalize one action name into lower-kebab-case tokens. */
33
33
  export declare function normalizeActionName(value: string): string;
34
+ /** Return whether an action can change workspace extension contracts. */
35
+ export declare function shouldInvalidateWorkspaceContractsCacheAfterAction(action: string): boolean;
34
36
  /** Canonicalize one space-separated command path for lookup comparisons. */
35
37
  export declare function normalizeCommandPath(value: string): string;
36
38
  /** Coerce an unknown payload value into a non-empty string array. */
@@ -5,7 +5,7 @@
5
5
  * primitives are shared by native action dispatchers and MCP-specific adapters.
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]="fde4fea5-94d6-53e2-bfbc-bff71d828c01")}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]="d42d5fb1-eebc-5549-ae88-dc923d9d3696")}catch(e){}}();
9
9
  import { EXIT_CODE } from "../core/shared/constants.js";
10
10
  import { PmCliError } from "../core/shared/errors.js";
11
11
  import { asRecordClone } from "../core/shared/primitives.js";
@@ -14,6 +14,25 @@ import { UPDATE_COMMANDER_STRING_OPTION_CONTRACTS } from "./cli-contracts/comman
14
14
  import { normalizeBulkIdsValue, } from "../core/io/bulk-ids-input.js";
15
15
  import { overlayMutationStdinTokenPolicy, preserveMutationStdinTokenLiterals, transferMutationStdinTokenPolicy, } from "../core/item/parse.js";
16
16
  const MCP_MUTATION_TRANSPORT = Symbol("pm.mcp-mutation-transport");
17
+ const WORKSPACE_CONTRACTS_CACHE_PRESERVING_ACTIONS = new Set([
18
+ "activity",
19
+ "aggregate",
20
+ "context",
21
+ "contracts",
22
+ "deps",
23
+ "files-discover",
24
+ "files-lookup",
25
+ "get",
26
+ "graph",
27
+ "health",
28
+ "history",
29
+ "list",
30
+ "next",
31
+ "search",
32
+ "stats",
33
+ "telemetry",
34
+ "validate",
35
+ ]);
17
36
  /** Mark an action object decoded from the MCP JSON-RPC transport. */
18
37
  export function markMcpMutationTransportInput(input) {
19
38
  Object.defineProperty(input, MCP_MUTATION_TRANSPORT, {
@@ -353,6 +372,10 @@ export function normalizeActionName(value) {
353
372
  }
354
373
  return chunks.join("");
355
374
  }
375
+ /** Return whether an action can change workspace extension contracts. */
376
+ export function shouldInvalidateWorkspaceContractsCacheAfterAction(action) {
377
+ return !WORKSPACE_CONTRACTS_CACHE_PRESERVING_ACTIONS.has(normalizeActionName(action));
378
+ }
356
379
  /** Canonicalize one space-separated command path for lookup comparisons. */
357
380
  export function normalizeCommandPath(value) {
358
381
  return value.trim().toLowerCase().split(/\s+/).filter(Boolean).join(" ");
@@ -589,4 +612,4 @@ export function updateManyOptionsFromFlat(options) {
589
612
  };
590
613
  }
591
614
  //# sourceMappingURL=runtime-input.js.map
592
- //# debugId=fde4fea5-94d6-53e2-bfbc-bff71d828c01
615
+ //# debugId=d42d5fb1-eebc-5549-ae88-dc923d9d3696
@@ -66,6 +66,7 @@ export type { ClaimResult, CloseResult, CreateResult, ReleaseResult, UpdateResul
66
66
  export { getActiveExtensionRegistrations, runActiveOnReadHooks, runActiveOnWriteHooks, } from "../core/extensions/index.js";
67
67
  export { pathExists, readFileIfExists, removeFileIfExists, writeFileAtomic, } from "../core/fs/fs-utils.js";
68
68
  export { appendHistoryEntry, createHistoryEntry, } from "../core/history/history.js";
69
+ export { classifyHistoryEvent, HISTORY_EVENT_CLASSIFICATION_VERSION, MAINTENANCE_HISTORY_OPERATIONS, SUBSTANTIVE_HISTORY_OPERATIONS, type HistoryEventClass } from "../core/history/event-classification.js";
69
70
  export { generateItemId, normalizeItemId, normalizeRawItemId, } from "../core/item/id.js";
70
71
  export { readBooleanOption, readCsvListOption, readStringOption, } from "./package-runtime-options.js";
71
72
  export { PM_CLI_EXPECTED_ERROR_NAME, createPmCliExpectedError, isPmCliExpectedError, type CreatePmCliExpectedErrorOptions, type PmCliExpectedError, } from "./errors.js";