@unbrained/pm-cli 2026.10.15 → 2026.10.18

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 (275) hide show
  1. package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +1 -1
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/AGENTS.md +1 -0
  4. package/CHANGELOG.md +45 -0
  5. package/dist/cli/extension-command-options.d.ts +3 -1
  6. package/dist/cli/extension-command-options.js +1 -1
  7. package/dist/cli/help-content.js +2 -2
  8. package/dist/cli/register-list-query.js +2 -2
  9. package/dist/cli/register-mutation.js +2 -2
  10. package/dist/cli/register-operations.js +1 -1
  11. package/dist/cli/register-structured-mutation.d.ts +0 -5
  12. package/dist/cli/register-structured-mutation.js +1 -1
  13. package/dist/cli/runtime/invocation-options.js +1 -1
  14. package/dist/cli-bundle/bundle-manifest.json +1 -1
  15. package/dist/cli-bundle/chunks/{chunk-7VHINXZP.js → chunk-4GA4MUTE.js} +2 -2
  16. package/dist/cli-bundle/chunks/{chunk-RJ5N44WY.js → chunk-4V6ONLI6.js} +2 -2
  17. package/dist/cli-bundle/chunks/{chunk-LNKLQYBG.js → chunk-6VZKYJW7.js} +2 -2
  18. package/dist/cli-bundle/chunks/chunk-7PATQWTH.js +20 -0
  19. package/dist/cli-bundle/chunks/chunk-7WIEAGDS.js +2 -0
  20. package/dist/cli-bundle/chunks/{chunk-52EZH2QQ.js → chunk-AETP4JEM.js} +2 -2
  21. package/dist/cli-bundle/chunks/{chunk-WBBW3WQX.js → chunk-FIJOSX2C.js} +28 -28
  22. package/dist/cli-bundle/chunks/chunk-LUKVNL72.js +2 -0
  23. package/dist/cli-bundle/chunks/{chunk-NC3QVGDD.js → chunk-OJ77ZQN3.js} +2 -2
  24. package/dist/cli-bundle/chunks/chunk-PYRREEUB.js +30 -0
  25. package/dist/cli-bundle/chunks/chunk-RHQJ6VWC.js +237 -0
  26. package/dist/cli-bundle/chunks/{chunk-N56CAQBU.js → chunk-RNABUEFB.js} +52 -52
  27. package/dist/cli-bundle/chunks/chunk-TO6CIV4C.js +2 -0
  28. package/dist/cli-bundle/chunks/{chunk-JGKTOBVB.js → chunk-ZZED447K.js} +4 -4
  29. package/dist/cli-bundle/chunks/{register-list-query-FKKFQ66D.js → register-list-query-PUCVYYBD.js} +7 -7
  30. package/dist/cli-bundle/chunks/register-mutation-GGGVBXD5.js +20 -0
  31. package/dist/cli-bundle/chunks/{register-operations-GEQ2H7PS.js → register-operations-NRZ6Q4QE.js} +2 -2
  32. package/dist/cli-bundle/chunks/{register-setup-PSJTQBBO.js → register-setup-MV3P3YSF.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/chunk-2MPQUMTF.js +2 -0
  34. package/dist/cli-bundle/focused-chunks/{chunk-H3P77KVU.js → chunk-5UKCSZWT.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/{chunk-4KQFMOM7.js → chunk-A4ZHHTEX.js} +5 -5
  36. package/dist/cli-bundle/focused-chunks/{chunk-5OO54BIV.js → chunk-B4YLP5ZB.js} +3 -3
  37. package/dist/cli-bundle/focused-chunks/chunk-BFEMT5U3.js +20 -0
  38. package/dist/cli-bundle/focused-chunks/{chunk-THYQR3ON.js → chunk-FW7CSSKL.js} +61 -61
  39. package/dist/cli-bundle/focused-chunks/{chunk-3RNUMVK4.js → chunk-HYPRPSYD.js} +2 -2
  40. package/dist/cli-bundle/focused-chunks/{chunk-FQKPOZKS.js → chunk-IRVL4UXR.js} +2 -2
  41. package/dist/cli-bundle/focused-chunks/{chunk-Q4VNCTR2.js → chunk-L55KQ2KT.js} +2 -2
  42. package/dist/cli-bundle/focused-chunks/{chunk-52I2SNKJ.js → chunk-MASIOFPG.js} +2 -2
  43. package/dist/cli-bundle/focused-chunks/chunk-RJ3EIHDU.js +26 -0
  44. package/dist/cli-bundle/focused-chunks/chunk-SEL4Z2OO.js +167 -0
  45. package/dist/cli-bundle/focused-chunks/{chunk-TYLG5VEB.js → chunk-TB7F4FCR.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/{chunk-KIIFVULU.js → chunk-TZUIBG3P.js} +2 -2
  47. package/dist/cli-bundle/focused-chunks/{chunk-N6FUKTZS.js → chunk-Z7YIFCNE.js} +2 -2
  48. package/dist/cli-bundle/focused-chunks/{chunk-5KRACGBK.js → chunk-ZDBS2DCT.js} +3 -3
  49. package/dist/cli-bundle/main.js +27 -27
  50. package/dist/cli-bundle/sdk-authoring.js +1 -1
  51. package/dist/cli-bundle/sdk-contracts.js +2 -2
  52. package/dist/cli-bundle/sdk-core.js +23 -23
  53. package/dist/cli-bundle/sdk-governance.js +1 -1
  54. package/dist/cli-bundle/sdk-graph.js +1 -1
  55. package/dist/cli-bundle/sdk-merge.js +55 -54
  56. package/dist/cli-bundle/sdk-query.js +1 -1
  57. package/dist/cli-bundle/sdk-runtime.js +1 -1
  58. package/dist/cli-bundle/sdk-testing.js +1 -1
  59. package/dist/cli-bundle/sdk.js +7 -7
  60. package/dist/core/extensions/extension-types.d.ts +15 -0
  61. package/dist/core/extensions/extension-types.js +1 -1
  62. package/dist/core/extensions/flag-value-types.d.ts +16 -0
  63. package/dist/core/extensions/flag-value-types.js +1 -1
  64. package/dist/core/extensions/registration-contracts.js +1 -1
  65. package/dist/core/history/event-index.d.ts +8 -1
  66. package/dist/core/history/event-index.js +19 -18
  67. package/dist/core/item/item-format.js +3 -3
  68. package/dist/core/lock/lock.d.ts +8 -1
  69. package/dist/core/lock/lock.js +3 -3
  70. package/dist/core/output/mutation-projection.d.ts +0 -21
  71. package/dist/core/output/mutation-projection.js +1 -1
  72. package/dist/core/output/output.js +2 -2
  73. package/dist/core/schema/type-workflows.d.ts +1 -1
  74. package/dist/core/schema/type-workflows.js +1 -1
  75. package/dist/core/shared/text-normalization.d.ts +2 -0
  76. package/dist/core/shared/text-normalization.js +1 -1
  77. package/dist/core/store/item-mutation-precondition.d.ts +11 -0
  78. package/dist/core/store/item-mutation-precondition.js +2 -0
  79. package/dist/core/store/item-store.js +1 -1
  80. package/dist/core/store/paths.js +1 -1
  81. package/dist/core/telemetry/policy.d.ts +2 -0
  82. package/dist/core/telemetry/policy.js +1 -1
  83. package/dist/core/telemetry/runtime.d.ts +5 -3
  84. package/dist/core/telemetry/runtime.js +3 -3
  85. package/dist/mcp/server.js +1 -1
  86. package/dist/mcp/tool-definitions.js +1 -1
  87. package/dist/sdk/cli-contracts/agent-output-contracts.js +1 -1
  88. package/dist/sdk/cli-contracts/flag-contracts.js +1 -1
  89. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -1
  90. package/dist/sdk/cli-contracts/registration-helpers.d.ts +1 -1
  91. package/dist/sdk/cli-contracts/registration-helpers.js +1 -1
  92. package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
  93. package/dist/sdk/cli-contracts/tool-schema.js +1 -1
  94. package/dist/sdk/context-intent-contracts.js +1 -1
  95. package/dist/sdk/core.d.ts +2 -1
  96. package/dist/sdk/core.js +1 -1
  97. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
  98. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
  99. package/dist/sdk/governance/health/projection.d.ts +37 -0
  100. package/dist/sdk/governance/health/projection.js +2 -0
  101. package/dist/sdk/governance/health.d.ts +7 -18
  102. package/dist/sdk/governance/health.js +2 -2
  103. package/dist/sdk/guide-topics.js +1 -1
  104. package/dist/sdk/index.d.ts +2 -1
  105. package/dist/sdk/index.js +1 -1
  106. package/dist/sdk/item-transaction.d.ts +72 -9
  107. package/dist/sdk/item-transaction.js +1 -1
  108. package/dist/sdk/lifecycle/claim.d.ts +15 -1
  109. package/dist/sdk/lifecycle/claim.js +1 -1
  110. package/dist/sdk/lifecycle/close.d.ts +2 -8
  111. package/dist/sdk/lifecycle/close.js +1 -1
  112. package/dist/sdk/lifecycle/core-item-fields.d.ts +6 -0
  113. package/dist/sdk/lifecycle/core-item-fields.js +2 -0
  114. package/dist/sdk/lifecycle/mcp-actions.js +1 -1
  115. package/dist/sdk/lifecycle/mutation-option-validation.d.ts +2 -0
  116. package/dist/sdk/lifecycle/mutation-option-validation.js +2 -0
  117. package/dist/sdk/lifecycle/release-handoff.d.ts +12 -0
  118. package/dist/sdk/lifecycle/release-handoff.js +2 -0
  119. package/dist/sdk/lifecycle/structured-mutation-plan.d.ts +33 -0
  120. package/dist/sdk/lifecycle/structured-mutation-plan.js +2 -0
  121. package/dist/sdk/lifecycle/task-composition.d.ts +2 -2
  122. package/dist/sdk/lifecycle/task-composition.js +1 -1
  123. package/dist/sdk/lifecycle/update.d.ts +3 -11
  124. package/dist/sdk/lifecycle/update.js +1 -1
  125. package/dist/sdk/lifecycle/workflow-transition.d.ts +13 -0
  126. package/dist/sdk/lifecycle/workflow-transition.js +2 -0
  127. package/dist/sdk/lifecycle-policy.d.ts +12 -2
  128. package/dist/sdk/lifecycle-policy.js +1 -1
  129. package/dist/sdk/mutation-events.js +1 -1
  130. package/dist/sdk/public-surface.json +1 -1
  131. package/dist/sdk/query/list.d.ts +2 -0
  132. package/dist/sdk/query/list.js +1 -1
  133. package/dist/sdk/read-output-budget.js +1 -1
  134. package/dist/sdk/runtime-input.js +1 -1
  135. package/dist/sdk/runtime-primitives.d.ts +1 -1
  136. package/dist/sdk/runtime-primitives.js +1 -1
  137. package/dist/sdk/runtime.d.ts +8 -8
  138. package/dist/sdk/runtime.js +1 -1
  139. package/dist/sdk/structured-mutations.d.ts +52 -1
  140. package/dist/sdk/structured-mutations.js +1 -1
  141. package/dist/sdk/workspace-transaction.js +2 -2
  142. package/dist/types.d.ts +2 -2
  143. package/dist/types.js +1 -1
  144. package/docs/AGENT_GUIDE.md +33 -4
  145. package/docs/CLOSE_EVIDENCE_RECOVERY.md +16 -7
  146. package/docs/COMMANDS.md +111 -10
  147. package/docs/CONFIGURATION.md +22 -1
  148. package/docs/DEVELOPMENT_DEPENDENCY_SECURITY.md +22 -3
  149. package/docs/ECOSYSTEM_PLANNING_REVIEW.md +5 -1
  150. package/docs/EXTENSIONS.md +1 -1
  151. package/docs/OUTPUT_PROJECTION_CONTRACTS.md +10 -0
  152. package/docs/RELEASING.md +8 -1
  153. package/docs/SDK.md +114 -2
  154. package/docs/SDK_CONTEXT_COORDINATION.md +71 -7
  155. package/docs/SDK_STORAGE_LIFECYCLE.md +24 -2
  156. package/docs/TESTING.md +23 -0
  157. package/docs/examples/ci/github-actions-pm-extension-gate.yml +1 -1
  158. package/docs/examples/ci/gitlab-ci-pm-extension-gate.yml +1 -1
  159. package/docs/examples/ci/jenkins-pm-extension-gate.Jenkinsfile +1 -1
  160. package/docs/generated/FLAG_LEXICON_BUDGETS.md +1 -1
  161. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +16 -3
  162. package/marketplace.json +1 -1
  163. package/node_modules/@opentelemetry/core/package.json +2 -1
  164. package/node_modules/@opentelemetry/instrumentation/package.json +2 -1
  165. package/node_modules/@opentelemetry/resources/package.json +2 -1
  166. package/node_modules/@opentelemetry/sdk-trace/package.json +2 -1
  167. package/node_modules/@opentelemetry/sdk-trace-base/package.json +2 -1
  168. package/node_modules/@sentry/core/build/cjs/client.js +5 -4
  169. package/node_modules/@sentry/core/build/cjs/tracing/ai/gen-ai-attributes.js +0 -4
  170. package/node_modules/@sentry/core/build/cjs/tracing/ai/utils.js +33 -23
  171. package/node_modules/@sentry/core/build/cjs/tracing/anthropic-ai/index.js +7 -6
  172. package/node_modules/@sentry/core/build/cjs/tracing/anthropic-ai/streaming.js +3 -1
  173. package/node_modules/@sentry/core/build/cjs/tracing/google-genai/index.js +13 -14
  174. package/node_modules/@sentry/core/build/cjs/tracing/google-genai/streaming.js +6 -1
  175. package/node_modules/@sentry/core/build/cjs/tracing/langchain/utils.js +71 -21
  176. package/node_modules/@sentry/core/build/cjs/tracing/langgraph/utils.js +23 -33
  177. package/node_modules/@sentry/core/build/cjs/tracing/openai/streaming.js +6 -0
  178. package/node_modules/@sentry/core/build/cjs/tracing/openai/utils.js +11 -0
  179. package/node_modules/@sentry/core/build/cjs/tracing/workers-ai/utils.js +1 -1
  180. package/node_modules/@sentry/core/build/cjs/utils/eventUtils.js +4 -0
  181. package/node_modules/@sentry/core/build/cjs/utils/prepareEvent.js +2 -2
  182. package/node_modules/@sentry/core/build/cjs/utils/version.js +1 -1
  183. package/node_modules/@sentry/core/build/esm/client.js +6 -5
  184. package/node_modules/@sentry/core/build/esm/package.json +1 -1
  185. package/node_modules/@sentry/core/build/esm/tracing/ai/gen-ai-attributes.js +1 -3
  186. package/node_modules/@sentry/core/build/esm/tracing/ai/utils.js +34 -24
  187. package/node_modules/@sentry/core/build/esm/tracing/anthropic-ai/index.js +8 -7
  188. package/node_modules/@sentry/core/build/esm/tracing/anthropic-ai/streaming.js +3 -1
  189. package/node_modules/@sentry/core/build/esm/tracing/google-genai/index.js +15 -16
  190. package/node_modules/@sentry/core/build/esm/tracing/google-genai/streaming.js +6 -1
  191. package/node_modules/@sentry/core/build/esm/tracing/langchain/utils.js +73 -24
  192. package/node_modules/@sentry/core/build/esm/tracing/langgraph/utils.js +24 -34
  193. package/node_modules/@sentry/core/build/esm/tracing/openai/streaming.js +6 -0
  194. package/node_modules/@sentry/core/build/esm/tracing/openai/utils.js +11 -0
  195. package/node_modules/@sentry/core/build/esm/tracing/workers-ai/utils.js +2 -2
  196. package/node_modules/@sentry/core/build/esm/utils/eventUtils.js +4 -1
  197. package/node_modules/@sentry/core/build/esm/utils/prepareEvent.js +2 -2
  198. package/node_modules/@sentry/core/build/esm/utils/version.js +1 -1
  199. package/node_modules/@sentry/core/build/types/tracing/ai/utils.d.ts +3 -7
  200. package/node_modules/@sentry/core/build/types/tracing/anthropic-ai/types.d.ts +2 -2
  201. package/node_modules/@sentry/core/build/types/tracing/langchain/types.d.ts +15 -0
  202. package/node_modules/@sentry/core/build/types/tracing/langchain/utils.d.ts +1 -0
  203. package/node_modules/@sentry/core/build/types/tracing/langgraph/utils.d.ts +2 -0
  204. package/node_modules/@sentry/core/build/types/tracing/openai/types.d.ts +2 -0
  205. package/node_modules/@sentry/core/build/types/utils/eventUtils.d.ts +2 -1
  206. package/node_modules/@sentry/core/build/types-ts3.8/tracing/ai/utils.d.ts +3 -7
  207. package/node_modules/@sentry/core/build/types-ts3.8/tracing/anthropic-ai/types.d.ts +2 -2
  208. package/node_modules/@sentry/core/build/types-ts3.8/tracing/langchain/types.d.ts +15 -0
  209. package/node_modules/@sentry/core/build/types-ts3.8/tracing/langchain/utils.d.ts +1 -0
  210. package/node_modules/@sentry/core/build/types-ts3.8/tracing/langgraph/utils.d.ts +2 -0
  211. package/node_modules/@sentry/core/build/types-ts3.8/tracing/openai/types.d.ts +2 -0
  212. package/node_modules/@sentry/core/build/types-ts3.8/utils/eventUtils.d.ts +2 -1
  213. package/node_modules/@sentry/core/package.json +1 -1
  214. package/node_modules/@sentry/node/build/esm/package.json +1 -1
  215. package/node_modules/@sentry/node/package.json +5 -5
  216. package/node_modules/@sentry/node-core/build/cjs/integrations/anr/index.js +1 -1
  217. package/node_modules/@sentry/node-core/build/cjs/integrations/local-variables/local-variables-async.js +1 -1
  218. package/node_modules/@sentry/node-core/build/esm/integrations/anr/index.js +1 -1
  219. package/node_modules/@sentry/node-core/build/esm/integrations/anr/worker-script.js +2 -2
  220. package/node_modules/@sentry/node-core/build/esm/integrations/local-variables/local-variables-async.js +1 -1
  221. package/node_modules/@sentry/node-core/build/esm/integrations/local-variables/worker-script.js +1 -1
  222. package/node_modules/@sentry/node-core/build/esm/package.json +1 -1
  223. package/node_modules/@sentry/node-core/package.json +10 -4
  224. package/node_modules/@sentry/opentelemetry/build/esm/package.json +1 -1
  225. package/node_modules/@sentry/opentelemetry/package.json +5 -2
  226. package/node_modules/@sentry/server-utils/build/THIRD-PARTY-LICENSES.txt +55 -55
  227. package/node_modules/@sentry/server-utils/build/esm/package.json +1 -1
  228. package/node_modules/@sentry/server-utils/package.json +2 -2
  229. package/node_modules/@toon-format/toon/README.md +10 -41
  230. package/node_modules/@toon-format/toon/dist/index.d.mts +12 -36
  231. package/node_modules/@toon-format/toon/dist/index.mjs +134 -202
  232. package/node_modules/@toon-format/toon/package.json +2 -2
  233. package/node_modules/debug/package.json +3 -0
  234. package/node_modules/fdir/package.json +3 -0
  235. package/node_modules/has-flag/index.d.ts +39 -0
  236. package/node_modules/has-flag/index.js +8 -0
  237. package/node_modules/has-flag/license +9 -0
  238. package/node_modules/has-flag/package.json +46 -0
  239. package/node_modules/has-flag/readme.md +89 -0
  240. package/node_modules/supports-color/browser.js +5 -0
  241. package/node_modules/supports-color/index.js +135 -0
  242. package/node_modules/supports-color/license +9 -0
  243. package/node_modules/supports-color/package.json +53 -0
  244. package/node_modules/supports-color/readme.md +76 -0
  245. package/package.json +5 -4
  246. package/packages/pm-beads/package.json +1 -1
  247. package/packages/pm-calendar/package.json +1 -1
  248. package/packages/pm-command-kit/package.json +1 -1
  249. package/packages/pm-digital-twin/package.json +1 -1
  250. package/packages/pm-governance-audit/package.json +1 -1
  251. package/packages/pm-guide-shell/package.json +1 -1
  252. package/packages/pm-kanban/package.json +1 -1
  253. package/packages/pm-lifecycle-hooks/package.json +1 -1
  254. package/packages/pm-linked-test-adapters/package.json +1 -1
  255. package/packages/pm-search-advanced/package.json +1 -1
  256. package/packages/pm-templates/package.json +1 -1
  257. package/packages/pm-todos/package.json +1 -1
  258. package/packages/pm-vcs/package.json +1 -1
  259. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  260. package/plugins/pm-claude/package.json +1 -1
  261. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  262. package/plugins/pm-codex/package.json +1 -1
  263. package/plugins/pm-codex/plugin.json +1 -1
  264. package/runtime-dependencies.json +1 -1
  265. package/dist/cli-bundle/chunks/chunk-7OEGNA4X.js +0 -20
  266. package/dist/cli-bundle/chunks/chunk-EMEEHV2Y.js +0 -2
  267. package/dist/cli-bundle/chunks/chunk-JSUJWIHQ.js +0 -30
  268. package/dist/cli-bundle/chunks/chunk-VIMQCFCK.js +0 -2
  269. package/dist/cli-bundle/chunks/chunk-X2H6UR26.js +0 -236
  270. package/dist/cli-bundle/chunks/register-mutation-EWMMVZJB.js +0 -20
  271. package/dist/cli-bundle/focused-chunks/chunk-5TBAVZDR.js +0 -20
  272. package/dist/cli-bundle/focused-chunks/chunk-HTA3TNC3.js +0 -26
  273. package/dist/cli-bundle/focused-chunks/chunk-JKBH7YGX.js +0 -2
  274. package/dist/cli-bundle/focused-chunks/chunk-PDYE7QDX.js +0 -166
  275. package/docs/ecosystem-review-2026-09-28.json +0 -1
@@ -1,6 +1,9 @@
1
1
  # SDK Storage Lifecycle
2
2
 
3
- Tracked by [pm-p5u6](../.agents/pm/chores/pm-p5u6.toon).
3
+ Tracked by [pm-p5u6](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/chores/pm-p5u6.toon) and
4
+ [pm-xj80p9](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-xj80p9.toon).
5
+
6
+ Tracker records live in the repository and are excluded from the npm package.
4
7
 
5
8
  Detached telemetry reads existing settings without scaffolding schemas/identity.
6
9
  Locks, queue/state rewrites and event/OTLP completion preserve owner-removed
@@ -10,7 +13,17 @@ storage. Delivery stays best effort/nonblocking; foreground defaults create pare
10
13
  import { acquireLock, writeFileAtomic } from "@unbrained/pm-cli/sdk";
11
14
 
12
15
  const policy = { createParentDirectories: false };
13
- const release = await acquireLock(root, "job", 60, "worker", false, true, 5000, policy);
16
+ const lockOptions = { ...policy, maxWaitMs: 0 };
17
+ const release = await acquireLock(
18
+ root,
19
+ "job",
20
+ 60,
21
+ "worker",
22
+ false,
23
+ true,
24
+ 5000,
25
+ lockOptions,
26
+ );
14
27
  try {
15
28
  await writeFileAtomic(resultPath, serializedResult, policy);
16
29
  } finally {
@@ -22,6 +35,15 @@ Owners initialize lock/result parents; absence fails without recreation. The
22
35
  policy cannot pin identity or prevent symlink/replacement races. Extension lock
23
36
  overrides own their lifecycle.
24
37
 
38
+ For optional background work, pass `maxWaitMs: 0` in the final `acquireLock`
39
+ options object. The built-in lock then fails fast for active contention, even
40
+ when `PM_LOCK_WAIT_MS` requests a longer wait. Stale-lock handling may still
41
+ retry creation after removing a confirmed stale owner. A positive `maxWaitMs` caps the normal
42
+ environment-or-caller retry budget without increasing it. Filesystem calls and
43
+ extension execution still take their ordinary execution time; the cap is not a
44
+ wall-clock timeout. Extension lock overrides receive `max_wait_ms` and remain
45
+ responsible for observing it.
46
+
25
47
  Async scripts use `registerTempOperation`: signal children, check after
26
48
  uncancellable SDK work, `finish` after finally disposal. Interrupts close admission
27
49
  and await completion; timeout retains evidence. Sync scripts use
package/docs/TESTING.md CHANGED
@@ -209,6 +209,14 @@ Use focused runs while iterating, then run coverage before closure when risk or
209
209
 
210
210
  ## CI Retry and Timeout Diagnostics
211
211
 
212
+ The required `Gates (coverage)` job runs after the coverage matrix settles and
213
+ explicitly requires every shard to succeed. Failed, canceled, skipped, or missing
214
+ shard outcomes fail that required context before checkout or report merging.
215
+ Shard artifacts retain failure diagnostics. After successful shard admission,
216
+ coverage-threshold failures still retain merged reports and Codecov uploads.
217
+ This enforcement is tracked by [pm-0p4aal](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-0p4aal.toon).
218
+ Tracker records live in the repository and are excluded from the npm package.
219
+
212
220
  Platform regressions from [pm-hrhfgi](../.agents/pm/issues/pm-hrhfgi.toon) and
213
221
  [pm-zk67yf](../.agents/pm/issues/pm-zk67yf.toon) have portable negative controls.
214
222
  Complete source scans process at most 32 item files per batch; the descriptor
@@ -650,6 +658,21 @@ pm test <item-id> --run --workspace-context snapshot --override-linked-workspace
650
658
  The real filesystem and CLI snapshot suite runs in the required Node 22
651
659
  telemetry regression job and native Windows regression job before merge.
652
660
 
661
+ Windows execution is tracked by [pm-bj7rq0](../.agents/pm/issues/pm-bj7rq0.toon).
662
+ Script and native keeper cohorts run independently on Windows Node 24. Their
663
+ source/script keeper steps retain the two-worker cap, and each cohort retains
664
+ the 12-minute deadline. The required
665
+ `Windows regression (Node 24)` check waits for both cohorts and fails if either
666
+ fails, is cancelled, or is skipped. This preserves every selected regression
667
+ while avoiding a shared serial job deadline. See GitHub's
668
+ [job dependency semantics](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-jobs#defining-prerequisite-jobs).
669
+
670
+ The real point-read corpus keeper runs with the lifecycle latency keeper in
671
+ the existing sequential performance phase after parallel contracts. Its
672
+ 1,500-item corpus, work-observer assertions and 30-second deadline remain
673
+ unchanged. Standalone script identity is resolved from the test module URL,
674
+ independently of temporary SDK working directories.
675
+
653
676
  The real-filesystem regression for this contract is tracked by
654
677
  [pm-5iwfkj](../.agents/pm/issues/pm-5iwfkj.toon).
655
678
 
@@ -16,7 +16,7 @@ jobs:
16
16
  - name: Setup pnpm
17
17
  uses: pnpm/action-setup@v4
18
18
  with:
19
- version: 11.10.0
19
+ version: 11.28.5
20
20
 
21
21
  - name: Setup Node
22
22
  uses: actions/setup-node@v4
@@ -8,7 +8,7 @@ stages:
8
8
 
9
9
  before_script:
10
10
  - corepack enable
11
- - corepack prepare pnpm@11.10.0 --activate
11
+ - corepack prepare pnpm@11.28.5 --activate
12
12
  - pnpm install --frozen-lockfile
13
13
 
14
14
  build:
@@ -9,7 +9,7 @@ pipeline {
9
9
  stage("Install") {
10
10
  steps {
11
11
  sh "corepack enable"
12
- sh "corepack prepare pnpm@11.10.0 --activate"
12
+ sh "corepack prepare pnpm@11.28.5 --activate"
13
13
  sh "pnpm install --frozen-lockfile"
14
14
  }
15
15
  }
@@ -68,7 +68,7 @@ This file is generated by `listPmFlagLexicon()`. Compatibility aliases do not co
68
68
  | `workspace` | workspace | 23 | 23 |
69
69
  | `contracts` | quality | 29 | 29 |
70
70
  | `claim` | lifecycle | 39 | 39 |
71
- | `release` | lifecycle | 24 | 24 |
71
+ | `release` | lifecycle | 25 | 25 |
72
72
  | `start-task` | lifecycle | 23 | 23 |
73
73
  | `pause-task` | lifecycle | 23 | 23 |
74
74
  | `close-task` | lifecycle | 24 | 24 |
@@ -4,12 +4,12 @@ Tracker: `pm-f05lsg`.
4
4
 
5
5
  Every catalog code is listed. An `uncovered` row is an explicit closure obligation, never an omission or implied approval.
6
6
 
7
- - Catalog error codes: 406
7
+ - Catalog error codes: 419
8
8
  - Executable error codes: 19
9
9
  - Executable-code ratchet floor: 18
10
10
  - Required executable canonical codes: `bulk_ids_input_empty`, `bulk_ids_input_missing_path`, `bulk_ids_input_unreadable`, `invalid_argument_value`, `manifest_unknown_key`, `missing_lifecycle_target`, `missing_required_argument`, `no_version_bounds_declared`, `projection_options_mutually_exclusive`, `tracker_not_initialized`, `tracker_root_missing`, `tracker_root_not_directory`, `tracker_root_unreadable`, `unknown_context_intent`, `unknown_field_projection`, `unknown_option`, `unknown_subcommand`
11
- - Uncovered error codes: 387
12
- - Coverage fraction: 0.046798
11
+ - Uncovered error codes: 400
12
+ - Coverage fraction: 0.045346
13
13
  - Closed-domain probes: 19
14
14
  - Grammar probes: 117
15
15
 
@@ -36,6 +36,7 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
36
36
  | `body_file_missing_path` | `body_file_missing_path` | uncovered | none | 0 |
37
37
  | `body_file_unreadable` | `body_file_unreadable` | uncovered | none | 0 |
38
38
  | `budget_exceeded` | `budget_exceeded` | uncovered | none | 0 |
39
+ | `bulk_create_route` | `bulk_create_route` | uncovered | none | 0 |
39
40
  | `bulk_ids_input_empty` | `bulk_ids_input_empty` | executable | owned_state | 1 |
40
41
  | `bulk_ids_input_missing_path` | `bulk_ids_input_missing_path` | executable | owned_state | 1 |
41
42
  | `bulk_ids_input_unreadable` | `bulk_ids_input_unreadable` | executable | owned_state | 1 |
@@ -89,6 +90,7 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
89
90
  | `extension_dependency_name_unsafe` | `extension_dependency_name_unsafe` | uncovered | none | 0 |
90
91
  | `extension_dependency_spec_invalid` | `extension_dependency_spec_invalid` | uncovered | none | 0 |
91
92
  | `extension_dependency_version_unsafe` | `extension_dependency_version_unsafe` | uncovered | none | 0 |
93
+ | `extension_flag_value_invalid` | `extension_flag_value_invalid` | uncovered | none | 0 |
92
94
  | `extension_install_incomplete_source_scan` | `extension_install_incomplete_source_scan` | uncovered | none | 0 |
93
95
  | `extension_install_soft_failed` | `extension_install_soft_failed` | uncovered | none | 0 |
94
96
  | `extension_install_source_contains_destination` | `extension_install_source_contains_destination` | uncovered | none | 0 |
@@ -241,6 +243,8 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
241
243
  | `module_import_failed` | `module_import_failed` | uncovered | none | 0 |
242
244
  | `multi_target_github_install_ambiguous` | `multi_target_github_install_ambiguous` | uncovered | none | 0 |
243
245
  | `mutation_author_required` | `mutation_author_required` | uncovered | none | 0 |
246
+ | `mutation_document_unreadable` | `mutation_document_unreadable` | uncovered | none | 0 |
247
+ | `mutation_option_value_invalid` | `mutation_option_value_invalid` | uncovered | none | 0 |
244
248
  | `mutation_secret_guard_blocked` | `mutation_secret_guard_blocked` | uncovered | none | 0 |
245
249
  | `no_matching_tests` | `no_matching_tests` | uncovered | none | 0 |
246
250
  | `no_projects_matched_filters` | `no_projects_matched_filters` | uncovered | none | 0 |
@@ -328,11 +332,15 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
328
332
  | `terminal_state_conflict` | `terminal_state_conflict` | uncovered | none | 0 |
329
333
  | `test_measure_requires_execution` | `test_measure_requires_execution` | uncovered | none | 0 |
330
334
  | `test_measure_requires_run` | `test_measure_requires_run` | uncovered | none | 0 |
335
+ | `text_unpaired_surrogate` | `text_unpaired_surrogate` | uncovered | none | 0 |
331
336
  | `tracked_runtime_cache_files` | `tracked_runtime_cache_files` | uncovered | none | 0 |
332
337
  | `tracker_not_initialized` | `tracker_not_initialized` | executable | owned_state | 1 |
333
338
  | `tracker_root_missing` | `tracker_root_missing` | executable | owned_state | 1 |
334
339
  | `tracker_root_not_directory` | `tracker_root_not_directory` | executable | owned_state | 1 |
335
340
  | `tracker_root_unreadable` | `tracker_root_unreadable` | executable | owned_state | 1 |
341
+ | `transaction_create_compensated` | `transaction_create_compensated` | uncovered | none | 0 |
342
+ | `transaction_journal_invalid` | `transaction_journal_invalid` | uncovered | none | 0 |
343
+ | `transaction_plan_mismatch` | `transaction_plan_mismatch` | uncovered | none | 0 |
336
344
  | `transaction_preview_external_schema` | `transaction_preview_external_schema` | uncovered | none | 0 |
337
345
  | `transaction_preview_non_regular_file` | `transaction_preview_non_regular_file` | uncovered | none | 0 |
338
346
  | `transaction_preview_snapshot_changed` | `transaction_preview_snapshot_changed` | uncovered | none | 0 |
@@ -355,6 +363,11 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
355
363
  | `unknown_subcommand` | `unknown_subcommand` | executable | grammar, owned_state | 14 |
356
364
  | `unsafe_init_recovery` | `unsafe_init_recovery` | uncovered | none | 0 |
357
365
  | `unsupported_update_option` | `unsupported_update_option` | uncovered | none | 0 |
366
+ | `upsert_key_ambiguous` | `upsert_key_ambiguous` | uncovered | none | 0 |
367
+ | `upsert_key_conflict` | `upsert_key_conflict` | uncovered | none | 0 |
368
+ | `upsert_key_duplicate` | `upsert_key_duplicate` | uncovered | none | 0 |
369
+ | `upsert_key_missing` | `upsert_key_missing` | uncovered | none | 0 |
370
+ | `upsert_match_changed` | `upsert_match_changed` | uncovered | none | 0 |
358
371
  | `validate_command_references_stale_pm_ids` | `validate_command_references_stale_pm_ids` | uncovered | none | 0 |
359
372
  | `validate_files_missing_linked_paths` | `validate_files_missing_linked_paths` | uncovered | none | 0 |
360
373
  | `validate_files_orphaned_paths` | `validate_files_orphaned_paths` | uncovered | none | 0 |
package/marketplace.json CHANGED
@@ -1 +1 @@
1
- {"name":"pm","owner":{"name":"unbrained","url":"https://github.com/unbraind/pm-cli"},"description":"Official marketplace for pm CLI — native git-based project management for Claude Code and AI coding agents.","version":"2026.10.15","plugins":[{"name":"pm-claude","source":"./plugins/pm-claude","description":"Native pm CLI integration for Claude Code — 32 MCP tools, 14 workflow skills with slash invocations, 4 subagents, hybrid TUI task tracking, session context injection, and coordination subagents for git-based project management without leaving Claude Code.","version":"2026.10.15","author":{"name":"unbrained","url":"https://github.com/unbraind/pm-cli"},"homepage":"https://github.com/unbraind/pm-cli","repository":"https://github.com/unbraind/pm-cli","license":"MIT","keywords":["pm-cli","project-management","mcp","tasks","agents","workflows","git-native","task-tracker","ai"],"category":"productivity"}]}
1
+ {"name":"pm","owner":{"name":"unbrained","url":"https://github.com/unbraind/pm-cli"},"description":"Official marketplace for pm CLI — native git-based project management for Claude Code and AI coding agents.","version":"2026.10.18","plugins":[{"name":"pm-claude","source":"./plugins/pm-claude","description":"Native pm CLI integration for Claude Code — 32 MCP tools, 14 workflow skills with slash invocations, 4 subagents, hybrid TUI task tracking, session context injection, and coordination subagents for git-based project management without leaving Claude Code.","version":"2026.10.18","author":{"name":"unbrained","url":"https://github.com/unbraind/pm-cli"},"homepage":"https://github.com/unbraind/pm-cli","repository":"https://github.com/unbraind/pm-cli","license":"MIT","keywords":["pm-cli","project-management","mcp","tasks","agents","workflows","git-native","task-tracker","ai"],"category":"productivity"}]}
@@ -86,7 +86,8 @@
86
86
  "@opentelemetry/api": ">=1.0.0 <1.10.0"
87
87
  },
88
88
  "dependencies": {
89
- "@opentelemetry/semantic-conventions": "^1.29.0"
89
+ "@opentelemetry/semantic-conventions": "^1.29.0",
90
+ "@opentelemetry/api": "1.9.1"
90
91
  },
91
92
  "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-core",
92
93
  "sideEffects": false,
@@ -72,7 +72,8 @@
72
72
  "dependencies": {
73
73
  "@opentelemetry/api-logs": "0.220.0",
74
74
  "import-in-the-middle": "^3.0.0",
75
- "require-in-the-middle": "^8.0.0"
75
+ "require-in-the-middle": "^8.0.0",
76
+ "@opentelemetry/api": "1.9.1"
76
77
  },
77
78
  "peerDependencies": {
78
79
  "@opentelemetry/api": "^1.3.0"
@@ -83,7 +83,8 @@
83
83
  },
84
84
  "dependencies": {
85
85
  "@opentelemetry/core": "2.12.0",
86
- "@opentelemetry/semantic-conventions": "^1.29.0"
86
+ "@opentelemetry/semantic-conventions": "^1.29.0",
87
+ "@opentelemetry/api": "1.9.1"
87
88
  },
88
89
  "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-resources",
89
90
  "sideEffects": false,
@@ -92,7 +92,8 @@
92
92
  "dependencies": {
93
93
  "@opentelemetry/core": "2.12.0",
94
94
  "@opentelemetry/resources": "2.12.0",
95
- "@opentelemetry/semantic-conventions": "^1.29.0"
95
+ "@opentelemetry/semantic-conventions": "^1.29.0",
96
+ "@opentelemetry/api": "1.9.1"
96
97
  },
97
98
  "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/sdk-trace",
98
99
  "sideEffects": false,
@@ -92,7 +92,8 @@
92
92
  "@opentelemetry/core": "2.12.0",
93
93
  "@opentelemetry/resources": "2.12.0",
94
94
  "@opentelemetry/sdk-trace": "2.12.0",
95
- "@opentelemetry/semantic-conventions": "^1.29.0"
95
+ "@opentelemetry/semantic-conventions": "^1.29.0",
96
+ "@opentelemetry/api": "1.9.1"
96
97
  },
97
98
  "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-base",
98
99
  "sideEffects": false,
@@ -333,8 +333,10 @@ class Client {
333
333
  this.emit("beforeSendEvent", event, hint);
334
334
  const genAiSpanItem = extractGenAiSpans.extractGenAiSpansFromEvent(event, this);
335
335
  let env = envelope.createEventEnvelope(event, this._dsn, this._options._metadata, this._options.tunnel);
336
- for (const attachment of hint.attachments || []) {
337
- env = envelope$1.addItemToEnvelope(env, envelope$1.createAttachmentEnvelopeItem(attachment));
336
+ if (!eventUtils.isInternalException(hint)) {
337
+ for (const attachment of hint.attachments || []) {
338
+ env = envelope$1.addItemToEnvelope(env, envelope$1.createAttachmentEnvelopeItem(attachment));
339
+ }
338
340
  }
339
341
  if (genAiSpanItem) {
340
342
  env = envelope$1.addItemToEnvelope(env, genAiSpanItem);
@@ -588,8 +590,7 @@ class Client {
588
590
  this.recordDroppedEvent("event_processor", dataCategory);
589
591
  throw _makeDoNotSendEventError("An event processor returned `null`, will not send event.");
590
592
  }
591
- const isInternalException = hint.data?.__sentry__ === true;
592
- if (isInternalException) {
593
+ if (eventUtils.isInternalException(hint)) {
593
594
  return prepared;
594
595
  }
595
596
  const result = processBeforeSend(this, options, prepared, hint);
@@ -31,8 +31,6 @@ const GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE = "gen_ai.response.tool_calls";
31
31
  const GEN_AI_AGENT_NAME_ATTRIBUTE = "gen_ai.agent.name";
32
32
  const GEN_AI_PIPELINE_NAME_ATTRIBUTE = "gen_ai.pipeline.name";
33
33
  const GEN_AI_CONVERSATION_ID_ATTRIBUTE = "gen_ai.conversation.id";
34
- const GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS_ATTRIBUTE = "gen_ai.usage.cache_creation_input_tokens";
35
- const GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS_ATTRIBUTE = "gen_ai.usage.cache_read_input_tokens";
36
34
  const GEN_AI_USAGE_INPUT_TOKENS_CACHE_WRITE_ATTRIBUTE = "gen_ai.usage.input_tokens.cache_write";
37
35
  const GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE = "gen_ai.usage.input_tokens.cached";
38
36
  const GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE = "gen_ai.invoke_agent";
@@ -84,8 +82,6 @@ exports.GEN_AI_TOOL_INPUT_ATTRIBUTE = GEN_AI_TOOL_INPUT_ATTRIBUTE;
84
82
  exports.GEN_AI_TOOL_NAME_ATTRIBUTE = GEN_AI_TOOL_NAME_ATTRIBUTE;
85
83
  exports.GEN_AI_TOOL_OUTPUT_ATTRIBUTE = GEN_AI_TOOL_OUTPUT_ATTRIBUTE;
86
84
  exports.GEN_AI_TOOL_TYPE_ATTRIBUTE = GEN_AI_TOOL_TYPE_ATTRIBUTE;
87
- exports.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS_ATTRIBUTE = GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS_ATTRIBUTE;
88
- exports.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS_ATTRIBUTE = GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS_ATTRIBUTE;
89
85
  exports.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE = GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE;
90
86
  exports.GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE = GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE;
91
87
  exports.GEN_AI_USAGE_INPUT_TOKENS_CACHE_WRITE_ATTRIBUTE = GEN_AI_USAGE_INPUT_TOKENS_CACHE_WRITE_ATTRIBUTE;
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
+ const attributes = require('@sentry/conventions/attributes');
3
4
  const currentScopes = require('../../currentScopes.js');
4
5
  const hasSpanStreamingEnabled = require('../spans/hasSpanStreamingEnabled.js');
5
6
  const is = require('../../utils/is.js');
@@ -27,23 +28,26 @@ function shouldEnableTruncation(enableTruncation) {
27
28
  function buildMethodPath(currentPath, prop) {
28
29
  return currentPath ? `${currentPath}.${prop}` : prop;
29
30
  }
30
- function setTokenUsageAttributes(span, promptTokens, completionTokens, cachedInputTokens, cachedOutputTokens) {
31
- if (promptTokens !== void 0) {
32
- span.setAttributes({
33
- [genAiAttributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE]: promptTokens
34
- });
35
- }
36
- if (completionTokens !== void 0) {
37
- span.setAttributes({
38
- [genAiAttributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: completionTokens
39
- });
40
- }
41
- if (promptTokens !== void 0 || completionTokens !== void 0 || cachedInputTokens !== void 0 || cachedOutputTokens !== void 0) {
42
- const totalTokens = (promptTokens ?? 0) + (completionTokens ?? 0) + (cachedInputTokens ?? 0) + (cachedOutputTokens ?? 0);
43
- span.setAttributes({
44
- [genAiAttributes.GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: totalTokens
45
- });
31
+ function getTokenUsageAttributes(promptTokens, completionTokens, cacheCreationInputTokens, cacheReadInputTokens, totalTokens) {
32
+ const attributes$1 = {};
33
+ if (typeof promptTokens === "number") {
34
+ attributes$1[genAiAttributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE] = promptTokens;
46
35
  }
36
+ if (typeof cacheCreationInputTokens === "number") {
37
+ attributes$1[attributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS] = cacheCreationInputTokens;
38
+ }
39
+ if (typeof cacheReadInputTokens === "number") {
40
+ attributes$1[attributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS] = cacheReadInputTokens;
41
+ }
42
+ if (typeof completionTokens === "number") {
43
+ attributes$1[genAiAttributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] = completionTokens;
44
+ }
45
+ if (typeof totalTokens === "number") {
46
+ attributes$1[genAiAttributes.GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE] = totalTokens;
47
+ } else if (typeof promptTokens === "number" || typeof completionTokens === "number") {
48
+ attributes$1[genAiAttributes.GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE] = (typeof promptTokens === "number" ? promptTokens : 0) + (typeof completionTokens === "number" ? completionTokens : 0);
49
+ }
50
+ return attributes$1;
47
51
  }
48
52
  function endStreamSpan(span, state, recordOutputs) {
49
53
  if (!span.isRecording()) {
@@ -54,12 +58,18 @@ function endStreamSpan(span, state, recordOutputs) {
54
58
  };
55
59
  if (state.responseId) attrs[genAiAttributes.GEN_AI_RESPONSE_ID_ATTRIBUTE] = state.responseId;
56
60
  if (state.responseModel) attrs[genAiAttributes.GEN_AI_RESPONSE_MODEL_ATTRIBUTE] = state.responseModel;
57
- if (state.promptTokens !== void 0) attrs[genAiAttributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE] = state.promptTokens;
58
- if (state.completionTokens !== void 0) attrs[genAiAttributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] = state.completionTokens;
59
- if (state.totalTokens !== void 0) {
60
- attrs[genAiAttributes.GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE] = state.totalTokens;
61
- } else if (state.promptTokens !== void 0 || state.completionTokens !== void 0 || state.cacheCreationInputTokens !== void 0 || state.cacheReadInputTokens !== void 0) {
62
- attrs[genAiAttributes.GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE] = (state.promptTokens ?? 0) + (state.completionTokens ?? 0) + (state.cacheCreationInputTokens ?? 0) + (state.cacheReadInputTokens ?? 0);
61
+ Object.assign(
62
+ attrs,
63
+ getTokenUsageAttributes(
64
+ state.promptTokens,
65
+ state.completionTokens,
66
+ state.cacheCreationInputTokens,
67
+ state.cacheReadInputTokens,
68
+ state.totalTokens
69
+ )
70
+ );
71
+ if (typeof state.reasoningOutputTokens === "number") {
72
+ attrs[attributes.GEN_AI_USAGE_REASONING_OUTPUT_TOKENS] = state.reasoningOutputTokens;
63
73
  }
64
74
  if (state.finishReasons.length) {
65
75
  attrs[genAiAttributes.GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE] = JSON.stringify(state.finishReasons);
@@ -135,9 +145,9 @@ function wrapPromiseWithMethods(originalPromiseLike, instrumentedPromise) {
135
145
  exports.buildMethodPath = buildMethodPath;
136
146
  exports.endStreamSpan = endStreamSpan;
137
147
  exports.extractSystemInstructions = extractSystemInstructions;
148
+ exports.getTokenUsageAttributes = getTokenUsageAttributes;
138
149
  exports.getTruncatedJsonString = getTruncatedJsonString;
139
150
  exports.resolveAIRecordingOptions = resolveAIRecordingOptions;
140
- exports.setTokenUsageAttributes = setTokenUsageAttributes;
141
151
  exports.shouldEnableTruncation = shouldEnableTruncation;
142
152
  exports.wrapPromiseWithMethods = wrapPromiseWithMethods;
143
153
  //# sourceMappingURL=utils.js.map
@@ -77,12 +77,13 @@ function addMetadataAttributes(span, response) {
77
77
  [genAiAttributes.GEN_AI_RESPONSE_MODEL_ATTRIBUTE]: response.model
78
78
  });
79
79
  if ("usage" in response && response.usage) {
80
- utils$1.setTokenUsageAttributes(
81
- span,
82
- response.usage.input_tokens,
83
- response.usage.output_tokens,
84
- response.usage.cache_creation_input_tokens,
85
- response.usage.cache_read_input_tokens
80
+ span.setAttributes(
81
+ utils$1.getTokenUsageAttributes(
82
+ response.usage.input_tokens + (response.usage.cache_creation_input_tokens ?? 0) + (response.usage.cache_read_input_tokens ?? 0),
83
+ response.usage.output_tokens,
84
+ response.usage.cache_creation_input_tokens,
85
+ response.usage.cache_read_input_tokens
86
+ )
86
87
  );
87
88
  }
88
89
  }
@@ -28,7 +28,9 @@ function handleMessageMetadata(event, state) {
28
28
  if (message.id) state.responseId = message.id;
29
29
  if (message.model) state.responseModel = message.model;
30
30
  if (message.usage) {
31
- if (typeof message.usage.input_tokens === "number") state.promptTokens = message.usage.input_tokens;
31
+ if (typeof message.usage.input_tokens === "number") {
32
+ state.promptTokens = message.usage.input_tokens + (message.usage.cache_creation_input_tokens ?? 0) + (message.usage.cache_read_input_tokens ?? 0);
33
+ }
32
34
  if (typeof message.usage.cache_creation_input_tokens === "number")
33
35
  state.cacheCreationInputTokens = message.usage.cache_creation_input_tokens;
34
36
  if (typeof message.usage.cache_read_input_tokens === "number")
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
+ const attributes = require('@sentry/conventions/attributes');
3
4
  const semanticAttributes = require('../../semanticAttributes.js');
4
5
  const string = require('../../utils/string.js');
5
6
  const spanstatus = require('../spanstatus.js');
@@ -114,20 +115,18 @@ function addResponseAttributes(span, response, recordOutputs) {
114
115
  }
115
116
  if (response.usageMetadata && typeof response.usageMetadata === "object") {
116
117
  const usage = response.usageMetadata;
117
- if (typeof usage.promptTokenCount === "number") {
118
- span.setAttributes({
119
- [genAiAttributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE]: usage.promptTokenCount
120
- });
121
- }
122
- if (typeof usage.candidatesTokenCount === "number") {
123
- span.setAttributes({
124
- [genAiAttributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: usage.candidatesTokenCount
125
- });
126
- }
127
- if (typeof usage.totalTokenCount === "number") {
128
- span.setAttributes({
129
- [genAiAttributes.GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: usage.totalTokenCount
130
- });
118
+ const hasOutput = typeof usage.candidatesTokenCount === "number" || typeof usage.thoughtsTokenCount === "number";
119
+ span.setAttributes(
120
+ utils$1.getTokenUsageAttributes(
121
+ usage.promptTokenCount,
122
+ hasOutput ? (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0) : void 0,
123
+ void 0,
124
+ usage.cachedContentTokenCount,
125
+ usage.totalTokenCount
126
+ )
127
+ );
128
+ if (typeof usage.thoughtsTokenCount === "number") {
129
+ span.setAttribute(attributes.GEN_AI_USAGE_REASONING_OUTPUT_TOKENS, usage.thoughtsTokenCount);
131
130
  }
132
131
  }
133
132
  if (recordOutputs && Array.isArray(response.candidates) && response.candidates.length > 0) {
@@ -22,8 +22,13 @@ function handleResponseMetadata(chunk, state) {
22
22
  const usage = chunk.usageMetadata;
23
23
  if (usage) {
24
24
  if (typeof usage.promptTokenCount === "number") state.promptTokens = usage.promptTokenCount;
25
- if (typeof usage.candidatesTokenCount === "number") state.completionTokens = usage.candidatesTokenCount;
25
+ if (typeof usage.candidatesTokenCount === "number") state.candidateTokens = usage.candidatesTokenCount;
26
+ if (typeof usage.thoughtsTokenCount === "number") state.reasoningOutputTokens = usage.thoughtsTokenCount;
27
+ if (state.candidateTokens !== void 0 || state.reasoningOutputTokens !== void 0) {
28
+ state.completionTokens = (state.candidateTokens ?? 0) + (state.reasoningOutputTokens ?? 0);
29
+ }
26
30
  if (typeof usage.totalTokenCount === "number") state.totalTokens = usage.totalTokenCount;
31
+ if (typeof usage.cachedContentTokenCount === "number") state.cacheReadInputTokens = usage.cachedContentTokenCount;
27
32
  }
28
33
  }
29
34
  function handleCandidateContent(chunk, state, recordOutputs) {
@@ -1,7 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
+ const attributes = require('@sentry/conventions/attributes');
3
4
  const semanticAttributes = require('../../semanticAttributes.js');
4
5
  const string = require('../../utils/string.js');
6
+ const is = require('../../utils/is.js');
5
7
  const genAiAttributes = require('../ai/gen-ai-attributes.js');
6
8
  const mediaStripping = require('../ai/mediaStripping.js');
7
9
  const utils = require('../ai/utils.js');
@@ -172,29 +174,76 @@ function addToolCallsAttributes(generations, attrs) {
172
174
  setIfDefined(attrs, genAiAttributes.GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE, string.stringify(toolCalls, String));
173
175
  }
174
176
  }
175
- function addTokenUsageAttributes(llmOutput, attrs) {
177
+ function extractMessageTokenUsageAttributes(message) {
178
+ const usage = message.usage_metadata;
179
+ if (is.isObjectLike(usage)) {
180
+ const details = is.isObjectLike(usage.input_token_details) ? usage.input_token_details : void 0;
181
+ return utils.getTokenUsageAttributes(
182
+ usage.input_tokens,
183
+ usage.output_tokens,
184
+ details?.cache_creation,
185
+ details?.cache_read,
186
+ usage.total_tokens
187
+ );
188
+ }
189
+ const metadata = message.response_metadata;
190
+ const tokenUsage = is.isObjectLike(metadata) && is.isObjectLike(metadata.tokenUsage) ? metadata.tokenUsage : void 0;
191
+ return utils.getTokenUsageAttributes(
192
+ tokenUsage?.promptTokens,
193
+ tokenUsage?.completionTokens,
194
+ void 0,
195
+ void 0,
196
+ tokenUsage?.totalTokens
197
+ );
198
+ }
199
+ function addTokenUsageAttributes(llmResult, attrs) {
200
+ const normalizedUsage = {};
201
+ const legacyMessageUsage = {};
202
+ for (const generations of llmResult.generations ?? []) {
203
+ const message = generations[0]?.message;
204
+ if (message) {
205
+ const usage = is.isObjectLike(message.usage_metadata) ? normalizedUsage : legacyMessageUsage;
206
+ for (const [key, value] of Object.entries(extractMessageTokenUsageAttributes(message))) {
207
+ usage[key] = (usage[key] ?? 0) + value;
208
+ }
209
+ }
210
+ }
211
+ Object.assign(attrs, Object.keys(normalizedUsage).length > 0 ? normalizedUsage : legacyMessageUsage);
212
+ const llmOutput = llmResult.llmOutput;
176
213
  if (!llmOutput) return;
177
214
  const tokenUsage = llmOutput.tokenUsage;
178
215
  const anthropicUsage = llmOutput.usage;
179
- if (tokenUsage) {
180
- setNumberIfDefined(attrs, genAiAttributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE, tokenUsage.promptTokens);
181
- setNumberIfDefined(attrs, genAiAttributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE, tokenUsage.completionTokens);
182
- setNumberIfDefined(attrs, genAiAttributes.GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE, tokenUsage.totalTokens);
183
- } else if (anthropicUsage) {
184
- setNumberIfDefined(attrs, genAiAttributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE, anthropicUsage.input_tokens);
185
- setNumberIfDefined(attrs, genAiAttributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE, anthropicUsage.output_tokens);
186
- const input = Number(anthropicUsage.input_tokens);
187
- const output = Number(anthropicUsage.output_tokens);
188
- const total = (Number.isNaN(input) ? 0 : input) + (Number.isNaN(output) ? 0 : output);
189
- if (total > 0) setNumberIfDefined(attrs, genAiAttributes.GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE, total);
190
- if (anthropicUsage.cache_creation_input_tokens !== void 0)
191
- setNumberIfDefined(
192
- attrs,
193
- genAiAttributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS_ATTRIBUTE,
194
- anthropicUsage.cache_creation_input_tokens
195
- );
196
- if (anthropicUsage.cache_read_input_tokens !== void 0)
197
- setNumberIfDefined(attrs, genAiAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS_ATTRIBUTE, anthropicUsage.cache_read_input_tokens);
216
+ if (anthropicUsage && Object.keys(normalizedUsage).length === 0 && Object.keys(legacyMessageUsage).length === 0) {
217
+ const { input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens } = anthropicUsage;
218
+ const hasInput = input_tokens !== void 0 || cache_creation_input_tokens !== void 0 || cache_read_input_tokens !== void 0;
219
+ Object.assign(
220
+ attrs,
221
+ utils.getTokenUsageAttributes(
222
+ hasInput ? (input_tokens ?? 0) + (cache_creation_input_tokens ?? 0) + (cache_read_input_tokens ?? 0) : void 0,
223
+ output_tokens,
224
+ cache_creation_input_tokens,
225
+ cache_read_input_tokens
226
+ )
227
+ );
228
+ } else if (tokenUsage && Object.keys(normalizedUsage).length === 0 && Object.keys(legacyMessageUsage).length === 0) {
229
+ Object.assign(
230
+ attrs,
231
+ utils.getTokenUsageAttributes(
232
+ tokenUsage.promptTokens,
233
+ tokenUsage.completionTokens,
234
+ void 0,
235
+ void 0,
236
+ tokenUsage.totalTokens
237
+ )
238
+ );
239
+ }
240
+ if (anthropicUsage) {
241
+ if (typeof anthropicUsage.cache_creation_input_tokens === "number" && !(attributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS in attrs)) {
242
+ attrs[attributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS] = anthropicUsage.cache_creation_input_tokens;
243
+ }
244
+ if (typeof anthropicUsage.cache_read_input_tokens === "number" && !(attributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS in attrs)) {
245
+ attrs[attributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS] = anthropicUsage.cache_read_input_tokens;
246
+ }
198
247
  }
199
248
  }
200
249
  function extractLlmResponseAttributes(llmResult, recordOutputs) {
@@ -221,7 +270,7 @@ function extractLlmResponseAttributes(llmResult, recordOutputs) {
221
270
  }
222
271
  }
223
272
  }
224
- addTokenUsageAttributes(llmResult.llmOutput, attrs);
273
+ addTokenUsageAttributes(llmResult, attrs);
225
274
  const llmOutput = llmResult.llmOutput;
226
275
  const firstGeneration = llmResult.generations?.[0]?.[0];
227
276
  const v1Message = firstGeneration?.message;
@@ -294,6 +343,7 @@ exports._INTERNAL_mergeLangChainCallbackHandler = _INTERNAL_mergeLangChainCallba
294
343
  exports.extractChatModelRequestAttributes = extractChatModelRequestAttributes;
295
344
  exports.extractLLMRequestAttributes = extractLLMRequestAttributes;
296
345
  exports.extractLlmResponseAttributes = extractLlmResponseAttributes;
346
+ exports.extractMessageTokenUsageAttributes = extractMessageTokenUsageAttributes;
297
347
  exports.extractToolDefinitions = extractToolDefinitions;
298
348
  exports.getAgentNameFromMetadata = getAgentNameFromMetadata;
299
349
  exports.getInvocationParams = getInvocationParams;