@unbrained/pm-cli 2026.9.3 → 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 (228) 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 +52 -0
  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 +154 -154
  22. package/dist/cli-bundle/chunks/{chunk-EDPIS7EB.js → chunk-3HBDTJRK.js} +2 -2
  23. package/dist/cli-bundle/chunks/chunk-66VPKFP2.js +5 -0
  24. package/dist/cli-bundle/chunks/{chunk-Y4PJ6HPK.js → chunk-HUAQITVW.js} +2 -2
  25. package/dist/cli-bundle/chunks/{chunk-DKGP3QLE.js → chunk-IBYREGSP.js} +2 -2
  26. package/dist/cli-bundle/chunks/chunk-LUI4E32I.js +231 -0
  27. package/dist/cli-bundle/chunks/{chunk-UPPM2FOZ.js → chunk-QPZHQY2O.js} +2 -2
  28. package/dist/cli-bundle/chunks/{chunk-34HASX3S.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-LENC656S.js → chunk-WWAEGW4V.js} +67 -70
  32. package/dist/cli-bundle/chunks/chunk-ZRAQS3UA.js +8 -0
  33. package/dist/cli-bundle/chunks/{register-list-query-W2ZTOMKP.js → register-list-query-AYKGODWT.js} +3 -3
  34. package/dist/cli-bundle/chunks/{register-mutation-RVND5NCG.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-D3ZFHY3L.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-M5M6SVHS.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-S27XMBIN.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-5RFXUPN5.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-Q45NHPF2.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-D7KXFBXV.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-4HJFY4MB.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-WOCIPMW7.js +2 -0
  54. package/dist/cli-bundle/focused-chunks/{chunk-GT7MXDLW.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 -32
  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 +45 -37
  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 +10 -10
  66. package/dist/core/diagnostics/remediation.js +4 -4
  67. package/dist/core/extensions/extension-types.d.ts +2 -0
  68. package/dist/core/extensions/extension-types.js +2 -2
  69. package/dist/core/history/drift-scan.d.ts +5 -0
  70. package/dist/core/history/drift-scan.js +16 -6
  71. package/dist/core/history/event-classification.d.ts +1 -1
  72. package/dist/core/history/event-classification.js +3 -2
  73. package/dist/core/history/history.d.ts +37 -1
  74. package/dist/core/history/history.js +311 -59
  75. package/dist/core/history/identity.d.ts +15 -0
  76. package/dist/core/history/identity.js +31 -0
  77. package/dist/core/history/projection.js +50 -17
  78. package/dist/core/history/read.js +6 -3
  79. package/dist/core/history/replay.d.ts +1 -2
  80. package/dist/core/history/replay.js +70 -36
  81. package/dist/core/history/version-address.d.ts +13 -0
  82. package/dist/core/history/version-address.js +33 -0
  83. package/dist/core/item/actionability.d.ts +21 -1
  84. package/dist/core/item/actionability.js +45 -10
  85. package/dist/core/item/id.js +8 -4
  86. package/dist/core/item/item-type-definition.d.ts +2 -0
  87. package/dist/core/item/item-type-definition.js +9 -2
  88. package/dist/core/item/type-registry.d.ts +5 -1
  89. package/dist/core/item/type-registry.js +9 -4
  90. package/dist/core/lock/lock.d.ts +10 -0
  91. package/dist/core/lock/lock.js +42 -3
  92. package/dist/core/shared/author.d.ts +3 -1
  93. package/dist/core/shared/author.js +111 -23
  94. package/dist/core/shared/errors.d.ts +8 -0
  95. package/dist/core/shared/errors.js +2 -2
  96. package/dist/core/store/item-store.d.ts +14 -0
  97. package/dist/core/store/item-store.js +48 -10
  98. package/dist/core/store/settings-validator.js +3 -2
  99. package/dist/sdk/actionability.d.ts +1 -1
  100. package/dist/sdk/actionability.js +3 -3
  101. package/dist/sdk/cli-contracts/command-aliases.js +11 -2
  102. package/dist/sdk/cli-contracts/completeness.js +4 -3
  103. package/dist/sdk/cli-contracts/flag-contracts.js +29 -5
  104. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +19 -12
  105. package/dist/sdk/cli-contracts/tool-parameter-tables.js +14 -2
  106. package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
  107. package/dist/sdk/cli-contracts/tool-schema.js +19 -6
  108. package/dist/sdk/context-intent-contracts.js +3 -3
  109. package/dist/sdk/context-usage.js +9 -11
  110. package/dist/sdk/define.d.ts +1 -1
  111. package/dist/sdk/define.js +2 -2
  112. package/dist/sdk/environment/agent-environment.d.ts +296 -0
  113. package/dist/sdk/environment/agent-environment.js +467 -0
  114. package/dist/sdk/environment/project-runtime-compatibility.d.ts +19 -1
  115. package/dist/sdk/environment/project-runtime-compatibility.js +118 -21
  116. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +98 -38
  117. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +50 -2
  118. package/dist/sdk/governance/health.js +13 -44
  119. package/dist/sdk/governance/merge-receipt-history.d.ts +62 -0
  120. package/dist/sdk/governance/merge-receipt-history.js +207 -0
  121. package/dist/sdk/governance/provenance-health.js +9 -3
  122. package/dist/sdk/governance/validate-history-drift.js +16 -5
  123. package/dist/sdk/guide-topics.js +116 -2
  124. package/dist/sdk/history/salvage.d.ts +35 -0
  125. package/dist/sdk/history/salvage.js +248 -0
  126. package/dist/sdk/history-compact.js +41 -37
  127. package/dist/sdk/history-read.d.ts +3 -2
  128. package/dist/sdk/history-read.js +6 -3
  129. package/dist/sdk/history-redact.js +58 -23
  130. package/dist/sdk/history-repair.d.ts +5 -0
  131. package/dist/sdk/history-repair.js +28 -6
  132. package/dist/sdk/index.d.ts +2 -0
  133. package/dist/sdk/index.js +4 -2
  134. package/dist/sdk/lifecycle/claim.d.ts +4 -0
  135. package/dist/sdk/lifecycle/claim.js +9 -3
  136. package/dist/sdk/lifecycle/restore.d.ts +1 -0
  137. package/dist/sdk/lifecycle/restore.js +19 -7
  138. package/dist/sdk/merge/driver.d.ts +3 -1
  139. package/dist/sdk/merge/driver.js +9 -9
  140. package/dist/sdk/merge/index.d.ts +1 -1
  141. package/dist/sdk/merge/index.js +3 -3
  142. package/dist/sdk/merge/receipts.d.ts +17 -6
  143. package/dist/sdk/merge/receipts.js +246 -75
  144. package/dist/sdk/merge/reconcile.d.ts +9 -7
  145. package/dist/sdk/merge/reconcile.js +175 -12
  146. package/dist/sdk/merge/three-way.d.ts +22 -2
  147. package/dist/sdk/merge/three-way.js +92 -25
  148. package/dist/sdk/output-projection.d.ts +3 -1
  149. package/dist/sdk/output-projection.js +11 -3
  150. package/dist/sdk/public-surface.json +1 -0
  151. package/dist/sdk/query/context.d.ts +9 -0
  152. package/dist/sdk/query/context.js +33 -21
  153. package/dist/sdk/query/get.d.ts +2 -2
  154. package/dist/sdk/query/get.js +4 -3
  155. package/dist/sdk/query/history.d.ts +11 -0
  156. package/dist/sdk/query/history.js +34 -10
  157. package/dist/sdk/query/next.d.ts +15 -1
  158. package/dist/sdk/query/next.js +43 -20
  159. package/dist/sdk/query.d.ts +1 -0
  160. package/dist/sdk/query.js +3 -2
  161. package/dist/sdk/runtime-primitives.d.ts +3 -3
  162. package/dist/sdk/runtime-primitives.js +5 -5
  163. package/dist/types.d.ts +27 -0
  164. package/dist/types.js +2 -2
  165. package/docs/AGENT_ENVIRONMENTS.md +47 -0
  166. package/docs/AGENT_GUIDE.md +36 -0
  167. package/docs/AGENT_PROVENANCE_ADR.md +17 -2
  168. package/docs/CONTEXT_INTEGRITY_CONTRACTS.md +38 -1
  169. package/docs/HISTORY_RECOVERY.md +146 -0
  170. package/docs/MERGE_SAFETY.md +119 -23
  171. package/docs/README.md +2 -0
  172. package/docs/RELEASING.md +25 -11
  173. package/docs/SDK_CONTEXT_EVIDENCE_CONTRACTS.md +24 -2
  174. package/docs/SDK_CONTEXT_TRUTH_CONTRACTS.md +24 -1
  175. package/docs/SDK_EXECUTION_CONTRACTS.md +105 -0
  176. package/docs/SDK_RUNTIME_BOUNDARIES.md +17 -1
  177. package/docs/TESTING.md +5 -0
  178. package/docs/agent-task-token-baseline.json +17 -17
  179. package/docs/agent-task-transcripts.json +2 -1
  180. package/docs/examples/sdk-agent-environment/README.md +14 -0
  181. package/docs/examples/sdk-agent-environment/package.json +8 -0
  182. package/docs/examples/sdk-agent-environment/run-agent-environment.mjs +154 -0
  183. package/docs/generated/FLAG_LEXICON_BUDGETS.md +10 -10
  184. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +12 -3
  185. package/marketplace.json +2 -2
  186. package/package.json +5 -6
  187. package/packages/pm-beads/package.json +1 -1
  188. package/packages/pm-calendar/package.json +1 -1
  189. package/packages/pm-command-kit/package.json +1 -1
  190. package/packages/pm-digital-twin/package.json +1 -1
  191. package/packages/pm-governance-audit/package.json +1 -1
  192. package/packages/pm-guide-shell/package.json +1 -1
  193. package/packages/pm-kanban/package.json +1 -1
  194. package/packages/pm-lifecycle-hooks/package.json +1 -1
  195. package/packages/pm-linked-test-adapters/package.json +1 -1
  196. package/packages/pm-search-advanced/package.json +1 -1
  197. package/packages/pm-templates/package.json +1 -1
  198. package/packages/pm-todos/package.json +1 -1
  199. package/packages/pm-vcs/package.json +1 -1
  200. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  201. package/plugins/pm-claude/skills/pm-audit/SKILL.md +2 -2
  202. package/plugins/pm-claude/skills/pm-developer/SKILL.md +2 -2
  203. package/plugins/pm-claude/skills/pm-planner/SKILL.md +2 -2
  204. package/plugins/pm-claude/skills/pm-release/SKILL.md +2 -2
  205. package/plugins/pm-claude/skills/pm-workflow/SKILL.md +3 -3
  206. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  207. package/plugins/pm-codex/skills/pm-auditor/SKILL.md +2 -2
  208. package/plugins/pm-codex/skills/pm-native/SKILL.md +3 -4
  209. package/plugins/pm-codex/skills/pm-release/SKILL.md +2 -2
  210. package/scripts/finalize-build.mjs +13 -1
  211. package/dist/cli-bundle/chunks/chunk-AY324UJ5.js +0 -9
  212. package/dist/cli-bundle/chunks/chunk-E5RBBCXO.js +0 -230
  213. package/dist/cli-bundle/chunks/chunk-IEHHE6GA.js +0 -5
  214. package/dist/cli-bundle/chunks/chunk-L7B7343B.js +0 -8
  215. package/dist/cli-bundle/chunks/chunk-LISESA7W.js +0 -35
  216. package/dist/cli-bundle/chunks/register-operations-TTROIVC4.js +0 -2
  217. package/dist/cli-bundle/focused-chunks/chunk-3ZBI35HU.js +0 -176
  218. package/dist/cli-bundle/focused-chunks/chunk-4RRHC3S4.js +0 -6
  219. package/dist/cli-bundle/focused-chunks/chunk-4WR46RMG.js +0 -9
  220. package/dist/cli-bundle/focused-chunks/chunk-BWKHEIVF.js +0 -2
  221. package/dist/cli-bundle/focused-chunks/chunk-GHCZ3YFR.js +0 -20
  222. package/dist/cli-bundle/focused-chunks/chunk-KBLZRU62.js +0 -2
  223. package/dist/cli-bundle/focused-chunks/chunk-KZ2NB3ET.js +0 -2
  224. package/dist/cli-bundle/focused-chunks/chunk-OL5EH6I3.js +0 -2
  225. package/dist/cli-bundle/focused-chunks/chunk-QKHCSUGJ.js +0 -51
  226. package/dist/cli-bundle/focused-chunks/chunk-TXE4TSHM.js +0 -12
  227. package/dist/cli-bundle/focused-chunks/chunk-UCLO3XDU.js +0 -2
  228. package/sdk/public-surface.json +0 -32524
@@ -38,6 +38,8 @@ export interface NormalizeItemTypeDefinitionOptions {
38
38
  /** How to resolve a raw policy `command` value (defaults to {@link keepPolicyCommand}). */
39
39
  resolvePolicyCommand?: ResolvePolicyCommand;
40
40
  }
41
+ /** Validate an execution role before a settings or extension definition enters scheduling. Unknown values fail instead of silently enabling dispatch. */
42
+ export declare function parseItemExecutionRole(value: unknown): ItemTypeDefinition["execution_role"];
41
43
  /**
42
44
  * Normalize a full {@link ItemTypeDefinition}, returning null when the name is blank.
43
45
  *
@@ -15,7 +15,7 @@
15
15
  */
16
16
  /** Dedupe + sort a string list: trim, drop blanks, unique, locale-sorted. */
17
17
 
18
- !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]="815165a9-27a7-5933-adae-c7e55330c8e4")}catch(e){}}();
18
+ !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]="f02cb2e7-2d5f-5cc8-8a60-18db78b50da0")}catch(e){}}();
19
19
  export function normalizeItemTypeStringList(values) {
20
20
  return [
21
21
  ...new Set((values ?? [])
@@ -85,6 +85,12 @@ function optionalNonEmptyString(value) {
85
85
  const normalized = value?.trim();
86
86
  return normalized && normalized.length > 0 ? normalized : undefined;
87
87
  }
88
+ /** Validate an execution role before a settings or extension definition enters scheduling. Unknown values fail instead of silently enabling dispatch. */
89
+ export function parseItemExecutionRole(value) {
90
+ if (value === undefined || value === "agent" || value === "human" || value === "gate")
91
+ return value;
92
+ throw new Error("Item type execution_role must be agent, human, or gate.");
93
+ }
88
94
  /**
89
95
  * Normalize a full {@link ItemTypeDefinition}, returning null when the name is blank.
90
96
  *
@@ -113,6 +119,7 @@ export function normalizeItemTypeDefinition(definition, options = {}) {
113
119
  name,
114
120
  description: optionalNonEmptyString(definition.description),
115
121
  default_status: optionalNonEmptyString(definition.default_status),
122
+ ...(definition.execution_role === undefined ? {} : { execution_role: parseItemExecutionRole(definition.execution_role) }),
116
123
  folder: optionalNonEmptyString(definition.folder),
117
124
  aliases: aliases.length > 0 ? aliases : undefined,
118
125
  required_create_fields: normalizeOptionalStringList(definition.required_create_fields, hasRequiredCreateFields),
@@ -124,4 +131,4 @@ export function normalizeItemTypeDefinition(definition, options = {}) {
124
131
  };
125
132
  }
126
133
  //# sourceMappingURL=item-type-definition.js.map
127
- //# debugId=815165a9-27a7-5933-adae-c7e55330c8e4
134
+ //# debugId=f02cb2e7-2d5f-5cc8-8a60-18db78b50da0
@@ -1,5 +1,7 @@
1
1
  import type { ExtensionRegistrationRegistry } from "../extensions/loader.js";
2
- import type { ItemTypeCommandOptionPolicy, ItemTypeOptionDefinition, PmSettings } from "../../types/index.js";
2
+ import type { ItemTypeCommandOptionPolicy, ItemTypeDefinition, ItemTypeOptionDefinition, PmSettings } from "../../types/index.js";
3
+ /** Default dispatch roles for built-in types whose work requires human input or outcome verification. Custom definitions can override these through the same registry. */
4
+ export declare const BUILTIN_ITEM_EXECUTION_ROLES: Readonly<Record<string, "human" | "gate">>;
3
5
  /** Fallback required create fields used when callers do not provide an override. */
4
6
  export declare const DEFAULT_REQUIRED_CREATE_FIELDS: readonly ["title", "description", "status", "priority", "tags", "body", "deadline", "estimatedMinutes", "acceptanceCriteria", "author", "message", "assignee"];
5
7
  /** Fallback required create repeatables used when callers do not provide an override. */
@@ -31,6 +33,8 @@ export interface ResolvedItemTypeDefinition {
31
33
  aliases: string[];
32
34
  /** Optional per-type status applied at create time when `--status` is omitted. */
33
35
  default_status?: string;
36
+ /** Effective dispatch role; absent legacy definitions are resolved through the built-in defaults. */
37
+ execution_role?: ItemTypeDefinition["execution_role"];
34
38
  /** Value that configures or reports required create fields for this contract. */
35
39
  required_create_fields: string[];
36
40
  /** Value that configures or reports required create repeatables for this contract. */
@@ -4,11 +4,13 @@
4
4
  * Defines item parsing, formatting, and lifecycle helpers for Type Registry.
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]="88b2ed4e-b5fd-5014-abf1-c163db033abf")}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]="506efdc7-b04e-5023-ab59-57ede87558f9")}catch(e){}}();
8
8
  import path from "node:path";
9
9
  import { TYPE_TO_FOLDER } from "../shared/constants.js";
10
10
  import { ITEM_TYPE_VALUES } from "../../types/index.js";
11
- import { normalizeItemTypeDefinition as normalizeSharedItemTypeDefinition, normalizeItemTypeStringList, strictPolicyCommand, } from "./item-type-definition.js";
11
+ import { normalizeItemTypeDefinition as normalizeSharedItemTypeDefinition, normalizeItemTypeStringList, strictPolicyCommand, parseItemExecutionRole, } from "./item-type-definition.js";
12
+ /** Default dispatch roles for built-in types whose work requires human input or outcome verification. Custom definitions can override these through the same registry. */
13
+ export const BUILTIN_ITEM_EXECUTION_ROLES = Object.freeze({ decision: "human", milestone: "gate" });
12
14
  /** Fallback required create fields used when callers do not provide an override. */
13
15
  export const DEFAULT_REQUIRED_CREATE_FIELDS = [
14
16
  "title",
@@ -421,6 +423,7 @@ function coerceTypeDefinitionFromUnknown(raw) {
421
423
  name,
422
424
  description,
423
425
  default_status: defaultStatus,
426
+ execution_role: parseItemExecutionRole(record.execution_role),
424
427
  folder,
425
428
  aliases: readStringArray(record, "aliases"),
426
429
  required_create_fields: readStringArray(record, "required_create_fields"),
@@ -462,6 +465,7 @@ function buildResolvedTypeDefinition(normalizedDefinition, existing) {
462
465
  toDefaultFolder(keepName));
463
466
  const resolvedDefinition = {
464
467
  name: keepName,
468
+ execution_role: normalizedDefinition.execution_role,
465
469
  folder,
466
470
  aliases: normalizeItemTypeStringList([
467
471
  ...(existing?.aliases ?? []),
@@ -488,7 +492,7 @@ function applyTypeDefinitions(source, target) {
488
492
  }
489
493
  const lowerName = normalizedDefinition.name.toLowerCase();
490
494
  const existing = target.get(lowerName);
491
- target.set(lowerName, buildResolvedTypeDefinition(normalizedDefinition, existing));
495
+ target.set(lowerName, buildResolvedTypeDefinition({ ...normalizedDefinition, execution_role: normalizedDefinition.execution_role ?? existing?.execution_role }, existing));
492
496
  }
493
497
  }
494
498
  function collectExtensionTypeDefinitions(registrations) {
@@ -516,6 +520,7 @@ export function resolveItemTypeRegistry(settings, extensionRegistrations = null)
516
520
  for (const builtin of ITEM_TYPE_VALUES) {
517
521
  byLowerName.set(builtin.toLowerCase(), {
518
522
  name: builtin,
523
+ execution_role: BUILTIN_ITEM_EXECUTION_ROLES[builtin.toLowerCase()] ?? "agent",
519
524
  folder: TYPE_TO_FOLDER[builtin],
520
525
  aliases: [],
521
526
  required_create_fields: [...DEFAULT_REQUIRED_CREATE_FIELDS],
@@ -708,4 +713,4 @@ export function validateTypeOptions(typeName, rawTypeOptions, registry) {
708
713
  };
709
714
  }
710
715
  //# sourceMappingURL=type-registry.js.map
711
- //# debugId=88b2ed4e-b5fd-5014-abf1-c163db033abf
716
+ //# debugId=506efdc7-b04e-5023-ab59-57ede87558f9
@@ -25,6 +25,15 @@ export interface ProcessIdentity {
25
25
  declare function parseLockInfo(raw: string): LockReadResult;
26
26
  declare function readLockInfo(lockPath: string, emitReadHook?: boolean): Promise<LockReadResult>;
27
27
  declare function isErrno(error: unknown, code: string): boolean;
28
+ /**
29
+ * Classify exclusive-create failures that prove another lock lifecycle is in
30
+ * flight. Windows can report `EPERM`, `EACCES`, or `EBUSY` while a just-unlinked
31
+ * lock is still delete-pending; treating those as fatal makes bounded lock
32
+ * waiting fail nondeterministically. Existing paths are contention on every
33
+ * host. A missing or temporarily unstatable Windows path is contention only
34
+ * when its parent remains writable, preserving genuine permission failures.
35
+ */
36
+ declare function isLockCreateContention(error: unknown, lockPath: string, platform?: NodeJS.Platform): Promise<boolean>;
28
37
  declare function buildLockPayload(id: string, owner: string, ttlSeconds: number, token?: string): LockInfo;
29
38
  declare function isStaleLock(info: LockInfo | null, ttlSeconds: number): boolean;
30
39
  declare function lockOwnerSuffix(info: LockInfo | null): string;
@@ -57,6 +66,7 @@ export declare const _testOnly: {
57
66
  parseLockInfo: typeof parseLockInfo;
58
67
  readLockInfo: typeof readLockInfo;
59
68
  isErrno: typeof isErrno;
69
+ isLockCreateContention: typeof isLockCreateContention;
60
70
  buildLockPayload: typeof buildLockPayload;
61
71
  isStaleLock: typeof isStaleLock;
62
72
  lockOwnerSuffix: typeof lockOwnerSuffix;
@@ -4,8 +4,9 @@
4
4
  * Coordinates tracker lock ownership and cleanup for Lock.
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]="7352375d-55f2-5751-934e-ba0cd5c358d5")}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]="b21a63b8-9da9-5c7c-b288-3a2dae342bef")}catch(e){}}();
8
8
  import { isFileMissingError } from "../fs/fs-utils.js";
9
+ import { constants as fsConstants } from "node:fs";
9
10
  import fs from "node:fs/promises";
10
11
  import path from "node:path";
11
12
  import { randomUUID } from "node:crypto";
@@ -95,6 +96,43 @@ function isErrno(error, code) {
95
96
  "code" in error &&
96
97
  error.code === code);
97
98
  }
99
+ /**
100
+ * Classify exclusive-create failures that prove another lock lifecycle is in
101
+ * flight. Windows can report `EPERM`, `EACCES`, or `EBUSY` while a just-unlinked
102
+ * lock is still delete-pending; treating those as fatal makes bounded lock
103
+ * waiting fail nondeterministically. Existing paths are contention on every
104
+ * host. A missing or temporarily unstatable Windows path is contention only
105
+ * when its parent remains writable, preserving genuine permission failures.
106
+ */
107
+ async function isLockCreateContention(error, lockPath, platform = process.platform) {
108
+ if (isErrno(error, "EEXIST"))
109
+ return true;
110
+ if (!isErrno(error, "EPERM") &&
111
+ !isErrno(error, "EACCES") &&
112
+ !isErrno(error, "EBUSY")) {
113
+ return false;
114
+ }
115
+ try {
116
+ await fs.lstat(lockPath);
117
+ return true;
118
+ }
119
+ catch (probeError) {
120
+ if (platform !== "win32" ||
121
+ (!isFileMissingError(probeError) &&
122
+ !isErrno(probeError, "EPERM") &&
123
+ !isErrno(probeError, "EACCES") &&
124
+ !isErrno(probeError, "EBUSY"))) {
125
+ return false;
126
+ }
127
+ }
128
+ try {
129
+ await fs.access(path.dirname(lockPath), fsConstants.W_OK);
130
+ return true;
131
+ }
132
+ catch {
133
+ return false;
134
+ }
135
+ }
98
136
  async function emitLockWriteHook(lockPath, op) {
99
137
  await runActiveOnWriteHooks({
100
138
  path: lockPath,
@@ -464,6 +502,7 @@ export const _testOnly = {
464
502
  parseLockInfo,
465
503
  readLockInfo,
466
504
  isErrno,
505
+ isLockCreateContention,
467
506
  buildLockPayload,
468
507
  isStaleLock,
469
508
  lockOwnerSuffix,
@@ -515,7 +554,7 @@ export async function acquireLock(pmRoot, id, ttlSeconds, owner, force = false,
515
554
  };
516
555
  }
517
556
  catch (error) {
518
- if (!isErrno(error, "EEXIST")) {
557
+ if (!(await isLockCreateContention(error, lockPath))) {
519
558
  throw new PmCliError(`Failed to acquire lock for ${id}: ${toErrorMessage(error)}`, EXIT_CODE.GENERIC_FAILURE);
520
559
  }
521
560
  let lockInfo = await readLockInfo(lockPath);
@@ -549,4 +588,4 @@ export async function acquireLock(pmRoot, id, ttlSeconds, owner, force = false,
549
588
  }
550
589
  }
551
590
  //# sourceMappingURL=lock.js.map
552
- //# debugId=7352375d-55f2-5751-934e-ba0cd5c358d5
591
+ //# debugId=b21a63b8-9da9-5c7c-b288-3a2dae342bef
@@ -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
@@ -53,6 +53,14 @@ export interface PmCliErrorRecoveryPayload {
53
53
  export interface PmCliErrorContext {
54
54
  /** Value that configures or reports code for this contract. */
55
55
  code?: string;
56
+ /** Item whose document could not be decoded or parsed. */
57
+ item_id?: string;
58
+ /** Exact filesystem path of the unreadable item document. */
59
+ item_path?: string;
60
+ /** Original document size before decoding or parsing. */
61
+ byte_length?: number;
62
+ /** Whether the original item document contained no bytes. */
63
+ empty?: boolean;
56
64
  /** Stable failure class within the operation-specific error code. */
57
65
  reason?: string;
58
66
  /** Metadata field responsible for a validation failure, when known. */
@@ -1,6 +1,6 @@
1
1
  /** Implements the exported pm cli error runtime abstraction for core/shared/errors.ts. */
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]="922e2e27-1499-5466-98e4-322d0d742e40")}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]="9ab4b378-900c-5a2a-9237-b1d8d4f2ae13")}catch(e){}}();
4
4
  export class PmCliError extends Error {
5
5
  /** Value that configures or reports exit code for this contract. */
6
6
  exitCode;
@@ -18,4 +18,4 @@ export class PmCliError extends Error {
18
18
  }
19
19
  }
20
20
  //# sourceMappingURL=errors.js.map
21
- //# debugId=922e2e27-1499-5466-98e4-322d0d742e40
21
+ //# debugId=9ab4b378-900c-5a2a-9237-b1d8d4f2ae13
@@ -25,6 +25,20 @@ export declare function readLocatedItem(item: LocatedItem, options?: {
25
25
  raw: string;
26
26
  document: ItemDocument;
27
27
  }>;
28
+ /**
29
+ * Read once and retain a recoverable parse failure beside its exact text snapshot.
30
+ * Filesystem and merge-conflict errors still throw; callers must explicitly
31
+ * reconstruct an invalid document before performing any mutation.
32
+ */
33
+ export declare function readLocatedItemSnapshot(item: LocatedItem, options?: Parameters<typeof readLocatedItem>[1]): Promise<{
34
+ raw: string;
35
+ document: ItemDocument;
36
+ error: null;
37
+ } | {
38
+ raw: string;
39
+ document: null;
40
+ error: PmCliError;
41
+ }>;
28
42
  /** Implements list all item metadata for the public runtime surface of this module. */
29
43
  export declare function listAllItemMetadata(pmRoot: string, preferredFormat?: ItemFormat, typeToFolder?: Record<string, string>, warnings?: string[], schema?: RuntimeSchemaSettings): Promise<ItemMetadata[]>;
30
44
  /**
@@ -4,7 +4,7 @@
4
4
  * Reads and writes tracker storage with format-aware helpers for Item Store.
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]="bffd3114-3e85-58ae-90c7-eea5069cdb89")}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]="c3390c01-c153-5baa-b9bd-07ea8d34828f")}catch(e){}}();
8
8
  import fs from "node:fs/promises";
9
9
  import path from "node:path";
10
10
  import { getActiveExtensionRegistrations, projectAfterCommandItemSnapshot, recordAfterCommandAffectedItem, runActiveOnReadHooks, runActiveBeforeMutationHooks, runActiveOnWriteHooks, runActiveServiceOverride, } from "../extensions/index.js";
@@ -18,6 +18,7 @@ import { canonicalDocument, parseItemDocument, serializeItemDocument, } from "..
18
18
  import { resolveItemTypeRegistry } from "../item/type-registry.js";
19
19
  import { acquireLock } from "../lock/lock.js";
20
20
  import { writeFileAtomic } from "../fs/fs-utils.js";
21
+ import { isUtf8 } from "node:buffer";
21
22
  import { normalizeItemId, normalizeRawItemId } from "../item/id.js";
22
23
  import { acquireItemMetadataDerivedIndexLock, listAllDocumentCandidatesCached, listAllDocumentsCached, listAllDocumentsCachedLight, refreshItemMetadataDerivedIndex, } from "./item-metadata-cache.js";
23
24
  import { getHistoryPath, getItemPath, ITEM_FILE_EXTENSIONS } from "./paths.js";
@@ -96,18 +97,55 @@ export async function locateItem(pmRoot, rawId, idPrefix = "pm-", preferredForma
96
97
  }
97
98
  /** Implements read located item for the public runtime surface of this module. */
98
99
  export async function readLocatedItem(item, options = {}) {
99
- const raw = await fs.readFile(item.itemPath, "utf8");
100
+ const snapshot = await readLocatedItemSnapshot(item, options);
101
+ if (snapshot.error !== null)
102
+ throw snapshot.error;
103
+ return { raw: snapshot.raw, document: snapshot.document };
104
+ }
105
+ /**
106
+ * Read once and retain a recoverable parse failure beside its exact text snapshot.
107
+ * Filesystem and merge-conflict errors still throw; callers must explicitly
108
+ * reconstruct an invalid document before performing any mutation.
109
+ */
110
+ export async function readLocatedItemSnapshot(item, options = {}) {
111
+ const bytes = await fs.readFile(item.itemPath);
112
+ if (!isUtf8(bytes)) {
113
+ throw new PmCliError("Item contains invalid UTF-8; preserve a binary backup before recovering it.", EXIT_CODE.CONFLICT, { code: "item_document_encoding_invalid", item_id: item.id, item_path: item.itemPath, byte_length: bytes.length, empty: false });
114
+ }
115
+ const raw = bytes.toString("utf8");
100
116
  await runActiveOnReadHooks({
101
117
  path: item.itemPath,
102
118
  scope: "project",
103
119
  });
104
- const document = parseItemDocument(raw, {
105
- format: item.item_format,
106
- schema: options.schema,
107
- extensionFieldNames: resolveActiveExtensionFieldNames(options.extensionFieldNames),
108
- onWarning: (warning) => appendWarning(options.warnings, warning),
109
- });
110
- return { raw, document };
120
+ let document;
121
+ try {
122
+ document = parseItemDocument(raw, {
123
+ format: item.item_format,
124
+ schema: options.schema,
125
+ extensionFieldNames: resolveActiveExtensionFieldNames(options.extensionFieldNames),
126
+ onWarning: (warning) => appendWarning(options.warnings, warning),
127
+ });
128
+ }
129
+ catch (error) {
130
+ if (error instanceof PmCliError && error.code === "item_document_invalid") {
131
+ return {
132
+ raw,
133
+ document: null,
134
+ error: new PmCliError(`Cannot read ${item.id} at ${item.itemPath}${bytes.length === 0 ? " (zero-length file)" : ""}: ${error.message}`, error.exitCode, {
135
+ ...error.context,
136
+ item_id: item.id,
137
+ item_path: item.itemPath,
138
+ byte_length: bytes.length,
139
+ empty: bytes.length === 0,
140
+ nextSteps: [
141
+ `Run pm history ${item.id} --full, then pm restore ${item.id} <version> to recover a recorded state.`,
142
+ ],
143
+ }),
144
+ };
145
+ }
146
+ throw error;
147
+ }
148
+ return { raw, document, error: null };
111
149
  }
112
150
  /** Implements list all item metadata for the public runtime surface of this module. */
113
151
  export async function listAllItemMetadata(pmRoot, preferredFormat, typeToFolder = TYPE_TO_FOLDER, warnings, schema) {
@@ -649,4 +687,4 @@ export async function deleteItem(params) {
649
687
  }
650
688
  }
651
689
  //# sourceMappingURL=item-store.js.map
652
- //# debugId=bffd3114-3e85-58ae-90c7-eea5069cdb89
690
+ //# debugId=c3390c01-c153-5baa-b9bd-07ea8d34828f
@@ -12,7 +12,7 @@
12
12
  * byte-identical to the previous implementation.
13
13
  */
14
14
 
15
- !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]="0e135793-d2ed-505b-b73e-6db55218d8af")}catch(e){}}();
15
+ !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]="c9cac741-16ba-5466-806f-bf8881a2ffa2")}catch(e){}}();
16
16
  import { GOVERNANCE_PRESET_VALUES, RUNTIME_FIELD_COMMAND_VALUES, RUNTIME_FIELD_TYPE_VALUES, RUNTIME_STATUS_ROLE_VALUES, RUNTIME_UNKNOWN_FIELD_POLICY_VALUES, } from "../../types.js";
17
17
  // Generic over `never` so it is assignable to every `Outcome<T>`.
18
18
  const FAIL = { ok: false };
@@ -137,6 +137,7 @@ const itemTypeDefinition = vObject({
137
137
  // Per-type create-time default status (config-driven); preserved so inline
138
138
  // settings.item_types.definitions behave identically to schema/types.json.
139
139
  default_status: vOptional(vString),
140
+ execution_role: vOptional(vLiteral("agent", "human", "gate")),
140
141
  folder: vOptional(vString),
141
142
  aliases: vOptional(vArray(vString)),
142
143
  required_create_fields: vOptional(vArray(vString)),
@@ -418,4 +419,4 @@ export function validateSettings(raw) {
418
419
  return { success: true, data: result.value };
419
420
  }
420
421
  //# sourceMappingURL=settings-validator.js.map
421
- //# debugId=0e135793-d2ed-505b-b73e-6db55218d8af
422
+ //# debugId=c9cac741-16ba-5466-806f-bf8881a2ffa2
@@ -7,4 +7,4 @@
7
7
  * blocker or ready-work classifications without storage or rendering side
8
8
  * effects.
9
9
  */
10
- export { ACTIONABILITY_ORDERING_KINDS, collectBlockedByIds, collectBlockedByIdsFromCorpus, collectDependencyBlockedIds, computeActionabilityReport, indexBlockedByIds, resolveItemBlockers, type ActionabilityReport, type ActionableEntry, type ResolvedBlocker, } from "../core/item/actionability.js";
10
+ export { ACTIONABILITY_ORDERING_KINDS, collectBlockedByIds, collectBlockedByIdsFromCorpus, collectDependencyBlockedIds, computeActionabilityReport, indexBlockedByIds, resolveItemBlockers, resolveItemExecutionRole, selectActionableEntries, type ActionabilitySelectionOptions, type ActionabilityReport, type ActionableEntry, type ResolvedBlocker, } from "../core/item/actionability.js";
@@ -8,7 +8,7 @@
8
8
  * effects.
9
9
  */
10
10
 
11
- !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]="cc271a73-9767-54bb-a142-d4d4569e3c6a")}catch(e){}}();
12
- export { ACTIONABILITY_ORDERING_KINDS, collectBlockedByIds, collectBlockedByIdsFromCorpus, collectDependencyBlockedIds, computeActionabilityReport, indexBlockedByIds, resolveItemBlockers, } from "../core/item/actionability.js";
11
+ !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]="7d393eb0-d24d-55d2-8e4e-e94805d91784")}catch(e){}}();
12
+ export { ACTIONABILITY_ORDERING_KINDS, collectBlockedByIds, collectBlockedByIdsFromCorpus, collectDependencyBlockedIds, computeActionabilityReport, indexBlockedByIds, resolveItemBlockers, resolveItemExecutionRole, selectActionableEntries, } from "../core/item/actionability.js";
13
13
  //# sourceMappingURL=actionability.js.map
14
- //# debugId=cc271a73-9767-54bb-a142-d4d4569e3c6a
14
+ //# debugId=7d393eb0-d24d-55d2-8e4e-e94805d91784