@unbrained/pm-cli 2026.9.2 → 2026.9.4

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 (165) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +44 -0
  3. package/dist/cli/after-command-context-usage.js +16 -3
  4. package/dist/cli-bundle/bundle-manifest.json +151 -151
  5. package/dist/cli-bundle/chunks/chunk-6XSKPNCF.js +230 -0
  6. package/dist/cli-bundle/chunks/chunk-A24WAVE6.js +8 -0
  7. package/dist/cli-bundle/chunks/{chunk-TAG4VC22.js → chunk-HI6BHPCU.js} +27 -27
  8. package/dist/cli-bundle/chunks/{chunk-Y7VOMSZT.js → chunk-I2AS367G.js} +2 -2
  9. package/dist/cli-bundle/chunks/{chunk-X4RCGLTX.js → chunk-OGBVU67G.js} +5 -5
  10. package/dist/cli-bundle/chunks/{chunk-DTGWEL23.js → chunk-RI4XNOYS.js} +2 -2
  11. package/dist/cli-bundle/chunks/chunk-TXW6VL33.js +38 -0
  12. package/dist/cli-bundle/chunks/{chunk-FZ4Z2J4F.js → chunk-V72UV7QS.js} +76 -79
  13. package/dist/cli-bundle/chunks/chunk-VGLHECAP.js +9 -0
  14. package/dist/cli-bundle/chunks/{chunk-T6H5BZCP.js → chunk-X6CMGV6L.js} +2 -2
  15. package/dist/cli-bundle/chunks/{chunk-3WICXLVT.js → chunk-YW4QK2G7.js} +2 -2
  16. package/dist/cli-bundle/chunks/{register-list-query-XYNX4ASQ.js → register-list-query-Z5YYSJJG.js} +2 -2
  17. package/dist/cli-bundle/chunks/{register-mutation-WFQ7MJTX.js → register-mutation-ELSP6I4I.js} +2 -2
  18. package/dist/cli-bundle/chunks/{register-operations-JVTI7JPP.js → register-operations-OH7R3ZT4.js} +2 -2
  19. package/dist/cli-bundle/chunks/{register-setup-KVNC5KPL.js → register-setup-E2AE72QG.js} +2 -2
  20. package/dist/cli-bundle/focused-chunks/{chunk-MEASX544.js → chunk-25UJBH4M.js} +2 -2
  21. package/dist/cli-bundle/focused-chunks/{chunk-SVXJYD6G.js → chunk-3646BZ4W.js} +2 -2
  22. package/dist/cli-bundle/focused-chunks/chunk-4YRAVI43.js +12 -0
  23. package/dist/cli-bundle/focused-chunks/chunk-53IHPICX.js +3 -0
  24. package/dist/cli-bundle/focused-chunks/chunk-5P4HVOWG.js +176 -0
  25. package/dist/cli-bundle/focused-chunks/chunk-636VVQ7F.js +54 -0
  26. package/dist/cli-bundle/focused-chunks/{chunk-4O4CJAR6.js → chunk-6PWPQKDN.js} +2 -2
  27. package/dist/cli-bundle/focused-chunks/chunk-7N2TV7WZ.js +8 -0
  28. package/dist/cli-bundle/focused-chunks/chunk-AJR3OP2E.js +3 -0
  29. package/dist/cli-bundle/focused-chunks/chunk-B3A6MJYE.js +2 -0
  30. package/dist/cli-bundle/focused-chunks/chunk-BFDDJ2T2.js +2 -0
  31. package/dist/cli-bundle/focused-chunks/chunk-BHUIRZWQ.js +9 -0
  32. package/dist/cli-bundle/focused-chunks/chunk-JADHHPY6.js +6 -0
  33. package/dist/cli-bundle/focused-chunks/{chunk-KB5OFSFD.js → chunk-MHKUIPJW.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/chunk-NBMJD6MK.js +2 -0
  35. package/dist/cli-bundle/focused-chunks/chunk-NSKBLHVI.js +20 -0
  36. package/dist/cli-bundle/focused-chunks/{chunk-BEVHCEWG.js → chunk-P2GOAOQN.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/chunk-YARWJM2B.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 -31
  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 +43 -36
  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 +10 -10
  49. package/dist/core/diagnostics/remediation.js +4 -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.d.ts +37 -1
  55. package/dist/core/history/history.js +320 -71
  56. package/dist/core/history/replay.js +68 -34
  57. package/dist/core/history/workspace-history.js +7 -6
  58. package/dist/core/lock/lock.d.ts +32 -2
  59. package/dist/core/lock/lock.js +161 -20
  60. package/dist/core/output/output.js +31 -7
  61. package/dist/core/shared/author.d.ts +3 -1
  62. package/dist/core/shared/author.js +111 -23
  63. package/dist/core/shared/time.d.ts +2 -0
  64. package/dist/core/shared/time.js +8 -2
  65. package/dist/core/store/item-metadata-query-index.js +5 -5
  66. package/dist/sdk/context/recency.d.ts +9 -0
  67. package/dist/sdk/context/recency.js +34 -0
  68. package/dist/sdk/context/usage-egress.d.ts +9 -0
  69. package/dist/sdk/context/usage-egress.js +30 -0
  70. package/dist/sdk/context-intent-contracts.js +7 -3
  71. package/dist/sdk/context-relevance.d.ts +23 -0
  72. package/dist/sdk/context-relevance.js +94 -23
  73. package/dist/sdk/context-signal-store.d.ts +7 -3
  74. package/dist/sdk/context-signal-store.js +155 -42
  75. package/dist/sdk/context-usage.d.ts +54 -0
  76. package/dist/sdk/context-usage.js +245 -16
  77. package/dist/sdk/environment/agent-environment.d.ts +296 -0
  78. package/dist/sdk/environment/agent-environment.js +467 -0
  79. package/dist/sdk/environment/project-runtime-compatibility.d.ts +19 -1
  80. package/dist/sdk/environment/project-runtime-compatibility.js +118 -21
  81. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +14 -2
  82. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +14 -2
  83. package/dist/sdk/governance/health.js +13 -44
  84. package/dist/sdk/governance/merge-receipt-history.d.ts +62 -0
  85. package/dist/sdk/governance/merge-receipt-history.js +207 -0
  86. package/dist/sdk/governance/provenance-health.js +9 -3
  87. package/dist/sdk/history-compact.js +14 -5
  88. package/dist/sdk/history-redact.js +58 -23
  89. package/dist/sdk/history-repair.js +16 -6
  90. package/dist/sdk/index.d.ts +4 -0
  91. package/dist/sdk/index.js +6 -2
  92. package/dist/sdk/init.d.ts +2 -0
  93. package/dist/sdk/init.js +18 -9
  94. package/dist/sdk/merge/driver.d.ts +3 -1
  95. package/dist/sdk/merge/driver.js +9 -9
  96. package/dist/sdk/merge/index.d.ts +1 -1
  97. package/dist/sdk/merge/index.js +3 -3
  98. package/dist/sdk/merge/receipts.d.ts +17 -6
  99. package/dist/sdk/merge/receipts.js +246 -75
  100. package/dist/sdk/merge/reconcile.d.ts +9 -7
  101. package/dist/sdk/merge/reconcile.js +175 -12
  102. package/dist/sdk/merge/three-way.d.ts +22 -2
  103. package/dist/sdk/merge/three-way.js +92 -25
  104. package/dist/sdk/query/context.d.ts +3 -1
  105. package/dist/sdk/query/context.js +21 -9
  106. package/dist/sdk/query/next.js +18 -9
  107. package/dist/sdk/runtime-input.d.ts +2 -0
  108. package/dist/sdk/runtime-input.js +25 -2
  109. package/dist/sdk/runtime-primitives.d.ts +2 -2
  110. package/dist/sdk/runtime-primitives.js +4 -4
  111. package/dist/sdk/runtime.d.ts +1 -0
  112. package/dist/sdk/runtime.js +17 -26
  113. package/dist/types.d.ts +27 -0
  114. package/dist/types.js +2 -2
  115. package/docs/AGENT_ENVIRONMENTS.md +47 -0
  116. package/docs/AGENT_PROVENANCE_ADR.md +17 -2
  117. package/docs/CONTEXT_INTEGRITY_CONTRACTS.md +38 -1
  118. package/docs/CONTEXT_RELEVANCE.md +44 -1
  119. package/docs/MERGE_SAFETY.md +119 -23
  120. package/docs/PERFORMANCE.md +6 -3
  121. package/docs/README.md +1 -0
  122. package/docs/READ_OUTPUT_CONTRACTS.md +9 -1
  123. package/docs/SDK.md +11 -8
  124. package/docs/SDK_CONTEXT.md +7 -0
  125. package/docs/SDK_CONTEXT_EVIDENCE_CONTRACTS.md +24 -2
  126. package/docs/SDK_RUNTIME_BOUNDARIES.md +17 -1
  127. package/docs/examples/sdk-agent-environment/README.md +14 -0
  128. package/docs/examples/sdk-agent-environment/package.json +8 -0
  129. package/docs/examples/sdk-agent-environment/run-agent-environment.mjs +154 -0
  130. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +5 -3
  131. package/marketplace.json +2 -2
  132. package/package.json +5 -5
  133. package/packages/pm-beads/package.json +1 -1
  134. package/packages/pm-calendar/package.json +1 -1
  135. package/packages/pm-command-kit/package.json +1 -1
  136. package/packages/pm-digital-twin/package.json +1 -1
  137. package/packages/pm-governance-audit/package.json +1 -1
  138. package/packages/pm-guide-shell/package.json +1 -1
  139. package/packages/pm-kanban/package.json +1 -1
  140. package/packages/pm-lifecycle-hooks/package.json +1 -1
  141. package/packages/pm-linked-test-adapters/package.json +1 -1
  142. package/packages/pm-search-advanced/package.json +1 -1
  143. package/packages/pm-templates/package.json +1 -1
  144. package/packages/pm-todos/package.json +1 -1
  145. package/packages/pm-vcs/package.json +1 -1
  146. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  147. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  148. package/sdk/public-surface.json +773 -46
  149. package/dist/cli-bundle/chunks/chunk-GOACULJW.js +0 -13
  150. package/dist/cli-bundle/chunks/chunk-NOPL37X4.js +0 -205
  151. package/dist/cli-bundle/chunks/chunk-UDW64J2W.js +0 -8
  152. package/dist/cli-bundle/chunks/chunk-ZLJIFSOE.js +0 -35
  153. package/dist/cli-bundle/focused-chunks/chunk-242AXYB2.js +0 -2
  154. package/dist/cli-bundle/focused-chunks/chunk-2FEZ5SKM.js +0 -3
  155. package/dist/cli-bundle/focused-chunks/chunk-6GCRSLPG.js +0 -2
  156. package/dist/cli-bundle/focused-chunks/chunk-7VATS5QY.js +0 -16
  157. package/dist/cli-bundle/focused-chunks/chunk-JEFKLWMM.js +0 -2
  158. package/dist/cli-bundle/focused-chunks/chunk-MKHG3T76.js +0 -20
  159. package/dist/cli-bundle/focused-chunks/chunk-O67VDLOT.js +0 -51
  160. package/dist/cli-bundle/focused-chunks/chunk-PF3E6Q36.js +0 -8
  161. package/dist/cli-bundle/focused-chunks/chunk-QDFJIRKN.js +0 -4
  162. package/dist/cli-bundle/focused-chunks/chunk-RMRCQPWU.js +0 -2
  163. package/dist/cli-bundle/focused-chunks/chunk-S4U5CN5Q.js +0 -2
  164. package/dist/cli-bundle/focused-chunks/chunk-T2LXXSOD.js +0 -158
  165. package/dist/cli-bundle/focused-chunks/chunk-Z2USIBR2.js +0 -5
@@ -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
@@ -17,10 +17,10 @@ export { isFileMissingError, pathExists, readFileIfExists, removeFileIfExists, w
17
17
  export { normalizeBulkIdsValue, parseBulkIdsText, resolveCliBulkIdsInput, type BulkIdsFileReader, type BulkIdsInputReaders, type BulkIdsStdinReader, type BulkIdsValue, } from "../core/io/bulk-ids-input.js";
18
18
  export { type HistoryDiffValueEntry, computeHistoryDiff, patchPathToChangedField, } from "../core/history/history-diff.js";
19
19
  export { enforceHistoryStreamPolicyForItem, enforceHistoryStreamPolicyForItems, } from "../core/history/history-stream-policy.js";
20
- export { appendHistoryEntry, CURRENT_HISTORY_ITEM_HASH_VERSION, createHistoryEntry, hashDocument, hashDocumentForVersion, hashEmptyDocument, SUPPORTED_HISTORY_ITEM_HASH_VERSIONS, type HistoryItemHashVersion, } from "../core/history/history.js";
20
+ export { appendHistoryEntry, CURRENT_HISTORY_ITEM_HASH_VERSION, CURRENT_HISTORY_RECORD_HASH_VERSION, createHistoryEntry, hashDocument, hashDocumentForVersion, hashEmptyDocument, hashHistoryPatch, hashHistoryRecord, hashHistoryStream, resealHistoryRewrite, sealHistoryRecord, SUPPORTED_HISTORY_ITEM_HASH_VERSIONS, SUPPORTED_HISTORY_RECORD_HASH_VERSIONS, verifyHistoryRecordHash, verifyHistoryRewriteEvidence, type HistoryItemHashVersion, type HistoryRecordHashVersion, } from "../core/history/history.js";
21
21
  export { readHistoryEntries } from "../core/history/read.js";
22
22
  export { appendWorkspaceAuditEvent, appendWorkspaceHistoryChange, getWorkspaceHistoryPath, inspectWorkspaceHistoryState, mutateWorkspaceJsonWithHistory, reconcileWorkspaceJsonHistory, restoreWorkspaceJsonFromHistory, WORKSPACE_HISTORY_ID, writeWorkspaceJsonWithHistory, type WorkspaceAuditEventOptions, type WorkspaceHistoryChange, type WorkspaceHistoryStateAgreement, type WorkspaceJsonMutation, type WorkspaceJsonMutationOptions, type WorkspaceJsonReconciliationOptions, type WorkspaceJsonRestoreOptions, type WorkspaceJsonRestoreResult, type WorkspaceJsonWriteOptions, } from "../core/history/workspace-history.js";
23
- export { normalizeReplayPatchOps, replayToCanonicalItemDocument, replayToItemDocument, toReplayDocument, verifyHistoryChain, verifyHistoryChainWithVersion, } from "../core/history/replay.js";
23
+ export { normalizeReplayPatchOps, reanchorHistoryEntries, replayToCanonicalItemDocument, replayToItemDocument, toReplayDocument, verifyHistoryChain, verifyHistoryChainWithVersion, } from "../core/history/replay.js";
24
24
  export { resolveBodyFileContent } from "../core/io/body-file.js";
25
25
  export { generateItemId, normalizeItemId, normalizeRawItemId, } from "../core/item/id.js";
26
26
  export { canonicalDocument, normalizeItemMetadata, parseItemDocument, serializeItemDocument, } from "../core/item/item-format.js";
@@ -7,7 +7,7 @@
7
7
  * prefer the typed operations exported by the main SDK barrel.
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]="d45775e5-6826-521b-80b3-429ed22947d9")}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]="aba5403c-0694-5c51-95a8-ae7e7575347b")}catch(e){}}();
11
11
  export { createCheckpointId, loadMutationCheckpoint, restoreCheckpointItems, writeMutationCheckpoint, } from "../core/checkpoint/mutation-checkpoint.js";
12
12
  export { flattenFlagListValue, resolveFlagValueKind, } from "../core/extensions/flag-value-types.js";
13
13
  export { createUnknownSubcommandError, } from "./agent/subcommand-recovery.js";
@@ -19,10 +19,10 @@ export { isFileMissingError, pathExists, readFileIfExists, removeFileIfExists, w
19
19
  export { normalizeBulkIdsValue, parseBulkIdsText, resolveCliBulkIdsInput, } from "../core/io/bulk-ids-input.js";
20
20
  export { computeHistoryDiff, patchPathToChangedField, } from "../core/history/history-diff.js";
21
21
  export { enforceHistoryStreamPolicyForItem, enforceHistoryStreamPolicyForItems, } from "../core/history/history-stream-policy.js";
22
- export { appendHistoryEntry, CURRENT_HISTORY_ITEM_HASH_VERSION, createHistoryEntry, hashDocument, hashDocumentForVersion, hashEmptyDocument, SUPPORTED_HISTORY_ITEM_HASH_VERSIONS, } from "../core/history/history.js";
22
+ export { appendHistoryEntry, CURRENT_HISTORY_ITEM_HASH_VERSION, CURRENT_HISTORY_RECORD_HASH_VERSION, createHistoryEntry, hashDocument, hashDocumentForVersion, hashEmptyDocument, hashHistoryPatch, hashHistoryRecord, hashHistoryStream, resealHistoryRewrite, sealHistoryRecord, SUPPORTED_HISTORY_ITEM_HASH_VERSIONS, SUPPORTED_HISTORY_RECORD_HASH_VERSIONS, verifyHistoryRecordHash, verifyHistoryRewriteEvidence, } from "../core/history/history.js";
23
23
  export { readHistoryEntries } from "../core/history/read.js";
24
24
  export { appendWorkspaceAuditEvent, appendWorkspaceHistoryChange, getWorkspaceHistoryPath, inspectWorkspaceHistoryState, mutateWorkspaceJsonWithHistory, reconcileWorkspaceJsonHistory, restoreWorkspaceJsonFromHistory, WORKSPACE_HISTORY_ID, writeWorkspaceJsonWithHistory, } from "../core/history/workspace-history.js";
25
- export { normalizeReplayPatchOps, replayToCanonicalItemDocument, replayToItemDocument, toReplayDocument, verifyHistoryChain, verifyHistoryChainWithVersion, } from "../core/history/replay.js";
25
+ export { normalizeReplayPatchOps, reanchorHistoryEntries, replayToCanonicalItemDocument, replayToItemDocument, toReplayDocument, verifyHistoryChain, verifyHistoryChainWithVersion, } from "../core/history/replay.js";
26
26
  export { resolveBodyFileContent } from "../core/io/body-file.js";
27
27
  export { generateItemId, normalizeItemId, normalizeRawItemId, } from "../core/item/id.js";
28
28
  export { canonicalDocument, normalizeItemMetadata, parseItemDocument, serializeItemDocument, } from "../core/item/item-format.js";
@@ -82,4 +82,4 @@ export { maybeRunFirstUseTelemetryPrompt } from "../core/telemetry/consent.js";
82
82
  export { deriveTelemetryCommandResolution, } from "../core/telemetry/observability.js";
83
83
  export { emitTelemetryErrorEvent, finishTelemetryCommand, startTelemetryCommand, } from "../core/telemetry/runtime.js";
84
84
  //# sourceMappingURL=runtime-primitives.js.map
85
- //# debugId=d45775e5-6826-521b-80b3-429ed22947d9
85
+ //# debugId=aba5403c-0694-5c51-95a8-ae7e7575347b
@@ -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";
@@ -4,7 +4,7 @@
4
4
  * Defines public SDK APIs and package-author helpers for Runtime.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="b67ba0fe-bbca-57ab-b3be-a4a028f21de4")}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]="099c7cda-4a92-553c-ad60-00e185b5971b")}catch(e){}}();
8
8
  export { PM_GITIGNORE_END, PM_GITIGNORE_START, ensurePmGitignore, getPmGitignoreBlock, } from "./workspace.js";
9
9
  export { SEARCH_EXTENSION_FLAG_DEFINITIONS } from "./extension-contracts.js";
10
10
  export * from "./cli-contracts/agent-output-contracts.js";
@@ -33,6 +33,7 @@ import { SDK_ACTION_ALIASES } from "./runtime-action-aliases.js";
33
33
  import { createExtensionCommandSdk } from "./extension-command-context.js";
34
34
  import { createUnknownSubcommandError } from "./agent/subcommand-recovery.js";
35
35
  import { applyContextIntentProjection, attachReadOutputContracts, } from "./context-intent-contracts.js";
36
+ import { finalizeContextUsageEgress } from "./context/usage-egress.js";
36
37
  import { runWithDiscoveredContextIntentContracts, } from "./context-intent-runtime.js";
37
38
  import { normalizeReadOutputIncludeModeOptions, validateReadOutputOptions, } from "./read-output-contracts.js";
38
39
  export { clearWorkspaceContractsCache } from "./workspace-contracts-cache.js";
@@ -65,14 +66,14 @@ import { runHealth, } from "./governance/health.js";
65
66
  import { runValidate, } from "./governance/validate.js";
66
67
  import { runExtension, } from "./extension.js";
67
68
  import { runConfig } from "./config.js";
68
- import { runInit } from "./init.js";
69
+ import { INIT_INVOCATION_CWD, runInit } from "./init.js";
69
70
  import { runRuntimeEvalAction, runRuntimeEventsAction, runRuntimeMergeAction, runRuntimeSchedulingAction, runRuntimeWorkspaceAction, } from "./runtime-extended-actions.js";
70
71
  import { acknowledgeUnknownAuthorHistoryEventsFromTransport, } from "./author-attribution.js";
71
72
  import { PROFILE_SUBCOMMANDS, runProfileApply, runProfileLint, runProfileList, runProfileShow, } from "./profile.js";
72
73
  import { runHistoryRedact, } from "./history-redact.js";
73
74
  import { runMcpHistoryCompactAction, runMcpHistoryRepairAction, } from "./history-mcp.js";
74
75
  import { runMcpCloseAction, runMcpReopenAction } from "./lifecycle/mcp-actions.js";
75
- import { actionGlobalOptions as globalOptions, closeManyOptionsFromFlat, extensionOptionsFromArgs, graphOptionsFromFlat, mutationListOptions, mutationOptionsWithOverrides, normalizeActionName, normalizeCommandPath, normalizeMcpOptionsArrays, normalizeMcpUpdateOptions, optionsWithAuthor, parseRuntimeInteger as parseMcpInteger, readRuntimeScalarString as readScalarString, readRuntimeScalarStringAllowBlank as readScalarStringAllowBlank, readRuntimeString as readString, readRuntimeStringArray as readStringArray, resolveRuntimeLimit, updateManyOptionsFromFlat, withAddNoteOption, withFilesDiscoveryOptions, withMutationCompaction, } from "./runtime-input.js";
76
+ import { actionGlobalOptions as globalOptions, closeManyOptionsFromFlat, extensionOptionsFromArgs, graphOptionsFromFlat, mutationListOptions, mutationOptionsWithOverrides, normalizeActionName, normalizeCommandPath, normalizeMcpOptionsArrays, normalizeMcpUpdateOptions, optionsWithAuthor, parseRuntimeInteger as parseMcpInteger, readRuntimeScalarString as readScalarString, readRuntimeScalarStringAllowBlank as readScalarStringAllowBlank, readRuntimeString as readString, readRuntimeStringArray as readStringArray, resolveRuntimeLimit, shouldInvalidateWorkspaceContractsCacheAfterAction, updateManyOptionsFromFlat, withAddNoteOption, withFilesDiscoveryOptions, withMutationCompaction, } from "./runtime-input.js";
76
77
  import { runDeps } from "./dependencies.js";
77
78
  import { runDocs } from "./docs.js";
78
79
  import { runGraph, } from "./graph/run.js";
@@ -92,6 +93,7 @@ import { SCHEMA_SUBCOMMANDS, runSchemaAddField, runSchemaAddStatus, runSchemaAdd
92
93
  export { getActiveExtensionRegistrations, runActiveOnReadHooks, runActiveOnWriteHooks, } from "../core/extensions/index.js";
93
94
  export { pathExists, readFileIfExists, removeFileIfExists, writeFileAtomic, } from "../core/fs/fs-utils.js";
94
95
  export { appendHistoryEntry, createHistoryEntry, } from "../core/history/history.js";
96
+ export { classifyHistoryEvent, HISTORY_EVENT_CLASSIFICATION_VERSION, MAINTENANCE_HISTORY_OPERATIONS, SUBSTANTIVE_HISTORY_OPERATIONS } from "../core/history/event-classification.js";
95
97
  export { generateItemId, normalizeItemId, normalizeRawItemId, } from "../core/item/id.js";
96
98
  export { readBooleanOption, readCsvListOption, readStringOption, } from "./package-runtime-options.js";
97
99
  export { PM_CLI_EXPECTED_ERROR_NAME, createPmCliExpectedError, isPmCliExpectedError, } from "./errors.js";
@@ -1276,24 +1278,6 @@ async function withCwd(cwd, run) {
1276
1278
  process.chdir(previous);
1277
1279
  }
1278
1280
  }
1279
- const WORKSPACE_CONTRACTS_CACHE_PRESERVING_ACTIONS = new Set([
1280
- "activity",
1281
- "aggregate",
1282
- "context",
1283
- "contracts",
1284
- "deps",
1285
- "files-discover",
1286
- "get",
1287
- "graph",
1288
- "health",
1289
- "history",
1290
- "list",
1291
- "next",
1292
- "search",
1293
- "stats",
1294
- "telemetry",
1295
- "validate",
1296
- ]);
1297
1281
  function resolveSdkActionInput(args) {
1298
1282
  const rawAction = readRequiredString(args, "action");
1299
1283
  const normalizedAction = normalizeActionName(rawAction);
@@ -1311,9 +1295,6 @@ function resolveSdkActionInput(args) {
1311
1295
  }
1312
1296
  return { action, args: resolvedArgs };
1313
1297
  }
1314
- function shouldInvalidateWorkspaceContractsCacheAfterAction(action) {
1315
- return !WORKSPACE_CONTRACTS_CACHE_PRESERVING_ACTIONS.has(normalizeActionName(action));
1316
- }
1317
1298
  /** Execute one native or extension-contributed pm action in-process. */
1318
1299
  export async function runAction(args) {
1319
1300
  const resolved = resolveSdkActionInput(args);
@@ -1328,6 +1309,14 @@ export async function runAction(args) {
1328
1309
  // pins process.cwd() (inside the serialized slot) for the built-in handler.
1329
1310
  const explicitCwd = readString(resolved.args, "cwd");
1330
1311
  const resolutionCwd = explicitCwd ?? process.cwd();
1312
+ if (resolved.action === "init") {
1313
+ global[INIT_INVOCATION_CWD] = resolutionCwd;
1314
+ }
1315
+ if (resolved.action !== "init" ||
1316
+ global.path !== undefined ||
1317
+ (process.env.PM_PATH?.trim().length ?? 0) > 0) {
1318
+ global.path = resolvePmRoot(resolutionCwd, global.path);
1319
+ }
1331
1320
  try {
1332
1321
  if (args[ACTIVE_EXTENSION_HOST_CONTEXT] === true ||
1333
1322
  activeExtensionScope.getStore() === true) {
@@ -1886,7 +1875,9 @@ async function dispatchAction(action, args, global, activeExtensions) {
1886
1875
  ? await handler(ctx)
1887
1876
  : await dispatchActiveExtensionAction(action, args, options, global, activeExtensions);
1888
1877
  options.resolvedOutputFormat = "json";
1889
- return attachReadOutputContracts(action, options, result);
1878
+ const projected = attachReadOutputContracts(action, options, result);
1879
+ await finalizeContextUsageEgress(resolvePmRoot(process.cwd(), global.path), projected);
1880
+ return projected;
1890
1881
  }
1891
1882
  const actionRunnerTestHooks = {
1892
1883
  closeManyOptionsFromFlat,
@@ -1933,4 +1924,4 @@ async function loadWorkspaceExtensionRegistrations(pmRoot, settings, cwd) {
1933
1924
  }
1934
1925
  }
1935
1926
  //# sourceMappingURL=runtime.js.map
1936
- //# debugId=b67ba0fe-bbca-57ab-b3be-a4a028f21de4
1927
+ //# debugId=099c7cda-4a92-553c-ad60-00e185b5971b
package/dist/types.d.ts CHANGED
@@ -789,6 +789,25 @@ export interface HistoryPatchOp {
789
789
  /** Value that configures or reports value for this contract. */
790
790
  value?: unknown;
791
791
  }
792
+ /** Immutable evidence retained whenever history maintenance replaces anchors or patch operations. */
793
+ export interface HistoryReanchorEvidence {
794
+ /** Before-state anchor present on the record before re-anchoring. */
795
+ before_hash: string;
796
+ /** After-state anchor present on the record before re-anchoring. */
797
+ after_hash: string;
798
+ /** Item hash epoch present before re-anchoring. */
799
+ item_hash_version?: number;
800
+ /** Hash of the original patch, retained even when redaction forbids retaining its values. */
801
+ patch_hash: string;
802
+ /** Original patch operations when repair replaced or skipped recorded intent. */
803
+ patch?: HistoryPatchOp[];
804
+ /** Record-integrity epoch protecting the pre-re-anchor record. */
805
+ record_hash_version?: number;
806
+ /** Record hash protecting the pre-re-anchor attribution and operation metadata. */
807
+ record_hash?: string;
808
+ /** Exact prior sealed record when maintenance can retain its non-sensitive payload. */
809
+ record?: HistoryEntry;
810
+ }
792
811
  /** Documents the history entry payload exchanged by command, SDK, and package integrations. */
793
812
  export interface HistoryEntry {
794
813
  /** Value that configures or reports ts for this contract. */
@@ -829,6 +848,8 @@ export interface HistoryEntry {
829
848
  };
830
849
  /** Value that configures or reports op for this contract. */
831
850
  op: string;
851
+ /** Declared semantic effect used by recency consumers. Absent on legacy entries. */
852
+ event_class?: "substantive" | "maintenance";
832
853
  /** Value that configures or reports patch for this contract. */
833
854
  patch: HistoryPatchOp[];
834
855
  /** Value that configures or reports before hash for this contract. */
@@ -837,6 +858,12 @@ export interface HistoryEntry {
837
858
  after_hash: string;
838
859
  /** Version of the item canonicalization used by before_hash and after_hash. Absent on legacy streams. */
839
860
  item_hash_version?: number;
861
+ /** Version of the canonical immutable-record envelope. Absent on legacy entries whose coverage is item-state-only. */
862
+ record_hash_version?: number;
863
+ /** SHA-256 hash covering this event's immutable metadata, patch, and item anchors. */
864
+ record_hash?: string;
865
+ /** Append-only evidence for every prior anchor or patch representation replaced by maintenance. */
866
+ reanchor_evidence?: HistoryReanchorEvidence[];
840
867
  /** Human-readable explanation suitable for logs and agent-facing output. */
841
868
  message?: string;
842
869
  /** Structured audit metadata that does not alter replayed item state. */
package/dist/types.js CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
  /** Supported values accepted by the builtin item type contract. */
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]="64223a83-1287-57ac-915d-dbd5e375a6eb")}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]="4ee067ac-f28d-5411-9ac7-c92112384a64")}catch(e){}}();
9
9
  export const BUILTIN_ITEM_TYPE_VALUES = [
10
10
  "Epic",
11
11
  "Feature",
@@ -243,4 +243,4 @@ export const CONTEXT_SECTION_VALUES = [
243
243
  "tests",
244
244
  ];
245
245
  //# sourceMappingURL=types.js.map
246
- //# debugId=64223a83-1287-57ac-915d-dbd5e375a6eb
246
+ //# debugId=4ee067ac-f28d-5411-9ac7-c92112384a64
@@ -0,0 +1,47 @@
1
+ # SDK Agent Environments
2
+
3
+ Tracker: [pm-e1vkee](../.agents/pm/features/pm-e1vkee.toon), [pm-gd6vnn](../.agents/pm/features/pm-gd6vnn.toon), [pm-li2fj5](../.agents/pm/features/pm-li2fj5.toon), [pm-t8a0x1](../.agents/pm/features/pm-t8a0x1.toon)
4
+
5
+ ## Agent Quick Context
6
+
7
+ `@unbrained/pm-cli/sdk` provides three composable contracts for building reproducible project-management environments without a machine-learning runtime dependency:
8
+
9
+ - an observation contract declares every read ceiling, emitted-byte calibration, corpus-size dependence, and an ordered degradation ladder;
10
+ - a verdict contract evaluates named, versioned predicates over recorded state and returns `satisfied`, `violated`, or `not_applicable` without producing a reward signal;
11
+ - an episode specification combines a deterministic workspace recipe, canonical task items, observable and withheld fields, hard limits, and an adapter for ordinary `PmClient` actions.
12
+
13
+ The executable [public-SDK example](examples/sdk-agent-environment/README.md) runs the complete reset → observe → act → verdict → close loop in a temporary pm workspace.
14
+
15
+ ## Contract Boundaries
16
+
17
+ Observation cost is knowable before a read. `describeObservationCost()` returns the sum of the declared read ceilings plus the calibrated expected emitted bytes. `serveDeclaredObservation()` measures stable serialized bytes, attempts tiers in declaration order, names the served tier, and returns a payload-free refusal if no tier fits.
18
+
19
+ Verdicts only inspect the adapter's `WorkspaceRecordedState`. Evidence identifies the exact snapshot and JSON pointer while a digest avoids copying field values into the result. The interpreter is deterministic and read-only; `policy: "verdict_only_no_reward"` makes the non-reward boundary machine-readable.
20
+
21
+ Episodes never grant a second mutation vocabulary. The adapter's `execute()` method should call ordinary public `PmClient` methods, so lifecycle validation, history, extensions, and policy remain authoritative. Each session owns its counters and trajectory, allowing concurrent runs without shared episode state.
22
+
23
+ Withheld grading fields cannot also be observable. Every tier field must be declared observable, and projection copies only the selected tier fields. Hard action and observation limits fail closed.
24
+
25
+ ## Minimal Shape
26
+
27
+ ```ts
28
+ import {
29
+ defineEpisodeSpecification,
30
+ openPmEpisode,
31
+ type EpisodeRuntimeAdapter,
32
+ } from "@unbrained/pm-cli/sdk";
33
+
34
+ const specification = defineEpisodeSpecification({
35
+ // Versioned recipe, task set, observation, verdict, and limits.
36
+ });
37
+ const session = await openPmEpisode(
38
+ specification,
39
+ adapter satisfies EpisodeRuntimeAdapter<MyAction>,
40
+ );
41
+
42
+ await session.observe();
43
+ await session.step({ kind: "close" });
44
+ const evidence = await session.close();
45
+ ```
46
+
47
+ Use the same specification and adapter boundary for benchmarks, evaluations, training data collection, or scale-transfer experiments. Consumer intent changes through `mode`; the pm action and evidence contracts do not.
@@ -10,7 +10,9 @@ Implementation lineage:
10
10
  resolution and patch-free historical reads implemented by
11
11
  [pm-ffz0a9](../.agents/pm/issues/pm-ffz0a9.toon),
12
12
  [pm-v8gfi7](../.agents/pm/issues/pm-v8gfi7.toon), and
13
- [pm-3yxwv5](../.agents/pm/issues/pm-3yxwv5.toon). Cross-harness adapters and
13
+ [pm-3yxwv5](../.agents/pm/issues/pm-3yxwv5.toon). Stable Claude session
14
+ discovery across child working directories is tracked by
15
+ [pm-l7m7k5](../.agents/pm/issues/pm-l7m7k5.toon). Cross-harness adapters and
14
16
  operator-managed probe/vocabulary controls are tracked by
15
17
  [pm-c0lrdm](../.agents/pm/features/pm-c0lrdm.toon) and
16
18
  [pm-yds9dt](../.agents/pm/chores/pm-yds9dt.toon).
@@ -56,7 +58,13 @@ from literal descriptor keys, trusted caller data, or a named bounded resolver.
56
58
  Detection does not spawn processes, traverse process trees, evaluate user
57
59
  regexes, or access the network. The built-in Claude and Codex resolvers read
58
60
  only bounded windows of the current session's harness-owned JSONL file. Claude
59
- uses the recent tail to recover its recorded model/version. Codex uses the
61
+ resolves an explicitly supplied transcript first, then the direct workspace
62
+ coordinate, then performs a deterministic scan of at most 512 immediate
63
+ project directories for the unique stable session id. This keeps provenance
64
+ attached when the invocation cwd moves into a child package. No match is
65
+ reported as `resolver_input_missing`; multiple matches are ambiguous and remain
66
+ `resolver_failed` instead of selecting an arbitrary transcript. Claude uses the
67
+ bounded session window to recover its recorded model/version. Codex uses the
60
68
  recent tail plus a bounded initial-head fallback for oversized sessions to
61
69
  recover allow-listed `turn_context.model` and `turn_context.effort` values.
62
70
  Both cap traversal, file bytes, lines, and line length, ignore all other fields,
@@ -70,6 +78,13 @@ the existing domain-separated, truncated `agent_instance` digest. Public
70
78
  telemetry continues to use installation-scoped hashes or presence booleans; it
71
79
  does not export raw provenance values.
72
80
 
81
+ Health counts resolvers with an available input, plus failed or ambiguous
82
+ resolution attempts, as attempts. A sustained attempted-but-zero-success series
83
+ remains advisory: it truthfully identifies parser, filesystem, ambiguity, or
84
+ provider-shape drift without treating missing descriptive metadata as
85
+ authorization or item-state corruption. Missing-input and probes-disabled
86
+ events are classified separately and do not inflate that warning.
87
+
73
88
  ## Compatibility
74
89
 
75
90
  All new history fields are optional. Readers must accept:
@@ -1,6 +1,6 @@
1
1
  # Context Integrity Contracts
2
2
 
3
- Tracker references: [pm-4fwgaz](../.agents/pm/issues/pm-4fwgaz.toon), [pm-qqoumq](../.agents/pm/issues/pm-qqoumq.toon), [pm-fpdk37](../.agents/pm/issues/pm-fpdk37.toon), [pm-jn1x30](../.agents/pm/issues/pm-jn1x30.toon), and [pm-0wfdim](../.agents/pm/issues/pm-0wfdim.toon).
3
+ Tracker references: [pm-4fwgaz](../.agents/pm/issues/pm-4fwgaz.toon), [pm-qqoumq](../.agents/pm/issues/pm-qqoumq.toon), [pm-fpdk37](../.agents/pm/issues/pm-fpdk37.toon), [pm-jn1x30](../.agents/pm/issues/pm-jn1x30.toon), [pm-0wfdim](../.agents/pm/issues/pm-0wfdim.toon), [pm-javbsq](../.agents/pm/issues/pm-javbsq.toon), and [pm-aka8m7](../.agents/pm/issues/pm-aka8m7.toon).
4
4
 
5
5
  ## Agent Quick Context
6
6
 
@@ -53,6 +53,43 @@ History writers using item-hash epoch 2 always emit `item_hash_version: 2`. An e
53
53
 
54
54
  Repair keeps implicit legacy streams implicit and byte-stable when no drift exists. Unsupported explicit epochs still fail with a typed `unsupported_item_hash_version` diagnostic instead of being rewritten.
55
55
 
56
+ | Writer/runtime range | Item-hash output | Read contract |
57
+ | ---------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------ |
58
+ | Legacy writers before an explicit marker | implicit epoch 1 | Modern readers retain legacy canonicalization candidates. |
59
+ | Observed 2026.8.24 through 2026.8.28 | explicit epoch 2 | Modern readers accept both field-frozen and expanded epoch-2 forms without mixing forms inside one entry. |
60
+ | 2026.8.31 and newer | explicit epoch 3 | Exact pins and bounded ranges that cannot select an epoch-3 reader cause current runtimes to reject the write before mutation. |
61
+
62
+ The table records confirmed release boundaries rather than inventing an exact
63
+ first release for legacy epoch 1 or epoch 2. The SDK exports
64
+ `HISTORY_ITEM_HASH_VERSION_3_INTRODUCED_IN`, and runtime compatibility checks
65
+ use that boundary for package-manager-neutral write refusal.
66
+
67
+ ## Whole-Record History Integrity
68
+
69
+ Item anchors prove the replayed project state; they do not prove who recorded an
70
+ event, when it happened, which operation produced it, or which provenance and
71
+ context were attached. New events therefore use a separate record-integrity
72
+ epoch. `record_hash_version: 1` seals every immutable field while preserving the
73
+ item-hash epoch as an independent compatibility contract.
74
+
75
+ `verifyHistoryRecordHash()` reports `record_and_item_state` for a valid sealed
76
+ event and `item_state_only` for a legacy event with neither record-envelope
77
+ field. Half-present, unsupported, and mismatched envelopes fail closed. The
78
+ public SDK also exports the record and patch hashing, sealing,
79
+ `verifyHistoryRewriteEvidence()`, rewrite-resealing, stream-digest, and
80
+ reanchoring primitives so packages and embedded hosts do not need private core
81
+ imports or their own canonicalization.
82
+
83
+ Maintenance retains prior anchors and patch digests in `reanchor_evidence`.
84
+ When policy permits, it also retains the exact prior sealed record so
85
+ metadata-only rewrites remain independently verifiable. Privacy-sensitive
86
+ redaction and provenance normalization deliberately retain digest-only evidence
87
+ instead of embedding the removed value. This separates two claims: the current
88
+ chain is replay-consistent, and a rewrite preserved evidence of what it
89
+ replaced. Compaction records a digest of its pruned prefix and explicitly states
90
+ that individual pruned entries require the pre-compaction stream; it never
91
+ upgrades intentional information loss into a stronger assurance claim.
92
+
56
93
  ## Verification Boundary
57
94
 
58
95
  The regression suite covers each contract at its public SDK or command boundary. Release verification additionally installs the packed package into a temporary project and exercises sparse reads, remote docs, graph impact, extension diagnostics, and history repair without touching the repository tracker.
@@ -1,6 +1,6 @@
1
1
  # Context relevance and packing
2
2
 
3
- Tracked by [pm-4k6b](../.agents/pm/features/pm-4k6b.toon), [pm-3hps](../.agents/pm/tasks/pm-3hps.toon), and [pm-801d](../.agents/pm/features/pm-801d.toon).
3
+ Tracked by [pm-4k6b](../.agents/pm/features/pm-4k6b.toon), [pm-07pt16](../.agents/pm/issues/pm-07pt16.toon), [pm-wv47pf](../.agents/pm/issues/pm-wv47pf.toon), [pm-3hps](../.agents/pm/tasks/pm-3hps.toon), and [pm-801d](../.agents/pm/features/pm-801d.toon).
4
4
 
5
5
  `pm context` and `pm next` share one public SDK relevance pipeline. The built-in
6
6
  commands assemble authoritative item metadata, load rebuildable signal rows,
@@ -73,6 +73,49 @@ Graph proximity normalizes parent and dependency degree. SDK hosts can supply
73
73
  their own pre-normalized signal maps when their project model has richer
74
74
  activity, graph, semantic, or usage data.
75
75
 
76
+ ### Substantive recency
77
+
78
+ Recency is a property of what happened, not of the last file write. Every new
79
+ history entry declares `event_class: substantive|maintenance` through the
80
+ versioned `classifyHistoryEvent()` SDK contract. Legacy entries are classified
81
+ by the same declared operation and patch-field policy; unknown operations fail
82
+ closed as substantive. Package and extension scorers can therefore reuse the
83
+ core vocabulary instead of maintaining private operation lists.
84
+
85
+ The signal selects the most recent substantive history event, then a stamped
86
+ calendar release cohort such as `v2026.7.20`, then `created_at`. It never ranks
87
+ bare `updated_at`, so release attribution, relationship enrichment,
88
+ normalization, linked-artifact updates, and history maintenance cannot promote
89
+ otherwise unchanged work. The rebuildable v5 history-event index stores the
90
+ declared class and retrieves one latest substantive row per requested stream;
91
+ individual immutable streams remain the authoritative fallback. Rebuilds,
92
+ indexed validation reads, and compliant indexed appends share one cross-process
93
+ coordination lock; indexed appends commit their projection row and stream size
94
+ in one SQLite transaction. A lock-conflict fallback append writes authoritative
95
+ history without committing projection data in that transaction, publishes an
96
+ invalidation marker when possible, and discards the derived projection. The
97
+ index must validate or rebuild before serving that append.
98
+
99
+ Explained ranking includes `recency.source`, `coordinate`, and, for history,
100
+ `history_op` plus `event_class` on every served scorer row. Signal snapshots
101
+ persist that evidence alongside the normalized value so a fresh snapshot keeps
102
+ the same explanation as the ranking it serves.
103
+
104
+ ### Delivered usage feedback
105
+
106
+ Usage affinity learns from post-egress delivery rather than pre-budget packing.
107
+ A versioned serve event records the full propensity rows and a correlation id;
108
+ CLI and `PmClient` egress append a delivery event containing the final
109
+ `result_omitted` decision and exact emitted item ids. A whole-result omission
110
+ therefore delivers zero items even when the packer selected rows earlier.
111
+
112
+ Direct `runContext` and `runNext` calls record only their assembled rows on a
113
+ serve event; they do not claim delivery or train affinity by themselves. A
114
+ later CLI or `PmClient` projection appends the correlated delivery decision.
115
+ Legacy serve events have no correlation marker, so the affinity reader ignores
116
+ their inclusion flags and reports them as `untrusted_serving_events` instead of
117
+ training on unverifiable phantom serves.
118
+
76
119
  For corpora of at least 10,000 items, `context` automatically allocates a
77
120
  bounded fraction of its token budget to recent calendar-epoch and epic-lineage
78
121
  rollups. `search` attaches only matching rollups. The projection contains