@unbrained/pm-cli 2026.9.4 → 2026.9.5

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 (190) hide show
  1. package/.agents/skills/HARNESS_COMPATIBILITY.md +1 -1
  2. package/.agents/skills/README.md +2 -2
  3. package/.agents/skills/pm-developer/SKILL.md +4 -1
  4. package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +10 -0
  5. package/.agents/skills/pm-developer/references/GRAPH_AND_RELATIONSHIPS.md +3 -1
  6. package/.agents/skills/pm-extensions/SKILL.md +2 -2
  7. package/.agents/skills/pm-extensions/references/LIFECYCLE.md +3 -3
  8. package/.agents/skills/pm-extensions/references/TROUBLESHOOTING.md +3 -3
  9. package/.agents/skills/pm-user/SKILL.md +2 -0
  10. package/.agents/skills/pm-user/references/BACKLOG_SHAPING.md +5 -0
  11. package/.agents/skills/pm-user/references/WORKFLOWS.md +20 -5
  12. package/.claude-plugin/marketplace.json +2 -2
  13. package/CHANGELOG.md +26 -1
  14. package/dist/cli/commander-usage.d.ts +2 -0
  15. package/dist/cli/commander-usage.js +15 -12
  16. package/dist/cli/help-json-payload.js +12 -7
  17. package/dist/cli/main.js +15 -6
  18. package/dist/cli/register-list-query.js +4 -2
  19. package/dist/cli/register-mutation.js +4 -2
  20. package/dist/cli/register-operations.js +6 -2
  21. package/dist/cli-bundle/bundle-manifest.json +153 -153
  22. package/dist/cli-bundle/chunks/{chunk-RI4XNOYS.js → chunk-3HBDTJRK.js} +2 -2
  23. package/dist/cli-bundle/chunks/chunk-66VPKFP2.js +5 -0
  24. package/dist/cli-bundle/chunks/{chunk-I2AS367G.js → chunk-HUAQITVW.js} +2 -2
  25. package/dist/cli-bundle/chunks/{chunk-HI6BHPCU.js → chunk-IBYREGSP.js} +2 -2
  26. package/dist/cli-bundle/chunks/chunk-LUI4E32I.js +231 -0
  27. package/dist/cli-bundle/chunks/{chunk-YW4QK2G7.js → chunk-QPZHQY2O.js} +2 -2
  28. package/dist/cli-bundle/chunks/{chunk-X6CMGV6L.js → chunk-SF6SM6U5.js} +2 -2
  29. package/dist/cli-bundle/chunks/chunk-SVK5Y64D.js +40 -0
  30. package/dist/cli-bundle/chunks/chunk-V5GBD5KV.js +9 -0
  31. package/dist/cli-bundle/chunks/{chunk-V72UV7QS.js → chunk-WWAEGW4V.js} +57 -57
  32. package/dist/cli-bundle/chunks/{chunk-A24WAVE6.js → chunk-ZRAQS3UA.js} +2 -2
  33. package/dist/cli-bundle/chunks/{register-list-query-Z5YYSJJG.js → register-list-query-AYKGODWT.js} +3 -3
  34. package/dist/cli-bundle/chunks/{register-mutation-ELSP6I4I.js → register-mutation-YZYG53SQ.js} +4 -4
  35. package/dist/cli-bundle/chunks/register-operations-KFSCC7QV.js +2 -0
  36. package/dist/cli-bundle/chunks/{register-setup-E2AE72QG.js → register-setup-UJCRVGBG.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/chunk-24IG6ONG.js +2 -0
  38. package/dist/cli-bundle/focused-chunks/{chunk-53IHPICX.js → chunk-3ASU6WGI.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/chunk-3ITLIBKS.js +56 -0
  40. package/dist/cli-bundle/focused-chunks/chunk-3NQD5YDG.js +2 -0
  41. package/dist/cli-bundle/focused-chunks/{chunk-7N2TV7WZ.js → chunk-4OSHLNUE.js} +2 -2
  42. package/dist/cli-bundle/focused-chunks/chunk-65N6JHAN.js +2 -0
  43. package/dist/cli-bundle/focused-chunks/{chunk-AJR3OP2E.js → chunk-B2TTQGFG.js} +2 -2
  44. package/dist/cli-bundle/focused-chunks/chunk-GUBM3RGY.js +20 -0
  45. package/dist/cli-bundle/focused-chunks/{chunk-25UJBH4M.js → chunk-H5FOGAVD.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/chunk-JX3RCVCX.js +2 -0
  47. package/dist/cli-bundle/focused-chunks/{chunk-6PWPQKDN.js → chunk-KWWCBWFO.js} +2 -2
  48. package/dist/cli-bundle/focused-chunks/chunk-MV752SUC.js +12 -0
  49. package/dist/cli-bundle/focused-chunks/chunk-PKIPMCFS.js +6 -0
  50. package/dist/cli-bundle/focused-chunks/{chunk-3646BZ4W.js → chunk-QL66QNWG.js} +2 -2
  51. package/dist/cli-bundle/focused-chunks/chunk-RJMR2JIF.js +9 -0
  52. package/dist/cli-bundle/focused-chunks/chunk-WIUPWIZR.js +177 -0
  53. package/dist/cli-bundle/focused-chunks/{chunk-NBMJD6MK.js → chunk-WOCIPMW7.js} +2 -2
  54. package/dist/cli-bundle/focused-chunks/{chunk-MHKUIPJW.js → chunk-YEF5PQQ2.js} +2 -2
  55. package/dist/cli-bundle/main.js +22 -15
  56. package/dist/cli-bundle/sdk-authoring.js +1 -1
  57. package/dist/cli-bundle/sdk-contracts.js +1 -1
  58. package/dist/cli-bundle/sdk-core.js +29 -29
  59. package/dist/cli-bundle/sdk-governance.js +1 -1
  60. package/dist/cli-bundle/sdk-graph.js +1 -1
  61. package/dist/cli-bundle/sdk-merge.js +42 -39
  62. package/dist/cli-bundle/sdk-query.js +1 -1
  63. package/dist/cli-bundle/sdk-runtime.js +1 -1
  64. package/dist/cli-bundle/sdk-testing.js +1 -1
  65. package/dist/cli-bundle/sdk.js +8 -8
  66. package/dist/core/extensions/extension-types.d.ts +2 -0
  67. package/dist/core/extensions/extension-types.js +2 -2
  68. package/dist/core/history/drift-scan.d.ts +5 -0
  69. package/dist/core/history/drift-scan.js +16 -6
  70. package/dist/core/history/event-classification.d.ts +1 -1
  71. package/dist/core/history/event-classification.js +3 -2
  72. package/dist/core/history/history.js +37 -5
  73. package/dist/core/history/identity.d.ts +15 -0
  74. package/dist/core/history/identity.js +31 -0
  75. package/dist/core/history/projection.js +50 -17
  76. package/dist/core/history/read.js +6 -3
  77. package/dist/core/history/replay.d.ts +1 -2
  78. package/dist/core/history/replay.js +4 -4
  79. package/dist/core/history/version-address.d.ts +13 -0
  80. package/dist/core/history/version-address.js +33 -0
  81. package/dist/core/item/actionability.d.ts +21 -1
  82. package/dist/core/item/actionability.js +45 -10
  83. package/dist/core/item/id.js +8 -4
  84. package/dist/core/item/item-type-definition.d.ts +2 -0
  85. package/dist/core/item/item-type-definition.js +9 -2
  86. package/dist/core/item/type-registry.d.ts +5 -1
  87. package/dist/core/item/type-registry.js +9 -4
  88. package/dist/core/shared/errors.d.ts +8 -0
  89. package/dist/core/shared/errors.js +2 -2
  90. package/dist/core/store/item-store.d.ts +14 -0
  91. package/dist/core/store/item-store.js +48 -10
  92. package/dist/core/store/settings-validator.js +3 -2
  93. package/dist/sdk/actionability.d.ts +1 -1
  94. package/dist/sdk/actionability.js +3 -3
  95. package/dist/sdk/cli-contracts/command-aliases.js +11 -2
  96. package/dist/sdk/cli-contracts/completeness.js +4 -3
  97. package/dist/sdk/cli-contracts/flag-contracts.js +29 -5
  98. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +19 -12
  99. package/dist/sdk/cli-contracts/tool-parameter-tables.js +14 -2
  100. package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
  101. package/dist/sdk/cli-contracts/tool-schema.js +19 -6
  102. package/dist/sdk/context-intent-contracts.js +3 -3
  103. package/dist/sdk/context-usage.js +9 -11
  104. package/dist/sdk/define.d.ts +1 -1
  105. package/dist/sdk/define.js +2 -2
  106. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +98 -50
  107. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +50 -2
  108. package/dist/sdk/governance/validate-history-drift.js +16 -5
  109. package/dist/sdk/guide-topics.js +116 -2
  110. package/dist/sdk/history/salvage.d.ts +35 -0
  111. package/dist/sdk/history/salvage.js +248 -0
  112. package/dist/sdk/history-compact.js +32 -37
  113. package/dist/sdk/history-read.d.ts +3 -2
  114. package/dist/sdk/history-read.js +6 -3
  115. package/dist/sdk/history-repair.d.ts +5 -0
  116. package/dist/sdk/history-repair.js +14 -2
  117. package/dist/sdk/lifecycle/claim.d.ts +4 -0
  118. package/dist/sdk/lifecycle/claim.js +9 -3
  119. package/dist/sdk/lifecycle/restore.d.ts +1 -0
  120. package/dist/sdk/lifecycle/restore.js +19 -7
  121. package/dist/sdk/output-projection.d.ts +3 -1
  122. package/dist/sdk/output-projection.js +11 -3
  123. package/dist/sdk/public-surface.json +1 -0
  124. package/dist/sdk/query/context.d.ts +9 -0
  125. package/dist/sdk/query/context.js +33 -21
  126. package/dist/sdk/query/get.d.ts +2 -2
  127. package/dist/sdk/query/get.js +4 -3
  128. package/dist/sdk/query/history.d.ts +11 -0
  129. package/dist/sdk/query/history.js +34 -10
  130. package/dist/sdk/query/next.d.ts +15 -1
  131. package/dist/sdk/query/next.js +43 -20
  132. package/dist/sdk/query.d.ts +1 -0
  133. package/dist/sdk/query.js +3 -2
  134. package/dist/sdk/runtime-primitives.d.ts +1 -1
  135. package/dist/sdk/runtime-primitives.js +3 -3
  136. package/dist/types.d.ts +2 -0
  137. package/dist/types.js +2 -2
  138. package/docs/AGENT_GUIDE.md +36 -0
  139. package/docs/HISTORY_RECOVERY.md +146 -0
  140. package/docs/README.md +1 -0
  141. package/docs/RELEASING.md +25 -11
  142. package/docs/SDK_CONTEXT_TRUTH_CONTRACTS.md +24 -1
  143. package/docs/SDK_EXECUTION_CONTRACTS.md +105 -0
  144. package/docs/TESTING.md +5 -0
  145. package/docs/agent-task-token-baseline.json +17 -17
  146. package/docs/agent-task-transcripts.json +2 -1
  147. package/docs/generated/FLAG_LEXICON_BUDGETS.md +10 -10
  148. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +11 -3
  149. package/marketplace.json +2 -2
  150. package/package.json +4 -5
  151. package/packages/pm-beads/package.json +1 -1
  152. package/packages/pm-calendar/package.json +1 -1
  153. package/packages/pm-command-kit/package.json +1 -1
  154. package/packages/pm-digital-twin/package.json +1 -1
  155. package/packages/pm-governance-audit/package.json +1 -1
  156. package/packages/pm-guide-shell/package.json +1 -1
  157. package/packages/pm-kanban/package.json +1 -1
  158. package/packages/pm-lifecycle-hooks/package.json +1 -1
  159. package/packages/pm-linked-test-adapters/package.json +1 -1
  160. package/packages/pm-search-advanced/package.json +1 -1
  161. package/packages/pm-templates/package.json +1 -1
  162. package/packages/pm-todos/package.json +1 -1
  163. package/packages/pm-vcs/package.json +1 -1
  164. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  165. package/plugins/pm-claude/skills/pm-audit/SKILL.md +2 -2
  166. package/plugins/pm-claude/skills/pm-developer/SKILL.md +2 -2
  167. package/plugins/pm-claude/skills/pm-planner/SKILL.md +2 -2
  168. package/plugins/pm-claude/skills/pm-release/SKILL.md +2 -2
  169. package/plugins/pm-claude/skills/pm-workflow/SKILL.md +3 -3
  170. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  171. package/plugins/pm-codex/skills/pm-auditor/SKILL.md +2 -2
  172. package/plugins/pm-codex/skills/pm-native/SKILL.md +3 -4
  173. package/plugins/pm-codex/skills/pm-release/SKILL.md +2 -2
  174. package/scripts/finalize-build.mjs +13 -1
  175. package/dist/cli-bundle/chunks/chunk-6XSKPNCF.js +0 -230
  176. package/dist/cli-bundle/chunks/chunk-OGBVU67G.js +0 -5
  177. package/dist/cli-bundle/chunks/chunk-TXW6VL33.js +0 -38
  178. package/dist/cli-bundle/chunks/chunk-VGLHECAP.js +0 -9
  179. package/dist/cli-bundle/chunks/register-operations-OH7R3ZT4.js +0 -2
  180. package/dist/cli-bundle/focused-chunks/chunk-4YRAVI43.js +0 -12
  181. package/dist/cli-bundle/focused-chunks/chunk-5P4HVOWG.js +0 -176
  182. package/dist/cli-bundle/focused-chunks/chunk-636VVQ7F.js +0 -54
  183. package/dist/cli-bundle/focused-chunks/chunk-B3A6MJYE.js +0 -2
  184. package/dist/cli-bundle/focused-chunks/chunk-BFDDJ2T2.js +0 -2
  185. package/dist/cli-bundle/focused-chunks/chunk-BHUIRZWQ.js +0 -9
  186. package/dist/cli-bundle/focused-chunks/chunk-JADHHPY6.js +0 -6
  187. package/dist/cli-bundle/focused-chunks/chunk-NSKBLHVI.js +0 -20
  188. package/dist/cli-bundle/focused-chunks/chunk-P2GOAOQN.js +0 -2
  189. package/dist/cli-bundle/focused-chunks/chunk-YARWJM2B.js +0 -2
  190. package/sdk/public-surface.json +0 -33034
@@ -839,6 +839,8 @@ export interface SchemaItemTypeDefinition {
839
839
  description?: string;
840
840
  /** Initial status assigned when the contributed item type is created. */
841
841
  default_status?: string;
842
+ /** Dispatch role inherited by next, context, and automatic claims. Gates track outcomes; human roles require decisions. */
843
+ execution_role?: "agent" | "human" | "gate";
842
844
  /** Value that configures or reports required create fields for this contract. */
843
845
  required_create_fields?: string[];
844
846
  /** Value that configures or reports required create repeatables for this contract. */
@@ -1,6 +1,6 @@
1
1
  /** Public contract for known extension capabilities, shared by SDK and presentation-layer consumers. */
2
2
 
3
- !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]="ef5c8553-c206-5bb5-913a-85afb936f6d7")}catch(e){}}();
3
+ !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]="a2f05fd9-1331-5e75-b8c1-42ad6deb425e")}catch(e){}}();
4
4
  export const KNOWN_EXTENSION_CAPABILITIES = [
5
5
  "commands",
6
6
  "renderers",
@@ -100,4 +100,4 @@ export function createDefaultExtensionGovernancePolicy() {
100
100
  };
101
101
  }
102
102
  //# sourceMappingURL=extension-types.js.map
103
- //# debugId=ef5c8553-c206-5bb5-913a-85afb936f6d7
103
+ //# debugId=a2f05fd9-1331-5e75-b8c1-42ad6deb425e
@@ -1,6 +1,11 @@
1
+ import { type HistoryIdentityDiscontinuity } from "./identity.js";
1
2
  import type { ItemMetadata } from "../../types/index.js";
2
3
  /** Documents the drift scan result payload exchanged by command, SDK, and package integrations. */
3
4
  export interface DriftScanResult {
5
+ /** Repeated genesis ordinals and observed sequence, keyed by affected item. */
6
+ identityDiscontinuities?: Array<HistoryIdentityDiscontinuity & {
7
+ item_id: string;
8
+ }>;
4
9
  /** Value that configures or reports missing streams for this contract. */
5
10
  missingStreams: string[];
6
11
  /** Value that configures or reports unreadable streams for this contract. */
@@ -1,5 +1,5 @@
1
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]="1c6c65ef-115b-50e2-815e-84f6e91158cd")}catch(e){}}();
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]="80648bfe-2436-5b5a-8a16-b9c2875f95fd")}catch(e){}}();
3
3
  import fs from "node:fs/promises";
4
4
  import { createHash } from "node:crypto";
5
5
  import path from "node:path";
@@ -7,12 +7,14 @@ import { getHistoryPath } from "../store/paths.js";
7
7
  import { isFileMissingError, writeFileAtomic } from "../fs/fs-utils.js";
8
8
  import { CURRENT_HISTORY_ITEM_HASH_VERSION, SUPPORTED_HISTORY_ITEM_HASH_VERSIONS, hashDocumentVerificationCandidates, } from "./history.js";
9
9
  import { verifyHistoryChainWithVersion } from "./replay.js";
10
+ import { findHistoryIdentityDiscontinuities, } from "./identity.js";
10
11
  import { getWorkspaceHistoryPath, inspectWorkspaceHistoryState, WORKSPACE_HISTORY_ID, } from "./workspace-history.js";
11
- const DRIFT_CACHE_VERSION = 9;
12
+ const DRIFT_CACHE_VERSION = 10;
12
13
  const DRIFT_CACHE_FILENAME = "history-drift-cache.json";
13
14
  function getDriftCachePath(pmRoot) {
14
15
  return path.join(pmRoot, "runtime", DRIFT_CACHE_FILENAME);
15
16
  }
17
+ /** Discard unreadable or stale cache envelopes, including prior verification semantics. */
16
18
  async function loadDriftCache(pmRoot) {
17
19
  try {
18
20
  const raw = await fs.readFile(getDriftCachePath(pmRoot), "utf8");
@@ -123,6 +125,7 @@ async function verifyHistoryStream(historyPath) {
123
125
  : verification.item_hash_version;
124
126
  return {
125
127
  latestAfterHash,
128
+ identityDiscontinuities: findHistoryIdentityDiscontinuities(entries),
126
129
  chainOk: verification.ok,
127
130
  versionSkew,
128
131
  latestHashComparable: latestHashVersion !== undefined &&
@@ -153,15 +156,15 @@ async function loadFreshStreamVerification(itemId, historyPath, accumulator) {
153
156
  return null;
154
157
  }
155
158
  }
159
+ /** Reverify invalid streams and content-sensitive cache hits; reuse only compatible healthy evidence. */
156
160
  async function resolveStreamVerification(params) {
157
161
  const cachedContentHash = typeof params.cached?.content_hash === "string" &&
158
162
  params.cached.content_hash.length > 0
159
163
  ? params.cached.content_hash
160
164
  : undefined;
161
165
  const canUseCache = cacheMetadataMatches(params.cached, params.stat) &&
162
- cachedContentHash !== undefined &&
163
- params.cached !== undefined;
164
- if (!canUseCache || !params.cached) {
166
+ cachedContentHash !== undefined;
167
+ if (!canUseCache || !params.cached || !params.cached.chain_ok) {
165
168
  return {
166
169
  verification: await loadFreshStreamVerification(params.itemId, params.historyPath, params.accumulator),
167
170
  cacheDirty: true,
@@ -183,6 +186,7 @@ async function resolveStreamVerification(params) {
183
186
  }
184
187
  return {
185
188
  verification: {
189
+ identityDiscontinuities: [],
186
190
  latestAfterHash: params.cached.latest_after_hash,
187
191
  chainOk: params.cached.chain_ok,
188
192
  versionSkew: params.cached.version_skew === true,
@@ -217,6 +221,12 @@ async function scanItemHistory(pmRoot, item, cache, accumulator) {
217
221
  });
218
222
  if (!resolved.verification)
219
223
  return resolved.cacheDirty;
224
+ if (resolved.verification.identityDiscontinuities.length > 0) {
225
+ (accumulator.identityDiscontinuities ??= []).push(...resolved.verification.identityDiscontinuities.map((finding) => ({
226
+ ...finding,
227
+ item_id: item.id,
228
+ })));
229
+ }
220
230
  if (resolved.verification.versionSkew) {
221
231
  accumulator.versionSkews.push(item.id);
222
232
  }
@@ -330,4 +340,4 @@ export async function scanHistoryDrift(pmRoot, items, options = {}) {
330
340
  return { ...accumulator, driftedItems };
331
341
  }
332
342
  //# sourceMappingURL=drift-scan.js.map
333
- //# debugId=1c6c65ef-115b-50e2-815e-84f6e91158cd
343
+ //# debugId=80648bfe-2436-5b5a-8a16-b9c2875f95fd
@@ -10,7 +10,7 @@ export declare const HISTORY_EVENT_CLASSIFICATION_VERSION: 1;
10
10
  /** Semantic effect of an immutable history event on project recency. */
11
11
  export type HistoryEventClass = "substantive" | "maintenance";
12
12
  /** Operations whose meaning is always governance or storage maintenance. */
13
- export declare const MAINTENANCE_HISTORY_OPERATIONS: readonly ["docs_add", "files_add", "history:author-acknowledge", "history_author_acknowledge", "history_compact", "history_compact_baseline", "history_redact", "history_repair", "normalize", "release", "test_run_track", "tests_add", "tests_remove", "update_audit", "update_ownership_bypass"];
13
+ export declare const MAINTENANCE_HISTORY_OPERATIONS: readonly ["docs_add", "files_add", "history:author-acknowledge", "history_author_acknowledge", "history_compact", "history_compact_baseline", "history_redact", "history_repair", "history_salvage", "normalize", "release", "test_run_track", "tests_add", "tests_remove", "update_audit", "update_ownership_bypass"];
14
14
  /** Operations whose meaning always advances lifecycle or working context. */
15
15
  export declare const SUBSTANTIVE_HISTORY_OPERATIONS: readonly ["append", "cancel", "claim", "close", "comment_add", "create", "learning_add", "note_add", "reopen"];
16
16
  /**
@@ -1,6 +1,6 @@
1
1
  /** Current version of the public history-event classification policy. */
2
2
 
3
- !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]="6398c65d-fb5c-5479-93c2-0be963352a92")}catch(e){}}();
3
+ !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]="9ad6614e-44bc-549c-915c-6177c3a43c1f")}catch(e){}}();
4
4
  export const HISTORY_EVENT_CLASSIFICATION_VERSION = 1;
5
5
  /** Operations whose meaning is always governance or storage maintenance. */
6
6
  export const MAINTENANCE_HISTORY_OPERATIONS = [
@@ -12,6 +12,7 @@ export const MAINTENANCE_HISTORY_OPERATIONS = [
12
12
  "history_compact_baseline",
13
13
  "history_redact",
14
14
  "history_repair",
15
+ "history_salvage",
15
16
  "normalize",
16
17
  "release",
17
18
  "test_run_track",
@@ -106,4 +107,4 @@ export function classifyHistoryEvent(entry) {
106
107
  : "substantive";
107
108
  }
108
109
  //# sourceMappingURL=event-classification.js.map
109
- //# debugId=6398c65d-fb5c-5479-93c2-0be963352a92
110
+ //# debugId=9ad6614e-44bc-549c-915c-6177c3a43c1f
@@ -4,8 +4,10 @@
4
4
  * Implements append-only history and replay behavior for History.
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]="bf6a9831-134c-5dc2-a3e2-74dca00cf22c")}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]="a5449fec-c5b4-5cf4-9a7f-b7c5dc7161c2")}catch(e){}}();
8
8
  import jsonPatch from "fast-json-patch";
9
+ import fs from "node:fs/promises";
10
+ import path from "node:path";
9
11
  import { EXIT_CODE, ITEM_METADATA_KEY_ORDER } from "../shared/constants.js";
10
12
  import { runActiveServiceOverride } from "../extensions/index.js";
11
13
  import { appendLineAtomic } from "../fs/fs-utils.js";
@@ -539,7 +541,8 @@ async function applyHistoryAppendOverride(historyPath, entry, result) {
539
541
  if (result === false)
540
542
  return true;
541
543
  if (typeof result === "string") {
542
- await appendLineAtomic(historyPath, serializeHistoryLine(result, entry));
544
+ const line = serializeHistoryLine(result, entry);
545
+ await appendHistoryLineWithIdentityReservation(historyPath, line);
543
546
  await invalidateHistoryDriftCacheForPath(historyPath);
544
547
  await removeHistoryEventIndexForHistoryPath(historyPath);
545
548
  return true;
@@ -550,11 +553,40 @@ async function applyHistoryAppendOverride(historyPath, entry, result) {
550
553
  if (record.skip === true)
551
554
  return true;
552
555
  const nextHistoryPath = typeof record.history_path === "string" ? record.history_path : historyPath;
553
- await appendLineAtomic(nextHistoryPath, serializeHistoryLine(typeof record.line === "string" ? record.line : (record.entry ?? entry), entry));
556
+ const line = serializeHistoryLine(typeof record.line === "string" ? record.line : (record.entry ?? entry), entry);
557
+ await appendHistoryLineWithIdentityReservation(nextHistoryPath, line);
554
558
  await invalidateHistoryDriftCacheForPath(nextHistoryPath);
555
559
  await removeHistoryEventIndexForHistoryPath(nextHistoryPath);
556
560
  return true;
557
561
  }
562
+ /** Exclusively create genesis streams at their effective destination; never remove a failed partial reservation. */
563
+ async function appendHistoryLineWithIdentityReservation(historyPath, line) {
564
+ let record;
565
+ try {
566
+ record = JSON.parse(line);
567
+ }
568
+ catch {
569
+ // Legacy service overrides may provide non-JSON lines; verification diagnoses them.
570
+ record = null;
571
+ }
572
+ if (!isRecord(record) || record.op !== "create") {
573
+ await appendLineAtomic(historyPath, line);
574
+ return;
575
+ }
576
+ await fs.mkdir(path.dirname(historyPath), { recursive: true });
577
+ try {
578
+ await fs.writeFile(historyPath, `${line}\n`, { encoding: "utf8", flag: "wx" });
579
+ }
580
+ catch (error) {
581
+ if (error.code !== "EEXIST")
582
+ throw error;
583
+ throw new PmCliError("This item identity is reserved by an existing history stream.", EXIT_CODE.CONFLICT, {
584
+ code: "item_identity_reserved",
585
+ required: "Choose a new item ID or restore the original item from its history.",
586
+ nextSteps: ["Run pm history <id> --full, then pm restore <id> <version> to recover the original item."],
587
+ });
588
+ }
589
+ }
558
590
  /** Implements append history entry for the public runtime surface of this module. */
559
591
  export async function appendHistoryEntry(historyPath, entry) {
560
592
  const override = await runActiveServiceOverride("history_append", {
@@ -573,7 +605,7 @@ export async function appendHistoryEntry(historyPath, entry) {
573
605
  event_class: classifyHistoryEvent(timestampedEntry),
574
606
  });
575
607
  await appendHistoryEntryWithEventIndex(historyPath, normalizedEntry, async () => {
576
- await appendLineAtomic(historyPath, serializeHistoryLine(normalizedEntry, normalizedEntry));
608
+ await appendHistoryLineWithIdentityReservation(historyPath, serializeHistoryLine(normalizedEntry, normalizedEntry));
577
609
  });
578
610
  await invalidateHistoryDriftCacheForPath(historyPath);
579
611
  }
@@ -583,4 +615,4 @@ export const _testOnly = {
583
615
  isDefinedPointerPath,
584
616
  };
585
617
  //# sourceMappingURL=history.js.map
586
- //# debugId=bf6a9831-134c-5dc2-a3e2-74dca00cf22c
618
+ //# debugId=a5449fec-c5b4-5cf4-9a7f-b7c5dc7161c2
@@ -0,0 +1,15 @@
1
+ /** @module core/history/identity
2
+ * Identifies multiple genesis records without inferring an unrecorded writer.
3
+ */
4
+ import type { HistoryEntry } from "../../types/index.js";
5
+ /** Evidence of a second subject occupying one append-only identity stream. */
6
+ export interface HistoryIdentityDiscontinuity {
7
+ /** One-based physical ordinal of the original create or retained baseline. */
8
+ prior_genesis_index: number;
9
+ /** One-based physical ordinal of the later create record. */
10
+ repeated_create_index: number;
11
+ /** Observed record sequence, not an assertion about branch or writer origin. */
12
+ sequence: "delete_then_create" | "multiple_creates" | "checkpoint_then_create";
13
+ }
14
+ /** Find every repeated genesis, including histories that start at a checkpoint. */
15
+ export declare function findHistoryIdentityDiscontinuities(entries: readonly HistoryEntry[]): HistoryIdentityDiscontinuity[];
@@ -0,0 +1,31 @@
1
+ /** Find every repeated genesis, including histories that start at a checkpoint. */
2
+
3
+ !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]="ffaea7bd-daa4-5ff5-8cd5-82ad04e2256e")}catch(e){}}();
4
+ export function findHistoryIdentityDiscontinuities(entries) {
5
+ const findings = [];
6
+ const checkpoint = entries[0]?.op === "history_compact_baseline";
7
+ let genesis = checkpoint ? 1 : undefined;
8
+ let deleted = false;
9
+ for (const [index, entry] of entries.entries()) {
10
+ if (entry.op === "delete")
11
+ deleted = true;
12
+ if (entry.op !== "create")
13
+ continue;
14
+ if (genesis !== undefined) {
15
+ findings.push({
16
+ prior_genesis_index: genesis,
17
+ repeated_create_index: index + 1,
18
+ sequence: deleted
19
+ ? "delete_then_create"
20
+ : checkpoint
21
+ ? "checkpoint_then_create"
22
+ : "multiple_creates",
23
+ });
24
+ }
25
+ genesis ??= index + 1;
26
+ deleted = false;
27
+ }
28
+ return findings;
29
+ }
30
+ //# sourceMappingURL=identity.js.map
31
+ //# debugId=ffaea7bd-daa4-5ff5-8cd5-82ad04e2256e
@@ -6,10 +6,11 @@
6
6
  * replay kernel so read and write paths cannot disagree about a version.
7
7
  */
8
8
 
9
- !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]="47c087c2-124a-58b7-a5c9-09403235f4a2")}catch(e){}}();
9
+ !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]="2efbffc1-722c-5f3a-9ca5-e4e7a4f97729")}catch(e){}}();
10
10
  import { EXIT_CODE } from "../shared/constants.js";
11
11
  import { PmCliError } from "../shared/errors.js";
12
- import { EMPTY_REPLAY_DOCUMENT, replayHash, tryApplyReplayPatch, } from "./replay.js";
12
+ import { historyVersionOffset } from "./version-address.js";
13
+ import { EMPTY_REPLAY_DOCUMENT, verifyHistoryChain, tryApplyReplayPatch, } from "./replay.js";
13
14
  /** Find the final history entry recorded at or before a parsed timestamp. */
14
15
  function findHistoryIndexAtTimestamp(history, parsedTarget) {
15
16
  let historyIndex = -1;
@@ -25,7 +26,7 @@ function findHistoryIndexAtTimestamp(history, parsedTarget) {
25
26
  return historyIndex;
26
27
  }
27
28
  /** Build structured target-range guidance once for every resolver error path. */
28
- function buildHistoryTargetGuidance(history) {
29
+ function buildHistoryTargetGuidance(history, offset) {
29
30
  const firstTimestamp = history[0]?.ts ?? null;
30
31
  const lastTimestamp = history.at(-1)?.ts ?? null;
31
32
  const guidance = {
@@ -44,9 +45,12 @@ function buildHistoryTargetGuidance(history) {
44
45
  },
45
46
  };
46
47
  if (lastTimestamp !== null) {
47
- guidance.examples = ["1", String(history.length), lastTimestamp];
48
- guidance.valid_range.first_version = 1;
49
- guidance.valid_range.last_version = history.length;
48
+ guidance.examples = [lastTimestamp];
49
+ if (offset !== null) {
50
+ guidance.examples.unshift(String(offset + 1), String(offset + history.length));
51
+ guidance.valid_range.first_version = offset + 1;
52
+ guidance.valid_range.last_version = offset + history.length;
53
+ }
50
54
  }
51
55
  return { guidance, lastTimestamp };
52
56
  }
@@ -90,18 +94,25 @@ export function resolveHistoryTarget(target, history, options = {}) {
90
94
  const trimmed = target.trim();
91
95
  const errorSubject = options.errorSubject ?? "history";
92
96
  const errorSubjectTitle = errorSubject === "restore" ? "Restore" : "History";
93
- const { guidance, lastTimestamp } = buildHistoryTargetGuidance(history);
97
+ const { guidance, lastTimestamp } = buildHistoryTargetGuidance(history, historyVersionOffset(history, true));
94
98
  if (!trimmed) {
95
99
  throw new PmCliError(`Missing ${errorSubject} target. Use a timestamp or version number.`, EXIT_CODE.USAGE, guidance);
96
100
  }
97
101
  if (/^\d+$/.test(trimmed)) {
102
+ const offset = historyVersionOffset(history);
98
103
  const version = Number(trimmed);
104
+ if (version >= 1 && version <= offset) {
105
+ throw new PmCliError(`History version ${version} was pruned by compaction.`, EXIT_CODE.USAGE, {
106
+ ...guidance,
107
+ code: "history_version_pruned",
108
+ });
109
+ }
99
110
  if (!Number.isSafeInteger(version) ||
100
111
  version < 1 ||
101
- version > history.length) {
102
- throw new PmCliError(`${errorSubjectTitle} version must be between 1 and ${history.length} for this item.`, EXIT_CODE.USAGE, guidance);
112
+ version > offset + history.length) {
113
+ throw new PmCliError(`${errorSubjectTitle} version must be between ${offset + 1} and ${offset + history.length} for this item.`, EXIT_CODE.USAGE, guidance);
103
114
  }
104
- return { kind: "version", raw: trimmed, historyIndex: version - 1 };
115
+ return { kind: "version", raw: trimmed, historyIndex: version - offset - 1 };
105
116
  }
106
117
  const parsedTarget = Date.parse(trimmed);
107
118
  if (!Number.isFinite(parsedTarget)) {
@@ -137,28 +148,50 @@ export function applyHistoryPatch(current, patch, entryNumber, entryOp) {
137
148
  }
138
149
  /** Replay and hash-verify a history stream through a zero-based target entry. */
139
150
  export function replayHistoryToTarget(history, targetIndex) {
151
+ const first = history[0];
152
+ if (first && first.op !== "create" && first.op !== "history_compact_baseline") {
153
+ const baseline = tryApplyReplayPatch(EMPTY_REPLAY_DOCUMENT, first.patch);
154
+ if (!baseline.ok || typeof baseline.document.metadata.id !== "string") {
155
+ throw new PmCliError("History starts without a reconstructable item baseline.", EXIT_CODE.GENERIC_FAILURE, {
156
+ code: "history_baseline_unavailable",
157
+ required: "Recover the original create entry or a complete checkpoint from version control.",
158
+ nextSteps: ["Run pm history <id> --full to inspect the missing baseline."],
159
+ });
160
+ }
161
+ }
162
+ const selected = history.slice(0, targetIndex + 1);
163
+ const verification = verifyHistoryChain([...selected]);
140
164
  let document = structuredClone(EMPTY_REPLAY_DOCUMENT);
141
165
  for (let index = 0; index <= targetIndex; index += 1) {
142
166
  const entry = history[index];
143
167
  if (!entry) {
144
168
  throw new PmCliError(`History target entry ${index + 1} does not exist.`, EXIT_CODE.USAGE);
145
169
  }
146
- if (replayHash(document) !== entry.before_hash) {
147
- throw new PmCliError(`History hash mismatch before replay at entry ${index + 1}.`, EXIT_CODE.GENERIC_FAILURE);
148
- }
149
170
  document = applyHistoryPatch(document, entry.patch, index + 1, entry.op);
150
- if (replayHash(document) !== entry.after_hash) {
151
- throw new PmCliError(`History hash mismatch after replay at entry ${index + 1}.`, EXIT_CODE.GENERIC_FAILURE);
152
- }
171
+ }
172
+ if (!verification.ok) {
173
+ throw new PmCliError(`History cannot be replayed: ${verification.errors.join(", ")}.`, EXIT_CODE.GENERIC_FAILURE, {
174
+ code: "history_replay_invalid",
175
+ verification_errors: verification.errors,
176
+ required: "Inspect the history integrity findings before attempting recovery.",
177
+ nextSteps: ["Run pm history <id> --verify --full."],
178
+ });
153
179
  }
154
180
  return document;
155
181
  }
156
182
  /** Reject a version whose reconstructed state represents a deleted item. */
157
183
  export function ensureMaterializedHistoryTarget(replayDocument, target) {
158
184
  if (Object.keys(replayDocument.metadata).length > 0) {
185
+ if (typeof replayDocument.metadata.id !== "string" || !Array.isArray(replayDocument.metadata.tags)) {
186
+ throw new PmCliError("History has no complete item baseline for this target.", EXIT_CODE.GENERIC_FAILURE, {
187
+ code: "history_baseline_unavailable",
188
+ required: "Recover the original create entry or a complete checkpoint from version control.",
189
+ nextSteps: ["Run pm history <id> --full to inspect the first recorded state."],
190
+ });
191
+ }
159
192
  return replayDocument;
160
193
  }
161
194
  throw new PmCliError(`History target ${target.raw} resolves to a deleted state; choose a version or timestamp where the item exists.`, EXIT_CODE.USAGE);
162
195
  }
163
196
  //# sourceMappingURL=projection.js.map
164
- //# debugId=47c087c2-124a-58b7-a5c9-09403235f4a2
197
+ //# debugId=2efbffc1-722c-5f3a-9ca5-e4e7a4f97729
@@ -7,7 +7,7 @@
7
7
  * maintenance APIs from depending on presentation-layer modules.
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]="aa65b74d-ef5d-57ed-b613-3034da52a8ba")}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]="999c126a-112a-50f6-b53e-bd36dbc5b885")}catch(e){}}();
11
11
  import { readFileIfExists } from "../fs/fs-utils.js";
12
12
  import { runActiveOnReadHooks } from "../extensions/index.js";
13
13
  import { EXIT_CODE } from "../shared/constants.js";
@@ -46,10 +46,13 @@ export async function readHistoryEntries(historyPath, itemId) {
46
46
  entries.push(JSON.parse(line));
47
47
  }
48
48
  catch {
49
- throw new PmCliError(`History for ${itemId} contains invalid JSON at line ${index + 1}. Repair or restore the history stream and retry.`, EXIT_CODE.GENERIC_FAILURE);
49
+ throw new PmCliError(`History for ${itemId} contains invalid JSON at line ${index + 1}. Repair or restore the history stream and retry.`, EXIT_CODE.GENERIC_FAILURE, {
50
+ code: "history_json_invalid",
51
+ nextSteps: [`Run pm history-repair ${itemId} --salvage-tail --dry-run to check whether only an invalid suffix is damaged.`],
52
+ });
50
53
  }
51
54
  }
52
55
  return entries;
53
56
  }
54
57
  //# sourceMappingURL=read.js.map
55
- //# debugId=aa65b74d-ef5d-57ed-b613-3034da52a8ba
58
+ //# debugId=999c126a-112a-50f6-b53e-bd36dbc5b885
@@ -47,7 +47,6 @@ export type ReplayApplyResult = {
47
47
  };
48
48
  /** Strictly apply a history patch (front_matter->metadata normalized) to a replay document. Returns a result envelope rather than throwing so each caller can format its own error contract. */
49
49
  export declare function tryApplyReplayPatch(current: ReplayDocument, patch: HistoryPatchOp[]): ReplayApplyResult;
50
- /** Deterministically verify a history chain: each entry's before_hash must equal the prior replayed after_hash, the patch must strictly apply, and the recorded after_hash must equal the replayed result. */
51
50
  /** Verify a chain and report the explicit or auto-detected item hash epoch. */
52
51
  export declare function verifyHistoryChainWithVersion(entries: HistoryEntry[]): {
53
52
  ok: boolean;
@@ -119,6 +118,6 @@ export interface ReanchorHistoryOptions {
119
118
  */
120
119
  export declare function resolveHistoryRepairItemHashVersion(entries: HistoryEntry[]): HistoryItemHashVersion;
121
120
  /** Re-anchor a drifted history chain: replay every entry from empty, recompute the before/after hashes, and only rewrite a patch when the original op set no longer strictly applies (legacy drift). Clean entries keep their patch verbatim so the on-disk diff stays minimal. The returned chain verifies via verifyHistoryChain. */
122
- export declare function reanchorHistoryEntries(entries: HistoryEntry[], itemHashVersion?: 1 | 2 | 3, options?: ReanchorHistoryOptions): ReanchorResult;
121
+ export declare function reanchorHistoryEntries(entries: HistoryEntry[], itemHashVersion?: HistoryItemHashVersion, options?: ReanchorHistoryOptions): ReanchorResult;
123
122
  /** Implements history entries to raw for the public runtime surface of this module. */
124
123
  export declare function historyEntriesToRaw(entries: HistoryEntry[]): string;
@@ -4,8 +4,9 @@
4
4
  * Implements append-only history and replay behavior for Replay.
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]="ce8dfbdf-8471-5843-8179-5608140330e1")}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]="b0230e20-93c4-531c-9cc1-85f85c1def7a")}catch(e){}}();
8
8
  import jsonPatch from "fast-json-patch";
9
+ import { findHistoryIdentityDiscontinuities } from "./identity.js";
9
10
  import { ITEM_METADATA_KEY_ORDER } from "../shared/constants.js";
10
11
  import { canonicalDocument } from "../item/item-format.js";
11
12
  import { toItemRecord } from "../item/item-record.js";
@@ -190,13 +191,12 @@ function assertHistoryEntryIntegrity(entry, index) {
190
191
  throw new TypeError(`${integrityError}:entry_${index + 1}`);
191
192
  }
192
193
  }
193
- /** Deterministically verify a history chain: each entry's before_hash must equal the prior replayed after_hash, the patch must strictly apply, and the recorded after_hash must equal the replayed result. */
194
194
  /** Verify a chain and report the explicit or auto-detected item hash epoch. */
195
195
  export function verifyHistoryChainWithVersion(entries) {
196
196
  let replay = cloneEmptyReplayDocument();
197
197
  let detectedVersion;
198
198
  let authoritativeExplicitVersion;
199
- const errors = [];
199
+ const errors = findHistoryIdentityDiscontinuities(entries).map((finding) => `verify_failed:duplicate_create:entry_${finding.repeated_create_index}:prior_${finding.prior_genesis_index}`);
200
200
  for (let index = 0; index < entries.length; index += 1) {
201
201
  const entry = entries[index];
202
202
  const explicitVersion = entry.item_hash_version;
@@ -437,4 +437,4 @@ export function historyEntriesToRaw(entries) {
437
437
  return `${entries.map((entry) => JSON.stringify(entry)).join("\n")}\n`;
438
438
  }
439
439
  //# sourceMappingURL=replay.js.map
440
- //# debugId=ce8dfbdf-8471-5843-8179-5608140330e1
440
+ //# debugId=b0230e20-93c4-531c-9cc1-85f85c1def7a
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @module core/history/version-address
3
+ * Stable ordinal addressing for streams whose retained prefix is a checkpoint.
4
+ */
5
+ import type { HistoryEntry } from "../../types/index.js";
6
+ /**
7
+ * Return the number added to physical one-based positions to obtain durable
8
+ * version addresses. Legacy checkpoints cannot prove their original ordinal;
9
+ * refusing them prevents silently selecting a different historical state.
10
+ */
11
+ export declare function historyVersionOffset(history: readonly HistoryEntry[], allowUnknown: true): number | null;
12
+ /** Resolve a required durable offset, refusing ambiguous legacy checkpoints. */
13
+ export declare function historyVersionOffset(history: readonly HistoryEntry[], allowUnknown?: false): number;
@@ -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]="7ad4e6c0-7545-51cb-9af7-4ba1ad4c4758")}catch(e){}}();
3
+ import { EXIT_CODE } from "../shared/constants.js";
4
+ import { PmCliError } from "../shared/errors.js";
5
+ /** Resolve the checkpoint offset with an explicit opt-in for unknown legacy addresses. */
6
+ export function historyVersionOffset(history, allowUnknown = false) {
7
+ const first = history[0];
8
+ if (first?.op !== "history_compact_baseline")
9
+ return 0;
10
+ const receipt = first.context?.history_compaction;
11
+ const offset = typeof receipt === "object" &&
12
+ receipt !== null &&
13
+ "version_offset" in receipt
14
+ ? receipt.version_offset
15
+ : undefined;
16
+ if (typeof offset === "number" &&
17
+ Number.isSafeInteger(offset) &&
18
+ offset >= 0 &&
19
+ Number.isSafeInteger(offset + history.length)) {
20
+ return offset;
21
+ }
22
+ if (allowUnknown)
23
+ return null;
24
+ throw new PmCliError("This compacted stream has no trustworthy version offset; numeric history addresses are unavailable.", EXIT_CODE.USAGE, {
25
+ code: "history_version_mapping_unavailable",
26
+ required: "Use a retained timestamp or recover the pre-compaction stream from version control.",
27
+ nextSteps: [
28
+ "Run pm history <id> --full to inspect the retained timestamps and checkpoint evidence.",
29
+ ],
30
+ });
31
+ }
32
+ //# sourceMappingURL=version-address.js.map
33
+ //# debugId=7ad4e6c0-7545-51cb-9af7-4ba1ad4c4758
@@ -1,5 +1,8 @@
1
1
  import type { RuntimeStatusRegistry } from "../schema/runtime-schema.js";
2
2
  import type { ItemMetadata, ItemStatus } from "../../types/index.js";
3
+ import { type ItemTypeRegistry } from "./type-registry.js";
4
+ /** Resolve dispatch semantics once for SDK callers, honoring custom and extension type aliases before built-in defaults. */
5
+ export declare function resolveItemExecutionRole(type: string, registry?: ItemTypeRegistry): "agent" | "human" | "gate";
3
6
  /** Built-in ordering kinds that must remain reachable by blocker resolution. */
4
7
  export declare const ACTIONABILITY_ORDERING_KINDS: readonly string[];
5
8
  /** Collects the blocker item ids declared by an item: the legacy scalar `blocked_by` field plus every `blocked_by` dependency edge. Ids are trimmed, de-duplicated, and returned in stable lexicographic order. This is the single source of truth for "what must close before this item can proceed", shared by `pm next` readiness classification and the close-time auto-unblock sweep. */
@@ -54,11 +57,28 @@ export interface ActionabilityReport {
54
57
  ready: ActionableEntry[];
55
58
  /** Active leaves with at least one open blocker — waiting to become ready. */
56
59
  blocked: ActionableEntry[];
60
+ /** Active containers with unresolved descendants, including their blocker evidence. */
61
+ containers: ActionableEntry[];
62
+ /** Unblocked leaf work that requires a human decision. */
63
+ decisions: ActionableEntry[];
64
+ /** Unblocked leaf outcome gates held out of automatic dispatch. */
65
+ gates: ActionableEntry[];
57
66
  /** Active candidates considered before the leaf/blocker split. */
58
67
  active_count: number;
59
68
  /** Active candidates skipped because they still have open descendants. */
60
69
  container_count: number;
61
70
  }
71
+ /** Explicit dispatch opt-ins; dependency and lifecycle blocking always remain enforced. */
72
+ export interface ActionabilitySelectionOptions {
73
+ /** Include human decision work in the executable selection. */
74
+ includeDecisions?: boolean;
75
+ /** Include outcome gates in the executable selection. */
76
+ includeGates?: boolean;
77
+ /** Include containers whose descendants are still unfinished. */
78
+ includeContainers?: boolean;
79
+ }
80
+ /** Select dispatch candidates from a classified report while retaining held-out worklists. Ownership and ranking remain caller responsibilities. */
81
+ export declare function selectActionableEntries(report: ActionabilityReport, statusRegistry: RuntimeStatusRegistry, options?: ActionabilitySelectionOptions, typeRegistry?: ItemTypeRegistry): Pick<ActionabilityReport, "ready" | "decisions" | "gates">;
62
82
  /**
63
83
  * Partitions a candidate set into ready vs blocked leaf work using the corpus to
64
84
  * resolve blockers, descendants, and downstream dependents.
@@ -70,4 +90,4 @@ export interface ActionabilityReport {
70
90
  * blockers and the non-terminal items it would unblock. Returned lists preserve
71
91
  * the candidate order so the caller can apply its own ranking.
72
92
  */
73
- export declare function computeActionabilityReport(candidates: ItemMetadata[], corpus: ItemMetadata[], statusRegistry: RuntimeStatusRegistry): ActionabilityReport;
93
+ export declare function computeActionabilityReport(candidates: ItemMetadata[], corpus: ItemMetadata[], statusRegistry: RuntimeStatusRegistry, typeRegistry?: ItemTypeRegistry): ActionabilityReport;