@unbrained/pm-cli 2026.10.13 → 2026.10.14

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 (98) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +19 -0
  3. package/dist/cli/extension-command-help.js +2 -2
  4. package/dist/cli/extension-command-options.js +1 -1
  5. package/dist/cli/main.js +2 -2
  6. package/dist/cli-bundle/bundle-manifest.json +1 -1
  7. package/dist/cli-bundle/chunks/{chunk-AM2XOZKE.js → chunk-2UKKO45F.js} +2 -2
  8. package/dist/cli-bundle/chunks/chunk-3S5SEMEB.js +8 -0
  9. package/dist/cli-bundle/chunks/{chunk-LBDWFWPK.js → chunk-5LU6PWA4.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-RL45OYTL.js → chunk-66BZVFIK.js} +2 -2
  11. package/dist/cli-bundle/chunks/chunk-IDEHMKYZ.js +235 -0
  12. package/dist/cli-bundle/chunks/{chunk-UBTYYZIE.js → chunk-JTF6VMXH.js} +2 -2
  13. package/dist/cli-bundle/chunks/{chunk-YH6H3UVE.js → chunk-LE4IEHDG.js} +3 -3
  14. package/dist/cli-bundle/chunks/{chunk-APWPC4ZZ.js → chunk-LKESCZEN.js} +2 -2
  15. package/dist/cli-bundle/chunks/{chunk-HXHFKXLV.js → chunk-LOSRTNNP.js} +2 -2
  16. package/dist/cli-bundle/chunks/{chunk-N5EXRYCZ.js → chunk-MAT4AP7P.js} +2 -2
  17. package/dist/cli-bundle/chunks/{chunk-PSNS537F.js → chunk-PP3BVMFL.js} +28 -28
  18. package/dist/cli-bundle/chunks/{chunk-IFPJDJUM.js → chunk-UNQZGMJL.js} +2 -2
  19. package/dist/cli-bundle/chunks/{chunk-WYZGZV2M.js → chunk-YXRAYL7H.js} +2 -2
  20. package/dist/cli-bundle/chunks/{register-list-query-BJ742QOR.js → register-list-query-GBLTOQQL.js} +2 -2
  21. package/dist/cli-bundle/chunks/{register-mutation-GGGBRIH2.js → register-mutation-TNRHNK4N.js} +2 -2
  22. package/dist/cli-bundle/chunks/{register-operations-E6HXYHNM.js → register-operations-J3WXP3MA.js} +2 -2
  23. package/dist/cli-bundle/chunks/{register-setup-4ZVTVEPY.js → register-setup-HLSKKU4V.js} +2 -2
  24. package/dist/cli-bundle/focused-chunks/{chunk-73UNAJHD.js → chunk-23ACMPGB.js} +2 -2
  25. package/dist/cli-bundle/focused-chunks/{chunk-NNW5BS5L.js → chunk-4UA7KY4V.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/{chunk-KGFRQ34R.js → chunk-AULVKHYX.js} +2 -2
  27. package/dist/cli-bundle/focused-chunks/{chunk-3LQEBXU5.js → chunk-BUAGNTLG.js} +2 -2
  28. package/dist/cli-bundle/focused-chunks/{chunk-DVK7VKZL.js → chunk-ELQNEJDA.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-SOB7X4FJ.js → chunk-ESOW6PH4.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/chunk-HNRI2KBT.js +3 -0
  31. package/dist/cli-bundle/focused-chunks/{chunk-IIKFTJVC.js → chunk-IGBSAHCA.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/{chunk-F5J3ATMV.js → chunk-JDVZF75H.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/{chunk-RU6GCFN3.js → chunk-KSMQEB3V.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/chunk-LKWDWER4.js +20 -0
  35. package/dist/cli-bundle/focused-chunks/{chunk-RAA7SVRA.js → chunk-QIU4Y3AB.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/{chunk-R23T7GFZ.js → chunk-RHQCQTZA.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/{chunk-UPJA45K7.js → chunk-WIXZF5SS.js} +18 -18
  38. package/dist/cli-bundle/focused-chunks/{chunk-6BTUISKV.js → chunk-Y5A4XOSK.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/{chunk-QMNAY25P.js → chunk-YJNKISEI.js} +6 -6
  40. package/dist/cli-bundle/main.js +22 -22
  41. package/dist/cli-bundle/sdk-authoring.js +1 -1
  42. package/dist/cli-bundle/sdk-contracts.js +1 -1
  43. package/dist/cli-bundle/sdk-core.js +22 -22
  44. package/dist/cli-bundle/sdk-governance.js +1 -1
  45. package/dist/cli-bundle/sdk-graph.js +1 -1
  46. package/dist/cli-bundle/sdk-merge.js +46 -46
  47. package/dist/cli-bundle/sdk-query.js +1 -1
  48. package/dist/cli-bundle/sdk-runtime.js +1 -1
  49. package/dist/cli-bundle/sdk-testing.js +1 -1
  50. package/dist/cli-bundle/sdk.js +7 -7
  51. package/dist/core/extensions/flag-definition-validation.d.ts +13 -0
  52. package/dist/core/extensions/flag-definition-validation.js +1 -1
  53. package/dist/core/extensions/flag-value-types.js +1 -1
  54. package/dist/core/sentry/helpers.d.ts +2 -0
  55. package/dist/core/sentry/helpers.js +1 -1
  56. package/dist/core/sentry/instrument.d.ts +2 -0
  57. package/dist/core/sentry/instrument.js +1 -1
  58. package/dist/core/telemetry/runtime.d.ts +1 -1
  59. package/dist/core/telemetry/runtime.js +2 -2
  60. package/dist/sdk/cli-contracts/runtime-contracts.js +1 -1
  61. package/dist/sdk/governance/defect-recurrence.js +2 -1
  62. package/dist/sdk/merge/install.js +1 -1
  63. package/dist/sdk/public-surface.json +1 -1
  64. package/dist/sdk/runtime-primitives.d.ts +4 -2
  65. package/dist/sdk/runtime-primitives.js +1 -1
  66. package/dist/sdk/testing.d.ts +4 -0
  67. package/dist/sdk/testing.js +2 -2
  68. package/docs/CONFIGURATION.md +43 -0
  69. package/docs/DEFECT_RECURRENCE.md +8 -0
  70. package/docs/EXTENSIONS.md +1 -1
  71. package/docs/EXTENSION_AUTHOR_CONTRACTS.md +19 -0
  72. package/docs/MERGE_SAFETY.md +8 -0
  73. package/docs/SDK.md +19 -0
  74. package/marketplace.json +1 -1
  75. package/package.json +1 -1
  76. package/packages/pm-beads/package.json +1 -1
  77. package/packages/pm-calendar/package.json +1 -1
  78. package/packages/pm-command-kit/package.json +1 -1
  79. package/packages/pm-digital-twin/package.json +1 -1
  80. package/packages/pm-governance-audit/package.json +1 -1
  81. package/packages/pm-guide-shell/package.json +1 -1
  82. package/packages/pm-kanban/package.json +1 -1
  83. package/packages/pm-lifecycle-hooks/package.json +1 -1
  84. package/packages/pm-linked-test-adapters/package.json +1 -1
  85. package/packages/pm-search-advanced/package.json +1 -1
  86. package/packages/pm-templates/package.json +1 -1
  87. package/packages/pm-todos/package.json +1 -1
  88. package/packages/pm-vcs/package.json +1 -1
  89. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  90. package/plugins/pm-claude/package.json +1 -1
  91. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  92. package/plugins/pm-codex/package.json +1 -1
  93. package/plugins/pm-codex/plugin.json +1 -1
  94. package/runtime-dependencies.json +1 -1
  95. package/dist/cli-bundle/chunks/chunk-DJDRHJBP.js +0 -234
  96. package/dist/cli-bundle/chunks/chunk-DUK5DHI6.js +0 -8
  97. package/dist/cli-bundle/focused-chunks/chunk-IOTNG6CN.js +0 -2
  98. package/dist/cli-bundle/focused-chunks/chunk-S6ITXQ5T.js +0 -20
@@ -3,6 +3,19 @@
3
3
  * legacy underscore aliases, and an optional value placeholder.
4
4
  */
5
5
  export declare const EXTENSION_LONG_FLAG_PATTERN: RegExp;
6
+ /** Canonical identity and value syntax of a supported long flag declaration. */
7
+ export interface ExtensionLongFlagSpelling {
8
+ /** Bare long option identity used for dispatch and discovery. */
9
+ name: string;
10
+ /** Inline value label, or null for a bare declaration. */
11
+ valueName: string | null;
12
+ /** Whether the inline value uses optional brackets. */
13
+ optional: boolean;
14
+ }
15
+ /** Parse supported legacy placeholder syntax without duplicating its option identity. */
16
+ export declare function parseExtensionLongFlagToken(value: unknown): ExtensionLongFlagSpelling | null;
17
+ /** Resolve supported canonical names while preserving trimmed legacy spellings for permissive consumers. Validation remains separate. */
18
+ export declare function resolveExtensionLongFlagName(value: unknown): string | null;
6
19
  /** Machine-readable failure returned for one invalid extension flag token. */
7
20
  export type ExtensionFlagTokenFailure = "host_owned_flag_collision" | "malformed_long_flag";
8
21
  /** Invalid token and failure classification returned for one flag definition. */
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="0403fec1-f10a-5361-982b-c127c2617e95")}catch{}})();import{RESERVED_EXTENSION_HOST_FLAG_NAMES}from"./reserved-host-flags.js";const EXTENSION_LONG_FLAG_PATTERN=/^--[a-z0-9][a-z0-9_-]*(?:[ =](?:<[^<>]+>|\[[^[\]]+\]))?$/;function validateExtensionLongFlagToken(value){if(typeof value!="string")return null;const token=value.trim(),hostToken=token.split(/[ =]/,1)[0];return RESERVED_EXTENSION_HOST_FLAG_NAMES.has(hostToken)?"host_owned_flag_collision":EXTENSION_LONG_FLAG_PATTERN.test(token)?null:"malformed_long_flag"}function findExtensionFlagTokenFailure(long,short){const reserved=[long,short].find(token2=>typeof token2=="string"&&RESERVED_EXTENSION_HOST_FLAG_NAMES.has(token2.trim().split(/[ =]/,1)[0]));if(typeof reserved=="string")return{token:reserved.trim().split(/[ =]/,1)[0],failure:"host_owned_flag_collision"};if(typeof long!="string")return null;const token=long.trim(),failure=validateExtensionLongFlagToken(token);return failure===null?null:{token,failure}}function describeExtensionLongFlagFailure(token,failure){return failure==="host_owned_flag_collision"?`cannot shadow host-owned global flag "${token}"; read it from context.global instead`:`long flag "${token}" must start with a double-dash name such as "--my-flag" or "--my-flag <value>"`}export{EXTENSION_LONG_FLAG_PATTERN,describeExtensionLongFlagFailure,findExtensionFlagTokenFailure,validateExtensionLongFlagToken};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="896ebde0-4ca1-50ed-bb8e-2a8c2d978d94")}catch{}})();import{RESERVED_EXTENSION_HOST_FLAG_NAMES}from"./reserved-host-flags.js";const EXTENSION_LONG_FLAG_PATTERN=/^(--[a-z0-9][a-z0-9_-]*)(?:[ =](<[^<>]+>|\[[^[\]]+\]))?$/;function parseExtensionLongFlagToken(value){if(typeof value!="string")return null;const matched=EXTENSION_LONG_FLAG_PATTERN.exec(value.trim());if(!matched)return null;const placeholder=matched[2];return{name:matched[1],valueName:placeholder?placeholder.slice(1,-1):null,optional:placeholder?.startsWith("[")??!1}}function resolveExtensionLongFlagName(value){const parsed=parseExtensionLongFlagToken(value);return parsed?parsed.name:typeof value=="string"&&value.trim()||null}function validateExtensionLongFlagToken(value){if(typeof value!="string")return null;const token=value.trim(),hostToken=token.split(/[ =]/,1)[0];return RESERVED_EXTENSION_HOST_FLAG_NAMES.has(hostToken)?"host_owned_flag_collision":EXTENSION_LONG_FLAG_PATTERN.test(token)?null:"malformed_long_flag"}function findExtensionFlagTokenFailure(long,short){const reserved=[long,short].find(token2=>typeof token2=="string"&&RESERVED_EXTENSION_HOST_FLAG_NAMES.has(token2.trim().split(/[ =]/,1)[0]));if(typeof reserved=="string")return{token:reserved.trim().split(/[ =]/,1)[0],failure:"host_owned_flag_collision"};if(typeof long!="string")return null;const token=long.trim(),failure=validateExtensionLongFlagToken(token);return failure===null?null:{token,failure}}function describeExtensionLongFlagFailure(token,failure){return failure==="host_owned_flag_collision"?`cannot shadow host-owned global flag "${token}"; read it from context.global instead`:`long flag "${token}" must start with a double-dash name such as "--my-flag" or "--my-flag <value>"`}export{EXTENSION_LONG_FLAG_PATTERN,describeExtensionLongFlagFailure,findExtensionFlagTokenFailure,parseExtensionLongFlagToken,resolveExtensionLongFlagName,validateExtensionLongFlagToken};
2
2
  //# sourceMappingURL=flag-definition-validation.js.map
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a2ab8801-f75b-5ba0-88a5-354d24c37c6f")}catch{}})();const FLAG_VALUE_KIND_BY_ALIAS=Object.freeze({string:"string",number:"number",int:"number",integer:"number",float:"number",boolean:"boolean",bool:"boolean"});function resolveFlagValueKind(raw){return typeof raw!="string"?null:FLAG_VALUE_KIND_BY_ALIAS[raw.trim().toLowerCase()]??null}function flattenFlagListValue(value){const entries=[],collect=input=>{if(Array.isArray(input)){for(const item of input)collect(item);return}if(typeof input=="string"){for(const part of input.split(",")){const trimmed=part.trim();trimmed.length>0&&entries.push(trimmed)}return}input!=null&&entries.push(input)};return collect(value),entries}function isFlagDefaultValueCoercible(value,kind){return kind==="string"?!0:kind==="number"?typeof value=="number"?Number.isFinite(value):typeof value=="string"&&value.trim().length>0&&Number.isFinite(Number(value)):typeof value=="boolean"?!0:typeof value=="string"&&["true","false","1","0"].includes(value.trim().toLowerCase())}export{flattenFlagListValue,isFlagDefaultValueCoercible,resolveFlagValueKind};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="37bea108-61cc-53ca-b09b-e890f9d92a68")}catch{}})();const FLAG_VALUE_KIND_BY_ALIAS=Object.freeze({string:"string",number:"number",int:"number",integer:"number",float:"number",boolean:"boolean",bool:"boolean"});function resolveFlagValueKind(raw){if(typeof raw!="string")return null;const alias=raw.trim().toLowerCase();return Object.hasOwn(FLAG_VALUE_KIND_BY_ALIAS,alias)?FLAG_VALUE_KIND_BY_ALIAS[alias]:null}function flattenFlagListValue(value){const entries=[],collect=input=>{if(Array.isArray(input)){for(const item of input)collect(item);return}if(typeof input=="string"){for(const part of input.split(",")){const trimmed=part.trim();trimmed.length>0&&entries.push(trimmed)}return}input!=null&&entries.push(input)};return collect(value),entries}function isFlagDefaultValueCoercible(value,kind){return kind==="string"?!0:kind==="number"?typeof value=="number"?Number.isFinite(value):typeof value=="string"&&value.trim().length>0&&Number.isFinite(Number(value)):typeof value=="boolean"?!0:typeof value=="string"&&["true","false","1","0"].includes(value.trim().toLowerCase())}export{flattenFlagListValue,isFlagDefaultValueCoercible,resolveFlagValueKind};
2
2
  //# sourceMappingURL=flag-value-types.js.map
@@ -7,6 +7,8 @@ source_context_source?: string;
7
7
  }): void;
8
8
  /** Implements sentry start command span for the public runtime surface of this module. */
9
9
  export declare function sentryStartCommandSpan(command: string): void;
10
+ /** Clear the pending command span without ending it or submitting it for export. */
11
+ export declare function sentryDiscardCommandSpan(): void;
10
12
  /** Implements sentry finish command span for the public runtime surface of this module. */
11
13
  export declare function sentryFinishCommandSpan(ok: boolean, error?: string, metadata?: {
12
14
  error_code?: string;
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ceaee876-c2c8-5b28-91ee-f670384fd559")}catch{}})();import{getSentry}from"./instrument.js";import{PmCliError}from"../shared/errors.js";import{EXIT_CODE}from"../shared/constants.js";import{deriveTelemetryCommandResolution,deriveTelemetryCommandTaxonomy}from"../telemetry/observability.js";let activeCommandSpan;function setSpanAttribute(span,key,value){if(value===void 0)return;const attributeTarget=span;typeof attributeTarget.setAttribute=="function"&&attributeTarget.setAttribute(key,value)}function setSentryTagIfPresent(Sentry,key,value){typeof value=="string"&&value.trim().length>0&&Sentry.setTag(key,value)}function setSentryCommandFinishTags(Sentry,normalizedOk,metadata){Sentry.setTag("pm.ok",normalizedOk),Sentry.setTag("pm.command_ok",normalizedOk),typeof metadata?.exit_code=="number"&&(Sentry.setTag("pm.exit_code",String(metadata.exit_code)),Sentry.setTag("pm.command_exit_code",String(metadata.exit_code))),setSentryTagIfPresent(Sentry,"pm.error_code",metadata?.error_code),setSentryTagIfPresent(Sentry,"pm.error_category",metadata?.error_category),setSentryTagIfPresent(Sentry,"pm.command_resolution",metadata?.command_resolution),setSentryTagIfPresent(Sentry,"pm.resolution_stage",metadata?.resolution_stage)}function setCommandSpanFinishAttributes(span,normalizedOk,normalizedExitCode,metadata){setSpanAttribute(span,"pm.ok",normalizedOk),setSpanAttribute(span,"pm.command_ok",normalizedOk),setSpanAttribute(span,"pm.exit_code",normalizedExitCode),setSpanAttribute(span,"pm.command_exit_code",normalizedExitCode),setSpanAttribute(span,"pm.error_code",metadata?.error_code),setSpanAttribute(span,"pm.error_category",metadata?.error_category),setSpanAttribute(span,"pm.command_resolution",metadata?.command_resolution),setSpanAttribute(span,"pm.resolution_stage",metadata?.resolution_stage)}function sentrySetCommandContext(command,args,options,metadata){const Sentry=getSentry();if(!Sentry)return;const taxonomy=deriveTelemetryCommandTaxonomy(command);Sentry.setTag("pm.command",command),Sentry.setTag("pm.command_root",taxonomy.command_root),Sentry.setTag("pm.command_family",taxonomy.command_family),typeof metadata?.source_context=="string"&&metadata.source_context.trim().length>0&&Sentry.setTag("pm.source_context",metadata.source_context);const safeArgs=args.map(arg=>arg.startsWith("--")?arg.split("=")[0]:arg);Sentry.setContext("pm.command",{name:command,root:taxonomy.command_root,leaf:taxonomy.command_leaf,family:taxonomy.command_family,args:safeArgs,option_keys:Object.keys(options).sort(),source_context:metadata?.source_context,source_context_source:metadata?.source_context_source}),Sentry.addBreadcrumb({category:"pm.command",message:`pm ${command}`,level:"info",data:{args:safeArgs,command_root:taxonomy.command_root,command_family:taxonomy.command_family,source_context:metadata?.source_context}})}function sentryStartCommandSpan(command){const Sentry=getSentry();Sentry&&(activeCommandSpan=Sentry.startInactiveSpan({op:"pm.command",name:`pm ${command}`,forceTransaction:!0}))}function sentryFinishCommandSpan(ok,error,metadata){if(!activeCommandSpan)return;const normalizedOk=ok?"true":"false",normalizedExitCode=typeof metadata?.exit_code=="number"?String(metadata.exit_code):void 0,Sentry=getSentry();Sentry&&setSentryCommandFinishTags(Sentry,normalizedOk,metadata),setCommandSpanFinishAttributes(activeCommandSpan,normalizedOk,normalizedExitCode,metadata),activeCommandSpan.setStatus(ok?{code:1}:{code:2,message:error??"command_failed"}),activeCommandSpan.end(),activeCommandSpan=void 0}const UNCLASSIFIED_CAPTURED_ERROR_CODE="unclassified_runtime_error";function readCapturedErrorContract(error){const candidate=typeof error=="object"&&error!==null?error:void 0,hasDeclaredExitCode=typeof candidate?.exitCode=="number",exitCode=hasDeclaredExitCode?Math.trunc(candidate?.exitCode):EXIT_CODE.GENERIC_FAILURE;return{error_code:typeof candidate?.code=="string"&&candidate.code.length>0&&hasDeclaredExitCode?candidate?.code:UNCLASSIFIED_CAPTURED_ERROR_CODE,exit_code:exitCode}}function buildCapturedErrorTags(error){const contract=readCapturedErrorContract(error);return{"pm.error_code":contract.error_code,"pm.exit_code":String(contract.exit_code)}}function sentryCaptureCliError(error){if(!shouldCaptureCliError(error))return;const Sentry=getSentry();if(!Sentry)return;const tags=buildCapturedErrorTags(error);if(error instanceof Error){const extras={};"exitCode"in error&&typeof error.exitCode=="number"&&(extras.exit_code=error.exitCode),"context"in error&&typeof error.context=="object"&&(extras.error_context=error.context),Sentry.captureException(error,{extra:extras,tags})}else Sentry.captureException(new Error(String(error)),{tags})}function sentryLogCliUsageError(params){const Sentry=getSentry();if(!Sentry)return;const resolvedCommandResolution=params.command_resolution??deriveTelemetryCommandResolution({ok:!1,errorCode:params.error_code,errorCategory:params.error_category}),resolvedResolutionStage=params.resolution_stage??"unknown",payload={"pm.command":params.command,"pm.error_code":params.error_code,"pm.error_category":params.error_category,"pm.exit_code":params.exit_code,"pm.error_message":params.error_message,"pm.command_resolution":resolvedCommandResolution,"pm.resolution_stage":resolvedResolutionStage,"pm.source_context":params.source_context??""},loggerCandidate=Sentry.logger;if(loggerCandidate&&typeof loggerCandidate.warn=="function"){loggerCandidate.warn("pm_cli_usage_error",payload);return}Sentry.captureMessage(`pm_cli_usage_error:${params.error_code}`,{level:"warning",tags:{"pm.command":params.command,"pm.error_code":params.error_code,"pm.error_category":params.error_category,"pm.exit_code":String(params.exit_code),"pm.command_resolution":resolvedCommandResolution,"pm.resolution_stage":resolvedResolutionStage,"pm.source_context":params.source_context??"unknown"},extra:payload})}function shouldCaptureCliError(error){if(error instanceof PmCliError||error instanceof Error&&error.name==="AbortError"&&/(?:ctrl\+[cd]|sigint|user[- ]initiated)/i.test(error.message))return!1;if(typeof error=="object"&&error!==null&&"exitCode"in error&&typeof error.exitCode=="number"){if(error instanceof Error&&error.name==="CommandError")return!1;const exitCode=Math.trunc(error.exitCode);return!new Set([EXIT_CODE.SUCCESS,EXIT_CODE.USAGE,EXIT_CODE.NOT_FOUND,EXIT_CODE.CONFLICT]).has(exitCode)}return!0}async function sentryFlush(timeoutMs=3e3){const Sentry=getSentry();if(Sentry)try{await Sentry.flush(timeoutMs)}catch{}}export{UNCLASSIFIED_CAPTURED_ERROR_CODE,sentryCaptureCliError,sentryFinishCommandSpan,sentryFlush,sentryLogCliUsageError,sentrySetCommandContext,sentryStartCommandSpan,shouldCaptureCliError};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="0d9d54cd-bd42-5958-83df-15316ea520c7")}catch{}})();import{getSentry}from"./instrument.js";import{PmCliError}from"../shared/errors.js";import{EXIT_CODE}from"../shared/constants.js";import{deriveTelemetryCommandResolution,deriveTelemetryCommandTaxonomy}from"../telemetry/observability.js";let activeCommandSpan;function setSpanAttribute(span,key,value){if(value===void 0)return;const attributeTarget=span;typeof attributeTarget.setAttribute=="function"&&attributeTarget.setAttribute(key,value)}function setSentryTagIfPresent(Sentry,key,value){typeof value=="string"&&value.trim().length>0&&Sentry.setTag(key,value)}function setSentryCommandFinishTags(Sentry,normalizedOk,metadata){Sentry.setTag("pm.ok",normalizedOk),Sentry.setTag("pm.command_ok",normalizedOk),typeof metadata?.exit_code=="number"&&(Sentry.setTag("pm.exit_code",String(metadata.exit_code)),Sentry.setTag("pm.command_exit_code",String(metadata.exit_code))),setSentryTagIfPresent(Sentry,"pm.error_code",metadata?.error_code),setSentryTagIfPresent(Sentry,"pm.error_category",metadata?.error_category),setSentryTagIfPresent(Sentry,"pm.command_resolution",metadata?.command_resolution),setSentryTagIfPresent(Sentry,"pm.resolution_stage",metadata?.resolution_stage)}function setCommandSpanFinishAttributes(span,normalizedOk,normalizedExitCode,metadata){setSpanAttribute(span,"pm.ok",normalizedOk),setSpanAttribute(span,"pm.command_ok",normalizedOk),setSpanAttribute(span,"pm.exit_code",normalizedExitCode),setSpanAttribute(span,"pm.command_exit_code",normalizedExitCode),setSpanAttribute(span,"pm.error_code",metadata?.error_code),setSpanAttribute(span,"pm.error_category",metadata?.error_category),setSpanAttribute(span,"pm.command_resolution",metadata?.command_resolution),setSpanAttribute(span,"pm.resolution_stage",metadata?.resolution_stage)}function sentrySetCommandContext(command,args,options,metadata){const Sentry=getSentry();if(!Sentry)return;const taxonomy=deriveTelemetryCommandTaxonomy(command);Sentry.setTag("pm.command",command),Sentry.setTag("pm.command_root",taxonomy.command_root),Sentry.setTag("pm.command_family",taxonomy.command_family),typeof metadata?.source_context=="string"&&metadata.source_context.trim().length>0&&Sentry.setTag("pm.source_context",metadata.source_context);const safeArgs=args.map(()=>"[redacted]");Sentry.setContext("pm.command",{name:command,root:taxonomy.command_root,leaf:taxonomy.command_leaf,family:taxonomy.command_family,args:safeArgs,option_keys:Object.keys(options).sort(),source_context:metadata?.source_context,source_context_source:metadata?.source_context_source}),Sentry.addBreadcrumb({category:"pm.command",message:`pm ${command}`,level:"info",data:{args:safeArgs,command_root:taxonomy.command_root,command_family:taxonomy.command_family,source_context:metadata?.source_context}})}function sentryStartCommandSpan(command){const Sentry=getSentry();if(!Sentry)return;const taxonomy=deriveTelemetryCommandTaxonomy(command);activeCommandSpan=Sentry.startInactiveSpan({op:"pm.command",name:`pm ${command}`,forceTransaction:!0,attributes:{"pm.command":command,"pm.command_root":taxonomy.command_root,"pm.command_family":taxonomy.command_family}})}function sentryDiscardCommandSpan(){activeCommandSpan=void 0}function sentryFinishCommandSpan(ok,error,metadata){if(!activeCommandSpan)return;const normalizedOk=ok?"true":"false",normalizedExitCode=typeof metadata?.exit_code=="number"?String(metadata.exit_code):void 0,Sentry=getSentry();Sentry&&setSentryCommandFinishTags(Sentry,normalizedOk,metadata),setCommandSpanFinishAttributes(activeCommandSpan,normalizedOk,normalizedExitCode,metadata),activeCommandSpan.setStatus(ok?{code:1}:{code:2,message:error??"command_failed"}),activeCommandSpan.end(),activeCommandSpan=void 0}const UNCLASSIFIED_CAPTURED_ERROR_CODE="unclassified_runtime_error";function readCapturedErrorContract(error){const candidate=typeof error=="object"&&error!==null?error:void 0,hasDeclaredExitCode=typeof candidate?.exitCode=="number",exitCode=hasDeclaredExitCode?Math.trunc(candidate?.exitCode):EXIT_CODE.GENERIC_FAILURE;return{error_code:typeof candidate?.code=="string"&&candidate.code.length>0&&hasDeclaredExitCode?candidate?.code:UNCLASSIFIED_CAPTURED_ERROR_CODE,exit_code:exitCode}}function buildCapturedErrorTags(error){const contract=readCapturedErrorContract(error);return{"pm.error_code":contract.error_code,"pm.exit_code":String(contract.exit_code)}}function sentryCaptureCliError(error){if(!shouldCaptureCliError(error))return;const Sentry=getSentry();if(!Sentry)return;const tags=buildCapturedErrorTags(error);if(error instanceof Error){const extras={};"exitCode"in error&&typeof error.exitCode=="number"&&(extras.exit_code=error.exitCode),"context"in error&&typeof error.context=="object"&&(extras.error_context=error.context),Sentry.captureException(error,{extra:extras,tags})}else Sentry.captureException(new Error(String(error)),{tags})}function sentryLogCliUsageError(params){const Sentry=getSentry();if(!Sentry)return;const resolvedCommandResolution=params.command_resolution??deriveTelemetryCommandResolution({ok:!1,errorCode:params.error_code,errorCategory:params.error_category}),resolvedResolutionStage=params.resolution_stage??"unknown",payload={"pm.command":params.command,"pm.error_code":params.error_code,"pm.error_category":params.error_category,"pm.exit_code":params.exit_code,"pm.error_message":params.error_message,"pm.command_resolution":resolvedCommandResolution,"pm.resolution_stage":resolvedResolutionStage,"pm.source_context":params.source_context??""},loggerCandidate=Sentry.logger;if(loggerCandidate&&typeof loggerCandidate.warn=="function"){loggerCandidate.warn("pm_cli_usage_error",payload);return}Sentry.captureMessage(`pm_cli_usage_error:${params.error_code}`,{level:"warning",tags:{"pm.command":params.command,"pm.error_code":params.error_code,"pm.error_category":params.error_category,"pm.exit_code":String(params.exit_code),"pm.command_resolution":resolvedCommandResolution,"pm.resolution_stage":resolvedResolutionStage,"pm.source_context":params.source_context??"unknown"},extra:payload})}function shouldCaptureCliError(error){if(error instanceof PmCliError||error instanceof Error&&error.name==="AbortError"&&/(?:ctrl\+[cd]|sigint|user[- ]initiated)/i.test(error.message))return!1;if(typeof error=="object"&&error!==null&&"exitCode"in error&&typeof error.exitCode=="number"){if(error instanceof Error&&error.name==="CommandError")return!1;const exitCode=Math.trunc(error.exitCode);return!new Set([EXIT_CODE.SUCCESS,EXIT_CODE.USAGE,EXIT_CODE.NOT_FOUND,EXIT_CODE.CONFLICT]).has(exitCode)}return!0}async function sentryFlush(timeoutMs=3e3){const Sentry=getSentry();if(Sentry)try{await Sentry.flush(timeoutMs)}catch{}}export{UNCLASSIFIED_CAPTURED_ERROR_CODE,sentryCaptureCliError,sentryDiscardCommandSpan,sentryFinishCommandSpan,sentryFlush,sentryLogCliUsageError,sentrySetCommandContext,sentryStartCommandSpan,shouldCaptureCliError};
2
2
  //# sourceMappingURL=helpers.js.map
@@ -53,6 +53,8 @@ message?: string;
53
53
  declare function resolveTracesSampleRate(): number;
54
54
  /** Implements ensure sentry init for the public runtime surface of this module. */
55
55
  export declare function ensureSentryInit(): Promise<SentryLike | undefined>;
56
+ /** Return tracing permission only after explicit consent, opt-in, sampling and process policy agree. */
57
+ export declare function ensureSentryCommandTracing(telemetryEnabled: boolean): Promise<boolean>;
56
58
  /** Implements get sentry for the public runtime surface of this module. */
57
59
  export declare function getSentry(): SentryLike | undefined;
58
60
  /** Public contract for test only, shared by SDK and presentation-layer consumers. */
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="da2c4c10-3c43-5037-ac69-31204480af99")}catch{}})();import{createRequire}from"node:module";import{resolvePmCliVersion}from"../packages/root.js";import{resolveTelemetryEnvironmentPolicy}from"../telemetry/policy.js";const OPT_OUT_VALUES=new Set(["1","true","yes","on"]);function isSentryDisabled(){return!!(OPT_OUT_VALUES.has((process.env.PM_SENTRY_DISABLED??"").trim().toLowerCase())||resolveTelemetryEnvironmentPolicy().telemetry_disabled||typeof process.env.VITEST=="string"||typeof process.env.VITEST_WORKER_ID=="string")}const SENSITIVE_KEY_PATTERN=/(?:token|secret|password|passwd|api[_-]?key|apikey|authorization|cookie|credentials|bearer|dsn)/i,INLINE_SENSITIVE_ASSIGNMENT_RE=new RegExp(`\\b(${SENSITIVE_KEY_PATTERN.source})\\s*[:=]\\s*([^\\s,;]+)`,"giu"),ABSOLUTE_PATH_TOKEN_RE=/(^|[\s"'`(=])\/(?:[^\s"'`),;]+)/g,FILE_URL_PATH_RE=/file:\/\/\/?[^\s"'`),;]+/giu,WINDOWS_PATH_TOKEN_RE=/\b[A-Za-z]:\\[^\s"'`),;]+/g,PRIVATE_IP_RE=/\b(?:10\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|172\.(?:1[6-9]|2\d|3[01])\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|192\.168\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d))\b/g,PATH_FIELD_KEY_PATTERN=/(?:^|[_-])(path|filename|file|module|cwd|dir|directory|location|source|script)s?$/i,MAX_KNOWN_NOISY_CONSOLE_MESSAGE_PATTERNS=15,KNOWN_NOISY_CONSOLE_MESSAGE_PATTERNS=["[starter-extension] activating","[starter-extension] all 8 capabilities registered.","[starter-extension] commands:","[starter] preflight check for workspace","[starter] output_format service override active","[pm-ext-ts-starter] activating","[pm-ext-ts-starter] all capabilities registered.","run `pm init` first to initialise a pm workspace"];function looksLikeFilesystemPath(value){const normalized=value.trim();return normalized.length===0?!1:normalized.startsWith("/")||normalized.startsWith("file://")||/^[A-Za-z]:\\/.test(normalized)||normalized.startsWith("\\\\")?!0:normalized.includes("/home/")}function scrubString(value,keyHint){if(keyHint&&PATH_FIELD_KEY_PATTERN.test(keyHint)&&looksLikeFilesystemPath(value))return"[scrubbed_path]";const scrubbed=value.replaceAll(INLINE_SENSITIVE_ASSIGNMENT_RE,(_m,key)=>`${key}=[scrubbed]`).replaceAll(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/giu,"[scrubbed_email]").replaceAll(/bearer\s+[a-z0-9._=-]+/giu,"bearer [scrubbed]").replaceAll(/sntr[ysu]_[A-Za-z0-9_-]+/g,"[scrubbed_sentry_token]").replaceAll(PRIVATE_IP_RE,"[scrubbed_ip]").replaceAll(FILE_URL_PATH_RE,"[scrubbed_path]").replaceAll(WINDOWS_PATH_TOKEN_RE,"[scrubbed_path]").replaceAll(ABSOLUTE_PATH_TOKEN_RE,(_match,prefix)=>`${prefix}[scrubbed_path]`);return looksLikeFilesystemPath(scrubbed)?"[scrubbed_path]":scrubbed}function scrubEventData(obj){const result={};for(const[key,value]of Object.entries(obj))SENSITIVE_KEY_PATTERN.test(key)?result[key]="[scrubbed]":typeof value=="string"?result[key]=scrubString(value,key):Array.isArray(value)?result[key]=value.map(entry=>typeof entry=="string"?scrubString(entry,key):entry&&typeof entry=="object"?scrubEventData(entry):entry):value&&typeof value=="object"?result[key]=scrubEventData(value):result[key]=value;return result}function scrubStackFrame(frame){for(const key of["filename","absPath","abs_path","module"]){const rawValue=frame[key];typeof rawValue=="string"&&(frame[key]=scrubString(rawValue,key))}const contextLine=frame.context_line;typeof contextLine=="string"&&(frame.context_line=scrubString(contextLine,"context_line"));for(const key of["pre_context","post_context"]){const context=frame[key];Array.isArray(context)&&(frame[key]=context.map(entry=>typeof entry=="string"?scrubString(entry,key):entry))}frame.vars&&typeof frame.vars=="object"&&(frame.vars=scrubEventData(frame.vars)),frame.data&&typeof frame.data=="object"&&(frame.data=scrubEventData(frame.data))}const requireFromInstrument=createRequire(import.meta.url),defaultSentryLoader=()=>requireFromInstrument("@sentry/node");let _sentry,_initDone=!1,_loadSentry=defaultSentryLoader;const PM_CLI_SENTRY_DSN="https://bf7ad2ec76c0051c2ee94e48e8bd6868@o4510603477712896.ingest.de.sentry.io/4511316775338064";function hasPmCliErrorPrefix(value){return/^\s*PmCliError:/.test(value)}function isKnownNoisyConsoleMessage(value){const normalized=value.trim().toLowerCase();return normalized.length===0?!1:KNOWN_NOISY_CONSOLE_MESSAGE_PATTERNS.some(pattern=>normalized.includes(pattern))}function isKnownNoisyConsoleEvent(event){return event.logger!=="console"?!1:typeof event.message=="string"&&isKnownNoisyConsoleMessage(event.message)?!0:Array.isArray(event.exception?.values)&&event.exception.values.some(entry=>typeof entry.value=="string"&&isKnownNoisyConsoleMessage(entry.value))}function isNodeRuntimeWarningEvent(event){if(event.logger!=="console")return!1;const isRuntimeWarning=value=>typeof value=="string"&&/^\(node:\d+\) MaxListenersExceededWarning: Possible EventEmitter memory leak detected\./.test(value);return isRuntimeWarning(event.message)?!0:Array.isArray(event.exception?.values)&&event.exception.values.some(entry=>isRuntimeWarning(entry.value))}function isExpectedCliErrorEvent(event){return!!(event.exception?.values?.some(ex=>ex.type==="PmCliError")||event.exception?.values?.some(ex=>typeof ex.value=="string"&&hasPmCliErrorPrefix(ex.value))||event.logger==="console"&&typeof event.message=="string"&&hasPmCliErrorPrefix(event.message))}function isPmCliErrorBreadcrumb(breadcrumb){return breadcrumb.category==="console"&&typeof breadcrumb.message=="string"&&hasPmCliErrorPrefix(breadcrumb.message)}function isKnownNoisyConsoleBreadcrumb(breadcrumb){return breadcrumb.category==="console"&&typeof breadcrumb.message=="string"&&isKnownNoisyConsoleMessage(breadcrumb.message)}function resolveCliVersion(){return resolvePmCliVersion(import.meta.url,["../../.."])??"0.0.0"}function resolveEnvironment(){const explicit=process.env.SENTRY_ENVIRONMENT?.trim();return explicit&&explicit.length>0?explicit:process.env.VITEST||process.env.VITEST_WORKER_ID||process.env.NODE_ENV==="test"?"test":process.env.CI?"ci":"production"}const DEFAULT_TRACES_SAMPLE_RATE=.2;function resolveTracesSampleRate(){const raw=process.env.SENTRY_TRACES_SAMPLE_RATE?.trim();if(!raw)return DEFAULT_TRACES_SAMPLE_RATE;const parsed=Number(raw);return!Number.isFinite(parsed)||parsed<0||parsed>1?DEFAULT_TRACES_SAMPLE_RATE:parsed}function scrubSentryExceptionValues(event){if(event.exception?.values){for(const exception of event.exception.values)if(exception.value&&(exception.value=scrubString(exception.value,"value")),exception.stacktrace?.frames)for(const frame of exception.stacktrace.frames)scrubStackFrame(frame)}}function scrubSentryBreadcrumbs(event){if(event.breadcrumbs)for(const breadcrumb of event.breadcrumbs)breadcrumb.message&&(breadcrumb.message=scrubString(breadcrumb.message)),breadcrumb.data&&typeof breadcrumb.data=="object"&&(breadcrumb.data=scrubEventData(breadcrumb.data))}function scrubSentryContexts(event){if(event.contexts)for(const[ctxKey,ctx]of Object.entries(event.contexts))ctx&&typeof ctx=="object"&&(event.contexts[ctxKey]=scrubEventData(ctx))}function scrubSentryRecordField(event,key){const target=event,value=target[key];value&&typeof value=="object"&&(target[key]=scrubEventData(value))}const beforeSend=event=>{if(isExpectedCliErrorEvent(event)||isKnownNoisyConsoleEvent(event))return null;isNodeRuntimeWarningEvent(event)&&(event.level="warning",event.tags={...event.tags,"pm.diagnostic_class":"node_runtime_warning"}),event.message&&(event.message=scrubString(event.message,"message")),event.transaction&&(event.transaction=scrubString(event.transaction,"transaction")),scrubSentryExceptionValues(event),scrubSentryBreadcrumbs(event),scrubSentryRecordField(event,"extra"),scrubSentryContexts(event);for(const key of["request","user","tags"])scrubSentryRecordField(event,key);return event},beforeSendTransaction=event=>(event.breadcrumbs&&(event.breadcrumbs=event.breadcrumbs.filter(breadcrumb=>!isPmCliErrorBreadcrumb(breadcrumb)&&!isKnownNoisyConsoleBreadcrumb(breadcrumb)),scrubSentryBreadcrumbs(event)),scrubSentryContexts(event),event),beforeBreadcrumb=breadcrumb=>isPmCliErrorBreadcrumb(breadcrumb)||isKnownNoisyConsoleBreadcrumb(breadcrumb)?null:(breadcrumb.message&&(breadcrumb.message=scrubString(breadcrumb.message,"message")),breadcrumb.data&&typeof breadcrumb.data=="object"&&(breadcrumb.data=scrubEventData(breadcrumb.data)),breadcrumb);async function ensureSentryInit(){if(_initDone)return _sentry;if(_initDone=!0,isSentryDisabled())return;const SentryModule=_loadSentry();_sentry=SentryModule;const dsn=process.env.SENTRY_DSN?.trim()||PM_CLI_SENTRY_DSN,release=resolveCliVersion();return SentryModule.init({dsn,release:`pm-cli@${release}`,environment:resolveEnvironment(),tracesSampleRate:resolveTracesSampleRate(),enableLogs:!0,attachStacktrace:!0,normalizeDepth:6,shutdownTimeout:3e3,sendDefaultPii:!1,serverName:void 0,integrations:[SentryModule.extraErrorDataIntegration({depth:4}),SentryModule.captureConsoleIntegration({levels:["warn","error"]})],initialScope:{tags:{"cli.name":"pm-cli","cli.version":release,"runtime.node":process.version,"runtime.platform":process.platform,"runtime.arch":process.arch}},beforeSend,beforeSendTransaction,beforeBreadcrumb}),SentryModule}function getSentry(){return _sentry}const _testOnly={isExpectedCliErrorEvent,isKnownNoisyConsoleEvent,isNodeRuntimeWarningEvent,isPmCliErrorBreadcrumb,isKnownNoisyConsoleBreadcrumb,scrubString,scrubEventData,resolveTracesSampleRate,KNOWN_NOISY_CONSOLE_MESSAGE_PATTERNS,MAX_KNOWN_NOISY_CONSOLE_MESSAGE_PATTERNS,defaultSentryLoader,setSentryLoaderForTests(loader){_loadSentry=loader??defaultSentryLoader},resetSentryStateForTests(){_sentry=void 0,_initDone=!1}};export{_testOnly,ensureSentryInit,getSentry};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f0ba610e-dd20-5ff4-9f90-d9b6e411d90a")}catch{}})();import{createRequire}from"node:module";import{resolvePmCliVersion}from"../packages/root.js";import{resolveTelemetryEnvironmentPolicy}from"../telemetry/policy.js";const OPT_OUT_VALUES=new Set(["1","true","yes","on"]);function isSentryDisabled(){return!!(OPT_OUT_VALUES.has((process.env.PM_SENTRY_DISABLED??"").trim().toLowerCase())||resolveTelemetryEnvironmentPolicy().telemetry_disabled||typeof process.env.VITEST=="string"||typeof process.env.VITEST_WORKER_ID=="string")}const SENSITIVE_KEY_PATTERN=/(?:token|secret|password|passwd|api[_-]?key|apikey|authorization|cookie|credentials|bearer|dsn)/i,INLINE_SENSITIVE_ASSIGNMENT_RE=new RegExp(`(?:\\b|(?<=_))(${SENSITIVE_KEY_PATTERN.source})\\s*[:=]\\s*([^\\s,;]+)`,"giu"),ABSOLUTE_PATH_TOKEN_RE=/(^|[\s"'`(=])\/(?:[^\s"'`),;]+)/g,FILE_URL_PATH_RE=/file:\/\/\/?[^\s"'`),;]+/giu,WINDOWS_PATH_TOKEN_RE=/\b[A-Za-z]:\\[^\s"'`),;]+/g,PRIVATE_IP_RE=/\b(?:10\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|172\.(?:1[6-9]|2\d|3[01])\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|192\.168\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d))\b/g,PATH_FIELD_KEY_PATTERN=/(?:^|[_-])(path|filename|file|module|cwd|dir|directory|location|source|script)s?$/i,MAX_KNOWN_NOISY_CONSOLE_MESSAGE_PATTERNS=15,KNOWN_NOISY_CONSOLE_MESSAGE_PATTERNS=["[starter-extension] activating","[starter-extension] all 8 capabilities registered.","[starter-extension] commands:","[starter] preflight check for workspace","[starter] output_format service override active","[pm-ext-ts-starter] activating","[pm-ext-ts-starter] all capabilities registered.","run `pm init` first to initialise a pm workspace"];function looksLikeFilesystemPath(value){const normalized=value.trim();return normalized.length===0?!1:normalized.startsWith("/")||normalized.startsWith("file://")||/^[A-Za-z]:\\/.test(normalized)||normalized.startsWith("\\\\")?!0:normalized.includes("/home/")}function sensitiveAssignmentEnd(value,start,unquotedEnd){const quote=value[start];if(quote!=='"'&&quote!=="'")return unquotedEnd;for(let index=start+1;index<value.length;index++){if(value[index]==="\\"){index++;continue}if(value[index]===quote)return index+1}return value.length}function scrubInlineSensitiveAssignments(value){const chunks=[];let consumed=0;for(const match of value.matchAll(INLINE_SENSITIVE_ASSIGNMENT_RE)){if(match.index<consumed)continue;const unquotedEnd=match.index+match[0].length,start=unquotedEnd-match[2].length;chunks.push(value.slice(consumed,match.index),`${match[1]}=[scrubbed]`),consumed=sensitiveAssignmentEnd(value,start,unquotedEnd)}return chunks.push(value.slice(consumed)),chunks.join("")}function scrubString(value,keyHint){if(keyHint&&PATH_FIELD_KEY_PATTERN.test(keyHint)&&looksLikeFilesystemPath(value))return"[scrubbed_path]";const scrubbed=scrubInlineSensitiveAssignments(value).replaceAll(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/giu,"[scrubbed_email]").replaceAll(/bearer\s+[a-z0-9._=-]+/giu,"bearer [scrubbed]").replaceAll(/sntr[ysu]_[A-Za-z0-9_-]+/g,"[scrubbed_sentry_token]").replaceAll(PRIVATE_IP_RE,"[scrubbed_ip]").replaceAll(FILE_URL_PATH_RE,"[scrubbed_path]").replaceAll(WINDOWS_PATH_TOKEN_RE,"[scrubbed_path]").replaceAll(ABSOLUTE_PATH_TOKEN_RE,(_match,prefix)=>`${prefix}[scrubbed_path]`);return looksLikeFilesystemPath(scrubbed)?"[scrubbed_path]":scrubbed}function scrubEventData(obj){const result={};for(const[key,value]of Object.entries(obj))SENSITIVE_KEY_PATTERN.test(key)||key.startsWith("sentry.message.parameter.")?result[key]="[scrubbed]":typeof value=="string"?result[key]=scrubString(value,key):Array.isArray(value)?result[key]=value.map(entry=>typeof entry=="string"?scrubString(entry,key):entry&&typeof entry=="object"?scrubEventData(entry):entry):value&&typeof value=="object"?result[key]=scrubEventData(value):result[key]=value;return result}function scrubStackFrame(frame){for(const key of["filename","absPath","abs_path","module"]){const rawValue=frame[key];typeof rawValue=="string"&&(frame[key]=scrubString(rawValue,key))}const contextLine=frame.context_line;typeof contextLine=="string"&&(frame.context_line=scrubString(contextLine,"context_line"));for(const key of["pre_context","post_context"]){const context=frame[key];Array.isArray(context)&&(frame[key]=context.map(entry=>typeof entry=="string"?scrubString(entry,key):entry))}frame.vars&&typeof frame.vars=="object"&&(frame.vars=scrubEventData(frame.vars)),frame.data&&typeof frame.data=="object"&&(frame.data=scrubEventData(frame.data))}const requireFromInstrument=createRequire(import.meta.url),defaultSentryLoader=()=>requireFromInstrument("@sentry/node");let _sentry,_initDone=!1,_loadSentry=defaultSentryLoader;const PM_CLI_SENTRY_DSN="https://bf7ad2ec76c0051c2ee94e48e8bd6868@o4510603477712896.ingest.de.sentry.io/4511316775338064";function hasPmCliErrorPrefix(value){return/^\s*PmCliError:/.test(value)}function isKnownNoisyConsoleMessage(value){const normalized=value.trim().toLowerCase();return normalized.length===0?!1:KNOWN_NOISY_CONSOLE_MESSAGE_PATTERNS.some(pattern=>normalized.includes(pattern))}function isKnownNoisyConsoleEvent(event){return event.logger!=="console"?!1:typeof event.message=="string"&&isKnownNoisyConsoleMessage(event.message)?!0:Array.isArray(event.exception?.values)&&event.exception.values.some(entry=>typeof entry.value=="string"&&isKnownNoisyConsoleMessage(entry.value))}function isNodeRuntimeWarningEvent(event){if(event.logger!=="console")return!1;const isRuntimeWarning=value=>typeof value=="string"&&/^\(node:\d+\) MaxListenersExceededWarning: Possible EventEmitter memory leak detected\./.test(value);return isRuntimeWarning(event.message)?!0:Array.isArray(event.exception?.values)&&event.exception.values.some(entry=>isRuntimeWarning(entry.value))}function isExpectedCliErrorEvent(event){return!!(event.exception?.values?.some(ex=>ex.type==="PmCliError")||event.exception?.values?.some(ex=>typeof ex.value=="string"&&hasPmCliErrorPrefix(ex.value))||event.logger==="console"&&typeof event.message=="string"&&hasPmCliErrorPrefix(event.message))}function isPmCliErrorBreadcrumb(breadcrumb){return breadcrumb.category==="console"&&typeof breadcrumb.message=="string"&&hasPmCliErrorPrefix(breadcrumb.message)}function isKnownNoisyConsoleBreadcrumb(breadcrumb){return breadcrumb.category==="console"&&typeof breadcrumb.message=="string"&&isKnownNoisyConsoleMessage(breadcrumb.message)}function resolveCliVersion(){return resolvePmCliVersion(import.meta.url,["../../.."])??"0.0.0"}function resolveEnvironment(){const explicit=process.env.SENTRY_ENVIRONMENT?.trim();return explicit&&explicit.length>0?explicit:process.env.VITEST||process.env.VITEST_WORKER_ID||process.env.NODE_ENV==="test"?"test":process.env.CI?"ci":"production"}const DEFAULT_TRACES_SAMPLE_RATE=.2;function resolveTracesSampleRate(){const raw=process.env.SENTRY_TRACES_SAMPLE_RATE?.trim();if(!raw)return DEFAULT_TRACES_SAMPLE_RATE;const parsed=Number(raw);return!Number.isFinite(parsed)||parsed<0||parsed>1?DEFAULT_TRACES_SAMPLE_RATE:parsed}function scrubSentryExceptionValues(event){if(event.exception?.values){for(const exception of event.exception.values)if(exception.value&&(exception.value=scrubString(exception.value,"value")),exception.stacktrace?.frames)for(const frame of exception.stacktrace.frames)scrubStackFrame(frame)}}function scrubSentryBreadcrumbs(event){if(event.breadcrumbs)for(const breadcrumb of event.breadcrumbs)breadcrumb.message&&(breadcrumb.message=scrubString(breadcrumb.message)),breadcrumb.data&&typeof breadcrumb.data=="object"&&(breadcrumb.data=scrubEventData(breadcrumb.data))}function scrubSentryContexts(event){if(event.contexts)for(const[ctxKey,ctx]of Object.entries(event.contexts))ctx&&typeof ctx=="object"&&(event.contexts[ctxKey]=scrubEventData(ctx))}function scrubSentryRecordField(event,key){const target=event,value=target[key];value&&typeof value=="object"&&(target[key]=scrubEventData(value))}const beforeSend=event=>{if(isExpectedCliErrorEvent(event)||isKnownNoisyConsoleEvent(event))return null;isNodeRuntimeWarningEvent(event)&&(event.level="warning",event.tags={...event.tags,"pm.diagnostic_class":"node_runtime_warning"}),event.message&&(event.message=scrubString(event.message,"message")),event.transaction&&(event.transaction=scrubString(event.transaction,"transaction")),scrubSentryExceptionValues(event),scrubSentryBreadcrumbs(event),scrubSentryRecordField(event,"extra"),scrubSentryContexts(event);for(const key of["request","user","tags"])scrubSentryRecordField(event,key);return event},beforeSendTransaction=event=>(event.breadcrumbs&&(event.breadcrumbs=event.breadcrumbs.filter(breadcrumb=>!isPmCliErrorBreadcrumb(breadcrumb)&&!isKnownNoisyConsoleBreadcrumb(breadcrumb)),scrubSentryBreadcrumbs(event)),scrubSentryContexts(event),event),beforeSendSpan=span=>scrubEventData(span),beforeSendLog=log=>(log.message=scrubString(log.message),log.attributes&&(log.attributes=scrubEventData(log.attributes)),log);function scrubSentryLogEnvelope(envelope){for(const item of envelope[1])if(item[0].type==="log")for(const log of item[1].items){log.body=scrubString(log.body);const attributes=log.attributes;if(attributes)for(const[key,attribute]of Object.entries(attributes)){const value=scrubEventData({[key]:attribute.value})[key];typeof value=="string"&&(attributes[key]={type:"string",value})}}}const beforeBreadcrumb=breadcrumb=>isPmCliErrorBreadcrumb(breadcrumb)||isKnownNoisyConsoleBreadcrumb(breadcrumb)?null:(breadcrumb.message&&(breadcrumb.message=scrubString(breadcrumb.message,"message")),breadcrumb.data&&typeof breadcrumb.data=="object"&&(breadcrumb.data=scrubEventData(breadcrumb.data)),breadcrumb);async function ensureSentryInit(){if(_initDone)return _sentry;if(_initDone=!0,isSentryDisabled())return;const SentryModule=_loadSentry(),dsn=process.env.SENTRY_DSN?.trim()||PM_CLI_SENTRY_DSN,release=resolveCliVersion();SentryModule.init({dsn,release:`pm-cli@${release}`,environment:resolveEnvironment(),tracesSampleRate:resolveTracesSampleRate(),enableLogs:!0,attachStacktrace:!0,normalizeDepth:6,shutdownTimeout:3e3,traceLifecycle:"stream",dataCollection:{userInfo:!1,cookies:!1,httpHeaders:{request:!1,response:!1},httpBodies:[],urlQueryParams:!1,genAI:{inputs:!1,outputs:!1},databaseQueryData:!1,graphQL:{document:!1,variables:!1},stackFrameVariables:!1,frameContextLines:0},serverName:void 0,integrations:[SentryModule.extraErrorDataIntegration({depth:4}),SentryModule.captureConsoleIntegration({levels:["warn","error"]})],initialScope:{tags:{"cli.name":"pm-cli","cli.version":release,"runtime.node":process.version,"runtime.platform":process.platform,"runtime.arch":process.arch}},beforeSend,beforeSendTransaction,beforeSendSpan:SentryModule.withStreamedSpan(beforeSendSpan),beforeSendLog,beforeBreadcrumb});const client=SentryModule.getClient();if(client)return client.on("beforeEnvelope",scrubSentryLogEnvelope),_sentry=SentryModule,SentryModule}async function ensureSentryCommandTracing(telemetryEnabled){if(telemetryEnabled!==!0||!OPT_OUT_VALUES.has((process.env.PM_SENTRY_TRACE_COMMANDS??"").trim().toLowerCase())||resolveTracesSampleRate()===0||isSentryDisabled())return!1;try{return await ensureSentryInit()!==void 0}catch{return _sentry=void 0,!1}}function getSentry(){return _sentry}const _testOnly={isExpectedCliErrorEvent,isKnownNoisyConsoleEvent,isNodeRuntimeWarningEvent,isPmCliErrorBreadcrumb,isKnownNoisyConsoleBreadcrumb,scrubString,scrubEventData,resolveTracesSampleRate,KNOWN_NOISY_CONSOLE_MESSAGE_PATTERNS,MAX_KNOWN_NOISY_CONSOLE_MESSAGE_PATTERNS,defaultSentryLoader,setSentryLoaderForTests(loader){_loadSentry=loader??defaultSentryLoader},resetSentryStateForTests(){_sentry=void 0,_initDone=!1}};export{_testOnly,ensureSentryCommandTracing,ensureSentryInit,getSentry};
2
2
  //# sourceMappingURL=instrument.js.map
@@ -408,7 +408,7 @@ flushSpawnLockPath: typeof flushSpawnLockPath;
408
408
  runtimeStatePath: typeof runtimeStatePath;
409
409
  writeRuntimeState: typeof writeRuntimeState;
410
410
  };
411
- declare function flushQueueWithProcessLock(globalPmRoot: string, endpoint: string, retentionDays: number): Promise<void>;
411
+ declare function flushQueueWithProcessLock(globalPmRoot: string, endpoint: string, retentionDays: number): Promise<boolean>;
412
412
  declare function scheduleTelemetryFlush(globalPmRoot: string, endpoint: string, retentionDays: number): void;
413
413
  /** Drain consented event and span queues without reviving removed storage in detached workers. Foreground SDK callers retain identity initialization; workers only read existing base settings and never scaffold directories, schemas or identities. */
414
414
  export declare function flushTelemetryQueueNow(globalPmRoot?: string): Promise<void>;
@@ -1,4 +1,4 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4a63e054-a0e2-5826-976f-9076f6905388")}catch{}})();import crypto from"node:crypto";import{spawn}from"node:child_process";import{mkdirSync,rmSync,statSync}from"node:fs";import{mkdir,readdir,rm,stat}from"node:fs/promises";import{request as httpRequest}from"node:http";import{request as httpsRequest}from"node:https";import os from"node:os";import path from"node:path";import{acquireLock}from"../lock/lock.js";import{isActiveCommandUnextended,runWithIsolatedExtensionRuntime}from"../extensions/index.js";import{resolveAutomaticReadSampleRate}from"./read-sampling.js";import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES,resolveTelemetryEnvironmentPolicy}from"./policy.js";import{resolvePmPackageRootFromModule}from"../packages/root.js";import{isFileMissingError,appendLineAtomic,readFileIfExists,writeFileAtomic}from"../fs/fs-utils.js";import{resolveTelemetryErrorCategory}from"../shared/constants.js";import{nowIso}from"../shared/time.js";import{detectAgentIdentity,readAuthorEnvironment}from"../shared/author.js";import{resolveGlobalPmRoot}from"../store/paths.js";import{isConfigurationOnlySettingsRead,readSettings,runWithConfigurationOnlySettings,writeSettings}from"../store/settings.js";import{clearSettingsReadCache}from"../store/settings-read-cache.js";import{deriveTelemetryCommandResolution,deriveTelemetryCommandTaxonomy,inferTelemetryErrorCode}from"./observability.js";const TELEMETRY_QUEUE_RELATIVE_PATH=path.join("runtime","telemetry","events.jsonl"),TELEMETRY_STATE_RELATIVE_PATH=path.join("runtime","telemetry","state.json"),TELEMETRY_OTEL_SPANS_RELATIVE_PATH=path.join("runtime","telemetry","otel-spans.jsonl"),TELEMETRY_OTEL_SPANS_FLUSH_BATCH_SIZE=8,TELEMETRY_OTEL_SPANS_MAX_PENDING=500,TELEMETRY_SCHEMA_VERSION=1,TELEMETRY_CLIENT_SCHEMA_VERSION=1,TELEMETRY_FLUSH_BATCH_SIZE=100,TELEMETRY_MAX_RETRY_DELAY_MS=36e5,TELEMETRY_RETRY_BASE_DELAY_MS=3e4,TELEMETRY_HTTP_TIMEOUT_DEFAULT_MS=2e4,TELEMETRY_HTTP_TIMEOUT_MIN_MS=1e3,TELEMETRY_HTTP_TIMEOUT_MAX_MS=25e3,TELEMETRY_FOREGROUND_LOCK_WAIT_MS=250,MILLISECONDS_PER_DAY=864e5,TELEMETRY_MAX_EVENT_BYTES=65536,TELEMETRY_SANITIZE_MAX_DEPTH=6,TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS=20,TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS=15,TELEMETRY_RESULT_PREVIEW_MAX_BYTES=8192,TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS=[25,50,100,200],TELEMETRY_QUEUE_TMP_ORPHAN_MAX_AGE_MS=3600*1e3,TELEMETRY_FLUSH_LOCK_STALE_MS=6e4,TELEMETRY_FLUSH_SPAWN_LOCK_STALE_MS=6e4,OTEL_TRACES_ENDPOINT_ENV="OTEL_EXPORTER_OTLP_TRACES_ENDPOINT",OTEL_BASE_ENDPOINT_ENV="OTEL_EXPORTER_OTLP_ENDPOINT",OTEL_SERVICE_NAME_ENV="OTEL_SERVICE_NAME",PM_TELEMETRY_OTEL_DISABLED_ENV="PM_TELEMETRY_OTEL_DISABLED",PM_TELEMETRY_OTEL_DISABLED_VALUES=new Set(["1","true","yes","on"]),PM_TELEMETRY_INLINE_FLUSH_ENV="PM_TELEMETRY_INLINE_FLUSH",PM_TELEMETRY_FLUSH_CHILD_ENV="PM_TELEMETRY_FLUSH_CHILD",PM_TELEMETRY_SOURCE_CONTEXT_ENV="PM_TELEMETRY_SOURCE_CONTEXT",PM_TELEMETRY_HTTP_TIMEOUT_MS_ENV="PM_TELEMETRY_HTTP_TIMEOUT_MS",NATIVE_FETCH=globalThis.fetch;import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES as PM_TELEMETRY_SOURCE_CONTEXT_VALUES2}from"./policy.js";let sourceContextWarningEmitted=!1,_lastFlushPromise=Promise.resolve(),_queueMutationPromise=Promise.resolve();const deferredReadStarts=new WeakMap;async function waitForPendingFlush(){await _lastFlushPromise,await _queueMutationPromise}const PM_TELEMETRY_SOURCE_CONTEXT_SET=new Set(PM_TELEMETRY_SOURCE_CONTEXT_VALUES),BOOLEAN_TRUE_VALUES=new Set(["1","true","yes","on"]),TELEMETRY_HARNESSES=new Set(["claude-code","codex","pi","opencode","cursor","aider","gemini-cli","ci"]),PROCESS_SESSION_ID=crypto.randomUUID(),SENSITIVE_KEYWORDS=["token","secret","password","passwd","api_key","apikey","authorization","cookie","session","credentials","bearer"],REDACTION_INPUT_KEYS=new Set(["literal","literals","regex","regexes","replacement","replacements","setjson","set_json","update"]),SENSITIVE_INLINE_KEY_PATTERN="(?:token|secret|password|passwd|api[_-]?key|apikey|authorization|cookie|session|credentials|bearer|literals?|regex(?:es)?|replacements?)",INLINE_SENSITIVE_ASSIGNMENT_PATTERN=new RegExp(`\\b(${SENSITIVE_INLINE_KEY_PATTERN})\\s*([:=])\\s*([^\\s,;]+)`,"giu"),INLINE_SENSITIVE_FLAG_PATTERN=new RegExp(`(--${SENSITIVE_INLINE_KEY_PATTERN})(=|\\s+)([^\\s,;]+)`,"giu"),ABSOLUTE_PATH_TOKEN_PATTERN=/(^|[\s"'`(=])\/(?:[^\s"'`),;]+)/g,BEARER_TOKEN_PATTERN=/bearer\s+[a-z0-9._=-]+/giu,PRIVATE_IP_PATTERN=/\b(?:10\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|172\.(?:1[6-9]|2\d|3[01])\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|192\.168\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d))\b/g;function queuePath(globalPmRoot){return path.join(globalPmRoot,TELEMETRY_QUEUE_RELATIVE_PATH)}function otelSpansQueuePath(globalPmRoot){return path.join(globalPmRoot,TELEMETRY_OTEL_SPANS_RELATIVE_PATH)}function telemetryRuntimeDirectory(globalPmRoot){return path.dirname(queuePath(globalPmRoot))}function runtimeStatePath(globalPmRoot){return path.join(globalPmRoot,TELEMETRY_STATE_RELATIVE_PATH)}function flushLockPath(globalPmRoot){return path.join(globalPmRoot,"runtime","telemetry","flush.lock")}function flushSpawnLockPath(globalPmRoot){return path.join(globalPmRoot,"runtime","telemetry","flush.spawn.lock")}function telemetryFlushRunnerPath(){return path.join(resolvePmPackageRootFromModule(import.meta.url,["../../.."]),"dist","cli","telemetry-flush.js")}function shouldFlushInline(){if(parseBooleanTrueLike(process.env[PM_TELEMETRY_INLINE_FLUSH_ENV])||parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV]))return!0;const nodeEnv=(process.env.NODE_ENV??"").trim().toLowerCase();return typeof process.env.VITEST=="string"||typeof process.env.VITEST_WORKER_ID=="string"||nodeEnv==="test"}async function readRuntimeState(globalPmRoot){const raw=await readFileIfExists(runtimeStatePath(globalPmRoot));if(!raw||raw.trim().length===0)return{};try{const parsed=JSON.parse(raw);return typeof parsed!="object"||parsed===null||Array.isArray(parsed)?{}:parsed}catch{return{}}}async function writeRuntimeState(globalPmRoot,patch){try{await withQueueMutation(async()=>{const next={...await readRuntimeState(globalPmRoot),...patch},normalized=Object.fromEntries(Object.entries(next).filter(([,value])=>value!==void 0).sort((left,right)=>left[0].localeCompare(right[0])));await writeFileAtomic(runtimeStatePath(globalPmRoot),`${JSON.stringify(normalized,null,2)}
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="11e932b0-f880-5848-abd3-0360e21289ec")}catch{}})();import crypto from"node:crypto";import{spawn}from"node:child_process";import{mkdirSync,rmSync,statSync}from"node:fs";import{mkdir,readdir,rm,stat}from"node:fs/promises";import{request as httpRequest}from"node:http";import{request as httpsRequest}from"node:https";import os from"node:os";import path from"node:path";import{acquireLock}from"../lock/lock.js";import{isActiveCommandUnextended,runWithIsolatedExtensionRuntime}from"../extensions/index.js";import{resolveAutomaticReadSampleRate}from"./read-sampling.js";import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES,resolveTelemetryEnvironmentPolicy}from"./policy.js";import{resolvePmPackageRootFromModule}from"../packages/root.js";import{isFileMissingError,appendLineAtomic,readFileIfExists,writeFileAtomic}from"../fs/fs-utils.js";import{resolveTelemetryErrorCategory}from"../shared/constants.js";import{nowIso}from"../shared/time.js";import{detectAgentIdentity,readAuthorEnvironment}from"../shared/author.js";import{resolveGlobalPmRoot}from"../store/paths.js";import{isConfigurationOnlySettingsRead,readSettings,runWithConfigurationOnlySettings,writeSettings}from"../store/settings.js";import{clearSettingsReadCache}from"../store/settings-read-cache.js";import{deriveTelemetryCommandResolution,deriveTelemetryCommandTaxonomy,inferTelemetryErrorCode}from"./observability.js";const TELEMETRY_QUEUE_RELATIVE_PATH=path.join("runtime","telemetry","events.jsonl"),TELEMETRY_STATE_RELATIVE_PATH=path.join("runtime","telemetry","state.json"),TELEMETRY_OTEL_SPANS_RELATIVE_PATH=path.join("runtime","telemetry","otel-spans.jsonl"),TELEMETRY_OTEL_SPANS_FLUSH_BATCH_SIZE=8,TELEMETRY_OTEL_SPANS_MAX_PENDING=500,TELEMETRY_SCHEMA_VERSION=1,TELEMETRY_CLIENT_SCHEMA_VERSION=1,TELEMETRY_FLUSH_BATCH_SIZE=100,TELEMETRY_MAX_RETRY_DELAY_MS=36e5,TELEMETRY_RETRY_BASE_DELAY_MS=3e4,TELEMETRY_HTTP_TIMEOUT_DEFAULT_MS=2e4,TELEMETRY_HTTP_TIMEOUT_MIN_MS=1e3,TELEMETRY_HTTP_TIMEOUT_MAX_MS=25e3,TELEMETRY_FOREGROUND_LOCK_WAIT_MS=250,MILLISECONDS_PER_DAY=864e5,TELEMETRY_MAX_EVENT_BYTES=65536,TELEMETRY_SANITIZE_MAX_DEPTH=6,TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS=20,TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS=15,TELEMETRY_RESULT_PREVIEW_MAX_BYTES=8192,TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS=[25,50,100,200],TELEMETRY_QUEUE_TMP_ORPHAN_MAX_AGE_MS=3600*1e3,TELEMETRY_FLUSH_LOCK_STALE_MS=6e4,TELEMETRY_FLUSH_SPAWN_LOCK_STALE_MS=6e4,OTEL_TRACES_ENDPOINT_ENV="OTEL_EXPORTER_OTLP_TRACES_ENDPOINT",OTEL_BASE_ENDPOINT_ENV="OTEL_EXPORTER_OTLP_ENDPOINT",OTEL_SERVICE_NAME_ENV="OTEL_SERVICE_NAME",PM_TELEMETRY_OTEL_DISABLED_ENV="PM_TELEMETRY_OTEL_DISABLED",PM_TELEMETRY_OTEL_DISABLED_VALUES=new Set(["1","true","yes","on"]),PM_TELEMETRY_INLINE_FLUSH_ENV="PM_TELEMETRY_INLINE_FLUSH",PM_TELEMETRY_FLUSH_CHILD_ENV="PM_TELEMETRY_FLUSH_CHILD",PM_TELEMETRY_SOURCE_CONTEXT_ENV="PM_TELEMETRY_SOURCE_CONTEXT",PM_TELEMETRY_HTTP_TIMEOUT_MS_ENV="PM_TELEMETRY_HTTP_TIMEOUT_MS",NATIVE_FETCH=globalThis.fetch;import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES as PM_TELEMETRY_SOURCE_CONTEXT_VALUES2}from"./policy.js";let sourceContextWarningEmitted=!1,_lastFlushPromise=Promise.resolve(),_queueMutationPromise=Promise.resolve();const deferredReadStarts=new WeakMap;async function waitForPendingFlush(){await _lastFlushPromise,await _queueMutationPromise}const PM_TELEMETRY_SOURCE_CONTEXT_SET=new Set(PM_TELEMETRY_SOURCE_CONTEXT_VALUES),BOOLEAN_TRUE_VALUES=new Set(["1","true","yes","on"]),TELEMETRY_HARNESSES=new Set(["claude-code","codex","pi","opencode","cursor","aider","gemini-cli","ci"]),PROCESS_SESSION_ID=crypto.randomUUID(),SENSITIVE_KEYWORDS=["token","secret","password","passwd","api_key","apikey","authorization","cookie","session","credentials","bearer"],REDACTION_INPUT_KEYS=new Set(["literal","literals","regex","regexes","replacement","replacements","setjson","set_json","update"]),SENSITIVE_INLINE_KEY_PATTERN="(?:token|secret|password|passwd|api[_-]?key|apikey|authorization|cookie|session|credentials|bearer|literals?|regex(?:es)?|replacements?)",INLINE_SENSITIVE_ASSIGNMENT_PATTERN=new RegExp(`\\b(${SENSITIVE_INLINE_KEY_PATTERN})\\s*([:=])\\s*([^\\s,;]+)`,"giu"),INLINE_SENSITIVE_FLAG_PATTERN=new RegExp(`(--${SENSITIVE_INLINE_KEY_PATTERN})(=|\\s+)([^\\s,;]+)`,"giu"),ABSOLUTE_PATH_TOKEN_PATTERN=/(^|[\s"'`(=])\/(?:[^\s"'`),;]+)/g,BEARER_TOKEN_PATTERN=/bearer\s+[a-z0-9._=-]+/giu,PRIVATE_IP_PATTERN=/\b(?:10\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|172\.(?:1[6-9]|2\d|3[01])\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|192\.168\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d))\b/g;function queuePath(globalPmRoot){return path.join(globalPmRoot,TELEMETRY_QUEUE_RELATIVE_PATH)}function otelSpansQueuePath(globalPmRoot){return path.join(globalPmRoot,TELEMETRY_OTEL_SPANS_RELATIVE_PATH)}function telemetryRuntimeDirectory(globalPmRoot){return path.dirname(queuePath(globalPmRoot))}function runtimeStatePath(globalPmRoot){return path.join(globalPmRoot,TELEMETRY_STATE_RELATIVE_PATH)}function flushLockPath(globalPmRoot){return path.join(globalPmRoot,"runtime","telemetry","flush.lock")}function flushSpawnLockPath(globalPmRoot){return path.join(globalPmRoot,"runtime","telemetry","flush.spawn.lock")}function telemetryFlushRunnerPath(){return path.join(resolvePmPackageRootFromModule(import.meta.url,["../../.."]),"dist","cli","telemetry-flush.js")}function shouldFlushInline(){if(parseBooleanTrueLike(process.env[PM_TELEMETRY_INLINE_FLUSH_ENV])||parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV]))return!0;const nodeEnv=(process.env.NODE_ENV??"").trim().toLowerCase();return typeof process.env.VITEST=="string"||typeof process.env.VITEST_WORKER_ID=="string"||nodeEnv==="test"}async function readRuntimeState(globalPmRoot){const raw=await readFileIfExists(runtimeStatePath(globalPmRoot));if(!raw||raw.trim().length===0)return{};try{const parsed=JSON.parse(raw);return typeof parsed!="object"||parsed===null||Array.isArray(parsed)?{}:parsed}catch{return{}}}async function writeRuntimeState(globalPmRoot,patch){try{await withQueueMutation(async()=>{const next={...await readRuntimeState(globalPmRoot),...patch},normalized=Object.fromEntries(Object.entries(next).filter(([,value])=>value!==void 0).sort((left,right)=>left[0].localeCompare(right[0])));await writeFileAtomic(runtimeStatePath(globalPmRoot),`${JSON.stringify(normalized,null,2)}
2
2
  `,{createParentDirectories:!parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])})},globalPmRoot)}catch{}}function isSensitiveKey(key){const normalized=key.trim().toLowerCase().replaceAll("-","_").replaceAll(/[^a-z0-9_]+/g,"_"),tokens=normalized.split("_").filter(token=>token.length>0);return REDACTION_INPUT_KEYS.has(normalized)||SENSITIVE_KEYWORDS.some(keyword=>normalized===keyword||normalized.endsWith(`_${keyword}`)||tokens.includes(keyword))}function redactInlineSensitiveAssignments(input){return input.replaceAll(INLINE_SENSITIVE_ASSIGNMENT_PATTERN,(_match,key,delimiter)=>`${key}${delimiter}[redacted]`).replaceAll(INLINE_SENSITIVE_FLAG_PATTERN,(_match,flag,delimiter)=>`${flag}${delimiter}[redacted]`)}function redactAbsolutePathTokens(input){return input.replaceAll(ABSOLUTE_PATH_TOKEN_PATTERN,(_match,prefix)=>`${prefix}[redacted_path]`)}function isAsciiLetterOrDigitCode(code){const isUpper=code>=65&&code<=90,isLower=code>=97&&code<=122,isDigit=code>=48&&code<=57;return isUpper||isLower||isDigit}function isEmailLocalCharacter(character){if(!character)return!1;const code=character.charCodeAt(0);return isAsciiLetterOrDigitCode(code)?!0:character==="."||character==="_"||character==="%"||character==="+"||character==="-"}function isEmailDomainCharacter(character){if(!character)return!1;const code=character.charCodeAt(0);return isAsciiLetterOrDigitCode(code)?!0:character==="."||character==="-"}function looksLikeEmailToken(token){const atIndex=token.indexOf("@");if(atIndex<=0||atIndex!==token.lastIndexOf("@")||atIndex===token.length-1)return!1;const localPart=token.slice(0,atIndex),domainPart=token.slice(atIndex+1),lastDot=domainPart.lastIndexOf(".");if(lastDot<=0||lastDot===domainPart.length-1||domainPart.length-(lastDot+1)<2)return!1;for(const character of localPart)if(!isEmailLocalCharacter(character))return!1;for(const character of domainPart)if(!isEmailDomainCharacter(character))return!1;return!0}function redactEmailTokens(input){let redacted="",cursor=0;for(;cursor<input.length;){const atIndex=input.indexOf("@",cursor);if(atIndex<0){redacted+=input.slice(cursor);break}let start=atIndex-1;for(;start>=cursor&&isEmailLocalCharacter(input[start]);)start-=1;start+=1;let end=atIndex+1;for(;end<input.length&&isEmailDomainCharacter(input[end]);)end+=1;const candidate=input.slice(start,end);if(looksLikeEmailToken(candidate)){redacted+=input.slice(cursor,start),redacted+="[redacted_email]",cursor=end;continue}redacted+=input.slice(cursor,atIndex+1),cursor=atIndex+1}return redacted}function sanitizeCommonSensitiveTokens(input){return redactEmailTokens(input).replaceAll(BEARER_TOKEN_PATTERN,"bearer [redacted_token]").replaceAll(PRIVATE_IP_PATTERN,"[redacted_ip]")}function sanitizeStringRedacted(input){const withoutCommonSensitiveTokens=sanitizeCommonSensitiveTokens(input),withoutInlineSecrets=redactInlineSensitiveAssignments(withoutCommonSensitiveTokens),withoutAbsolutePaths=redactAbsolutePathTokens(withoutInlineSecrets),trimmed=withoutAbsolutePaths.trim();return trimmed.startsWith("/")&&trimmed.length>1?"[redacted_path]":withoutAbsolutePaths.length>512?`${withoutAbsolutePaths.slice(0,509)}...`:withoutAbsolutePaths}function sanitizeStringMax(input){const withoutCommonSensitiveTokens=sanitizeCommonSensitiveTokens(input),withoutInlineSecrets=redactInlineSensitiveAssignments(withoutCommonSensitiveTokens),withoutAbsolutePaths=redactAbsolutePathTokens(withoutInlineSecrets),trimmed=withoutAbsolutePaths.trim();return trimmed.startsWith("/")&&trimmed.length>1?"[redacted_path]":withoutAbsolutePaths.length>2048?`${withoutAbsolutePaths.slice(0,2045)}...`:withoutAbsolutePaths}function sanitizeString(input,captureLevel="redacted"){return captureLevel==="max"?sanitizeStringMax(input):sanitizeStringRedacted(input)}function sanitizeValue(value,keyHint,captureLevel="redacted",depth=0){if(keyHint&&isSensitiveKey(keyHint))return"[redacted]";if(value==null)return value;if(typeof value=="string")return sanitizeString(value,captureLevel);if(typeof value=="number"||typeof value=="boolean")return value;if(depth>=TELEMETRY_SANITIZE_MAX_DEPTH)return"[depth_truncated]";if(Array.isArray(value))return value.slice(0,TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS).map(entry=>sanitizeValue(entry,void 0,captureLevel,depth+1));if(typeof value=="object"){const record=value,sanitized={};for(const[key,nested]of Object.entries(record))sanitized[key]=sanitizeValue(nested,key,captureLevel,depth+1);return sanitized}return String(value)}function sanitizeCommandArgs(args,captureLevel="redacted"){const sanitized=[];let nextIsSensitiveValue=!1;for(const rawArg of args){const arg=sanitizeString(rawArg,captureLevel);if(nextIsSensitiveValue){sanitized.push("[redacted]"),nextIsSensitiveValue=!1;continue}if(arg.startsWith("--")){const withoutPrefix=arg.slice(2),delimiterIndex=withoutPrefix.indexOf("=");if(delimiterIndex>=0){const key=withoutPrefix.slice(0,delimiterIndex),value=withoutPrefix.slice(delimiterIndex+1);isSensitiveKey(key)?sanitized.push(`--${key}=[redacted]`):sanitized.push(`--${key}=${sanitizeString(value,captureLevel)}`);continue}if(isSensitiveKey(withoutPrefix)){sanitized.push(`--${withoutPrefix}`),nextIsSensitiveValue=!0;continue}}sanitized.push(arg)}return sanitized}function normalizeCaptureLevel(value){const normalized=value?.trim().toLowerCase();return normalized==="minimal"||normalized==="redacted"||normalized==="max"?normalized:"redacted"}function parseBooleanTrueLike(value){return BOOLEAN_TRUE_VALUES.has((value??"").trim().toLowerCase())}function resolveTelemetryHttpTimeoutMs(){const rawConfigured=process.env[PM_TELEMETRY_HTTP_TIMEOUT_MS_ENV]?.trim();if(!rawConfigured)return TELEMETRY_HTTP_TIMEOUT_DEFAULT_MS;const configured=Number(rawConfigured);return Number.isFinite(configured)?Math.min(TELEMETRY_HTTP_TIMEOUT_MAX_MS,Math.max(TELEMETRY_HTTP_TIMEOUT_MIN_MS,Math.trunc(configured))):TELEMETRY_HTTP_TIMEOUT_DEFAULT_MS}async function postTelemetryJson(endpoint,headers,body){const url=new URL(endpoint);if(globalThis.fetch!==NATIVE_FETCH){const controller=new AbortController;let timeout;const deadline=new Promise((_resolve,reject)=>{timeout=setTimeout(()=>{controller.abort(),reject(new Error("telemetry_http_timeout"))},resolveTelemetryHttpTimeoutMs())});try{return(await Promise.race([globalThis.fetch(endpoint,{method:"POST",headers,body,signal:controller.signal}),deadline])).status}finally{clearTimeout(timeout)}}const request=url.protocol==="https:"?httpsRequest:url.protocol==="http:"?httpRequest:void 0;if(!request)throw new Error(`telemetry_http_protocol_unsupported_${url.protocol}`);return new Promise((resolve,reject)=>{const timeoutMs=resolveTelemetryHttpTimeoutMs(),requestOptions={method:"POST",headers:{...headers,"content-length":Buffer.byteLength(body)},signal:AbortSignal.timeout(timeoutMs),autoSelectFamilyAttemptTimeout:Math.min(5e3,timeoutMs)},clientRequest=request(url,requestOptions,response=>{response.once("error",reject),response.once("end",()=>resolve(response.statusCode)),response.resume()});clientRequest.once("error",reject),clientRequest.end(body)})}function normalizePmVersion(value){const trimmed=typeof value=="string"?value.trim():"";return trimmed.length>0?trimmed:"0.0.0"}function normalizeTelemetryErrorCode(value){const normalized=value?.trim();return normalized&&normalized.length>0?normalized:void 0}function normalizeTelemetryExitCode(exitCode,ok){return Number.isFinite(exitCode)?Math.max(0,Math.trunc(exitCode)):ok?0:1}function normalizeTelemetryErrorCategory(params){if(!params.ok)return typeof params.errorCategory=="string"&&params.errorCategory.trim().length>0?params.errorCategory:typeof params.errorCode=="string"&&params.errorCode.trim().length>0?resolveTelemetryErrorCategory(params.errorCode):"unknown"}function resolveTelemetrySourceContext(globalOptions){const override=(process.env[PM_TELEMETRY_SOURCE_CONTEXT_ENV]??"").trim().toLowerCase();if(PM_TELEMETRY_SOURCE_CONTEXT_SET.has(override))return{source_context:override,source_context_source:"env_override"};const source=override.length>0?"env_override_rejected":"inferred";return source==="env_override_rejected"&&!sourceContextWarningEmitted&&!globalOptions.quiet&&(sourceContextWarningEmitted=!0,process.stderr.write(`[pm] warning: PM_TELEMETRY_SOURCE_CONTEXT is not one of ${PM_TELEMETRY_SOURCE_CONTEXT_VALUES.join("|")}; ignoring override.
3
3
  `)),{source_context:inferTelemetrySourceContext(globalOptions),source_context_source:source}}function inferTelemetrySourceContext(globalOptions){const nodeEnv=(process.env.NODE_ENV??"").trim().toLowerCase();if(typeof process.env.VITEST=="string"||typeof process.env.VITEST_WORKER_ID=="string"||nodeEnv==="test")return"test";const nonTty=process.stdin.isTTY!==!0||process.stdout.isTTY!==!0,ci=parseBooleanTrueLike(process.env.CI),scriptLikeMode=globalOptions.json===!0||globalOptions.quiet===!0;return nonTty||ci||scriptLikeMode?"automation":"user"}function hashWithInstallationId(installationId,value){return crypto.createHash("sha256").update(`${installationId}:${value}`).digest("hex")}function buildAuthorContextPayloadFields(captureLevel,installationId){const author=(readAuthorEnvironment()??"").trim(),agent=detectAgentIdentity({env:process.env,argv:process.argv}),hasAgentContext=agent.harness!==void 0||agent.model!==void 0;return captureLevel==="minimal"?{has_author_context:author.length>0,has_agent_context:hasAgentContext}:{agent_harness:agent.harness?TELEMETRY_HARNESSES.has(agent.harness)?agent.harness:"other":"none",ci:parseBooleanTrueLike(process.env.CI),...author.length>0?{author_context_hash:hashWithInstallationId(installationId,author)}:{},...agent.harness?{agent_harness_hash:hashWithInstallationId(installationId,agent.harness)}:{},...agent.model?{agent_model_hash:hashWithInstallationId(installationId,agent.model)}:{},...agent.model_source?{agent_model_source:agent.model_source}:{}}}function normalizeForHash(value,depth=0){if(value==null||typeof value=="string"||typeof value=="number"||typeof value=="boolean")return value;if(depth>=TELEMETRY_SANITIZE_MAX_DEPTH)return"[depth_truncated]";if(Array.isArray(value))return value.slice(0,TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS).map(entry=>normalizeForHash(entry,depth+1));if(typeof value=="object"){const record=value,normalized={},sortedKeys=Object.keys(record).sort((left,right)=>left.localeCompare(right));for(const key of sortedKeys)normalized[key]=normalizeForHash(record[key],depth+1);return normalized}return String(value)}function hashTelemetryValue(installationId,value){return hashWithInstallationId(installationId,JSON.stringify(normalizeForHash(value)))}function hashCommandArgs(installationId,args){return{hashes:args.map(arg=>hashWithInstallationId(installationId,arg)),digest:hashWithInstallationId(installationId,args.join("\0"))}}function hashTelemetryErrorFingerprint(installationId,command,errorCode2,errorMessage){const normalizedMessage=sanitizeString(typeof errorMessage=="string"?errorMessage:"","redacted"),normalizedCode=typeof errorCode2=="string"&&errorCode2.length>0?errorCode2:"unknown_error",fingerprintSource=`${command}\0${normalizedCode}\0${normalizedMessage}`;return hashWithInstallationId(installationId,fingerprintSource)}function resolveOtelTracesEndpoint(){if(PM_TELEMETRY_OTEL_DISABLED_VALUES.has((process.env[PM_TELEMETRY_OTEL_DISABLED_ENV]??"").trim().toLowerCase()))return null;const directEndpoint=(process.env[OTEL_TRACES_ENDPOINT_ENV]??"").trim();if(directEndpoint.length>0)try{return new URL(directEndpoint).toString()}catch{return null}const baseEndpoint=(process.env[OTEL_BASE_ENDPOINT_ENV]??"").trim();if(baseEndpoint.length===0)return null;try{const url=new URL(baseEndpoint),normalizedPath=url.pathname.replace(/\/+$/,"");return normalizedPath.endsWith("/v1/traces")||(url.pathname=`${normalizedPath.length===0?"":normalizedPath}/v1/traces`),url.toString()}catch{return null}}function isoToUnixNano(iso){const parsedMs=Date.parse(iso),epochMs=Number.isNaN(parsedMs)?Date.now():parsedMs;return`${BigInt(epochMs)*1000000n}`}function otlpStringAttribute(key,value){return{key,value:{stringValue:value}}}function otlpBoolAttribute(key,value){return{key,value:{boolValue:value}}}function otlpIntAttribute(key,value){return{key,value:{intValue:String(Math.max(0,Math.trunc(value)))}}}function buildOtelSpanRequest(activeCommand,outcome,finishedAtIso,durationMs,sampleRate=1){const endpoint=activeCommand.otel_traces_endpoint;if(typeof endpoint!="string"||endpoint.trim().length===0||[activeCommand.otel_trace_id,activeCommand.otel_span_id].some(id=>typeof id!="string"||id.length===0))return null;const serviceNameCandidate=sanitizeString((process.env[OTEL_SERVICE_NAME_ENV]??"").trim()),serviceName=serviceNameCandidate.length>0?serviceNameCandidate:"pm-cli",normalizedExitCode=normalizeTelemetryExitCode(outcome.exit_code,outcome.ok),normalizedErrorCode=normalizeTelemetryErrorCode(outcome.error_code),normalizedErrorCategory=normalizeTelemetryErrorCategory({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:outcome.error_category}),attributes=[otlpStringAttribute("pm.command",sanitizeString(activeCommand.command)),otlpStringAttribute("pm.version",activeCommand.pm_version),otlpStringAttribute("pm.source_context",activeCommand.source_context),otlpStringAttribute("pm.source_context_source",activeCommand.source_context_source),otlpStringAttribute("pm.installation_id",activeCommand.installation_id),otlpStringAttribute("pm.session_id",PROCESS_SESSION_ID),otlpStringAttribute("pm.pm_root_hash",activeCommand.pm_root_hash),otlpStringAttribute("pm.cwd_hash",activeCommand.cwd_hash),otlpBoolAttribute("pm.ok",outcome.ok),otlpIntAttribute("pm.exit_code",normalizedExitCode),otlpIntAttribute("pm.duration_ms",durationMs),otlpStringAttribute("pm.sample_rate",String(sampleRate))];typeof normalizedErrorCode=="string"&&attributes.push(otlpStringAttribute("pm.error_code",normalizedErrorCode)),typeof normalizedErrorCategory=="string"&&attributes.push(otlpStringAttribute("pm.error_category",normalizedErrorCategory)),typeof outcome.error=="string"&&outcome.error.trim().length>0&&attributes.push(otlpStringAttribute("pm.error",sanitizeString(outcome.error)));const payload={resourceSpans:[{resource:{attributes:[otlpStringAttribute("service.name",serviceName)]},scopeSpans:[{scope:{name:"pm-cli.telemetry",version:"1"},spans:[{traceId:activeCommand.otel_trace_id,spanId:activeCommand.otel_span_id,name:`pm.command.${sanitizeString(activeCommand.command)}`,kind:1,startTimeUnixNano:isoToUnixNano(activeCommand.started_at),endTimeUnixNano:isoToUnixNano(finishedAtIso),attributes,status:{code:outcome.ok?1:2,message:outcome.ok?"":sanitizeString(typeof outcome.error=="string"?outcome.error:"command_failed")}}]}]}]};return{endpoint,payload}}function summarizeResult(result,captureLevel="redacted"){if(result==null)return{type:"nullish"};if(typeof result=="string")return{type:"string",value:sanitizeString(result,captureLevel)};if(typeof result=="number"||typeof result=="boolean")return{type:typeof result,value:result};if(Array.isArray(result))return{type:"array",length:result.length,sample:result.slice(0,5).map(entry=>sanitizeValue(entry,void 0,captureLevel))};if(typeof result=="object"){const record=result,keys=Object.keys(record).filter(key=>key!=="tests").sort((left,right)=>left.localeCompare(right)),sanitized={};let previewBytes=0;for(const key of keys.slice(0,25)){const sanitizedValue=sanitizeValue(record[key],key,captureLevel);if(sanitizedValue===void 0)continue;const entrySize=JSON.stringify(sanitizedValue).length;if(previewBytes+entrySize>TELEMETRY_RESULT_PREVIEW_MAX_BYTES){sanitized[key]="[preview_truncated]";break}previewBytes+=entrySize,sanitized[key]=sanitizedValue}return{type:"object",key_count:keys.length,keys_preview:keys.slice(0,50),preview:sanitized}}return{type:typeof result,value:String(result)}}function buildCommandStartPayload(params){const{captureLevel,context,pmVersion,sourceContext,pmRootHash,cwdHash,installationId}=params,commandTaxonomy=deriveTelemetryCommandTaxonomy(context.command),hashedArgs=hashCommandArgs(installationId,context.args),commandInvocationDigest=hashWithInstallationId(installationId,`${context.command}\0${context.args.join("\0")}`),commandOptionsDigest=hashTelemetryValue(installationId,context.options),globalOptionsDigest=hashTelemetryValue(installationId,context.global),authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);return captureLevel==="minimal"?{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_args_digest:hashedArgs.digest,command_invocation_digest:commandInvocationDigest,command_options_digest:commandOptionsDigest,global_options_digest:globalOptionsDigest,...authorContextFields}:{pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,...authorContextFields,command_args:sanitizeCommandArgs(context.args,captureLevel),command_args_hashes:hashedArgs.hashes,command_args_digest:hashedArgs.digest,command_invocation_digest:commandInvocationDigest,command_options:sanitizeValue(context.options,void 0,captureLevel),command_options_digest:commandOptionsDigest,global_options:sanitizeValue(context.global,void 0,captureLevel),global_options_digest:globalOptionsDigest,pm_root_hash:pmRootHash,cwd_hash:cwdHash,capture_level:captureLevel,runtime:{node:process.version,platform:process.platform,arch:process.arch,hostname_hash:hashWithInstallationId(installationId,os.hostname()),stdin_tty:process.stdin.isTTY===!0,stdout_tty:process.stdout.isTTY===!0}}}function buildCommandFinishPayload(params){const{captureLevel,pmVersion,sourceContext,outcome,durationMs,startedAt,command,installationId,commandTaxonomy,exitCode,errorCode:errorCode2,errorCategory,commandResolution,resolutionStage}=params,errorFingerprint=outcome.ok===!1?hashTelemetryErrorFingerprint(installationId,command,errorCode2,outcome.error):void 0,authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);return captureLevel==="minimal"?{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_resolution:commandResolution,resolution_stage:resolutionStage,ok:outcome.ok,exit_code:exitCode,error_code:errorCode2,error_category:errorCategory,error:outcome.error?sanitizeString(outcome.error,"redacted"):void 0,error_fingerprint:errorFingerprint,duration_ms:durationMs,...authorContextFields}:{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_resolution:commandResolution,resolution_stage:resolutionStage,...authorContextFields,ok:outcome.ok,exit_code:exitCode,error_code:errorCode2,error_category:errorCategory,error:outcome.error?sanitizeString(outcome.error,captureLevel):void 0,error_fingerprint:errorFingerprint,duration_ms:durationMs,started_at:startedAt,result_summary:summarizeResult(outcome.result,captureLevel)}}function buildCommandErrorPayload(params){const{captureLevel,pmVersion,sourceContext,command,commandTaxonomy,commandResolution,resolutionStage,args,options,pmRootHash,cwdHash,installationId,errorCode:errorCode2,errorMessage,errorCategory,exitCode}=params,attemptedArgHashes=hashCommandArgs(installationId,args),attemptedCommandDigest=hashWithInstallationId(installationId,command),attemptedOptionsDigest=hashTelemetryValue(installationId,options),errorFingerprint=hashTelemetryErrorFingerprint(installationId,command,errorCode2,errorMessage),authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);return captureLevel==="minimal"?{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_resolution:commandResolution,resolution_stage:resolutionStage,attempted_command_digest:attemptedCommandDigest,attempted_args_digest:attemptedArgHashes.digest,attempted_options_digest:attemptedOptionsDigest,error_code:errorCode2,error_category:errorCategory,exit_code:exitCode,error:sanitizeString(errorMessage,"redacted"),error_fingerprint:errorFingerprint,...authorContextFields}:{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_resolution:commandResolution,resolution_stage:resolutionStage,...authorContextFields,attempted_command:sanitizeString(command,captureLevel),attempted_command_digest:attemptedCommandDigest,attempted_args:sanitizeCommandArgs(args,captureLevel),attempted_args_hashes:attemptedArgHashes.hashes,attempted_args_digest:attemptedArgHashes.digest,attempted_options:sanitizeValue(options,void 0,captureLevel),attempted_options_digest:attemptedOptionsDigest,error_code:errorCode2,error_category:errorCategory,exit_code:exitCode,error:sanitizeString(errorMessage,captureLevel),error_fingerprint:errorFingerprint,pm_root_hash:pmRootHash,cwd_hash:cwdHash,runtime:{node:process.version,platform:process.platform,arch:process.arch,hostname_hash:hashWithInstallationId(installationId,os.hostname()),stdin_tty:process.stdin.isTTY===!0,stdout_tty:process.stdout.isTTY===!0}}}async function ensureInstallationId(globalPmRoot){const settings=await readSettings(globalPmRoot);if(!settings.telemetry.enabled||resolveTelemetryEnvironmentPolicy().telemetry_disabled)return null;if(settings.telemetry.installation_id.trim().length===0){if(isConfigurationOnlySettingsRead(globalPmRoot))return null;settings.telemetry.installation_id=crypto.randomUUID(),await writeSettings(globalPmRoot,settings,"telemetry:install_id")}return{installationId:settings.telemetry.installation_id,endpoint:settings.telemetry.endpoint,retentionDays:Math.max(1,Math.trunc(settings.telemetry.retention_days)),captureLevel:normalizeCaptureLevel(settings.telemetry.capture_level)}}async function appendTelemetryEvent(globalPmRoot,event){let serialized=JSON.stringify({client_schema_version:TELEMETRY_CLIENT_SCHEMA_VERSION,event,attempts:0});if(serialized.length>TELEMETRY_MAX_EVENT_BYTES){const trimmed={...event,payload:{...event.payload,result_summary:{truncated:!0,reason:"payload_size_exceeded",original_bytes:serialized.length}}};serialized=JSON.stringify({client_schema_version:TELEMETRY_CLIENT_SCHEMA_VERSION,event:trimmed,attempts:0})}await appendLineAtomic(queuePath(globalPmRoot),serialized)}async function enqueueTelemetryEvent(globalPmRoot,event){await withQueueMutation(()=>appendTelemetryEvent(globalPmRoot,event),globalPmRoot)}function parseQueueLines(raw){const entries=[];for(const line of raw.split(`
4
4
  `)){const trimmed=line.trim();if(trimmed.length!==0)try{const parsed=JSON.parse(trimmed);parsed&&typeof parsed=="object"&&parsed.event&&typeof parsed.event=="object"&&typeof parsed.attempts=="number"&&(parsed.client_schema_version===void 0||typeof parsed.client_schema_version=="number"&&Number.isFinite(parsed.client_schema_version))&&entries.push(parsed)}catch{}}return entries}function nextRetryIso(attempts){const delay=Math.min(TELEMETRY_RETRY_BASE_DELAY_MS*2**Math.max(attempts-1,0),TELEMETRY_MAX_RETRY_DELAY_MS);return new Date(Date.now()+delay).toISOString()}function isDueForRetryAt(nextAttemptAfter){if(typeof nextAttemptAfter!="string"||nextAttemptAfter.trim().length===0)return!0;const dueAtMs=Date.parse(nextAttemptAfter);return Number.isNaN(dueAtMs)?!0:dueAtMs<=Date.now()}function isDueForRetry(entry){return isDueForRetryAt(entry.next_attempt_after)}function retentionCutoffMs(retentionDays){const normalizedDays=Number.isFinite(retentionDays)?Math.max(1,Math.trunc(retentionDays)):1;return Date.now()-normalizedDays*MILLISECONDS_PER_DAY}function isExpiredQueueEntry(entry,cutoffMs){const occurredAt=entry.event?.occurred_at;if(typeof occurredAt!="string"||occurredAt.trim().length===0)return!1;const occurredAtMs=Date.parse(occurredAt);return Number.isNaN(occurredAtMs)?!1:occurredAtMs<cutoffMs}function pruneExpiredQueueEntries(entries,retentionDays){const cutoffMs=retentionCutoffMs(retentionDays),retained=[];let prunedCount=0;for(const entry of entries){if(JSON.stringify(entry).length>TELEMETRY_MAX_EVENT_BYTES||isExpiredQueueEntry(entry,cutoffMs)||entry.attempts>=TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS){prunedCount+=1;continue}retained.push(entry)}return{entries:retained,prunedCount}}async function rewriteQueue(globalPmRoot,entries){const serialized=entries.map(entry=>JSON.stringify(entry)).join(`
@@ -6,5 +6,5 @@
6
6
  `:"";for(let attempt=0;;attempt+=1)try{await writeFileAtomic(queuePath(globalPmRoot),contents,{createParentDirectories:!parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])});return}catch(error){const retryDelay=TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS[attempt];if(retryDelay===void 0||!isRetryableQueueRewriteError(error))throw error;await sleep(retryDelay)}}function isRetryableQueueRewriteError(error){if(typeof error!="object"||error===null||!("code"in error))return!1;const code=error.code;return code==="EACCES"||code==="EBUSY"||code==="EPERM"}function sleep(milliseconds){return new Promise(resolve=>{setTimeout(resolve,milliseconds)})}async function appendPendingOtelSpan(globalPmRoot,request){const pending={id:crypto.randomUUID(),endpoint:request.endpoint,payload:request.payload,enqueued_at:nowIso(),attempts:0},serialized=JSON.stringify(pending);serialized.length>TELEMETRY_MAX_EVENT_BYTES||await appendLineAtomic(otelSpansQueuePath(globalPmRoot),serialized)}async function enqueuePendingOtelSpan(globalPmRoot,request){await withQueueMutation(()=>appendPendingOtelSpan(globalPmRoot,request),globalPmRoot)}function backfillPendingOtelSpanId(entry){const material=JSON.stringify([entry.endpoint,entry.enqueued_at,entry.payload]);return crypto.createHash("sha256").update(material).digest("hex").slice(0,32)}function parsePendingOtelSpanLines(raw){const entries=[];for(const line of raw.split(`
7
7
  `)){const trimmed=line.trim();if(trimmed.length!==0)try{const parsed=JSON.parse(trimmed);parsed&&typeof parsed=="object"&&typeof parsed.endpoint=="string"&&parsed.endpoint.trim().length>0&&"payload"in parsed&&typeof parsed.attempts=="number"&&Number.isFinite(parsed.attempts)&&((typeof parsed.id!="string"||parsed.id.length===0)&&(parsed.id=backfillPendingOtelSpanId(parsed)),entries.push(parsed))}catch{}}return entries}function isExpiredPendingOtelSpan(entry,cutoffMs){if(typeof entry.enqueued_at!="string"||entry.enqueued_at.trim().length===0)return!1;const enqueuedAtMs=Date.parse(entry.enqueued_at);return Number.isNaN(enqueuedAtMs)?!1:enqueuedAtMs<cutoffMs}function prunePendingOtelSpans(entries,retentionDays){const cutoffMs=retentionCutoffMs(retentionDays),retained=[];let prunedCount=0;for(const entry of entries){if(JSON.stringify(entry).length>TELEMETRY_MAX_EVENT_BYTES||isExpiredPendingOtelSpan(entry,cutoffMs)||entry.attempts>=TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS){prunedCount+=1;continue}retained.push(entry)}if(retained.length>TELEMETRY_OTEL_SPANS_MAX_PENDING){const overflow=retained.length-TELEMETRY_OTEL_SPANS_MAX_PENDING;return prunedCount+=overflow,{entries:retained.slice(overflow),prunedCount}}return{entries:retained,prunedCount}}async function rewritePendingOtelSpans(globalPmRoot,entries){const serialized=entries.map(entry=>JSON.stringify(entry)).join(`
8
8
  `),contents=serialized.length>0?`${serialized}
9
- `:"";for(let attempt=0;;attempt+=1)try{await writeFileAtomic(otelSpansQueuePath(globalPmRoot),contents,{createParentDirectories:!parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])});return}catch(error){const retryDelay=TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS[attempt];if(retryDelay===void 0||!isRetryableQueueRewriteError(error))throw error;await sleep(retryDelay)}}async function reconcilePendingOtelSpansAfterFlush(globalPmRoot,retentionDays,succeededIds,failedUpdates){return withQueueMutation(async()=>{const raw=await readFileIfExists(otelSpansQueuePath(globalPmRoot)),current=raw===null?[]:parsePendingOtelSpanLines(raw),reconciled=[];for(const entry of current){if(succeededIds.has(entry.id))continue;const failure=failedUpdates.get(entry.id);reconciled.push(failure?{...entry,attempts:failure.attempts,next_attempt_after:failure.next_attempt_after}:entry)}const{entries:retained}=prunePendingOtelSpans(reconciled,retentionDays);return await rewritePendingOtelSpans(globalPmRoot,retained),retained.length},globalPmRoot)}async function flushPendingOtelSpans(globalPmRoot,retentionDays){const raw=await readFileIfExists(otelSpansQueuePath(globalPmRoot));if(raw===null||raw.trim().length===0){await writeRuntimeState(globalPmRoot,{pending_otel_spans:0});return}const entries=parsePendingOtelSpanLines(raw),{entries:retained,prunedCount}=prunePendingOtelSpans(entries,retentionDays),due=retained.filter(entry=>isDueForRetryAt(entry.next_attempt_after)).slice(0,TELEMETRY_OTEL_SPANS_FLUSH_BATCH_SIZE);if(due.length===0){const remaining2=prunedCount>0?await reconcilePendingOtelSpansAfterFlush(globalPmRoot,retentionDays,new Set,new Map):retained.length;await writeRuntimeState(globalPmRoot,{pending_otel_spans:remaining2});return}const attemptTime=nowIso(),succeededIds=new Set,failedUpdates=new Map;let succeededCount=0,lastError;await Promise.all(due.map(async span=>{try{const status=await postTelemetryJson(span.endpoint,{"content-type":"application/json"},JSON.stringify(span.payload));if(status<200||status>=300)throw new Error(`local_otel_export_http_${status}`);succeededIds.add(span.id),succeededCount+=1}catch(error){lastError=error instanceof Error?sanitizeString(error.message,"redacted"):"local_otel_export_failed";const nextAttempts=span.attempts+1;failedUpdates.set(span.id,{attempts:nextAttempts,next_attempt_after:nextRetryIso(nextAttempts)})}}));const remaining=await reconcilePendingOtelSpansAfterFlush(globalPmRoot,retentionDays,succeededIds,failedUpdates),statePatch={pending_otel_spans:remaining,last_otel_attempt_at:attemptTime};succeededCount>0&&(statePatch.last_otel_success_at=attemptTime),lastError!==void 0?(statePatch.last_otel_failure_at=attemptTime,statePatch.last_otel_failure_error=lastError):remaining===0&&(statePatch.last_otel_failure_at=void 0,statePatch.last_otel_failure_error=void 0),await writeRuntimeState(globalPmRoot,statePatch)}async function flushTelemetryArtifacts(globalPmRoot,endpoint,retentionDays){try{await flushQueue(globalPmRoot,endpoint,retentionDays)}catch{}try{await flushPendingOtelSpans(globalPmRoot,retentionDays)}catch{}}async function cleanupTelemetryQueueTempOrphans(globalPmRoot,maxAgeMs=TELEMETRY_QUEUE_TMP_ORPHAN_MAX_AGE_MS){try{const dirPath=telemetryRuntimeDirectory(globalPmRoot),entries=await readdir(dirPath,{withFileTypes:!0}),cutoffMs=Date.now()-Math.max(0,maxAgeMs);await Promise.all(entries.filter(entry=>entry.isFile()&&/^\.events\.jsonl\.\d+\.\d+\.[a-f0-9]+\.tmp$/.test(entry.name)).map(async entry=>{const candidate=path.join(dirPath,entry.name);(await stat(candidate)).mtimeMs<cutoffMs&&await rm(candidate,{force:!0})}))}catch{}}async function withQueueMutation(operation,globalPmRoot=resolveGlobalPmRoot(process.cwd()),waitMs=5e3){const run=_queueMutationPromise.catch(()=>{}).then(()=>runWithIsolatedExtensionRuntime(async()=>{const release=await acquireLock(globalPmRoot,"telemetry-queue",60,"telemetry",!1,!1,waitMs,{createParentDirectories:!parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])});try{return clearSettingsReadCache(globalPmRoot),await operation()}finally{await release()}}));return _queueMutationPromise=run.catch(()=>{}),run}async function readCurrentQueueEntries(globalPmRoot){const raw=await readFileIfExists(queuePath(globalPmRoot));return raw===null||raw.trim().length===0?[]:parseQueueLines(raw)}async function removeFlushedEntriesFromCurrentQueue(globalPmRoot,flushedIds,retentionDays){return withQueueMutation(async()=>{const currentEntries=await readCurrentQueueEntries(globalPmRoot),{entries:retainedEntries}=pruneExpiredQueueEntries(currentEntries,retentionDays),remaining=retainedEntries.filter(entry=>!flushedIds.has(entry.event.event_id));return await rewriteQueue(globalPmRoot,remaining),remaining},globalPmRoot)}async function markFailedEntriesInCurrentQueue(globalPmRoot,failedIds,attemptTime,retentionDays){return withQueueMutation(async()=>{const currentEntries=await readCurrentQueueEntries(globalPmRoot),{entries:retainedEntries}=pruneExpiredQueueEntries(currentEntries,retentionDays),retried=retainedEntries.map(entry=>{if(!failedIds.has(entry.event.event_id))return entry;const attempts=entry.attempts+1;return{...entry,attempts,last_attempt_at:attemptTime,next_attempt_after:nextRetryIso(attempts)}});return await rewriteQueue(globalPmRoot,retried),retried},globalPmRoot)}async function flushQueue(globalPmRoot,endpoint,retentionDays){await cleanupTelemetryQueueTempOrphans(globalPmRoot);const normalizedEndpoint=endpoint.trim();if(normalizedEndpoint.length===0)return;const raw=await readFileIfExists(queuePath(globalPmRoot));if(raw===null||raw.trim().length===0){await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:0});return}const queueEntries=parseQueueLines(raw);if(queueEntries.length===0){await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:0});return}const{entries:retainedEntries,prunedCount}=pruneExpiredQueueEntries(queueEntries,retentionDays);if(retainedEntries.length===0){const remaining=await removeFlushedEntriesFromCurrentQueue(globalPmRoot,new Set,retentionDays);await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:remaining.length});return}const dueEntries=retainedEntries.filter(entry=>isDueForRetry(entry)).slice(0,TELEMETRY_FLUSH_BATCH_SIZE);if(dueEntries.length===0){const remaining=prunedCount>0?await removeFlushedEntriesFromCurrentQueue(globalPmRoot,new Set,retentionDays):retainedEntries;await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:remaining.length});return}const dueIds=new Set(dueEntries.map(entry=>entry.event.event_id)),attemptTime=nowIso(),requestHeaders={"content-type":"application/json"},ingestKey=process.env.PM_TELEMETRY_INGEST_KEY?.trim();ingestKey&&(requestHeaders["x-pm-telemetry-key"]=ingestKey);try{const status=await postTelemetryJson(normalizedEndpoint,requestHeaders,JSON.stringify({schema_version:TELEMETRY_SCHEMA_VERSION,events:dueEntries.map(entry=>entry.event)}));if(status<200||status>=300)throw new Error(`telemetry_flush_http_${status}`)}catch(error){const retried=await markFailedEntriesInCurrentQueue(globalPmRoot,dueIds,attemptTime,retentionDays),errorMessage=error instanceof Error?sanitizeString(error.message,"redacted"):"telemetry_flush_failed";await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:retried.length,last_attempted_flush_at:attemptTime,last_failed_flush_at:attemptTime,last_failed_flush_error:errorMessage});return}try{const remaining=await removeFlushedEntriesFromCurrentQueue(globalPmRoot,dueIds,retentionDays);await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:remaining.length,last_attempted_flush_at:attemptTime,last_successful_flush_at:attemptTime,last_failed_flush_at:void 0,last_failed_flush_error:void 0})}catch(error){const errorMessage=error instanceof Error?sanitizeString(error.message,"redacted"):"telemetry_flush_failed",currentEntries=await readCurrentQueueEntries(globalPmRoot).catch(()=>retainedEntries);await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:currentEntries.length,last_attempted_flush_at:attemptTime,last_failed_flush_at:attemptTime,last_failed_flush_error:errorMessage})}}async function acquireTelemetryFlushLock(globalPmRoot){const lockPath=flushLockPath(globalPmRoot);parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])||await mkdir(path.dirname(lockPath),{recursive:!0});try{return await mkdir(lockPath),!0}catch(error){if(typeof error!="object"||error===null||!("code"in error)||error.code!=="EEXIST")throw error}try{const lockStats=await stat(lockPath);return Date.now()-lockStats.mtimeMs<TELEMETRY_FLUSH_LOCK_STALE_MS?!1:(await rm(lockPath,{recursive:!0,force:!0}),await mkdir(lockPath),!0)}catch{return!1}}function isFreshDirectoryLock(lockPath,staleMs){try{return Date.now()-statSync(lockPath).mtimeMs<staleMs}catch{return!1}}function removeDirectoryLockBestEffort(lockPath){try{rmSync(lockPath,{recursive:!0,force:!0})}catch{}}function errorCode(error){if(typeof error!="object"||error===null||!("code"in error))return;const code=error.code;return typeof code=="string"?code:void 0}function createDirectoryLock(lockPath){try{return mkdirSync(lockPath),!0}catch(error){if(errorCode(error)==="EEXIST"||!isFileMissingError(error))return!1}try{return mkdirSync(path.dirname(lockPath),{recursive:!0}),mkdirSync(lockPath),!0}catch{return!1}}function acquireTelemetryFlushSpawnGate(globalPmRoot){if(isFreshDirectoryLock(flushLockPath(globalPmRoot),TELEMETRY_FLUSH_LOCK_STALE_MS))return!1;const lockPath=flushSpawnLockPath(globalPmRoot);try{if(Date.now()-statSync(lockPath).mtimeMs<TELEMETRY_FLUSH_SPAWN_LOCK_STALE_MS)return!1;removeDirectoryLockBestEffort(lockPath)}catch(error){if(!isFileMissingError(error))return!1}return createDirectoryLock(lockPath)}function releaseTelemetryFlushSpawnGate(globalPmRoot){removeDirectoryLockBestEffort(flushSpawnLockPath(globalPmRoot))}const _testOnly={acquireTelemetryFlushSpawnGate,acquireTelemetryFlushLock,buildAuthorContextPayloadFields,buildCommandErrorPayload,buildCommandFinishPayload,buildCommandStartPayload,buildOtelSpanRequest,createDirectoryLock,enqueuePendingOtelSpan,enqueueTelemetryEvent,errorCode,flushPendingOtelSpans,flushQueue,flushQueueWithProcessLock,flushTelemetryArtifacts,hashTelemetryErrorFingerprint,hashTelemetryValue,isEmailDomainCharacter,isEmailLocalCharacter,isExpiredPendingOtelSpan,isExpiredQueueEntry,isFreshDirectoryLock,isDueForRetry,isDueForRetryAt,isRetryableQueueRewriteError,looksLikeEmailToken,otelSpansQueuePath,parseBooleanTrueLike,postTelemetryJson,parsePendingOtelSpanLines,prunePendingOtelSpans,reconcilePendingOtelSpansAfterFlush,retentionCutoffMs,resolveOtelTracesEndpoint,resolveTelemetryHttpTimeoutMs,rewritePendingOtelSpans,normalizeForHash,normalizeCaptureLevel,normalizePmVersion,normalizeTelemetryErrorCategory,normalizeTelemetryErrorCode,normalizeTelemetryExitCode,parseQueueLines,pruneExpiredQueueEntries,readRuntimeState,readCurrentQueueEntries,releaseTelemetryFlushSpawnGate,removeFlushedEntriesFromCurrentQueue,removeDirectoryLockBestEffort,resolveTelemetrySourceContext,rewriteQueue,sanitizeCommandArgs,sanitizeStringMax,sanitizeStringRedacted,sanitizeValue,scheduleTelemetryFlush,shouldFlushInline,sleep,summarizeResult,telemetryFlushRunnerPath,withQueueMutation,flushLockPath,flushSpawnLockPath,runtimeStatePath,writeRuntimeState};async function flushQueueWithProcessLock(globalPmRoot,endpoint,retentionDays){const acquired=await acquireTelemetryFlushLock(globalPmRoot);if(releaseTelemetryFlushSpawnGate(globalPmRoot),!!acquired)try{await flushTelemetryArtifacts(globalPmRoot,endpoint,retentionDays)}finally{try{await rm(flushLockPath(globalPmRoot),{recursive:!0,force:!0})}catch{}}}function scheduleTelemetryFlush(globalPmRoot,endpoint,retentionDays){if(!isConfigurationOnlySettingsRead(globalPmRoot)){if(shouldFlushInline()){const previousFlush=_lastFlushPromise,nextFlush=flushTelemetryArtifacts(globalPmRoot,endpoint,retentionDays);_lastFlushPromise=Promise.allSettled([previousFlush,nextFlush]).then(()=>{});return}try{if(!acquireTelemetryFlushSpawnGate(globalPmRoot))return;const child=spawn(process.execPath,[telemetryFlushRunnerPath()],{detached:!0,stdio:"ignore",cwd:os.tmpdir(),env:{...process.env,PM_GLOBAL_PATH:globalPmRoot,[PM_TELEMETRY_FLUSH_CHILD_ENV]:"1"}});child.on("error",()=>{releaseTelemetryFlushSpawnGate(globalPmRoot)}),child.unref()}catch{releaseTelemetryFlushSpawnGate(globalPmRoot)}}}async function flushTelemetryQueueNow(globalPmRoot=resolveGlobalPmRoot(process.cwd())){if(!resolveTelemetryEnvironmentPolicy().telemetry_disabled)try{await runWithConfigurationOnlySettings(globalPmRoot,async()=>{if(!(await readSettings(globalPmRoot)).telemetry.enabled)return;const installation=await withQueueMutation(()=>ensureInstallationId(globalPmRoot),globalPmRoot);installation&&await flushQueueWithProcessLock(globalPmRoot,installation.endpoint,installation.retentionDays)},()=>parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV]))}catch{}}async function startTelemetryCommand(context){if(resolveTelemetryEnvironmentPolicy().telemetry_disabled||context.command==="telemetry"&&context.args.some(token=>token.trim().toLowerCase()==="clear"))return null;try{const globalPmRoot=resolveGlobalPmRoot(process.cwd());if(!(await readSettings(globalPmRoot)).telemetry.enabled)return null;const coreReadOwned=context.global.noExtensions===!0||isActiveCommandUnextended(context.command),activeCommand=await withQueueMutation(async()=>{const installation=await ensureInstallationId(globalPmRoot);if(!installation)return null;const{installationId,endpoint,retentionDays,captureLevel}=installation,pmVersion=normalizePmVersion(context.pm_version),sourceContext=resolveTelemetrySourceContext(context.global),pmRootHash=hashWithInstallationId(installationId,context.pm_root),cwdHash=hashWithInstallationId(installationId,process.cwd()),otelTracesEndpoint=resolveOtelTracesEndpoint(),occurredAt=nowIso(),event={schema_version:TELEMETRY_SCHEMA_VERSION,event_id:crypto.randomUUID(),event_type:"command_start",occurred_at:occurredAt,installation_id:installationId,session_id:PROCESS_SESSION_ID,command:context.command,payload:buildCommandStartPayload({captureLevel,context,pmVersion,sourceContext,pmRootHash,cwdHash,installationId})},sampleRate=await resolveAutomaticReadSampleRate(globalPmRoot,context.command,coreReadOwned);sampleRate===1&&await appendTelemetryEvent(globalPmRoot,event);const commandTaxonomy=deriveTelemetryCommandTaxonomy(context.command),active={...sampleRate<1?{sample_rate:sampleRate}:{},started_at:occurredAt,started_at_ms:Date.now(),command:context.command,command_taxonomy:commandTaxonomy,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,installation_id:installationId,pm_root_hash:pmRootHash,cwd_hash:cwdHash,endpoint,retention_days:retentionDays,global_pm_root:globalPmRoot,capture_level:captureLevel,otel_traces_endpoint:otelTracesEndpoint??void 0,otel_trace_id:otelTracesEndpoint?crypto.randomBytes(16).toString("hex"):void 0,otel_span_id:otelTracesEndpoint?crypto.randomBytes(8).toString("hex"):void 0};return sampleRate<1&&deferredReadStarts.set(active,event),active},globalPmRoot,TELEMETRY_FOREGROUND_LOCK_WAIT_MS);return activeCommand&&activeCommand.sample_rate===void 0&&scheduleTelemetryFlush(globalPmRoot,activeCommand.endpoint,activeCommand.retention_days),activeCommand}catch{return null}}async function finishTelemetryCommand(activeCommand,outcome){if(!(!activeCommand||resolveTelemetryEnvironmentPolicy().telemetry_disabled))try{if(!await withQueueMutation(async()=>{const settings=await readSettings(activeCommand.global_pm_root);if(resolveTelemetryEnvironmentPolicy().telemetry_disabled||!settings.telemetry.enabled||settings.telemetry.installation_id!==activeCommand.installation_id)return deferredReadStarts.delete(activeCommand),!1;const deferredStart=deferredReadStarts.get(activeCommand),sampleRate=outcome.ok?activeCommand.sample_rate??1:1;if(deferredStart){if(deferredReadStarts.delete(activeCommand),crypto.randomBytes(6).readUIntBE(0,6)/281474976710656>=sampleRate)return!1;deferredStart.payload.sample_rate=sampleRate,await appendTelemetryEvent(activeCommand.global_pm_root,deferredStart)}const finishedAt=nowIso(),durationMs=Math.max(0,Date.now()-activeCommand.started_at_ms),normalizedErrorCode=normalizeTelemetryErrorCode(inferTelemetryErrorCode({ok:outcome.ok,errorCode:outcome.error_code,errorMessage:outcome.error,exitCode:outcome.exit_code})),normalizedErrorCategory=normalizeTelemetryErrorCategory({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:outcome.error_category}),normalizedExitCode=normalizeTelemetryExitCode(outcome.exit_code,outcome.ok),commandResolution=outcome.command_resolution??deriveTelemetryCommandResolution({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:normalizedErrorCategory}),resolutionStage=outcome.resolution_stage??"execute",event={schema_version:TELEMETRY_SCHEMA_VERSION,event_id:crypto.randomUUID(),event_type:"command_finish",occurred_at:finishedAt,installation_id:activeCommand.installation_id,session_id:PROCESS_SESSION_ID,command:activeCommand.command,payload:{...deferredStart?{sample_rate:sampleRate}:{},...buildCommandFinishPayload({captureLevel:activeCommand.capture_level,pmVersion:activeCommand.pm_version,sourceContext:{source_context:activeCommand.source_context,source_context_source:activeCommand.source_context_source},outcome,durationMs,startedAt:activeCommand.started_at,command:activeCommand.command,installationId:activeCommand.installation_id,commandTaxonomy:activeCommand.command_taxonomy,exitCode:normalizedExitCode,errorCode:normalizedErrorCode,errorCategory:normalizedErrorCategory,commandResolution,resolutionStage})}};await appendTelemetryEvent(activeCommand.global_pm_root,event);const otelRequest=buildOtelSpanRequest(activeCommand,{...outcome,exit_code:normalizedExitCode,error_code:normalizedErrorCode,error_category:normalizedErrorCategory},finishedAt,durationMs,sampleRate);return otelRequest&&await appendPendingOtelSpan(activeCommand.global_pm_root,otelRequest),!0},activeCommand.global_pm_root,TELEMETRY_FOREGROUND_LOCK_WAIT_MS))return;scheduleTelemetryFlush(activeCommand.global_pm_root,activeCommand.endpoint,activeCommand.retention_days)}catch{}}async function emitTelemetryErrorEvent(context){if(!resolveTelemetryEnvironmentPolicy().telemetry_disabled)try{const globalPmRoot=resolveGlobalPmRoot(process.cwd());if(!(await readSettings(globalPmRoot)).telemetry.enabled)return;const captured=await withQueueMutation(async()=>{const installation=await ensureInstallationId(globalPmRoot);if(!installation)return null;const{installationId,captureLevel}=installation,pmVersion=normalizePmVersion(context.pm_version),sourceContext=resolveTelemetrySourceContext(context.global),pmRootHash=hashWithInstallationId(installationId,context.pm_root),cwdHash=hashWithInstallationId(installationId,process.cwd()),occurredAt=nowIso(),normalizedErrorCode=normalizeTelemetryErrorCode(inferTelemetryErrorCode({ok:!1,errorCode:context.error_code,errorMessage:context.error_message,exitCode:context.exit_code})),normalizedErrorCategory=context.error_category??resolveTelemetryErrorCategory(normalizedErrorCode),normalizedExitCode=normalizeTelemetryExitCode(context.exit_code,!1),normalizedCommand=context.command.trim().length>0?context.command:"<unknown>",commandTaxonomy=deriveTelemetryCommandTaxonomy(normalizedCommand),commandResolution=context.command_resolution??deriveTelemetryCommandResolution({ok:!1,errorCode:normalizedErrorCode,errorCategory:normalizedErrorCategory}),resolutionStage=context.resolution_stage??"unknown",event={schema_version:TELEMETRY_SCHEMA_VERSION,event_id:crypto.randomUUID(),event_type:"command_error",occurred_at:occurredAt,installation_id:installationId,session_id:PROCESS_SESSION_ID,command:sanitizeString(normalizedCommand,"redacted"),payload:buildCommandErrorPayload({captureLevel,pmVersion,sourceContext,command:normalizedCommand,commandTaxonomy,commandResolution,resolutionStage,args:context.args,options:context.options,pmRootHash,cwdHash,installationId,errorCode:normalizedErrorCode,errorCategory:normalizedErrorCategory,exitCode:normalizedExitCode,errorMessage:context.error_message})};return await appendTelemetryEvent(globalPmRoot,event),installation},globalPmRoot,TELEMETRY_FOREGROUND_LOCK_WAIT_MS);captured&&scheduleTelemetryFlush(globalPmRoot,captured.endpoint,captured.retentionDays)}catch{}}export{PM_TELEMETRY_SOURCE_CONTEXT_VALUES2 as PM_TELEMETRY_SOURCE_CONTEXT_VALUES,TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS,TELEMETRY_SCHEMA_VERSION,_testOnly,emitTelemetryErrorEvent,finishTelemetryCommand,flushTelemetryQueueNow,startTelemetryCommand,waitForPendingFlush,withQueueMutation as withTelemetryQueueMutation};
9
+ `:"";for(let attempt=0;;attempt+=1)try{await writeFileAtomic(otelSpansQueuePath(globalPmRoot),contents,{createParentDirectories:!parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])});return}catch(error){const retryDelay=TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS[attempt];if(retryDelay===void 0||!isRetryableQueueRewriteError(error))throw error;await sleep(retryDelay)}}async function reconcilePendingOtelSpansAfterFlush(globalPmRoot,retentionDays,succeededIds,failedUpdates){return withQueueMutation(async()=>{const raw=await readFileIfExists(otelSpansQueuePath(globalPmRoot)),current=raw===null?[]:parsePendingOtelSpanLines(raw),reconciled=[];for(const entry of current){if(succeededIds.has(entry.id))continue;const failure=failedUpdates.get(entry.id);reconciled.push(failure?{...entry,attempts:failure.attempts,next_attempt_after:failure.next_attempt_after}:entry)}const{entries:retained}=prunePendingOtelSpans(reconciled,retentionDays);return await rewritePendingOtelSpans(globalPmRoot,retained),retained.length},globalPmRoot)}async function flushPendingOtelSpans(globalPmRoot,retentionDays){const raw=await readFileIfExists(otelSpansQueuePath(globalPmRoot));if(raw===null||raw.trim().length===0){await writeRuntimeState(globalPmRoot,{pending_otel_spans:0});return}const entries=parsePendingOtelSpanLines(raw),{entries:retained,prunedCount}=prunePendingOtelSpans(entries,retentionDays),due=retained.filter(entry=>isDueForRetryAt(entry.next_attempt_after)).slice(0,TELEMETRY_OTEL_SPANS_FLUSH_BATCH_SIZE);if(due.length===0){const remaining2=prunedCount>0?await reconcilePendingOtelSpansAfterFlush(globalPmRoot,retentionDays,new Set,new Map):retained.length;await writeRuntimeState(globalPmRoot,{pending_otel_spans:remaining2});return}const attemptTime=nowIso(),succeededIds=new Set,failedUpdates=new Map;let succeededCount=0,lastError;await Promise.all(due.map(async span=>{try{const status=await postTelemetryJson(span.endpoint,{"content-type":"application/json"},JSON.stringify(span.payload));if(status<200||status>=300)throw new Error(`local_otel_export_http_${status}`);succeededIds.add(span.id),succeededCount+=1}catch(error){lastError=error instanceof Error?sanitizeString(error.message,"redacted"):"local_otel_export_failed";const nextAttempts=span.attempts+1;failedUpdates.set(span.id,{attempts:nextAttempts,next_attempt_after:nextRetryIso(nextAttempts)})}}));const remaining=await reconcilePendingOtelSpansAfterFlush(globalPmRoot,retentionDays,succeededIds,failedUpdates),statePatch={pending_otel_spans:remaining,last_otel_attempt_at:attemptTime};succeededCount>0&&(statePatch.last_otel_success_at=attemptTime),lastError!==void 0?(statePatch.last_otel_failure_at=attemptTime,statePatch.last_otel_failure_error=lastError):remaining===0&&(statePatch.last_otel_failure_at=void 0,statePatch.last_otel_failure_error=void 0),await writeRuntimeState(globalPmRoot,statePatch)}async function flushTelemetryArtifacts(globalPmRoot,endpoint,retentionDays){try{await flushQueue(globalPmRoot,endpoint,retentionDays)}catch{}try{await flushPendingOtelSpans(globalPmRoot,retentionDays)}catch{}}async function cleanupTelemetryQueueTempOrphans(globalPmRoot,maxAgeMs=TELEMETRY_QUEUE_TMP_ORPHAN_MAX_AGE_MS){try{const dirPath=telemetryRuntimeDirectory(globalPmRoot),entries=await readdir(dirPath,{withFileTypes:!0}),cutoffMs=Date.now()-Math.max(0,maxAgeMs);await Promise.all(entries.filter(entry=>entry.isFile()&&/^\.events\.jsonl\.\d+\.\d+\.[a-f0-9]+\.tmp$/.test(entry.name)).map(async entry=>{const candidate=path.join(dirPath,entry.name);(await stat(candidate)).mtimeMs<cutoffMs&&await rm(candidate,{force:!0})}))}catch{}}async function withQueueMutation(operation,globalPmRoot=resolveGlobalPmRoot(process.cwd()),waitMs=5e3){const run=_queueMutationPromise.catch(()=>{}).then(()=>runWithIsolatedExtensionRuntime(async()=>{const release=await acquireLock(globalPmRoot,"telemetry-queue",60,"telemetry",!1,!1,waitMs,{createParentDirectories:!parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])});try{return clearSettingsReadCache(globalPmRoot),await operation()}finally{await release()}}));return _queueMutationPromise=run.catch(()=>{}),run}async function readCurrentQueueEntries(globalPmRoot){const raw=await readFileIfExists(queuePath(globalPmRoot));return raw===null||raw.trim().length===0?[]:parseQueueLines(raw)}async function removeFlushedEntriesFromCurrentQueue(globalPmRoot,flushedIds,retentionDays){return withQueueMutation(async()=>{const currentEntries=await readCurrentQueueEntries(globalPmRoot),{entries:retainedEntries}=pruneExpiredQueueEntries(currentEntries,retentionDays),remaining=retainedEntries.filter(entry=>!flushedIds.has(entry.event.event_id));return await rewriteQueue(globalPmRoot,remaining),remaining},globalPmRoot)}async function markFailedEntriesInCurrentQueue(globalPmRoot,failedIds,attemptTime,retentionDays){return withQueueMutation(async()=>{const currentEntries=await readCurrentQueueEntries(globalPmRoot),{entries:retainedEntries}=pruneExpiredQueueEntries(currentEntries,retentionDays),retried=retainedEntries.map(entry=>{if(!failedIds.has(entry.event.event_id))return entry;const attempts=entry.attempts+1;return{...entry,attempts,last_attempt_at:attemptTime,next_attempt_after:nextRetryIso(attempts)}});return await rewriteQueue(globalPmRoot,retried),retried},globalPmRoot)}async function flushQueue(globalPmRoot,endpoint,retentionDays){await cleanupTelemetryQueueTempOrphans(globalPmRoot);const normalizedEndpoint=endpoint.trim();if(normalizedEndpoint.length===0)return;const raw=await readFileIfExists(queuePath(globalPmRoot));if(raw===null||raw.trim().length===0){await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:0});return}const queueEntries=parseQueueLines(raw);if(queueEntries.length===0){await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:0});return}const{entries:retainedEntries,prunedCount}=pruneExpiredQueueEntries(queueEntries,retentionDays);if(retainedEntries.length===0){const remaining=await removeFlushedEntriesFromCurrentQueue(globalPmRoot,new Set,retentionDays);await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:remaining.length});return}const dueEntries=retainedEntries.filter(entry=>isDueForRetry(entry)).slice(0,TELEMETRY_FLUSH_BATCH_SIZE);if(dueEntries.length===0){const remaining=prunedCount>0?await removeFlushedEntriesFromCurrentQueue(globalPmRoot,new Set,retentionDays):retainedEntries;await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:remaining.length});return}const dueIds=new Set(dueEntries.map(entry=>entry.event.event_id)),attemptTime=nowIso(),requestHeaders={"content-type":"application/json"},ingestKey=process.env.PM_TELEMETRY_INGEST_KEY?.trim();ingestKey&&(requestHeaders["x-pm-telemetry-key"]=ingestKey);try{const status=await postTelemetryJson(normalizedEndpoint,requestHeaders,JSON.stringify({schema_version:TELEMETRY_SCHEMA_VERSION,events:dueEntries.map(entry=>entry.event)}));if(status<200||status>=300)throw new Error(`telemetry_flush_http_${status}`)}catch(error){const retried=await markFailedEntriesInCurrentQueue(globalPmRoot,dueIds,attemptTime,retentionDays),errorMessage=error instanceof Error?sanitizeString(error.message,"redacted"):"telemetry_flush_failed";await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:retried.length,last_attempted_flush_at:attemptTime,last_failed_flush_at:attemptTime,last_failed_flush_error:errorMessage});return}try{const remaining=await removeFlushedEntriesFromCurrentQueue(globalPmRoot,dueIds,retentionDays);await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:remaining.length,last_attempted_flush_at:attemptTime,last_successful_flush_at:attemptTime,last_failed_flush_at:void 0,last_failed_flush_error:void 0})}catch(error){const errorMessage=error instanceof Error?sanitizeString(error.message,"redacted"):"telemetry_flush_failed",currentEntries=await readCurrentQueueEntries(globalPmRoot).catch(()=>retainedEntries);await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:currentEntries.length,last_attempted_flush_at:attemptTime,last_failed_flush_at:attemptTime,last_failed_flush_error:errorMessage})}}async function acquireTelemetryFlushLock(globalPmRoot){const lockPath=flushLockPath(globalPmRoot);parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])||await mkdir(path.dirname(lockPath),{recursive:!0});try{return await mkdir(lockPath),!0}catch(error){if(typeof error!="object"||error===null||!("code"in error)||error.code!=="EEXIST")throw error}try{const lockStats=await stat(lockPath);return Date.now()-lockStats.mtimeMs<TELEMETRY_FLUSH_LOCK_STALE_MS?!1:(await rm(lockPath,{recursive:!0,force:!0}),await mkdir(lockPath),!0)}catch{return!1}}function isFreshDirectoryLock(lockPath,staleMs){try{return Date.now()-statSync(lockPath).mtimeMs<staleMs}catch{return!1}}function removeDirectoryLockBestEffort(lockPath){try{rmSync(lockPath,{recursive:!0,force:!0})}catch{}}function errorCode(error){if(typeof error!="object"||error===null||!("code"in error))return;const code=error.code;return typeof code=="string"?code:void 0}function createDirectoryLock(lockPath){try{return mkdirSync(lockPath),!0}catch(error){if(errorCode(error)==="EEXIST"||!isFileMissingError(error))return!1}try{return mkdirSync(path.dirname(lockPath),{recursive:!0}),mkdirSync(lockPath),!0}catch{return!1}}function acquireTelemetryFlushSpawnGate(globalPmRoot){if(isFreshDirectoryLock(flushLockPath(globalPmRoot),TELEMETRY_FLUSH_LOCK_STALE_MS))return!1;const lockPath=flushSpawnLockPath(globalPmRoot);try{if(Date.now()-statSync(lockPath).mtimeMs<TELEMETRY_FLUSH_SPAWN_LOCK_STALE_MS)return!1;removeDirectoryLockBestEffort(lockPath)}catch(error){if(!isFileMissingError(error))return!1}return createDirectoryLock(lockPath)}function releaseTelemetryFlushSpawnGate(globalPmRoot){removeDirectoryLockBestEffort(flushSpawnLockPath(globalPmRoot))}const _testOnly={acquireTelemetryFlushSpawnGate,acquireTelemetryFlushLock,buildAuthorContextPayloadFields,buildCommandErrorPayload,buildCommandFinishPayload,buildCommandStartPayload,buildOtelSpanRequest,createDirectoryLock,enqueuePendingOtelSpan,enqueueTelemetryEvent,errorCode,flushPendingOtelSpans,flushQueue,flushQueueWithProcessLock,flushTelemetryArtifacts,hashTelemetryErrorFingerprint,hashTelemetryValue,isEmailDomainCharacter,isEmailLocalCharacter,isExpiredPendingOtelSpan,isExpiredQueueEntry,isFreshDirectoryLock,isDueForRetry,isDueForRetryAt,isRetryableQueueRewriteError,looksLikeEmailToken,otelSpansQueuePath,parseBooleanTrueLike,postTelemetryJson,parsePendingOtelSpanLines,prunePendingOtelSpans,reconcilePendingOtelSpansAfterFlush,retentionCutoffMs,resolveOtelTracesEndpoint,resolveTelemetryHttpTimeoutMs,rewritePendingOtelSpans,normalizeForHash,normalizeCaptureLevel,normalizePmVersion,normalizeTelemetryErrorCategory,normalizeTelemetryErrorCode,normalizeTelemetryExitCode,parseQueueLines,pruneExpiredQueueEntries,readRuntimeState,readCurrentQueueEntries,releaseTelemetryFlushSpawnGate,removeFlushedEntriesFromCurrentQueue,removeDirectoryLockBestEffort,resolveTelemetrySourceContext,rewriteQueue,sanitizeCommandArgs,sanitizeStringMax,sanitizeStringRedacted,sanitizeValue,scheduleTelemetryFlush,shouldFlushInline,sleep,summarizeResult,telemetryFlushRunnerPath,withQueueMutation,flushLockPath,flushSpawnLockPath,runtimeStatePath,writeRuntimeState};async function flushQueueWithProcessLock(globalPmRoot,endpoint,retentionDays){const acquired=await acquireTelemetryFlushLock(globalPmRoot);if(releaseTelemetryFlushSpawnGate(globalPmRoot),!acquired)return!1;try{await flushTelemetryArtifacts(globalPmRoot,endpoint,retentionDays)}finally{try{await rm(flushLockPath(globalPmRoot),{recursive:!0,force:!0})}catch{}}return!0}async function dueTelemetryArtifactIds(globalPmRoot,retentionDays){const ids=new Set;try{const{entries}=pruneExpiredQueueEntries(await readCurrentQueueEntries(globalPmRoot),retentionDays);for(const entry of entries.filter(isDueForRetry))ids.add(`event:${entry.event.event_id}`)}catch{}try{const raw=await readFileIfExists(otelSpansQueuePath(globalPmRoot));if(raw!==null)for(const entry of prunePendingOtelSpans(parsePendingOtelSpanLines(raw),retentionDays).entries)isDueForRetryAt(entry.next_attempt_after)&&ids.add(`span:${entry.id}`)}catch{}return ids}function scheduleTelemetryFlush(globalPmRoot,endpoint,retentionDays){if(!isConfigurationOnlySettingsRead(globalPmRoot)){if(shouldFlushInline()){const previousFlush=_lastFlushPromise,nextFlush=flushTelemetryArtifacts(globalPmRoot,endpoint,retentionDays);_lastFlushPromise=Promise.allSettled([previousFlush,nextFlush]).then(()=>{});return}try{if(!acquireTelemetryFlushSpawnGate(globalPmRoot))return;const child=spawn(process.execPath,[telemetryFlushRunnerPath()],{detached:!0,stdio:"ignore",cwd:os.tmpdir(),env:{...process.env,PM_GLOBAL_PATH:globalPmRoot,[PM_TELEMETRY_FLUSH_CHILD_ENV]:"1"}});child.on("error",()=>{releaseTelemetryFlushSpawnGate(globalPmRoot)}),child.unref()}catch{releaseTelemetryFlushSpawnGate(globalPmRoot)}}}async function flushTelemetryQueueNow(globalPmRoot=resolveGlobalPmRoot(process.cwd())){if(!resolveTelemetryEnvironmentPolicy().telemetry_disabled)try{await runWithConfigurationOnlySettings(globalPmRoot,async()=>{const detached=parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV]);let continueDraining=!0;for(;continueDraining;){if(!(await readSettings(globalPmRoot)).telemetry.enabled)return;const installation=await withQueueMutation(()=>ensureInstallationId(globalPmRoot),globalPmRoot);if(!installation)return;const before=detached?await dueTelemetryArtifactIds(globalPmRoot,installation.retentionDays):new Set;if(!await flushQueueWithProcessLock(globalPmRoot,installation.endpoint,installation.retentionDays)||!detached)return;const after=await dueTelemetryArtifactIds(globalPmRoot,installation.retentionDays);continueDraining=after.size>0&&(after.size!==before.size||[...after].some(id=>!before.has(id)))}},()=>parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV]))}catch{}}async function startTelemetryCommand(context){if(resolveTelemetryEnvironmentPolicy().telemetry_disabled||context.command==="telemetry"&&context.args.some(token=>token.trim().toLowerCase()==="clear"))return null;try{const globalPmRoot=resolveGlobalPmRoot(process.cwd());if(!(await readSettings(globalPmRoot)).telemetry.enabled)return null;const coreReadOwned=context.global.noExtensions===!0||isActiveCommandUnextended(context.command),activeCommand=await withQueueMutation(async()=>{const installation=await ensureInstallationId(globalPmRoot);if(!installation)return null;const{installationId,endpoint,retentionDays,captureLevel}=installation,pmVersion=normalizePmVersion(context.pm_version),sourceContext=resolveTelemetrySourceContext(context.global),pmRootHash=hashWithInstallationId(installationId,context.pm_root),cwdHash=hashWithInstallationId(installationId,process.cwd()),otelTracesEndpoint=resolveOtelTracesEndpoint(),occurredAt=nowIso(),event={schema_version:TELEMETRY_SCHEMA_VERSION,event_id:crypto.randomUUID(),event_type:"command_start",occurred_at:occurredAt,installation_id:installationId,session_id:PROCESS_SESSION_ID,command:context.command,payload:buildCommandStartPayload({captureLevel,context,pmVersion,sourceContext,pmRootHash,cwdHash,installationId})},sampleRate=await resolveAutomaticReadSampleRate(globalPmRoot,context.command,coreReadOwned);sampleRate===1&&await appendTelemetryEvent(globalPmRoot,event);const commandTaxonomy=deriveTelemetryCommandTaxonomy(context.command),active={...sampleRate<1?{sample_rate:sampleRate}:{},started_at:occurredAt,started_at_ms:Date.now(),command:context.command,command_taxonomy:commandTaxonomy,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,installation_id:installationId,pm_root_hash:pmRootHash,cwd_hash:cwdHash,endpoint,retention_days:retentionDays,global_pm_root:globalPmRoot,capture_level:captureLevel,otel_traces_endpoint:otelTracesEndpoint??void 0,otel_trace_id:otelTracesEndpoint?crypto.randomBytes(16).toString("hex"):void 0,otel_span_id:otelTracesEndpoint?crypto.randomBytes(8).toString("hex"):void 0};return sampleRate<1&&deferredReadStarts.set(active,event),active},globalPmRoot,TELEMETRY_FOREGROUND_LOCK_WAIT_MS);return activeCommand&&activeCommand.sample_rate===void 0&&scheduleTelemetryFlush(globalPmRoot,activeCommand.endpoint,activeCommand.retention_days),activeCommand}catch{return null}}async function finishTelemetryCommand(activeCommand,outcome){if(!(!activeCommand||resolveTelemetryEnvironmentPolicy().telemetry_disabled))try{if(!await withQueueMutation(async()=>{const settings=await readSettings(activeCommand.global_pm_root);if(resolveTelemetryEnvironmentPolicy().telemetry_disabled||!settings.telemetry.enabled||settings.telemetry.installation_id!==activeCommand.installation_id)return deferredReadStarts.delete(activeCommand),!1;const deferredStart=deferredReadStarts.get(activeCommand),sampleRate=outcome.ok?activeCommand.sample_rate??1:1;if(deferredStart){if(deferredReadStarts.delete(activeCommand),crypto.randomBytes(6).readUIntBE(0,6)/281474976710656>=sampleRate)return!1;deferredStart.payload.sample_rate=sampleRate,await appendTelemetryEvent(activeCommand.global_pm_root,deferredStart)}const finishedAt=nowIso(),durationMs=Math.max(0,Date.now()-activeCommand.started_at_ms),normalizedErrorCode=normalizeTelemetryErrorCode(inferTelemetryErrorCode({ok:outcome.ok,errorCode:outcome.error_code,errorMessage:outcome.error,exitCode:outcome.exit_code})),normalizedErrorCategory=normalizeTelemetryErrorCategory({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:outcome.error_category}),normalizedExitCode=normalizeTelemetryExitCode(outcome.exit_code,outcome.ok),commandResolution=outcome.command_resolution??deriveTelemetryCommandResolution({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:normalizedErrorCategory}),resolutionStage=outcome.resolution_stage??"execute",event={schema_version:TELEMETRY_SCHEMA_VERSION,event_id:crypto.randomUUID(),event_type:"command_finish",occurred_at:finishedAt,installation_id:activeCommand.installation_id,session_id:PROCESS_SESSION_ID,command:activeCommand.command,payload:{...deferredStart?{sample_rate:sampleRate}:{},...buildCommandFinishPayload({captureLevel:activeCommand.capture_level,pmVersion:activeCommand.pm_version,sourceContext:{source_context:activeCommand.source_context,source_context_source:activeCommand.source_context_source},outcome,durationMs,startedAt:activeCommand.started_at,command:activeCommand.command,installationId:activeCommand.installation_id,commandTaxonomy:activeCommand.command_taxonomy,exitCode:normalizedExitCode,errorCode:normalizedErrorCode,errorCategory:normalizedErrorCategory,commandResolution,resolutionStage})}};await appendTelemetryEvent(activeCommand.global_pm_root,event);const otelRequest=buildOtelSpanRequest(activeCommand,{...outcome,exit_code:normalizedExitCode,error_code:normalizedErrorCode,error_category:normalizedErrorCategory},finishedAt,durationMs,sampleRate);return otelRequest&&await appendPendingOtelSpan(activeCommand.global_pm_root,otelRequest),!0},activeCommand.global_pm_root,TELEMETRY_FOREGROUND_LOCK_WAIT_MS))return;scheduleTelemetryFlush(activeCommand.global_pm_root,activeCommand.endpoint,activeCommand.retention_days)}catch{}}async function emitTelemetryErrorEvent(context){if(!resolveTelemetryEnvironmentPolicy().telemetry_disabled)try{const globalPmRoot=resolveGlobalPmRoot(process.cwd());if(!(await readSettings(globalPmRoot)).telemetry.enabled)return;const captured=await withQueueMutation(async()=>{const installation=await ensureInstallationId(globalPmRoot);if(!installation)return null;const{installationId,captureLevel}=installation,pmVersion=normalizePmVersion(context.pm_version),sourceContext=resolveTelemetrySourceContext(context.global),pmRootHash=hashWithInstallationId(installationId,context.pm_root),cwdHash=hashWithInstallationId(installationId,process.cwd()),occurredAt=nowIso(),normalizedErrorCode=normalizeTelemetryErrorCode(inferTelemetryErrorCode({ok:!1,errorCode:context.error_code,errorMessage:context.error_message,exitCode:context.exit_code})),normalizedErrorCategory=context.error_category??resolveTelemetryErrorCategory(normalizedErrorCode),normalizedExitCode=normalizeTelemetryExitCode(context.exit_code,!1),normalizedCommand=context.command.trim().length>0?context.command:"<unknown>",commandTaxonomy=deriveTelemetryCommandTaxonomy(normalizedCommand),commandResolution=context.command_resolution??deriveTelemetryCommandResolution({ok:!1,errorCode:normalizedErrorCode,errorCategory:normalizedErrorCategory}),resolutionStage=context.resolution_stage??"unknown",event={schema_version:TELEMETRY_SCHEMA_VERSION,event_id:crypto.randomUUID(),event_type:"command_error",occurred_at:occurredAt,installation_id:installationId,session_id:PROCESS_SESSION_ID,command:sanitizeString(normalizedCommand,"redacted"),payload:buildCommandErrorPayload({captureLevel,pmVersion,sourceContext,command:normalizedCommand,commandTaxonomy,commandResolution,resolutionStage,args:context.args,options:context.options,pmRootHash,cwdHash,installationId,errorCode:normalizedErrorCode,errorCategory:normalizedErrorCategory,exitCode:normalizedExitCode,errorMessage:context.error_message})};return await appendTelemetryEvent(globalPmRoot,event),installation},globalPmRoot,TELEMETRY_FOREGROUND_LOCK_WAIT_MS);captured&&scheduleTelemetryFlush(globalPmRoot,captured.endpoint,captured.retentionDays)}catch{}}export{PM_TELEMETRY_SOURCE_CONTEXT_VALUES2 as PM_TELEMETRY_SOURCE_CONTEXT_VALUES,TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS,TELEMETRY_SCHEMA_VERSION,_testOnly,emitTelemetryErrorEvent,finishTelemetryCommand,flushTelemetryQueueNow,startTelemetryCommand,waitForPendingFlush,withQueueMutation as withTelemetryQueueMutation};
10
10
  //# sourceMappingURL=runtime.js.map