@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
@@ -4,13 +4,14 @@
4
4
  * Formats compact human and machine output for Output.
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]="202cbb3e-71fe-5701-a1f5-eb515bf56561")}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]="fa89762b-915f-5ef0-a091-f05338c11683")}catch(e){}}();
8
8
  import { getActiveCommandContext, runActiveCommandOverride, runActiveRendererOverride, runActiveServiceOverrideSync, setActiveCommandResult, } from "../extensions/index.js";
9
9
  import { EXIT_CODE } from "../shared/constants.js";
10
10
  import { isHostOutputSuppressed } from "./output-control.js";
11
11
  import { projectMutationResult } from "./mutation-projection.js";
12
12
  import { attachReadOutputContracts } from "../../sdk/context-intent-contracts.js";
13
13
  import { attachOutputTokenAccounting } from "../../sdk/output-token-accounting.js";
14
+ import { propagateContextUsageServingReceipt } from "../../sdk/context-usage.js";
14
15
  import { isReadOutputBudgetExceeded, resolveReadOutputEncoding, } from "../../sdk/read-output-contracts.js";
15
16
  import { encode as encodeToon } from "@toon-format/toon";
16
17
  const DECLARED_PROCESS_EXIT_CODES = new Set(Object.values(EXIT_CODE));
@@ -19,6 +20,18 @@ let streamErrorHandlersInstalled = false;
19
20
  function isPlainObject(value) {
20
21
  return typeof value === "object" && value !== null && !Array.isArray(value);
21
22
  }
23
+ function setActiveCommandResultOmitted(source) {
24
+ const omitted = { read_output: { result_omitted: true } };
25
+ propagateContextUsageServingReceipt(source, omitted);
26
+ setActiveCommandResult(omitted);
27
+ }
28
+ function setActiveCommandDeliveryResult(result, receiptSource, structuredDeliveryPreserved) {
29
+ if (structuredDeliveryPreserved) {
30
+ setActiveCommandResult(result);
31
+ return;
32
+ }
33
+ setActiveCommandResultOmitted(receiptSource);
34
+ }
22
35
  function shouldUseNativeOutput(result) {
23
36
  return isPlainObject(result) && result[NATIVE_OUTPUT_MARKER] === true;
24
37
  }
@@ -346,11 +359,13 @@ function resolveOutputService(effectiveResult, nativeOutput, options, format) {
346
359
  rendered: serviceOverride.result.endsWith("\n")
347
360
  ? serviceOverride.result
348
361
  : `${serviceOverride.result}\n`,
362
+ structuredDeliveryPreserved: false,
349
363
  };
350
364
  }
351
365
  return {
352
366
  result: serviceOverride.handled ? serviceOverride.result : effectiveResult,
353
367
  rendered: null,
368
+ structuredDeliveryPreserved: !serviceOverride.handled || isPlainObject(serviceOverride.result),
354
369
  };
355
370
  }
356
371
  /** Formats a command result after command-level output ownership is resolved. */
@@ -382,9 +397,12 @@ function formatEffectiveOutput(effectiveResult, nativeOutput, options) {
382
397
  commandOptions: resolvedCommandOptions,
383
398
  };
384
399
  const service = resolveOutputService(effectiveResult, nativeOutput, effectiveOptions, format);
385
- if (service.rendered !== null)
400
+ if (service.rendered !== null) {
401
+ setActiveCommandResultOmitted(effectiveResult);
386
402
  return service.rendered;
403
+ }
387
404
  const outputResult = service.result;
405
+ propagateContextUsageServingReceipt(effectiveResult, outputResult);
388
406
  const projectedOutputResult = command === "test"
389
407
  ? projectLinkedTestEvidence(outputResult, options.lean === true)
390
408
  : outputResult;
@@ -392,6 +410,7 @@ function formatEffectiveOutput(effectiveResult, nativeOutput, options) {
392
410
  if (isReadOutputBudgetExceeded(intentOutputResult)) {
393
411
  process.exitCode ||= EXIT_CODE.USAGE;
394
412
  }
413
+ let { structuredDeliveryPreserved } = service;
395
414
  const renderResolvedOutput = (value) => {
396
415
  if (format === "toon") {
397
416
  const markdownDefault = renderDefaultMarkdownResult(value);
@@ -402,6 +421,7 @@ function formatEffectiveOutput(effectiveResult, nativeOutput, options) {
402
421
  ? { rendered: null }
403
422
  : runActiveRendererOverride(format, value);
404
423
  if (rendererOverride.rendered !== null) {
424
+ structuredDeliveryPreserved = false;
405
425
  return rendererOverride.rendered.endsWith("\n")
406
426
  ? rendererOverride.rendered
407
427
  : `${rendererOverride.rendered}\n`;
@@ -414,7 +434,9 @@ function formatEffectiveOutput(effectiveResult, nativeOutput, options) {
414
434
  const accountedOutputResult = options.tokenAccounting === true
415
435
  ? attachOutputTokenAccounting(intentOutputResult, renderResolvedOutput)
416
436
  : intentOutputResult;
417
- return renderResolvedOutput(accountedOutputResult);
437
+ const rendered = renderResolvedOutput(accountedOutputResult);
438
+ setActiveCommandDeliveryResult(accountedOutputResult, effectiveResult, options.quiet !== true && structuredDeliveryPreserved);
439
+ return rendered;
418
440
  }
419
441
  /** Implements format output for the public runtime surface of this module. */
420
442
  export function formatOutput(result, options) {
@@ -427,9 +449,11 @@ export function formatOutput(result, options) {
427
449
  ? suppressedOutput.result
428
450
  : stripNativeOutputMarker(commandOverride.result);
429
451
  setActiveCommandResult(effectiveResult);
430
- return suppressedOutput
431
- ? ""
432
- : formatEffectiveOutput(effectiveResult, nativeOutput, options);
452
+ if (suppressedOutput) {
453
+ setActiveCommandResultOmitted(effectiveResult);
454
+ return "";
455
+ }
456
+ return formatEffectiveOutput(effectiveResult, nativeOutput, options);
433
457
  }
434
458
  /** Implements print result for the public runtime surface of this module. */
435
459
  export function printResult(result, options) {
@@ -468,4 +492,4 @@ export const outputTestOnly = {
468
492
  renderToonValue,
469
493
  };
470
494
  //# sourceMappingURL=output.js.map
471
- //# debugId=202cbb3e-71fe-5701-a1f5-eb515bf56561
495
+ //# debugId=fa89762b-915f-5ef0-a091-f05338c11683
@@ -26,7 +26,7 @@ export interface AgentProvenanceObservation {
26
26
  */
27
27
  export type AgentProvenance = Readonly<Record<string, AgentProvenanceObservation | null>>;
28
28
  /** Bounded reason explaining why one declared provenance dimension was absent. */
29
- export type AgentProvenanceAbsenceReason = "harness_unavailable" | "resolver_failed" | "resolver_not_configured" | "probes_disabled" | "invalid_value";
29
+ export type AgentProvenanceAbsenceReason = "harness_unavailable" | "resolver_input_missing" | "resolver_failed" | "resolver_not_configured" | "probes_disabled" | "invalid_value";
30
30
  /** Machine-readable resolution outcome for one provenance dimension. */
31
31
  export interface AgentProvenanceOutcome {
32
32
  /** Whether the dimension resolved without retaining private source material. */
@@ -168,6 +168,8 @@ export interface HarnessDetectionSignals {
168
168
  cwd?: string;
169
169
  /** Home directory override used by embedders and isolated tests. */
170
170
  home_dir?: string;
171
+ /** Explicit harness-owned session file supplied by an embedding host. */
172
+ session_file?: string;
171
173
  }
172
174
  /** Built-in agent descriptors evaluated before package and workspace additions. */
173
175
  export declare const BUILTIN_HARNESS_SIGNAL_DESCRIPTORS: readonly HarnessSignalDescriptor[];
@@ -4,7 +4,7 @@
4
4
  * Provides shared primitives and utilities for Author.
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]="cf550961-0040-5e04-9d8d-16e316027e43")}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]="dfbf4eb8-1f02-5880-a70a-0e7ed9b9784a")}catch(e){}}();
8
8
  import { AsyncLocalStorage } from "node:async_hooks";
9
9
  import { createHash } from "node:crypto";
10
10
  import fs from "node:fs";
@@ -12,6 +12,7 @@ import os from "node:os";
12
12
  import path from "node:path";
13
13
  import { resolveAgentSessionContextFromSignals, } from "./agent-session-context.js";
14
14
  import { readAgentSemanticAttributionSync, } from "../session/session-state.js";
15
+ import { isFileAbsentError } from "../fs/fs-utils.js";
15
16
  /** Stable built-in provenance dimensions understood by the default runtime. */
16
17
  export const AGENT_PROVENANCE_DIMENSIONS = [
17
18
  "model",
@@ -357,18 +358,83 @@ function parseClaudeProvenanceLine(line) {
357
358
  }
358
359
  return Object.freeze({ model, version });
359
360
  }
360
- function readClaudeSessionProvenance(dimension, signals, env) {
361
+ /** Classify one candidate without following symlinks or leaking filesystem detail. */
362
+ function claudeTranscriptCandidateStatus(candidate) {
363
+ try {
364
+ return fs.lstatSync(candidate).isFile() ? "available" : "missing";
365
+ }
366
+ catch (error) {
367
+ return isFileAbsentError(error) ? "missing" : "failed";
368
+ }
369
+ }
370
+ /** Resolve a bounded cross-workspace Claude transcript discovery result. */
371
+ function discoverClaudeSessionFile(projectsRoot, session) {
372
+ let discovered;
373
+ try {
374
+ discovered = fs
375
+ .readdirSync(projectsRoot, { withFileTypes: true })
376
+ .filter((entry) => entry.isDirectory())
377
+ .sort((left, right) => left.name.localeCompare(right.name))
378
+ .slice(0, 512)
379
+ .map((entry) => {
380
+ const candidate = path.join(projectsRoot, entry.name, `${session}.jsonl`);
381
+ return {
382
+ candidate,
383
+ status: claudeTranscriptCandidateStatus(candidate),
384
+ };
385
+ });
386
+ }
387
+ catch (error) {
388
+ return { status: isFileAbsentError(error) ? "missing" : "failed" };
389
+ }
390
+ const matches = discovered
391
+ .filter(({ status }) => status === "available")
392
+ .map(({ candidate }) => candidate);
393
+ if (matches.length === 0) {
394
+ return {
395
+ status: discovered.some(({ status }) => status === "failed")
396
+ ? "failed"
397
+ : "missing",
398
+ };
399
+ }
400
+ if (matches.length > 1)
401
+ return { status: "ambiguous" };
402
+ return { status: "available", path: matches[0] };
403
+ }
404
+ /** Resolve one Claude transcript by stable session identity without exposing its path. */
405
+ function resolveClaudeSessionFile(signals, env) {
361
406
  const session = nonBlank(env.CLAUDE_CODE_SESSION_ID);
362
- if (!session || !/^[A-Za-z0-9_-]{1,128}$/u.test(session))
363
- return undefined;
407
+ if (!session || !/^[A-Za-z0-9_-]{1,128}$/u.test(session)) {
408
+ return { status: "unavailable" };
409
+ }
364
410
  const workspace = path.resolve(signals.cwd ?? process.cwd());
365
411
  const encodedWorkspace = workspace.replaceAll(/[^A-Za-z0-9-]/gu, "-");
366
- const sessionPath = path.join(signals.home_dir ?? os.homedir(), ".claude", "projects", encodedWorkspace, `${session}.jsonl`);
412
+ const projectsRoot = path.join(signals.home_dir ?? os.homedir(), ".claude", "projects");
413
+ const directPath = path.join(projectsRoot, encodedWorkspace, `${session}.jsonl`);
414
+ const explicitPath = nonBlank(signals.session_file);
415
+ const suppliedPath = explicitPath && path.basename(explicitPath) === `${session}.jsonl`
416
+ ? explicitPath
417
+ : undefined;
418
+ for (const candidate of [suppliedPath, directPath]) {
419
+ if (!candidate)
420
+ continue;
421
+ const status = claudeTranscriptCandidateStatus(candidate);
422
+ if (status === "available")
423
+ return { status, path: candidate };
424
+ if (status === "failed")
425
+ return { status };
426
+ }
427
+ return discoverClaudeSessionFile(projectsRoot, session);
428
+ }
429
+ function readClaudeSessionProvenance(dimension, signals, env) {
430
+ const resolution = resolveClaudeSessionFile(signals, env);
431
+ if (resolution.status !== "available")
432
+ return undefined;
367
433
  try {
368
- const file = fs.openSync(sessionPath, "r");
434
+ const file = fs.openSync(resolution.path, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
369
435
  try {
370
436
  const stats = fs.fstatSync(file);
371
- const cacheKey = `${sessionPath}\u0000${stats.size}\u0000${stats.mtimeMs}`;
437
+ const cacheKey = `${resolution.path}\u0000${stats.size}\u0000${stats.mtimeMs}`;
372
438
  const cached = claudeProvenanceSnapshotCache.get(cacheKey);
373
439
  if (cached)
374
440
  return cached[dimension];
@@ -553,14 +619,20 @@ function resolveProvenanceProbe(dimension, signals, env, descriptor) {
553
619
  }
554
620
  return undefined;
555
621
  }
556
- function provenanceResolverHasInput(resolver, descriptor, env) {
622
+ function provenanceResolverHasInput(resolver, descriptor, signals, env) {
557
623
  if (resolver === "ai_agent_version") {
558
624
  const value = nonBlank(env.AI_AGENT);
559
- return (value !== undefined && literalSignalMatches(value, descriptor.harness));
625
+ return value !== undefined &&
626
+ literalSignalMatches(value, descriptor.harness)
627
+ ? "available"
628
+ : "unavailable";
629
+ }
630
+ if (resolver === "codex_session_file") {
631
+ return nonBlank(env.CODEX_THREAD_ID) !== undefined
632
+ ? "available"
633
+ : "unavailable";
560
634
  }
561
- return resolver === "codex_session_file"
562
- ? nonBlank(env.CODEX_THREAD_ID) !== undefined
563
- : nonBlank(env.CLAUDE_CODE_SESSION_ID) !== undefined;
635
+ return resolveClaudeSessionFile(signals, env).status;
564
636
  }
565
637
  function effectiveHarnessDetectionSignals(signals) {
566
638
  if (signals)
@@ -907,7 +979,17 @@ export function detectAgentIdentity(signals) {
907
979
  ];
908
980
  return Object.fromEntries(entries.filter((entry) => entry[1] !== undefined));
909
981
  }
910
- function resolveProvenanceOutcome(dimension, identity, descriptor, env, probesEnabled, invalidValue) {
982
+ /** Classify one configured resolver's privacy-safe absence outcome. */
983
+ function provenanceResolverAbsence(resolverInput) {
984
+ if (resolverInput === "unavailable") {
985
+ return { status: "unavailable", reason: "harness_unavailable" };
986
+ }
987
+ if (resolverInput === "missing") {
988
+ return { status: "unavailable", reason: "resolver_input_missing" };
989
+ }
990
+ return { status: "failed", reason: "resolver_failed" };
991
+ }
992
+ function resolveProvenanceOutcome(dimension, identity, descriptor, signals, env, probesEnabled, invalidValue) {
911
993
  const resolver = descriptor?.provenance_resolvers[dimension];
912
994
  if (identity.provenance?.[dimension]) {
913
995
  return {
@@ -924,14 +1006,20 @@ function resolveProvenanceOutcome(dimension, identity, descriptor, env, probesEn
924
1006
  };
925
1007
  }
926
1008
  if (resolver) {
927
- const resolverHasInput = provenanceResolverHasInput(resolver, descriptor, env);
928
- const status = resolverHasInput && probesEnabled ? "failed" : "unavailable";
929
- const reason = !resolverHasInput
930
- ? "harness_unavailable"
931
- : probesEnabled
932
- ? "resolver_failed"
933
- : "probes_disabled";
934
- return { status, reason, resolver, rule_version: "v1" };
1009
+ if (!probesEnabled) {
1010
+ return {
1011
+ status: "unavailable",
1012
+ reason: "probes_disabled",
1013
+ resolver,
1014
+ rule_version: "v1",
1015
+ };
1016
+ }
1017
+ const resolverInput = provenanceResolverHasInput(resolver, descriptor, signals, env);
1018
+ return {
1019
+ ...provenanceResolverAbsence(resolverInput),
1020
+ resolver,
1021
+ rule_version: "v1",
1022
+ };
935
1023
  }
936
1024
  return {
937
1025
  status: descriptor?.provenance_unavailable_dimensions.includes(dimension)
@@ -972,7 +1060,7 @@ export function diagnoseAgentIdentity(signals) {
972
1060
  });
973
1061
  const outcomes = Object.fromEntries(AGENT_PROVENANCE_DIMENSIONS.map((dimension) => [
974
1062
  dimension,
975
- resolveProvenanceOutcome(dimension, identity, descriptor, env, probesEnabled, dimension === "role" && invalidRoleValue),
1063
+ resolveProvenanceOutcome(dimension, identity, descriptor, effectiveSignals, env, probesEnabled, dimension === "role" && invalidRoleValue),
976
1064
  ]));
977
1065
  return { ...identity, provenance_outcomes: outcomes };
978
1066
  }
@@ -1082,4 +1170,4 @@ export function resolveAuthor(candidate, fallback) {
1082
1170
  return identity.author;
1083
1171
  }
1084
1172
  //# sourceMappingURL=author.js.map
1085
- //# debugId=cf550961-0040-5e04-9d8d-16e316027e43
1173
+ //# debugId=dfbf4eb8-1f02-5880-a70a-0e7ed9b9784a
@@ -4,6 +4,8 @@ export declare function nowIso(): string;
4
4
  export declare function isTimestampLiteral(input: string): boolean;
5
5
  /** Return whether a string is a calendar-valid RFC 3339 date-time. */
6
6
  export declare function isRfc3339DateTime(input: string): boolean;
7
+ /** Return whether a value is a calendar-valid RFC 3339 date-time whose fractional seconds carry no sub-millisecond information. */
8
+ export declare function isMillisecondPrecisionRfc3339DateTime(input: string): boolean;
7
9
  /** Implements compare timestamp strings for the public runtime surface of this module. */
8
10
  export declare function compareTimestampStrings(left: string, right: string): number;
9
11
  /** Timestamp-bearing record accepted by shared inclusive bound filtering. */
@@ -4,7 +4,7 @@
4
4
  * Provides shared primitives and utilities for Time.
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]="7887e752-b1b8-5c5e-9dd8-93b41cb757af")}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]="fb1102d4-1beb-5de8-87e6-af2efebafe39")}catch(e){}}();
8
8
  import { PmCliError } from "./errors.js";
9
9
  import { evictOldestMemoEntries } from "./memo.js";
10
10
  import { EXIT_CODE } from "./constants.js";
@@ -48,6 +48,12 @@ export function isRfc3339DateTime(input) {
48
48
  (offsetHourRaw === undefined || Number(offsetHourRaw) <= 23) &&
49
49
  (offsetMinuteRaw === undefined || Number(offsetMinuteRaw) <= 59));
50
50
  }
51
+ /** Return whether a value is a calendar-valid RFC 3339 date-time whose fractional seconds carry no sub-millisecond information. */
52
+ export function isMillisecondPrecisionRfc3339DateTime(input) {
53
+ const fraction = /\.(\d+)(?:Z|[+-]\d{2}:\d{2})$/iu.exec(input)?.[1];
54
+ return (isRfc3339DateTime(input) &&
55
+ (fraction === undefined || /^\d{0,3}0*$/u.test(fraction)));
56
+ }
51
57
  /**
52
58
  * Memoized `Date.parse` for {@link compareTimestampStrings}. Sort comparators call it
53
59
  * O(n log n) times over a corpus whose timestamp strings repeat heavily, and
@@ -298,4 +304,4 @@ export const _testOnly = {
298
304
  isWhitespaceCharacter,
299
305
  };
300
306
  //# sourceMappingURL=time.js.map
301
- //# debugId=7887e752-b1b8-5c5e-9dd8-93b41cb757af
307
+ //# debugId=fb1102d4-1beb-5de8-87e6-af2efebafe39
@@ -4,7 +4,7 @@
4
4
  * Maintains a rebuildable SQLite projection for bounded metadata queries.
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]="e94075b0-810d-506c-b6a2-ae322526c078")}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]="97cfeab2-8e3f-5b70-9f64-10494158d141")}catch(e){}}();
8
8
  import fs from "node:fs/promises";
9
9
  import path from "node:path";
10
10
  import { randomUUID } from "node:crypto";
@@ -185,13 +185,13 @@ function readIndexMetadata(database) {
185
185
  * callers can remove and lazily rebuild this optional projection.
186
186
  */
187
187
  export async function updateItemMetadataQueryIndex(options) {
188
+ const Database = resolveDatabaseSync();
189
+ if (!Database)
190
+ return false;
188
191
  const indexPath = queryIndexPath(options.pmRoot);
189
192
  let database;
190
193
  try {
191
194
  await fs.access(indexPath);
192
- const Database = resolveDatabaseSync();
193
- if (!Database)
194
- return false;
195
195
  database = new Database(indexPath);
196
196
  database.exec("PRAGMA foreign_keys = ON");
197
197
  const metadata = readIndexMetadata(database);
@@ -470,4 +470,4 @@ export const _testOnly = {
470
470
  },
471
471
  };
472
472
  //# sourceMappingURL=item-metadata-query-index.js.map
473
- //# debugId=e94075b0-810d-506c-b6a2-ae322526c078
473
+ //# debugId=97cfeab2-8e3f-5b70-9f64-10494158d141
@@ -0,0 +1,9 @@
1
+ /** Deterministic oldest coordinate used when legacy creation metadata is invalid. */
2
+ export declare const CONTEXT_RECENCY_EPOCH = "1970-01-01T00:00:00.000Z";
3
+ /**
4
+ * Canonicalize a calendar-valid RFC 3339 instant or dashed legacy date-only
5
+ * value. Compact dates, sub-millisecond instants, and host-local date-times are
6
+ * rejected because they cannot round-trip through the strict timestamp contract
7
+ * losslessly and deterministically.
8
+ */
9
+ export declare function canonicalizeContextRecencyCoordinate(value: unknown): string | null;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @module sdk/context/recency
3
+ *
4
+ * Canonicalizes the absolute timestamps used as durable context-recency
5
+ * coordinates without accepting relative or host-local date-time values.
6
+ */
7
+
8
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="377499d7-13b3-55f0-9d44-425bfcaf7964")}catch(e){}}();
9
+ import { isMillisecondPrecisionRfc3339DateTime, resolveIsoOrRelative, } from "../../core/shared/time.js";
10
+ /** Deterministic oldest coordinate used when legacy creation metadata is invalid. */
11
+ export const CONTEXT_RECENCY_EPOCH = "1970-01-01T00:00:00.000Z";
12
+ /**
13
+ * Canonicalize a calendar-valid RFC 3339 instant or dashed legacy date-only
14
+ * value. Compact dates, sub-millisecond instants, and host-local date-times are
15
+ * rejected because they cannot round-trip through the strict timestamp contract
16
+ * losslessly and deterministically.
17
+ */
18
+ export function canonicalizeContextRecencyCoordinate(value) {
19
+ if (typeof value !== "string")
20
+ return null;
21
+ const trimmed = value.trim();
22
+ if (!isMillisecondPrecisionRfc3339DateTime(trimmed) &&
23
+ !/^\d{4}-\d{2}-\d{2}$/u.test(trimmed)) {
24
+ return null;
25
+ }
26
+ try {
27
+ return resolveIsoOrRelative(trimmed, new Date(Number.NaN), "context signal recency coordinate");
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ //# sourceMappingURL=recency.js.map
34
+ //# debugId=377499d7-13b3-55f0-9d44-425bfcaf7964
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @module sdk/context/usage-egress
3
+ *
4
+ * Keeps post-projection context feedback best-effort without weakening the
5
+ * response contract returned by embedded SDK and MCP hosts.
6
+ */
7
+ import { finalizeContextUsageDelivery } from "../context-usage.js";
8
+ /** Finalize derived usage feedback and attach a stable warning on failure. */
9
+ export declare function finalizeContextUsageEgress(pmRoot: string, projected: unknown, finalize?: typeof finalizeContextUsageDelivery): Promise<void>;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @module sdk/context/usage-egress
3
+ *
4
+ * Keeps post-projection context feedback best-effort without weakening the
5
+ * response contract returned by embedded SDK and MCP hosts.
6
+ */
7
+
8
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="c5a14f99-ce5b-5da7-8b17-6b6a56f0644a")}catch(e){}}();
9
+ import { finalizeContextUsageDelivery } from "../context-usage.js";
10
+ /** Finalize derived usage feedback and attach a stable warning on failure. */
11
+ export async function finalizeContextUsageEgress(pmRoot, projected, finalize = finalizeContextUsageDelivery) {
12
+ try {
13
+ await finalize({ pmRoot, result: projected });
14
+ }
15
+ catch {
16
+ if (typeof projected === "object" &&
17
+ projected !== null &&
18
+ !Array.isArray(projected)) {
19
+ const record = projected;
20
+ const warnings = Array.isArray(record.warnings)
21
+ ? record.warnings.filter((warning) => typeof warning === "string")
22
+ : [];
23
+ record.warnings = [
24
+ ...new Set([...warnings, "context_usage_feedback_write_failed"]),
25
+ ].sort();
26
+ }
27
+ }
28
+ }
29
+ //# sourceMappingURL=usage-egress.js.map
30
+ //# debugId=c5a14f99-ce5b-5da7-8b17-6b6a56f0644a
@@ -5,12 +5,13 @@
5
5
  * workspace configuration, and packages.
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]="da15ca02-02cc-5886-8c82-610939b8581c")}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]="5dc9c6e4-6db8-560f-a87f-368132e2ffb3")}catch(e){}}();
9
9
  import { AsyncLocalStorage } from "node:async_hooks";
10
10
  import { renderPmCommand } from "./command-line.js";
11
11
  import { attachOutputOmissionReceipt } from "./output-projection.js";
12
12
  import { encodeQueryCursor } from "./pagination.js";
13
13
  import { applyReadOutputDimensions, stabilizeReadOutputReceiptEstimates, } from "./read-output-contracts.js";
14
+ import { propagateContextUsageServingReceipt } from "./context-usage.js";
14
15
  import { EXIT_CODE } from "../core/shared/constants.js";
15
16
  import { PmCliError } from "../core/shared/errors.js";
16
17
  /** Built-in intent projections shared by CLI, SDK, MCP, and package authors. */
@@ -692,6 +693,7 @@ export function attachReadOutputContracts(command, options, result) {
692
693
  !Array.isArray(disclosedResult)
693
694
  ? applyReadOutputDimensions(command ?? "", options, collapseContinuationMetadata(options, attachContextIntentReceipt(command ?? "", options, disclosedResult)))
694
695
  : disclosedResult;
696
+ propagateContextUsageServingReceipt(result, projected);
695
697
  if (options.outputRowContract === true ||
696
698
  options.output_row_contract === true ||
697
699
  typeof projected !== "object" ||
@@ -700,7 +702,9 @@ export function attachReadOutputContracts(command, options, result) {
700
702
  !Object.hasOwn(projected, "row_contract")) {
701
703
  return projected;
702
704
  }
703
- return stabilizeSuppressedRowContractReceipts(Object.fromEntries(Object.entries(projected).filter(([key]) => key !== "row_contract")), options);
705
+ const suppressed = stabilizeSuppressedRowContractReceipts(Object.fromEntries(Object.entries(projected).filter(([key]) => key !== "row_contract")), options);
706
+ propagateContextUsageServingReceipt(projected, suppressed);
707
+ return suppressed;
704
708
  }
705
709
  //# sourceMappingURL=context-intent-contracts.js.map
706
- //# debugId=da15ca02-02cc-5886-8c82-610939b8581c
710
+ //# debugId=5dc9c6e4-6db8-560f-a87f-368132e2ffb3
@@ -1,11 +1,28 @@
1
1
  import type { RuntimeStatusRegistry } from "../core/schema/runtime-schema.js";
2
2
  import type { ItemMetadata } from "../types/index.js";
3
+ import type { HistoryEventClass } from "../core/history/event-classification.js";
3
4
  /** Canonical signal keys understood by the built-in relevance model. */
4
5
  export declare const CONTEXT_RELEVANCE_SIGNAL_NAMES: readonly ["structural", "recency", "activity_density", "graph_proximity", "claim_focus", "priority_pressure", "risk_pressure", "deadline_pressure", "knowledge_density", "author_affinity", "usage_affinity", "semantic_similarity"];
5
6
  /** A normalized signal consumed by the built-in context relevance scorer. */
6
7
  export type ContextRelevanceSignalName = (typeof CONTEXT_RELEVANCE_SIGNAL_NAMES)[number];
7
8
  /** Normalized candidate features; omitted signals are excluded from weighting. */
8
9
  export type ContextRelevanceSignals = Partial<Record<Exclude<ContextRelevanceSignalName, "structural">, number>>;
10
+ /** Authoritative coordinate and fallback that produced an item's recency. */
11
+ export interface ContextRecencyEvidence {
12
+ /** Source selected by the canonical fallback ladder. */
13
+ source: "substantive_history" | "release_cohort" | "created_at";
14
+ /** ISO coordinate used for deterministic recency ordering. */
15
+ coordinate: string;
16
+ /** Immutable operation selected from history when source is substantive_history. */
17
+ history_op?: string;
18
+ /** Declared class selected from history when source is substantive_history. */
19
+ event_class?: HistoryEventClass;
20
+ }
21
+ /** Per-signal provenance exposed by explained relevance results. */
22
+ export interface ContextSignalProvenance {
23
+ /** Evidence for the canonical temporal component. */
24
+ recency: ContextRecencyEvidence;
25
+ }
9
26
  /** A project-management object and its derived relevance signals. */
10
27
  export interface ContextRelevanceCandidate<TItem> {
11
28
  /** Stable identifier used to reference this record across commands and storage. */
@@ -14,11 +31,15 @@ export interface ContextRelevanceCandidate<TItem> {
14
31
  item: TItem;
15
32
  /** Value that configures or reports signals for this contract. */
16
33
  signals?: ContextRelevanceSignals;
34
+ /** Authoritative source details for explainable derived signals. */
35
+ signal_provenance?: ContextSignalProvenance;
17
36
  }
18
37
  /** Item candidate whose built-in metadata derivation always supplies signals. */
19
38
  export interface ItemContextRelevanceCandidate extends ContextRelevanceCandidate<ItemMetadata> {
20
39
  /** Complete built-in derivation result, with unavailable signals omitted by value. */
21
40
  signals: ContextRelevanceSignals;
41
+ /** Built-in recency derivation always discloses its source. */
42
+ signal_provenance: ContextSignalProvenance;
22
43
  }
23
44
  /** Inputs that make item-signal derivation deterministic and host-configurable. */
24
45
  export interface BuildItemContextRelevanceCandidatesOptions {
@@ -42,6 +63,8 @@ export interface BuildItemContextRelevanceCandidatesOptions {
42
63
  knowledgeDensity?: Readonly<Record<string, number>>;
43
64
  /** Optional history-derived author affinity by item id. */
44
65
  authorAffinity?: Readonly<Record<string, number>>;
66
+ /** Latest substantive history evidence keyed by item id. */
67
+ recencyEvidence?: Readonly<Record<string, ContextRecencyEvidence>>;
45
68
  }
46
69
  /**
47
70
  * Derive the canonical metadata signals consumed by `pm context` and `pm next`.