@unbrained/pm-cli 2026.8.10 → 2026.8.11

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 (175) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +102 -80
  3. package/dist/cli/commander-usage.js +79 -7
  4. package/dist/cli/error-guidance.d.ts +10 -0
  5. package/dist/cli/error-guidance.js +76 -25
  6. package/dist/cli/main.js +6 -2
  7. package/dist/cli/register-assurance.d.ts +8 -0
  8. package/dist/cli/register-assurance.js +52 -0
  9. package/dist/cli/register-files-lookup.js +14 -3
  10. package/dist/cli/register-mutation.js +30 -9
  11. package/dist/cli/register-operations.js +16 -11
  12. package/dist/cli-bundle/bundle-manifest.json +159 -159
  13. package/dist/cli-bundle/chunks/{chunk-TRWXF476.js → chunk-2OOU2AFH.js} +2 -2
  14. package/dist/cli-bundle/chunks/chunk-2RA2YTHJ.js +33 -0
  15. package/dist/cli-bundle/chunks/chunk-A2SJGHSI.js +3 -0
  16. package/dist/cli-bundle/chunks/chunk-DSKYD4LG.js +13 -0
  17. package/dist/cli-bundle/chunks/chunk-HC3GM6YY.js +194 -0
  18. package/dist/cli-bundle/chunks/chunk-IUNRVDAI.js +2 -0
  19. package/dist/cli-bundle/chunks/chunk-W7CPZGSB.js +2 -0
  20. package/dist/cli-bundle/chunks/{chunk-EBO7OUUE.js → chunk-WMEZHCFI.js} +59 -53
  21. package/dist/cli-bundle/chunks/{chunk-ETML5C6H.js → chunk-ZU34C3LH.js} +47 -47
  22. package/dist/cli-bundle/chunks/chunk-ZXOC6HG5.js +5 -0
  23. package/dist/cli-bundle/chunks/{register-list-query-OJ6ZXKV4.js → register-list-query-HAUXVUPY.js} +8 -8
  24. package/dist/cli-bundle/chunks/register-mutation-7Y5U7ABT.js +20 -0
  25. package/dist/cli-bundle/chunks/register-operations-EQX3DLAZ.js +2 -0
  26. package/dist/cli-bundle/chunks/{register-setup-S3KT2LTH.js → register-setup-NOCOOWQY.js} +2 -2
  27. package/dist/cli-bundle/focused-chunks/{chunk-34SX654S.js → chunk-23FTGO3W.js} +2 -2
  28. package/dist/cli-bundle/focused-chunks/{chunk-2COZ67XT.js → chunk-2DL3MRTD.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/chunk-3AYKXMYX.js +2 -0
  30. package/dist/cli-bundle/focused-chunks/chunk-4AHEC74N.js +2 -0
  31. package/dist/cli-bundle/focused-chunks/{chunk-7UN6BHHO.js → chunk-4H5IA6AV.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/chunk-4SV3ZKG3.js +16 -0
  33. package/dist/cli-bundle/focused-chunks/chunk-55BIB6DV.js +2 -0
  34. package/dist/cli-bundle/focused-chunks/chunk-6JW6Z2P5.js +8 -0
  35. package/dist/cli-bundle/focused-chunks/{chunk-IW43E4XL.js → chunk-BKPIY34S.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/chunk-D4PIWE6D.js +2 -0
  37. package/dist/cli-bundle/focused-chunks/{chunk-KR5RVXLQ.js → chunk-DPO7TEFX.js} +29 -29
  38. package/dist/cli-bundle/focused-chunks/{chunk-JMVA4HKR.js → chunk-E3KCL7AY.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/chunk-ERAAFLPS.js +153 -0
  40. package/dist/cli-bundle/focused-chunks/{chunk-RIIN5V4N.js → chunk-F6E4JZKG.js} +2 -2
  41. package/dist/cli-bundle/focused-chunks/chunk-FPSYO5ZG.js +18 -0
  42. package/dist/cli-bundle/focused-chunks/{chunk-M6RPIXKC.js → chunk-J5EKAIVD.js} +2 -2
  43. package/dist/cli-bundle/focused-chunks/{chunk-2EXI2DKR.js → chunk-KDH5OX3D.js} +2 -2
  44. package/dist/cli-bundle/focused-chunks/chunk-OJ3LVVIS.js +2 -0
  45. package/dist/cli-bundle/focused-chunks/{chunk-DZGAHZZV.js → chunk-TL5M2PAY.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/{chunk-75774JWP.js → chunk-UDAZWT25.js} +2 -2
  47. package/dist/cli-bundle/focused-chunks/chunk-VABB4L5Y.js +17 -0
  48. package/dist/cli-bundle/main.js +13 -13
  49. package/dist/cli-bundle/sdk-authoring.js +1 -1
  50. package/dist/cli-bundle/sdk-contracts.js +1 -1
  51. package/dist/cli-bundle/sdk-core.js +41 -39
  52. package/dist/cli-bundle/sdk-governance.js +1 -1
  53. package/dist/cli-bundle/sdk-graph.js +1 -1
  54. package/dist/cli-bundle/sdk-merge.js +1 -1
  55. package/dist/cli-bundle/sdk-query.js +1 -1
  56. package/dist/cli-bundle/sdk-runtime.js +1 -1
  57. package/dist/cli-bundle/sdk-testing.js +1 -1
  58. package/dist/cli-bundle/sdk.js +2 -2
  59. package/dist/core/session/session-state.d.ts +47 -0
  60. package/dist/core/session/session-state.js +207 -6
  61. package/dist/core/shared/author.d.ts +7 -1
  62. package/dist/core/shared/author.js +66 -46
  63. package/dist/core/shared/errors.d.ts +8 -0
  64. package/dist/core/shared/errors.js +2 -2
  65. package/dist/sdk/agent/refusal-reachability.d.ts +40 -0
  66. package/dist/sdk/agent/refusal-reachability.js +72 -0
  67. package/dist/sdk/agent/subcommand-recovery.d.ts +40 -0
  68. package/dist/sdk/agent/subcommand-recovery.js +84 -0
  69. package/dist/sdk/cli-bootstrap.d.ts +8 -0
  70. package/dist/sdk/cli-bootstrap.js +7 -7
  71. package/dist/sdk/cli-contracts/completeness.js +13 -3
  72. package/dist/sdk/cli-contracts/enum-contracts.d.ts +1 -1
  73. package/dist/sdk/cli-contracts/enum-contracts.js +3 -2
  74. package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
  75. package/dist/sdk/cli-contracts/flag-contracts.js +17 -2
  76. package/dist/sdk/cli-contracts/runtime-contracts.js +4 -3
  77. package/dist/sdk/cli-contracts/schemas/assurance-definition.d.ts +513 -0
  78. package/dist/sdk/cli-contracts/schemas/assurance-definition.js +251 -0
  79. package/dist/sdk/cli-contracts/tool-parameter-tables.js +79 -2
  80. package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
  81. package/dist/sdk/cli-contracts/tool-schema.js +34 -4
  82. package/dist/sdk/cli-contracts.d.ts +1 -1
  83. package/dist/sdk/cli-contracts.js +3 -3
  84. package/dist/sdk/completion.js +9 -3
  85. package/dist/sdk/config.js +9 -3
  86. package/dist/sdk/context/semantic-session-attribution.d.ts +32 -0
  87. package/dist/sdk/context/semantic-session-attribution.js +83 -0
  88. package/dist/sdk/core-governance.d.ts +3 -1
  89. package/dist/sdk/core-governance.js +5 -3
  90. package/dist/sdk/core.d.ts +1 -1
  91. package/dist/sdk/core.js +2 -2
  92. package/dist/sdk/error-code-catalog.d.ts +13 -0
  93. package/dist/sdk/error-code-catalog.js +35 -2
  94. package/dist/sdk/extension.js +18 -17
  95. package/dist/sdk/files.d.ts +11 -0
  96. package/dist/sdk/files.js +82 -24
  97. package/dist/sdk/generated-error-code-catalog.js +32 -13
  98. package/dist/sdk/governance/assurance-action-contracts.d.ts +7 -0
  99. package/dist/sdk/governance/assurance-action-contracts.js +5 -0
  100. package/dist/sdk/governance/assurance-action.d.ts +70 -0
  101. package/dist/sdk/governance/assurance-action.js +198 -0
  102. package/dist/sdk/governance/assurance-limits.d.ts +7 -0
  103. package/dist/sdk/governance/assurance-limits.js +11 -0
  104. package/dist/sdk/governance/assurance-runtime.d.ts +20 -0
  105. package/dist/sdk/governance/assurance-runtime.js +131 -0
  106. package/dist/sdk/governance/assurance.d.ts +432 -0
  107. package/dist/sdk/governance/assurance.js +689 -0
  108. package/dist/sdk/graph/run.js +8 -3
  109. package/dist/sdk/index.d.ts +6 -1
  110. package/dist/sdk/index.js +8 -3
  111. package/dist/sdk/lifecycle/claim.js +18 -3
  112. package/dist/sdk/lifecycle/focus.js +13 -3
  113. package/dist/sdk/lifecycle/plan.js +8 -3
  114. package/dist/sdk/provenance.d.ts +38 -0
  115. package/dist/sdk/provenance.js +64 -2
  116. package/dist/sdk/query/context.js +19 -8
  117. package/dist/sdk/runtime-extended-actions.js +22 -5
  118. package/dist/sdk/runtime-primitives.d.ts +2 -0
  119. package/dist/sdk/runtime-primitives.js +4 -2
  120. package/dist/sdk/runtime.d.ts +4 -0
  121. package/dist/sdk/runtime.js +31 -27
  122. package/dist/sdk/telemetry.js +7 -4
  123. package/dist/sdk/traceability/runtime-files-lookup.d.ts +8 -0
  124. package/dist/sdk/traceability/runtime-files-lookup.js +33 -0
  125. package/dist/sdk/traceability/source-traceability.d.ts +102 -0
  126. package/dist/sdk/traceability/source-traceability.js +293 -0
  127. package/dist/types.d.ts +8 -2
  128. package/dist/types.js +2 -2
  129. package/docs/ASSURANCE.md +132 -0
  130. package/docs/README.md +1 -0
  131. package/docs/RELEASING.md +9 -5
  132. package/docs/SDK.md +12 -1
  133. package/docs/SDK_AGENT_SESSION_CONTEXT.md +40 -4
  134. package/docs/SDK_EVIDENCE_TRACEABILITY.md +39 -1
  135. package/docs/SDK_RUNTIME_BOUNDARIES.md +36 -1
  136. package/docs/TESTING.md +12 -9
  137. package/docs/generated/AGENT_COMMAND_SURFACE.md +1 -0
  138. package/marketplace.json +2 -2
  139. package/package.json +3 -3
  140. package/packages/pm-beads/package.json +1 -1
  141. package/packages/pm-calendar/package.json +1 -1
  142. package/packages/pm-command-kit/package.json +1 -1
  143. package/packages/pm-digital-twin/package.json +1 -1
  144. package/packages/pm-governance-audit/package.json +1 -1
  145. package/packages/pm-guide-shell/package.json +1 -1
  146. package/packages/pm-kanban/package.json +1 -1
  147. package/packages/pm-lifecycle-hooks/package.json +1 -1
  148. package/packages/pm-linked-test-adapters/package.json +1 -1
  149. package/packages/pm-search-advanced/package.json +1 -1
  150. package/packages/pm-templates/extensions/templates/index.ts +9 -3
  151. package/packages/pm-templates/package.json +1 -1
  152. package/packages/pm-todos/package.json +1 -1
  153. package/packages/pm-vcs/package.json +1 -1
  154. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  155. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  156. package/sdk/public-surface.json +840 -28
  157. package/dist/cli-bundle/chunks/chunk-2QYH4QMI.js +0 -30
  158. package/dist/cli-bundle/chunks/chunk-JUDU4RO4.js +0 -194
  159. package/dist/cli-bundle/chunks/chunk-JZSNADRR.js +0 -5
  160. package/dist/cli-bundle/chunks/chunk-MENWVGJW.js +0 -2
  161. package/dist/cli-bundle/chunks/chunk-S4EITGLA.js +0 -3
  162. package/dist/cli-bundle/chunks/chunk-TIGKWVLA.js +0 -13
  163. package/dist/cli-bundle/chunks/chunk-TSLDTJLQ.js +0 -2
  164. package/dist/cli-bundle/chunks/register-mutation-DKI7QC7O.js +0 -20
  165. package/dist/cli-bundle/chunks/register-operations-P5OGMT6I.js +0 -2
  166. package/dist/cli-bundle/focused-chunks/chunk-36FTZ2NT.js +0 -2
  167. package/dist/cli-bundle/focused-chunks/chunk-3CQECMKR.js +0 -16
  168. package/dist/cli-bundle/focused-chunks/chunk-CHIBMEZR.js +0 -8
  169. package/dist/cli-bundle/focused-chunks/chunk-FF4MNAYB.js +0 -153
  170. package/dist/cli-bundle/focused-chunks/chunk-GHTN2ILR.js +0 -2
  171. package/dist/cli-bundle/focused-chunks/chunk-I4YM2I7S.js +0 -2
  172. package/dist/cli-bundle/focused-chunks/chunk-IMDTEN7K.js +0 -2
  173. package/dist/cli-bundle/focused-chunks/chunk-KSNJG4KI.js +0 -16
  174. package/dist/cli-bundle/focused-chunks/chunk-MXYSIQ56.js +0 -18
  175. package/dist/cli-bundle/focused-chunks/chunk-RKWSCYYN.js +0 -2
@@ -15,6 +15,8 @@ export type { PmReadOutputSessionReceipt, PmReadOutputSessionState, } from "./re
15
15
  export type { PmContextIntentContract } from "./context-intent-contracts.js";
16
16
  export type { PmErrorCodeContract } from "./error-code-catalog.js";
17
17
  export { clearWorkspaceContractsCache } from "./workspace-contracts-cache.js";
18
+ import { type AssuranceActionInput, type AssuranceActionResult } from "./governance/assurance-action.js";
19
+ export type * from "./governance/assurance-action-contracts.js";
18
20
  import { type AggregateOptions, type AggregateResult } from "./query/aggregate.js";
19
21
  import { type UpgradeCommandOptions, type UpgradeResult } from "./governance/upgrade.js";
20
22
  import { type CreateResult } from "./lifecycle/create.js";
@@ -235,6 +237,8 @@ export declare class PmClient {
235
237
  health<Options extends ReadOptions<RunHealthOptions> = RunHealthOptions>(options?: Options): ReadPromise<HealthResult, Options>;
236
238
  /** Run tracker cache/runtime garbage collection. */
237
239
  gc(options?: GcCommandOptions): Promise<GcResult>;
240
+ /** Declare, inspect, or evaluate a project assurance contract. */
241
+ assurance(input: AssuranceActionInput): Promise<AssuranceActionResult>;
238
242
  /** Redact sensitive values while preserving an audited, verified history chain. */
239
243
  historyRedact(id: string, options: HistoryRedactCommandOptions): Promise<HistoryRedactResult>;
240
244
  /** Repair and re-anchor one drifted history stream. */
@@ -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]="70ce3cab-35f0-508b-9348-2f8479495946")}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]="a294f940-5bb9-55a4-bf2c-64842a3a177b")}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
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -28,11 +28,13 @@ import { PM_TOOL_ACTIONS } from "./cli-contracts/enum-contracts.js";
28
28
  import { clearWorkspaceContractsCache, memoizeWorkspaceExtensionRegistrations, } from "./workspace-contracts-cache.js";
29
29
  import { SDK_ACTION_ALIASES } from "./runtime-action-aliases.js";
30
30
  import { createExtensionCommandSdk } from "./extension-command-context.js";
31
+ import { createUnknownSubcommandError } from "./agent/subcommand-recovery.js";
31
32
  import { applyContextIntentProjection, attachReadOutputContracts, } from "./context-intent-contracts.js";
32
33
  import { runWithDiscoveredContextIntentContracts, } from "./context-intent-runtime.js";
33
34
  import { validateReadOutputOptions, } from "./read-output-contracts.js";
34
35
  export { clearWorkspaceContractsCache } from "./workspace-contracts-cache.js";
35
36
  import { runActivity } from "./query/activity.js";
37
+ import { runAssuranceDispatch } from "./governance/assurance-action.js";
36
38
  import { runAggregate, } from "./query/aggregate.js";
37
39
  import { runAppend } from "./lifecycle/append.js";
38
40
  import { runClaim, runClaimNext, runRelease } from "./lifecycle/claim.js";
@@ -63,7 +65,7 @@ import { runConfig } from "./config.js";
63
65
  import { runInit } from "./init.js";
64
66
  import { runRuntimeEvalAction, runRuntimeEventsAction, runRuntimeMergeAction, runRuntimeSchedulingAction, runRuntimeWorkspaceAction, } from "./runtime-extended-actions.js";
65
67
  import { acknowledgeUnknownAuthorHistoryEventsFromTransport, } from "./author-attribution.js";
66
- import { runProfileApply, runProfileLint, runProfileList, runProfileShow, } from "./profile.js";
68
+ import { PROFILE_SUBCOMMANDS, runProfileApply, runProfileLint, runProfileList, runProfileShow, } from "./profile.js";
67
69
  import { runHistoryRedact, } from "./history-redact.js";
68
70
  import { runMcpHistoryCompactAction, runMcpHistoryRepairAction, } from "./history-mcp.js";
69
71
  import { actionGlobalOptions as globalOptions, closeManyOptionsFromFlat, extensionOptionsFromArgs, graphOptionsFromFlat, mutationListOptions, 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";
@@ -71,6 +73,7 @@ import { runDeps } from "./dependencies.js";
71
73
  import { runDocs } from "./docs.js";
72
74
  import { runGraph, } from "./graph/run.js";
73
75
  import { runFiles, runFilesDiscover, runFilesLookup } from "./files.js";
76
+ import { runtimeFilesLookupOptions } from "./traceability/runtime-files-lookup.js";
74
77
  import { runContracts, } from "./cli-contracts/runtime-contracts.js";
75
78
  import { runList } from "./query/list.js";
76
79
  import { runSearch, } from "./query/search.js";
@@ -81,7 +84,7 @@ import { runTelemetry } from "./telemetry.js";
81
84
  import { runTest } from "./test/execution.js";
82
85
  import { runTestAll } from "./test/batch.js";
83
86
  import { resolveStartTaskInProgressStatus } from "./start-task-status.js";
84
- import { runSchemaAddField, runSchemaAddStatus, runSchemaAddType, runSchemaApplyPreset, runSchemaInferTypes, runSchemaList, runSchemaListFields, runSchemaEvolutionMigration, runSchemaRemoveField, runSchemaRemoveStatus, runSchemaRemoveType, runSchemaShow, runSchemaShowField, runSchemaShowStatus, } from "./schema.js";
87
+ import { SCHEMA_SUBCOMMANDS, runSchemaAddField, runSchemaAddStatus, runSchemaAddType, runSchemaApplyPreset, runSchemaInferTypes, runSchemaList, runSchemaListFields, runSchemaEvolutionMigration, runSchemaRemoveField, runSchemaRemoveStatus, runSchemaRemoveType, runSchemaShow, runSchemaShowField, runSchemaShowStatus, } from "./schema.js";
85
88
  export { getActiveExtensionRegistrations, runActiveOnReadHooks, runActiveOnWriteHooks, } from "../core/extensions/index.js";
86
89
  export { pathExists, readFileIfExists, removeFileIfExists, writeFileAtomic, } from "../core/fs/fs-utils.js";
87
90
  export { appendHistoryEntry, createHistoryEntry, } from "../core/history/history.js";
@@ -408,6 +411,10 @@ export class PmClient {
408
411
  gc(options = {}) {
409
412
  return this.runTyped("gc", { options });
410
413
  }
414
+ /** Declare, inspect, or evaluate a project assurance contract. */
415
+ assurance(input) {
416
+ return this.runTyped("assurance", { options: { ...input, subcommand: input.action } });
417
+ }
411
418
  /** Redact sensitive values while preserving an audited, verified history chain. */
412
419
  historyRedact(id, options) {
413
420
  return this.runTyped("history-redact", { id, options });
@@ -1401,25 +1408,20 @@ function runMcpCommentsAction(ctx) {
1401
1408
  commentOptions.delete === undefined;
1402
1409
  if (isListing) {
1403
1410
  commentOptions.includeMeta = true;
1404
- if (commentOptions.limit === undefined && commentOptions.fullHistory !== true) {
1411
+ if (commentOptions.limit === undefined &&
1412
+ commentOptions.fullHistory !== true) {
1405
1413
  commentOptions.limit = "20";
1406
1414
  }
1407
1415
  }
1408
1416
  return runComments(requireMcpItemId(ctx), commentOptions, ctx.global);
1409
1417
  }
1418
+ function runMcpFilesLookupAction(ctx, paths) {
1419
+ return runFilesLookup(runtimeFilesLookupOptions(ctx.options, paths, parseMcpInteger), ctx.global);
1420
+ }
1410
1421
  function runMcpFilesAction(ctx) {
1411
1422
  const lookupPaths = readStringArray(ctx.options.lookupPath);
1412
1423
  if (lookupPaths && lookupPaths.length > 0) {
1413
- return runFilesLookup({
1414
- paths: lookupPaths,
1415
- scope: ctx.options.scope === "project" || ctx.options.scope === "global"
1416
- ? ctx.options.scope
1417
- : undefined,
1418
- limit: parseMcpInteger(ctx.options.limit, "files lookup limit"),
1419
- offset: parseMcpInteger(ctx.options.offset, "files lookup offset"),
1420
- noTruncate: ctx.options.noTruncate === true,
1421
- strictRead: ctx.options.strictRead === true,
1422
- }, ctx.global);
1424
+ return runMcpFilesLookupAction(ctx, lookupPaths);
1423
1425
  }
1424
1426
  const fileId = requireMcpItemId(ctx);
1425
1427
  return ctx.options.discover === true
@@ -1644,7 +1646,12 @@ function runMcpSchemaAction(ctx) {
1644
1646
  }
1645
1647
  return runMcpSchemaAddTypeAction(schema);
1646
1648
  }
1647
- throw new PmCliError(`Unknown pm schema subcommand "${schema.subcommand}". Allowed: add-type, remove-type, add-status, remove-status, add-field, remove-field, rename-type, rename-field, remap-status, list-fields, show-field, apply-preset, list, show, show-status`, 64);
1649
+ throw createUnknownSubcommandError({
1650
+ command_path: "schema",
1651
+ token: schema.subcommand,
1652
+ allowed: SCHEMA_SUBCOMMANDS,
1653
+ exit_code: 64,
1654
+ });
1648
1655
  }
1649
1656
  function runMcpProfileAction(ctx) {
1650
1657
  const subcommand = readString(ctx.args, "subcommand") ??
@@ -1663,7 +1670,12 @@ function runMcpProfileAction(ctx) {
1663
1670
  };
1664
1671
  const handler = getOwnHandler(handlers, normalizedSubcommand);
1665
1672
  if (!handler) {
1666
- throw new PmCliError(`Unknown pm profile subcommand "${subcommand}". Allowed: list, show, apply, lint`, 64);
1673
+ throw createUnknownSubcommandError({
1674
+ command_path: "profile",
1675
+ token: subcommand,
1676
+ allowed: PROFILE_SUBCOMMANDS,
1677
+ exit_code: 64,
1678
+ });
1667
1679
  }
1668
1680
  return handler();
1669
1681
  }
@@ -1813,6 +1825,7 @@ const SDK_ACTION_HANDLERS = {
1813
1825
  runUpdate: (id, options, global) => runUpdate(id, options, global),
1814
1826
  }),
1815
1827
  health: runMcpHealthAction,
1828
+ assurance: (ctx) => runAssuranceDispatch(ctx.args, ctx.options, ctx.global),
1816
1829
  contracts: (ctx) => runContracts(ctx.options, ctx.global),
1817
1830
  config: runMcpConfigAction,
1818
1831
  activity: runMcpActivityAction,
@@ -1825,16 +1838,7 @@ const SDK_ACTION_HANDLERS = {
1825
1838
  deps: (ctx) => runDeps(requireMcpItemId(ctx), ctx.options, ctx.global),
1826
1839
  graph: runMcpGraphAction,
1827
1840
  "files-discover": (ctx) => runFilesDiscover(requireMcpItemId(ctx), ctx.options, ctx.global),
1828
- "files-lookup": (ctx) => runFilesLookup({
1829
- paths: readStringArray(ctx.options.paths),
1830
- scope: ctx.options.scope === "project" || ctx.options.scope === "global"
1831
- ? ctx.options.scope
1832
- : undefined,
1833
- limit: parseMcpInteger(ctx.options.limit, "files lookup limit"),
1834
- offset: parseMcpInteger(ctx.options.offset, "files lookup offset"),
1835
- noTruncate: ctx.options.noTruncate === true,
1836
- strictRead: ctx.options.strictRead === true,
1837
- }, ctx.global),
1841
+ "files-lookup": (ctx) => runMcpFilesLookupAction(ctx, readStringArray(ctx.options.paths)),
1838
1842
  history: (ctx) => runHistory(requireMcpItemId(ctx), ctx.options, ctx.global),
1839
1843
  "history-redact": (ctx) => runHistoryRedact(requireMcpItemId(ctx), ctx.options, ctx.global),
1840
1844
  "history-repair": runMcpHistoryRepairAction,
@@ -1930,4 +1934,4 @@ async function loadWorkspaceExtensionRegistrations(pmRoot, settings, cwd) {
1930
1934
  }
1931
1935
  }
1932
1936
  //# sourceMappingURL=runtime.js.map
1933
- //# debugId=70ce3cab-35f0-508b-9348-2f8479495946
1937
+ //# debugId=a294f940-5bb9-55a4-bf2c-64842a3a177b
@@ -4,7 +4,7 @@
4
4
  * Implements the pm telemetry command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="150c6ff7-cfb5-542f-bd3d-3c8088d1086a")}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]="ad3110ca-e85b-5a7e-b0a1-591796c298eb")}catch(e){}}();
8
8
  import fs from "node:fs/promises";
9
9
  import path from "node:path";
10
10
  import { pathExists, readFileIfExists } from "../core/fs/fs-utils.js";
@@ -14,6 +14,7 @@ import { nowIso } from "../core/shared/time.js";
14
14
  import { resolveGlobalPmRoot } from "../core/store/paths.js";
15
15
  import { readSettings, writeSettings } from "../core/store/settings.js";
16
16
  import { flushTelemetryQueueNow } from "../core/telemetry/runtime.js";
17
+ import { createUnknownSubcommandError } from "./agent/subcommand-recovery.js";
17
18
  const TELEMETRY_QUEUE_RELATIVE_PATH = path.join("runtime", "telemetry", "events.jsonl");
18
19
  const TELEMETRY_STATE_RELATIVE_PATH = path.join("runtime", "telemetry", "state.json");
19
20
  const TELEMETRY_RUNTIME_RELATIVE_PATH = path.join("runtime", "telemetry");
@@ -161,8 +162,10 @@ const normalizeTelemetrySubcommand = (value) => {
161
162
  }
162
163
  // `value` is always a defined string here: an undefined subcommand normalizes
163
164
  // to "status" above (a valid value) and never reaches this throw.
164
- throw new PmCliError(`Unknown pm telemetry subcommand "${value}". Allowed: ${TELEMETRY_SUBCOMMANDS.join(", ")}`, EXIT_CODE.USAGE, {
165
- code: "unknown_subcommand",
165
+ throw createUnknownSubcommandError({
166
+ command_path: "telemetry",
167
+ token: value?.trim() || "<empty>",
168
+ allowed: TELEMETRY_SUBCOMMANDS,
166
169
  examples: [
167
170
  "pm telemetry status",
168
171
  "pm telemetry flush",
@@ -400,4 +403,4 @@ export async function runTelemetry(options, _global) {
400
403
  });
401
404
  }
402
405
  //# sourceMappingURL=telemetry.js.map
403
- //# debugId=150c6ff7-cfb5-542f-bd3d-3c8088d1086a
406
+ //# debugId=ad3110ca-e85b-5a7e-b0a1-591796c298eb
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @module sdk/traceability/runtime-files-lookup
3
+ *
4
+ * Projects transport-neutral action values into reverse source lookup options.
5
+ */
6
+ import type { FilesLookupOptions } from "../files.js";
7
+ /** Convert bounded MCP/action values into the public files lookup contract. */
8
+ export declare function runtimeFilesLookupOptions(options: Readonly<Record<string, unknown>>, paths: string[], parseInteger: (value: unknown, label: string) => number | undefined): FilesLookupOptions;
@@ -0,0 +1,33 @@
1
+
2
+ !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]="c2ef0de1-bc44-5550-862c-f3929334fbef")}catch(e){}}();
3
+ import { parseSourceLineRange } from "./source-traceability.js";
4
+ /** Convert bounded MCP/action values into the public files lookup contract. */
5
+ export function runtimeFilesLookupOptions(options, paths, parseInteger) {
6
+ let lineRange;
7
+ if (typeof options.lines === "string") {
8
+ lineRange = parseSourceLineRange(options.lines);
9
+ }
10
+ else if (options.lineRange !== undefined) {
11
+ if (options.lineRange === null ||
12
+ typeof options.lineRange !== "object" ||
13
+ Array.isArray(options.lineRange)) {
14
+ throw new RangeError("Source line range must be an object with numeric start and end values.");
15
+ }
16
+ lineRange = parseSourceLineRange(`${String(Reflect.get(options.lineRange, "start"))}:${String(Reflect.get(options.lineRange, "end"))}`);
17
+ }
18
+ return {
19
+ paths,
20
+ scope: options.scope === "project" || options.scope === "global"
21
+ ? options.scope
22
+ : undefined,
23
+ limit: parseInteger(options.limit, "files lookup limit"),
24
+ offset: parseInteger(options.offset, "files lookup offset"),
25
+ noTruncate: options.noTruncate === true,
26
+ strictRead: options.strictRead === true,
27
+ explain: options.explain === true,
28
+ lineRange,
29
+ decisionDepth: parseInteger(options.decisionDepth, "files lookup decision depth"),
30
+ };
31
+ }
32
+ //# sourceMappingURL=runtime-files-lookup.js.map
33
+ //# debugId=c2ef0de1-bc44-5550-862c-f3929334fbef
@@ -0,0 +1,102 @@
1
+ import type { ItemMetadata, LinkedFile } from "../../types/index.js";
2
+ /** Inclusive one-based source range accepted by traceability lookup. */
3
+ export interface SourceLineRange {
4
+ /** First included source line. */
5
+ start: number;
6
+ /** Last included source line. */
7
+ end: number;
8
+ }
9
+ /** One evidence class supporting a source-to-item association. */
10
+ export interface SourceTraceabilityEvidence {
11
+ /** Evidence producer. */
12
+ kind: "linked_file" | "git_commit";
13
+ /** Linked path or abbreviated commit identifier. */
14
+ reference: string;
15
+ /** Number of selected lines attributed to this evidence. */
16
+ contribution_lines?: number;
17
+ }
18
+ /** Rationale fields projected without arbitrary body or comment content. */
19
+ export interface SourceTraceabilityRationale {
20
+ /** User or project value statement. */
21
+ value: string | null;
22
+ /** Recorded timing rationale. */
23
+ why_now: string | null;
24
+ /** Recorded intended or achieved outcome. */
25
+ outcome: string | null;
26
+ /** Recorded implementation objective. */
27
+ objective: string | null;
28
+ }
29
+ /** Shortest typed path from source-owning work to a governing decision. */
30
+ export interface SourceDecisionPath {
31
+ /** Whether a unique decision path was found under the bound. */
32
+ status: "found" | "ambiguous" | "not_found";
33
+ /** Ordered item identifiers, including source work and decision. */
34
+ nodes: string[];
35
+ /** Relationship kinds connecting consecutive nodes. */
36
+ kinds: string[];
37
+ /** Equally short governing decision candidates. */
38
+ alternative_decision_ids: string[];
39
+ }
40
+ /** Explainable fields added to one reverse linked-file match. */
41
+ export interface SourceTraceabilityExplanation {
42
+ /** Higher values sort first within the original scheduling priority. */
43
+ score: number;
44
+ /** Selected source lines attributable to commits naming this item. */
45
+ contribution_lines: number;
46
+ /** Structured evidence supporting the association. */
47
+ evidence: SourceTraceabilityEvidence[];
48
+ /** Project rationale carried by the item. */
49
+ rationale: SourceTraceabilityRationale;
50
+ /** Governing decision path under the declared graph bound. */
51
+ decision_path: SourceDecisionPath;
52
+ /** Honest ambiguity codes; an empty list means no ambiguity was observed. */
53
+ ambiguities: string[];
54
+ }
55
+ /** Aggregate line-attribution receipt returned beside explained matches. */
56
+ export interface SourceTraceabilityReceipt {
57
+ /** Inclusive selected range, or null for path-only explanation. */
58
+ line_range: SourceLineRange | null;
59
+ /** Number of distinct blamed commits. */
60
+ blamed_commit_count: number;
61
+ /** Number of blamed commits whose message named at least one pm item. */
62
+ mapped_commit_count: number;
63
+ /** Number of blamed commits without an item reference. */
64
+ unmapped_commit_count: number;
65
+ /** Maximum relationship depth searched for a governing decision. */
66
+ decision_depth: number;
67
+ }
68
+ interface TraceabilityCandidate {
69
+ item: ItemMetadata;
70
+ files: LinkedFile[];
71
+ }
72
+ interface GitAttribution {
73
+ commitLines: Map<string, number>;
74
+ commitItems: Map<string, string[]>;
75
+ available: boolean;
76
+ }
77
+ /** Parse an inclusive `start:end` source-line selector. */
78
+ export declare function parseSourceLineRange(value: string): SourceLineRange;
79
+ declare function parseBlameCommits(output: string): Map<string, number>;
80
+ declare function parseCommitItemReferences(output: string): Map<string, string[]>;
81
+ declare function shortestDecisionPath(itemId: string, corpus: readonly ItemMetadata[], maxDepth: number): SourceDecisionPath;
82
+ declare function mappedBlamedCommits(attribution: GitAttribution): string[];
83
+ /** Enrich reverse linked-file candidates with bounded source rationale. */
84
+ export declare function explainSourceTraceability(params: {
85
+ workspaceRoot: string;
86
+ paths: readonly string[];
87
+ candidates: readonly TraceabilityCandidate[];
88
+ corpus: readonly ItemMetadata[];
89
+ lineRange?: SourceLineRange;
90
+ decisionDepth?: number;
91
+ }): Promise<{
92
+ explanations: Map<string, SourceTraceabilityExplanation>;
93
+ receipt: SourceTraceabilityReceipt;
94
+ }>;
95
+ /** Internal parser and traversal seams for deterministic boundary tests. */
96
+ export declare const _testOnlySourceTraceability: {
97
+ mappedBlamedCommits: typeof mappedBlamedCommits;
98
+ parseBlameCommits: typeof parseBlameCommits;
99
+ parseCommitItemReferences: typeof parseCommitItemReferences;
100
+ shortestDecisionPath: typeof shortestDecisionPath;
101
+ };
102
+ export {};
@@ -0,0 +1,293 @@
1
+ /**
2
+ * @module sdk/source-traceability
3
+ *
4
+ * Composes linked-file evidence, bounded Git line attribution, item rationale,
5
+ * and typed relationship paths into an explainable source-to-work projection.
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]="b8b3f729-be32-5a77-b08f-f616ee068e0f")}catch(e){}}();
9
+ import { execFile } from "node:child_process";
10
+ import path from "node:path";
11
+ import { assembleWorkspaceRelationshipGraph } from "../graph/assembly.js";
12
+ function runGit(workspaceRoot, args) {
13
+ return new Promise((resolve, reject) => {
14
+ execFile("git", [...args], {
15
+ cwd: workspaceRoot,
16
+ encoding: "utf8",
17
+ maxBuffer: 4 * 1024 * 1024,
18
+ }, (error, stdout) => {
19
+ if (error)
20
+ reject(error);
21
+ else
22
+ resolve(stdout);
23
+ });
24
+ });
25
+ }
26
+ function validateLineRange(range) {
27
+ if (range &&
28
+ (!Number.isSafeInteger(range.start) ||
29
+ !Number.isSafeInteger(range.end) ||
30
+ range.start < 1 ||
31
+ range.end < range.start)) {
32
+ throw new RangeError("Source line range must be inclusive positive integers with end >= start.");
33
+ }
34
+ }
35
+ /** Parse an inclusive `start:end` source-line selector. */
36
+ export function parseSourceLineRange(value) {
37
+ const match = /^(\d+):(\d+)$/u.exec(value.trim());
38
+ const range = match
39
+ ? { start: Number(match[1]), end: Number(match[2]) }
40
+ : undefined;
41
+ validateLineRange(range);
42
+ if (!range) {
43
+ throw new RangeError("Source line range must use start:end.");
44
+ }
45
+ return range;
46
+ }
47
+ function parseBlameCommits(output) {
48
+ const lines = new Map();
49
+ for (const row of output.split("\n")) {
50
+ const commit = /^([0-9a-f^]{40,64}) \d+ \d+(?: \d+)?$/u.exec(row)?.[1];
51
+ if (commit)
52
+ lines.set(commit, (lines.get(commit) ?? 0) + 1);
53
+ }
54
+ return lines;
55
+ }
56
+ function parseCommitItemReferences(output) {
57
+ const fields = output.split("\0");
58
+ const references = new Map();
59
+ for (let index = 0; index + 1 < fields.length; index += 2) {
60
+ const commit = fields[index]?.trim();
61
+ if (!commit)
62
+ continue;
63
+ const ids = [
64
+ ...new Set(fields[index + 1]?.match(/\bpm-[a-z0-9][a-z0-9-]{2,63}\b/gu) ?? []),
65
+ ].sort((left, right) => left.localeCompare(right));
66
+ references.set(commit, ids);
67
+ }
68
+ return references;
69
+ }
70
+ async function readGitAttribution(params) {
71
+ const relativePath = path.relative(params.workspaceRoot, path.resolve(params.workspaceRoot, params.sourcePath));
72
+ const blame = await runGit(params.workspaceRoot, [
73
+ "blame",
74
+ "--line-porcelain",
75
+ "-L",
76
+ `${params.lineRange.start},${params.lineRange.end}`,
77
+ "--",
78
+ relativePath,
79
+ ]);
80
+ const log = await runGit(params.workspaceRoot, [
81
+ "log",
82
+ "-n",
83
+ "256",
84
+ "--format=%H%x00%B%x00",
85
+ "--",
86
+ relativePath,
87
+ ]);
88
+ return {
89
+ commitLines: parseBlameCommits(blame),
90
+ commitItems: parseCommitItemReferences(log),
91
+ available: true,
92
+ };
93
+ }
94
+ function expandDecisionPath(params) {
95
+ const tail = params.current.nodes.at(-1);
96
+ const nextDepth = params.current.kinds.length + 1;
97
+ let foundDepth;
98
+ for (const edge of params.graph.incidentEdges(tail)) {
99
+ const outgoing = edge.source === tail;
100
+ const next = outgoing ? edge.target : edge.source;
101
+ if ((params.visitedDepth.get(next) ?? Number.POSITIVE_INFINITY) < nextDepth)
102
+ continue;
103
+ params.visitedDepth.set(next, nextDepth);
104
+ const definition = params.graph.registry().require(edge.kind);
105
+ const nextPath = {
106
+ nodes: [...params.current.nodes, next],
107
+ kinds: [
108
+ ...params.current.kinds,
109
+ outgoing ? edge.kind : (definition.inverse ?? edge.kind),
110
+ ],
111
+ };
112
+ if (params.details.get(next)?.type?.toLowerCase() === "decision") {
113
+ foundDepth = nextDepth;
114
+ params.found.push(nextPath);
115
+ }
116
+ else {
117
+ params.queue.push(nextPath);
118
+ }
119
+ }
120
+ return foundDepth;
121
+ }
122
+ function collectDecisionPaths(params) {
123
+ const queue = [
124
+ { nodes: [params.itemId], kinds: [] },
125
+ ];
126
+ const visitedDepth = new Map([[params.itemId, 0]]);
127
+ const found = [];
128
+ let foundDepth;
129
+ while (queue.length > 0) {
130
+ const current = queue.shift();
131
+ const depth = current.kinds.length;
132
+ if (foundDepth !== undefined && depth >= foundDepth)
133
+ continue;
134
+ if (depth >= params.maxDepth)
135
+ continue;
136
+ foundDepth =
137
+ expandDecisionPath({
138
+ current,
139
+ graph: params.graph,
140
+ details: params.details,
141
+ visitedDepth,
142
+ queue,
143
+ found,
144
+ }) ?? foundDepth;
145
+ }
146
+ found.sort((left, right) => left.nodes.join("\0").localeCompare(right.nodes.join("\0")));
147
+ return found;
148
+ }
149
+ function shortestDecisionPath(itemId, corpus, maxDepth) {
150
+ const assembly = assembleWorkspaceRelationshipGraph(corpus);
151
+ if (!assembly.graph.hasNode(itemId)) {
152
+ return {
153
+ status: "not_found",
154
+ nodes: [],
155
+ kinds: [],
156
+ alternative_decision_ids: [],
157
+ };
158
+ }
159
+ const found = collectDecisionPaths({
160
+ itemId,
161
+ maxDepth,
162
+ graph: assembly.graph,
163
+ details: new Map(assembly.details.map((detail) => [detail.id, detail])),
164
+ });
165
+ const selected = found[0];
166
+ if (!selected) {
167
+ return {
168
+ status: "not_found",
169
+ nodes: [],
170
+ kinds: [],
171
+ alternative_decision_ids: [],
172
+ };
173
+ }
174
+ const decisionIds = [...new Set(found.map((entry) => entry.nodes.at(-1)))];
175
+ return {
176
+ status: decisionIds.length === 1 ? "found" : "ambiguous",
177
+ nodes: selected.nodes,
178
+ kinds: selected.kinds,
179
+ alternative_decision_ids: decisionIds.slice(1),
180
+ };
181
+ }
182
+ async function resolveGitAttribution(params) {
183
+ if (!params.lineRange) {
184
+ return {
185
+ commitLines: new Map(),
186
+ commitItems: new Map(),
187
+ available: true,
188
+ };
189
+ }
190
+ try {
191
+ return await readGitAttribution({
192
+ workspaceRoot: params.workspaceRoot,
193
+ sourcePath: params.paths[0],
194
+ lineRange: params.lineRange,
195
+ });
196
+ }
197
+ catch {
198
+ return {
199
+ commitLines: new Map(),
200
+ commitItems: new Map(),
201
+ available: false,
202
+ };
203
+ }
204
+ }
205
+ function sourceAmbiguities(params) {
206
+ const ambiguities = [];
207
+ if (params.hasLineRange && !params.attributionAvailable) {
208
+ ambiguities.push("git_attribution_unavailable");
209
+ }
210
+ if (params.hasLineRange && params.contributionLines === 0) {
211
+ ambiguities.push("line_attribution_unmapped");
212
+ }
213
+ if (params.decisionStatus === "ambiguous") {
214
+ ambiguities.push("multiple_governing_decisions");
215
+ }
216
+ if (params.decisionStatus === "not_found") {
217
+ ambiguities.push("governing_decision_not_found");
218
+ }
219
+ return ambiguities;
220
+ }
221
+ function mappedBlamedCommits(attribution) {
222
+ return [...attribution.commitLines.keys()].filter((commit) => (attribution.commitItems.get(commit)?.length ?? 0) > 0);
223
+ }
224
+ /** Enrich reverse linked-file candidates with bounded source rationale. */
225
+ export async function explainSourceTraceability(params) {
226
+ validateLineRange(params.lineRange);
227
+ const decisionDepth = params.decisionDepth ?? 8;
228
+ if (!Number.isSafeInteger(decisionDepth) ||
229
+ decisionDepth < 1 ||
230
+ decisionDepth > 32) {
231
+ throw new RangeError("Decision path depth must be an integer from 1 to 32.");
232
+ }
233
+ const attribution = await resolveGitAttribution(params);
234
+ const mappedCommits = mappedBlamedCommits(attribution);
235
+ const explanations = new Map();
236
+ for (const candidate of params.candidates) {
237
+ const attributedCommits = [...attribution.commitLines.entries()].filter(([commit]) => attribution.commitItems.get(commit)?.includes(candidate.item.id));
238
+ const contributionLines = attributedCommits.reduce((total, [, lines]) => total + lines, 0);
239
+ const decisionPath = shortestDecisionPath(candidate.item.id, params.corpus, decisionDepth);
240
+ const ambiguities = sourceAmbiguities({
241
+ hasLineRange: params.lineRange !== undefined,
242
+ attributionAvailable: attribution.available,
243
+ contributionLines,
244
+ decisionStatus: decisionPath.status,
245
+ });
246
+ explanations.set(candidate.item.id, {
247
+ score: contributionLines * 100 +
248
+ candidate.files.length * 10 +
249
+ Math.max(0, 9 -
250
+ Math.floor((Date.now() - Date.parse(candidate.item.updated_at)) /
251
+ (30 * 24 * 60 * 60 * 1000))),
252
+ contribution_lines: contributionLines,
253
+ evidence: [
254
+ ...candidate.files.map((file) => ({
255
+ kind: "linked_file",
256
+ reference: file.path,
257
+ })),
258
+ ...attributedCommits.map(([commit, lines]) => ({
259
+ kind: "git_commit",
260
+ reference: commit.slice(0, 12),
261
+ contribution_lines: lines,
262
+ })),
263
+ ],
264
+ rationale: {
265
+ value: candidate.item.value?.trim() || null,
266
+ why_now: candidate.item.why_now?.trim() || null,
267
+ outcome: candidate.item.outcome?.trim() || null,
268
+ objective: candidate.item.objective?.trim() || null,
269
+ },
270
+ decision_path: decisionPath,
271
+ ambiguities,
272
+ });
273
+ }
274
+ return {
275
+ explanations,
276
+ receipt: {
277
+ line_range: params.lineRange ?? null,
278
+ blamed_commit_count: attribution.commitLines.size,
279
+ mapped_commit_count: mappedCommits.length,
280
+ unmapped_commit_count: attribution.commitLines.size - mappedCommits.length,
281
+ decision_depth: decisionDepth,
282
+ },
283
+ };
284
+ }
285
+ /** Internal parser and traversal seams for deterministic boundary tests. */
286
+ export const _testOnlySourceTraceability = {
287
+ mappedBlamedCommits,
288
+ parseBlameCommits,
289
+ parseCommitItemReferences,
290
+ shortestDecisionPath,
291
+ };
292
+ //# sourceMappingURL=source-traceability.js.map
293
+ //# debugId=b8b3f729-be32-5a77-b08f-f616ee068e0f
package/dist/types.d.ts CHANGED
@@ -743,7 +743,7 @@ export interface HistoryEntry {
743
743
  /** Observed agent model identifier, retained in local history. */
744
744
  agent_model?: string;
745
745
  /** Bounded signal class that supplied `agent_model`. */
746
- agent_model_source?: "override" | "environment" | "mcp_client" | "argv" | "host" | "session" | "probe";
746
+ agent_model_source?: "override" | "environment" | "mcp_client" | "argv" | "host" | "session" | "probe" | "inferred";
747
747
  /** Privacy-safe fingerprint distinguishing concurrent harness invocations. */
748
748
  agent_instance?: string;
749
749
  /** Extensible local-only descriptive agent provenance; null means declared but unavailable. */
@@ -751,7 +751,13 @@ export interface HistoryEntry {
751
751
  /** Bounded descriptive value observed for this dimension. */
752
752
  value: string;
753
753
  /** Bounded signal class that supplied the value. */
754
- source: "override" | "environment" | "mcp_client" | "argv" | "host" | "session" | "probe";
754
+ source: "override" | "environment" | "mcp_client" | "argv" | "host" | "session" | "probe" | "inferred";
755
+ /** Confidence attached to a semantic inference. */
756
+ confidence?: "high" | "medium" | "low";
757
+ /** Versioned semantic inference rule. */
758
+ rule_version?: "v2";
759
+ /** Bounded item and lineage references supporting the inference. */
760
+ evidence?: readonly string[];
755
761
  } | null>>;
756
762
  /** Stable declared episode identity; absent on legacy or undeclared events. */
757
763
  agent_episode?: {