@unbrained/pm-cli 2026.9.13 → 2026.9.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 (90) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +22 -0
  3. package/dist/cli/commander-usage.js +2 -2
  4. package/dist/cli/error-guidance.js +1 -1
  5. package/dist/cli/extension-command-help.d.ts +2 -2
  6. package/dist/cli/extension-command-help.js +2 -2
  7. package/dist/cli-bundle/bundle-manifest.json +152 -152
  8. package/dist/cli-bundle/chunks/chunk-33PER336.js +236 -0
  9. package/dist/cli-bundle/chunks/{chunk-KM4XVZR7.js → chunk-5JIJAWIF.js} +2 -2
  10. package/dist/cli-bundle/chunks/chunk-A2Q64TGR.js +2 -0
  11. package/dist/cli-bundle/chunks/{chunk-XM7RWQLM.js → chunk-B6W5LIXK.js} +2 -2
  12. package/dist/cli-bundle/chunks/{chunk-YDSV4QIQ.js → chunk-BY3ID7QI.js} +2 -2
  13. package/dist/cli-bundle/chunks/{chunk-YQTJACN5.js → chunk-D5AJQU7F.js} +2 -2
  14. package/dist/cli-bundle/chunks/{chunk-ZZI7IHMM.js → chunk-DBHQIS6Z.js} +2 -2
  15. package/dist/cli-bundle/chunks/{chunk-LA44JECQ.js → chunk-GQMILIC5.js} +2 -2
  16. package/dist/cli-bundle/chunks/{chunk-3DWX3CKN.js → chunk-NYE6EREL.js} +2 -2
  17. package/dist/cli-bundle/chunks/{chunk-XEZOGC3P.js → chunk-O7SRS7Y3.js} +2 -2
  18. package/dist/cli-bundle/chunks/{chunk-GBK5MV6N.js → chunk-XEV7BHH3.js} +26 -26
  19. package/dist/cli-bundle/chunks/{chunk-GQQR6JAL.js → chunk-ZYRN2OG3.js} +2 -2
  20. package/dist/cli-bundle/chunks/{register-list-query-WMJTBWNW.js → register-list-query-B2U36YWL.js} +2 -2
  21. package/dist/cli-bundle/chunks/{register-mutation-EXGOXP3D.js → register-mutation-GX42CQYR.js} +2 -2
  22. package/dist/cli-bundle/chunks/{register-operations-2H4CDRGU.js → register-operations-ZV34KX5E.js} +2 -2
  23. package/dist/cli-bundle/chunks/{register-setup-NYBWGPOS.js → register-setup-W4OS7IZW.js} +2 -2
  24. package/dist/cli-bundle/focused-chunks/{chunk-FBCLVOBE.js → chunk-6WZBO4VQ.js} +2 -2
  25. package/dist/cli-bundle/focused-chunks/{chunk-OENAWWP4.js → chunk-7BUJABHB.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/{chunk-F66QJWI4.js → chunk-C5NQVXKE.js} +2 -2
  27. package/dist/cli-bundle/focused-chunks/chunk-CMCSUANO.js +20 -0
  28. package/dist/cli-bundle/focused-chunks/{chunk-FPNI4U2B.js → chunk-CPQQIVDL.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-V7PSTKHD.js → chunk-D4FQV6TY.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/{chunk-TUHRUFID.js → chunk-ENJH7CBZ.js} +2 -2
  31. package/dist/cli-bundle/focused-chunks/{chunk-DSJYL4VP.js → chunk-FHQLQOUZ.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/{chunk-B6JAANOH.js → chunk-FNLAQJES.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/chunk-GGDO6VBT.js +30 -0
  34. package/dist/cli-bundle/focused-chunks/{chunk-SDQCJF4H.js → chunk-KWP3QTN7.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/{chunk-XCCM7P7V.js → chunk-LFGTCEHX.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/{chunk-KP3N6PVZ.js → chunk-N23WTRCC.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/{chunk-ZAMG7HBB.js → chunk-O4EROPO3.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/chunk-UFSMYVZF.js +2 -0
  39. package/dist/cli-bundle/focused-chunks/{chunk-LQ67C7ZO.js → chunk-ZFNRD7EN.js} +2 -2
  40. package/dist/cli-bundle/main.js +19 -19
  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 +24 -24
  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 +15 -15
  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 +8 -8
  51. package/dist/core/output/output.js +3 -3
  52. package/dist/core/telemetry/runtime.d.ts +35 -8
  53. package/dist/core/telemetry/runtime.js +5 -4
  54. package/dist/sdk/agent/command-suggestions.d.ts +6 -0
  55. package/dist/sdk/agent/command-suggestions.js +1 -1
  56. package/dist/sdk/cli-contracts/command-aliases.js +1 -1
  57. package/dist/sdk/cli-contracts/grammar-contracts.d.ts +2 -2
  58. package/dist/sdk/cli-contracts/grammar-contracts.js +1 -1
  59. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +7 -3
  60. package/dist/sdk/cli-contracts/runtime-contracts.js +1 -1
  61. package/dist/sdk/public-surface.json +1 -1
  62. package/dist/sdk/telemetry.js +1 -1
  63. package/docs/AGENT_UX_CONTRACTS.md +10 -2
  64. package/docs/CLI_GRAMMAR.md +28 -0
  65. package/docs/CONFIGURATION.md +35 -1
  66. package/docs/generated/AGENT_CAPABILITY_ROUTING.md +1 -1
  67. package/docs/generated/AGENT_COMMAND_SURFACE.md +1 -0
  68. package/docs/generated/FLAG_LEXICON_BUDGETS.md +1 -0
  69. package/marketplace.json +2 -2
  70. package/package.json +5 -5
  71. package/packages/pm-beads/package.json +1 -1
  72. package/packages/pm-calendar/package.json +1 -1
  73. package/packages/pm-command-kit/package.json +1 -1
  74. package/packages/pm-digital-twin/package.json +1 -1
  75. package/packages/pm-governance-audit/package.json +1 -1
  76. package/packages/pm-guide-shell/package.json +1 -1
  77. package/packages/pm-kanban/package.json +1 -1
  78. package/packages/pm-lifecycle-hooks/package.json +1 -1
  79. package/packages/pm-linked-test-adapters/package.json +1 -1
  80. package/packages/pm-search-advanced/package.json +1 -1
  81. package/packages/pm-templates/package.json +1 -1
  82. package/packages/pm-todos/package.json +1 -1
  83. package/packages/pm-vcs/package.json +1 -1
  84. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  85. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  86. package/dist/cli-bundle/chunks/chunk-6KHYW3FH.js +0 -235
  87. package/dist/cli-bundle/chunks/chunk-AKTBOX6U.js +0 -2
  88. package/dist/cli-bundle/focused-chunks/chunk-7JR6M2JR.js +0 -30
  89. package/dist/cli-bundle/focused-chunks/chunk-YUXBHIUV.js +0 -20
  90. package/dist/cli-bundle/focused-chunks/chunk-ZF5PXK6A.js +0 -2
@@ -1,9 +1,9 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1a9ff3c9-9c7e-50ec-bb12-8a7f91de757f")}catch(e2){}})();import{getActiveCommandContext,runActiveCommandOverride,runActiveRendererOverride,runActiveServiceOverrideSync,setActiveCommandResult}from"../extensions/index.js";import{EXIT_CODE}from"../shared/constants.js";import{isHostOutputSuppressed}from"./output-control.js";import{projectMutationResult}from"./mutation-projection.js";import{attachReadOutputContracts}from"../../sdk/context-intent-contracts.js";import{attachOutputTokenAccounting}from"../../sdk/output-token-accounting.js";import{propagateContextUsageServingReceipt}from"../../sdk/context-usage.js";import{isReadOutputBudgetExceeded,resolveReadOutputEncoding}from"../../sdk/read-output-contracts.js";import{encode as encodeToon}from"@toon-format/toon";const DECLARED_PROCESS_EXIT_CODES=new Set(Object.values(EXIT_CODE));const NATIVE_OUTPUT_MARKER="__pm_native_output";let streamErrorHandlersInstalled=false;function isPlainObject(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function setActiveCommandResultOmitted(source){const omitted={read_output:{result_omitted:true}};propagateContextUsageServingReceipt(source,omitted);setActiveCommandResult(omitted)}function setActiveCommandDeliveryResult(result,receiptSource,structuredDeliveryPreserved){if(structuredDeliveryPreserved){setActiveCommandResult(result);return}setActiveCommandResultOmitted(receiptSource)}function shouldUseNativeOutput(result){return isPlainObject(result)&&result[NATIVE_OUTPUT_MARKER]===true}function stripNativeOutputMarker(result){if(!isPlainObject(result)||result[NATIVE_OUTPUT_MARKER]!==true){return result}const{[NATIVE_OUTPUT_MARKER]:_marker,...rest}=result;return rest}function isBrokenPipeError(error){return typeof error==="object"&&error!==null&&error.code==="EPIPE"}function markStdoutBrokenPipeExitCode(){if(process.exitCode===void 0||process.exitCode===EXIT_CODE.SUCCESS){process.exitCode=EXIT_CODE.SUCCESS}}function markStderrBrokenPipeExitCode(){if(process.exitCode===void 0||process.exitCode===EXIT_CODE.SUCCESS){process.exitCode=EXIT_CODE.GENERIC_FAILURE}}function markBrokenPipeExitCode(target){if(target==="stdout"){markStdoutBrokenPipeExitCode();return}markStderrBrokenPipeExitCode()}function handleUnhandledStreamError(error){const unhandled=error instanceof Error?error:new Error(String(error));setImmediate(()=>{throw unhandled})}function installStreamErrorHandlers(){if(streamErrorHandlersInstalled){return}streamErrorHandlersInstalled=true;process.stdout.on("error",error=>{if(isBrokenPipeError(error)){markBrokenPipeExitCode("stdout");return}handleUnhandledStreamError(error)});process.stderr.on("error",error=>{if(isBrokenPipeError(error)){markBrokenPipeExitCode("stderr");return}handleUnhandledStreamError(error)})}function writeToStream(target,text){installStreamErrorHandlers();try{if(target==="stdout"){process.stdout.write(text)}else{process.stderr.write(text)}return true}catch(error){if(isBrokenPipeError(error)){markBrokenPipeExitCode(target);return false}throw error}}function writeStdout(text){return writeToStream("stdout",text)}function writeStderr(text){return writeToStream("stderr",text)}function renderScalar(value){if(typeof value==="string")return JSON.stringify(value);if(typeof value==="number"||typeof value==="boolean")return String(value);if(value===null)return"null";return JSON.stringify(value)}function isToonPrimitive(value){return value===null||typeof value==="string"||typeof value==="number"||typeof value==="boolean"}function tabularObjectArray(value){if(value.length===0||!value.every(isPlainObject))return false;const keys=Object.keys(value[0]);return keys.length>0&&value.every(entry=>Object.keys(entry).length===keys.length&&keys.every(key=>Object.hasOwn(entry,key)&&isToonPrimitive(entry[key])))}function indentToon(encoded,depth){const indent=" ".repeat(depth);return encoded.split("\n").map(line=>`${indent}${line}`).join("\n")}function renderToonObjectEntry(key,entry,depth){const indent=" ".repeat(depth);if(!isPlainObject(entry)&&!Array.isArray(entry)){return`${indent}${key}: ${renderScalar(entry)}`}if(Array.isArray(entry)&&entry.length===0){return`${indent}${key}: []`}if(Array.isArray(entry)&&tabularObjectArray(entry)){return indentToon(encodeToon({[key]:entry}),depth)}if(isPlainObject(entry)&&Object.keys(entry).length===0){return`${indent}${key}: {}`}return`${indent}${key}:
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="2ca9480d-0ae4-50e8-887e-c4183501d92c")}catch(e2){}})();import{getActiveCommandContext,runActiveCommandOverride,runActiveRendererOverride,runActiveServiceOverrideSync,setActiveCommandResult}from"../extensions/index.js";import{EXIT_CODE}from"../shared/constants.js";import{isHostOutputSuppressed}from"./output-control.js";import{projectMutationResult}from"./mutation-projection.js";import{attachReadOutputContracts}from"../../sdk/context-intent-contracts.js";import{attachOutputTokenAccounting}from"../../sdk/output-token-accounting.js";import{propagateContextUsageServingReceipt}from"../../sdk/context-usage.js";import{isReadOutputBudgetExceeded,resolveReadOutputEncoding}from"../../sdk/read-output-contracts.js";import{encode as encodeToon}from"@toon-format/toon";const DECLARED_PROCESS_EXIT_CODES=new Set(Object.values(EXIT_CODE));const NATIVE_OUTPUT_MARKER="__pm_native_output";let streamErrorHandlersInstalled=false;function isPlainObject(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function setActiveCommandResultOmitted(source){const omitted={read_output:{result_omitted:true}};propagateContextUsageServingReceipt(source,omitted);setActiveCommandResult(omitted)}function setActiveCommandDeliveryResult(result,receiptSource,structuredDeliveryPreserved){if(structuredDeliveryPreserved){setActiveCommandResult(result);return}setActiveCommandResultOmitted(receiptSource)}function shouldUseNativeOutput(result){return isPlainObject(result)&&result[NATIVE_OUTPUT_MARKER]===true}function stripNativeOutputMarker(result){if(!isPlainObject(result)||result[NATIVE_OUTPUT_MARKER]!==true){return result}const{[NATIVE_OUTPUT_MARKER]:_marker,...rest}=result;return rest}function isBrokenPipeError(error){return typeof error==="object"&&error!==null&&error.code==="EPIPE"}function markStdoutBrokenPipeExitCode(){if(process.exitCode===void 0||process.exitCode===EXIT_CODE.SUCCESS){process.exitCode=EXIT_CODE.SUCCESS}}function markStderrBrokenPipeExitCode(){if(process.exitCode===void 0||process.exitCode===EXIT_CODE.SUCCESS){process.exitCode=EXIT_CODE.GENERIC_FAILURE}}function markBrokenPipeExitCode(target){if(target==="stdout"){markStdoutBrokenPipeExitCode();return}markStderrBrokenPipeExitCode()}function handleUnhandledStreamError(error){const unhandled=error instanceof Error?error:new Error(String(error));setImmediate(()=>{throw unhandled})}function installStreamErrorHandlers(){if(streamErrorHandlersInstalled){return}streamErrorHandlersInstalled=true;process.stdout.on("error",error=>{if(isBrokenPipeError(error)){markBrokenPipeExitCode("stdout");return}handleUnhandledStreamError(error)});process.stderr.on("error",error=>{if(isBrokenPipeError(error)){markBrokenPipeExitCode("stderr");return}handleUnhandledStreamError(error)})}function writeToStream(target,text){installStreamErrorHandlers();try{if(target==="stdout"){process.stdout.write(text)}else{process.stderr.write(text)}return true}catch(error){if(isBrokenPipeError(error)){markBrokenPipeExitCode(target);return false}throw error}}function writeStdout(text){return writeToStream("stdout",text)}function writeStderr(text){return writeToStream("stderr",text)}function renderScalar(value){if(typeof value==="string")return JSON.stringify(value);if(typeof value==="number"||typeof value==="boolean")return String(value);if(value===null)return"null";return JSON.stringify(value)}function isToonPrimitive(value){return value===null||typeof value==="string"||typeof value==="number"||typeof value==="boolean"}function tabularObjectArray(value){if(value.length===0||!value.every(isPlainObject))return false;const keys=Object.keys(value[0]);return keys.length>0&&value.every(entry=>Object.keys(entry).length===keys.length&&keys.every(key=>Object.hasOwn(entry,key)&&isToonPrimitive(entry[key])))}function indentToon(encoded,depth){const indent=" ".repeat(depth);return encoded.split("\n").map(line=>`${indent}${line}`).join("\n")}function renderToonObjectEntry(key,entry,depth){const indent=" ".repeat(depth);if(!isPlainObject(entry)&&!Array.isArray(entry)){return`${indent}${key}: ${renderScalar(entry)}`}if(Array.isArray(entry)&&entry.length===0){return`${indent}${key}: []`}if(Array.isArray(entry)&&tabularObjectArray(entry)){return indentToon(encodeToon({[key]:entry}),depth)}if(isPlainObject(entry)&&Object.keys(entry).length===0){return`${indent}${key}: {}`}return`${indent}${key}:
2
2
  ${renderToonValue(entry,depth+1)}`}function compactToonValue(value){if(value===null||value===void 0){return void 0}if(Array.isArray(value)){const compactedEntries=value.map(entry=>compactToonValue(entry)).filter(entry=>entry!==void 0);return compactedEntries.length>0?compactedEntries:void 0}if(isPlainObject(value)){const compacted={};for(const[key,entry]of Object.entries(value)){if(key==="omitted_field_groups"&&Array.isArray(entry)&&entry.length===0){compacted[key]=[];continue}const compactedEntry=compactToonValue(entry);if(compactedEntry!==void 0){compacted[key]=compactedEntry}}return Object.keys(compacted).length>0?compacted:void 0}return value}function renderToonValue(value,depth){const indent=" ".repeat(depth);if(Array.isArray(value)){if(value.length===0)return"[]";if(tabularObjectArray(value)){return indentToon(encodeToon(value),depth)}return value.map(entry=>{if(!isPlainObject(entry)&&!Array.isArray(entry)){return`${indent}- ${renderScalar(entry)}`}const rendered=renderToonValue(entry,depth+1);const lines=rendered.split("\n");const[firstLine,...rest]=lines;if(rest.length===0){return`${indent}- ${firstLine.trimStart()}`}return`${indent}- ${firstLine.trimStart()}
3
3
  ${rest.join("\n")}`}).join("\n")}if(isPlainObject(value)){const entries=Object.entries(value);if(entries.length===0)return"{}";return entries.map(([key,entry])=>renderToonObjectEntry(key,entry,depth)).join("\n")}return`${indent}${renderScalar(value)}`}function renderDefaultMarkdownResult(value){if(!isPlainObject(value)||value.output_default!=="markdown"){return null}if(typeof value.view!=="string"||!Array.isArray(value.events)||!Array.isArray(value.days)){return null}const lines=[`# pm calendar (${value.view})`,""];const summary=isPlainObject(value.summary)?value.summary:{};lines.push(`- events: ${String(summary.events??0)}`);lines.push("");if(value.events.length===0){lines.push("No calendar events matched the selected filters.");return`${lines.join("\n")}
4
4
  `}for(const event of value.events){if(!isPlainObject(event)){continue}const kind=typeof event.kind==="string"?event.kind:"event";const title=typeof event.item_title==="string"?event.item_title:"";const itemId=typeof event.item_id==="string"?event.item_id:"";const reminderText=typeof event.reminder_text==="string"&&event.reminder_text.length>0?` ${event.reminder_text}`:"";lines.push(`- [${kind}] ${itemId} ${title}${reminderText}`.trim())}return`${lines.join("\n")}
5
- `}function resolveOutputFormat(options){return options.json===true||options.json===void 0&&options.defaultOutputFormat==="json"?"json":"toon"}const LEAN_READ_ENVELOPE_ECHO_KEYS=new Set(["filters","now","projection","sorting"]);function projectLeanJsonValue(value){const compacted=compactToonValue(value);if(!isPlainObject(compacted)||!Array.isArray(compacted.items)){return compacted??null}const projected=Object.fromEntries(Object.entries(compacted).filter(([key])=>!LEAN_READ_ENVELOPE_ECHO_KEYS.has(key)));if(projected.has_more!==true){delete projected.next_cursor}return projected}function projectLinkedTestEvidence(value,lean){if(!isPlainObject(value)||!Array.isArray(value.run_results)){return value}if(!value.run_results.every(isPlainObject)){return value}const rows=value.run_results;const contexts=rows.map(row=>row.execution_context).filter(context=>context!==void 0);const sharedContext=contexts.length===rows.length&&contexts.length>0&&contexts.every(context=>JSON.stringify(context)===JSON.stringify(contexts[0]))?contexts[0]:void 0;const runResults=rows.map(row=>{const{execution_context:_executionContext,stdout,stderr,...rest}=row;if(sharedContext===void 0){return row}if(!lean||row.status!=="passed"){return{...rest,stdout,stderr}}return rest});return{...value,...sharedContext===void 0?{}:{execution_context:sharedContext},run_results:runResults}}function formatBuiltInOutput(result,format){if(format==="json"){return`${JSON.stringify(result,null,2)}
6
- `}const compactedToon=compactToonValue(result);return compactedToon===void 0?"{}\n":`${renderToonValue(compactedToon,0)}
5
+ `}function resolveOutputFormat(options){return options.json===true||options.json===void 0&&options.defaultOutputFormat==="json"?"json":"toon"}const LEAN_READ_ENVELOPE_ECHO_KEYS=new Set(["filters","now","projection","sorting"]);function projectLeanJsonValue(value){const compacted=compactToonValue(value);if(!isPlainObject(compacted)||!Array.isArray(compacted.items)){return compacted??null}const projected=Object.fromEntries(Object.entries(compacted).filter(([key])=>!LEAN_READ_ENVELOPE_ECHO_KEYS.has(key)));if(projected.has_more!==true){delete projected.next_cursor}return projected}function projectLinkedTestEvidence(value,lean){if(!isPlainObject(value)||!Array.isArray(value.run_results)){return value}if(!value.run_results.every(isPlainObject)){return value}const rows=value.run_results;const contexts=rows.map(row=>row.execution_context).filter(context=>context!==void 0);const sharedContext=contexts.length===rows.length&&contexts.length>0&&contexts.every(context=>JSON.stringify(context)===JSON.stringify(contexts[0]))?contexts[0]:void 0;const runResults=rows.map(row=>{const{execution_context:_executionContext,stdout,stderr,...rest}=row;if(sharedContext===void 0){return row}if(!lean||row.status!=="passed"){return{...rest,stdout,stderr}}return rest});return{...value,...sharedContext===void 0?{}:{execution_context:sharedContext},run_results:runResults}}function projectCompleteBriefList(value){if(!isPlainObject(value)||!Array.isArray(value.items)||Object.hasOwn(value,"details")||!isPlainObject(value.projection)||value.projection.mode!=="brief"||!isPlainObject(value.completeness)||value.completeness.status!=="complete"||[value.completeness.unreadable_item_count,value.completeness.unreadable_directory_count].some(count=>count!==0)||[value.has_more,value.truncated].some(flag=>flag!==false)||value.count!==value.items.length||value.total!==value.count||!isPlainObject(value.omission_receipt)||JSON.stringify(value.omission_receipt.omitted_field_groups)!==JSON.stringify([{name:"full_item_fields",restore_with:"--full"}])){return value}const{total:_total,has_more:_hasMore,truncated:_truncated,next_cursor:_nextCursor,completeness:_completeness,projection:_projection,now:_now,omission_receipt:_omissions,sorting,...rest}=value;return{...rest,...isPlainObject(sorting)&&sorting.sort==="default"?{}:{sorting},details:"--full"}}function formatBuiltInOutput(result,format){if(format==="json"){return`${JSON.stringify(result,null,2)}
6
+ `}const compactedToon=compactToonValue(projectCompleteBriefList(result));return compactedToon===void 0?"{}\n":`${renderToonValue(compactedToon,0)}
7
7
  `}function resolveOutputService(effectiveResult,nativeOutput,options,format){const serviceOverride=nativeOutput?{handled:false,result:effectiveResult,warnings:[]}:runActiveServiceOverrideSync("output_format",{command:options.command,args:options.commandArgs,command_options:options.commandOptions,global:{...options},pm_root:options.pmRoot,format,options:{...options},result:effectiveResult});const legacyPayloadEchoWarning=serviceOverride.warnings.find(warning=>warning.startsWith("extension_output_format_payload_echo_deprecated:"));if(legacyPayloadEchoWarning!==void 0){writeStderr(`Warning: ${legacyPayloadEchoWarning}. Returning context.payload now declines safely for compatibility; migrate the override to declineServiceOverride() or { handled: false }.
8
8
  `)}if(serviceOverride.handled&&typeof serviceOverride.result==="string"){return{result:serviceOverride.result,rendered:serviceOverride.result.endsWith("\n")?serviceOverride.result:`${serviceOverride.result}
9
9
  `,structuredDeliveryPreserved:false}}return{result:serviceOverride.handled?serviceOverride.result:effectiveResult,rendered:null,structuredDeliveryPreserved:!serviceOverride.handled||isPlainObject(serviceOverride.result)}}function formatEffectiveOutput(effectiveResult,nativeOutput,options){const activeCommandContext=getActiveCommandContext();const command=options.command??activeCommandContext?.command;const commandOptions={...activeCommandContext?.options,...options.commandOptions,...Object.fromEntries([["outputInclude",options.outputInclude],["outputLimit",options.outputLimit],["outputBudget",options.outputBudget],["outputFormat",options.outputFormat],["outputSession",options.outputSession],["outputCursor",options.outputCursor],["outputRowContract",options.outputRowContract]].filter(entry=>entry[1]!==void 0))};const format=resolveReadOutputEncoding(command??"",commandOptions)??resolveOutputFormat(options);const resolvedCommandOptions={...commandOptions,resolvedOutputFormat:format};const effectiveOptions={...options,command,commandOptions:resolvedCommandOptions};const service=resolveOutputService(effectiveResult,nativeOutput,effectiveOptions,format);if(service.rendered!==null){setActiveCommandResultOmitted(effectiveResult);return service.rendered}const outputResult=service.result;propagateContextUsageServingReceipt(effectiveResult,outputResult);const projectedOutputResult=command==="test"?projectLinkedTestEvidence(outputResult,options.lean===true):outputResult;const intentOutputResult=attachReadOutputContracts(command,resolvedCommandOptions,projectedOutputResult);if(isReadOutputBudgetExceeded(intentOutputResult)){process.exitCode||=EXIT_CODE.USAGE}let{structuredDeliveryPreserved}=service;const renderResolvedOutput=value=>{if(format==="toon"){const markdownDefault=renderDefaultMarkdownResult(value);if(markdownDefault!==null)return markdownDefault}const rendererOverride=nativeOutput?{rendered:null}:runActiveRendererOverride(format,value);if(rendererOverride.rendered!==null){structuredDeliveryPreserved=false;return rendererOverride.rendered.endsWith("\n")?rendererOverride.rendered:`${rendererOverride.rendered}
@@ -51,7 +51,7 @@ interface PendingOtelSpan {
51
51
  }
52
52
  type TelemetryCaptureLevel = "minimal" | "redacted" | "max";
53
53
  type TelemetrySourceContext = (typeof PM_TELEMETRY_SOURCE_CONTEXT_VALUES)[number];
54
- type TelemetrySourceContextSource = "inferred" | "env_override";
54
+ type TelemetrySourceContextSource = "inferred" | "env_override" | "env_override_rejected";
55
55
  interface ResolvedTelemetrySourceContext {
56
56
  source_context: TelemetrySourceContext;
57
57
  source_context_source: TelemetrySourceContextSource;
@@ -72,7 +72,7 @@ export interface ActiveTelemetryCommand {
72
72
  pm_version: string;
73
73
  /** Value that configures or reports source context for this contract. */
74
74
  source_context: TelemetrySourceContext;
75
- /** Value that configures or reports source context source for this contract. */
75
+ /** Whether attribution was inferred, explicitly accepted, or inferred after rejecting an override without retaining its value. */
76
76
  source_context_source: TelemetrySourceContextSource;
77
77
  /** Value that configures or reports installation id for this contract. */
78
78
  installation_id: string;
@@ -177,14 +177,19 @@ declare function parseBooleanTrueLike(value: string | undefined): boolean;
177
177
  declare function resolveTelemetryHttpTimeoutMs(): number;
178
178
  /** POST a JSON payload with one total timeout that covers DNS, connection, TLS, and response completion. */
179
179
  declare function postTelemetryJson(endpoint: string, headers: Record<string, string>, body: string): Promise<number>;
180
+ /** Use a trimmed package version when provided, falling back to 0.0.0 for an unknown producer version. */
180
181
  declare function normalizePmVersion(value: string | undefined): string;
182
+ /** Trim a supplied diagnostic code and omit missing or whitespace-only codes from event payloads. */
181
183
  declare function normalizeTelemetryErrorCode(value: string | undefined): string | undefined;
184
+ /** Preserve finite non-negative integer exit codes; otherwise derive zero for success and one for failure. */
182
185
  declare function normalizeTelemetryExitCode(exitCode: number | undefined, ok: boolean): number;
186
+ /** Omit categories for successful outcomes; preserve explicit failure categories or derive them from a stable error code. */
183
187
  declare function normalizeTelemetryErrorCategory(params: {
184
188
  ok: boolean;
185
189
  errorCode?: string;
186
190
  errorCategory?: TelemetryErrorCategory;
187
191
  }): TelemetryErrorCategory | undefined;
192
+ /** Resolve explicit attribution and explain rejected input without retaining its value. */
188
193
  declare function resolveTelemetrySourceContext(globalOptions: GlobalOptions): ResolvedTelemetrySourceContext;
189
194
  /**
190
195
  * Builds privacy-bounded author and agent dimensions for a telemetry payload.
@@ -225,6 +230,7 @@ declare function buildOtelSpanRequest(activeCommand: ActiveTelemetryCommand, out
225
230
  } | null;
226
231
  /** Build a bounded, capture-level-sanitized result preview. Omit undefined object values as JSON does so optional fields cannot prevent completion telemetry. */
227
232
  declare function summarizeResult(result: unknown, captureLevel?: Exclude<TelemetryCaptureLevel, "minimal">): Record<string, unknown>;
233
+ /** Build invocation metadata for the selected capture level; minimal capture retains digests while richer levels include sanitized inputs and hashed runtime context. */
228
234
  declare function buildCommandStartPayload(params: {
229
235
  captureLevel: TelemetryCaptureLevel;
230
236
  context: TelemetryCommandContext;
@@ -234,6 +240,7 @@ declare function buildCommandStartPayload(params: {
234
240
  cwdHash: string;
235
241
  installationId: string;
236
242
  }): Record<string, unknown>;
243
+ /** Build completion diagnostics with sanitized errors and failure fingerprints; minimal capture omits start timestamps and result previews. */
237
244
  declare function buildCommandFinishPayload(params: {
238
245
  captureLevel: TelemetryCaptureLevel;
239
246
  pmVersion: string;
@@ -250,6 +257,7 @@ declare function buildCommandFinishPayload(params: {
250
257
  commandResolution: TelemetryCommandResolution;
251
258
  resolutionStage: TelemetryResolutionStage;
252
259
  }): Record<string, unknown>;
260
+ /** Build error diagnostics at the selected capture level, hashing attempted inputs and redacting error text even in minimal mode. */
253
261
  declare function buildCommandErrorPayload(params: {
254
262
  captureLevel: TelemetryCaptureLevel;
255
263
  pmVersion: string;
@@ -268,43 +276,62 @@ declare function buildCommandErrorPayload(params: {
268
276
  errorCategory: TelemetryErrorCategory;
269
277
  exitCode: number;
270
278
  }): Record<string, unknown>;
279
+ /** Append an event as an independent queue transaction; compound capture transactions use the private writer while already holding the mutex. */
271
280
  declare function enqueueTelemetryEvent(globalPmRoot: string, event: TelemetryEvent): Promise<void>;
281
+ /** Recover well-shaped event envelopes from JSONL while discarding malformed lines so one corrupt record cannot strand delivery. */
272
282
  declare function parseQueueLines(raw: string): QueuedTelemetryEvent[];
283
+ /** Allow immediate retry when scheduling metadata is absent or malformed; otherwise compare its timestamp with the current time. */
273
284
  declare function isDueForRetryAt(nextAttemptAfter: string | undefined): boolean;
285
+ /** Apply the shared due-time policy to an event envelope without altering its retry metadata. */
274
286
  declare function isDueForRetry(entry: QueuedTelemetryEvent): boolean;
287
+ /** Convert a finite retention duration to a cutoff using at least one whole day; invalid durations fall back to one day. */
275
288
  declare function retentionCutoffMs(retentionDays: number): number;
289
+ /** Expire only events with a valid occurrence timestamp before the cutoff; unknown dates do not establish expiration. */
276
290
  declare function isExpiredQueueEntry(entry: QueuedTelemetryEvent, cutoffMs: number): boolean;
291
+ /** Preserve event order while removing oversized, expired, and attempt-exhausted envelopes; return the retained snapshot and removal count. */
277
292
  declare function pruneExpiredQueueEntries(entries: QueuedTelemetryEvent[], retentionDays: number): {
278
293
  entries: QueuedTelemetryEvent[];
279
294
  prunedCount: number;
280
295
  };
296
+ /** Atomically replace the event snapshot with bounded retries for transient filesystem failures; mutation callers must hold the queue mutex. */
281
297
  declare function rewriteQueue(globalPmRoot: string, entries: QueuedTelemetryEvent[]): Promise<void>;
298
+ /** Recognize only access, busy, and permission filesystem codes as transient atomic-rewrite failures. */
282
299
  declare function isRetryableQueueRewriteError(error: unknown): boolean;
300
+ /** Yield for the requested retry delay without synchronously blocking the process. */
283
301
  declare function sleep(milliseconds: number): Promise<void>;
284
- /** Append a built OTLP span request to the bounded pending-spans queue. The detached flush worker drains and POSTs these so the foreground command never performs OTLP network I/O (GH-209). Best effort: a write failure never blocks the command, and the span is simply not exported. */
302
+ /** Serialize an independent pending-span append; compound completion capture calls the private writer under its existing queue transaction. */
285
303
  declare function enqueuePendingOtelSpan(globalPmRoot: string, request: {
286
304
  endpoint: string;
287
305
  payload: unknown;
288
306
  }): Promise<void>;
307
+ /** Recover valid pending span envelopes from JSONL, skip malformed rows, and assign stable content-derived IDs to legacy entries for reconciliation. */
289
308
  declare function parsePendingOtelSpanLines(raw: string): PendingOtelSpan[];
309
+ /** Compare valid enqueue timestamps with the retention cutoff; retain unknown or malformed dates rather than inventing an age. */
290
310
  declare function isExpiredPendingOtelSpan(entry: PendingOtelSpan, cutoffMs: number): boolean;
311
+ /** Drop oversized, expired, and attempt-exhausted spans, then keep the newest entries within the pending-span cap and report every removal. */
291
312
  declare function prunePendingOtelSpans(entries: PendingOtelSpan[], retentionDays: number): {
292
313
  entries: PendingOtelSpan[];
293
314
  prunedCount: number;
294
315
  };
316
+ /** Atomically replace the span snapshot, retrying transient filesystem contention; callers coordinate mutations with the queue mutex. */
295
317
  declare function rewritePendingOtelSpans(globalPmRoot: string, entries: PendingOtelSpan[]): Promise<void>;
296
- /** Drain the pending OTLP span queue and POST due spans to their traces endpoint. Runs only inside the flush worker (detached child) or the inline test path, so the foreground command never makes OTLP network calls. Failures increment per-span attempts with backoff and are retried by a later flush; runtime state records OTLP export diagnostics for `pm health` (GH-205). */
297
318
  /** Re-read the spans queue under the mutation serializer and rewrite it with the processed spans removed/updated by id, preserving any spans a concurrent foreground process appended during the (network) flush window. `succeededIds` are dropped; `failedUpdates` patch attempts/next_attempt_after by id; all other (incl. newly-appended) entries are retained, then pruned. Returns the count of spans left in the queue. Mirrors removeFlushedEntriesFromCurrentQueue. */
298
319
  declare function reconcilePendingOtelSpansAfterFlush(globalPmRoot: string, retentionDays: number, succeededIds: ReadonlySet<string>, failedUpdates: ReadonlyMap<string, {
299
320
  attempts: number;
300
321
  next_attempt_after: string;
301
322
  }>): Promise<number>;
323
+ /** POST due spans outside the mutation mutex, then reconcile successes and retry metadata against the current queue; publish export diagnostics for health inspection. */
302
324
  declare function flushPendingOtelSpans(globalPmRoot: string, retentionDays: number): Promise<void>;
303
325
  /** Flush both telemetry artifacts under the same worker invocation: the event ingest queue and the pending OTLP span queue. Used by the detached flush worker and the inline (test) path so OTLP export always happens off the foreground command's critical path. */
304
326
  declare function flushTelemetryArtifacts(globalPmRoot: string, endpoint: string, retentionDays: number): Promise<void>;
305
- declare function withQueueMutation<T>(operation: () => Promise<T>): Promise<T>;
327
+ export { withQueueMutation as withTelemetryQueueMutation };
328
+ /** Serialize complete queue transactions across processes. The per-acquisition wait defaults to five seconds for maintenance; foreground capture supplies a shorter budget. PM_LOCK_WAIT_MS remains an explicit override. Never hold the lock during network I/O. */
329
+ declare function withQueueMutation<T>(operation: () => Promise<T>, globalPmRoot?: string, waitMs?: number): Promise<T>;
330
+ /** Read the current event snapshot, treating a missing or blank queue as empty and dropping malformed records through the shared parser. */
306
331
  declare function readCurrentQueueEntries(globalPmRoot: string): Promise<QueuedTelemetryEvent[]>;
332
+ /** Remove acknowledged event IDs and expired entries from a fresh locked snapshot, returning the retained queue including intervening appends. */
307
333
  declare function removeFlushedEntriesFromCurrentQueue(globalPmRoot: string, flushedIds: ReadonlySet<string>, retentionDays: number): Promise<QueuedTelemetryEvent[]>;
334
+ /** Send one due event batch without holding the mutation mutex, then reconcile its result against the current queue and record delivery diagnostics. */
308
335
  declare function flushQueue(globalPmRoot: string, endpoint: string, retentionDays: number): Promise<void>;
309
336
  declare function acquireTelemetryFlushLock(globalPmRoot: string): Promise<boolean>;
310
337
  declare function isFreshDirectoryLock(lockPath: string, staleMs: number): boolean;
@@ -385,9 +412,9 @@ declare function flushQueueWithProcessLock(globalPmRoot: string, endpoint: strin
385
412
  declare function scheduleTelemetryFlush(globalPmRoot: string, endpoint: string, retentionDays: number): void;
386
413
  /** Best-effort drain of event and span queues when both process consent and persisted settings permit delivery. */
387
414
  export declare function flushTelemetryQueueNow(globalPmRoot?: string): Promise<void>;
388
- /** Begin a consent-permitted invocation, deferring sampled core reads until their outcome determines pair retention. */
415
+ /** Atomically validate consent, initialize identity, and capture an invocation; defer sampled reads until their outcome determines pair retention and schedule delivery after releasing the mutex. */
389
416
  export declare function startTelemetryCommand(context: TelemetryCommandContext): Promise<ActiveTelemetryCommand | null>;
390
- /** Complete an invocation after rechecking consent, retaining every failed read and weighting selected successful pairs. */
417
+ /** Complete an invocation only while process consent, saved consent, and its installation identity still agree; retain failed reads and weight selected successful pairs. */
391
418
  export declare function finishTelemetryCommand(activeCommand: ActiveTelemetryCommand | null, outcome: TelemetryCommandOutcome): Promise<void>;
392
- /** Record an unsampled, sanitized command error without creating identity or queue state when process consent forbids capture. */
419
+ /** Atomically validate consent and append a sanitized command error with its installation identity; schedule delivery only after releasing the queue mutex. */
393
420
  export declare function emitTelemetryErrorEvent(context: TelemetryErrorEventContext): Promise<void>;
@@ -1,5 +1,6 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="84b967fb-8de8-5e2f-b482-2328ef284acd")}catch(e2){}})();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{PM_TELEMETRY_SOURCE_CONTEXT_VALUES,resolveTelemetryEnvironmentPolicy,resolveTelemetryReadSampleRate}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{readSettings,writeSettings}from"../store/settings.js";import{deriveTelemetryCommandResolution,deriveTelemetryCommandTaxonomy,inferTelemetryErrorCode}from"./observability.js";const TELEMETRY_QUEUE_RELATIVE_PATH=path.join("runtime","telemetry","events.jsonl");const TELEMETRY_STATE_RELATIVE_PATH=path.join("runtime","telemetry","state.json");const TELEMETRY_OTEL_SPANS_RELATIVE_PATH=path.join("runtime","telemetry","otel-spans.jsonl");const TELEMETRY_OTEL_SPANS_FLUSH_BATCH_SIZE=8;const TELEMETRY_OTEL_SPANS_MAX_PENDING=500;const TELEMETRY_SCHEMA_VERSION=1;const TELEMETRY_CLIENT_SCHEMA_VERSION=1;const TELEMETRY_FLUSH_BATCH_SIZE=100;const TELEMETRY_MAX_RETRY_DELAY_MS=36e5;const TELEMETRY_RETRY_BASE_DELAY_MS=3e4;const TELEMETRY_HTTP_TIMEOUT_DEFAULT_MS=2e4;const TELEMETRY_HTTP_TIMEOUT_MIN_MS=1e3;const TELEMETRY_HTTP_TIMEOUT_MAX_MS=25e3;const MILLISECONDS_PER_DAY=864e5;const TELEMETRY_MAX_EVENT_BYTES=65536;const TELEMETRY_SANITIZE_MAX_DEPTH=6;const TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS=20;const TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS=15;const TELEMETRY_RESULT_PREVIEW_MAX_BYTES=8192;const TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS=[25,50,100,200];const TELEMETRY_QUEUE_TMP_ORPHAN_MAX_AGE_MS=60*60*1e3;const TELEMETRY_FLUSH_LOCK_STALE_MS=6e4;const TELEMETRY_FLUSH_SPAWN_LOCK_STALE_MS=6e4;const OTEL_TRACES_ENDPOINT_ENV="OTEL_EXPORTER_OTLP_TRACES_ENDPOINT";const OTEL_BASE_ENDPOINT_ENV="OTEL_EXPORTER_OTLP_ENDPOINT";const OTEL_SERVICE_NAME_ENV="OTEL_SERVICE_NAME";const PM_TELEMETRY_OTEL_DISABLED_ENV="PM_TELEMETRY_OTEL_DISABLED";const PM_TELEMETRY_OTEL_DISABLED_VALUES=new Set(["1","true","yes","on"]);const PM_TELEMETRY_INLINE_FLUSH_ENV="PM_TELEMETRY_INLINE_FLUSH";const PM_TELEMETRY_FLUSH_CHILD_ENV="PM_TELEMETRY_FLUSH_CHILD";const PM_TELEMETRY_SOURCE_CONTEXT_ENV="PM_TELEMETRY_SOURCE_CONTEXT";const PM_TELEMETRY_HTTP_TIMEOUT_MS_ENV="PM_TELEMETRY_HTTP_TIMEOUT_MS";const NATIVE_FETCH=globalThis.fetch;import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES as PM_TELEMETRY_SOURCE_CONTEXT_VALUES2}from"./policy.js";let _lastFlushPromise=Promise.resolve();let _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);const BOOLEAN_TRUE_VALUES=new Set(["1","true","yes","on"]);const TELEMETRY_HARNESSES=new Set(["claude-code","codex","pi","opencode","cursor","aider","gemini-cli","ci"]);const PROCESS_SESSION_ID=crypto.randomUUID();const SENSITIVE_KEYWORDS=["token","secret","password","passwd","api_key","apikey","authorization","cookie","session","credentials","bearer"];const REDACTION_INPUT_KEYS=new Set(["literal","literals","regex","regexes","replacement","replacements"]);const SENSITIVE_INLINE_KEY_PATTERN="(?:token|secret|password|passwd|api[_-]?key|apikey|authorization|cookie|session|credentials|bearer|literals?|regex(?:es)?|replacements?)";const INLINE_SENSITIVE_ASSIGNMENT_PATTERN=new RegExp(`\\b(${SENSITIVE_INLINE_KEY_PATTERN})\\s*([:=])\\s*([^\\s,;]+)`,"giu");const INLINE_SENSITIVE_FLAG_PATTERN=new RegExp(`(--${SENSITIVE_INLINE_KEY_PATTERN})(=|\\s+)([^\\s,;]+)`,"giu");const ABSOLUTE_PATH_TOKEN_PATTERN=/(^|[\s"'`(=])\/(?:[^\s"'`),;]+)/g;const BEARER_TOKEN_PATTERN=/bearer\s+[a-z0-9._=-]+/giu;const 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])){return true}if(parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])){return true}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);if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){return{}}return parsed}catch{return{}}}async function writeRuntimeState(globalPmRoot,patch){try{const current=await readRuntimeState(globalPmRoot);const next={...current,...patch};const 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
- `)}catch{}}function isSensitiveKey(key){const normalized=key.trim().toLowerCase().replaceAll("-","_").replaceAll(/[^a-z0-9_]+/g,"_");const 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){const withoutAssignments=input.replaceAll(INLINE_SENSITIVE_ASSIGNMENT_PATTERN,(_match,key,delimiter)=>`${key}${delimiter}[redacted]`);return withoutAssignments.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;const isLower=code>=97&&code<=122;const isDigit=code>=48&&code<=57;return isUpper||isLower||isDigit}function isEmailLocalCharacter(character){if(!character){return false}const code=character.charCodeAt(0);if(isAsciiLetterOrDigitCode(code)){return true}return character==="."||character==="_"||character==="%"||character==="+"||character==="-"}function isEmailDomainCharacter(character){if(!character){return false}const code=character.charCodeAt(0);if(isAsciiLetterOrDigitCode(code)){return true}return character==="."||character==="-"}function looksLikeEmailToken(token){const atIndex=token.indexOf("@");if(atIndex<=0||atIndex!==token.lastIndexOf("@")||atIndex===token.length-1){return false}const localPart=token.slice(0,atIndex);const domainPart=token.slice(atIndex+1);const lastDot=domainPart.lastIndexOf(".");if(lastDot<=0||lastDot===domainPart.length-1){return false}if(domainPart.length-(lastDot+1)<2){return false}for(const character of localPart){if(!isEmailLocalCharacter(character)){return false}}for(const character of domainPart){if(!isEmailDomainCharacter(character)){return false}}return true}function redactEmailTokens(input){let redacted="";let cursor=0;while(cursor<input.length){const atIndex=input.indexOf("@",cursor);if(atIndex<0){redacted+=input.slice(cursor);break}let start=atIndex-1;while(start>=cursor&&isEmailLocalCharacter(input[start])){start-=1}start+=1;let end=atIndex+1;while(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){const withoutEmails=redactEmailTokens(input);const withoutBearer=withoutEmails.replaceAll(BEARER_TOKEN_PATTERN,"bearer [redacted_token]");return withoutBearer.replaceAll(PRIVATE_IP_PATTERN,"[redacted_ip]")}function sanitizeStringRedacted(input){const withoutCommonSensitiveTokens=sanitizeCommonSensitiveTokens(input);const withoutInlineSecrets=redactInlineSensitiveAssignments(withoutCommonSensitiveTokens);const withoutAbsolutePaths=redactAbsolutePathTokens(withoutInlineSecrets);const trimmed=withoutAbsolutePaths.trim();if(trimmed.startsWith("/")&&trimmed.length>1){return"[redacted_path]"}if(withoutAbsolutePaths.length>512){return`${withoutAbsolutePaths.slice(0,509)}...`}return withoutAbsolutePaths}function sanitizeStringMax(input){const withoutCommonSensitiveTokens=sanitizeCommonSensitiveTokens(input);const withoutInlineSecrets=redactInlineSensitiveAssignments(withoutCommonSensitiveTokens);const withoutAbsolutePaths=redactAbsolutePathTokens(withoutInlineSecrets);const trimmed=withoutAbsolutePaths.trim();if(trimmed.startsWith("/")&&trimmed.length>1){return"[redacted_path]"}if(withoutAbsolutePaths.length>2048){return`${withoutAbsolutePaths.slice(0,2045)}...`}return withoutAbsolutePaths}function sanitizeString(input,captureLevel="redacted"){if(captureLevel==="max"){return sanitizeStringMax(input)}return sanitizeStringRedacted(input)}function sanitizeValue(value,keyHint,captureLevel="redacted",depth=0){if(keyHint&&isSensitiveKey(keyHint)){return"[redacted]"}if(value===null||value===void 0){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;const 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=false;for(const rawArg of args){const arg=sanitizeString(rawArg,captureLevel);if(nextIsSensitiveValue){sanitized.push("[redacted]");nextIsSensitiveValue=false;continue}if(arg.startsWith("--")){const withoutPrefix=arg.slice(2);const delimiterIndex=withoutPrefix.indexOf("=");if(delimiterIndex>=0){const key=withoutPrefix.slice(0,delimiterIndex);const value=withoutPrefix.slice(delimiterIndex+1);if(isSensitiveKey(key)){sanitized.push(`--${key}=[redacted]`)}else{sanitized.push(`--${key}=${sanitizeString(value,captureLevel)}`)}continue}if(isSensitiveKey(withoutPrefix)){sanitized.push(`--${withoutPrefix}`);nextIsSensitiveValue=true;continue}}sanitized.push(arg)}return sanitized}function normalizeCaptureLevel(value){const normalized=value?.trim().toLowerCase();if(normalized==="minimal"||normalized==="redacted"||normalized==="max"){return normalized}return"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);if(!Number.isFinite(configured)){return TELEMETRY_HTTP_TIMEOUT_DEFAULT_MS}return Math.min(TELEMETRY_HTTP_TIMEOUT_MAX_MS,Math.max(TELEMETRY_HTTP_TIMEOUT_MIN_MS,Math.trunc(configured)))}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{const response=await Promise.race([globalThis.fetch(endpoint,{method:"POST",headers,body,signal:controller.signal}),deadline]);return response.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();const requestOptions={method:"POST",headers:{...headers,"content-length":Buffer.byteLength(body)},signal:AbortSignal.timeout(timeoutMs),autoSelectFamilyAttemptTimeout:Math.min(5e3,timeoutMs)};const 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){if(Number.isFinite(exitCode)){return Math.max(0,Math.trunc(exitCode))}return ok?0:1}function normalizeTelemetryErrorCategory(params){if(params.ok){return void 0}if(typeof params.errorCategory==="string"&&params.errorCategory.trim().length>0){return params.errorCategory}if(typeof params.errorCode==="string"&&params.errorCode.trim().length>0){return resolveTelemetryErrorCategory(params.errorCode)}return"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 nodeEnv=(process.env.NODE_ENV??"").trim().toLowerCase();if(typeof process.env.VITEST==="string"||typeof process.env.VITEST_WORKER_ID==="string"||nodeEnv==="test"){return{source_context:"test",source_context_source:"inferred"}}const nonTty=process.stdin.isTTY!==true||process.stdout.isTTY!==true;const ci=parseBooleanTrueLike(process.env.CI);const scriptLikeMode=globalOptions.json===true||globalOptions.quiet===true;if(nonTty||ci||scriptLikeMode){return{source_context:"automation",source_context_source:"inferred"}}return{source_context:"user",source_context_source:"inferred"}}function hashWithInstallationId(installationId,value){return crypto.createHash("sha256").update(`${installationId}:${value}`).digest("hex")}function buildAuthorContextPayloadFields(captureLevel,installationId){const author=(readAuthorEnvironment()??"").trim();const agent=detectAgentIdentity({env:process.env,argv:process.argv});const hasAgentContext=agent.harness!==void 0||agent.model!==void 0;if(captureLevel==="minimal"){return{has_author_context:author.length>0,has_agent_context:hasAgentContext}}return{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||value===void 0){return value}if(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;const normalized={};const 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");const normalizedCode=typeof errorCode2==="string"&&errorCode2.length>0?errorCode2:"unknown_error";const 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);const normalizedPath=url.pathname.replace(/\/+$/,"");if(!normalizedPath.endsWith("/v1/traces")){url.pathname=`${normalizedPath.length===0?"":normalizedPath}/v1/traces`}return url.toString()}catch{return null}}function isoToUnixNano(iso){const parsedMs=Date.parse(iso);const 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());const serviceName=serviceNameCandidate.length>0?serviceNameCandidate:"pm-cli";const normalizedExitCode=normalizeTelemetryExitCode(outcome.exit_code,outcome.ok);const normalizedErrorCode=normalizeTelemetryErrorCode(outcome.error_code);const normalizedErrorCategory=normalizeTelemetryErrorCategory({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:outcome.error_category});const 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))];if(typeof normalizedErrorCode==="string"){attributes.push(otlpStringAttribute("pm.error_code",normalizedErrorCode))}if(typeof normalizedErrorCategory==="string"){attributes.push(otlpStringAttribute("pm.error_category",normalizedErrorCategory))}if(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||result===void 0){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;const keys=Object.keys(record).sort((left,right)=>left.localeCompare(right));const 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;const commandTaxonomy=deriveTelemetryCommandTaxonomy(context.command);const hashedArgs=hashCommandArgs(installationId,context.args);const commandInvocationDigest=hashWithInstallationId(installationId,`${context.command}\0${context.args.join("\0")}`);const commandOptionsDigest=hashTelemetryValue(installationId,context.options);const globalOptionsDigest=hashTelemetryValue(installationId,context.global);const authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);if(captureLevel==="minimal"){return{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}}return{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===true,stdout_tty:process.stdout.isTTY===true}}}function buildCommandFinishPayload(params){const{captureLevel,pmVersion,sourceContext,outcome,durationMs,startedAt,command,installationId,commandTaxonomy,exitCode,errorCode:errorCode2,errorCategory,commandResolution,resolutionStage}=params;const errorFingerprint=outcome.ok===false?hashTelemetryErrorFingerprint(installationId,command,errorCode2,outcome.error):void 0;const authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);if(captureLevel==="minimal"){return{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}}return{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;const attemptedArgHashes=hashCommandArgs(installationId,args);const attemptedCommandDigest=hashWithInstallationId(installationId,command);const attemptedOptionsDigest=hashTelemetryValue(installationId,options);const errorFingerprint=hashTelemetryErrorFingerprint(installationId,command,errorCode2,errorMessage);const authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);if(captureLevel==="minimal"){return{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}}return{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===true,stdout_tty:process.stdout.isTTY===true}}}async function ensureInstallationId(globalPmRoot){const settings=await readSettings(globalPmRoot);let changed=false;if(settings.telemetry.installation_id.trim().length===0){settings.telemetry.installation_id=crypto.randomUUID();changed=true}if(changed){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))}}async function enqueueTelemetryEvent(globalPmRoot,event){const queued={client_schema_version:TELEMETRY_CLIENT_SCHEMA_VERSION,event,attempts:0};let serialized=JSON.stringify(queued);if(serialized.length>TELEMETRY_MAX_EVENT_BYTES){const trimmed={...event,payload:{...event.payload,result_summary:{truncated:true,reason:"payload_size_exceeded",original_bytes:serialized.length}}};const trimmedQueued={client_schema_version:TELEMETRY_CLIENT_SCHEMA_VERSION,event:trimmed,attempts:0};serialized=JSON.stringify(trimmedQueued)}await withQueueMutation(async()=>{await appendLineAtomic(queuePath(globalPmRoot),serialized)})}function parseQueueLines(raw){const entries=[];for(const line of raw.split("\n")){const trimmed=line.trim();if(trimmed.length===0){continue}try{const parsed=JSON.parse(trimmed);if(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 true}const dueAtMs=Date.parse(nextAttemptAfter);if(Number.isNaN(dueAtMs)){return true}return 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 false}const occurredAtMs=Date.parse(occurredAt);if(Number.isNaN(occurredAtMs)){return false}return occurredAtMs<cutoffMs}function pruneExpiredQueueEntries(entries,retentionDays){const cutoffMs=retentionCutoffMs(retentionDays);const retained=[];let prunedCount=0;for(const entry of entries){const serializedSize=JSON.stringify(entry).length;const oversized=serializedSize>TELEMETRY_MAX_EVENT_BYTES;if(oversized||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("\n");const contents=serialized.length>0?`${serialized}
3
- `:"";for(let attempt=0;;attempt+=1){try{await writeFileAtomic(queuePath(globalPmRoot),contents);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 false}const code=error.code;return code==="EACCES"||code==="EBUSY"||code==="EPERM"}function sleep(milliseconds){return new Promise(resolve=>{setTimeout(resolve,milliseconds)})}async function enqueuePendingOtelSpan(globalPmRoot,request){const pending={id:crypto.randomUUID(),endpoint:request.endpoint,payload:request.payload,enqueued_at:nowIso(),attempts:0};const serialized=JSON.stringify(pending);if(serialized.length>TELEMETRY_MAX_EVENT_BYTES){return}await withQueueMutation(async()=>{await appendLineAtomic(otelSpansQueuePath(globalPmRoot),serialized)})}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("\n")){const trimmed=line.trim();if(trimmed.length===0){continue}try{const parsed=JSON.parse(trimmed);if(parsed&&typeof parsed==="object"&&typeof parsed.endpoint==="string"&&parsed.endpoint.trim().length>0&&"payload"in parsed&&typeof parsed.attempts==="number"&&Number.isFinite(parsed.attempts)){if(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 false}const enqueuedAtMs=Date.parse(entry.enqueued_at);if(Number.isNaN(enqueuedAtMs)){return false}return enqueuedAtMs<cutoffMs}function prunePendingOtelSpans(entries,retentionDays){const cutoffMs=retentionCutoffMs(retentionDays);const retained=[];let prunedCount=0;for(const entry of entries){const oversized=JSON.stringify(entry).length>TELEMETRY_MAX_EVENT_BYTES;if(oversized||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;prunedCount+=overflow;return{entries:retained.slice(overflow),prunedCount}}return{entries:retained,prunedCount}}async function rewritePendingOtelSpans(globalPmRoot,entries){const serialized=entries.map(entry=>JSON.stringify(entry)).join("\n");const contents=serialized.length>0?`${serialized}
4
- `:"";for(let attempt=0;;attempt+=1){try{await writeFileAtomic(otelSpansQueuePath(globalPmRoot),contents);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));const current=raw===null?[]:parsePendingOtelSpanLines(raw);const 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);await rewritePendingOtelSpans(globalPmRoot,retained);return retained.length})}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);const{entries:retained,prunedCount}=prunePendingOtelSpans(entries,retentionDays);const 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();const succeededIds=new Set;const failedUpdates=new Map;let succeededCount=0;let 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);const statePatch={pending_otel_spans:remaining,last_otel_attempt_at:attemptTime};if(succeededCount>0){statePatch.last_otel_success_at=attemptTime}if(lastError!==void 0){statePatch.last_otel_failure_at=attemptTime;statePatch.last_otel_failure_error=lastError}else if(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);const entries=await readdir(dirPath,{withFileTypes:true});const 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);const candidateStats=await stat(candidate);if(candidateStats.mtimeMs<cutoffMs){await rm(candidate,{force:true})}}))}catch{}}async function withQueueMutation(operation){const run=_queueMutationPromise.catch(()=>{}).then(operation);_queueMutationPromise=run.catch(()=>{});return run}async function readCurrentQueueEntries(globalPmRoot){const raw=await readFileIfExists(queuePath(globalPmRoot));if(raw===null||raw.trim().length===0){return[]}return parseQueueLines(raw)}async function removeFlushedEntriesFromCurrentQueue(globalPmRoot,flushedIds,retentionDays){return withQueueMutation(async()=>{const currentEntries=await readCurrentQueueEntries(globalPmRoot);const{entries:retainedEntries}=pruneExpiredQueueEntries(currentEntries,retentionDays);const remaining=retainedEntries.filter(entry=>!flushedIds.has(entry.event.event_id));await rewriteQueue(globalPmRoot,remaining);return remaining})}async function markFailedEntriesInCurrentQueue(globalPmRoot,failedIds,attemptTime,retentionDays){return withQueueMutation(async()=>{const currentEntries=await readCurrentQueueEntries(globalPmRoot);const{entries:retainedEntries}=pruneExpiredQueueEntries(currentEntries,retentionDays);const 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)}});await rewriteQueue(globalPmRoot,retried);return retried})}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){await rewriteQueue(globalPmRoot,[]);await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:0});return}const dueEntries=retainedEntries.filter(entry=>isDueForRetry(entry)).slice(0,TELEMETRY_FLUSH_BATCH_SIZE);if(dueEntries.length===0){if(prunedCount>0){await rewriteQueue(globalPmRoot,retainedEntries)}await writeRuntimeState(globalPmRoot,{endpoint:normalizedEndpoint,queue_entries:retainedEntries.length});return}const dueIds=new Set(dueEntries.map(entry=>entry.event.event_id));const attemptTime=nowIso();const requestHeaders={"content-type":"application/json"};const ingestKey=process.env.PM_TELEMETRY_INGEST_KEY?.trim();if(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);const errorMessage=(()=>{if(error instanceof Error){return sanitizeString(error.message,"redacted")}return"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=(()=>{if(error instanceof Error){return sanitizeString(error.message,"redacted")}return"telemetry_flush_failed"})();const 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);await mkdir(path.dirname(lockPath),{recursive:true});try{await mkdir(lockPath);return true}catch(error){if(typeof error!=="object"||error===null||!("code"in error)||error.code!=="EEXIST"){throw error}}try{const lockStats=await stat(lockPath);if(Date.now()-lockStats.mtimeMs<TELEMETRY_FLUSH_LOCK_STALE_MS){return false}await rm(lockPath,{recursive:true,force:true});await mkdir(lockPath);return true}catch{return false}}function isFreshDirectoryLock(lockPath,staleMs){try{return Date.now()-statSync(lockPath).mtimeMs<staleMs}catch{return false}}function removeDirectoryLockBestEffort(lockPath){try{rmSync(lockPath,{recursive:true,force:true})}catch{}}function errorCode(error){if(typeof error!=="object"||error===null||!("code"in error)){return void 0}const code=error.code;return typeof code==="string"?code:void 0}function createDirectoryLock(lockPath){try{mkdirSync(lockPath);return true}catch(error){const code=errorCode(error);if(code==="EEXIST"){return false}if(!isFileMissingError(error)){return false}}try{mkdirSync(path.dirname(lockPath),{recursive:true});mkdirSync(lockPath);return true}catch{return false}}function acquireTelemetryFlushSpawnGate(globalPmRoot){if(isFreshDirectoryLock(flushLockPath(globalPmRoot),TELEMETRY_FLUSH_LOCK_STALE_MS)){return false}const lockPath=flushSpawnLockPath(globalPmRoot);try{if(Date.now()-statSync(lockPath).mtimeMs<TELEMETRY_FLUSH_SPAWN_LOCK_STALE_MS){return false}removeDirectoryLockBestEffort(lockPath)}catch(error){if(!isFileMissingError(error)){return false}}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);releaseTelemetryFlushSpawnGate(globalPmRoot);if(!acquired){return}try{await flushTelemetryArtifacts(globalPmRoot,endpoint,retentionDays)}finally{try{await rm(flushLockPath(globalPmRoot),{recursive:true,force:true})}catch{}}}function scheduleTelemetryFlush(globalPmRoot,endpoint,retentionDays){if(shouldFlushInline()){const previousFlush=_lastFlushPromise;const nextFlush=flushTelemetryArtifacts(globalPmRoot,endpoint,retentionDays);_lastFlushPromise=Promise.allSettled([previousFlush,nextFlush]).then(()=>{});return}try{const acquiredSpawnGate=acquireTelemetryFlushSpawnGate(globalPmRoot);if(!acquiredSpawnGate){return}const child=spawn(process.execPath,[telemetryFlushRunnerPath()],{detached:true,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){return}try{const settings=await readSettings(globalPmRoot);if(!settings.telemetry.enabled){return}const{endpoint,retentionDays}=await ensureInstallationId(globalPmRoot);await flushQueueWithProcessLock(globalPmRoot,endpoint,retentionDays)}catch{}}async function startTelemetryCommand(context){if(resolveTelemetryEnvironmentPolicy().telemetry_disabled){return null}if(context.command==="telemetry"&&context.args.some(token=>token.trim().toLowerCase()==="clear")){return null}try{const globalPmRoot=resolveGlobalPmRoot(process.cwd());const settings=await readSettings(globalPmRoot);if(!settings.telemetry.enabled){return null}const captureLevel=normalizeCaptureLevel(settings.telemetry.capture_level);const{installationId,endpoint,retentionDays}=await ensureInstallationId(globalPmRoot);const pmVersion=normalizePmVersion(context.pm_version);const sourceContext=resolveTelemetrySourceContext(context.global);const pmRootHash=hashWithInstallationId(installationId,context.pm_root);const cwdHash=hashWithInstallationId(installationId,process.cwd());const otelTracesEndpoint=resolveOtelTracesEndpoint();const occurredAt=nowIso();const 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})};const sampleRate=resolveTelemetryReadSampleRate(context.command,context.global.noExtensions===true);if(sampleRate===1){await enqueueTelemetryEvent(globalPmRoot,event);scheduleTelemetryFlush(globalPmRoot,endpoint,retentionDays)}const commandTaxonomy=deriveTelemetryCommandTaxonomy(context.command);const 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};if(sampleRate<1)deferredReadStarts.set(active,event);return active}catch{return null}}async function finishTelemetryCommand(activeCommand,outcome){if(!activeCommand||resolveTelemetryEnvironmentPolicy().telemetry_disabled){return}try{const deferredStart=deferredReadStarts.get(activeCommand);const sampleRate=outcome.ok?activeCommand.sample_rate??1:1;if(deferredStart){deferredReadStarts.delete(activeCommand);if(crypto.randomBytes(6).readUIntBE(0,6)/2**48>=sampleRate)return;deferredStart.payload.sample_rate=sampleRate;await enqueueTelemetryEvent(activeCommand.global_pm_root,deferredStart)}const finishedAt=nowIso();const durationMs=Math.max(0,Date.now()-activeCommand.started_at_ms);const normalizedErrorCode=normalizeTelemetryErrorCode(inferTelemetryErrorCode({ok:outcome.ok,errorCode:outcome.error_code,errorMessage:outcome.error,exitCode:outcome.exit_code}));const normalizedErrorCategory=normalizeTelemetryErrorCategory({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:outcome.error_category});const normalizedExitCode=normalizeTelemetryExitCode(outcome.exit_code,outcome.ok);const commandResolution=outcome.command_resolution??deriveTelemetryCommandResolution({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:normalizedErrorCategory});const resolutionStage=outcome.resolution_stage??"execute";const 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 enqueueTelemetryEvent(activeCommand.global_pm_root,event);const otelRequest=buildOtelSpanRequest(activeCommand,{...outcome,exit_code:normalizedExitCode,error_code:normalizedErrorCode,error_category:normalizedErrorCategory},finishedAt,durationMs,sampleRate);if(otelRequest){await enqueuePendingOtelSpan(activeCommand.global_pm_root,otelRequest)}scheduleTelemetryFlush(activeCommand.global_pm_root,activeCommand.endpoint,activeCommand.retention_days)}catch{}}async function emitTelemetryErrorEvent(context){if(resolveTelemetryEnvironmentPolicy().telemetry_disabled){return}try{const globalPmRoot=resolveGlobalPmRoot(process.cwd());const settings=await readSettings(globalPmRoot);if(!settings.telemetry.enabled){return}const captureLevel=normalizeCaptureLevel(settings.telemetry.capture_level);const{installationId,endpoint,retentionDays}=await ensureInstallationId(globalPmRoot);const pmVersion=normalizePmVersion(context.pm_version);const sourceContext=resolveTelemetrySourceContext(context.global);const pmRootHash=hashWithInstallationId(installationId,context.pm_root);const cwdHash=hashWithInstallationId(installationId,process.cwd());const occurredAt=nowIso();const normalizedErrorCode=normalizeTelemetryErrorCode(inferTelemetryErrorCode({ok:false,errorCode:context.error_code,errorMessage:context.error_message,exitCode:context.exit_code}));const normalizedErrorCategory=context.error_category??resolveTelemetryErrorCategory(normalizedErrorCode);const normalizedExitCode=normalizeTelemetryExitCode(context.exit_code,false);const normalizedCommand=context.command.trim().length>0?context.command:"<unknown>";const commandTaxonomy=deriveTelemetryCommandTaxonomy(normalizedCommand);const commandResolution=context.command_resolution??deriveTelemetryCommandResolution({ok:false,errorCode:normalizedErrorCode,errorCategory:normalizedErrorCategory});const resolutionStage=context.resolution_stage??"unknown";const 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})};await enqueueTelemetryEvent(globalPmRoot,event);scheduleTelemetryFlush(globalPmRoot,endpoint,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};
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="da54e7d1-5a09-53b8-85df-6a6def6fe54f")}catch(e2){}})();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{runWithIsolatedExtensionRuntime}from"../extensions/index.js";import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES,resolveTelemetryEnvironmentPolicy,resolveTelemetryReadSampleRate}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{readSettings,writeSettings}from"../store/settings.js";import{deriveTelemetryCommandResolution,deriveTelemetryCommandTaxonomy,inferTelemetryErrorCode}from"./observability.js";const TELEMETRY_QUEUE_RELATIVE_PATH=path.join("runtime","telemetry","events.jsonl");const TELEMETRY_STATE_RELATIVE_PATH=path.join("runtime","telemetry","state.json");const TELEMETRY_OTEL_SPANS_RELATIVE_PATH=path.join("runtime","telemetry","otel-spans.jsonl");const TELEMETRY_OTEL_SPANS_FLUSH_BATCH_SIZE=8;const TELEMETRY_OTEL_SPANS_MAX_PENDING=500;const TELEMETRY_SCHEMA_VERSION=1;const TELEMETRY_CLIENT_SCHEMA_VERSION=1;const TELEMETRY_FLUSH_BATCH_SIZE=100;const TELEMETRY_MAX_RETRY_DELAY_MS=36e5;const TELEMETRY_RETRY_BASE_DELAY_MS=3e4;const TELEMETRY_HTTP_TIMEOUT_DEFAULT_MS=2e4;const TELEMETRY_HTTP_TIMEOUT_MIN_MS=1e3;const TELEMETRY_HTTP_TIMEOUT_MAX_MS=25e3;const TELEMETRY_FOREGROUND_LOCK_WAIT_MS=250;const MILLISECONDS_PER_DAY=864e5;const TELEMETRY_MAX_EVENT_BYTES=65536;const TELEMETRY_SANITIZE_MAX_DEPTH=6;const TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS=20;const TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS=15;const TELEMETRY_RESULT_PREVIEW_MAX_BYTES=8192;const TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS=[25,50,100,200];const TELEMETRY_QUEUE_TMP_ORPHAN_MAX_AGE_MS=60*60*1e3;const TELEMETRY_FLUSH_LOCK_STALE_MS=6e4;const TELEMETRY_FLUSH_SPAWN_LOCK_STALE_MS=6e4;const OTEL_TRACES_ENDPOINT_ENV="OTEL_EXPORTER_OTLP_TRACES_ENDPOINT";const OTEL_BASE_ENDPOINT_ENV="OTEL_EXPORTER_OTLP_ENDPOINT";const OTEL_SERVICE_NAME_ENV="OTEL_SERVICE_NAME";const PM_TELEMETRY_OTEL_DISABLED_ENV="PM_TELEMETRY_OTEL_DISABLED";const PM_TELEMETRY_OTEL_DISABLED_VALUES=new Set(["1","true","yes","on"]);const PM_TELEMETRY_INLINE_FLUSH_ENV="PM_TELEMETRY_INLINE_FLUSH";const PM_TELEMETRY_FLUSH_CHILD_ENV="PM_TELEMETRY_FLUSH_CHILD";const PM_TELEMETRY_SOURCE_CONTEXT_ENV="PM_TELEMETRY_SOURCE_CONTEXT";const PM_TELEMETRY_HTTP_TIMEOUT_MS_ENV="PM_TELEMETRY_HTTP_TIMEOUT_MS";const NATIVE_FETCH=globalThis.fetch;import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES as PM_TELEMETRY_SOURCE_CONTEXT_VALUES2}from"./policy.js";let sourceContextWarningEmitted=false;let _lastFlushPromise=Promise.resolve();let _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);const BOOLEAN_TRUE_VALUES=new Set(["1","true","yes","on"]);const TELEMETRY_HARNESSES=new Set(["claude-code","codex","pi","opencode","cursor","aider","gemini-cli","ci"]);const PROCESS_SESSION_ID=crypto.randomUUID();const SENSITIVE_KEYWORDS=["token","secret","password","passwd","api_key","apikey","authorization","cookie","session","credentials","bearer"];const REDACTION_INPUT_KEYS=new Set(["literal","literals","regex","regexes","replacement","replacements"]);const SENSITIVE_INLINE_KEY_PATTERN="(?:token|secret|password|passwd|api[_-]?key|apikey|authorization|cookie|session|credentials|bearer|literals?|regex(?:es)?|replacements?)";const INLINE_SENSITIVE_ASSIGNMENT_PATTERN=new RegExp(`\\b(${SENSITIVE_INLINE_KEY_PATTERN})\\s*([:=])\\s*([^\\s,;]+)`,"giu");const INLINE_SENSITIVE_FLAG_PATTERN=new RegExp(`(--${SENSITIVE_INLINE_KEY_PATTERN})(=|\\s+)([^\\s,;]+)`,"giu");const ABSOLUTE_PATH_TOKEN_PATTERN=/(^|[\s"'`(=])\/(?:[^\s"'`),;]+)/g;const BEARER_TOKEN_PATTERN=/bearer\s+[a-z0-9._=-]+/giu;const 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])){return true}if(parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])){return true}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);if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){return{}}return parsed}catch{return{}}}async function writeRuntimeState(globalPmRoot,patch){try{const current=await readRuntimeState(globalPmRoot);const next={...current,...patch};const 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
+ `)}catch{}}function isSensitiveKey(key){const normalized=key.trim().toLowerCase().replaceAll("-","_").replaceAll(/[^a-z0-9_]+/g,"_");const 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){const withoutAssignments=input.replaceAll(INLINE_SENSITIVE_ASSIGNMENT_PATTERN,(_match,key,delimiter)=>`${key}${delimiter}[redacted]`);return withoutAssignments.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;const isLower=code>=97&&code<=122;const isDigit=code>=48&&code<=57;return isUpper||isLower||isDigit}function isEmailLocalCharacter(character){if(!character){return false}const code=character.charCodeAt(0);if(isAsciiLetterOrDigitCode(code)){return true}return character==="."||character==="_"||character==="%"||character==="+"||character==="-"}function isEmailDomainCharacter(character){if(!character){return false}const code=character.charCodeAt(0);if(isAsciiLetterOrDigitCode(code)){return true}return character==="."||character==="-"}function looksLikeEmailToken(token){const atIndex=token.indexOf("@");if(atIndex<=0||atIndex!==token.lastIndexOf("@")||atIndex===token.length-1){return false}const localPart=token.slice(0,atIndex);const domainPart=token.slice(atIndex+1);const lastDot=domainPart.lastIndexOf(".");if(lastDot<=0||lastDot===domainPart.length-1){return false}if(domainPart.length-(lastDot+1)<2){return false}for(const character of localPart){if(!isEmailLocalCharacter(character)){return false}}for(const character of domainPart){if(!isEmailDomainCharacter(character)){return false}}return true}function redactEmailTokens(input){let redacted="";let cursor=0;while(cursor<input.length){const atIndex=input.indexOf("@",cursor);if(atIndex<0){redacted+=input.slice(cursor);break}let start=atIndex-1;while(start>=cursor&&isEmailLocalCharacter(input[start])){start-=1}start+=1;let end=atIndex+1;while(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){const withoutEmails=redactEmailTokens(input);const withoutBearer=withoutEmails.replaceAll(BEARER_TOKEN_PATTERN,"bearer [redacted_token]");return withoutBearer.replaceAll(PRIVATE_IP_PATTERN,"[redacted_ip]")}function sanitizeStringRedacted(input){const withoutCommonSensitiveTokens=sanitizeCommonSensitiveTokens(input);const withoutInlineSecrets=redactInlineSensitiveAssignments(withoutCommonSensitiveTokens);const withoutAbsolutePaths=redactAbsolutePathTokens(withoutInlineSecrets);const trimmed=withoutAbsolutePaths.trim();if(trimmed.startsWith("/")&&trimmed.length>1){return"[redacted_path]"}if(withoutAbsolutePaths.length>512){return`${withoutAbsolutePaths.slice(0,509)}...`}return withoutAbsolutePaths}function sanitizeStringMax(input){const withoutCommonSensitiveTokens=sanitizeCommonSensitiveTokens(input);const withoutInlineSecrets=redactInlineSensitiveAssignments(withoutCommonSensitiveTokens);const withoutAbsolutePaths=redactAbsolutePathTokens(withoutInlineSecrets);const trimmed=withoutAbsolutePaths.trim();if(trimmed.startsWith("/")&&trimmed.length>1){return"[redacted_path]"}if(withoutAbsolutePaths.length>2048){return`${withoutAbsolutePaths.slice(0,2045)}...`}return withoutAbsolutePaths}function sanitizeString(input,captureLevel="redacted"){if(captureLevel==="max"){return sanitizeStringMax(input)}return sanitizeStringRedacted(input)}function sanitizeValue(value,keyHint,captureLevel="redacted",depth=0){if(keyHint&&isSensitiveKey(keyHint)){return"[redacted]"}if(value===null||value===void 0){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;const 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=false;for(const rawArg of args){const arg=sanitizeString(rawArg,captureLevel);if(nextIsSensitiveValue){sanitized.push("[redacted]");nextIsSensitiveValue=false;continue}if(arg.startsWith("--")){const withoutPrefix=arg.slice(2);const delimiterIndex=withoutPrefix.indexOf("=");if(delimiterIndex>=0){const key=withoutPrefix.slice(0,delimiterIndex);const value=withoutPrefix.slice(delimiterIndex+1);if(isSensitiveKey(key)){sanitized.push(`--${key}=[redacted]`)}else{sanitized.push(`--${key}=${sanitizeString(value,captureLevel)}`)}continue}if(isSensitiveKey(withoutPrefix)){sanitized.push(`--${withoutPrefix}`);nextIsSensitiveValue=true;continue}}sanitized.push(arg)}return sanitized}function normalizeCaptureLevel(value){const normalized=value?.trim().toLowerCase();if(normalized==="minimal"||normalized==="redacted"||normalized==="max"){return normalized}return"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);if(!Number.isFinite(configured)){return TELEMETRY_HTTP_TIMEOUT_DEFAULT_MS}return Math.min(TELEMETRY_HTTP_TIMEOUT_MAX_MS,Math.max(TELEMETRY_HTTP_TIMEOUT_MIN_MS,Math.trunc(configured)))}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{const response=await Promise.race([globalThis.fetch(endpoint,{method:"POST",headers,body,signal:controller.signal}),deadline]);return response.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();const requestOptions={method:"POST",headers:{...headers,"content-length":Buffer.byteLength(body)},signal:AbortSignal.timeout(timeoutMs),autoSelectFamilyAttemptTimeout:Math.min(5e3,timeoutMs)};const 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){if(Number.isFinite(exitCode)){return Math.max(0,Math.trunc(exitCode))}return ok?0:1}function normalizeTelemetryErrorCategory(params){if(params.ok){return void 0}if(typeof params.errorCategory==="string"&&params.errorCategory.trim().length>0){return params.errorCategory}if(typeof params.errorCode==="string"&&params.errorCode.trim().length>0){return resolveTelemetryErrorCategory(params.errorCode)}return"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";if(source==="env_override_rejected"&&!sourceContextWarningEmitted&&!globalOptions.quiet){sourceContextWarningEmitted=true;process.stderr.write(`[pm] warning: PM_TELEMETRY_SOURCE_CONTEXT is not one of ${PM_TELEMETRY_SOURCE_CONTEXT_VALUES.join("|")}; ignoring override.
3
+ `)}return{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!==true||process.stdout.isTTY!==true;const ci=parseBooleanTrueLike(process.env.CI);const scriptLikeMode=globalOptions.json===true||globalOptions.quiet===true;if(nonTty||ci||scriptLikeMode){return"automation"}return"user"}function hashWithInstallationId(installationId,value){return crypto.createHash("sha256").update(`${installationId}:${value}`).digest("hex")}function buildAuthorContextPayloadFields(captureLevel,installationId){const author=(readAuthorEnvironment()??"").trim();const agent=detectAgentIdentity({env:process.env,argv:process.argv});const hasAgentContext=agent.harness!==void 0||agent.model!==void 0;if(captureLevel==="minimal"){return{has_author_context:author.length>0,has_agent_context:hasAgentContext}}return{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||value===void 0){return value}if(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;const normalized={};const 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");const normalizedCode=typeof errorCode2==="string"&&errorCode2.length>0?errorCode2:"unknown_error";const 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);const normalizedPath=url.pathname.replace(/\/+$/,"");if(!normalizedPath.endsWith("/v1/traces")){url.pathname=`${normalizedPath.length===0?"":normalizedPath}/v1/traces`}return url.toString()}catch{return null}}function isoToUnixNano(iso){const parsedMs=Date.parse(iso);const 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());const serviceName=serviceNameCandidate.length>0?serviceNameCandidate:"pm-cli";const normalizedExitCode=normalizeTelemetryExitCode(outcome.exit_code,outcome.ok);const normalizedErrorCode=normalizeTelemetryErrorCode(outcome.error_code);const normalizedErrorCategory=normalizeTelemetryErrorCategory({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:outcome.error_category});const 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))];if(typeof normalizedErrorCode==="string"){attributes.push(otlpStringAttribute("pm.error_code",normalizedErrorCode))}if(typeof normalizedErrorCategory==="string"){attributes.push(otlpStringAttribute("pm.error_category",normalizedErrorCategory))}if(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||result===void 0){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;const keys=Object.keys(record).sort((left,right)=>left.localeCompare(right));const 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;const commandTaxonomy=deriveTelemetryCommandTaxonomy(context.command);const hashedArgs=hashCommandArgs(installationId,context.args);const commandInvocationDigest=hashWithInstallationId(installationId,`${context.command}\0${context.args.join("\0")}`);const commandOptionsDigest=hashTelemetryValue(installationId,context.options);const globalOptionsDigest=hashTelemetryValue(installationId,context.global);const authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);if(captureLevel==="minimal"){return{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}}return{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===true,stdout_tty:process.stdout.isTTY===true}}}function buildCommandFinishPayload(params){const{captureLevel,pmVersion,sourceContext,outcome,durationMs,startedAt,command,installationId,commandTaxonomy,exitCode,errorCode:errorCode2,errorCategory,commandResolution,resolutionStage}=params;const errorFingerprint=outcome.ok===false?hashTelemetryErrorFingerprint(installationId,command,errorCode2,outcome.error):void 0;const authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);if(captureLevel==="minimal"){return{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}}return{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;const attemptedArgHashes=hashCommandArgs(installationId,args);const attemptedCommandDigest=hashWithInstallationId(installationId,command);const attemptedOptionsDigest=hashTelemetryValue(installationId,options);const errorFingerprint=hashTelemetryErrorFingerprint(installationId,command,errorCode2,errorMessage);const authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);if(captureLevel==="minimal"){return{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}}return{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===true,stdout_tty:process.stdout.isTTY===true}}}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){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){const queued={client_schema_version:TELEMETRY_CLIENT_SCHEMA_VERSION,event,attempts:0};let serialized=JSON.stringify(queued);if(serialized.length>TELEMETRY_MAX_EVENT_BYTES){const trimmed={...event,payload:{...event.payload,result_summary:{truncated:true,reason:"payload_size_exceeded",original_bytes:serialized.length}}};const trimmedQueued={client_schema_version:TELEMETRY_CLIENT_SCHEMA_VERSION,event:trimmed,attempts:0};serialized=JSON.stringify(trimmedQueued)}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("\n")){const trimmed=line.trim();if(trimmed.length===0){continue}try{const parsed=JSON.parse(trimmed);if(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 true}const dueAtMs=Date.parse(nextAttemptAfter);if(Number.isNaN(dueAtMs)){return true}return 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 false}const occurredAtMs=Date.parse(occurredAt);if(Number.isNaN(occurredAtMs)){return false}return occurredAtMs<cutoffMs}function pruneExpiredQueueEntries(entries,retentionDays){const cutoffMs=retentionCutoffMs(retentionDays);const retained=[];let prunedCount=0;for(const entry of entries){const serializedSize=JSON.stringify(entry).length;const oversized=serializedSize>TELEMETRY_MAX_EVENT_BYTES;if(oversized||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("\n");const contents=serialized.length>0?`${serialized}
4
+ `:"";for(let attempt=0;;attempt+=1){try{await writeFileAtomic(queuePath(globalPmRoot),contents);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 false}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};const serialized=JSON.stringify(pending);if(serialized.length>TELEMETRY_MAX_EVENT_BYTES){return}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("\n")){const trimmed=line.trim();if(trimmed.length===0){continue}try{const parsed=JSON.parse(trimmed);if(parsed&&typeof parsed==="object"&&typeof parsed.endpoint==="string"&&parsed.endpoint.trim().length>0&&"payload"in parsed&&typeof parsed.attempts==="number"&&Number.isFinite(parsed.attempts)){if(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 false}const enqueuedAtMs=Date.parse(entry.enqueued_at);if(Number.isNaN(enqueuedAtMs)){return false}return enqueuedAtMs<cutoffMs}function prunePendingOtelSpans(entries,retentionDays){const cutoffMs=retentionCutoffMs(retentionDays);const retained=[];let prunedCount=0;for(const entry of entries){const oversized=JSON.stringify(entry).length>TELEMETRY_MAX_EVENT_BYTES;if(oversized||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;prunedCount+=overflow;return{entries:retained.slice(overflow),prunedCount}}return{entries:retained,prunedCount}}async function rewritePendingOtelSpans(globalPmRoot,entries){const serialized=entries.map(entry=>JSON.stringify(entry)).join("\n");const contents=serialized.length>0?`${serialized}
5
+ `:"";for(let attempt=0;;attempt+=1){try{await writeFileAtomic(otelSpansQueuePath(globalPmRoot),contents);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));const current=raw===null?[]:parsePendingOtelSpanLines(raw);const 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);await rewritePendingOtelSpans(globalPmRoot,retained);return 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);const{entries:retained,prunedCount}=prunePendingOtelSpans(entries,retentionDays);const 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();const succeededIds=new Set;const failedUpdates=new Map;let succeededCount=0;let 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);const statePatch={pending_otel_spans:remaining,last_otel_attempt_at:attemptTime};if(succeededCount>0){statePatch.last_otel_success_at=attemptTime}if(lastError!==void 0){statePatch.last_otel_failure_at=attemptTime;statePatch.last_otel_failure_error=lastError}else if(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);const entries=await readdir(dirPath,{withFileTypes:true});const 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);const candidateStats=await stat(candidate);if(candidateStats.mtimeMs<cutoffMs){await rm(candidate,{force:true})}}))}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",false,false,waitMs);try{return await operation()}finally{await release()}}));_queueMutationPromise=run.catch(()=>{});return run}async function readCurrentQueueEntries(globalPmRoot){const raw=await readFileIfExists(queuePath(globalPmRoot));if(raw===null||raw.trim().length===0){return[]}return parseQueueLines(raw)}async function removeFlushedEntriesFromCurrentQueue(globalPmRoot,flushedIds,retentionDays){return withQueueMutation(async()=>{const currentEntries=await readCurrentQueueEntries(globalPmRoot);const{entries:retainedEntries}=pruneExpiredQueueEntries(currentEntries,retentionDays);const remaining=retainedEntries.filter(entry=>!flushedIds.has(entry.event.event_id));await rewriteQueue(globalPmRoot,remaining);return remaining},globalPmRoot)}async function markFailedEntriesInCurrentQueue(globalPmRoot,failedIds,attemptTime,retentionDays){return withQueueMutation(async()=>{const currentEntries=await readCurrentQueueEntries(globalPmRoot);const{entries:retainedEntries}=pruneExpiredQueueEntries(currentEntries,retentionDays);const 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)}});await rewriteQueue(globalPmRoot,retried);return 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));const attemptTime=nowIso();const requestHeaders={"content-type":"application/json"};const ingestKey=process.env.PM_TELEMETRY_INGEST_KEY?.trim();if(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);const errorMessage=(()=>{if(error instanceof Error){return sanitizeString(error.message,"redacted")}return"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=(()=>{if(error instanceof Error){return sanitizeString(error.message,"redacted")}return"telemetry_flush_failed"})();const 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);await mkdir(path.dirname(lockPath),{recursive:true});try{await mkdir(lockPath);return true}catch(error){if(typeof error!=="object"||error===null||!("code"in error)||error.code!=="EEXIST"){throw error}}try{const lockStats=await stat(lockPath);if(Date.now()-lockStats.mtimeMs<TELEMETRY_FLUSH_LOCK_STALE_MS){return false}await rm(lockPath,{recursive:true,force:true});await mkdir(lockPath);return true}catch{return false}}function isFreshDirectoryLock(lockPath,staleMs){try{return Date.now()-statSync(lockPath).mtimeMs<staleMs}catch{return false}}function removeDirectoryLockBestEffort(lockPath){try{rmSync(lockPath,{recursive:true,force:true})}catch{}}function errorCode(error){if(typeof error!=="object"||error===null||!("code"in error)){return void 0}const code=error.code;return typeof code==="string"?code:void 0}function createDirectoryLock(lockPath){try{mkdirSync(lockPath);return true}catch(error){const code=errorCode(error);if(code==="EEXIST"){return false}if(!isFileMissingError(error)){return false}}try{mkdirSync(path.dirname(lockPath),{recursive:true});mkdirSync(lockPath);return true}catch{return false}}function acquireTelemetryFlushSpawnGate(globalPmRoot){if(isFreshDirectoryLock(flushLockPath(globalPmRoot),TELEMETRY_FLUSH_LOCK_STALE_MS)){return false}const lockPath=flushSpawnLockPath(globalPmRoot);try{if(Date.now()-statSync(lockPath).mtimeMs<TELEMETRY_FLUSH_SPAWN_LOCK_STALE_MS){return false}removeDirectoryLockBestEffort(lockPath)}catch(error){if(!isFileMissingError(error)){return false}}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);releaseTelemetryFlushSpawnGate(globalPmRoot);if(!acquired){return}try{await flushTelemetryArtifacts(globalPmRoot,endpoint,retentionDays)}finally{try{await rm(flushLockPath(globalPmRoot),{recursive:true,force:true})}catch{}}}function scheduleTelemetryFlush(globalPmRoot,endpoint,retentionDays){if(shouldFlushInline()){const previousFlush=_lastFlushPromise;const nextFlush=flushTelemetryArtifacts(globalPmRoot,endpoint,retentionDays);_lastFlushPromise=Promise.allSettled([previousFlush,nextFlush]).then(()=>{});return}try{const acquiredSpawnGate=acquireTelemetryFlushSpawnGate(globalPmRoot);if(!acquiredSpawnGate){return}const child=spawn(process.execPath,[telemetryFlushRunnerPath()],{detached:true,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){return}try{const settings=await readSettings(globalPmRoot);if(!settings.telemetry.enabled){return}const installation=await withQueueMutation(()=>ensureInstallationId(globalPmRoot),globalPmRoot);if(!installation)return;await flushQueueWithProcessLock(globalPmRoot,installation.endpoint,installation.retentionDays)}catch{}}async function startTelemetryCommand(context){if(resolveTelemetryEnvironmentPolicy().telemetry_disabled){return null}if(context.command==="telemetry"&&context.args.some(token=>token.trim().toLowerCase()==="clear")){return null}try{const globalPmRoot=resolveGlobalPmRoot(process.cwd());const settings=await readSettings(globalPmRoot);if(!settings.telemetry.enabled){return null}const activeCommand=await withQueueMutation(async()=>{const installation=await ensureInstallationId(globalPmRoot);if(!installation)return null;const{installationId,endpoint,retentionDays,captureLevel}=installation;const pmVersion=normalizePmVersion(context.pm_version);const sourceContext=resolveTelemetrySourceContext(context.global);const pmRootHash=hashWithInstallationId(installationId,context.pm_root);const cwdHash=hashWithInstallationId(installationId,process.cwd());const otelTracesEndpoint=resolveOtelTracesEndpoint();const occurredAt=nowIso();const 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})};const sampleRate=resolveTelemetryReadSampleRate(context.command,context.global.noExtensions===true);if(sampleRate===1){await appendTelemetryEvent(globalPmRoot,event)}const commandTaxonomy=deriveTelemetryCommandTaxonomy(context.command);const 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};if(sampleRate<1)deferredReadStarts.set(active,event);return active},globalPmRoot,TELEMETRY_FOREGROUND_LOCK_WAIT_MS);if(activeCommand&&activeCommand.sample_rate===void 0){scheduleTelemetryFlush(globalPmRoot,activeCommand.endpoint,activeCommand.retention_days)}return activeCommand}catch{return null}}async function finishTelemetryCommand(activeCommand,outcome){if(!activeCommand||resolveTelemetryEnvironmentPolicy().telemetry_disabled){return}try{const captured=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){deferredReadStarts.delete(activeCommand);return false}const deferredStart=deferredReadStarts.get(activeCommand);const sampleRate=outcome.ok?activeCommand.sample_rate??1:1;if(deferredStart){deferredReadStarts.delete(activeCommand);if(crypto.randomBytes(6).readUIntBE(0,6)/2**48>=sampleRate)return false;deferredStart.payload.sample_rate=sampleRate;await appendTelemetryEvent(activeCommand.global_pm_root,deferredStart)}const finishedAt=nowIso();const durationMs=Math.max(0,Date.now()-activeCommand.started_at_ms);const normalizedErrorCode=normalizeTelemetryErrorCode(inferTelemetryErrorCode({ok:outcome.ok,errorCode:outcome.error_code,errorMessage:outcome.error,exitCode:outcome.exit_code}));const normalizedErrorCategory=normalizeTelemetryErrorCategory({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:outcome.error_category});const normalizedExitCode=normalizeTelemetryExitCode(outcome.exit_code,outcome.ok);const commandResolution=outcome.command_resolution??deriveTelemetryCommandResolution({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:normalizedErrorCategory});const resolutionStage=outcome.resolution_stage??"execute";const 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);if(otelRequest){await appendPendingOtelSpan(activeCommand.global_pm_root,otelRequest)}return true},activeCommand.global_pm_root,TELEMETRY_FOREGROUND_LOCK_WAIT_MS);if(!captured)return;scheduleTelemetryFlush(activeCommand.global_pm_root,activeCommand.endpoint,activeCommand.retention_days)}catch{}}async function emitTelemetryErrorEvent(context){if(resolveTelemetryEnvironmentPolicy().telemetry_disabled){return}try{const globalPmRoot=resolveGlobalPmRoot(process.cwd());const settings=await readSettings(globalPmRoot);if(!settings.telemetry.enabled){return}const captured=await withQueueMutation(async()=>{const installation=await ensureInstallationId(globalPmRoot);if(!installation)return null;const{installationId,captureLevel}=installation;const pmVersion=normalizePmVersion(context.pm_version);const sourceContext=resolveTelemetrySourceContext(context.global);const pmRootHash=hashWithInstallationId(installationId,context.pm_root);const cwdHash=hashWithInstallationId(installationId,process.cwd());const occurredAt=nowIso();const normalizedErrorCode=normalizeTelemetryErrorCode(inferTelemetryErrorCode({ok:false,errorCode:context.error_code,errorMessage:context.error_message,exitCode:context.exit_code}));const normalizedErrorCategory=context.error_category??resolveTelemetryErrorCategory(normalizedErrorCode);const normalizedExitCode=normalizeTelemetryExitCode(context.exit_code,false);const normalizedCommand=context.command.trim().length>0?context.command:"<unknown>";const commandTaxonomy=deriveTelemetryCommandTaxonomy(normalizedCommand);const commandResolution=context.command_resolution??deriveTelemetryCommandResolution({ok:false,errorCode:normalizedErrorCode,errorCategory:normalizedErrorCategory});const resolutionStage=context.resolution_stage??"unknown";const 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})};await appendTelemetryEvent(globalPmRoot,event);return installation},globalPmRoot,TELEMETRY_FOREGROUND_LOCK_WAIT_MS);if(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};
5
6
  //# sourceMappingURL=runtime.js.map
@@ -2,3 +2,9 @@
2
2
  export declare function scoreCommandPathMatch(commandPath: string, queryToken: string): number;
3
3
  /** Rank available command paths for one guessed token. */
4
4
  export declare function rankCommandPaths(commandPaths: string[], queryToken: string): string[];
5
+ /**
6
+ * Replace migration-only prefixes with installed canonical paths and required flags.
7
+ * A query token prefers known semantic matches over weaker spelling guesses after
8
+ * unavailable replacements have been removed.
9
+ */
10
+ export declare function canonicalizeCommandSuggestions(candidates: readonly string[], availablePaths: readonly string[], queryToken?: string): string[];
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="54cfd2e9-acc0-5d3b-b763-b89b6ac637ed")}catch(e2){}})();import{levenshteinDistanceWithinLimit}from"../../core/shared/levenshtein.js";import{resolvePmCommandOperation}from"../cli-contracts/command-aliases.js";const COMMAND_SYNONYMS={add:["create","append"],fetch:["get"],inspect:["get","health"],log:["history","comments","notes"],ls:["list"],pause:["release"],read:["get"],remove:["delete"],rm:["delete"],show:["get"]};function scoreCommandPathMatch(commandPath,queryToken){const normalizedPath=commandPath.trim().toLowerCase();const normalizedToken=queryToken.trim().toLowerCase();if(normalizedToken.length===0)return Number.POSITIVE_INFINITY;const segments=normalizedPath.split(" ");const semanticIndex=COMMAND_SYNONYMS[normalizedToken]?.indexOf(resolvePmCommandOperation(normalizedPath));if(semanticIndex!==void 0&&semanticIndex>=0)return semanticIndex;if(normalizedPath===normalizedToken)return 10;if(segments.includes(normalizedToken))return 11;if(segments.some(segment=>segment.startsWith(normalizedToken)))return 12;const maxDistance=normalizedToken.length>=5?2:1;let bestDistance=Number.POSITIVE_INFINITY;for(const segment of segments){const distance=levenshteinDistanceWithinLimit(segment,normalizedToken,maxDistance);if(distance!==null)bestDistance=Math.min(bestDistance,distance)}if(Number.isFinite(bestDistance))return 20+bestDistance;if(normalizedPath.includes(normalizedToken))return 30;return Number.POSITIVE_INFINITY}function rankCommandPaths(commandPaths,queryToken){return commandPaths.map(path=>({path,score:scoreCommandPathMatch(path,queryToken)})).filter(entry=>Number.isFinite(entry.score)).sort((left,right)=>{if(left.score!==right.score)return left.score-right.score;if(left.path===right.path)return 0;return left.path<right.path?-1:1}).map(entry=>entry.path)}export{rankCommandPaths,scoreCommandPathMatch};
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="925e5fec-4cc0-5315-a331-03cb128893f0")}catch(e2){}})();import{levenshteinDistanceWithinLimit}from"../../core/shared/levenshtein.js";import{PM_COMMAND_ALIAS_CONTRACTS,resolvePmCommandOperation}from"../cli-contracts/command-aliases.js";const COMMAND_SYNONYMS={add:["create","append"],fetch:["get"],inspect:["get","health"],log:["history","comments","notes"],ls:["list"],pause:["release"],read:["get"],remove:["delete"],rm:["delete"],show:["get"],start:["start-task"]};function scoreCommandPathMatch(commandPath,queryToken){const normalizedPath=commandPath.trim().toLowerCase();const normalizedToken=queryToken.trim().toLowerCase();if(normalizedToken.length===0)return Number.POSITIVE_INFINITY;const segments=normalizedPath.split(" ");const semanticIndex=COMMAND_SYNONYMS[normalizedToken]?.indexOf(resolvePmCommandOperation(normalizedPath));if(semanticIndex!==void 0&&semanticIndex>=0)return semanticIndex;if(normalizedPath===normalizedToken)return 10;if(segments.includes(normalizedToken))return 11;if(segments.some(segment=>segment.startsWith(normalizedToken)))return 12;const maxDistance=normalizedToken.length>=5?2:1;let bestDistance=Number.POSITIVE_INFINITY;for(const segment of segments){const distance=levenshteinDistanceWithinLimit(segment,normalizedToken,maxDistance);if(distance!==null)bestDistance=Math.min(bestDistance,distance)}if(Number.isFinite(bestDistance))return 20+bestDistance;if(normalizedPath.includes(normalizedToken))return 30;return Number.POSITIVE_INFINITY}function rankCommandPaths(commandPaths,queryToken){return commandPaths.map(path=>({path,score:scoreCommandPathMatch(path,queryToken)})).filter(entry=>Number.isFinite(entry.score)).sort((left,right)=>{if(left.score!==right.score)return left.score-right.score;if(left.path===right.path)return 0;return left.path<right.path?-1:1}).map(entry=>entry.path)}function canonicalizeCommandSuggestions(candidates,availablePaths,queryToken){const available=new Set(availablePaths);const aliases=PM_COMMAND_ALIAS_CONTRACTS.filter(alias=>alias.lifecycle==="deprecated").slice().sort((left,right)=>right.alias.length-left.alias.length);const preferred=[];const resolved=candidates.flatMap(candidate=>{const alias=aliases.find(entry=>candidate===entry.alias||candidate.startsWith(`${entry.alias} `));let canonical=candidate;if(alias){const suffix=candidate.slice(alias.alias.length);if(!available.has(`${alias.canonical}${suffix}`))return[];canonical=`${alias.canonical_argv.join(" ")}${suffix}`}if(queryToken!==void 0&&scoreCommandPathMatch(candidate,queryToken)<10)preferred.push(canonical);return[canonical]});return[...new Set(preferred.length>0?preferred:resolved)]}export{canonicalizeCommandSuggestions,rankCommandPaths,scoreCommandPathMatch};
2
2
  //# sourceMappingURL=command-suggestions.js.map
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f9a3ff17-949b-55e0-a2ec-18870aa52197")}catch(e2){}})();const PM_HISTORY_COMMAND_ALIASES=[["history-redact","history redact"],["history-repair","history repair"],["history-compact","history compact"],["activity","history activity"],["restore","history restore"]].map(([alias,canonical])=>({alias,canonical,canonical_argv:canonical.split(" "),lifecycle:"permanent",hidden:true,registration:"commander",owner:"pm-tqel"}));const PM_CONTEXT_OPS_COMMAND_ALIASES=[...["next","focus"].map(alias=>({alias,canonical:`context ${alias}`,owner:"pm-kcs4"})),...["stats","health","validate","gc","telemetry","eval","test-all"].map(alias=>({alias,canonical:`ops ${alias}`,owner:"pm-6apl"})),...["normalize","reindex"].map(alias=>({alias,canonical:`ops ${alias}`,owner:"pm-3i9q8g"})),{alias:"events",canonical:"history events",owner:"pm-3i9q8g"}].map(entry=>({...entry,canonical_argv:entry.canonical.split(" "),lifecycle:"permanent",hidden:true,registration:"bootstrap"}));const PM_BULK_LIFECYCLE_COMMAND_ALIASES=[["update-many","update many"],["close-many","close many"],["delete","close delete"]].map(([alias,canonical])=>({alias,canonical,canonical_argv:canonical.split(" "),lifecycle:"permanent",hidden:true,registration:"bootstrap",owner:"pm-ik19"}));const PM_RELOCATED_COMMAND_ALIASES=[...PM_CONTEXT_OPS_COMMAND_ALIASES,...PM_BULK_LIFECYCLE_COMMAND_ALIASES,...[...["comments","notes","learnings","files","docs","deps","append","test"].map(facet=>[facet,`item ${facet}`,"pm-yql1"]),["test-runs-worker","item test worker","pm-lp4j"],...["statuses","tags","types"].map(facet=>[`completion-${facet}`,`completion ${facet}`,"pm-szdc"]),["copy","item copy","pm-m6g87m"],["merge","workspace merge","pm-m6g87m"],["duplicates","item duplicates","pm-fmy9ih"],["dedupe-audit","item duplicates audit","pm-fmy9ih"],["dedupe-merge","item duplicates merge","pm-fmy9ih"],["comments-audit","item audit-comments","pm-fmy9ih"],["search-advanced","search advanced","pm-wfskfn"]].map(([alias,canonical,owner])=>({alias,canonical,canonical_argv:canonical.split(" "),lifecycle:"permanent",hidden:true,registration:"bootstrap",owner}))];const PM_NAMESPACED_COMMAND_ALIASES=[{alias:"history-attest",canonical:"history attest",canonical_argv:["history","attest"],lifecycle:"permanent",hidden:true,registration:"commander",owner:"pm-3z0k"},...PM_HISTORY_COMMAND_ALIASES,...PM_RELOCATED_COMMAND_ALIASES,...["discover","lookup"].map(action=>({alias:`files ${action}`,canonical:`item files ${action}`,canonical_argv:["item","files",action],lifecycle:"permanent",hidden:true,registration:"bootstrap",owner:"pm-yql1"}))];function findPmNamespacedCommand(tokens){let matched;for(const alias of PM_NAMESPACED_COMMAND_ALIASES){if(alias.canonical_argv.length<=(matched?.canonical_argv.length??0))continue;if(alias.canonical_argv.every((token,index)=>token===(index===0&&tokens[index]==="ctx"?"context":tokens[index])))matched=alias}return matched}function resolvePmCommandOperation(command){const normalized=command.trim().replace(/\s+/gu," ");return PM_NAMESPACED_COMMAND_ALIASES.find(alias=>alias.canonical===normalized.replace(/^ctx /u,"context "))?.alias??normalized}function resolvePmHistoryOperation(command){return resolvePmCommandOperation(command)}const PM_COMMAND_ALIAS_CONTRACTS=[...PM_NAMESPACED_COMMAND_ALIASES,...[["start-task","claim","--start"],["pause-task","release","--pause"],["close-task","close","--release-assignment"]].map(([alias,canonical,flag])=>({alias,canonical,canonical_argv:[canonical,flag],lifecycle:"deprecated",hidden:true,registration:"commander",owner:"pm-eq4x"})),{alias:"tests",canonical:"item test",canonical_argv:["item","test"],lifecycle:"permanent",hidden:false,registration:"bootstrap",owner:"pm-u4t9gp"},...[["fetch","get"],["read","get"],["show","get"],["view","get"],["comment","comments"],["note","notes"],["learning","learnings"]].map(([alias,canonical])=>({alias,canonical:["comments","notes","learnings"].includes(canonical)?`item ${canonical}`:canonical,canonical_argv:["comments","notes","learnings"].includes(canonical)?["item",canonical]:[canonical],lifecycle:"permanent",hidden:false,registration:"bootstrap",owner:"pm-pbyu"})),...[["extension list","extension catalog"],["extension scaffold","extension init"],["package list","package catalog"],["package scaffold","package init"],["packages list","packages catalog"],["packages scaffold","packages init"]].map(([alias,canonical])=>({alias,canonical,canonical_argv:canonical.split(" "),lifecycle:"permanent",hidden:false,registration:"commander",owner:"pm-ya7x55"})),{alias:"list-all",canonical:"list",canonical_argv:["list","--all"],lifecycle:"deprecated",hidden:true,registration:"commander",owner:"pm-pfqi"},...[["list-draft","draft"],["list-open","open"],["list-in-progress","in_progress"],["list-blocked","blocked"],["list-closed","closed"],["list-canceled","canceled"]].map(([alias,status])=>({alias,canonical:"list",canonical_argv:["list","--status",status],lifecycle:"deprecated",hidden:true,registration:"commander",owner:"pm-pfqi"})),...[["extension","package"],["install","package install"],["upgrade","package upgrade"]].map(([alias,canonical])=>({alias,canonical,canonical_argv:canonical.split(" "),lifecycle:"deprecated",hidden:true,registration:"commander",owner:"pm-tnud"}))];const EXECUTABLE_COMMAND_ALIASES=Object.fromEntries(PM_COMMAND_ALIAS_CONTRACTS.filter(contract=>contract.registration==="bootstrap").map(contract=>[contract.alias,contract.canonical]));function resolvePmCommandAlias(alias){const normalized=alias.trim().toLowerCase();return PM_COMMAND_ALIAS_CONTRACTS.find(contract=>contract.alias===normalized)}function renderPmCommandAliasMigrationHint(contract){return`Deprecated command \`${contract.alias}\`; use \`pm ${contract.canonical_argv.join(" ")}\`.`}export{EXECUTABLE_COMMAND_ALIASES,PM_BULK_LIFECYCLE_COMMAND_ALIASES,PM_COMMAND_ALIAS_CONTRACTS,PM_CONTEXT_OPS_COMMAND_ALIASES,PM_HISTORY_COMMAND_ALIASES,PM_NAMESPACED_COMMAND_ALIASES,PM_RELOCATED_COMMAND_ALIASES,findPmNamespacedCommand,renderPmCommandAliasMigrationHint,resolvePmCommandAlias,resolvePmCommandOperation,resolvePmHistoryOperation};
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4f0a2e76-6e07-579b-9d9b-1abbe7e5019b")}catch(e2){}})();const PM_HISTORY_COMMAND_ALIASES=[["history-redact","history redact"],["history-repair","history repair"],["history-compact","history compact"],["activity","history activity"],["restore","history restore"]].map(([alias,canonical])=>({alias,canonical,canonical_argv:canonical.split(" "),lifecycle:"permanent",hidden:true,registration:"commander",owner:"pm-tqel"}));const PM_CONTEXT_OPS_COMMAND_ALIASES=[...["next","focus"].map(alias=>({alias,canonical:`context ${alias}`,owner:"pm-kcs4"})),...["stats","health","validate","gc","telemetry","eval","test-all"].map(alias=>({alias,canonical:`ops ${alias}`,owner:"pm-6apl"})),...["normalize","reindex"].map(alias=>({alias,canonical:`ops ${alias}`,owner:"pm-3i9q8g"})),{alias:"events",canonical:"history events",owner:"pm-3i9q8g"}].map(entry=>({...entry,canonical_argv:entry.canonical.split(" "),lifecycle:"permanent",hidden:true,registration:"bootstrap"}));const PM_BULK_LIFECYCLE_COMMAND_ALIASES=[["update-many","update many"],["close-many","close many"],["delete","close delete"]].map(([alias,canonical])=>({alias,canonical,canonical_argv:canonical.split(" "),lifecycle:"permanent",hidden:true,registration:"bootstrap",owner:"pm-ik19"}));const PM_RELOCATED_COMMAND_ALIASES=[...PM_CONTEXT_OPS_COMMAND_ALIASES,...PM_BULK_LIFECYCLE_COMMAND_ALIASES,...[...["comments","notes","learnings","files","docs","deps","append","test"].map(facet=>[facet,`item ${facet}`,"pm-yql1"]),["test-runs-worker","item test worker","pm-lp4j"],...["statuses","tags","types"].map(facet=>[`completion-${facet}`,`completion ${facet}`,"pm-szdc"]),["history-author-acknowledge","history acknowledge","pm-djyvbk"],["copy","item copy","pm-m6g87m"],["merge","workspace merge","pm-m6g87m"],["duplicates","item duplicates","pm-fmy9ih"],["dedupe-audit","item duplicates audit","pm-fmy9ih"],["dedupe-merge","item duplicates merge","pm-fmy9ih"],["comments-audit","item audit-comments","pm-fmy9ih"],["search-advanced","search advanced","pm-wfskfn"]].map(([alias,canonical,owner])=>({alias,canonical,canonical_argv:canonical.split(" "),lifecycle:"permanent",hidden:true,registration:"bootstrap",owner}))];const PM_NAMESPACED_COMMAND_ALIASES=[{alias:"history-attest",canonical:"history attest",canonical_argv:["history","attest"],lifecycle:"permanent",hidden:true,registration:"commander",owner:"pm-3z0k"},...PM_HISTORY_COMMAND_ALIASES,...PM_RELOCATED_COMMAND_ALIASES,...["discover","lookup"].map(action=>({alias:`files ${action}`,canonical:`item files ${action}`,canonical_argv:["item","files",action],lifecycle:"permanent",hidden:true,registration:"bootstrap",owner:"pm-yql1"}))];function findPmNamespacedCommand(tokens){let matched;for(const alias of PM_NAMESPACED_COMMAND_ALIASES){if(alias.canonical_argv.length<=(matched?.canonical_argv.length??0))continue;if(alias.canonical_argv.every((token,index)=>token===(index===0&&tokens[index]==="ctx"?"context":tokens[index])))matched=alias}return matched}function resolvePmCommandOperation(command){const normalized=command.trim().replace(/\s+/gu," ");return PM_NAMESPACED_COMMAND_ALIASES.find(alias=>alias.canonical===normalized.replace(/^ctx /u,"context "))?.alias??normalized}function resolvePmHistoryOperation(command){return resolvePmCommandOperation(command)}const PM_COMMAND_ALIAS_CONTRACTS=[...PM_NAMESPACED_COMMAND_ALIASES,...[["ctx","context"],["packages","package"]].map(([alias,canonical])=>({alias,canonical,canonical_argv:[canonical],lifecycle:"permanent",hidden:false,registration:"commander",owner:"pm-pbyu"})),...[["start-task","claim","--start"],["pause-task","release","--pause"],["close-task","close","--release-assignment"]].map(([alias,canonical,flag])=>({alias,canonical,canonical_argv:[canonical,flag],lifecycle:"deprecated",hidden:true,registration:"commander",owner:"pm-eq4x"})),{alias:"tests",canonical:"item test",canonical_argv:["item","test"],lifecycle:"permanent",hidden:false,registration:"bootstrap",owner:"pm-u4t9gp"},...[["fetch","get"],["read","get"],["show","get"],["view","get"],["comment","comments"],["note","notes"],["learning","learnings"]].map(([alias,canonical])=>({alias,canonical:["comments","notes","learnings"].includes(canonical)?`item ${canonical}`:canonical,canonical_argv:["comments","notes","learnings"].includes(canonical)?["item",canonical]:[canonical],lifecycle:"permanent",hidden:false,registration:"bootstrap",owner:"pm-pbyu"})),...[["extension list","extension catalog"],["extension scaffold","extension init"],["package list","package catalog"],["package scaffold","package init"],["packages list","packages catalog"],["packages scaffold","packages init"]].map(([alias,canonical])=>({alias,canonical,canonical_argv:canonical.split(" "),lifecycle:"permanent",hidden:false,registration:"commander",owner:"pm-ya7x55"})),{alias:"list-all",canonical:"list",canonical_argv:["list","--all"],lifecycle:"deprecated",hidden:true,registration:"commander",owner:"pm-pfqi"},...[["list-draft","draft"],["list-open","open"],["list-in-progress","in_progress"],["list-blocked","blocked"],["list-closed","closed"],["list-canceled","canceled"]].map(([alias,status])=>({alias,canonical:"list",canonical_argv:["list","--status",status],lifecycle:"deprecated",hidden:true,registration:"commander",owner:"pm-pfqi"})),...[["extension","package"],["install","package install"],["upgrade","package upgrade"]].map(([alias,canonical])=>({alias,canonical,canonical_argv:canonical.split(" "),lifecycle:"deprecated",hidden:true,registration:"commander",owner:"pm-tnud"}))];const EXECUTABLE_COMMAND_ALIASES=Object.fromEntries(PM_COMMAND_ALIAS_CONTRACTS.filter(contract=>contract.registration==="bootstrap").map(contract=>[contract.alias,contract.canonical]));function resolvePmCommandAlias(alias){const normalized=alias.trim().toLowerCase();return PM_COMMAND_ALIAS_CONTRACTS.find(contract=>contract.alias===normalized)}function renderPmCommandAliasMigrationHint(contract){return`Deprecated command \`${contract.alias}\`; use \`pm ${contract.canonical_argv.join(" ")}\`.`}export{EXECUTABLE_COMMAND_ALIASES,PM_BULK_LIFECYCLE_COMMAND_ALIASES,PM_COMMAND_ALIAS_CONTRACTS,PM_CONTEXT_OPS_COMMAND_ALIASES,PM_HISTORY_COMMAND_ALIASES,PM_NAMESPACED_COMMAND_ALIASES,PM_RELOCATED_COMMAND_ALIASES,findPmNamespacedCommand,renderPmCommandAliasMigrationHint,resolvePmCommandAlias,resolvePmCommandOperation,resolvePmHistoryOperation};
2
2
  //# sourceMappingURL=command-aliases.js.map
@@ -10,7 +10,7 @@ import { type PmCommandAliasContract } from "./command-aliases.js";
10
10
  /** Canonical top-level domains an agent must retain to route pm operations. */
11
11
  export declare const PM_CLI_GRAMMAR_NOUNS: readonly ["item", "list", "context", "search", "graph", "history", "workspace", "package", "ops", "plan", "contracts", "help"];
12
12
  /** Shared verbs whose meaning transfers across domain nouns. */
13
- export declare const PM_CLI_SHARED_VERBS: readonly ["activate", "add", "adopt", "adopt-all", "catalog", "compact", "complete", "create", "deactivate", "delete", "describe", "doctor", "edit", "explore", "import", "init", "inspect", "install", "list", "manage", "migrate", "mutate", "read", "redact", "reload", "remove", "reopen", "repair", "restore", "run", "show", "uninstall", "upgrade", "verify"];
13
+ export declare const PM_CLI_SHARED_VERBS: readonly ["acknowledge", "activate", "add", "adopt", "adopt-all", "catalog", "compact", "complete", "create", "deactivate", "delete", "describe", "doctor", "edit", "explore", "import", "init", "inspect", "install", "list", "manage", "migrate", "mutate", "read", "redact", "reload", "remove", "reopen", "repair", "restore", "run", "show", "uninstall", "upgrade", "verify"];
14
14
  /** Why a current command is permitted while the grammar migration proceeds. */
15
15
  export type PmCommandDestinationDisposition = "target_noun" | "consolidation" | "package_owned" | "keep_as_is";
16
16
  /** Exact destination decision for one command emitted by runtime contracts. */
@@ -78,7 +78,7 @@ export declare const PM_COMMAND_POSITIONAL_CONTRACTS: readonly PmCommandPosition
78
78
  /** Immutable grammar policy used by contracts and the CI gate. */
79
79
  export declare const PM_CLI_GRAMMAR_CONTRACT: {
80
80
  readonly nouns: readonly ["item", "list", "context", "search", "graph", "history", "workspace", "package", "ops", "plan", "contracts", "help"];
81
- readonly shared_verbs: readonly ["activate", "add", "adopt", "adopt-all", "catalog", "compact", "complete", "create", "deactivate", "delete", "describe", "doctor", "edit", "explore", "import", "init", "inspect", "install", "list", "manage", "migrate", "mutate", "read", "redact", "reload", "remove", "reopen", "repair", "restore", "run", "show", "uninstall", "upgrade", "verify"];
81
+ readonly shared_verbs: readonly ["acknowledge", "activate", "add", "adopt", "adopt-all", "catalog", "compact", "complete", "create", "deactivate", "delete", "describe", "doctor", "edit", "explore", "import", "init", "inspect", "install", "list", "manage", "migrate", "mutate", "read", "redact", "reload", "remove", "reopen", "repair", "restore", "run", "show", "uninstall", "upgrade", "verify"];
82
82
  readonly scope_before_verb: true;
83
83
  readonly visible_top_level_ceiling: 69;
84
84
  readonly ceiling_raise_requires_pm_item: true;