@unbrained/pm-cli 2026.10.17 → 2026.10.19

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 (256) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +35 -0
  3. package/dist/cli/help-content.js +2 -2
  4. package/dist/cli/register-list-query.js +2 -2
  5. package/dist/cli/register-mutation.js +2 -2
  6. package/dist/cli/register-setup.js +1 -1
  7. package/dist/cli-bundle/bundle-manifest.json +1 -1
  8. package/dist/cli-bundle/chunks/chunk-4CXQSRSP.js +126 -0
  9. package/dist/cli-bundle/chunks/{chunk-EA2CG7UM.js → chunk-4ICKT4GH.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-W3KZ22DW.js → chunk-4MJ6WBMA.js} +2 -2
  11. package/dist/cli-bundle/chunks/chunk-4XFVAXA4.js +2 -0
  12. package/dist/cli-bundle/chunks/{chunk-6ZDKKOKM.js → chunk-5GZSX5HU.js} +72 -66
  13. package/dist/cli-bundle/chunks/{chunk-3QKI3XNX.js → chunk-6DS5CAN2.js} +2 -2
  14. package/dist/cli-bundle/chunks/{chunk-B5QVGCZX.js → chunk-D3EDNAN7.js} +2 -2
  15. package/dist/cli-bundle/chunks/chunk-DMFM5R4G.js +3 -0
  16. package/dist/cli-bundle/chunks/chunk-H3XYP24A.js +70 -0
  17. package/dist/cli-bundle/chunks/chunk-LBEMB3BW.js +6 -0
  18. package/dist/cli-bundle/chunks/chunk-NX7Q4LGN.js +8 -0
  19. package/dist/cli-bundle/chunks/chunk-O2ZRRLAP.js +8 -0
  20. package/dist/cli-bundle/chunks/chunk-OEJ3G7XT.js +20 -0
  21. package/dist/cli-bundle/chunks/{chunk-O4YBC3OM.js → chunk-QBNEZII5.js} +30 -30
  22. package/dist/cli-bundle/chunks/chunk-QG4LMU7A.js +112 -0
  23. package/dist/cli-bundle/chunks/chunk-QKAAZWGC.js +3 -0
  24. package/dist/cli-bundle/chunks/chunk-RUKSEZE7.js +2 -0
  25. package/dist/cli-bundle/chunks/chunk-TK3G3GAP.js +2 -0
  26. package/dist/cli-bundle/chunks/chunk-VS565KBX.js +2 -0
  27. package/dist/cli-bundle/chunks/{chunk-JS3B2M4D.js → chunk-XH7C3A5N.js} +2 -2
  28. package/dist/cli-bundle/chunks/indexed-receipt-blobs-BVSHK4WQ.js +4 -0
  29. package/dist/cli-bundle/chunks/{register-list-query-RU3QZSAQ.js → register-list-query-WQUVDJIH.js} +7 -7
  30. package/dist/cli-bundle/chunks/register-mutation-IWIBQIO3.js +20 -0
  31. package/dist/cli-bundle/chunks/register-operations-SUWOZNDU.js +2 -0
  32. package/dist/cli-bundle/chunks/register-setup-QGM5YJW7.js +2 -0
  33. package/dist/cli-bundle/chunks/settlement-hook-UNFMCKKQ.js +7 -0
  34. package/dist/cli-bundle/chunks/stage-7DELI4Z5.js +2 -0
  35. package/dist/cli-bundle/focused-chunks/{chunk-LDKX4KYJ.js → chunk-2IEWB6MB.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/chunk-3TEIACFU.js +3 -0
  37. package/dist/cli-bundle/focused-chunks/chunk-5YTOYBTZ.js +65 -0
  38. package/dist/cli-bundle/focused-chunks/chunk-AK2CI2GI.js +2 -0
  39. package/dist/cli-bundle/focused-chunks/chunk-BJMPRB7A.js +91 -0
  40. package/dist/cli-bundle/focused-chunks/chunk-ENZMATOY.js +20 -0
  41. package/dist/cli-bundle/focused-chunks/chunk-EOQ6W25I.js +8 -0
  42. package/dist/cli-bundle/focused-chunks/{chunk-FTUZ3JF2.js → chunk-FEN7WOOP.js} +2 -2
  43. package/dist/cli-bundle/focused-chunks/chunk-FOA7XKWP.js +2 -0
  44. package/dist/cli-bundle/focused-chunks/chunk-GWTV45SB.js +2 -0
  45. package/dist/cli-bundle/focused-chunks/{chunk-SIGIGZCG.js → chunk-H6BVQ63U.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/{chunk-RBLSY6ML.js → chunk-HYMYAGSY.js} +2 -2
  47. package/dist/cli-bundle/focused-chunks/chunk-JBJJW2WL.js +6 -0
  48. package/dist/cli-bundle/focused-chunks/chunk-JCLC6HKT.js +8 -0
  49. package/dist/cli-bundle/focused-chunks/{chunk-2IOHHNRT.js → chunk-JDBO7SMR.js} +2 -2
  50. package/dist/cli-bundle/focused-chunks/{chunk-UNTQE37U.js → chunk-KLJN44VY.js} +2 -2
  51. package/dist/cli-bundle/focused-chunks/chunk-L4PL3GZR.js +2 -0
  52. package/dist/cli-bundle/focused-chunks/chunk-OV2WVLUR.js +2 -0
  53. package/dist/cli-bundle/focused-chunks/chunk-PXDR77TO.js +78 -0
  54. package/dist/cli-bundle/focused-chunks/chunk-RLRMNFLF.js +3 -0
  55. package/dist/cli-bundle/focused-chunks/{chunk-E33QA7PK.js → chunk-SKYLOPU2.js} +2 -2
  56. package/dist/cli-bundle/focused-chunks/chunk-VVRXF4JO.js +2 -0
  57. package/dist/cli-bundle/focused-chunks/chunk-WZTEFFQI.js +3 -0
  58. package/dist/cli-bundle/focused-chunks/chunk-Y54ONBEX.js +25 -0
  59. package/dist/cli-bundle/focused-chunks/indexed-receipt-blobs-QW2VWWJE.js +4 -0
  60. package/dist/cli-bundle/focused-chunks/settlement-hook-X4FNHTOD.js +7 -0
  61. package/dist/cli-bundle/focused-chunks/stage-MZSVQYO4.js +2 -0
  62. package/dist/cli-bundle/main.js +3 -3
  63. package/dist/cli-bundle/sdk-authoring.js +1 -1
  64. package/dist/cli-bundle/sdk-contracts.js +1 -1
  65. package/dist/cli-bundle/sdk-core.js +29 -23
  66. package/dist/cli-bundle/sdk-governance.js +1 -1
  67. package/dist/cli-bundle/sdk-graph.js +1 -1
  68. package/dist/cli-bundle/sdk-merge.js +66 -52
  69. package/dist/cli-bundle/sdk-query.js +1 -1
  70. package/dist/cli-bundle/sdk-runtime.js +1 -1
  71. package/dist/cli-bundle/sdk-testing.js +1 -1
  72. package/dist/cli-bundle/sdk.js +2 -2
  73. package/dist/core/history/event-index.d.ts +8 -1
  74. package/dist/core/history/event-index.js +19 -18
  75. package/dist/core/item/item-format.js +1 -1
  76. package/dist/core/lock/lock.d.ts +8 -1
  77. package/dist/core/lock/lock.js +3 -3
  78. package/dist/core/output/output.js +2 -2
  79. package/dist/core/store/paths.js +1 -1
  80. package/dist/core/telemetry/policy.d.ts +2 -0
  81. package/dist/core/telemetry/policy.js +1 -1
  82. package/dist/core/telemetry/runtime.d.ts +5 -3
  83. package/dist/core/telemetry/runtime.js +3 -3
  84. package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -1
  85. package/dist/sdk/cli-contracts/flag-contracts.js +1 -1
  86. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -1
  87. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +1 -0
  88. package/dist/sdk/cli-contracts/runtime-contracts.js +1 -1
  89. package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -1
  90. package/dist/sdk/cli-contracts/tool-schema.js +1 -1
  91. package/dist/sdk/extension/install-sources.js +3 -3
  92. package/dist/sdk/extension/shared.js +1 -1
  93. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
  94. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
  95. package/dist/sdk/governance/health/projection.d.ts +37 -0
  96. package/dist/sdk/governance/health/projection.js +2 -0
  97. package/dist/sdk/governance/health.d.ts +7 -18
  98. package/dist/sdk/governance/health.js +2 -2
  99. package/dist/sdk/history-repair.js +1 -1
  100. package/dist/sdk/merge/driver.js +7 -1
  101. package/dist/sdk/merge/indexed-receipt-blobs.d.ts +2 -0
  102. package/dist/sdk/merge/indexed-receipt-blobs.js +4 -0
  103. package/dist/sdk/merge/install.d.ts +8 -0
  104. package/dist/sdk/merge/install.js +3 -3
  105. package/dist/sdk/merge/receipts.d.ts +6 -0
  106. package/dist/sdk/merge/receipts.js +2 -2
  107. package/dist/sdk/merge/reconcile.d.ts +6 -0
  108. package/dist/sdk/merge/reconcile.js +1 -1
  109. package/dist/sdk/merge/settlement-hook.d.ts +12 -0
  110. package/dist/sdk/merge/settlement-hook.js +7 -0
  111. package/dist/sdk/merge/stage.d.ts +13 -0
  112. package/dist/sdk/merge/stage.js +2 -0
  113. package/dist/sdk/mutation-events.js +1 -1
  114. package/dist/sdk/public-surface.json +1 -1
  115. package/dist/sdk/query/list.d.ts +2 -0
  116. package/dist/sdk/query/list.js +1 -1
  117. package/dist/sdk/runtime-extended-actions.js +1 -1
  118. package/dist/types.d.ts +2 -2
  119. package/dist/types.js +1 -1
  120. package/docs/COMMANDS.md +39 -0
  121. package/docs/CONFIGURATION.md +36 -1
  122. package/docs/DEVELOPMENT_DEPENDENCY_SECURITY.md +22 -3
  123. package/docs/MERGE_SAFETY.md +88 -5
  124. package/docs/OUTPUT_PROJECTION_CONTRACTS.md +10 -0
  125. package/docs/RELEASING.md +8 -1
  126. package/docs/SDK.md +26 -0
  127. package/docs/SDK_CONTEXT_COORDINATION.md +71 -7
  128. package/docs/SDK_STORAGE_LIFECYCLE.md +24 -2
  129. package/docs/TESTING.md +15 -0
  130. package/docs/examples/ci/github-actions-pm-extension-gate.yml +1 -1
  131. package/docs/examples/ci/gitlab-ci-pm-extension-gate.yml +1 -1
  132. package/docs/examples/ci/jenkins-pm-extension-gate.Jenkinsfile +1 -1
  133. package/docs/generated/FLAG_LEXICON_BUDGETS.md +2 -2
  134. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +6 -3
  135. package/marketplace.json +1 -1
  136. package/node_modules/@opentelemetry/core/package.json +2 -1
  137. package/node_modules/@opentelemetry/instrumentation/package.json +2 -1
  138. package/node_modules/@opentelemetry/resources/package.json +2 -1
  139. package/node_modules/@opentelemetry/sdk-trace/package.json +2 -1
  140. package/node_modules/@opentelemetry/sdk-trace-base/package.json +2 -1
  141. package/node_modules/@sentry/core/build/cjs/client.js +5 -4
  142. package/node_modules/@sentry/core/build/cjs/tracing/ai/gen-ai-attributes.js +0 -4
  143. package/node_modules/@sentry/core/build/cjs/tracing/ai/utils.js +33 -23
  144. package/node_modules/@sentry/core/build/cjs/tracing/anthropic-ai/index.js +7 -6
  145. package/node_modules/@sentry/core/build/cjs/tracing/anthropic-ai/streaming.js +3 -1
  146. package/node_modules/@sentry/core/build/cjs/tracing/google-genai/index.js +13 -14
  147. package/node_modules/@sentry/core/build/cjs/tracing/google-genai/streaming.js +6 -1
  148. package/node_modules/@sentry/core/build/cjs/tracing/langchain/utils.js +71 -21
  149. package/node_modules/@sentry/core/build/cjs/tracing/langgraph/utils.js +23 -33
  150. package/node_modules/@sentry/core/build/cjs/tracing/openai/streaming.js +6 -0
  151. package/node_modules/@sentry/core/build/cjs/tracing/openai/utils.js +11 -0
  152. package/node_modules/@sentry/core/build/cjs/tracing/workers-ai/utils.js +1 -1
  153. package/node_modules/@sentry/core/build/cjs/utils/eventUtils.js +4 -0
  154. package/node_modules/@sentry/core/build/cjs/utils/prepareEvent.js +2 -2
  155. package/node_modules/@sentry/core/build/cjs/utils/version.js +1 -1
  156. package/node_modules/@sentry/core/build/esm/client.js +6 -5
  157. package/node_modules/@sentry/core/build/esm/package.json +1 -1
  158. package/node_modules/@sentry/core/build/esm/tracing/ai/gen-ai-attributes.js +1 -3
  159. package/node_modules/@sentry/core/build/esm/tracing/ai/utils.js +34 -24
  160. package/node_modules/@sentry/core/build/esm/tracing/anthropic-ai/index.js +8 -7
  161. package/node_modules/@sentry/core/build/esm/tracing/anthropic-ai/streaming.js +3 -1
  162. package/node_modules/@sentry/core/build/esm/tracing/google-genai/index.js +15 -16
  163. package/node_modules/@sentry/core/build/esm/tracing/google-genai/streaming.js +6 -1
  164. package/node_modules/@sentry/core/build/esm/tracing/langchain/utils.js +73 -24
  165. package/node_modules/@sentry/core/build/esm/tracing/langgraph/utils.js +24 -34
  166. package/node_modules/@sentry/core/build/esm/tracing/openai/streaming.js +6 -0
  167. package/node_modules/@sentry/core/build/esm/tracing/openai/utils.js +11 -0
  168. package/node_modules/@sentry/core/build/esm/tracing/workers-ai/utils.js +2 -2
  169. package/node_modules/@sentry/core/build/esm/utils/eventUtils.js +4 -1
  170. package/node_modules/@sentry/core/build/esm/utils/prepareEvent.js +2 -2
  171. package/node_modules/@sentry/core/build/esm/utils/version.js +1 -1
  172. package/node_modules/@sentry/core/build/types/tracing/ai/utils.d.ts +3 -7
  173. package/node_modules/@sentry/core/build/types/tracing/anthropic-ai/types.d.ts +2 -2
  174. package/node_modules/@sentry/core/build/types/tracing/langchain/types.d.ts +15 -0
  175. package/node_modules/@sentry/core/build/types/tracing/langchain/utils.d.ts +1 -0
  176. package/node_modules/@sentry/core/build/types/tracing/langgraph/utils.d.ts +2 -0
  177. package/node_modules/@sentry/core/build/types/tracing/openai/types.d.ts +2 -0
  178. package/node_modules/@sentry/core/build/types/utils/eventUtils.d.ts +2 -1
  179. package/node_modules/@sentry/core/build/types-ts3.8/tracing/ai/utils.d.ts +3 -7
  180. package/node_modules/@sentry/core/build/types-ts3.8/tracing/anthropic-ai/types.d.ts +2 -2
  181. package/node_modules/@sentry/core/build/types-ts3.8/tracing/langchain/types.d.ts +15 -0
  182. package/node_modules/@sentry/core/build/types-ts3.8/tracing/langchain/utils.d.ts +1 -0
  183. package/node_modules/@sentry/core/build/types-ts3.8/tracing/langgraph/utils.d.ts +2 -0
  184. package/node_modules/@sentry/core/build/types-ts3.8/tracing/openai/types.d.ts +2 -0
  185. package/node_modules/@sentry/core/build/types-ts3.8/utils/eventUtils.d.ts +2 -1
  186. package/node_modules/@sentry/core/package.json +1 -1
  187. package/node_modules/@sentry/node/build/esm/package.json +1 -1
  188. package/node_modules/@sentry/node/package.json +5 -5
  189. package/node_modules/@sentry/node-core/build/cjs/integrations/anr/index.js +1 -1
  190. package/node_modules/@sentry/node-core/build/cjs/integrations/local-variables/local-variables-async.js +1 -1
  191. package/node_modules/@sentry/node-core/build/esm/integrations/anr/index.js +1 -1
  192. package/node_modules/@sentry/node-core/build/esm/integrations/anr/worker-script.js +2 -2
  193. package/node_modules/@sentry/node-core/build/esm/integrations/local-variables/local-variables-async.js +1 -1
  194. package/node_modules/@sentry/node-core/build/esm/integrations/local-variables/worker-script.js +1 -1
  195. package/node_modules/@sentry/node-core/build/esm/package.json +1 -1
  196. package/node_modules/@sentry/node-core/package.json +10 -4
  197. package/node_modules/@sentry/opentelemetry/build/esm/package.json +1 -1
  198. package/node_modules/@sentry/opentelemetry/package.json +5 -2
  199. package/node_modules/@sentry/server-utils/build/THIRD-PARTY-LICENSES.txt +55 -55
  200. package/node_modules/@sentry/server-utils/build/esm/package.json +1 -1
  201. package/node_modules/@sentry/server-utils/package.json +2 -2
  202. package/node_modules/@toon-format/toon/README.md +10 -41
  203. package/node_modules/@toon-format/toon/dist/index.d.mts +12 -36
  204. package/node_modules/@toon-format/toon/dist/index.mjs +134 -202
  205. package/node_modules/@toon-format/toon/package.json +2 -2
  206. package/node_modules/debug/package.json +3 -0
  207. package/node_modules/fdir/package.json +3 -0
  208. package/node_modules/has-flag/index.d.ts +39 -0
  209. package/node_modules/has-flag/index.js +8 -0
  210. package/node_modules/has-flag/license +9 -0
  211. package/node_modules/has-flag/package.json +46 -0
  212. package/node_modules/has-flag/readme.md +89 -0
  213. package/node_modules/supports-color/browser.js +5 -0
  214. package/node_modules/supports-color/index.js +135 -0
  215. package/node_modules/supports-color/license +9 -0
  216. package/node_modules/supports-color/package.json +53 -0
  217. package/node_modules/supports-color/readme.md +76 -0
  218. package/package.json +4 -4
  219. package/packages/pm-beads/package.json +1 -1
  220. package/packages/pm-calendar/package.json +1 -1
  221. package/packages/pm-command-kit/package.json +1 -1
  222. package/packages/pm-digital-twin/package.json +1 -1
  223. package/packages/pm-governance-audit/package.json +1 -1
  224. package/packages/pm-guide-shell/package.json +1 -1
  225. package/packages/pm-kanban/package.json +1 -1
  226. package/packages/pm-lifecycle-hooks/package.json +1 -1
  227. package/packages/pm-linked-test-adapters/package.json +1 -1
  228. package/packages/pm-search-advanced/package.json +1 -1
  229. package/packages/pm-templates/package.json +1 -1
  230. package/packages/pm-todos/package.json +1 -1
  231. package/packages/pm-vcs/package.json +1 -1
  232. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  233. package/plugins/pm-claude/package.json +1 -1
  234. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  235. package/plugins/pm-codex/package.json +1 -1
  236. package/plugins/pm-codex/plugin.json +1 -1
  237. package/runtime-dependencies.json +1 -1
  238. package/dist/cli-bundle/chunks/chunk-4PNPDT2N.js +0 -236
  239. package/dist/cli-bundle/chunks/chunk-HY7FQ7QX.js +0 -2
  240. package/dist/cli-bundle/chunks/chunk-J4LPQCET.js +0 -8
  241. package/dist/cli-bundle/chunks/chunk-OZCSXX4D.js +0 -80
  242. package/dist/cli-bundle/chunks/chunk-VMCSTFSO.js +0 -2
  243. package/dist/cli-bundle/chunks/chunk-X2ONXFBP.js +0 -3
  244. package/dist/cli-bundle/chunks/chunk-X53HM753.js +0 -20
  245. package/dist/cli-bundle/chunks/register-mutation-EQYMT32A.js +0 -20
  246. package/dist/cli-bundle/chunks/register-operations-VXBGE4XI.js +0 -2
  247. package/dist/cli-bundle/chunks/register-setup-UUDEGFRO.js +0 -2
  248. package/dist/cli-bundle/focused-chunks/chunk-5JEFDEL3.js +0 -166
  249. package/dist/cli-bundle/focused-chunks/chunk-AH6NX6GM.js +0 -3
  250. package/dist/cli-bundle/focused-chunks/chunk-JXR6UKFM.js +0 -3
  251. package/dist/cli-bundle/focused-chunks/chunk-MBQF6HT6.js +0 -2
  252. package/dist/cli-bundle/focused-chunks/chunk-NZO7GOXD.js +0 -20
  253. package/dist/cli-bundle/focused-chunks/chunk-PYC7BF6Z.js +0 -8
  254. package/dist/cli-bundle/focused-chunks/chunk-QOSVJDOO.js +0 -75
  255. package/dist/cli-bundle/focused-chunks/chunk-RHTH5ILM.js +0 -2
  256. package/dist/cli-bundle/focused-chunks/chunk-TRFVAWF2.js +0 -26
package/docs/SDK.md CHANGED
@@ -210,6 +210,32 @@ follow the migration guidance for changed unions or error codes. The shared
210
210
  [primitive inventory](SDK_PRIMITIVE_INVENTORY.md) records CLI/MCP ownership:
211
211
  presentation modules import the SDK and have zero private-core edges.
212
212
 
213
+ ### Portable merge settlement
214
+
215
+ Tracked by [pm-gh1475](../.agents/pm/issues/pm-gh1475.toon) and
216
+ [pm-gh1491](../.agents/pm/issues/pm-gh1491.toon). Import `runMergeInstall`,
217
+ `runMergeReconcile`, and `inspectMergeReceiptEvidence` from
218
+ `@unbrained/pm-cli/sdk/merge`. `runMergeInstall({ preCommitHook: true }, global)`
219
+ explicitly installs the merge-aware pre-commit hook; the default installs no hook.
220
+ `runMergeReconcile({ stage: true }, global)` previews first and stages only
221
+ verified lossless history and receipt artifacts. It refuses forced acceptance,
222
+ competing values, unrelated drift, dirty reconciliation paths and unresolved Git
223
+ paths. `staged_paths` reports exactly which relative paths were added to the index.
224
+
225
+ The single-commit journey pauses Git with `git merge --no-commit --no-ff` before
226
+ reconciliation or an opted-in pre-commit hook runs. `durable_receipt_ids` on the
227
+ inspection result reports counterparts with matching immutable provenance in
228
+ the active Git index. `unstaged_durable_receipt_ids` separates valid filesystem
229
+ sidecars that a read-only preview may inspect. Guarded staging prepares new
230
+ sidecars before auditing and restores their new index entries if apply fails.
231
+ Inspection lists indexed candidates once and reads bounded object batches.
232
+ Guarded settlement resolves tracker aliases before preview, proof verification
233
+ and apply, so every phase uses the same physical tracker root.
234
+ Ordinary apply requires indexed proof first. Missing portable proof
235
+ refuses an audit write even with `force`; local receipts alone cannot authorize
236
+ committed history references. See [Merge safety](MERGE_SAFETY.md#settle-a-lossless-merge-in-one-commit)
237
+ for the complete operator workflow and recovery boundaries.
238
+
213
239
  ### Build an entire custom project tool
214
240
 
215
241
  The [SDK-only custom-tool exemplar](examples/sdk-custom-tool/README.md)
@@ -1,6 +1,8 @@
1
1
  # SDK context coordination primitives
2
2
 
3
- Trackers: [pm-e200](../.agents/pm/features/pm-e200.toon), [pm-ez1dfg](../.agents/pm/tasks/pm-ez1dfg.toon), [pm-4ri6](../.agents/pm/features/pm-4ri6.toon), and [pm-hcrmye](../.agents/pm/issues/pm-hcrmye.toon).
3
+ Trackers: [pm-e200](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/features/pm-e200.toon), [pm-ez1dfg](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/tasks/pm-ez1dfg.toon), [pm-4ri6](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/features/pm-4ri6.toon), [pm-hcrmye](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-hcrmye.toon), [pm-gh1485](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-gh1485.toon), and [pm-xj80p9](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-xj80p9.toon).
4
+
5
+ Tracker records live in the repository and are excluded from the npm package.
4
6
 
5
7
  `pm` treats project management as context management. These primitives let an
6
8
  agent learn what changed, avoid creating redundant work, and keep that work
@@ -38,10 +40,61 @@ idempotently or deduplicate replays. `--cursor-mode row` preserves the previous
38
40
  shape with one `cursor` per event and no trailer for consumers that checkpoint
39
41
  every row. Already issued version-1 cursors remain accepted by `--since`.
40
42
 
41
- Node runtimes use the rebuildable SQLite event projection. Runtimes such as Bun
42
- that do not expose `node:sqlite` transparently scan the authoritative history
43
+ Version-1 cursor ordering uses recorded timestamps, stream ids, and offsets.
44
+ A fact committed later with an older timestamp falls before an advanced cursor.
45
+ Clock-independent ordering and late-commit recovery remain tracked by
46
+ [pm-10l1vm](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-10l1vm.toon). Hosts needing complete concurrent
47
+ observation can retain a fixed lower boundary and deduplicate snapshots by
48
+ `item_id` and `version` while work is being committed.
49
+
50
+ Runtimes exposing `node:sqlite` use the rebuildable SQLite event projection.
51
+ Runtimes without it transparently scan the authoritative history
43
52
  streams with the same ordering, filters, pagination, and cursor contract; pages
44
53
  identify that path with `source: "authoritative_history"`.
54
+ Writers without SQLite use the same pending and committed invalidation protocol,
55
+ so a later Node writer cannot certify a cache that omitted their facts.
56
+ Incremental writes also verify the previous size receipt before advancing it,
57
+ so merged history cannot be hidden by a later append. Upgraded runtimes rebuild
58
+ legacy projections that could contain omitted facts with apparently current
59
+ receipts; authoritative history does not require a format migration.
60
+
61
+ Index readers take a synchronous SQLite read transaction containing both event
62
+ rows and their stream-size receipts, then close the database before checking
63
+ authoritative files. They acquire neither history-index writer lock. File
64
+ identity and write timestamps, authoritative stream sizes, and pending or
65
+ committed invalidations must still match before a snapshot is returned. A
66
+ concurrent change refuses the optional snapshot; it cannot certify older rows
67
+ using a newer size receipt.
68
+
69
+ Incremental projection writes also use a zero SQLite busy timeout. Native
70
+ reader or writer contention falls back to the authoritative append and
71
+ invalidation protocol instead of spending a separate SQLite wait budget.
72
+ An unexpired, token-owned append lease marks ordinary incremental work as
73
+ active until its commit or invalidation completes. Native contention retains
74
+ the cache file and a committed contention marker; a zero-wait native probe
75
+ distinguishes an ongoing contender from settled damage before requesting repair.
76
+
77
+ Authoritative writers fail fast when an active owner holds the projection writer
78
+ lock, including when a full repair owns it. They publish an invalidation instead.
79
+ Stale-owner recovery follows the built-in lock policy. A repair
80
+ refuses publication if those markers changed during its scan. Full projection
81
+ construction yields between batches, and marker cleanup occurs outside the
82
+ short invalidation publication lock.
83
+ After a refused full publication or failed repair, a best effort per-tracker runtime receipt
84
+ defers automatic repair for five seconds. Busy periods therefore do not restart
85
+ a complete SQLite build on every read. Pages and recency reads continue using
86
+ authoritative history; after the cooldown, a later read can repair during a
87
+ quiet interval. This backoff bounds repair frequency, not index availability
88
+ during continuous writes.
89
+
90
+ Transient generation changes and SQLite contention use authoritative fallback
91
+ directly. Missing, incompatible, or damaged projections receive one optional
92
+ repair attempt without waiting for either projection lock. Repair failure or
93
+ invalidation after rebuilding
94
+ falls back to authoritative JSONL with the same filters and cursor format.
95
+ Pages may change `source` between calls. A fallback still reports malformed or
96
+ inaccessible authoritative history as an error. A successful repair may scan
97
+ the workspace; this protocol bounds lock waiting, not total execution time.
45
98
 
46
99
  `--full` also includes the complete authoritative history entry.
47
100
  `--type`, `--author`, and `--item` accept repeatable or comma-separated values.
@@ -109,10 +162,7 @@ Package authors can query the same scorer used by create/copy and the bundled
109
162
  governance audit:
110
163
 
111
164
  ```ts
112
- import {
113
- findSimilarItems,
114
- scoreItemSimilarity,
115
- } from "@unbrained/pm-cli/sdk";
165
+ import { findSimilarItems, scoreItemSimilarity } from "@unbrained/pm-cli/sdk";
116
166
 
117
167
  const score = scoreItemSimilarity("Fix OAuth refresh", "Fix oauth refresh");
118
168
  const matches = await findSimilarItems(
@@ -155,6 +205,20 @@ accepted aliases for existing automation.
155
205
 
156
206
  ## Scale contract
157
207
 
208
+ The mixed-reader acceptance used 100 fixed-boundary snapshot observers,
209
+ five SDK writer lanes, and five CLI writer lanes, with five updates per lane.
210
+ Both separate traced and untraced cohorts passed 5,000 unique observations,
211
+ duplicate-free pages, strict history integrity, and a 2,000 ms first-observation
212
+ ceiling. These are bounded host measurements recorded in
213
+ [pm-gh1485](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-gh1485.toon).
214
+
215
+ The native regression suspends filesystem validation and requires an
216
+ authoritative writer to finish before that reader resumes. Run it with:
217
+
218
+ ```bash
219
+ node scripts/run-tests.mjs test -- tests/unit/core/history/event-index-snapshots.spec.ts
220
+ ```
221
+
158
222
  Event catch-up reads from a persistent ordered projection and follows only new
159
223
  rows. Similarity governance is zero-cost when off and index-bounded when
160
224
  enabled on an indexed workspace. Production bundles are syntax-, whitespace-,
@@ -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
@@ -97,6 +97,13 @@ so PR-local CodeFactor maintainability annotations fail locally before commit or
97
97
  push. Existing legacy high-complexity test fixtures are tracked separately and
98
98
  must not be used as precedent for new changed production/script code.
99
99
 
100
+ Module-usage checks share the SDK boundary's literal-specifier parser and walk
101
+ nested AST nodes, including lazy `import("./module.js")` references. Unused
102
+ modules, comment-only references, and computed paths do not gain incoming
103
+ references. The regression is tracked by
104
+ [pm-f38ovr](../.agents/pm/issues/pm-f38ovr.toon); no module allowance or threshold
105
+ increase is required to keep optional SDK capabilities lazy.
106
+
100
107
  The same required static gate validates an explicit seven-day Dependabot
101
108
  cooldown for every updater and requires both npm and GitHub Actions entries.
102
109
  Missing values, semver overrides outside 7–90 days, invalid YAML, removed
@@ -209,6 +216,14 @@ Use focused runs while iterating, then run coverage before closure when risk or
209
216
 
210
217
  ## CI Retry and Timeout Diagnostics
211
218
 
219
+ The required `Gates (coverage)` job runs after the coverage matrix settles and
220
+ explicitly requires every shard to succeed. Failed, canceled, skipped, or missing
221
+ shard outcomes fail that required context before checkout or report merging.
222
+ Shard artifacts retain failure diagnostics. After successful shard admission,
223
+ coverage-threshold failures still retain merged reports and Codecov uploads.
224
+ This enforcement is tracked by [pm-0p4aal](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-0p4aal.toon).
225
+ Tracker records live in the repository and are excluded from the npm package.
226
+
212
227
  Platform regressions from [pm-hrhfgi](../.agents/pm/issues/pm-hrhfgi.toon) and
213
228
  [pm-zk67yf](../.agents/pm/issues/pm-zk67yf.toon) have portable negative controls.
214
229
  Complete source scans process at most 32 item files per batch; the descriptor
@@ -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
  }
@@ -39,7 +39,7 @@ This file is generated by `listPmFlagLexicon()`. Compatibility aliases do not co
39
39
  | `history-repair` | evidence | 27 | 27 |
40
40
  | `history-compact` | evidence | 30 | 30 |
41
41
  | `history-author-acknowledge` | evidence | 28 | 28 |
42
- | `merge` | workspace | 27 | 27 |
42
+ | `merge` | workspace | 29 | 29 |
43
43
  | `schema` | workspace | 43 | 43 |
44
44
  | `profile` | workspace | 22 | 22 |
45
45
  | `activity` | context | 35 | 35 |
@@ -110,7 +110,7 @@ This file is generated by `listPmFlagLexicon()`. Compatibility aliases do not co
110
110
  | `item test worker` | internal | 20 | 20 |
111
111
  | `history acknowledge` | evidence | 28 | 28 |
112
112
  | `item copy` | intake | 24 | 24 |
113
- | `workspace merge` | workspace | 27 | 27 |
113
+ | `workspace merge` | workspace | 29 | 29 |
114
114
  | `item duplicates` | context | 25 | 25 |
115
115
  | `calendar meet` | automation | 33 | 33 |
116
116
  | `calendar event` | automation | 33 | 33 |
@@ -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: 419
7
+ - Catalog error codes: 422
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: 400
12
- - Coverage fraction: 0.045346
11
+ - Uncovered error codes: 403
12
+ - Coverage fraction: 0.045024
13
13
  - Closed-domain probes: 19
14
14
  - Grammar probes: 117
15
15
 
@@ -221,9 +221,12 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
221
221
  | `merge_git_config_unwritable` | `merge_git_config_unwritable` | uncovered | none | 0 |
222
222
  | `merge_receipt_evidence_invalid` | `merge_receipt_evidence_invalid` | uncovered | none | 0 |
223
223
  | `merge_receipt_history_reference_missing` | `merge_receipt_history_reference_missing` | uncovered | none | 0 |
224
+ | `merge_receipt_not_portable` | `merge_receipt_not_portable` | uncovered | none | 0 |
224
225
  | `merge_receipts_pending` | `merge_receipts_pending` | uncovered | none | 0 |
225
226
  | `merge_reconcile_receipt_evidence_untrusted` | `merge_reconcile_receipt_evidence_untrusted` | uncovered | none | 0 |
226
227
  | `merge_root_not_found` | `merge_root_not_found` | uncovered | none | 0 |
228
+ | `merge_settlement_hook_conflict` | `merge_settlement_hook_conflict` | uncovered | none | 0 |
229
+ | `merge_settlement_review_required` | `merge_settlement_review_required` | uncovered | none | 0 |
227
230
  | `missing_allowed_values` | `missing_allowed_values` | uncovered | none | 0 |
228
231
  | `missing_budget` | `missing_budget` | uncovered | none | 0 |
229
232
  | `missing_cli_flag` | `missing_cli_flag` | 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.17","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.17","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.19","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.19","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) {