@unbrained/pm-cli 2026.10.21 → 2026.10.23

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 (186) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +134 -77
  3. package/dist/cli/error-guidance.d.ts +12 -0
  4. package/dist/cli/error-guidance.js +2 -2
  5. package/dist/cli/register-setup.js +1 -1
  6. package/dist/cli-bundle/bundle-manifest.json +1 -1
  7. package/dist/cli-bundle/chunks/{chunk-DIR3YEFD.js → chunk-2LTGJ5DL.js} +2 -2
  8. package/dist/cli-bundle/chunks/{chunk-EMGMLKRV.js → chunk-2UX2TAN2.js} +15 -15
  9. package/dist/cli-bundle/chunks/{chunk-2B5HAZFK.js → chunk-3S5FLCG7.js} +2 -2
  10. package/dist/cli-bundle/chunks/chunk-5DKCD4KV.js +126 -0
  11. package/dist/cli-bundle/chunks/{chunk-V3XONSVC.js → chunk-5V4HU6GK.js} +48 -48
  12. package/dist/cli-bundle/chunks/{chunk-QPV6UD55.js → chunk-AAX7CNL7.js} +2 -2
  13. package/dist/cli-bundle/chunks/{chunk-TMXWWOPJ.js → chunk-AXGFNNI3.js} +2 -2
  14. package/dist/cli-bundle/chunks/chunk-F76ZUP73.js +113 -0
  15. package/dist/cli-bundle/chunks/chunk-HDKY2YX3.js +3 -0
  16. package/dist/cli-bundle/chunks/{chunk-DR6DUBTU.js → chunk-KY34HTT2.js} +29 -29
  17. package/dist/cli-bundle/chunks/chunk-MMVX5L32.js +20 -0
  18. package/dist/cli-bundle/chunks/{chunk-C6SAXKBO.js → chunk-MTRYEVZR.js} +2 -2
  19. package/dist/cli-bundle/chunks/chunk-QSY55FTA.js +2 -0
  20. package/dist/cli-bundle/chunks/{chunk-GWIGZDRS.js → chunk-R7KWBFM2.js} +2 -2
  21. package/dist/cli-bundle/chunks/{chunk-5PZ7JNMI.js → chunk-REXCO5AG.js} +2 -2
  22. package/dist/cli-bundle/chunks/chunk-ZDVTXLA6.js +9 -0
  23. package/dist/cli-bundle/chunks/{chunk-DJQVNDXO.js → chunk-ZEI3DC5E.js} +6 -6
  24. package/dist/cli-bundle/chunks/{chunk-MOC5BJHW.js → chunk-ZMJF5HQW.js} +2 -2
  25. package/dist/cli-bundle/chunks/chunk-ZNDYAZZ6.js +6 -0
  26. package/dist/cli-bundle/chunks/{indexed-receipt-blobs-65XXSPPR.js → indexed-receipt-blobs-XANVELIV.js} +2 -2
  27. package/dist/cli-bundle/chunks/{mutation-admission-FNWOVJLN.js → mutation-admission-P6LOBNLO.js} +2 -2
  28. package/dist/cli-bundle/chunks/{register-list-query-6PT5Y2EZ.js → register-list-query-JOB65KDN.js} +2 -2
  29. package/dist/cli-bundle/chunks/{register-mutation-TAIQV46L.js → register-mutation-QMNIN3RJ.js} +2 -2
  30. package/dist/cli-bundle/chunks/{register-operations-ONIRO22G.js → register-operations-Z4VET3I7.js} +2 -2
  31. package/dist/cli-bundle/chunks/register-setup-GNKWL3VL.js +2 -0
  32. package/dist/cli-bundle/chunks/{settlement-hook-UVFYSBMU.js → settlement-hook-YUVCO65H.js} +2 -2
  33. package/dist/cli-bundle/chunks/{stage-FCPVFO3B.js → stage-FW5OXCCR.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/{chunk-VD64TPXI.js → chunk-4MNUQCGR.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/chunk-6GTZ24YV.js +3 -0
  36. package/dist/cli-bundle/focused-chunks/{chunk-XE7P7N5X.js → chunk-BM652VCB.js} +6 -6
  37. package/dist/cli-bundle/focused-chunks/{chunk-3LWH2RJC.js → chunk-BUZ2Z4P3.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/chunk-CGL36F6I.js +2 -0
  39. package/dist/cli-bundle/focused-chunks/{chunk-KVYUQS6Y.js → chunk-DWQMYLFM.js} +2 -2
  40. package/dist/cli-bundle/focused-chunks/{chunk-4HJVAUFX.js → chunk-EDXTOAXP.js} +2 -2
  41. package/dist/cli-bundle/focused-chunks/chunk-FO4U3FIP.js +91 -0
  42. package/dist/cli-bundle/focused-chunks/chunk-GXKP56W7.js +2 -0
  43. package/dist/cli-bundle/focused-chunks/chunk-I2USTQNQ.js +2 -0
  44. package/dist/cli-bundle/focused-chunks/{chunk-44353U27.js → chunk-JDN34LEZ.js} +2 -2
  45. package/dist/cli-bundle/focused-chunks/{chunk-CUWNNU4N.js → chunk-KI5YFKNN.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/{chunk-7UD7XTOE.js → chunk-LEHGCPZ6.js} +11 -11
  47. package/dist/cli-bundle/focused-chunks/{chunk-HNCMYF2W.js → chunk-MLET6I3I.js} +2 -2
  48. package/dist/cli-bundle/focused-chunks/{chunk-PDOWLRHC.js → chunk-NSMZY6IK.js} +2 -2
  49. package/dist/cli-bundle/focused-chunks/chunk-OMXMYTEX.js +26 -0
  50. package/dist/cli-bundle/focused-chunks/{chunk-JI3RXXRN.js → chunk-P7DPS5M4.js} +2 -2
  51. package/dist/cli-bundle/focused-chunks/chunk-R536272H.js +9 -0
  52. package/dist/cli-bundle/focused-chunks/{chunk-5IMM7GOF.js → chunk-UNTCCJPL.js} +3 -3
  53. package/dist/cli-bundle/focused-chunks/{chunk-32ZKLRWM.js → chunk-XIZYJDYW.js} +2 -2
  54. package/dist/cli-bundle/focused-chunks/chunk-Z5LDTMZ3.js +2 -0
  55. package/dist/cli-bundle/focused-chunks/chunk-ZHMF34DT.js +65 -0
  56. package/dist/cli-bundle/focused-chunks/{chunk-P5D7MHDS.js → chunk-ZR6ZKQUK.js} +15 -15
  57. package/dist/cli-bundle/focused-chunks/{indexed-receipt-blobs-CRP6HAZY.js → indexed-receipt-blobs-FVOA3XMI.js} +2 -2
  58. package/dist/cli-bundle/focused-chunks/{mutation-admission-KM57KDDF.js → mutation-admission-HTFAIHJL.js} +2 -2
  59. package/dist/cli-bundle/focused-chunks/{settlement-hook-MNCHFCAX.js → settlement-hook-2VXEB6PP.js} +2 -2
  60. package/dist/cli-bundle/focused-chunks/{stage-UJYGWNZ7.js → stage-X3BUGEJT.js} +2 -2
  61. package/dist/cli-bundle/main.js +21 -21
  62. package/dist/cli-bundle/sdk-authoring.js +1 -1
  63. package/dist/cli-bundle/sdk-contracts.js +5 -2
  64. package/dist/cli-bundle/sdk-core.js +33 -33
  65. package/dist/cli-bundle/sdk-governance.js +1 -1
  66. package/dist/cli-bundle/sdk-graph.js +1 -1
  67. package/dist/cli-bundle/sdk-merge.js +58 -58
  68. package/dist/cli-bundle/sdk-query.js +1 -1
  69. package/dist/cli-bundle/sdk-runtime.js +1 -1
  70. package/dist/cli-bundle/sdk-testing.js +1 -1
  71. package/dist/cli-bundle/sdk.js +12 -9
  72. package/dist/core/config/nested-settings.js +1 -1
  73. package/dist/core/extensions/loader.js +1 -1
  74. package/dist/core/extensions/version-diagnostics.d.ts +2 -0
  75. package/dist/core/extensions/version-diagnostics.js +2 -0
  76. package/dist/core/lock/lock.d.ts +40 -6
  77. package/dist/core/lock/lock.js +3 -3
  78. package/dist/core/shared/errors.d.ts +28 -0
  79. package/dist/core/shared/errors.js +1 -1
  80. package/dist/core/store/item-store.js +1 -1
  81. package/dist/mcp/http-server.js +2 -2
  82. package/dist/mcp/server.d.ts +2 -2
  83. package/dist/mcp/server.js +2 -2
  84. package/dist/sdk/agent/command-recovery.d.ts +2 -0
  85. package/dist/sdk/agent/command-recovery.js +1 -1
  86. package/dist/sdk/cli-contracts/agent-output-contracts.js +1 -1
  87. package/dist/sdk/cli-contracts/tool-option-contracts.d.ts +6 -0
  88. package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -1
  89. package/dist/sdk/cli-contracts/tool-schema.js +1 -1
  90. package/dist/sdk/context-intent-contracts.d.ts +13 -0
  91. package/dist/sdk/context-intent-contracts.js +1 -1
  92. package/dist/sdk/contracts.d.ts +2 -1
  93. package/dist/sdk/contracts.js +1 -1
  94. package/dist/sdk/core.d.ts +2 -2
  95. package/dist/sdk/core.js +1 -1
  96. package/dist/sdk/define.d.ts +15 -16
  97. package/dist/sdk/define.js +1 -1
  98. package/dist/sdk/dependencies.js +1 -1
  99. package/dist/sdk/extension/doctor.js +1 -1
  100. package/dist/sdk/extension/install-receipts.js +1 -1
  101. package/dist/sdk/extension/install-snapshot.d.ts +11 -0
  102. package/dist/sdk/extension/install-snapshot.js +1 -1
  103. package/dist/sdk/extension.d.ts +12 -0
  104. package/dist/sdk/extension.js +1 -1
  105. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
  106. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
  107. package/dist/sdk/governance/health.d.ts +1 -0
  108. package/dist/sdk/governance/health.js +2 -2
  109. package/dist/sdk/index.d.ts +3 -2
  110. package/dist/sdk/index.js +1 -1
  111. package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -1
  112. package/dist/sdk/lifecycle/restore.js +1 -1
  113. package/dist/sdk/mcp/executable.d.ts +13 -0
  114. package/dist/sdk/mcp/executable.js +5 -0
  115. package/dist/sdk/merge/install.js +2 -2
  116. package/dist/sdk/public-surface.json +1 -1
  117. package/dist/sdk/query/context.d.ts +5 -0
  118. package/dist/sdk/query/context.js +2 -2
  119. package/dist/sdk/read-output/session-result.d.ts +39 -0
  120. package/dist/sdk/read-output/session-result.js +2 -0
  121. package/dist/sdk/read-output-contracts.d.ts +18 -5
  122. package/dist/sdk/read-output-contracts.js +1 -1
  123. package/dist/sdk/read-output-session.d.ts +2 -0
  124. package/dist/sdk/read-output-session.js +1 -1
  125. package/dist/sdk/relationship-context.js +1 -1
  126. package/dist/sdk/runtime-input.js +1 -1
  127. package/dist/sdk/runtime-primitives.d.ts +7 -1
  128. package/dist/sdk/runtime-primitives.js +1 -1
  129. package/dist/sdk/runtime.d.ts +11 -9
  130. package/dist/sdk/runtime.js +1 -1
  131. package/dist/sdk/workspace-snapshot.d.ts +5 -1
  132. package/dist/sdk/workspace-snapshot.js +3 -3
  133. package/dist/sdk/workspace.d.ts +3 -1
  134. package/dist/sdk/workspace.js +8 -5
  135. package/docs/CONFIGURATION.md +28 -3
  136. package/docs/DEVELOPMENT_DEPENDENCY_SECURITY.md +30 -0
  137. package/docs/EXTENSION_AUTHOR_CONTRACTS.md +2 -1
  138. package/docs/EXTENSION_LIFECYCLE.md +47 -0
  139. package/docs/MCP_OPTION_CONFORMANCE.md +27 -1
  140. package/docs/MCP_REMOTE_TRANSPORT_SECURITY.md +16 -1
  141. package/docs/MERGE_SAFETY.md +8 -0
  142. package/docs/READ_OUTPUT_CONTRACTS.md +79 -0
  143. package/docs/RELATIONSHIP_GRAPH.md +15 -0
  144. package/docs/RELEASING.md +17 -0
  145. package/docs/SDK.md +76 -12
  146. package/docs/SDK_STORAGE_LIFECYCLE.md +2 -1
  147. package/docs/TESTING.md +16 -7
  148. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +6 -3
  149. package/marketplace.json +1 -1
  150. package/package.json +1 -1
  151. package/packages/pm-beads/package.json +1 -1
  152. package/packages/pm-calendar/package.json +1 -1
  153. package/packages/pm-command-kit/package.json +1 -1
  154. package/packages/pm-digital-twin/package.json +1 -1
  155. package/packages/pm-governance-audit/package.json +1 -1
  156. package/packages/pm-guide-shell/package.json +1 -1
  157. package/packages/pm-kanban/package.json +1 -1
  158. package/packages/pm-lifecycle-hooks/package.json +1 -1
  159. package/packages/pm-linked-test-adapters/package.json +1 -1
  160. package/packages/pm-search-advanced/package.json +1 -1
  161. package/packages/pm-templates/package.json +1 -1
  162. package/packages/pm-todos/package.json +1 -1
  163. package/packages/pm-vcs/package.json +1 -1
  164. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  165. package/plugins/pm-claude/package.json +1 -1
  166. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  167. package/plugins/pm-codex/package.json +1 -1
  168. package/plugins/pm-codex/plugin.json +1 -1
  169. package/runtime-dependencies.json +1 -1
  170. package/dist/cli-bundle/chunks/chunk-4OYU5OXQ.js +0 -6
  171. package/dist/cli-bundle/chunks/chunk-DIKQ2AL5.js +0 -2
  172. package/dist/cli-bundle/chunks/chunk-KBSVPUFD.js +0 -113
  173. package/dist/cli-bundle/chunks/chunk-MZZIAC6S.js +0 -20
  174. package/dist/cli-bundle/chunks/chunk-NNB65OOO.js +0 -3
  175. package/dist/cli-bundle/chunks/chunk-V5GJTXYW.js +0 -126
  176. package/dist/cli-bundle/chunks/chunk-ZNKFMIVA.js +0 -6
  177. package/dist/cli-bundle/chunks/register-setup-OQMUZBJV.js +0 -2
  178. package/dist/cli-bundle/focused-chunks/chunk-6QSZHRM7.js +0 -6
  179. package/dist/cli-bundle/focused-chunks/chunk-E2S42XCT.js +0 -2
  180. package/dist/cli-bundle/focused-chunks/chunk-GRSQGMRR.js +0 -2
  181. package/dist/cli-bundle/focused-chunks/chunk-IAGFXKMZ.js +0 -3
  182. package/dist/cli-bundle/focused-chunks/chunk-JMZPZQHR.js +0 -26
  183. package/dist/cli-bundle/focused-chunks/chunk-O3M6YWVL.js +0 -2
  184. package/dist/cli-bundle/focused-chunks/chunk-T27TLSEU.js +0 -65
  185. package/dist/cli-bundle/focused-chunks/chunk-VE6MTRH5.js +0 -2
  186. package/dist/cli-bundle/focused-chunks/chunk-YIWDX6KO.js +0 -91
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="2ae4f6da-17c5-5024-89a2-bb0a4be9a683")}catch{}})();const NESTED_SETTING_DESCRIPTORS=[{key:"search_provider",path:"search.provider",kind:"string",summary:"Search embedding provider name (e.g. openai, ollama, or an extension provider)."},{key:"search_default_mode",path:"search.default_mode",kind:"string",choices:["auto","keyword","semantic","hybrid"],summary:"Mode a bare pm search runs in: auto (hybrid when semantic search is explicitly configured and runnable, else keyword), or a pinned keyword, semantic, or hybrid."},{key:"search_mutation_refresh_policy",path:"search.mutation_refresh_policy",kind:"string",choices:["cache_only","semantic_configured","semantic_auto"],summary:"Mutation-time search refresh policy: cache_only, semantic_configured, or semantic_auto."},{key:"search_query_expansion_enabled",path:"search.query_expansion.enabled",kind:"boolean",summary:"Enable or disable query expansion for semantic/hybrid search."},{key:"search_query_expansion_provider",path:"search.query_expansion.provider",kind:"string",summary:"Query expansion provider name (built-in openai/ollama or extension provider)."},{key:"search_rerank_enabled",path:"search.rerank.enabled",kind:"boolean",summary:"Enable or disable post-retrieval reranking for hybrid search."},{key:"search_rerank_model",path:"search.rerank.model",kind:"string",summary:"Rerank model name override used by built-in providers."},{key:"search_rerank_top_k",path:"search.rerank.top_k",kind:"integer",min:1,summary:"Number of top hybrid candidates to rerank when rerank is enabled."},{key:"search_embedding_model",path:"search.embedding_model",kind:"string",summary:"Default embedding model name (overrides provider-specific model when set)."},{key:"search_embedding_corpus_max_characters",path:"search.embedding_corpus_max_characters",kind:"integer",min:1,summary:"Maximum semantic corpus characters per item before truncation."},{key:"search_embedding_batch_size",path:"search.embedding_batch_size",kind:"integer",min:1,summary:"Number of items embedded per request batch."},{key:"search_embedding_timeout_ms",path:"search.embedding_timeout_ms",kind:"integer",min:1,summary:"Per-request embedding timeout in milliseconds."},{key:"search_score_threshold",path:"search.score_threshold",kind:"number",summary:"Minimum score for a hit to be returned (0 keeps all matches)."},{key:"search_hybrid_semantic_weight",path:"search.hybrid_semantic_weight",kind:"ratio",summary:"Hybrid mode semantic weight in [0, 1] (1-weight goes to keyword)."},{key:"search_max_results",path:"search.max_results",kind:"integer",min:1,summary:"Default upper bound on search hits when --limit is not supplied."},{key:"search_bm25_k1",path:"search.bm25.k1",kind:"number",min:0,summary:"Offline BM25 term-frequency saturation (k1); higher saturates repeated terms slower (default 1.2)."},{key:"search_bm25_b",path:"search.bm25.b",kind:"ratio",summary:"Offline BM25 document-length normalization (b) in [0, 1]; 0 disables, 1 fully normalizes (default 0.75)."},{key:"openai_base_url",path:"providers.openai.base_url",kind:"string",summary:"OpenAI-compatible API base URL (LM Studio/vLLM also use this)."},{key:"openai_api_key",path:"providers.openai.api_key",kind:"string",summary:"OpenAI-compatible API key."},{key:"openai_model",path:"providers.openai.model",kind:"string",summary:"OpenAI-compatible embedding model name."},{key:"ollama_base_url",path:"providers.ollama.base_url",kind:"string",summary:"Ollama API base URL (typically http://localhost:11434)."},{key:"ollama_model",path:"providers.ollama.model",kind:"string",summary:"Ollama embedding model name (e.g. nomic-embed-text)."},{key:"vector_store_adapter",path:"vector_store.adapter",kind:"string",summary:"Vector store adapter name (lancedb, qdrant, or an extension adapter)."},{key:"vector_store_collection_name",path:"vector_store.collection_name",kind:"string",non_empty:!0,summary:"Vector collection/table name shared by Qdrant and LanceDB adapters."},{key:"qdrant_url",path:"vector_store.qdrant.url",kind:"string",summary:"Qdrant HTTP API URL."},{key:"qdrant_api_key",path:"vector_store.qdrant.api_key",kind:"string",summary:"Qdrant API key (empty if running unauthenticated)."},{key:"lancedb_path",path:"vector_store.lancedb.path",kind:"string",summary:"LanceDB storage path (relative to pm root or absolute)."},{key:"id_prefix",path:"id_prefix",kind:"string",non_empty:!0,summary:'Prefix for generated item IDs (e.g. "pm" produces pm-xxxx).'},{key:"author_default",path:"author_default",kind:"string",non_empty:!0,summary:"Default author recorded on mutations when --author is not supplied."},{key:"agent_identity_probes_enabled",path:"agent_identity.probes_enabled",kind:"boolean",summary:"Allow privacy-bounded local harness provenance probes; no network or subprocess access is permitted."},{key:"mutation_guard_require_attributed_author",path:"mutation_guard.require_attributed_author",kind:"boolean",summary:"Reject mutations whose effective author resolves to unknown."},{key:"mutation_guard_secret_guard",path:"mutation_guard.secret_guard",kind:"string",choices:["off","advise","block"],summary:"Detect credential-shaped mutation content: off, advise, or block."},{key:"mutation_guard_stale_in_progress_hours",path:"mutation_guard.stale_in_progress_hours",kind:"integer",min:1,summary:"Age threshold for unclaimed in-progress work surfaced by health."},{key:"governance_duplicate_detection_mode",path:"governance.duplicate_detection_mode",kind:"string",choices:["off","advisory","strict"],summary:"Create/copy duplicate governance: off, advisory, or strict explicit-bypass enforcement."},{key:"governance_duplicate_detection_threshold",path:"governance.duplicate_detection_threshold",kind:"ratio",summary:"Minimum shared similarity score in [0, 1] for create/copy duplicate governance."},{key:"governance_duplicate_detection_limit",path:"governance.duplicate_detection_limit",kind:"integer",min:0,max:20,summary:"Maximum likely duplicates returned by create/copy governance (0-20)."},{key:"output_default_format",path:"output.default_format",kind:"string",choices:["toon","json"],summary:"Default output format for commands that support it: toon or json."},{key:"ux_deprecation_hints",path:"ux.deprecation_hints",kind:"boolean",summary:"Emit one stderr migration hint for deprecated command aliases."},{key:"locks_ttl_seconds",path:"locks.ttl_seconds",kind:"integer",min:1,summary:"Claim/lock time-to-live in seconds before a stale lock can be reclaimed."},{key:"locks_wait_ms",path:"locks.wait_ms",kind:"integer",min:0,summary:"Bounded jittered wait in milliseconds before a contended item mutation fails with lock_conflict; 0 fails fast. PM_LOCK_WAIT_MS overrides per invocation."},{key:"ids_token_length",path:"ids.token_length",kind:"integer",min:4,max:12,summary:"Random base36 token length for newly minted item ids (4-12, default 4). Raise it to shrink cross-branch id collision odds in concurrent multi-agent workflows (pm-pibw)."},{key:"checkpoints_retention_days",path:"checkpoints.retention_days",kind:"integer",min:1,summary:"Age in days above which pm gc --scope checkpoints prunes bulk-mutation rollback checkpoints."},{key:"schema_unknown_field_policy",path:"schema.unknown_field_policy",kind:"string",choices:["allow","warn","reject"],summary:"How item I/O handles metadata keys not in the field registry: allow, warn, or reject."},{key:"history_compact_policy_enabled",path:"history.compact_policy.enabled",kind:"boolean",summary:"Enable the history-compaction advisory: pm health warns on over-threshold streams."},{key:"history_compact_policy_max_entries",path:"history.compact_policy.max_entries",kind:"integer",min:1,summary:"Entry count above which a history stream is flagged (and the default pm history-compact --all-over threshold)."},{key:"history_compact_policy_trigger",path:"history.compact_policy.trigger",kind:"string",choices:["health_warn","auto"],summary:"History-compaction policy intent: health_warn (advisory only) or auto (scheduled sweeps expected)."}],DESCRIPTOR_BY_KEY=new Map(NESTED_SETTING_DESCRIPTORS.flatMap(descriptor=>[[descriptor.key,descriptor],[descriptor.path.toLowerCase().replaceAll("-","_"),descriptor]]));function resolveNestedSettingDescriptor(raw){if(typeof raw!="string")return;const normalized=raw.trim().toLowerCase().replaceAll("-","_");if(normalized.length!==0)return DESCRIPTOR_BY_KEY.get(normalized)}function parseNestedBooleanValue(descriptor,rawValue){const normalized=rawValue.trim().toLowerCase();return normalized==="true"||normalized==="1"||normalized==="yes"||normalized==="on"?{ok:!0,parsed:{descriptor,value:!0}}:normalized==="false"||normalized==="0"||normalized==="no"||normalized==="off"?{ok:!0,parsed:{descriptor,value:!1}}:{ok:!1,error:{message:`Config set ${descriptor.key} requires a boolean value (true|false), got "${rawValue}"`}}}function parseNestedStringValue(descriptor,rawValue,trimmed){return descriptor.non_empty===!0&&trimmed.length===0?{ok:!1,error:{message:`Config set ${descriptor.key} requires a non-empty value`}}:descriptor.choices&&!descriptor.choices.includes(trimmed)?{ok:!1,error:{message:`Config set ${descriptor.key} must be one of ${descriptor.choices.join("|")}, got "${rawValue}"`}}:{ok:!0,parsed:{descriptor,value:trimmed}}}function parseFiniteNestedNumber(descriptor,rawValue,trimmed){if(trimmed.length===0)return{ok:!1,error:{message:`Config set ${descriptor.key} requires a non-empty value`}};const parsed=Number(trimmed);return Number.isFinite(parsed)?{ok:!0,value:parsed}:{ok:!1,error:{message:`Config set ${descriptor.key} requires a finite number, got "${rawValue}"`}}}function parseNestedIntegerValue(descriptor,rawValue,value){return!Number.isInteger(value)||value<0?{ok:!1,error:{message:`Config set ${descriptor.key} requires a non-negative integer, got "${rawValue}"`}}:descriptor.min!==void 0&&value<descriptor.min?{ok:!1,error:{message:`Config set ${descriptor.key} requires an integer >= ${descriptor.min}, got "${rawValue}" (the runtime silently ignores 0 here and falls back to the default)`}}:descriptor.max!==void 0&&value>descriptor.max?{ok:!1,error:{message:`Config set ${descriptor.key} requires an integer <= ${descriptor.max}, got "${rawValue}"`}}:{ok:!0,parsed:{descriptor,value}}}function parseNestedRatioValue(descriptor,rawValue,value){return value<0||value>1?{ok:!1,error:{message:`Config set ${descriptor.key} requires a number in [0, 1], got "${rawValue}"`}}:{ok:!0,parsed:{descriptor,value}}}function parseNestedNumberValue(descriptor,rawValue,value){return descriptor.min!==void 0&&value<descriptor.min?{ok:!1,error:{message:`Config set ${descriptor.key} requires a number >= ${descriptor.min}, got "${rawValue}"`}}:{ok:!0,parsed:{descriptor,value}}}function parseNestedSettingValue(descriptor,rawValue){if(typeof rawValue!="string")return{ok:!1,error:{message:`Config set ${descriptor.key} requires a string value`}};const trimmed=rawValue.trim();if(descriptor.kind==="boolean")return parseNestedBooleanValue(descriptor,rawValue);if(descriptor.kind==="string")return parseNestedStringValue(descriptor,rawValue,trimmed);const parsed=parseFiniteNestedNumber(descriptor,rawValue,trimmed);return parsed.ok?descriptor.kind==="integer"?parseNestedIntegerValue(descriptor,rawValue,parsed.value):descriptor.kind==="ratio"?parseNestedRatioValue(descriptor,rawValue,parsed.value):parseNestedNumberValue(descriptor,rawValue,parsed.value):{ok:!1,error:parsed.error}}function readNestedSettingValue(settings,descriptor){const segments=descriptor.path.split(".");let cursor=settings;for(const segment of segments){if(typeof cursor!="object"||cursor===null)return null;const property=Object.getOwnPropertyDescriptor(cursor,segment);if(!property||!Object.hasOwn(property,"value"))return null;cursor=property.value}return typeof cursor=="string"||typeof cursor=="number"||typeof cursor=="boolean"?cursor:null}function writeNestedSettingValue(settings,descriptor,value){const segments=descriptor.path.split(".");if(segments.some(segment=>segment.length===0||["__proto__","constructor","prototype"].includes(segment)))throw new Error("Unsafe settings path");let cursor=settings;for(let index=0;index<segments.length-1;index+=1){const segment=segments[index],existing=Object.getOwnPropertyDescriptor(cursor,segment)?.value;if(typeof existing!="object"||existing===null||Array.isArray(existing)){const next={};Object.defineProperty(cursor,segment,{value:next,writable:!0,enumerable:!0,configurable:!0}),cursor=next}else cursor=existing}const leafKey=segments[segments.length-1];return Object.getOwnPropertyDescriptor(cursor,leafKey)?.value===value?!1:(Object.defineProperty(cursor,leafKey,{value,writable:!0,enumerable:!0,configurable:!0}),!0)}export{NESTED_SETTING_DESCRIPTORS,parseNestedSettingValue,readNestedSettingValue,resolveNestedSettingDescriptor,writeNestedSettingValue};
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]="d681ddfe-ad15-527b-90de-bfbe341c6a86")}catch{}})();const NESTED_SETTING_DESCRIPTORS=[{key:"search_provider",path:"search.provider",kind:"string",summary:"Search embedding provider name (e.g. openai, ollama, or an extension provider)."},{key:"search_default_mode",path:"search.default_mode",kind:"string",choices:["auto","keyword","semantic","hybrid"],summary:"Mode a bare pm search runs in: auto (hybrid when semantic search is explicitly configured and runnable, else keyword), or a pinned keyword, semantic, or hybrid."},{key:"search_mutation_refresh_policy",path:"search.mutation_refresh_policy",kind:"string",choices:["cache_only","semantic_configured","semantic_auto"],summary:"Mutation-time search refresh policy: cache_only, semantic_configured, or semantic_auto."},{key:"search_query_expansion_enabled",path:"search.query_expansion.enabled",kind:"boolean",summary:"Enable or disable query expansion for semantic/hybrid search."},{key:"search_query_expansion_provider",path:"search.query_expansion.provider",kind:"string",summary:"Query expansion provider name (built-in openai/ollama or extension provider)."},{key:"search_rerank_enabled",path:"search.rerank.enabled",kind:"boolean",summary:"Enable or disable post-retrieval reranking for hybrid search."},{key:"search_rerank_model",path:"search.rerank.model",kind:"string",summary:"Rerank model name override used by built-in providers."},{key:"search_rerank_top_k",path:"search.rerank.top_k",kind:"integer",min:1,summary:"Number of top hybrid candidates to rerank when rerank is enabled."},{key:"search_embedding_model",path:"search.embedding_model",kind:"string",summary:"Default embedding model name (overrides provider-specific model when set)."},{key:"search_embedding_corpus_max_characters",path:"search.embedding_corpus_max_characters",kind:"integer",min:1,summary:"Maximum semantic corpus characters per item before truncation."},{key:"search_embedding_batch_size",path:"search.embedding_batch_size",kind:"integer",min:1,summary:"Number of items embedded per request batch."},{key:"search_embedding_timeout_ms",path:"search.embedding_timeout_ms",kind:"integer",min:1,summary:"Per-request embedding timeout in milliseconds."},{key:"search_score_threshold",path:"search.score_threshold",kind:"number",summary:"Minimum score for a hit to be returned (0 keeps all matches)."},{key:"search_hybrid_semantic_weight",path:"search.hybrid_semantic_weight",kind:"ratio",summary:"Hybrid mode semantic weight in [0, 1] (1-weight goes to keyword)."},{key:"search_max_results",path:"search.max_results",kind:"integer",min:1,summary:"Default upper bound on search hits when --limit is not supplied."},{key:"search_bm25_k1",path:"search.bm25.k1",kind:"number",min:0,summary:"Offline BM25 term-frequency saturation (k1); higher saturates repeated terms slower (default 1.2)."},{key:"search_bm25_b",path:"search.bm25.b",kind:"ratio",summary:"Offline BM25 document-length normalization (b) in [0, 1]; 0 disables, 1 fully normalizes (default 0.75)."},{key:"openai_base_url",path:"providers.openai.base_url",kind:"string",summary:"OpenAI-compatible API base URL (LM Studio/vLLM also use this)."},{key:"openai_api_key",path:"providers.openai.api_key",kind:"string",summary:"OpenAI-compatible API key."},{key:"openai_model",path:"providers.openai.model",kind:"string",summary:"OpenAI-compatible embedding model name."},{key:"ollama_base_url",path:"providers.ollama.base_url",kind:"string",summary:"Ollama API base URL (typically http://localhost:11434)."},{key:"ollama_model",path:"providers.ollama.model",kind:"string",summary:"Ollama embedding model name (e.g. nomic-embed-text)."},{key:"vector_store_adapter",path:"vector_store.adapter",kind:"string",summary:"Vector store adapter name (lancedb, qdrant, or an extension adapter)."},{key:"vector_store_collection_name",path:"vector_store.collection_name",kind:"string",non_empty:!0,summary:"Vector collection/table name shared by Qdrant and LanceDB adapters."},{key:"qdrant_url",path:"vector_store.qdrant.url",kind:"string",summary:"Qdrant HTTP API URL."},{key:"qdrant_api_key",path:"vector_store.qdrant.api_key",kind:"string",summary:"Qdrant API key (empty if running unauthenticated)."},{key:"lancedb_path",path:"vector_store.lancedb.path",kind:"string",summary:"LanceDB storage path (relative to pm root or absolute)."},{key:"id_prefix",path:"id_prefix",kind:"string",non_empty:!0,summary:'Prefix for generated item IDs (e.g. "pm" produces pm-xxxx).'},{key:"author_default",path:"author_default",kind:"string",non_empty:!0,summary:"Default author recorded on mutations when --author is not supplied."},{key:"agent_identity_probes_enabled",path:"agent_identity.probes_enabled",kind:"boolean",summary:"Allow privacy-bounded local harness provenance probes; no network or subprocess access is permitted."},{key:"mutation_guard_require_attributed_author",path:"mutation_guard.require_attributed_author",kind:"boolean",summary:"Reject mutations whose effective author resolves to unknown."},{key:"mutation_guard_secret_guard",path:"mutation_guard.secret_guard",kind:"string",choices:["off","advise","block"],summary:"Detect credential-shaped mutation content: off, advise, or block."},{key:"mutation_guard_stale_in_progress_hours",path:"mutation_guard.stale_in_progress_hours",kind:"integer",min:1,summary:"Age threshold for unclaimed in-progress work surfaced by health."},{key:"governance_duplicate_detection_mode",path:"governance.duplicate_detection_mode",kind:"string",choices:["off","advisory","strict"],summary:"Create/copy duplicate governance: off, advisory, or strict explicit-bypass enforcement."},{key:"governance_duplicate_detection_threshold",path:"governance.duplicate_detection_threshold",kind:"ratio",summary:"Minimum shared similarity score in [0, 1] for create/copy duplicate governance."},{key:"governance_duplicate_detection_limit",path:"governance.duplicate_detection_limit",kind:"integer",min:0,max:20,summary:"Maximum likely duplicates returned by create/copy governance (0-20)."},{key:"output_default_format",path:"output.default_format",kind:"string",choices:["toon","json"],summary:"Default output format for commands that support it: toon or json."},{key:"ux_deprecation_hints",path:"ux.deprecation_hints",kind:"boolean",summary:"Emit one stderr migration hint for deprecated command aliases."},{key:"locks_ttl_seconds",path:"locks.ttl_seconds",kind:"integer",min:1,summary:"Claim/lock time-to-live in seconds before a stale lock can be reclaimed."},{key:"locks_wait_ms",path:"locks.wait_ms",kind:"integer",min:0,summary:"Wait budget in milliseconds before a contended lock fails with lock_conflict; item-store mutations, restore and the hierarchy lock treat it as a no-progress window that each observed owner handoff restarts (120 s total cap), other locks as a fixed total; 0 fails fast. PM_LOCK_WAIT_MS overrides per invocation."},{key:"ids_token_length",path:"ids.token_length",kind:"integer",min:4,max:12,summary:"Random base36 token length for newly minted item ids (4-12, default 4). Raise it to shrink cross-branch id collision odds in concurrent multi-agent workflows (pm-pibw)."},{key:"checkpoints_retention_days",path:"checkpoints.retention_days",kind:"integer",min:1,summary:"Age in days above which pm gc --scope checkpoints prunes bulk-mutation rollback checkpoints."},{key:"schema_unknown_field_policy",path:"schema.unknown_field_policy",kind:"string",choices:["allow","warn","reject"],summary:"How item I/O handles metadata keys not in the field registry: allow, warn, or reject."},{key:"history_compact_policy_enabled",path:"history.compact_policy.enabled",kind:"boolean",summary:"Enable the history-compaction advisory: pm health warns on over-threshold streams."},{key:"history_compact_policy_max_entries",path:"history.compact_policy.max_entries",kind:"integer",min:1,summary:"Entry count above which a history stream is flagged (and the default pm history-compact --all-over threshold)."},{key:"history_compact_policy_trigger",path:"history.compact_policy.trigger",kind:"string",choices:["health_warn","auto"],summary:"History-compaction policy intent: health_warn (advisory only) or auto (scheduled sweeps expected)."}],DESCRIPTOR_BY_KEY=new Map(NESTED_SETTING_DESCRIPTORS.flatMap(descriptor=>[[descriptor.key,descriptor],[descriptor.path.toLowerCase().replaceAll("-","_"),descriptor]]));function resolveNestedSettingDescriptor(raw){if(typeof raw!="string")return;const normalized=raw.trim().toLowerCase().replaceAll("-","_");if(normalized.length!==0)return DESCRIPTOR_BY_KEY.get(normalized)}function parseNestedBooleanValue(descriptor,rawValue){const normalized=rawValue.trim().toLowerCase();return normalized==="true"||normalized==="1"||normalized==="yes"||normalized==="on"?{ok:!0,parsed:{descriptor,value:!0}}:normalized==="false"||normalized==="0"||normalized==="no"||normalized==="off"?{ok:!0,parsed:{descriptor,value:!1}}:{ok:!1,error:{message:`Config set ${descriptor.key} requires a boolean value (true|false), got "${rawValue}"`}}}function parseNestedStringValue(descriptor,rawValue,trimmed){return descriptor.non_empty===!0&&trimmed.length===0?{ok:!1,error:{message:`Config set ${descriptor.key} requires a non-empty value`}}:descriptor.choices&&!descriptor.choices.includes(trimmed)?{ok:!1,error:{message:`Config set ${descriptor.key} must be one of ${descriptor.choices.join("|")}, got "${rawValue}"`}}:{ok:!0,parsed:{descriptor,value:trimmed}}}function parseFiniteNestedNumber(descriptor,rawValue,trimmed){if(trimmed.length===0)return{ok:!1,error:{message:`Config set ${descriptor.key} requires a non-empty value`}};const parsed=Number(trimmed);return Number.isFinite(parsed)?{ok:!0,value:parsed}:{ok:!1,error:{message:`Config set ${descriptor.key} requires a finite number, got "${rawValue}"`}}}function parseNestedIntegerValue(descriptor,rawValue,value){return!Number.isInteger(value)||value<0?{ok:!1,error:{message:`Config set ${descriptor.key} requires a non-negative integer, got "${rawValue}"`}}:descriptor.min!==void 0&&value<descriptor.min?{ok:!1,error:{message:`Config set ${descriptor.key} requires an integer >= ${descriptor.min}, got "${rawValue}" (the runtime silently ignores 0 here and falls back to the default)`}}:descriptor.max!==void 0&&value>descriptor.max?{ok:!1,error:{message:`Config set ${descriptor.key} requires an integer <= ${descriptor.max}, got "${rawValue}"`}}:{ok:!0,parsed:{descriptor,value}}}function parseNestedRatioValue(descriptor,rawValue,value){return value<0||value>1?{ok:!1,error:{message:`Config set ${descriptor.key} requires a number in [0, 1], got "${rawValue}"`}}:{ok:!0,parsed:{descriptor,value}}}function parseNestedNumberValue(descriptor,rawValue,value){return descriptor.min!==void 0&&value<descriptor.min?{ok:!1,error:{message:`Config set ${descriptor.key} requires a number >= ${descriptor.min}, got "${rawValue}"`}}:{ok:!0,parsed:{descriptor,value}}}function parseNestedSettingValue(descriptor,rawValue){if(typeof rawValue!="string")return{ok:!1,error:{message:`Config set ${descriptor.key} requires a string value`}};const trimmed=rawValue.trim();if(descriptor.kind==="boolean")return parseNestedBooleanValue(descriptor,rawValue);if(descriptor.kind==="string")return parseNestedStringValue(descriptor,rawValue,trimmed);const parsed=parseFiniteNestedNumber(descriptor,rawValue,trimmed);return parsed.ok?descriptor.kind==="integer"?parseNestedIntegerValue(descriptor,rawValue,parsed.value):descriptor.kind==="ratio"?parseNestedRatioValue(descriptor,rawValue,parsed.value):parseNestedNumberValue(descriptor,rawValue,parsed.value):{ok:!1,error:parsed.error}}function readNestedSettingValue(settings,descriptor){const segments=descriptor.path.split(".");let cursor=settings;for(const segment of segments){if(typeof cursor!="object"||cursor===null)return null;const property=Object.getOwnPropertyDescriptor(cursor,segment);if(!property||!Object.hasOwn(property,"value"))return null;cursor=property.value}return typeof cursor=="string"||typeof cursor=="number"||typeof cursor=="boolean"?cursor:null}function writeNestedSettingValue(settings,descriptor,value){const segments=descriptor.path.split(".");if(segments.some(segment=>segment.length===0||["__proto__","constructor","prototype"].includes(segment)))throw new Error("Unsafe settings path");let cursor=settings;for(let index=0;index<segments.length-1;index+=1){const segment=segments[index],existing=Object.getOwnPropertyDescriptor(cursor,segment)?.value;if(typeof existing!="object"||existing===null||Array.isArray(existing)){const next={};Object.defineProperty(cursor,segment,{value:next,writable:!0,enumerable:!0,configurable:!0}),cursor=next}else cursor=existing}const leafKey=segments[segments.length-1];return Object.getOwnPropertyDescriptor(cursor,leafKey)?.value===value?!1:(Object.defineProperty(cursor,leafKey,{value,writable:!0,enumerable:!0,configurable:!0}),!0)}export{NESTED_SETTING_DESCRIPTORS,parseNestedSettingValue,readNestedSettingValue,resolveNestedSettingDescriptor,writeNestedSettingValue};
2
2
  //# sourceMappingURL=nested-settings.js.map
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="187f03b7-1a62-500c-9ebf-4d5a053afa74")}catch{}})();import fs from"node:fs/promises";import path from"node:path";import{pathToFileURL}from"node:url";import{createRelationshipKindRegistry}from"../../sdk/relationships.js";import{pathExists}from"../fs/fs-utils.js";import{isPathWithinDirectory}from"../fs/path-utils.js";import{isHostOutputSuppressed,suppressHostOutput}from"../output/output-control.js";import{resolvePmPackageRootFromModule}from"../packages/root.js";import{asRecordLoose,resolveActivatablePropertyRecord}from"../shared/primitives.js";import{resolveGlobalPmRoot}from"../store/paths.js";import{captureExtensionActivationRollback}from"./activation-transaction.js";import{assertCommandDefinitionMetadataStrings}from"./command-visibility-tier.js";import{normalizeExtensionReadOutput}from"./read-output-contract.js";import{normalizeExtensionContributionInventory}from"./contribution-inventory.js";import{buildImportExportContext,resolveImportExportArtifactOutput}from"./exporter-output-contract.js";import{buildReadyExtensionCandidate}from"./extension-candidate.js";import{collectUnknownExtensionCapabilities,formatLegacyExtensionCapabilityAliasWarning,formatUnknownExtensionCapabilityWarning,isKnownExtensionCapability,normalizeNames}from"./extension-capability-aliases.js";import{evaluateExtensionPolicyForCapability,evaluateExtensionPolicyForExtension,evaluateExtensionPolicyForRegistration,hydrateExtensionPolicy,normalizeExtensionPolicy,serializeExtensionPolicy}from"./extension-policy.js";import{createEmptyExtensionCommandRegistry,createEmptyExtensionHookRegistry,createEmptyExtensionParserRegistry,createEmptyExtensionPreflightRegistry,createEmptyExtensionRegistrationRegistry,createEmptyExtensionRendererRegistry,createEmptyExtensionServiceRegistry}from"./extension-registries.js";import{normalizeCommandName}from"./extension-runtime-helpers.js";import{KNOWN_EXTENSION_CAPABILITIES,KNOWN_EXTENSION_SERVICE_NAMES,createDefaultExtensionGovernancePolicy}from"./extension-types.js";import{parseExtensionManifestDocument}from"./manifest-parser.js";import{formatExtensionManifestSchemaWarnings}from"./manifest-schema.js";import{snapshotExtensionModuleGraph}from"./module-graph-snapshot.js";import{collectPreflightCollisionWarnings,normalizePreflightOverride}from"./preflight-ownership.js";import{applyProjectProfileDefaults,assertFlagValueTypeAndDefault,normalizeCommandDefinitionArguments,normalizeFlagDefinitions,resolveCommandDefinitionAction,validateFlagDefinitions,validateItemFieldDefinitions,validateItemTypeDefinitions,validateMigrationDefinition,validateProjectProfileDefinition}from"./registration-contracts.js";import{assertOptionalStringField,normalizeOptionalStringArrayField}from"./registration-validation.js";import{assertHookHandler,assertNonEmptyRegistrationString,assertRegistrationFunction,attachRuntimeDefinition,cloneRuntimeRegistrationValue,createRegistrationValidationError,extractRegistrationValidationTrace,isExtensionServiceName,isOutputRendererFormat,normalizeRegistrationName,normalizeRegistrationRecord,normalizeRegistrationRecordList,normalizeRuntimeRegistrationRecord,sanitizeRegistrationValue,toRegistrationCommandPath,validateAssuranceMeasurementProviderDefinition}from"./registration-values.js";import{normalizeServiceOverrideOwnership}from"./service-ownership.js";import{compareComparableVersions,evaluatePmMaxVersionBound,evaluatePmMinVersionBound,parseComparableVersion}from"./version-compat.js";import{parseLegacyExtensionCapabilityAliasWarning,parseUnknownExtensionCapabilityWarning}from"./extension-capability-aliases.js";import{createEmptyExtensionCommandRegistry as createEmptyExtensionCommandRegistry2,createEmptyExtensionHookRegistry as createEmptyExtensionHookRegistry2,createEmptyExtensionParserRegistry as createEmptyExtensionParserRegistry2,createEmptyExtensionPreflightRegistry as createEmptyExtensionPreflightRegistry2,createEmptyExtensionRegistrationRegistry as createEmptyExtensionRegistrationRegistry2,createEmptyExtensionRendererRegistry as createEmptyExtensionRendererRegistry2,createEmptyExtensionServiceRegistry as createEmptyExtensionServiceRegistry2}from"./extension-registries.js";import{runAfterCommandHooks,runBeforeCommandHooks,runBeforeMutationHooks,runCommandHandler,runCommandOverride,runOnIndexHooks,runOnReadHooks,runOnWriteHooks,runParserOverride,runPreflightOverride,runRendererOverride,runServiceOverride,runServiceOverrideSync}from"./extension-hook-runtime.js";export*from"./extension-types.js";import{DEFAULT_EXTENSION_PRIORITY,parseExtensionManifestDocument as parseExtensionManifestDocument2}from"./manifest-parser.js";let currentPmCliVersionPromise=null;const DEFAULT_EXTENSION_POLICY=Object.freeze(createDefaultExtensionGovernancePolicy());let extensionReloadEpoch=0;function nextExtensionReloadToken(seed=Date.now()){return extensionReloadEpoch+=1,`${extensionReloadEpoch}-${seed}`}function shouldEnable(name,enabled,disabled){return disabled.has(name)?!1:enabled.size===0?!0:enabled.has(name)}async function isCanonicalPathWithinDirectory(directory,targetPath){const[resolvedDirectory,resolvedTargetPath]=await Promise.all([fs.realpath(directory),fs.realpath(targetPath)]);return isPathWithinDirectory(resolvedDirectory,resolvedTargetPath)}function resolveExtensionRoots(pmRoot,cwd=process.cwd()){return{global:path.join(resolveGlobalPmRoot(cwd),"extensions"),project:path.join(pmRoot,"extensions")}}async function listExtensionDirectories(extensionsRoot){try{return(await fs.readdir(extensionsRoot,{withFileTypes:!0})).filter(entry=>entry.isDirectory()).map(entry=>entry.name).sort((a,b)=>a.localeCompare(b))}catch{return[]}}function summarizeCandidate(candidate){const summary={layer:candidate.layer,directory:candidate.directory,manifest_path:candidate.manifest_path,name:candidate.manifest.name,version:candidate.manifest.version,entry:candidate.manifest.entry,priority:candidate.manifest.priority,entry_path:candidate.entry_path,manifest_version:candidate.manifest.manifest_version,pm_min_version:candidate.manifest.pm_min_version,pm_max_version:candidate.manifest.pm_max_version,engines:candidate.manifest.engines,trusted:candidate.manifest.trusted,provenance:candidate.manifest.provenance,sandbox_profile:candidate.manifest.sandbox_profile,permissions:candidate.manifest.permissions,capabilities:[...candidate.manifest.capabilities],activation:candidate.manifest.activation?{commands:[...candidate.manifest.activation.commands]}:void 0,contributions:candidate.manifest.contributions??candidate.contributions};return candidate.source_package&&(summary.source_package=candidate.source_package),candidate.source_aliases&&(summary.source_aliases=[...candidate.source_aliases]),summary}function normalizeManagedSourcePackage(value){return typeof value=="string"&&value.trim().length>0?value.trim():void 0}async function readManagedExtensionSourcePackages(extensionsRoot){const packages=new Map;try{const parsed=JSON.parse(await fs.readFile(path.join(extensionsRoot,".managed-extensions.json"),"utf8")),entries=asRecordLoose(parsed)?.entries;if(!Array.isArray(entries))return packages;for(const entry of entries){if(typeof entry!="object"||entry===null)continue;const record=entry,sourcePackage=normalizeManagedSourcePackage(record.source?.package),aliases=[record.source?.input,record.source?.name,sourcePackage].map(value=>normalizeManagedSourcePackage(value)).filter(value=>value!==void 0),contributions=normalizeExtensionContributionInventory(record.contributions),identity={aliases:[...new Set(aliases)],...sourcePackage?{package_name:sourcePackage}:{},...contributions?{contributions}:{}};typeof record.directory=="string"&&record.directory.trim().length>0&&packages.set(`directory:${record.directory.trim()}`,identity),typeof record.name=="string"&&record.name.trim().length>0&&packages.set(`name:${record.name.trim()}`,identity)}}catch{return packages}return packages}function sortCandidates(candidates){return[...candidates].sort((left,right)=>{if(left.manifest.priority!==right.manifest.priority)return left.manifest.priority-right.manifest.priority;const byName=left.manifest.name.localeCompare(right.manifest.name);return byName!==0?byName:left.directory.localeCompare(right.directory)})}function buildEffectiveExtensions(globalCandidates,projectCandidates){const ordered=[...sortCandidates(globalCandidates),...sortCandidates(projectCandidates)],effective=[];for(const candidate of ordered){const existingIndex=effective.findIndex(entry=>entry.manifest.name===candidate.manifest.name);existingIndex>=0&&effective.splice(existingIndex,1),effective.push(candidate)}return effective}async function scanExtensionLayer(layer,extensionsRoot,enabled,disabled,pmMaxVersionExceededMode){const diagnostics=[],warnings=[],candidates=[],directories=await listExtensionDirectories(extensionsRoot),managedSourcePackages=await readManagedExtensionSourcePackages(extensionsRoot);for(const directory of directories){const scanned=await scanExtensionDirectory(layer,extensionsRoot,directory,enabled,disabled,managedSourcePackages,pmMaxVersionExceededMode);diagnostics.push(scanned.diagnostic),warnings.push(...scanned.warnings),scanned.candidate&&candidates.push(scanned.candidate)}return{diagnostics,warnings,candidates}}function emptyExtensionLayerScan(){return{diagnostics:[],warnings:[],candidates:[]}}function buildUnavailableExtensionScan(layer,directory,manifestPath,warning){return{diagnostic:{layer,directory,manifest_path:manifestPath,name:null,version:null,entry:null,priority:null,entry_path:null,enabled:null,status:"warn"},warnings:[warning],candidate:null}}function collectScannedExtensionWarnings(layer,manifest,rawManifest,entryWithinDirectory,entryExists,pmVersionCompatibility,pmMaxVersionCompatibility){const extensionWarnings=formatExtensionManifestSchemaWarnings(layer,manifest,rawManifest);Array.isArray(manifest.legacy_capability_aliases)&&manifest.legacy_capability_aliases.length>0&&extensionWarnings.push(formatLegacyExtensionCapabilityAliasWarning(layer,manifest.name,manifest.legacy_capability_aliases));for(const capability of collectUnknownExtensionCapabilities(manifest.capabilities))extensionWarnings.push(formatUnknownExtensionCapabilityWarning(layer,manifest.name,capability));return entryWithinDirectory?entryExists||extensionWarnings.push(`extension_entry_missing:${layer}:${manifest.name}`):extensionWarnings.push(`extension_entry_outside_extension:${layer}:${manifest.name}`),pmVersionCompatibility.warning&&extensionWarnings.push(pmVersionCompatibility.warning),pmMaxVersionCompatibility.warning&&extensionWarnings.push(pmMaxVersionCompatibility.warning),extensionWarnings}async function scanExtensionDirectory(layer,extensionsRoot,directory,enabled,disabled,managedSourcePackages,pmMaxVersionExceededMode){const extensionDir=path.join(extensionsRoot,directory),manifestPath=path.join(extensionDir,"manifest.json");if(!await pathExists(manifestPath))return buildUnavailableExtensionScan(layer,directory,manifestPath,`extension_manifest_missing:${layer}:${directory}`);let manifest,rawManifest;try{const parsed=JSON.parse(await fs.readFile(manifestPath,"utf8"));rawManifest=asRecordLoose(parsed),manifest=parseExtensionManifestDocument(parsed)}catch{rawManifest=null,manifest=null}if(!manifest||!rawManifest)return buildUnavailableExtensionScan(layer,directory,manifestPath,`extension_manifest_invalid:${layer}:${directory}`);const entryPath=path.resolve(extensionDir,manifest.entry),entryWithinDirectoryByPath=isPathWithinDirectory(extensionDir,entryPath),entryExists=entryWithinDirectoryByPath?await pathExists(entryPath):!1,entryWithinDirectory=entryWithinDirectoryByPath&&entryExists?await isCanonicalPathWithinDirectory(extensionDir,entryPath):entryWithinDirectoryByPath,enabledForLoad=shouldEnable(manifest.name,enabled,disabled),pmVersionCompatibility=await evaluatePmMinVersionCompatibility(layer,manifest),pmMaxVersionCompatibility=await evaluatePmMaxVersionCompatibility(layer,manifest,pmMaxVersionExceededMode),extensionWarnings=collectScannedExtensionWarnings(layer,manifest,rawManifest,entryWithinDirectory,entryExists,pmVersionCompatibility,pmMaxVersionCompatibility),extensionReady=entryWithinDirectory&&entryExists&&pmVersionCompatibility.allowed&&pmMaxVersionCompatibility.allowed,sourceIdentity=managedSourcePackages.get(`directory:${directory}`)??managedSourcePackages.get(`name:${manifest.name}`);return{diagnostic:{layer,directory,manifest_path:manifestPath,name:manifest.name,version:manifest.version,entry:manifest.entry,priority:manifest.priority,entry_path:entryPath,enabled:enabledForLoad,status:extensionReady?"ok":"warn"},warnings:extensionWarnings,candidate:buildReadyExtensionCandidate({layer,directory,manifestPath,entryPath,manifest,sourceIdentity,extensionReady,enabledForLoad})}}async function discoverExtensions(options){const roots=resolveExtensionRoots(options.pmRoot,options.cwd??process.cwd()),configured_enabled=normalizeNames(options.settings.extensions.enabled),configured_disabled=normalizeNames(options.settings.extensions.disabled),policy=normalizeExtensionPolicy(options.settings),serializedPolicy=serializeExtensionPolicy(policy);if(options.noExtensions)return{disabled_by_flag:!0,roots,configured_enabled,configured_disabled,discovered:[],effective:[],warnings:[...policy.warnings],policy:serializedPolicy};const enabled=new Set(configured_enabled),disabled=new Set(configured_disabled),globalScan=options.ignoreGlobalExtensions===!0?emptyExtensionLayerScan():await scanExtensionLayer("global",roots.global,enabled,disabled,policy.pmMaxVersionExceededMode.global),projectScan=await scanExtensionLayer("project",roots.project,enabled,disabled,policy.pmMaxVersionExceededMode.project),policyWarnings=[...policy.warnings],effectiveCandidates=buildEffectiveExtensions(globalScan.candidates,projectScan.candidates),effective=[];for(const candidate of effectiveCandidates){const extensionRef={layer:candidate.layer,name:candidate.manifest.name,trusted:candidate.manifest.trusted===!0,provenanceVerified:candidate.manifest.provenance?.verified===!0,sandboxProfile:candidate.manifest.sandbox_profile,permissions:candidate.manifest.permissions&&typeof candidate.manifest.permissions=="object"?{fs_read:candidate.manifest.permissions.fs_read,fs_write:candidate.manifest.permissions.fs_write,network:candidate.manifest.permissions.network,env_read:candidate.manifest.permissions.env_read,env_write:candidate.manifest.permissions.env_write,process_spawn:candidate.manifest.permissions.process_spawn}:void 0},extensionDecision=evaluateExtensionPolicyForExtension(policy,extensionRef);if(extensionDecision.warning&&policyWarnings.push(extensionDecision.warning),!!extensionDecision.allowed){for(const capability of candidate.manifest.capabilities){const capabilityDecision=evaluateExtensionPolicyForCapability(policy,extensionRef,capability);capabilityDecision.warning&&policyWarnings.push(capabilityDecision.warning)}effective.push(summarizeCandidate(candidate))}}return{disabled_by_flag:!1,roots,configured_enabled,configured_disabled,discovered:[...globalScan.diagnostics,...projectScan.diagnostics],effective,warnings:[...new Set([...globalScan.warnings,...projectScan.warnings,...policyWarnings])],policy:serializedPolicy}}function formatUnknownError(error){return error instanceof Error&&error.message.trim().length>0?error.message:String(error)}async function readCurrentPmCliVersion(){try{const packageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]),raw=await fs.readFile(path.join(packageRoot,"package.json"),"utf8"),parsed=JSON.parse(raw);return typeof parsed.version=="string"&&parsed.version.trim().length>0?parsed.version.trim():null}catch{return null}}function resolveCurrentPmCliVersion(){return currentPmCliVersionPromise??=readCurrentPmCliVersion(),currentPmCliVersionPromise}function formatPmVersionCompatibilityWarning(layer,manifest,evaluation){const current=evaluation.current??"unknown";if(evaluation.kind==="pm_min_version")switch(evaluation.status){case"invalid":return`extension_pm_min_version_invalid:${layer}:${manifest.name}:required=${evaluation.required}`;case"unchecked":return`extension_pm_min_version_unchecked:${layer}:${manifest.name}:required=${evaluation.required}:current=${current}`;case"unmet":return`extension_pm_min_version_unmet:${layer}:${manifest.name}:required=${evaluation.required}:current=${current}`;default:return}switch(evaluation.status){case"invalid":return`extension_pm_max_version_invalid:${layer}:${manifest.name}:allowed=${evaluation.required}`;case"unchecked":return`extension_pm_max_version_unchecked:${layer}:${manifest.name}:allowed=${evaluation.required}:current=${current}`;case"exceeded_warn":return`extension_pm_max_version_exceeded_warn:${layer}:${manifest.name}:allowed=${evaluation.required}:current=${current}`;case"exceeded":return`extension_pm_max_version_exceeded:${layer}:${manifest.name}:allowed=${evaluation.required}:current=${current}`;default:return}}async function evaluatePmMinVersionCompatibility(layer,manifest){if(manifest.pm_min_version===void 0)return{allowed:!0};const evaluation=evaluatePmMinVersionBound(manifest.pm_min_version,await resolveCurrentPmCliVersion()),warning=formatPmVersionCompatibilityWarning(layer,manifest,evaluation);return warning?{allowed:evaluation.allowed,warning}:{allowed:evaluation.allowed}}async function evaluatePmMaxVersionCompatibility(layer,manifest,exceededMode){if(manifest.pm_max_version===void 0)return{allowed:!0};const evaluation=evaluatePmMaxVersionBound(manifest.pm_max_version,await resolveCurrentPmCliVersion(),exceededMode),warning=formatPmVersionCompatibilityWarning(layer,manifest,evaluation);return warning?{allowed:evaluation.allowed,warning}:{allowed:evaluation.allowed}}async function fingerprintPath(pathToInspect){try{const stats=await fs.stat(pathToInspect);return`${Math.trunc(stats.mtimeMs)}-${stats.size}`}catch{return"missing"}}async function resolveExtensionImportHref(extension,options){let importEntryPath=extension.entry_path;options.module_graph_snapshot_root&&(importEntryPath=await snapshotExtensionModuleGraph(options.module_graph_snapshot_root,extension));const baseUrl=new URL(pathToFileURL(importEntryPath).href);if(!(options.cache_bust===!0||typeof options.reload_token=="string"))return baseUrl.href;const[entryFingerprint,manifestFingerprint]=await Promise.all([fingerprintPath(extension.entry_path),fingerprintPath(extension.manifest_path)]),reloadToken=options.reload_token??nextExtensionReloadToken();return baseUrl.searchParams.set("pm_ext_reload",reloadToken),baseUrl.searchParams.set("pm_ext_entry",entryFingerprint),baseUrl.searchParams.set("pm_ext_manifest",manifestFingerprint),baseUrl.href}async function loadExtensions(options){const discovery=await discoverExtensions(options),loaded=[],failed=[],warnings=[...discovery.warnings];if(discovery.disabled_by_flag)return{...discovery,warnings,loaded,failed};const extensionsToLoad=typeof options.extensionFilter=="function"?discovery.effective.filter(options.extensionFilter):discovery.effective;for(const extension of extensionsToLoad)try{const module=await import(await resolveExtensionImportHref(extension,options));loaded.push({...extension,module})}catch(error){warnings.push(`extension_load_failed:${extension.layer}:${extension.name}`),failed.push({layer:extension.layer,name:extension.name,entry_path:extension.entry_path,error:formatUnknownError(error)})}return{...discovery,warnings,loaded,failed}}const DEFAULT_EXTENSION_DEACTIVATE_TIMEOUT_MS=5e3,MAX_EXTENSION_DEACTIVATE_TIMEOUT_MS=2147483647;function toActivatableExtension(source){const activatable={activate:source.activate.bind(source)};if(typeof source.deactivate=="function"){const deactivate=source.deactivate;activatable.deactivate=deactivate.bind(source)}return activatable}function resolveActivatableExtension(module){const activatableRecord=resolveActivatablePropertyRecord(module);return activatableRecord?toActivatableExtension(activatableRecord):null}async function deactivateExtensions(loadResult,activationResult,options={}){const timeoutMs=normalizeExtensionDeactivateTimeout(options?.deactivate_timeout_ms),failedActivationKeys=new Set((activationResult?.failed??[]).map(entry=>`${entry.layer}:${entry.name}`)),targets=[];for(const extension of loadResult.loaded){if(failedActivationKeys.has(`${extension.layer}:${extension.name}`))continue;const activatable=resolveActivatableExtension(extension.module);!activatable||typeof activatable.deactivate!="function"||targets.push({extension,deactivate:activatable.deactivate})}const outcomes=await Promise.all(targets.map(async({extension,deactivate})=>{try{return await runExtensionDeactivateWithTimeout(deactivate,timeoutMs),{ok:!0}}catch(error){return{ok:!1,layer:extension.layer,name:extension.name,error:formatUnknownError(error)}}})),warnings=[],failed=[];let deactivated=0;for(const outcome of outcomes){if(outcome.ok){deactivated+=1;continue}warnings.push(`extension_deactivate_failed:${outcome.layer}:${outcome.name}`),failed.push({layer:outcome.layer,name:outcome.name,error:outcome.error})}return{deactivated,warnings,failed}}function normalizeExtensionDeactivateTimeout(rawTimeout){return typeof rawTimeout!="number"||rawTimeout<0?DEFAULT_EXTENSION_DEACTIVATE_TIMEOUT_MS:rawTimeout===0||rawTimeout===1/0?0:Number.isFinite(rawTimeout)?Math.min(MAX_EXTENSION_DEACTIVATE_TIMEOUT_MS,Math.max(1,Math.floor(rawTimeout))):DEFAULT_EXTENSION_DEACTIVATE_TIMEOUT_MS}async function runExtensionDeactivateWithTimeout(deactivate,timeoutMs){if(timeoutMs===0){await deactivate();return}let timeoutHandle;try{const deactivatePromise=Promise.resolve().then(()=>deactivate());deactivatePromise.catch(()=>{}),await Promise.race([deactivatePromise,new Promise((_,reject)=>{timeoutHandle=setTimeout(()=>{reject(new Error(`extension deactivate timed out after ${timeoutMs}ms`))},timeoutMs),timeoutHandle.unref?.()})])}finally{clearTimeout(timeoutHandle)}}function getDeclaredExtensionCapabilities(extension){if(!Array.isArray(extension.capabilities))return null;const declared=new Set;for(const capability of extension.capabilities){const normalized=capability.trim().toLowerCase();isKnownExtensionCapability(normalized)&&declared.add(normalized)}return declared}function assertExtensionCapability(extension,capability,method){const declared=getDeclaredExtensionCapabilities(extension);if(declared!==null&&!declared.has(capability))throw createRegistrationValidationError(`${method} requires capability '${capability}' in extension manifest capabilities`,{method,registration_index:-1,capability,missing_capability:capability,expected_schema:`"capabilities": [..., "${capability}"]`,received:extension.capabilities,hint:`Add "${capability}" to ${extension.name} manifest capabilities, or remove the ${method} registration call.`})}function buildExtensionSelfIdentity(extension){return Object.freeze({name:extension.name,layer:extension.layer,version:extension.version,capabilities:Object.freeze((extension.capabilities??[]).filter(capability=>KNOWN_EXTENSION_CAPABILITIES.includes(capability))),pm_min_version:extension.pm_min_version,pm_max_version:extension.pm_max_version,source_package:extension.source_package})}function buildPolicyExtensionRef(extension){return{layer:extension.layer,name:extension.name,trusted:extension.trusted===!0,provenanceVerified:extension.provenance?.verified===!0,sandboxProfile:extension.sandbox_profile,permissions:extension.permissions&&typeof extension.permissions=="object"?{fs_read:extension.permissions.fs_read,fs_write:extension.permissions.fs_write,network:extension.permissions.network,env_read:extension.permissions.env_read,env_write:extension.permissions.env_write,process_spawn:extension.permissions.process_spawn}:void 0}}class ExtensionApiRegistrar{extension;hooks;#loadedExtension;#extensionRef;#hookRegistry;#commandRegistry;#parserRegistry;#preflightRegistry;#serviceRegistry;#rendererRegistry;#registrationRegistry;#activationWarnings;#activationFailures;#policy;constructor(extension,hooks,commands,parsers,preflight,services,renderers,registrations,activationWarnings,activationFailures,policy){this.#loadedExtension=extension,this.extension=buildExtensionSelfIdentity(extension),this.#extensionRef=buildPolicyExtensionRef(extension),this.#hookRegistry=hooks,this.#commandRegistry=commands,this.#parserRegistry=parsers,this.#preflightRegistry=preflight,this.#serviceRegistry=services,this.#rendererRegistry=renderers,this.#registrationRegistry=registrations,this.#activationWarnings=activationWarnings,this.#activationFailures=activationFailures,this.#policy=policy,this.registerCommand=this.registerCommand.bind(this),this.registerParser=this.registerParser.bind(this),this.registerPreflight=this.registerPreflight.bind(this),this.registerService=this.registerService.bind(this),this.registerFlags=this.registerFlags.bind(this),this.registerItemFields=this.registerItemFields.bind(this),this.registerItemTypes=this.registerItemTypes.bind(this),this.registerRelationshipKinds=this.registerRelationshipKinds.bind(this),this.registerMigration=this.registerMigration.bind(this),this.registerProfile=this.registerProfile.bind(this),this.registerRenderer=this.registerRenderer.bind(this),this.registerImporter=this.registerImporter.bind(this),this.registerExporter=this.registerExporter.bind(this),this.registerSearchProvider=this.registerSearchProvider.bind(this),this.registerVectorStoreAdapter=this.registerVectorStoreAdapter.bind(this),this.registerAssuranceMeasurementProvider=this.registerAssuranceMeasurementProvider.bind(this),this.hooks={beforeCommand:hook=>this.registerBeforeCommand(hook),beforeMutation:hook=>this.registerBeforeMutation(hook),afterCommand:hook=>this.registerAfterCommand(hook),onWrite:hook=>this.registerOnWrite(hook),onRead:hook=>this.registerOnRead(hook),onIndex:hook=>this.registerOnIndex(hook)}}allowRegistration(surface,method,capability,details){const decision=evaluateExtensionPolicyForRegistration(this.#policy,this.#extensionRef,surface,method,capability,details);return decision.warning&&this.#activationWarnings.push(decision.warning),decision.allowed}registerCommandTrace(mode,command,expectedSchema,received,hint){return{method:"registerCommand",registration_index:mode==="override"?this.#commandRegistry.overrides.length:this.#commandRegistry.handlers.length,command,expected_schema:expectedSchema,received:sanitizeRegistrationValue(received),hint}}registerCommandOverride(command,override){const normalizedCommand=normalizeCommandName(command);if(normalizedCommand.length===0)throw createRegistrationValidationError("registerCommand requires a non-empty command name",this.registerCommandTrace("override",command,'registerCommand("<command>", (context) => unknown)',command,"Provide a non-empty command path as the first argument."));if(typeof override!="function"){const trace=this.registerCommandTrace("override",normalizedCommand,'registerCommand("<command>", (context) => unknown)',override,"Provide a function as the second registerCommand argument.");throw createRegistrationValidationError(`registerCommand requires an override function when command name is provided (command="${normalizedCommand}", registration_index=${trace.registration_index})`,trace)}this.allowRegistration("commands.override","registerCommand","commands",{command:normalizedCommand})&&this.#commandRegistry.overrides.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,command:normalizedCommand,run:override})}resolveCommandDefinitionRunHandler(definition,normalizedCommand){const runHandler=typeof definition.run=="function"?definition.run:void 0,legacyHandler=typeof definition.handler=="function"?definition.handler:void 0;return!runHandler&&legacyHandler&&this.#activationWarnings.push(`extension_command_definition_legacy_handler_alias:${this.#loadedExtension.layer}:${this.#loadedExtension.name}:${normalizedCommand}`),runHandler??legacyHandler}registerCommandDefinition(definition){if(typeof definition!="object"||definition===null)throw createRegistrationValidationError("registerCommand requires a command definition object",this.registerCommandTrace("definition",void 0,"{ name: string; run: (context) => unknown; }",definition,'Use registerCommand({ name: "command path", run: (context) => ... }).'));if(typeof definition.name!="string")throw createRegistrationValidationError("registerCommand requires a command definition name",this.registerCommandTrace("definition",void 0,"{ name: string; run: (context) => unknown; }",definition,"Set command definition.name to a non-empty string command path."));const normalizedCommand=normalizeCommandName(definition.name);if(normalizedCommand.length===0)throw createRegistrationValidationError("registerCommand requires a non-empty command definition name",this.registerCommandTrace("definition",definition.name,"{ name: string; run: (context) => unknown; }",definition,"Ensure command definition.name contains a non-empty command path."));const resolvedHandler=this.resolveCommandDefinitionRunHandler(definition,normalizedCommand);if(typeof resolvedHandler!="function"){const trace=this.registerCommandTrace("definition",normalizedCommand,"{ name: string; run: (context) => unknown; }",resolvedHandler,"Define command definition.run as a function.");throw createRegistrationValidationError(`registerCommand requires a command definition run handler (command="${normalizedCommand}", registration_index=${trace.registration_index})`,trace)}try{assertCommandDefinitionMetadataStrings(definition);const action=resolveCommandDefinitionAction(normalizedCommand,definition.action),readOutput=normalizeExtensionReadOutput(definition.read_output,normalizedCommand,action);if(!this.allowRegistration("commands.handler","registerCommand","commands",{command:normalizedCommand,action}))return;const description=definition.description?.trim(),intent=definition.intent?.trim(),examples=normalizeOptionalStringArrayField("registerCommand definition.examples",definition.examples),failureHints=normalizeOptionalStringArrayField("registerCommand definition.failure_hints",definition.failure_hints),argumentsDefinition=normalizeCommandDefinitionArguments(definition.arguments);definition.flags!==void 0&&(assertExtensionCapability(this.#loadedExtension,"schema","registerCommand flags"),this.allowRegistration("schema.flags","registerCommand flags","schema")&&(validateFlagDefinitions(definition.flags),this.#registrationRegistry.flags.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,target_command:normalizedCommand,flags:normalizeFlagDefinitions("registerCommand definition.flags",definition.flags)})));const registration={read_output:readOutput,layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,source_package:this.#loadedExtension.source_package,command:normalizedCommand,action,examples,failure_hints:failureHints,arguments:argumentsDefinition,tier:definition.tier??"standard",family:definition.family??"extensions"};description&&(registration.description=description),intent&&(registration.intent=intent),this.#registrationRegistry.commands.push(registration)}catch(error){const reason=formatUnknownError(error),trace=this.registerCommandTrace("definition",normalizedCommand,"{ name: string; run: (context) => unknown; action?: string; arguments?: object[]; flags?: object[]; }",definition,reason),validationError=createRegistrationValidationError(`registerCommand definition metadata invalid (command="${normalizedCommand}", registration_index=${trace.registration_index}): ${reason}`,trace);this.#activationWarnings.push(`extension_command_quarantined:${this.#loadedExtension.layer}:${this.#loadedExtension.name}:${normalizedCommand}`),this.#activationFailures.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,entry_path:this.#loadedExtension.entry_path,error:validationError.message,trace});return}this.#commandRegistry.handlers.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,command:normalizedCommand,run:resolvedHandler})}registerCommand(commandOrDefinition,override){if(assertExtensionCapability(this.#loadedExtension,"commands","registerCommand"),typeof commandOrDefinition=="string"){this.registerCommandOverride(commandOrDefinition,override);return}this.registerCommandDefinition(commandOrDefinition)}registerParser(command,override){if(assertExtensionCapability(this.#loadedExtension,"parser","registerParser"),!this.allowRegistration("parser.override","registerParser","parser"))return;const normalizedCommand=normalizeCommandName(assertNonEmptyRegistrationString("registerParser command",command));assertRegistrationFunction("registerParser override",override),this.#parserRegistry.overrides.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,command:normalizedCommand,run:override})}registerPreflight(override){if(assertExtensionCapability(this.#loadedExtension,"preflight","registerPreflight"),!this.allowRegistration("preflight.override","registerPreflight","preflight"))return;const normalized=normalizePreflightOverride(override);this.#preflightRegistry.overrides.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,...normalized})}registerService(service,override,ownership={}){assertExtensionCapability(this.#loadedExtension,"services","registerService");const normalizedService=String(service).trim().toLowerCase();if(!isExtensionServiceName(normalizedService))throw new TypeError(`registerService service must be one of: ${KNOWN_EXTENSION_SERVICE_NAMES.join(", ")}`);this.allowRegistration("services.override","registerService","services",{service:normalizedService})&&(assertRegistrationFunction("registerService override",override),this.#serviceRegistry.overrides.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,service:normalizedService,run:override,...normalizeServiceOverrideOwnership(ownership)?{passThrough:!0}:{}}))}registerRenderer(format,renderer,ownership={}){if(assertExtensionCapability(this.#loadedExtension,"renderers","registerRenderer"),!this.allowRegistration("renderers.override","registerRenderer","renderers"))return;if(typeof renderer!="function")throw new TypeError("registerRenderer requires a renderer function");const normalizedFormat=String(format).trim().toLowerCase();if(!isOutputRendererFormat(normalizedFormat))throw new Error(`registerRenderer format must be toon|json, received: ${String(format)}`);if(ownership.resultDiscriminator!==void 0&&typeof ownership.resultDiscriminator!="function")throw new TypeError("registerRenderer ownership.resultDiscriminator must be a function when provided");const commands=[...new Set((ownership.commands??[]).map(command=>{if(typeof command!="string"||command.trim().length===0)throw new TypeError("registerRenderer ownership.commands must contain non-empty command paths");return normalizeCommandName(command)}))];this.#rendererRegistry.overrides.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,format:normalizedFormat,run:renderer,commands,...ownership.resultDiscriminator?{resultDiscriminator:ownership.resultDiscriminator}:{}})}registerFlags(targetCommand,flags){if(assertExtensionCapability(this.#loadedExtension,"schema","registerFlags"),!this.allowRegistration("schema.flags","registerFlags","schema"))return;const normalizedTargetCommand=normalizeCommandName(assertNonEmptyRegistrationString("registerFlags targetCommand",targetCommand));validateFlagDefinitions(flags);const normalizedFlags=normalizeFlagDefinitions("registerFlags flags",flags);if(normalizedFlags.length===0)throw new TypeError("registerFlags requires at least one flag definition");this.#registrationRegistry.flags.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,target_command:normalizedTargetCommand,flags:normalizedFlags})}registerItemFields(fields){if(assertExtensionCapability(this.#loadedExtension,"schema","registerItemFields"),!this.allowRegistration("schema.itemfields","registerItemFields","schema"))return;validateItemFieldDefinitions(fields);const normalizedFields=normalizeRegistrationRecordList("registerItemFields fields",fields);if(normalizedFields.length===0)throw new TypeError("registerItemFields requires at least one field definition");this.#registrationRegistry.item_fields.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,fields:normalizedFields})}registerItemTypes(types){if(assertExtensionCapability(this.#loadedExtension,"schema","registerItemTypes"),!this.allowRegistration("schema.itemtypes","registerItemTypes","schema"))return;validateItemTypeDefinitions(types);const normalizedTypes=normalizeRegistrationRecordList("registerItemTypes types",types);if(normalizedTypes.length===0)throw new TypeError("registerItemTypes requires at least one type definition");this.#registrationRegistry.item_types.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,types:normalizedTypes})}registerRelationshipKinds(definitions){if(assertExtensionCapability(this.#loadedExtension,"schema","registerRelationshipKinds"),!this.allowRegistration("schema.relationshipkinds","registerRelationshipKinds","schema"))return;if(!Array.isArray(definitions))throw new TypeError("registerRelationshipKinds definitions requires an array of object definitions");if(definitions.length===0)throw new TypeError("registerRelationshipKinds requires at least one definition");const registry=createRelationshipKindRegistry();for(const registration of this.#registrationRegistry.relationship_kinds)for(const definition of registration.definitions)registry.register(definition);const validated=definitions.map(definition=>(registry.register(definition),registry.require(definition.kind)));this.#registrationRegistry.relationship_kinds.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,definitions:validated})}registerMigration(definition){if(assertExtensionCapability(this.#loadedExtension,"schema","registerMigration"),!this.allowRegistration("schema.migrations","registerMigration","schema"))return;validateMigrationDefinition(definition);const runtimeDefinition=normalizeRuntimeRegistrationRecord("registerMigration definition",definition);this.#registrationRegistry.migrations.push(attachRuntimeDefinition({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,definition:normalizeRegistrationRecord("registerMigration definition",definition)},runtimeDefinition))}registerProfile(profile){if(assertExtensionCapability(this.#loadedExtension,"schema","registerProfile"),!this.allowRegistration("schema.profiles","registerProfile","schema"))return;const snapshot=cloneRuntimeRegistrationValue(profile);validateProjectProfileDefinition(snapshot),this.#registrationRegistry.profiles.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,profile:applyProjectProfileDefaults(snapshot)})}registerImportExportCommandFlags(method,commandPath,resolvedOptions){resolvedOptions.flags!==void 0&&(assertExtensionCapability(this.#loadedExtension,"schema",`${method} options.flags`),this.allowRegistration("schema.flags",`${method} options.flags`,"schema")&&(validateFlagDefinitions(resolvedOptions.flags),this.#registrationRegistry.flags.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,target_command:commandPath,flags:normalizeFlagDefinitions(`${method} options.flags`,resolvedOptions.flags)})))}applyImportExportCommandMetadata(method,commandPath,options){if(options!==void 0&&(typeof options!="object"||options===null||Array.isArray(options)))throw new TypeError(`${method} options must be an object when provided`);const defaultDescription=`${method==="registerImporter"?"Import":"Export"} items with the registered extension adapter.`,defaultArguments=[{name:"file",required:!1,description:"Optional input or output file path."}],resolvedOptions={...options,description:options?.description??defaultDescription,arguments:options?.arguments??defaultArguments},output=resolveImportExportArtifactOutput(method,resolvedOptions,options?.description!==void 0);assertOptionalStringField(`${method} options.action`,resolvedOptions.action),assertOptionalStringField(`${method} options.description`,resolvedOptions.description),assertOptionalStringField(`${method} options.intent`,resolvedOptions.intent);const action=resolveCommandDefinitionAction(commandPath,resolvedOptions.action),examples=normalizeOptionalStringArrayField(`${method} options.examples`,resolvedOptions.examples),failureHints=normalizeOptionalStringArrayField(`${method} options.failure_hints`,resolvedOptions.failure_hints),argumentsDefinition=normalizeCommandDefinitionArguments(resolvedOptions.arguments);this.registerImportExportCommandFlags(method,commandPath,resolvedOptions);const registration={layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,source_package:this.#loadedExtension.source_package,command:commandPath,action,examples,failure_hints:failureHints,arguments:argumentsDefinition},description=resolvedOptions.description?.trim();description&&(registration.description=description);const intent=resolvedOptions.intent?.trim();return intent&&(registration.intent=intent),this.#registrationRegistry.commands.push(registration),output}registerImporter(name,importer,options){if(assertExtensionCapability(this.#loadedExtension,"importers","registerImporter"),!this.allowRegistration("importers.importer","registerImporter","importers"))return;const normalizedName=normalizeRegistrationName(assertNonEmptyRegistrationString("registerImporter name",name));assertRegistrationFunction("registerImporter importer",importer);const commandPath=toRegistrationCommandPath(normalizedName,"import");this.applyImportExportCommandMetadata("registerImporter",commandPath,options),this.#registrationRegistry.importers.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,importer:normalizedName}),this.#commandRegistry.handlers.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,command:commandPath,run:async context=>importer(buildImportExportContext(context,normalizedName,"import"))})}registerExporter(name,exporter,options){if(assertExtensionCapability(this.#loadedExtension,"importers","registerExporter"),!this.allowRegistration("importers.exporter","registerExporter","importers"))return;const normalizedName=normalizeRegistrationName(assertNonEmptyRegistrationString("registerExporter name",name));assertRegistrationFunction("registerExporter exporter",exporter);const commandPath=toRegistrationCommandPath(normalizedName,"export"),output=this.applyImportExportCommandMetadata("registerExporter",commandPath,options);this.#registrationRegistry.exporters.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,exporter:normalizedName,...output===void 0?{}:{output}}),this.#commandRegistry.handlers.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,command:commandPath,run:async context=>{const result=await exporter(buildImportExportContext(context,normalizedName,"export"));return output?.receipt==="suppress"&&!isHostOutputSuppressed(result)?suppressHostOutput(result):result}})}registerSearchProvider(provider){if(assertExtensionCapability(this.#loadedExtension,"search","registerSearchProvider"),!this.allowRegistration("search.provider","registerSearchProvider","search"))return;const runtimeDefinition=normalizeRuntimeRegistrationRecord("registerSearchProvider provider",provider);this.#registrationRegistry.search_providers.push(attachRuntimeDefinition({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,definition:normalizeRegistrationRecord("registerSearchProvider provider",provider)},runtimeDefinition))}registerVectorStoreAdapter(adapter){if(assertExtensionCapability(this.#loadedExtension,"search","registerVectorStoreAdapter"),!this.allowRegistration("search.vectorstore","registerVectorStoreAdapter","search"))return;const runtimeDefinition=normalizeRuntimeRegistrationRecord("registerVectorStoreAdapter adapter",adapter);this.#registrationRegistry.vector_store_adapters.push(attachRuntimeDefinition({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,definition:normalizeRegistrationRecord("registerVectorStoreAdapter adapter",adapter)},runtimeDefinition))}registerAssuranceMeasurementProvider(provider){if(assertExtensionCapability(this.#loadedExtension,"services","registerAssuranceMeasurementProvider"),!this.allowRegistration("services.assuranceprovider","registerAssuranceMeasurementProvider","services"))return;if(validateAssuranceMeasurementProviderDefinition(provider),provider.network&&this.#loadedExtension.permissions?.network!==!0)throw new TypeError("registerAssuranceMeasurementProvider network provider requires permissions.network=true");const runtimeDefinition=normalizeRuntimeRegistrationRecord("registerAssuranceMeasurementProvider provider",provider);this.#registrationRegistry.assurance_providers.push(attachRuntimeDefinition({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,network_permission:this.#loadedExtension.permissions?.network===!0,definition:normalizeRegistrationRecord("registerAssuranceMeasurementProvider provider",provider)},runtimeDefinition))}registerBeforeCommand(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.beforeCommand"),this.allowRegistration("hooks.beforecommand","api.hooks.beforeCommand","hooks")&&(assertHookHandler("beforeCommand",hook),this.#hookRegistry.beforeCommand.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,run:hook}))}registerBeforeMutation(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.beforeMutation"),this.allowRegistration("hooks.beforemutation","api.hooks.beforeMutation","hooks")&&(assertHookHandler("beforeMutation",hook),this.#hookRegistry.beforeMutation.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,run:hook}))}registerAfterCommand(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.afterCommand"),this.allowRegistration("hooks.aftercommand","api.hooks.afterCommand","hooks")&&(assertHookHandler("afterCommand",hook),this.#hookRegistry.afterCommand.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,run:hook}))}registerOnWrite(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.onWrite"),this.allowRegistration("hooks.onwrite","api.hooks.onWrite","hooks")&&(assertHookHandler("onWrite",hook),this.#hookRegistry.onWrite.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,run:hook}))}registerOnRead(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.onRead"),this.allowRegistration("hooks.onread","api.hooks.onRead","hooks")&&(assertHookHandler("onRead",hook),this.#hookRegistry.onRead.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,run:hook}))}registerOnIndex(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.onIndex"),this.allowRegistration("hooks.onindex","api.hooks.onIndex","hooks")&&(assertHookHandler("onIndex",hook),this.#hookRegistry.onIndex.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,run:hook}))}}function createExtensionApi(extension,hooks,commands,parsers,preflight,services,renderers,registrations,activationWarnings,activationFailures,policy){return new ExtensionApiRegistrar(extension,hooks,commands,parsers,preflight,services,renderers,registrations,activationWarnings,activationFailures,policy)}function getRegistrationCounts(registrations){const commandCount=registrations.commands.length,flagCount=registrations.flags.reduce((total,entry)=>total+entry.flags.length,0),itemFieldCount=registrations.item_fields.reduce((total,entry)=>total+entry.fields.length,0),itemTypeCount=registrations.item_types.reduce((total,entry)=>total+entry.types.length,0),relationshipKindCount=(registrations.relationship_kinds??[]).reduce((total,entry)=>total+entry.definitions.length,0);return{commands:commandCount,flags:flagCount,item_fields:itemFieldCount,item_types:itemTypeCount,...relationshipKindCount>0?{relationship_kinds:relationshipKindCount}:{},migrations:registrations.migrations.length,profiles:registrations.profiles.length,importers:registrations.importers.length,exporters:registrations.exporters.length,search_providers:registrations.search_providers.length,vector_store_adapters:registrations.vector_store_adapters.length,...(registrations.assurance_providers?.length??0)>0?{assurance_providers:registrations.assurance_providers.length}:{}}}function collectCommandCollisionWarnings(commands){const warnings=[],collectByCommand=(entries,codePrefix)=>{const grouped=new Map;for(const entry of entries){const bucket=grouped.get(entry.command)??[];bucket.push(entry),grouped.set(entry.command,bucket)}for(const command of[...grouped.keys()].sort((left,right)=>left.localeCompare(right))){const bucket=grouped.get(command);if(bucket.length<=1)continue;const winner=bucket[bucket.length-1];for(const displaced of bucket.slice(0,-1))warnings.push(`${codePrefix}:${command}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`)}};collectByCommand(commands.handlers,"extension_command_handler_collision"),collectByCommand(commands.overrides,"extension_command_override_collision");const handlerCommands=new Set(commands.handlers.map(entry=>entry.command)),overlapCommands=[...new Set(commands.overrides.map(entry=>entry.command))].filter(command=>handlerCommands.has(command));overlapCommands.sort((left,right)=>left.localeCompare(right));for(const command of overlapCommands){const handlers=commands.handlers.filter(entry=>entry.command===command),overrides=commands.overrides.filter(entry=>entry.command===command);for(const override of overrides)for(const handler of handlers)warnings.push(`extension_command_override_handler_overlap:${command}:${override.layer}:${override.name}:${handler.layer}:${handler.name}`)}return warnings}function collectRendererCollisionWarnings(renderers){const grouped=new Map;for(const entry of renderers.overrides){const bucket=grouped.get(entry.format)??[];bucket.push(entry),grouped.set(entry.format,bucket)}const warnings=[];for(const format of[...grouped.keys()].sort((left,right)=>left.localeCompare(right))){const bucket=grouped.get(format);if(bucket.length<=1)continue;const winner=bucket[bucket.length-1];for(const displaced of bucket.slice(0,-1))winner.commands?.length&&displaced.commands?.length&&!displaced.commands.some(command=>winner.commands?.includes(command))||warnings.push(`extension_renderer_collision:${format}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`)}return warnings}function collectParserCollisionWarnings(parsers){const warnings=[],grouped=new Map;for(const entry of parsers.overrides){const bucket=grouped.get(entry.command)??[];bucket.push(entry),grouped.set(entry.command,bucket)}for(const command of[...grouped.keys()].sort((left,right)=>left.localeCompare(right))){const bucket=grouped.get(command);if(bucket.length<=1)continue;const winner=bucket[bucket.length-1];for(const displaced of bucket.slice(0,-1))warnings.push(`extension_parser_override_collision:${command}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`)}return warnings}const CHAINED_SERVICE_NAMES=new Set(["output_format"]);function collectServiceCollisionWarnings(services){const warnings=[],grouped=new Map;for(const entry of services.overrides){const bucket=grouped.get(entry.service)??[];bucket.push(entry),grouped.set(entry.service,bucket)}for(const service of[...grouped.keys()].sort((left,right)=>left.localeCompare(right))){const bucket=grouped.get(service);if(bucket.length<=1||CHAINED_SERVICE_NAMES.has(service))continue;const winner=bucket[bucket.length-1];for(const displaced of bucket.slice(0,-1))warnings.push(`extension_service_override_collision:${service}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`)}return warnings}async function activateExtensions(loadResult){const policy=hydrateExtensionPolicy(loadResult.policy??DEFAULT_EXTENSION_POLICY),hooks=createEmptyExtensionHookRegistry(),commands=createEmptyExtensionCommandRegistry(),parsers=createEmptyExtensionParserRegistry(),preflight=createEmptyExtensionPreflightRegistry(),services=createEmptyExtensionServiceRegistry(),renderers=createEmptyExtensionRendererRegistry(),registrations=createEmptyExtensionRegistrationRegistry(),failed=[],warnings=[];for(const extension of loadResult.loaded){const activatable=resolveActivatableExtension(extension.module);if(!activatable)continue;const failedBeforeActivation=failed.length,rollbackPartialActivation=captureExtensionActivationRollback({hooks,commands,parsers,preflight,services,renderers,registrations});try{await activatable.activate(createExtensionApi(extension,hooks,commands,parsers,preflight,services,renderers,registrations,warnings,failed,policy)),failed.length>failedBeforeActivation&&(rollbackPartialActivation(),warnings.push(`extension_activation_rolled_back:${extension.layer}:${extension.name}`))}catch(error){rollbackPartialActivation(),warnings.push(`extension_activate_failed:${extension.layer}:${extension.name}`);const trace=extractRegistrationValidationTrace(error);failed.push({layer:extension.layer,name:extension.name,entry_path:extension.entry_path,error:formatUnknownError(error),trace})}}const collisionWarnings=[...collectCommandCollisionWarnings(commands),...collectParserCollisionWarnings(parsers),...collectPreflightCollisionWarnings(preflight),...collectServiceCollisionWarnings(services),...collectRendererCollisionWarnings(renderers)],mergedWarnings=[...new Set([...warnings,...collisionWarnings])];return{hooks,commands,parsers,preflight,services,renderers,registrations,failed,warnings:mergedWarnings,hook_counts:{before_command:hooks.beforeCommand.length,before_mutation:hooks.beforeMutation.length,after_command:hooks.afterCommand.length,on_write:hooks.onWrite.length,on_read:hooks.onRead.length,on_index:hooks.onIndex.length},command_override_count:commands.overrides.length,command_handler_count:commands.handlers.length,parser_override_count:parsers.overrides.length,preflight_override_count:preflight.overrides.length,service_override_count:services.overrides.length,renderer_override_count:renderers.overrides.length,registration_counts:getRegistrationCounts(registrations)}}const _testOnlyLoader={assertFlagValueTypeAndDefault,assertOptionalStringField,compareComparableVersions,collectCommandCollisionWarnings,collectParserCollisionWarnings,collectRendererCollisionWarnings,collectServiceCollisionWarnings,createExtensionApi,createRegistrationValidationError,evaluatePmMaxVersionCompatibility,evaluatePmMinVersionCompatibility,extractRegistrationValidationTrace,fingerprintPath,getRegistrationCounts,normalizeCommandDefinitionArguments,normalizeExtensionDeactivateTimeout,normalizeOptionalStringArrayField,normalizeRegistrationRecord,normalizeRegistrationRecordList,normalizeRuntimeRegistrationRecord,parseComparableVersion,parseManifest:parseExtensionManifestDocument,readCurrentPmCliVersion,readManagedExtensionSourcePackages:async extensionsRoot=>new Map([...await readManagedExtensionSourcePackages(extensionsRoot)].filter(entry=>typeof entry[1].package_name=="string").map(([key,identity])=>[key,identity.package_name])),resolveExtensionImportHref,resolveCurrentPmCliVersion,resolveCommandDefinitionAction,sanitizeRegistrationValue,validateItemFieldDefinitions,resetCurrentPmCliVersionCacheForTest:()=>{currentPmCliVersionPromise=null}};export{DEFAULT_EXTENSION_PRIORITY,_testOnlyLoader,activateExtensions,createEmptyExtensionCommandRegistry2 as createEmptyExtensionCommandRegistry,createEmptyExtensionHookRegistry2 as createEmptyExtensionHookRegistry,createEmptyExtensionParserRegistry2 as createEmptyExtensionParserRegistry,createEmptyExtensionPreflightRegistry2 as createEmptyExtensionPreflightRegistry,createEmptyExtensionRegistrationRegistry2 as createEmptyExtensionRegistrationRegistry,createEmptyExtensionRendererRegistry2 as createEmptyExtensionRendererRegistry,createEmptyExtensionServiceRegistry2 as createEmptyExtensionServiceRegistry,deactivateExtensions,discoverExtensions,isCanonicalPathWithinDirectory,loadExtensions,nextExtensionReloadToken,parseExtensionManifestDocument2 as parseExtensionManifestDocument,parseLegacyExtensionCapabilityAliasWarning,parseUnknownExtensionCapabilityWarning,resolveExtensionRoots,runAfterCommandHooks,runBeforeCommandHooks,runBeforeMutationHooks,runCommandHandler,runCommandOverride,runOnIndexHooks,runOnReadHooks,runOnWriteHooks,runParserOverride,runPreflightOverride,runRendererOverride,runServiceOverride,runServiceOverrideSync};
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]="d3066947-0087-5732-8511-74a31056b6e1")}catch{}})();import fs from"node:fs/promises";import path from"node:path";import{pathToFileURL}from"node:url";import{createRelationshipKindRegistry}from"../../sdk/relationships.js";import{pathExists}from"../fs/fs-utils.js";import{isPathWithinDirectory}from"../fs/path-utils.js";import{isHostOutputSuppressed,suppressHostOutput}from"../output/output-control.js";import{resolvePmPackageRootFromModule}from"../packages/root.js";import{asRecordLoose,resolveActivatablePropertyRecord}from"../shared/primitives.js";import{resolveGlobalPmRoot}from"../store/paths.js";import{captureExtensionActivationRollback}from"./activation-transaction.js";import{assertCommandDefinitionMetadataStrings}from"./command-visibility-tier.js";import{normalizeExtensionReadOutput}from"./read-output-contract.js";import{normalizeExtensionContributionInventory}from"./contribution-inventory.js";import{buildImportExportContext,resolveImportExportArtifactOutput}from"./exporter-output-contract.js";import{buildReadyExtensionCandidate}from"./extension-candidate.js";import{collectUnknownExtensionCapabilities,formatLegacyExtensionCapabilityAliasWarning,formatUnknownExtensionCapabilityWarning,isKnownExtensionCapability,normalizeNames}from"./extension-capability-aliases.js";import{evaluateExtensionPolicyForCapability,evaluateExtensionPolicyForExtension,evaluateExtensionPolicyForRegistration,hydrateExtensionPolicy,normalizeExtensionPolicy,serializeExtensionPolicy}from"./extension-policy.js";import{createEmptyExtensionCommandRegistry,createEmptyExtensionHookRegistry,createEmptyExtensionParserRegistry,createEmptyExtensionPreflightRegistry,createEmptyExtensionRegistrationRegistry,createEmptyExtensionRendererRegistry,createEmptyExtensionServiceRegistry}from"./extension-registries.js";import{normalizeCommandName}from"./extension-runtime-helpers.js";import{KNOWN_EXTENSION_CAPABILITIES,KNOWN_EXTENSION_SERVICE_NAMES,createDefaultExtensionGovernancePolicy}from"./extension-types.js";import{parseExtensionManifestDocument}from"./manifest-parser.js";import{formatExtensionManifestSchemaWarnings}from"./manifest-schema.js";import{snapshotExtensionModuleGraph}from"./module-graph-snapshot.js";import{collectPreflightCollisionWarnings,normalizePreflightOverride}from"./preflight-ownership.js";import{applyProjectProfileDefaults,assertFlagValueTypeAndDefault,normalizeCommandDefinitionArguments,normalizeFlagDefinitions,resolveCommandDefinitionAction,validateFlagDefinitions,validateItemFieldDefinitions,validateItemTypeDefinitions,validateMigrationDefinition,validateProjectProfileDefinition}from"./registration-contracts.js";import{assertOptionalStringField,normalizeOptionalStringArrayField}from"./registration-validation.js";import{assertHookHandler,assertNonEmptyRegistrationString,assertRegistrationFunction,attachRuntimeDefinition,cloneRuntimeRegistrationValue,createRegistrationValidationError,extractRegistrationValidationTrace,isExtensionServiceName,isOutputRendererFormat,normalizeRegistrationName,normalizeRegistrationRecord,normalizeRegistrationRecordList,normalizeRuntimeRegistrationRecord,sanitizeRegistrationValue,toRegistrationCommandPath,validateAssuranceMeasurementProviderDefinition}from"./registration-values.js";import{normalizeServiceOverrideOwnership}from"./service-ownership.js";import{compareComparableVersions,evaluatePmMaxVersionBound,evaluatePmMinVersionBound,parseComparableVersion}from"./version-compat.js";import{parseLegacyExtensionCapabilityAliasWarning,parseUnknownExtensionCapabilityWarning}from"./extension-capability-aliases.js";import{createEmptyExtensionCommandRegistry as createEmptyExtensionCommandRegistry2,createEmptyExtensionHookRegistry as createEmptyExtensionHookRegistry2,createEmptyExtensionParserRegistry as createEmptyExtensionParserRegistry2,createEmptyExtensionPreflightRegistry as createEmptyExtensionPreflightRegistry2,createEmptyExtensionRegistrationRegistry as createEmptyExtensionRegistrationRegistry2,createEmptyExtensionRendererRegistry as createEmptyExtensionRendererRegistry2,createEmptyExtensionServiceRegistry as createEmptyExtensionServiceRegistry2}from"./extension-registries.js";import{runAfterCommandHooks,runBeforeCommandHooks,runBeforeMutationHooks,runCommandHandler,runCommandOverride,runOnIndexHooks,runOnReadHooks,runOnWriteHooks,runParserOverride,runPreflightOverride,runRendererOverride,runServiceOverride,runServiceOverrideSync}from"./extension-hook-runtime.js";export*from"./extension-types.js";import{DEFAULT_EXTENSION_PRIORITY,parseExtensionManifestDocument as parseExtensionManifestDocument2}from"./manifest-parser.js";let currentPmCliVersionPromise=null;const DEFAULT_EXTENSION_POLICY=Object.freeze(createDefaultExtensionGovernancePolicy());let extensionReloadEpoch=0;function nextExtensionReloadToken(seed=Date.now()){return extensionReloadEpoch+=1,`${extensionReloadEpoch}-${seed}`}function shouldEnable(name,enabled,disabled){return disabled.has(name)?!1:enabled.size===0?!0:enabled.has(name)}async function isCanonicalPathWithinDirectory(directory,targetPath){const[resolvedDirectory,resolvedTargetPath]=await Promise.all([fs.realpath(directory),fs.realpath(targetPath)]);return isPathWithinDirectory(resolvedDirectory,resolvedTargetPath)}function resolveExtensionRoots(pmRoot,cwd=process.cwd()){return{global:path.join(resolveGlobalPmRoot(cwd),"extensions"),project:path.join(pmRoot,"extensions")}}async function listExtensionDirectories(extensionsRoot){try{return(await fs.readdir(extensionsRoot,{withFileTypes:!0})).filter(entry=>entry.isDirectory()).map(entry=>entry.name).sort((a,b)=>a.localeCompare(b))}catch{return[]}}function summarizeCandidate(candidate){const summary={layer:candidate.layer,directory:candidate.directory,manifest_path:candidate.manifest_path,name:candidate.manifest.name,version:candidate.manifest.version,entry:candidate.manifest.entry,priority:candidate.manifest.priority,entry_path:candidate.entry_path,manifest_version:candidate.manifest.manifest_version,pm_min_version:candidate.manifest.pm_min_version,pm_max_version:candidate.manifest.pm_max_version,engines:candidate.manifest.engines,trusted:candidate.manifest.trusted,provenance:candidate.manifest.provenance,sandbox_profile:candidate.manifest.sandbox_profile,permissions:candidate.manifest.permissions,capabilities:[...candidate.manifest.capabilities],activation:candidate.manifest.activation?{commands:[...candidate.manifest.activation.commands]}:void 0,contributions:candidate.manifest.contributions??candidate.contributions};return candidate.source_package&&(summary.source_package=candidate.source_package),candidate.source_aliases&&(summary.source_aliases=[...candidate.source_aliases]),summary}function normalizeManagedSourcePackage(value){return typeof value=="string"&&value.trim().length>0?value.trim():void 0}async function readManagedExtensionSourcePackages(extensionsRoot){const packages=new Map;try{const parsed=JSON.parse(await fs.readFile(path.join(extensionsRoot,".managed-extensions.json"),"utf8")),entries=asRecordLoose(parsed)?.entries;if(!Array.isArray(entries))return packages;for(const entry of entries){if(typeof entry!="object"||entry===null)continue;const record=entry,sourcePackage=normalizeManagedSourcePackage(record.source?.package),aliases=[record.source?.input,record.source?.name,sourcePackage].map(value=>normalizeManagedSourcePackage(value)).filter(value=>value!==void 0),contributions=normalizeExtensionContributionInventory(record.contributions),identity={aliases:[...new Set(aliases)],...sourcePackage?{package_name:sourcePackage}:{},...contributions?{contributions}:{}};typeof record.directory=="string"&&record.directory.trim().length>0&&packages.set(`directory:${record.directory.trim()}`,identity),typeof record.name=="string"&&record.name.trim().length>0&&packages.set(`name:${record.name.trim()}`,identity)}}catch{return packages}return packages}function sortCandidates(candidates){return[...candidates].sort((left,right)=>{if(left.manifest.priority!==right.manifest.priority)return left.manifest.priority-right.manifest.priority;const byName=left.manifest.name.localeCompare(right.manifest.name);return byName!==0?byName:left.directory.localeCompare(right.directory)})}function buildEffectiveExtensions(globalCandidates,projectCandidates){const ordered=[...sortCandidates(globalCandidates),...sortCandidates(projectCandidates)],effective=[];for(const candidate of ordered){const existingIndex=effective.findIndex(entry=>entry.manifest.name===candidate.manifest.name);existingIndex>=0&&effective.splice(existingIndex,1),effective.push(candidate)}return effective}async function scanExtensionLayer(layer,extensionsRoot,enabled,disabled,pmMaxVersionExceededMode){const diagnostics=[],warnings=[],candidates=[],directories=await listExtensionDirectories(extensionsRoot),managedSourcePackages=await readManagedExtensionSourcePackages(extensionsRoot);for(const directory of directories){const scanned=await scanExtensionDirectory(layer,extensionsRoot,directory,enabled,disabled,managedSourcePackages,pmMaxVersionExceededMode);diagnostics.push(scanned.diagnostic),warnings.push(...scanned.warnings),scanned.candidate&&candidates.push(scanned.candidate)}return{diagnostics,warnings,candidates}}function emptyExtensionLayerScan(){return{diagnostics:[],warnings:[],candidates:[]}}function buildUnavailableExtensionScan(layer,directory,manifestPath,warning){return{diagnostic:{layer,directory,manifest_path:manifestPath,name:null,version:null,entry:null,priority:null,entry_path:null,enabled:null,status:"warn"},warnings:[warning],candidate:null}}function collectScannedExtensionWarnings(layer,manifest,rawManifest,entryWithinDirectory,entryExists,pmVersionCompatibility,pmMaxVersionCompatibility,enabledForLoad){const extensionWarnings=formatExtensionManifestSchemaWarnings(layer,manifest,rawManifest);Array.isArray(manifest.legacy_capability_aliases)&&manifest.legacy_capability_aliases.length>0&&extensionWarnings.push(formatLegacyExtensionCapabilityAliasWarning(layer,manifest.name,manifest.legacy_capability_aliases));for(const capability of collectUnknownExtensionCapabilities(manifest.capabilities))extensionWarnings.push(formatUnknownExtensionCapabilityWarning(layer,manifest.name,capability));return entryWithinDirectory?entryExists||extensionWarnings.push(`extension_entry_missing:${layer}:${manifest.name}`):extensionWarnings.push(`extension_entry_outside_extension:${layer}:${manifest.name}`),pmVersionCompatibility.warning&&extensionWarnings.push(enabledForLoad?pmVersionCompatibility.warning:pmVersionCompatibility.warning.replace("extension_pm_","extension_disabled_pm_")),pmMaxVersionCompatibility.warning&&extensionWarnings.push(enabledForLoad?pmMaxVersionCompatibility.warning:pmMaxVersionCompatibility.warning.replace("extension_pm_","extension_disabled_pm_")),extensionWarnings}async function scanExtensionDirectory(layer,extensionsRoot,directory,enabled,disabled,managedSourcePackages,pmMaxVersionExceededMode){const extensionDir=path.join(extensionsRoot,directory),manifestPath=path.join(extensionDir,"manifest.json");if(!await pathExists(manifestPath))return buildUnavailableExtensionScan(layer,directory,manifestPath,`extension_manifest_missing:${layer}:${directory}`);let manifest,rawManifest;try{const parsed=JSON.parse(await fs.readFile(manifestPath,"utf8"));rawManifest=asRecordLoose(parsed),manifest=parseExtensionManifestDocument(parsed)}catch{rawManifest=null,manifest=null}if(!manifest||!rawManifest)return buildUnavailableExtensionScan(layer,directory,manifestPath,`extension_manifest_invalid:${layer}:${directory}`);const entryPath=path.resolve(extensionDir,manifest.entry),entryWithinDirectoryByPath=isPathWithinDirectory(extensionDir,entryPath),entryExists=entryWithinDirectoryByPath?await pathExists(entryPath):!1,entryWithinDirectory=entryWithinDirectoryByPath&&entryExists?await isCanonicalPathWithinDirectory(extensionDir,entryPath):entryWithinDirectoryByPath,enabledForLoad=shouldEnable(manifest.name,enabled,disabled),pmVersionCompatibility=await evaluatePmMinVersionCompatibility(layer,manifest),pmMaxVersionCompatibility=await evaluatePmMaxVersionCompatibility(layer,manifest,pmMaxVersionExceededMode),extensionWarnings=collectScannedExtensionWarnings(layer,manifest,rawManifest,entryWithinDirectory,entryExists,pmVersionCompatibility,pmMaxVersionCompatibility,enabledForLoad),extensionReady=entryWithinDirectory&&entryExists&&pmVersionCompatibility.allowed&&pmMaxVersionCompatibility.allowed,sourceIdentity=managedSourcePackages.get(`directory:${directory}`)??managedSourcePackages.get(`name:${manifest.name}`);return{diagnostic:{layer,directory,manifest_path:manifestPath,name:manifest.name,version:manifest.version,entry:manifest.entry,priority:manifest.priority,entry_path:entryPath,enabled:enabledForLoad,status:extensionReady?"ok":"warn"},warnings:extensionWarnings,candidate:buildReadyExtensionCandidate({layer,directory,manifestPath,entryPath,manifest,sourceIdentity,extensionReady,enabledForLoad})}}async function discoverExtensions(options){const roots=resolveExtensionRoots(options.pmRoot,options.cwd??process.cwd()),configured_enabled=normalizeNames(options.settings.extensions.enabled),configured_disabled=normalizeNames(options.settings.extensions.disabled),policy=normalizeExtensionPolicy(options.settings),serializedPolicy=serializeExtensionPolicy(policy);if(options.noExtensions)return{disabled_by_flag:!0,roots,configured_enabled,configured_disabled,discovered:[],effective:[],warnings:[...policy.warnings],policy:serializedPolicy};const enabled=new Set(configured_enabled),disabled=new Set(configured_disabled),globalScan=options.ignoreGlobalExtensions===!0?emptyExtensionLayerScan():await scanExtensionLayer("global",roots.global,enabled,disabled,policy.pmMaxVersionExceededMode.global),projectScan=await scanExtensionLayer("project",roots.project,enabled,disabled,policy.pmMaxVersionExceededMode.project),policyWarnings=[...policy.warnings],effectiveCandidates=buildEffectiveExtensions(globalScan.candidates,projectScan.candidates),effective=[];for(const candidate of effectiveCandidates){const extensionRef={layer:candidate.layer,name:candidate.manifest.name,trusted:candidate.manifest.trusted===!0,provenanceVerified:candidate.manifest.provenance?.verified===!0,sandboxProfile:candidate.manifest.sandbox_profile,permissions:candidate.manifest.permissions&&typeof candidate.manifest.permissions=="object"?{fs_read:candidate.manifest.permissions.fs_read,fs_write:candidate.manifest.permissions.fs_write,network:candidate.manifest.permissions.network,env_read:candidate.manifest.permissions.env_read,env_write:candidate.manifest.permissions.env_write,process_spawn:candidate.manifest.permissions.process_spawn}:void 0},extensionDecision=evaluateExtensionPolicyForExtension(policy,extensionRef);if(extensionDecision.warning&&policyWarnings.push(extensionDecision.warning),!!extensionDecision.allowed){for(const capability of candidate.manifest.capabilities){const capabilityDecision=evaluateExtensionPolicyForCapability(policy,extensionRef,capability);capabilityDecision.warning&&policyWarnings.push(capabilityDecision.warning)}effective.push(summarizeCandidate(candidate))}}return{disabled_by_flag:!1,roots,configured_enabled,configured_disabled,discovered:[...globalScan.diagnostics,...projectScan.diagnostics],effective,warnings:[...new Set([...globalScan.warnings,...projectScan.warnings,...policyWarnings])],policy:serializedPolicy}}function formatUnknownError(error){return error instanceof Error&&error.message.trim().length>0?error.message:String(error)}async function readCurrentPmCliVersion(){try{const packageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]),raw=await fs.readFile(path.join(packageRoot,"package.json"),"utf8"),parsed=JSON.parse(raw);return typeof parsed.version=="string"&&parsed.version.trim().length>0?parsed.version.trim():null}catch{return null}}function resolveCurrentPmCliVersion(){return currentPmCliVersionPromise??=readCurrentPmCliVersion(),currentPmCliVersionPromise}function formatPmVersionCompatibilityWarning(layer,manifest,evaluation){const current=evaluation.current??"unknown";if(evaluation.kind==="pm_min_version")switch(evaluation.status){case"invalid":return`extension_pm_min_version_invalid:${layer}:${manifest.name}:required=${evaluation.required}`;case"unchecked":return`extension_pm_min_version_unchecked:${layer}:${manifest.name}:required=${evaluation.required}:current=${current}`;case"unmet":return`extension_pm_min_version_unmet:${layer}:${manifest.name}:required=${evaluation.required}:current=${current}`;default:return}switch(evaluation.status){case"invalid":return`extension_pm_max_version_invalid:${layer}:${manifest.name}:allowed=${evaluation.required}`;case"unchecked":return`extension_pm_max_version_unchecked:${layer}:${manifest.name}:allowed=${evaluation.required}:current=${current}`;case"exceeded_warn":return`extension_pm_max_version_exceeded_warn:${layer}:${manifest.name}:allowed=${evaluation.required}:current=${current}`;case"exceeded":return`extension_pm_max_version_exceeded:${layer}:${manifest.name}:allowed=${evaluation.required}:current=${current}`;default:return}}async function evaluatePmMinVersionCompatibility(layer,manifest){if(manifest.pm_min_version===void 0)return{allowed:!0};const evaluation=evaluatePmMinVersionBound(manifest.pm_min_version,await resolveCurrentPmCliVersion()),warning=formatPmVersionCompatibilityWarning(layer,manifest,evaluation);return warning?{allowed:evaluation.allowed,warning}:{allowed:evaluation.allowed}}async function evaluatePmMaxVersionCompatibility(layer,manifest,exceededMode){if(manifest.pm_max_version===void 0)return{allowed:!0};const evaluation=evaluatePmMaxVersionBound(manifest.pm_max_version,await resolveCurrentPmCliVersion(),exceededMode),warning=formatPmVersionCompatibilityWarning(layer,manifest,evaluation);return warning?{allowed:evaluation.allowed,warning}:{allowed:evaluation.allowed}}async function fingerprintPath(pathToInspect){try{const stats=await fs.stat(pathToInspect);return`${Math.trunc(stats.mtimeMs)}-${stats.size}`}catch{return"missing"}}async function resolveExtensionImportHref(extension,options){let importEntryPath=extension.entry_path;options.module_graph_snapshot_root&&(importEntryPath=await snapshotExtensionModuleGraph(options.module_graph_snapshot_root,extension));const baseUrl=new URL(pathToFileURL(importEntryPath).href);if(!(options.cache_bust===!0||typeof options.reload_token=="string"))return baseUrl.href;const[entryFingerprint,manifestFingerprint]=await Promise.all([fingerprintPath(extension.entry_path),fingerprintPath(extension.manifest_path)]),reloadToken=options.reload_token??nextExtensionReloadToken();return baseUrl.searchParams.set("pm_ext_reload",reloadToken),baseUrl.searchParams.set("pm_ext_entry",entryFingerprint),baseUrl.searchParams.set("pm_ext_manifest",manifestFingerprint),baseUrl.href}async function loadExtensions(options){const discovery=await discoverExtensions(options),loaded=[],failed=[],warnings=[...discovery.warnings];if(discovery.disabled_by_flag)return{...discovery,warnings,loaded,failed};const extensionsToLoad=typeof options.extensionFilter=="function"?discovery.effective.filter(options.extensionFilter):discovery.effective;for(const extension of extensionsToLoad)try{const module=await import(await resolveExtensionImportHref(extension,options));loaded.push({...extension,module})}catch(error){warnings.push(`extension_load_failed:${extension.layer}:${extension.name}`),failed.push({layer:extension.layer,name:extension.name,entry_path:extension.entry_path,error:formatUnknownError(error)})}return{...discovery,warnings,loaded,failed}}const DEFAULT_EXTENSION_DEACTIVATE_TIMEOUT_MS=5e3,MAX_EXTENSION_DEACTIVATE_TIMEOUT_MS=2147483647;function toActivatableExtension(source){const activatable={activate:source.activate.bind(source)};if(typeof source.deactivate=="function"){const deactivate=source.deactivate;activatable.deactivate=deactivate.bind(source)}return activatable}function resolveActivatableExtension(module){const activatableRecord=resolveActivatablePropertyRecord(module);return activatableRecord?toActivatableExtension(activatableRecord):null}async function deactivateExtensions(loadResult,activationResult,options={}){const timeoutMs=normalizeExtensionDeactivateTimeout(options?.deactivate_timeout_ms),failedActivationKeys=new Set((activationResult?.failed??[]).map(entry=>`${entry.layer}:${entry.name}`)),targets=[];for(const extension of loadResult.loaded){if(failedActivationKeys.has(`${extension.layer}:${extension.name}`))continue;const activatable=resolveActivatableExtension(extension.module);!activatable||typeof activatable.deactivate!="function"||targets.push({extension,deactivate:activatable.deactivate})}const outcomes=await Promise.all(targets.map(async({extension,deactivate})=>{try{return await runExtensionDeactivateWithTimeout(deactivate,timeoutMs),{ok:!0}}catch(error){return{ok:!1,layer:extension.layer,name:extension.name,error:formatUnknownError(error)}}})),warnings=[],failed=[];let deactivated=0;for(const outcome of outcomes){if(outcome.ok){deactivated+=1;continue}warnings.push(`extension_deactivate_failed:${outcome.layer}:${outcome.name}`),failed.push({layer:outcome.layer,name:outcome.name,error:outcome.error})}return{deactivated,warnings,failed}}function normalizeExtensionDeactivateTimeout(rawTimeout){return typeof rawTimeout!="number"||rawTimeout<0?DEFAULT_EXTENSION_DEACTIVATE_TIMEOUT_MS:rawTimeout===0||rawTimeout===1/0?0:Number.isFinite(rawTimeout)?Math.min(MAX_EXTENSION_DEACTIVATE_TIMEOUT_MS,Math.max(1,Math.floor(rawTimeout))):DEFAULT_EXTENSION_DEACTIVATE_TIMEOUT_MS}async function runExtensionDeactivateWithTimeout(deactivate,timeoutMs){if(timeoutMs===0){await deactivate();return}let timeoutHandle;try{const deactivatePromise=Promise.resolve().then(()=>deactivate());deactivatePromise.catch(()=>{}),await Promise.race([deactivatePromise,new Promise((_,reject)=>{timeoutHandle=setTimeout(()=>{reject(new Error(`extension deactivate timed out after ${timeoutMs}ms`))},timeoutMs),timeoutHandle.unref?.()})])}finally{clearTimeout(timeoutHandle)}}function getDeclaredExtensionCapabilities(extension){if(!Array.isArray(extension.capabilities))return null;const declared=new Set;for(const capability of extension.capabilities){const normalized=capability.trim().toLowerCase();isKnownExtensionCapability(normalized)&&declared.add(normalized)}return declared}function assertExtensionCapability(extension,capability,method){const declared=getDeclaredExtensionCapabilities(extension);if(declared!==null&&!declared.has(capability))throw createRegistrationValidationError(`${method} requires capability '${capability}' in extension manifest capabilities`,{method,registration_index:-1,capability,missing_capability:capability,expected_schema:`"capabilities": [..., "${capability}"]`,received:extension.capabilities,hint:`Add "${capability}" to ${extension.name} manifest capabilities, or remove the ${method} registration call.`})}function buildExtensionSelfIdentity(extension){return Object.freeze({name:extension.name,layer:extension.layer,version:extension.version,capabilities:Object.freeze((extension.capabilities??[]).filter(capability=>KNOWN_EXTENSION_CAPABILITIES.includes(capability))),pm_min_version:extension.pm_min_version,pm_max_version:extension.pm_max_version,source_package:extension.source_package})}function buildPolicyExtensionRef(extension){return{layer:extension.layer,name:extension.name,trusted:extension.trusted===!0,provenanceVerified:extension.provenance?.verified===!0,sandboxProfile:extension.sandbox_profile,permissions:extension.permissions&&typeof extension.permissions=="object"?{fs_read:extension.permissions.fs_read,fs_write:extension.permissions.fs_write,network:extension.permissions.network,env_read:extension.permissions.env_read,env_write:extension.permissions.env_write,process_spawn:extension.permissions.process_spawn}:void 0}}class ExtensionApiRegistrar{extension;hooks;#loadedExtension;#extensionRef;#hookRegistry;#commandRegistry;#parserRegistry;#preflightRegistry;#serviceRegistry;#rendererRegistry;#registrationRegistry;#activationWarnings;#activationFailures;#policy;constructor(extension,hooks,commands,parsers,preflight,services,renderers,registrations,activationWarnings,activationFailures,policy){this.#loadedExtension=extension,this.extension=buildExtensionSelfIdentity(extension),this.#extensionRef=buildPolicyExtensionRef(extension),this.#hookRegistry=hooks,this.#commandRegistry=commands,this.#parserRegistry=parsers,this.#preflightRegistry=preflight,this.#serviceRegistry=services,this.#rendererRegistry=renderers,this.#registrationRegistry=registrations,this.#activationWarnings=activationWarnings,this.#activationFailures=activationFailures,this.#policy=policy,this.registerCommand=this.registerCommand.bind(this),this.registerParser=this.registerParser.bind(this),this.registerPreflight=this.registerPreflight.bind(this),this.registerService=this.registerService.bind(this),this.registerFlags=this.registerFlags.bind(this),this.registerItemFields=this.registerItemFields.bind(this),this.registerItemTypes=this.registerItemTypes.bind(this),this.registerRelationshipKinds=this.registerRelationshipKinds.bind(this),this.registerMigration=this.registerMigration.bind(this),this.registerProfile=this.registerProfile.bind(this),this.registerRenderer=this.registerRenderer.bind(this),this.registerImporter=this.registerImporter.bind(this),this.registerExporter=this.registerExporter.bind(this),this.registerSearchProvider=this.registerSearchProvider.bind(this),this.registerVectorStoreAdapter=this.registerVectorStoreAdapter.bind(this),this.registerAssuranceMeasurementProvider=this.registerAssuranceMeasurementProvider.bind(this),this.hooks={beforeCommand:hook=>this.registerBeforeCommand(hook),beforeMutation:hook=>this.registerBeforeMutation(hook),afterCommand:hook=>this.registerAfterCommand(hook),onWrite:hook=>this.registerOnWrite(hook),onRead:hook=>this.registerOnRead(hook),onIndex:hook=>this.registerOnIndex(hook)}}allowRegistration(surface,method,capability,details){const decision=evaluateExtensionPolicyForRegistration(this.#policy,this.#extensionRef,surface,method,capability,details);return decision.warning&&this.#activationWarnings.push(decision.warning),decision.allowed}registerCommandTrace(mode,command,expectedSchema,received,hint){return{method:"registerCommand",registration_index:mode==="override"?this.#commandRegistry.overrides.length:this.#commandRegistry.handlers.length,command,expected_schema:expectedSchema,received:sanitizeRegistrationValue(received),hint}}registerCommandOverride(command,override){const normalizedCommand=normalizeCommandName(command);if(normalizedCommand.length===0)throw createRegistrationValidationError("registerCommand requires a non-empty command name",this.registerCommandTrace("override",command,'registerCommand("<command>", (context) => unknown)',command,"Provide a non-empty command path as the first argument."));if(typeof override!="function"){const trace=this.registerCommandTrace("override",normalizedCommand,'registerCommand("<command>", (context) => unknown)',override,"Provide a function as the second registerCommand argument.");throw createRegistrationValidationError(`registerCommand requires an override function when command name is provided (command="${normalizedCommand}", registration_index=${trace.registration_index})`,trace)}this.allowRegistration("commands.override","registerCommand","commands",{command:normalizedCommand})&&this.#commandRegistry.overrides.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,command:normalizedCommand,run:override})}resolveCommandDefinitionRunHandler(definition,normalizedCommand){const runHandler=typeof definition.run=="function"?definition.run:void 0,legacyHandler=typeof definition.handler=="function"?definition.handler:void 0;return!runHandler&&legacyHandler&&this.#activationWarnings.push(`extension_command_definition_legacy_handler_alias:${this.#loadedExtension.layer}:${this.#loadedExtension.name}:${normalizedCommand}`),runHandler??legacyHandler}registerCommandDefinition(definition){if(typeof definition!="object"||definition===null)throw createRegistrationValidationError("registerCommand requires a command definition object",this.registerCommandTrace("definition",void 0,"{ name: string; run: (context) => unknown; }",definition,'Use registerCommand({ name: "command path", run: (context) => ... }).'));if(typeof definition.name!="string")throw createRegistrationValidationError("registerCommand requires a command definition name",this.registerCommandTrace("definition",void 0,"{ name: string; run: (context) => unknown; }",definition,"Set command definition.name to a non-empty string command path."));const normalizedCommand=normalizeCommandName(definition.name);if(normalizedCommand.length===0)throw createRegistrationValidationError("registerCommand requires a non-empty command definition name",this.registerCommandTrace("definition",definition.name,"{ name: string; run: (context) => unknown; }",definition,"Ensure command definition.name contains a non-empty command path."));const resolvedHandler=this.resolveCommandDefinitionRunHandler(definition,normalizedCommand);if(typeof resolvedHandler!="function"){const trace=this.registerCommandTrace("definition",normalizedCommand,"{ name: string; run: (context) => unknown; }",resolvedHandler,"Define command definition.run as a function.");throw createRegistrationValidationError(`registerCommand requires a command definition run handler (command="${normalizedCommand}", registration_index=${trace.registration_index})`,trace)}try{assertCommandDefinitionMetadataStrings(definition);const action=resolveCommandDefinitionAction(normalizedCommand,definition.action),readOutput=normalizeExtensionReadOutput(definition.read_output,normalizedCommand,action);if(!this.allowRegistration("commands.handler","registerCommand","commands",{command:normalizedCommand,action}))return;const description=definition.description?.trim(),intent=definition.intent?.trim(),examples=normalizeOptionalStringArrayField("registerCommand definition.examples",definition.examples),failureHints=normalizeOptionalStringArrayField("registerCommand definition.failure_hints",definition.failure_hints),argumentsDefinition=normalizeCommandDefinitionArguments(definition.arguments);definition.flags!==void 0&&(assertExtensionCapability(this.#loadedExtension,"schema","registerCommand flags"),this.allowRegistration("schema.flags","registerCommand flags","schema")&&(validateFlagDefinitions(definition.flags),this.#registrationRegistry.flags.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,target_command:normalizedCommand,flags:normalizeFlagDefinitions("registerCommand definition.flags",definition.flags)})));const registration={read_output:readOutput,layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,source_package:this.#loadedExtension.source_package,command:normalizedCommand,action,examples,failure_hints:failureHints,arguments:argumentsDefinition,tier:definition.tier??"standard",family:definition.family??"extensions"};description&&(registration.description=description),intent&&(registration.intent=intent),this.#registrationRegistry.commands.push(registration)}catch(error){const reason=formatUnknownError(error),trace=this.registerCommandTrace("definition",normalizedCommand,"{ name: string; run: (context) => unknown; action?: string; arguments?: object[]; flags?: object[]; }",definition,reason),validationError=createRegistrationValidationError(`registerCommand definition metadata invalid (command="${normalizedCommand}", registration_index=${trace.registration_index}): ${reason}`,trace);this.#activationWarnings.push(`extension_command_quarantined:${this.#loadedExtension.layer}:${this.#loadedExtension.name}:${normalizedCommand}`),this.#activationFailures.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,entry_path:this.#loadedExtension.entry_path,error:validationError.message,trace});return}this.#commandRegistry.handlers.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,command:normalizedCommand,run:resolvedHandler})}registerCommand(commandOrDefinition,override){if(assertExtensionCapability(this.#loadedExtension,"commands","registerCommand"),typeof commandOrDefinition=="string"){this.registerCommandOverride(commandOrDefinition,override);return}this.registerCommandDefinition(commandOrDefinition)}registerParser(command,override){if(assertExtensionCapability(this.#loadedExtension,"parser","registerParser"),!this.allowRegistration("parser.override","registerParser","parser"))return;const normalizedCommand=normalizeCommandName(assertNonEmptyRegistrationString("registerParser command",command));assertRegistrationFunction("registerParser override",override),this.#parserRegistry.overrides.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,command:normalizedCommand,run:override})}registerPreflight(override){if(assertExtensionCapability(this.#loadedExtension,"preflight","registerPreflight"),!this.allowRegistration("preflight.override","registerPreflight","preflight"))return;const normalized=normalizePreflightOverride(override);this.#preflightRegistry.overrides.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,...normalized})}registerService(service,override,ownership={}){assertExtensionCapability(this.#loadedExtension,"services","registerService");const normalizedService=String(service).trim().toLowerCase();if(!isExtensionServiceName(normalizedService))throw new TypeError(`registerService service must be one of: ${KNOWN_EXTENSION_SERVICE_NAMES.join(", ")}`);this.allowRegistration("services.override","registerService","services",{service:normalizedService})&&(assertRegistrationFunction("registerService override",override),this.#serviceRegistry.overrides.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,service:normalizedService,run:override,...normalizeServiceOverrideOwnership(ownership)?{passThrough:!0}:{}}))}registerRenderer(format,renderer,ownership={}){if(assertExtensionCapability(this.#loadedExtension,"renderers","registerRenderer"),!this.allowRegistration("renderers.override","registerRenderer","renderers"))return;if(typeof renderer!="function")throw new TypeError("registerRenderer requires a renderer function");const normalizedFormat=String(format).trim().toLowerCase();if(!isOutputRendererFormat(normalizedFormat))throw new Error(`registerRenderer format must be toon|json, received: ${String(format)}`);if(ownership.resultDiscriminator!==void 0&&typeof ownership.resultDiscriminator!="function")throw new TypeError("registerRenderer ownership.resultDiscriminator must be a function when provided");const commands=[...new Set((ownership.commands??[]).map(command=>{if(typeof command!="string"||command.trim().length===0)throw new TypeError("registerRenderer ownership.commands must contain non-empty command paths");return normalizeCommandName(command)}))];this.#rendererRegistry.overrides.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,format:normalizedFormat,run:renderer,commands,...ownership.resultDiscriminator?{resultDiscriminator:ownership.resultDiscriminator}:{}})}registerFlags(targetCommand,flags){if(assertExtensionCapability(this.#loadedExtension,"schema","registerFlags"),!this.allowRegistration("schema.flags","registerFlags","schema"))return;const normalizedTargetCommand=normalizeCommandName(assertNonEmptyRegistrationString("registerFlags targetCommand",targetCommand));validateFlagDefinitions(flags);const normalizedFlags=normalizeFlagDefinitions("registerFlags flags",flags);if(normalizedFlags.length===0)throw new TypeError("registerFlags requires at least one flag definition");this.#registrationRegistry.flags.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,target_command:normalizedTargetCommand,flags:normalizedFlags})}registerItemFields(fields){if(assertExtensionCapability(this.#loadedExtension,"schema","registerItemFields"),!this.allowRegistration("schema.itemfields","registerItemFields","schema"))return;validateItemFieldDefinitions(fields);const normalizedFields=normalizeRegistrationRecordList("registerItemFields fields",fields);if(normalizedFields.length===0)throw new TypeError("registerItemFields requires at least one field definition");this.#registrationRegistry.item_fields.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,fields:normalizedFields})}registerItemTypes(types){if(assertExtensionCapability(this.#loadedExtension,"schema","registerItemTypes"),!this.allowRegistration("schema.itemtypes","registerItemTypes","schema"))return;validateItemTypeDefinitions(types);const normalizedTypes=normalizeRegistrationRecordList("registerItemTypes types",types);if(normalizedTypes.length===0)throw new TypeError("registerItemTypes requires at least one type definition");this.#registrationRegistry.item_types.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,types:normalizedTypes})}registerRelationshipKinds(definitions){if(assertExtensionCapability(this.#loadedExtension,"schema","registerRelationshipKinds"),!this.allowRegistration("schema.relationshipkinds","registerRelationshipKinds","schema"))return;if(!Array.isArray(definitions))throw new TypeError("registerRelationshipKinds definitions requires an array of object definitions");if(definitions.length===0)throw new TypeError("registerRelationshipKinds requires at least one definition");const registry=createRelationshipKindRegistry();for(const registration of this.#registrationRegistry.relationship_kinds)for(const definition of registration.definitions)registry.register(definition);const validated=definitions.map(definition=>(registry.register(definition),registry.require(definition.kind)));this.#registrationRegistry.relationship_kinds.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,definitions:validated})}registerMigration(definition){if(assertExtensionCapability(this.#loadedExtension,"schema","registerMigration"),!this.allowRegistration("schema.migrations","registerMigration","schema"))return;validateMigrationDefinition(definition);const runtimeDefinition=normalizeRuntimeRegistrationRecord("registerMigration definition",definition);this.#registrationRegistry.migrations.push(attachRuntimeDefinition({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,definition:normalizeRegistrationRecord("registerMigration definition",definition)},runtimeDefinition))}registerProfile(profile){if(assertExtensionCapability(this.#loadedExtension,"schema","registerProfile"),!this.allowRegistration("schema.profiles","registerProfile","schema"))return;const snapshot=cloneRuntimeRegistrationValue(profile);validateProjectProfileDefinition(snapshot),this.#registrationRegistry.profiles.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,profile:applyProjectProfileDefaults(snapshot)})}registerImportExportCommandFlags(method,commandPath,resolvedOptions){resolvedOptions.flags!==void 0&&(assertExtensionCapability(this.#loadedExtension,"schema",`${method} options.flags`),this.allowRegistration("schema.flags",`${method} options.flags`,"schema")&&(validateFlagDefinitions(resolvedOptions.flags),this.#registrationRegistry.flags.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,target_command:commandPath,flags:normalizeFlagDefinitions(`${method} options.flags`,resolvedOptions.flags)})))}applyImportExportCommandMetadata(method,commandPath,options){if(options!==void 0&&(typeof options!="object"||options===null||Array.isArray(options)))throw new TypeError(`${method} options must be an object when provided`);const defaultDescription=`${method==="registerImporter"?"Import":"Export"} items with the registered extension adapter.`,defaultArguments=[{name:"file",required:!1,description:"Optional input or output file path."}],resolvedOptions={...options,description:options?.description??defaultDescription,arguments:options?.arguments??defaultArguments},output=resolveImportExportArtifactOutput(method,resolvedOptions,options?.description!==void 0);assertOptionalStringField(`${method} options.action`,resolvedOptions.action),assertOptionalStringField(`${method} options.description`,resolvedOptions.description),assertOptionalStringField(`${method} options.intent`,resolvedOptions.intent);const action=resolveCommandDefinitionAction(commandPath,resolvedOptions.action),examples=normalizeOptionalStringArrayField(`${method} options.examples`,resolvedOptions.examples),failureHints=normalizeOptionalStringArrayField(`${method} options.failure_hints`,resolvedOptions.failure_hints),argumentsDefinition=normalizeCommandDefinitionArguments(resolvedOptions.arguments);this.registerImportExportCommandFlags(method,commandPath,resolvedOptions);const registration={layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,source_package:this.#loadedExtension.source_package,command:commandPath,action,examples,failure_hints:failureHints,arguments:argumentsDefinition},description=resolvedOptions.description?.trim();description&&(registration.description=description);const intent=resolvedOptions.intent?.trim();return intent&&(registration.intent=intent),this.#registrationRegistry.commands.push(registration),output}registerImporter(name,importer,options){if(assertExtensionCapability(this.#loadedExtension,"importers","registerImporter"),!this.allowRegistration("importers.importer","registerImporter","importers"))return;const normalizedName=normalizeRegistrationName(assertNonEmptyRegistrationString("registerImporter name",name));assertRegistrationFunction("registerImporter importer",importer);const commandPath=toRegistrationCommandPath(normalizedName,"import");this.applyImportExportCommandMetadata("registerImporter",commandPath,options),this.#registrationRegistry.importers.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,importer:normalizedName}),this.#commandRegistry.handlers.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,command:commandPath,run:async context=>importer(buildImportExportContext(context,normalizedName,"import"))})}registerExporter(name,exporter,options){if(assertExtensionCapability(this.#loadedExtension,"importers","registerExporter"),!this.allowRegistration("importers.exporter","registerExporter","importers"))return;const normalizedName=normalizeRegistrationName(assertNonEmptyRegistrationString("registerExporter name",name));assertRegistrationFunction("registerExporter exporter",exporter);const commandPath=toRegistrationCommandPath(normalizedName,"export"),output=this.applyImportExportCommandMetadata("registerExporter",commandPath,options);this.#registrationRegistry.exporters.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,exporter:normalizedName,...output===void 0?{}:{output}}),this.#commandRegistry.handlers.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,command:commandPath,run:async context=>{const result=await exporter(buildImportExportContext(context,normalizedName,"export"));return output?.receipt==="suppress"&&!isHostOutputSuppressed(result)?suppressHostOutput(result):result}})}registerSearchProvider(provider){if(assertExtensionCapability(this.#loadedExtension,"search","registerSearchProvider"),!this.allowRegistration("search.provider","registerSearchProvider","search"))return;const runtimeDefinition=normalizeRuntimeRegistrationRecord("registerSearchProvider provider",provider);this.#registrationRegistry.search_providers.push(attachRuntimeDefinition({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,definition:normalizeRegistrationRecord("registerSearchProvider provider",provider)},runtimeDefinition))}registerVectorStoreAdapter(adapter){if(assertExtensionCapability(this.#loadedExtension,"search","registerVectorStoreAdapter"),!this.allowRegistration("search.vectorstore","registerVectorStoreAdapter","search"))return;const runtimeDefinition=normalizeRuntimeRegistrationRecord("registerVectorStoreAdapter adapter",adapter);this.#registrationRegistry.vector_store_adapters.push(attachRuntimeDefinition({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,definition:normalizeRegistrationRecord("registerVectorStoreAdapter adapter",adapter)},runtimeDefinition))}registerAssuranceMeasurementProvider(provider){if(assertExtensionCapability(this.#loadedExtension,"services","registerAssuranceMeasurementProvider"),!this.allowRegistration("services.assuranceprovider","registerAssuranceMeasurementProvider","services"))return;if(validateAssuranceMeasurementProviderDefinition(provider),provider.network&&this.#loadedExtension.permissions?.network!==!0)throw new TypeError("registerAssuranceMeasurementProvider network provider requires permissions.network=true");const runtimeDefinition=normalizeRuntimeRegistrationRecord("registerAssuranceMeasurementProvider provider",provider);this.#registrationRegistry.assurance_providers.push(attachRuntimeDefinition({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,network_permission:this.#loadedExtension.permissions?.network===!0,definition:normalizeRegistrationRecord("registerAssuranceMeasurementProvider provider",provider)},runtimeDefinition))}registerBeforeCommand(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.beforeCommand"),this.allowRegistration("hooks.beforecommand","api.hooks.beforeCommand","hooks")&&(assertHookHandler("beforeCommand",hook),this.#hookRegistry.beforeCommand.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,run:hook}))}registerBeforeMutation(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.beforeMutation"),this.allowRegistration("hooks.beforemutation","api.hooks.beforeMutation","hooks")&&(assertHookHandler("beforeMutation",hook),this.#hookRegistry.beforeMutation.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,run:hook}))}registerAfterCommand(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.afterCommand"),this.allowRegistration("hooks.aftercommand","api.hooks.afterCommand","hooks")&&(assertHookHandler("afterCommand",hook),this.#hookRegistry.afterCommand.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,run:hook}))}registerOnWrite(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.onWrite"),this.allowRegistration("hooks.onwrite","api.hooks.onWrite","hooks")&&(assertHookHandler("onWrite",hook),this.#hookRegistry.onWrite.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,run:hook}))}registerOnRead(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.onRead"),this.allowRegistration("hooks.onread","api.hooks.onRead","hooks")&&(assertHookHandler("onRead",hook),this.#hookRegistry.onRead.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,run:hook}))}registerOnIndex(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.onIndex"),this.allowRegistration("hooks.onindex","api.hooks.onIndex","hooks")&&(assertHookHandler("onIndex",hook),this.#hookRegistry.onIndex.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,run:hook}))}}function createExtensionApi(extension,hooks,commands,parsers,preflight,services,renderers,registrations,activationWarnings,activationFailures,policy){return new ExtensionApiRegistrar(extension,hooks,commands,parsers,preflight,services,renderers,registrations,activationWarnings,activationFailures,policy)}function getRegistrationCounts(registrations){const commandCount=registrations.commands.length,flagCount=registrations.flags.reduce((total,entry)=>total+entry.flags.length,0),itemFieldCount=registrations.item_fields.reduce((total,entry)=>total+entry.fields.length,0),itemTypeCount=registrations.item_types.reduce((total,entry)=>total+entry.types.length,0),relationshipKindCount=(registrations.relationship_kinds??[]).reduce((total,entry)=>total+entry.definitions.length,0);return{commands:commandCount,flags:flagCount,item_fields:itemFieldCount,item_types:itemTypeCount,...relationshipKindCount>0?{relationship_kinds:relationshipKindCount}:{},migrations:registrations.migrations.length,profiles:registrations.profiles.length,importers:registrations.importers.length,exporters:registrations.exporters.length,search_providers:registrations.search_providers.length,vector_store_adapters:registrations.vector_store_adapters.length,...(registrations.assurance_providers?.length??0)>0?{assurance_providers:registrations.assurance_providers.length}:{}}}function collectCommandCollisionWarnings(commands){const warnings=[],collectByCommand=(entries,codePrefix)=>{const grouped=new Map;for(const entry of entries){const bucket=grouped.get(entry.command)??[];bucket.push(entry),grouped.set(entry.command,bucket)}for(const command of[...grouped.keys()].sort((left,right)=>left.localeCompare(right))){const bucket=grouped.get(command);if(bucket.length<=1)continue;const winner=bucket[bucket.length-1];for(const displaced of bucket.slice(0,-1))warnings.push(`${codePrefix}:${command}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`)}};collectByCommand(commands.handlers,"extension_command_handler_collision"),collectByCommand(commands.overrides,"extension_command_override_collision");const handlerCommands=new Set(commands.handlers.map(entry=>entry.command)),overlapCommands=[...new Set(commands.overrides.map(entry=>entry.command))].filter(command=>handlerCommands.has(command));overlapCommands.sort((left,right)=>left.localeCompare(right));for(const command of overlapCommands){const handlers=commands.handlers.filter(entry=>entry.command===command),overrides=commands.overrides.filter(entry=>entry.command===command);for(const override of overrides)for(const handler of handlers)warnings.push(`extension_command_override_handler_overlap:${command}:${override.layer}:${override.name}:${handler.layer}:${handler.name}`)}return warnings}function collectRendererCollisionWarnings(renderers){const grouped=new Map;for(const entry of renderers.overrides){const bucket=grouped.get(entry.format)??[];bucket.push(entry),grouped.set(entry.format,bucket)}const warnings=[];for(const format of[...grouped.keys()].sort((left,right)=>left.localeCompare(right))){const bucket=grouped.get(format);if(bucket.length<=1)continue;const winner=bucket[bucket.length-1];for(const displaced of bucket.slice(0,-1))winner.commands?.length&&displaced.commands?.length&&!displaced.commands.some(command=>winner.commands?.includes(command))||warnings.push(`extension_renderer_collision:${format}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`)}return warnings}function collectParserCollisionWarnings(parsers){const warnings=[],grouped=new Map;for(const entry of parsers.overrides){const bucket=grouped.get(entry.command)??[];bucket.push(entry),grouped.set(entry.command,bucket)}for(const command of[...grouped.keys()].sort((left,right)=>left.localeCompare(right))){const bucket=grouped.get(command);if(bucket.length<=1)continue;const winner=bucket[bucket.length-1];for(const displaced of bucket.slice(0,-1))warnings.push(`extension_parser_override_collision:${command}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`)}return warnings}const CHAINED_SERVICE_NAMES=new Set(["output_format"]);function collectServiceCollisionWarnings(services){const warnings=[],grouped=new Map;for(const entry of services.overrides){const bucket=grouped.get(entry.service)??[];bucket.push(entry),grouped.set(entry.service,bucket)}for(const service of[...grouped.keys()].sort((left,right)=>left.localeCompare(right))){const bucket=grouped.get(service);if(bucket.length<=1||CHAINED_SERVICE_NAMES.has(service))continue;const winner=bucket[bucket.length-1];for(const displaced of bucket.slice(0,-1))warnings.push(`extension_service_override_collision:${service}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`)}return warnings}async function activateExtensions(loadResult){const policy=hydrateExtensionPolicy(loadResult.policy??DEFAULT_EXTENSION_POLICY),hooks=createEmptyExtensionHookRegistry(),commands=createEmptyExtensionCommandRegistry(),parsers=createEmptyExtensionParserRegistry(),preflight=createEmptyExtensionPreflightRegistry(),services=createEmptyExtensionServiceRegistry(),renderers=createEmptyExtensionRendererRegistry(),registrations=createEmptyExtensionRegistrationRegistry(),failed=[],warnings=[];for(const extension of loadResult.loaded){const activatable=resolveActivatableExtension(extension.module);if(!activatable)continue;const failedBeforeActivation=failed.length,rollbackPartialActivation=captureExtensionActivationRollback({hooks,commands,parsers,preflight,services,renderers,registrations});try{await activatable.activate(createExtensionApi(extension,hooks,commands,parsers,preflight,services,renderers,registrations,warnings,failed,policy)),failed.length>failedBeforeActivation&&(rollbackPartialActivation(),warnings.push(`extension_activation_rolled_back:${extension.layer}:${extension.name}`))}catch(error){rollbackPartialActivation(),warnings.push(`extension_activate_failed:${extension.layer}:${extension.name}`);const trace=extractRegistrationValidationTrace(error);failed.push({layer:extension.layer,name:extension.name,entry_path:extension.entry_path,error:formatUnknownError(error),trace})}}const collisionWarnings=[...collectCommandCollisionWarnings(commands),...collectParserCollisionWarnings(parsers),...collectPreflightCollisionWarnings(preflight),...collectServiceCollisionWarnings(services),...collectRendererCollisionWarnings(renderers)],mergedWarnings=[...new Set([...warnings,...collisionWarnings])];return{hooks,commands,parsers,preflight,services,renderers,registrations,failed,warnings:mergedWarnings,hook_counts:{before_command:hooks.beforeCommand.length,before_mutation:hooks.beforeMutation.length,after_command:hooks.afterCommand.length,on_write:hooks.onWrite.length,on_read:hooks.onRead.length,on_index:hooks.onIndex.length},command_override_count:commands.overrides.length,command_handler_count:commands.handlers.length,parser_override_count:parsers.overrides.length,preflight_override_count:preflight.overrides.length,service_override_count:services.overrides.length,renderer_override_count:renderers.overrides.length,registration_counts:getRegistrationCounts(registrations)}}const _testOnlyLoader={assertFlagValueTypeAndDefault,assertOptionalStringField,compareComparableVersions,collectCommandCollisionWarnings,collectParserCollisionWarnings,collectRendererCollisionWarnings,collectServiceCollisionWarnings,createExtensionApi,createRegistrationValidationError,evaluatePmMaxVersionCompatibility,evaluatePmMinVersionCompatibility,extractRegistrationValidationTrace,fingerprintPath,getRegistrationCounts,normalizeCommandDefinitionArguments,normalizeExtensionDeactivateTimeout,normalizeOptionalStringArrayField,normalizeRegistrationRecord,normalizeRegistrationRecordList,normalizeRuntimeRegistrationRecord,parseComparableVersion,parseManifest:parseExtensionManifestDocument,readCurrentPmCliVersion,readManagedExtensionSourcePackages:async extensionsRoot=>new Map([...await readManagedExtensionSourcePackages(extensionsRoot)].filter(entry=>typeof entry[1].package_name=="string").map(([key,identity])=>[key,identity.package_name])),resolveExtensionImportHref,resolveCurrentPmCliVersion,resolveCommandDefinitionAction,sanitizeRegistrationValue,validateItemFieldDefinitions,resetCurrentPmCliVersionCacheForTest:()=>{currentPmCliVersionPromise=null}};export{DEFAULT_EXTENSION_PRIORITY,_testOnlyLoader,activateExtensions,createEmptyExtensionCommandRegistry2 as createEmptyExtensionCommandRegistry,createEmptyExtensionHookRegistry2 as createEmptyExtensionHookRegistry,createEmptyExtensionParserRegistry2 as createEmptyExtensionParserRegistry,createEmptyExtensionPreflightRegistry2 as createEmptyExtensionPreflightRegistry,createEmptyExtensionRegistrationRegistry2 as createEmptyExtensionRegistrationRegistry,createEmptyExtensionRendererRegistry2 as createEmptyExtensionRendererRegistry,createEmptyExtensionServiceRegistry2 as createEmptyExtensionServiceRegistry,deactivateExtensions,discoverExtensions,isCanonicalPathWithinDirectory,loadExtensions,nextExtensionReloadToken,parseExtensionManifestDocument2 as parseExtensionManifestDocument,parseLegacyExtensionCapabilityAliasWarning,parseUnknownExtensionCapabilityWarning,resolveExtensionRoots,runAfterCommandHooks,runBeforeCommandHooks,runBeforeMutationHooks,runCommandHandler,runCommandOverride,runOnIndexHooks,runOnReadHooks,runOnWriteHooks,runParserOverride,runPreflightOverride,runRendererOverride,runServiceOverride,runServiceOverrideSync};
2
2
  //# sourceMappingURL=loader.js.map
@@ -0,0 +1,2 @@
1
+ /** Explain one version-bound finding without changing package enablement or compatibility policy. */
2
+ export declare function extensionVersionRemediation(warning:string):string | undefined;
@@ -0,0 +1,2 @@
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a8289336-e833-5617-9a32-0a21f28f294e")}catch{}})();import{renderPmCommand}from"../../sdk/command-line.js";function extensionVersionRemediation(warning){const match=/^extension_(disabled_)?pm_(min|max)_version_([a-z_]+):(project|global):([^:]+):(.+)$/u.exec(warning);if(!match)return;const[,disabled,bound,status,scope,name,details]=match,constraint=details.split(":")[0].replace(bound==="min"?"required=":"allowed=",""),requirement=status==="invalid"?`a valid pm_${bound}_version instead of ${constraint}`:`pm ${bound==="min"?">=":"<="} ${constraint}`;return disabled?`Package ${name} is disabled and requires ${requirement} before activation. After satisfying the bound, run ${renderPmCommand(["package","activate",name,`--${scope}`])}.`:`Package ${name} requires ${requirement}. Use a compatible host or package version, or keep it disabled with ${renderPmCommand(["package","deactivate",name,`--${scope}`])}.`}export{extensionVersionRemediation};
2
+ //# sourceMappingURL=version-diagnostics.js.map
@@ -36,6 +36,10 @@ export declare function hasUnexpiredLockOwner(pmRoot:string,id:string,ownerPrefi
36
36
  declare function lockOwnerSuffix(info:LockInfo | null):string;
37
37
  /** Resolves the effective bounded wait budget for a contended lock: the PM_LOCK_WAIT_MS environment override wins when it parses as a non-negative integer, then the caller-provided budget (settings `locks.wait_ms`), then 0 (fail-fast, the pre-wait behavior). */
38
38
  declare function resolveLockWaitMs(waitMs:number | undefined):number;
39
+ /** Identity of one lock generation; a change proves another writer made progress. */
40
+ declare function lockGenerationKey(info:LockInfo | null):string;
41
+ /** Wait (bounded) for the per-lock cleanup gate that every takeover must also hold; null when it stays held. */
42
+ export declare function waitForStaleCleanupGate(lockPath:string,id:string):Promise<(() => Promise<void>) | null>;
39
43
  /** Fence lock publication, release and garbage collection under one cleanup owner. */
40
44
  export declare function acquireStaleCleanupGate(lockPath:string,_id:string):Promise<(() => Promise<void>) | null>;
41
45
  /** Retain an immutable local audit of early-recovery intent before removing the observed owner. */
@@ -61,11 +65,37 @@ buildLockPayload:typeof buildLockPayload;
61
65
  isStaleLock:typeof isStaleLock;
62
66
  lockOwnerSuffix:typeof lockOwnerSuffix;
63
67
  resolveLockWaitMs:typeof resolveLockWaitMs;
68
+ lockGenerationKey:typeof lockGenerationKey;
64
69
  parseLinuxProcessStartIdentity:typeof parseLinuxProcessStartIdentity;
65
70
  readProcessStartIdentity:typeof readProcessStartIdentity;
66
71
  acquireStaleCleanupGate:typeof acquireStaleCleanupGate;
67
72
  removeConfirmedStaleLock:typeof removeConfirmedStaleLock;
68
73
  };
74
+ /** A held tracker lock whose commits can be fenced against a lost lease. */
75
+ export interface LockLease {
76
+ /** Release the lock if this writer still owns it; idempotent for peers' locks. */
77
+ release:() => Promise<void>;
78
+ /**
79
+ * Run `commit` only while this lease still owns its lock generation. A lease
80
+ * that expired and was taken over (or released) refuses with `lock_lost` and
81
+ * never runs `commit`. Extension lock overrides own their lifecycle, so their
82
+ * leases run `commit` unfenced.
83
+ */
84
+ fence:<T>(commit:() => Promise<T>) => Promise<T>;
85
+ }
86
+ /** Positional lock policy shared by acquireLock and acquireLockLease. */
87
+ type AcquireLockOptions = {
88
+ /** Allow lock acquisition to initialize missing lock directories. */
89
+ createParentDirectories?:boolean;
90
+ /** Ceiling on the effective retry budget, including PM_LOCK_WAIT_MS. */
91
+ maxWaitMs?:number;
92
+ /**
93
+ * How the wait budget is spent. "total" (default) refuses once the budget
94
+ * elapses. "progress" treats it as a no-progress window that every observed
95
+ * owner handoff restarts, bounded by maxWaitMs or LOCK_PROGRESS_MAX_WAIT_MS.
96
+ */
97
+ waitPolicy?:"total" | "progress";
98
+ };
69
99
  /**
70
100
  * Acquire a token-owned tracker lock with bounded contention waiting and
71
101
  * explicit stale-owner policy. Proven same-host original-process death permits
@@ -76,9 +106,13 @@ removeConfirmedStaleLock:typeof removeConfirmedStaleLock;
76
106
  * environment requests a longer wait. Extension overrides receive that ceiling
77
107
  * and retain responsibility for their own lifecycle.
78
108
  */
79
- export declare function acquireLock(pmRoot:string,id:string,ttlSeconds:number,owner:string,force?:boolean,forceRequiredForStaleLock?:boolean,waitMs?:number,options?:{
80
- /** Allow lock acquisition to initialize missing lock directories. */
81
- createParentDirectories?:boolean;
82
- /** Ceiling on the effective retry budget, including PM_LOCK_WAIT_MS. */
83
- maxWaitMs?:number;
84
- }):Promise<() => Promise<void>>;
109
+ export declare function acquireLock(pmRoot:string,id:string,ttlSeconds:number,owner:string,force?:boolean,forceRequiredForStaleLock?:boolean,waitMs?:number,options?:AcquireLockOptions):Promise<() => Promise<void>>;
110
+ /**
111
+ * Acquire a lock as a fenceable lease. With `waitPolicy: "progress"` the wait
112
+ * budget is a no-progress window: every observed owner handoff restarts it, so a
113
+ * queue of live writers drains instead of failing at a fixed deadline, while a
114
+ * stalled owner still refuses after the configured budget. Without an explicit
115
+ * maxWaitMs such a wait is bounded by LOCK_PROGRESS_MAX_WAIT_MS (or the budget
116
+ * itself when larger). The default "total" policy keeps a fixed total budget.
117
+ */
118
+ export declare function acquireLockLease(pmRoot:string,id:string,ttlSeconds:number,owner:string,force?:boolean,forceRequiredForStaleLock?:boolean,waitMs?:number,options?:AcquireLockOptions):Promise<LockLease>;
@@ -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]="8aac3d30-44d1-5876-ab56-6dbc2285d28f")}catch{}})();import{isFileMissingError}from"../fs/fs-utils.js";import{constants as fsConstants}from"node:fs";import fs from"node:fs/promises";import path from"node:path";import{randomUUID}from"node:crypto";import{runActiveOnReadHooks,runActiveOnWriteHooks,runActiveServiceOverride}from"../extensions/index.js";import{EXIT_CODE}from"../shared/constants.js";import{PmCliError}from"../shared/errors.js";import{toErrorMessage}from"../shared/primitives.js";import{getLockPath}from"../store/paths.js";import{nowIso}from"../shared/time.js";import{captureProcessIdentity,captureLockOwnerIdentity,inspectLockOwner,isProcessIdentityAlive,parseLinuxProcessStartIdentity,readProcessStartIdentity}from"./lock-owner.js";import{captureProcessIdentity as captureProcessIdentity2,isProcessIdentityAlive as isProcessIdentityAlive2,readProcessStartIdentity as readProcessStartIdentity2}from"./lock-owner.js";function parseLockInfo(raw){let parsed;try{parsed=JSON.parse(raw)}catch{return{info:null,warnings:["lock_info_invalid_json"]}}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))return{info:null,warnings:["lock_info_invalid_shape"]};const candidate=parsed,id=candidate.id,pid=candidate.pid,owner=candidate.owner,token=candidate.token,createdAt=candidate.created_at,ttlSeconds=candidate.ttl_seconds;return typeof id!="string"||typeof pid!="number"||!Number.isFinite(pid)||typeof owner!="string"||token!==void 0&&(typeof token!="string"||token.trim().length===0)||typeof createdAt!="string"||typeof ttlSeconds!="number"||!Number.isFinite(ttlSeconds)?{info:null,warnings:["lock_info_invalid_shape"]}:{info:{id,pid,owner,...typeof token=="string"?{token}:{},created_at:createdAt,ttl_seconds:ttlSeconds,host_identity:candidate.host_identity,process_start_identity:candidate.process_start_identity},warnings:[]}}async function readLockInfo(lockPath,emitReadHook=!0){try{const raw=await fs.readFile(lockPath,"utf8");return emitReadHook&&await runActiveOnReadHooks({path:lockPath,scope:"project"}),parseLockInfo(raw)}catch(error){return isFileMissingError(error)?{info:null,warnings:[]}:{info:null,warnings:["lock_info_read_failed"]}}}function isErrno(error,code){return typeof error=="object"&&error!==null&&"code"in error&&error.code===code}async function isLockCreateContention(error,lockPath,platform=process.platform){if(isErrno(error,"EEXIST"))return!0;if(!isErrno(error,"EPERM")&&!isErrno(error,"EACCES")&&!isErrno(error,"EBUSY"))return!1;try{return await fs.lstat(lockPath),!0}catch(probeError){if(platform!=="win32"||!isFileMissingError(probeError)&&!isErrno(probeError,"EPERM")&&!isErrno(probeError,"EACCES")&&!isErrno(probeError,"EBUSY"))return!1}try{return await fs.access(path.dirname(lockPath),fsConstants.W_OK),!0}catch{return!1}}async function emitLockWriteHook(lockPath,op){await runActiveOnWriteHooks({path:lockPath,scope:"project",op})}async function buildLockPayload(id,owner,ttlSeconds,token=randomUUID()){return{...await captureLockOwnerIdentity(),id,pid:process.pid,owner,token,created_at:nowIso(),ttl_seconds:ttlSeconds}}async function createLockFile(lockPath,id,owner,ttlSeconds,token,createParentDirectories){createParentDirectories&&await fs.mkdir(path.dirname(lockPath),{recursive:!0});const releaseCleanupGate=await acquireStaleCleanupGate(lockPath,id);if(releaseCleanupGate===null)throw await fs.access(path.dirname(lockPath)),Object.assign(new Error("Lock initialization is contended"),{code:"EEXIST"});try{const handle=await fs.open(lockPath,"wx");try{try{await handle.writeFile(`${JSON.stringify(await buildLockPayload(id,owner,ttlSeconds,token),null,2)}
2
- `,"utf8")}finally{await handle.close()}}catch(error){throw await unlinkLockWithHook(lockPath,"lock:release"),error}}finally{await releaseCleanupGate()}await emitLockWriteHook(lockPath,"lock:create")}async function unlinkLockWithHook(lockPath,op){try{return await fs.unlink(lockPath),await emitLockWriteHook(lockPath,op),!0}catch{return!1}}async function releaseOwnedLock(lockPath,id,owner,token){const startedAtMs=Date.now();let backoffMs=LOCK_WAIT_INITIAL_DELAY_MS;for(;;){const releaseCleanupGate=await acquireStaleCleanupGate(lockPath,id);if(releaseCleanupGate!==null){try{const current2=await readLockInfo(lockPath,!1);isOwnedLock(current2.info,id,owner,token)&&await unlinkLockWithHook(lockPath,"lock:release")}finally{await releaseCleanupGate()}return}const current=await readLockInfo(lockPath,!1);if(!isOwnedLock(current.info,id,owner,token))return;const elapsedMs=Date.now()-startedAtMs;if(elapsedMs>=LOCK_RELEASE_GATE_WAIT_MS)return;await sleepWithJitter(Math.min(backoffMs,LOCK_RELEASE_GATE_WAIT_MS-elapsedMs)),backoffMs=Math.min(backoffMs*2,LOCK_WAIT_MAX_DELAY_MS)}}function isOwnedLock(info,id,owner,token){return info?.id===id&&info.pid===process.pid&&info.owner===owner&&info.token===token}function isStaleLock(info,ttlSeconds){const createdAtMs=info?.created_at?Date.parse(info.created_at):Number.NaN;return(Number.isFinite(createdAtMs)?Date.now()-createdAtMs:Number.POSITIVE_INFINITY)>ttlSeconds*1e3}async function isConfirmedDeadLock(info){return info!==null&&Number.isFinite(Date.parse(info.created_at))&&await inspectLockOwner(info)==="dead"}async function isReclaimableLock(info,ttlSeconds){return isStaleLock(info,ttlSeconds)||await isConfirmedDeadLock(info)}async function hasUnexpiredLockOwner(pmRoot,id,ownerPrefix){const{info}=await readLockInfo(getLockPath(pmRoot,id),!1);return info!==null&&info.owner.startsWith(ownerPrefix)&&!await isReclaimableLock(info,info.ttl_seconds)}function lockOwnerSuffix(info){return info?.owner?` (owner ${info.owner})`:""}const LOCK_WAIT_INITIAL_DELAY_MS=25,LOCK_WAIT_MAX_DELAY_MS=200,LOCK_CONFLICT_RETRY_HINT_MS=250,MAX_STALE_LOCK_REMOVALS=3,STALE_CLEANUP_GATE_SUFFIX=".stale-cleanup",STALE_CLEANUP_GATE_OWNER_FILE="owner.json",STALE_CLEANUP_GATE_STALE_MS=1e4,LOCK_RELEASE_GATE_WAIT_MS=STALE_CLEANUP_GATE_STALE_MS+LOCK_WAIT_MAX_DELAY_MS,STALE_CLEANUP_GATE_MAX_UNVERIFIED_MS=60*6e4;function parseNonNegativeIntegerWaitMs(value){if(typeof value=="string"){const trimmed=value.trim();if(!/^\d+$/.test(trimmed))return;const parsed=Number(trimmed);return Number.isSafeInteger(parsed)?parsed:void 0}if(typeof value=="number"&&Number.isFinite(value)&&value>=0)return Math.trunc(value)}function resolveLockWaitMs(waitMs){const envRaw=process.env.PM_LOCK_WAIT_MS,envParsed=parseNonNegativeIntegerWaitMs(envRaw);if(envParsed!==void 0)return envParsed;const callerParsed=parseNonNegativeIntegerWaitMs(waitMs);return callerParsed!==void 0?callerParsed:0}function cappedLockWaitMs(waitMs,maxWaitMs){return Math.min(resolveLockWaitMs(waitMs),maxWaitMs??1/0)}function sleepWithJitter(baseDelayMs){const jitteredMs=Math.max(1,Math.round(baseDelayMs*(.5+Math.random())));return new Promise(resolve=>setTimeout(resolve,jitteredMs))}async function buildLockConflictError(id,info,waitedMs){const ownerState=await inspectLockOwner(info),waitedSuffix=waitedMs>0?` after waiting ${waitedMs}ms`:"";return new PmCliError(`Item ${id} is locked${lockOwnerSuffix(info)} (owner process ${ownerState})${waitedSuffix}`,EXIT_CODE.CONFLICT,{code:"lock_conflict",item_id:id,reason:`lock_owner_${ownerState}`,required:"Wait for the owner to release the lock, then retry the same operation. Set PM_LOCK_WAIT_MS to a larger bounded millisecond budget when contention is expected. Inspect stale receipts with pm gc --scope locks --dry-run.",recovery:{retry_after_ms:LOCK_CONFLICT_RETRY_HINT_MS}})}function resolveLockOverrideRelease(result){if(typeof result=="function")return result;if(typeof result=="object"&&result!==null&&"release"in result){const release=result.release;return typeof release=="function"?release:null}return null}function throwIfStaleLockNeedsForce(id,lockInfo,force,forceRequired){if(!force&&forceRequired){const warningSuffix=lockInfo.warnings.length>0?` (${lockInfo.warnings.join(",")})`:"";throw new PmCliError(`Item ${id} lock is stale${warningSuffix}; rerun with --force when supported for this command`,EXIT_CODE.CONFLICT)}}function parseStaleCleanupGateOwner(raw){let parsed;try{parsed=JSON.parse(raw)}catch{return null}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))return null;const candidate=parsed,pid=candidate.pid,token=candidate.token,processStartIdentity=candidate.process_start_identity;return typeof pid!="number"||!Number.isInteger(pid)||pid<=0||typeof token!="string"||token.length===0||processStartIdentity!==void 0&&(typeof processStartIdentity!="string"||!/^\d+$/u.test(processStartIdentity))?null:{pid,token,...typeof processStartIdentity=="string"?{process_start_identity:processStartIdentity}:{}}}async function readStaleCleanupGateOwner(gatePath){try{return parseStaleCleanupGateOwner(await fs.readFile(path.join(gatePath,STALE_CLEANUP_GATE_OWNER_FILE),"utf8"))}catch{return null}}async function removeStaleCleanupGateDirectory(gatePath){try{return await fs.rm(gatePath,{recursive:!0,force:!0}),!0}catch{return!1}}async function releaseStaleCleanupGate(gatePath,token){const owner=await readStaleCleanupGateOwner(gatePath);owner===null||owner.token!==token||await removeStaleCleanupGateDirectory(gatePath)}async function tryCreateStaleCleanupGate(gatePath){try{await fs.mkdir(gatePath)}catch(error){return isErrno(error,"EEXIST"),null}const owner={...await captureProcessIdentity(),token:randomUUID()};try{await fs.writeFile(path.join(gatePath,STALE_CLEANUP_GATE_OWNER_FILE),`${JSON.stringify(owner)}
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]="c1ee0cca-ae03-50eb-8158-46510be6f43d")}catch{}})();import{isFileMissingError}from"../fs/fs-utils.js";import{constants as fsConstants}from"node:fs";import fs from"node:fs/promises";import path from"node:path";import{randomUUID}from"node:crypto";import{runActiveOnReadHooks,runActiveOnWriteHooks,runActiveServiceOverride}from"../extensions/index.js";import{EXIT_CODE}from"../shared/constants.js";import{PmCliError}from"../shared/errors.js";import{toErrorMessage}from"../shared/primitives.js";import{getLockPath}from"../store/paths.js";import{nowIso}from"../shared/time.js";import{captureProcessIdentity,captureLockOwnerIdentity,inspectLockOwner,isProcessIdentityAlive,parseLinuxProcessStartIdentity,readProcessStartIdentity}from"./lock-owner.js";import{captureProcessIdentity as captureProcessIdentity2,isProcessIdentityAlive as isProcessIdentityAlive2,readProcessStartIdentity as readProcessStartIdentity2}from"./lock-owner.js";function parseLockInfo(raw){let parsed;try{parsed=JSON.parse(raw)}catch{return{info:null,warnings:["lock_info_invalid_json"]}}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))return{info:null,warnings:["lock_info_invalid_shape"]};const candidate=parsed,id=candidate.id,pid=candidate.pid,owner=candidate.owner,token=candidate.token,createdAt=candidate.created_at,ttlSeconds=candidate.ttl_seconds;return typeof id!="string"||typeof pid!="number"||!Number.isFinite(pid)||typeof owner!="string"||token!==void 0&&(typeof token!="string"||token.trim().length===0)||typeof createdAt!="string"||typeof ttlSeconds!="number"||!Number.isFinite(ttlSeconds)?{info:null,warnings:["lock_info_invalid_shape"]}:{info:{id,pid,owner,...typeof token=="string"?{token}:{},created_at:createdAt,ttl_seconds:ttlSeconds,host_identity:candidate.host_identity,process_start_identity:candidate.process_start_identity},warnings:[]}}async function readLockInfo(lockPath,emitReadHook=!0){try{const raw=await fs.readFile(lockPath,"utf8");return emitReadHook&&await runActiveOnReadHooks({path:lockPath,scope:"project"}),parseLockInfo(raw)}catch(error){return isFileMissingError(error)?{info:null,warnings:[]}:{info:null,warnings:["lock_info_read_failed"]}}}function isErrno(error,code){return typeof error=="object"&&error!==null&&"code"in error&&error.code===code}async function isLockCreateContention(error,lockPath,platform=process.platform){if(isErrno(error,"EEXIST"))return!0;if(!isErrno(error,"EPERM")&&!isErrno(error,"EACCES")&&!isErrno(error,"EBUSY"))return!1;try{return await fs.lstat(lockPath),!0}catch(probeError){if(platform!=="win32"||!isFileMissingError(probeError)&&!isErrno(probeError,"EPERM")&&!isErrno(probeError,"EACCES")&&!isErrno(probeError,"EBUSY"))return!1}try{return await fs.access(path.dirname(lockPath),fsConstants.W_OK),!0}catch{return!1}}async function emitLockWriteHook(lockPath,op){await runActiveOnWriteHooks({path:lockPath,scope:"project",op})}async function buildLockPayload(id,owner,ttlSeconds,token=randomUUID()){return{...await captureLockOwnerIdentity(),id,pid:process.pid,owner,token,created_at:nowIso(),ttl_seconds:ttlSeconds}}async function createLockFile(lockPath,id,owner,ttlSeconds,token,createParentDirectories){createParentDirectories&&await fs.mkdir(path.dirname(lockPath),{recursive:!0});const releaseCleanupGate=await acquireStaleCleanupGate(lockPath,id);if(releaseCleanupGate===null)throw await fs.access(path.dirname(lockPath)),Object.assign(new Error("Lock initialization is contended"),{code:"EEXIST"});let createdAt;try{const handle=await fs.open(lockPath,"wx");try{try{const payload=await buildLockPayload(id,owner,ttlSeconds,token);createdAt=payload.created_at,await handle.writeFile(`${JSON.stringify(payload,null,2)}
2
+ `,"utf8")}finally{await handle.close()}}catch(error){throw await unlinkLockWithHook(lockPath,"lock:release"),error}}finally{await releaseCleanupGate()}return await emitLockWriteHook(lockPath,"lock:create"),createdAt}async function unlinkLockWithHook(lockPath,op){try{return await fs.unlink(lockPath),await emitLockWriteHook(lockPath,op),!0}catch{return!1}}async function releaseOwnedLock(lockPath,id,owner,token){const startedAtMs=Date.now();let backoffMs=LOCK_WAIT_INITIAL_DELAY_MS;for(;;){const releaseCleanupGate=await acquireStaleCleanupGate(lockPath,id);if(releaseCleanupGate!==null){try{const current2=await readLockInfo(lockPath,!1);isOwnedLock(current2.info,id,owner,token)&&await unlinkLockWithHook(lockPath,"lock:release")}finally{await releaseCleanupGate()}return}const current=await readLockInfo(lockPath,!1);if(!isOwnedLock(current.info,id,owner,token))return;const elapsedMs=Date.now()-startedAtMs;if(elapsedMs>=LOCK_RELEASE_GATE_WAIT_MS)return;await sleepWithJitter(Math.min(backoffMs,LOCK_RELEASE_GATE_WAIT_MS-elapsedMs)),backoffMs=Math.min(backoffMs*2,LOCK_WAIT_MAX_DELAY_MS)}}function isOwnedLock(info,id,owner,token){return info?.id===id&&info.pid===process.pid&&info.owner===owner&&info.token===token}function isStaleLock(info,ttlSeconds){const createdAtMs=info?.created_at?Date.parse(info.created_at):Number.NaN;return(Number.isFinite(createdAtMs)?Date.now()-createdAtMs:Number.POSITIVE_INFINITY)>ttlSeconds*1e3}async function isConfirmedDeadLock(info){return info!==null&&Number.isFinite(Date.parse(info.created_at))&&await inspectLockOwner(info)==="dead"}async function isReclaimableLock(info,ttlSeconds){return isStaleLock(info,ttlSeconds)||await isConfirmedDeadLock(info)}async function hasUnexpiredLockOwner(pmRoot,id,ownerPrefix){const{info}=await readLockInfo(getLockPath(pmRoot,id),!1);return info!==null&&info.owner.startsWith(ownerPrefix)&&!await isReclaimableLock(info,info.ttl_seconds)}function lockOwnerSuffix(info){return info?.owner?` (owner ${info.owner})`:""}const LOCK_WAIT_INITIAL_DELAY_MS=25,LOCK_WAIT_MAX_DELAY_MS=200,LOCK_CONFLICT_RETRY_HINT_MS=250,LOCK_PROGRESS_MAX_WAIT_MS=12e4,MAX_STALE_LOCK_REMOVALS=3,STALE_CLEANUP_GATE_SUFFIX=".stale-cleanup",STALE_CLEANUP_GATE_OWNER_FILE="owner.json",STALE_CLEANUP_GATE_STALE_MS=1e4,LOCK_RELEASE_GATE_WAIT_MS=STALE_CLEANUP_GATE_STALE_MS+LOCK_WAIT_MAX_DELAY_MS,STALE_CLEANUP_GATE_MAX_UNVERIFIED_MS=60*6e4;function parseNonNegativeIntegerWaitMs(value){if(typeof value=="string"){const trimmed=value.trim();if(!/^\d+$/.test(trimmed))return;const parsed=Number(trimmed);return Number.isSafeInteger(parsed)?parsed:void 0}if(typeof value=="number"&&Number.isFinite(value)&&value>=0)return Math.trunc(value)}function resolveLockWaitMs(waitMs){const envRaw=process.env.PM_LOCK_WAIT_MS,envParsed=parseNonNegativeIntegerWaitMs(envRaw);if(envParsed!==void 0)return envParsed;const callerParsed=parseNonNegativeIntegerWaitMs(waitMs);return callerParsed!==void 0?callerParsed:0}function cappedLockWaitMs(waitMs,maxWaitMs){return Math.min(resolveLockWaitMs(waitMs),maxWaitMs??1/0)}function sleepWithJitter(baseDelayMs){const jitteredMs=Math.max(1,Math.round(baseDelayMs*(.5+Math.random())));return new Promise(resolve=>setTimeout(resolve,jitteredMs))}async function buildLockConflictError(id,info,waitedMs,ownerHandoffs=0){const ownerState=await inspectLockOwner(info),handoffSuffix=ownerHandoffs>0?` across ${ownerHandoffs} owner handoff(s)`:"",waitedSuffix=waitedMs>0?` after waiting ${waitedMs}ms${handoffSuffix}`:"";return new PmCliError(`Item ${id} is locked${lockOwnerSuffix(info)} (owner process ${ownerState})${waitedSuffix}`,EXIT_CODE.CONFLICT,{code:"lock_conflict",item_id:id,reason:`lock_owner_${ownerState}`,required:"Wait for the owner to release the lock, then retry the same operation. Set PM_LOCK_WAIT_MS to a larger bounded millisecond budget when contention is expected. Inspect stale receipts with pm gc --scope locks --dry-run.",recovery:{retry_after_ms:LOCK_CONFLICT_RETRY_HINT_MS,...waitedMs>0?{waited_ms:waitedMs,owner_handoffs:ownerHandoffs}:{}}})}function createLockWaitTracker(waitBudgetMs,totalCeilingMs){const startedAtMs=Date.now();let stallStartedAtMs=startedAtMs,observedGeneration,ownerHandoffs=0;return{startedAtMs,observe(info){const nowMs=Date.now(),generation=lockGenerationKey(info);observedGeneration!==void 0&&generation!==observedGeneration&&(ownerHandoffs+=1,stallStartedAtMs=nowMs),observedGeneration=generation;const elapsedMs=nowMs-startedAtMs,stalledMs=nowMs-stallStartedAtMs;return{exhausted:waitBudgetMs===0||stalledMs>=waitBudgetMs||elapsedMs>=totalCeilingMs,elapsedMs,remainingMs:Math.min(waitBudgetMs-stalledMs,totalCeilingMs-elapsedMs),ownerHandoffs}}}}function resolveLockWaitCeilingMs(waitBudgetMs,maxWaitMs,waitPolicy){return waitPolicy!=="progress"||maxWaitMs!==void 0?waitBudgetMs:Math.max(waitBudgetMs,LOCK_PROGRESS_MAX_WAIT_MS)}function lockGenerationKey(info){return info===null?"released":info.token??`${info.pid}:${info.owner}:${info.created_at}`}function describeLease(lease){const expiresAtMs=Date.parse(lease.acquiredAt)+lease.ttlSeconds*1e3;return{owner:lease.owner,acquired_at:lease.acquiredAt,ttl_seconds:lease.ttlSeconds,expires_at:new Date(expiresAtMs).toISOString()}}function describeLockLoss(id,lease,current,reason){const leaseLabel=`the lease acquired at ${lease.acquiredAt} (ttl ${lease.ttlSeconds}s)`;if(reason==="fence_gate_unavailable")return{summary:`Lock for ${id} could not be verified before commit: ${leaseLabel} could not enter its commit fence because the stale-cleanup gate stayed held.`,required:"Retry the same operation; this writer's change was not committed. Inspect pm gc --scope locks --dry-run if the stale-cleanup gate stays held."};const holder=current===null?"the lock no longer exists":`it is now held by ${current.owner} since ${current.created_at}`;return{summary:`Lock for ${id} was lost before commit: ${leaseLabel} is no longer owned by this writer, and ${holder}.`,required:"Re-read the item and apply the mutation again; this writer's change was not committed and the newer value was kept. Keep mutation work shorter than locks.ttl_seconds, or raise locks.ttl_seconds for long-running callbacks."}}function buildLockLostError(id,lease,current,reason){const{summary,required}=describeLockLoss(id,lease,current,reason);return new PmCliError(`${summary} Nothing was written.`,EXIT_CODE.CONFLICT,{code:"lock_lost",item_id:id,reason,lease:describeLease(lease),current_owner:current===null?null:{owner:current.owner,pid:current.pid,created_at:current.created_at,ttl_seconds:current.ttl_seconds},required,recovery:{retry_after_ms:LOCK_CONFLICT_RETRY_HINT_MS}})}async function waitForStaleCleanupGate(lockPath,id){const startedAtMs=Date.now();let backoffMs=LOCK_WAIT_INITIAL_DELAY_MS;for(;;){const releaseCleanupGate=await acquireStaleCleanupGate(lockPath,id);if(releaseCleanupGate!==null)return releaseCleanupGate;const elapsedMs=Date.now()-startedAtMs;if(elapsedMs>=LOCK_RELEASE_GATE_WAIT_MS)return null;await sleepWithJitter(Math.min(backoffMs,LOCK_RELEASE_GATE_WAIT_MS-elapsedMs)),backoffMs=Math.min(backoffMs*2,LOCK_WAIT_MAX_DELAY_MS)}}async function fenceOwnedLock(lockPath,id,lease,commit){const releaseCleanupGate=await waitForStaleCleanupGate(lockPath,id);if(releaseCleanupGate===null){const current=await readLockInfo(lockPath,!1);throw buildLockLostError(id,lease,current.info,"fence_gate_unavailable")}try{const current=await readLockInfo(lockPath,!1);if(!isOwnedLock(current.info,id,lease.owner,lease.token))throw buildLockLostError(id,lease,current.info,current.info===null?"lease_released":"lease_taken_over");return await commit()}finally{await releaseCleanupGate()}}function resolveLockOverrideRelease(result){if(typeof result=="function")return result;if(typeof result=="object"&&result!==null&&"release"in result){const release=result.release;return typeof release=="function"?release:null}return null}function throwIfStaleLockNeedsForce(id,lockInfo,force,forceRequired){if(!force&&forceRequired){const warningSuffix=lockInfo.warnings.length>0?` (${lockInfo.warnings.join(",")})`:"";throw new PmCliError(`Item ${id} lock is stale${warningSuffix}; rerun with --force when supported for this command`,EXIT_CODE.CONFLICT)}}function parseStaleCleanupGateOwner(raw){let parsed;try{parsed=JSON.parse(raw)}catch{return null}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))return null;const candidate=parsed,pid=candidate.pid,token=candidate.token,processStartIdentity=candidate.process_start_identity;return typeof pid!="number"||!Number.isInteger(pid)||pid<=0||typeof token!="string"||token.length===0||processStartIdentity!==void 0&&(typeof processStartIdentity!="string"||!/^\d+$/u.test(processStartIdentity))?null:{pid,token,...typeof processStartIdentity=="string"?{process_start_identity:processStartIdentity}:{}}}async function readStaleCleanupGateOwner(gatePath){try{return parseStaleCleanupGateOwner(await fs.readFile(path.join(gatePath,STALE_CLEANUP_GATE_OWNER_FILE),"utf8"))}catch{return null}}async function removeStaleCleanupGateDirectory(gatePath){try{return await fs.rm(gatePath,{recursive:!0,force:!0}),!0}catch{return!1}}async function releaseStaleCleanupGate(gatePath,token){const owner=await readStaleCleanupGateOwner(gatePath);owner===null||owner.token!==token||await removeStaleCleanupGateDirectory(gatePath)}async function tryCreateStaleCleanupGate(gatePath){try{await fs.mkdir(gatePath)}catch(error){return isErrno(error,"EEXIST"),null}const owner={...await captureProcessIdentity(),token:randomUUID()};try{await fs.writeFile(path.join(gatePath,STALE_CLEANUP_GATE_OWNER_FILE),`${JSON.stringify(owner)}
3
3
  `,"utf8")}catch{return await removeStaleCleanupGateDirectory(gatePath),null}return owner}async function removeExpiredStaleCleanupGate(gatePath){let gateAgeMs;try{const stats=await fs.stat(gatePath);if(gateAgeMs=Date.now()-stats.mtimeMs,gateAgeMs<=STALE_CLEANUP_GATE_STALE_MS)return!1}catch(error){return isFileMissingError(error)}const owner=await readStaleCleanupGateOwner(gatePath);return owner!==null&&await isProcessIdentityAlive(owner,gateAgeMs,STALE_CLEANUP_GATE_MAX_UNVERIFIED_MS)?!1:removeStaleCleanupGateDirectory(gatePath)}async function acquireStaleCleanupGate(lockPath,_id){const gatePath=`${lockPath}${STALE_CLEANUP_GATE_SUFFIX}`,owner=await tryCreateStaleCleanupGate(gatePath);if(owner!==null)return async()=>releaseStaleCleanupGate(gatePath,owner.token);if(!await removeExpiredStaleCleanupGate(gatePath))return null;const recoveredOwner=await tryCreateStaleCleanupGate(gatePath);return recoveredOwner===null?null:async()=>releaseStaleCleanupGate(gatePath,recoveredOwner.token)}async function recordDeadLockRecovery(lockPath,raw){const directory=path.join(path.dirname(lockPath),"recoveries");await fs.mkdir(directory,{recursive:!0}),await fs.writeFile(path.join(directory,`${randomUUID()}.json`),`${JSON.stringify({event:"owner_dead_recovery_attempt",recorded_at:nowIso(),lock:JSON.parse(raw)})}
4
- `,{encoding:"utf8",flag:"wx",mode:384})}async function removeConfirmedStaleLock(params){const releaseCleanupGate=await acquireStaleCleanupGate(params.lockPath,params.id);if(releaseCleanupGate===null)return{lockInfo:params.fallbackLockInfo,shouldRetryCreate:!1,staleRemovalCounted:!1};try{const currentLockInfo=await readLockInfo(params.lockPath);if(currentLockInfo.info===null&&currentLockInfo.warnings.length===0)return{lockInfo:currentLockInfo,shouldRetryCreate:!0,staleRemovalCounted:!1};const ownerDead=await isConfirmedDeadLock(currentLockInfo.info);if(!isStaleLock(currentLockInfo.info,params.ttlSeconds)&&!ownerDead)return{lockInfo:currentLockInfo,shouldRetryCreate:!1,staleRemovalCounted:!1};if(throwIfStaleLockNeedsForce(params.id,currentLockInfo,params.force||ownerDead,params.forceRequiredForStaleLock),params.staleRemovals>=MAX_STALE_LOCK_REMOVALS)throw await buildLockConflictError(params.id,currentLockInfo.info,Date.now()-params.startedAtMs);return ownerDead&&await recordDeadLockRecovery(params.lockPath,JSON.stringify(currentLockInfo.info)),{lockInfo:currentLockInfo,shouldRetryCreate:await unlinkLockWithHook(params.lockPath,"lock:stale_remove"),staleRemovalCounted:!0}}finally{await releaseCleanupGate()}}const _testOnly={parseLockInfo,readLockInfo,isErrno,isLockCreateContention,buildLockPayload,isStaleLock,lockOwnerSuffix,resolveLockWaitMs,parseLinuxProcessStartIdentity,readProcessStartIdentity,acquireStaleCleanupGate,removeConfirmedStaleLock};async function acquireLock(pmRoot,id,ttlSeconds,owner,force=!1,forceRequiredForStaleLock=!0,waitMs,options={}){const maxWaitMs=parseNonNegativeIntegerWaitMs(options.maxWaitMs),lockOverride=await runActiveServiceOverride("lock_acquire",{pm_root:pmRoot,id,ttl_seconds:ttlSeconds,owner,force,force_required_for_stale_lock:forceRequiredForStaleLock,...maxWaitMs===void 0?{}:{max_wait_ms:maxWaitMs}});if(lockOverride.handled){const release=resolveLockOverrideRelease(lockOverride.result);if(release)return async()=>{await Promise.resolve(release()),await runActiveServiceOverride("lock_release",{pm_root:pmRoot,id,owner})}}const lockPath=getLockPath(pmRoot,id),waitBudgetMs=cappedLockWaitMs(waitMs,maxWaitMs),startedAtMs=Date.now();let staleRemovals=0,backoffMs=LOCK_WAIT_INITIAL_DELAY_MS;const token=randomUUID();for(;;)try{return await createLockFile(lockPath,id,owner,ttlSeconds,token,options.createParentDirectories!==!1),async()=>{await releaseOwnedLock(lockPath,id,owner,token),await runActiveServiceOverride("lock_release",{pm_root:pmRoot,id,owner})}}catch(error){if(!await isLockCreateContention(error,lockPath))throw new PmCliError(`Failed to acquire lock for ${id}: ${toErrorMessage(error)}`,EXIT_CODE.GENERIC_FAILURE);let lockInfo=await readLockInfo(lockPath);if(await isReclaimableLock(lockInfo.info,ttlSeconds)){const staleRemoval=await removeConfirmedStaleLock({lockPath,id,ttlSeconds,force,forceRequiredForStaleLock,staleRemovals,waitBudgetMs,startedAtMs,fallbackLockInfo:lockInfo});if(lockInfo=staleRemoval.lockInfo,staleRemoval.staleRemovalCounted&&(staleRemovals+=1),staleRemoval.shouldRetryCreate)continue}const elapsedMs=Date.now()-startedAtMs;if(waitBudgetMs===0||elapsedMs>=waitBudgetMs)throw await buildLockConflictError(id,lockInfo.info,waitBudgetMs===0?0:elapsedMs);await sleepWithJitter(Math.min(backoffMs,waitBudgetMs-elapsedMs)),backoffMs=Math.min(backoffMs*2,LOCK_WAIT_MAX_DELAY_MS)}}export{_testOnly,acquireLock,acquireStaleCleanupGate,captureProcessIdentity2 as captureProcessIdentity,hasUnexpiredLockOwner,isProcessIdentityAlive2 as isProcessIdentityAlive,readProcessStartIdentity2 as readProcessStartIdentity,recordDeadLockRecovery};
4
+ `,{encoding:"utf8",flag:"wx",mode:384})}async function removeConfirmedStaleLock(params){const releaseCleanupGate=await acquireStaleCleanupGate(params.lockPath,params.id);if(releaseCleanupGate===null)return{lockInfo:params.fallbackLockInfo,shouldRetryCreate:!1,staleRemovalCounted:!1};try{const currentLockInfo=await readLockInfo(params.lockPath);if(currentLockInfo.info===null&&currentLockInfo.warnings.length===0)return{lockInfo:currentLockInfo,shouldRetryCreate:!0,staleRemovalCounted:!1};const ownerDead=await isConfirmedDeadLock(currentLockInfo.info);if(!isStaleLock(currentLockInfo.info,params.ttlSeconds)&&!ownerDead)return{lockInfo:currentLockInfo,shouldRetryCreate:!1,staleRemovalCounted:!1};if(throwIfStaleLockNeedsForce(params.id,currentLockInfo,params.force||ownerDead,params.forceRequiredForStaleLock),params.staleRemovals>=MAX_STALE_LOCK_REMOVALS)throw await buildLockConflictError(params.id,currentLockInfo.info,Date.now()-params.startedAtMs);return ownerDead&&await recordDeadLockRecovery(params.lockPath,JSON.stringify(currentLockInfo.info)),{lockInfo:currentLockInfo,shouldRetryCreate:await unlinkLockWithHook(params.lockPath,"lock:stale_remove"),staleRemovalCounted:!0}}finally{await releaseCleanupGate()}}const _testOnly={parseLockInfo,readLockInfo,isErrno,isLockCreateContention,buildLockPayload,isStaleLock,lockOwnerSuffix,resolveLockWaitMs,lockGenerationKey,parseLinuxProcessStartIdentity,readProcessStartIdentity,acquireStaleCleanupGate,removeConfirmedStaleLock};async function acquireLock(pmRoot,id,ttlSeconds,owner,force=!1,forceRequiredForStaleLock=!0,waitMs,options={}){return(await acquireLockLease(pmRoot,id,ttlSeconds,owner,force,forceRequiredForStaleLock,waitMs,options)).release}async function acquireLockLease(pmRoot,id,ttlSeconds,owner,force=!1,forceRequiredForStaleLock=!0,waitMs,options={}){const maxWaitMs=parseNonNegativeIntegerWaitMs(options.maxWaitMs),lockOverride=await runActiveServiceOverride("lock_acquire",{pm_root:pmRoot,id,ttl_seconds:ttlSeconds,owner,force,force_required_for_stale_lock:forceRequiredForStaleLock,...maxWaitMs===void 0?{}:{max_wait_ms:maxWaitMs}});if(lockOverride.handled){const release=resolveLockOverrideRelease(lockOverride.result);if(release)return{release:async()=>{await Promise.resolve(release()),await runActiveServiceOverride("lock_release",{pm_root:pmRoot,id,owner})},fence:commit=>commit()}}const lockPath=getLockPath(pmRoot,id),waitBudgetMs=cappedLockWaitMs(waitMs,maxWaitMs),totalCeilingMs=resolveLockWaitCeilingMs(waitBudgetMs,maxWaitMs,options.waitPolicy),waitTracker=createLockWaitTracker(waitBudgetMs,totalCeilingMs),startedAtMs=waitTracker.startedAtMs;let staleRemovals=0,backoffMs=LOCK_WAIT_INITIAL_DELAY_MS;const token=randomUUID();for(;;)try{const acquiredAt=await createLockFile(lockPath,id,owner,ttlSeconds,token,options.createParentDirectories!==!1),lease={owner,token,acquiredAt,ttlSeconds};return{release:async()=>{await releaseOwnedLock(lockPath,id,owner,token),await runActiveServiceOverride("lock_release",{pm_root:pmRoot,id,owner})},fence:commit=>fenceOwnedLock(lockPath,id,lease,commit)}}catch(error){if(!await isLockCreateContention(error,lockPath))throw new PmCliError(`Failed to acquire lock for ${id}: ${toErrorMessage(error)}`,EXIT_CODE.GENERIC_FAILURE);let lockInfo=await readLockInfo(lockPath);if(await isReclaimableLock(lockInfo.info,ttlSeconds)){const staleRemoval=await removeConfirmedStaleLock({lockPath,id,ttlSeconds,force,forceRequiredForStaleLock,staleRemovals,waitBudgetMs,startedAtMs,fallbackLockInfo:lockInfo});if(lockInfo=staleRemoval.lockInfo,staleRemoval.staleRemovalCounted&&(staleRemovals+=1),staleRemoval.shouldRetryCreate)continue}const observation=waitTracker.observe(lockInfo.info);if(observation.exhausted)throw await buildLockConflictError(id,lockInfo.info,waitBudgetMs===0?0:observation.elapsedMs,observation.ownerHandoffs);await sleepWithJitter(Math.min(backoffMs,observation.remainingMs)),backoffMs=Math.min(backoffMs*2,LOCK_WAIT_MAX_DELAY_MS)}}export{_testOnly,acquireLock,acquireLockLease,acquireStaleCleanupGate,captureProcessIdentity2 as captureProcessIdentity,hasUnexpiredLockOwner,isProcessIdentityAlive2 as isProcessIdentityAlive,readProcessStartIdentity2 as readProcessStartIdentity,recordDeadLockRecovery,waitForStaleCleanupGate};
5
5
  //# sourceMappingURL=lock.js.map
@@ -78,6 +78,10 @@ suggested_retry_args?:string[];
78
78
  token_budget?:PmTokenBudgetRecovery;
79
79
  /** Elapsed time in milliseconds for retry after. */
80
80
  retry_after_ms?:number;
81
+ /** Milliseconds a refused lock acquisition waited before giving up. */
82
+ waited_ms?:number;
83
+ /** Lock generations observed to change hands while the refused acquisition waited. */
84
+ owner_handoffs?:number;
81
85
  /** Value that configures or reports fallback candidates for this contract. */
82
86
  fallback_candidates?:Array<{
83
87
  source:string;
@@ -93,6 +97,8 @@ export interface PmCliErrorContext {
93
97
  changed?:false;
94
98
  /** Value that configures or reports code for this contract. */
95
99
  code?:string;
100
+ /** Original typed diagnostic retained when recovery also fails. */
101
+ original_code?:string;
96
102
  /** Canonical existing item identity returned by a refused create operation. */
97
103
  id?:string;
98
104
  /** Actual persisted existing-item path returned by a refused create operation. */
@@ -241,6 +247,28 @@ first_timestamp:string | null;
241
247
  /** Latest available history timestamp, or null for an empty stream. */
242
248
  last_timestamp:string | null;
243
249
  };
250
+ /** Lease a refused `lock_lost` commit held when it tried to commit. */
251
+ lease?:{
252
+ /** Principal recorded as the lease owner. */
253
+ owner:string;
254
+ /** When the lease's lock generation was published. */
255
+ acquired_at:string;
256
+ /** Stale-lock lifetime the lease was acquired under. */
257
+ ttl_seconds:number;
258
+ /** When the lease became reclaimable by TTL. */
259
+ expires_at:string;
260
+ };
261
+ /** Lock generation observed at a refused `lock_lost` commit, or null when no lock exists. */
262
+ current_owner?:{
263
+ /** Principal recorded as the current lock owner. */
264
+ owner:string;
265
+ /** Process that published the current lock generation. */
266
+ pid:number;
267
+ /** When the current lock generation was published. */
268
+ created_at:string;
269
+ /** Stale-lock lifetime of the current lock generation. */
270
+ ttl_seconds:number;
271
+ } | null;
244
272
  /** Value that configures or reports recovery for this contract. */
245
273
  recovery?:PmCliErrorRecoveryPayload;
246
274
  }
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3399082a-aeaf-5235-9524-d0e86253ee95")}catch{}})();class PmCliError extends Error{exitCode;code;context;constructor(message,exitCode,context={}){super(message),this.name="PmCliError",this.exitCode=exitCode,this.context=context,this.code=context.code}}export{PmCliError};
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]="5740fcf4-dad8-5bcc-b68d-99fa81c43655")}catch{}})();class PmCliError extends Error{exitCode;code;context;constructor(message,exitCode,context={}){super(message),this.name="PmCliError",this.exitCode=exitCode,this.context=context,this.code=context.code}}export{PmCliError};
2
2
  //# sourceMappingURL=errors.js.map