@unbrained/pm-cli 2026.9.7 → 2026.9.9

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 (746) hide show
  1. package/.agents/skills/pm-developer/SKILL.md +12 -4
  2. package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +19 -10
  3. package/.agents/skills/pm-extensions/SKILL.md +6 -0
  4. package/.agents/skills/pm-sdk/SKILL.md +11 -2
  5. package/.agents/skills/pm-user/SKILL.md +7 -2
  6. package/.agents/skills/pm-user/references/ECOSYSTEM_PLANNING.md +95 -0
  7. package/.claude-plugin/marketplace.json +2 -2
  8. package/CHANGELOG.md +231 -182
  9. package/dist/cli/after-command-context-usage.js +1 -48
  10. package/dist/cli/argv-utils.js +1 -40
  11. package/dist/cli/bootstrap-args.js +1 -9
  12. package/dist/cli/bundle-integrity.js +2 -110
  13. package/dist/cli/commander-usage.js +11 -771
  14. package/dist/cli/commands/activity.js +1 -9
  15. package/dist/cli/commands/aggregate.js +1 -5
  16. package/dist/cli/commands/append.js +1 -5
  17. package/dist/cli/commands/claim.js +1 -5
  18. package/dist/cli/commands/close-many.js +1 -5
  19. package/dist/cli/commands/close.js +1 -9
  20. package/dist/cli/commands/comments.js +1 -5
  21. package/dist/cli/commands/config.js +1 -9
  22. package/dist/cli/commands/context.js +1 -9
  23. package/dist/cli/commands/contracts.js +1 -5
  24. package/dist/cli/commands/copy.js +1 -9
  25. package/dist/cli/commands/create.js +1 -9
  26. package/dist/cli/commands/delete.js +1 -9
  27. package/dist/cli/commands/deps.js +1 -9
  28. package/dist/cli/commands/docs.js +1 -9
  29. package/dist/cli/commands/duplicates.js +1 -9
  30. package/dist/cli/commands/eval.js +1 -9
  31. package/dist/cli/commands/extension/describe.js +1 -5
  32. package/dist/cli/commands/extension/scaffold.js +1 -5
  33. package/dist/cli/commands/extension/shared.js +1 -5
  34. package/dist/cli/commands/extension.js +1 -9
  35. package/dist/cli/commands/files.js +1 -9
  36. package/dist/cli/commands/focus.js +1 -9
  37. package/dist/cli/commands/gc.js +1 -9
  38. package/dist/cli/commands/get.js +1 -9
  39. package/dist/cli/commands/graph.js +1 -10
  40. package/dist/cli/commands/health.js +1 -9
  41. package/dist/cli/commands/history-compact.js +1 -10
  42. package/dist/cli/commands/history-redact.js +1 -11
  43. package/dist/cli/commands/history-repair.js +1 -10
  44. package/dist/cli/commands/history.js +1 -5
  45. package/dist/cli/commands/index.js +1 -58
  46. package/dist/cli/commands/init-agent-guidance.js +1 -9
  47. package/dist/cli/commands/init.js +1 -9
  48. package/dist/cli/commands/learnings.js +1 -5
  49. package/dist/cli/commands/lifecycle-transitions.js +1 -5
  50. package/dist/cli/commands/list.js +1 -9
  51. package/dist/cli/commands/merge.js +1 -11
  52. package/dist/cli/commands/next.js +1 -9
  53. package/dist/cli/commands/notes.js +1 -5
  54. package/dist/cli/commands/plan.js +1 -9
  55. package/dist/cli/commands/profile.js +1 -9
  56. package/dist/cli/commands/restore.js +1 -9
  57. package/dist/cli/commands/scheduling-shortcuts.js +1 -9
  58. package/dist/cli/commands/schema.js +1 -10
  59. package/dist/cli/commands/search.js +1 -9
  60. package/dist/cli/commands/stats.js +1 -9
  61. package/dist/cli/commands/telemetry.js +1 -9
  62. package/dist/cli/commands/test-all.js +1 -9
  63. package/dist/cli/commands/test-runs.js +1 -9
  64. package/dist/cli/commands/test.js +1 -9
  65. package/dist/cli/commands/update-many.js +1 -5
  66. package/dist/cli/commands/update.js +1 -9
  67. package/dist/cli/commands/upgrade.js +1 -5
  68. package/dist/cli/commands/validate.js +1 -15
  69. package/dist/cli/context-intent-invocation.js +1 -20
  70. package/dist/cli/description-stdin.js +1 -17
  71. package/dist/cli/error-guidance.js +1 -1353
  72. package/dist/cli/extension-command-help.js +5 -636
  73. package/dist/cli/extension-command-options.js +1 -427
  74. package/dist/cli/extension-recovery.js +1 -126
  75. package/dist/cli/help-content.js +2 -1001
  76. package/dist/cli/help-json-payload.js +4 -570
  77. package/dist/cli/main.d.ts +4 -0
  78. package/dist/cli/main.js +5 -2573
  79. package/dist/cli/migration-gates.js +1 -289
  80. package/dist/cli/public.js +1 -20
  81. package/dist/cli/register-annotations.js +1 -270
  82. package/dist/cli/register-assurance.js +1 -62
  83. package/dist/cli/register-files-lookup.js +1 -56
  84. package/dist/cli/register-history-activity.d.ts +8 -0
  85. package/dist/cli/register-history-activity.js +2 -0
  86. package/dist/cli/register-history-author.js +1 -38
  87. package/dist/cli/register-history-maintenance.d.ts +9 -0
  88. package/dist/cli/register-history-maintenance.js +2 -0
  89. package/dist/cli/register-list-query.js +10 -943
  90. package/dist/cli/register-mutation-options.js +1 -9
  91. package/dist/cli/register-mutation.d.ts +0 -5
  92. package/dist/cli/register-mutation.js +19 -1893
  93. package/dist/cli/register-operations.js +1 -920
  94. package/dist/cli/register-setup.js +1 -716
  95. package/dist/cli/register-structured-mutation.js +1 -196
  96. package/dist/cli/registration-helpers.js +1 -5
  97. package/dist/cli/runtime-compatibility-boundary.js +4 -42
  98. package/dist/cli/schema-registration-helpers.js +1 -73
  99. package/dist/cli/search-refresh.js +1 -13
  100. package/dist/cli/stats-analytics-json.js +1 -68
  101. package/dist/cli/telemetry-flush.js +1 -10
  102. package/dist/cli-bundle/bundle-manifest.json +164 -156
  103. package/dist/cli-bundle/chunks/{chunk-NPN5I67J.js → chunk-3IPRM75M.js} +3 -3
  104. package/dist/cli-bundle/chunks/chunk-4VL5P22L.js +2 -0
  105. package/dist/cli-bundle/chunks/chunk-AAFBV3U3.js +29 -0
  106. package/dist/cli-bundle/chunks/chunk-D3YVILJJ.js +20 -0
  107. package/dist/cli-bundle/chunks/{chunk-WYRZZ5ZE.js → chunk-DEZPZOQ7.js} +2 -2
  108. package/dist/cli-bundle/chunks/chunk-ECBLPN7B.js +3 -0
  109. package/dist/cli-bundle/chunks/chunk-J6ERHBV2.js +235 -0
  110. package/dist/cli-bundle/chunks/chunk-JUNJ5EKI.js +2 -0
  111. package/dist/cli-bundle/chunks/chunk-L5RCDKQ2.js +2 -0
  112. package/dist/cli-bundle/chunks/chunk-NSAPNEYH.js +2 -0
  113. package/dist/cli-bundle/chunks/chunk-OHNLSGGV.js +79 -0
  114. package/dist/cli-bundle/chunks/chunk-WQKMSFBV.js +5 -0
  115. package/dist/cli-bundle/chunks/{chunk-BAX2BYUW.js → chunk-XZ6T7YPP.js} +256 -150
  116. package/dist/cli-bundle/chunks/{chunk-JT6XF6GE.js → chunk-Z3XVXUVF.js} +4 -4
  117. package/dist/cli-bundle/chunks/register-list-query-UIHRCS6D.js +11 -0
  118. package/dist/cli-bundle/chunks/register-mutation-WHWMGRVX.js +20 -0
  119. package/dist/cli-bundle/chunks/register-operations-64YZYTC5.js +2 -0
  120. package/dist/cli-bundle/chunks/register-setup-PERI45EM.js +2 -0
  121. package/dist/cli-bundle/focused-chunks/chunk-2W4XIYOB.js +2 -0
  122. package/dist/cli-bundle/focused-chunks/chunk-2WSBXIGF.js +12 -0
  123. package/dist/cli-bundle/focused-chunks/chunk-5FHTCOHS.js +3 -0
  124. package/dist/cli-bundle/focused-chunks/chunk-7N6DOREF.js +26 -0
  125. package/dist/cli-bundle/focused-chunks/{chunk-3BZEOXLT.js → chunk-7PC4R5QB.js} +2 -2
  126. package/dist/cli-bundle/focused-chunks/chunk-BUCJUZVG.js +6 -0
  127. package/dist/cli-bundle/focused-chunks/chunk-FE3BABLJ.js +2 -0
  128. package/dist/cli-bundle/focused-chunks/chunk-IWITF53W.js +2 -0
  129. package/dist/cli-bundle/focused-chunks/chunk-OQUGRHKV.js +10 -0
  130. package/dist/cli-bundle/focused-chunks/{chunk-M6PBRFSH.js → chunk-PNKIANFZ.js} +2 -2
  131. package/dist/cli-bundle/focused-chunks/{chunk-LIJIA4TY.js → chunk-QQQ4SAUO.js} +3 -3
  132. package/dist/cli-bundle/focused-chunks/chunk-TTYXF5YD.js +177 -0
  133. package/dist/cli-bundle/focused-chunks/chunk-XNR3DM6J.js +2 -0
  134. package/dist/cli-bundle/focused-chunks/chunk-XSS3APUF.js +9 -0
  135. package/dist/cli-bundle/focused-chunks/chunk-YCDQ2N23.js +8 -0
  136. package/dist/cli-bundle/focused-chunks/chunk-YJUXGS57.js +20 -0
  137. package/dist/cli-bundle/focused-chunks/chunk-ZTCE4UO6.js +58 -0
  138. package/dist/cli-bundle/main.js +20 -20
  139. package/dist/cli-bundle/sdk-authoring.js +1 -1
  140. package/dist/cli-bundle/sdk-contracts.js +2 -2
  141. package/dist/cli-bundle/sdk-core.js +37 -37
  142. package/dist/cli-bundle/sdk-governance.js +1 -1
  143. package/dist/cli-bundle/sdk-graph.js +1 -1
  144. package/dist/cli-bundle/sdk-merge.js +42 -42
  145. package/dist/cli-bundle/sdk-query.js +1 -1
  146. package/dist/cli-bundle/sdk-runtime.js +1 -1
  147. package/dist/cli-bundle/sdk-testing.js +1 -1
  148. package/dist/cli-bundle/sdk.js +11 -11
  149. package/dist/cli.js +1 -104
  150. package/dist/core/checkpoint/checkpoint-gc.js +1 -169
  151. package/dist/core/checkpoint/mutation-checkpoint.js +2 -133
  152. package/dist/core/config/nested-settings.js +1 -534
  153. package/dist/core/config/positional-value.js +1 -109
  154. package/dist/core/diagnostics/remediation.js +1 -506
  155. package/dist/core/extensions/activation-summary-markdown.js +2 -145
  156. package/dist/core/extensions/activation-summary.js +1 -92
  157. package/dist/core/extensions/activation-transaction.js +1 -46
  158. package/dist/core/extensions/capability-usage.js +1 -173
  159. package/dist/core/extensions/command-hook-context.js +1 -13
  160. package/dist/core/extensions/command-metadata-contract.js +1 -22
  161. package/dist/core/extensions/command-visibility-tier.js +1 -29
  162. package/dist/core/extensions/contribution-inventory.js +1 -173
  163. package/dist/core/extensions/exporter-output-contract.js +1 -66
  164. package/dist/core/extensions/extension-candidate.js +1 -18
  165. package/dist/core/extensions/extension-capability-aliases.js +1 -158
  166. package/dist/core/extensions/extension-hook-runtime.js +1 -699
  167. package/dist/core/extensions/extension-policy.js +1 -599
  168. package/dist/core/extensions/extension-registries.js +1 -62
  169. package/dist/core/extensions/extension-runtime-helpers.js +1 -33
  170. package/dist/core/extensions/extension-types.js +1 -102
  171. package/dist/core/extensions/flag-definition-validation.js +1 -52
  172. package/dist/core/extensions/flag-value-types.js +1 -64
  173. package/dist/core/extensions/index.js +1 -526
  174. package/dist/core/extensions/item-field-types.js +1 -39
  175. package/dist/core/extensions/item-fields.js +1 -261
  176. package/dist/core/extensions/loader.js +1 -2223
  177. package/dist/core/extensions/manifest-schema.js +1 -69
  178. package/dist/core/extensions/module-graph-snapshot.js +1 -33
  179. package/dist/core/extensions/preflight-ownership.js +1 -41
  180. package/dist/core/extensions/registration-validation.js +1 -82
  181. package/dist/core/extensions/registration-values.js +1 -209
  182. package/dist/core/extensions/reserved-host-flags.js +1 -36
  183. package/dist/core/extensions/runtime-registrations.js +1 -67
  184. package/dist/core/extensions/service-ownership.js +1 -19
  185. package/dist/core/extensions/version-compat.js +1 -216
  186. package/dist/core/fs/fs-utils.js +2 -158
  187. package/dist/core/fs/host-environment-errors.js +1 -141
  188. package/dist/core/fs/index.js +1 -9
  189. package/dist/core/fs/path-utils.js +1 -17
  190. package/dist/core/governance/content-fields.js +1 -160
  191. package/dist/core/governance/issue-codes.js +1 -151
  192. package/dist/core/governance/metadata-coverage.js +1 -358
  193. package/dist/core/history/drift-cache.js +3 -72
  194. package/dist/core/history/drift-scan.js +1 -342
  195. package/dist/core/history/event-classification.js +1 -109
  196. package/dist/core/history/event-index.js +8 -784
  197. package/dist/core/history/history-compact-bulk.js +1 -104
  198. package/dist/core/history/history-diff.js +1 -158
  199. package/dist/core/history/history-rewrite.d.ts +6 -1
  200. package/dist/core/history/history-rewrite.js +1 -107
  201. package/dist/core/history/history-storage-stats.js +1 -102
  202. package/dist/core/history/history-stream-policy.js +1 -62
  203. package/dist/core/history/history.js +2 -617
  204. package/dist/core/history/identity.js +1 -30
  205. package/dist/core/history/index.js +1 -9
  206. package/dist/core/history/projection.js +1 -196
  207. package/dist/core/history/read.d.ts +9 -0
  208. package/dist/core/history/read.js +1 -57
  209. package/dist/core/history/replay.js +2 -439
  210. package/dist/core/history/version-address.js +1 -32
  211. package/dist/core/history/workspace-history.js +2 -433
  212. package/dist/core/io/body-file.js +1 -62
  213. package/dist/core/io/bulk-ids-input.js +1 -112
  214. package/dist/core/item/actionability.js +1 -327
  215. package/dist/core/item/dependency-reference.js +1 -20
  216. package/dist/core/item/id.js +1 -112
  217. package/dist/core/item/index.js +1 -12
  218. package/dist/core/item/item-format-version.js +1 -78
  219. package/dist/core/item/item-format.js +5 -1473
  220. package/dist/core/item/item-record.js +1 -23
  221. package/dist/core/item/item-type-definition.js +1 -133
  222. package/dist/core/item/parent-reference-policy.js +1 -57
  223. package/dist/core/item/parse.js +2 -603
  224. package/dist/core/item/plan-lifecycle.js +1 -19
  225. package/dist/core/item/priority.js +1 -61
  226. package/dist/core/item/sprint-release-format.js +1 -38
  227. package/dist/core/item/status-filter.js +1 -115
  228. package/dist/core/item/status.js +1 -43
  229. package/dist/core/item/toon-decode.js +1 -29
  230. package/dist/core/item/type-registry.js +1 -715
  231. package/dist/core/item/type-synonyms.js +1 -38
  232. package/dist/core/lock/index.js +1 -9
  233. package/dist/core/lock/lock-gc.js +1 -240
  234. package/dist/core/lock/lock.js +3 -590
  235. package/dist/core/output/mutation-projection.js +1 -217
  236. package/dist/core/output/output-control.js +1 -25
  237. package/dist/core/output/output.js +11 -494
  238. package/dist/core/output/query-summary.js +1 -58
  239. package/dist/core/output/tabular.js +1 -77
  240. package/dist/core/packages/manifest.js +1 -244
  241. package/dist/core/packages/root.js +1 -84
  242. package/dist/core/policy/workflow-policy-schema.d.ts +312 -0
  243. package/dist/core/policy/workflow-policy-schema.js +2 -0
  244. package/dist/core/policy/workflow-policy-store.d.ts +24 -0
  245. package/dist/core/policy/workflow-policy-store.js +2 -0
  246. package/dist/core/policy/workflow-policy.d.ts +139 -0
  247. package/dist/core/policy/workflow-policy.js +2 -0
  248. package/dist/core/profile/profile-describe.js +1 -83
  249. package/dist/core/profile/profile-lint.js +1 -415
  250. package/dist/core/profile/profile-plan.js +0 -0
  251. package/dist/core/profile/profile-presets.js +1 -370
  252. package/dist/core/reproducibility/context.js +1 -82
  253. package/dist/core/schema/fields-file.js +2 -288
  254. package/dist/core/schema/item-types-file.js +2 -296
  255. package/dist/core/schema/runtime-field-filters.js +1 -49
  256. package/dist/core/schema/runtime-field-values.js +1 -313
  257. package/dist/core/schema/runtime-schema.js +2 -826
  258. package/dist/core/schema/status-defs-file.js +2 -227
  259. package/dist/core/schema/status-token.js +1 -31
  260. package/dist/core/schema/type-inference.js +1 -95
  261. package/dist/core/schema/type-presets.js +1 -87
  262. package/dist/core/schema/type-workflows.js +1 -104
  263. package/dist/core/search/background-refresh.js +2 -286
  264. package/dist/core/search/bm25.js +1 -146
  265. package/dist/core/search/cache.js +2 -534
  266. package/dist/core/search/corpus.js +1 -311
  267. package/dist/core/search/embedding-batches.js +1 -163
  268. package/dist/core/search/eval.js +1 -225
  269. package/dist/core/search/http-client.js +1 -75
  270. package/dist/core/search/providers.js +1 -242
  271. package/dist/core/search/relevance.js +1 -244
  272. package/dist/core/search/semantic-defaults.js +1 -199
  273. package/dist/core/search/staleness.js +1 -30
  274. package/dist/core/search/vector-stores.js +2 -664
  275. package/dist/core/search/vectorization-metadata.js +1 -81
  276. package/dist/core/sentry/helpers.js +1 -272
  277. package/dist/core/sentry/instrument.js +1 -387
  278. package/dist/core/session/session-state.js +1 -260
  279. package/dist/core/shared/agent-session-context.js +1 -133
  280. package/dist/core/shared/author.js +1 -1172
  281. package/dist/core/shared/command-types.js +1 -4
  282. package/dist/core/shared/conflict-markers.js +1 -31
  283. package/dist/core/shared/constants.js +1 -405
  284. package/dist/core/shared/errors.js +1 -20
  285. package/dist/core/shared/html-entity-decode.js +1 -131
  286. package/dist/core/shared/index.js +1 -12
  287. package/dist/core/shared/item-metadata-contract.js +1 -89
  288. package/dist/core/shared/lazy-module.js +1 -16
  289. package/dist/core/shared/levenshtein.js +1 -61
  290. package/dist/core/shared/memo.js +1 -19
  291. package/dist/core/shared/numeric-parsers.js +1 -20
  292. package/dist/core/shared/option-alias-visibility.js +1 -67
  293. package/dist/core/shared/primitives.js +1 -127
  294. package/dist/core/shared/serial-queue.js +1 -79
  295. package/dist/core/shared/serialization.js +1 -210
  296. package/dist/core/shared/split-comma-list.js +1 -30
  297. package/dist/core/shared/text-normalization.js +1 -38
  298. package/dist/core/shared/time.js +1 -306
  299. package/dist/core/store/index.js +1 -12
  300. package/dist/core/store/item-format-migration.js +1 -125
  301. package/dist/core/store/item-metadata-cache.js +1 -1116
  302. package/dist/core/store/item-metadata-query-index.js +9 -394
  303. package/dist/core/store/item-metadata-read-work.js +1 -43
  304. package/dist/core/store/item-store.js +1 -693
  305. package/dist/core/store/paths.d.ts +1 -1
  306. package/dist/core/store/paths.js +1 -214
  307. package/dist/core/store/settings-read-cache.js +1 -85
  308. package/dist/core/store/settings-validator.d.ts +1 -0
  309. package/dist/core/store/settings-validator.js +1 -421
  310. package/dist/core/store/settings.js +3 -1309
  311. package/dist/core/store/tracker-preflight.js +1 -141
  312. package/dist/core/telemetry/consent.js +5 -108
  313. package/dist/core/telemetry/observability.js +1 -246
  314. package/dist/core/telemetry/runtime.js +4 -1988
  315. package/dist/core/test/background-runs.js +4 -945
  316. package/dist/core/test/item-test-run-tracking.js +1 -63
  317. package/dist/core/test/run-selectors.js +1 -120
  318. package/dist/core/validate/estimate-defaults.js +1 -89
  319. package/dist/core/validate/fix-planning.js +1 -189
  320. package/dist/core/validate/linked-artifact-reference.js +1 -36
  321. package/dist/core/validate/missing-by-type.js +1 -34
  322. package/dist/core/validate/missing-link-owners.js +1 -95
  323. package/dist/core/validate/stale-file-classification.js +1 -82
  324. package/dist/mcp/http-server.js +5 -448
  325. package/dist/mcp/legacy-adapter.js +1 -77
  326. package/dist/mcp/runtime-capabilities.js +1 -200
  327. package/dist/mcp/server.js +4 -1233
  328. package/dist/mcp/tool-definitions.js +1 -804
  329. package/dist/sdk/actionability.js +1 -13
  330. package/dist/sdk/agent/closed-domain-contracts.js +1 -161
  331. package/dist/sdk/agent/command-recovery.js +1 -59
  332. package/dist/sdk/agent/command-suggestions.js +1 -66
  333. package/dist/sdk/agent/create-option-policy.js +1 -31
  334. package/dist/sdk/agent/identity-config.js +1 -106
  335. package/dist/sdk/agent/item-addressing.js +1 -207
  336. package/dist/sdk/agent/refusal-closure-census.js +1 -151
  337. package/dist/sdk/agent/refusal-closure.js +1 -133
  338. package/dist/sdk/agent/refusal-corpus-contracts.js +1 -193
  339. package/dist/sdk/agent/refusal-reachability.js +1 -593
  340. package/dist/sdk/agent/subcommand-recovery.js +1 -83
  341. package/dist/sdk/agent/task-transcript-contracts.js +1 -197
  342. package/dist/sdk/agent/tracker-preflight-contracts.js +1 -126
  343. package/dist/sdk/agent-capability-contracts.js +1 -428
  344. package/dist/sdk/agent-session-context.js +1 -9
  345. package/dist/sdk/annotations.js +1 -448
  346. package/dist/sdk/author-attribution.js +1 -468
  347. package/dist/sdk/authoring.js +1 -20
  348. package/dist/sdk/cli-bootstrap.js +1 -838
  349. package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +1 -1
  350. package/dist/sdk/cli-contracts/agent-output-contracts.js +4 -476
  351. package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -79
  352. package/dist/sdk/cli-contracts/command-aliases.d.ts +4 -0
  353. package/dist/sdk/cli-contracts/command-aliases.js +1 -107
  354. package/dist/sdk/cli-contracts/command-exit-contracts.js +1 -151
  355. package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1081
  356. package/dist/sdk/cli-contracts/commander-types.js +1 -159
  357. package/dist/sdk/cli-contracts/completeness.js +1 -393
  358. package/dist/sdk/cli-contracts/enum-contracts.d.ts +1 -1
  359. package/dist/sdk/cli-contracts/enum-contracts.js +1 -222
  360. package/dist/sdk/cli-contracts/flag-contracts.js +1 -1947
  361. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -347
  362. package/dist/sdk/cli-contracts/grammar-contracts.js +1 -986
  363. package/dist/sdk/cli-contracts/registration-helpers.js +7 -990
  364. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +5 -0
  365. package/dist/sdk/cli-contracts/runtime-contracts.js +1 -2090
  366. package/dist/sdk/cli-contracts/schemas/assurance-definition.js +1 -324
  367. package/dist/sdk/cli-contracts/string-lists.js +1 -16
  368. package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -461
  369. package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -2167
  370. package/dist/sdk/cli-contracts/tool-schema.d.ts +3 -1
  371. package/dist/sdk/cli-contracts/tool-schema.js +1 -1664
  372. package/dist/sdk/cli-contracts/typed-action-inputs.js +1 -4
  373. package/dist/sdk/cli-contracts.d.ts +1 -1
  374. package/dist/sdk/cli-contracts.js +1 -17
  375. package/dist/sdk/cli-program.js +1 -49
  376. package/dist/sdk/command-line.d.ts +2 -5
  377. package/dist/sdk/command-line.js +1 -78
  378. package/dist/sdk/comments.js +1 -133
  379. package/dist/sdk/compile-cache.js +1 -73
  380. package/dist/sdk/completion.js +174 -839
  381. package/dist/sdk/compose.js +1 -1090
  382. package/dist/sdk/config.js +1 -1204
  383. package/dist/sdk/context/recency.js +1 -33
  384. package/dist/sdk/context/semantic-session-attribution.js +1 -82
  385. package/dist/sdk/context/usage-egress.js +1 -29
  386. package/dist/sdk/context/usage-ledger.js +3 -185
  387. package/dist/sdk/context-intent-contracts.js +1 -709
  388. package/dist/sdk/context-intent-runtime.js +1 -115
  389. package/dist/sdk/context-packing.js +1 -218
  390. package/dist/sdk/context-relevance.js +1 -503
  391. package/dist/sdk/context-signal-store.js +2 -426
  392. package/dist/sdk/context-usage.js +1 -367
  393. package/dist/sdk/contracts.js +1 -23
  394. package/dist/sdk/core-governance.js +1 -14
  395. package/dist/sdk/core.js +1 -14
  396. package/dist/sdk/corpus-shape.js +1 -401
  397. package/dist/sdk/define.js +1 -220
  398. package/dist/sdk/dependencies.js +1 -718
  399. package/dist/sdk/dependency-flag-validation.js +1 -156
  400. package/dist/sdk/dependency-provenance.js +1 -135
  401. package/dist/sdk/docs.js +1 -14
  402. package/dist/sdk/duplicates.js +1 -40
  403. package/dist/sdk/environment/agent-environment.js +1 -466
  404. package/dist/sdk/environment/host-environment-errors.js +1 -8
  405. package/dist/sdk/environment/project-runtime-compatibility.js +1 -481
  406. package/dist/sdk/environment/source-context.js +1 -28
  407. package/dist/sdk/environment/tracker-preflight.js +1 -9
  408. package/dist/sdk/error-code-catalog.js +1 -153
  409. package/dist/sdk/error-runtime.js +1 -58
  410. package/dist/sdk/errors.js +1 -58
  411. package/dist/sdk/eval.js +1 -190
  412. package/dist/sdk/extension/author-manifest.js +1 -92
  413. package/dist/sdk/extension/bundled-catalog.js +1 -332
  414. package/dist/sdk/extension/concurrency.js +1 -25
  415. package/dist/sdk/extension/copy-scope.d.ts +2 -0
  416. package/dist/sdk/extension/copy-scope.js +2 -0
  417. package/dist/sdk/extension/custom-field-collisions.js +1 -30
  418. package/dist/sdk/extension/describe.js +3 -189
  419. package/dist/sdk/extension/doctor.js +1 -606
  420. package/dist/sdk/extension/install-plan.d.ts +69 -0
  421. package/dist/sdk/extension/install-plan.js +2 -0
  422. package/dist/sdk/extension/install-receipts.d.ts +7 -0
  423. package/dist/sdk/extension/install-receipts.js +2 -0
  424. package/dist/sdk/extension/install-runtime.js +3 -313
  425. package/dist/sdk/extension/install-snapshot.js +1 -66
  426. package/dist/sdk/extension/install-sources.js +5 -1057
  427. package/dist/sdk/extension/managed-state.js +2 -252
  428. package/dist/sdk/extension/migrations.js +2 -174
  429. package/dist/sdk/extension/output-ownership.js +1 -25
  430. package/dist/sdk/extension/runtime-summary.js +1 -18
  431. package/dist/sdk/extension/scaffold.js +4 -2308
  432. package/dist/sdk/extension/shared.js +1 -147
  433. package/dist/sdk/extension/source-resolution.js +1 -65
  434. package/dist/sdk/extension/update-check.js +1 -67
  435. package/dist/sdk/extension-command-context.js +1 -44
  436. package/dist/sdk/extension-contracts.js +1 -73
  437. package/dist/sdk/extension.d.ts +7 -2
  438. package/dist/sdk/extension.js +1 -2196
  439. package/dist/sdk/files.js +1 -535
  440. package/dist/sdk/flag-invocation-contracts.d.ts +0 -5
  441. package/dist/sdk/flag-invocation-contracts.js +1 -344
  442. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -2224
  443. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -2236
  444. package/dist/sdk/generated-error-code-catalog.js +1 -16
  445. package/dist/sdk/governance/assurance-action-contracts.js +1 -4
  446. package/dist/sdk/governance/assurance-action.js +1 -411
  447. package/dist/sdk/governance/assurance-limits.js +1 -10
  448. package/dist/sdk/governance/assurance-mutation-error.js +1 -81
  449. package/dist/sdk/governance/assurance-presets.js +1 -135
  450. package/dist/sdk/governance/assurance-runtime.js +1 -238
  451. package/dist/sdk/governance/assurance.js +4 -1182
  452. package/dist/sdk/governance/boundary-fixtures.js +1 -200
  453. package/dist/sdk/governance/coverage-assurance.js +1 -60
  454. package/dist/sdk/governance/defect-recurrence-coverage.js +1 -188
  455. package/dist/sdk/governance/defect-recurrence-graph.js +1 -120
  456. package/dist/sdk/governance/defect-recurrence-signals.js +1 -24
  457. package/dist/sdk/governance/defect-recurrence.js +1 -623
  458. package/dist/sdk/governance/extension-host-version.js +1 -115
  459. package/dist/sdk/governance/gc.js +1 -368
  460. package/dist/sdk/governance/health.js +1 -2367
  461. package/dist/sdk/governance/hierarchy-validation.js +1 -108
  462. package/dist/sdk/governance/linked-file-report.js +1 -71
  463. package/dist/sdk/governance/merge-receipt-history.js +1 -206
  464. package/dist/sdk/governance/provenance-health.js +1 -282
  465. package/dist/sdk/governance/reindex.js +4 -761
  466. package/dist/sdk/governance/stale-work.js +1 -82
  467. package/dist/sdk/governance/status-role-diagnostics.js +1 -35
  468. package/dist/sdk/governance/storage-integrity.js +1 -280
  469. package/dist/sdk/governance/tracked-runtime-cache.js +1 -106
  470. package/dist/sdk/governance/upgrade.js +2 -327
  471. package/dist/sdk/governance/validate-history-drift.js +1 -81
  472. package/dist/sdk/governance/validate-item-reader.js +1 -17
  473. package/dist/sdk/governance/validate-normalization.js +1 -36
  474. package/dist/sdk/governance/validate.d.ts +3 -1
  475. package/dist/sdk/governance/validate.js +1 -2261
  476. package/dist/sdk/governance/workflow-completeness.d.ts +32 -0
  477. package/dist/sdk/governance/workflow-completeness.js +2 -0
  478. package/dist/sdk/governance/workflow-policy.d.ts +47 -0
  479. package/dist/sdk/governance/workflow-policy.js +4 -0
  480. package/dist/sdk/governance/workspace-position.js +1 -163
  481. package/dist/sdk/governance.d.ts +2 -0
  482. package/dist/sdk/governance.js +1 -31
  483. package/dist/sdk/graph/adapter.js +1 -181
  484. package/dist/sdk/graph/analytics.js +1 -474
  485. package/dist/sdk/graph/assembly.js +1 -377
  486. package/dist/sdk/graph/cache.js +1 -160
  487. package/dist/sdk/graph/centrality.js +1 -258
  488. package/dist/sdk/graph/conformance.js +1 -130
  489. package/dist/sdk/graph/deadline-scheduling.d.ts +90 -0
  490. package/dist/sdk/graph/deadline-scheduling.js +2 -0
  491. package/dist/sdk/graph/durable-cache.d.ts +1 -1
  492. package/dist/sdk/graph/durable-cache.js +1 -361
  493. package/dist/sdk/graph/governance-contracts.js +1 -34
  494. package/dist/sdk/graph/governance.d.ts +13 -1
  495. package/dist/sdk/graph/governance.js +1 -735
  496. package/dist/sdk/graph/hierarchy-integrity.js +1 -310
  497. package/dist/sdk/graph/index.d.ts +3 -2
  498. package/dist/sdk/graph/index.js +1 -26
  499. package/dist/sdk/graph/lifecycle-coverage.d.ts +32 -0
  500. package/dist/sdk/graph/lifecycle-coverage.js +2 -0
  501. package/dist/sdk/graph/mutation-advisory.js +1 -176
  502. package/dist/sdk/graph/remediation.js +1 -197
  503. package/dist/sdk/graph/run.d.ts +15 -1
  504. package/dist/sdk/graph/run.js +1 -768
  505. package/dist/sdk/graph/scheduling.js +1 -124
  506. package/dist/sdk/graph/traversal.js +1 -284
  507. package/dist/sdk/graph/workspace-relationship-kind-registry.js +1 -27
  508. package/dist/sdk/graph.js +1 -15
  509. package/dist/sdk/guide-topics.js +1 -707
  510. package/dist/sdk/guide.js +1 -279
  511. package/dist/sdk/history/maintenance.d.ts +71 -0
  512. package/dist/sdk/history/maintenance.js +2 -0
  513. package/dist/sdk/history/salvage.js +2 -247
  514. package/dist/sdk/history/subject.d.ts +19 -0
  515. package/dist/sdk/history/subject.js +2 -0
  516. package/dist/sdk/history-analytics.js +1 -282
  517. package/dist/sdk/history-compact.js +1 -527
  518. package/dist/sdk/history-mcp.js +1 -68
  519. package/dist/sdk/history-provenance.js +1 -182
  520. package/dist/sdk/history-read.js +1 -96
  521. package/dist/sdk/history-redact.d.ts +1 -14
  522. package/dist/sdk/history-redact.js +1 -643
  523. package/dist/sdk/history-repair.d.ts +5 -0
  524. package/dist/sdk/history-repair.js +1 -657
  525. package/dist/sdk/improvement-ledger-validation.js +1 -62
  526. package/dist/sdk/improvement-ledger.js +2 -257
  527. package/dist/sdk/index.d.ts +4 -1
  528. package/dist/sdk/index.js +1 -183
  529. package/dist/sdk/init-agent-guidance.js +2 -496
  530. package/dist/sdk/init.js +2 -820
  531. package/dist/sdk/invocation-author.js +1 -39
  532. package/dist/sdk/item-children.js +1 -90
  533. package/dist/sdk/item-metadata-index.js +1 -15
  534. package/dist/sdk/item-schedule.js +1 -27
  535. package/dist/sdk/item-transaction.js +1 -396
  536. package/dist/sdk/learnings.js +1 -29
  537. package/dist/sdk/lifecycle/append.js +2 -53
  538. package/dist/sdk/lifecycle/claim.d.ts +2 -0
  539. package/dist/sdk/lifecycle/claim.js +1 -242
  540. package/dist/sdk/lifecycle/close-many.js +1 -438
  541. package/dist/sdk/lifecycle/close.js +1 -468
  542. package/dist/sdk/lifecycle/copy.js +1 -212
  543. package/dist/sdk/lifecycle/create.js +1 -1949
  544. package/dist/sdk/lifecycle/delete.js +1 -45
  545. package/dist/sdk/lifecycle/event-validation-messages.js +1 -91
  546. package/dist/sdk/lifecycle/focus.js +1 -91
  547. package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -24
  548. package/dist/sdk/lifecycle/legacy-none-tokens.js +1 -149
  549. package/dist/sdk/lifecycle/lifecycle-transitions.js +1 -40
  550. package/dist/sdk/lifecycle/mcp-actions.d.ts +2 -0
  551. package/dist/sdk/lifecycle/mcp-actions.js +1 -51
  552. package/dist/sdk/lifecycle/metadata-normalizers.js +1 -46
  553. package/dist/sdk/lifecycle/mutation-command-options.js +1 -9
  554. package/dist/sdk/lifecycle/plan.js +1 -1606
  555. package/dist/sdk/lifecycle/recurrence-parsers.d.ts +1 -1
  556. package/dist/sdk/lifecycle/recurrence-parsers.js +1 -147
  557. package/dist/sdk/lifecycle/reopen.js +1 -68
  558. package/dist/sdk/lifecycle/repeatable-metadata-parsers.js +1 -143
  559. package/dist/sdk/lifecycle/restore.d.ts +1 -0
  560. package/dist/sdk/lifecycle/restore.js +1 -330
  561. package/dist/sdk/lifecycle/shared-unset-fields.js +1 -295
  562. package/dist/sdk/lifecycle/update-many.js +1 -861
  563. package/dist/sdk/lifecycle/update.js +1 -2136
  564. package/dist/sdk/lifecycle-completion.js +1 -92
  565. package/dist/sdk/lifecycle-policy.js +1 -120
  566. package/dist/sdk/linked-artifacts.js +1 -530
  567. package/dist/sdk/mcp/apps.js +4 -133
  568. package/dist/sdk/mcp/authorization.js +1 -404
  569. package/dist/sdk/mcp/discovery.js +1 -494
  570. package/dist/sdk/mcp/interactions.js +1 -336
  571. package/dist/sdk/mcp/protocol.d.ts +7 -0
  572. package/dist/sdk/mcp/protocol.js +1 -184
  573. package/dist/sdk/mcp/skills.js +1 -389
  574. package/dist/sdk/mcp/subscriptions.js +1 -211
  575. package/dist/sdk/mcp/tasks.js +2 -430
  576. package/dist/sdk/mcp/transport.js +1 -260
  577. package/dist/sdk/merge/abandoned-receipts.js +1 -46
  578. package/dist/sdk/merge/driver.js +1 -212
  579. package/dist/sdk/merge/index.js +1 -16
  580. package/dist/sdk/merge/install.js +3 -561
  581. package/dist/sdk/merge/receipt-file-boundary.js +1 -46
  582. package/dist/sdk/merge/receipt-operation.js +1 -96
  583. package/dist/sdk/merge/receipt-schema.js +1 -397
  584. package/dist/sdk/merge/receipts.js +4 -525
  585. package/dist/sdk/merge/reconcile.js +1 -352
  586. package/dist/sdk/merge/three-way.js +3 -775
  587. package/dist/sdk/merge.js +1 -10
  588. package/dist/sdk/mutation-events.js +1 -292
  589. package/dist/sdk/mutation-guard.js +1 -216
  590. package/dist/sdk/notes.js +1 -139
  591. package/dist/sdk/output-contracts.js +1 -172
  592. package/dist/sdk/output-projection.js +1 -430
  593. package/dist/sdk/output-token-accounting.js +1 -140
  594. package/dist/sdk/output.js +1 -64
  595. package/dist/sdk/ownership-source.js +1 -21
  596. package/dist/sdk/package-import-adapters.js +1 -442
  597. package/dist/sdk/package-migrations.js +1 -20
  598. package/dist/sdk/package-runtime-options.js +1 -80
  599. package/dist/sdk/pagination.js +1 -162
  600. package/dist/sdk/profile.js +1 -454
  601. package/dist/sdk/provenance.js +1 -258
  602. package/dist/sdk/public-surface.json +1 -1
  603. package/dist/sdk/query/activity.js +1 -401
  604. package/dist/sdk/query/aggregate.d.ts +16 -0
  605. package/dist/sdk/query/aggregate.js +1 -390
  606. package/dist/sdk/query/calendar.js +1 -964
  607. package/dist/sdk/query/complete-list.js +1 -215
  608. package/dist/sdk/query/context.js +1 -1702
  609. package/dist/sdk/query/duplicate-candidates.js +1 -70
  610. package/dist/sdk/query/get.js +1 -450
  611. package/dist/sdk/query/history.js +1 -186
  612. package/dist/sdk/query/item-filter-options.js +1 -9
  613. package/dist/sdk/query/light-metadata.js +1 -18
  614. package/dist/sdk/query/list-filter-shared.js +1 -81
  615. package/dist/sdk/query/list.js +1 -1304
  616. package/dist/sdk/query/multi-value-filters.js +1 -78
  617. package/dist/sdk/query/next.js +1 -513
  618. package/dist/sdk/query/parsers.js +1 -44
  619. package/dist/sdk/query/projection-contracts.js +1 -184
  620. package/dist/sdk/query/search-contracts.d.ts +27 -0
  621. package/dist/sdk/query/search-contracts.js +1 -230
  622. package/dist/sdk/query/search-pagination.js +1 -35
  623. package/dist/sdk/query/search-rendering.js +1 -105
  624. package/dist/sdk/query/search.d.ts +6 -4
  625. package/dist/sdk/query/search.js +2 -1987
  626. package/dist/sdk/query.js +1 -35
  627. package/dist/sdk/read-output/continuation.js +1 -194
  628. package/dist/sdk/read-output-budget.js +1 -135
  629. package/dist/sdk/read-output-contracts.d.ts +1 -1
  630. package/dist/sdk/read-output-contracts.js +1 -1225
  631. package/dist/sdk/read-output-rows.js +1 -186
  632. package/dist/sdk/read-output-session.js +1 -208
  633. package/dist/sdk/relationship-analytics.js +1 -410
  634. package/dist/sdk/relationship-context.js +1 -284
  635. package/dist/sdk/relationship-history.js +4 -519
  636. package/dist/sdk/relationship-kinds/contract.js +1 -22
  637. package/dist/sdk/relationship-migration.js +1 -77
  638. package/dist/sdk/relationships.js +1 -579
  639. package/dist/sdk/reproducibility/process.js +1 -87
  640. package/dist/sdk/runtime-action-aliases.js +1 -59
  641. package/dist/sdk/runtime-extended-actions.js +1 -177
  642. package/dist/sdk/runtime-input.js +1 -614
  643. package/dist/sdk/runtime-primitives.js +1 -84
  644. package/dist/sdk/runtime-public-contracts.d.ts +2 -1
  645. package/dist/sdk/runtime-public-contracts.js +1 -4
  646. package/dist/sdk/runtime-stats-options.js +1 -38
  647. package/dist/sdk/runtime.d.ts +4 -0
  648. package/dist/sdk/runtime.js +1 -1928
  649. package/dist/sdk/scheduling-shortcuts.js +1 -63
  650. package/dist/sdk/schema-migration.js +3 -856
  651. package/dist/sdk/schema.d.ts +2 -1
  652. package/dist/sdk/schema.js +1 -1376
  653. package/dist/sdk/search-refresh-worker.js +1 -18
  654. package/dist/sdk/similarity-scoring.js +1 -53
  655. package/dist/sdk/similarity.js +1 -326
  656. package/dist/sdk/start-task-status.js +1 -14
  657. package/dist/sdk/stats.js +1 -270
  658. package/dist/sdk/structured-mutations.js +1 -580
  659. package/dist/sdk/telemetry-flush.js +1 -13
  660. package/dist/sdk/telemetry.js +1 -405
  661. package/dist/sdk/templates.js +2 -292
  662. package/dist/sdk/test/batch.js +2 -509
  663. package/dist/sdk/test/entry.js +1 -70
  664. package/dist/sdk/test/execution.js +6 -2211
  665. package/dist/sdk/test/linked-command-detection.js +1 -546
  666. package/dist/sdk/test/measurements.js +1 -91
  667. package/dist/sdk/test/parsers.js +1 -545
  668. package/dist/sdk/test/runs.js +1 -193
  669. package/dist/sdk/test/trust.js +2 -206
  670. package/dist/sdk/testing.js +4 -1391
  671. package/dist/sdk/traceability/runtime-files-lookup.js +1 -32
  672. package/dist/sdk/traceability/source-traceability.js +1 -292
  673. package/dist/sdk/tracker-root-discovery.js +1 -9
  674. package/dist/sdk/workspace-contracts-cache.js +1 -28
  675. package/dist/sdk/workspace-contracts.js +1 -33
  676. package/dist/sdk/workspace-memory.js +2 -318
  677. package/dist/sdk/workspace-recipe.js +1 -71
  678. package/dist/sdk/workspace-snapshot.js +4 -613
  679. package/dist/sdk/workspace-transaction-gc.js +1 -149
  680. package/dist/sdk/workspace-transaction.js +2 -363
  681. package/dist/sdk/workspace.js +3 -127
  682. package/dist/types/index.js +1 -9
  683. package/dist/types.d.ts +4 -0
  684. package/dist/types.js +1 -245
  685. package/docs/AGENT_GUIDE.md +1 -1
  686. package/docs/COMMANDS.md +10 -0
  687. package/docs/CONFIGURATION.md +12 -1
  688. package/docs/CONTEXT_ALGORITHM_PORTFOLIO.md +167 -0
  689. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +9 -3
  690. package/docs/EXTENSIONS.md +1 -0
  691. package/docs/HISTORY_MAINTENANCE.md +125 -0
  692. package/docs/MCP_2026_07_28_CONFORMANCE.md +20 -10
  693. package/docs/PACKAGE_EVIDENCE.md +92 -0
  694. package/docs/PLANNING_MEASUREMENTS.md +183 -0
  695. package/docs/README.md +4 -0
  696. package/docs/READ_OUTPUT_CONTRACTS.md +5 -0
  697. package/docs/SCRIPTING.md +21 -0
  698. package/docs/TESTING.md +33 -0
  699. package/docs/WORKFLOW_POLICIES.md +129 -0
  700. package/docs/generated/FLAG_LEXICON_BUDGETS.md +7 -7
  701. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +11 -5
  702. package/marketplace.json +2 -2
  703. package/package.json +5 -5
  704. package/packages/pm-beads/package.json +1 -1
  705. package/packages/pm-calendar/package.json +1 -1
  706. package/packages/pm-command-kit/package.json +1 -1
  707. package/packages/pm-digital-twin/package.json +1 -1
  708. package/packages/pm-governance-audit/package.json +1 -1
  709. package/packages/pm-guide-shell/package.json +1 -1
  710. package/packages/pm-kanban/package.json +1 -1
  711. package/packages/pm-lifecycle-hooks/package.json +1 -1
  712. package/packages/pm-linked-test-adapters/package.json +1 -1
  713. package/packages/pm-search-advanced/package.json +1 -1
  714. package/packages/pm-templates/package.json +1 -1
  715. package/packages/pm-todos/package.json +1 -1
  716. package/packages/pm-vcs/package.json +1 -1
  717. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  718. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  719. package/scripts/finalize-build.mjs +45 -3
  720. package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +0 -9
  721. package/dist/cli-bundle/chunks/chunk-CKOL5U7J.js +0 -77
  722. package/dist/cli-bundle/chunks/chunk-JX4DH4WC.js +0 -3
  723. package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +0 -5
  724. package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +0 -232
  725. package/dist/cli-bundle/chunks/chunk-QWRRFYK3.js +0 -2
  726. package/dist/cli-bundle/chunks/chunk-RWWBOWJ5.js +0 -2
  727. package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +0 -40
  728. package/dist/cli-bundle/chunks/chunk-WI2AYPA7.js +0 -2
  729. package/dist/cli-bundle/chunks/register-list-query-5JL52D33.js +0 -11
  730. package/dist/cli-bundle/chunks/register-mutation-ZPG7KMVP.js +0 -20
  731. package/dist/cli-bundle/chunks/register-operations-I5W3KMGB.js +0 -2
  732. package/dist/cli-bundle/chunks/register-setup-H4SVAVX7.js +0 -2
  733. package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +0 -2
  734. package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +0 -6
  735. package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +0 -20
  736. package/dist/cli-bundle/focused-chunks/chunk-EZR3GHFE.js +0 -2
  737. package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +0 -56
  738. package/dist/cli-bundle/focused-chunks/chunk-NTPY5GSO.js +0 -3
  739. package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +0 -2
  740. package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +0 -177
  741. package/dist/cli-bundle/focused-chunks/chunk-PEFABF7E.js +0 -26
  742. package/dist/cli-bundle/focused-chunks/chunk-QTVCLMSZ.js +0 -6
  743. package/dist/cli-bundle/focused-chunks/chunk-QTZRBUYA.js +0 -8
  744. package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +0 -12
  745. package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +0 -10
  746. package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +0 -2
@@ -1,2224 +1,2 @@
1
- /**
2
- * @module core/extensions/loader
3
- *
4
- * Implements extension runtime contracts and governance for Loader.
5
- */
6
-
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e4e1b7c2-6551-5e56-b26a-30062aed5b97")}catch(e){}}();
8
- import fs from "node:fs/promises";
9
- import path from "node:path";
10
- import { pathToFileURL } from "node:url";
11
- import { pathExists } from "../fs/fs-utils.js";
12
- import { isPathWithinDirectory } from "../fs/path-utils.js";
13
- import { isHostOutputSuppressed, suppressHostOutput, } from "../output/output-control.js";
14
- import { resolvePmPackageRootFromModule } from "../packages/root.js";
15
- import { resolveGlobalPmRoot } from "../store/paths.js";
16
- import { asRecordLoose, resolveActivatablePropertyRecord, } from "../shared/primitives.js";
17
- import { flattenFlagListValue, isFlagDefaultValueCoercible, resolveFlagValueKind, } from "./flag-value-types.js";
18
- import { KNOWN_ITEM_FIELD_TYPES, normalizeItemFieldType, suggestKnownItemFieldType, } from "./item-field-types.js";
19
- import { snapshotExtensionModuleGraph } from "./module-graph-snapshot.js";
20
- import { captureExtensionActivationRollback } from "./activation-transaction.js";
21
- import { collectPreflightCollisionWarnings, normalizePreflightOverride, } from "./preflight-ownership.js";
22
- import { normalizeServiceOverrideOwnership } from "./service-ownership.js";
23
- import { assertCommandDefinitionMetadataStrings } from "./command-visibility-tier.js";
24
- import { buildImportExportContext, resolveImportExportArtifactOutput, } from "./exporter-output-contract.js";
25
- import { asRegistrationRecord, assertOptionalBooleanField, assertOptionalFlagDefaultField, assertOptionalStringArrayField, assertOptionalStringField, normalizeOptionalStringArrayField, } from "./registration-validation.js";
26
- import { describeExtensionLongFlagFailure, findExtensionFlagTokenFailure, } from "./flag-definition-validation.js";
27
- import { compareComparableVersions, evaluatePmMaxVersionBound, evaluatePmMinVersionBound, parseComparableVersion, } from "./version-compat.js";
28
- import { createRelationshipKindRegistry, } from "../../sdk/relationships.js";
29
- import { normalizeNames, isKnownExtensionCapability, collectUnknownExtensionCapabilities, normalizeManifestCapabilities, formatUnknownExtensionCapabilityWarning, formatLegacyExtensionCapabilityAliasWarning, } from "./extension-capability-aliases.js";
30
- import { normalizeExtensionPolicy, serializeExtensionPolicy, hydrateExtensionPolicy, normalizePolicySandboxProfile, evaluateExtensionPolicyForExtension, evaluateExtensionPolicyForCapability, evaluateExtensionPolicyForRegistration, } from "./extension-policy.js";
31
- import { createEmptyExtensionHookRegistry, createEmptyExtensionCommandRegistry, createEmptyExtensionParserRegistry, createEmptyExtensionPreflightRegistry, createEmptyExtensionServiceRegistry, createEmptyExtensionRendererRegistry, createEmptyExtensionRegistrationRegistry, } from "./extension-registries.js";
32
- import { normalizeCommandName } from "./extension-runtime-helpers.js";
33
- import { normalizeExtensionContributionInventory } from "./contribution-inventory.js";
34
- import { formatExtensionManifestSchemaWarnings } from "./manifest-schema.js";
35
- import { attachRuntimeDefinition, assertHookHandler, assertNonEmptyRegistrationString, assertRegistrationFunction, cloneRuntimeRegistrationValue, createRegistrationValidationError, extractRegistrationValidationTrace, isExtensionServiceName, isOutputRendererFormat, normalizeRegistrationRecord, normalizeRegistrationRecordList, normalizeRuntimeRegistrationRecord, normalizeRegistrationName, sanitizeRegistrationValue, toRegistrationCommandPath, validateAssuranceMeasurementProviderDefinition, } from "./registration-values.js";
36
- import { buildReadyExtensionCandidate, } from "./extension-candidate.js";
37
- export { parseUnknownExtensionCapabilityWarning, parseLegacyExtensionCapabilityAliasWarning, } from "./extension-capability-aliases.js";
38
- export { createEmptyExtensionHookRegistry, createEmptyExtensionCommandRegistry, createEmptyExtensionParserRegistry, createEmptyExtensionPreflightRegistry, createEmptyExtensionServiceRegistry, createEmptyExtensionRendererRegistry, createEmptyExtensionRegistrationRegistry, } from "./extension-registries.js";
39
- export { runBeforeCommandHooks, runBeforeMutationHooks, runAfterCommandHooks, runOnWriteHooks, runOnReadHooks, runOnIndexHooks, runCommandHandler, runParserOverride, runPreflightOverride, runServiceOverrideSync, runServiceOverride, runCommandOverride, runRendererOverride, } from "./extension-hook-runtime.js";
40
- import { KNOWN_EXTENSION_CAPABILITIES, KNOWN_EXTENSION_SERVICE_NAMES, createDefaultExtensionGovernancePolicy, } from "./extension-types.js";
41
- export * from "./extension-types.js";
42
- /** Fallback extension priority used when callers do not provide an override. */
43
- export const DEFAULT_EXTENSION_PRIORITY = 100;
44
- let currentPmCliVersionPromise = null;
45
- const DEFAULT_EXTENSION_POLICY = Object.freeze(createDefaultExtensionGovernancePolicy());
46
- let extensionReloadEpoch = 0;
47
- /** Implements next extension reload token for the public runtime surface of this module. */
48
- export function nextExtensionReloadToken(seed = Date.now()) {
49
- extensionReloadEpoch += 1;
50
- return `${extensionReloadEpoch}-${seed}`;
51
- }
52
- function parseOptionalManifestString(candidate, field) {
53
- const value = candidate[field];
54
- if (value === undefined || value === null) {
55
- return undefined;
56
- }
57
- if (typeof value !== "string" || value.trim().length === 0) {
58
- return null;
59
- }
60
- return value.trim();
61
- }
62
- function parseManifestEngines(value) {
63
- if (value === undefined || value === null) {
64
- return undefined;
65
- }
66
- const enginesRecord = asRecordLoose(value);
67
- if (!enginesRecord) {
68
- return null;
69
- }
70
- const engines = {};
71
- for (const key of Object.keys(enginesRecord).sort((left, right) => left.localeCompare(right))) {
72
- if (key.trim().length === 0) {
73
- return null;
74
- }
75
- const engineValue = enginesRecord[key];
76
- if (typeof engineValue !== "string" || engineValue.trim().length === 0) {
77
- return null;
78
- }
79
- engines[key.trim()] = engineValue.trim();
80
- }
81
- return Object.keys(engines).length > 0 ? engines : undefined;
82
- }
83
- /** Parse a required manifest string field, returning `null` when it is absent, non-string, or blank. */
84
- function parseRequiredManifestString(candidate, field) {
85
- const value = candidate[field];
86
- if (typeof value !== "string" || value.trim().length === 0) {
87
- return null;
88
- }
89
- return value.trim();
90
- }
91
- /** Parse an optional integer value (`undefined` when absent, `null` when present but not an integer). */
92
- function parseOptionalIntegerValue(value) {
93
- if (value === undefined || value === null) {
94
- return undefined;
95
- }
96
- if (typeof value !== "number" || !Number.isInteger(value)) {
97
- return null;
98
- }
99
- return value;
100
- }
101
- /** Parse an optional boolean value (`undefined` when absent, `null` when present but not a boolean). */
102
- function parseOptionalBooleanValue(value) {
103
- if (value === undefined || value === null) {
104
- return undefined;
105
- }
106
- if (typeof value !== "boolean") {
107
- return null;
108
- }
109
- return value;
110
- }
111
- /** Parse the optional integer `priority`, defaulting to {@link DEFAULT_EXTENSION_PRIORITY} when absent and rejecting (`null`) a non-integer. */
112
- function parseManifestPriority(candidate) {
113
- const value = parseOptionalIntegerValue(candidate.priority);
114
- return value === undefined ? DEFAULT_EXTENSION_PRIORITY : value;
115
- }
116
- /** Parse the optional `sandbox_profile`, rejecting (`null`) any value that does not round-trip through {@link normalizePolicySandboxProfile}. */
117
- function parseManifestSandboxProfile(candidate) {
118
- const value = candidate.sandbox_profile;
119
- if (value === undefined || value === null) {
120
- return undefined;
121
- }
122
- if (typeof value !== "string") {
123
- return null;
124
- }
125
- const normalizedProfile = normalizePolicySandboxProfile(value);
126
- if (normalizedProfile !== value.trim().toLowerCase()) {
127
- return null;
128
- }
129
- return normalizedProfile;
130
- }
131
- /** Return the trimmed string when `value` is a non-blank string, otherwise `undefined`. */
132
- function optionalTrimmedString(value) {
133
- return typeof value === "string" && value.trim().length > 0
134
- ? value.trim()
135
- : undefined;
136
- }
137
- /** Parse the optional `provenance` record (`undefined` absent, `null` malformed), keeping only the present trimmed string fields and a boolean `verified`. */
138
- function parseManifestProvenance(value) {
139
- if (value === undefined || value === null) {
140
- return undefined;
141
- }
142
- const provenanceRecord = asRecordLoose(value);
143
- if (!provenanceRecord) {
144
- return null;
145
- }
146
- const source = optionalTrimmedString(provenanceRecord.source);
147
- const signature = optionalTrimmedString(provenanceRecord.signature);
148
- const attestation = optionalTrimmedString(provenanceRecord.attestation);
149
- const verified = provenanceRecord.verified === undefined ||
150
- provenanceRecord.verified === null
151
- ? undefined
152
- : typeof provenanceRecord.verified === "boolean"
153
- ? provenanceRecord.verified
154
- : null;
155
- if (verified === null) {
156
- return null;
157
- }
158
- return {
159
- ...(source ? { source } : {}),
160
- ...(signature ? { signature } : {}),
161
- ...(attestation ? { attestation } : {}),
162
- ...(typeof verified === "boolean" ? { verified } : {}),
163
- };
164
- }
165
- /** Parse the optional `permissions` record (`undefined` absent, `null` malformed), keeping only the boolean grants that are present. */
166
- function parseManifestPermissions(value) {
167
- if (value === undefined || value === null) {
168
- return undefined;
169
- }
170
- const permissionsRecord = asRecordLoose(value);
171
- if (!permissionsRecord) {
172
- return null;
173
- }
174
- const fsRead = parseOptionalBooleanValue(permissionsRecord.fs_read);
175
- const fsWrite = parseOptionalBooleanValue(permissionsRecord.fs_write);
176
- const network = parseOptionalBooleanValue(permissionsRecord.network);
177
- const envRead = parseOptionalBooleanValue(permissionsRecord.env_read);
178
- const envWrite = parseOptionalBooleanValue(permissionsRecord.env_write);
179
- const processSpawn = parseOptionalBooleanValue(permissionsRecord.process_spawn);
180
- if ([fsRead, fsWrite, network, envRead, envWrite, processSpawn].includes(null)) {
181
- return null;
182
- }
183
- return {
184
- ...(typeof fsRead === "boolean" ? { fs_read: fsRead } : {}),
185
- ...(typeof fsWrite === "boolean" ? { fs_write: fsWrite } : {}),
186
- ...(typeof network === "boolean" ? { network } : {}),
187
- ...(typeof envRead === "boolean" ? { env_read: envRead } : {}),
188
- ...(typeof envWrite === "boolean" ? { env_write: envWrite } : {}),
189
- ...(typeof processSpawn === "boolean"
190
- ? { process_spawn: processSpawn }
191
- : {}),
192
- };
193
- }
194
- /** Parse the optional `capabilities` array, normalizing legacy aliases; returns empty lists when absent and `null` when the field is not a string array. */
195
- function parseManifestCapabilities(value) {
196
- if (value === undefined || value === null) {
197
- return { capabilities: [], legacy_aliases: [] };
198
- }
199
- if (!Array.isArray(value) ||
200
- value.some((entry) => typeof entry !== "string")) {
201
- return null;
202
- }
203
- const normalizedCapabilities = normalizeManifestCapabilities(value);
204
- return {
205
- capabilities: normalizedCapabilities.capabilities,
206
- legacy_aliases: normalizedCapabilities.legacy_aliases,
207
- };
208
- }
209
- /** Parse the optional `activation` block, returning the de-duplicated sorted `commands` set, `undefined` when no command activation is declared, and `null` when the block is malformed. */
210
- function parseManifestActivation(value) {
211
- if (value === undefined || value === null) {
212
- return undefined;
213
- }
214
- const activationRecord = asRecordLoose(value);
215
- if (!activationRecord) {
216
- return null;
217
- }
218
- const rawCommands = activationRecord.commands;
219
- if (rawCommands === undefined || rawCommands === null) {
220
- return undefined;
221
- }
222
- if (!Array.isArray(rawCommands) ||
223
- rawCommands.some((entry) => typeof entry !== "string")) {
224
- return null;
225
- }
226
- const commands = [
227
- ...new Set(rawCommands
228
- .map((entry) => normalizeCommandName(entry))
229
- .filter((entry) => entry.length > 0)),
230
- ].sort((left, right) => left.localeCompare(right));
231
- return commands.length > 0 ? { commands } : undefined;
232
- }
233
- /** Parse every optional manifest metadata field, returning `null` as soon as any one is malformed. */
234
- function parseManifestMetadata(candidate) {
235
- const manifestVersion = parseOptionalIntegerValue(candidate.manifest_version);
236
- if (manifestVersion === null) {
237
- return null;
238
- }
239
- const pmMinVersion = parseOptionalManifestString(candidate, "pm_min_version");
240
- if (pmMinVersion === null) {
241
- return null;
242
- }
243
- const pmMaxVersion = parseOptionalManifestString(candidate, "pm_max_version");
244
- if (pmMaxVersion === null) {
245
- return null;
246
- }
247
- const engines = parseManifestEngines(candidate.engines);
248
- if (engines === null) {
249
- return null;
250
- }
251
- const trusted = parseOptionalBooleanValue(candidate.trusted);
252
- if (trusted === null) {
253
- return null;
254
- }
255
- const sandboxProfile = parseManifestSandboxProfile(candidate);
256
- if (sandboxProfile === null) {
257
- return null;
258
- }
259
- const provenance = parseManifestProvenance(candidate.provenance);
260
- if (provenance === null) {
261
- return null;
262
- }
263
- const permissions = parseManifestPermissions(candidate.permissions);
264
- if (permissions === null) {
265
- return null;
266
- }
267
- const capabilities = parseManifestCapabilities(candidate.capabilities);
268
- if (capabilities === null) {
269
- return null;
270
- }
271
- const activation = parseManifestActivation(candidate.activation);
272
- if (activation === null) {
273
- return null;
274
- }
275
- const contributions = normalizeExtensionContributionInventory(candidate.contributions);
276
- if (contributions === null) {
277
- return null;
278
- }
279
- return {
280
- manifest_version: manifestVersion,
281
- pm_min_version: pmMinVersion,
282
- pm_max_version: pmMaxVersion,
283
- engines,
284
- trusted,
285
- sandbox_profile: sandboxProfile,
286
- provenance,
287
- permissions,
288
- capabilities: capabilities.capabilities,
289
- legacy_capability_aliases: capabilities.legacy_aliases,
290
- activation,
291
- contributions,
292
- };
293
- }
294
- /** Parse and normalize one complete on-disk extension manifest contract. */
295
- export function parseExtensionManifestDocument(raw) {
296
- if (typeof raw !== "object" || raw === null) {
297
- return null;
298
- }
299
- const candidate = raw;
300
- const name = parseRequiredManifestString(candidate, "name");
301
- if (name === null) {
302
- return null;
303
- }
304
- const version = parseRequiredManifestString(candidate, "version");
305
- if (version === null) {
306
- return null;
307
- }
308
- const entry = parseRequiredManifestString(candidate, "entry");
309
- if (entry === null) {
310
- return null;
311
- }
312
- const priority = parseManifestPriority(candidate);
313
- if (priority === null) {
314
- return null;
315
- }
316
- const metadata = parseManifestMetadata(candidate);
317
- if (metadata === null) {
318
- return null;
319
- }
320
- return {
321
- name,
322
- version,
323
- entry,
324
- priority,
325
- manifest_version: metadata.manifest_version,
326
- pm_min_version: metadata.pm_min_version,
327
- pm_max_version: metadata.pm_max_version,
328
- engines: metadata.engines,
329
- trusted: metadata.trusted,
330
- provenance: metadata.provenance,
331
- sandbox_profile: metadata.sandbox_profile,
332
- permissions: metadata.permissions,
333
- activation: metadata.activation,
334
- contributions: metadata.contributions,
335
- capabilities: metadata.capabilities,
336
- legacy_capability_aliases: metadata.legacy_capability_aliases.length > 0
337
- ? metadata.legacy_capability_aliases
338
- : undefined,
339
- };
340
- }
341
- function shouldEnable(name, enabled, disabled) {
342
- if (disabled.has(name)) {
343
- return false;
344
- }
345
- if (enabled.size === 0) {
346
- return true;
347
- }
348
- return enabled.has(name);
349
- }
350
- /** Resolve symlinks on both paths before the containment check so a link inside the directory cannot escape it. */
351
- export async function isCanonicalPathWithinDirectory(directory, targetPath) {
352
- const [resolvedDirectory, resolvedTargetPath] = await Promise.all([
353
- fs.realpath(directory),
354
- fs.realpath(targetPath),
355
- ]);
356
- return isPathWithinDirectory(resolvedDirectory, resolvedTargetPath);
357
- }
358
- /** Implements resolve extension roots for the public runtime surface of this module. */
359
- export function resolveExtensionRoots(pmRoot, cwd = process.cwd()) {
360
- return {
361
- global: path.join(resolveGlobalPmRoot(cwd), "extensions"),
362
- project: path.join(pmRoot, "extensions"),
363
- };
364
- }
365
- async function listExtensionDirectories(extensionsRoot) {
366
- try {
367
- const entries = await fs.readdir(extensionsRoot, { withFileTypes: true });
368
- return entries
369
- .filter((entry) => entry.isDirectory())
370
- .map((entry) => entry.name)
371
- .sort((a, b) => a.localeCompare(b));
372
- }
373
- catch {
374
- return [];
375
- }
376
- }
377
- function summarizeCandidate(candidate) {
378
- const summary = {
379
- layer: candidate.layer,
380
- directory: candidate.directory,
381
- manifest_path: candidate.manifest_path,
382
- name: candidate.manifest.name,
383
- version: candidate.manifest.version,
384
- entry: candidate.manifest.entry,
385
- priority: candidate.manifest.priority,
386
- entry_path: candidate.entry_path,
387
- manifest_version: candidate.manifest.manifest_version,
388
- pm_min_version: candidate.manifest.pm_min_version,
389
- pm_max_version: candidate.manifest.pm_max_version,
390
- engines: candidate.manifest.engines,
391
- trusted: candidate.manifest.trusted,
392
- provenance: candidate.manifest.provenance,
393
- sandbox_profile: candidate.manifest.sandbox_profile,
394
- permissions: candidate.manifest.permissions,
395
- capabilities: [...candidate.manifest.capabilities],
396
- activation: candidate.manifest.activation
397
- ? {
398
- commands: [...candidate.manifest.activation.commands],
399
- }
400
- : undefined,
401
- contributions: candidate.manifest.contributions ?? candidate.contributions,
402
- };
403
- if (candidate.source_package) {
404
- summary.source_package = candidate.source_package;
405
- }
406
- if (candidate.source_aliases) {
407
- summary.source_aliases = [...candidate.source_aliases];
408
- }
409
- return summary;
410
- }
411
- function normalizeManagedSourcePackage(value) {
412
- return typeof value === "string" && value.trim().length > 0
413
- ? value.trim()
414
- : undefined;
415
- }
416
- async function readManagedExtensionSourcePackages(extensionsRoot) {
417
- const packages = new Map();
418
- try {
419
- const parsed = JSON.parse(await fs.readFile(path.join(extensionsRoot, ".managed-extensions.json"), "utf8"));
420
- const managedExtensions = asRecordLoose(parsed);
421
- const entries = managedExtensions?.entries;
422
- if (!Array.isArray(entries)) {
423
- return packages;
424
- }
425
- for (const entry of entries) {
426
- if (typeof entry !== "object" || entry === null) {
427
- continue;
428
- }
429
- const record = entry;
430
- const sourcePackage = normalizeManagedSourcePackage(record.source?.package);
431
- const aliases = [record.source?.input, record.source?.name, sourcePackage]
432
- .map((value) => normalizeManagedSourcePackage(value))
433
- .filter((value) => value !== undefined);
434
- const contributions = normalizeExtensionContributionInventory(record.contributions);
435
- const identity = {
436
- aliases: [...new Set(aliases)],
437
- ...(sourcePackage ? { package_name: sourcePackage } : {}),
438
- ...(contributions ? { contributions } : {}),
439
- };
440
- if (typeof record.directory === "string" &&
441
- record.directory.trim().length > 0) {
442
- packages.set(`directory:${record.directory.trim()}`, identity);
443
- }
444
- if (typeof record.name === "string" && record.name.trim().length > 0) {
445
- packages.set(`name:${record.name.trim()}`, identity);
446
- }
447
- }
448
- }
449
- catch {
450
- return packages;
451
- }
452
- return packages;
453
- }
454
- function sortCandidates(candidates) {
455
- return [...candidates].sort((left, right) => {
456
- if (left.manifest.priority !== right.manifest.priority) {
457
- return left.manifest.priority - right.manifest.priority;
458
- }
459
- const byName = left.manifest.name.localeCompare(right.manifest.name);
460
- if (byName !== 0) {
461
- return byName;
462
- }
463
- return left.directory.localeCompare(right.directory);
464
- });
465
- }
466
- function buildEffectiveExtensions(globalCandidates, projectCandidates) {
467
- const ordered = [
468
- ...sortCandidates(globalCandidates),
469
- ...sortCandidates(projectCandidates),
470
- ];
471
- const effective = [];
472
- for (const candidate of ordered) {
473
- const existingIndex = effective.findIndex((entry) => entry.manifest.name === candidate.manifest.name);
474
- if (existingIndex >= 0) {
475
- effective.splice(existingIndex, 1);
476
- }
477
- effective.push(candidate);
478
- }
479
- return effective;
480
- }
481
- async function scanExtensionLayer(layer, extensionsRoot, enabled, disabled, pmMaxVersionExceededMode) {
482
- const diagnostics = [];
483
- const warnings = [];
484
- const candidates = [];
485
- const directories = await listExtensionDirectories(extensionsRoot);
486
- const managedSourcePackages = await readManagedExtensionSourcePackages(extensionsRoot);
487
- for (const directory of directories) {
488
- const scanned = await scanExtensionDirectory(layer, extensionsRoot, directory, enabled, disabled, managedSourcePackages, pmMaxVersionExceededMode);
489
- diagnostics.push(scanned.diagnostic);
490
- warnings.push(...scanned.warnings);
491
- if (scanned.candidate) {
492
- candidates.push(scanned.candidate);
493
- }
494
- }
495
- return { diagnostics, warnings, candidates };
496
- }
497
- function emptyExtensionLayerScan() {
498
- return { diagnostics: [], warnings: [], candidates: [] };
499
- }
500
- /** Build the `warn`-status scan result for a directory whose manifest is missing or unparseable, carrying the supplied diagnostic warning and no candidate. */
501
- function buildUnavailableExtensionScan(layer, directory, manifestPath, warning) {
502
- return {
503
- diagnostic: {
504
- layer,
505
- directory,
506
- manifest_path: manifestPath,
507
- name: null,
508
- version: null,
509
- entry: null,
510
- priority: null,
511
- entry_path: null,
512
- enabled: null,
513
- status: "warn",
514
- },
515
- warnings: [warning],
516
- candidate: null,
517
- };
518
- }
519
- /** Collect the non-fatal load warnings for a parsed extension manifest, in detection order: legacy capability aliases, unknown capabilities, an entry outside or absent from the extension directory, then the pm version floor/ceiling incompatibility warnings. */
520
- function collectScannedExtensionWarnings(layer, manifest, rawManifest, entryWithinDirectory, entryExists, pmVersionCompatibility, pmMaxVersionCompatibility) {
521
- const extensionWarnings = formatExtensionManifestSchemaWarnings(layer, manifest, rawManifest);
522
- if (Array.isArray(manifest.legacy_capability_aliases) &&
523
- manifest.legacy_capability_aliases.length > 0) {
524
- extensionWarnings.push(formatLegacyExtensionCapabilityAliasWarning(layer, manifest.name, manifest.legacy_capability_aliases));
525
- }
526
- for (const capability of collectUnknownExtensionCapabilities(manifest.capabilities)) {
527
- extensionWarnings.push(formatUnknownExtensionCapabilityWarning(layer, manifest.name, capability));
528
- }
529
- if (!entryWithinDirectory) {
530
- extensionWarnings.push(`extension_entry_outside_extension:${layer}:${manifest.name}`);
531
- }
532
- else if (!entryExists) {
533
- extensionWarnings.push(`extension_entry_missing:${layer}:${manifest.name}`);
534
- }
535
- if (pmVersionCompatibility.warning) {
536
- extensionWarnings.push(pmVersionCompatibility.warning);
537
- }
538
- if (pmMaxVersionCompatibility.warning) {
539
- extensionWarnings.push(pmMaxVersionCompatibility.warning);
540
- }
541
- return extensionWarnings;
542
- }
543
- async function scanExtensionDirectory(layer, extensionsRoot, directory, enabled, disabled, managedSourcePackages, pmMaxVersionExceededMode) {
544
- const extensionDir = path.join(extensionsRoot, directory);
545
- const manifestPath = path.join(extensionDir, "manifest.json");
546
- if (!(await pathExists(manifestPath))) {
547
- return buildUnavailableExtensionScan(layer, directory, manifestPath, `extension_manifest_missing:${layer}:${directory}`);
548
- }
549
- let manifest;
550
- let rawManifest;
551
- try {
552
- const parsed = JSON.parse(await fs.readFile(manifestPath, "utf8"));
553
- rawManifest = asRecordLoose(parsed);
554
- manifest = parseExtensionManifestDocument(parsed);
555
- }
556
- catch {
557
- rawManifest = null;
558
- manifest = null;
559
- }
560
- if (!manifest || !rawManifest) {
561
- return buildUnavailableExtensionScan(layer, directory, manifestPath, `extension_manifest_invalid:${layer}:${directory}`);
562
- }
563
- const entryPath = path.resolve(extensionDir, manifest.entry);
564
- const entryWithinDirectoryByPath = isPathWithinDirectory(extensionDir, entryPath);
565
- const entryExists = entryWithinDirectoryByPath
566
- ? await pathExists(entryPath)
567
- : false;
568
- const entryWithinDirectory = entryWithinDirectoryByPath && entryExists
569
- ? await isCanonicalPathWithinDirectory(extensionDir, entryPath)
570
- : entryWithinDirectoryByPath;
571
- const enabledForLoad = shouldEnable(manifest.name, enabled, disabled);
572
- const pmVersionCompatibility = await evaluatePmMinVersionCompatibility(layer, manifest);
573
- const pmMaxVersionCompatibility = await evaluatePmMaxVersionCompatibility(layer, manifest, pmMaxVersionExceededMode);
574
- const extensionWarnings = collectScannedExtensionWarnings(layer, manifest, rawManifest, entryWithinDirectory, entryExists, pmVersionCompatibility, pmMaxVersionCompatibility);
575
- const extensionReady = entryWithinDirectory &&
576
- entryExists &&
577
- pmVersionCompatibility.allowed &&
578
- pmMaxVersionCompatibility.allowed;
579
- const sourceIdentity = managedSourcePackages.get(`directory:${directory}`) ??
580
- managedSourcePackages.get(`name:${manifest.name}`);
581
- return {
582
- diagnostic: {
583
- layer,
584
- directory,
585
- manifest_path: manifestPath,
586
- name: manifest.name,
587
- version: manifest.version,
588
- entry: manifest.entry,
589
- priority: manifest.priority,
590
- entry_path: entryPath,
591
- enabled: enabledForLoad,
592
- status: extensionReady ? "ok" : "warn",
593
- },
594
- warnings: extensionWarnings,
595
- candidate: buildReadyExtensionCandidate({
596
- layer,
597
- directory,
598
- manifestPath,
599
- entryPath,
600
- manifest,
601
- sourceIdentity,
602
- extensionReady,
603
- enabledForLoad,
604
- }),
605
- };
606
- }
607
- /** Implements discover extensions for the public runtime surface of this module. */
608
- export async function discoverExtensions(options) {
609
- const roots = resolveExtensionRoots(options.pmRoot, options.cwd ?? process.cwd());
610
- const configured_enabled = normalizeNames(options.settings.extensions.enabled);
611
- const configured_disabled = normalizeNames(options.settings.extensions.disabled);
612
- const policy = normalizeExtensionPolicy(options.settings);
613
- const serializedPolicy = serializeExtensionPolicy(policy);
614
- if (options.noExtensions) {
615
- return {
616
- disabled_by_flag: true,
617
- roots,
618
- configured_enabled,
619
- configured_disabled,
620
- discovered: [],
621
- effective: [],
622
- warnings: [...policy.warnings],
623
- policy: serializedPolicy,
624
- };
625
- }
626
- const enabled = new Set(configured_enabled);
627
- const disabled = new Set(configured_disabled);
628
- const globalScan = options.ignoreGlobalExtensions === true
629
- ? emptyExtensionLayerScan()
630
- : await scanExtensionLayer("global", roots.global, enabled, disabled, policy.pmMaxVersionExceededMode.global);
631
- const projectScan = await scanExtensionLayer("project", roots.project, enabled, disabled, policy.pmMaxVersionExceededMode.project);
632
- const policyWarnings = [...policy.warnings];
633
- const effectiveCandidates = buildEffectiveExtensions(globalScan.candidates, projectScan.candidates);
634
- const effective = [];
635
- for (const candidate of effectiveCandidates) {
636
- const extensionRef = {
637
- layer: candidate.layer,
638
- name: candidate.manifest.name,
639
- trusted: candidate.manifest.trusted === true,
640
- provenanceVerified: candidate.manifest.provenance?.verified === true,
641
- sandboxProfile: candidate.manifest.sandbox_profile,
642
- permissions: candidate.manifest.permissions &&
643
- typeof candidate.manifest.permissions === "object"
644
- ? {
645
- fs_read: candidate.manifest.permissions.fs_read,
646
- fs_write: candidate.manifest.permissions.fs_write,
647
- network: candidate.manifest.permissions.network,
648
- env_read: candidate.manifest.permissions.env_read,
649
- env_write: candidate.manifest.permissions.env_write,
650
- process_spawn: candidate.manifest.permissions.process_spawn,
651
- }
652
- : undefined,
653
- };
654
- const extensionDecision = evaluateExtensionPolicyForExtension(policy, extensionRef);
655
- if (extensionDecision.warning) {
656
- policyWarnings.push(extensionDecision.warning);
657
- }
658
- if (!extensionDecision.allowed) {
659
- continue;
660
- }
661
- for (const capability of candidate.manifest.capabilities) {
662
- const capabilityDecision = evaluateExtensionPolicyForCapability(policy, extensionRef, capability);
663
- if (capabilityDecision.warning) {
664
- policyWarnings.push(capabilityDecision.warning);
665
- }
666
- }
667
- effective.push(summarizeCandidate(candidate));
668
- }
669
- return {
670
- disabled_by_flag: false,
671
- roots,
672
- configured_enabled,
673
- configured_disabled,
674
- discovered: [...globalScan.diagnostics, ...projectScan.diagnostics],
675
- effective,
676
- warnings: [
677
- ...new Set([
678
- ...globalScan.warnings,
679
- ...projectScan.warnings,
680
- ...policyWarnings,
681
- ]),
682
- ],
683
- policy: serializedPolicy,
684
- };
685
- }
686
- function formatUnknownError(error) {
687
- if (error instanceof Error && error.message.trim().length > 0) {
688
- return error.message;
689
- }
690
- return String(error);
691
- }
692
- async function readCurrentPmCliVersion() {
693
- try {
694
- const packageRoot = resolvePmPackageRootFromModule(import.meta.url, [
695
- "../../..",
696
- ]);
697
- const raw = await fs.readFile(path.join(packageRoot, "package.json"), "utf8");
698
- const parsed = JSON.parse(raw);
699
- return typeof parsed.version === "string" &&
700
- parsed.version.trim().length > 0
701
- ? parsed.version.trim()
702
- : null;
703
- }
704
- catch {
705
- return null;
706
- }
707
- }
708
- function resolveCurrentPmCliVersion() {
709
- currentPmCliVersionPromise ??= readCurrentPmCliVersion();
710
- return currentPmCliVersionPromise;
711
- }
712
- function formatPmVersionCompatibilityWarning(layer, manifest, evaluation) {
713
- const current = evaluation.current ?? "unknown";
714
- if (evaluation.kind === "pm_min_version") {
715
- switch (evaluation.status) {
716
- case "invalid":
717
- return `extension_pm_min_version_invalid:${layer}:${manifest.name}:required=${evaluation.required}`;
718
- case "unchecked":
719
- return `extension_pm_min_version_unchecked:${layer}:${manifest.name}:required=${evaluation.required}:current=${current}`;
720
- case "unmet":
721
- return `extension_pm_min_version_unmet:${layer}:${manifest.name}:required=${evaluation.required}:current=${current}`;
722
- default:
723
- return undefined;
724
- }
725
- }
726
- switch (evaluation.status) {
727
- case "invalid":
728
- return `extension_pm_max_version_invalid:${layer}:${manifest.name}:allowed=${evaluation.required}`;
729
- case "unchecked":
730
- return `extension_pm_max_version_unchecked:${layer}:${manifest.name}:allowed=${evaluation.required}:current=${current}`;
731
- case "exceeded_warn":
732
- return `extension_pm_max_version_exceeded_warn:${layer}:${manifest.name}:allowed=${evaluation.required}:current=${current}`;
733
- case "exceeded":
734
- return `extension_pm_max_version_exceeded:${layer}:${manifest.name}:allowed=${evaluation.required}:current=${current}`;
735
- default:
736
- return undefined;
737
- }
738
- }
739
- async function evaluatePmMinVersionCompatibility(layer, manifest) {
740
- // Resolve the current CLI version only when a bound is declared, so the common
741
- // no-bound case never reads package.json.
742
- if (manifest.pm_min_version === undefined) {
743
- return { allowed: true };
744
- }
745
- const evaluation = evaluatePmMinVersionBound(manifest.pm_min_version, await resolveCurrentPmCliVersion());
746
- const warning = formatPmVersionCompatibilityWarning(layer, manifest, evaluation);
747
- return warning
748
- ? { allowed: evaluation.allowed, warning }
749
- : { allowed: evaluation.allowed };
750
- }
751
- async function evaluatePmMaxVersionCompatibility(layer, manifest, exceededMode) {
752
- if (manifest.pm_max_version === undefined) {
753
- return { allowed: true };
754
- }
755
- const evaluation = evaluatePmMaxVersionBound(manifest.pm_max_version, await resolveCurrentPmCliVersion(), exceededMode);
756
- const warning = formatPmVersionCompatibilityWarning(layer, manifest, evaluation);
757
- return warning
758
- ? { allowed: evaluation.allowed, warning }
759
- : { allowed: evaluation.allowed };
760
- }
761
- async function fingerprintPath(pathToInspect) {
762
- try {
763
- const stats = await fs.stat(pathToInspect);
764
- return `${Math.trunc(stats.mtimeMs)}-${stats.size}`;
765
- }
766
- catch {
767
- return "missing";
768
- }
769
- }
770
- async function resolveExtensionImportHref(extension, options) {
771
- let importEntryPath = extension.entry_path;
772
- if (options.module_graph_snapshot_root) {
773
- importEntryPath = await snapshotExtensionModuleGraph(options.module_graph_snapshot_root, extension);
774
- }
775
- const baseUrl = new URL(pathToFileURL(importEntryPath).href);
776
- const shouldCacheBust = options.cache_bust === true || typeof options.reload_token === "string";
777
- if (!shouldCacheBust) {
778
- return baseUrl.href;
779
- }
780
- const [entryFingerprint, manifestFingerprint] = await Promise.all([
781
- fingerprintPath(extension.entry_path),
782
- fingerprintPath(extension.manifest_path),
783
- ]);
784
- const reloadToken = options.reload_token ?? nextExtensionReloadToken();
785
- baseUrl.searchParams.set("pm_ext_reload", reloadToken);
786
- baseUrl.searchParams.set("pm_ext_entry", entryFingerprint);
787
- baseUrl.searchParams.set("pm_ext_manifest", manifestFingerprint);
788
- return baseUrl.href;
789
- }
790
- /** Implements load extensions for the public runtime surface of this module. */
791
- export async function loadExtensions(options) {
792
- const discovery = await discoverExtensions(options);
793
- const loaded = [];
794
- const failed = [];
795
- const warnings = [...discovery.warnings];
796
- if (discovery.disabled_by_flag) {
797
- return {
798
- ...discovery,
799
- warnings,
800
- loaded,
801
- failed,
802
- };
803
- }
804
- const extensionsToLoad = typeof options.extensionFilter === "function"
805
- ? discovery.effective.filter(options.extensionFilter)
806
- : discovery.effective;
807
- for (const extension of extensionsToLoad) {
808
- try {
809
- const importHref = await resolveExtensionImportHref(extension, options);
810
- const module = await import(importHref);
811
- loaded.push({
812
- ...extension,
813
- module,
814
- });
815
- }
816
- catch (error) {
817
- warnings.push(`extension_load_failed:${extension.layer}:${extension.name}`);
818
- failed.push({
819
- layer: extension.layer,
820
- name: extension.name,
821
- entry_path: extension.entry_path,
822
- error: formatUnknownError(error),
823
- });
824
- }
825
- }
826
- return {
827
- ...discovery,
828
- warnings,
829
- loaded,
830
- failed,
831
- };
832
- }
833
- const DEFAULT_EXTENSION_DEACTIVATE_TIMEOUT_MS = 5_000;
834
- const MAX_EXTENSION_DEACTIVATE_TIMEOUT_MS = 2_147_483_647;
835
- function toActivatableExtension(source) {
836
- // Bind to `source` so a module/default-export authored with methods (or a class
837
- // instance) keeps its `this` across both lifecycle calls — `activate` is a
838
- // method call on a fresh object and `deactivate` is invoked bare, so without
839
- // binding the two would see different (or undefined) `this`.
840
- const activate = source.activate;
841
- const activatable = {
842
- activate: activate.bind(source),
843
- };
844
- if (typeof source.deactivate === "function") {
845
- const deactivate = source.deactivate;
846
- activatable.deactivate = deactivate.bind(source);
847
- }
848
- return activatable;
849
- }
850
- function resolveActivatableExtension(module) {
851
- const activatableRecord = resolveActivatablePropertyRecord(module);
852
- return activatableRecord ? toActivatableExtension(activatableRecord) : null;
853
- }
854
- /**
855
- * Run the optional `deactivate` teardown hook for every loaded extension that
856
- * exports one. Best-effort: a throwing teardown is captured as a warning and a
857
- * failure entry rather than propagated, so one extension cannot block another's
858
- * cleanup. Hosts call this on shutdown/reload (e.g. the MCP server between
859
- * native-action requests) to release resources opened during `activate`.
860
- *
861
- * Pass the `activationResult` to skip extensions whose `activate` failed — they
862
- * never fully initialized, so (VS Code-style) their `deactivate` must not run.
863
- * Teardowns run concurrently and each hook has a bounded timeout by default, so
864
- * one slow or hanging hook cannot serialize the rest or block the host
865
- * indefinitely unless the host explicitly disables the timeout; the returned
866
- * warnings/failures preserve loaded order.
867
- */
868
- export async function deactivateExtensions(loadResult, activationResult, options = {}) {
869
- const timeoutMs = normalizeExtensionDeactivateTimeout(options?.deactivate_timeout_ms);
870
- const failedActivationKeys = new Set((activationResult?.failed ?? []).map((entry) => `${entry.layer}:${entry.name}`));
871
- const targets = [];
872
- for (const extension of loadResult.loaded) {
873
- if (failedActivationKeys.has(`${extension.layer}:${extension.name}`)) {
874
- continue;
875
- }
876
- const activatable = resolveActivatableExtension(extension.module);
877
- if (!activatable || typeof activatable.deactivate !== "function") {
878
- continue;
879
- }
880
- targets.push({ extension, deactivate: activatable.deactivate });
881
- }
882
- const outcomes = await Promise.all(targets.map(async ({ extension, deactivate }) => {
883
- try {
884
- await runExtensionDeactivateWithTimeout(deactivate, timeoutMs);
885
- return { ok: true };
886
- }
887
- catch (error) {
888
- return {
889
- ok: false,
890
- layer: extension.layer,
891
- name: extension.name,
892
- error: formatUnknownError(error),
893
- };
894
- }
895
- }));
896
- const warnings = [];
897
- const failed = [];
898
- let deactivated = 0;
899
- for (const outcome of outcomes) {
900
- if (outcome.ok) {
901
- deactivated += 1;
902
- continue;
903
- }
904
- warnings.push(`extension_deactivate_failed:${outcome.layer}:${outcome.name}`);
905
- failed.push({
906
- layer: outcome.layer,
907
- name: outcome.name,
908
- error: outcome.error,
909
- });
910
- }
911
- return { deactivated, warnings, failed };
912
- }
913
- function normalizeExtensionDeactivateTimeout(rawTimeout) {
914
- if (typeof rawTimeout !== "number" || rawTimeout < 0) {
915
- return DEFAULT_EXTENSION_DEACTIVATE_TIMEOUT_MS;
916
- }
917
- if (rawTimeout === 0 || rawTimeout === Infinity) {
918
- return 0;
919
- }
920
- if (!Number.isFinite(rawTimeout)) {
921
- return DEFAULT_EXTENSION_DEACTIVATE_TIMEOUT_MS;
922
- }
923
- return Math.min(MAX_EXTENSION_DEACTIVATE_TIMEOUT_MS, Math.max(1, Math.floor(rawTimeout)));
924
- }
925
- async function runExtensionDeactivateWithTimeout(deactivate, timeoutMs) {
926
- if (timeoutMs === 0) {
927
- await deactivate();
928
- return;
929
- }
930
- let timeoutHandle;
931
- try {
932
- // A timed-out deactivate promise may still finish later; JavaScript promises
933
- // are not cancellable, so the host only stops waiting and consumes any late
934
- // rejection from the hook.
935
- const deactivatePromise = Promise.resolve().then(() => deactivate());
936
- deactivatePromise.catch(() => { });
937
- await Promise.race([
938
- deactivatePromise,
939
- new Promise((_, reject) => {
940
- timeoutHandle = setTimeout(() => {
941
- reject(new Error(`extension deactivate timed out after ${timeoutMs}ms`));
942
- }, timeoutMs);
943
- timeoutHandle.unref?.();
944
- }),
945
- ]);
946
- }
947
- finally {
948
- clearTimeout(timeoutHandle);
949
- }
950
- }
951
- const FLAG_DEFINITION_KEYS = new Set([
952
- "default",
953
- "description",
954
- "enabled",
955
- "list",
956
- "long",
957
- "repeatable",
958
- "required",
959
- "short",
960
- "type",
961
- "value_name",
962
- "value_type",
963
- "visible",
964
- ]);
965
- function normalizeFlagDefinitions(name, value) {
966
- return normalizeRegistrationRecordList(name, value).map((record) => {
967
- if (record.repeatable === true) {
968
- record.list = true;
969
- }
970
- return record;
971
- });
972
- }
973
- function normalizeCommandActionName(value) {
974
- return value
975
- .trim()
976
- .toLowerCase()
977
- .replace(/[\s_]+/g, "-")
978
- .replace(/[^a-z0-9-]/g, "-")
979
- .replace(/-+/g, "-")
980
- .replace(/^-+|-+$/g, "");
981
- }
982
- function resolveCommandDefinitionAction(commandPath, action) {
983
- if (action === undefined) {
984
- return commandPath.replace(/\s+/g, "-");
985
- }
986
- if (typeof action !== "string" || action.trim().length === 0) {
987
- throw new TypeError("registerCommand definition.action must be a non-empty string when provided");
988
- }
989
- const normalized = normalizeCommandActionName(action);
990
- if (normalized.length === 0) {
991
- throw new TypeError("registerCommand definition.action must contain alphanumeric characters");
992
- }
993
- return normalized;
994
- }
995
- function normalizeCommandDefinitionArguments(value) {
996
- if (value === undefined) {
997
- return [];
998
- }
999
- if (!Array.isArray(value)) {
1000
- throw new TypeError("registerCommand definition.arguments must be an array when provided");
1001
- }
1002
- const normalized = [];
1003
- for (const [index, entry] of value.entries()) {
1004
- const record = asRegistrationRecord(`registerCommand definition.arguments[${index}]`, entry);
1005
- const name = assertNonEmptyRegistrationString(`registerCommand definition.arguments[${index}].name`, record.name);
1006
- assertOptionalBooleanField(`registerCommand definition.arguments[${index}].required`, record.required);
1007
- assertOptionalBooleanField(`registerCommand definition.arguments[${index}].variadic`, record.variadic);
1008
- assertOptionalStringField(`registerCommand definition.arguments[${index}].description`, record.description);
1009
- if (name.includes(" ")) {
1010
- throw new TypeError(`registerCommand definition.arguments[${index}].name must not contain spaces`);
1011
- }
1012
- const definition = {
1013
- name,
1014
- };
1015
- if (record.required === true) {
1016
- definition.required = true;
1017
- }
1018
- if (record.variadic === true) {
1019
- definition.variadic = true;
1020
- }
1021
- if (typeof record.description === "string") {
1022
- definition.description = record.description.trim();
1023
- }
1024
- normalized.push(definition);
1025
- }
1026
- const variadicIndexes = normalized
1027
- .map((argument, index) => (argument.variadic ? index : -1))
1028
- .filter((index) => index >= 0);
1029
- if (variadicIndexes.length > 1) {
1030
- throw new TypeError("registerCommand definition.arguments supports at most one variadic argument");
1031
- }
1032
- if (variadicIndexes.length === 1 &&
1033
- variadicIndexes[0] !== normalized.length - 1) {
1034
- throw new TypeError("registerCommand definition.arguments variadic argument must be the final argument");
1035
- }
1036
- return normalized;
1037
- }
1038
- function validateFlagDefinitions(flags) {
1039
- if (!Array.isArray(flags)) {
1040
- throw new TypeError("registerFlags flags requires an array of object definitions");
1041
- }
1042
- for (const [index, raw] of flags.entries()) {
1043
- const record = asRegistrationRecord(`registerFlags flags[${index}]`, raw);
1044
- const unknownKeys = Object.keys(record)
1045
- .filter((key) => !FLAG_DEFINITION_KEYS.has(key))
1046
- .sort((left, right) => left.localeCompare(right));
1047
- if (unknownKeys.length > 0) {
1048
- throw new TypeError(`registerFlags flags[${index}] contains unknown field(s): ${unknownKeys.join(", ")}`);
1049
- }
1050
- const long = record.long;
1051
- const short = record.short;
1052
- if (long === undefined && short === undefined) {
1053
- throw new TypeError(`registerFlags flags[${index}] requires at least one of long or short`);
1054
- }
1055
- assertOptionalStringField(`registerFlags flags[${index}].long`, long);
1056
- assertOptionalStringField(`registerFlags flags[${index}].short`, short);
1057
- const tokenFinding = findExtensionFlagTokenFailure(long, short);
1058
- if (tokenFinding !== null) {
1059
- throw new TypeError(`registerFlags flags[${index}] ${describeExtensionLongFlagFailure(tokenFinding.token, tokenFinding.failure)}`);
1060
- }
1061
- assertOptionalStringField(`registerFlags flags[${index}].value_name`, record.value_name);
1062
- assertOptionalStringField(`registerFlags flags[${index}].description`, record.description);
1063
- assertOptionalBooleanField(`registerFlags flags[${index}].required`, record.required);
1064
- assertOptionalBooleanField(`registerFlags flags[${index}].enabled`, record.enabled);
1065
- assertOptionalBooleanField(`registerFlags flags[${index}].visible`, record.visible);
1066
- assertOptionalBooleanField(`registerFlags flags[${index}].list`, record.list);
1067
- assertOptionalBooleanField(`registerFlags flags[${index}].repeatable`, record.repeatable);
1068
- if (record.list !== undefined &&
1069
- record.repeatable !== undefined &&
1070
- record.list !== record.repeatable) {
1071
- throw new TypeError(`registerFlags flags[${index}].list and repeatable must match when both are provided`);
1072
- }
1073
- assertOptionalFlagDefaultField(`registerFlags flags[${index}].default`, record.default);
1074
- if (Array.isArray(record.default) &&
1075
- record.list !== true &&
1076
- record.repeatable !== true) {
1077
- throw new TypeError(`registerFlags flags[${index}].default cannot be an array unless list is true.`);
1078
- }
1079
- assertFlagValueTypeAndDefault(`registerFlags flags[${index}]`, record);
1080
- }
1081
- }
1082
- /** Reject a declared `value_type`/`type` that is not a known flag value kind, and a `default` whose value(s) would not cleanly coerce under that kind — so the typed-flag contract is enforced at registration instead of silently leaving an untyped value to surface at use time. */
1083
- function assertFlagValueTypeAndDefault(label, record) {
1084
- const declaredType = (typeof record.value_type === "string" ? record.value_type : undefined) ??
1085
- (typeof record.type === "string" ? record.type : undefined);
1086
- if (declaredType === undefined) {
1087
- return;
1088
- }
1089
- const kind = resolveFlagValueKind(declaredType);
1090
- if (kind === null) {
1091
- throw new TypeError(`${label} value_type "${declaredType}" is not a known flag value type (expected one of: string, number, boolean).`);
1092
- }
1093
- if (record.default === undefined) {
1094
- return;
1095
- }
1096
- // For list flags, validate the default exactly as the runtime will see it —
1097
- // comma-joined strings and nested arrays are flattened first — so a valid
1098
- // default like `value_type: "number", default: "10,20"` is not wrongly rejected.
1099
- const defaults = record.list === true || record.repeatable === true
1100
- ? flattenFlagListValue(record.default)
1101
- : [record.default];
1102
- for (const [defaultIndex, defaultValue] of defaults.entries()) {
1103
- if (!isFlagDefaultValueCoercible(defaultValue, kind)) {
1104
- const suffix = defaults.length > 1 ? `default[${defaultIndex}]` : "default";
1105
- throw new TypeError(`${label}.${suffix} (${JSON.stringify(defaultValue)}) is not coercible to ${kind}.`);
1106
- }
1107
- }
1108
- }
1109
- function validateItemFieldDefinitions(fields) {
1110
- if (!Array.isArray(fields)) {
1111
- throw new TypeError("registerItemFields fields requires an array of object definitions");
1112
- }
1113
- for (const [index, raw] of fields.entries()) {
1114
- const record = asRegistrationRecord(`registerItemFields fields[${index}]`, raw);
1115
- assertNonEmptyRegistrationString(`registerItemFields fields[${index}].name`, record.name);
1116
- const fieldType = assertNonEmptyRegistrationString(`registerItemFields fields[${index}].type`, record.type);
1117
- if (normalizeItemFieldType(fieldType) === null) {
1118
- const suggestion = suggestKnownItemFieldType(fieldType);
1119
- const hint = suggestion ? ` Did you mean "${suggestion}"?` : "";
1120
- throw new TypeError(`registerItemFields fields[${index}].type "${fieldType}" is not a known field type ` +
1121
- `(expected one of: ${KNOWN_ITEM_FIELD_TYPES.join(", ")}).${hint}`);
1122
- }
1123
- assertOptionalBooleanField(`registerItemFields fields[${index}].optional`, record.optional);
1124
- }
1125
- }
1126
- /** Validate the optional command-specific visibility and requirement policies of one extension item type. */
1127
- function validateItemTypeCommandOptionPolicies(typeIndex, value) {
1128
- if (value === undefined) {
1129
- return;
1130
- }
1131
- const label = `registerItemTypes types[${typeIndex}].command_option_policies`;
1132
- if (!Array.isArray(value)) {
1133
- throw new TypeError(`${label} must be an array when provided`);
1134
- }
1135
- for (const [policyIndex, rawPolicy] of value.entries()) {
1136
- const at = `${label}[${policyIndex}]`;
1137
- const policy = asRegistrationRecord(at, rawPolicy);
1138
- assertNonEmptyRegistrationString(`${at}.command`, policy.command);
1139
- assertNonEmptyRegistrationString(`${at}.option`, policy.option);
1140
- assertOptionalBooleanField(`${at}.enabled`, policy.enabled);
1141
- assertOptionalBooleanField(`${at}.required`, policy.required);
1142
- assertOptionalBooleanField(`${at}.visible`, policy.visible);
1143
- }
1144
- }
1145
- /** Validate the optional custom option vocabulary of one extension item type. */
1146
- function validateItemTypeOptions(typeIndex, value) {
1147
- if (value === undefined) {
1148
- return;
1149
- }
1150
- const label = `registerItemTypes types[${typeIndex}].options`;
1151
- if (!Array.isArray(value)) {
1152
- throw new TypeError(`${label} must be an array when provided`);
1153
- }
1154
- for (const [optionIndex, rawOption] of value.entries()) {
1155
- const at = `${label}[${optionIndex}]`;
1156
- const option = asRegistrationRecord(at, rawOption);
1157
- assertNonEmptyRegistrationString(`${at}.key`, option.key);
1158
- assertOptionalStringArrayField(`${at}.values`, option.values);
1159
- assertOptionalBooleanField(`${at}.required`, option.required);
1160
- assertOptionalStringArrayField(`${at}.aliases`, option.aliases);
1161
- }
1162
- }
1163
- function validateItemTypeDefinitions(types) {
1164
- if (!Array.isArray(types)) {
1165
- throw new TypeError("registerItemTypes types requires an array of object definitions");
1166
- }
1167
- for (const [typeIndex, raw] of types.entries()) {
1168
- const at = `registerItemTypes types[${typeIndex}]`;
1169
- const record = asRegistrationRecord(at, raw);
1170
- assertNonEmptyRegistrationString(`${at}.name`, record.name);
1171
- assertOptionalStringField(`${at}.folder`, record.folder);
1172
- assertOptionalStringArrayField(`${at}.aliases`, record.aliases);
1173
- assertOptionalStringArrayField(`${at}.required_create_fields`, record.required_create_fields);
1174
- assertOptionalStringArrayField(`${at}.required_create_repeatables`, record.required_create_repeatables);
1175
- validateItemTypeCommandOptionPolicies(typeIndex, record.command_option_policies);
1176
- validateItemTypeOptions(typeIndex, record.options);
1177
- }
1178
- }
1179
- function validateMigrationDefinition(definition) {
1180
- const record = asRegistrationRecord("registerMigration definition", definition);
1181
- if (record.id !== undefined && typeof record.id !== "string") {
1182
- throw new TypeError("registerMigration definition.id must be a string when provided");
1183
- }
1184
- if (record.description !== undefined &&
1185
- typeof record.description !== "string") {
1186
- throw new TypeError("registerMigration definition.description must be a string when provided");
1187
- }
1188
- if (record.status !== undefined && typeof record.status !== "string") {
1189
- throw new TypeError("registerMigration definition.status must be a string when provided");
1190
- }
1191
- assertOptionalBooleanField("registerMigration definition.mandatory", record.mandatory);
1192
- if (record.run !== undefined && typeof record.run !== "function") {
1193
- throw new TypeError("registerMigration definition.run must be a function when provided");
1194
- }
1195
- }
1196
- /**
1197
- * The seven array-valued dimensions a {@link ProjectProfileDefinition} stages.
1198
- * Each is "optional-by-emptiness": an omitted dimension normalizes to an empty
1199
- * array so the profile planner can iterate every dimension unconditionally.
1200
- */
1201
- const PROJECT_PROFILE_DIMENSIONS = [
1202
- "types",
1203
- "statuses",
1204
- "fields",
1205
- "workflows",
1206
- "config",
1207
- "templates",
1208
- "packages",
1209
- ];
1210
- /** Dimension-specific profile entry validators used after the common object-shape boundary. */
1211
- const PROJECT_PROFILE_ENTRY_VALIDATORS = {
1212
- types: (at, entry) => {
1213
- if (entry.name !== undefined && typeof entry.name !== "string") {
1214
- throw new TypeError(`${at}.name must be a string when provided`);
1215
- }
1216
- },
1217
- workflows: (at, entry) => {
1218
- if (typeof entry.type !== "string") {
1219
- throw new TypeError(`${at}.type must be a string`);
1220
- }
1221
- if (!Array.isArray(entry.allowed_transitions)) {
1222
- throw new TypeError(`${at}.allowed_transitions must be an array`);
1223
- }
1224
- for (const [pairIndex, pair] of entry.allowed_transitions.entries()) {
1225
- if (!Array.isArray(pair)) {
1226
- throw new TypeError(`${at}.allowed_transitions[${pairIndex}] must be a [from, to] array`);
1227
- }
1228
- }
1229
- },
1230
- templates: (at, entry) => {
1231
- if (typeof entry.name !== "string") {
1232
- throw new TypeError(`${at}.name must be a string`);
1233
- }
1234
- if (typeof entry.options !== "object" ||
1235
- entry.options === null ||
1236
- Array.isArray(entry.options)) {
1237
- throw new TypeError(`${at}.options must be an object`);
1238
- }
1239
- },
1240
- packages: (at, entry) => {
1241
- if (typeof entry.spec !== "string") {
1242
- throw new TypeError(`${at}.spec must be a string`);
1243
- }
1244
- },
1245
- };
1246
- function validateProjectProfileDefinition(profile) {
1247
- const record = asRegistrationRecord("registerProfile profile", profile);
1248
- assertNonEmptyRegistrationString("registerProfile profile.name", record.name);
1249
- assertNonEmptyRegistrationString("registerProfile profile.title", record.title);
1250
- if (record.summary !== undefined && typeof record.summary !== "string") {
1251
- throw new TypeError("registerProfile profile.summary must be a string when provided");
1252
- }
1253
- for (const dimension of PROJECT_PROFILE_DIMENSIONS) {
1254
- const value = record[dimension];
1255
- if (value === undefined) {
1256
- continue;
1257
- }
1258
- if (!Array.isArray(value)) {
1259
- throw new TypeError(`registerProfile profile.${dimension} must be an array when provided`);
1260
- }
1261
- // Each dimension entry must be a non-null object: a primitive or null entry
1262
- // (e.g. `statuses: [null]`, `types: [42]`) survives an array-only check but
1263
- // crashes the profile planner and `pm profile show` when they read `entry.id`
1264
- // / `entry.key` / `entry.type` later. Reject it at the registration boundary.
1265
- for (const [index, entry] of value.entries()) {
1266
- if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
1267
- throw new TypeError(`registerProfile profile.${dimension}[${index}] must be an object`);
1268
- }
1269
- // Beyond "is an object", validate the specific field shapes consumers
1270
- // dereference so a type-violating entry can never crash the planner, the
1271
- // `pm profile` surfaces, or describeProjectProfile downstream.
1272
- PROJECT_PROFILE_ENTRY_VALIDATORS[dimension]?.(`registerProfile profile.${dimension}[${index}]`, entry);
1273
- }
1274
- }
1275
- }
1276
- /**
1277
- * Fills an already-validated profile snapshot's optional surfaces — an absent
1278
- * `summary` becomes an empty string and every omitted dimension an empty array —
1279
- * so the stored definition always has the full {@link ProjectProfileDefinition}
1280
- * shape the profile planner and `pm profile` resolution rely on. It runs after
1281
- * validation on the cloned snapshot, so it only ever supplies missing defaults
1282
- * and never has to coerce an invalid type (those are already rejected).
1283
- */
1284
- function applyProjectProfileDefaults(profile) {
1285
- if (profile.summary === undefined) {
1286
- profile.summary = "";
1287
- }
1288
- for (const dimension of PROJECT_PROFILE_DIMENSIONS) {
1289
- if (profile[dimension] === undefined) {
1290
- profile[dimension] = [];
1291
- }
1292
- }
1293
- return profile;
1294
- }
1295
- function getDeclaredExtensionCapabilities(extension) {
1296
- if (!Array.isArray(extension.capabilities)) {
1297
- return null;
1298
- }
1299
- const declared = new Set();
1300
- for (const capability of extension.capabilities) {
1301
- const normalized = capability.trim().toLowerCase();
1302
- if (isKnownExtensionCapability(normalized)) {
1303
- declared.add(normalized);
1304
- }
1305
- }
1306
- return declared;
1307
- }
1308
- function assertExtensionCapability(extension, capability, method) {
1309
- const declared = getDeclaredExtensionCapabilities(extension);
1310
- // Keep direct unit tests that construct LoadedExtension fixtures without
1311
- // capability metadata backwards-compatible while enforcing manifest-declared
1312
- // capabilities for runtime-loaded extensions.
1313
- if (declared === null) {
1314
- return;
1315
- }
1316
- if (!declared.has(capability)) {
1317
- throw createRegistrationValidationError(`${method} requires capability '${capability}' in extension manifest capabilities`, {
1318
- method,
1319
- registration_index: -1,
1320
- capability,
1321
- missing_capability: capability,
1322
- expected_schema: `"capabilities": [..., "${capability}"]`,
1323
- received: extension.capabilities,
1324
- hint: `Add "${capability}" to ${extension.name} manifest capabilities, or remove the ${method} registration call.`,
1325
- });
1326
- }
1327
- }
1328
- function buildExtensionSelfIdentity(extension) {
1329
- return Object.freeze({
1330
- name: extension.name,
1331
- layer: extension.layer,
1332
- version: extension.version,
1333
- capabilities: Object.freeze((extension.capabilities ?? []).filter((capability) => KNOWN_EXTENSION_CAPABILITIES.includes(capability))),
1334
- pm_min_version: extension.pm_min_version,
1335
- pm_max_version: extension.pm_max_version,
1336
- source_package: extension.source_package,
1337
- });
1338
- }
1339
- function buildPolicyExtensionRef(extension) {
1340
- return {
1341
- layer: extension.layer,
1342
- name: extension.name,
1343
- trusted: extension.trusted === true,
1344
- provenanceVerified: extension.provenance?.verified === true,
1345
- sandboxProfile: extension.sandbox_profile,
1346
- permissions: extension.permissions && typeof extension.permissions === "object"
1347
- ? {
1348
- fs_read: extension.permissions.fs_read,
1349
- fs_write: extension.permissions.fs_write,
1350
- network: extension.permissions.network,
1351
- env_read: extension.permissions.env_read,
1352
- env_write: extension.permissions.env_write,
1353
- process_spawn: extension.permissions.process_spawn,
1354
- }
1355
- : undefined,
1356
- };
1357
- }
1358
- class ExtensionApiRegistrar {
1359
- extension;
1360
- hooks;
1361
- #loadedExtension;
1362
- #extensionRef;
1363
- #hookRegistry;
1364
- #commandRegistry;
1365
- #parserRegistry;
1366
- #preflightRegistry;
1367
- #serviceRegistry;
1368
- #rendererRegistry;
1369
- #registrationRegistry;
1370
- #activationWarnings;
1371
- #activationFailures;
1372
- #policy;
1373
- constructor(extension, hooks, commands, parsers, preflight, services, renderers, registrations, activationWarnings, activationFailures, policy) {
1374
- this.#loadedExtension = extension;
1375
- this.extension = buildExtensionSelfIdentity(extension);
1376
- this.#extensionRef = buildPolicyExtensionRef(extension);
1377
- this.#hookRegistry = hooks;
1378
- this.#commandRegistry = commands;
1379
- this.#parserRegistry = parsers;
1380
- this.#preflightRegistry = preflight;
1381
- this.#serviceRegistry = services;
1382
- this.#rendererRegistry = renderers;
1383
- this.#registrationRegistry = registrations;
1384
- this.#activationWarnings = activationWarnings;
1385
- this.#activationFailures = activationFailures;
1386
- this.#policy = policy;
1387
- this.registerCommand = this.registerCommand.bind(this);
1388
- this.registerParser = this.registerParser.bind(this);
1389
- this.registerPreflight = this.registerPreflight.bind(this);
1390
- this.registerService = this.registerService.bind(this);
1391
- this.registerFlags = this.registerFlags.bind(this);
1392
- this.registerItemFields = this.registerItemFields.bind(this);
1393
- this.registerItemTypes = this.registerItemTypes.bind(this);
1394
- this.registerRelationshipKinds = this.registerRelationshipKinds.bind(this);
1395
- this.registerMigration = this.registerMigration.bind(this);
1396
- this.registerProfile = this.registerProfile.bind(this);
1397
- this.registerRenderer = this.registerRenderer.bind(this);
1398
- this.registerImporter = this.registerImporter.bind(this);
1399
- this.registerExporter = this.registerExporter.bind(this);
1400
- this.registerSearchProvider = this.registerSearchProvider.bind(this);
1401
- this.registerVectorStoreAdapter =
1402
- this.registerVectorStoreAdapter.bind(this);
1403
- this.registerAssuranceMeasurementProvider =
1404
- this.registerAssuranceMeasurementProvider.bind(this);
1405
- this.hooks = {
1406
- beforeCommand: (hook) => this.registerBeforeCommand(hook),
1407
- beforeMutation: (hook) => this.registerBeforeMutation(hook),
1408
- afterCommand: (hook) => this.registerAfterCommand(hook),
1409
- onWrite: (hook) => this.registerOnWrite(hook),
1410
- onRead: (hook) => this.registerOnRead(hook),
1411
- onIndex: (hook) => this.registerOnIndex(hook),
1412
- };
1413
- }
1414
- allowRegistration(surface, method, capability, details) {
1415
- const decision = evaluateExtensionPolicyForRegistration(this.#policy, this.#extensionRef, surface, method, capability, details);
1416
- if (decision.warning) {
1417
- this.#activationWarnings.push(decision.warning);
1418
- }
1419
- return decision.allowed;
1420
- }
1421
- registerCommandTrace(mode, command, expectedSchema, received, hint) {
1422
- return {
1423
- method: "registerCommand",
1424
- registration_index: mode === "override"
1425
- ? this.#commandRegistry.overrides.length
1426
- : this.#commandRegistry.handlers.length,
1427
- command,
1428
- expected_schema: expectedSchema,
1429
- received: sanitizeRegistrationValue(received),
1430
- hint,
1431
- };
1432
- }
1433
- registerCommandOverride(command, override) {
1434
- const normalizedCommand = normalizeCommandName(command);
1435
- if (normalizedCommand.length === 0) {
1436
- 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."));
1437
- }
1438
- if (typeof override !== "function") {
1439
- const trace = this.registerCommandTrace("override", normalizedCommand, 'registerCommand("<command>", (context) => unknown)', override, "Provide a function as the second registerCommand argument.");
1440
- throw createRegistrationValidationError(`registerCommand requires an override function when command name is provided (command="${normalizedCommand}", registration_index=${trace.registration_index})`, trace);
1441
- }
1442
- if (!this.allowRegistration("commands.override", "registerCommand", "commands", { command: normalizedCommand })) {
1443
- return;
1444
- }
1445
- this.#commandRegistry.overrides.push({
1446
- layer: this.#loadedExtension.layer,
1447
- name: this.#loadedExtension.name,
1448
- command: normalizedCommand,
1449
- run: override,
1450
- });
1451
- }
1452
- resolveCommandDefinitionRunHandler(definition, normalizedCommand) {
1453
- const runHandler = typeof definition.run === "function" ? definition.run : undefined;
1454
- const legacyHandler = typeof definition.handler === "function" ? definition.handler : undefined;
1455
- if (!runHandler && legacyHandler) {
1456
- this.#activationWarnings.push(`extension_command_definition_legacy_handler_alias:${this.#loadedExtension.layer}:${this.#loadedExtension.name}:${normalizedCommand}`);
1457
- }
1458
- return runHandler ?? legacyHandler;
1459
- }
1460
- registerCommandDefinition(definition) {
1461
- if (typeof definition !== "object" || definition === null) {
1462
- throw createRegistrationValidationError("registerCommand requires a command definition object", this.registerCommandTrace("definition", undefined, "{ name: string; run: (context) => unknown; }", definition, 'Use registerCommand({ name: "command path", run: (context) => ... }).'));
1463
- }
1464
- if (typeof definition.name !== "string") {
1465
- throw createRegistrationValidationError("registerCommand requires a command definition name", this.registerCommandTrace("definition", undefined, "{ name: string; run: (context) => unknown; }", definition, "Set command definition.name to a non-empty string command path."));
1466
- }
1467
- const normalizedCommand = normalizeCommandName(definition.name);
1468
- if (normalizedCommand.length === 0) {
1469
- 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."));
1470
- }
1471
- const resolvedHandler = this.resolveCommandDefinitionRunHandler(definition, normalizedCommand);
1472
- if (typeof resolvedHandler !== "function") {
1473
- const trace = this.registerCommandTrace("definition", normalizedCommand, "{ name: string; run: (context) => unknown; }", resolvedHandler, "Define command definition.run as a function.");
1474
- throw createRegistrationValidationError(`registerCommand requires a command definition run handler (command="${normalizedCommand}", registration_index=${trace.registration_index})`, trace);
1475
- }
1476
- try {
1477
- assertCommandDefinitionMetadataStrings(definition);
1478
- const action = resolveCommandDefinitionAction(normalizedCommand, definition.action);
1479
- if (!this.allowRegistration("commands.handler", "registerCommand", "commands", { command: normalizedCommand, action })) {
1480
- return;
1481
- }
1482
- const description = definition.description?.trim();
1483
- const intent = definition.intent?.trim();
1484
- const examples = normalizeOptionalStringArrayField("registerCommand definition.examples", definition.examples);
1485
- const failureHints = normalizeOptionalStringArrayField("registerCommand definition.failure_hints", definition.failure_hints);
1486
- const argumentsDefinition = normalizeCommandDefinitionArguments(definition.arguments);
1487
- if (definition.flags !== undefined) {
1488
- assertExtensionCapability(this.#loadedExtension, "schema", "registerCommand flags");
1489
- if (this.allowRegistration("schema.flags", "registerCommand flags", "schema")) {
1490
- validateFlagDefinitions(definition.flags);
1491
- this.#registrationRegistry.flags.push({
1492
- layer: this.#loadedExtension.layer,
1493
- name: this.#loadedExtension.name,
1494
- target_command: normalizedCommand,
1495
- flags: normalizeFlagDefinitions("registerCommand definition.flags", definition.flags),
1496
- });
1497
- }
1498
- }
1499
- const registration = {
1500
- layer: this.#loadedExtension.layer,
1501
- name: this.#loadedExtension.name,
1502
- source_package: this.#loadedExtension.source_package,
1503
- command: normalizedCommand,
1504
- action,
1505
- examples,
1506
- failure_hints: failureHints,
1507
- arguments: argumentsDefinition,
1508
- tier: definition.tier ?? "standard",
1509
- family: definition.family ?? "extensions",
1510
- };
1511
- if (description) {
1512
- registration.description = description;
1513
- }
1514
- if (intent) {
1515
- registration.intent = intent;
1516
- }
1517
- this.#registrationRegistry.commands.push(registration);
1518
- }
1519
- catch (error) {
1520
- const reason = formatUnknownError(error);
1521
- const trace = this.registerCommandTrace("definition", normalizedCommand, "{ name: string; run: (context) => unknown; action?: string; arguments?: object[]; flags?: object[]; }", definition, reason);
1522
- const validationError = createRegistrationValidationError(`registerCommand definition metadata invalid (command="${normalizedCommand}", registration_index=${trace.registration_index}): ${reason}`, trace);
1523
- this.#activationWarnings.push(`extension_command_quarantined:${this.#loadedExtension.layer}:${this.#loadedExtension.name}:${normalizedCommand}`);
1524
- this.#activationFailures.push({
1525
- layer: this.#loadedExtension.layer,
1526
- name: this.#loadedExtension.name,
1527
- entry_path: this.#loadedExtension.entry_path,
1528
- error: validationError.message,
1529
- trace,
1530
- });
1531
- return;
1532
- }
1533
- this.#commandRegistry.handlers.push({
1534
- layer: this.#loadedExtension.layer,
1535
- name: this.#loadedExtension.name,
1536
- command: normalizedCommand,
1537
- run: resolvedHandler,
1538
- });
1539
- }
1540
- registerCommand(commandOrDefinition, override) {
1541
- assertExtensionCapability(this.#loadedExtension, "commands", "registerCommand");
1542
- if (typeof commandOrDefinition === "string") {
1543
- this.registerCommandOverride(commandOrDefinition, override);
1544
- return;
1545
- }
1546
- this.registerCommandDefinition(commandOrDefinition);
1547
- }
1548
- registerParser(command, override) {
1549
- assertExtensionCapability(this.#loadedExtension, "parser", "registerParser");
1550
- if (!this.allowRegistration("parser.override", "registerParser", "parser")) {
1551
- return;
1552
- }
1553
- const normalizedCommand = normalizeCommandName(assertNonEmptyRegistrationString("registerParser command", command));
1554
- assertRegistrationFunction("registerParser override", override);
1555
- this.#parserRegistry.overrides.push({
1556
- layer: this.#loadedExtension.layer,
1557
- name: this.#loadedExtension.name,
1558
- command: normalizedCommand,
1559
- run: override,
1560
- });
1561
- }
1562
- registerPreflight(override) {
1563
- assertExtensionCapability(this.#loadedExtension, "preflight", "registerPreflight");
1564
- if (!this.allowRegistration("preflight.override", "registerPreflight", "preflight")) {
1565
- return;
1566
- }
1567
- const normalized = normalizePreflightOverride(override);
1568
- this.#preflightRegistry.overrides.push({
1569
- layer: this.#loadedExtension.layer,
1570
- name: this.#loadedExtension.name,
1571
- ...normalized,
1572
- });
1573
- }
1574
- registerService(service, override, ownership = {}) {
1575
- assertExtensionCapability(this.#loadedExtension, "services", "registerService");
1576
- const normalizedService = String(service).trim().toLowerCase();
1577
- if (!isExtensionServiceName(normalizedService)) {
1578
- throw new TypeError(`registerService service must be one of: ${KNOWN_EXTENSION_SERVICE_NAMES.join(", ")}`);
1579
- }
1580
- if (!this.allowRegistration("services.override", "registerService", "services", { service: normalizedService })) {
1581
- return;
1582
- }
1583
- assertRegistrationFunction("registerService override", override);
1584
- this.#serviceRegistry.overrides.push({
1585
- layer: this.#loadedExtension.layer,
1586
- name: this.#loadedExtension.name,
1587
- service: normalizedService,
1588
- run: override,
1589
- ...(normalizeServiceOverrideOwnership(ownership)
1590
- ? { passThrough: true }
1591
- : {}),
1592
- });
1593
- }
1594
- registerRenderer(format, renderer, ownership = {}) {
1595
- assertExtensionCapability(this.#loadedExtension, "renderers", "registerRenderer");
1596
- if (!this.allowRegistration("renderers.override", "registerRenderer", "renderers")) {
1597
- return;
1598
- }
1599
- if (typeof renderer !== "function") {
1600
- throw new TypeError("registerRenderer requires a renderer function");
1601
- }
1602
- const normalizedFormat = String(format).trim().toLowerCase();
1603
- if (!isOutputRendererFormat(normalizedFormat)) {
1604
- throw new Error(`registerRenderer format must be toon|json, received: ${String(format)}`);
1605
- }
1606
- if (ownership.resultDiscriminator !== undefined &&
1607
- typeof ownership.resultDiscriminator !== "function") {
1608
- throw new TypeError("registerRenderer ownership.resultDiscriminator must be a function when provided");
1609
- }
1610
- const commands = [
1611
- ...new Set((ownership.commands ?? []).map((command) => {
1612
- if (typeof command !== "string" || command.trim().length === 0) {
1613
- throw new TypeError("registerRenderer ownership.commands must contain non-empty command paths");
1614
- }
1615
- return normalizeCommandName(command);
1616
- })),
1617
- ];
1618
- this.#rendererRegistry.overrides.push({
1619
- layer: this.#loadedExtension.layer,
1620
- name: this.#loadedExtension.name,
1621
- format: normalizedFormat,
1622
- run: renderer,
1623
- commands,
1624
- ...(ownership.resultDiscriminator
1625
- ? { resultDiscriminator: ownership.resultDiscriminator }
1626
- : {}),
1627
- });
1628
- }
1629
- registerFlags(targetCommand, flags) {
1630
- assertExtensionCapability(this.#loadedExtension, "schema", "registerFlags");
1631
- if (!this.allowRegistration("schema.flags", "registerFlags", "schema")) {
1632
- return;
1633
- }
1634
- const normalizedTargetCommand = normalizeCommandName(assertNonEmptyRegistrationString("registerFlags targetCommand", targetCommand));
1635
- validateFlagDefinitions(flags);
1636
- const normalizedFlags = normalizeFlagDefinitions("registerFlags flags", flags);
1637
- if (normalizedFlags.length === 0) {
1638
- throw new TypeError("registerFlags requires at least one flag definition");
1639
- }
1640
- this.#registrationRegistry.flags.push({
1641
- layer: this.#loadedExtension.layer,
1642
- name: this.#loadedExtension.name,
1643
- target_command: normalizedTargetCommand,
1644
- flags: normalizedFlags,
1645
- });
1646
- }
1647
- registerItemFields(fields) {
1648
- assertExtensionCapability(this.#loadedExtension, "schema", "registerItemFields");
1649
- if (!this.allowRegistration("schema.itemfields", "registerItemFields", "schema")) {
1650
- return;
1651
- }
1652
- validateItemFieldDefinitions(fields);
1653
- const normalizedFields = normalizeRegistrationRecordList("registerItemFields fields", fields);
1654
- if (normalizedFields.length === 0) {
1655
- throw new TypeError("registerItemFields requires at least one field definition");
1656
- }
1657
- this.#registrationRegistry.item_fields.push({
1658
- layer: this.#loadedExtension.layer,
1659
- name: this.#loadedExtension.name,
1660
- fields: normalizedFields,
1661
- });
1662
- }
1663
- registerItemTypes(types) {
1664
- assertExtensionCapability(this.#loadedExtension, "schema", "registerItemTypes");
1665
- if (!this.allowRegistration("schema.itemtypes", "registerItemTypes", "schema")) {
1666
- return;
1667
- }
1668
- validateItemTypeDefinitions(types);
1669
- const normalizedTypes = normalizeRegistrationRecordList("registerItemTypes types", types);
1670
- if (normalizedTypes.length === 0) {
1671
- throw new TypeError("registerItemTypes requires at least one type definition");
1672
- }
1673
- this.#registrationRegistry.item_types.push({
1674
- layer: this.#loadedExtension.layer,
1675
- name: this.#loadedExtension.name,
1676
- types: normalizedTypes,
1677
- });
1678
- }
1679
- registerRelationshipKinds(definitions) {
1680
- assertExtensionCapability(this.#loadedExtension, "schema", "registerRelationshipKinds");
1681
- if (!this.allowRegistration("schema.relationshipkinds", "registerRelationshipKinds", "schema")) {
1682
- return;
1683
- }
1684
- if (!Array.isArray(definitions)) {
1685
- throw new TypeError("registerRelationshipKinds definitions requires an array of object definitions");
1686
- }
1687
- if (definitions.length === 0) {
1688
- throw new TypeError("registerRelationshipKinds requires at least one definition");
1689
- }
1690
- const registry = createRelationshipKindRegistry();
1691
- for (const registration of this.#registrationRegistry.relationship_kinds) {
1692
- for (const definition of registration.definitions) {
1693
- registry.register(definition);
1694
- }
1695
- }
1696
- const validated = definitions.map((definition) => {
1697
- registry.register(definition);
1698
- return registry.require(definition.kind);
1699
- });
1700
- this.#registrationRegistry.relationship_kinds.push({
1701
- layer: this.#loadedExtension.layer,
1702
- name: this.#loadedExtension.name,
1703
- definitions: validated,
1704
- });
1705
- }
1706
- registerMigration(definition) {
1707
- assertExtensionCapability(this.#loadedExtension, "schema", "registerMigration");
1708
- if (!this.allowRegistration("schema.migrations", "registerMigration", "schema")) {
1709
- return;
1710
- }
1711
- validateMigrationDefinition(definition);
1712
- const runtimeDefinition = normalizeRuntimeRegistrationRecord("registerMigration definition", definition);
1713
- this.#registrationRegistry.migrations.push(attachRuntimeDefinition({
1714
- layer: this.#loadedExtension.layer,
1715
- name: this.#loadedExtension.name,
1716
- definition: normalizeRegistrationRecord("registerMigration definition", definition),
1717
- }, runtimeDefinition));
1718
- }
1719
- registerProfile(profile) {
1720
- assertExtensionCapability(this.#loadedExtension, "schema", "registerProfile");
1721
- if (!this.allowRegistration("schema.profiles", "registerProfile", "schema")) {
1722
- return;
1723
- }
1724
- // Snapshot first, then validate and default the snapshot: cloning resolves
1725
- // any getters once into plain data decoupled from the caller's object, so
1726
- // validation and storage operate on the same value — a getter cannot present
1727
- // one value to validation and another to the registry. Defaults are applied
1728
- // only after validation, so an invalid type is rejected, not silently coerced.
1729
- const snapshot = cloneRuntimeRegistrationValue(profile);
1730
- validateProjectProfileDefinition(snapshot);
1731
- this.#registrationRegistry.profiles.push({
1732
- layer: this.#loadedExtension.layer,
1733
- name: this.#loadedExtension.name,
1734
- profile: applyProjectProfileDefaults(snapshot),
1735
- });
1736
- }
1737
- /** Validates and records optional importer/exporter flag metadata through the schema policy gate. */
1738
- registerImportExportCommandFlags(method, commandPath, resolvedOptions) {
1739
- if (resolvedOptions.flags === undefined) {
1740
- return;
1741
- }
1742
- assertExtensionCapability(this.#loadedExtension, "schema", `${method} options.flags`);
1743
- if (!this.allowRegistration("schema.flags", `${method} options.flags`, "schema")) {
1744
- return;
1745
- }
1746
- validateFlagDefinitions(resolvedOptions.flags);
1747
- this.#registrationRegistry.flags.push({
1748
- layer: this.#loadedExtension.layer,
1749
- name: this.#loadedExtension.name,
1750
- target_command: commandPath,
1751
- flags: normalizeFlagDefinitions(`${method} options.flags`, resolvedOptions.flags),
1752
- });
1753
- }
1754
- applyImportExportCommandMetadata(method, commandPath, options) {
1755
- if (options !== undefined &&
1756
- (typeof options !== "object" ||
1757
- options === null ||
1758
- Array.isArray(options))) {
1759
- throw new TypeError(`${method} options must be an object when provided`);
1760
- }
1761
- const defaultDescription = `${method === "registerImporter" ? "Import" : "Export"} items with the registered extension adapter.`;
1762
- const defaultArguments = [
1763
- {
1764
- name: "file",
1765
- required: false,
1766
- description: "Optional input or output file path.",
1767
- },
1768
- ];
1769
- const resolvedOptions = {
1770
- ...options,
1771
- description: options?.description ?? defaultDescription,
1772
- arguments: options?.arguments ?? defaultArguments,
1773
- };
1774
- const output = resolveImportExportArtifactOutput(method, resolvedOptions, options?.description !== undefined);
1775
- assertOptionalStringField(`${method} options.action`, resolvedOptions.action);
1776
- assertOptionalStringField(`${method} options.description`, resolvedOptions.description);
1777
- assertOptionalStringField(`${method} options.intent`, resolvedOptions.intent);
1778
- const action = resolveCommandDefinitionAction(commandPath, resolvedOptions.action);
1779
- const examples = normalizeOptionalStringArrayField(`${method} options.examples`, resolvedOptions.examples);
1780
- const failureHints = normalizeOptionalStringArrayField(`${method} options.failure_hints`, resolvedOptions.failure_hints);
1781
- const argumentsDefinition = normalizeCommandDefinitionArguments(resolvedOptions.arguments);
1782
- this.registerImportExportCommandFlags(method, commandPath, resolvedOptions);
1783
- const registration = {
1784
- layer: this.#loadedExtension.layer,
1785
- name: this.#loadedExtension.name,
1786
- source_package: this.#loadedExtension.source_package,
1787
- command: commandPath,
1788
- action,
1789
- examples,
1790
- failure_hints: failureHints,
1791
- arguments: argumentsDefinition,
1792
- };
1793
- const description = resolvedOptions.description?.trim();
1794
- if (description) {
1795
- registration.description = description;
1796
- }
1797
- const intent = resolvedOptions.intent?.trim();
1798
- if (intent) {
1799
- registration.intent = intent;
1800
- }
1801
- this.#registrationRegistry.commands.push(registration);
1802
- return output;
1803
- }
1804
- registerImporter(name, importer, options) {
1805
- assertExtensionCapability(this.#loadedExtension, "importers", "registerImporter");
1806
- if (!this.allowRegistration("importers.importer", "registerImporter", "importers")) {
1807
- return;
1808
- }
1809
- const normalizedName = normalizeRegistrationName(assertNonEmptyRegistrationString("registerImporter name", name));
1810
- assertRegistrationFunction("registerImporter importer", importer);
1811
- const commandPath = toRegistrationCommandPath(normalizedName, "import");
1812
- // Validate and register optional command metadata before mutating the registry
1813
- // so an invalid options object leaves no partial importer registration.
1814
- this.applyImportExportCommandMetadata("registerImporter", commandPath, options);
1815
- this.#registrationRegistry.importers.push({
1816
- layer: this.#loadedExtension.layer,
1817
- name: this.#loadedExtension.name,
1818
- importer: normalizedName,
1819
- });
1820
- this.#commandRegistry.handlers.push({
1821
- layer: this.#loadedExtension.layer,
1822
- name: this.#loadedExtension.name,
1823
- command: commandPath,
1824
- run: async (context) => importer(buildImportExportContext(context, normalizedName, "import")),
1825
- });
1826
- }
1827
- registerExporter(name, exporter, options) {
1828
- assertExtensionCapability(this.#loadedExtension, "importers", "registerExporter");
1829
- if (!this.allowRegistration("importers.exporter", "registerExporter", "importers")) {
1830
- return;
1831
- }
1832
- const normalizedName = normalizeRegistrationName(assertNonEmptyRegistrationString("registerExporter name", name));
1833
- assertRegistrationFunction("registerExporter exporter", exporter);
1834
- const commandPath = toRegistrationCommandPath(normalizedName, "export");
1835
- // Validate and register optional command metadata before mutating the registry
1836
- // so an invalid options object leaves no partial exporter registration.
1837
- const output = this.applyImportExportCommandMetadata("registerExporter", commandPath, options);
1838
- this.#registrationRegistry.exporters.push({
1839
- layer: this.#loadedExtension.layer,
1840
- name: this.#loadedExtension.name,
1841
- exporter: normalizedName,
1842
- ...(output === undefined ? {} : { output }),
1843
- });
1844
- this.#commandRegistry.handlers.push({
1845
- layer: this.#loadedExtension.layer,
1846
- name: this.#loadedExtension.name,
1847
- command: commandPath,
1848
- run: async (context) => {
1849
- const result = await exporter(buildImportExportContext(context, normalizedName, "export"));
1850
- return output?.receipt === "suppress" &&
1851
- !isHostOutputSuppressed(result)
1852
- ? suppressHostOutput(result)
1853
- : result;
1854
- },
1855
- });
1856
- }
1857
- registerSearchProvider(provider) {
1858
- assertExtensionCapability(this.#loadedExtension, "search", "registerSearchProvider");
1859
- if (!this.allowRegistration("search.provider", "registerSearchProvider", "search")) {
1860
- return;
1861
- }
1862
- const runtimeDefinition = normalizeRuntimeRegistrationRecord("registerSearchProvider provider", provider);
1863
- this.#registrationRegistry.search_providers.push(attachRuntimeDefinition({
1864
- layer: this.#loadedExtension.layer,
1865
- name: this.#loadedExtension.name,
1866
- definition: normalizeRegistrationRecord("registerSearchProvider provider", provider),
1867
- }, runtimeDefinition));
1868
- }
1869
- registerVectorStoreAdapter(adapter) {
1870
- assertExtensionCapability(this.#loadedExtension, "search", "registerVectorStoreAdapter");
1871
- if (!this.allowRegistration("search.vectorstore", "registerVectorStoreAdapter", "search")) {
1872
- return;
1873
- }
1874
- const runtimeDefinition = normalizeRuntimeRegistrationRecord("registerVectorStoreAdapter adapter", adapter);
1875
- this.#registrationRegistry.vector_store_adapters.push(attachRuntimeDefinition({
1876
- layer: this.#loadedExtension.layer,
1877
- name: this.#loadedExtension.name,
1878
- definition: normalizeRegistrationRecord("registerVectorStoreAdapter adapter", adapter),
1879
- }, runtimeDefinition));
1880
- }
1881
- registerAssuranceMeasurementProvider(provider) {
1882
- assertExtensionCapability(this.#loadedExtension, "services", "registerAssuranceMeasurementProvider");
1883
- if (!this.allowRegistration("services.assuranceprovider", "registerAssuranceMeasurementProvider", "services")) {
1884
- return;
1885
- }
1886
- validateAssuranceMeasurementProviderDefinition(provider);
1887
- if (provider.network &&
1888
- this.#loadedExtension.permissions?.network !== true) {
1889
- throw new TypeError("registerAssuranceMeasurementProvider network provider requires permissions.network=true");
1890
- }
1891
- const runtimeDefinition = normalizeRuntimeRegistrationRecord("registerAssuranceMeasurementProvider provider", provider);
1892
- this.#registrationRegistry.assurance_providers.push(attachRuntimeDefinition({
1893
- layer: this.#loadedExtension.layer,
1894
- name: this.#loadedExtension.name,
1895
- network_permission: this.#loadedExtension.permissions?.network === true,
1896
- definition: normalizeRegistrationRecord("registerAssuranceMeasurementProvider provider", provider),
1897
- }, runtimeDefinition));
1898
- }
1899
- registerBeforeCommand(hook) {
1900
- assertExtensionCapability(this.#loadedExtension, "hooks", "api.hooks.beforeCommand");
1901
- if (!this.allowRegistration("hooks.beforecommand", "api.hooks.beforeCommand", "hooks"))
1902
- return;
1903
- assertHookHandler("beforeCommand", hook);
1904
- this.#hookRegistry.beforeCommand.push({
1905
- layer: this.#loadedExtension.layer,
1906
- name: this.#loadedExtension.name,
1907
- run: hook,
1908
- });
1909
- }
1910
- registerBeforeMutation(hook) {
1911
- assertExtensionCapability(this.#loadedExtension, "hooks", "api.hooks.beforeMutation");
1912
- if (!this.allowRegistration("hooks.beforemutation", "api.hooks.beforeMutation", "hooks"))
1913
- return;
1914
- assertHookHandler("beforeMutation", hook);
1915
- this.#hookRegistry.beforeMutation.push({
1916
- layer: this.#loadedExtension.layer,
1917
- name: this.#loadedExtension.name,
1918
- run: hook,
1919
- });
1920
- }
1921
- registerAfterCommand(hook) {
1922
- assertExtensionCapability(this.#loadedExtension, "hooks", "api.hooks.afterCommand");
1923
- if (!this.allowRegistration("hooks.aftercommand", "api.hooks.afterCommand", "hooks"))
1924
- return;
1925
- assertHookHandler("afterCommand", hook);
1926
- this.#hookRegistry.afterCommand.push({
1927
- layer: this.#loadedExtension.layer,
1928
- name: this.#loadedExtension.name,
1929
- run: hook,
1930
- });
1931
- }
1932
- registerOnWrite(hook) {
1933
- assertExtensionCapability(this.#loadedExtension, "hooks", "api.hooks.onWrite");
1934
- if (!this.allowRegistration("hooks.onwrite", "api.hooks.onWrite", "hooks"))
1935
- return;
1936
- assertHookHandler("onWrite", hook);
1937
- this.#hookRegistry.onWrite.push({
1938
- layer: this.#loadedExtension.layer,
1939
- name: this.#loadedExtension.name,
1940
- run: hook,
1941
- });
1942
- }
1943
- registerOnRead(hook) {
1944
- assertExtensionCapability(this.#loadedExtension, "hooks", "api.hooks.onRead");
1945
- if (!this.allowRegistration("hooks.onread", "api.hooks.onRead", "hooks"))
1946
- return;
1947
- assertHookHandler("onRead", hook);
1948
- this.#hookRegistry.onRead.push({
1949
- layer: this.#loadedExtension.layer,
1950
- name: this.#loadedExtension.name,
1951
- run: hook,
1952
- });
1953
- }
1954
- registerOnIndex(hook) {
1955
- assertExtensionCapability(this.#loadedExtension, "hooks", "api.hooks.onIndex");
1956
- if (!this.allowRegistration("hooks.onindex", "api.hooks.onIndex", "hooks"))
1957
- return;
1958
- assertHookHandler("onIndex", hook);
1959
- this.#hookRegistry.onIndex.push({
1960
- layer: this.#loadedExtension.layer,
1961
- name: this.#loadedExtension.name,
1962
- run: hook,
1963
- });
1964
- }
1965
- }
1966
- function createExtensionApi(extension, hooks, commands, parsers, preflight, services, renderers, registrations, activationWarnings, activationFailures, policy) {
1967
- return new ExtensionApiRegistrar(extension, hooks, commands, parsers, preflight, services, renderers, registrations, activationWarnings, activationFailures, policy);
1968
- }
1969
- function getRegistrationCounts(registrations) {
1970
- const commandCount = registrations.commands.length;
1971
- const flagCount = registrations.flags.reduce((total, entry) => total + entry.flags.length, 0);
1972
- const itemFieldCount = registrations.item_fields.reduce((total, entry) => total + entry.fields.length, 0);
1973
- const itemTypeCount = registrations.item_types.reduce((total, entry) => total + entry.types.length, 0);
1974
- // Preserve compatibility with activation payloads produced before this registry existed.
1975
- const relationshipKindCount = (registrations.relationship_kinds ?? []).reduce((total, entry) => total + entry.definitions.length, 0);
1976
- return {
1977
- commands: commandCount,
1978
- flags: flagCount,
1979
- item_fields: itemFieldCount,
1980
- item_types: itemTypeCount,
1981
- ...(relationshipKindCount > 0
1982
- ? { relationship_kinds: relationshipKindCount }
1983
- : {}),
1984
- migrations: registrations.migrations.length,
1985
- profiles: registrations.profiles.length,
1986
- importers: registrations.importers.length,
1987
- exporters: registrations.exporters.length,
1988
- search_providers: registrations.search_providers.length,
1989
- vector_store_adapters: registrations.vector_store_adapters.length,
1990
- ...((registrations.assurance_providers?.length ?? 0) > 0
1991
- ? { assurance_providers: registrations.assurance_providers.length }
1992
- : {}),
1993
- };
1994
- }
1995
- function collectCommandCollisionWarnings(commands) {
1996
- const warnings = [];
1997
- const collectByCommand = (entries, codePrefix) => {
1998
- const grouped = new Map();
1999
- for (const entry of entries) {
2000
- const bucket = grouped.get(entry.command) ?? [];
2001
- bucket.push(entry);
2002
- grouped.set(entry.command, bucket);
2003
- }
2004
- for (const command of [...grouped.keys()].sort((left, right) => left.localeCompare(right))) {
2005
- const bucket = grouped.get(command);
2006
- if (bucket.length <= 1) {
2007
- continue;
2008
- }
2009
- const winner = bucket[bucket.length - 1];
2010
- for (const displaced of bucket.slice(0, -1)) {
2011
- warnings.push(`${codePrefix}:${command}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`);
2012
- }
2013
- }
2014
- };
2015
- collectByCommand(commands.handlers, "extension_command_handler_collision");
2016
- collectByCommand(commands.overrides, "extension_command_override_collision");
2017
- const handlerCommands = new Set(commands.handlers.map((entry) => entry.command));
2018
- const overlapCommands = [
2019
- ...new Set(commands.overrides.map((entry) => entry.command)),
2020
- ].filter((command) => handlerCommands.has(command));
2021
- overlapCommands.sort((left, right) => left.localeCompare(right));
2022
- for (const command of overlapCommands) {
2023
- const handlers = commands.handlers.filter((entry) => entry.command === command);
2024
- const overrides = commands.overrides.filter((entry) => entry.command === command);
2025
- for (const override of overrides) {
2026
- for (const handler of handlers) {
2027
- warnings.push(`extension_command_override_handler_overlap:${command}:${override.layer}:${override.name}:${handler.layer}:${handler.name}`);
2028
- }
2029
- }
2030
- }
2031
- return warnings;
2032
- }
2033
- function collectRendererCollisionWarnings(renderers) {
2034
- const grouped = new Map();
2035
- for (const entry of renderers.overrides) {
2036
- const bucket = grouped.get(entry.format) ?? [];
2037
- bucket.push(entry);
2038
- grouped.set(entry.format, bucket);
2039
- }
2040
- const warnings = [];
2041
- for (const format of [...grouped.keys()].sort((left, right) => left.localeCompare(right))) {
2042
- const bucket = grouped.get(format);
2043
- if (bucket.length <= 1) {
2044
- continue;
2045
- }
2046
- const winner = bucket[bucket.length - 1];
2047
- for (const displaced of bucket.slice(0, -1)) {
2048
- if (winner.commands?.length &&
2049
- displaced.commands?.length &&
2050
- !displaced.commands.some((command) => winner.commands?.includes(command))) {
2051
- continue;
2052
- }
2053
- warnings.push(`extension_renderer_collision:${format}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`);
2054
- }
2055
- }
2056
- return warnings;
2057
- }
2058
- function collectParserCollisionWarnings(parsers) {
2059
- const warnings = [];
2060
- const grouped = new Map();
2061
- for (const entry of parsers.overrides) {
2062
- const bucket = grouped.get(entry.command) ?? [];
2063
- bucket.push(entry);
2064
- grouped.set(entry.command, bucket);
2065
- }
2066
- for (const command of [...grouped.keys()].sort((left, right) => left.localeCompare(right))) {
2067
- const bucket = grouped.get(command);
2068
- if (bucket.length <= 1) {
2069
- continue;
2070
- }
2071
- const winner = bucket[bucket.length - 1];
2072
- for (const displaced of bucket.slice(0, -1)) {
2073
- warnings.push(`extension_parser_override_collision:${command}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`);
2074
- }
2075
- }
2076
- return warnings;
2077
- }
2078
- // Services whose runtime semantics are chain/fall-through (each override gets a chance);
2079
- // for those, registering multiple overrides is by design, not a collision.
2080
- const CHAINED_SERVICE_NAMES = new Set(["output_format"]);
2081
- function collectServiceCollisionWarnings(services) {
2082
- const warnings = [];
2083
- const grouped = new Map();
2084
- for (const entry of services.overrides) {
2085
- const bucket = grouped.get(entry.service) ?? [];
2086
- bucket.push(entry);
2087
- grouped.set(entry.service, bucket);
2088
- }
2089
- for (const service of [...grouped.keys()].sort((left, right) => left.localeCompare(right))) {
2090
- const bucket = grouped.get(service);
2091
- if (bucket.length <= 1) {
2092
- continue;
2093
- }
2094
- if (CHAINED_SERVICE_NAMES.has(service)) {
2095
- continue;
2096
- }
2097
- const winner = bucket[bucket.length - 1];
2098
- for (const displaced of bucket.slice(0, -1)) {
2099
- warnings.push(`extension_service_override_collision:${service}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`);
2100
- }
2101
- }
2102
- return warnings;
2103
- }
2104
- /** Implements activate extensions for the public runtime surface of this module. */
2105
- export async function activateExtensions(loadResult) {
2106
- const policy = hydrateExtensionPolicy(loadResult.policy ?? DEFAULT_EXTENSION_POLICY);
2107
- const hooks = createEmptyExtensionHookRegistry();
2108
- const commands = createEmptyExtensionCommandRegistry();
2109
- const parsers = createEmptyExtensionParserRegistry();
2110
- const preflight = createEmptyExtensionPreflightRegistry();
2111
- const services = createEmptyExtensionServiceRegistry();
2112
- const renderers = createEmptyExtensionRendererRegistry();
2113
- const registrations = createEmptyExtensionRegistrationRegistry();
2114
- const failed = [];
2115
- const warnings = [];
2116
- for (const extension of loadResult.loaded) {
2117
- const activatable = resolveActivatableExtension(extension.module);
2118
- if (!activatable) {
2119
- continue;
2120
- }
2121
- const failedBeforeActivation = failed.length;
2122
- const rollbackPartialActivation = captureExtensionActivationRollback({
2123
- hooks,
2124
- commands,
2125
- parsers,
2126
- preflight,
2127
- services,
2128
- renderers,
2129
- registrations,
2130
- });
2131
- try {
2132
- await activatable.activate(createExtensionApi(extension, hooks, commands, parsers, preflight, services, renderers, registrations, warnings, failed, policy));
2133
- if (failed.length > failedBeforeActivation) {
2134
- rollbackPartialActivation();
2135
- warnings.push(`extension_activation_rolled_back:${extension.layer}:${extension.name}`);
2136
- }
2137
- }
2138
- catch (error) {
2139
- rollbackPartialActivation();
2140
- warnings.push(`extension_activate_failed:${extension.layer}:${extension.name}`);
2141
- const trace = extractRegistrationValidationTrace(error);
2142
- failed.push({
2143
- layer: extension.layer,
2144
- name: extension.name,
2145
- entry_path: extension.entry_path,
2146
- error: formatUnknownError(error),
2147
- trace,
2148
- });
2149
- }
2150
- }
2151
- const collisionWarnings = [
2152
- ...collectCommandCollisionWarnings(commands),
2153
- ...collectParserCollisionWarnings(parsers),
2154
- ...collectPreflightCollisionWarnings(preflight),
2155
- ...collectServiceCollisionWarnings(services),
2156
- ...collectRendererCollisionWarnings(renderers),
2157
- ];
2158
- const mergedWarnings = [...new Set([...warnings, ...collisionWarnings])];
2159
- return {
2160
- hooks,
2161
- commands,
2162
- parsers,
2163
- preflight,
2164
- services,
2165
- renderers,
2166
- registrations,
2167
- failed,
2168
- warnings: mergedWarnings,
2169
- hook_counts: {
2170
- before_command: hooks.beforeCommand.length,
2171
- before_mutation: hooks.beforeMutation.length,
2172
- after_command: hooks.afterCommand.length,
2173
- on_write: hooks.onWrite.length,
2174
- on_read: hooks.onRead.length,
2175
- on_index: hooks.onIndex.length,
2176
- },
2177
- command_override_count: commands.overrides.length,
2178
- command_handler_count: commands.handlers.length,
2179
- parser_override_count: parsers.overrides.length,
2180
- preflight_override_count: preflight.overrides.length,
2181
- service_override_count: services.overrides.length,
2182
- renderer_override_count: renderers.overrides.length,
2183
- registration_counts: getRegistrationCounts(registrations),
2184
- };
2185
- }
2186
- /** Public contract for test only loader, shared by SDK and presentation-layer consumers. */
2187
- export const _testOnlyLoader = {
2188
- assertFlagValueTypeAndDefault,
2189
- assertOptionalStringField,
2190
- compareComparableVersions,
2191
- collectCommandCollisionWarnings,
2192
- collectParserCollisionWarnings,
2193
- collectRendererCollisionWarnings,
2194
- collectServiceCollisionWarnings,
2195
- createExtensionApi,
2196
- createRegistrationValidationError,
2197
- evaluatePmMaxVersionCompatibility,
2198
- evaluatePmMinVersionCompatibility,
2199
- extractRegistrationValidationTrace,
2200
- fingerprintPath,
2201
- getRegistrationCounts,
2202
- normalizeCommandDefinitionArguments,
2203
- normalizeExtensionDeactivateTimeout,
2204
- normalizeOptionalStringArrayField,
2205
- normalizeRegistrationRecord,
2206
- normalizeRegistrationRecordList,
2207
- normalizeRuntimeRegistrationRecord,
2208
- parseComparableVersion,
2209
- parseManifest: parseExtensionManifestDocument,
2210
- readCurrentPmCliVersion,
2211
- readManagedExtensionSourcePackages: async (extensionsRoot) => new Map([...(await readManagedExtensionSourcePackages(extensionsRoot))]
2212
- .filter((entry) => typeof entry[1].package_name === "string")
2213
- .map(([key, identity]) => [key, identity.package_name])),
2214
- resolveExtensionImportHref,
2215
- resolveCurrentPmCliVersion,
2216
- resolveCommandDefinitionAction,
2217
- sanitizeRegistrationValue,
2218
- validateItemFieldDefinitions,
2219
- resetCurrentPmCliVersionCacheForTest: () => {
2220
- currentPmCliVersionPromise = null;
2221
- },
2222
- };
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="2f54ac29-9bf8-51f4-9352-8f57d1b5a798")}catch(e2){}})();import fs from"node:fs/promises";import path from"node:path";import{pathToFileURL}from"node:url";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{resolveGlobalPmRoot}from"../store/paths.js";import{asRecordLoose,resolveActivatablePropertyRecord}from"../shared/primitives.js";import{flattenFlagListValue,isFlagDefaultValueCoercible,resolveFlagValueKind}from"./flag-value-types.js";import{KNOWN_ITEM_FIELD_TYPES,normalizeItemFieldType,suggestKnownItemFieldType}from"./item-field-types.js";import{snapshotExtensionModuleGraph}from"./module-graph-snapshot.js";import{captureExtensionActivationRollback}from"./activation-transaction.js";import{collectPreflightCollisionWarnings,normalizePreflightOverride}from"./preflight-ownership.js";import{normalizeServiceOverrideOwnership}from"./service-ownership.js";import{assertCommandDefinitionMetadataStrings}from"./command-visibility-tier.js";import{buildImportExportContext,resolveImportExportArtifactOutput}from"./exporter-output-contract.js";import{asRegistrationRecord,assertOptionalBooleanField,assertOptionalFlagDefaultField,assertOptionalStringArrayField,assertOptionalStringField,normalizeOptionalStringArrayField}from"./registration-validation.js";import{describeExtensionLongFlagFailure,findExtensionFlagTokenFailure}from"./flag-definition-validation.js";import{compareComparableVersions,evaluatePmMaxVersionBound,evaluatePmMinVersionBound,parseComparableVersion}from"./version-compat.js";import{createRelationshipKindRegistry}from"../../sdk/relationships.js";import{normalizeNames,isKnownExtensionCapability,collectUnknownExtensionCapabilities,normalizeManifestCapabilities,formatUnknownExtensionCapabilityWarning,formatLegacyExtensionCapabilityAliasWarning}from"./extension-capability-aliases.js";import{normalizeExtensionPolicy,serializeExtensionPolicy,hydrateExtensionPolicy,normalizePolicySandboxProfile,evaluateExtensionPolicyForExtension,evaluateExtensionPolicyForCapability,evaluateExtensionPolicyForRegistration}from"./extension-policy.js";import{createEmptyExtensionHookRegistry,createEmptyExtensionCommandRegistry,createEmptyExtensionParserRegistry,createEmptyExtensionPreflightRegistry,createEmptyExtensionServiceRegistry,createEmptyExtensionRendererRegistry,createEmptyExtensionRegistrationRegistry}from"./extension-registries.js";import{normalizeCommandName}from"./extension-runtime-helpers.js";import{normalizeExtensionContributionInventory}from"./contribution-inventory.js";import{formatExtensionManifestSchemaWarnings}from"./manifest-schema.js";import{attachRuntimeDefinition,assertHookHandler,assertNonEmptyRegistrationString,assertRegistrationFunction,cloneRuntimeRegistrationValue,createRegistrationValidationError,extractRegistrationValidationTrace,isExtensionServiceName,isOutputRendererFormat,normalizeRegistrationRecord,normalizeRegistrationRecordList,normalizeRuntimeRegistrationRecord,normalizeRegistrationName,sanitizeRegistrationValue,toRegistrationCommandPath,validateAssuranceMeasurementProviderDefinition}from"./registration-values.js";import{buildReadyExtensionCandidate}from"./extension-candidate.js";import{parseUnknownExtensionCapabilityWarning,parseLegacyExtensionCapabilityAliasWarning}from"./extension-capability-aliases.js";import{createEmptyExtensionHookRegistry as createEmptyExtensionHookRegistry2,createEmptyExtensionCommandRegistry as createEmptyExtensionCommandRegistry2,createEmptyExtensionParserRegistry as createEmptyExtensionParserRegistry2,createEmptyExtensionPreflightRegistry as createEmptyExtensionPreflightRegistry2,createEmptyExtensionServiceRegistry as createEmptyExtensionServiceRegistry2,createEmptyExtensionRendererRegistry as createEmptyExtensionRendererRegistry2,createEmptyExtensionRegistrationRegistry as createEmptyExtensionRegistrationRegistry2}from"./extension-registries.js";import{runBeforeCommandHooks,runBeforeMutationHooks,runAfterCommandHooks,runOnWriteHooks,runOnReadHooks,runOnIndexHooks,runCommandHandler,runParserOverride,runPreflightOverride,runServiceOverrideSync,runServiceOverride,runCommandOverride,runRendererOverride}from"./extension-hook-runtime.js";import{KNOWN_EXTENSION_CAPABILITIES,KNOWN_EXTENSION_SERVICE_NAMES,createDefaultExtensionGovernancePolicy}from"./extension-types.js";export*from"./extension-types.js";const DEFAULT_EXTENSION_PRIORITY=100;let currentPmCliVersionPromise=null;const DEFAULT_EXTENSION_POLICY=Object.freeze(createDefaultExtensionGovernancePolicy());let extensionReloadEpoch=0;function nextExtensionReloadToken(seed=Date.now()){extensionReloadEpoch+=1;return`${extensionReloadEpoch}-${seed}`}function parseOptionalManifestString(candidate,field){const value=candidate[field];if(value===void 0||value===null){return void 0}if(typeof value!=="string"||value.trim().length===0){return null}return value.trim()}function parseManifestEngines(value){if(value===void 0||value===null){return void 0}const enginesRecord=asRecordLoose(value);if(!enginesRecord){return null}const engines={};for(const key of Object.keys(enginesRecord).sort((left,right)=>left.localeCompare(right))){if(key.trim().length===0){return null}const engineValue=enginesRecord[key];if(typeof engineValue!=="string"||engineValue.trim().length===0){return null}engines[key.trim()]=engineValue.trim()}return Object.keys(engines).length>0?engines:void 0}function parseRequiredManifestString(candidate,field){const value=candidate[field];if(typeof value!=="string"||value.trim().length===0){return null}return value.trim()}function parseOptionalIntegerValue(value){if(value===void 0||value===null){return void 0}if(typeof value!=="number"||!Number.isInteger(value)){return null}return value}function parseOptionalBooleanValue(value){if(value===void 0||value===null){return void 0}if(typeof value!=="boolean"){return null}return value}function parseManifestPriority(candidate){const value=parseOptionalIntegerValue(candidate.priority);return value===void 0?DEFAULT_EXTENSION_PRIORITY:value}function parseManifestSandboxProfile(candidate){const value=candidate.sandbox_profile;if(value===void 0||value===null){return void 0}if(typeof value!=="string"){return null}const normalizedProfile=normalizePolicySandboxProfile(value);if(normalizedProfile!==value.trim().toLowerCase()){return null}return normalizedProfile}function optionalTrimmedString(value){return typeof value==="string"&&value.trim().length>0?value.trim():void 0}function parseManifestProvenance(value){if(value===void 0||value===null){return void 0}const provenanceRecord=asRecordLoose(value);if(!provenanceRecord){return null}const source=optionalTrimmedString(provenanceRecord.source);const signature=optionalTrimmedString(provenanceRecord.signature);const attestation=optionalTrimmedString(provenanceRecord.attestation);const verified=provenanceRecord.verified===void 0||provenanceRecord.verified===null?void 0:typeof provenanceRecord.verified==="boolean"?provenanceRecord.verified:null;if(verified===null){return null}return{...source?{source}:{},...signature?{signature}:{},...attestation?{attestation}:{},...typeof verified==="boolean"?{verified}:{}}}function parseManifestPermissions(value){if(value===void 0||value===null){return void 0}const permissionsRecord=asRecordLoose(value);if(!permissionsRecord){return null}const fsRead=parseOptionalBooleanValue(permissionsRecord.fs_read);const fsWrite=parseOptionalBooleanValue(permissionsRecord.fs_write);const network=parseOptionalBooleanValue(permissionsRecord.network);const envRead=parseOptionalBooleanValue(permissionsRecord.env_read);const envWrite=parseOptionalBooleanValue(permissionsRecord.env_write);const processSpawn=parseOptionalBooleanValue(permissionsRecord.process_spawn);if([fsRead,fsWrite,network,envRead,envWrite,processSpawn].includes(null)){return null}return{...typeof fsRead==="boolean"?{fs_read:fsRead}:{},...typeof fsWrite==="boolean"?{fs_write:fsWrite}:{},...typeof network==="boolean"?{network}:{},...typeof envRead==="boolean"?{env_read:envRead}:{},...typeof envWrite==="boolean"?{env_write:envWrite}:{},...typeof processSpawn==="boolean"?{process_spawn:processSpawn}:{}}}function parseManifestCapabilities(value){if(value===void 0||value===null){return{capabilities:[],legacy_aliases:[]}}if(!Array.isArray(value)||value.some(entry=>typeof entry!=="string")){return null}const normalizedCapabilities=normalizeManifestCapabilities(value);return{capabilities:normalizedCapabilities.capabilities,legacy_aliases:normalizedCapabilities.legacy_aliases}}function parseManifestActivation(value){if(value===void 0||value===null){return void 0}const activationRecord=asRecordLoose(value);if(!activationRecord){return null}const rawCommands=activationRecord.commands;if(rawCommands===void 0||rawCommands===null){return void 0}if(!Array.isArray(rawCommands)||rawCommands.some(entry=>typeof entry!=="string")){return null}const commands=[...new Set(rawCommands.map(entry=>normalizeCommandName(entry)).filter(entry=>entry.length>0))].sort((left,right)=>left.localeCompare(right));return commands.length>0?{commands}:void 0}function parseManifestMetadata(candidate){const manifestVersion=parseOptionalIntegerValue(candidate.manifest_version);if(manifestVersion===null){return null}const pmMinVersion=parseOptionalManifestString(candidate,"pm_min_version");if(pmMinVersion===null){return null}const pmMaxVersion=parseOptionalManifestString(candidate,"pm_max_version");if(pmMaxVersion===null){return null}const engines=parseManifestEngines(candidate.engines);if(engines===null){return null}const trusted=parseOptionalBooleanValue(candidate.trusted);if(trusted===null){return null}const sandboxProfile=parseManifestSandboxProfile(candidate);if(sandboxProfile===null){return null}const provenance=parseManifestProvenance(candidate.provenance);if(provenance===null){return null}const permissions=parseManifestPermissions(candidate.permissions);if(permissions===null){return null}const capabilities=parseManifestCapabilities(candidate.capabilities);if(capabilities===null){return null}const activation=parseManifestActivation(candidate.activation);if(activation===null){return null}const contributions=normalizeExtensionContributionInventory(candidate.contributions);if(contributions===null){return null}return{manifest_version:manifestVersion,pm_min_version:pmMinVersion,pm_max_version:pmMaxVersion,engines,trusted,sandbox_profile:sandboxProfile,provenance,permissions,capabilities:capabilities.capabilities,legacy_capability_aliases:capabilities.legacy_aliases,activation,contributions}}function parseExtensionManifestDocument(raw){if(typeof raw!=="object"||raw===null){return null}const candidate=raw;const name=parseRequiredManifestString(candidate,"name");if(name===null){return null}const version=parseRequiredManifestString(candidate,"version");if(version===null){return null}const entry=parseRequiredManifestString(candidate,"entry");if(entry===null){return null}const priority=parseManifestPriority(candidate);if(priority===null){return null}const metadata=parseManifestMetadata(candidate);if(metadata===null){return null}return{name,version,entry,priority,manifest_version:metadata.manifest_version,pm_min_version:metadata.pm_min_version,pm_max_version:metadata.pm_max_version,engines:metadata.engines,trusted:metadata.trusted,provenance:metadata.provenance,sandbox_profile:metadata.sandbox_profile,permissions:metadata.permissions,activation:metadata.activation,contributions:metadata.contributions,capabilities:metadata.capabilities,legacy_capability_aliases:metadata.legacy_capability_aliases.length>0?metadata.legacy_capability_aliases:void 0}}function shouldEnable(name,enabled,disabled){if(disabled.has(name)){return false}if(enabled.size===0){return true}return 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{const entries=await fs.readdir(extensionsRoot,{withFileTypes:true});return entries.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};if(candidate.source_package){summary.source_package=candidate.source_package}if(candidate.source_aliases){summary.source_aliases=[...candidate.source_aliases]}return 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"));const managedExtensions=asRecordLoose(parsed);const entries=managedExtensions?.entries;if(!Array.isArray(entries)){return packages}for(const entry of entries){if(typeof entry!=="object"||entry===null){continue}const record=entry;const sourcePackage=normalizeManagedSourcePackage(record.source?.package);const aliases=[record.source?.input,record.source?.name,sourcePackage].map(value=>normalizeManagedSourcePackage(value)).filter(value=>value!==void 0);const contributions=normalizeExtensionContributionInventory(record.contributions);const identity={aliases:[...new Set(aliases)],...sourcePackage?{package_name:sourcePackage}:{},...contributions?{contributions}:{}};if(typeof record.directory==="string"&&record.directory.trim().length>0){packages.set(`directory:${record.directory.trim()}`,identity)}if(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);if(byName!==0){return byName}return left.directory.localeCompare(right.directory)})}function buildEffectiveExtensions(globalCandidates,projectCandidates){const ordered=[...sortCandidates(globalCandidates),...sortCandidates(projectCandidates)];const effective=[];for(const candidate of ordered){const existingIndex=effective.findIndex(entry=>entry.manifest.name===candidate.manifest.name);if(existingIndex>=0){effective.splice(existingIndex,1)}effective.push(candidate)}return effective}async function scanExtensionLayer(layer,extensionsRoot,enabled,disabled,pmMaxVersionExceededMode){const diagnostics=[];const warnings=[];const candidates=[];const directories=await listExtensionDirectories(extensionsRoot);const 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);if(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);if(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))}if(!entryWithinDirectory){extensionWarnings.push(`extension_entry_outside_extension:${layer}:${manifest.name}`)}else if(!entryExists){extensionWarnings.push(`extension_entry_missing:${layer}:${manifest.name}`)}if(pmVersionCompatibility.warning){extensionWarnings.push(pmVersionCompatibility.warning)}if(pmMaxVersionCompatibility.warning){extensionWarnings.push(pmMaxVersionCompatibility.warning)}return extensionWarnings}async function scanExtensionDirectory(layer,extensionsRoot,directory,enabled,disabled,managedSourcePackages,pmMaxVersionExceededMode){const extensionDir=path.join(extensionsRoot,directory);const manifestPath=path.join(extensionDir,"manifest.json");if(!await pathExists(manifestPath)){return buildUnavailableExtensionScan(layer,directory,manifestPath,`extension_manifest_missing:${layer}:${directory}`)}let manifest;let 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);const entryWithinDirectoryByPath=isPathWithinDirectory(extensionDir,entryPath);const entryExists=entryWithinDirectoryByPath?await pathExists(entryPath):false;const entryWithinDirectory=entryWithinDirectoryByPath&&entryExists?await isCanonicalPathWithinDirectory(extensionDir,entryPath):entryWithinDirectoryByPath;const enabledForLoad=shouldEnable(manifest.name,enabled,disabled);const pmVersionCompatibility=await evaluatePmMinVersionCompatibility(layer,manifest);const pmMaxVersionCompatibility=await evaluatePmMaxVersionCompatibility(layer,manifest,pmMaxVersionExceededMode);const extensionWarnings=collectScannedExtensionWarnings(layer,manifest,rawManifest,entryWithinDirectory,entryExists,pmVersionCompatibility,pmMaxVersionCompatibility);const extensionReady=entryWithinDirectory&&entryExists&&pmVersionCompatibility.allowed&&pmMaxVersionCompatibility.allowed;const 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());const configured_enabled=normalizeNames(options.settings.extensions.enabled);const configured_disabled=normalizeNames(options.settings.extensions.disabled);const policy=normalizeExtensionPolicy(options.settings);const serializedPolicy=serializeExtensionPolicy(policy);if(options.noExtensions){return{disabled_by_flag:true,roots,configured_enabled,configured_disabled,discovered:[],effective:[],warnings:[...policy.warnings],policy:serializedPolicy}}const enabled=new Set(configured_enabled);const disabled=new Set(configured_disabled);const globalScan=options.ignoreGlobalExtensions===true?emptyExtensionLayerScan():await scanExtensionLayer("global",roots.global,enabled,disabled,policy.pmMaxVersionExceededMode.global);const projectScan=await scanExtensionLayer("project",roots.project,enabled,disabled,policy.pmMaxVersionExceededMode.project);const policyWarnings=[...policy.warnings];const effectiveCandidates=buildEffectiveExtensions(globalScan.candidates,projectScan.candidates);const effective=[];for(const candidate of effectiveCandidates){const extensionRef={layer:candidate.layer,name:candidate.manifest.name,trusted:candidate.manifest.trusted===true,provenanceVerified:candidate.manifest.provenance?.verified===true,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};const extensionDecision=evaluateExtensionPolicyForExtension(policy,extensionRef);if(extensionDecision.warning){policyWarnings.push(extensionDecision.warning)}if(!extensionDecision.allowed){continue}for(const capability of candidate.manifest.capabilities){const capabilityDecision=evaluateExtensionPolicyForCapability(policy,extensionRef,capability);if(capabilityDecision.warning){policyWarnings.push(capabilityDecision.warning)}}effective.push(summarizeCandidate(candidate))}return{disabled_by_flag:false,roots,configured_enabled,configured_disabled,discovered:[...globalScan.diagnostics,...projectScan.diagnostics],effective,warnings:[...new Set([...globalScan.warnings,...projectScan.warnings,...policyWarnings])],policy:serializedPolicy}}function formatUnknownError(error){if(error instanceof Error&&error.message.trim().length>0){return error.message}return String(error)}async function readCurrentPmCliVersion(){try{const packageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]);const raw=await fs.readFile(path.join(packageRoot,"package.json"),"utf8");const parsed=JSON.parse(raw);return typeof parsed.version==="string"&&parsed.version.trim().length>0?parsed.version.trim():null}catch{return null}}function resolveCurrentPmCliVersion(){currentPmCliVersionPromise??=readCurrentPmCliVersion();return 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 void 0}}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 void 0}}async function evaluatePmMinVersionCompatibility(layer,manifest){if(manifest.pm_min_version===void 0){return{allowed:true}}const evaluation=evaluatePmMinVersionBound(manifest.pm_min_version,await resolveCurrentPmCliVersion());const 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:true}}const evaluation=evaluatePmMaxVersionBound(manifest.pm_max_version,await resolveCurrentPmCliVersion(),exceededMode);const 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;if(options.module_graph_snapshot_root){importEntryPath=await snapshotExtensionModuleGraph(options.module_graph_snapshot_root,extension)}const baseUrl=new URL(pathToFileURL(importEntryPath).href);const shouldCacheBust=options.cache_bust===true||typeof options.reload_token==="string";if(!shouldCacheBust){return baseUrl.href}const[entryFingerprint,manifestFingerprint]=await Promise.all([fingerprintPath(extension.entry_path),fingerprintPath(extension.manifest_path)]);const reloadToken=options.reload_token??nextExtensionReloadToken();baseUrl.searchParams.set("pm_ext_reload",reloadToken);baseUrl.searchParams.set("pm_ext_entry",entryFingerprint);baseUrl.searchParams.set("pm_ext_manifest",manifestFingerprint);return baseUrl.href}async function loadExtensions(options){const discovery=await discoverExtensions(options);const loaded=[];const failed=[];const 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 importHref=await resolveExtensionImportHref(extension,options);const module=await import(importHref);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;const MAX_EXTENSION_DEACTIVATE_TIMEOUT_MS=2147483647;function toActivatableExtension(source){const activate=source.activate;const activatable={activate: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);const failedActivationKeys=new Set((activationResult?.failed??[]).map(entry=>`${entry.layer}:${entry.name}`));const targets=[];for(const extension of loadResult.loaded){if(failedActivationKeys.has(`${extension.layer}:${extension.name}`)){continue}const activatable=resolveActivatableExtension(extension.module);if(!activatable||typeof activatable.deactivate!=="function"){continue}targets.push({extension,deactivate:activatable.deactivate})}const outcomes=await Promise.all(targets.map(async({extension,deactivate})=>{try{await runExtensionDeactivateWithTimeout(deactivate,timeoutMs);return{ok:true}}catch(error){return{ok:false,layer:extension.layer,name:extension.name,error:formatUnknownError(error)}}}));const warnings=[];const 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){if(typeof rawTimeout!=="number"||rawTimeout<0){return DEFAULT_EXTENSION_DEACTIVATE_TIMEOUT_MS}if(rawTimeout===0||rawTimeout===Infinity){return 0}if(!Number.isFinite(rawTimeout)){return DEFAULT_EXTENSION_DEACTIVATE_TIMEOUT_MS}return Math.min(MAX_EXTENSION_DEACTIVATE_TIMEOUT_MS,Math.max(1,Math.floor(rawTimeout)))}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)}}const FLAG_DEFINITION_KEYS=new Set(["default","description","enabled","list","long","repeatable","required","short","type","value_name","value_type","visible"]);function normalizeFlagDefinitions(name,value){return normalizeRegistrationRecordList(name,value).map(record=>{if(record.repeatable===true){record.list=true}return record})}function normalizeCommandActionName(value){return value.trim().toLowerCase().replace(/[\s_]+/g,"-").replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function resolveCommandDefinitionAction(commandPath,action){if(action===void 0){return commandPath.replace(/\s+/g,"-")}if(typeof action!=="string"||action.trim().length===0){throw new TypeError("registerCommand definition.action must be a non-empty string when provided")}const normalized=normalizeCommandActionName(action);if(normalized.length===0){throw new TypeError("registerCommand definition.action must contain alphanumeric characters")}return normalized}function normalizeCommandDefinitionArguments(value){if(value===void 0){return[]}if(!Array.isArray(value)){throw new TypeError("registerCommand definition.arguments must be an array when provided")}const normalized=[];for(const[index,entry]of value.entries()){const record=asRegistrationRecord(`registerCommand definition.arguments[${index}]`,entry);const name=assertNonEmptyRegistrationString(`registerCommand definition.arguments[${index}].name`,record.name);assertOptionalBooleanField(`registerCommand definition.arguments[${index}].required`,record.required);assertOptionalBooleanField(`registerCommand definition.arguments[${index}].variadic`,record.variadic);assertOptionalStringField(`registerCommand definition.arguments[${index}].description`,record.description);if(name.includes(" ")){throw new TypeError(`registerCommand definition.arguments[${index}].name must not contain spaces`)}const definition={name};if(record.required===true){definition.required=true}if(record.variadic===true){definition.variadic=true}if(typeof record.description==="string"){definition.description=record.description.trim()}normalized.push(definition)}const variadicIndexes=normalized.map((argument,index)=>argument.variadic?index:-1).filter(index=>index>=0);if(variadicIndexes.length>1){throw new TypeError("registerCommand definition.arguments supports at most one variadic argument")}if(variadicIndexes.length===1&&variadicIndexes[0]!==normalized.length-1){throw new TypeError("registerCommand definition.arguments variadic argument must be the final argument")}return normalized}function validateFlagDefinitions(flags){if(!Array.isArray(flags)){throw new TypeError("registerFlags flags requires an array of object definitions")}for(const[index,raw]of flags.entries()){const record=asRegistrationRecord(`registerFlags flags[${index}]`,raw);const unknownKeys=Object.keys(record).filter(key=>!FLAG_DEFINITION_KEYS.has(key)).sort((left,right)=>left.localeCompare(right));if(unknownKeys.length>0){throw new TypeError(`registerFlags flags[${index}] contains unknown field(s): ${unknownKeys.join(", ")}`)}const long=record.long;const short=record.short;if(long===void 0&&short===void 0){throw new TypeError(`registerFlags flags[${index}] requires at least one of long or short`)}assertOptionalStringField(`registerFlags flags[${index}].long`,long);assertOptionalStringField(`registerFlags flags[${index}].short`,short);const tokenFinding=findExtensionFlagTokenFailure(long,short);if(tokenFinding!==null){throw new TypeError(`registerFlags flags[${index}] ${describeExtensionLongFlagFailure(tokenFinding.token,tokenFinding.failure)}`)}assertOptionalStringField(`registerFlags flags[${index}].value_name`,record.value_name);assertOptionalStringField(`registerFlags flags[${index}].description`,record.description);assertOptionalBooleanField(`registerFlags flags[${index}].required`,record.required);assertOptionalBooleanField(`registerFlags flags[${index}].enabled`,record.enabled);assertOptionalBooleanField(`registerFlags flags[${index}].visible`,record.visible);assertOptionalBooleanField(`registerFlags flags[${index}].list`,record.list);assertOptionalBooleanField(`registerFlags flags[${index}].repeatable`,record.repeatable);if(record.list!==void 0&&record.repeatable!==void 0&&record.list!==record.repeatable){throw new TypeError(`registerFlags flags[${index}].list and repeatable must match when both are provided`)}assertOptionalFlagDefaultField(`registerFlags flags[${index}].default`,record.default);if(Array.isArray(record.default)&&record.list!==true&&record.repeatable!==true){throw new TypeError(`registerFlags flags[${index}].default cannot be an array unless list is true.`)}assertFlagValueTypeAndDefault(`registerFlags flags[${index}]`,record)}}function assertFlagValueTypeAndDefault(label,record){const declaredType=(typeof record.value_type==="string"?record.value_type:void 0)??(typeof record.type==="string"?record.type:void 0);if(declaredType===void 0){return}const kind=resolveFlagValueKind(declaredType);if(kind===null){throw new TypeError(`${label} value_type "${declaredType}" is not a known flag value type (expected one of: string, number, boolean).`)}if(record.default===void 0){return}const defaults=record.list===true||record.repeatable===true?flattenFlagListValue(record.default):[record.default];for(const[defaultIndex,defaultValue]of defaults.entries()){if(!isFlagDefaultValueCoercible(defaultValue,kind)){const suffix=defaults.length>1?`default[${defaultIndex}]`:"default";throw new TypeError(`${label}.${suffix} (${JSON.stringify(defaultValue)}) is not coercible to ${kind}.`)}}}function validateItemFieldDefinitions(fields){if(!Array.isArray(fields)){throw new TypeError("registerItemFields fields requires an array of object definitions")}for(const[index,raw]of fields.entries()){const record=asRegistrationRecord(`registerItemFields fields[${index}]`,raw);assertNonEmptyRegistrationString(`registerItemFields fields[${index}].name`,record.name);const fieldType=assertNonEmptyRegistrationString(`registerItemFields fields[${index}].type`,record.type);if(normalizeItemFieldType(fieldType)===null){const suggestion=suggestKnownItemFieldType(fieldType);const hint=suggestion?` Did you mean "${suggestion}"?`:"";throw new TypeError(`registerItemFields fields[${index}].type "${fieldType}" is not a known field type (expected one of: ${KNOWN_ITEM_FIELD_TYPES.join(", ")}).${hint}`)}assertOptionalBooleanField(`registerItemFields fields[${index}].optional`,record.optional)}}function validateItemTypeCommandOptionPolicies(typeIndex,value){if(value===void 0){return}const label=`registerItemTypes types[${typeIndex}].command_option_policies`;if(!Array.isArray(value)){throw new TypeError(`${label} must be an array when provided`)}for(const[policyIndex,rawPolicy]of value.entries()){const at=`${label}[${policyIndex}]`;const policy=asRegistrationRecord(at,rawPolicy);assertNonEmptyRegistrationString(`${at}.command`,policy.command);assertNonEmptyRegistrationString(`${at}.option`,policy.option);assertOptionalBooleanField(`${at}.enabled`,policy.enabled);assertOptionalBooleanField(`${at}.required`,policy.required);assertOptionalBooleanField(`${at}.visible`,policy.visible)}}function validateItemTypeOptions(typeIndex,value){if(value===void 0){return}const label=`registerItemTypes types[${typeIndex}].options`;if(!Array.isArray(value)){throw new TypeError(`${label} must be an array when provided`)}for(const[optionIndex,rawOption]of value.entries()){const at=`${label}[${optionIndex}]`;const option=asRegistrationRecord(at,rawOption);assertNonEmptyRegistrationString(`${at}.key`,option.key);assertOptionalStringArrayField(`${at}.values`,option.values);assertOptionalBooleanField(`${at}.required`,option.required);assertOptionalStringArrayField(`${at}.aliases`,option.aliases)}}function validateItemTypeDefinitions(types){if(!Array.isArray(types)){throw new TypeError("registerItemTypes types requires an array of object definitions")}for(const[typeIndex,raw]of types.entries()){const at=`registerItemTypes types[${typeIndex}]`;const record=asRegistrationRecord(at,raw);assertNonEmptyRegistrationString(`${at}.name`,record.name);assertOptionalStringField(`${at}.folder`,record.folder);assertOptionalStringArrayField(`${at}.aliases`,record.aliases);assertOptionalStringArrayField(`${at}.required_create_fields`,record.required_create_fields);assertOptionalStringArrayField(`${at}.required_create_repeatables`,record.required_create_repeatables);validateItemTypeCommandOptionPolicies(typeIndex,record.command_option_policies);validateItemTypeOptions(typeIndex,record.options)}}function validateMigrationDefinition(definition){const record=asRegistrationRecord("registerMigration definition",definition);if(record.id!==void 0&&typeof record.id!=="string"){throw new TypeError("registerMigration definition.id must be a string when provided")}if(record.description!==void 0&&typeof record.description!=="string"){throw new TypeError("registerMigration definition.description must be a string when provided")}if(record.status!==void 0&&typeof record.status!=="string"){throw new TypeError("registerMigration definition.status must be a string when provided")}assertOptionalBooleanField("registerMigration definition.mandatory",record.mandatory);if(record.run!==void 0&&typeof record.run!=="function"){throw new TypeError("registerMigration definition.run must be a function when provided")}}const PROJECT_PROFILE_DIMENSIONS=["types","statuses","fields","workflows","config","templates","packages"];const PROJECT_PROFILE_ENTRY_VALIDATORS={types:(at,entry)=>{if(entry.name!==void 0&&typeof entry.name!=="string"){throw new TypeError(`${at}.name must be a string when provided`)}},workflows:(at,entry)=>{if(typeof entry.type!=="string"){throw new TypeError(`${at}.type must be a string`)}if(!Array.isArray(entry.allowed_transitions)){throw new TypeError(`${at}.allowed_transitions must be an array`)}for(const[pairIndex,pair]of entry.allowed_transitions.entries()){if(!Array.isArray(pair)){throw new TypeError(`${at}.allowed_transitions[${pairIndex}] must be a [from, to] array`)}}},templates:(at,entry)=>{if(typeof entry.name!=="string"){throw new TypeError(`${at}.name must be a string`)}if(typeof entry.options!=="object"||entry.options===null||Array.isArray(entry.options)){throw new TypeError(`${at}.options must be an object`)}},packages:(at,entry)=>{if(typeof entry.spec!=="string"){throw new TypeError(`${at}.spec must be a string`)}}};function validateProjectProfileDefinition(profile){const record=asRegistrationRecord("registerProfile profile",profile);assertNonEmptyRegistrationString("registerProfile profile.name",record.name);assertNonEmptyRegistrationString("registerProfile profile.title",record.title);if(record.summary!==void 0&&typeof record.summary!=="string"){throw new TypeError("registerProfile profile.summary must be a string when provided")}for(const dimension of PROJECT_PROFILE_DIMENSIONS){const value=record[dimension];if(value===void 0){continue}if(!Array.isArray(value)){throw new TypeError(`registerProfile profile.${dimension} must be an array when provided`)}for(const[index,entry]of value.entries()){if(typeof entry!=="object"||entry===null||Array.isArray(entry)){throw new TypeError(`registerProfile profile.${dimension}[${index}] must be an object`)}PROJECT_PROFILE_ENTRY_VALIDATORS[dimension]?.(`registerProfile profile.${dimension}[${index}]`,entry)}}}function applyProjectProfileDefaults(profile){if(profile.summary===void 0){profile.summary=""}for(const dimension of PROJECT_PROFILE_DIMENSIONS){if(profile[dimension]===void 0){profile[dimension]=[]}}return profile}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();if(isKnownExtensionCapability(normalized)){declared.add(normalized)}}return declared}function assertExtensionCapability(extension,capability,method){const declared=getDeclaredExtensionCapabilities(extension);if(declared===null){return}if(!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===true,provenanceVerified:extension.provenance?.verified===true,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);if(decision.warning){this.#activationWarnings.push(decision.warning)}return 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)}if(!this.allowRegistration("commands.override","registerCommand","commands",{command:normalizedCommand})){return}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;const legacyHandler=typeof definition.handler==="function"?definition.handler:void 0;if(!runHandler&&legacyHandler){this.#activationWarnings.push(`extension_command_definition_legacy_handler_alias:${this.#loadedExtension.layer}:${this.#loadedExtension.name}:${normalizedCommand}`)}return 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);if(!this.allowRegistration("commands.handler","registerCommand","commands",{command:normalizedCommand,action})){return}const description=definition.description?.trim();const intent=definition.intent?.trim();const examples=normalizeOptionalStringArrayField("registerCommand definition.examples",definition.examples);const failureHints=normalizeOptionalStringArrayField("registerCommand definition.failure_hints",definition.failure_hints);const argumentsDefinition=normalizeCommandDefinitionArguments(definition.arguments);if(definition.flags!==void 0){assertExtensionCapability(this.#loadedExtension,"schema","registerCommand flags");if(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={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"};if(description){registration.description=description}if(intent){registration.intent=intent}this.#registrationRegistry.commands.push(registration)}catch(error){const reason=formatUnknownError(error);const trace=this.registerCommandTrace("definition",normalizedCommand,"{ name: string; run: (context) => unknown; action?: string; arguments?: object[]; flags?: object[]; }",definition,reason);const 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){assertExtensionCapability(this.#loadedExtension,"commands","registerCommand");if(typeof commandOrDefinition==="string"){this.registerCommandOverride(commandOrDefinition,override);return}this.registerCommandDefinition(commandOrDefinition)}registerParser(command,override){assertExtensionCapability(this.#loadedExtension,"parser","registerParser");if(!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){assertExtensionCapability(this.#loadedExtension,"preflight","registerPreflight");if(!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(", ")}`)}if(!this.allowRegistration("services.override","registerService","services",{service:normalizedService})){return}assertRegistrationFunction("registerService override",override);this.#serviceRegistry.overrides.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,service:normalizedService,run:override,...normalizeServiceOverrideOwnership(ownership)?{passThrough:true}:{}})}registerRenderer(format,renderer,ownership={}){assertExtensionCapability(this.#loadedExtension,"renderers","registerRenderer");if(!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){assertExtensionCapability(this.#loadedExtension,"schema","registerFlags");if(!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){assertExtensionCapability(this.#loadedExtension,"schema","registerItemFields");if(!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){assertExtensionCapability(this.#loadedExtension,"schema","registerItemTypes");if(!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){assertExtensionCapability(this.#loadedExtension,"schema","registerRelationshipKinds");if(!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);return registry.require(definition.kind)});this.#registrationRegistry.relationship_kinds.push({layer:this.#loadedExtension.layer,name:this.#loadedExtension.name,definitions:validated})}registerMigration(definition){assertExtensionCapability(this.#loadedExtension,"schema","registerMigration");if(!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){assertExtensionCapability(this.#loadedExtension,"schema","registerProfile");if(!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){if(resolvedOptions.flags===void 0){return}assertExtensionCapability(this.#loadedExtension,"schema",`${method} options.flags`);if(!this.allowRegistration("schema.flags",`${method} options.flags`,"schema")){return}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.`;const defaultArguments=[{name:"file",required:false,description:"Optional input or output file path."}];const resolvedOptions={...options,description:options?.description??defaultDescription,arguments:options?.arguments??defaultArguments};const 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);const examples=normalizeOptionalStringArrayField(`${method} options.examples`,resolvedOptions.examples);const failureHints=normalizeOptionalStringArrayField(`${method} options.failure_hints`,resolvedOptions.failure_hints);const 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};const description=resolvedOptions.description?.trim();if(description){registration.description=description}const intent=resolvedOptions.intent?.trim();if(intent){registration.intent=intent}this.#registrationRegistry.commands.push(registration);return output}registerImporter(name,importer,options){assertExtensionCapability(this.#loadedExtension,"importers","registerImporter");if(!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){assertExtensionCapability(this.#loadedExtension,"importers","registerExporter");if(!this.allowRegistration("importers.exporter","registerExporter","importers")){return}const normalizedName=normalizeRegistrationName(assertNonEmptyRegistrationString("registerExporter name",name));assertRegistrationFunction("registerExporter exporter",exporter);const commandPath=toRegistrationCommandPath(normalizedName,"export");const 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){assertExtensionCapability(this.#loadedExtension,"search","registerSearchProvider");if(!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){assertExtensionCapability(this.#loadedExtension,"search","registerVectorStoreAdapter");if(!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){assertExtensionCapability(this.#loadedExtension,"services","registerAssuranceMeasurementProvider");if(!this.allowRegistration("services.assuranceprovider","registerAssuranceMeasurementProvider","services")){return}validateAssuranceMeasurementProviderDefinition(provider);if(provider.network&&this.#loadedExtension.permissions?.network!==true){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===true,definition:normalizeRegistrationRecord("registerAssuranceMeasurementProvider provider",provider)},runtimeDefinition))}registerBeforeCommand(hook){assertExtensionCapability(this.#loadedExtension,"hooks","api.hooks.beforeCommand");if(!this.allowRegistration("hooks.beforecommand","api.hooks.beforeCommand","hooks"))return;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");if(!this.allowRegistration("hooks.beforemutation","api.hooks.beforeMutation","hooks"))return;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");if(!this.allowRegistration("hooks.aftercommand","api.hooks.afterCommand","hooks"))return;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");if(!this.allowRegistration("hooks.onwrite","api.hooks.onWrite","hooks"))return;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");if(!this.allowRegistration("hooks.onread","api.hooks.onRead","hooks"))return;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");if(!this.allowRegistration("hooks.onindex","api.hooks.onIndex","hooks"))return;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;const flagCount=registrations.flags.reduce((total,entry)=>total+entry.flags.length,0);const itemFieldCount=registrations.item_fields.reduce((total,entry)=>total+entry.fields.length,0);const itemTypeCount=registrations.item_types.reduce((total,entry)=>total+entry.types.length,0);const 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=[];const 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));const 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);const 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)){if(winner.commands?.length&&displaced.commands?.length&&!displaced.commands.some(command=>winner.commands?.includes(command))){continue}warnings.push(`extension_renderer_collision:${format}:${winner.layer}:${winner.name}:${displaced.layer}:${displaced.name}`)}}return warnings}function collectParserCollisionWarnings(parsers){const warnings=[];const 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=[];const 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){continue}if(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);const hooks=createEmptyExtensionHookRegistry();const commands=createEmptyExtensionCommandRegistry();const parsers=createEmptyExtensionParserRegistry();const preflight=createEmptyExtensionPreflightRegistry();const services=createEmptyExtensionServiceRegistry();const renderers=createEmptyExtensionRendererRegistry();const registrations=createEmptyExtensionRegistrationRegistry();const failed=[];const warnings=[];for(const extension of loadResult.loaded){const activatable=resolveActivatableExtension(extension.module);if(!activatable){continue}const failedBeforeActivation=failed.length;const 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));if(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)];const 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,parseExtensionManifestDocument,parseLegacyExtensionCapabilityAliasWarning,parseUnknownExtensionCapabilityWarning,resolveExtensionRoots,runAfterCommandHooks,runBeforeCommandHooks,runBeforeMutationHooks,runCommandHandler,runCommandOverride,runOnIndexHooks,runOnReadHooks,runOnWriteHooks,runParserOverride,runPreflightOverride,runRendererOverride,runServiceOverride,runServiceOverrideSync};
2223
2
  //# sourceMappingURL=loader.js.map
2224
- //# debugId=e4e1b7c2-6551-5e56-b26a-30062aed5b97