@unbrained/pm-cli 2026.11.1 → 2026.11.2

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 (146) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +18 -0
  3. package/CONTRIBUTING.md +1 -1
  4. package/dist/cli/migration-gates.js +1 -1
  5. package/dist/cli-bundle/bundle-manifest.json +1 -1
  6. package/dist/cli-bundle/chunks/{chunk-TMPO4CTZ.js → chunk-3A4NVHYS.js} +2 -2
  7. package/dist/cli-bundle/chunks/{chunk-UUN3WNMQ.js → chunk-3ZQQVJT2.js} +3 -3
  8. package/dist/cli-bundle/chunks/{chunk-TYERATXH.js → chunk-4HW253W2.js} +2 -2
  9. package/dist/cli-bundle/chunks/{chunk-F3ECOBKA.js → chunk-4OELCF3O.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-2GK2IVU5.js → chunk-533L6D2N.js} +3 -3
  11. package/dist/cli-bundle/chunks/{chunk-NILQ2ZMV.js → chunk-ABFFRQRO.js} +2 -2
  12. package/dist/cli-bundle/chunks/chunk-BFZUJ5QP.js +115 -0
  13. package/dist/cli-bundle/chunks/{chunk-SBVX5CMV.js → chunk-D52QQ7LP.js} +2 -2
  14. package/dist/cli-bundle/chunks/{chunk-WFBYKDB2.js → chunk-DAZFCSDV.js} +2 -2
  15. package/dist/cli-bundle/chunks/{chunk-ICT6E4IW.js → chunk-EN27ZQSV.js} +2 -2
  16. package/dist/cli-bundle/chunks/{chunk-MRUA2Z43.js → chunk-GK2CHAT3.js} +2 -2
  17. package/dist/cli-bundle/chunks/{chunk-MTRIGD7M.js → chunk-HOGKWJU5.js} +42 -42
  18. package/dist/cli-bundle/chunks/{chunk-WX25MU4N.js → chunk-J3JM36EH.js} +3 -3
  19. package/dist/cli-bundle/chunks/{chunk-O56O7NIE.js → chunk-JRXD7SIL.js} +2 -2
  20. package/dist/cli-bundle/chunks/{chunk-5KW4WUAK.js → chunk-K46GDAKX.js} +2 -2
  21. package/dist/cli-bundle/chunks/{chunk-N45IXPCA.js → chunk-KJLGBLR3.js} +2 -2
  22. package/dist/cli-bundle/chunks/{chunk-UEEG47TU.js → chunk-NGRPD3ZO.js} +2 -2
  23. package/dist/cli-bundle/chunks/chunk-OJR2YGXF.js +31 -0
  24. package/dist/cli-bundle/chunks/chunk-QHHFXNSQ.js +3 -0
  25. package/dist/cli-bundle/chunks/{chunk-Y7CKVU56.js → chunk-RGHLQGEX.js} +2 -2
  26. package/dist/cli-bundle/chunks/{chunk-6PKWKVS6.js → chunk-VEOFWE32.js} +2 -2
  27. package/dist/cli-bundle/chunks/chunk-ZNWDYDFF.js +129 -0
  28. package/dist/cli-bundle/chunks/{indexed-receipt-blobs-KGMJVFH2.js → indexed-receipt-blobs-IEJ2QOW3.js} +2 -2
  29. package/dist/cli-bundle/chunks/item-transaction-JHPBH6N7.js +2 -0
  30. package/dist/cli-bundle/chunks/{mutation-admission-BOOCJPCU.js → mutation-admission-QUNQZCZ5.js} +2 -2
  31. package/dist/cli-bundle/chunks/{register-list-query-23OX36Q3.js → register-list-query-NZTK3AXA.js} +2 -2
  32. package/dist/cli-bundle/chunks/{register-mutation-JPJ5YNDX.js → register-mutation-2OFAMOVH.js} +2 -2
  33. package/dist/cli-bundle/chunks/{register-operations-IGR7ERY5.js → register-operations-RFMM5KZ6.js} +2 -2
  34. package/dist/cli-bundle/chunks/{register-setup-BMIFKZZP.js → register-setup-6B6Q7M5L.js} +2 -2
  35. package/dist/cli-bundle/chunks/{settlement-hook-YWSWFOZY.js → settlement-hook-UTCEZBFT.js} +2 -2
  36. package/dist/cli-bundle/chunks/{stage-ON7CYYPM.js → stage-VLI4OBVX.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/{chunk-5TWS5KOM.js → chunk-3UD6F2KQ.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/{chunk-5WCQFH6D.js → chunk-4NVPDZLX.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/{chunk-PAT6QF63.js → chunk-4UUE3YXZ.js} +2 -2
  40. package/dist/cli-bundle/focused-chunks/{chunk-2Y77HWIX.js → chunk-5UDDRPYR.js} +2 -2
  41. package/dist/cli-bundle/focused-chunks/{chunk-RPUDOJVB.js → chunk-745IDMTD.js} +2 -2
  42. package/dist/cli-bundle/focused-chunks/{chunk-3NYWMUX3.js → chunk-B6OOKKOX.js} +3 -3
  43. package/dist/cli-bundle/focused-chunks/{chunk-JCR32IAO.js → chunk-EJJWOFP5.js} +2 -2
  44. package/dist/cli-bundle/focused-chunks/chunk-FUGYXUUL.js +80 -0
  45. package/dist/cli-bundle/focused-chunks/{chunk-Z7GIVH6B.js → chunk-HMXVTWIV.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/{chunk-UQIBGLDR.js → chunk-I4Z2SCV5.js} +2 -2
  47. package/dist/cli-bundle/focused-chunks/chunk-JLN5CFYM.js +2 -0
  48. package/dist/cli-bundle/focused-chunks/chunk-K4FMZB4Y.js +23 -0
  49. package/dist/cli-bundle/focused-chunks/{chunk-DFUTCKUF.js → chunk-MQVBWFJF.js} +2 -2
  50. package/dist/cli-bundle/focused-chunks/{chunk-6GMYW42K.js → chunk-NJFMG3IK.js} +2 -2
  51. package/dist/cli-bundle/focused-chunks/{chunk-6OKPYCLU.js → chunk-PCCZ72C3.js} +54 -54
  52. package/dist/cli-bundle/focused-chunks/chunk-PF553UVP.js +44 -0
  53. package/dist/cli-bundle/focused-chunks/{chunk-VFQAZLKO.js → chunk-Q23K6WLV.js} +2 -2
  54. package/dist/cli-bundle/focused-chunks/{chunk-LVA76N27.js → chunk-QNXXOFLQ.js} +2 -2
  55. package/dist/cli-bundle/focused-chunks/{chunk-JLXGRDTG.js → chunk-QVFE5LIX.js} +3 -3
  56. package/dist/cli-bundle/focused-chunks/{chunk-VS2ZFPXD.js → chunk-RUCG6UWN.js} +2 -2
  57. package/dist/cli-bundle/focused-chunks/{chunk-WX2RVS2Y.js → chunk-SGWYNU7T.js} +2 -2
  58. package/dist/cli-bundle/focused-chunks/chunk-TGS5RXBY.js +26 -0
  59. package/dist/cli-bundle/focused-chunks/{chunk-AL7SOFUL.js → chunk-WD43E7RU.js} +2 -2
  60. package/dist/cli-bundle/focused-chunks/{chunk-GE755ODZ.js → chunk-YM4AMP7H.js} +2 -2
  61. package/dist/cli-bundle/focused-chunks/{indexed-receipt-blobs-KHWT44EK.js → indexed-receipt-blobs-FT3KF6VJ.js} +2 -2
  62. package/dist/cli-bundle/focused-chunks/{item-transaction-7VLPA2SU.js → item-transaction-F4SN7TXJ.js} +2 -2
  63. package/dist/cli-bundle/focused-chunks/{mutation-admission-2DH27R5Y.js → mutation-admission-7R2FXJ5O.js} +2 -2
  64. package/dist/cli-bundle/focused-chunks/{settlement-hook-SJV52ZTV.js → settlement-hook-KMIBD4F2.js} +2 -2
  65. package/dist/cli-bundle/focused-chunks/{stage-FYOBWQA7.js → stage-6B3O2GZ6.js} +2 -2
  66. package/dist/cli-bundle/main.js +24 -24
  67. package/dist/cli-bundle/sdk-authoring.js +1 -1
  68. package/dist/cli-bundle/sdk-contracts.js +1 -1
  69. package/dist/cli-bundle/sdk-core.js +1 -1
  70. package/dist/cli-bundle/sdk-governance.js +1 -1
  71. package/dist/cli-bundle/sdk-graph.js +1 -1
  72. package/dist/cli-bundle/sdk-merge.js +57 -57
  73. package/dist/cli-bundle/sdk-query.js +1 -1
  74. package/dist/cli-bundle/sdk-runtime.js +1 -1
  75. package/dist/cli-bundle/sdk-testing.js +1 -1
  76. package/dist/cli-bundle/sdk.js +9 -9
  77. package/dist/core/extensions/extension-types.d.ts +5 -0
  78. package/dist/core/extensions/extension-types.js +1 -1
  79. package/dist/core/item/parse.js +2 -2
  80. package/dist/core/lock/lock-confinement.d.ts +55 -0
  81. package/dist/core/lock/lock-confinement.js +2 -0
  82. package/dist/core/lock/lock-gc.js +1 -1
  83. package/dist/core/lock/lock.js +2 -2
  84. package/dist/core/shared/errors.d.ts +6 -0
  85. package/dist/core/shared/errors.js +1 -1
  86. package/dist/core/store/settings-sections.d.ts +61 -0
  87. package/dist/core/store/settings-sections.js +3 -0
  88. package/dist/core/store/settings-validator.d.ts +4 -0
  89. package/dist/core/store/settings-validator.js +1 -1
  90. package/dist/core/store/settings.d.ts +29 -2
  91. package/dist/core/store/settings.js +4 -3
  92. package/dist/core/telemetry/consent.js +2 -2
  93. package/dist/core/telemetry/runtime.js +2 -2
  94. package/dist/core/test/background-runs.js +3 -3
  95. package/dist/sdk/config.js +1 -1
  96. package/dist/sdk/extension-command-context.js +2 -2
  97. package/dist/sdk/generated/error-code-catalog-rows.d.ts +39 -0
  98. package/dist/sdk/generated/error-code-catalog-rows.js +2 -0
  99. package/dist/sdk/generated/generated-error-code-catalog-part-1.d.ts +3 -3
  100. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
  101. package/dist/sdk/generated/generated-error-code-catalog-part-2.d.ts +3 -3
  102. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
  103. package/dist/sdk/generated-error-code-catalog.js +1 -1
  104. package/dist/sdk/mcp/discovery.js +1 -1
  105. package/dist/sdk/public-surface.json +1 -1
  106. package/dist/sdk/runtime-primitives.d.ts +2 -1
  107. package/dist/sdk/runtime-primitives.js +1 -1
  108. package/docs/AGENT_EVIDENCE_CONSISTENCY.md +10 -0
  109. package/docs/CONFIGURATION.md +9 -0
  110. package/docs/DEVELOPMENT_DEPENDENCY_SECURITY.md +9 -6
  111. package/docs/RELEASING.md +22 -2
  112. package/docs/SDK.md +28 -1
  113. package/docs/SDK_CONFIGURATION_SAFETY.md +55 -0
  114. package/docs/TESTING.md +2 -1
  115. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +12 -3
  116. package/marketplace.json +1 -1
  117. package/package.json +9 -3
  118. package/packages/pm-beads/package.json +1 -1
  119. package/packages/pm-calendar/package.json +1 -1
  120. package/packages/pm-command-kit/package.json +1 -1
  121. package/packages/pm-digital-twin/package.json +1 -1
  122. package/packages/pm-governance-audit/package.json +1 -1
  123. package/packages/pm-guide-shell/package.json +1 -1
  124. package/packages/pm-kanban/package.json +1 -1
  125. package/packages/pm-lifecycle-hooks/package.json +1 -1
  126. package/packages/pm-linked-test-adapters/package.json +1 -1
  127. package/packages/pm-search-advanced/package.json +1 -1
  128. package/packages/pm-templates/package.json +1 -1
  129. package/packages/pm-todos/package.json +1 -1
  130. package/packages/pm-vcs/package.json +1 -1
  131. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  132. package/plugins/pm-claude/package.json +1 -1
  133. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  134. package/plugins/pm-codex/package.json +1 -1
  135. package/plugins/pm-codex/plugin.json +1 -1
  136. package/runtime-dependencies.json +1 -1
  137. package/dist/cli-bundle/chunks/chunk-5WVE7XBS.js +0 -114
  138. package/dist/cli-bundle/chunks/chunk-E74BORFX.js +0 -128
  139. package/dist/cli-bundle/chunks/chunk-MP2DQJH2.js +0 -3
  140. package/dist/cli-bundle/chunks/chunk-O6TFUV6M.js +0 -31
  141. package/dist/cli-bundle/chunks/item-transaction-Q5S5YLEJ.js +0 -2
  142. package/dist/cli-bundle/focused-chunks/chunk-3Z53POXU.js +0 -2
  143. package/dist/cli-bundle/focused-chunks/chunk-7WJDRZOR.js +0 -22
  144. package/dist/cli-bundle/focused-chunks/chunk-CIQ6YWCW.js +0 -26
  145. package/dist/cli-bundle/focused-chunks/chunk-M22TI7LP.js +0 -79
  146. package/dist/cli-bundle/focused-chunks/chunk-SXZM4PSS.js +0 -44
@@ -1,5 +1,6 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="8d586108-d5b3-5c84-861a-cf532a979cdf")}catch{}})();import{AsyncLocalStorage}from"node:async_hooks";import{lstat,realpath}from"node:fs/promises";import path from"node:path";import{validateSettings}from"./settings-validator.js";import{runActiveOnReadHooks,runActiveOnWriteHooks}from"../extensions/index.js";import{EXIT_CODE,GOVERNANCE_PRESET_DEFAULTS,SETTINGS_DEFAULTS}from"../shared/constants.js";import{PmCliError}from"../shared/errors.js";import{resolveAuthor}from"../shared/author.js";import{isFileAbsentError,readFileIfExists,readRegularFile,transactionPreviewNonRegularFileError}from"../fs/fs-utils.js";import{mutateWorkspaceJsonWithHistory}from"../history/workspace-history.js";import{reconcileSettingsSnapshot}from"./settings-concurrency.js";import{DEFAULT_RUNTIME_SCHEMA_FILE_PATHS,filePathForSchemaSection,loadRuntimeSchemaFromOptionalFiles,normalizeRuntimeSchemaSettings}from"../schema/runtime-schema.js";import{getSettingsPath}from"./paths.js";import{orderObject,stableValueEquals}from"../shared/serialization.js";import{normalizeItemTypeDefinition}from"../item/item-type-definition.js";import{normalizeEstimateDefaultOverrides}from"../validate/estimate-defaults.js";import{clearSettingsReadCache,collectSettingsReadCacheSignatures,getSettingsReadCacheEntry,setSettingsReadCacheEntry,settingsReadCacheSignaturesEqual}from"./settings-read-cache.js";const configurationOnlySettingsRoots=new AsyncLocalStorage;async function runWithConfigurationOnlySettings(pmRoot,run,isEnabled=()=>!0){const roots=new Set([path.resolve(pmRoot)]);try{roots.add(await realpath(pmRoot))}catch{}return configurationOnlySettingsRoots.run([...configurationOnlySettingsRoots.getStore()??[],[roots,isEnabled]],run)}function isConfigurationOnlySettingsRead(pmRoot){const root=path.resolve(pmRoot);return configurationOnlySettingsRoots.getStore()?.some(([roots,isEnabled])=>roots.has(root)&&isEnabled())??!1}const SETTINGS_WRITE_OP="settings:write",SETTINGS_PERSIST_SOURCE_SYMBOL=Symbol("pm.settings.persist_source"),MAX_VECTOR_STORE_COLLECTION_NAME_LENGTH=128,DUPLICATE_DETECTION_MODES=new Set(["off","advisory","strict"]);function resolveGovernanceKnobsFromPreset(preset){return structuredClone(GOVERNANCE_PRESET_DEFAULTS[preset])}function normalizeGovernancePreset(value){return value==="minimal"||value==="default"||value==="strict"||value==="custom"?value:SETTINGS_DEFAULTS.governance.preset}function withGovernanceExtras(base,governance){const createDefaultType=typeof governance.create_default_type=="string"?governance.create_default_type.trim():void 0;return createDefaultType&&createDefaultType.length>0&&(base.create_default_type=createDefaultType),(governance.workflow_enforcement==="off"||governance.workflow_enforcement==="warn"||governance.workflow_enforcement==="strict")&&(base.workflow_enforcement=governance.workflow_enforcement),governance.require_close_reason===!1&&(base.require_close_reason=!1),base.duplicate_detection_mode=governance.duplicate_detection_mode,base.duplicate_detection_threshold=governance.duplicate_detection_threshold,base.duplicate_detection_limit=governance.duplicate_detection_limit,base}function normalizeGovernanceForPersist(governance){return governance.preset==="custom"?withGovernanceExtras({preset:"custom",ownership_enforcement:governance.ownership_enforcement,create_mode_default:governance.create_mode_default,close_validation_default:governance.close_validation_default,parent_reference:governance.parent_reference,metadata_profile:governance.metadata_profile,force_required_for_stale_lock:governance.force_required_for_stale_lock},governance):withGovernanceExtras({preset:governance.preset},governance)}function resolveGovernanceExtras(rawGovernance){const createDefaultType=typeof rawGovernance.create_default_type=="string"?rawGovernance.create_default_type.trim():void 0,extras={};createDefaultType&&createDefaultType.length>0&&(extras.create_default_type=createDefaultType),(rawGovernance.workflow_enforcement==="off"||rawGovernance.workflow_enforcement==="warn"||rawGovernance.workflow_enforcement==="strict")&&(extras.workflow_enforcement=rawGovernance.workflow_enforcement),typeof rawGovernance.require_close_reason=="boolean"&&(extras.require_close_reason=rawGovernance.require_close_reason),DUPLICATE_DETECTION_MODES.has(String(rawGovernance.duplicate_detection_mode))&&(extras.duplicate_detection_mode=rawGovernance.duplicate_detection_mode);const threshold=rawGovernance.duplicate_detection_threshold;[typeof threshold=="number",Number.isFinite(threshold),Number(threshold)>=0,Number(threshold)<=1].every(Boolean)&&(extras.duplicate_detection_threshold=threshold);const limit=rawGovernance.duplicate_detection_limit;return[typeof limit=="number",Number.isSafeInteger(limit),Number(limit)>=0,Number(limit)<=20].every(Boolean)&&(extras.duplicate_detection_limit=limit),extras}function resolveGovernanceKnobs(settings){const rawGovernance=settings.governance??{},preset=normalizeGovernancePreset(rawGovernance.preset),extras=resolveGovernanceExtras(rawGovernance);if(preset==="custom"){const baseline2=resolveGovernanceKnobsFromPreset("default"),requireCloseReason2=extras.require_close_reason??baseline2.require_close_reason;return{preset,ownership_enforcement:rawGovernance.ownership_enforcement??baseline2.ownership_enforcement,create_mode_default:rawGovernance.create_mode_default??baseline2.create_mode_default,close_validation_default:rawGovernance.close_validation_default??baseline2.close_validation_default,parent_reference:rawGovernance.parent_reference??baseline2.parent_reference,metadata_profile:rawGovernance.metadata_profile??baseline2.metadata_profile,force_required_for_stale_lock:rawGovernance.force_required_for_stale_lock??baseline2.force_required_for_stale_lock,...extras,require_close_reason:requireCloseReason2,duplicate_detection_mode:extras.duplicate_detection_mode??baseline2.duplicate_detection_mode,duplicate_detection_threshold:extras.duplicate_detection_threshold??baseline2.duplicate_detection_threshold,duplicate_detection_limit:extras.duplicate_detection_limit??baseline2.duplicate_detection_limit}}const baseline=resolveGovernanceKnobsFromPreset(preset),requireCloseReason=extras.require_close_reason??baseline.require_close_reason;return{preset,...baseline,...extras,require_close_reason:requireCloseReason}}function cloneDefaults(){return structuredClone(SETTINGS_DEFAULTS)}function normalizeSearchMutationRefreshPolicy(value){return value==="cache_only"||value==="semantic_configured"||value==="semantic_auto"?value:SETTINGS_DEFAULTS.search.mutation_refresh_policy}function normalizeSearchDefaultMode(value){return value==="auto"||value==="keyword"||value==="semantic"||value==="hybrid"?value:"auto"}function normalizeSearchQueryExpansionEnabled(value){return typeof value=="boolean"?value:SETTINGS_DEFAULTS.search.query_expansion.enabled}function normalizeSearchQueryExpansionProvider(value){return typeof value!="string"?SETTINGS_DEFAULTS.search.query_expansion.provider:value.trim()}function normalizeSearchRerankEnabled(value){return typeof value=="boolean"?value:SETTINGS_DEFAULTS.search.rerank.enabled}function normalizeSearchRerankModel(value){return typeof value!="string"?SETTINGS_DEFAULTS.search.rerank.model:value.trim()}function normalizeSearchRerankTopK(value){return typeof value=="number"&&Number.isFinite(value)&&Number.isInteger(value)&&value>0?value:SETTINGS_DEFAULTS.search.rerank.top_k}function normalizeVectorStoreCollectionName(value){if(typeof value!="string")return SETTINGS_DEFAULTS.vector_store.collection_name;const truncated=value.trim().replaceAll(/[^a-zA-Z0-9_-]/g,"_").slice(0,MAX_VECTOR_STORE_COLLECTION_NAME_LENGTH);return truncated.length>0?truncated:SETTINGS_DEFAULTS.vector_store.collection_name}function cloneOptionalArray(value){return{present:Array.isArray(value),values:Array.isArray(value)?structuredClone(value):[]}}function buildSettingsPersistSourceSnapshot(parsedSettings,runtimeSettings){const sourceSchema=parsedSettings.schema,sourceStatuses=cloneOptionalArray(sourceSchema?.statuses),sourceFields=cloneOptionalArray(sourceSchema?.fields),sourceTypeWorkflows=cloneOptionalArray(sourceSchema?.type_workflows);return{persisted_settings:structuredClone(parsedSettings),source_settings:structuredClone(parsedSettings),has_source_item_type_definitions:Array.isArray(parsedSettings.item_types?.definitions),source_item_type_definitions:normalizeItemTypeDefinitions(parsedSettings.item_types?.definitions),has_source_schema_statuses:sourceStatuses.present,source_schema_statuses:sourceStatuses.values,has_source_schema_fields:sourceFields.present,source_schema_fields:sourceFields.values,has_source_schema_type_workflows:sourceTypeWorkflows.present,source_schema_type_workflows:sourceTypeWorkflows.values,runtime_item_type_definitions:normalizeItemTypeDefinitions(runtimeSettings.item_types?.definitions),runtime_schema_statuses:structuredClone(runtimeSettings.schema.statuses),runtime_schema_fields:structuredClone(runtimeSettings.schema.fields),runtime_schema_type_workflows:structuredClone(runtimeSettings.schema.type_workflows??[])}}function attachSettingsPersistSourceSnapshot(settings,source){Object.defineProperty(settings,SETTINGS_PERSIST_SOURCE_SYMBOL,{value:source,writable:!0,configurable:!0,enumerable:!1})}function getSettingsPersistSourceSnapshot(settings){const candidate=settings[SETTINGS_PERSIST_SOURCE_SYMBOL];if(!(!candidate||typeof candidate!="object"))return candidate}function persistSelectedItemFormat(settings){const source=getSettingsPersistSourceSnapshot(settings);if(source){const detachedSource=structuredClone(source);detachedSource.source_settings.item_format=settings.item_format,attachSettingsPersistSourceSnapshot(settings,detachedSource)}}function cloneSettingsReadResult(result){const clonedSettings=structuredClone(result.settings),persistSource=getSettingsPersistSourceSnapshot(result.settings);return persistSource&&attachSettingsPersistSourceSnapshot(clonedSettings,persistSource),{settings:clonedSettings,metadata:{has_explicit_item_format:result.metadata.has_explicit_item_format},warnings:[...result.warnings]}}function resolveSettingsReadTrackedPaths(pmRoot,schema,settingsPath){const normalizedSchema=normalizeRuntimeSchemaSettings(schema);return[settingsPath,filePathForSchemaSection(pmRoot,normalizedSchema.files.types,DEFAULT_RUNTIME_SCHEMA_FILE_PATHS.types),filePathForSchemaSection(pmRoot,normalizedSchema.files.statuses,DEFAULT_RUNTIME_SCHEMA_FILE_PATHS.statuses),filePathForSchemaSection(pmRoot,normalizedSchema.files.fields,DEFAULT_RUNTIME_SCHEMA_FILE_PATHS.fields),filePathForSchemaSection(pmRoot,normalizedSchema.files.workflows,DEFAULT_RUNTIME_SCHEMA_FILE_PATHS.workflows)]}async function cacheSettingsReadResult(pmRoot,trackedPaths,result){const signatures=await collectSettingsReadCacheSignatures(trackedPaths);setSettingsReadCacheEntry(pmRoot,{tracked_paths:trackedPaths,signatures,value:cloneSettingsReadResult(result)})}async function cacheSettingsReadResultSafe(pmRoot,trackedPaths,result){try{await cacheSettingsReadResult(pmRoot,trackedPaths,result)}catch{clearSettingsReadCache(pmRoot)}}function findSettingsReadCacheSignature(signatures,targetPath){return signatures.find(signature=>signature.path===targetPath)}function selectedSettingsReadCacheSignaturesEqual(before,after,targetPaths){for(const targetPath of targetPaths){const beforeSignature=findSettingsReadCacheSignature(before,targetPath),afterSignature=findSettingsReadCacheSignature(after,targetPath);if(!beforeSignature||!afterSignature||!settingsReadCacheSignaturesEqual([beforeSignature],[afterSignature]))return!1}return!0}async function cacheSettingsReadResultIfStable(pmRoot,trackedPaths,result,stableSignatures,stablePaths){try{const currentSignatures=await collectSettingsReadCacheSignatures(trackedPaths);if(!selectedSettingsReadCacheSignaturesEqual(stableSignatures,currentSignatures,stablePaths)){clearSettingsReadCache(pmRoot);return}setSettingsReadCacheEntry(pmRoot,{tracked_paths:trackedPaths,signatures:currentSignatures,value:cloneSettingsReadResult(result)})}catch{clearSettingsReadCache(pmRoot)}}function resolvePersistedFileBackedSchemaSections(settings,source){const normalizedSchema=normalizeRuntimeSchemaSettings(settings.schema),currentItemTypeDefinitions=normalizeItemTypeDefinitions(settings.item_types?.definitions);if(!source)return{item_type_definitions:currentItemTypeDefinitions,schema_statuses:normalizedSchema.statuses,schema_fields:normalizedSchema.fields,schema_type_workflows:normalizedSchema.type_workflows};const currentTypeWorkflows=normalizedSchema.type_workflows??[],itemTypeDefinitionsUnchanged=stableValueEquals(currentItemTypeDefinitions,source.runtime_item_type_definitions),schemaStatusesUnchanged=stableValueEquals(normalizedSchema.statuses,source.runtime_schema_statuses),schemaFieldsUnchanged=stableValueEquals(normalizedSchema.fields,source.runtime_schema_fields),schemaTypeWorkflowsUnchanged=stableValueEquals(currentTypeWorkflows,source.runtime_schema_type_workflows);return{item_type_definitions:itemTypeDefinitionsUnchanged?source.has_source_item_type_definitions?normalizeItemTypeDefinitions(source.source_item_type_definitions):[]:currentItemTypeDefinitions,schema_statuses:schemaStatusesUnchanged?source.has_source_schema_statuses?structuredClone(source.source_schema_statuses):[]:normalizedSchema.statuses,schema_fields:schemaFieldsUnchanged?source.has_source_schema_fields?structuredClone(source.source_schema_fields):[]:normalizedSchema.fields,schema_type_workflows:schemaTypeWorkflowsUnchanged?source.has_source_schema_type_workflows?structuredClone(source.source_schema_type_workflows):void 0:normalizedSchema.type_workflows}}function buildFallbackSettingsReadResult(warning){return{settings:cloneDefaults(),metadata:{has_explicit_item_format:!1},warnings:warning?[warning]:[]}}function hasExplicitItemFormat(raw){if(typeof raw!="object"||raw===null||Array.isArray(raw))return!1;const itemFormat=raw.item_format;return itemFormat==="toon"||itemFormat==="json_markdown"}function normalizeStringList(values){return[...new Set((values??[]).map(value=>value.trim()).filter(value=>value.length>0))].sort((left,right)=>left.localeCompare(right))}function normalizeAgentGuidanceSettings(value){const defaults=SETTINGS_DEFAULTS.agent_guidance,templateVersion=value?.template_version;return{prompt_completed:value?.prompt_completed===!0,declined:value?.declined===!0,declined_at:typeof value?.declined_at=="string"?value.declined_at:defaults.declined_at,template_version:typeof templateVersion=="number"&&Number.isInteger(templateVersion)&&templateVersion>0?templateVersion:defaults.template_version,last_checked_files:normalizeStringList(value?.last_checked_files??defaults.last_checked_files)}}function normalizeLowerStringList(values){return[...new Set((values??[]).map(value=>value.trim().toLowerCase()).filter(value=>value.length>0))].sort((left,right)=>left.localeCompare(right))}function normalizeExtensionPolicyMode(value){return value==="off"||value==="warn"||value==="enforce"?value:SETTINGS_DEFAULTS.extensions.policy.mode}function normalizeExtensionTrustMode(value){return value==="off"||value==="warn"||value==="enforce"?value:SETTINGS_DEFAULTS.extensions.policy.trust_mode}function normalizeExtensionSandboxProfile(value){return value==="none"||value==="restricted"||value==="strict"?value:SETTINGS_DEFAULTS.extensions.policy.default_sandbox_profile}function normalizeExtensionPolicyOverride(override){const name=override.name.trim().toLowerCase();if(name.length===0)return null;const normalized={name};override.disabled===!0&&(normalized.disabled=!0),override.require_trusted===!0&&(normalized.require_trusted=!0),override.require_provenance===!0&&(normalized.require_provenance=!0),override.sandbox_profile!==void 0&&(normalized.sandbox_profile=normalizeExtensionSandboxProfile(override.sandbox_profile));const allowedCapabilities=normalizeLowerStringList(override.allowed_capabilities),blockedCapabilities=normalizeLowerStringList(override.blocked_capabilities),allowedSurfaces=normalizeLowerStringList(override.allowed_surfaces),blockedSurfaces=normalizeLowerStringList(override.blocked_surfaces),allowedCommands=normalizeLowerStringList(override.allowed_commands),blockedCommands=normalizeLowerStringList(override.blocked_commands),allowedActions=normalizeLowerStringList(override.allowed_actions),blockedActions=normalizeLowerStringList(override.blocked_actions),allowedServices=normalizeLowerStringList(override.allowed_services),blockedServices=normalizeLowerStringList(override.blocked_services);return allowedCapabilities.length>0&&(normalized.allowed_capabilities=allowedCapabilities),blockedCapabilities.length>0&&(normalized.blocked_capabilities=blockedCapabilities),allowedSurfaces.length>0&&(normalized.allowed_surfaces=allowedSurfaces),blockedSurfaces.length>0&&(normalized.blocked_surfaces=blockedSurfaces),allowedCommands.length>0&&(normalized.allowed_commands=allowedCommands),blockedCommands.length>0&&(normalized.blocked_commands=blockedCommands),allowedActions.length>0&&(normalized.allowed_actions=allowedActions),blockedActions.length>0&&(normalized.blocked_actions=blockedActions),allowedServices.length>0&&(normalized.allowed_services=allowedServices),blockedServices.length>0&&(normalized.blocked_services=blockedServices),normalized}function normalizeExtensionPolicyOverrides(overrides){const dedupedByName=new Map;for(const override of overrides??[]){const normalized=normalizeExtensionPolicyOverride(override);normalized&&dedupedByName.set(normalized.name,normalized)}return[...dedupedByName.values()].sort((left,right)=>left.name.localeCompare(right.name))}function normalizePmMaxVersionExceededModeValue(value){return value==="block"||value==="warn"?value:void 0}function normalizePmMaxVersionExceededModeSetting(value){if(typeof value=="string")return normalizePmMaxVersionExceededModeValue(value);if(typeof value=="object"&&value!==null&&!Array.isArray(value)){const global2=normalizePmMaxVersionExceededModeValue(value.global),project=normalizePmMaxVersionExceededModeValue(value.project);return global2===void 0&&project===void 0?void 0:{...global2!==void 0?{global:global2}:{},...project!==void 0?{project}:{}}}}function normalizeExtensionPolicyList(policy,key){return normalizeLowerStringList(policy?.[key]??SETTINGS_DEFAULTS.extensions.policy[key])}function normalizeExtensionPolicySettings(policy){const pmMaxVersionExceededMode=normalizePmMaxVersionExceededModeSetting(policy?.pm_max_version_exceeded_mode);return{mode:normalizeExtensionPolicyMode(policy?.mode),trust_mode:normalizeExtensionTrustMode(policy?.trust_mode),...pmMaxVersionExceededMode!==void 0?{pm_max_version_exceeded_mode:pmMaxVersionExceededMode}:{},require_provenance:policy?.require_provenance===!0,trusted_extensions:normalizeExtensionPolicyList(policy,"trusted_extensions"),default_sandbox_profile:normalizeExtensionSandboxProfile(policy?.default_sandbox_profile),allowed_extensions:normalizeExtensionPolicyList(policy,"allowed_extensions"),blocked_extensions:normalizeExtensionPolicyList(policy,"blocked_extensions"),allowed_capabilities:normalizeExtensionPolicyList(policy,"allowed_capabilities"),blocked_capabilities:normalizeExtensionPolicyList(policy,"blocked_capabilities"),allowed_surfaces:normalizeExtensionPolicyList(policy,"allowed_surfaces"),blocked_surfaces:normalizeExtensionPolicyList(policy,"blocked_surfaces"),allowed_commands:normalizeExtensionPolicyList(policy,"allowed_commands"),blocked_commands:normalizeExtensionPolicyList(policy,"blocked_commands"),allowed_actions:normalizeExtensionPolicyList(policy,"allowed_actions"),blocked_actions:normalizeExtensionPolicyList(policy,"blocked_actions"),allowed_services:normalizeExtensionPolicyList(policy,"allowed_services"),blocked_services:normalizeExtensionPolicyList(policy,"blocked_services"),extension_overrides:normalizeExtensionPolicyOverrides(policy?.extension_overrides??SETTINGS_DEFAULTS.extensions.policy.extension_overrides)}}function normalizeValidationMetadataRequiredFields(values){return[...new Set((values??[]).map(value=>value.trim().toLowerCase().replaceAll("-","_")))].filter(value=>value.length>0).sort((left,right)=>left.localeCompare(right)).filter(value=>["author","acceptance_criteria","estimated_minutes","close_reason","reviewer","risk","confidence","sprint","release"].includes(value))}function normalizeValidationPatternList(values){return[...new Set((values??[]).map(value=>value.trim().toLowerCase()).filter(value=>value.length>0))].sort((left,right)=>left.localeCompare(right))}function valueOrDefault(value,fallback){return value===void 0?fallback:value}function recordOrEmpty(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)?value:{}}function arrayOrEmpty(value){return Array.isArray(value)?value:[]}function buildValidationSettings(settings,defaults,governance){return{...defaults.validation,...settings.validation,parent_reference:governance.parent_reference,metadata_profile:governance.metadata_profile,metadata_required_fields:normalizeValidationMetadataRequiredFields(settings.validation?.metadata_required_fields),lifecycle_stale_blocker_reason_patterns:normalizeValidationPatternList(settings.validation?.lifecycle_stale_blocker_reason_patterns??defaults.validation.lifecycle_stale_blocker_reason_patterns),lifecycle_closure_like_blocked_reason_patterns:normalizeValidationPatternList(settings.validation?.lifecycle_closure_like_blocked_reason_patterns??defaults.validation.lifecycle_closure_like_blocked_reason_patterns),lifecycle_closure_like_resolution_patterns:normalizeValidationPatternList(settings.validation?.lifecycle_closure_like_resolution_patterns??defaults.validation.lifecycle_closure_like_resolution_patterns),lifecycle_closure_like_actual_result_patterns:normalizeValidationPatternList(settings.validation?.lifecycle_closure_like_actual_result_patterns??defaults.validation.lifecycle_closure_like_actual_result_patterns),estimate_defaults_by_type:normalizeEstimateDefaultOverrides(settings.validation?.estimate_defaults_by_type)}}function buildTelemetrySettings(settings,defaults){return{enabled:settings.telemetry?.enabled??defaults.telemetry.enabled,first_run_prompt_completed:settings.telemetry?.first_run_prompt_completed??defaults.telemetry.first_run_prompt_completed,capture_level:settings.telemetry?.capture_level??defaults.telemetry.capture_level,endpoint:settings.telemetry?.endpoint??defaults.telemetry.endpoint,installation_id:settings.telemetry?.installation_id??defaults.telemetry.installation_id,retention_days:settings.telemetry?.retention_days??defaults.telemetry.retention_days}}function buildSearchSettings(settings,defaults){return{...defaults.search,...settings.search,default_mode:normalizeSearchDefaultMode(settings.search?.default_mode),mutation_refresh_policy:normalizeSearchMutationRefreshPolicy(settings.search?.mutation_refresh_policy),query_expansion:{...defaults.search.query_expansion,...settings.search?.query_expansion,enabled:normalizeSearchQueryExpansionEnabled(settings.search?.query_expansion?.enabled),provider:normalizeSearchQueryExpansionProvider(settings.search?.query_expansion?.provider)},rerank:{...defaults.search.rerank,...settings.search?.rerank,enabled:normalizeSearchRerankEnabled(settings.search?.rerank?.enabled),model:normalizeSearchRerankModel(settings.search?.rerank?.model),top_k:normalizeSearchRerankTopK(settings.search?.rerank?.top_k)}}}function buildVectorStoreSettings(settings,defaults){return{adapter:settings.vector_store.adapter??defaults.vector_store.adapter,collection_name:normalizeVectorStoreCollectionName(settings.vector_store.collection_name),qdrant:{...defaults.vector_store.qdrant,...settings.vector_store.qdrant},lancedb:{...defaults.vector_store.lancedb,...settings.vector_store.lancedb}}}function normalizeSettingsItemFormat(settings,defaults){return settings.item_format==="json_markdown"?"toon":settings.item_format??defaults.item_format}function buildContextSettings(settings,defaults){return{default_depth:settings.context?.default_depth??defaults.context.default_depth,activity_limit:settings.context?.activity_limit??defaults.context.activity_limit,stale_threshold_days:settings.context?.stale_threshold_days??defaults.context.stale_threshold_days,next_ranking_policy:settings.context?.next_ranking_policy??defaults.context.next_ranking_policy,sections:{...defaults.context.sections,...settings.context?.sections}}}function buildProviderSettings(settings,defaults){return{openai:{...defaults.providers.openai,...settings.providers.openai},ollama:{...defaults.providers.ollama,...settings.providers.ollama}}}function normalizeItemTypeDefinitions(definitions){const normalized=(definitions??[]).map(definition=>normalizeItemTypeDefinition(definition)).filter(definition=>definition!==null),dedupedByName=new Map;for(const definition of normalized)dedupedByName.set(definition.name.toLowerCase(),definition);return[...dedupedByName.values()].sort((left,right)=>left.name.localeCompare(right.name))}function mergeSettings(settings){const defaults=cloneDefaults(),governance=resolveGovernanceKnobs({governance:settings.governance??{preset:"default"}});return{...defaults,...settings,item_format:normalizeSettingsItemFormat(settings,defaults),locks:{...defaults.locks,...settings.locks},ids:{...defaults.ids,...settings.ids},agent_identity:structuredClone(settings.agent_identity??defaults.agent_identity),mutation_guard:{...defaults.mutation_guard,...settings.mutation_guard},checkpoints:{...defaults.checkpoints,...settings.checkpoints},output:{...defaults.output,...settings.output},ux:{...defaults.ux,...settings.ux},history:{...defaults.history,...settings.history,compact_policy:{...defaults.history.compact_policy,...settings.history?.compact_policy}},validation:buildValidationSettings(settings,defaults,governance),governance,workflow:{definition_of_done:[...settings.workflow?.definition_of_done??defaults.workflow.definition_of_done]},testing:{record_results_to_items:settings.testing?.record_results_to_items??defaults.testing.record_results_to_items,allow_untrusted_linked_tests:settings.testing?.allow_untrusted_linked_tests??defaults.testing.allow_untrusted_linked_tests},telemetry:buildTelemetrySettings(settings,defaults),agent_guidance:normalizeAgentGuidanceSettings(settings.agent_guidance??defaults.agent_guidance),item_types:{definitions:normalizeItemTypeDefinitions(settings.item_types?.definitions)},schema:normalizeRuntimeSchemaSettings(settings.schema??defaults.schema),context:buildContextSettings(settings,defaults),extensions:{enabled:[...settings.extensions.enabled],disabled:[...settings.extensions.disabled],policy:normalizeExtensionPolicySettings(settings.extensions.policy??defaults.extensions.policy)},search:buildSearchSettings(settings,defaults),providers:buildProviderSettings(settings,defaults),vector_store:buildVectorStoreSettings(settings,defaults)}}function orderSerializedSettingsSections(ordered){ordered.agent_identity=orderObject(ordered.agent_identity,["probes_enabled","identity_vocabulary","harness_signals"]);const orderedAgentIdentity=ordered.agent_identity;Object.hasOwn(orderedAgentIdentity,"identity_vocabulary")&&(orderedAgentIdentity.identity_vocabulary=orderObject(recordOrEmpty(orderedAgentIdentity.identity_vocabulary),["version","aliases"])),ordered.agent_identity.harness_signals=arrayOrEmpty(ordered.agent_identity.harness_signals).map(entry=>orderObject(recordOrEmpty(entry),["harness","environment_keys","model_environment_keys","session_environment_keys","provenance_environment_keys","provenance_resolvers","provenance_unavailable_dimensions","argv_markers","client_names"])),ordered.locks=orderObject(ordered.locks,["ttl_seconds","wait_ms"]),ordered.ids=orderObject(ordered.ids,["token_length"]),ordered.mutation_guard=orderObject(ordered.mutation_guard,["require_attributed_author","secret_guard","stale_in_progress_hours"]),ordered.checkpoints=orderObject(ordered.checkpoints,["retention_days"]),ordered.output=orderObject(ordered.output,["default_format"]),ordered.ux=orderObject(ordered.ux,["deprecation_hints"]),ordered.history=orderObject(ordered.history,["missing_stream","compact_policy"]),ordered.validation=orderObject(ordered.validation,["sprint_release_format","parent_reference","metadata_profile","metadata_required_fields","lifecycle_stale_blocker_reason_patterns","lifecycle_closure_like_blocked_reason_patterns","lifecycle_closure_like_resolution_patterns","lifecycle_closure_like_actual_result_patterns","estimate_defaults_by_type"]),ordered.governance=orderObject(ordered.governance,["preset","ownership_enforcement","create_mode_default","close_validation_default","require_close_reason","parent_reference","metadata_profile","force_required_for_stale_lock","create_default_type","workflow_enforcement","duplicate_detection_mode","duplicate_detection_threshold","duplicate_detection_limit"]),ordered.workflow=orderObject(ordered.workflow,["definition_of_done"]),ordered.testing=orderObject(ordered.testing,["record_results_to_items","allow_untrusted_linked_tests"]),ordered.telemetry=orderObject(ordered.telemetry,["enabled","first_run_prompt_completed","capture_level","endpoint","installation_id","retention_days"]),ordered.agent_guidance=orderObject(ordered.agent_guidance,["prompt_completed","declined","declined_at","template_version","last_checked_files"]),ordered.item_types=orderObject(ordered.item_types,["definitions"]),ordered.schema=orderObject(ordered.schema,["version","files","statuses","fields","workflow","type_workflows","unknown_field_policy"]),ordered.schema.files=orderObject(recordOrEmpty(ordered.schema.files),["types","statuses","fields","workflows"]),ordered.schema.workflow=orderObject(recordOrEmpty(ordered.schema.workflow),["draft_status","open_status","in_progress_status","blocked_status","close_status","canceled_status"]),ordered.context=orderObject(ordered.context,["default_depth","activity_limit","stale_threshold_days","next_ranking_policy","sections"]),ordered.context.sections=orderObject(recordOrEmpty(ordered.context.sections),["hierarchy","activity","progress","blockers","files","workload","staleness","tests"]),ordered.extensions=orderObject(ordered.extensions,["enabled","disabled","policy"]),ordered.extensions.policy=orderObject(recordOrEmpty(ordered.extensions.policy),["mode","trust_mode","pm_max_version_exceeded_mode","require_provenance","trusted_extensions","default_sandbox_profile","allowed_extensions","blocked_extensions","allowed_capabilities","blocked_capabilities","allowed_surfaces","blocked_surfaces","allowed_commands","blocked_commands","allowed_actions","blocked_actions","allowed_services","blocked_services","extension_overrides"]),ordered.extensions.policy.extension_overrides=arrayOrEmpty(ordered.extensions.policy.extension_overrides).map(entry=>orderObject(recordOrEmpty(entry),["name","disabled","require_trusted","require_provenance","sandbox_profile","allowed_capabilities","blocked_capabilities","allowed_surfaces","blocked_surfaces","allowed_commands","blocked_commands","allowed_actions","blocked_actions","allowed_services","blocked_services"])),ordered.search=orderObject(ordered.search,["score_threshold","hybrid_semantic_weight","max_results","embedding_model","embedding_corpus_max_characters","embedding_batch_size","embedding_timeout_ms","scanner_max_batch_retries","provider","default_mode","mutation_refresh_policy","query_expansion","rerank"]),ordered.search.query_expansion=orderObject(recordOrEmpty(ordered.search.query_expansion),["enabled","provider"]),ordered.search.rerank=orderObject(recordOrEmpty(ordered.search.rerank),["enabled","model","top_k"]),ordered.providers=orderObject(ordered.providers,["openai","ollama"]),ordered.providers.openai=orderObject(recordOrEmpty(ordered.providers.openai),["base_url","api_key","model"]),ordered.providers.ollama=orderObject(recordOrEmpty(ordered.providers.ollama),["base_url","model"]),ordered.vector_store=orderObject(ordered.vector_store,["adapter","collection_name","qdrant","lancedb"]),ordered.vector_store.qdrant=orderObject(recordOrEmpty(ordered.vector_store.qdrant),["url","api_key"]),ordered.vector_store.lancedb=orderObject(recordOrEmpty(ordered.vector_store.lancedb),["path"])}function buildSerializeBaseSettings(settings){return{...settings,locks:valueOrDefault(settings.locks,SETTINGS_DEFAULTS.locks),ids:valueOrDefault(settings.ids,SETTINGS_DEFAULTS.ids),agent_identity:valueOrDefault(settings.agent_identity,SETTINGS_DEFAULTS.agent_identity),mutation_guard:valueOrDefault(settings.mutation_guard,SETTINGS_DEFAULTS.mutation_guard),checkpoints:valueOrDefault(settings.checkpoints,SETTINGS_DEFAULTS.checkpoints),output:valueOrDefault(settings.output,SETTINGS_DEFAULTS.output),ux:valueOrDefault(settings.ux,SETTINGS_DEFAULTS.ux),history:valueOrDefault(settings.history,SETTINGS_DEFAULTS.history),validation:valueOrDefault(settings.validation,SETTINGS_DEFAULTS.validation),workflow:valueOrDefault(settings.workflow,SETTINGS_DEFAULTS.workflow),testing:valueOrDefault(settings.testing,SETTINGS_DEFAULTS.testing),telemetry:valueOrDefault(settings.telemetry,SETTINGS_DEFAULTS.telemetry),agent_guidance:valueOrDefault(settings.agent_guidance,SETTINGS_DEFAULTS.agent_guidance),item_types:valueOrDefault(settings.item_types,SETTINGS_DEFAULTS.item_types),schema:valueOrDefault(settings.schema,SETTINGS_DEFAULTS.schema),context:valueOrDefault(settings.context,SETTINGS_DEFAULTS.context),extensions:valueOrDefault(settings.extensions,SETTINGS_DEFAULTS.extensions),search:valueOrDefault(settings.search,SETTINGS_DEFAULTS.search),providers:valueOrDefault(settings.providers,SETTINGS_DEFAULTS.providers),vector_store:valueOrDefault(settings.vector_store,SETTINGS_DEFAULTS.vector_store)}}function buildSerializedValidationSettings(baseSettings,governance){return{...baseSettings.validation,parent_reference:governance.parent_reference,metadata_profile:governance.metadata_profile,metadata_required_fields:normalizeValidationMetadataRequiredFields(baseSettings.validation?.metadata_required_fields),lifecycle_stale_blocker_reason_patterns:normalizeValidationPatternList(baseSettings.validation?.lifecycle_stale_blocker_reason_patterns??SETTINGS_DEFAULTS.validation.lifecycle_stale_blocker_reason_patterns),lifecycle_closure_like_blocked_reason_patterns:normalizeValidationPatternList(baseSettings.validation?.lifecycle_closure_like_blocked_reason_patterns??SETTINGS_DEFAULTS.validation.lifecycle_closure_like_blocked_reason_patterns),lifecycle_closure_like_resolution_patterns:normalizeValidationPatternList(baseSettings.validation?.lifecycle_closure_like_resolution_patterns??SETTINGS_DEFAULTS.validation.lifecycle_closure_like_resolution_patterns),lifecycle_closure_like_actual_result_patterns:normalizeValidationPatternList(baseSettings.validation?.lifecycle_closure_like_actual_result_patterns??SETTINGS_DEFAULTS.validation.lifecycle_closure_like_actual_result_patterns),estimate_defaults_by_type:normalizeEstimateDefaultOverrides(baseSettings.validation?.estimate_defaults_by_type)}}function buildSerializedSearchSettings(baseSettings){return{...SETTINGS_DEFAULTS.search,...baseSettings.search,default_mode:normalizeSearchDefaultMode(baseSettings.search?.default_mode),mutation_refresh_policy:normalizeSearchMutationRefreshPolicy(baseSettings.search?.mutation_refresh_policy),query_expansion:{...SETTINGS_DEFAULTS.search.query_expansion,...baseSettings.search?.query_expansion,enabled:normalizeSearchQueryExpansionEnabled(baseSettings.search?.query_expansion?.enabled),provider:normalizeSearchQueryExpansionProvider(baseSettings.search?.query_expansion?.provider)},rerank:{...SETTINGS_DEFAULTS.search.rerank,...baseSettings.search?.rerank,enabled:normalizeSearchRerankEnabled(baseSettings.search?.rerank?.enabled),model:normalizeSearchRerankModel(baseSettings.search?.rerank?.model),top_k:normalizeSearchRerankTopK(baseSettings.search?.rerank?.top_k)}}}function buildSerializedContextSettings(baseSettings){return{default_depth:baseSettings.context?.default_depth??SETTINGS_DEFAULTS.context.default_depth,activity_limit:baseSettings.context?.activity_limit??SETTINGS_DEFAULTS.context.activity_limit,stale_threshold_days:baseSettings.context?.stale_threshold_days??SETTINGS_DEFAULTS.context.stale_threshold_days,next_ranking_policy:baseSettings.context?.next_ranking_policy??SETTINGS_DEFAULTS.context.next_ranking_policy,sections:{...SETTINGS_DEFAULTS.context.sections,...baseSettings.context?.sections}}}function buildSerializedVectorStoreSettings(baseSettings){return{...baseSettings.vector_store,adapter:baseSettings.vector_store?.adapter??SETTINGS_DEFAULTS.vector_store.adapter,collection_name:normalizeVectorStoreCollectionName(baseSettings.vector_store?.collection_name),qdrant:{...baseSettings.vector_store?.qdrant},lancedb:{...baseSettings.vector_store?.lancedb}}}function buildNormalizedSettingsForSerialization(baseSettings,governance,normalizedSchema,persistedFileBackedSections){return{...baseSettings,item_format:"toon",validation:buildSerializedValidationSettings(baseSettings,governance),governance,agent_guidance:normalizeAgentGuidanceSettings(baseSettings.agent_guidance),item_types:{definitions:persistedFileBackedSections.item_type_definitions},schema:{...normalizedSchema,statuses:persistedFileBackedSections.schema_statuses,fields:persistedFileBackedSections.schema_fields,type_workflows:persistedFileBackedSections.schema_type_workflows},search:buildSerializedSearchSettings(baseSettings),context:buildSerializedContextSettings(baseSettings),extensions:{enabled:normalizeStringList(baseSettings.extensions?.enabled),disabled:normalizeStringList(baseSettings.extensions?.disabled),policy:normalizeExtensionPolicySettings(baseSettings.extensions?.policy)},vector_store:buildSerializedVectorStoreSettings(baseSettings)}}function overlayPresentSettingsSource(target,source){for(const key of Object.keys(source)){const value=Reflect.get(source,key),existing=target[key];typeof value=="object"&&value!==null&&!Array.isArray(value)&&typeof existing=="object"&&existing!==null&&!Array.isArray(existing)?overlayPresentSettingsSource(existing,value):target[key]=structuredClone(value)}}function applySettingsDelta(target,baseline,current){const keys=new Set([...Object.keys(baseline),...Object.keys(current)]);for(const key of keys){const before=baseline[key],after=current[key];if(!stableValueEquals(before,after)){if(after===void 0){delete target[key];continue}if(typeof before=="object"&&before!==null&&!Array.isArray(before)&&typeof after=="object"&&after!==null&&!Array.isArray(after)){const existing=target[key],nestedTarget=typeof existing=="object"&&existing!==null&&!Array.isArray(existing)?existing:{};applySettingsDelta(nestedTarget,before,after),Object.keys(nestedTarget).length>0?target[key]=nestedTarget:delete target[key];continue}target[key]=structuredClone(after)}}}const SETTINGS_TOP_LEVEL_KEY_ORDER=["version","id_prefix","ids","author_default","agent_identity","mutation_guard","item_format","locks","checkpoints","output","ux","history","validation","governance","workflow","testing","telemetry","agent_guidance","item_types","schema","context","extensions","search","providers","vector_store"];function buildOrderedSettingsForSerialization(settings,persistSource){const baseSettings=buildSerializeBaseSettings(settings),governance=resolveGovernanceKnobs(baseSettings),normalizedSchema=normalizeRuntimeSchemaSettings(baseSettings.schema),persistedFileBackedSections=resolvePersistedFileBackedSchemaSections(baseSettings,persistSource),normalizedSettings=buildNormalizedSettingsForSerialization(baseSettings,governance,normalizedSchema,persistedFileBackedSections),ordered=orderObject({...normalizedSettings,governance:normalizeGovernanceForPersist(governance)},SETTINGS_TOP_LEVEL_KEY_ORDER);return orderSerializedSettingsSections(ordered),ordered}function serializeSettings(settings,options={}){const persistSource=options.source===void 0?options.persist_source:buildSettingsPersistSourceSnapshot(options.source.validated,mergeSettings(options.source.validated)),ordered=buildOrderedSettingsForSerialization(settings,persistSource);if(persistSource){const baselineSettings=mergeSettings(persistSource.source_settings);baselineSettings.item_types={definitions:structuredClone(persistSource.runtime_item_type_definitions)},baselineSettings.schema={...baselineSettings.schema,statuses:structuredClone(persistSource.runtime_schema_statuses),fields:structuredClone(persistSource.runtime_schema_fields),type_workflows:structuredClone(persistSource.runtime_schema_type_workflows)};const baseline=buildOrderedSettingsForSerialization(baselineSettings,persistSource);options.source!==void 0&&overlayPresentSettingsSource(baseline,options.source.validated);const sparse=structuredClone(options.source===void 0?persistSource.source_settings:options.source.raw);return applySettingsDelta(sparse,baseline,ordered),`${JSON.stringify(orderObject(sparse,SETTINGS_TOP_LEVEL_KEY_ORDER),null,2)}
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f9ff37ec-3a6f-5496-b59d-cdf2cce3a63a")}catch{}})();import{AsyncLocalStorage}from"node:async_hooks";import{lstat,realpath}from"node:fs/promises";import path from"node:path";import{CORE_SETTINGS_SECTION_KEYS,validateSettings}from"./settings-validator.js";import{runActiveOnReadHooks,runActiveOnWriteHooks}from"../extensions/index.js";import{EXIT_CODE,GOVERNANCE_PRESET_DEFAULTS,SETTINGS_DEFAULTS}from"../shared/constants.js";import{PmCliError}from"../shared/errors.js";import{resolveAuthor}from"../shared/author.js";import{isFileAbsentError,readFileIfExists,readRegularFile,transactionPreviewNonRegularFileError}from"../fs/fs-utils.js";import{mutateWorkspaceJsonWithHistory}from"../history/workspace-history.js";import{reconcileSettingsSnapshot}from"./settings-concurrency.js";import{DEFAULT_RUNTIME_SCHEMA_FILE_PATHS,filePathForSchemaSection,loadRuntimeSchemaFromOptionalFiles,normalizeRuntimeSchemaSettings}from"../schema/runtime-schema.js";import{getSettingsPath}from"./paths.js";import{orderObject,stableValueEquals}from"../shared/serialization.js";import{normalizeItemTypeDefinition}from"../item/item-type-definition.js";import{normalizeEstimateDefaultOverrides}from"../validate/estimate-defaults.js";import{clearSettingsReadCache,collectSettingsReadCacheSignatures,getSettingsReadCacheEntry,setSettingsReadCacheEntry,settingsReadCacheSignaturesEqual}from"./settings-read-cache.js";const configurationOnlySettingsRoots=new AsyncLocalStorage;async function runWithConfigurationOnlySettings(pmRoot,run,isEnabled=()=>!0){const roots=new Set([path.resolve(pmRoot)]);try{roots.add(await realpath(pmRoot))}catch{}return configurationOnlySettingsRoots.run([...configurationOnlySettingsRoots.getStore()??[],[roots,isEnabled]],run)}function isConfigurationOnlySettingsRead(pmRoot){const root=path.resolve(pmRoot);return configurationOnlySettingsRoots.getStore()?.some(([roots,isEnabled])=>roots.has(root)&&isEnabled())??!1}const SETTINGS_WRITE_OP="settings:write",SETTINGS_PERSIST_SOURCE_SYMBOL=Symbol("pm.settings.persist_source"),SETTINGS_FALLBACK_ORIGIN_SYMBOL=Symbol("pm.settings.fallback_origin"),SETTINGS_FALLBACK_BASELINE_SYMBOL=Symbol("pm.settings.fallback_baseline"),MAX_VECTOR_STORE_COLLECTION_NAME_LENGTH=128,DUPLICATE_DETECTION_MODES=new Set(["off","advisory","strict"]);function resolveGovernanceKnobsFromPreset(preset){return structuredClone(GOVERNANCE_PRESET_DEFAULTS[preset])}function normalizeGovernancePreset(value){return value==="minimal"||value==="default"||value==="strict"||value==="custom"?value:SETTINGS_DEFAULTS.governance.preset}function withGovernanceExtras(base,governance){const createDefaultType=typeof governance.create_default_type=="string"?governance.create_default_type.trim():void 0;return createDefaultType&&createDefaultType.length>0&&(base.create_default_type=createDefaultType),(governance.workflow_enforcement==="off"||governance.workflow_enforcement==="warn"||governance.workflow_enforcement==="strict")&&(base.workflow_enforcement=governance.workflow_enforcement),governance.require_close_reason===!1&&(base.require_close_reason=!1),base.duplicate_detection_mode=governance.duplicate_detection_mode,base.duplicate_detection_threshold=governance.duplicate_detection_threshold,base.duplicate_detection_limit=governance.duplicate_detection_limit,base}function normalizeGovernanceForPersist(governance){return governance.preset==="custom"?withGovernanceExtras({preset:"custom",ownership_enforcement:governance.ownership_enforcement,create_mode_default:governance.create_mode_default,close_validation_default:governance.close_validation_default,parent_reference:governance.parent_reference,metadata_profile:governance.metadata_profile,force_required_for_stale_lock:governance.force_required_for_stale_lock},governance):withGovernanceExtras({preset:governance.preset},governance)}function resolveGovernanceExtras(rawGovernance){const createDefaultType=typeof rawGovernance.create_default_type=="string"?rawGovernance.create_default_type.trim():void 0,extras={};createDefaultType&&createDefaultType.length>0&&(extras.create_default_type=createDefaultType),(rawGovernance.workflow_enforcement==="off"||rawGovernance.workflow_enforcement==="warn"||rawGovernance.workflow_enforcement==="strict")&&(extras.workflow_enforcement=rawGovernance.workflow_enforcement),typeof rawGovernance.require_close_reason=="boolean"&&(extras.require_close_reason=rawGovernance.require_close_reason),DUPLICATE_DETECTION_MODES.has(String(rawGovernance.duplicate_detection_mode))&&(extras.duplicate_detection_mode=rawGovernance.duplicate_detection_mode);const threshold=rawGovernance.duplicate_detection_threshold;[typeof threshold=="number",Number.isFinite(threshold),Number(threshold)>=0,Number(threshold)<=1].every(Boolean)&&(extras.duplicate_detection_threshold=threshold);const limit=rawGovernance.duplicate_detection_limit;return[typeof limit=="number",Number.isSafeInteger(limit),Number(limit)>=0,Number(limit)<=20].every(Boolean)&&(extras.duplicate_detection_limit=limit),extras}function resolveGovernanceKnobs(settings){const rawGovernance=settings.governance??{},preset=normalizeGovernancePreset(rawGovernance.preset),extras=resolveGovernanceExtras(rawGovernance);if(preset==="custom"){const baseline2=resolveGovernanceKnobsFromPreset("default"),requireCloseReason2=extras.require_close_reason??baseline2.require_close_reason;return{preset,ownership_enforcement:rawGovernance.ownership_enforcement??baseline2.ownership_enforcement,create_mode_default:rawGovernance.create_mode_default??baseline2.create_mode_default,close_validation_default:rawGovernance.close_validation_default??baseline2.close_validation_default,parent_reference:rawGovernance.parent_reference??baseline2.parent_reference,metadata_profile:rawGovernance.metadata_profile??baseline2.metadata_profile,force_required_for_stale_lock:rawGovernance.force_required_for_stale_lock??baseline2.force_required_for_stale_lock,...extras,require_close_reason:requireCloseReason2,duplicate_detection_mode:extras.duplicate_detection_mode??baseline2.duplicate_detection_mode,duplicate_detection_threshold:extras.duplicate_detection_threshold??baseline2.duplicate_detection_threshold,duplicate_detection_limit:extras.duplicate_detection_limit??baseline2.duplicate_detection_limit}}const baseline=resolveGovernanceKnobsFromPreset(preset),requireCloseReason=extras.require_close_reason??baseline.require_close_reason;return{preset,...baseline,...extras,require_close_reason:requireCloseReason}}function cloneDefaults(){return structuredClone(SETTINGS_DEFAULTS)}function normalizeSearchMutationRefreshPolicy(value){return value==="cache_only"||value==="semantic_configured"||value==="semantic_auto"?value:SETTINGS_DEFAULTS.search.mutation_refresh_policy}function normalizeSearchDefaultMode(value){return value==="auto"||value==="keyword"||value==="semantic"||value==="hybrid"?value:"auto"}function normalizeSearchQueryExpansionEnabled(value){return typeof value=="boolean"?value:SETTINGS_DEFAULTS.search.query_expansion.enabled}function normalizeSearchQueryExpansionProvider(value){return typeof value!="string"?SETTINGS_DEFAULTS.search.query_expansion.provider:value.trim()}function normalizeSearchRerankEnabled(value){return typeof value=="boolean"?value:SETTINGS_DEFAULTS.search.rerank.enabled}function normalizeSearchRerankModel(value){return typeof value!="string"?SETTINGS_DEFAULTS.search.rerank.model:value.trim()}function normalizeSearchRerankTopK(value){return typeof value=="number"&&Number.isFinite(value)&&Number.isInteger(value)&&value>0?value:SETTINGS_DEFAULTS.search.rerank.top_k}function normalizeVectorStoreCollectionName(value){if(typeof value!="string")return SETTINGS_DEFAULTS.vector_store.collection_name;const truncated=value.trim().replaceAll(/[^a-zA-Z0-9_-]/g,"_").slice(0,MAX_VECTOR_STORE_COLLECTION_NAME_LENGTH);return truncated.length>0?truncated:SETTINGS_DEFAULTS.vector_store.collection_name}function cloneOptionalArray(value){return{present:Array.isArray(value),values:Array.isArray(value)?structuredClone(value):[]}}function buildSettingsPersistSourceSnapshot(parsedSettings,runtimeSettings){const sourceSchema=parsedSettings.schema,sourceStatuses=cloneOptionalArray(sourceSchema?.statuses),sourceFields=cloneOptionalArray(sourceSchema?.fields),sourceTypeWorkflows=cloneOptionalArray(sourceSchema?.type_workflows);return{persisted_settings:structuredClone(parsedSettings),source_settings:structuredClone(parsedSettings),has_source_item_type_definitions:Array.isArray(parsedSettings.item_types?.definitions),source_item_type_definitions:normalizeItemTypeDefinitions(parsedSettings.item_types?.definitions),has_source_schema_statuses:sourceStatuses.present,source_schema_statuses:sourceStatuses.values,has_source_schema_fields:sourceFields.present,source_schema_fields:sourceFields.values,has_source_schema_type_workflows:sourceTypeWorkflows.present,source_schema_type_workflows:sourceTypeWorkflows.values,runtime_item_type_definitions:normalizeItemTypeDefinitions(runtimeSettings.item_types?.definitions),runtime_schema_statuses:structuredClone(runtimeSettings.schema.statuses),runtime_schema_fields:structuredClone(runtimeSettings.schema.fields),runtime_schema_type_workflows:structuredClone(runtimeSettings.schema.type_workflows??[])}}function attachSettingsPersistSourceSnapshot(settings,source){Object.defineProperty(settings,SETTINGS_PERSIST_SOURCE_SYMBOL,{value:source,writable:!0,configurable:!0,enumerable:!1})}function getSettingsPersistSourceSnapshot(settings){const candidate=settings[SETTINGS_PERSIST_SOURCE_SYMBOL];if(!(!candidate||typeof candidate!="object"))return candidate}function persistSelectedItemFormat(settings){const source=getSettingsPersistSourceSnapshot(settings);if(source){const detachedSource=structuredClone(source);detachedSource.source_settings.item_format=settings.item_format,attachSettingsPersistSourceSnapshot(settings,detachedSource)}}function cloneSettingsReadResult(result){const clonedSettings=structuredClone(result.settings),persistSource=getSettingsPersistSourceSnapshot(result.settings);persistSource&&attachSettingsPersistSourceSnapshot(clonedSettings,persistSource);const fallbackOrigin=getSettingsFallbackOrigin(result.settings);return fallbackOrigin!==void 0&&markSettingsFallbackOrigin(clonedSettings,fallbackOrigin),{settings:clonedSettings,metadata:{has_explicit_item_format:result.metadata.has_explicit_item_format},warnings:[...result.warnings]}}function resolveSettingsReadTrackedPaths(pmRoot,schema,settingsPath){const normalizedSchema=normalizeRuntimeSchemaSettings(schema);return[settingsPath,filePathForSchemaSection(pmRoot,normalizedSchema.files.types,DEFAULT_RUNTIME_SCHEMA_FILE_PATHS.types),filePathForSchemaSection(pmRoot,normalizedSchema.files.statuses,DEFAULT_RUNTIME_SCHEMA_FILE_PATHS.statuses),filePathForSchemaSection(pmRoot,normalizedSchema.files.fields,DEFAULT_RUNTIME_SCHEMA_FILE_PATHS.fields),filePathForSchemaSection(pmRoot,normalizedSchema.files.workflows,DEFAULT_RUNTIME_SCHEMA_FILE_PATHS.workflows)]}async function cacheSettingsReadResult(pmRoot,trackedPaths,result){const signatures=await collectSettingsReadCacheSignatures(trackedPaths);setSettingsReadCacheEntry(pmRoot,{tracked_paths:trackedPaths,signatures,value:cloneSettingsReadResult(result)})}async function cacheSettingsReadResultSafe(pmRoot,trackedPaths,result){try{await cacheSettingsReadResult(pmRoot,trackedPaths,result)}catch{clearSettingsReadCache(pmRoot)}}function findSettingsReadCacheSignature(signatures,targetPath){return signatures.find(signature=>signature.path===targetPath)}function selectedSettingsReadCacheSignaturesEqual(before,after,targetPaths){for(const targetPath of targetPaths){const beforeSignature=findSettingsReadCacheSignature(before,targetPath),afterSignature=findSettingsReadCacheSignature(after,targetPath);if(!beforeSignature||!afterSignature||!settingsReadCacheSignaturesEqual([beforeSignature],[afterSignature]))return!1}return!0}async function cacheSettingsReadResultIfStable(pmRoot,trackedPaths,result,stableSignatures,stablePaths){try{const currentSignatures=await collectSettingsReadCacheSignatures(trackedPaths);if(!selectedSettingsReadCacheSignaturesEqual(stableSignatures,currentSignatures,stablePaths)){clearSettingsReadCache(pmRoot);return}setSettingsReadCacheEntry(pmRoot,{tracked_paths:trackedPaths,signatures:currentSignatures,value:cloneSettingsReadResult(result)})}catch{clearSettingsReadCache(pmRoot)}}function resolvePersistedFileBackedSchemaSections(settings,source){const normalizedSchema=normalizeRuntimeSchemaSettings(settings.schema),currentItemTypeDefinitions=normalizeItemTypeDefinitions(settings.item_types?.definitions);if(!source)return{item_type_definitions:currentItemTypeDefinitions,schema_statuses:normalizedSchema.statuses,schema_fields:normalizedSchema.fields,schema_type_workflows:normalizedSchema.type_workflows};const currentTypeWorkflows=normalizedSchema.type_workflows??[],itemTypeDefinitionsUnchanged=stableValueEquals(currentItemTypeDefinitions,source.runtime_item_type_definitions),schemaStatusesUnchanged=stableValueEquals(normalizedSchema.statuses,source.runtime_schema_statuses),schemaFieldsUnchanged=stableValueEquals(normalizedSchema.fields,source.runtime_schema_fields),schemaTypeWorkflowsUnchanged=stableValueEquals(currentTypeWorkflows,source.runtime_schema_type_workflows);return{item_type_definitions:itemTypeDefinitionsUnchanged?source.has_source_item_type_definitions?normalizeItemTypeDefinitions(source.source_item_type_definitions):[]:currentItemTypeDefinitions,schema_statuses:schemaStatusesUnchanged?source.has_source_schema_statuses?structuredClone(source.source_schema_statuses):[]:normalizedSchema.statuses,schema_fields:schemaFieldsUnchanged?source.has_source_schema_fields?structuredClone(source.source_schema_fields):[]:normalizedSchema.fields,schema_type_workflows:schemaTypeWorkflowsUnchanged?source.has_source_schema_type_workflows?structuredClone(source.source_schema_type_workflows):void 0:normalizedSchema.type_workflows}}function markSettingsFallbackOrigin(settings,warning){Object.defineProperty(settings,SETTINGS_FALLBACK_ORIGIN_SYMBOL,{value:warning,writable:!0,configurable:!0,enumerable:!1})}function isSettingsReadFallback(settings){return getSettingsFallbackOrigin(settings)!==void 0}function getSettingsFallbackOrigin(settings){const candidate=settings[SETTINGS_FALLBACK_ORIGIN_SYMBOL];return typeof candidate=="string"?candidate:void 0}function getSettingsFallbackBaseline(settings){return settings[SETTINGS_FALLBACK_BASELINE_SYMBOL]}function setSettingsFallbackBaseline(settings,baseline){Object.defineProperty(settings,SETTINGS_FALLBACK_BASELINE_SYMBOL,{value:baseline,writable:!0,configurable:!0,enumerable:!1})}function buildFallbackSettingsReadResult(warning){const settings=cloneDefaults();return warning!==void 0&&markSettingsFallbackOrigin(settings,warning),{settings,metadata:{has_explicit_item_format:!1},warnings:warning?[warning]:[]}}function hasExplicitItemFormat(raw){if(typeof raw!="object"||raw===null||Array.isArray(raw))return!1;const itemFormat=raw.item_format;return itemFormat==="toon"||itemFormat==="json_markdown"}function normalizeStringList(values){return[...new Set((values??[]).map(value=>value.trim()).filter(value=>value.length>0))].sort((left,right)=>left.localeCompare(right))}function normalizeAgentGuidanceSettings(value){const defaults=SETTINGS_DEFAULTS.agent_guidance,templateVersion=value?.template_version;return{prompt_completed:value?.prompt_completed===!0,declined:value?.declined===!0,declined_at:typeof value?.declined_at=="string"?value.declined_at:defaults.declined_at,template_version:typeof templateVersion=="number"&&Number.isInteger(templateVersion)&&templateVersion>0?templateVersion:defaults.template_version,last_checked_files:normalizeStringList(value?.last_checked_files??defaults.last_checked_files)}}function normalizeLowerStringList(values){return[...new Set((values??[]).map(value=>value.trim().toLowerCase()).filter(value=>value.length>0))].sort((left,right)=>left.localeCompare(right))}function normalizeExtensionPolicyMode(value){return value==="off"||value==="warn"||value==="enforce"?value:SETTINGS_DEFAULTS.extensions.policy.mode}function normalizeExtensionTrustMode(value){return value==="off"||value==="warn"||value==="enforce"?value:SETTINGS_DEFAULTS.extensions.policy.trust_mode}function normalizeExtensionSandboxProfile(value){return value==="none"||value==="restricted"||value==="strict"?value:SETTINGS_DEFAULTS.extensions.policy.default_sandbox_profile}function normalizeExtensionPolicyOverride(override){const name=override.name.trim().toLowerCase();if(name.length===0)return null;const normalized={name};override.disabled===!0&&(normalized.disabled=!0),override.require_trusted===!0&&(normalized.require_trusted=!0),override.require_provenance===!0&&(normalized.require_provenance=!0),override.sandbox_profile!==void 0&&(normalized.sandbox_profile=normalizeExtensionSandboxProfile(override.sandbox_profile));const allowedCapabilities=normalizeLowerStringList(override.allowed_capabilities),blockedCapabilities=normalizeLowerStringList(override.blocked_capabilities),allowedSurfaces=normalizeLowerStringList(override.allowed_surfaces),blockedSurfaces=normalizeLowerStringList(override.blocked_surfaces),allowedCommands=normalizeLowerStringList(override.allowed_commands),blockedCommands=normalizeLowerStringList(override.blocked_commands),allowedActions=normalizeLowerStringList(override.allowed_actions),blockedActions=normalizeLowerStringList(override.blocked_actions),allowedServices=normalizeLowerStringList(override.allowed_services),blockedServices=normalizeLowerStringList(override.blocked_services);return allowedCapabilities.length>0&&(normalized.allowed_capabilities=allowedCapabilities),blockedCapabilities.length>0&&(normalized.blocked_capabilities=blockedCapabilities),allowedSurfaces.length>0&&(normalized.allowed_surfaces=allowedSurfaces),blockedSurfaces.length>0&&(normalized.blocked_surfaces=blockedSurfaces),allowedCommands.length>0&&(normalized.allowed_commands=allowedCommands),blockedCommands.length>0&&(normalized.blocked_commands=blockedCommands),allowedActions.length>0&&(normalized.allowed_actions=allowedActions),blockedActions.length>0&&(normalized.blocked_actions=blockedActions),allowedServices.length>0&&(normalized.allowed_services=allowedServices),blockedServices.length>0&&(normalized.blocked_services=blockedServices),normalized}function normalizeExtensionPolicyOverrides(overrides){const dedupedByName=new Map;for(const override of overrides??[]){const normalized=normalizeExtensionPolicyOverride(override);normalized&&dedupedByName.set(normalized.name,normalized)}return[...dedupedByName.values()].sort((left,right)=>left.name.localeCompare(right.name))}function normalizePmMaxVersionExceededModeValue(value){return value==="block"||value==="warn"?value:void 0}function normalizePmMaxVersionExceededModeSetting(value){if(typeof value=="string")return normalizePmMaxVersionExceededModeValue(value);if(typeof value=="object"&&value!==null&&!Array.isArray(value)){const global2=normalizePmMaxVersionExceededModeValue(value.global),project=normalizePmMaxVersionExceededModeValue(value.project);return global2===void 0&&project===void 0?void 0:{...global2!==void 0?{global:global2}:{},...project!==void 0?{project}:{}}}}function normalizeExtensionPolicyList(policy,key){return normalizeLowerStringList(policy?.[key]??SETTINGS_DEFAULTS.extensions.policy[key])}function normalizeExtensionPolicySettings(policy){const pmMaxVersionExceededMode=normalizePmMaxVersionExceededModeSetting(policy?.pm_max_version_exceeded_mode);return{mode:normalizeExtensionPolicyMode(policy?.mode),trust_mode:normalizeExtensionTrustMode(policy?.trust_mode),...pmMaxVersionExceededMode!==void 0?{pm_max_version_exceeded_mode:pmMaxVersionExceededMode}:{},require_provenance:policy?.require_provenance===!0,trusted_extensions:normalizeExtensionPolicyList(policy,"trusted_extensions"),default_sandbox_profile:normalizeExtensionSandboxProfile(policy?.default_sandbox_profile),allowed_extensions:normalizeExtensionPolicyList(policy,"allowed_extensions"),blocked_extensions:normalizeExtensionPolicyList(policy,"blocked_extensions"),allowed_capabilities:normalizeExtensionPolicyList(policy,"allowed_capabilities"),blocked_capabilities:normalizeExtensionPolicyList(policy,"blocked_capabilities"),allowed_surfaces:normalizeExtensionPolicyList(policy,"allowed_surfaces"),blocked_surfaces:normalizeExtensionPolicyList(policy,"blocked_surfaces"),allowed_commands:normalizeExtensionPolicyList(policy,"allowed_commands"),blocked_commands:normalizeExtensionPolicyList(policy,"blocked_commands"),allowed_actions:normalizeExtensionPolicyList(policy,"allowed_actions"),blocked_actions:normalizeExtensionPolicyList(policy,"blocked_actions"),allowed_services:normalizeExtensionPolicyList(policy,"allowed_services"),blocked_services:normalizeExtensionPolicyList(policy,"blocked_services"),extension_overrides:normalizeExtensionPolicyOverrides(policy?.extension_overrides??SETTINGS_DEFAULTS.extensions.policy.extension_overrides)}}function normalizeValidationMetadataRequiredFields(values){return[...new Set((values??[]).map(value=>value.trim().toLowerCase().replaceAll("-","_")))].filter(value=>value.length>0).sort((left,right)=>left.localeCompare(right)).filter(value=>["author","acceptance_criteria","estimated_minutes","close_reason","reviewer","risk","confidence","sprint","release"].includes(value))}function normalizeValidationPatternList(values){return[...new Set((values??[]).map(value=>value.trim().toLowerCase()).filter(value=>value.length>0))].sort((left,right)=>left.localeCompare(right))}function valueOrDefault(value,fallback){return value===void 0?fallback:value}function recordOrEmpty(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)?value:{}}function arrayOrEmpty(value){return Array.isArray(value)?value:[]}function buildValidationSettings(settings,defaults,governance){return{...defaults.validation,...settings.validation,parent_reference:governance.parent_reference,metadata_profile:governance.metadata_profile,metadata_required_fields:normalizeValidationMetadataRequiredFields(settings.validation?.metadata_required_fields),lifecycle_stale_blocker_reason_patterns:normalizeValidationPatternList(settings.validation?.lifecycle_stale_blocker_reason_patterns??defaults.validation.lifecycle_stale_blocker_reason_patterns),lifecycle_closure_like_blocked_reason_patterns:normalizeValidationPatternList(settings.validation?.lifecycle_closure_like_blocked_reason_patterns??defaults.validation.lifecycle_closure_like_blocked_reason_patterns),lifecycle_closure_like_resolution_patterns:normalizeValidationPatternList(settings.validation?.lifecycle_closure_like_resolution_patterns??defaults.validation.lifecycle_closure_like_resolution_patterns),lifecycle_closure_like_actual_result_patterns:normalizeValidationPatternList(settings.validation?.lifecycle_closure_like_actual_result_patterns??defaults.validation.lifecycle_closure_like_actual_result_patterns),estimate_defaults_by_type:normalizeEstimateDefaultOverrides(settings.validation?.estimate_defaults_by_type)}}function buildTelemetrySettings(settings,defaults){return{enabled:settings.telemetry?.enabled??defaults.telemetry.enabled,first_run_prompt_completed:settings.telemetry?.first_run_prompt_completed??defaults.telemetry.first_run_prompt_completed,capture_level:settings.telemetry?.capture_level??defaults.telemetry.capture_level,endpoint:settings.telemetry?.endpoint??defaults.telemetry.endpoint,installation_id:settings.telemetry?.installation_id??defaults.telemetry.installation_id,retention_days:settings.telemetry?.retention_days??defaults.telemetry.retention_days}}function buildSearchSettings(settings,defaults){return{...defaults.search,...settings.search,default_mode:normalizeSearchDefaultMode(settings.search?.default_mode),mutation_refresh_policy:normalizeSearchMutationRefreshPolicy(settings.search?.mutation_refresh_policy),query_expansion:{...defaults.search.query_expansion,...settings.search?.query_expansion,enabled:normalizeSearchQueryExpansionEnabled(settings.search?.query_expansion?.enabled),provider:normalizeSearchQueryExpansionProvider(settings.search?.query_expansion?.provider)},rerank:{...defaults.search.rerank,...settings.search?.rerank,enabled:normalizeSearchRerankEnabled(settings.search?.rerank?.enabled),model:normalizeSearchRerankModel(settings.search?.rerank?.model),top_k:normalizeSearchRerankTopK(settings.search?.rerank?.top_k)}}}function buildVectorStoreSettings(settings,defaults){return{adapter:settings.vector_store.adapter??defaults.vector_store.adapter,collection_name:normalizeVectorStoreCollectionName(settings.vector_store.collection_name),qdrant:{...defaults.vector_store.qdrant,...settings.vector_store.qdrant},lancedb:{...defaults.vector_store.lancedb,...settings.vector_store.lancedb}}}function normalizeSettingsItemFormat(settings,defaults){return settings.item_format==="json_markdown"?"toon":settings.item_format??defaults.item_format}function buildContextSettings(settings,defaults){return{default_depth:settings.context?.default_depth??defaults.context.default_depth,activity_limit:settings.context?.activity_limit??defaults.context.activity_limit,stale_threshold_days:settings.context?.stale_threshold_days??defaults.context.stale_threshold_days,next_ranking_policy:settings.context?.next_ranking_policy??defaults.context.next_ranking_policy,sections:{...defaults.context.sections,...settings.context?.sections}}}function buildProviderSettings(settings,defaults){return{openai:{...defaults.providers.openai,...settings.providers.openai},ollama:{...defaults.providers.ollama,...settings.providers.ollama}}}function normalizeItemTypeDefinitions(definitions){const normalized=(definitions??[]).map(definition=>normalizeItemTypeDefinition(definition)).filter(definition=>definition!==null),dedupedByName=new Map;for(const definition of normalized)dedupedByName.set(definition.name.toLowerCase(),definition);return[...dedupedByName.values()].sort((left,right)=>left.name.localeCompare(right.name))}function mergeSettings(settings){const defaults=cloneDefaults(),governance=resolveGovernanceKnobs({governance:settings.governance??{preset:"default"}});return{...defaults,...settings,item_format:normalizeSettingsItemFormat(settings,defaults),locks:{...defaults.locks,...settings.locks},ids:{...defaults.ids,...settings.ids},agent_identity:structuredClone(settings.agent_identity??defaults.agent_identity),mutation_guard:{...defaults.mutation_guard,...settings.mutation_guard},checkpoints:{...defaults.checkpoints,...settings.checkpoints},output:{...defaults.output,...settings.output},ux:{...defaults.ux,...settings.ux},history:{...defaults.history,...settings.history,compact_policy:{...defaults.history.compact_policy,...settings.history?.compact_policy}},validation:buildValidationSettings(settings,defaults,governance),governance,workflow:{definition_of_done:[...settings.workflow?.definition_of_done??defaults.workflow.definition_of_done]},testing:{record_results_to_items:settings.testing?.record_results_to_items??defaults.testing.record_results_to_items,allow_untrusted_linked_tests:settings.testing?.allow_untrusted_linked_tests??defaults.testing.allow_untrusted_linked_tests},telemetry:buildTelemetrySettings(settings,defaults),agent_guidance:normalizeAgentGuidanceSettings(settings.agent_guidance??defaults.agent_guidance),item_types:{definitions:normalizeItemTypeDefinitions(settings.item_types?.definitions)},schema:normalizeRuntimeSchemaSettings(settings.schema??defaults.schema),context:buildContextSettings(settings,defaults),extensions:{enabled:[...settings.extensions.enabled],disabled:[...settings.extensions.disabled],policy:normalizeExtensionPolicySettings(settings.extensions.policy??defaults.extensions.policy)},search:buildSearchSettings(settings,defaults),providers:buildProviderSettings(settings,defaults),vector_store:buildVectorStoreSettings(settings,defaults)}}function orderSerializedSettingsSections(ordered){ordered.agent_identity=orderObject(ordered.agent_identity,["probes_enabled","identity_vocabulary","harness_signals"]);const orderedAgentIdentity=ordered.agent_identity;Object.hasOwn(orderedAgentIdentity,"identity_vocabulary")&&(orderedAgentIdentity.identity_vocabulary=orderObject(recordOrEmpty(orderedAgentIdentity.identity_vocabulary),["version","aliases"])),ordered.agent_identity.harness_signals=arrayOrEmpty(ordered.agent_identity.harness_signals).map(entry=>orderObject(recordOrEmpty(entry),["harness","environment_keys","model_environment_keys","session_environment_keys","provenance_environment_keys","provenance_resolvers","provenance_unavailable_dimensions","argv_markers","client_names"])),ordered.locks=orderObject(ordered.locks,["ttl_seconds","wait_ms"]),ordered.ids=orderObject(ordered.ids,["token_length"]),ordered.mutation_guard=orderObject(ordered.mutation_guard,["require_attributed_author","secret_guard","stale_in_progress_hours"]),ordered.checkpoints=orderObject(ordered.checkpoints,["retention_days"]),ordered.output=orderObject(ordered.output,["default_format"]),ordered.ux=orderObject(ordered.ux,["deprecation_hints"]),ordered.history=orderObject(ordered.history,["missing_stream","compact_policy"]),ordered.validation=orderObject(ordered.validation,["sprint_release_format","parent_reference","metadata_profile","metadata_required_fields","lifecycle_stale_blocker_reason_patterns","lifecycle_closure_like_blocked_reason_patterns","lifecycle_closure_like_resolution_patterns","lifecycle_closure_like_actual_result_patterns","estimate_defaults_by_type"]),ordered.governance=orderObject(ordered.governance,["preset","ownership_enforcement","create_mode_default","close_validation_default","require_close_reason","parent_reference","metadata_profile","force_required_for_stale_lock","create_default_type","workflow_enforcement","duplicate_detection_mode","duplicate_detection_threshold","duplicate_detection_limit"]),ordered.workflow=orderObject(ordered.workflow,["definition_of_done"]),ordered.testing=orderObject(ordered.testing,["record_results_to_items","allow_untrusted_linked_tests"]),ordered.telemetry=orderObject(ordered.telemetry,["enabled","first_run_prompt_completed","capture_level","endpoint","installation_id","retention_days"]),ordered.agent_guidance=orderObject(ordered.agent_guidance,["prompt_completed","declined","declined_at","template_version","last_checked_files"]),ordered.item_types=orderObject(ordered.item_types,["definitions"]),ordered.schema=orderObject(ordered.schema,["version","files","statuses","fields","workflow","type_workflows","unknown_field_policy"]),ordered.schema.files=orderObject(recordOrEmpty(ordered.schema.files),["types","statuses","fields","workflows"]),ordered.schema.workflow=orderObject(recordOrEmpty(ordered.schema.workflow),["draft_status","open_status","in_progress_status","blocked_status","close_status","canceled_status"]),ordered.context=orderObject(ordered.context,["default_depth","activity_limit","stale_threshold_days","next_ranking_policy","sections"]),ordered.context.sections=orderObject(recordOrEmpty(ordered.context.sections),["hierarchy","activity","progress","blockers","files","workload","staleness","tests"]),ordered.extensions=orderObject(ordered.extensions,["enabled","disabled","policy"]),ordered.extensions.policy=orderObject(recordOrEmpty(ordered.extensions.policy),["mode","trust_mode","pm_max_version_exceeded_mode","require_provenance","trusted_extensions","default_sandbox_profile","allowed_extensions","blocked_extensions","allowed_capabilities","blocked_capabilities","allowed_surfaces","blocked_surfaces","allowed_commands","blocked_commands","allowed_actions","blocked_actions","allowed_services","blocked_services","extension_overrides"]),ordered.extensions.policy.extension_overrides=arrayOrEmpty(ordered.extensions.policy.extension_overrides).map(entry=>orderObject(recordOrEmpty(entry),["name","disabled","require_trusted","require_provenance","sandbox_profile","allowed_capabilities","blocked_capabilities","allowed_surfaces","blocked_surfaces","allowed_commands","blocked_commands","allowed_actions","blocked_actions","allowed_services","blocked_services"])),ordered.search=orderObject(ordered.search,["score_threshold","hybrid_semantic_weight","max_results","embedding_model","embedding_corpus_max_characters","embedding_batch_size","embedding_timeout_ms","scanner_max_batch_retries","provider","default_mode","mutation_refresh_policy","query_expansion","rerank"]),ordered.search.query_expansion=orderObject(recordOrEmpty(ordered.search.query_expansion),["enabled","provider"]),ordered.search.rerank=orderObject(recordOrEmpty(ordered.search.rerank),["enabled","model","top_k"]),ordered.providers=orderObject(ordered.providers,["openai","ollama"]),ordered.providers.openai=orderObject(recordOrEmpty(ordered.providers.openai),["base_url","api_key","model"]),ordered.providers.ollama=orderObject(recordOrEmpty(ordered.providers.ollama),["base_url","model"]),ordered.vector_store=orderObject(ordered.vector_store,["adapter","collection_name","qdrant","lancedb"]),ordered.vector_store.qdrant=orderObject(recordOrEmpty(ordered.vector_store.qdrant),["url","api_key"]),ordered.vector_store.lancedb=orderObject(recordOrEmpty(ordered.vector_store.lancedb),["path"])}function buildSerializeBaseSettings(settings){return{...settings,locks:valueOrDefault(settings.locks,SETTINGS_DEFAULTS.locks),ids:valueOrDefault(settings.ids,SETTINGS_DEFAULTS.ids),agent_identity:valueOrDefault(settings.agent_identity,SETTINGS_DEFAULTS.agent_identity),mutation_guard:valueOrDefault(settings.mutation_guard,SETTINGS_DEFAULTS.mutation_guard),checkpoints:valueOrDefault(settings.checkpoints,SETTINGS_DEFAULTS.checkpoints),output:valueOrDefault(settings.output,SETTINGS_DEFAULTS.output),ux:valueOrDefault(settings.ux,SETTINGS_DEFAULTS.ux),history:valueOrDefault(settings.history,SETTINGS_DEFAULTS.history),validation:valueOrDefault(settings.validation,SETTINGS_DEFAULTS.validation),workflow:valueOrDefault(settings.workflow,SETTINGS_DEFAULTS.workflow),testing:valueOrDefault(settings.testing,SETTINGS_DEFAULTS.testing),telemetry:valueOrDefault(settings.telemetry,SETTINGS_DEFAULTS.telemetry),agent_guidance:valueOrDefault(settings.agent_guidance,SETTINGS_DEFAULTS.agent_guidance),item_types:valueOrDefault(settings.item_types,SETTINGS_DEFAULTS.item_types),schema:valueOrDefault(settings.schema,SETTINGS_DEFAULTS.schema),context:valueOrDefault(settings.context,SETTINGS_DEFAULTS.context),extensions:valueOrDefault(settings.extensions,SETTINGS_DEFAULTS.extensions),search:valueOrDefault(settings.search,SETTINGS_DEFAULTS.search),providers:valueOrDefault(settings.providers,SETTINGS_DEFAULTS.providers),vector_store:valueOrDefault(settings.vector_store,SETTINGS_DEFAULTS.vector_store)}}function buildSerializedValidationSettings(baseSettings,governance){return{...baseSettings.validation,parent_reference:governance.parent_reference,metadata_profile:governance.metadata_profile,metadata_required_fields:normalizeValidationMetadataRequiredFields(baseSettings.validation?.metadata_required_fields),lifecycle_stale_blocker_reason_patterns:normalizeValidationPatternList(baseSettings.validation?.lifecycle_stale_blocker_reason_patterns??SETTINGS_DEFAULTS.validation.lifecycle_stale_blocker_reason_patterns),lifecycle_closure_like_blocked_reason_patterns:normalizeValidationPatternList(baseSettings.validation?.lifecycle_closure_like_blocked_reason_patterns??SETTINGS_DEFAULTS.validation.lifecycle_closure_like_blocked_reason_patterns),lifecycle_closure_like_resolution_patterns:normalizeValidationPatternList(baseSettings.validation?.lifecycle_closure_like_resolution_patterns??SETTINGS_DEFAULTS.validation.lifecycle_closure_like_resolution_patterns),lifecycle_closure_like_actual_result_patterns:normalizeValidationPatternList(baseSettings.validation?.lifecycle_closure_like_actual_result_patterns??SETTINGS_DEFAULTS.validation.lifecycle_closure_like_actual_result_patterns),estimate_defaults_by_type:normalizeEstimateDefaultOverrides(baseSettings.validation?.estimate_defaults_by_type)}}function buildSerializedSearchSettings(baseSettings){return{...SETTINGS_DEFAULTS.search,...baseSettings.search,default_mode:normalizeSearchDefaultMode(baseSettings.search?.default_mode),mutation_refresh_policy:normalizeSearchMutationRefreshPolicy(baseSettings.search?.mutation_refresh_policy),query_expansion:{...SETTINGS_DEFAULTS.search.query_expansion,...baseSettings.search?.query_expansion,enabled:normalizeSearchQueryExpansionEnabled(baseSettings.search?.query_expansion?.enabled),provider:normalizeSearchQueryExpansionProvider(baseSettings.search?.query_expansion?.provider)},rerank:{...SETTINGS_DEFAULTS.search.rerank,...baseSettings.search?.rerank,enabled:normalizeSearchRerankEnabled(baseSettings.search?.rerank?.enabled),model:normalizeSearchRerankModel(baseSettings.search?.rerank?.model),top_k:normalizeSearchRerankTopK(baseSettings.search?.rerank?.top_k)}}}function buildSerializedContextSettings(baseSettings){return{default_depth:baseSettings.context?.default_depth??SETTINGS_DEFAULTS.context.default_depth,activity_limit:baseSettings.context?.activity_limit??SETTINGS_DEFAULTS.context.activity_limit,stale_threshold_days:baseSettings.context?.stale_threshold_days??SETTINGS_DEFAULTS.context.stale_threshold_days,next_ranking_policy:baseSettings.context?.next_ranking_policy??SETTINGS_DEFAULTS.context.next_ranking_policy,sections:{...SETTINGS_DEFAULTS.context.sections,...baseSettings.context?.sections}}}function buildSerializedVectorStoreSettings(baseSettings){return{...baseSettings.vector_store,adapter:baseSettings.vector_store?.adapter??SETTINGS_DEFAULTS.vector_store.adapter,collection_name:normalizeVectorStoreCollectionName(baseSettings.vector_store?.collection_name),qdrant:{...baseSettings.vector_store?.qdrant},lancedb:{...baseSettings.vector_store?.lancedb}}}function buildNormalizedSettingsForSerialization(baseSettings,governance,normalizedSchema,persistedFileBackedSections){return{...baseSettings,item_format:"toon",validation:buildSerializedValidationSettings(baseSettings,governance),governance,agent_guidance:normalizeAgentGuidanceSettings(baseSettings.agent_guidance),item_types:{definitions:persistedFileBackedSections.item_type_definitions},schema:{...normalizedSchema,statuses:persistedFileBackedSections.schema_statuses,fields:persistedFileBackedSections.schema_fields,type_workflows:persistedFileBackedSections.schema_type_workflows},search:buildSerializedSearchSettings(baseSettings),context:buildSerializedContextSettings(baseSettings),extensions:{enabled:normalizeStringList(baseSettings.extensions?.enabled),disabled:normalizeStringList(baseSettings.extensions?.disabled),policy:normalizeExtensionPolicySettings(baseSettings.extensions?.policy)},vector_store:buildSerializedVectorStoreSettings(baseSettings)}}function overlayPresentSettingsSource(target,source){for(const key of Object.keys(source)){const value=Reflect.get(source,key),existing=target[key];typeof value=="object"&&value!==null&&!Array.isArray(value)&&typeof existing=="object"&&existing!==null&&!Array.isArray(existing)?overlayPresentSettingsSource(existing,value):target[key]=structuredClone(value)}}function applySettingsDelta(target,baseline,current){const keys=new Set([...Object.keys(baseline),...Object.keys(current)]);for(const key of keys){const before=baseline[key],after=current[key];if(!stableValueEquals(before,after)){if(after===void 0){delete target[key];continue}if(typeof before=="object"&&before!==null&&!Array.isArray(before)&&typeof after=="object"&&after!==null&&!Array.isArray(after)){const existing=target[key],nestedTarget=typeof existing=="object"&&existing!==null&&!Array.isArray(existing)?existing:{};applySettingsDelta(nestedTarget,before,after),Object.keys(nestedTarget).length>0?target[key]=nestedTarget:delete target[key];continue}target[key]=structuredClone(after)}}}const SETTINGS_TOP_LEVEL_KEY_ORDER=["version","id_prefix","ids","author_default","agent_identity","mutation_guard","item_format","locks","checkpoints","output","ux","history","validation","governance","workflow","testing","telemetry","agent_guidance","item_types","schema","context","extensions","search","providers","vector_store"];function buildOrderedSettingsForSerialization(settings,persistSource){const baseSettings=buildSerializeBaseSettings(settings),governance=resolveGovernanceKnobs(baseSettings),normalizedSchema=normalizeRuntimeSchemaSettings(baseSettings.schema),persistedFileBackedSections=resolvePersistedFileBackedSchemaSections(baseSettings,persistSource),normalizedSettings=buildNormalizedSettingsForSerialization(baseSettings,governance,normalizedSchema,persistedFileBackedSections),ordered=orderObject({...normalizedSettings,governance:normalizeGovernanceForPersist(governance)},SETTINGS_TOP_LEVEL_KEY_ORDER);return orderSerializedSettingsSections(ordered),ordered}function serializeSettings(settings,options={}){const persistSource=options.source===void 0?options.persist_source:buildSettingsPersistSourceSnapshot(options.source.validated,mergeSettings(options.source.validated)),ordered=buildOrderedSettingsForSerialization(settings,persistSource);if(persistSource){const baselineSettings=mergeSettings(persistSource.source_settings);baselineSettings.item_types={definitions:structuredClone(persistSource.runtime_item_type_definitions)},baselineSettings.schema={...baselineSettings.schema,statuses:structuredClone(persistSource.runtime_schema_statuses),fields:structuredClone(persistSource.runtime_schema_fields),type_workflows:structuredClone(persistSource.runtime_schema_type_workflows)};const baseline=buildOrderedSettingsForSerialization(baselineSettings,persistSource);options.source!==void 0&&overlayPresentSettingsSource(baseline,options.source.validated);const sparse=structuredClone(options.source===void 0?persistSource.source_settings:options.source.raw);return applySettingsDelta(sparse,baseline,ordered),`${JSON.stringify(orderObject(sparse,SETTINGS_TOP_LEVEL_KEY_ORDER),null,2)}
2
2
  `}return`${JSON.stringify(ordered,null,2)}
3
- `}async function readConfigurationOnlySettings(pmRoot){let root;try{root=await realpath(pmRoot)}catch(error){if(isFileAbsentError(error))return buildFallbackSettingsReadResult();throw error}const file=getSettingsPath(root);let entry;try{entry=await lstat(file)}catch(error){if(isFileAbsentError(error))return buildFallbackSettingsReadResult();throw error}if(!entry.isFile())throw transactionPreviewNonRegularFileError("settings.json");let raw;try{raw=await readRegularFile(file,transactionPreviewNonRegularFileError("settings.json"))}catch(error){if(isFileAbsentError(error))return buildFallbackSettingsReadResult();throw error}let parsed;try{parsed=JSON.parse(raw)}catch{return buildFallbackSettingsReadResult("settings_read_invalid_json")}const validated=validateSettings(parsed);return validated.success?{settings:mergeSettings(validated.data),metadata:{has_explicit_item_format:hasExplicitItemFormat(parsed)},warnings:validated.data.item_format==="json_markdown"?["settings_item_format_legacy_json_markdown_coerced_to_toon"]:[]}:buildFallbackSettingsReadResult("settings_read_invalid_schema")}async function readSettingsWithMetadata(pmRoot){if(isConfigurationOnlySettingsRead(pmRoot))return readConfigurationOnlySettings(pmRoot);const settingsPath=getSettingsPath(pmRoot);let trackedPathsForFailure=[settingsPath];await runActiveOnReadHooks({path:settingsPath,scope:"project"});const cachedResult=getSettingsReadCacheEntry(pmRoot);if(cachedResult){const currentSignatures=await collectSettingsReadCacheSignatures(cachedResult.tracked_paths);if(settingsReadCacheSignaturesEqual(currentSignatures,cachedResult.signatures))return cloneSettingsReadResult(cachedResult.value)}const settingsOnlySignatures=await collectSettingsReadCacheSignatures([settingsPath]);let raw;try{raw=await readFileIfExists(settingsPath)}catch{return buildFallbackSettingsReadResult("settings_read_fs_error")}if(raw===null){const fallback=buildFallbackSettingsReadResult();return await cacheSettingsReadResultIfStable(pmRoot,[settingsPath],fallback,settingsOnlySignatures,[settingsPath]),fallback}const settingsSignaturesAfterRead=await collectSettingsReadCacheSignatures([settingsPath]);if(!settingsReadCacheSignaturesEqual(settingsOnlySignatures,settingsSignaturesAfterRead))return clearSettingsReadCache(pmRoot),readSettingsWithMetadata(pmRoot);let parsed;try{parsed=JSON.parse(raw)}catch{const fallback=buildFallbackSettingsReadResult("settings_read_invalid_json");return await cacheSettingsReadResultIfStable(pmRoot,[settingsPath],fallback,settingsSignaturesAfterRead,[settingsPath]),fallback}const validated=validateSettings(parsed);if(!validated.success){const fallback=buildFallbackSettingsReadResult("settings_read_invalid_schema");return await cacheSettingsReadResultIfStable(pmRoot,[settingsPath],fallback,settingsSignaturesAfterRead,[settingsPath]),fallback}try{const mergedSettings=mergeSettings(validated.data),trackedPaths=resolveSettingsReadTrackedPaths(pmRoot,mergedSettings.schema,settingsPath);trackedPathsForFailure=trackedPaths;const signaturesBeforeSchemaLoad=await collectSettingsReadCacheSignatures(trackedPaths),loadedSchemaSections=await loadRuntimeSchemaFromOptionalFiles(pmRoot,mergedSettings.schema),signaturesAfterSchemaLoad=await collectSettingsReadCacheSignatures(trackedPaths),settings={...mergedSettings,item_types:{definitions:normalizeItemTypeDefinitions([...mergedSettings.item_types.definitions,...arrayOrEmpty(loadedSchemaSections.type_definitions_from_file)])},schema:loadedSchemaSections.schema};attachSettingsPersistSourceSnapshot(settings,buildSettingsPersistSourceSnapshot(validated.data,settings));const result={settings,metadata:{has_explicit_item_format:hasExplicitItemFormat(parsed)},warnings:[...validated.data.item_format==="json_markdown"?["settings_item_format_legacy_json_markdown_coerced_to_toon"]:[],...loadedSchemaSections.warnings]};return settingsReadCacheSignaturesEqual(signaturesBeforeSchemaLoad,signaturesAfterSchemaLoad)?setSettingsReadCacheEntry(pmRoot,{tracked_paths:trackedPaths,signatures:signaturesAfterSchemaLoad,value:cloneSettingsReadResult(result)}):clearSettingsReadCache(pmRoot),result}catch{const fallback=buildFallbackSettingsReadResult("settings_read_merge_failed");return await cacheSettingsReadResultSafe(pmRoot,trackedPathsForFailure,fallback),fallback}}async function readSettings(pmRoot){return(await readSettingsWithMetadata(pmRoot)).settings}async function writeSettings(pmRoot,settings,op=SETTINGS_WRITE_OP){const settingsPath=getSettingsPath(pmRoot),source=getSettingsPersistSourceSnapshot(settings),afterRaw=serializeSettings(settings,{persist_source:source}),proposed=JSON.parse(afterRaw);try{await mutateWorkspaceJsonWithHistory({pmRoot,filePath:settingsPath,mutate:beforeRaw=>{let current=null;if(beforeRaw!==null)try{current=JSON.parse(beforeRaw)}catch{throw new PmCliError("Existing settings.json is malformed; the settings write was refused.",EXIT_CODE.USAGE,{code:"settings_write_invalid_existing_json",reason:"existing_settings_json_malformed",why:"Writing defaults over malformed settings could destroy intended project configuration.",nextSteps:["Repair the syntax in .agents/pm/settings.json, then retry the original command.","Run pm health to confirm the settings warning has cleared."]})}return{raw:source?`${JSON.stringify(orderObject(reconcileSettingsSnapshot(source.persisted_settings,proposed,current),SETTINGS_TOP_LEVEL_KEY_ORDER),null,2)}
4
- `:afterRaw,result:void 0}},op,author:resolveAuthor(void 0,settings.author_default),lockTtlSeconds:settings.locks.ttl_seconds,lockWaitMs:settings.locks.wait_ms,recordCreation:!1}),source&&attachSettingsPersistSourceSnapshot(settings,{...source,persisted_settings:structuredClone(proposed)}),await runActiveOnWriteHooks({path:settingsPath,scope:"project",op})}finally{clearSettingsReadCache(pmRoot)}}const settingsStoreTestOnly={applySettingsDelta,hasExplicitItemFormat,buildSettingsPersistSourceSnapshot,cacheSettingsReadResultIfStable,cacheSettingsReadResultSafe,mergeSettings,normalizeExtensionPolicySettings,normalizeExtensionPolicyOverride,normalizeExtensionPolicyOverrides,normalizeExtensionPolicyMode,normalizePmMaxVersionExceededModeSetting,normalizeExtensionSandboxProfile,normalizeExtensionTrustMode,normalizeLowerStringList,normalizeStringList,valueOrDefault,arrayOrEmpty,normalizeValidationPatternList,normalizeValidationMetadataRequiredFields,resolveSettingsReadTrackedPaths,resolvePersistedFileBackedSchemaSections,selectedSettingsReadCacheSignaturesEqual};export{isConfigurationOnlySettingsRead,mergeSettings,normalizeItemTypeDefinitions,persistSelectedItemFormat,readSettings,readSettingsWithMetadata,resolveGovernanceKnobs,runWithConfigurationOnlySettings,serializeSettings,settingsStoreTestOnly,writeSettings};
3
+ `}async function readConfigurationOnlySettings(pmRoot){let root;try{root=await realpath(pmRoot)}catch(error){if(isFileAbsentError(error))return buildFallbackSettingsReadResult();throw error}const file=getSettingsPath(root);let entry;try{entry=await lstat(file)}catch(error){if(isFileAbsentError(error))return buildFallbackSettingsReadResult();throw error}if(!entry.isFile())throw transactionPreviewNonRegularFileError("settings.json");let raw;try{raw=await readRegularFile(file,transactionPreviewNonRegularFileError("settings.json"))}catch(error){if(isFileAbsentError(error))return buildFallbackSettingsReadResult();throw error}let parsed;try{parsed=JSON.parse(raw)}catch{return buildFallbackSettingsReadResult("settings_read_invalid_json")}const validated=validateSettings(parsed);return validated.success?{settings:mergeSettings(validated.data),metadata:{has_explicit_item_format:hasExplicitItemFormat(parsed)},warnings:validated.data.item_format==="json_markdown"?["settings_item_format_legacy_json_markdown_coerced_to_toon"]:[]}:buildFallbackSettingsReadResult("settings_read_invalid_schema")}async function readSettingsWithMetadata(pmRoot){if(isConfigurationOnlySettingsRead(pmRoot))return readConfigurationOnlySettings(pmRoot);const settingsPath=getSettingsPath(pmRoot);let trackedPathsForFailure=[settingsPath];await runActiveOnReadHooks({path:settingsPath,scope:"project"});const cachedResult=getSettingsReadCacheEntry(pmRoot);if(cachedResult){const currentSignatures=await collectSettingsReadCacheSignatures(cachedResult.tracked_paths);if(settingsReadCacheSignaturesEqual(currentSignatures,cachedResult.signatures))return cloneSettingsReadResult(cachedResult.value)}const settingsOnlySignatures=await collectSettingsReadCacheSignatures([settingsPath]);let raw;try{raw=await readFileIfExists(settingsPath)}catch{return buildFallbackSettingsReadResult("settings_read_fs_error")}if(raw===null){const fallback=buildFallbackSettingsReadResult();return await cacheSettingsReadResultIfStable(pmRoot,[settingsPath],fallback,settingsOnlySignatures,[settingsPath]),fallback}const settingsSignaturesAfterRead=await collectSettingsReadCacheSignatures([settingsPath]);if(!settingsReadCacheSignaturesEqual(settingsOnlySignatures,settingsSignaturesAfterRead))return clearSettingsReadCache(pmRoot),readSettingsWithMetadata(pmRoot);let parsed;try{parsed=JSON.parse(raw)}catch{const fallback=buildFallbackSettingsReadResult("settings_read_invalid_json");return await cacheSettingsReadResultIfStable(pmRoot,[settingsPath],fallback,settingsSignaturesAfterRead,[settingsPath]),fallback}const validated=validateSettings(parsed);if(!validated.success){const fallback=buildFallbackSettingsReadResult("settings_read_invalid_schema");return await cacheSettingsReadResultIfStable(pmRoot,[settingsPath],fallback,settingsSignaturesAfterRead,[settingsPath]),fallback}try{const mergedSettings=mergeSettings(validated.data),trackedPaths=resolveSettingsReadTrackedPaths(pmRoot,mergedSettings.schema,settingsPath);trackedPathsForFailure=trackedPaths;const signaturesBeforeSchemaLoad=await collectSettingsReadCacheSignatures(trackedPaths),loadedSchemaSections=await loadRuntimeSchemaFromOptionalFiles(pmRoot,mergedSettings.schema),signaturesAfterSchemaLoad=await collectSettingsReadCacheSignatures(trackedPaths),settings={...mergedSettings,item_types:{definitions:normalizeItemTypeDefinitions([...mergedSettings.item_types.definitions,...arrayOrEmpty(loadedSchemaSections.type_definitions_from_file)])},schema:loadedSchemaSections.schema};attachSettingsPersistSourceSnapshot(settings,buildSettingsPersistSourceSnapshot(validated.data,settings));const result={settings,metadata:{has_explicit_item_format:hasExplicitItemFormat(parsed)},warnings:[...validated.data.item_format==="json_markdown"?["settings_item_format_legacy_json_markdown_coerced_to_toon"]:[],...loadedSchemaSections.warnings]};return settingsReadCacheSignaturesEqual(signaturesBeforeSchemaLoad,signaturesAfterSchemaLoad)?setSettingsReadCacheEntry(pmRoot,{tracked_paths:trackedPaths,signatures:signaturesAfterSchemaLoad,value:cloneSettingsReadResult(result)}):clearSettingsReadCache(pmRoot),result}catch{const fallback=buildFallbackSettingsReadResult("settings_read_merge_failed");return await cacheSettingsReadResultSafe(pmRoot,trackedPathsForFailure,fallback),fallback}}const ASSIGNED_SETTINGS_PATH_SEGMENT=/^[A-Za-z0-9_-]+$/u,RESERVED_SETTINGS_PATH_SEGMENTS=new Set(["__proto__","constructor","prototype"]);function asPlainRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)?value:void 0}function assertAssignedSettingsPaths(assignedPaths){for(const assignedPath of assignedPaths)if(assignedPath.split(".").find(segment=>!ASSIGNED_SETTINGS_PATH_SEGMENT.test(segment)||RESERVED_SETTINGS_PATH_SEGMENTS.has(segment))!==void 0)throw new PmCliError(`Settings write assignedPaths entry "${assignedPath}" is not a dotted settings path.`,EXIT_CODE.USAGE,{code:"settings_write_assigned_path_invalid",reason:"assigned_path_segment_invalid",field:assignedPath,why:"Assigned paths name settings keys; an empty, reserved or non-identifier segment cannot address one safely.",nextSteps:["Pass dotted settings keys such as context.next_ranking_policy in assignedPaths."]})}function ownRecordAt(record,segment){return asPlainRecord(Object.hasOwn(record,segment)?record[segment]:void 0)}function findAssignedSource(proposed,parents){let source=proposed;for(const segment of parents)if(source=ownRecordAt(source,segment),source===void 0)return;return source}function ensureAssignedParent(target,parents){let cursor=target;for(const segment of parents){let next=ownRecordAt(cursor,segment);next===void 0&&(next={},cursor[segment]=next),cursor=next}return cursor}function applyAssignedSettingsPaths(target,proposed,assignedPaths){for(const assignedPath of assignedPaths){const parents=assignedPath.split("."),leaf=parents.pop(),source=findAssignedSource(proposed,parents);if(source===void 0)continue;if(Object.hasOwn(source,leaf)){ensureAssignedParent(target,parents)[leaf]=structuredClone(source[leaf]);continue}if(!CORE_SETTINGS_SECTION_KEYS.includes(parents[0]??leaf))continue;const storedParent=findAssignedSource(target,parents);storedParent!==void 0&&delete storedParent[leaf]}}function applyFallbackChangeToStoredSettings(current,proposedCanonical,fallbackOrigin,assignedPaths,baseline){const baselineCanonical=baseline??JSON.parse(serializeSettings(cloneDefaults())),candidate=structuredClone(asPlainRecord(current)??{});applySettingsDelta(candidate,baselineCanonical,proposedCanonical),applyAssignedSettingsPaths(candidate,proposedCanonical,assignedPaths);const validated=validateSettings(candidate);if(!validated.success){const field=validated.path;throw new PmCliError(`Existing settings.json fails validation at ${field}; the settings write was refused and nothing was changed.`,EXIT_CODE.USAGE,{code:"settings_write_invalid_existing_schema",reason:"existing_settings_schema_invalid",field,original_code:fallbackOrigin,why:"The stored settings could not be read, so writing would either keep an invalid document or replace intended project configuration with defaults.",nextSteps:[`Fix or remove ${field} in settings.json, then retry the original command.`,"A configurable setting can also be repaired explicitly, even to its default value, with pm config <scope> set <dotted.key> <value>.","Run pm health to confirm the settings warning has cleared."]})}return`${JSON.stringify(orderObject(candidate,SETTINGS_TOP_LEVEL_KEY_ORDER),null,2)}
4
+ `}function parseExistingSettingsForWrite(raw){try{return JSON.parse(raw)}catch{throw new PmCliError("Existing settings.json is malformed; the settings write was refused.",EXIT_CODE.USAGE,{code:"settings_write_invalid_existing_json",reason:"existing_settings_json_malformed",why:"Writing defaults over malformed settings could destroy intended project configuration.",nextSteps:["Repair the syntax in .agents/pm/settings.json, then retry the original command.","Run pm health to confirm the settings warning has cleared."]})}}async function readSettings(pmRoot){return(await readSettingsWithMetadata(pmRoot)).settings}async function writeSettings(pmRoot,settings,op=SETTINGS_WRITE_OP,options={}){const assignedPaths=options.assignedPaths??[];assertAssignedSettingsPaths(assignedPaths);const settingsPath=getSettingsPath(pmRoot),source=getSettingsPersistSourceSnapshot(settings),fallbackOrigin=source?void 0:getSettingsFallbackOrigin(settings),afterRaw=serializeSettings(settings,{persist_source:source}),proposed=JSON.parse(afterRaw);try{await mutateWorkspaceJsonWithHistory({pmRoot,filePath:settingsPath,mutate:beforeRaw=>{const current=beforeRaw===null?null:parseExistingSettingsForWrite(beforeRaw);return fallbackOrigin!==void 0&&beforeRaw!==null?{raw:applyFallbackChangeToStoredSettings(current,proposed,fallbackOrigin,assignedPaths,getSettingsFallbackBaseline(settings)),result:void 0}:{raw:source?`${JSON.stringify(orderObject(reconcileSettingsSnapshot(source.persisted_settings,proposed,current),SETTINGS_TOP_LEVEL_KEY_ORDER),null,2)}
5
+ `:afterRaw,result:void 0}},op,author:resolveAuthor(void 0,settings.author_default),lockTtlSeconds:settings.locks.ttl_seconds,lockWaitMs:settings.locks.wait_ms,recordCreation:!1}),source?attachSettingsPersistSourceSnapshot(settings,{...source,persisted_settings:structuredClone(proposed)}):fallbackOrigin!==void 0&&setSettingsFallbackBaseline(settings,structuredClone(proposed)),await runActiveOnWriteHooks({path:settingsPath,scope:"project",op})}finally{clearSettingsReadCache(pmRoot)}}const settingsStoreTestOnly={applySettingsDelta,hasExplicitItemFormat,buildSettingsPersistSourceSnapshot,cacheSettingsReadResultIfStable,cacheSettingsReadResultSafe,mergeSettings,normalizeExtensionPolicySettings,normalizeExtensionPolicyOverride,normalizeExtensionPolicyOverrides,normalizeExtensionPolicyMode,normalizePmMaxVersionExceededModeSetting,normalizeExtensionSandboxProfile,normalizeExtensionTrustMode,normalizeLowerStringList,normalizeStringList,valueOrDefault,arrayOrEmpty,normalizeValidationPatternList,normalizeValidationMetadataRequiredFields,resolveSettingsReadTrackedPaths,resolvePersistedFileBackedSchemaSections,selectedSettingsReadCacheSignaturesEqual};export{isConfigurationOnlySettingsRead,isSettingsReadFallback,mergeSettings,normalizeItemTypeDefinitions,persistSelectedItemFormat,readSettings,readSettingsWithMetadata,resolveGovernanceKnobs,runWithConfigurationOnlySettings,serializeSettings,settingsStoreTestOnly,writeSettings};
5
6
  //# sourceMappingURL=settings.js.map
@@ -1,6 +1,6 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7c005413-4db4-58ce-a8ec-96ebc91a54f9")}catch{}})();import readline from"node:readline/promises";import{stdin as input,stdout as output}from"node:process";import{resolveGlobalPmRoot}from"../store/paths.js";import{readSettings,writeSettings}from"../store/settings.js";import{resolveTelemetryEnvironmentPolicy}from"./policy.js";const TELEMETRY_PROMPT_DISABLE_ENV="PM_TELEMETRY_PROMPT",TELEMETRY_PROMPT_DISABLE_VALUES=new Set(["0","false","no","off"]),TELEMETRY_PROMPT_SKIPPED_COMMANDS=new Set(["init","completion","completion-statuses","completion-tags","completion-types"]);function parseBooleanLike(value){return typeof value!="string"?!1:TELEMETRY_PROMPT_DISABLE_VALUES.has(value.trim().toLowerCase())}function isTruthyEnvValue(value){if(typeof value!="string")return!1;const normalized=value.trim().toLowerCase();return normalized.length===0?!1:!TELEMETRY_PROMPT_DISABLE_VALUES.has(normalized)}function shouldSkipTelemetryPrompt(commandPath,globalOptions){if(globalOptions.json===!0||globalOptions.quiet===!0||process.stdin.isTTY!==!0||process.stdout.isTTY!==!0||parseBooleanLike(process.env[TELEMETRY_PROMPT_DISABLE_ENV])||isTruthyEnvValue(process.env.CI))return!0;const normalizedCommandPath=commandPath.trim().toLowerCase();return normalizedCommandPath.length===0?!0:TELEMETRY_PROMPT_SKIPPED_COMMANDS.has(normalizedCommandPath)}function parseTelemetryPromptAnswer(answer){const normalized=answer.trim().toLowerCase();return!(normalized==="n"||normalized==="no")}async function promptTelemetryConsent(currentDefault){const prompt=`pm telemetry helps improve reliability and usage diagnostics.
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="88db9929-8e1d-56ad-9a5f-6cc0febadfb3")}catch{}})();import readline from"node:readline/promises";import{stdin as input,stdout as output}from"node:process";import{resolveGlobalPmRoot}from"../store/paths.js";import{isSettingsReadFallback,readSettings,writeSettings}from"../store/settings.js";import{resolveTelemetryEnvironmentPolicy}from"./policy.js";const TELEMETRY_PROMPT_DISABLE_ENV="PM_TELEMETRY_PROMPT",TELEMETRY_PROMPT_DISABLE_VALUES=new Set(["0","false","no","off"]),TELEMETRY_PROMPT_SKIPPED_COMMANDS=new Set(["init","completion","completion-statuses","completion-tags","completion-types"]);function parseBooleanLike(value){return typeof value!="string"?!1:TELEMETRY_PROMPT_DISABLE_VALUES.has(value.trim().toLowerCase())}function isTruthyEnvValue(value){if(typeof value!="string")return!1;const normalized=value.trim().toLowerCase();return normalized.length===0?!1:!TELEMETRY_PROMPT_DISABLE_VALUES.has(normalized)}function shouldSkipTelemetryPrompt(commandPath,globalOptions){if(globalOptions.json===!0||globalOptions.quiet===!0||process.stdin.isTTY!==!0||process.stdout.isTTY!==!0||parseBooleanLike(process.env[TELEMETRY_PROMPT_DISABLE_ENV])||isTruthyEnvValue(process.env.CI))return!0;const normalizedCommandPath=commandPath.trim().toLowerCase();return normalizedCommandPath.length===0?!0:TELEMETRY_PROMPT_SKIPPED_COMMANDS.has(normalizedCommandPath)}function parseTelemetryPromptAnswer(answer){const normalized=answer.trim().toLowerCase();return!(normalized==="n"||normalized==="no")}async function promptTelemetryConsent(currentDefault){const prompt=`pm telemetry helps improve reliability and usage diagnostics.
2
2
  It is enabled by default and can be changed anytime via:
3
3
  pm config global set telemetry-tracking --policy disabled
4
- Enable telemetry now? [${currentDefault?"Y/n":"y/N"}] `,rl=readline.createInterface({input,output});try{const answer=await rl.question(prompt);return answer.trim().length===0?currentDefault:parseTelemetryPromptAnswer(answer)}finally{rl.close()}}async function maybeRunFirstUseTelemetryPrompt(commandPath,globalOptions){if(!(resolveTelemetryEnvironmentPolicy().telemetry_disabled||shouldSkipTelemetryPrompt(commandPath,globalOptions)))try{const globalPmRoot=resolveGlobalPmRoot(process.cwd()),settings=await readSettings(globalPmRoot);if(settings.telemetry.first_run_prompt_completed)return;const enabled=await promptTelemetryConsent(settings.telemetry.enabled);settings.telemetry.enabled=enabled,settings.telemetry.first_run_prompt_completed=!0,await writeSettings(globalPmRoot,settings,"telemetry:first_run_prompt"),output.write(`Telemetry ${enabled?"enabled":"disabled"} for this CLI install. Update any time with pm config global set telemetry-tracking --policy ${enabled?"disabled":"enabled"}.
4
+ Enable telemetry now? [${currentDefault?"Y/n":"y/N"}] `,rl=readline.createInterface({input,output});try{const answer=await rl.question(prompt);return answer.trim().length===0?currentDefault:parseTelemetryPromptAnswer(answer)}finally{rl.close()}}async function maybeRunFirstUseTelemetryPrompt(commandPath,globalOptions){if(!(resolveTelemetryEnvironmentPolicy().telemetry_disabled||shouldSkipTelemetryPrompt(commandPath,globalOptions)))try{const globalPmRoot=resolveGlobalPmRoot(process.cwd()),settings=await readSettings(globalPmRoot);if(settings.telemetry.first_run_prompt_completed||isSettingsReadFallback(settings))return;const enabled=await promptTelemetryConsent(settings.telemetry.enabled);settings.telemetry.enabled=enabled,settings.telemetry.first_run_prompt_completed=!0,await writeSettings(globalPmRoot,settings,"telemetry:first_run_prompt"),output.write(`Telemetry ${enabled?"enabled":"disabled"} for this CLI install. Update any time with pm config global set telemetry-tracking --policy ${enabled?"disabled":"enabled"}.
5
5
  `)}catch{}}export{maybeRunFirstUseTelemetryPrompt};
6
6
  //# sourceMappingURL=consent.js.map
@@ -1,6 +1,6 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4b15f41e-4b2a-511a-b2a1-c1c3e3d909c5")}catch{}})();import crypto from"node:crypto";import{spawn}from"node:child_process";import{mkdirSync,rmSync,statSync}from"node:fs";import{mkdir,readdir,rm,stat}from"node:fs/promises";import{request as httpRequest}from"node:http";import{request as httpsRequest}from"node:https";import os from"node:os";import path from"node:path";import{acquireLock}from"../lock/lock.js";import{isActiveCommandUnextended,runWithIsolatedExtensionRuntime}from"../extensions/index.js";import{resolveAutomaticReadSampleRate}from"./read-sampling.js";import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES,isTelemetryTestEnvironment,resolveTelemetryEnvironmentPolicy,resolveTelemetrySourceAttribution}from"./policy.js";import{resolvePmPackageRootFromModule}from"../packages/root.js";import{isFileMissingError,appendLineAtomic,readFileIfExists,writeFileAtomic}from"../fs/fs-utils.js";import{resolveTelemetryErrorCategory}from"../shared/constants.js";import{nowIso}from"../shared/time.js";import{detectAgentIdentity,readAuthorEnvironment}from"../shared/author.js";import{resolveGlobalPmRoot}from"../store/paths.js";import{isConfigurationOnlySettingsRead,readSettings,runWithConfigurationOnlySettings,writeSettings}from"../store/settings.js";import{clearSettingsReadCache}from"../store/settings-read-cache.js";import{deriveTelemetryCommandResolution,deriveTelemetryCommandTaxonomy,inferTelemetryErrorCode}from"./observability.js";const TELEMETRY_QUEUE_RELATIVE_PATH=path.join("runtime","telemetry","events.jsonl"),TELEMETRY_STATE_RELATIVE_PATH=path.join("runtime","telemetry","state.json"),TELEMETRY_OTEL_SPANS_RELATIVE_PATH=path.join("runtime","telemetry","otel-spans.jsonl"),TELEMETRY_OTEL_SPANS_FLUSH_BATCH_SIZE=8,TELEMETRY_OTEL_SPANS_MAX_PENDING=500,TELEMETRY_SCHEMA_VERSION=1,TELEMETRY_CLIENT_SCHEMA_VERSION=1,TELEMETRY_FLUSH_BATCH_SIZE=100,TELEMETRY_MAX_RETRY_DELAY_MS=36e5,TELEMETRY_RETRY_BASE_DELAY_MS=3e4,TELEMETRY_HTTP_TIMEOUT_DEFAULT_MS=2e4,TELEMETRY_HTTP_TIMEOUT_MIN_MS=1e3,TELEMETRY_HTTP_TIMEOUT_MAX_MS=25e3,TELEMETRY_FOREGROUND_LOCK_WAIT_MS=250,MILLISECONDS_PER_DAY=864e5,TELEMETRY_MAX_EVENT_BYTES=65536,TELEMETRY_SANITIZE_MAX_DEPTH=6,TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS=20,TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS=15,TELEMETRY_RESULT_PREVIEW_MAX_BYTES=8192,TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS=[25,50,100,200],TELEMETRY_QUEUE_TMP_ORPHAN_MAX_AGE_MS=3600*1e3,TELEMETRY_FLUSH_LOCK_STALE_MS=6e4,TELEMETRY_FLUSH_SPAWN_LOCK_STALE_MS=6e4,OTEL_TRACES_ENDPOINT_ENV="OTEL_EXPORTER_OTLP_TRACES_ENDPOINT",OTEL_BASE_ENDPOINT_ENV="OTEL_EXPORTER_OTLP_ENDPOINT",OTEL_SERVICE_NAME_ENV="OTEL_SERVICE_NAME",PM_TELEMETRY_OTEL_DISABLED_ENV="PM_TELEMETRY_OTEL_DISABLED",PM_TELEMETRY_OTEL_DISABLED_VALUES=new Set(["1","true","yes","on"]),PM_TELEMETRY_INLINE_FLUSH_ENV="PM_TELEMETRY_INLINE_FLUSH",PM_TELEMETRY_FLUSH_CHILD_ENV="PM_TELEMETRY_FLUSH_CHILD",PM_TELEMETRY_HTTP_TIMEOUT_MS_ENV="PM_TELEMETRY_HTTP_TIMEOUT_MS",NATIVE_FETCH=globalThis.fetch;import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES as PM_TELEMETRY_SOURCE_CONTEXT_VALUES2}from"./policy.js";let sourceContextWarningEmitted=!1,_lastFlushPromise=Promise.resolve(),_queueMutationPromise=Promise.resolve();const deferredReadStarts=new WeakMap;async function waitForPendingFlush(){await _lastFlushPromise,await _queueMutationPromise}const BOOLEAN_TRUE_VALUES=new Set(["1","true","yes","on"]),TELEMETRY_HARNESSES=new Set(["claude-code","codex","pi","opencode","cursor","aider","gemini-cli","ci"]),PROCESS_SESSION_ID=crypto.randomUUID(),SENSITIVE_KEYWORDS=["token","secret","password","passwd","api_key","apikey","authorization","cookie","session","credentials","bearer"],REDACTION_INPUT_KEYS=new Set(["literal","literals","regex","regexes","replacement","replacements","setjson","set_json","update"]),SENSITIVE_INLINE_KEY_PATTERN="(?:token|secret|password|passwd|api[_-]?key|apikey|authorization|cookie|session|credentials|bearer|literals?|regex(?:es)?|replacements?)",INLINE_SENSITIVE_ASSIGNMENT_PATTERN=new RegExp(`\\b(${SENSITIVE_INLINE_KEY_PATTERN})\\s*([:=])\\s*([^\\s,;]+)`,"giu"),INLINE_SENSITIVE_FLAG_PATTERN=new RegExp(`(--${SENSITIVE_INLINE_KEY_PATTERN})(=|\\s+)([^\\s,;]+)`,"giu"),ABSOLUTE_PATH_TOKEN_PATTERN=/(^|[\s"'`(=])\/(?:[^\s"'`),;]+)/g,BEARER_TOKEN_PATTERN=/bearer\s+[a-z0-9._=-]+/giu,PRIVATE_IP_PATTERN=/\b(?:10\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|172\.(?:1[6-9]|2\d|3[01])\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|192\.168\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d))\b/g;function queuePath(globalPmRoot){return path.join(globalPmRoot,TELEMETRY_QUEUE_RELATIVE_PATH)}function otelSpansQueuePath(globalPmRoot){return path.join(globalPmRoot,TELEMETRY_OTEL_SPANS_RELATIVE_PATH)}function telemetryRuntimeDirectory(globalPmRoot){return path.dirname(queuePath(globalPmRoot))}function runtimeStatePath(globalPmRoot){return path.join(globalPmRoot,TELEMETRY_STATE_RELATIVE_PATH)}function flushLockPath(globalPmRoot){return path.join(globalPmRoot,"runtime","telemetry","flush.lock")}function flushSpawnLockPath(globalPmRoot){return path.join(globalPmRoot,"runtime","telemetry","flush.spawn.lock")}function telemetryFlushRunnerPath(){return path.join(resolvePmPackageRootFromModule(import.meta.url,["../../.."]),"dist","cli","telemetry-flush.js")}function shouldFlushInline(){return parseBooleanTrueLike(process.env[PM_TELEMETRY_INLINE_FLUSH_ENV])||parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])?!0:isTelemetryTestEnvironment()}async function readRuntimeState(globalPmRoot){const raw=await readFileIfExists(runtimeStatePath(globalPmRoot));if(!raw||raw.trim().length===0)return{};try{const parsed=JSON.parse(raw);return typeof parsed!="object"||parsed===null||Array.isArray(parsed)?{}:parsed}catch{return{}}}async function writeRuntimeState(globalPmRoot,patch){try{await withQueueMutation(async()=>{const next={...await readRuntimeState(globalPmRoot),...patch},normalized=Object.fromEntries(Object.entries(next).filter(([,value])=>value!==void 0).sort((left,right)=>left[0].localeCompare(right[0])));await writeFileAtomic(runtimeStatePath(globalPmRoot),`${JSON.stringify(normalized,null,2)}
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="cbcb519e-1348-5974-bd16-ea5905c468a4")}catch{}})();import crypto from"node:crypto";import{spawn}from"node:child_process";import{mkdirSync,rmSync,statSync}from"node:fs";import{mkdir,readdir,rm,stat}from"node:fs/promises";import{request as httpRequest}from"node:http";import{request as httpsRequest}from"node:https";import os from"node:os";import path from"node:path";import{acquireLock}from"../lock/lock.js";import{isActiveCommandUnextended,runWithIsolatedExtensionRuntime}from"../extensions/index.js";import{resolveAutomaticReadSampleRate}from"./read-sampling.js";import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES,isTelemetryTestEnvironment,resolveTelemetryEnvironmentPolicy,resolveTelemetrySourceAttribution}from"./policy.js";import{resolvePmPackageRootFromModule}from"../packages/root.js";import{isFileMissingError,appendLineAtomic,readFileIfExists,writeFileAtomic}from"../fs/fs-utils.js";import{resolveTelemetryErrorCategory}from"../shared/constants.js";import{nowIso}from"../shared/time.js";import{detectAgentIdentity,readAuthorEnvironment}from"../shared/author.js";import{resolveGlobalPmRoot}from"../store/paths.js";import{isConfigurationOnlySettingsRead,isSettingsReadFallback,readSettings,runWithConfigurationOnlySettings,writeSettings}from"../store/settings.js";import{clearSettingsReadCache}from"../store/settings-read-cache.js";import{deriveTelemetryCommandResolution,deriveTelemetryCommandTaxonomy,inferTelemetryErrorCode}from"./observability.js";const TELEMETRY_QUEUE_RELATIVE_PATH=path.join("runtime","telemetry","events.jsonl"),TELEMETRY_STATE_RELATIVE_PATH=path.join("runtime","telemetry","state.json"),TELEMETRY_OTEL_SPANS_RELATIVE_PATH=path.join("runtime","telemetry","otel-spans.jsonl"),TELEMETRY_OTEL_SPANS_FLUSH_BATCH_SIZE=8,TELEMETRY_OTEL_SPANS_MAX_PENDING=500,TELEMETRY_SCHEMA_VERSION=1,TELEMETRY_CLIENT_SCHEMA_VERSION=1,TELEMETRY_FLUSH_BATCH_SIZE=100,TELEMETRY_MAX_RETRY_DELAY_MS=36e5,TELEMETRY_RETRY_BASE_DELAY_MS=3e4,TELEMETRY_HTTP_TIMEOUT_DEFAULT_MS=2e4,TELEMETRY_HTTP_TIMEOUT_MIN_MS=1e3,TELEMETRY_HTTP_TIMEOUT_MAX_MS=25e3,TELEMETRY_FOREGROUND_LOCK_WAIT_MS=250,MILLISECONDS_PER_DAY=864e5,TELEMETRY_MAX_EVENT_BYTES=65536,TELEMETRY_SANITIZE_MAX_DEPTH=6,TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS=20,TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS=15,TELEMETRY_RESULT_PREVIEW_MAX_BYTES=8192,TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS=[25,50,100,200],TELEMETRY_QUEUE_TMP_ORPHAN_MAX_AGE_MS=3600*1e3,TELEMETRY_FLUSH_LOCK_STALE_MS=6e4,TELEMETRY_FLUSH_SPAWN_LOCK_STALE_MS=6e4,OTEL_TRACES_ENDPOINT_ENV="OTEL_EXPORTER_OTLP_TRACES_ENDPOINT",OTEL_BASE_ENDPOINT_ENV="OTEL_EXPORTER_OTLP_ENDPOINT",OTEL_SERVICE_NAME_ENV="OTEL_SERVICE_NAME",PM_TELEMETRY_OTEL_DISABLED_ENV="PM_TELEMETRY_OTEL_DISABLED",PM_TELEMETRY_OTEL_DISABLED_VALUES=new Set(["1","true","yes","on"]),PM_TELEMETRY_INLINE_FLUSH_ENV="PM_TELEMETRY_INLINE_FLUSH",PM_TELEMETRY_FLUSH_CHILD_ENV="PM_TELEMETRY_FLUSH_CHILD",PM_TELEMETRY_HTTP_TIMEOUT_MS_ENV="PM_TELEMETRY_HTTP_TIMEOUT_MS",NATIVE_FETCH=globalThis.fetch;import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES as PM_TELEMETRY_SOURCE_CONTEXT_VALUES2}from"./policy.js";let sourceContextWarningEmitted=!1,_lastFlushPromise=Promise.resolve(),_queueMutationPromise=Promise.resolve();const deferredReadStarts=new WeakMap;async function waitForPendingFlush(){await _lastFlushPromise,await _queueMutationPromise}const BOOLEAN_TRUE_VALUES=new Set(["1","true","yes","on"]),TELEMETRY_HARNESSES=new Set(["claude-code","codex","pi","opencode","cursor","aider","gemini-cli","ci"]),PROCESS_SESSION_ID=crypto.randomUUID(),SENSITIVE_KEYWORDS=["token","secret","password","passwd","api_key","apikey","authorization","cookie","session","credentials","bearer"],REDACTION_INPUT_KEYS=new Set(["literal","literals","regex","regexes","replacement","replacements","setjson","set_json","update"]),SENSITIVE_INLINE_KEY_PATTERN="(?:token|secret|password|passwd|api[_-]?key|apikey|authorization|cookie|session|credentials|bearer|literals?|regex(?:es)?|replacements?)",INLINE_SENSITIVE_ASSIGNMENT_PATTERN=new RegExp(`\\b(${SENSITIVE_INLINE_KEY_PATTERN})\\s*([:=])\\s*([^\\s,;]+)`,"giu"),INLINE_SENSITIVE_FLAG_PATTERN=new RegExp(`(--${SENSITIVE_INLINE_KEY_PATTERN})(=|\\s+)([^\\s,;]+)`,"giu"),ABSOLUTE_PATH_TOKEN_PATTERN=/(^|[\s"'`(=])\/(?:[^\s"'`),;]+)/g,BEARER_TOKEN_PATTERN=/bearer\s+[a-z0-9._=-]+/giu,PRIVATE_IP_PATTERN=/\b(?:10\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|172\.(?:1[6-9]|2\d|3[01])\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|192\.168\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d))\b/g;function queuePath(globalPmRoot){return path.join(globalPmRoot,TELEMETRY_QUEUE_RELATIVE_PATH)}function otelSpansQueuePath(globalPmRoot){return path.join(globalPmRoot,TELEMETRY_OTEL_SPANS_RELATIVE_PATH)}function telemetryRuntimeDirectory(globalPmRoot){return path.dirname(queuePath(globalPmRoot))}function runtimeStatePath(globalPmRoot){return path.join(globalPmRoot,TELEMETRY_STATE_RELATIVE_PATH)}function flushLockPath(globalPmRoot){return path.join(globalPmRoot,"runtime","telemetry","flush.lock")}function flushSpawnLockPath(globalPmRoot){return path.join(globalPmRoot,"runtime","telemetry","flush.spawn.lock")}function telemetryFlushRunnerPath(){return path.join(resolvePmPackageRootFromModule(import.meta.url,["../../.."]),"dist","cli","telemetry-flush.js")}function shouldFlushInline(){return parseBooleanTrueLike(process.env[PM_TELEMETRY_INLINE_FLUSH_ENV])||parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])?!0:isTelemetryTestEnvironment()}async function readRuntimeState(globalPmRoot){const raw=await readFileIfExists(runtimeStatePath(globalPmRoot));if(!raw||raw.trim().length===0)return{};try{const parsed=JSON.parse(raw);return typeof parsed!="object"||parsed===null||Array.isArray(parsed)?{}:parsed}catch{return{}}}async function writeRuntimeState(globalPmRoot,patch){try{await withQueueMutation(async()=>{const next={...await readRuntimeState(globalPmRoot),...patch},normalized=Object.fromEntries(Object.entries(next).filter(([,value])=>value!==void 0).sort((left,right)=>left[0].localeCompare(right[0])));await writeFileAtomic(runtimeStatePath(globalPmRoot),`${JSON.stringify(normalized,null,2)}
2
2
  `,{createParentDirectories:!parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])})},globalPmRoot)}catch{}}function isSensitiveKey(key){const normalized=key.trim().toLowerCase().replaceAll("-","_").replaceAll(/[^a-z0-9_]+/g,"_"),tokens=normalized.split("_").filter(token=>token.length>0);return REDACTION_INPUT_KEYS.has(normalized)||SENSITIVE_KEYWORDS.some(keyword=>normalized===keyword||normalized.endsWith(`_${keyword}`)||tokens.includes(keyword))}function redactInlineSensitiveAssignments(input){return input.replaceAll(INLINE_SENSITIVE_ASSIGNMENT_PATTERN,(_match,key,delimiter)=>`${key}${delimiter}[redacted]`).replaceAll(INLINE_SENSITIVE_FLAG_PATTERN,(_match,flag,delimiter)=>`${flag}${delimiter}[redacted]`)}function redactAbsolutePathTokens(input){return input.replaceAll(ABSOLUTE_PATH_TOKEN_PATTERN,(_match,prefix)=>`${prefix}[redacted_path]`)}function isAsciiLetterOrDigitCode(code){const isUpper=code>=65&&code<=90,isLower=code>=97&&code<=122,isDigit=code>=48&&code<=57;return isUpper||isLower||isDigit}function isEmailLocalCharacter(character){if(!character)return!1;const code=character.charCodeAt(0);return isAsciiLetterOrDigitCode(code)?!0:character==="."||character==="_"||character==="%"||character==="+"||character==="-"}function isEmailDomainCharacter(character){if(!character)return!1;const code=character.charCodeAt(0);return isAsciiLetterOrDigitCode(code)?!0:character==="."||character==="-"}function looksLikeEmailToken(token){const atIndex=token.indexOf("@");if(atIndex<=0||atIndex!==token.lastIndexOf("@")||atIndex===token.length-1)return!1;const localPart=token.slice(0,atIndex),domainPart=token.slice(atIndex+1),lastDot=domainPart.lastIndexOf(".");if(lastDot<=0||lastDot===domainPart.length-1||domainPart.length-(lastDot+1)<2)return!1;for(const character of localPart)if(!isEmailLocalCharacter(character))return!1;for(const character of domainPart)if(!isEmailDomainCharacter(character))return!1;return!0}function redactEmailTokens(input){let redacted="",cursor=0;for(;cursor<input.length;){const atIndex=input.indexOf("@",cursor);if(atIndex<0){redacted+=input.slice(cursor);break}let start=atIndex-1;for(;start>=cursor&&isEmailLocalCharacter(input[start]);)start-=1;start+=1;let end=atIndex+1;for(;end<input.length&&isEmailDomainCharacter(input[end]);)end+=1;const candidate=input.slice(start,end);if(looksLikeEmailToken(candidate)){redacted+=input.slice(cursor,start),redacted+="[redacted_email]",cursor=end;continue}redacted+=input.slice(cursor,atIndex+1),cursor=atIndex+1}return redacted}function sanitizeCommonSensitiveTokens(input){return redactEmailTokens(input).replaceAll(BEARER_TOKEN_PATTERN,"bearer [redacted_token]").replaceAll(PRIVATE_IP_PATTERN,"[redacted_ip]")}function sanitizeStringRedacted(input){const withoutCommonSensitiveTokens=sanitizeCommonSensitiveTokens(input),withoutInlineSecrets=redactInlineSensitiveAssignments(withoutCommonSensitiveTokens),withoutAbsolutePaths=redactAbsolutePathTokens(withoutInlineSecrets),trimmed=withoutAbsolutePaths.trim();return trimmed.startsWith("/")&&trimmed.length>1?"[redacted_path]":withoutAbsolutePaths.length>512?`${withoutAbsolutePaths.slice(0,509)}...`:withoutAbsolutePaths}function sanitizeStringMax(input){const withoutCommonSensitiveTokens=sanitizeCommonSensitiveTokens(input),withoutInlineSecrets=redactInlineSensitiveAssignments(withoutCommonSensitiveTokens),withoutAbsolutePaths=redactAbsolutePathTokens(withoutInlineSecrets),trimmed=withoutAbsolutePaths.trim();return trimmed.startsWith("/")&&trimmed.length>1?"[redacted_path]":withoutAbsolutePaths.length>2048?`${withoutAbsolutePaths.slice(0,2045)}...`:withoutAbsolutePaths}function sanitizeString(input,captureLevel="redacted"){return captureLevel==="max"?sanitizeStringMax(input):sanitizeStringRedacted(input)}function sanitizeValue(value,keyHint,captureLevel="redacted",depth=0){if(keyHint&&isSensitiveKey(keyHint))return"[redacted]";if(value==null)return value;if(typeof value=="string")return sanitizeString(value,captureLevel);if(typeof value=="number"||typeof value=="boolean")return value;if(depth>=TELEMETRY_SANITIZE_MAX_DEPTH)return"[depth_truncated]";if(Array.isArray(value))return value.slice(0,TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS).map(entry=>sanitizeValue(entry,void 0,captureLevel,depth+1));if(typeof value=="object"){const record=value,sanitized={};for(const[key,nested]of Object.entries(record))sanitized[key]=sanitizeValue(nested,key,captureLevel,depth+1);return sanitized}return String(value)}function sanitizeCommandArgs(args,captureLevel="redacted"){const sanitized=[];let nextIsSensitiveValue=!1;for(const rawArg of args){const arg=sanitizeString(rawArg,captureLevel);if(nextIsSensitiveValue){sanitized.push("[redacted]"),nextIsSensitiveValue=!1;continue}if(arg.startsWith("--")){const withoutPrefix=arg.slice(2),delimiterIndex=withoutPrefix.indexOf("=");if(delimiterIndex>=0){const key=withoutPrefix.slice(0,delimiterIndex),value=withoutPrefix.slice(delimiterIndex+1);isSensitiveKey(key)?sanitized.push(`--${key}=[redacted]`):sanitized.push(`--${key}=${sanitizeString(value,captureLevel)}`);continue}if(isSensitiveKey(withoutPrefix)){sanitized.push(`--${withoutPrefix}`),nextIsSensitiveValue=!0;continue}}sanitized.push(arg)}return sanitized}function normalizeCaptureLevel(value){const normalized=value?.trim().toLowerCase();return normalized==="minimal"||normalized==="redacted"||normalized==="max"?normalized:"redacted"}function parseBooleanTrueLike(value){return BOOLEAN_TRUE_VALUES.has((value??"").trim().toLowerCase())}function resolveTelemetryHttpTimeoutMs(){const rawConfigured=process.env[PM_TELEMETRY_HTTP_TIMEOUT_MS_ENV]?.trim();if(!rawConfigured)return TELEMETRY_HTTP_TIMEOUT_DEFAULT_MS;const configured=Number(rawConfigured);return Number.isFinite(configured)?Math.min(TELEMETRY_HTTP_TIMEOUT_MAX_MS,Math.max(TELEMETRY_HTTP_TIMEOUT_MIN_MS,Math.trunc(configured))):TELEMETRY_HTTP_TIMEOUT_DEFAULT_MS}async function postTelemetryJson(endpoint,headers,body){const url=new URL(endpoint);if(globalThis.fetch!==NATIVE_FETCH){const controller=new AbortController;let timeout;const deadline=new Promise((_resolve,reject)=>{timeout=setTimeout(()=>{controller.abort(),reject(new Error("telemetry_http_timeout"))},resolveTelemetryHttpTimeoutMs())});try{return(await Promise.race([globalThis.fetch(endpoint,{method:"POST",headers,body,signal:controller.signal}),deadline])).status}finally{clearTimeout(timeout)}}const request=url.protocol==="https:"?httpsRequest:url.protocol==="http:"?httpRequest:void 0;if(!request)throw new Error(`telemetry_http_protocol_unsupported_${url.protocol}`);return new Promise((resolve,reject)=>{const timeoutMs=resolveTelemetryHttpTimeoutMs(),requestOptions={method:"POST",headers:{...headers,"content-length":Buffer.byteLength(body)},signal:AbortSignal.timeout(timeoutMs),autoSelectFamilyAttemptTimeout:Math.min(5e3,timeoutMs)},clientRequest=request(url,requestOptions,response=>{response.once("error",reject),response.once("end",()=>resolve(response.statusCode)),response.resume()});clientRequest.once("error",reject),clientRequest.end(body)})}function normalizePmVersion(value){const trimmed=typeof value=="string"?value.trim():"";return trimmed.length>0?trimmed:"0.0.0"}function normalizeTelemetryErrorCode(value){const normalized=value?.trim();return normalized&&normalized.length>0?normalized:void 0}function normalizeTelemetryExitCode(exitCode,ok){return Number.isFinite(exitCode)?Math.max(0,Math.trunc(exitCode)):ok?0:1}function normalizeTelemetryErrorCategory(params){if(!params.ok)return typeof params.errorCategory=="string"&&params.errorCategory.trim().length>0?params.errorCategory:typeof params.errorCode=="string"&&params.errorCode.trim().length>0?resolveTelemetryErrorCategory(params.errorCode):"unknown"}function resolveTelemetrySourceContext(globalOptions){const resolved=resolveTelemetrySourceAttribution(globalOptions);return resolved.source_context_source==="env_override_rejected"&&!sourceContextWarningEmitted&&!globalOptions.quiet&&(sourceContextWarningEmitted=!0,process.stderr.write(`[pm] warning: PM_TELEMETRY_SOURCE_CONTEXT is not one of ${PM_TELEMETRY_SOURCE_CONTEXT_VALUES.join("|")}; ignoring override.
3
- `)),resolved}function hashWithInstallationId(installationId,value){return crypto.createHash("sha256").update(`${installationId}:${value}`).digest("hex")}function buildAuthorContextPayloadFields(captureLevel,installationId){const author=(readAuthorEnvironment()??"").trim(),agent=detectAgentIdentity({env:process.env,argv:process.argv}),hasAgentContext=agent.harness!==void 0||agent.model!==void 0;return captureLevel==="minimal"?{has_author_context:author.length>0,has_agent_context:hasAgentContext}:{agent_harness:agent.harness?TELEMETRY_HARNESSES.has(agent.harness)?agent.harness:"other":"none",ci:parseBooleanTrueLike(process.env.CI),...author.length>0?{author_context_hash:hashWithInstallationId(installationId,author)}:{},...agent.harness?{agent_harness_hash:hashWithInstallationId(installationId,agent.harness)}:{},...agent.model?{agent_model_hash:hashWithInstallationId(installationId,agent.model)}:{},...agent.model_source?{agent_model_source:agent.model_source}:{}}}function normalizeForHash(value,depth=0){if(value==null||typeof value=="string"||typeof value=="number"||typeof value=="boolean")return value;if(depth>=TELEMETRY_SANITIZE_MAX_DEPTH)return"[depth_truncated]";if(Array.isArray(value))return value.slice(0,TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS).map(entry=>normalizeForHash(entry,depth+1));if(typeof value=="object"){const record=value,normalized={},sortedKeys=Object.keys(record).sort((left,right)=>left.localeCompare(right));for(const key of sortedKeys)normalized[key]=normalizeForHash(record[key],depth+1);return normalized}return String(value)}function hashTelemetryValue(installationId,value){return hashWithInstallationId(installationId,JSON.stringify(normalizeForHash(value)))}function hashCommandArgs(installationId,args){return{hashes:args.map(arg=>hashWithInstallationId(installationId,arg)),digest:hashWithInstallationId(installationId,args.join("\0"))}}function hashTelemetryErrorFingerprint(installationId,command,errorCode2,errorMessage){const normalizedMessage=sanitizeString(typeof errorMessage=="string"?errorMessage:"","redacted"),normalizedCode=typeof errorCode2=="string"&&errorCode2.length>0?errorCode2:"unknown_error",fingerprintSource=`${command}\0${normalizedCode}\0${normalizedMessage}`;return hashWithInstallationId(installationId,fingerprintSource)}function resolveOtelTracesEndpoint(){if(PM_TELEMETRY_OTEL_DISABLED_VALUES.has((process.env[PM_TELEMETRY_OTEL_DISABLED_ENV]??"").trim().toLowerCase()))return null;const directEndpoint=(process.env[OTEL_TRACES_ENDPOINT_ENV]??"").trim();if(directEndpoint.length>0)try{return new URL(directEndpoint).toString()}catch{return null}const baseEndpoint=(process.env[OTEL_BASE_ENDPOINT_ENV]??"").trim();if(baseEndpoint.length===0)return null;try{const url=new URL(baseEndpoint),normalizedPath=url.pathname.replace(/\/+$/,"");return normalizedPath.endsWith("/v1/traces")||(url.pathname=`${normalizedPath.length===0?"":normalizedPath}/v1/traces`),url.toString()}catch{return null}}function isoToUnixNano(iso){const parsedMs=Date.parse(iso),epochMs=Number.isNaN(parsedMs)?Date.now():parsedMs;return`${BigInt(epochMs)*1000000n}`}function otlpStringAttribute(key,value){return{key,value:{stringValue:value}}}function otlpBoolAttribute(key,value){return{key,value:{boolValue:value}}}function otlpIntAttribute(key,value){return{key,value:{intValue:String(Math.max(0,Math.trunc(value)))}}}function buildOtelSpanRequest(activeCommand,outcome,finishedAtIso,durationMs,sampleRate=1){const endpoint=activeCommand.otel_traces_endpoint;if(typeof endpoint!="string"||endpoint.trim().length===0||[activeCommand.otel_trace_id,activeCommand.otel_span_id].some(id=>typeof id!="string"||id.length===0))return null;const serviceNameCandidate=sanitizeString((process.env[OTEL_SERVICE_NAME_ENV]??"").trim()),serviceName=serviceNameCandidate.length>0?serviceNameCandidate:"pm-cli",normalizedExitCode=normalizeTelemetryExitCode(outcome.exit_code,outcome.ok),normalizedErrorCode=normalizeTelemetryErrorCode(outcome.error_code),normalizedErrorCategory=normalizeTelemetryErrorCategory({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:outcome.error_category}),attributes=[otlpStringAttribute("pm.command",sanitizeString(activeCommand.command)),otlpStringAttribute("pm.version",activeCommand.pm_version),otlpStringAttribute("pm.source_context",activeCommand.source_context),otlpStringAttribute("pm.source_context_source",activeCommand.source_context_source),otlpStringAttribute("pm.installation_id",activeCommand.installation_id),otlpStringAttribute("pm.session_id",PROCESS_SESSION_ID),otlpStringAttribute("pm.pm_root_hash",activeCommand.pm_root_hash),otlpStringAttribute("pm.cwd_hash",activeCommand.cwd_hash),otlpBoolAttribute("pm.ok",outcome.ok),otlpIntAttribute("pm.exit_code",normalizedExitCode),otlpIntAttribute("pm.duration_ms",durationMs),otlpStringAttribute("pm.sample_rate",String(sampleRate))];typeof normalizedErrorCode=="string"&&attributes.push(otlpStringAttribute("pm.error_code",normalizedErrorCode)),typeof normalizedErrorCategory=="string"&&attributes.push(otlpStringAttribute("pm.error_category",normalizedErrorCategory)),typeof outcome.error=="string"&&outcome.error.trim().length>0&&attributes.push(otlpStringAttribute("pm.error",sanitizeString(outcome.error)));const payload={resourceSpans:[{resource:{attributes:[otlpStringAttribute("service.name",serviceName)]},scopeSpans:[{scope:{name:"pm-cli.telemetry",version:"1"},spans:[{traceId:activeCommand.otel_trace_id,spanId:activeCommand.otel_span_id,name:`pm.command.${sanitizeString(activeCommand.command)}`,kind:1,startTimeUnixNano:isoToUnixNano(activeCommand.started_at),endTimeUnixNano:isoToUnixNano(finishedAtIso),attributes,status:{code:outcome.ok?1:2,message:outcome.ok?"":sanitizeString(typeof outcome.error=="string"?outcome.error:"command_failed")}}]}]}]};return{endpoint,payload}}function summarizeResult(result,captureLevel="redacted"){if(result==null)return{type:"nullish"};if(typeof result=="string")return{type:"string",value:sanitizeString(result,captureLevel)};if(typeof result=="number"||typeof result=="boolean")return{type:typeof result,value:result};if(Array.isArray(result))return{type:"array",length:result.length,sample:result.slice(0,5).map(entry=>sanitizeValue(entry,void 0,captureLevel))};if(typeof result=="object"){const record=result,keys=Object.keys(record).filter(key=>key!=="tests").sort((left,right)=>left.localeCompare(right)),sanitized={};let previewBytes=0;for(const key of keys.slice(0,25)){const sanitizedValue=sanitizeValue(record[key],key,captureLevel);if(sanitizedValue===void 0)continue;const entrySize=JSON.stringify(sanitizedValue).length;if(previewBytes+entrySize>TELEMETRY_RESULT_PREVIEW_MAX_BYTES){sanitized[key]="[preview_truncated]";break}previewBytes+=entrySize,sanitized[key]=sanitizedValue}return{type:"object",key_count:keys.length,keys_preview:keys.slice(0,50),preview:sanitized}}return{type:typeof result,value:String(result)}}function buildCommandStartPayload(params){const{captureLevel,context,pmVersion,sourceContext,pmRootHash,cwdHash,installationId}=params,commandTaxonomy=deriveTelemetryCommandTaxonomy(context.command),hashedArgs=hashCommandArgs(installationId,context.args),commandInvocationDigest=hashWithInstallationId(installationId,`${context.command}\0${context.args.join("\0")}`),commandOptionsDigest=hashTelemetryValue(installationId,context.options),globalOptionsDigest=hashTelemetryValue(installationId,context.global),authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);return captureLevel==="minimal"?{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_args_digest:hashedArgs.digest,command_invocation_digest:commandInvocationDigest,command_options_digest:commandOptionsDigest,global_options_digest:globalOptionsDigest,...authorContextFields}:{pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,...authorContextFields,command_args:sanitizeCommandArgs(context.args,captureLevel),command_args_hashes:hashedArgs.hashes,command_args_digest:hashedArgs.digest,command_invocation_digest:commandInvocationDigest,command_options:sanitizeValue(context.options,void 0,captureLevel),command_options_digest:commandOptionsDigest,global_options:sanitizeValue(context.global,void 0,captureLevel),global_options_digest:globalOptionsDigest,pm_root_hash:pmRootHash,cwd_hash:cwdHash,capture_level:captureLevel,runtime:{node:process.version,platform:process.platform,arch:process.arch,hostname_hash:hashWithInstallationId(installationId,os.hostname()),stdin_tty:process.stdin.isTTY===!0,stdout_tty:process.stdout.isTTY===!0}}}function buildCommandFinishPayload(params){const{captureLevel,pmVersion,sourceContext,outcome,durationMs,startedAt,command,installationId,commandTaxonomy,exitCode,errorCode:errorCode2,errorCategory,commandResolution,resolutionStage}=params,errorFingerprint=outcome.ok===!1?hashTelemetryErrorFingerprint(installationId,command,errorCode2,outcome.error):void 0,authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);return captureLevel==="minimal"?{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_resolution:commandResolution,resolution_stage:resolutionStage,ok:outcome.ok,exit_code:exitCode,error_code:errorCode2,error_category:errorCategory,error:outcome.error?sanitizeString(outcome.error,"redacted"):void 0,error_fingerprint:errorFingerprint,duration_ms:durationMs,...authorContextFields}:{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_resolution:commandResolution,resolution_stage:resolutionStage,...authorContextFields,ok:outcome.ok,exit_code:exitCode,error_code:errorCode2,error_category:errorCategory,error:outcome.error?sanitizeString(outcome.error,captureLevel):void 0,error_fingerprint:errorFingerprint,duration_ms:durationMs,started_at:startedAt,result_summary:summarizeResult(outcome.result,captureLevel)}}function buildCommandErrorPayload(params){const{captureLevel,pmVersion,sourceContext,command,commandTaxonomy,commandResolution,resolutionStage,args,options,pmRootHash,cwdHash,installationId,errorCode:errorCode2,errorMessage,errorCategory,exitCode}=params,attemptedArgHashes=hashCommandArgs(installationId,args),attemptedCommandDigest=hashWithInstallationId(installationId,command),attemptedOptionsDigest=hashTelemetryValue(installationId,options),errorFingerprint=hashTelemetryErrorFingerprint(installationId,command,errorCode2,errorMessage),authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);return captureLevel==="minimal"?{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_resolution:commandResolution,resolution_stage:resolutionStage,attempted_command_digest:attemptedCommandDigest,attempted_args_digest:attemptedArgHashes.digest,attempted_options_digest:attemptedOptionsDigest,error_code:errorCode2,error_category:errorCategory,exit_code:exitCode,error:sanitizeString(errorMessage,"redacted"),error_fingerprint:errorFingerprint,...authorContextFields}:{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_resolution:commandResolution,resolution_stage:resolutionStage,...authorContextFields,attempted_command:sanitizeString(command,captureLevel),attempted_command_digest:attemptedCommandDigest,attempted_args:sanitizeCommandArgs(args,captureLevel),attempted_args_hashes:attemptedArgHashes.hashes,attempted_args_digest:attemptedArgHashes.digest,attempted_options:sanitizeValue(options,void 0,captureLevel),attempted_options_digest:attemptedOptionsDigest,error_code:errorCode2,error_category:errorCategory,exit_code:exitCode,error:sanitizeString(errorMessage,captureLevel),error_fingerprint:errorFingerprint,pm_root_hash:pmRootHash,cwd_hash:cwdHash,runtime:{node:process.version,platform:process.platform,arch:process.arch,hostname_hash:hashWithInstallationId(installationId,os.hostname()),stdin_tty:process.stdin.isTTY===!0,stdout_tty:process.stdout.isTTY===!0}}}async function ensureInstallationId(globalPmRoot){const settings=await readSettings(globalPmRoot);if(!settings.telemetry.enabled||resolveTelemetryEnvironmentPolicy().telemetry_disabled)return null;if(settings.telemetry.installation_id.trim().length===0){if(isConfigurationOnlySettingsRead(globalPmRoot))return null;settings.telemetry.installation_id=crypto.randomUUID(),await writeSettings(globalPmRoot,settings,"telemetry:install_id")}return{installationId:settings.telemetry.installation_id,endpoint:settings.telemetry.endpoint,retentionDays:Math.max(1,Math.trunc(settings.telemetry.retention_days)),captureLevel:normalizeCaptureLevel(settings.telemetry.capture_level)}}async function appendTelemetryEvent(globalPmRoot,event){let serialized=JSON.stringify({client_schema_version:TELEMETRY_CLIENT_SCHEMA_VERSION,event,attempts:0});if(serialized.length>TELEMETRY_MAX_EVENT_BYTES){const trimmed={...event,payload:{...event.payload,result_summary:{truncated:!0,reason:"payload_size_exceeded",original_bytes:serialized.length}}};serialized=JSON.stringify({client_schema_version:TELEMETRY_CLIENT_SCHEMA_VERSION,event:trimmed,attempts:0})}await appendLineAtomic(queuePath(globalPmRoot),serialized)}async function enqueueTelemetryEvent(globalPmRoot,event){await withQueueMutation(()=>appendTelemetryEvent(globalPmRoot,event),globalPmRoot)}function parseQueueLines(raw){const entries=[];for(const line of raw.split(`
3
+ `)),resolved}function hashWithInstallationId(installationId,value){return crypto.createHash("sha256").update(`${installationId}:${value}`).digest("hex")}function buildAuthorContextPayloadFields(captureLevel,installationId){const author=(readAuthorEnvironment()??"").trim(),agent=detectAgentIdentity({env:process.env,argv:process.argv}),hasAgentContext=agent.harness!==void 0||agent.model!==void 0;return captureLevel==="minimal"?{has_author_context:author.length>0,has_agent_context:hasAgentContext}:{agent_harness:agent.harness?TELEMETRY_HARNESSES.has(agent.harness)?agent.harness:"other":"none",ci:parseBooleanTrueLike(process.env.CI),...author.length>0?{author_context_hash:hashWithInstallationId(installationId,author)}:{},...agent.harness?{agent_harness_hash:hashWithInstallationId(installationId,agent.harness)}:{},...agent.model?{agent_model_hash:hashWithInstallationId(installationId,agent.model)}:{},...agent.model_source?{agent_model_source:agent.model_source}:{}}}function normalizeForHash(value,depth=0){if(value==null||typeof value=="string"||typeof value=="number"||typeof value=="boolean")return value;if(depth>=TELEMETRY_SANITIZE_MAX_DEPTH)return"[depth_truncated]";if(Array.isArray(value))return value.slice(0,TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS).map(entry=>normalizeForHash(entry,depth+1));if(typeof value=="object"){const record=value,normalized={},sortedKeys=Object.keys(record).sort((left,right)=>left.localeCompare(right));for(const key of sortedKeys)normalized[key]=normalizeForHash(record[key],depth+1);return normalized}return String(value)}function hashTelemetryValue(installationId,value){return hashWithInstallationId(installationId,JSON.stringify(normalizeForHash(value)))}function hashCommandArgs(installationId,args){return{hashes:args.map(arg=>hashWithInstallationId(installationId,arg)),digest:hashWithInstallationId(installationId,args.join("\0"))}}function hashTelemetryErrorFingerprint(installationId,command,errorCode2,errorMessage){const normalizedMessage=sanitizeString(typeof errorMessage=="string"?errorMessage:"","redacted"),normalizedCode=typeof errorCode2=="string"&&errorCode2.length>0?errorCode2:"unknown_error",fingerprintSource=`${command}\0${normalizedCode}\0${normalizedMessage}`;return hashWithInstallationId(installationId,fingerprintSource)}function resolveOtelTracesEndpoint(){if(PM_TELEMETRY_OTEL_DISABLED_VALUES.has((process.env[PM_TELEMETRY_OTEL_DISABLED_ENV]??"").trim().toLowerCase()))return null;const directEndpoint=(process.env[OTEL_TRACES_ENDPOINT_ENV]??"").trim();if(directEndpoint.length>0)try{return new URL(directEndpoint).toString()}catch{return null}const baseEndpoint=(process.env[OTEL_BASE_ENDPOINT_ENV]??"").trim();if(baseEndpoint.length===0)return null;try{const url=new URL(baseEndpoint),normalizedPath=url.pathname.replace(/\/+$/,"");return normalizedPath.endsWith("/v1/traces")||(url.pathname=`${normalizedPath.length===0?"":normalizedPath}/v1/traces`),url.toString()}catch{return null}}function isoToUnixNano(iso){const parsedMs=Date.parse(iso),epochMs=Number.isNaN(parsedMs)?Date.now():parsedMs;return`${BigInt(epochMs)*1000000n}`}function otlpStringAttribute(key,value){return{key,value:{stringValue:value}}}function otlpBoolAttribute(key,value){return{key,value:{boolValue:value}}}function otlpIntAttribute(key,value){return{key,value:{intValue:String(Math.max(0,Math.trunc(value)))}}}function buildOtelSpanRequest(activeCommand,outcome,finishedAtIso,durationMs,sampleRate=1){const endpoint=activeCommand.otel_traces_endpoint;if(typeof endpoint!="string"||endpoint.trim().length===0||[activeCommand.otel_trace_id,activeCommand.otel_span_id].some(id=>typeof id!="string"||id.length===0))return null;const serviceNameCandidate=sanitizeString((process.env[OTEL_SERVICE_NAME_ENV]??"").trim()),serviceName=serviceNameCandidate.length>0?serviceNameCandidate:"pm-cli",normalizedExitCode=normalizeTelemetryExitCode(outcome.exit_code,outcome.ok),normalizedErrorCode=normalizeTelemetryErrorCode(outcome.error_code),normalizedErrorCategory=normalizeTelemetryErrorCategory({ok:outcome.ok,errorCode:normalizedErrorCode,errorCategory:outcome.error_category}),attributes=[otlpStringAttribute("pm.command",sanitizeString(activeCommand.command)),otlpStringAttribute("pm.version",activeCommand.pm_version),otlpStringAttribute("pm.source_context",activeCommand.source_context),otlpStringAttribute("pm.source_context_source",activeCommand.source_context_source),otlpStringAttribute("pm.installation_id",activeCommand.installation_id),otlpStringAttribute("pm.session_id",PROCESS_SESSION_ID),otlpStringAttribute("pm.pm_root_hash",activeCommand.pm_root_hash),otlpStringAttribute("pm.cwd_hash",activeCommand.cwd_hash),otlpBoolAttribute("pm.ok",outcome.ok),otlpIntAttribute("pm.exit_code",normalizedExitCode),otlpIntAttribute("pm.duration_ms",durationMs),otlpStringAttribute("pm.sample_rate",String(sampleRate))];typeof normalizedErrorCode=="string"&&attributes.push(otlpStringAttribute("pm.error_code",normalizedErrorCode)),typeof normalizedErrorCategory=="string"&&attributes.push(otlpStringAttribute("pm.error_category",normalizedErrorCategory)),typeof outcome.error=="string"&&outcome.error.trim().length>0&&attributes.push(otlpStringAttribute("pm.error",sanitizeString(outcome.error)));const payload={resourceSpans:[{resource:{attributes:[otlpStringAttribute("service.name",serviceName)]},scopeSpans:[{scope:{name:"pm-cli.telemetry",version:"1"},spans:[{traceId:activeCommand.otel_trace_id,spanId:activeCommand.otel_span_id,name:`pm.command.${sanitizeString(activeCommand.command)}`,kind:1,startTimeUnixNano:isoToUnixNano(activeCommand.started_at),endTimeUnixNano:isoToUnixNano(finishedAtIso),attributes,status:{code:outcome.ok?1:2,message:outcome.ok?"":sanitizeString(typeof outcome.error=="string"?outcome.error:"command_failed")}}]}]}]};return{endpoint,payload}}function summarizeResult(result,captureLevel="redacted"){if(result==null)return{type:"nullish"};if(typeof result=="string")return{type:"string",value:sanitizeString(result,captureLevel)};if(typeof result=="number"||typeof result=="boolean")return{type:typeof result,value:result};if(Array.isArray(result))return{type:"array",length:result.length,sample:result.slice(0,5).map(entry=>sanitizeValue(entry,void 0,captureLevel))};if(typeof result=="object"){const record=result,keys=Object.keys(record).filter(key=>key!=="tests").sort((left,right)=>left.localeCompare(right)),sanitized={};let previewBytes=0;for(const key of keys.slice(0,25)){const sanitizedValue=sanitizeValue(record[key],key,captureLevel);if(sanitizedValue===void 0)continue;const entrySize=JSON.stringify(sanitizedValue).length;if(previewBytes+entrySize>TELEMETRY_RESULT_PREVIEW_MAX_BYTES){sanitized[key]="[preview_truncated]";break}previewBytes+=entrySize,sanitized[key]=sanitizedValue}return{type:"object",key_count:keys.length,keys_preview:keys.slice(0,50),preview:sanitized}}return{type:typeof result,value:String(result)}}function buildCommandStartPayload(params){const{captureLevel,context,pmVersion,sourceContext,pmRootHash,cwdHash,installationId}=params,commandTaxonomy=deriveTelemetryCommandTaxonomy(context.command),hashedArgs=hashCommandArgs(installationId,context.args),commandInvocationDigest=hashWithInstallationId(installationId,`${context.command}\0${context.args.join("\0")}`),commandOptionsDigest=hashTelemetryValue(installationId,context.options),globalOptionsDigest=hashTelemetryValue(installationId,context.global),authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);return captureLevel==="minimal"?{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_args_digest:hashedArgs.digest,command_invocation_digest:commandInvocationDigest,command_options_digest:commandOptionsDigest,global_options_digest:globalOptionsDigest,...authorContextFields}:{pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,...authorContextFields,command_args:sanitizeCommandArgs(context.args,captureLevel),command_args_hashes:hashedArgs.hashes,command_args_digest:hashedArgs.digest,command_invocation_digest:commandInvocationDigest,command_options:sanitizeValue(context.options,void 0,captureLevel),command_options_digest:commandOptionsDigest,global_options:sanitizeValue(context.global,void 0,captureLevel),global_options_digest:globalOptionsDigest,pm_root_hash:pmRootHash,cwd_hash:cwdHash,capture_level:captureLevel,runtime:{node:process.version,platform:process.platform,arch:process.arch,hostname_hash:hashWithInstallationId(installationId,os.hostname()),stdin_tty:process.stdin.isTTY===!0,stdout_tty:process.stdout.isTTY===!0}}}function buildCommandFinishPayload(params){const{captureLevel,pmVersion,sourceContext,outcome,durationMs,startedAt,command,installationId,commandTaxonomy,exitCode,errorCode:errorCode2,errorCategory,commandResolution,resolutionStage}=params,errorFingerprint=outcome.ok===!1?hashTelemetryErrorFingerprint(installationId,command,errorCode2,outcome.error):void 0,authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);return captureLevel==="minimal"?{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_resolution:commandResolution,resolution_stage:resolutionStage,ok:outcome.ok,exit_code:exitCode,error_code:errorCode2,error_category:errorCategory,error:outcome.error?sanitizeString(outcome.error,"redacted"):void 0,error_fingerprint:errorFingerprint,duration_ms:durationMs,...authorContextFields}:{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_resolution:commandResolution,resolution_stage:resolutionStage,...authorContextFields,ok:outcome.ok,exit_code:exitCode,error_code:errorCode2,error_category:errorCategory,error:outcome.error?sanitizeString(outcome.error,captureLevel):void 0,error_fingerprint:errorFingerprint,duration_ms:durationMs,started_at:startedAt,result_summary:summarizeResult(outcome.result,captureLevel)}}function buildCommandErrorPayload(params){const{captureLevel,pmVersion,sourceContext,command,commandTaxonomy,commandResolution,resolutionStage,args,options,pmRootHash,cwdHash,installationId,errorCode:errorCode2,errorMessage,errorCategory,exitCode}=params,attemptedArgHashes=hashCommandArgs(installationId,args),attemptedCommandDigest=hashWithInstallationId(installationId,command),attemptedOptionsDigest=hashTelemetryValue(installationId,options),errorFingerprint=hashTelemetryErrorFingerprint(installationId,command,errorCode2,errorMessage),authorContextFields=buildAuthorContextPayloadFields(captureLevel,installationId);return captureLevel==="minimal"?{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_resolution:commandResolution,resolution_stage:resolutionStage,attempted_command_digest:attemptedCommandDigest,attempted_args_digest:attemptedArgHashes.digest,attempted_options_digest:attemptedOptionsDigest,error_code:errorCode2,error_category:errorCategory,exit_code:exitCode,error:sanitizeString(errorMessage,"redacted"),error_fingerprint:errorFingerprint,...authorContextFields}:{capture_level:captureLevel,pm_version:pmVersion,source_context:sourceContext.source_context,source_context_source:sourceContext.source_context_source,command_taxonomy:commandTaxonomy,command_resolution:commandResolution,resolution_stage:resolutionStage,...authorContextFields,attempted_command:sanitizeString(command,captureLevel),attempted_command_digest:attemptedCommandDigest,attempted_args:sanitizeCommandArgs(args,captureLevel),attempted_args_hashes:attemptedArgHashes.hashes,attempted_args_digest:attemptedArgHashes.digest,attempted_options:sanitizeValue(options,void 0,captureLevel),attempted_options_digest:attemptedOptionsDigest,error_code:errorCode2,error_category:errorCategory,exit_code:exitCode,error:sanitizeString(errorMessage,captureLevel),error_fingerprint:errorFingerprint,pm_root_hash:pmRootHash,cwd_hash:cwdHash,runtime:{node:process.version,platform:process.platform,arch:process.arch,hostname_hash:hashWithInstallationId(installationId,os.hostname()),stdin_tty:process.stdin.isTTY===!0,stdout_tty:process.stdout.isTTY===!0}}}async function ensureInstallationId(globalPmRoot){const settings=await readSettings(globalPmRoot);if(!settings.telemetry.enabled||resolveTelemetryEnvironmentPolicy().telemetry_disabled)return null;if(settings.telemetry.installation_id.trim().length===0){if(isConfigurationOnlySettingsRead(globalPmRoot)||isSettingsReadFallback(settings))return null;settings.telemetry.installation_id=crypto.randomUUID(),await writeSettings(globalPmRoot,settings,"telemetry:install_id")}return{installationId:settings.telemetry.installation_id,endpoint:settings.telemetry.endpoint,retentionDays:Math.max(1,Math.trunc(settings.telemetry.retention_days)),captureLevel:normalizeCaptureLevel(settings.telemetry.capture_level)}}async function appendTelemetryEvent(globalPmRoot,event){let serialized=JSON.stringify({client_schema_version:TELEMETRY_CLIENT_SCHEMA_VERSION,event,attempts:0});if(serialized.length>TELEMETRY_MAX_EVENT_BYTES){const trimmed={...event,payload:{...event.payload,result_summary:{truncated:!0,reason:"payload_size_exceeded",original_bytes:serialized.length}}};serialized=JSON.stringify({client_schema_version:TELEMETRY_CLIENT_SCHEMA_VERSION,event:trimmed,attempts:0})}await appendLineAtomic(queuePath(globalPmRoot),serialized)}async function enqueueTelemetryEvent(globalPmRoot,event){await withQueueMutation(()=>appendTelemetryEvent(globalPmRoot,event),globalPmRoot)}function parseQueueLines(raw){const entries=[];for(const line of raw.split(`
4
4
  `)){const trimmed=line.trim();if(trimmed.length!==0)try{const parsed=JSON.parse(trimmed);parsed&&typeof parsed=="object"&&parsed.event&&typeof parsed.event=="object"&&typeof parsed.attempts=="number"&&(parsed.client_schema_version===void 0||typeof parsed.client_schema_version=="number"&&Number.isFinite(parsed.client_schema_version))&&entries.push(parsed)}catch{}}return entries}function nextRetryIso(attempts){const delay=Math.min(TELEMETRY_RETRY_BASE_DELAY_MS*2**Math.max(attempts-1,0),TELEMETRY_MAX_RETRY_DELAY_MS);return new Date(Date.now()+delay).toISOString()}function isDueForRetryAt(nextAttemptAfter){if(typeof nextAttemptAfter!="string"||nextAttemptAfter.trim().length===0)return!0;const dueAtMs=Date.parse(nextAttemptAfter);return Number.isNaN(dueAtMs)?!0:dueAtMs<=Date.now()}function isDueForRetry(entry){return isDueForRetryAt(entry.next_attempt_after)}function retentionCutoffMs(retentionDays){const normalizedDays=Number.isFinite(retentionDays)?Math.max(1,Math.trunc(retentionDays)):1;return Date.now()-normalizedDays*MILLISECONDS_PER_DAY}function isExpiredQueueEntry(entry,cutoffMs){const occurredAt=entry.event?.occurred_at;if(typeof occurredAt!="string"||occurredAt.trim().length===0)return!1;const occurredAtMs=Date.parse(occurredAt);return Number.isNaN(occurredAtMs)?!1:occurredAtMs<cutoffMs}function pruneExpiredQueueEntries(entries,retentionDays){const cutoffMs=retentionCutoffMs(retentionDays),retained=[];let prunedCount=0;for(const entry of entries){if(JSON.stringify(entry).length>TELEMETRY_MAX_EVENT_BYTES||isExpiredQueueEntry(entry,cutoffMs)||entry.attempts>=TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS){prunedCount+=1;continue}retained.push(entry)}return{entries:retained,prunedCount}}async function rewriteQueue(globalPmRoot,entries){const serialized=entries.map(entry=>JSON.stringify(entry)).join(`
5
5
  `),contents=serialized.length>0?`${serialized}
6
6
  `:"";for(let attempt=0;;attempt+=1)try{await writeFileAtomic(queuePath(globalPmRoot),contents,{createParentDirectories:!parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])});return}catch(error){const retryDelay=TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS[attempt];if(retryDelay===void 0||!isRetryableQueueRewriteError(error))throw error;await sleep(retryDelay)}}function isRetryableQueueRewriteError(error){if(typeof error!="object"||error===null||!("code"in error))return!1;const code=error.code;return code==="EACCES"||code==="EBUSY"||code==="EPERM"}function sleep(milliseconds){return new Promise(resolve=>{setTimeout(resolve,milliseconds)})}async function appendPendingOtelSpan(globalPmRoot,request){const pending={id:crypto.randomUUID(),endpoint:request.endpoint,payload:request.payload,enqueued_at:nowIso(),attempts:0},serialized=JSON.stringify(pending);serialized.length>TELEMETRY_MAX_EVENT_BYTES||await appendLineAtomic(otelSpansQueuePath(globalPmRoot),serialized)}async function enqueuePendingOtelSpan(globalPmRoot,request){await withQueueMutation(()=>appendPendingOtelSpan(globalPmRoot,request),globalPmRoot)}function backfillPendingOtelSpanId(entry){const material=JSON.stringify([entry.endpoint,entry.enqueued_at,entry.payload]);return crypto.createHash("sha256").update(material).digest("hex").slice(0,32)}function parsePendingOtelSpanLines(raw){const entries=[];for(const line of raw.split(`
@@ -1,5 +1,5 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7c89b3de-0b7c-529b-a655-87d3e83bd46c")}catch{}})();import fs from"node:fs/promises";import{spawn}from"node:child_process";import{createHash,randomBytes}from"node:crypto";import path from"node:path";import{ensureDir,pathExists,readFileIfExists,writeFileAtomic}from"../fs/fs-utils.js";import{PmCliError}from"../shared/errors.js";import{EXIT_CODE}from"../shared/constants.js";import{nowIso}from"../shared/time.js";import{getTestRunRecordPath,getTestRunResultPath,getTestRunStderrPath,getTestRunStdoutPath,getTestRunsPath,getTestRunsRecordsPath,getTestRunsResultsPath,getTestRunsStderrPath,getTestRunsStdoutPath}from"../store/paths.js";const BACKGROUND_RUN_ACTIVE_STATUSES=new Set(["queued","running"]),BACKGROUND_RUN_TERMINAL_STATUSES=new Set(["passed","failed","stopped","canceled"]),DEFAULT_BACKGROUND_RUN_RESOURCE_SNAPSHOT_INTERVAL_MS=3e3,DEFAULT_BACKGROUND_RUN_FORCE_KILL_DELAY_MS=3e3,DEFAULT_BACKGROUND_RUN_HEARTBEAT_STALE_MS=3e4,DEFAULT_BACKGROUND_RUN_LOG_TAIL_LINES=100,PROC_STAT_TICKS_PER_SECOND=100;function nowMs(){return Date.now()}function normalizeCommandArgs(args){return args.map(entry=>entry.trim()).filter(entry=>entry.length>0)}function summarizeCommandLabel(args){const joined=args.join(" ").replaceAll(/\s+/g," ").trim();return joined.length<=180?joined:`${joined.slice(0,177)}...`}function buildRunId(){const timePart=Date.now().toString(36),randomPart=randomBytes(3).toString("hex");return`tr-${timePart}-${randomPart}`}function buildBackgroundTestRunFingerprint(kind,commandArgs,pmRoot){const payload={kind,command:normalizeCommandArgs(commandArgs),pm_root:path.resolve(pmRoot)};return createHash("sha256").update(JSON.stringify(payload)).digest("hex")}function isPidRunning(pid){if(!Number.isInteger(pid)||!pid||pid<=0)return!1;try{return process.kill(pid,0),!0}catch(error){return(typeof error=="object"&&error!==null&&"code"in error?error.code:void 0)==="EPERM"}}async function ensureBackgroundRunStorage(pmRoot){await ensureDir(getTestRunsPath(pmRoot)),await ensureDir(getTestRunsRecordsPath(pmRoot)),await ensureDir(getTestRunsStdoutPath(pmRoot)),await ensureDir(getTestRunsStderrPath(pmRoot)),await ensureDir(getTestRunsResultsPath(pmRoot))}async function parseBackgroundRunRecord(raw,recordPath){try{const parsed=JSON.parse(raw);if(!parsed||typeof parsed!="object"||typeof parsed.id!="string")throw new Error("invalid run record payload");return parsed}catch(error){throw new PmCliError(`Failed to parse background test run record at ${recordPath}: ${error instanceof Error?error.message:String(error)}`,EXIT_CODE.GENERIC_FAILURE)}}async function writeBackgroundRunRecord(pmRoot,record){const next={...record,updated_at:nowIso()};await writeFileAtomic(getTestRunRecordPath(pmRoot,record.id),`${JSON.stringify(next,null,2)}
2
- `)}async function readBackgroundTestRunRecord(pmRoot,runId){const recordPath=getTestRunRecordPath(pmRoot,runId),raw=await readFileIfExists(recordPath);return raw?parseBackgroundRunRecord(raw,recordPath):null}async function listBackgroundRunRecordPaths(pmRoot){const recordsRoot=getTestRunsRecordsPath(pmRoot);return await pathExists(recordsRoot)?(await fs.readdir(recordsRoot,{withFileTypes:!0})).filter(entry=>entry.isFile()&&entry.name.endsWith(".json")).map(entry=>path.join(recordsRoot,entry.name)).sort((left,right)=>right.localeCompare(left)):[]}function parseLinuxRssStatus(raw){const match=raw.match(/^VmRSS:\s+(\d+)\s+kB$/m);if(match)return Number.parseInt(match[1],10)*1024}async function readLinuxRssBytes(pid){if(process.platform==="linux")try{const raw=await fs.readFile(`/proc/${pid}/status`,"utf8");return parseLinuxRssStatus(raw)}catch{return}}function parseLinuxCpuStat(raw){const closeParenIndex=raw.lastIndexOf(")");if(closeParenIndex<0)return{};const parts=raw.slice(closeParenIndex+2).trim().split(/\s+/),utimeTicks=Number.parseInt(parts[11],10),stimeTicks=Number.parseInt(parts[12],10);return!Number.isFinite(utimeTicks)||!Number.isFinite(stimeTicks)?{}:{cpu_user_seconds:utimeTicks/PROC_STAT_TICKS_PER_SECOND,cpu_system_seconds:stimeTicks/PROC_STAT_TICKS_PER_SECOND}}async function readLinuxCpuSeconds(pid){if(process.platform!=="linux")return{};try{const raw=await fs.readFile(`/proc/${pid}/stat`,"utf8");return parseLinuxCpuStat(raw)}catch{return{}}}async function buildResourceSnapshot(record){const pid=record.child_pid??record.worker_pid;if(!isPidRunning(pid))return;const rssBytes=await readLinuxRssBytes(pid),cpu=await readLinuxCpuSeconds(pid),startedAtMs=record.started_at?Date.parse(record.started_at):Number.NaN,uptimeSeconds=Number.isFinite(startedAtMs)?Math.max(0,(nowMs()-startedAtMs)/1e3):void 0;return{recorded_at:nowIso(),rss_bytes:rssBytes,cpu_user_seconds:cpu.cpu_user_seconds,cpu_system_seconds:cpu.cpu_system_seconds,uptime_seconds:uptimeSeconds}}function readCount(value){return typeof value=="number"&&Number.isFinite(value)?value:0}function evaluateWorkerResult(kind,payload){if(!payload||typeof payload!="object")return{summary:{passed:0,failed:1,skipped:0},parsedResult:null};const record=payload;if(kind==="test-all"){const totals=record.totals??{};return{summary:{items:typeof totals.items=="number"?totals.items:void 0,linked_tests:typeof totals.linked_tests=="number"?totals.linked_tests:void 0,passed:readCount(totals.passed),failed:readCount(totals.failed),skipped:readCount(totals.skipped),fail_on_skipped_triggered:record.fail_on_skipped_triggered===!0?!0:void 0},parsedResult:payload}}const runResults=Array.isArray(record.run_results)?record.run_results:[];let passed=0,failed=0,skipped=0;for(const entry of runResults){if(!entry||typeof entry!="object")continue;const status=entry.status;if(status==="passed"){passed+=1;continue}if(status==="failed"||status==="refused"){failed+=1;continue}skipped+=1}return{summary:{passed,failed,skipped,fail_on_skipped_triggered:record.fail_on_skipped_triggered===!0?!0:void 0},parsedResult:payload}}function parseProgressLine(stderrLine){const line=stderrLine.trim();if(line.length===0)return null;const testAllMatch=line.match(/\[pm test-all\]\s+item\s+(\d+)\/(\d+)\s+(start|end)\s+id=([^\s]+)/i);if(testAllMatch){const itemIndex=Number.parseInt(testAllMatch[1],10),itemTotal=Number.parseInt(testAllMatch[2],10);return{item_index:itemIndex,item_total:itemTotal,item_id:testAllMatch[4],linked_test_index:void 0,linked_test_total:void 0,current_command:void 0,elapsed_ms:void 0,heartbeat_at:nowIso(),phase:testAllMatch[3]?.toLowerCase()==="end"?"finished":"running"}}const linkedTestMatch=line.match(/\[pm test\]\s+linked-test\s+(\d+)\/(\d+)\s+(start|running|end)(?:.*elapsed_ms=(\d+))?/i);if(!linkedTestMatch)return null;const index=Number.parseInt(linkedTestMatch[1],10),total=Number.parseInt(linkedTestMatch[2],10),elapsed=linkedTestMatch[4]?Number.parseInt(linkedTestMatch[4],10):void 0,commandMatch=line.match(/\scommand="((?:\\.|[^"\\])*)"/),currentCommand=commandMatch?commandMatch[1].replaceAll('\\"','"').replaceAll("\\\\","\\"):void 0;return{linked_test_index:index,linked_test_total:total,current_command:currentCommand,elapsed_ms:Number.isFinite(elapsed)?elapsed:void 0,heartbeat_at:nowIso(),phase:linkedTestMatch[3]?.toLowerCase()==="end"?"finished":"running"}}function splitLines(value){return value.split(/\r?\n/).map(entry=>entry.trimEnd()).filter(entry=>entry.length>0)}function tailLines(value,limit){if(limit<=0)return[];const lines=splitLines(value);return lines.length<=limit?lines:lines.slice(lines.length-limit)}async function resolveBackgroundCliEntry(cwd){const configured=process.env.PM_BACKGROUND_CLI_ENTRY?.trim();if(configured&&configured.length>0){const resolvedConfigured=path.resolve(cwd,configured);if(await pathExists(resolvedConfigured))return resolvedConfigured}const distEntry=path.resolve(cwd,"dist","cli.js");if(await pathExists(distEntry))return distEntry;const argvEntry=process.argv[1]?.trim();if(argvEntry&&argvEntry.length>0){const resolvedArgvEntry=path.resolve(cwd,argvEntry);if(await pathExists(resolvedArgvEntry))return resolvedArgvEntry}throw new PmCliError("Unable to resolve a CLI entrypoint for background test runs. Build the project or set PM_BACKGROUND_CLI_ENTRY.",EXIT_CODE.GENERIC_FAILURE)}async function refreshRunIfStale(pmRoot,record){if(!BACKGROUND_RUN_ACTIVE_STATUSES.has(record.status)||isPidRunning(record.worker_pid)||record.finished_at)return record;const next={...record,status:"failed",finished_at:nowIso(),error:record.error??"Background test run worker exited before writing terminal status."};return await writeBackgroundRunRecord(pmRoot,next),next}async function startBackgroundTestRun(options){await ensureBackgroundRunStorage(options.pmRoot);const normalizedArgs=normalizeCommandArgs(options.commandArgs);if(normalizedArgs.length===0)throw new PmCliError("Background test run requires command arguments.",EXIT_CODE.USAGE);const fingerprint=buildBackgroundTestRunFingerprint(options.kind,normalizedArgs,options.pmRoot),existingRuns=await listBackgroundTestRuns(options.pmRoot,{});for(const existing of existingRuns){const refreshed=await refreshRunIfStale(options.pmRoot,existing);if(refreshed.fingerprint===fingerprint&&!(!BACKGROUND_RUN_ACTIVE_STATUSES.has(refreshed.status)||!isPidRunning(refreshed.worker_pid)))return{started:!1,run:{...refreshed,duplicate_of:refreshed.id},duplicate_of:refreshed.id}}const runId=buildRunId(),createdAt=nowIso(),stdoutPath=getTestRunStdoutPath(options.pmRoot,runId),stderrPath=getTestRunStderrPath(options.pmRoot,runId),resultPath=getTestRunResultPath(options.pmRoot,runId);await fs.writeFile(stdoutPath,"","utf8"),await fs.writeFile(stderrPath,"","utf8");const record={id:runId,kind:options.kind,status:"queued",created_at:createdAt,updated_at:createdAt,requested_by:options.requestedBy,fingerprint,command_args:normalizedArgs,command_label:summarizeCommandLabel(normalizedArgs),pm_root:options.pmRoot,global_pm_root:options.globalPmRoot,target_id:options.targetId,status_filter:options.statusFilter,attempt:typeof options.attempt=="number"&&Number.isFinite(options.attempt)&&options.attempt>=1?Math.floor(options.attempt):1,resumed_from:options.resumedFrom,resumed_by:options.resumedBy,stdout_path:stdoutPath,stderr_path:stderrPath,result_path:resultPath,progress:{phase:"queued",message:"Queued for background execution.",heartbeat_at:createdAt}};return await writeBackgroundRunRecord(options.pmRoot,record),{started:!0,run:record}}async function spawnBackgroundTestRunWorker(options){const record=await readBackgroundTestRunRecord(options.pmRoot,options.runId);if(!record)throw new PmCliError(`Background test run ${options.runId} not found`,EXIT_CODE.NOT_FOUND);if(BACKGROUND_RUN_TERMINAL_STATUSES.has(record.status))throw new PmCliError(`Background test run ${record.id} is already terminal (${record.status}).`,EXIT_CODE.CONFLICT);const cliEntry=await resolveBackgroundCliEntry(process.cwd()),args=[];options.noExtensions===!0&&args.push("--no-extensions"),args.push("--path",record.pm_root,"test-runs-worker",record.id);const env={...process.env,PM_PATH:record.pm_root,PM_GLOBAL_PATH:record.global_pm_root,PM_BACKGROUND_TEST_RUN_ID:record.id,PM_BACKGROUND_TEST_RUN_ATTEMPT:String(record.attempt),PM_BACKGROUND_TEST_RUN_RESUMED_FROM:record.resumed_from??"",FORCE_COLOR:"0"},child=spawn(process.execPath,[cliEntry,...args],{cwd:process.cwd(),env,detached:!0,stdio:"ignore",windowsHide:!0});child.unref();const next={...record,status:"queued",worker_pid:child.pid,progress:{phase:"queued",message:"Worker process started.",heartbeat_at:nowIso()}};return await writeBackgroundRunRecord(options.pmRoot,next),next}async function appendFileOrdered(queue,filePath,text){await queue,await fs.appendFile(filePath,text,"utf8")}function resolvePositiveEnvInteger(name,fallback){const parsed=Number.parseInt(process.env[name]??"",10);return Number.isFinite(parsed)&&parsed>0?parsed:fallback}function buildBackgroundWorkerEnv(record){return{...process.env,PM_PATH:record.pm_root,PM_GLOBAL_PATH:record.global_pm_root,FORCE_COLOR:"0"}}function buildBackgroundWorkerChildArgs(record,noExtensions){return noExtensions?["--no-extensions",...record.command_args]:[...record.command_args]}function createBackgroundRunRecordWriteScheduler(pmRoot,record){let writeQueue=Promise.resolve();return{schedule(){writeQueue=writeQueue.then(async()=>{try{await writeBackgroundRunRecord(pmRoot,record)}catch{}})},async flush(){await writeQueue}}}function requestChildSignal(child,signal){try{child.kill(signal)}catch{}}async function requestBackgroundWorkerStop(record,child,state,scheduleRecordWrite){state.stopRequested||(state.stopRequested=!0,record.stop_requested_at=nowIso(),record.progress={...record.progress,phase:"stopping",message:"Stop requested for background run.",heartbeat_at:nowIso()},scheduleRecordWrite(),requestChildSignal(child,"SIGTERM"),setTimeout(()=>requestChildSignal(child,"SIGKILL"),resolvePositiveEnvInteger("PM_BACKGROUND_RUN_FORCE_KILL_DELAY_MS",DEFAULT_BACKGROUND_RUN_FORCE_KILL_DELAY_MS)).unref?.())}function buildItemBackgroundProgress(line,progressPatch,phase){return{phase,message:line,heartbeat_at:nowIso(),item_index:progressPatch.item_index,item_total:progressPatch.item_total,item_id:progressPatch.item_id,linked_test_index:void 0,linked_test_total:void 0,current_command:void 0,elapsed_ms:void 0}}function buildLinkedTestBackgroundProgress(line,record,progressPatch,phase){return{phase,message:line,heartbeat_at:nowIso(),item_index:progressPatch.item_index??record.progress?.item_index,item_total:progressPatch.item_total??record.progress?.item_total,item_id:progressPatch.item_id??record.progress?.item_id,linked_test_index:progressPatch.linked_test_index,linked_test_total:progressPatch.linked_test_total,current_command:progressPatch.current_command,elapsed_ms:progressPatch.elapsed_ms}}function applyBackgroundWorkerProgressLine(record,line,stopRequested){const progressPatch=parseProgressLine(line);if(!progressPatch)return!1;const phase=record.progress?.phase==="stopping"?"stopping":"running";return record.progress=progressPatch.item_id?buildItemBackgroundProgress(line,progressPatch,phase):buildLinkedTestBackgroundProgress(line,record,progressPatch,phase),progressPatch.phase==="finished"&&!stopRequested&&(record.progress.phase="running"),!0}function parseBackgroundWorkerStdout(stdoutBuffer){if(stdoutBuffer.trim().length===0)return null;try{return JSON.parse(stdoutBuffer)}catch{return null}}function resolveBackgroundWorkerFinalStatus(record,stopRequested){return stopRequested?"stopped":record.exit_code===0&&(record.summary?.failed??0)===0&&record.summary?.fail_on_skipped_triggered!==!0?"passed":"failed"}function buildFinishedBackgroundProgress(record,stopRequested){return{phase:"finished",message:stopRequested?"Background run stopped.":`Background run finished with status=${record.status}.`,heartbeat_at:nowIso(),item_index:record.progress?.item_index,item_total:record.progress?.item_total,item_id:record.progress?.item_id,linked_test_index:record.progress?.linked_test_index,linked_test_total:record.progress?.linked_test_total,current_command:record.progress?.current_command,elapsed_ms:record.progress?.elapsed_ms}}async function writeBackgroundWorkerResult(record,parsedResult,stdoutBuffer){if(parsedResult!==null){await writeFileAtomic(record.result_path,`${JSON.stringify(parsedResult,null,2)}
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7a7096c6-a9c3-5d8e-96e4-ed1b0218234e")}catch{}})();import fs from"node:fs/promises";import{spawn}from"node:child_process";import{createHash,randomBytes}from"node:crypto";import path from"node:path";import{ensureDir,pathExists,readFileIfExists,writeFileAtomic}from"../fs/fs-utils.js";import{PmCliError}from"../shared/errors.js";import{EXIT_CODE}from"../shared/constants.js";import{nowIso}from"../shared/time.js";import{getTestRunRecordPath,getTestRunResultPath,getTestRunStderrPath,getTestRunStdoutPath,getTestRunsPath,getTestRunsRecordsPath,getTestRunsResultsPath,getTestRunsStderrPath,getTestRunsStdoutPath}from"../store/paths.js";const BACKGROUND_RUN_ACTIVE_STATUSES=new Set(["queued","running"]),BACKGROUND_RUN_TERMINAL_STATUSES=new Set(["passed","failed","stopped","canceled"]),DEFAULT_BACKGROUND_RUN_RESOURCE_SNAPSHOT_INTERVAL_MS=3e3,DEFAULT_BACKGROUND_RUN_FORCE_KILL_DELAY_MS=3e3,DEFAULT_BACKGROUND_RUN_HEARTBEAT_STALE_MS=3e4,DEFAULT_BACKGROUND_RUN_LOG_TAIL_LINES=100,PROC_STAT_TICKS_PER_SECOND=100;function nowMs(){return Date.now()}function normalizeCommandArgs(args){return args.map(entry=>entry.trim()).filter(entry=>entry.length>0)}function summarizeCommandLabel(args){const joined=args.join(" ").replaceAll(/\s+/g," ").trim();return joined.length<=180?joined:`${joined.slice(0,177)}...`}function buildRunId(){const timePart=Date.now().toString(36),randomPart=randomBytes(3).toString("hex");return`tr-${timePart}-${randomPart}`}function buildBackgroundTestRunFingerprint(kind,commandArgs,pmRoot){const payload={kind,command:normalizeCommandArgs(commandArgs),pm_root:path.resolve(pmRoot)};return createHash("sha256").update(JSON.stringify(payload)).digest("hex")}function isPidRunning(pid){if(!Number.isInteger(pid)||!pid||pid<=0)return!1;try{return process.kill(pid,0),!0}catch(error){return(typeof error=="object"&&error!==null&&"code"in error?error.code:void 0)==="EPERM"}}async function ensureBackgroundRunStorage(pmRoot){await ensureDir(getTestRunsPath(pmRoot)),await ensureDir(getTestRunsRecordsPath(pmRoot)),await ensureDir(getTestRunsStdoutPath(pmRoot)),await ensureDir(getTestRunsStderrPath(pmRoot)),await ensureDir(getTestRunsResultsPath(pmRoot))}async function parseBackgroundRunRecord(raw,recordPath){try{const parsed=JSON.parse(raw);if(!parsed||typeof parsed!="object"||typeof parsed.id!="string")throw new Error("invalid run record payload");return parsed}catch(error){throw new PmCliError(`Failed to parse background test run record at ${recordPath}: ${error instanceof Error?error.message:String(error)}`,EXIT_CODE.GENERIC_FAILURE)}}async function writeBackgroundRunRecord(pmRoot,record){const next={...record,updated_at:nowIso()};await writeFileAtomic(getTestRunRecordPath(pmRoot,record.id),`${JSON.stringify(next,null,2)}
2
+ `)}async function readBackgroundTestRunRecord(pmRoot,runId){const recordPath=getTestRunRecordPath(pmRoot,runId),raw=await readFileIfExists(recordPath);return raw?parseBackgroundRunRecord(raw,recordPath):null}async function listBackgroundRunRecordPaths(pmRoot){const recordsRoot=getTestRunsRecordsPath(pmRoot);return await pathExists(recordsRoot)?(await fs.readdir(recordsRoot,{withFileTypes:!0})).filter(entry=>entry.isFile()&&entry.name.endsWith(".json")).map(entry=>path.join(recordsRoot,entry.name)).sort((left,right)=>right.localeCompare(left)):[]}function parseLinuxRssStatus(raw){const match=raw.match(/^VmRSS:\s+(\d+)\s+kB$/m);if(match)return Number.parseInt(match[1],10)*1024}async function readLinuxRssBytes(pid){if(process.platform==="linux")try{const raw=await fs.readFile(`/proc/${pid}/status`,"utf8");return parseLinuxRssStatus(raw)}catch{return}}function parseLinuxCpuStat(raw){const closeParenIndex=raw.lastIndexOf(")");if(closeParenIndex<0)return{};const parts=raw.slice(closeParenIndex+2).trim().split(/\s+/),utimeTicks=Number.parseInt(parts[11],10),stimeTicks=Number.parseInt(parts[12],10);return!Number.isFinite(utimeTicks)||!Number.isFinite(stimeTicks)?{}:{cpu_user_seconds:utimeTicks/PROC_STAT_TICKS_PER_SECOND,cpu_system_seconds:stimeTicks/PROC_STAT_TICKS_PER_SECOND}}async function readLinuxCpuSeconds(pid){if(process.platform!=="linux")return{};try{const raw=await fs.readFile(`/proc/${pid}/stat`,"utf8");return parseLinuxCpuStat(raw)}catch{return{}}}async function buildResourceSnapshot(record){const pid=record.child_pid??record.worker_pid;if(!isPidRunning(pid))return;const rssBytes=await readLinuxRssBytes(pid),cpu=await readLinuxCpuSeconds(pid),startedAtMs=record.started_at?Date.parse(record.started_at):Number.NaN,uptimeSeconds=Number.isFinite(startedAtMs)?Math.max(0,(nowMs()-startedAtMs)/1e3):void 0;return{recorded_at:nowIso(),rss_bytes:rssBytes,cpu_user_seconds:cpu.cpu_user_seconds,cpu_system_seconds:cpu.cpu_system_seconds,uptime_seconds:uptimeSeconds}}function readCount(value){return typeof value=="number"&&Number.isFinite(value)?value:0}function evaluateWorkerResult(kind,payload){if(!payload||typeof payload!="object")return{summary:{passed:0,failed:1,skipped:0},parsedResult:null};const record=payload;if(kind==="test-all"){const totals=record.totals??{};return{summary:{items:typeof totals.items=="number"?totals.items:void 0,linked_tests:typeof totals.linked_tests=="number"?totals.linked_tests:void 0,passed:readCount(totals.passed),failed:readCount(totals.failed),skipped:readCount(totals.skipped),fail_on_skipped_triggered:record.fail_on_skipped_triggered===!0?!0:void 0},parsedResult:payload}}const runResults=Array.isArray(record.run_results)?record.run_results:[];let passed=0,failed=0,skipped=0;for(const entry of runResults){if(!entry||typeof entry!="object")continue;const status=entry.status;if(status==="passed"){passed+=1;continue}if(status==="failed"||status==="refused"){failed+=1;continue}skipped+=1}return{summary:{passed,failed,skipped,fail_on_skipped_triggered:record.fail_on_skipped_triggered===!0?!0:void 0},parsedResult:payload}}function parseProgressLine(stderrLine){const line=stderrLine.trim();if(line.length===0)return null;const testAllMatch=line.match(/\[pm test-all\]\s+item\s+(\d+)\/(\d+)\s+(start|end)\s+id=([^\s]+)/i);if(testAllMatch){const itemIndex=Number.parseInt(testAllMatch[1],10),itemTotal=Number.parseInt(testAllMatch[2],10);return{item_index:itemIndex,item_total:itemTotal,item_id:testAllMatch[4],linked_test_index:void 0,linked_test_total:void 0,current_command:void 0,elapsed_ms:void 0,heartbeat_at:nowIso(),phase:testAllMatch[3]?.toLowerCase()==="end"?"finished":"running"}}const linkedTestMatch=line.match(/\[pm test\]\s+linked-test\s+(\d+)\/(\d+)\s+(start|running|end)(?:.*elapsed_ms=(\d+))?/i);if(!linkedTestMatch)return null;const index=Number.parseInt(linkedTestMatch[1],10),total=Number.parseInt(linkedTestMatch[2],10),elapsed=linkedTestMatch[4]?Number.parseInt(linkedTestMatch[4],10):void 0,commandMatch=line.match(/\scommand="((?:\\.|[^"\\])*)"/),currentCommand=commandMatch?commandMatch[1].replaceAll('\\"','"').replaceAll("\\\\","\\"):void 0;return{linked_test_index:index,linked_test_total:total,current_command:currentCommand,elapsed_ms:Number.isFinite(elapsed)?elapsed:void 0,heartbeat_at:nowIso(),phase:linkedTestMatch[3]?.toLowerCase()==="end"?"finished":"running"}}function splitLines(value){return value.split(/\r?\n/).map(entry=>entry.trimEnd()).filter(entry=>entry.length>0)}function tailLines(value,limit){if(limit<=0)return[];const lines=splitLines(value);return lines.length<=limit?lines:lines.slice(lines.length-limit)}async function resolveBackgroundCliEntry(cwd){const configured=process.env.PM_BACKGROUND_CLI_ENTRY?.trim();if(configured&&configured.length>0){const resolvedConfigured=path.resolve(cwd,configured);if(await pathExists(resolvedConfigured))return resolvedConfigured}const distEntry=path.resolve(cwd,"dist","cli.js");if(await pathExists(distEntry))return distEntry;const argvEntry=process.argv[1]?.trim();if(argvEntry&&argvEntry.length>0){const resolvedArgvEntry=path.resolve(cwd,argvEntry);if(await pathExists(resolvedArgvEntry))return resolvedArgvEntry}throw new PmCliError("Unable to resolve a CLI entrypoint for background test runs. Build the project or set PM_BACKGROUND_CLI_ENTRY.",EXIT_CODE.GENERIC_FAILURE)}async function refreshRunIfStale(pmRoot,record){if(!BACKGROUND_RUN_ACTIVE_STATUSES.has(record.status)||isPidRunning(record.worker_pid)||record.finished_at)return record;const next={...record,status:"failed",finished_at:nowIso(),error:record.error??"Background test run worker exited before writing terminal status."};return await writeBackgroundRunRecord(pmRoot,next),next}async function startBackgroundTestRun(options){await ensureBackgroundRunStorage(options.pmRoot);const normalizedArgs=normalizeCommandArgs(options.commandArgs);if(normalizedArgs.length===0)throw new PmCliError("Background test run requires command arguments.",EXIT_CODE.USAGE);const fingerprint=buildBackgroundTestRunFingerprint(options.kind,normalizedArgs,options.pmRoot),existingRuns=await listBackgroundTestRuns(options.pmRoot,{});for(const existing of existingRuns){const refreshed=await refreshRunIfStale(options.pmRoot,existing);if(refreshed.fingerprint===fingerprint&&!(!BACKGROUND_RUN_ACTIVE_STATUSES.has(refreshed.status)||!isPidRunning(refreshed.worker_pid)))return{started:!1,run:{...refreshed,duplicate_of:refreshed.id},duplicate_of:refreshed.id}}const runId=buildRunId(),createdAt=nowIso(),stdoutPath=getTestRunStdoutPath(options.pmRoot,runId),stderrPath=getTestRunStderrPath(options.pmRoot,runId),resultPath=getTestRunResultPath(options.pmRoot,runId);await fs.writeFile(stdoutPath,"","utf8"),await fs.writeFile(stderrPath,"","utf8");const record={id:runId,kind:options.kind,status:"queued",created_at:createdAt,updated_at:createdAt,requested_by:options.requestedBy,fingerprint,command_args:normalizedArgs,command_label:summarizeCommandLabel(normalizedArgs),pm_root:options.pmRoot,global_pm_root:options.globalPmRoot,target_id:options.targetId,status_filter:options.statusFilter,attempt:typeof options.attempt=="number"&&Number.isFinite(options.attempt)&&options.attempt>=1?Math.floor(options.attempt):1,resumed_from:options.resumedFrom,resumed_by:options.resumedBy,stdout_path:stdoutPath,stderr_path:stderrPath,result_path:resultPath,progress:{phase:"queued",message:"Queued for background execution.",heartbeat_at:createdAt}};return await writeBackgroundRunRecord(options.pmRoot,record),{started:!0,run:record}}async function spawnBackgroundTestRunWorker(options){const record=await readBackgroundTestRunRecord(options.pmRoot,options.runId);if(!record)throw new PmCliError(`Background test run ${options.runId} not found`,EXIT_CODE.NOT_FOUND);if(BACKGROUND_RUN_TERMINAL_STATUSES.has(record.status))throw new PmCliError(`Background test run ${record.id} is already terminal (${record.status}).`,EXIT_CODE.CONFLICT);const cliEntry=await resolveBackgroundCliEntry(process.cwd()),args=[];options.noExtensions===!0&&args.push("--no-extensions"),args.push("--path",record.pm_root,"test-runs-worker",record.id);const env={...process.env,PM_PATH:record.pm_root,PM_GLOBAL_PATH:record.global_pm_root,PM_BACKGROUND_TEST_RUN_ID:record.id,PM_BACKGROUND_TEST_RUN_ATTEMPT:String(record.attempt),PM_BACKGROUND_TEST_RUN_RESUMED_FROM:record.resumed_from??"",FORCE_COLOR:"0"},child=spawn(process.execPath,[cliEntry,...args],{cwd:process.cwd(),env,detached:!0,stdio:"ignore",windowsHide:!0});child.unref();const next={...record,status:"queued",worker_pid:child.pid,progress:{phase:"queued",message:"Worker process started.",heartbeat_at:nowIso()}};return await writeBackgroundRunRecord(options.pmRoot,next),next}async function appendFileOrdered(queue,filePath,text){await queue,await fs.appendFile(filePath,text,"utf8")}function resolvePositiveEnvInteger(name,fallback){const parsed=Number.parseInt(process.env[name]??"",10);return Number.isFinite(parsed)&&parsed>0?parsed:fallback}function buildBackgroundWorkerEnv(record){return{...process.env,PM_PATH:record.pm_root,PM_GLOBAL_PATH:record.global_pm_root,FORCE_COLOR:"0"}}function buildBackgroundWorkerChildArgs(record,noExtensions){return noExtensions?["--no-extensions",...record.command_args]:[...record.command_args]}function createBackgroundRunRecordWriteScheduler(pmRoot,record){let writeQueue=Promise.resolve();return{schedule(){writeQueue=writeQueue.then(async()=>{try{await writeBackgroundRunRecord(pmRoot,record)}catch{}})},async flush(){await writeQueue}}}function requestChildSignal(child,signal){try{child.kill(signal)}catch{}}async function requestBackgroundWorkerStop(record,child,state,scheduleRecordWrite){state.stopRequested||(state.stopRequested=!0,record.stop_requested_at=nowIso(),record.progress={...record.progress,phase:"stopping",message:"Stop requested for background run.",heartbeat_at:nowIso()},scheduleRecordWrite(),requestChildSignal(child,"SIGTERM"),setTimeout(()=>requestChildSignal(child,"SIGKILL"),resolvePositiveEnvInteger("PM_BACKGROUND_RUN_FORCE_KILL_DELAY_MS",DEFAULT_BACKGROUND_RUN_FORCE_KILL_DELAY_MS)).unref?.())}function buildItemBackgroundProgress(line,progressPatch,phase){return{phase,message:line,heartbeat_at:nowIso(),item_index:progressPatch.item_index,item_total:progressPatch.item_total,item_id:progressPatch.item_id,linked_test_index:void 0,linked_test_total:void 0,current_command:void 0,elapsed_ms:void 0}}function buildLinkedTestBackgroundProgress(line,record,progressPatch,phase){return{phase,message:line,heartbeat_at:nowIso(),item_index:progressPatch.item_index??record.progress?.item_index,item_total:progressPatch.item_total??record.progress?.item_total,item_id:progressPatch.item_id??record.progress?.item_id,linked_test_index:progressPatch.linked_test_index,linked_test_total:progressPatch.linked_test_total,current_command:progressPatch.current_command,elapsed_ms:progressPatch.elapsed_ms}}function applyBackgroundWorkerProgressLine(record,line,stopRequested){const progressPatch=parseProgressLine(line);if(!progressPatch)return!1;const phase=record.progress?.phase==="stopping"?"stopping":"running";return record.progress=progressPatch.item_id?buildItemBackgroundProgress(line,progressPatch,phase):buildLinkedTestBackgroundProgress(line,record,progressPatch,phase),progressPatch.phase==="finished"&&!stopRequested&&(record.progress.phase="running"),!0}function parseBackgroundWorkerStdout(stdoutBuffer){if(stdoutBuffer.trim().length===0)return null;try{return JSON.parse(stdoutBuffer)}catch{return null}}function resolveBackgroundWorkerFinalStatus(exitCode,summary,stopRequested){return stopRequested?"stopped":exitCode===0&&summary.failed===0&&summary.fail_on_skipped_triggered!==!0?"passed":"failed"}function buildFinishedBackgroundProgress(record,stopRequested){return{phase:"finished",message:stopRequested?"Background run stopped.":`Background run finished with status=${record.status}.`,heartbeat_at:nowIso(),item_index:record.progress?.item_index,item_total:record.progress?.item_total,item_id:record.progress?.item_id,linked_test_index:record.progress?.linked_test_index,linked_test_total:record.progress?.linked_test_total,current_command:record.progress?.current_command,elapsed_ms:record.progress?.elapsed_ms}}async function writeBackgroundWorkerResult(record,parsedResult,stdoutBuffer){if(parsedResult!==null){await writeFileAtomic(record.result_path,`${JSON.stringify(parsedResult,null,2)}
3
3
  `);return}await writeFileAtomic(record.result_path,`${JSON.stringify({parse_error:"Background run output was not valid JSON.",stdout_excerpt:tailLines(stdoutBuffer,DEFAULT_BACKGROUND_RUN_LOG_TAIL_LINES)},null,2)}
4
- `)}async function runBackgroundTestRunWorker(pmRoot,runId,noExtensions=!1){const loaded=await readBackgroundTestRunRecord(pmRoot,runId);if(!loaded)throw new PmCliError(`Background test run ${runId} not found`,EXIT_CODE.NOT_FOUND);const record={...loaded,status:"running",started_at:loaded.started_at??nowIso(),worker_pid:process.pid,progress:{phase:"running",message:"Worker started.",heartbeat_at:nowIso()}},cliEntry=await resolveBackgroundCliEntry(process.cwd()),env=buildBackgroundWorkerEnv(record);await writeBackgroundRunRecord(pmRoot,record);const childArgs=buildBackgroundWorkerChildArgs(record,noExtensions),child=spawn(process.execPath,[cliEntry,...childArgs],{cwd:process.cwd(),env,detached:!1,stdio:["ignore","pipe","pipe"],windowsHide:!0});record.child_pid=child.pid;const recordWriteScheduler=createBackgroundRunRecordWriteScheduler(pmRoot,record),scheduleRecordWrite=recordWriteScheduler.schedule;let stdoutWriteQueue=Promise.resolve(),stderrWriteQueue=Promise.resolve(),stdoutBuffer="",stderrBuffer="";const stopState={stopRequested:!1},onSignal=()=>{requestBackgroundWorkerStop(record,child,stopState,scheduleRecordWrite)};process.on("SIGTERM",onSignal),process.on("SIGINT",onSignal);const resourceTimer=setInterval(()=>{(async()=>(record.resource=await buildResourceSnapshot(record),record.progress.heartbeat_at=nowIso(),scheduleRecordWrite()))()},resolvePositiveEnvInteger("PM_BACKGROUND_RUN_RESOURCE_INTERVAL_MS",DEFAULT_BACKGROUND_RUN_RESOURCE_SNAPSHOT_INTERVAL_MS));resourceTimer.unref?.(),child.stdout?.on("data",chunk=>{const text=chunk.toString("utf8");stdoutBuffer+=text,stdoutWriteQueue=appendFileOrdered(stdoutWriteQueue,record.stdout_path,text)}),child.stderr?.on("data",chunk=>{const text=chunk.toString("utf8");stderrWriteQueue=appendFileOrdered(stderrWriteQueue,record.stderr_path,text),stderrBuffer+=text;const parts=stderrBuffer.split(/\r?\n/);stderrBuffer=parts.pop();let progressChanged=!1;for(const part of parts){const line=part.trimEnd();line.length>0&&applyBackgroundWorkerProgressLine(record,line,stopState.stopRequested)&&(progressChanged=!0)}progressChanged&&scheduleRecordWrite()});let exitCode=null,signal=null;try{({code:exitCode,signal}=await new Promise(resolve=>{child.on("close",(code,closeSignal)=>{resolve({code,signal:closeSignal})})}))}finally{clearInterval(resourceTimer),process.off("SIGTERM",onSignal),process.off("SIGINT",onSignal)}await stdoutWriteQueue,await stderrWriteQueue;const trailingStderrLine=stderrBuffer.trimEnd();trailingStderrLine.length>0&&applyBackgroundWorkerProgressLine(record,trailingStderrLine,stopState.stopRequested)&&scheduleRecordWrite(),stderrBuffer="";const parsedResult=parseBackgroundWorkerStdout(stdoutBuffer),evaluated=evaluateWorkerResult(record.kind,parsedResult);return record.summary=evaluated.summary,record.exit_code=typeof exitCode=="number"?exitCode:void 0,record.signal=signal??void 0,record.finished_at=nowIso(),record.status=resolveBackgroundWorkerFinalStatus(record,stopState.stopRequested),record.progress=buildFinishedBackgroundProgress(record,stopState.stopRequested),record.resource=await buildResourceSnapshot(record),await writeBackgroundWorkerResult(record,parsedResult,stdoutBuffer),await writeBackgroundRunRecord(pmRoot,record),await recordWriteScheduler.flush(),record}async function listBackgroundTestRuns(pmRoot,options){const recordPaths=await listBackgroundRunRecordPaths(pmRoot),runs=[];for(const recordPath of recordPaths){const raw=await readFileIfExists(recordPath);if(!raw)continue;const parsed=await parseBackgroundRunRecord(raw,recordPath);runs.push(parsed)}const refreshed=[];for(const run of runs)refreshed.push(await refreshRunIfStale(pmRoot,run));const sorted=(options.status?refreshed.filter(entry=>entry.status===options.status):refreshed).sort((left,right)=>{const byUpdated=Date.parse(right.updated_at)-Date.parse(left.updated_at);return Number.isFinite(byUpdated)&&byUpdated!==0?byUpdated:right.id.localeCompare(left.id)}),limit=typeof options.limit=="number"&&options.limit>=0?options.limit:void 0;return limit===void 0?sorted:sorted.slice(0,limit)}async function getBackgroundTestRunStatus(pmRoot,runId){const loaded=await readBackgroundTestRunRecord(pmRoot,runId);if(!loaded)throw new PmCliError(`Background test run ${runId} not found`,EXIT_CODE.NOT_FOUND);const refreshed=await refreshRunIfStale(pmRoot,loaded),workerAlive=isPidRunning(refreshed.worker_pid),childAlive=isPidRunning(refreshed.child_pid);refreshed.status==="running"&&!childAlive&&!refreshed.finished_at&&!workerAlive&&(refreshed.status="failed",refreshed.finished_at=nowIso(),refreshed.error=refreshed.error??"Background run process exited unexpectedly.",await writeBackgroundRunRecord(pmRoot,refreshed)),refreshed.status==="running"&&(refreshed.resource=await buildResourceSnapshot(refreshed),await writeBackgroundRunRecord(pmRoot,refreshed));const heartbeatAt=refreshed.progress?.heartbeat_at,heartbeatAtMs=heartbeatAt?Date.parse(heartbeatAt):Number.NaN,lagMs=Number.isFinite(heartbeatAtMs)?Math.max(0,nowMs()-heartbeatAtMs):void 0,staleMs=Number.parseInt(process.env.PM_BACKGROUND_RUN_HEARTBEAT_STALE_MS??"",10),staleThresholdMs=Number.isFinite(staleMs)&&staleMs>0?staleMs:DEFAULT_BACKGROUND_RUN_HEARTBEAT_STALE_MS,healthState=refreshed.status==="running"?lagMs!==void 0&&lagMs>staleThresholdMs?"stale":"healthy":"inactive";return{run:refreshed,health:{state:healthState,last_heartbeat_at:heartbeatAt,heartbeat_lag_ms:lagMs,worker_alive:workerAlive,child_alive:childAlive}}}function sendBackgroundRunStopSignal(record,force){const signal=force?"SIGKILL":"SIGTERM";if(!isPidRunning(record.worker_pid)||!record.worker_pid)return"none";try{return process.kill(record.worker_pid,signal),signal}catch{return"none"}}function buildStoppingBackgroundProgress(record,signalSent){return{phase:"stopping",message:signalSent==="none"?"Run marked stopped.":`Stop requested via ${signalSent}.`,heartbeat_at:nowIso(),item_index:record.progress?.item_index,item_total:record.progress?.item_total,item_id:record.progress?.item_id,linked_test_index:record.progress?.linked_test_index,linked_test_total:record.progress?.linked_test_total,current_command:record.progress?.current_command,elapsed_ms:record.progress?.elapsed_ms}}async function stopBackgroundTestRun(pmRoot,runId,force=!1){const loaded=await readBackgroundTestRunRecord(pmRoot,runId);if(!loaded)throw new PmCliError(`Background test run ${runId} not found`,EXIT_CODE.NOT_FOUND);const refreshed=await refreshRunIfStale(pmRoot,loaded);if(BACKGROUND_RUN_TERMINAL_STATUSES.has(refreshed.status))return{run:refreshed,signal_sent:"none"};const signalSent=sendBackgroundRunStopSignal(refreshed,force);return signalSent==="none"&&(refreshed.status="stopped",refreshed.finished_at=refreshed.finished_at??nowIso()),refreshed.stop_requested_at=nowIso(),refreshed.progress=buildStoppingBackgroundProgress(refreshed,signalSent),await writeBackgroundRunRecord(pmRoot,refreshed),{run:refreshed,signal_sent:signalSent}}async function resumeBackgroundTestRun(pmRoot,runId,requestedBy,noExtensions=!1){const loaded=await readBackgroundTestRunRecord(pmRoot,runId);if(!loaded)throw new PmCliError(`Background test run ${runId} not found`,EXIT_CODE.NOT_FOUND);const refreshed=await refreshRunIfStale(pmRoot,loaded);if(!BACKGROUND_RUN_TERMINAL_STATUSES.has(refreshed.status))throw new PmCliError(`Background test run ${runId} is not terminal and cannot be resumed.`,EXIT_CODE.CONFLICT);const started=await startBackgroundTestRun({pmRoot:refreshed.pm_root,globalPmRoot:refreshed.global_pm_root,kind:refreshed.kind,commandArgs:refreshed.command_args,requestedBy,targetId:refreshed.target_id,statusFilter:refreshed.status_filter,resumedFrom:refreshed.id,resumedBy:requestedBy,attempt:refreshed.attempt+1});if(!started.started)return started.run;const spawned=await spawnBackgroundTestRunWorker({pmRoot,runId:started.run.id,noExtensions}),prior={...refreshed,resumed_by:spawned.id};return await writeBackgroundRunRecord(pmRoot,prior),spawned}async function readBackgroundTestRunLogs(pmRoot,runId,stream,tail){const loaded=await readBackgroundTestRunRecord(pmRoot,runId);if(!loaded)throw new PmCliError(`Background test run ${runId} not found`,EXIT_CODE.NOT_FOUND);const resolvedTail=typeof tail=="number"&&Number.isFinite(tail)&&tail>=0?Math.floor(tail):DEFAULT_BACKGROUND_RUN_LOG_TAIL_LINES,stdoutRaw=stream==="stdout"||stream==="both"?await readFileIfExists(loaded.stdout_path)??"":"",stderrRaw=stream==="stderr"||stream==="both"?await readFileIfExists(loaded.stderr_path)??"":"";return{run:loaded,stream,tail:resolvedTail,stdout:stream==="stdout"||stream==="both"?tailLines(stdoutRaw,resolvedTail):[],stderr:stream==="stderr"||stream==="both"?tailLines(stderrRaw,resolvedTail):[]}}const _testOnly={buildResourceSnapshot,evaluateWorkerResult,isPidRunning,parseLinuxCpuStat,parseLinuxRssStatus,parseProgressLine,readLinuxCpuSeconds,readLinuxRssBytes,refreshRunIfStale,splitLines,tailLines};export{_testOnly,buildBackgroundTestRunFingerprint,getBackgroundTestRunStatus,listBackgroundTestRuns,readBackgroundTestRunLogs,readBackgroundTestRunRecord,resumeBackgroundTestRun,runBackgroundTestRunWorker,spawnBackgroundTestRunWorker,startBackgroundTestRun,stopBackgroundTestRun};
4
+ `)}async function runBackgroundTestRunWorker(pmRoot,runId,noExtensions=!1){const loaded=await readBackgroundTestRunRecord(pmRoot,runId);if(!loaded)throw new PmCliError(`Background test run ${runId} not found`,EXIT_CODE.NOT_FOUND);const record={...loaded,status:"running",started_at:loaded.started_at??nowIso(),worker_pid:process.pid,progress:{phase:"running",message:"Worker started.",heartbeat_at:nowIso()}},cliEntry=await resolveBackgroundCliEntry(process.cwd()),env=buildBackgroundWorkerEnv(record);await writeBackgroundRunRecord(pmRoot,record);const childArgs=buildBackgroundWorkerChildArgs(record,noExtensions),child=spawn(process.execPath,[cliEntry,...childArgs],{cwd:process.cwd(),env,detached:!1,stdio:["ignore","pipe","pipe"],windowsHide:!0});record.child_pid=child.pid;const recordWriteScheduler=createBackgroundRunRecordWriteScheduler(pmRoot,record),scheduleRecordWrite=recordWriteScheduler.schedule;let stdoutWriteQueue=Promise.resolve(),stderrWriteQueue=Promise.resolve(),stdoutBuffer="",stderrBuffer="";const stopState={stopRequested:!1},onSignal=()=>{requestBackgroundWorkerStop(record,child,stopState,scheduleRecordWrite)};process.on("SIGTERM",onSignal),process.on("SIGINT",onSignal);const resourceTimer=setInterval(()=>{(async()=>(record.resource=await buildResourceSnapshot(record),record.progress.heartbeat_at=nowIso(),scheduleRecordWrite()))()},resolvePositiveEnvInteger("PM_BACKGROUND_RUN_RESOURCE_INTERVAL_MS",DEFAULT_BACKGROUND_RUN_RESOURCE_SNAPSHOT_INTERVAL_MS));resourceTimer.unref?.(),child.stdout?.on("data",chunk=>{const text=chunk.toString("utf8");stdoutBuffer+=text,stdoutWriteQueue=appendFileOrdered(stdoutWriteQueue,record.stdout_path,text)}),child.stderr?.on("data",chunk=>{const text=chunk.toString("utf8");stderrWriteQueue=appendFileOrdered(stderrWriteQueue,record.stderr_path,text),stderrBuffer+=text;const parts=stderrBuffer.split(/\r?\n/);stderrBuffer=parts.pop();let progressChanged=!1;for(const part of parts){const line=part.trimEnd();line.length>0&&applyBackgroundWorkerProgressLine(record,line,stopState.stopRequested)&&(progressChanged=!0)}progressChanged&&scheduleRecordWrite()});let exitCode=null,signal=null;try{({code:exitCode,signal}=await new Promise(resolve=>{child.on("close",(code,closeSignal)=>{resolve({code,signal:closeSignal})})}))}finally{clearInterval(resourceTimer),process.off("SIGTERM",onSignal),process.off("SIGINT",onSignal)}await stdoutWriteQueue,await stderrWriteQueue;const trailingStderrLine=stderrBuffer.trimEnd();trailingStderrLine.length>0&&applyBackgroundWorkerProgressLine(record,trailingStderrLine,stopState.stopRequested)&&scheduleRecordWrite(),stderrBuffer="";const parsedResult=parseBackgroundWorkerStdout(stdoutBuffer),evaluated=evaluateWorkerResult(record.kind,parsedResult);return record.summary=evaluated.summary,record.exit_code=typeof exitCode=="number"?exitCode:void 0,record.signal=signal??void 0,record.finished_at=nowIso(),record.status=resolveBackgroundWorkerFinalStatus(record.exit_code,evaluated.summary,stopState.stopRequested),record.progress=buildFinishedBackgroundProgress(record,stopState.stopRequested),record.resource=await buildResourceSnapshot(record),await writeBackgroundWorkerResult(record,parsedResult,stdoutBuffer),await writeBackgroundRunRecord(pmRoot,record),await recordWriteScheduler.flush(),record}async function listBackgroundTestRuns(pmRoot,options){const recordPaths=await listBackgroundRunRecordPaths(pmRoot),runs=[];for(const recordPath of recordPaths){const raw=await readFileIfExists(recordPath);if(!raw)continue;const parsed=await parseBackgroundRunRecord(raw,recordPath);runs.push(parsed)}const refreshed=[];for(const run of runs)refreshed.push(await refreshRunIfStale(pmRoot,run));const sorted=(options.status?refreshed.filter(entry=>entry.status===options.status):refreshed).sort((left,right)=>{const byUpdated=Date.parse(right.updated_at)-Date.parse(left.updated_at);return Number.isFinite(byUpdated)&&byUpdated!==0?byUpdated:right.id.localeCompare(left.id)}),limit=typeof options.limit=="number"&&options.limit>=0?options.limit:void 0;return limit===void 0?sorted:sorted.slice(0,limit)}async function getBackgroundTestRunStatus(pmRoot,runId){const loaded=await readBackgroundTestRunRecord(pmRoot,runId);if(!loaded)throw new PmCliError(`Background test run ${runId} not found`,EXIT_CODE.NOT_FOUND);const refreshed=await refreshRunIfStale(pmRoot,loaded),workerAlive=isPidRunning(refreshed.worker_pid),childAlive=isPidRunning(refreshed.child_pid);refreshed.status==="running"&&!childAlive&&!refreshed.finished_at&&!workerAlive&&(refreshed.status="failed",refreshed.finished_at=nowIso(),refreshed.error=refreshed.error??"Background run process exited unexpectedly.",await writeBackgroundRunRecord(pmRoot,refreshed)),refreshed.status==="running"&&(refreshed.resource=await buildResourceSnapshot(refreshed),await writeBackgroundRunRecord(pmRoot,refreshed));const heartbeatAt=refreshed.progress?.heartbeat_at,heartbeatAtMs=heartbeatAt?Date.parse(heartbeatAt):Number.NaN,lagMs=Number.isFinite(heartbeatAtMs)?Math.max(0,nowMs()-heartbeatAtMs):void 0,staleMs=Number.parseInt(process.env.PM_BACKGROUND_RUN_HEARTBEAT_STALE_MS??"",10),staleThresholdMs=Number.isFinite(staleMs)&&staleMs>0?staleMs:DEFAULT_BACKGROUND_RUN_HEARTBEAT_STALE_MS,healthState=refreshed.status==="running"?lagMs!==void 0&&lagMs>staleThresholdMs?"stale":"healthy":"inactive";return{run:refreshed,health:{state:healthState,last_heartbeat_at:heartbeatAt,heartbeat_lag_ms:lagMs,worker_alive:workerAlive,child_alive:childAlive}}}function sendBackgroundRunStopSignal(record,force){const signal=force?"SIGKILL":"SIGTERM";if(!isPidRunning(record.worker_pid)||!record.worker_pid)return"none";try{return process.kill(record.worker_pid,signal),signal}catch{return"none"}}function buildStoppingBackgroundProgress(record,signalSent){return{phase:"stopping",message:signalSent==="none"?"Run marked stopped.":`Stop requested via ${signalSent}.`,heartbeat_at:nowIso(),item_index:record.progress?.item_index,item_total:record.progress?.item_total,item_id:record.progress?.item_id,linked_test_index:record.progress?.linked_test_index,linked_test_total:record.progress?.linked_test_total,current_command:record.progress?.current_command,elapsed_ms:record.progress?.elapsed_ms}}async function stopBackgroundTestRun(pmRoot,runId,force=!1){const loaded=await readBackgroundTestRunRecord(pmRoot,runId);if(!loaded)throw new PmCliError(`Background test run ${runId} not found`,EXIT_CODE.NOT_FOUND);const refreshed=await refreshRunIfStale(pmRoot,loaded);if(BACKGROUND_RUN_TERMINAL_STATUSES.has(refreshed.status))return{run:refreshed,signal_sent:"none"};const signalSent=sendBackgroundRunStopSignal(refreshed,force);return signalSent==="none"&&(refreshed.status="stopped",refreshed.finished_at=refreshed.finished_at??nowIso()),refreshed.stop_requested_at=nowIso(),refreshed.progress=buildStoppingBackgroundProgress(refreshed,signalSent),await writeBackgroundRunRecord(pmRoot,refreshed),{run:refreshed,signal_sent:signalSent}}async function resumeBackgroundTestRun(pmRoot,runId,requestedBy,noExtensions=!1){const loaded=await readBackgroundTestRunRecord(pmRoot,runId);if(!loaded)throw new PmCliError(`Background test run ${runId} not found`,EXIT_CODE.NOT_FOUND);const refreshed=await refreshRunIfStale(pmRoot,loaded);if(!BACKGROUND_RUN_TERMINAL_STATUSES.has(refreshed.status))throw new PmCliError(`Background test run ${runId} is not terminal and cannot be resumed.`,EXIT_CODE.CONFLICT);const started=await startBackgroundTestRun({pmRoot:refreshed.pm_root,globalPmRoot:refreshed.global_pm_root,kind:refreshed.kind,commandArgs:refreshed.command_args,requestedBy,targetId:refreshed.target_id,statusFilter:refreshed.status_filter,resumedFrom:refreshed.id,resumedBy:requestedBy,attempt:refreshed.attempt+1});if(!started.started)return started.run;const spawned=await spawnBackgroundTestRunWorker({pmRoot,runId:started.run.id,noExtensions}),prior={...refreshed,resumed_by:spawned.id};return await writeBackgroundRunRecord(pmRoot,prior),spawned}async function readBackgroundTestRunLogs(pmRoot,runId,stream,tail){const loaded=await readBackgroundTestRunRecord(pmRoot,runId);if(!loaded)throw new PmCliError(`Background test run ${runId} not found`,EXIT_CODE.NOT_FOUND);const resolvedTail=typeof tail=="number"&&Number.isFinite(tail)&&tail>=0?Math.floor(tail):DEFAULT_BACKGROUND_RUN_LOG_TAIL_LINES,stdoutRaw=stream==="stdout"||stream==="both"?await readFileIfExists(loaded.stdout_path)??"":"",stderrRaw=stream==="stderr"||stream==="both"?await readFileIfExists(loaded.stderr_path)??"":"";return{run:loaded,stream,tail:resolvedTail,stdout:stream==="stdout"||stream==="both"?tailLines(stdoutRaw,resolvedTail):[],stderr:stream==="stderr"||stream==="both"?tailLines(stderrRaw,resolvedTail):[]}}const _testOnly={buildResourceSnapshot,evaluateWorkerResult,isPidRunning,parseLinuxCpuStat,parseLinuxRssStatus,parseProgressLine,readLinuxCpuSeconds,readLinuxRssBytes,refreshRunIfStale,splitLines,tailLines};export{_testOnly,buildBackgroundTestRunFingerprint,getBackgroundTestRunStatus,listBackgroundTestRuns,readBackgroundTestRunLogs,readBackgroundTestRunRecord,resumeBackgroundTestRun,runBackgroundTestRunWorker,spawnBackgroundTestRunWorker,startBackgroundTestRun,stopBackgroundTestRun};
5
5
  //# sourceMappingURL=background-runs.js.map