@unbrained/pm-cli 2026.10.4 → 2026.10.5

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 (732) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +11 -0
  3. package/dist/cli/after-command-context-usage.js +1 -1
  4. package/dist/cli/argv-utils.js +1 -1
  5. package/dist/cli/bootstrap-args.js +1 -1
  6. package/dist/cli/bundle-integrity.js +2 -2
  7. package/dist/cli/command-namespaces.js +1 -1
  8. package/dist/cli/commander-usage.d.ts +1 -1
  9. package/dist/cli/commander-usage.js +7 -4
  10. package/dist/cli/commands/annotations/comments.js +1 -1
  11. package/dist/cli/commands/annotations/docs.js +1 -1
  12. package/dist/cli/commands/annotations/files.js +1 -1
  13. package/dist/cli/commands/annotations/learnings.js +1 -1
  14. package/dist/cli/commands/annotations/notes.js +1 -1
  15. package/dist/cli/commands/extension/describe.js +1 -1
  16. package/dist/cli/commands/extension/extension.js +1 -1
  17. package/dist/cli/commands/extension/scaffold.js +1 -1
  18. package/dist/cli/commands/extension/shared.js +1 -1
  19. package/dist/cli/commands/governance/gc.js +1 -1
  20. package/dist/cli/commands/governance/health.js +1 -1
  21. package/dist/cli/commands/governance/telemetry.js +1 -1
  22. package/dist/cli/commands/governance/validate.js +1 -1
  23. package/dist/cli/commands/history/activity.js +1 -1
  24. package/dist/cli/commands/history/history-compact.js +1 -1
  25. package/dist/cli/commands/history/history-redact.js +1 -1
  26. package/dist/cli/commands/history/history-repair.js +1 -1
  27. package/dist/cli/commands/history/history.js +1 -1
  28. package/dist/cli/commands/history/restore.js +1 -1
  29. package/dist/cli/commands/lifecycle/append.js +1 -1
  30. package/dist/cli/commands/lifecycle/claim.js +1 -1
  31. package/dist/cli/commands/lifecycle/close-many.js +1 -1
  32. package/dist/cli/commands/lifecycle/close.js +1 -1
  33. package/dist/cli/commands/lifecycle/copy.js +1 -1
  34. package/dist/cli/commands/lifecycle/create.js +1 -1
  35. package/dist/cli/commands/lifecycle/delete.js +1 -1
  36. package/dist/cli/commands/lifecycle/focus.js +1 -1
  37. package/dist/cli/commands/lifecycle/plan.js +1 -1
  38. package/dist/cli/commands/lifecycle/update-many.js +1 -1
  39. package/dist/cli/commands/lifecycle/update.js +1 -1
  40. package/dist/cli/commands/query/aggregate.js +1 -1
  41. package/dist/cli/commands/query/context.js +1 -1
  42. package/dist/cli/commands/query/deps.js +1 -1
  43. package/dist/cli/commands/query/duplicates.js +1 -1
  44. package/dist/cli/commands/query/eval.js +1 -1
  45. package/dist/cli/commands/query/get.js +1 -1
  46. package/dist/cli/commands/query/graph.js +1 -1
  47. package/dist/cli/commands/query/list.js +1 -1
  48. package/dist/cli/commands/query/next.js +1 -1
  49. package/dist/cli/commands/query/search.js +1 -1
  50. package/dist/cli/commands/query/stats.js +1 -1
  51. package/dist/cli/commands/test/test-all.js +1 -1
  52. package/dist/cli/commands/test/test-runs.js +1 -1
  53. package/dist/cli/commands/test/test.js +1 -1
  54. package/dist/cli/commands/workspace/config.js +1 -1
  55. package/dist/cli/commands/workspace/contracts.js +1 -1
  56. package/dist/cli/commands/workspace/init.js +1 -1
  57. package/dist/cli/commands/workspace/merge.js +1 -1
  58. package/dist/cli/commands/workspace/profile.js +1 -1
  59. package/dist/cli/commands/workspace/schema.js +1 -1
  60. package/dist/cli/commands/workspace/upgrade.js +1 -1
  61. package/dist/cli/context-intent-invocation.js +1 -1
  62. package/dist/cli/description-stdin.js +1 -1
  63. package/dist/cli/error-guidance.js +3 -1
  64. package/dist/cli/extension-command-help.js +5 -3
  65. package/dist/cli/extension-command-options.js +1 -1
  66. package/dist/cli/extension-recovery.js +1 -1
  67. package/dist/cli/help-content.js +5 -2
  68. package/dist/cli/help-json-payload.js +6 -3
  69. package/dist/cli/invocation-profile.js +2 -2
  70. package/dist/cli/main.js +5 -5
  71. package/dist/cli/migration-gates.js +1 -1
  72. package/dist/cli/option-values.js +1 -1
  73. package/dist/cli/public.js +1 -1
  74. package/dist/cli/register-annotations.js +1 -1
  75. package/dist/cli/register-assurance.js +1 -1
  76. package/dist/cli/register-files-lookup.js +1 -1
  77. package/dist/cli/register-history-activity.js +1 -1
  78. package/dist/cli/register-history-author.js +1 -1
  79. package/dist/cli/register-history-maintenance.js +2 -2
  80. package/dist/cli/register-list-query.js +10 -10
  81. package/dist/cli/register-mutation-options.js +1 -1
  82. package/dist/cli/register-mutation.js +2 -2
  83. package/dist/cli/register-operations.js +1 -1
  84. package/dist/cli/register-setup.js +1 -1
  85. package/dist/cli/register-structured-mutation.js +1 -1
  86. package/dist/cli/registration-helpers.js +1 -1
  87. package/dist/cli/runtime/activation.js +1 -1
  88. package/dist/cli/runtime/invocation-options.js +1 -1
  89. package/dist/cli/runtime/projection-retry.js +1 -1
  90. package/dist/cli/runtime/selection.js +1 -1
  91. package/dist/cli/runtime/telemetry-outcome.js +1 -1
  92. package/dist/cli/runtime-compatibility-boundary.js +4 -4
  93. package/dist/cli/schema/registration.js +2 -2
  94. package/dist/cli/schema-registration-helpers.js +1 -1
  95. package/dist/cli/search-refresh.js +1 -1
  96. package/dist/cli/stats-analytics-json.js +1 -1
  97. package/dist/cli/telemetry-flush.js +1 -1
  98. package/dist/cli-bundle/bundle-manifest.json +163 -163
  99. package/dist/cli-bundle/chunks/chunk-3CYOBJUK.js +3 -0
  100. package/dist/cli-bundle/chunks/chunk-5MNOWZPN.js +3 -0
  101. package/dist/cli-bundle/chunks/chunk-AJ7H6XUF.js +20 -0
  102. package/dist/cli-bundle/chunks/chunk-D332RXZ7.js +80 -0
  103. package/dist/cli-bundle/chunks/chunk-HRJ6G6ZG.js +31 -0
  104. package/dist/cli-bundle/chunks/chunk-KRVI56QE.js +6 -0
  105. package/dist/cli-bundle/chunks/chunk-N4YGSG6F.js +238 -0
  106. package/dist/cli-bundle/chunks/{chunk-7CE2DJMA.js → chunk-OOLYASYJ.js} +2 -2
  107. package/dist/cli-bundle/chunks/chunk-R7CG2DB7.js +2 -0
  108. package/dist/cli-bundle/chunks/chunk-TGMONGWX.js +2 -0
  109. package/dist/cli-bundle/chunks/chunk-UZ7BIUCI.js +2 -0
  110. package/dist/cli-bundle/chunks/{chunk-GZMWISWW.js → chunk-VZ63DEVJ.js} +3 -3
  111. package/dist/cli-bundle/chunks/chunk-WFZ4UEOB.js +2 -0
  112. package/dist/cli-bundle/chunks/chunk-YVBRASXO.js +8 -0
  113. package/dist/cli-bundle/chunks/{chunk-SMKHR6BM.js → chunk-Z66DWDAU.js} +87 -87
  114. package/dist/cli-bundle/chunks/{register-list-query-QBGXO5JJ.js → register-list-query-75QXHIFH.js} +11 -11
  115. package/dist/cli-bundle/chunks/register-mutation-YS54SCHG.js +20 -0
  116. package/dist/cli-bundle/chunks/register-operations-6KHZQSYJ.js +2 -0
  117. package/dist/cli-bundle/chunks/register-setup-RTATEN2M.js +2 -0
  118. package/dist/cli-bundle/focused-chunks/{chunk-Q6DJ5DFQ.js → chunk-2CVX3KR3.js} +2 -2
  119. package/dist/cli-bundle/focused-chunks/chunk-5C3IDDW7.js +2 -0
  120. package/dist/cli-bundle/focused-chunks/{chunk-467EW5RL.js → chunk-ABV67XCC.js} +3 -3
  121. package/dist/cli-bundle/focused-chunks/chunk-B5RSLVE6.js +3 -0
  122. package/dist/cli-bundle/focused-chunks/chunk-C224METM.js +20 -0
  123. package/dist/cli-bundle/focused-chunks/chunk-CLDPTMQY.js +6 -0
  124. package/dist/cli-bundle/focused-chunks/chunk-DDRN42PB.js +8 -0
  125. package/dist/cli-bundle/focused-chunks/{chunk-7O4NUJVO.js → chunk-DOVTUKJQ.js} +2 -2
  126. package/dist/cli-bundle/focused-chunks/chunk-ECBOPEJE.js +75 -0
  127. package/dist/cli-bundle/focused-chunks/chunk-GITOYRUW.js +165 -0
  128. package/dist/cli-bundle/focused-chunks/chunk-GUIF3WVC.js +30 -0
  129. package/dist/cli-bundle/focused-chunks/chunk-LE4JUCRR.js +3 -0
  130. package/dist/cli-bundle/focused-chunks/{chunk-HFAW3FJQ.js → chunk-PSXFFQFT.js} +2 -2
  131. package/dist/cli-bundle/focused-chunks/chunk-RHIH6XIW.js +12 -0
  132. package/dist/cli-bundle/focused-chunks/chunk-UDYRVBOZ.js +2 -0
  133. package/dist/cli-bundle/focused-chunks/chunk-XV5RV4ZT.js +2 -0
  134. package/dist/cli-bundle/focused-chunks/{chunk-JCVMOSWQ.js → chunk-YMU42COG.js} +2 -2
  135. package/dist/cli-bundle/main.js +27 -27
  136. package/dist/cli-bundle/sdk-authoring.js +1 -1
  137. package/dist/cli-bundle/sdk-contracts.js +2 -2
  138. package/dist/cli-bundle/sdk-core.js +32 -32
  139. package/dist/cli-bundle/sdk-governance.js +1 -1
  140. package/dist/cli-bundle/sdk-graph.js +1 -1
  141. package/dist/cli-bundle/sdk-merge.js +55 -55
  142. package/dist/cli-bundle/sdk-query.js +1 -1
  143. package/dist/cli-bundle/sdk-runtime.js +1 -1
  144. package/dist/cli-bundle/sdk-testing.js +1 -1
  145. package/dist/cli-bundle/sdk.js +10 -10
  146. package/dist/cli.js +1 -1
  147. package/dist/core/checkpoint/checkpoint-gc.js +1 -1
  148. package/dist/core/checkpoint/mutation-checkpoint.js +2 -2
  149. package/dist/core/config/nested-settings.js +1 -1
  150. package/dist/core/config/positional-value.js +1 -1
  151. package/dist/core/diagnostics/remediation.js +1 -1
  152. package/dist/core/extensions/activation-summary-markdown.js +2 -1
  153. package/dist/core/extensions/activation-summary.js +1 -1
  154. package/dist/core/extensions/activation-transaction.js +1 -1
  155. package/dist/core/extensions/capability-usage.js +1 -1
  156. package/dist/core/extensions/command-hook-context.js +1 -1
  157. package/dist/core/extensions/command-metadata-contract.js +1 -1
  158. package/dist/core/extensions/command-visibility-tier.js +1 -1
  159. package/dist/core/extensions/contribution-inventory.js +1 -1
  160. package/dist/core/extensions/exporter-output-contract.js +1 -1
  161. package/dist/core/extensions/extension-candidate.js +1 -1
  162. package/dist/core/extensions/extension-capability-aliases.js +1 -1
  163. package/dist/core/extensions/extension-hook-runtime.js +1 -1
  164. package/dist/core/extensions/extension-policy.js +1 -1
  165. package/dist/core/extensions/extension-registries.js +1 -1
  166. package/dist/core/extensions/extension-runtime-helpers.js +1 -1
  167. package/dist/core/extensions/extension-types.js +1 -1
  168. package/dist/core/extensions/flag-definition-validation.js +1 -1
  169. package/dist/core/extensions/flag-value-types.js +1 -1
  170. package/dist/core/extensions/index.js +1 -1
  171. package/dist/core/extensions/item-field-types.js +1 -1
  172. package/dist/core/extensions/item-fields.js +1 -1
  173. package/dist/core/extensions/loader.js +1 -1
  174. package/dist/core/extensions/manifest-parser.js +1 -1
  175. package/dist/core/extensions/manifest-schema.js +1 -1
  176. package/dist/core/extensions/module-graph-snapshot.js +1 -1
  177. package/dist/core/extensions/preflight-ownership.js +1 -1
  178. package/dist/core/extensions/registration-contracts.js +1 -1
  179. package/dist/core/extensions/registration-validation.js +1 -1
  180. package/dist/core/extensions/registration-values.js +1 -1
  181. package/dist/core/extensions/reserved-host-flags.js +1 -1
  182. package/dist/core/extensions/runtime-registrations.js +1 -1
  183. package/dist/core/extensions/service-ownership.js +1 -1
  184. package/dist/core/extensions/version-compat.js +1 -1
  185. package/dist/core/fs/atomic-create.js +1 -1
  186. package/dist/core/fs/fs-utils.js +2 -2
  187. package/dist/core/fs/host-environment-errors.js +1 -1
  188. package/dist/core/fs/index.js +1 -1
  189. package/dist/core/fs/path-utils.js +1 -1
  190. package/dist/core/governance/content-fields.js +1 -1
  191. package/dist/core/governance/issue-codes.js +1 -1
  192. package/dist/core/governance/metadata-coverage.js +1 -1
  193. package/dist/core/history/digest.js +1 -1
  194. package/dist/core/history/drift-cache.js +3 -3
  195. package/dist/core/history/drift-scan.d.ts +4 -0
  196. package/dist/core/history/drift-scan.js +1 -1
  197. package/dist/core/history/event-classification.js +1 -1
  198. package/dist/core/history/event-index.js +8 -7
  199. package/dist/core/history/history-compact-bulk.js +1 -1
  200. package/dist/core/history/history-diff.js +1 -1
  201. package/dist/core/history/history-rewrite.js +1 -1
  202. package/dist/core/history/history-storage-stats.js +1 -1
  203. package/dist/core/history/history-stream-policy.js +1 -1
  204. package/dist/core/history/history.js +2 -2
  205. package/dist/core/history/identity.js +1 -1
  206. package/dist/core/history/index.js +1 -1
  207. package/dist/core/history/operation-contract.js +1 -1
  208. package/dist/core/history/projection.js +1 -1
  209. package/dist/core/history/read.js +1 -1
  210. package/dist/core/history/replay.js +2 -1
  211. package/dist/core/history/tombstone.js +1 -1
  212. package/dist/core/history/version-address.js +1 -1
  213. package/dist/core/history/workspace-history.js +2 -2
  214. package/dist/core/io/body-file.js +1 -1
  215. package/dist/core/io/bulk-ids-input.js +2 -1
  216. package/dist/core/item/actionability.js +1 -1
  217. package/dist/core/item/dependency-reference.js +1 -1
  218. package/dist/core/item/id.js +1 -1
  219. package/dist/core/item/index.js +1 -1
  220. package/dist/core/item/item-format-version.js +1 -1
  221. package/dist/core/item/item-format.js +6 -4
  222. package/dist/core/item/item-record.js +1 -1
  223. package/dist/core/item/item-type-definition.js +1 -1
  224. package/dist/core/item/parent-reference-policy.js +1 -1
  225. package/dist/core/item/parse.js +8 -2
  226. package/dist/core/item/plan-lifecycle.js +1 -1
  227. package/dist/core/item/priority.js +1 -1
  228. package/dist/core/item/sprint-release-format.js +1 -1
  229. package/dist/core/item/status-filter.js +1 -1
  230. package/dist/core/item/status.js +1 -1
  231. package/dist/core/item/toon-decode.js +1 -1
  232. package/dist/core/item/type-registry.js +1 -1
  233. package/dist/core/item/type-synonyms.js +1 -1
  234. package/dist/core/lock/index.js +1 -1
  235. package/dist/core/lock/lock-gc.js +1 -1
  236. package/dist/core/lock/lock.js +3 -3
  237. package/dist/core/output/mutation-projection.js +1 -1
  238. package/dist/core/output/output-control.js +1 -1
  239. package/dist/core/output/output.js +22 -10
  240. package/dist/core/output/query-summary.js +1 -1
  241. package/dist/core/output/tabular.js +3 -1
  242. package/dist/core/packages/manifest.js +1 -1
  243. package/dist/core/packages/root.js +1 -1
  244. package/dist/core/policy/workflow-policy-schema.js +1 -1
  245. package/dist/core/policy/workflow-policy-store.js +1 -1
  246. package/dist/core/policy/workflow-policy.js +1 -1
  247. package/dist/core/profile/profile-describe.js +1 -1
  248. package/dist/core/profile/profile-lint.js +1 -1
  249. package/dist/core/profile/profile-plan.js +1 -1
  250. package/dist/core/profile/profile-presets.js +25 -1
  251. package/dist/core/reproducibility/context.js +1 -1
  252. package/dist/core/schema/fields-file.js +2 -2
  253. package/dist/core/schema/item-types-file.js +2 -2
  254. package/dist/core/schema/runtime-field-filters.js +1 -1
  255. package/dist/core/schema/runtime-field-values.js +1 -1
  256. package/dist/core/schema/runtime-schema.js +2 -2
  257. package/dist/core/schema/status-defs-file.js +2 -2
  258. package/dist/core/schema/status-token.js +1 -1
  259. package/dist/core/schema/type-inference.js +1 -1
  260. package/dist/core/schema/type-presets.js +1 -1
  261. package/dist/core/schema/type-workflows.js +1 -1
  262. package/dist/core/search/background-refresh.js +2 -2
  263. package/dist/core/search/bm25.js +1 -1
  264. package/dist/core/search/cache.js +2 -2
  265. package/dist/core/search/corpus.js +1 -1
  266. package/dist/core/search/embedding-batches.js +1 -1
  267. package/dist/core/search/eval-thresholds.js +1 -1
  268. package/dist/core/search/eval.js +1 -1
  269. package/dist/core/search/http-client.js +1 -1
  270. package/dist/core/search/providers.js +1 -1
  271. package/dist/core/search/relevance.js +1 -1
  272. package/dist/core/search/semantic-defaults.js +1 -1
  273. package/dist/core/search/staleness.js +1 -1
  274. package/dist/core/search/vector-stores.js +2 -2
  275. package/dist/core/search/vectorization-metadata.js +1 -1
  276. package/dist/core/sentry/helpers.js +1 -1
  277. package/dist/core/sentry/instrument.js +1 -1
  278. package/dist/core/session/session-state.js +1 -1
  279. package/dist/core/shared/agent-session-context.js +1 -1
  280. package/dist/core/shared/author.js +5 -1
  281. package/dist/core/shared/command-line.js +1 -1
  282. package/dist/core/shared/command-types.js +1 -1
  283. package/dist/core/shared/conflict-markers.js +1 -1
  284. package/dist/core/shared/constants.js +1 -1
  285. package/dist/core/shared/errors.js +1 -1
  286. package/dist/core/shared/html-entity-decode.js +1 -1
  287. package/dist/core/shared/index.js +1 -1
  288. package/dist/core/shared/item-metadata-contract.js +1 -1
  289. package/dist/core/shared/lazy-module.js +1 -1
  290. package/dist/core/shared/levenshtein.js +1 -1
  291. package/dist/core/shared/memo.js +1 -1
  292. package/dist/core/shared/numeric-parsers.js +1 -1
  293. package/dist/core/shared/option-alias-visibility.js +1 -1
  294. package/dist/core/shared/primitives.js +1 -1
  295. package/dist/core/shared/secret-rules.js +1 -1
  296. package/dist/core/shared/serial-queue.js +1 -1
  297. package/dist/core/shared/serialization.js +1 -1
  298. package/dist/core/shared/split-comma-list.js +1 -1
  299. package/dist/core/shared/text-normalization.js +1 -1
  300. package/dist/core/shared/time.js +2 -1
  301. package/dist/core/store/index.js +1 -1
  302. package/dist/core/store/item-format-migration.js +1 -1
  303. package/dist/core/store/item-metadata-cache.js +1 -1
  304. package/dist/core/store/item-metadata-query-index.js +7 -7
  305. package/dist/core/store/item-metadata-read-work.js +1 -1
  306. package/dist/core/store/item-store.js +1 -1
  307. package/dist/core/store/paths.js +1 -1
  308. package/dist/core/store/settings-concurrency.js +1 -1
  309. package/dist/core/store/settings-read-cache.js +1 -1
  310. package/dist/core/store/settings-validator.js +1 -1
  311. package/dist/core/store/settings.js +3 -3
  312. package/dist/core/store/tracker-preflight.js +1 -1
  313. package/dist/core/telemetry/consent.js +2 -2
  314. package/dist/core/telemetry/observability.js +1 -1
  315. package/dist/core/telemetry/policy.js +1 -1
  316. package/dist/core/telemetry/read-sampling.js +2 -2
  317. package/dist/core/telemetry/runtime.js +9 -5
  318. package/dist/core/test/background-runs.js +3 -3
  319. package/dist/core/test/item-test-run-tracking.js +1 -1
  320. package/dist/core/test/run-selectors.js +1 -1
  321. package/dist/core/validate/estimate-defaults.js +1 -1
  322. package/dist/core/validate/fix-planning.js +1 -1
  323. package/dist/core/validate/linked-artifact-reference.js +1 -1
  324. package/dist/core/validate/missing-by-type.js +1 -1
  325. package/dist/core/validate/missing-link-owners.js +1 -1
  326. package/dist/core/validate/stale-file-classification.js +1 -1
  327. package/dist/mcp/http-server.js +6 -4
  328. package/dist/mcp/legacy-adapter.js +1 -1
  329. package/dist/mcp/runtime-capabilities.js +1 -1
  330. package/dist/mcp/server.js +4 -4
  331. package/dist/mcp/tool-definitions.js +1 -1
  332. package/dist/sdk/actionability.js +1 -1
  333. package/dist/sdk/agent/closed-domain-contracts.js +1 -1
  334. package/dist/sdk/agent/command-recovery.js +1 -1
  335. package/dist/sdk/agent/command-suggestions.js +1 -1
  336. package/dist/sdk/agent/create-option-policy.js +1 -1
  337. package/dist/sdk/agent/identity-config.js +1 -1
  338. package/dist/sdk/agent/item-addressing.js +1 -1
  339. package/dist/sdk/agent/refusal-closure-census.js +2 -1
  340. package/dist/sdk/agent/refusal-closure.js +1 -1
  341. package/dist/sdk/agent/refusal-corpus-contracts.js +1 -1
  342. package/dist/sdk/agent/refusal-reachability.js +3 -1
  343. package/dist/sdk/agent/subcommand-recovery.js +1 -1
  344. package/dist/sdk/agent/task-transcript-contracts.js +1 -1
  345. package/dist/sdk/agent/tracker-preflight-contracts.js +1 -1
  346. package/dist/sdk/agent-capability-contracts.js +3 -1
  347. package/dist/sdk/agent-session-context.js +1 -1
  348. package/dist/sdk/annotations.js +1 -1
  349. package/dist/sdk/author-attribution.js +1 -1
  350. package/dist/sdk/authoring.js +1 -1
  351. package/dist/sdk/cli-bootstrap.js +1 -1
  352. package/dist/sdk/cli-contracts/agent-output-contracts.js +5 -3
  353. package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -1
  354. package/dist/sdk/cli-contracts/command-aliases.js +1 -1
  355. package/dist/sdk/cli-contracts/command-exit-contracts.js +1 -1
  356. package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1
  357. package/dist/sdk/cli-contracts/commander-types.js +1 -1
  358. package/dist/sdk/cli-contracts/completeness.js +1 -1
  359. package/dist/sdk/cli-contracts/enum-contracts.js +1 -1
  360. package/dist/sdk/cli-contracts/flag-contracts.js +1 -1
  361. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +2 -1
  362. package/dist/sdk/cli-contracts/grammar-contracts.js +1 -1
  363. package/dist/sdk/cli-contracts/registration-helpers.js +7 -7
  364. package/dist/sdk/cli-contracts/runtime-contracts.js +1 -1
  365. package/dist/sdk/cli-contracts/schemas/assurance-definition.js +1 -1
  366. package/dist/sdk/cli-contracts/string-lists.js +1 -1
  367. package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -1
  368. package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -1
  369. package/dist/sdk/cli-contracts/tool-schema.js +1 -1
  370. package/dist/sdk/cli-contracts/typed-action-inputs.js +1 -1
  371. package/dist/sdk/cli-contracts.js +1 -1
  372. package/dist/sdk/cli-program.js +1 -1
  373. package/dist/sdk/command-line.js +1 -1
  374. package/dist/sdk/comments.js +1 -1
  375. package/dist/sdk/compile-cache.js +1 -1
  376. package/dist/sdk/completion/bash.js +2 -1
  377. package/dist/sdk/completion/fish.js +13 -7
  378. package/dist/sdk/completion/shared.js +1 -1
  379. package/dist/sdk/completion/zsh.js +14 -8
  380. package/dist/sdk/completion.js +1 -1
  381. package/dist/sdk/compose.js +1 -1
  382. package/dist/sdk/config.js +1 -1
  383. package/dist/sdk/context/recency.js +1 -1
  384. package/dist/sdk/context/semantic-session-attribution.js +1 -1
  385. package/dist/sdk/context/usage-egress.js +1 -1
  386. package/dist/sdk/context/usage-ledger.js +6 -3
  387. package/dist/sdk/context-intent-contracts.js +1 -1
  388. package/dist/sdk/context-intent-runtime.js +1 -1
  389. package/dist/sdk/context-packing.js +1 -1
  390. package/dist/sdk/context-relevance.js +1 -1
  391. package/dist/sdk/context-signal-store.js +2 -2
  392. package/dist/sdk/context-usage.js +1 -1
  393. package/dist/sdk/contracts.js +1 -1
  394. package/dist/sdk/core-governance.js +1 -1
  395. package/dist/sdk/core.js +1 -1
  396. package/dist/sdk/corpus-shape.js +1 -1
  397. package/dist/sdk/define.js +1 -1
  398. package/dist/sdk/dependencies.js +1 -1
  399. package/dist/sdk/dependency-flag-validation.js +1 -1
  400. package/dist/sdk/dependency-provenance.js +1 -1
  401. package/dist/sdk/docs.js +1 -1
  402. package/dist/sdk/duplicates.js +1 -1
  403. package/dist/sdk/environment/agent-environment.js +1 -1
  404. package/dist/sdk/environment/host-environment-errors.js +1 -1
  405. package/dist/sdk/environment/project-runtime-compatibility.js +2 -1
  406. package/dist/sdk/environment/source-context.js +1 -1
  407. package/dist/sdk/environment/tracker-preflight.js +1 -1
  408. package/dist/sdk/error-code-catalog.js +1 -1
  409. package/dist/sdk/error-runtime.js +1 -1
  410. package/dist/sdk/errors.js +1 -1
  411. package/dist/sdk/eval.js +1 -1
  412. package/dist/sdk/extension/author-manifest.js +1 -1
  413. package/dist/sdk/extension/bundled-catalog.js +1 -1
  414. package/dist/sdk/extension/concurrency.js +1 -1
  415. package/dist/sdk/extension/copy-scope.js +1 -1
  416. package/dist/sdk/extension/custom-field-collisions.js +1 -1
  417. package/dist/sdk/extension/describe.js +4 -2
  418. package/dist/sdk/extension/doctor.js +1 -1
  419. package/dist/sdk/extension/install-plan.js +1 -1
  420. package/dist/sdk/extension/install-receipts.js +1 -1
  421. package/dist/sdk/extension/install-runtime.js +3 -3
  422. package/dist/sdk/extension/install-snapshot.js +1 -1
  423. package/dist/sdk/extension/install-sources.js +5 -5
  424. package/dist/sdk/extension/managed-state.js +2 -2
  425. package/dist/sdk/extension/migrations.js +2 -2
  426. package/dist/sdk/extension/output-ownership.js +1 -1
  427. package/dist/sdk/extension/runtime-summary.js +1 -1
  428. package/dist/sdk/extension/scaffold.js +11 -4
  429. package/dist/sdk/extension/shared.js +1 -1
  430. package/dist/sdk/extension/source-resolution.js +1 -1
  431. package/dist/sdk/extension/static-inventory.js +1 -1
  432. package/dist/sdk/extension/update-check.js +1 -1
  433. package/dist/sdk/extension-command-context.js +1 -1
  434. package/dist/sdk/extension-contracts.js +1 -1
  435. package/dist/sdk/extension.js +1 -1
  436. package/dist/sdk/files.js +1 -1
  437. package/dist/sdk/flag-invocation-contracts.js +1 -1
  438. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
  439. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
  440. package/dist/sdk/generated-error-code-catalog.js +1 -1
  441. package/dist/sdk/governance/assurance-action-contracts.js +1 -1
  442. package/dist/sdk/governance/assurance-action.js +1 -1
  443. package/dist/sdk/governance/assurance-limits.js +1 -1
  444. package/dist/sdk/governance/assurance-mutation-error.js +1 -1
  445. package/dist/sdk/governance/assurance-presets.js +1 -1
  446. package/dist/sdk/governance/assurance-runtime.js +1 -1
  447. package/dist/sdk/governance/assurance.js +4 -4
  448. package/dist/sdk/governance/boundary-fixtures.js +1 -1
  449. package/dist/sdk/governance/closure-timestamps.js +1 -1
  450. package/dist/sdk/governance/coverage-assurance.js +1 -1
  451. package/dist/sdk/governance/defect-recurrence-coverage.js +1 -1
  452. package/dist/sdk/governance/defect-recurrence-graph.js +1 -1
  453. package/dist/sdk/governance/defect-recurrence-signals.js +1 -1
  454. package/dist/sdk/governance/defect-recurrence.js +1 -1
  455. package/dist/sdk/governance/extension-host-version.js +1 -1
  456. package/dist/sdk/governance/gc.js +1 -1
  457. package/dist/sdk/governance/health-merge-evidence.js +1 -1
  458. package/dist/sdk/governance/health.js +2 -1
  459. package/dist/sdk/governance/hierarchy-validation.js +1 -1
  460. package/dist/sdk/governance/linked-file-report.js +1 -1
  461. package/dist/sdk/governance/merge-receipt-history.js +1 -1
  462. package/dist/sdk/governance/provenance-health.js +4 -1
  463. package/dist/sdk/governance/reindex.js +5 -4
  464. package/dist/sdk/governance/stale-work.js +1 -1
  465. package/dist/sdk/governance/status-role-diagnostics.js +1 -1
  466. package/dist/sdk/governance/storage-integrity.js +1 -1
  467. package/dist/sdk/governance/tracked-runtime-cache.js +1 -1
  468. package/dist/sdk/governance/upgrade.js +2 -2
  469. package/dist/sdk/governance/validate-history-drift.js +1 -1
  470. package/dist/sdk/governance/validate-item-reader.js +1 -1
  471. package/dist/sdk/governance/validate-normalization.js +1 -1
  472. package/dist/sdk/governance/validate.js +1 -1
  473. package/dist/sdk/governance/workflow-completeness.js +1 -1
  474. package/dist/sdk/governance/workflow-policy.js +3 -3
  475. package/dist/sdk/governance/workspace-position.js +2 -1
  476. package/dist/sdk/governance.js +1 -1
  477. package/dist/sdk/graph/adapter.js +1 -1
  478. package/dist/sdk/graph/analytics.js +1 -1
  479. package/dist/sdk/graph/assembly.js +1 -1
  480. package/dist/sdk/graph/cache.js +1 -1
  481. package/dist/sdk/graph/centrality.js +1 -1
  482. package/dist/sdk/graph/conformance.js +1 -1
  483. package/dist/sdk/graph/deadline-scheduling.js +1 -1
  484. package/dist/sdk/graph/durable-cache.js +1 -1
  485. package/dist/sdk/graph/governance-contracts.js +1 -1
  486. package/dist/sdk/graph/governance.js +1 -1
  487. package/dist/sdk/graph/hierarchy-integrity.js +1 -1
  488. package/dist/sdk/graph/index.js +1 -1
  489. package/dist/sdk/graph/lifecycle-coverage.js +1 -1
  490. package/dist/sdk/graph/mutation-advisory.js +1 -1
  491. package/dist/sdk/graph/query-contracts.js +1 -1
  492. package/dist/sdk/graph/remediation.js +1 -1
  493. package/dist/sdk/graph/run.js +1 -1
  494. package/dist/sdk/graph/scheduling.js +1 -1
  495. package/dist/sdk/graph/traversal.js +1 -1
  496. package/dist/sdk/graph/workspace-relationship-kind-registry.js +1 -1
  497. package/dist/sdk/graph.js +1 -1
  498. package/dist/sdk/guide-topics.js +1 -1
  499. package/dist/sdk/guide.js +8 -1
  500. package/dist/sdk/history/attestation-command.js +1 -1
  501. package/dist/sdk/history/attestation-contract.js +1 -1
  502. package/dist/sdk/history/attestation-scan.js +1 -1
  503. package/dist/sdk/history/attestation.js +1 -1
  504. package/dist/sdk/history/maintenance.js +1 -1
  505. package/dist/sdk/history/salvage.js +3 -2
  506. package/dist/sdk/history/subject.js +1 -1
  507. package/dist/sdk/history-analytics.js +1 -1
  508. package/dist/sdk/history-compact.js +1 -1
  509. package/dist/sdk/history-mcp.js +1 -1
  510. package/dist/sdk/history-provenance.js +1 -1
  511. package/dist/sdk/history-read.js +1 -1
  512. package/dist/sdk/history-redact.js +1 -1
  513. package/dist/sdk/history-repair.js +1 -1
  514. package/dist/sdk/improvement-ledger-validation.js +1 -1
  515. package/dist/sdk/improvement-ledger.js +2 -2
  516. package/dist/sdk/index.js +1 -1
  517. package/dist/sdk/init-agent-guidance.js +16 -2
  518. package/dist/sdk/init.js +16 -2
  519. package/dist/sdk/invocation-author.js +1 -1
  520. package/dist/sdk/item-children.js +1 -1
  521. package/dist/sdk/item-metadata-index.js +1 -1
  522. package/dist/sdk/item-schedule.js +1 -1
  523. package/dist/sdk/item-transaction.js +1 -1
  524. package/dist/sdk/learnings.js +1 -1
  525. package/dist/sdk/lifecycle/append.js +4 -2
  526. package/dist/sdk/lifecycle/claim.js +1 -1
  527. package/dist/sdk/lifecycle/close-many.js +1 -1
  528. package/dist/sdk/lifecycle/close.js +1 -1
  529. package/dist/sdk/lifecycle/copy.js +1 -1
  530. package/dist/sdk/lifecycle/create.js +1 -1
  531. package/dist/sdk/lifecycle/delete.js +1 -1
  532. package/dist/sdk/lifecycle/event-validation-messages.js +1 -1
  533. package/dist/sdk/lifecycle/focus.js +1 -1
  534. package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -1
  535. package/dist/sdk/lifecycle/legacy-none-tokens.js +1 -1
  536. package/dist/sdk/lifecycle/lifecycle-transitions.js +1 -1
  537. package/dist/sdk/lifecycle/mcp-actions.js +1 -1
  538. package/dist/sdk/lifecycle/metadata-normalizers.js +1 -1
  539. package/dist/sdk/lifecycle/mutation-command-options.js +1 -1
  540. package/dist/sdk/lifecycle/plan-mutation-receipt.js +1 -1
  541. package/dist/sdk/lifecycle/plan.js +1 -1
  542. package/dist/sdk/lifecycle/recurrence-parsers.js +1 -1
  543. package/dist/sdk/lifecycle/reopen.js +1 -1
  544. package/dist/sdk/lifecycle/repeatable-metadata-parsers.js +2 -1
  545. package/dist/sdk/lifecycle/restore.js +1 -1
  546. package/dist/sdk/lifecycle/shared-unset-fields.js +1 -1
  547. package/dist/sdk/lifecycle/task-composition.js +1 -1
  548. package/dist/sdk/lifecycle/update-many.js +1 -1
  549. package/dist/sdk/lifecycle/update.js +2 -1
  550. package/dist/sdk/lifecycle-completion.js +1 -1
  551. package/dist/sdk/lifecycle-policy.js +1 -1
  552. package/dist/sdk/linked-artifacts.js +2 -1
  553. package/dist/sdk/mcp/apps.js +1 -1
  554. package/dist/sdk/mcp/authorization.js +1 -1
  555. package/dist/sdk/mcp/discovery.js +1 -1
  556. package/dist/sdk/mcp/interactions.js +1 -1
  557. package/dist/sdk/mcp/protocol.js +1 -1
  558. package/dist/sdk/mcp/skills.js +3 -1
  559. package/dist/sdk/mcp/subscriptions.js +1 -1
  560. package/dist/sdk/mcp/tasks.js +2 -2
  561. package/dist/sdk/mcp/transport.js +1 -1
  562. package/dist/sdk/merge/abandoned-receipts.js +1 -1
  563. package/dist/sdk/merge/driver.js +1 -1
  564. package/dist/sdk/merge/index.js +1 -1
  565. package/dist/sdk/merge/install.js +4 -2
  566. package/dist/sdk/merge/receipt-file-boundary.js +1 -1
  567. package/dist/sdk/merge/receipt-operation.js +1 -1
  568. package/dist/sdk/merge/receipt-schema.js +1 -1
  569. package/dist/sdk/merge/receipts.js +4 -4
  570. package/dist/sdk/merge/reconcile.js +1 -1
  571. package/dist/sdk/merge/three-way.js +3 -2
  572. package/dist/sdk/merge/worktree-config.js +1 -1
  573. package/dist/sdk/merge.js +1 -1
  574. package/dist/sdk/mutation-events.js +1 -1
  575. package/dist/sdk/mutation-guard.js +1 -1
  576. package/dist/sdk/notes.js +1 -1
  577. package/dist/sdk/output-contracts.js +1 -1
  578. package/dist/sdk/output-projection.js +1 -1
  579. package/dist/sdk/output-token-accounting.js +1 -1
  580. package/dist/sdk/output.js +2 -1
  581. package/dist/sdk/ownership-source.js +1 -1
  582. package/dist/sdk/package-import-adapters.js +1 -1
  583. package/dist/sdk/package-migrations.js +1 -1
  584. package/dist/sdk/package-runtime-options.js +1 -1
  585. package/dist/sdk/pagination.js +1 -1
  586. package/dist/sdk/profile.js +5 -1
  587. package/dist/sdk/provenance.js +1 -1
  588. package/dist/sdk/public-surface.json +1 -1
  589. package/dist/sdk/query/activity.js +1 -1
  590. package/dist/sdk/query/aggregate.js +1 -1
  591. package/dist/sdk/query/calendar.js +4 -1
  592. package/dist/sdk/query/complete-list.js +1 -1
  593. package/dist/sdk/query/context.js +2 -1
  594. package/dist/sdk/query/duplicate-candidates.js +1 -1
  595. package/dist/sdk/query/get.d.ts +14 -2
  596. package/dist/sdk/query/get.js +1 -1
  597. package/dist/sdk/query/history.js +1 -1
  598. package/dist/sdk/query/item-filter-options.js +1 -1
  599. package/dist/sdk/query/light-metadata.js +1 -1
  600. package/dist/sdk/query/list-filter-shared.js +1 -1
  601. package/dist/sdk/query/list.js +1 -1
  602. package/dist/sdk/query/multi-value-filters.js +1 -1
  603. package/dist/sdk/query/next-ready-budget.js +1 -1
  604. package/dist/sdk/query/next.js +2 -1
  605. package/dist/sdk/query/parsers.js +1 -1
  606. package/dist/sdk/query/projection-contracts.js +1 -1
  607. package/dist/sdk/query/search/corpus.js +2 -1
  608. package/dist/sdk/query/search/filters.js +1 -1
  609. package/dist/sdk/query/search/input.js +1 -1
  610. package/dist/sdk/query/search/lexical.js +1 -1
  611. package/dist/sdk/query/search/response.js +1 -1
  612. package/dist/sdk/query/search/semantic.js +3 -2
  613. package/dist/sdk/query/search/types.js +1 -1
  614. package/dist/sdk/query/search-contracts.js +1 -1
  615. package/dist/sdk/query/search-pagination.js +1 -1
  616. package/dist/sdk/query/search-rendering.js +1 -1
  617. package/dist/sdk/query/search.js +1 -1
  618. package/dist/sdk/query/workspace-contracts.js +1 -1
  619. package/dist/sdk/query.js +1 -1
  620. package/dist/sdk/read-output/continuation.js +1 -1
  621. package/dist/sdk/read-output/options.js +1 -1
  622. package/dist/sdk/read-output/provenance.js +1 -1
  623. package/dist/sdk/read-output-budget.js +1 -1
  624. package/dist/sdk/read-output-contracts.js +1 -1
  625. package/dist/sdk/read-output-rows.js +1 -1
  626. package/dist/sdk/read-output-session.js +1 -1
  627. package/dist/sdk/relationship-analytics.js +1 -1
  628. package/dist/sdk/relationship-context.js +1 -1
  629. package/dist/sdk/relationship-history.js +7 -4
  630. package/dist/sdk/relationship-kinds/contract.js +1 -1
  631. package/dist/sdk/relationship-migration.js +1 -1
  632. package/dist/sdk/relationships.js +1 -1
  633. package/dist/sdk/reproducibility/process.js +1 -1
  634. package/dist/sdk/runtime/actions.js +1 -1
  635. package/dist/sdk/runtime/context.js +1 -1
  636. package/dist/sdk/runtime/schema-preview.js +1 -1
  637. package/dist/sdk/runtime/schema.js +1 -1
  638. package/dist/sdk/runtime-action-aliases.js +1 -1
  639. package/dist/sdk/runtime-extended-actions.js +1 -1
  640. package/dist/sdk/runtime-input.js +1 -1
  641. package/dist/sdk/runtime-primitives.js +1 -1
  642. package/dist/sdk/runtime-public-contracts.js +1 -1
  643. package/dist/sdk/runtime-stats-options.js +1 -1
  644. package/dist/sdk/runtime.js +1 -1
  645. package/dist/sdk/scheduling-shortcuts.js +1 -1
  646. package/dist/sdk/schema-migration.js +4 -3
  647. package/dist/sdk/schema.js +7 -1
  648. package/dist/sdk/search-refresh-worker.js +1 -1
  649. package/dist/sdk/similarity-scoring.js +1 -1
  650. package/dist/sdk/similarity.js +1 -1
  651. package/dist/sdk/start-task-status.js +1 -1
  652. package/dist/sdk/stats.js +1 -1
  653. package/dist/sdk/structured-mutations.js +1 -1
  654. package/dist/sdk/telemetry-flush.js +1 -1
  655. package/dist/sdk/telemetry.js +4 -3
  656. package/dist/sdk/templates.js +26 -2
  657. package/dist/sdk/test/batch.js +2 -2
  658. package/dist/sdk/test/entry.js +1 -1
  659. package/dist/sdk/test/execution.js +6 -5
  660. package/dist/sdk/test/json-path.js +1 -1
  661. package/dist/sdk/test/linked-command-detection.js +1 -1
  662. package/dist/sdk/test/measurements.js +1 -1
  663. package/dist/sdk/test/parsers.js +1 -1
  664. package/dist/sdk/test/runs.js +1 -1
  665. package/dist/sdk/test/trust.js +2 -2
  666. package/dist/sdk/test/workspace-snapshot.js +1 -1
  667. package/dist/sdk/testing.js +7 -4
  668. package/dist/sdk/traceability/runtime-files-lookup.js +1 -1
  669. package/dist/sdk/traceability/source-traceability.js +2 -1
  670. package/dist/sdk/tracker-root-discovery.js +1 -1
  671. package/dist/sdk/workspace-contracts-cache.js +1 -1
  672. package/dist/sdk/workspace-contracts.js +1 -1
  673. package/dist/sdk/workspace-memory.js +2 -2
  674. package/dist/sdk/workspace-recipe.js +1 -1
  675. package/dist/sdk/workspace-snapshot.js +5 -4
  676. package/dist/sdk/workspace-transaction-gc.js +1 -1
  677. package/dist/sdk/workspace-transaction.js +2 -2
  678. package/dist/sdk/workspace.js +3 -2
  679. package/dist/types/index.js +1 -1
  680. package/dist/types.js +1 -1
  681. package/docs/AGENT_EVIDENCE_CONSISTENCY.md +88 -0
  682. package/docs/GET_READ_EVIDENCE.md +68 -0
  683. package/docs/README.md +2 -0
  684. package/marketplace.json +2 -2
  685. package/package.json +1 -1
  686. package/packages/pm-beads/package.json +1 -1
  687. package/packages/pm-calendar/package.json +1 -1
  688. package/packages/pm-command-kit/package.json +1 -1
  689. package/packages/pm-digital-twin/package.json +1 -1
  690. package/packages/pm-governance-audit/package.json +1 -1
  691. package/packages/pm-guide-shell/package.json +1 -1
  692. package/packages/pm-kanban/package.json +1 -1
  693. package/packages/pm-lifecycle-hooks/package.json +1 -1
  694. package/packages/pm-linked-test-adapters/package.json +1 -1
  695. package/packages/pm-search-advanced/package.json +1 -1
  696. package/packages/pm-templates/package.json +1 -1
  697. package/packages/pm-todos/package.json +1 -1
  698. package/packages/pm-vcs/extensions/vcs/index.ts +4 -2
  699. package/packages/pm-vcs/package.json +1 -1
  700. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  701. package/plugins/pm-claude/package.json +2 -2
  702. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  703. package/plugins/pm-codex/package.json +2 -2
  704. package/plugins/pm-codex/plugin.json +1 -1
  705. package/scripts/finalize-build.mjs +3 -2
  706. package/dist/cli-bundle/chunks/chunk-7UVXKI7K.js +0 -2
  707. package/dist/cli-bundle/chunks/chunk-D7Z2ZMJL.js +0 -3
  708. package/dist/cli-bundle/chunks/chunk-DEZPZOQ7.js +0 -2
  709. package/dist/cli-bundle/chunks/chunk-J52QIRRZ.js +0 -80
  710. package/dist/cli-bundle/chunks/chunk-JDKD3WGG.js +0 -6
  711. package/dist/cli-bundle/chunks/chunk-JQ7DW663.js +0 -2
  712. package/dist/cli-bundle/chunks/chunk-QXIDOOWT.js +0 -20
  713. package/dist/cli-bundle/chunks/chunk-SGFQQXFD.js +0 -2
  714. package/dist/cli-bundle/chunks/chunk-V3U77H3V.js +0 -31
  715. package/dist/cli-bundle/chunks/chunk-XZDWAYJC.js +0 -3
  716. package/dist/cli-bundle/chunks/chunk-Y6VRBTP3.js +0 -238
  717. package/dist/cli-bundle/chunks/chunk-YAAFYFS4.js +0 -8
  718. package/dist/cli-bundle/chunks/register-mutation-53ZLT4RX.js +0 -20
  719. package/dist/cli-bundle/chunks/register-operations-OBK2FXUU.js +0 -2
  720. package/dist/cli-bundle/chunks/register-setup-HM3OCBH2.js +0 -2
  721. package/dist/cli-bundle/focused-chunks/chunk-2JFYR56O.js +0 -2
  722. package/dist/cli-bundle/focused-chunks/chunk-32EVUSS4.js +0 -8
  723. package/dist/cli-bundle/focused-chunks/chunk-5GUSO2P4.js +0 -20
  724. package/dist/cli-bundle/focused-chunks/chunk-6XBRADQQ.js +0 -3
  725. package/dist/cli-bundle/focused-chunks/chunk-CURTIIQT.js +0 -2
  726. package/dist/cli-bundle/focused-chunks/chunk-IJUWEEEB.js +0 -6
  727. package/dist/cli-bundle/focused-chunks/chunk-JMJK2L4Z.js +0 -3
  728. package/dist/cli-bundle/focused-chunks/chunk-KG3H4UZZ.js +0 -30
  729. package/dist/cli-bundle/focused-chunks/chunk-MHQ2XICU.js +0 -2
  730. package/dist/cli-bundle/focused-chunks/chunk-RJV6QVJE.js +0 -75
  731. package/dist/cli-bundle/focused-chunks/chunk-ZE2JZ7R6.js +0 -12
  732. package/dist/cli-bundle/focused-chunks/chunk-ZLEN4HZD.js +0 -165
@@ -1,7 +1,8 @@
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]="8cf44754-b3ec-5c75-b635-c7ae89238fca")}catch(e2){}})();import{readJsonPathValue,splitJsonPathSegments}from"./json-path.js";import{seedLinkedTestWorkspaceSnapshot}from"./workspace-snapshot.js";import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{spawn}from"node:child_process";import{cp,mkdir,mkdtemp,open,readdir,rm,symlink}from"node:fs/promises";import{tmpdir}from"node:os";import path from"node:path";import{getActiveExtensionRegistrations}from"../../core/extensions/index.js";import{isFileMissingError,pathExists,readFileIfExists}from"../../core/fs/fs-utils.js";import{getWorkspaceHistoryPath,writeWorkspaceJsonWithHistory}from"../../core/history/workspace-history.js";import{resolveItemTypeRegistry}from"../../core/item/type-registry.js";import{createStdinTokenResolver,parseCsvKv,parseOptionalNumber}from"../../core/item/parse.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{resolveAuthor}from"../../core/shared/author.js";import{PmCliError}from"../../core/shared/errors.js";import{stableValueEquals}from"../../core/shared/serialization.js";import{nowIso}from"../../core/shared/time.js";import{locateItem,mutateItem,readLocatedItem}from"../../core/store/item-store.js";import{getSettingsPath,ITEM_FILE_EXTENSIONS,resolveGlobalPmRoot,resolvePmRoot}from"../../core/store/paths.js";import{readSettings}from"../../core/store/settings.js";import{appendTrackedTestRunSummary,buildTrackedTestRunHistory}from"../../core/test/item-test-run-tracking.js";import{runInit}from"../init.js";import{looksLikeStructuredLinkedTestEntry,normalizeStructuredLinkedTestEntry}from"./entry.js";import{LINKED_TEST_PM_CONTEXT_MODE_VALUES as PM_CONTEXT_MODE_VALUES,LINKED_TEST_PROTECTED_ENV_KEYS,parseLinkedTestAssertionEqualsMap,parseLinkedTestAssertionGteMap,parseLinkedTestBoolean as parseLinkedTestBooleanValue,parseLinkedTestContextMode as parseLinkedTestContextModeValue,parseLinkedTestEnvClear as parseLinkedTestEnvClearValue,parseLinkedTestEnvSet as parseLinkedTestEnvSetValue,parseLinkedTestJsonEntries,parseLinkedTestMinLines,parseLinkedTestRegexList,parseLinkedTestStringList,parseLinkedTestWorkspaceContextMode}from"./parsers.js";import{parseOnlyIndexValue,resolveLinkedTestRunSelection}from"../../core/test/run-selectors.js";import{SCOPE_VALUES}from"../../types/index.js";import{diffTestRunMeasurements,parseTestRunMeasurements,queryTestRunMeasurementsBelow}from"./measurements.js";import{withHostEnvironmentBoundary}from"../environment/host-environment-errors.js";import{SOURCE_CONTEXT_ACCESS_ENV}from"../environment/source-context.js";import{acknowledgeLinkedTests,attachLinkedTestMutationProvenance,resolveLinkedTestSourceRef,resolveLinkedTestSourceWorkspaceRoot,resolveLinkedTestTrust}from"./trust.js";const TEST_OUTPUT_MAX_BUFFER_BYTES=20*1024*1024;const DEFAULT_LINKED_TEST_TIMEOUT_FORCE_KILL_DELAY_MS=3e3;const DEFAULT_LINKED_TEST_HEARTBEAT_INTERVAL_MS=1e4;const DEFAULT_LINKED_TEST_PIPE_CLOSE_GRACE_MS=5e3;const MAX_LINKED_TEST_COMMAND_LABEL_LENGTH=120;const LINKED_TEST_TRACKER_DIRS_TO_SKIP=new Set(["locks","extensions","runtime"]);const LINKED_TEST_ITEM_COUNT_DIRS_TO_SKIP=new Set(["history","index","search","extensions","locks","runtime"]);const LINKED_TEST_INFRA_COLLISION_PATTERNS=[/eaddrinuse/i,/address already in use/i,/port\s+\d+\s+is already in use/i,/web server[^.\n]*already running/i,/failed to listen on/i];const LINKED_TEST_LOCK_ACQUISITION_PATTERN=/\b(?:could not|failed to|unable to)\s+acquire\b[^\n.]*\block\b/i;const LINKED_TEST_LOCK_CONTENTION_CONTEXT_PATTERN=/\b(?:already running|timed?\s*out|timeout|held by another|lock\s+is\s+held)\b/i;const PM_TRACKER_READ_SUBCOMMANDS=new Set(["activity","calendar","context","ctx","deps","get","health","history","list","list-all","list-blocked","list-canceled","list-closed","list-draft","list-in-progress","list-open","search","stats","test-all","validate"]);function readPositiveIntegerEnv(name,fallback){const raw=process.env[name];if(typeof raw!=="string"||raw.trim().length===0){return fallback}const parsed=Number.parseInt(raw,10);if(!Number.isFinite(parsed)||parsed<=0){return fallback}return parsed}function linkedTestTimeoutForceKillDelayMs(){return readPositiveIntegerEnv("PM_LINKED_TEST_TIMEOUT_FORCE_KILL_DELAY_MS",DEFAULT_LINKED_TEST_TIMEOUT_FORCE_KILL_DELAY_MS)}function linkedTestHeartbeatIntervalMs(){return readPositiveIntegerEnv("PM_LINKED_TEST_HEARTBEAT_INTERVAL_MS",DEFAULT_LINKED_TEST_HEARTBEAT_INTERVAL_MS)}function linkedTestPipeCloseGraceMs(){return readPositiveIntegerEnv("PM_LINKED_TEST_PIPE_CLOSE_GRACE_MS",DEFAULT_LINKED_TEST_PIPE_CLOSE_GRACE_MS)}function resolveTrackedRunId(kind){const fromEnv=process.env.PM_BACKGROUND_TEST_RUN_ID?.trim();if(fromEnv&&fromEnv.length>0){return fromEnv}return`${kind}-local-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function summarizeRunResultStatuses(results){let passed=0;let failed=0;let skipped=0;for(const entry of results){if(entry.status==="passed"){passed+=1;continue}if(entry.status==="failed"){failed+=1;continue}skipped+=1}return{passed,failed,skipped}}function summarizeContextPreflight(runResults){let checkedPmCommands=0;let trackerReadCommands=0;let mismatches=0;let autoRemediated=0;for(const result of runResults){const context=result.execution_context;if(!context||context.is_pm_command!==true){continue}checkedPmCommands+=1;if(context.is_pm_tracker_read_command===true){trackerReadCommands+=1}if(context.mismatch_detected===true){mismatches+=1}if(context.auto_pm_context_applied===true){autoRemediated+=1}}return{checked_pm_commands:checkedPmCommands,tracker_read_commands:trackerReadCommands,mismatches,auto_remediated:autoRemediated}}function ensureScope(raw){const value=raw??"project";if(!SCOPE_VALUES.includes(value)){throw new PmCliError(`Invalid scope "${raw}"`,EXIT_CODE.USAGE)}return value}function parsePmContextMode(raw){if(!raw){return"schema"}const normalized=raw.trim().toLowerCase();if(PM_CONTEXT_MODE_VALUES.includes(normalized)){return normalized}throw new PmCliError(`Invalid --pm-context value "${raw}". Expected one of: ${PM_CONTEXT_MODE_VALUES.join(", ")}`,EXIT_CODE.USAGE)}function parseWorkspaceContextMode(raw){return parseLinkedTestWorkspaceContextMode(raw??"source","--workspace-context")}function resolveLinkedTestWorkspaceContextMode(linkedTest,runLevelMode,overrideLinkedMode){if(overrideLinkedMode){return runLevelMode}return parseLinkedTestWorkspaceContextMode(linkedTest.workspace_context_mode,"linked test")??runLevelMode}function resolveLinkedTestRequestedContextMode(linkedTest,runLevelMode,overrideLinkedPmContext){if(overrideLinkedPmContext){return runLevelMode}if(typeof linkedTest.pm_context_mode!=="string"||linkedTest.pm_context_mode.trim().length===0){return runLevelMode}return parsePmContextMode(linkedTest.pm_context_mode)}function resolveLinkedTestEffectiveContextMode(requestedMode,isPmTrackerReadCommand){if(requestedMode==="auto"){return isPmTrackerReadCommand?"tracker":"schema"}return requestedMode}function hasLinkedTestAssertions(linkedTest){return Object.entries(linkedTest).filter(([key])=>key.startsWith("assert_")).some(([,value])=>{if(value===void 0||value===null)return false;if(Array.isArray(value))return value.length>0;if(typeof value==="object")return Object.keys(value).length>0;if(typeof value==="string")return value.trim().length>0;return true})}function buildPmContextMismatchHint(params){const{executionContext,runLevelPmContextMode,linkedOverridePmContextMode}=params;if(!executionContext.is_pm_tracker_read_command||!executionContext.mismatch_detected){return""}if(runLevelPmContextMode==="tracker"&&linkedOverridePmContextMode==="schema"){return" Linked test metadata pm_context_mode=schema overrides run-level --pm-context tracker. Set pm_context_mode=tracker (or auto) on the linked test, or remove the override, to run against seeded tracker data."}if(executionContext.pm_context_mode==="schema"){return" Use --auto-pm-context to route PM tracker-read linked commands through seeded tracker data automatically. Alternatively, use --pm-context tracker for the whole run."}return""}function mergeEnvSetDirectives(entries,optionName){const merged={};if(!entries){return merged}for(const entry of entries){const parsed=parseLinkedTestEnvSetValue(entry,optionName);if(!parsed){continue}for(const[key,value]of Object.entries(parsed)){merged[key]=value}}return merged}function mergeEnvClearDirectives(entries,optionName){if(!entries){return[]}const values=[];for(const entry of entries){const parsed=parseLinkedTestEnvClearValue(entry,optionName);if(parsed){values.push(...parsed)}}return[...new Set(values)]}import{BUN_GLOBAL_FLAGS_WITH_VALUE,NPM_GLOBAL_FLAGS_WITH_VALUE,PNPM_GLOBAL_FLAGS_WITH_VALUE,SCRIPT_RUN_FLAGS_WITH_VALUE,SCRIPT_RUN_SUBCOMMANDS,YARN_GLOBAL_FLAGS_WITH_VALUE,firstPmSubcommand,extractPmInvocationArgsFromSegment,isPmCliPackageToken,isPmCliScriptToken,isPmExecutableToken,parseLauncherSubcommand,parseNpmExecCommand,parseNpxCommand,parsePnpmDlxCommand,resolvePmSubcommandContext,splitNormalizedCommandSegments,stripLeadingEnvAssignments}from"./linked-command-detection.js";import{extractReferencedPmItemIdsFromCommand}from"./linked-command-detection.js";function commandInvokesPmCli(command){const normalizedCommand=normalizeCommandForValidation(command);return splitNormalizedCommandSegments(normalizedCommand).some(segment=>extractPmInvocationArgsFromSegment(segment)!==null)}function commandInvokesPmTrackerReadCommand(command){const normalizedCommand=normalizeCommandForValidation(command);return splitNormalizedCommandSegments(normalizedCommand).some(segment=>{const invocationArgs=extractPmInvocationArgsFromSegment(segment);if(!invocationArgs){return false}const context=resolvePmSubcommandContext(invocationArgs);if(!context){return false}return PM_TRACKER_READ_SUBCOMMANDS.has(context.subcommand)})}function resolveDirectRunnerSubcommand(parsed){if(!parsed){return void 0}if(!SCRIPT_RUN_SUBCOMMANDS.has(parsed.subcommand)){return parsed.subcommand}return parseLauncherSubcommand(parsed.args,SCRIPT_RUN_FLAGS_WITH_VALUE)?.subcommand}function firstDirectTestRunnerSubcommand(executable,args){if(executable==="npx"||executable==="bunx"){return parseNpxCommand(args)?.command}if(executable==="pnpm"){return resolveDirectRunnerSubcommand(parseLauncherSubcommand(args,PNPM_GLOBAL_FLAGS_WITH_VALUE))}if(executable==="npm"){return resolveDirectRunnerSubcommand(parseLauncherSubcommand(args,NPM_GLOBAL_FLAGS_WITH_VALUE))}if(executable==="yarn"){return resolveDirectRunnerSubcommand(parseLauncherSubcommand(args,YARN_GLOBAL_FLAGS_WITH_VALUE))}if(executable==="bun"){return resolveDirectRunnerSubcommand(parseLauncherSubcommand(args,BUN_GLOBAL_FLAGS_WITH_VALUE))}return void 0}function isDirectTestRunnerSubcommand(token){if(!token){return false}return token==="vitest"||token==="test"||token.startsWith("test:")}function parsedLauncherInvokesRecursiveTestAll(parsed){if(!parsed){return false}if(!isPmExecutableToken(parsed.command)&&!isPmCliPackageToken(parsed.command)){return false}return firstPmSubcommand(parsed.args)==="test-all"}const SHELL_COMMAND_FLAG_PATTERNS=new Map([...["sh","bash","dash","zsh"].map(executable=>[executable,/^(?:-c|-[a-z]*c[a-z]*)$/u]),...["cmd","cmd.exe"].map(executable=>[executable,/^\/[ck]$/u]),...["powershell","powershell.exe","pwsh","pwsh.exe"].map(executable=>[executable,/^-(?:c|command)$/u])]);const PACKAGE_EXEC_EXECUTABLES=new Set(["npx","bunx"]);function segmentInvokesRecursiveTestAll(segment){const rawTokens=segment.split(" ").filter(token=>token.length>0);const tokens=stripLeadingEnvAssignments(rawTokens);if(tokens.length===0){return false}const[executable,...args]=tokens;const shellCommandFlagPattern=SHELL_COMMAND_FLAG_PATTERNS.get(executable);if(shellCommandFlagPattern){const commandFlagIndex=args.findIndex(arg=>shellCommandFlagPattern.test(arg));return commandFlagIndex>=0?segmentInvokesRecursiveTestAll(args.slice(commandFlagIndex+1).join(" ")):false}if(isPmExecutableToken(executable)||isPmCliScriptToken(executable)){return firstPmSubcommand(args)==="test-all"}if(executable==="node"&&args.length>0&&isPmCliScriptToken(args[0])){return firstPmSubcommand(args.slice(1))==="test-all"}if(PACKAGE_EXEC_EXECUTABLES.has(executable)){return parsedLauncherInvokesRecursiveTestAll(parseNpxCommand(args))}if(executable==="pnpm"){return parsedLauncherInvokesRecursiveTestAll(parsePnpmDlxCommand(args))}if(executable==="npm"){return parsedLauncherInvokesRecursiveTestAll(parseNpmExecCommand(args))}return false}function invokesRecursiveTestAllCommand(command){const normalized=normalizeCommandForValidation(command);return splitNormalizedCommandSegments(normalized).some(segment=>segmentInvokesRecursiveTestAll(segment))}function assertNoRecursiveTestAllCommand(command){if(!invokesRecursiveTestAllCommand(command))return;throw new PmCliError('Linked test commands must not invoke "pm test-all"; this creates recursive orchestration.',EXIT_CODE.USAGE)}function normalizeCommandForValidation(command){return command.trim().replaceAll("\\","/").replaceAll('"',"").replaceAll("'","").replaceAll(/\s+/g," ").toLowerCase()}function commandUsesSandboxRunner(normalizedCommand){return normalizedCommand.includes("node scripts/run-tests.mjs ")||normalizedCommand.endsWith("node scripts/run-tests.mjs")||normalizedCommand.includes("node ./scripts/run-tests.mjs ")||normalizedCommand.endsWith("node ./scripts/run-tests.mjs")}function segmentInvokesDirectTestRunner(normalizedSegment){const rawTokens=normalizedSegment.split(" ").filter(token=>token.length>0);const tokens=stripLeadingEnvAssignments(rawTokens);if(tokens.length===0){return false}const[executable,...args]=tokens;const shellCommandFlagPattern=SHELL_COMMAND_FLAG_PATTERNS.get(executable);if(shellCommandFlagPattern){const commandFlagIndex=args.findIndex(argument=>shellCommandFlagPattern.test(argument));return commandFlagIndex>=0&&segmentInvokesDirectTestRunner(args.slice(commandFlagIndex+1).join(" "))}if(executable==="vitest"||executable.endsWith("/vitest")||executable.endsWith("/vitest.mjs")){return true}if(executable==="node"){return nodeArgsInvokeDirectTestRunner(args)}return packageManagerInvokesDirectTestRunner(executable,args)}function nodeArgsInvokeDirectTestRunner(args){return args.includes("--test")||args.some(arg=>arg==="vitest"||arg==="vitest.mjs"||arg.endsWith("/vitest")||arg.endsWith("/vitest.mjs"))}function packageManagerInvokesDirectTestRunner(executable,args){if(executable==="npx"||executable==="bunx"){return isDirectTestRunnerSubcommand(parseNpxCommand(args)?.command)}if(executable==="pnpm"||executable==="npm"){return isDirectTestRunnerSubcommand((executable==="pnpm"?parsePnpmDlxCommand(args):parseNpmExecCommand(args))?.command)||isDirectTestRunnerSubcommand(firstDirectTestRunnerSubcommand(executable,args))}return(executable==="yarn"||executable==="bun")&&isDirectTestRunnerSubcommand(firstDirectTestRunnerSubcommand(executable,args))}function classifyLinkedTestCommandSafety(command){const normalized=normalizeCommandForValidation(command);const segments=splitNormalizedCommandSegments(normalized);const directRunner=segments.some(segment=>!commandUsesSandboxRunner(segment)&&segmentInvokesDirectTestRunner(segment));const sandboxRunner=segments.some(commandUsesSandboxRunner);return{accepted:true,command_kind:directRunner?"direct_runner":sandboxRunner?"sandbox_runner":"other",tracker_isolation:"runtime_injected",trust_boundary:"provenance",advisory:directRunner?"Accepted with runtime-injected tracker isolation. Prefer the repository sandbox runner when available for reproducible build and coverage setup.":"Accepted with runtime-injected tracker isolation and provenance checks before execution."}}function getRuntimeSafetySkipReason(command){if(!invokesRecursiveTestAllCommand(command))return void 0;return'Linked test command skipped: Linked test commands must not invoke "pm test-all"; this creates recursive orchestration.'}function parseAddEntries(raw){if(!raw)return[];return raw.map(parseAddEntry)}function parseAddEntry(entry){const trimmed=entry.trim();const kv=looksLikeStructuredLinkedTestEntry(trimmed)?normalizeStructuredLinkedTestEntry(parseCsvKv(entry,"--add"),"--add"):{command:trimmed};const command=trimLinkedTestEntryField(kv.command);if(!command){throw new PmCliError("--add requires command=<value> or a bare command (path=<value> is optional metadata)",EXIT_CODE.USAGE)}assertNoRecursiveTestAllCommand(command);return{command,path:trimLinkedTestEntryField(kv.path),scope:ensureScope(kv.scope),timeout_seconds:parseLinkedTestTimeoutSeconds(trimLinkedTestEntryField(kv.timeout_seconds),trimLinkedTestEntryField(kv.timeout)),pm_context_mode:parseLinkedTestContextModeValue(trimLinkedTestEntryField(kv.pm_context_mode),"--add"),workspace_context_mode:parseLinkedTestWorkspaceContextMode(trimLinkedTestEntryField(kv.workspace_context_mode),"--add"),env_set:parseLinkedTestEnvSetValue(trimLinkedTestEntryField(kv.env_set),"--add"),env_clear:parseLinkedTestEnvClearValue(trimLinkedTestEntryField(kv.env_clear),"--add"),shared_host_safe:parseLinkedTestBooleanValue(trimLinkedTestEntryField(kv.shared_host_safe),"--add","shared_host_safe"),assert_stdout_contains:parseLinkedTestStringList(trimLinkedTestEntryField(kv.assert_stdout_contains)),assert_stdout_regex:parseLinkedTestRegexList(trimLinkedTestEntryField(kv.assert_stdout_regex),"--add","assert_stdout_regex"),assert_stderr_contains:parseLinkedTestStringList(trimLinkedTestEntryField(kv.assert_stderr_contains)),assert_stderr_regex:parseLinkedTestRegexList(trimLinkedTestEntryField(kv.assert_stderr_regex),"--add","assert_stderr_regex"),assert_stdout_min_lines:parseLinkedTestMinLines(trimLinkedTestEntryField(kv.assert_stdout_min_lines),"--add"),assert_json_field_equals:parseLinkedTestAssertionEqualsMap(trimLinkedTestEntryField(kv.assert_json_field_equals),"--add"),assert_json_field_gte:parseLinkedTestAssertionGteMap(trimLinkedTestEntryField(kv.assert_json_field_gte),"--add"),note:trimLinkedTestEntryField(kv.note)}}function trimLinkedTestEntryField(value){const trimmed=value?.trim();return trimmed&&trimmed.length>0?trimmed:void 0}function parseLinkedTestTimeoutSeconds(timeoutSecondsRaw,timeoutAliasRaw){if(timeoutSecondsRaw&&timeoutAliasRaw&&timeoutSecondsRaw!==timeoutAliasRaw){throw new PmCliError("--add timeout and timeout_seconds must match when both are provided",EXIT_CODE.USAGE)}const timeoutRaw=timeoutSecondsRaw??timeoutAliasRaw;if(timeoutRaw===void 0)return void 0;const timeout=Math.floor(parseOptionalNumber(timeoutRaw,"timeout_seconds"));if(timeout<=0){throw new PmCliError("--add timeout_seconds must be a positive integer",EXIT_CODE.USAGE)}return timeout}function parseAddJsonEntries(raw){if(!raw)return[];return raw.flatMap(entry=>{const parsed=parseLinkedTestJsonEntries(entry,"--add-json");for(const linkedTest of parsed){const command=linkedTest.command;if(!command){throw new PmCliError("--add-json requires a non-empty command string",EXIT_CODE.USAGE)}assertNoRecursiveTestAllCommand(command)}return parsed})}function parseRemoveEntries(raw){if(!raw)return[];return raw.map(entry=>{const trimmed=entry.trim();if(!trimmed){throw new PmCliError("--remove requires command or path value",EXIT_CODE.USAGE)}const identityPrefix=/^(command|path)\s*=/i.exec(trimmed);if(identityPrefix){const value=trimmed.slice(identityPrefix[0].length).trim();if(!value){throw new PmCliError("--remove requires a non-empty command=<value> or path=<value>",EXIT_CODE.USAGE)}return{kind:identityPrefix[1].toLowerCase(),value}}if(/^[A-Za-z_][\w-]*=\S+$/u.test(trimmed)){throw new PmCliError("--remove structured selectors require command=<value> or path=<value>",EXIT_CODE.USAGE)}if(/^(?:[-*+]\s+)?(?:path|command)\s*:/i.test(trimmed)||trimmed.startsWith("```")){const kv=parseCsvKv(trimmed,"--remove");const kind=kv.path!==void 0?"path":"command";const value=kv.path??kv.command;if(!value?.trim()){throw new PmCliError("--remove requires command=<value> and/or path=<value>",EXIT_CODE.USAGE)}return{kind,value:value.trim()}}return{kind:"either",value:trimmed}})}function parseRemoveIndexes(raw){if(!raw)return[];return[...new Set(raw.map(value=>{const parsed=typeof value==="number"?value:Number.parseInt(value,10);if(!Number.isInteger(parsed)||parsed<1||String(parsed)!==String(value).trim()){throw new PmCliError("--remove-index must be a positive integer",EXIT_CODE.USAGE)}return parsed}))]}function closeLinkedTestStdin(child){try{child.stdin?.end()}catch{}}function summarizeLinkedTestCommand(command){const normalized=command.trim().replaceAll(/\s+/g," ");if(normalized.length<=MAX_LINKED_TEST_COMMAND_LABEL_LENGTH){return normalized}return`${normalized.slice(0,MAX_LINKED_TEST_COMMAND_LABEL_LENGTH-3)}...`}function shouldEmitLinkedTestProgress(mode){if(mode==="off"){return false}if(mode==="always"){return true}return process.stderr.isTTY===true}function emitLinkedTestProgress(message){try{process.stderr.write(`${message}
2
- `)}catch{}}function beginLinkedTestProgress(context,mode){if(!shouldEmitLinkedTestProgress(mode)){return null}const commandLabel=summarizeLinkedTestCommand(context.command);const startAt=Date.now();emitLinkedTestProgress(`[pm test] linked-test ${context.index}/${context.total} start timeout_ms=${context.timeoutMs} command="${commandLabel}"`);const heartbeat=setInterval(()=>{const elapsedMs=Date.now()-startAt;emitLinkedTestProgress(`[pm test] linked-test ${context.index}/${context.total} running elapsed_ms=${elapsedMs} command="${commandLabel}"`)},linkedTestHeartbeatIntervalMs());heartbeat.unref?.();return heartbeat}function endLinkedTestProgress(context,executionResult,startedAt,mode){if(!shouldEmitLinkedTestProgress(mode)){return}const commandLabel=summarizeLinkedTestCommand(context.command);const elapsedMs=Date.now()-startedAt;const failed=executionResult.timedOut||executionResult.maxBufferExceeded||executionResult.exitCode!==0;const statusLabel=failed?"failed":"passed";const reasonTokens=[];if(executionResult.timedOut){reasonTokens.push("reason=timeout")}if(executionResult.maxBufferExceeded){reasonTokens.push("reason=max_buffer")}if(executionResult.outputTruncated){reasonTokens.push("output=truncated")}if(executionResult.signal){reasonTokens.push(`signal=${executionResult.signal}`)}const exitLabel=executionResult.exitCode===null?"null":String(executionResult.exitCode);const reasonSuffix=reasonTokens.length>0?` ${reasonTokens.join(" ")}`:"";emitLinkedTestProgress(`[pm test] linked-test ${context.index}/${context.total} end status=${statusLabel} exit_code=${exitLabel} elapsed_ms=${elapsedMs}${reasonSuffix} command="${commandLabel}"`)}async function killProcessTree(pid){if(!Number.isInteger(pid)||pid<=0){return}if(process.platform==="win32"){await new Promise(resolve=>{const killer=spawn("taskkill",["/pid",String(pid),"/T","/F"],{stdio:"ignore",windowsHide:true});killer.on("error",()=>resolve());killer.on("close",()=>resolve())});return}try{process.kill(-pid,"SIGKILL");return}catch{}try{process.kill(pid,"SIGKILL")}catch{}}function clearLinkedTestTimers(timers){if(timers.heartbeat){clearInterval(timers.heartbeat)}if(timers.timedOutTimer){clearTimeout(timers.timedOutTimer);timers.timedOutTimer=null}if(timers.forceKillTimer){clearTimeout(timers.forceKillTimer);timers.forceKillTimer=null}}function createLinkedTestTerminationRequester(child,timers){let terminationRequested=false;return async()=>{if(terminationRequested){return}terminationRequested=true;const pid=child.pid;if(!pid||pid<=0){try{child.kill("SIGTERM")}catch{}return}if(process.platform==="win32"){await killProcessTree(pid);return}try{process.kill(-pid,"SIGTERM")}catch{try{child.kill("SIGTERM")}catch{}}timers.forceKillTimer=setTimeout(()=>{void killProcessTree(pid)},linkedTestTimeoutForceKillDelayMs());timers.forceKillTimer.unref?.()}}function waitForLinkedTestChildClose(child){return new Promise(resolve=>{let settled=false;let pipeCloseGraceTimer=null;const settle=(value,destroyPipes=false)=>{if(settled){return}settled=true;if(pipeCloseGraceTimer){clearTimeout(pipeCloseGraceTimer);pipeCloseGraceTimer=null}if(destroyPipes){child.stdin?.destroy();child.stdout?.destroy();child.stderr?.destroy()}resolve(value)};child.on("exit",(exitCode,exitSignal)=>{if(settled){return}pipeCloseGraceTimer=setTimeout(()=>{settle({code:exitCode,signal:exitSignal},true)},linkedTestPipeCloseGraceMs());pipeCloseGraceTimer.unref?.()});child.on("close",(closeCode,closeSignal)=>{settle({code:closeCode,signal:closeSignal})})})}function createLinkedTestChild(command,env,stdoutFd,stderrFd,cwd){return spawn(command,{cwd,env,shell:true,windowsHide:true,detached:process.platform!=="win32",stdio:["pipe",stdoutFd,stderrFd]})}async function readLinkedTestCapture(capturePath){const handle=await open(capturePath,"r");try{const size=(await handle.stat()).size;const retainedBytes=Math.min(size,TEST_OUTPUT_MAX_BUFFER_BYTES);const buffer=Buffer.alloc(retainedBytes);if(retainedBytes>0){await handle.read(buffer,0,retainedBytes,0)}return{text:buffer.toString("utf8"),truncated:size>TEST_OUTPUT_MAX_BUFFER_BYTES}}finally{await handle.close()}}async function runLinkedTestCommand(command,timeoutMs,env,progressContext,progressMode,cwd=process.cwd()){const startedAt=Date.now();const captureRoot=await mkdtemp(path.join(tmpdir(),"pm-linked-test-output-"));try{const stdoutPath=path.join(captureRoot,"stdout.log");const stderrPath=path.join(captureRoot,"stderr.log");const[stdoutHandle,stderrHandle]=await Promise.all([open(stdoutPath,"w"),open(stderrPath,"w")]);let child;try{child=createLinkedTestChild(command,env,stdoutHandle.fd,stderrHandle.fd,cwd)}catch(error){await Promise.all([stdoutHandle.close(),stderrHandle.close()]);throw error}const childClose=waitForLinkedTestChildClose(child);let spawnError;child.on("error",error=>{spawnError=error.message});await Promise.all([stdoutHandle.close(),stderrHandle.close()]);closeLinkedTestStdin(child);const timers={heartbeat:beginLinkedTestProgress(progressContext,progressMode),forceKillTimer:null,timedOutTimer:null};const requestTermination=createLinkedTestTerminationRequester(child,timers);let timedOut=false;timers.timedOutTimer=setTimeout(()=>{timedOut=true;void requestTermination()},timeoutMs);timers.timedOutTimer.unref?.();const{code,signal}=await childClose;clearLinkedTestTimers(timers);const[stdout,stderr]=await Promise.all([readLinkedTestCapture(stdoutPath),readLinkedTestCapture(stderrPath)]);const outputTruncated=stdout.truncated||stderr.truncated;const truncationNotice=outputTruncated?`
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6700ed53-3964-5cc4-ab5e-9759acefdae2")}catch{}})();import{readJsonPathValue,splitJsonPathSegments}from"./json-path.js";import{seedLinkedTestWorkspaceSnapshot}from"./workspace-snapshot.js";import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{spawn}from"node:child_process";import{cp,mkdir,mkdtemp,open,readdir,rm,symlink}from"node:fs/promises";import{tmpdir}from"node:os";import path from"node:path";import{getActiveExtensionRegistrations}from"../../core/extensions/index.js";import{isFileMissingError,pathExists,readFileIfExists}from"../../core/fs/fs-utils.js";import{getWorkspaceHistoryPath,writeWorkspaceJsonWithHistory}from"../../core/history/workspace-history.js";import{resolveItemTypeRegistry}from"../../core/item/type-registry.js";import{createStdinTokenResolver,parseCsvKv,parseOptionalNumber}from"../../core/item/parse.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{resolveAuthor}from"../../core/shared/author.js";import{PmCliError}from"../../core/shared/errors.js";import{stableValueEquals}from"../../core/shared/serialization.js";import{nowIso}from"../../core/shared/time.js";import{locateItem,mutateItem,readLocatedItem}from"../../core/store/item-store.js";import{getSettingsPath,ITEM_FILE_EXTENSIONS,resolveGlobalPmRoot,resolvePmRoot}from"../../core/store/paths.js";import{readSettings}from"../../core/store/settings.js";import{appendTrackedTestRunSummary,buildTrackedTestRunHistory}from"../../core/test/item-test-run-tracking.js";import{runInit}from"../init.js";import{looksLikeStructuredLinkedTestEntry,normalizeStructuredLinkedTestEntry}from"./entry.js";import{LINKED_TEST_PM_CONTEXT_MODE_VALUES as PM_CONTEXT_MODE_VALUES,LINKED_TEST_PROTECTED_ENV_KEYS,parseLinkedTestAssertionEqualsMap,parseLinkedTestAssertionGteMap,parseLinkedTestBoolean as parseLinkedTestBooleanValue,parseLinkedTestContextMode as parseLinkedTestContextModeValue,parseLinkedTestEnvClear as parseLinkedTestEnvClearValue,parseLinkedTestEnvSet as parseLinkedTestEnvSetValue,parseLinkedTestJsonEntries,parseLinkedTestMinLines,parseLinkedTestRegexList,parseLinkedTestStringList,parseLinkedTestWorkspaceContextMode}from"./parsers.js";import{parseOnlyIndexValue,resolveLinkedTestRunSelection}from"../../core/test/run-selectors.js";import{SCOPE_VALUES}from"../../types/index.js";import{diffTestRunMeasurements,parseTestRunMeasurements,queryTestRunMeasurementsBelow}from"./measurements.js";import{withHostEnvironmentBoundary}from"../environment/host-environment-errors.js";import{SOURCE_CONTEXT_ACCESS_ENV}from"../environment/source-context.js";import{acknowledgeLinkedTests,attachLinkedTestMutationProvenance,resolveLinkedTestSourceRef,resolveLinkedTestSourceWorkspaceRoot,resolveLinkedTestTrust}from"./trust.js";const TEST_OUTPUT_MAX_BUFFER_BYTES=20*1024*1024,DEFAULT_LINKED_TEST_TIMEOUT_FORCE_KILL_DELAY_MS=3e3,DEFAULT_LINKED_TEST_HEARTBEAT_INTERVAL_MS=1e4,DEFAULT_LINKED_TEST_PIPE_CLOSE_GRACE_MS=5e3,MAX_LINKED_TEST_COMMAND_LABEL_LENGTH=120,LINKED_TEST_TRACKER_DIRS_TO_SKIP=new Set(["locks","extensions","runtime"]),LINKED_TEST_ITEM_COUNT_DIRS_TO_SKIP=new Set(["history","index","search","extensions","locks","runtime"]),LINKED_TEST_INFRA_COLLISION_PATTERNS=[/eaddrinuse/i,/address already in use/i,/port\s+\d+\s+is already in use/i,/web server[^.\n]*already running/i,/failed to listen on/i],LINKED_TEST_LOCK_ACQUISITION_PATTERN=/\b(?:could not|failed to|unable to)\s+acquire\b[^\n.]*\block\b/i,LINKED_TEST_LOCK_CONTENTION_CONTEXT_PATTERN=/\b(?:already running|timed?\s*out|timeout|held by another|lock\s+is\s+held)\b/i,PM_TRACKER_READ_SUBCOMMANDS=new Set(["activity","calendar","context","ctx","deps","get","health","history","list","list-all","list-blocked","list-canceled","list-closed","list-draft","list-in-progress","list-open","search","stats","test-all","validate"]);function readPositiveIntegerEnv(name,fallback){const raw=process.env[name];if(typeof raw!="string"||raw.trim().length===0)return fallback;const parsed=Number.parseInt(raw,10);return!Number.isFinite(parsed)||parsed<=0?fallback:parsed}function linkedTestTimeoutForceKillDelayMs(){return readPositiveIntegerEnv("PM_LINKED_TEST_TIMEOUT_FORCE_KILL_DELAY_MS",DEFAULT_LINKED_TEST_TIMEOUT_FORCE_KILL_DELAY_MS)}function linkedTestHeartbeatIntervalMs(){return readPositiveIntegerEnv("PM_LINKED_TEST_HEARTBEAT_INTERVAL_MS",DEFAULT_LINKED_TEST_HEARTBEAT_INTERVAL_MS)}function linkedTestPipeCloseGraceMs(){return readPositiveIntegerEnv("PM_LINKED_TEST_PIPE_CLOSE_GRACE_MS",DEFAULT_LINKED_TEST_PIPE_CLOSE_GRACE_MS)}function resolveTrackedRunId(kind){const fromEnv=process.env.PM_BACKGROUND_TEST_RUN_ID?.trim();return fromEnv&&fromEnv.length>0?fromEnv:`${kind}-local-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function summarizeRunResultStatuses(results){let passed=0,failed=0,skipped=0;for(const entry of results){if(entry.status==="passed"){passed+=1;continue}if(entry.status==="failed"){failed+=1;continue}skipped+=1}return{passed,failed,skipped}}function summarizeContextPreflight(runResults){let checkedPmCommands=0,trackerReadCommands=0,mismatches=0,autoRemediated=0;for(const result of runResults){const context=result.execution_context;!context||context.is_pm_command!==!0||(checkedPmCommands+=1,context.is_pm_tracker_read_command===!0&&(trackerReadCommands+=1),context.mismatch_detected===!0&&(mismatches+=1),context.auto_pm_context_applied===!0&&(autoRemediated+=1))}return{checked_pm_commands:checkedPmCommands,tracker_read_commands:trackerReadCommands,mismatches,auto_remediated:autoRemediated}}function ensureScope(raw){const value=raw??"project";if(!SCOPE_VALUES.includes(value))throw new PmCliError(`Invalid scope "${raw}"`,EXIT_CODE.USAGE);return value}function parsePmContextMode(raw){if(!raw)return"schema";const normalized=raw.trim().toLowerCase();if(PM_CONTEXT_MODE_VALUES.includes(normalized))return normalized;throw new PmCliError(`Invalid --pm-context value "${raw}". Expected one of: ${PM_CONTEXT_MODE_VALUES.join(", ")}`,EXIT_CODE.USAGE)}function parseWorkspaceContextMode(raw){return parseLinkedTestWorkspaceContextMode(raw??"source","--workspace-context")}function resolveLinkedTestWorkspaceContextMode(linkedTest,runLevelMode,overrideLinkedMode){return overrideLinkedMode?runLevelMode:parseLinkedTestWorkspaceContextMode(linkedTest.workspace_context_mode,"linked test")??runLevelMode}function resolveLinkedTestRequestedContextMode(linkedTest,runLevelMode,overrideLinkedPmContext){return overrideLinkedPmContext||typeof linkedTest.pm_context_mode!="string"||linkedTest.pm_context_mode.trim().length===0?runLevelMode:parsePmContextMode(linkedTest.pm_context_mode)}function resolveLinkedTestEffectiveContextMode(requestedMode,isPmTrackerReadCommand){return requestedMode==="auto"?isPmTrackerReadCommand?"tracker":"schema":requestedMode}function hasLinkedTestAssertions(linkedTest){return Object.entries(linkedTest).filter(([key])=>key.startsWith("assert_")).some(([,value])=>value==null?!1:Array.isArray(value)?value.length>0:typeof value=="object"?Object.keys(value).length>0:typeof value=="string"?value.trim().length>0:!0)}function buildPmContextMismatchHint(params){const{executionContext,runLevelPmContextMode,linkedOverridePmContextMode}=params;return!executionContext.is_pm_tracker_read_command||!executionContext.mismatch_detected?"":runLevelPmContextMode==="tracker"&&linkedOverridePmContextMode==="schema"?" Linked test metadata pm_context_mode=schema overrides run-level --pm-context tracker. Set pm_context_mode=tracker (or auto) on the linked test, or remove the override, to run against seeded tracker data.":executionContext.pm_context_mode==="schema"?" Use --auto-pm-context to route PM tracker-read linked commands through seeded tracker data automatically. Alternatively, use --pm-context tracker for the whole run.":""}function mergeEnvSetDirectives(entries,optionName){const merged={};if(!entries)return merged;for(const entry of entries){const parsed=parseLinkedTestEnvSetValue(entry,optionName);if(parsed)for(const[key,value]of Object.entries(parsed))merged[key]=value}return merged}function mergeEnvClearDirectives(entries,optionName){if(!entries)return[];const values=[];for(const entry of entries){const parsed=parseLinkedTestEnvClearValue(entry,optionName);parsed&&values.push(...parsed)}return[...new Set(values)]}import{BUN_GLOBAL_FLAGS_WITH_VALUE,NPM_GLOBAL_FLAGS_WITH_VALUE,PNPM_GLOBAL_FLAGS_WITH_VALUE,SCRIPT_RUN_FLAGS_WITH_VALUE,SCRIPT_RUN_SUBCOMMANDS,YARN_GLOBAL_FLAGS_WITH_VALUE,firstPmSubcommand,extractPmInvocationArgsFromSegment,isPmCliPackageToken,isPmCliScriptToken,isPmExecutableToken,parseLauncherSubcommand,parseNpmExecCommand,parseNpxCommand,parsePnpmDlxCommand,resolvePmSubcommandContext,splitNormalizedCommandSegments,stripLeadingEnvAssignments}from"./linked-command-detection.js";import{extractReferencedPmItemIdsFromCommand}from"./linked-command-detection.js";function commandInvokesPmCli(command){const normalizedCommand=normalizeCommandForValidation(command);return splitNormalizedCommandSegments(normalizedCommand).some(segment=>extractPmInvocationArgsFromSegment(segment)!==null)}function commandInvokesPmTrackerReadCommand(command){const normalizedCommand=normalizeCommandForValidation(command);return splitNormalizedCommandSegments(normalizedCommand).some(segment=>{const invocationArgs=extractPmInvocationArgsFromSegment(segment);if(!invocationArgs)return!1;const context=resolvePmSubcommandContext(invocationArgs);return context?PM_TRACKER_READ_SUBCOMMANDS.has(context.subcommand):!1})}function resolveDirectRunnerSubcommand(parsed){if(parsed)return SCRIPT_RUN_SUBCOMMANDS.has(parsed.subcommand)?parseLauncherSubcommand(parsed.args,SCRIPT_RUN_FLAGS_WITH_VALUE)?.subcommand:parsed.subcommand}function firstDirectTestRunnerSubcommand(executable,args){if(executable==="npx"||executable==="bunx")return parseNpxCommand(args)?.command;if(executable==="pnpm")return resolveDirectRunnerSubcommand(parseLauncherSubcommand(args,PNPM_GLOBAL_FLAGS_WITH_VALUE));if(executable==="npm")return resolveDirectRunnerSubcommand(parseLauncherSubcommand(args,NPM_GLOBAL_FLAGS_WITH_VALUE));if(executable==="yarn")return resolveDirectRunnerSubcommand(parseLauncherSubcommand(args,YARN_GLOBAL_FLAGS_WITH_VALUE));if(executable==="bun")return resolveDirectRunnerSubcommand(parseLauncherSubcommand(args,BUN_GLOBAL_FLAGS_WITH_VALUE))}function isDirectTestRunnerSubcommand(token){return token?token==="vitest"||token==="test"||token.startsWith("test:"):!1}function parsedLauncherInvokesRecursiveTestAll(parsed){return!parsed||!isPmExecutableToken(parsed.command)&&!isPmCliPackageToken(parsed.command)?!1:firstPmSubcommand(parsed.args)==="test-all"}const SHELL_COMMAND_FLAG_PATTERNS=new Map([...["sh","bash","dash","zsh"].map(executable=>[executable,/^(?:-c|-[a-z]*c[a-z]*)$/u]),...["cmd","cmd.exe"].map(executable=>[executable,/^\/[ck]$/u]),...["powershell","powershell.exe","pwsh","pwsh.exe"].map(executable=>[executable,/^-(?:c|command)$/u])]),PACKAGE_EXEC_EXECUTABLES=new Set(["npx","bunx"]);function segmentInvokesRecursiveTestAll(segment){const rawTokens=segment.split(" ").filter(token=>token.length>0),tokens=stripLeadingEnvAssignments(rawTokens);if(tokens.length===0)return!1;const[executable,...args]=tokens,shellCommandFlagPattern=SHELL_COMMAND_FLAG_PATTERNS.get(executable);if(shellCommandFlagPattern){const commandFlagIndex=args.findIndex(arg=>shellCommandFlagPattern.test(arg));return commandFlagIndex>=0?segmentInvokesRecursiveTestAll(args.slice(commandFlagIndex+1).join(" ")):!1}return isPmExecutableToken(executable)||isPmCliScriptToken(executable)?firstPmSubcommand(args)==="test-all":executable==="node"&&args.length>0&&isPmCliScriptToken(args[0])?firstPmSubcommand(args.slice(1))==="test-all":PACKAGE_EXEC_EXECUTABLES.has(executable)?parsedLauncherInvokesRecursiveTestAll(parseNpxCommand(args)):executable==="pnpm"?parsedLauncherInvokesRecursiveTestAll(parsePnpmDlxCommand(args)):executable==="npm"?parsedLauncherInvokesRecursiveTestAll(parseNpmExecCommand(args)):!1}function invokesRecursiveTestAllCommand(command){const normalized=normalizeCommandForValidation(command);return splitNormalizedCommandSegments(normalized).some(segment=>segmentInvokesRecursiveTestAll(segment))}function assertNoRecursiveTestAllCommand(command){if(invokesRecursiveTestAllCommand(command))throw new PmCliError('Linked test commands must not invoke "pm test-all"; this creates recursive orchestration.',EXIT_CODE.USAGE)}function normalizeCommandForValidation(command){return command.trim().replaceAll("\\","/").replaceAll('"',"").replaceAll("'","").replaceAll(/\s+/g," ").toLowerCase()}function commandUsesSandboxRunner(normalizedCommand){return normalizedCommand.includes("node scripts/run-tests.mjs ")||normalizedCommand.endsWith("node scripts/run-tests.mjs")||normalizedCommand.includes("node ./scripts/run-tests.mjs ")||normalizedCommand.endsWith("node ./scripts/run-tests.mjs")}function segmentInvokesDirectTestRunner(normalizedSegment){const rawTokens=normalizedSegment.split(" ").filter(token=>token.length>0),tokens=stripLeadingEnvAssignments(rawTokens);if(tokens.length===0)return!1;const[executable,...args]=tokens,shellCommandFlagPattern=SHELL_COMMAND_FLAG_PATTERNS.get(executable);if(shellCommandFlagPattern){const commandFlagIndex=args.findIndex(argument=>shellCommandFlagPattern.test(argument));return commandFlagIndex>=0&&segmentInvokesDirectTestRunner(args.slice(commandFlagIndex+1).join(" "))}return executable==="vitest"||executable.endsWith("/vitest")||executable.endsWith("/vitest.mjs")?!0:executable==="node"?nodeArgsInvokeDirectTestRunner(args):packageManagerInvokesDirectTestRunner(executable,args)}function nodeArgsInvokeDirectTestRunner(args){return args.includes("--test")||args.some(arg=>arg==="vitest"||arg==="vitest.mjs"||arg.endsWith("/vitest")||arg.endsWith("/vitest.mjs"))}function packageManagerInvokesDirectTestRunner(executable,args){return executable==="npx"||executable==="bunx"?isDirectTestRunnerSubcommand(parseNpxCommand(args)?.command):executable==="pnpm"||executable==="npm"?isDirectTestRunnerSubcommand((executable==="pnpm"?parsePnpmDlxCommand(args):parseNpmExecCommand(args))?.command)||isDirectTestRunnerSubcommand(firstDirectTestRunnerSubcommand(executable,args)):(executable==="yarn"||executable==="bun")&&isDirectTestRunnerSubcommand(firstDirectTestRunnerSubcommand(executable,args))}function classifyLinkedTestCommandSafety(command){const normalized=normalizeCommandForValidation(command),segments=splitNormalizedCommandSegments(normalized),directRunner=segments.some(segment=>!commandUsesSandboxRunner(segment)&&segmentInvokesDirectTestRunner(segment)),sandboxRunner=segments.some(commandUsesSandboxRunner);return{accepted:!0,command_kind:directRunner?"direct_runner":sandboxRunner?"sandbox_runner":"other",tracker_isolation:"runtime_injected",trust_boundary:"provenance",advisory:directRunner?"Accepted with runtime-injected tracker isolation. Prefer the repository sandbox runner when available for reproducible build and coverage setup.":"Accepted with runtime-injected tracker isolation and provenance checks before execution."}}function getRuntimeSafetySkipReason(command){if(invokesRecursiveTestAllCommand(command))return'Linked test command skipped: Linked test commands must not invoke "pm test-all"; this creates recursive orchestration.'}function parseAddEntries(raw){return raw?raw.map(parseAddEntry):[]}function parseAddEntry(entry){const trimmed=entry.trim(),kv=looksLikeStructuredLinkedTestEntry(trimmed)?normalizeStructuredLinkedTestEntry(parseCsvKv(entry,"--add"),"--add"):{command:trimmed},command=trimLinkedTestEntryField(kv.command);if(!command)throw new PmCliError("--add requires command=<value> or a bare command (path=<value> is optional metadata)",EXIT_CODE.USAGE);return assertNoRecursiveTestAllCommand(command),{command,path:trimLinkedTestEntryField(kv.path),scope:ensureScope(kv.scope),timeout_seconds:parseLinkedTestTimeoutSeconds(trimLinkedTestEntryField(kv.timeout_seconds),trimLinkedTestEntryField(kv.timeout)),pm_context_mode:parseLinkedTestContextModeValue(trimLinkedTestEntryField(kv.pm_context_mode),"--add"),workspace_context_mode:parseLinkedTestWorkspaceContextMode(trimLinkedTestEntryField(kv.workspace_context_mode),"--add"),env_set:parseLinkedTestEnvSetValue(trimLinkedTestEntryField(kv.env_set),"--add"),env_clear:parseLinkedTestEnvClearValue(trimLinkedTestEntryField(kv.env_clear),"--add"),shared_host_safe:parseLinkedTestBooleanValue(trimLinkedTestEntryField(kv.shared_host_safe),"--add","shared_host_safe"),assert_stdout_contains:parseLinkedTestStringList(trimLinkedTestEntryField(kv.assert_stdout_contains)),assert_stdout_regex:parseLinkedTestRegexList(trimLinkedTestEntryField(kv.assert_stdout_regex),"--add","assert_stdout_regex"),assert_stderr_contains:parseLinkedTestStringList(trimLinkedTestEntryField(kv.assert_stderr_contains)),assert_stderr_regex:parseLinkedTestRegexList(trimLinkedTestEntryField(kv.assert_stderr_regex),"--add","assert_stderr_regex"),assert_stdout_min_lines:parseLinkedTestMinLines(trimLinkedTestEntryField(kv.assert_stdout_min_lines),"--add"),assert_json_field_equals:parseLinkedTestAssertionEqualsMap(trimLinkedTestEntryField(kv.assert_json_field_equals),"--add"),assert_json_field_gte:parseLinkedTestAssertionGteMap(trimLinkedTestEntryField(kv.assert_json_field_gte),"--add"),note:trimLinkedTestEntryField(kv.note)}}function trimLinkedTestEntryField(value){const trimmed=value?.trim();return trimmed&&trimmed.length>0?trimmed:void 0}function parseLinkedTestTimeoutSeconds(timeoutSecondsRaw,timeoutAliasRaw){if(timeoutSecondsRaw&&timeoutAliasRaw&&timeoutSecondsRaw!==timeoutAliasRaw)throw new PmCliError("--add timeout and timeout_seconds must match when both are provided",EXIT_CODE.USAGE);const timeoutRaw=timeoutSecondsRaw??timeoutAliasRaw;if(timeoutRaw===void 0)return;const timeout=Math.floor(parseOptionalNumber(timeoutRaw,"timeout_seconds"));if(timeout<=0)throw new PmCliError("--add timeout_seconds must be a positive integer",EXIT_CODE.USAGE);return timeout}function parseAddJsonEntries(raw){return raw?raw.flatMap(entry=>{const parsed=parseLinkedTestJsonEntries(entry,"--add-json");for(const linkedTest of parsed){const command=linkedTest.command;if(!command)throw new PmCliError("--add-json requires a non-empty command string",EXIT_CODE.USAGE);assertNoRecursiveTestAllCommand(command)}return parsed}):[]}function parseRemoveEntries(raw){return raw?raw.map(entry=>{const trimmed=entry.trim();if(!trimmed)throw new PmCliError("--remove requires command or path value",EXIT_CODE.USAGE);const identityPrefix=/^(command|path)\s*=/i.exec(trimmed);if(identityPrefix){const value=trimmed.slice(identityPrefix[0].length).trim();if(!value)throw new PmCliError("--remove requires a non-empty command=<value> or path=<value>",EXIT_CODE.USAGE);return{kind:identityPrefix[1].toLowerCase(),value}}if(/^[A-Za-z_][\w-]*=\S+$/u.test(trimmed))throw new PmCliError("--remove structured selectors require command=<value> or path=<value>",EXIT_CODE.USAGE);if(/^(?:[-*+]\s+)?(?:path|command)\s*:/i.test(trimmed)||trimmed.startsWith("```")){const kv=parseCsvKv(trimmed,"--remove"),kind=kv.path!==void 0?"path":"command",value=kv.path??kv.command;if(!value?.trim())throw new PmCliError("--remove requires command=<value> and/or path=<value>",EXIT_CODE.USAGE);return{kind,value:value.trim()}}return{kind:"either",value:trimmed}}):[]}function parseRemoveIndexes(raw){return raw?[...new Set(raw.map(value=>{const parsed=typeof value=="number"?value:Number.parseInt(value,10);if(!Number.isInteger(parsed)||parsed<1||String(parsed)!==String(value).trim())throw new PmCliError("--remove-index must be a positive integer",EXIT_CODE.USAGE);return parsed}))]:[]}function closeLinkedTestStdin(child){try{child.stdin?.end()}catch{}}function summarizeLinkedTestCommand(command){const normalized=command.trim().replaceAll(/\s+/g," ");return normalized.length<=MAX_LINKED_TEST_COMMAND_LABEL_LENGTH?normalized:`${normalized.slice(0,MAX_LINKED_TEST_COMMAND_LABEL_LENGTH-3)}...`}function shouldEmitLinkedTestProgress(mode){return mode==="off"?!1:mode==="always"?!0:process.stderr.isTTY===!0}function emitLinkedTestProgress(message){try{process.stderr.write(`${message}
2
+ `)}catch{}}function beginLinkedTestProgress(context,mode){if(!shouldEmitLinkedTestProgress(mode))return null;const commandLabel=summarizeLinkedTestCommand(context.command),startAt=Date.now();emitLinkedTestProgress(`[pm test] linked-test ${context.index}/${context.total} start timeout_ms=${context.timeoutMs} command="${commandLabel}"`);const heartbeat=setInterval(()=>{const elapsedMs=Date.now()-startAt;emitLinkedTestProgress(`[pm test] linked-test ${context.index}/${context.total} running elapsed_ms=${elapsedMs} command="${commandLabel}"`)},linkedTestHeartbeatIntervalMs());return heartbeat.unref?.(),heartbeat}function endLinkedTestProgress(context,executionResult,startedAt,mode){if(!shouldEmitLinkedTestProgress(mode))return;const commandLabel=summarizeLinkedTestCommand(context.command),elapsedMs=Date.now()-startedAt,statusLabel=executionResult.timedOut||executionResult.maxBufferExceeded||executionResult.exitCode!==0?"failed":"passed",reasonTokens=[];executionResult.timedOut&&reasonTokens.push("reason=timeout"),executionResult.maxBufferExceeded&&reasonTokens.push("reason=max_buffer"),executionResult.outputTruncated&&reasonTokens.push("output=truncated"),executionResult.signal&&reasonTokens.push(`signal=${executionResult.signal}`);const exitLabel=executionResult.exitCode===null?"null":String(executionResult.exitCode),reasonSuffix=reasonTokens.length>0?` ${reasonTokens.join(" ")}`:"";emitLinkedTestProgress(`[pm test] linked-test ${context.index}/${context.total} end status=${statusLabel} exit_code=${exitLabel} elapsed_ms=${elapsedMs}${reasonSuffix} command="${commandLabel}"`)}async function killProcessTree(pid){if(!(!Number.isInteger(pid)||pid<=0)){if(process.platform==="win32"){await new Promise(resolve=>{const killer=spawn("taskkill",["/pid",String(pid),"/T","/F"],{stdio:"ignore",windowsHide:!0});killer.on("error",()=>resolve()),killer.on("close",()=>resolve())});return}try{process.kill(-pid,"SIGKILL");return}catch{}try{process.kill(pid,"SIGKILL")}catch{}}}function clearLinkedTestTimers(timers){timers.heartbeat&&clearInterval(timers.heartbeat),timers.timedOutTimer&&(clearTimeout(timers.timedOutTimer),timers.timedOutTimer=null),timers.forceKillTimer&&(clearTimeout(timers.forceKillTimer),timers.forceKillTimer=null)}function createLinkedTestTerminationRequester(child,timers){let terminationRequested=!1;return async()=>{if(terminationRequested)return;terminationRequested=!0;const pid=child.pid;if(!pid||pid<=0){try{child.kill("SIGTERM")}catch{}return}if(process.platform==="win32"){await killProcessTree(pid);return}try{process.kill(-pid,"SIGTERM")}catch{try{child.kill("SIGTERM")}catch{}}timers.forceKillTimer=setTimeout(()=>{killProcessTree(pid)},linkedTestTimeoutForceKillDelayMs()),timers.forceKillTimer.unref?.()}}function waitForLinkedTestChildClose(child){return new Promise(resolve=>{let settled=!1,pipeCloseGraceTimer=null;const settle=(value,destroyPipes=!1)=>{settled||(settled=!0,pipeCloseGraceTimer&&(clearTimeout(pipeCloseGraceTimer),pipeCloseGraceTimer=null),destroyPipes&&(child.stdin?.destroy(),child.stdout?.destroy(),child.stderr?.destroy()),resolve(value))};child.on("exit",(exitCode,exitSignal)=>{settled||(pipeCloseGraceTimer=setTimeout(()=>{settle({code:exitCode,signal:exitSignal},!0)},linkedTestPipeCloseGraceMs()),pipeCloseGraceTimer.unref?.())}),child.on("close",(closeCode,closeSignal)=>{settle({code:closeCode,signal:closeSignal})})})}function createLinkedTestChild(command,env,stdoutFd,stderrFd,cwd){return spawn(command,{cwd,env,shell:!0,windowsHide:!0,detached:process.platform!=="win32",stdio:["pipe",stdoutFd,stderrFd]})}async function readLinkedTestCapture(capturePath){const handle=await open(capturePath,"r");try{const size=(await handle.stat()).size,retainedBytes=Math.min(size,TEST_OUTPUT_MAX_BUFFER_BYTES),buffer=Buffer.alloc(retainedBytes);return retainedBytes>0&&await handle.read(buffer,0,retainedBytes,0),{text:buffer.toString("utf8"),truncated:size>TEST_OUTPUT_MAX_BUFFER_BYTES}}finally{await handle.close()}}async function runLinkedTestCommand(command,timeoutMs,env,progressContext,progressMode,cwd=process.cwd()){const startedAt=Date.now(),captureRoot=await mkdtemp(path.join(tmpdir(),"pm-linked-test-output-"));try{const stdoutPath=path.join(captureRoot,"stdout.log"),stderrPath=path.join(captureRoot,"stderr.log"),[stdoutHandle,stderrHandle]=await Promise.all([open(stdoutPath,"w"),open(stderrPath,"w")]);let child;try{child=createLinkedTestChild(command,env,stdoutHandle.fd,stderrHandle.fd,cwd)}catch(error){throw await Promise.all([stdoutHandle.close(),stderrHandle.close()]),error}const childClose=waitForLinkedTestChildClose(child);let spawnError;child.on("error",error=>{spawnError=error.message}),await Promise.all([stdoutHandle.close(),stderrHandle.close()]),closeLinkedTestStdin(child);const timers={heartbeat:beginLinkedTestProgress(progressContext,progressMode),forceKillTimer:null,timedOutTimer:null},requestTermination=createLinkedTestTerminationRequester(child,timers);let timedOut=!1;timers.timedOutTimer=setTimeout(()=>{timedOut=!0,requestTermination()},timeoutMs),timers.timedOutTimer.unref?.();const{code,signal}=await childClose;clearLinkedTestTimers(timers);const[stdout,stderr]=await Promise.all([readLinkedTestCapture(stdoutPath),readLinkedTestCapture(stderrPath)]),outputTruncated=stdout.truncated||stderr.truncated,truncationNotice=outputTruncated?`
3
3
  [pm linked-test output truncated at ${TEST_OUTPUT_MAX_BUFFER_BYTES} bytes per stream; the child process continued to completion]
4
- `:"";const executionResult={stdout:`${stdout.text}${truncationNotice}`,stderr:stderr.text,exitCode:code,signal,timedOut,maxBufferExceeded:false,outputTruncated,spawnError};endLinkedTestProgress(progressContext,executionResult,startedAt,progressMode);return executionResult}finally{await rm(captureRoot,{recursive:true,force:true})}}function formatLinkedTestExecutionError(result,timeoutMs){const details=[];if(result.maxBufferExceeded){details.push(`Linked test output exceeded maxBuffer=${TEST_OUTPUT_MAX_BUFFER_BYTES} bytes. Reduce output volume or split the command.`)}if(result.timedOut&&timeoutMs>0){details.push(`Linked test timed out after ${timeoutMs}ms.`)}const signalMessage=result.signal?`Linked test command terminated by signal ${result.signal}.`:void 0;const baseMessage=result.spawnError?.trim()||signalMessage||"Linked test command failed.";if(details.length===0){return baseMessage}return`${baseMessage} ${details.join(" ")}`}function hasInfraCollisionSignal(result){const combined=[result.spawnError??"",result.stderr,result.stdout].join("\n");return LINKED_TEST_INFRA_COLLISION_PATTERNS.some(pattern=>pattern.test(combined))||combined.split(/\r?\n/u).some(line=>LINKED_TEST_LOCK_ACQUISITION_PATTERN.test(line)&&LINKED_TEST_LOCK_CONTENTION_CONTEXT_PATTERN.test(line))}function classifyLinkedTestFailure(result){if(hasInfraCollisionSignal(result)){return"infra_collision"}if(result.timedOut){return"timeout"}if(result.maxBufferExceeded){return"max_buffer"}if(result.spawnError){return"spawn_error"}if(result.signal){return"signal"}return"assertion_failure"}function createEmptyFailureCategoryCounts(){return{infra_collision:0,trust_refusal:0,assertion_failure:0,empty_run:0,timeout:0,max_buffer:0,spawn_error:0,signal:0}}function countFailureCategories(runResults){const counts=createEmptyFailureCategoryCounts();for(const result of runResults){if(result.status!=="failed"||!result.failure_category){continue}counts[result.failure_category]+=1}return counts}function applyEnvDirectiveStage(env,directives){for(const[key,value]of Object.entries(directives.env_set)){if(LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())){continue}env[key]=value}for(const key of directives.env_clear){if(LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())){continue}delete env[key]}}function applySharedHostSafeDefaults(env){if(env.PORT===void 0){env.PORT="0"}if(env.HOST===void 0){env.HOST="127.0.0.1"}if(env.PM_SHARED_HOST_SAFE===void 0){env.PM_SHARED_HOST_SAFE="1"}if(env.PLAYWRIGHT_HTML_OPEN===void 0){env.PLAYWRIGHT_HTML_OPEN="never"}if(env.PW_TEST_HTML_REPORT_OPEN===void 0){env.PW_TEST_HTML_REPORT_OPEN="never"}}function resolveEffectiveLinkedTestDirectives(runtimeDirectives,linkedTest){const envSet={...runtimeDirectives.env_set,...linkedTest.env_set};const envClear=[...new Set([...runtimeDirectives.env_clear,...linkedTest.env_clear??[]])];const sharedHostSafe=linkedTest.shared_host_safe??runtimeDirectives.shared_host_safe;return{env_set:envSet,env_clear:envClear,shared_host_safe:sharedHostSafe}}function resolveRuntimeDirectives(envSetEntries,envClearEntries,sharedHostSafe){return{env_set:mergeEnvSetDirectives(envSetEntries,"--env-set"),env_clear:mergeEnvClearDirectives(envClearEntries,"--env-clear"),shared_host_safe:sharedHostSafe===true}}async function copyIntoSandboxIfPresent(sourcePath,targetPath,recursive=false,makeDirectory=mkdir){if(!await pathExists(sourcePath)){return}try{await withHostEnvironmentBoundary("seed_linked_test",async()=>{await makeDirectory(path.dirname(targetPath),{recursive:true});if(recursive){await cp(sourcePath,targetPath,{recursive:true,force:true});return}await cp(sourcePath,targetPath,{force:true})},{why:"Linked tests need an isolated PM context without mutating the source tracker.",nextSteps:["Reclaim capacity on the filesystem that hosts the linked-test temporary directory."]})}catch(error){if(typeof error==="object"&&error!==null&&"code"in error&&isFileMissingError(error)){return}throw error}}async function seedLinkedTestSandbox(sandboxPmPath,sandboxGlobalPath,sourceRoots){await copyIntoSandboxIfPresent(getSettingsPath(sourceRoots.projectPmRoot),getSettingsPath(sandboxPmPath));await copyIntoSandboxIfPresent(path.join(sourceRoots.projectPmRoot,"extensions"),path.join(sandboxPmPath,"extensions"),true);await copyIntoSandboxIfPresent(getSettingsPath(sourceRoots.globalPmRoot),getSettingsPath(sandboxGlobalPath));await copyIntoSandboxIfPresent(path.join(sourceRoots.globalPmRoot,"extensions"),path.join(sandboxGlobalPath,"extensions"),true)}async function seedLinkedTestTrackerData(sourceRoot,sandboxRoot){if(!await pathExists(sourceRoot)){return}const entries=await readdir(sourceRoot,{withFileTypes:true});for(const entry of entries){if(LINKED_TEST_TRACKER_DIRS_TO_SKIP.has(entry.name)){continue}const sourcePath=path.join(sourceRoot,entry.name);const targetPath=path.join(sandboxRoot,entry.name);if(entry.isDirectory()){await copyIntoSandboxIfPresent(sourcePath,targetPath,true);continue}if(entry.isFile()){await copyIntoSandboxIfPresent(sourcePath,targetPath)}}}async function seedMissingLinkedTestSettingsHistory(sourceRoot,sandboxRoot){const sourceSettingsRaw=await readFileIfExists(getSettingsPath(sourceRoot));if(sourceSettingsRaw===null||await pathExists(getWorkspaceHistoryPath(sourceRoot))){return}const sandboxSettings=await readSettings(sandboxRoot);await rm(getWorkspaceHistoryPath(sandboxRoot),{force:true});await rm(getSettingsPath(sandboxRoot),{force:true});await writeWorkspaceJsonWithHistory({pmRoot:sandboxRoot,filePath:getSettingsPath(sandboxRoot),raw:sourceSettingsRaw,op:"settings:write",author:resolveAuthor(void 0,sandboxSettings.author_default),lockTtlSeconds:sandboxSettings.locks.ttl_seconds,lockWaitMs:sandboxSettings.locks.wait_ms,recordCreation:true,message:"Seed linked-test tracker settings history"})}async function countLinkedTestItemFiles(pmRoot){if(!await pathExists(pmRoot)){return 0}let total=0;const entries=await readdir(pmRoot,{withFileTypes:true});for(const entry of entries){if(!entry.isDirectory()||LINKED_TEST_ITEM_COUNT_DIRS_TO_SKIP.has(entry.name)){continue}const folderPath=path.join(pmRoot,entry.name);let files;try{files=await readdir(folderPath,{withFileTypes:true})}catch{continue}for(const file of files){if(!file.isFile()){continue}if(ITEM_FILE_EXTENSIONS.some(extension=>file.name.toLowerCase().endsWith(extension))){total+=1}}}return total}function resolveLinkedTestFailureExitCode(execution){const rawExitCode=typeof execution.exitCode==="number"?execution.exitCode:1;if((execution.timedOut||execution.maxBufferExceeded)&&rawExitCode===0){return 1}return rawExitCode}function parseAssertionLiteral(raw){const trimmed=raw.trim();if(trimmed==="true"){return true}if(trimmed==="false"){return false}if(trimmed==="null"){return null}const numeric=Number(trimmed);if(trimmed.length>0&&Number.isFinite(numeric)){return numeric}if(trimmed.startsWith("{")&&trimmed.endsWith("}")||trimmed.startsWith("[")&&trimmed.endsWith("]")){try{return JSON.parse(trimmed)}catch{}}return trimmed}function compareAssertionValues(actual,expected){if(typeof actual==="object"&&actual!==null&&typeof expected==="object"&&expected!==null){return stableValueEquals(actual,expected)}return Object.is(actual,expected)}function evaluateLinkedTestAssertions(linkedTest,stdout,stderr){const failures=[];failures.push(...evaluateContainsAssertions("stdout",stdout,linkedTest.assert_stdout_contains));failures.push(...evaluateRegexAssertions("stdout",stdout,linkedTest.assert_stdout_regex));failures.push(...evaluateContainsAssertions("stderr",stderr,linkedTest.assert_stderr_contains));failures.push(...evaluateRegexAssertions("stderr",stderr,linkedTest.assert_stderr_regex));failures.push(...evaluateStdoutLineCountAssertion(stdout,linkedTest.assert_stdout_min_lines));const jsonEqualsAssertions=linkedTest.assert_json_field_equals??{};const jsonGteAssertions=linkedTest.assert_json_field_gte??{};const needsJsonAssertions=Object.keys(jsonEqualsAssertions).length>0||Object.keys(jsonGteAssertions).length>0;if(!needsJsonAssertions){return failures}let parsedJson;try{parsedJson=JSON.parse(stdout)}catch(error){failures.push(`stdout is not valid JSON for assert_json_field_* checks: ${error instanceof Error?error.message:String(error)}`);return failures}for(const[fieldPath,expectedRaw]of Object.entries(jsonEqualsAssertions)){const resolved=readJsonPathValue(parsedJson,fieldPath);if(!resolved.found){failures.push(`assert_json_field_equals missing path "${fieldPath}"`);continue}const expected=parseAssertionLiteral(expectedRaw);if(!compareAssertionValues(resolved.value,expected)){failures.push(`assert_json_field_equals mismatch at "${fieldPath}" (expected=${JSON.stringify(expected)} actual=${JSON.stringify(resolved.value)})`)}}for(const[fieldPath,expectedMinimum]of Object.entries(jsonGteAssertions)){const resolved=readJsonPathValue(parsedJson,fieldPath);if(!resolved.found){failures.push(`assert_json_field_gte missing path "${fieldPath}"`);continue}if(typeof resolved.value!=="number"||!Number.isFinite(resolved.value)){failures.push(`assert_json_field_gte path "${fieldPath}" resolved to non-numeric value`);continue}if(resolved.value<expectedMinimum){failures.push(`assert_json_field_gte failed at "${fieldPath}" (expected >= ${expectedMinimum}, actual ${resolved.value})`)}}return failures}function evaluateContainsAssertions(streamName,output,expectedValues){const failures=[];for(const expected of expectedValues??[]){if(!output.includes(expected)){failures.push(`${streamName} missing required text: "${expected}"`)}}return failures}function evaluateRegexAssertions(streamName,output,patterns){const failures=[];for(const pattern of patterns??[]){try{const regex=new RegExp(pattern,"m");if(!regex.test(output)){failures.push(`${streamName} failed regex assertion: /${pattern}/m`)}}catch(error){failures.push(`${streamName} regex assertion is invalid: /${pattern}/ (${error instanceof Error?error.message:String(error)})`)}}return failures}function evaluateStdoutLineCountAssertion(stdout,minimum){if(typeof minimum!=="number"){return[]}const lineCount=stdout.split(/\r?\n/).map(line=>line.trim()).filter(line=>line.length>0).length;return lineCount<minimum?[`stdout line count ${lineCount} is below required minimum ${minimum}`]:[]}const EMPTY_LINKED_TEST_RUN_PATTERNS=[{code:"no_projects_matched_filters",regex:/\bNo projects matched the filters\b/i},{code:"no_test_files_found",regex:/\bNo test files found\b/i},{code:"no_tests_found",regex:/\bNo tests found\b/i},{code:"no_matching_tests",regex:/\bNo matching tests?\b/i},{code:"collected_zero_items",regex:/\bcollected 0 items?\b/i},{code:"reported_zero_passes",regex:/(?:^\s*(?:#|ℹ)?\s*tests\s+0\s*$[\s\S]*^\s*(?:#|ℹ)?\s*pass\s+0\s*$|^\s*(?:#|ℹ)?\s*pass\s+0\s*$[\s\S]*^\s*(?:#|ℹ)?\s*tests\s+0\s*$)/imu},{code:"reported_zero_tests",regex:/^\s*(?:#|ℹ)?\s*tests\s+0\s*$/imu}];const POSITIVE_LINKED_TEST_RUN_PATTERNS=[/^\s*(?:#|ℹ)?\s*tests\s+[1-9]\d*\s*$/imu,/^\s*(?:#|ℹ)?\s*pass\s+[1-9]\d*\s*$/imu,/\bTests?\s+[1-9]\d*\s+passed\b/iu,/\b[1-9]\d*\s+passed\b/iu,/\bTests:\s+(?:.*\b)?[1-9]\d*\s+passed\b/iu];function detectEmptyLinkedTestRun(stdout,stderr){const combined=`${stdout}
5
- ${stderr}`;for(const pattern of EMPTY_LINKED_TEST_RUN_PATTERNS){if(pattern.regex.test(combined)){return{code:pattern.code}}}return null}function hasPositiveLinkedTestRunReceipt(stdout,stderr){const combined=`${stdout}
6
- ${stderr}`;return POSITIVE_LINKED_TEST_RUN_PATTERNS.some(pattern=>pattern.test(combined))}function commandUsesTestNameFilter(command){const normalized=normalizeCommandForValidation(command);if(/(?:^|\s)(?:--test-name-pattern|--testnamepattern)(?:=|\s)/u.test(normalized)){return true}return splitNormalizedCommandSegments(normalized).some(segment=>/(?:^|\s)-t(?:=|\s)/u.test(segment)&&segmentInvokesDirectTestRunner(segment))}function createLinkedTestSandboxLayout(sandboxRoot){return{root:sandboxRoot,schemaProjectPmPath:path.join(sandboxRoot,"schema","project",".agents","pm"),schemaGlobalPmPath:path.join(sandboxRoot,"schema","global"),trackerProjectPmPath:path.join(sandboxRoot,"tracker","project",".agents","pm"),trackerGlobalPmPath:path.join(sandboxRoot,"tracker","global"),workspaceSnapshotRoot:path.join(sandboxRoot,"workspace","project"),workspaceIsolatedRoot:path.join(sandboxRoot,"workspace","isolated")}}function linkedTestsRequireWorkspaceSnapshot(tests,runLevelMode,overrideLinkedMode){return tests.some(linkedTest=>resolveLinkedTestWorkspaceContextMode(linkedTest,runLevelMode,overrideLinkedMode)==="snapshot")}async function bindSnapshotTracker(snapshotRoot,sandboxPmPath){const agentsRoot=path.join(snapshotRoot,".agents");const target=path.join(agentsRoot,"pm");await mkdir(agentsRoot,{recursive:true});await rm(target,{recursive:true,force:true});await symlink(sandboxPmPath,target,process.platform==="win32"?"junction":"dir")}async function initializeLinkedTestSandboxes(layout,initialize=runInit,includeTrackerData=true){const initOptions={defaults:true,agentGuidance:"skip"};await initialize(void 0,{path:layout.schemaProjectPmPath},initOptions);await initialize(void 0,{path:layout.schemaGlobalPmPath},initOptions);if(!includeTrackerData){return}await initialize(void 0,{path:layout.trackerProjectPmPath},initOptions);await initialize(void 0,{path:layout.trackerGlobalPmPath},initOptions)}async function seedLinkedTestSandboxesFromSource(layout,sourceRoots,includeTrackerData){if(!sourceRoots){return}await seedLinkedTestSandbox(layout.schemaProjectPmPath,layout.schemaGlobalPmPath,sourceRoots);if(!includeTrackerData){return}await seedLinkedTestSandbox(layout.trackerProjectPmPath,layout.trackerGlobalPmPath,sourceRoots);await seedLinkedTestTrackerData(sourceRoots.projectPmRoot,layout.trackerProjectPmPath);await seedLinkedTestTrackerData(sourceRoots.globalPmRoot,layout.trackerGlobalPmPath);await seedMissingLinkedTestSettingsHistory(sourceRoots.projectPmRoot,layout.trackerProjectPmPath);await seedMissingLinkedTestSettingsHistory(sourceRoots.globalPmRoot,layout.trackerGlobalPmPath)}function linkedTestsRequireTrackerData(tests,runLevelPmContextMode,options){return tests.some(linkedTest=>{const command=linkedTest.command??"";const isPmTrackerReadCommand=command.length>0&&commandInvokesPmTrackerReadCommand(command);const requestedPmContextMode=options?.autoPmContext===true&&isPmTrackerReadCommand?"auto":resolveLinkedTestRequestedContextMode(linkedTest,runLevelPmContextMode,options?.overrideLinkedPmContext===true);return resolveLinkedTestEffectiveContextMode(requestedPmContextMode,isPmTrackerReadCommand)==="tracker"})}async function countLinkedTestSandboxItems(layout,sourceRoots){return{sourceProjectItemCount:sourceRoots?await countLinkedTestItemFiles(sourceRoots.projectPmRoot):0,sourceGlobalItemCount:sourceRoots?await countLinkedTestItemFiles(sourceRoots.globalPmRoot):0,schemaProjectItemCount:await countLinkedTestItemFiles(layout.schemaProjectPmPath),schemaGlobalItemCount:await countLinkedTestItemFiles(layout.schemaGlobalPmPath),trackerProjectItemCount:await countLinkedTestItemFiles(layout.trackerProjectPmPath),trackerGlobalItemCount:await countLinkedTestItemFiles(layout.trackerGlobalPmPath)}}function buildLinkedTestExecutionContext(params){const trackerMode=params.effectivePmContextMode==="tracker";const selectedSandboxProjectPmPath=trackerMode?params.layout.trackerProjectPmPath:params.layout.schemaProjectPmPath;const selectedSandboxGlobalPmPath=trackerMode?params.layout.trackerGlobalPmPath:params.layout.schemaGlobalPmPath;const selectedSandboxProjectItemCount=trackerMode?params.counts.trackerProjectItemCount:params.counts.schemaProjectItemCount;const selectedSandboxGlobalItemCount=trackerMode?params.counts.trackerGlobalItemCount:params.counts.schemaGlobalItemCount;const workingDirectory=params.workspaceContextMode==="snapshot"?params.layout.workspaceSnapshotRoot:params.workspaceContextMode==="isolated"?params.layout.workspaceIsolatedRoot:params.sourceWorkspaceRoot;const exposedSourceWorkspaceRoot=params.workspaceContextMode==="isolated"?"":workingDirectory;return{requested_pm_context_mode:params.requestedPmContextMode,pm_context_mode:params.effectivePmContextMode,auto_pm_context_applied:params.autoPmContextApplied,is_pm_command:params.isPmCommand,is_pm_tracker_read_command:params.isPmTrackerReadCommand,source_project_pm_path:params.sourceRoots?.projectPmRoot??"",sandbox_project_pm_path:selectedSandboxProjectPmPath,source_global_pm_path:params.sourceRoots?.globalPmRoot??"",sandbox_global_pm_path:selectedSandboxGlobalPmPath,source_project_item_count:params.counts.sourceProjectItemCount,sandbox_project_item_count:selectedSandboxProjectItemCount,source_global_item_count:params.counts.sourceGlobalItemCount,sandbox_global_item_count:selectedSandboxGlobalItemCount,mismatch_detected:params.isPmCommand&&(params.counts.sourceProjectItemCount!==selectedSandboxProjectItemCount||params.counts.sourceGlobalItemCount!==selectedSandboxGlobalItemCount),project_extensions_seeded:Boolean(params.sourceRoots),global_extensions_seeded:Boolean(params.sourceRoots),requested_workspace_context_mode:params.requestedWorkspaceContextMode,workspace_context_mode:params.workspaceContextMode,working_directory:workingDirectory,source_workspace_root:exposedSourceWorkspaceRoot,trust:params.trust}}async function resolveLinkedTestCommandContext(params){const linkedOverridePmContextMode=typeof params.linkedTest.pm_context_mode==="string"&&params.linkedTest.pm_context_mode.trim().length>0?parsePmContextMode(params.linkedTest.pm_context_mode):void 0;const command=typeof params.linkedTest.command==="string"&&params.linkedTest.command.length>0?params.linkedTest.command:void 0;const isPmCommand=command?commandInvokesPmCli(command):false;const isPmTrackerReadCommand=isPmCommand&&command?commandInvokesPmTrackerReadCommand(command):false;const autoPmContextApplied=params.options?.autoPmContext===true&&isPmTrackerReadCommand;const requestedPmContextMode=autoPmContextApplied?"auto":resolveLinkedTestRequestedContextMode(params.linkedTest,params.runLevelPmContextMode,params.options?.overrideLinkedPmContext===true);const effectivePmContextMode=resolveLinkedTestEffectiveContextMode(requestedPmContextMode,isPmTrackerReadCommand);const selectedSandboxProjectPmPath=effectivePmContextMode==="tracker"?params.layout.trackerProjectPmPath:params.layout.schemaProjectPmPath;if(params.workspaceContextMode==="snapshot"){await bindSnapshotTracker(params.layout.workspaceSnapshotRoot,selectedSandboxProjectPmPath)}const trust=params.options?.pmRoot?await resolveLinkedTestTrust(params.options.pmRoot,params.linkedTest,params.currentSourceRef):await resolveLinkedTestTrust(params.layout.root,params.linkedTest,params.currentSourceRef);return{linkedOverridePmContextMode,executionContext:buildLinkedTestExecutionContext({layout:params.layout,counts:params.counts,sourceRoots:params.sourceRoots,isPmCommand,isPmTrackerReadCommand,requestedPmContextMode,effectivePmContextMode,autoPmContextApplied,requestedWorkspaceContextMode:params.requestedWorkspaceContextMode,workspaceContextMode:params.workspaceContextMode,sourceWorkspaceRoot:params.sourceWorkspaceRoot,trust})}}function buildLinkedTestSkippedResult(linkedTest,executionContext,error){return{command:linkedTest.command,path:linkedTest.path,status:"skipped",execution_context:executionContext,error}}function buildLinkedTestAssertionFailureResult(linkedTest,executionContext,error,output){return{command:linkedTest.command,path:linkedTest.path,status:"failed",exit_code:1,failure_category:"assertion_failure",execution_context:executionContext,...output?{stdout:output.stdout,stderr:output.stderr}:{},error}}function buildLinkedTestTrustRefusalResult(linkedTest,executionContext,error){return{command:linkedTest.command,path:linkedTest.path,status:"failed",exit_code:1,failure_category:"trust_refusal",execution_context:executionContext,error}}function resolveLinkedTestTrustPreflightResult(params){if(params.executionContext.trust.trusted)return null;const overrideRequested=params.options?.allowUntrustedLinkedTests===true;const policyEnabled=params.options?.untrustedLinkedTestsPolicyEnabled===true;if(overrideRequested&&policyEnabled)return null;const recovery=policyEnabled?"Retry with --allow-untrusted-linked-tests for this invocation, or acknowledge the current commands with --acknowledge-linked-tests.":"Set testing.allow_untrusted_linked_tests=true, then retry with --allow-untrusted-linked-tests; alternatively acknowledge the current commands with --acknowledge-linked-tests.";return buildLinkedTestTrustRefusalResult(params.linkedTest,params.executionContext,`Linked test command is not trusted by this clone (source_ref=${params.executionContext.trust.source_ref??"unknown"}, current_ref=${params.executionContext.trust.current_source_ref??"unknown"}). ${recovery}`)}function resolveLinkedTestSafetyPreflightResult(params){if(!params.linkedTest.command){return buildLinkedTestSkippedResult(params.linkedTest,params.executionContext,"No command configured for this linked test.")}const runtimeSafetySkipReason=getRuntimeSafetySkipReason(params.linkedTest.command);return runtimeSafetySkipReason?buildLinkedTestSkippedResult(params.linkedTest,params.executionContext,runtimeSafetySkipReason):null}function resolveUnboundPmContextFailure(params){if(params.executionContext.pm_context_mode!=="none")return null;if(params.executionContext.workspace_context_mode==="source"){return buildLinkedTestAssertionFailureResult(params.linkedTest,params.executionContext,"pm_context_mode=none requires workspace_context_mode=isolated or snapshot so implicit tracker discovery cannot reach the source workspace.")}if(params.executionContext.is_pm_command){return buildLinkedTestAssertionFailureResult(params.linkedTest,params.executionContext,"pm_context_mode=none is for self-isolating SDK tests; direct PM commands require schema, tracker, or auto context.")}return null}function resolvePmContextMismatchFailure(params){const failOnMismatchByDefault=params.executionContext.pm_context_mode==="schema"&&params.executionContext.is_pm_tracker_read_command&&params.executionContext.mismatch_detected;const failOnMismatchByFlag=params.options?.failOnContextMismatch===true&&params.executionContext.is_pm_command&&params.executionContext.mismatch_detected;if(!failOnMismatchByDefault&&!failOnMismatchByFlag)return null;const mismatchHint=buildPmContextMismatchHint({executionContext:params.executionContext,runLevelPmContextMode:params.runLevelPmContextMode,linkedOverridePmContextMode:params.linkedOverridePmContextMode});const mismatchPrefix=params.options?.checkContext===true?"Linked test preflight PM context mismatch detected":"Linked test PM context mismatch detected";return buildLinkedTestAssertionFailureResult(params.linkedTest,params.executionContext,`${mismatchPrefix} (source_project_items=${params.executionContext.source_project_item_count}, sandbox_project_items=${params.executionContext.sandbox_project_item_count}).${mismatchHint}`)}function resolveLinkedTestPreflightResult(params){const safetyFailure=resolveLinkedTestSafetyPreflightResult(params);if(safetyFailure)return safetyFailure;const trustFailure=resolveLinkedTestTrustPreflightResult(params);if(trustFailure)return trustFailure;const unboundContextFailure=resolveUnboundPmContextFailure(params);if(unboundContextFailure)return unboundContextFailure;const mismatchFailure=resolvePmContextMismatchFailure(params);if(mismatchFailure)return mismatchFailure;if(params.options?.requireAssertionsForPm===true&&params.executionContext.is_pm_command&&!hasLinkedTestAssertions(params.linkedTest)){return buildLinkedTestAssertionFailureResult(params.linkedTest,params.executionContext,"Linked PM command requires assertions when --require-assertions-for-pm is enabled.")}return null}function buildLinkedTestExecutionEnv(params){const effectiveDirectives=resolveEffectiveLinkedTestDirectives(params.runtimeDirectives,params.linkedTest);const executionEnv={...process.env,SENTRY_ENVIRONMENT:"test"};applyEnvDirectiveStage(executionEnv,params.runtimeDirectives);applyEnvDirectiveStage(executionEnv,{env_set:params.linkedTest.env_set??{},env_clear:params.linkedTest.env_clear??[]});if(effectiveDirectives.shared_host_safe){applySharedHostSafeDefaults(executionEnv)}executionEnv.FORCE_COLOR="0";if(params.executionContext.pm_context_mode==="none"){delete executionEnv.PM_PATH}else{executionEnv.PM_PATH=params.executionContext.sandbox_project_pm_path}executionEnv.PM_GLOBAL_PATH=params.executionContext.sandbox_global_pm_path;if(params.executionContext.workspace_context_mode==="isolated"){delete executionEnv.PM_SOURCE_WORKSPACE_ROOT;delete executionEnv.PM_SOURCE_PM_PATH;delete executionEnv[SOURCE_CONTEXT_ACCESS_ENV]}else{executionEnv.PM_SOURCE_WORKSPACE_ROOT=params.executionContext.source_workspace_root;executionEnv.PM_SOURCE_PM_PATH=params.executionContext.workspace_context_mode==="snapshot"?params.executionContext.sandbox_project_pm_path:params.executionContext.source_project_pm_path;executionEnv[SOURCE_CONTEXT_ACCESS_ENV]="read_only"}return executionEnv}function buildLinkedTestPassedResult(linkedTest,executionContext,execution){return{command:linkedTest.command,path:linkedTest.path,status:"passed",exit_code:0,execution_context:executionContext,stdout:execution.stdout,stderr:execution.stderr}}function buildLinkedTestEmptyRunResult(params){return{command:params.linkedTest.command,path:params.linkedTest.path,status:"failed",exit_code:1,failure_category:"empty_run",execution_context:params.executionContext,stdout:params.execution.stdout,stderr:params.execution.stderr,error:`Linked test reported an empty test run (${params.emptyRunSignal.code}). Update the test selection so at least one test executes; unfiltered commands may opt out by omitting --fail-on-empty-test-run.`}}function buildLinkedTestCommandFailureResult(params){return{command:params.linkedTest.command,path:params.linkedTest.path,status:"failed",exit_code:resolveLinkedTestFailureExitCode(params.execution),failure_category:classifyLinkedTestFailure(params.execution),execution_context:params.executionContext,stdout:params.execution.stdout,stderr:params.execution.stderr,error:formatLinkedTestExecutionError(params.execution,params.timeoutMs)}}function buildLinkedTestPassedExecutionResult(params){if(params.options?.failOnEmptyTestRun===true||commandUsesTestNameFilter(params.linkedTest.command??"")){const emptyRunSignal=detectEmptyLinkedTestRun(params.execution.stdout,params.execution.stderr);if(emptyRunSignal){return buildLinkedTestEmptyRunResult({...params,emptyRunSignal})}if(commandUsesTestNameFilter(params.linkedTest.command??"")&&!hasPositiveLinkedTestRunReceipt(params.execution.stdout,params.execution.stderr)){return buildLinkedTestEmptyRunResult({...params,emptyRunSignal:{code:"missing_positive_execution_receipt"}})}}const assertionFailures=evaluateLinkedTestAssertions(params.linkedTest,params.execution.stdout,params.execution.stderr);if(assertionFailures.length>0){return buildLinkedTestAssertionFailureResult(params.linkedTest,params.executionContext,`Linked test assertion(s) failed: ${assertionFailures.join("; ")}`,params.execution)}return buildLinkedTestPassedResult(params.linkedTest,params.executionContext,params.execution)}async function runSingleLinkedTest(params){const command=params.linkedTest.command??"";const timeoutMs=(params.linkedTest.timeout_seconds??params.defaultTimeoutSeconds??120)*1e3;const execution=await runLinkedTestCommand(command,timeoutMs,buildLinkedTestExecutionEnv(params),{index:params.index+1,total:params.total,timeoutMs,command},params.progressMode,params.executionContext.working_directory);const passed=execution.exitCode===0&&!execution.timedOut&&!execution.maxBufferExceeded;return passed?buildLinkedTestPassedExecutionResult({...params,execution}):buildLinkedTestCommandFailureResult({...params,execution,timeoutMs})}async function runLinkedTests(tests,defaultTimeoutSeconds,options){const results=[];const sandboxRoot=await mkdtemp(path.join(tmpdir(),"pm-linked-test-"));const layout=createLinkedTestSandboxLayout(sandboxRoot);const runLevelPmContextMode=parsePmContextMode(options?.pmContext);const runLevelWorkspaceContextMode=parseWorkspaceContextMode(options?.workspaceContext);const progressMode=options?.progress===true?"always":"auto";const runtimeDirectives=resolveRuntimeDirectives(options?.envSet,options?.envClear,options?.sharedHostSafe);const sourceRoots=options?.sourceRoots;const sourceWorkspaceRoot=resolveLinkedTestSourceWorkspaceRoot();const includeTrackerData=linkedTestsRequireTrackerData(tests,runLevelPmContextMode,options);const includeWorkspaceSnapshot=linkedTestsRequireWorkspaceSnapshot(tests,runLevelWorkspaceContextMode,options?.overrideLinkedWorkspaceContext===true);const currentSourceRef=await resolveLinkedTestSourceRef(sourceWorkspaceRoot);try{await initializeLinkedTestSandboxes(layout,runInit,includeTrackerData);await mkdir(layout.workspaceIsolatedRoot,{recursive:true});await seedLinkedTestSandboxesFromSource(layout,sourceRoots,includeTrackerData);if(includeWorkspaceSnapshot){await seedLinkedTestWorkspaceSnapshot(sourceWorkspaceRoot,layout.workspaceSnapshotRoot)}const counts=await countLinkedTestSandboxItems(layout,sourceRoots);for(let index=0;index<tests.length;index+=1){const linkedTest=tests[index];const workspaceContextMode=resolveLinkedTestWorkspaceContextMode(linkedTest,runLevelWorkspaceContextMode,options?.overrideLinkedWorkspaceContext===true);const commandContext=await resolveLinkedTestCommandContext({linkedTest,layout,counts,sourceRoots,runLevelPmContextMode,options,requestedWorkspaceContextMode:runLevelWorkspaceContextMode,workspaceContextMode,currentSourceRef,sourceWorkspaceRoot});const preflightResult=resolveLinkedTestPreflightResult({linkedTest,executionContext:commandContext.executionContext,runLevelPmContextMode,linkedOverridePmContextMode:commandContext.linkedOverridePmContextMode,options});if(preflightResult){results.push(preflightResult);continue}results.push(await runSingleLinkedTest({linkedTest,index,total:tests.length,defaultTimeoutSeconds,runtimeDirectives,progressMode,executionContext:commandContext.executionContext,options}))}}finally{await rm(layout.root,{recursive:true,force:true,maxRetries:3,retryDelay:100})}return results}async function readLinkedTestItem(params){const{id,pmRoot,settings,typeToFolder}=params;const located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeToFolder);if(!located){throw new PmCliError(`Item ${id} not found`,EXIT_CODE.NOT_FOUND)}const loaded=await readLocatedItem(located,{schema:settings.schema});return{itemId:located.id,tests:loaded.document.metadata.tests??[],testRuns:loaded.document.metadata.test_runs??[],changed:false,removed:0}}function linkedTestsHaveSameIdentity(left,right){return left.command===right.command&&left.path===right.path&&left.scope===right.scope&&left.pm_context_mode===right.pm_context_mode&&left.workspace_context_mode===right.workspace_context_mode}function appendMissingLinkedTests(current,additions){const next=[...current];for(const addition of additions){if(!next.some(entry=>linkedTestsHaveSameIdentity(entry,addition))){next.push(addition)}}return next}function removeLinkedTestsBySelector(current,removals,removeIndexes){if(removals.length===0&&removeIndexes.length===0){return{tests:current,removed:0}}const indexSet=new Set(removeIndexes);const tests=current.filter((entry,index)=>{if(indexSet.has(index+1))return false;return!removals.some(selector=>{if(selector.kind==="command")return entry.command===selector.value;if(selector.kind==="path")return entry.path===selector.value;return entry.command===selector.value||entry.path===selector.value})});return{tests,removed:current.length-tests.length}}function applyLinkedTestMutations(previous,adds,removes,removeIndexes){return removeLinkedTestsBySelector(appendMissingLinkedTests(previous,adds),removes,removeIndexes)}function hasTestRuntimeDirectiveFlags(options){return[(options.envSet?.length??0)>0,(options.envClear?.length??0)>0,options.sharedHostSafe===true,options.pmContext!==void 0,options.overrideLinkedPmContext===true,options.failOnContextMismatch===true,options.failOnSkipped===true,options.failOnEmptyTestRun===true,options.requireAssertionsForPm===true,options.checkContext===true,options.autoPmContext===true,options.workspaceContext!==void 0,options.overrideLinkedWorkspaceContext===true,options.allowUntrustedLinkedTests===true].some(Boolean)}function assertTestRunFlagUsage(options){if(hasTestRuntimeDirectiveFlags(options)&&options.run!==true){throw new PmCliError("--env-set, --env-clear, --shared-host-safe, --pm-context, --override-linked-pm-context, --workspace-context, --override-linked-workspace-context, --allow-untrusted-linked-tests, --fail-on-context-mismatch, --fail-on-skipped, --fail-on-empty-test-run, --require-assertions-for-pm, --check-context, and --auto-pm-context require --run",EXIT_CODE.USAGE)}if(options.acknowledgeLinkedTests===true&&options.run===true){throw new PmCliError("--acknowledge-linked-tests records trust without executing commands; run it separately before --run",EXIT_CODE.USAGE)}const hasSelectorFlags=options.match!==void 0||options.onlyIndex!==void 0||options.onlyLast===true;if(hasSelectorFlags&&options.run!==true){throw new PmCliError("--match, --only-index, and --only-last require --run",EXIT_CODE.USAGE)}}async function resolveLinkedTestItem(params){const{id,options,pmRoot,settings,typeToFolder,adds,removes,removeIndexes}=params;if(adds.length===0&&removes.length===0&&removeIndexes.length===0){return readLinkedTestItem({id,pmRoot,settings,typeToFolder})}let removed=0;const result=await mutateItem({pmRoot,settings,id,op:adds.length>0?"tests_add":"tests_remove",author:resolveAuthor(options.author,settings.author_default),message:options.message,force:options.force,skipNoop:true,mutate(document){const previous=document.metadata.tests??[];const mutation=applyLinkedTestMutations(previous,adds,removes,removeIndexes);removed=mutation.removed;if((removes.length>0||removeIndexes.length>0)&&removed===0){throw new PmCliError("No linked tests matched the requested removal selector",EXIT_CODE.NOT_FOUND,{code:"linked_test_remove_no_match",unmatched:[...removes.map(entry=>`${entry.kind}=${entry.value}`),...removeIndexes.map(index=>`index=${index}`)],required:"List linked tests and retry with an exact command/path or a current 1-based --remove-index.",examples:[`pm test ${id} --list`,`pm test ${id} --remove-index 1`]})}document.metadata.tests=mutation.tests;return{changedFields:stableValueEquals(previous,mutation.tests)?[]:["tests"]}}});return{itemId:result.item.id,tests:result.item.tests??[],testRuns:result.item.test_runs??[],changed:result.changedFields.length>0,removed}}function resolveTestRunOptions(options,tests){assertTestRunFlagUsage(options);const selectorInput={match:options.match,onlyIndex:options.onlyIndex===void 0?void 0:parseOnlyIndexValue(options.onlyIndex),onlyLast:options.onlyLast};const runSelection=options.run===true?resolveLinkedTestRunSelection(tests,selectorInput):void 0;const defaultTimeoutSeconds=options.timeout===void 0?void 0:parseOptionalNumber(options.timeout,"timeout");if(defaultTimeoutSeconds!==void 0&&defaultTimeoutSeconds<=0){throw new PmCliError("Test timeout must be a positive number",EXIT_CODE.USAGE)}return{defaultTimeoutSeconds,pmContextMode:parsePmContextMode(options.pmContext),runSelection,testsToRun:runSelection?.selected??tests}}async function executeSelectedLinkedTests(params){const{options,runOptions,pmRoot}=params;if(options.run!==true){return[]}return await runLinkedTests(runOptions.testsToRun,runOptions.defaultTimeoutSeconds,{progress:options.progress,envSet:options.envSet,envClear:options.envClear,sharedHostSafe:options.sharedHostSafe,pmContext:runOptions.pmContextMode,overrideLinkedPmContext:options.overrideLinkedPmContext,failOnContextMismatch:options.failOnContextMismatch,failOnEmptyTestRun:options.failOnEmptyTestRun,requireAssertionsForPm:options.requireAssertionsForPm,checkContext:options.checkContext,autoPmContext:options.autoPmContext,workspaceContext:options.workspaceContext,overrideLinkedWorkspaceContext:options.overrideLinkedWorkspaceContext,pmRoot,allowUntrustedLinkedTests:options.allowUntrustedLinkedTests,untrustedLinkedTestsPolicyEnabled:params.untrustedLinkedTestsPolicyEnabled,sourceRoots:{projectPmRoot:pmRoot,globalPmRoot:resolveGlobalPmRoot(process.cwd())}})}function buildTestWarnings(options,runSelection,runResults){const warnings=[];if(runSelection&&runSelection.selector!==null){warnings.push(`linked_test_selection:${runSelection.selector}=${runSelection.requested};selected=${runSelection.selected_count};skipped=${runSelection.skipped_count};indexes=${runSelection.selected_indexes.join(",")}`)}if(options.run===true&&options.checkContext===true){const preflight=summarizeContextPreflight(runResults);warnings.push(`context_preflight:checked_pm_commands=${preflight.checked_pm_commands};tracker_read_commands=${preflight.tracker_read_commands};mismatches=${preflight.mismatches};auto_remediated=${preflight.auto_remediated}`)}return warnings}function buildTrackedTestRunSummary(params){const summary=summarizeRunResultStatuses(params.runResults);const parsedAttempt=Number.parseInt(process.env.PM_BACKGROUND_TEST_RUN_ATTEMPT?.trim()??"",10);const resumedFrom=process.env.PM_BACKGROUND_TEST_RUN_RESUMED_FROM?.trim();const recordedAt=nowIso();const measurements=parseTestRunMeasurements(params.options.measure,recordedAt);return{run_id:resolveTrackedRunId("test"),kind:"test",status:summary.failed>0||params.failOnSkippedTriggered?"failed":"passed",started_at:params.runStartedAt,finished_at:recordedAt,recorded_at:recordedAt,attempt:Number.isFinite(parsedAttempt)&&parsedAttempt>=1?parsedAttempt:void 0,resumed_from:resumedFrom&&resumedFrom.length>0?resumedFrom:void 0,passed:summary.passed,failed:summary.failed,skipped:summary.skipped,fail_on_skipped_triggered:params.failOnSkippedTriggered?true:void 0,measurements:measurements.length>0?measurements:void 0,executions:params.runResults.filter(result=>result.command?.trim()).slice(0,32).map(result=>({command:result.command.trim(),requested_pm_context_mode:result.execution_context?.requested_pm_context_mode,pm_context_mode:result.execution_context?.pm_context_mode,workspace_context_mode:result.execution_context?.workspace_context_mode,trust_reason:result.execution_context?.trust.reason}))}}async function recordTestRunSummary(params){const{options,pmRoot,settings,itemId,runStartedAt,runResults,failOnSkippedTriggered,warnings}=params;if(options.run!==true||!runStartedAt){return void 0}const entry=buildTrackedTestRunSummary({options,runStartedAt,runResults,failOnSkippedTriggered});if(settings.testing.record_results_to_items!==true){return{entry,receipt:{recorded:false,reason:"tracking_disabled",run_id:entry.run_id,recovery_command:"pm config project set test-result-tracking --policy enabled"}}}try{await appendTrackedTestRunSummary({pmRoot,settings,itemId,author:resolveAuthor(options.author,settings.author_default),message:`Track test run summary (${entry.run_id})`,entry});return{entry,receipt:{recorded:true,reason:"recorded",run_id:entry.run_id}}}catch(error){warnings.push(`test_result_tracking_failed:${itemId}:${error instanceof Error?error.message:String(error)}`);return{entry,receipt:{recorded:false,reason:"write_failed",run_id:entry.run_id}}}}function buildTestMeasurementProjection(options,runs,recordedRun){let metricBelow;if(options.metricBelow!==void 0){const separator=options.metricBelow.indexOf("=");const name=options.metricBelow.slice(0,separator).trim();const thresholdText=options.metricBelow.slice(separator+1).trim();const threshold=Number(thresholdText);if(separator<=0||name.length===0||thresholdText.length===0||!Number.isFinite(threshold)){throw new PmCliError("--metric-below must use name=value",EXIT_CODE.USAGE)}metricBelow=queryTestRunMeasurementsBelow(runs,name,threshold)}return{measurements:recordedRun?.measurements,metric_below:metricBelow,metric_diff:options.metricDiff===void 0?void 0:diffTestRunMeasurements(runs,options.metricDiff)}}async function maybeAcknowledgeLinkedTests(options,pmRoot,tests){if(options.acknowledgeLinkedTests!==true)return void 0;return acknowledgeLinkedTests(pmRoot,tests,nowIso())}function projectTestResult(input){const{item,runResults,failureCategories,runSelection,failOnSkippedTriggered,warnings,recording,measurementProjection}=input;return{ok:runResults.every(entry=>entry.status!=="failed")&&failOnSkippedTriggered!==true,id:item.itemId,tests:item.tests,run_results:runResults,failure_categories:failureCategories,selection:runSelection?{selector:runSelection.selector,requested:runSelection.requested,selected_indexes:runSelection.selected_indexes,selected_count:runSelection.selected_count,skipped_count:runSelection.skipped_count}:void 0,fail_on_skipped_triggered:failOnSkippedTriggered?true:void 0,warnings:warnings.length>0?warnings:void 0,changed:item.changed||recording?.receipt.recorded===true,...recording?{evidence_recording:recording.receipt}:{},count:item.tests.length,...item.removed>0?{removed:item.removed}:{},...measurementProjection}}async function runTest(id,options,global2){const stdinResolver=createStdinTokenResolver();const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot);if((options.measure?.length??0)>0&&options.run!==true){throw new PmCliError("--measure requires --run",EXIT_CODE.USAGE)}parseTestRunMeasurements(options.measure,"validation");buildTestMeasurementProjection(options,[],void 0);const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());const resolvedAdds=await stdinResolver.resolveList(options.add,"--add");const resolvedAddJsons=await stdinResolver.resolveList(options.addJson,"--add-json");const resolvedRemoves=await stdinResolver.resolveList(options.remove,"--remove");const parsedAdds=[...parseAddEntries(resolvedAdds),...parseAddJsonEntries(resolvedAddJsons)];const adds=await attachLinkedTestMutationProvenance(parsedAdds,resolveAuthor(options.author,settings.author_default),nowIso())??[];const removes=parseRemoveEntries(resolvedRemoves);const removeIndexes=parseRemoveIndexes(options.removeIndex);const item=await resolveLinkedTestItem({id,options,pmRoot,settings,typeToFolder:typeRegistry.type_to_folder,adds,removes,removeIndexes});const runOptions=resolveTestRunOptions(options,item.tests);const trustAcknowledgement=await maybeAcknowledgeLinkedTests(options,pmRoot,item.tests);const runStartedAt=options.run===true?nowIso():void 0;const runResults=await executeSelectedLinkedTests({options,runOptions,pmRoot,untrustedLinkedTestsPolicyEnabled:settings.testing.allow_untrusted_linked_tests});const failureCategories=countFailureCategories(runResults);const failOnSkippedTriggered=options.run===true&&options.failOnSkipped===true&&runResults.some(entry=>entry.status==="skipped");const warnings=buildTestWarnings(options,runOptions.runSelection,runResults);if(trustAcknowledgement){warnings.push(`linked_test_trust_acknowledged:${trustAcknowledgement.acknowledged}`)}const recording=await recordTestRunSummary({options,pmRoot,settings,itemId:item.itemId,runStartedAt,runResults,failOnSkippedTriggered,warnings});const runs=recording?.receipt.recorded?buildTrackedTestRunHistory([...item.testRuns,recording.entry]):item.testRuns;const measurementProjection=buildTestMeasurementProjection(options,runs,recording?.entry);return projectTestResult({item,runResults,failureCategories,runSelection:runOptions.runSelection,failOnSkippedTriggered,warnings,recording,measurementProjection})}const _testOnlyTestCommand={buildLinkedTestExecutionContext,buildPmContextMismatchHint,commandInvokesPmCli,commandInvokesPmTrackerReadCommand,commandUsesTestNameFilter,copyIntoSandboxIfPresent,countLinkedTestItemFiles,ensureScope,evaluateLinkedTestAssertions,endLinkedTestProgress,extractPmInvocationArgsFromSegment,firstDirectTestRunnerSubcommand,formatLinkedTestExecutionError,hasLinkedTestAssertions,initializeLinkedTestSandboxes,linkedTestsRequireTrackerData,parseAddJsonEntries,parseLinkedTestTimeoutSeconds,parsePmContextMode,readJsonPathValue,resolveAuthor,resolveDirectRunnerSubcommand,resolveLinkedTestEffectiveContextMode,resolveLinkedTestFailureExitCode,resolveLinkedTestRequestedContextMode,resolveTestRunOptions,resolveTrackedRunId,runLinkedTestCommand,seedMissingLinkedTestSettingsHistory,seedLinkedTestSandbox,seedLinkedTestTrackerData,segmentInvokesRecursiveTestAll,splitJsonPathSegments,summarizeRunResultStatuses};export{_testOnlyTestCommand,classifyLinkedTestCommandSafety,classifyLinkedTestFailure,countFailureCategories,extractReferencedPmItemIdsFromCommand,resolveLinkedTestFailureExitCode,runLinkedTests,runTest,summarizeContextPreflight};
4
+ `:"",executionResult={stdout:`${stdout.text}${truncationNotice}`,stderr:stderr.text,exitCode:code,signal,timedOut,maxBufferExceeded:!1,outputTruncated,spawnError};return endLinkedTestProgress(progressContext,executionResult,startedAt,progressMode),executionResult}finally{await rm(captureRoot,{recursive:!0,force:!0})}}function formatLinkedTestExecutionError(result,timeoutMs){const details=[];result.maxBufferExceeded&&details.push(`Linked test output exceeded maxBuffer=${TEST_OUTPUT_MAX_BUFFER_BYTES} bytes. Reduce output volume or split the command.`),result.timedOut&&timeoutMs>0&&details.push(`Linked test timed out after ${timeoutMs}ms.`);const signalMessage=result.signal?`Linked test command terminated by signal ${result.signal}.`:void 0,baseMessage=result.spawnError?.trim()||signalMessage||"Linked test command failed.";return details.length===0?baseMessage:`${baseMessage} ${details.join(" ")}`}function hasInfraCollisionSignal(result){const combined=[result.spawnError??"",result.stderr,result.stdout].join(`
5
+ `);return LINKED_TEST_INFRA_COLLISION_PATTERNS.some(pattern=>pattern.test(combined))||combined.split(/\r?\n/u).some(line=>LINKED_TEST_LOCK_ACQUISITION_PATTERN.test(line)&&LINKED_TEST_LOCK_CONTENTION_CONTEXT_PATTERN.test(line))}function classifyLinkedTestFailure(result){return hasInfraCollisionSignal(result)?"infra_collision":result.timedOut?"timeout":result.maxBufferExceeded?"max_buffer":result.spawnError?"spawn_error":result.signal?"signal":"assertion_failure"}function createEmptyFailureCategoryCounts(){return{infra_collision:0,trust_refusal:0,assertion_failure:0,empty_run:0,timeout:0,max_buffer:0,spawn_error:0,signal:0}}function countFailureCategories(runResults){const counts=createEmptyFailureCategoryCounts();for(const result of runResults)result.status!=="failed"||!result.failure_category||(counts[result.failure_category]+=1);return counts}function applyEnvDirectiveStage(env,directives){for(const[key,value]of Object.entries(directives.env_set))LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())||(env[key]=value);for(const key of directives.env_clear)LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())||delete env[key]}function applySharedHostSafeDefaults(env){env.PORT===void 0&&(env.PORT="0"),env.HOST===void 0&&(env.HOST="127.0.0.1"),env.PM_SHARED_HOST_SAFE===void 0&&(env.PM_SHARED_HOST_SAFE="1"),env.PLAYWRIGHT_HTML_OPEN===void 0&&(env.PLAYWRIGHT_HTML_OPEN="never"),env.PW_TEST_HTML_REPORT_OPEN===void 0&&(env.PW_TEST_HTML_REPORT_OPEN="never")}function resolveEffectiveLinkedTestDirectives(runtimeDirectives,linkedTest){const envSet={...runtimeDirectives.env_set,...linkedTest.env_set},envClear=[...new Set([...runtimeDirectives.env_clear,...linkedTest.env_clear??[]])],sharedHostSafe=linkedTest.shared_host_safe??runtimeDirectives.shared_host_safe;return{env_set:envSet,env_clear:envClear,shared_host_safe:sharedHostSafe}}function resolveRuntimeDirectives(envSetEntries,envClearEntries,sharedHostSafe){return{env_set:mergeEnvSetDirectives(envSetEntries,"--env-set"),env_clear:mergeEnvClearDirectives(envClearEntries,"--env-clear"),shared_host_safe:sharedHostSafe===!0}}async function copyIntoSandboxIfPresent(sourcePath,targetPath,recursive=!1,makeDirectory=mkdir){if(await pathExists(sourcePath))try{await withHostEnvironmentBoundary("seed_linked_test",async()=>{if(await makeDirectory(path.dirname(targetPath),{recursive:!0}),recursive){await cp(sourcePath,targetPath,{recursive:!0,force:!0});return}await cp(sourcePath,targetPath,{force:!0})},{why:"Linked tests need an isolated PM context without mutating the source tracker.",nextSteps:["Reclaim capacity on the filesystem that hosts the linked-test temporary directory."]})}catch(error){if(typeof error=="object"&&error!==null&&"code"in error&&isFileMissingError(error))return;throw error}}async function seedLinkedTestSandbox(sandboxPmPath,sandboxGlobalPath,sourceRoots){await copyIntoSandboxIfPresent(getSettingsPath(sourceRoots.projectPmRoot),getSettingsPath(sandboxPmPath)),await copyIntoSandboxIfPresent(path.join(sourceRoots.projectPmRoot,"extensions"),path.join(sandboxPmPath,"extensions"),!0),await copyIntoSandboxIfPresent(getSettingsPath(sourceRoots.globalPmRoot),getSettingsPath(sandboxGlobalPath)),await copyIntoSandboxIfPresent(path.join(sourceRoots.globalPmRoot,"extensions"),path.join(sandboxGlobalPath,"extensions"),!0)}async function seedLinkedTestTrackerData(sourceRoot,sandboxRoot){if(!await pathExists(sourceRoot))return;const entries=await readdir(sourceRoot,{withFileTypes:!0});for(const entry of entries){if(LINKED_TEST_TRACKER_DIRS_TO_SKIP.has(entry.name))continue;const sourcePath=path.join(sourceRoot,entry.name),targetPath=path.join(sandboxRoot,entry.name);if(entry.isDirectory()){await copyIntoSandboxIfPresent(sourcePath,targetPath,!0);continue}entry.isFile()&&await copyIntoSandboxIfPresent(sourcePath,targetPath)}}async function seedMissingLinkedTestSettingsHistory(sourceRoot,sandboxRoot){const sourceSettingsRaw=await readFileIfExists(getSettingsPath(sourceRoot));if(sourceSettingsRaw===null||await pathExists(getWorkspaceHistoryPath(sourceRoot)))return;const sandboxSettings=await readSettings(sandboxRoot);await rm(getWorkspaceHistoryPath(sandboxRoot),{force:!0}),await rm(getSettingsPath(sandboxRoot),{force:!0}),await writeWorkspaceJsonWithHistory({pmRoot:sandboxRoot,filePath:getSettingsPath(sandboxRoot),raw:sourceSettingsRaw,op:"settings:write",author:resolveAuthor(void 0,sandboxSettings.author_default),lockTtlSeconds:sandboxSettings.locks.ttl_seconds,lockWaitMs:sandboxSettings.locks.wait_ms,recordCreation:!0,message:"Seed linked-test tracker settings history"})}async function countLinkedTestItemFiles(pmRoot){if(!await pathExists(pmRoot))return 0;let total=0;const entries=await readdir(pmRoot,{withFileTypes:!0});for(const entry of entries){if(!entry.isDirectory()||LINKED_TEST_ITEM_COUNT_DIRS_TO_SKIP.has(entry.name))continue;const folderPath=path.join(pmRoot,entry.name);let files;try{files=await readdir(folderPath,{withFileTypes:!0})}catch{continue}for(const file of files)file.isFile()&&ITEM_FILE_EXTENSIONS.some(extension=>file.name.toLowerCase().endsWith(extension))&&(total+=1)}return total}function resolveLinkedTestFailureExitCode(execution){const rawExitCode=typeof execution.exitCode=="number"?execution.exitCode:1;return(execution.timedOut||execution.maxBufferExceeded)&&rawExitCode===0?1:rawExitCode}function parseAssertionLiteral(raw){const trimmed=raw.trim();if(trimmed==="true")return!0;if(trimmed==="false")return!1;if(trimmed==="null")return null;const numeric=Number(trimmed);if(trimmed.length>0&&Number.isFinite(numeric))return numeric;if(trimmed.startsWith("{")&&trimmed.endsWith("}")||trimmed.startsWith("[")&&trimmed.endsWith("]"))try{return JSON.parse(trimmed)}catch{}return trimmed}function compareAssertionValues(actual,expected){return typeof actual=="object"&&actual!==null&&typeof expected=="object"&&expected!==null?stableValueEquals(actual,expected):Object.is(actual,expected)}function evaluateLinkedTestAssertions(linkedTest,stdout,stderr){const failures=[];failures.push(...evaluateContainsAssertions("stdout",stdout,linkedTest.assert_stdout_contains)),failures.push(...evaluateRegexAssertions("stdout",stdout,linkedTest.assert_stdout_regex)),failures.push(...evaluateContainsAssertions("stderr",stderr,linkedTest.assert_stderr_contains)),failures.push(...evaluateRegexAssertions("stderr",stderr,linkedTest.assert_stderr_regex)),failures.push(...evaluateStdoutLineCountAssertion(stdout,linkedTest.assert_stdout_min_lines));const jsonEqualsAssertions=linkedTest.assert_json_field_equals??{},jsonGteAssertions=linkedTest.assert_json_field_gte??{};if(!(Object.keys(jsonEqualsAssertions).length>0||Object.keys(jsonGteAssertions).length>0))return failures;let parsedJson;try{parsedJson=JSON.parse(stdout)}catch(error){return failures.push(`stdout is not valid JSON for assert_json_field_* checks: ${error instanceof Error?error.message:String(error)}`),failures}for(const[fieldPath,expectedRaw]of Object.entries(jsonEqualsAssertions)){const resolved=readJsonPathValue(parsedJson,fieldPath);if(!resolved.found){failures.push(`assert_json_field_equals missing path "${fieldPath}"`);continue}const expected=parseAssertionLiteral(expectedRaw);compareAssertionValues(resolved.value,expected)||failures.push(`assert_json_field_equals mismatch at "${fieldPath}" (expected=${JSON.stringify(expected)} actual=${JSON.stringify(resolved.value)})`)}for(const[fieldPath,expectedMinimum]of Object.entries(jsonGteAssertions)){const resolved=readJsonPathValue(parsedJson,fieldPath);if(!resolved.found){failures.push(`assert_json_field_gte missing path "${fieldPath}"`);continue}if(typeof resolved.value!="number"||!Number.isFinite(resolved.value)){failures.push(`assert_json_field_gte path "${fieldPath}" resolved to non-numeric value`);continue}resolved.value<expectedMinimum&&failures.push(`assert_json_field_gte failed at "${fieldPath}" (expected >= ${expectedMinimum}, actual ${resolved.value})`)}return failures}function evaluateContainsAssertions(streamName,output,expectedValues){const failures=[];for(const expected of expectedValues??[])output.includes(expected)||failures.push(`${streamName} missing required text: "${expected}"`);return failures}function evaluateRegexAssertions(streamName,output,patterns){const failures=[];for(const pattern of patterns??[])try{new RegExp(pattern,"m").test(output)||failures.push(`${streamName} failed regex assertion: /${pattern}/m`)}catch(error){failures.push(`${streamName} regex assertion is invalid: /${pattern}/ (${error instanceof Error?error.message:String(error)})`)}return failures}function evaluateStdoutLineCountAssertion(stdout,minimum){if(typeof minimum!="number")return[];const lineCount=stdout.split(/\r?\n/).map(line=>line.trim()).filter(line=>line.length>0).length;return lineCount<minimum?[`stdout line count ${lineCount} is below required minimum ${minimum}`]:[]}const EMPTY_LINKED_TEST_RUN_PATTERNS=[{code:"no_projects_matched_filters",regex:/\bNo projects matched the filters\b/i},{code:"no_test_files_found",regex:/\bNo test files found\b/i},{code:"no_tests_found",regex:/\bNo tests found\b/i},{code:"no_matching_tests",regex:/\bNo matching tests?\b/i},{code:"collected_zero_items",regex:/\bcollected 0 items?\b/i},{code:"reported_zero_passes",regex:/(?:^\s*(?:#|ℹ)?\s*tests\s+0\s*$[\s\S]*^\s*(?:#|ℹ)?\s*pass\s+0\s*$|^\s*(?:#|ℹ)?\s*pass\s+0\s*$[\s\S]*^\s*(?:#|ℹ)?\s*tests\s+0\s*$)/imu},{code:"reported_zero_tests",regex:/^\s*(?:#|ℹ)?\s*tests\s+0\s*$/imu}],POSITIVE_LINKED_TEST_RUN_PATTERNS=[/^\s*(?:#|ℹ)?\s*tests\s+[1-9]\d*\s*$/imu,/^\s*(?:#|ℹ)?\s*pass\s+[1-9]\d*\s*$/imu,/\bTests?\s+[1-9]\d*\s+passed\b/iu,/\b[1-9]\d*\s+passed\b/iu,/\bTests:\s+(?:.*\b)?[1-9]\d*\s+passed\b/iu];function detectEmptyLinkedTestRun(stdout,stderr){const combined=`${stdout}
6
+ ${stderr}`;for(const pattern of EMPTY_LINKED_TEST_RUN_PATTERNS)if(pattern.regex.test(combined))return{code:pattern.code};return null}function hasPositiveLinkedTestRunReceipt(stdout,stderr){const combined=`${stdout}
7
+ ${stderr}`;return POSITIVE_LINKED_TEST_RUN_PATTERNS.some(pattern=>pattern.test(combined))}function commandUsesTestNameFilter(command){const normalized=normalizeCommandForValidation(command);return/(?:^|\s)(?:--test-name-pattern|--testnamepattern)(?:=|\s)/u.test(normalized)?!0:splitNormalizedCommandSegments(normalized).some(segment=>/(?:^|\s)-t(?:=|\s)/u.test(segment)&&segmentInvokesDirectTestRunner(segment))}function createLinkedTestSandboxLayout(sandboxRoot){return{root:sandboxRoot,schemaProjectPmPath:path.join(sandboxRoot,"schema","project",".agents","pm"),schemaGlobalPmPath:path.join(sandboxRoot,"schema","global"),trackerProjectPmPath:path.join(sandboxRoot,"tracker","project",".agents","pm"),trackerGlobalPmPath:path.join(sandboxRoot,"tracker","global"),workspaceSnapshotRoot:path.join(sandboxRoot,"workspace","project"),workspaceIsolatedRoot:path.join(sandboxRoot,"workspace","isolated")}}function linkedTestsRequireWorkspaceSnapshot(tests,runLevelMode,overrideLinkedMode){return tests.some(linkedTest=>resolveLinkedTestWorkspaceContextMode(linkedTest,runLevelMode,overrideLinkedMode)==="snapshot")}async function bindSnapshotTracker(snapshotRoot,sandboxPmPath){const agentsRoot=path.join(snapshotRoot,".agents"),target=path.join(agentsRoot,"pm");await mkdir(agentsRoot,{recursive:!0}),await rm(target,{recursive:!0,force:!0}),await symlink(sandboxPmPath,target,process.platform==="win32"?"junction":"dir")}async function initializeLinkedTestSandboxes(layout,initialize=runInit,includeTrackerData=!0){const initOptions={defaults:!0,agentGuidance:"skip"};await initialize(void 0,{path:layout.schemaProjectPmPath},initOptions),await initialize(void 0,{path:layout.schemaGlobalPmPath},initOptions),includeTrackerData&&(await initialize(void 0,{path:layout.trackerProjectPmPath},initOptions),await initialize(void 0,{path:layout.trackerGlobalPmPath},initOptions))}async function seedLinkedTestSandboxesFromSource(layout,sourceRoots,includeTrackerData){sourceRoots&&(await seedLinkedTestSandbox(layout.schemaProjectPmPath,layout.schemaGlobalPmPath,sourceRoots),includeTrackerData&&(await seedLinkedTestSandbox(layout.trackerProjectPmPath,layout.trackerGlobalPmPath,sourceRoots),await seedLinkedTestTrackerData(sourceRoots.projectPmRoot,layout.trackerProjectPmPath),await seedLinkedTestTrackerData(sourceRoots.globalPmRoot,layout.trackerGlobalPmPath),await seedMissingLinkedTestSettingsHistory(sourceRoots.projectPmRoot,layout.trackerProjectPmPath),await seedMissingLinkedTestSettingsHistory(sourceRoots.globalPmRoot,layout.trackerGlobalPmPath)))}function linkedTestsRequireTrackerData(tests,runLevelPmContextMode,options){return tests.some(linkedTest=>{const command=linkedTest.command??"",isPmTrackerReadCommand=command.length>0&&commandInvokesPmTrackerReadCommand(command),requestedPmContextMode=options?.autoPmContext===!0&&isPmTrackerReadCommand?"auto":resolveLinkedTestRequestedContextMode(linkedTest,runLevelPmContextMode,options?.overrideLinkedPmContext===!0);return resolveLinkedTestEffectiveContextMode(requestedPmContextMode,isPmTrackerReadCommand)==="tracker"})}async function countLinkedTestSandboxItems(layout,sourceRoots){return{sourceProjectItemCount:sourceRoots?await countLinkedTestItemFiles(sourceRoots.projectPmRoot):0,sourceGlobalItemCount:sourceRoots?await countLinkedTestItemFiles(sourceRoots.globalPmRoot):0,schemaProjectItemCount:await countLinkedTestItemFiles(layout.schemaProjectPmPath),schemaGlobalItemCount:await countLinkedTestItemFiles(layout.schemaGlobalPmPath),trackerProjectItemCount:await countLinkedTestItemFiles(layout.trackerProjectPmPath),trackerGlobalItemCount:await countLinkedTestItemFiles(layout.trackerGlobalPmPath)}}function buildLinkedTestExecutionContext(params){const trackerMode=params.effectivePmContextMode==="tracker",selectedSandboxProjectPmPath=trackerMode?params.layout.trackerProjectPmPath:params.layout.schemaProjectPmPath,selectedSandboxGlobalPmPath=trackerMode?params.layout.trackerGlobalPmPath:params.layout.schemaGlobalPmPath,selectedSandboxProjectItemCount=trackerMode?params.counts.trackerProjectItemCount:params.counts.schemaProjectItemCount,selectedSandboxGlobalItemCount=trackerMode?params.counts.trackerGlobalItemCount:params.counts.schemaGlobalItemCount,workingDirectory=params.workspaceContextMode==="snapshot"?params.layout.workspaceSnapshotRoot:params.workspaceContextMode==="isolated"?params.layout.workspaceIsolatedRoot:params.sourceWorkspaceRoot,exposedSourceWorkspaceRoot=params.workspaceContextMode==="isolated"?"":workingDirectory;return{requested_pm_context_mode:params.requestedPmContextMode,pm_context_mode:params.effectivePmContextMode,auto_pm_context_applied:params.autoPmContextApplied,is_pm_command:params.isPmCommand,is_pm_tracker_read_command:params.isPmTrackerReadCommand,source_project_pm_path:params.sourceRoots?.projectPmRoot??"",sandbox_project_pm_path:selectedSandboxProjectPmPath,source_global_pm_path:params.sourceRoots?.globalPmRoot??"",sandbox_global_pm_path:selectedSandboxGlobalPmPath,source_project_item_count:params.counts.sourceProjectItemCount,sandbox_project_item_count:selectedSandboxProjectItemCount,source_global_item_count:params.counts.sourceGlobalItemCount,sandbox_global_item_count:selectedSandboxGlobalItemCount,mismatch_detected:params.isPmCommand&&(params.counts.sourceProjectItemCount!==selectedSandboxProjectItemCount||params.counts.sourceGlobalItemCount!==selectedSandboxGlobalItemCount),project_extensions_seeded:!!params.sourceRoots,global_extensions_seeded:!!params.sourceRoots,requested_workspace_context_mode:params.requestedWorkspaceContextMode,workspace_context_mode:params.workspaceContextMode,working_directory:workingDirectory,source_workspace_root:exposedSourceWorkspaceRoot,trust:params.trust}}async function resolveLinkedTestCommandContext(params){const linkedOverridePmContextMode=typeof params.linkedTest.pm_context_mode=="string"&&params.linkedTest.pm_context_mode.trim().length>0?parsePmContextMode(params.linkedTest.pm_context_mode):void 0,command=typeof params.linkedTest.command=="string"&&params.linkedTest.command.length>0?params.linkedTest.command:void 0,isPmCommand=command?commandInvokesPmCli(command):!1,isPmTrackerReadCommand=isPmCommand&&command?commandInvokesPmTrackerReadCommand(command):!1,autoPmContextApplied=params.options?.autoPmContext===!0&&isPmTrackerReadCommand,requestedPmContextMode=autoPmContextApplied?"auto":resolveLinkedTestRequestedContextMode(params.linkedTest,params.runLevelPmContextMode,params.options?.overrideLinkedPmContext===!0),effectivePmContextMode=resolveLinkedTestEffectiveContextMode(requestedPmContextMode,isPmTrackerReadCommand),selectedSandboxProjectPmPath=effectivePmContextMode==="tracker"?params.layout.trackerProjectPmPath:params.layout.schemaProjectPmPath;params.workspaceContextMode==="snapshot"&&await bindSnapshotTracker(params.layout.workspaceSnapshotRoot,selectedSandboxProjectPmPath);const trust=params.options?.pmRoot?await resolveLinkedTestTrust(params.options.pmRoot,params.linkedTest,params.currentSourceRef):await resolveLinkedTestTrust(params.layout.root,params.linkedTest,params.currentSourceRef);return{linkedOverridePmContextMode,executionContext:buildLinkedTestExecutionContext({layout:params.layout,counts:params.counts,sourceRoots:params.sourceRoots,isPmCommand,isPmTrackerReadCommand,requestedPmContextMode,effectivePmContextMode,autoPmContextApplied,requestedWorkspaceContextMode:params.requestedWorkspaceContextMode,workspaceContextMode:params.workspaceContextMode,sourceWorkspaceRoot:params.sourceWorkspaceRoot,trust})}}function buildLinkedTestSkippedResult(linkedTest,executionContext,error){return{command:linkedTest.command,path:linkedTest.path,status:"skipped",execution_context:executionContext,error}}function buildLinkedTestAssertionFailureResult(linkedTest,executionContext,error,output){return{command:linkedTest.command,path:linkedTest.path,status:"failed",exit_code:1,failure_category:"assertion_failure",execution_context:executionContext,...output?{stdout:output.stdout,stderr:output.stderr}:{},error}}function buildLinkedTestTrustRefusalResult(linkedTest,executionContext,error){return{command:linkedTest.command,path:linkedTest.path,status:"failed",exit_code:1,failure_category:"trust_refusal",execution_context:executionContext,error}}function resolveLinkedTestTrustPreflightResult(params){if(params.executionContext.trust.trusted)return null;const overrideRequested=params.options?.allowUntrustedLinkedTests===!0,policyEnabled=params.options?.untrustedLinkedTestsPolicyEnabled===!0;if(overrideRequested&&policyEnabled)return null;const recovery=policyEnabled?"Retry with --allow-untrusted-linked-tests for this invocation, or acknowledge the current commands with --acknowledge-linked-tests.":"Set testing.allow_untrusted_linked_tests=true, then retry with --allow-untrusted-linked-tests; alternatively acknowledge the current commands with --acknowledge-linked-tests.";return buildLinkedTestTrustRefusalResult(params.linkedTest,params.executionContext,`Linked test command is not trusted by this clone (source_ref=${params.executionContext.trust.source_ref??"unknown"}, current_ref=${params.executionContext.trust.current_source_ref??"unknown"}). ${recovery}`)}function resolveLinkedTestSafetyPreflightResult(params){if(!params.linkedTest.command)return buildLinkedTestSkippedResult(params.linkedTest,params.executionContext,"No command configured for this linked test.");const runtimeSafetySkipReason=getRuntimeSafetySkipReason(params.linkedTest.command);return runtimeSafetySkipReason?buildLinkedTestSkippedResult(params.linkedTest,params.executionContext,runtimeSafetySkipReason):null}function resolveUnboundPmContextFailure(params){return params.executionContext.pm_context_mode!=="none"?null:params.executionContext.workspace_context_mode==="source"?buildLinkedTestAssertionFailureResult(params.linkedTest,params.executionContext,"pm_context_mode=none requires workspace_context_mode=isolated or snapshot so implicit tracker discovery cannot reach the source workspace."):params.executionContext.is_pm_command?buildLinkedTestAssertionFailureResult(params.linkedTest,params.executionContext,"pm_context_mode=none is for self-isolating SDK tests; direct PM commands require schema, tracker, or auto context."):null}function resolvePmContextMismatchFailure(params){const failOnMismatchByDefault=params.executionContext.pm_context_mode==="schema"&&params.executionContext.is_pm_tracker_read_command&&params.executionContext.mismatch_detected,failOnMismatchByFlag=params.options?.failOnContextMismatch===!0&&params.executionContext.is_pm_command&&params.executionContext.mismatch_detected;if(!failOnMismatchByDefault&&!failOnMismatchByFlag)return null;const mismatchHint=buildPmContextMismatchHint({executionContext:params.executionContext,runLevelPmContextMode:params.runLevelPmContextMode,linkedOverridePmContextMode:params.linkedOverridePmContextMode}),mismatchPrefix=params.options?.checkContext===!0?"Linked test preflight PM context mismatch detected":"Linked test PM context mismatch detected";return buildLinkedTestAssertionFailureResult(params.linkedTest,params.executionContext,`${mismatchPrefix} (source_project_items=${params.executionContext.source_project_item_count}, sandbox_project_items=${params.executionContext.sandbox_project_item_count}).${mismatchHint}`)}function resolveLinkedTestPreflightResult(params){return resolveLinkedTestSafetyPreflightResult(params)||resolveLinkedTestTrustPreflightResult(params)||resolveUnboundPmContextFailure(params)||resolvePmContextMismatchFailure(params)||(params.options?.requireAssertionsForPm===!0&&params.executionContext.is_pm_command&&!hasLinkedTestAssertions(params.linkedTest)?buildLinkedTestAssertionFailureResult(params.linkedTest,params.executionContext,"Linked PM command requires assertions when --require-assertions-for-pm is enabled."):null)}function buildLinkedTestExecutionEnv(params){const effectiveDirectives=resolveEffectiveLinkedTestDirectives(params.runtimeDirectives,params.linkedTest),executionEnv={...process.env,SENTRY_ENVIRONMENT:"test"};return applyEnvDirectiveStage(executionEnv,params.runtimeDirectives),applyEnvDirectiveStage(executionEnv,{env_set:params.linkedTest.env_set??{},env_clear:params.linkedTest.env_clear??[]}),effectiveDirectives.shared_host_safe&&applySharedHostSafeDefaults(executionEnv),executionEnv.FORCE_COLOR="0",params.executionContext.pm_context_mode==="none"?delete executionEnv.PM_PATH:executionEnv.PM_PATH=params.executionContext.sandbox_project_pm_path,executionEnv.PM_GLOBAL_PATH=params.executionContext.sandbox_global_pm_path,params.executionContext.workspace_context_mode==="isolated"?(delete executionEnv.PM_SOURCE_WORKSPACE_ROOT,delete executionEnv.PM_SOURCE_PM_PATH,delete executionEnv[SOURCE_CONTEXT_ACCESS_ENV]):(executionEnv.PM_SOURCE_WORKSPACE_ROOT=params.executionContext.source_workspace_root,executionEnv.PM_SOURCE_PM_PATH=params.executionContext.workspace_context_mode==="snapshot"?params.executionContext.sandbox_project_pm_path:params.executionContext.source_project_pm_path,executionEnv[SOURCE_CONTEXT_ACCESS_ENV]="read_only"),executionEnv}function buildLinkedTestPassedResult(linkedTest,executionContext,execution){return{command:linkedTest.command,path:linkedTest.path,status:"passed",exit_code:0,execution_context:executionContext,stdout:execution.stdout,stderr:execution.stderr}}function buildLinkedTestEmptyRunResult(params){return{command:params.linkedTest.command,path:params.linkedTest.path,status:"failed",exit_code:1,failure_category:"empty_run",execution_context:params.executionContext,stdout:params.execution.stdout,stderr:params.execution.stderr,error:`Linked test reported an empty test run (${params.emptyRunSignal.code}). Update the test selection so at least one test executes; unfiltered commands may opt out by omitting --fail-on-empty-test-run.`}}function buildLinkedTestCommandFailureResult(params){return{command:params.linkedTest.command,path:params.linkedTest.path,status:"failed",exit_code:resolveLinkedTestFailureExitCode(params.execution),failure_category:classifyLinkedTestFailure(params.execution),execution_context:params.executionContext,stdout:params.execution.stdout,stderr:params.execution.stderr,error:formatLinkedTestExecutionError(params.execution,params.timeoutMs)}}function buildLinkedTestPassedExecutionResult(params){if(params.options?.failOnEmptyTestRun===!0||commandUsesTestNameFilter(params.linkedTest.command??"")){const emptyRunSignal=detectEmptyLinkedTestRun(params.execution.stdout,params.execution.stderr);if(emptyRunSignal)return buildLinkedTestEmptyRunResult({...params,emptyRunSignal});if(commandUsesTestNameFilter(params.linkedTest.command??"")&&!hasPositiveLinkedTestRunReceipt(params.execution.stdout,params.execution.stderr))return buildLinkedTestEmptyRunResult({...params,emptyRunSignal:{code:"missing_positive_execution_receipt"}})}const assertionFailures=evaluateLinkedTestAssertions(params.linkedTest,params.execution.stdout,params.execution.stderr);return assertionFailures.length>0?buildLinkedTestAssertionFailureResult(params.linkedTest,params.executionContext,`Linked test assertion(s) failed: ${assertionFailures.join("; ")}`,params.execution):buildLinkedTestPassedResult(params.linkedTest,params.executionContext,params.execution)}async function runSingleLinkedTest(params){const command=params.linkedTest.command??"",timeoutMs=(params.linkedTest.timeout_seconds??params.defaultTimeoutSeconds??120)*1e3,execution=await runLinkedTestCommand(command,timeoutMs,buildLinkedTestExecutionEnv(params),{index:params.index+1,total:params.total,timeoutMs,command},params.progressMode,params.executionContext.working_directory);return execution.exitCode===0&&!execution.timedOut&&!execution.maxBufferExceeded?buildLinkedTestPassedExecutionResult({...params,execution}):buildLinkedTestCommandFailureResult({...params,execution,timeoutMs})}async function runLinkedTests(tests,defaultTimeoutSeconds,options){const results=[],sandboxRoot=await mkdtemp(path.join(tmpdir(),"pm-linked-test-")),layout=createLinkedTestSandboxLayout(sandboxRoot),runLevelPmContextMode=parsePmContextMode(options?.pmContext),runLevelWorkspaceContextMode=parseWorkspaceContextMode(options?.workspaceContext),progressMode=options?.progress===!0?"always":"auto",runtimeDirectives=resolveRuntimeDirectives(options?.envSet,options?.envClear,options?.sharedHostSafe),sourceRoots=options?.sourceRoots,sourceWorkspaceRoot=resolveLinkedTestSourceWorkspaceRoot(),includeTrackerData=linkedTestsRequireTrackerData(tests,runLevelPmContextMode,options),includeWorkspaceSnapshot=linkedTestsRequireWorkspaceSnapshot(tests,runLevelWorkspaceContextMode,options?.overrideLinkedWorkspaceContext===!0),currentSourceRef=await resolveLinkedTestSourceRef(sourceWorkspaceRoot);try{await initializeLinkedTestSandboxes(layout,runInit,includeTrackerData),await mkdir(layout.workspaceIsolatedRoot,{recursive:!0}),await seedLinkedTestSandboxesFromSource(layout,sourceRoots,includeTrackerData),includeWorkspaceSnapshot&&await seedLinkedTestWorkspaceSnapshot(sourceWorkspaceRoot,layout.workspaceSnapshotRoot);const counts=await countLinkedTestSandboxItems(layout,sourceRoots);for(let index=0;index<tests.length;index+=1){const linkedTest=tests[index],workspaceContextMode=resolveLinkedTestWorkspaceContextMode(linkedTest,runLevelWorkspaceContextMode,options?.overrideLinkedWorkspaceContext===!0),commandContext=await resolveLinkedTestCommandContext({linkedTest,layout,counts,sourceRoots,runLevelPmContextMode,options,requestedWorkspaceContextMode:runLevelWorkspaceContextMode,workspaceContextMode,currentSourceRef,sourceWorkspaceRoot}),preflightResult=resolveLinkedTestPreflightResult({linkedTest,executionContext:commandContext.executionContext,runLevelPmContextMode,linkedOverridePmContextMode:commandContext.linkedOverridePmContextMode,options});if(preflightResult){results.push(preflightResult);continue}results.push(await runSingleLinkedTest({linkedTest,index,total:tests.length,defaultTimeoutSeconds,runtimeDirectives,progressMode,executionContext:commandContext.executionContext,options}))}}finally{await rm(layout.root,{recursive:!0,force:!0,maxRetries:3,retryDelay:100})}return results}async function readLinkedTestItem(params){const{id,pmRoot,settings,typeToFolder}=params,located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeToFolder);if(!located)throw new PmCliError(`Item ${id} not found`,EXIT_CODE.NOT_FOUND);const loaded=await readLocatedItem(located,{schema:settings.schema});return{itemId:located.id,tests:loaded.document.metadata.tests??[],testRuns:loaded.document.metadata.test_runs??[],changed:!1,removed:0}}function linkedTestsHaveSameIdentity(left,right){return left.command===right.command&&left.path===right.path&&left.scope===right.scope&&left.pm_context_mode===right.pm_context_mode&&left.workspace_context_mode===right.workspace_context_mode}function appendMissingLinkedTests(current,additions){const next=[...current];for(const addition of additions)next.some(entry=>linkedTestsHaveSameIdentity(entry,addition))||next.push(addition);return next}function removeLinkedTestsBySelector(current,removals,removeIndexes){if(removals.length===0&&removeIndexes.length===0)return{tests:current,removed:0};const indexSet=new Set(removeIndexes),tests=current.filter((entry,index)=>indexSet.has(index+1)?!1:!removals.some(selector=>selector.kind==="command"?entry.command===selector.value:selector.kind==="path"?entry.path===selector.value:entry.command===selector.value||entry.path===selector.value));return{tests,removed:current.length-tests.length}}function applyLinkedTestMutations(previous,adds,removes,removeIndexes){return removeLinkedTestsBySelector(appendMissingLinkedTests(previous,adds),removes,removeIndexes)}function hasTestRuntimeDirectiveFlags(options){return[(options.envSet?.length??0)>0,(options.envClear?.length??0)>0,options.sharedHostSafe===!0,options.pmContext!==void 0,options.overrideLinkedPmContext===!0,options.failOnContextMismatch===!0,options.failOnSkipped===!0,options.failOnEmptyTestRun===!0,options.requireAssertionsForPm===!0,options.checkContext===!0,options.autoPmContext===!0,options.workspaceContext!==void 0,options.overrideLinkedWorkspaceContext===!0,options.allowUntrustedLinkedTests===!0].some(Boolean)}function assertTestRunFlagUsage(options){if(hasTestRuntimeDirectiveFlags(options)&&options.run!==!0)throw new PmCliError("--env-set, --env-clear, --shared-host-safe, --pm-context, --override-linked-pm-context, --workspace-context, --override-linked-workspace-context, --allow-untrusted-linked-tests, --fail-on-context-mismatch, --fail-on-skipped, --fail-on-empty-test-run, --require-assertions-for-pm, --check-context, and --auto-pm-context require --run",EXIT_CODE.USAGE);if(options.acknowledgeLinkedTests===!0&&options.run===!0)throw new PmCliError("--acknowledge-linked-tests records trust without executing commands; run it separately before --run",EXIT_CODE.USAGE);if((options.match!==void 0||options.onlyIndex!==void 0||options.onlyLast===!0)&&options.run!==!0)throw new PmCliError("--match, --only-index, and --only-last require --run",EXIT_CODE.USAGE)}async function resolveLinkedTestItem(params){const{id,options,pmRoot,settings,typeToFolder,adds,removes,removeIndexes}=params;if(adds.length===0&&removes.length===0&&removeIndexes.length===0)return readLinkedTestItem({id,pmRoot,settings,typeToFolder});let removed=0;const result=await mutateItem({pmRoot,settings,id,op:adds.length>0?"tests_add":"tests_remove",author:resolveAuthor(options.author,settings.author_default),message:options.message,force:options.force,skipNoop:!0,mutate(document){const previous=document.metadata.tests??[],mutation=applyLinkedTestMutations(previous,adds,removes,removeIndexes);if(removed=mutation.removed,(removes.length>0||removeIndexes.length>0)&&removed===0)throw new PmCliError("No linked tests matched the requested removal selector",EXIT_CODE.NOT_FOUND,{code:"linked_test_remove_no_match",unmatched:[...removes.map(entry=>`${entry.kind}=${entry.value}`),...removeIndexes.map(index=>`index=${index}`)],required:"List linked tests and retry with an exact command/path or a current 1-based --remove-index.",examples:[`pm test ${id} --list`,`pm test ${id} --remove-index 1`]});return document.metadata.tests=mutation.tests,{changedFields:stableValueEquals(previous,mutation.tests)?[]:["tests"]}}});return{itemId:result.item.id,tests:result.item.tests??[],testRuns:result.item.test_runs??[],changed:result.changedFields.length>0,removed}}function resolveTestRunOptions(options,tests){assertTestRunFlagUsage(options);const selectorInput={match:options.match,onlyIndex:options.onlyIndex===void 0?void 0:parseOnlyIndexValue(options.onlyIndex),onlyLast:options.onlyLast},runSelection=options.run===!0?resolveLinkedTestRunSelection(tests,selectorInput):void 0,defaultTimeoutSeconds=options.timeout===void 0?void 0:parseOptionalNumber(options.timeout,"timeout");if(defaultTimeoutSeconds!==void 0&&defaultTimeoutSeconds<=0)throw new PmCliError("Test timeout must be a positive number",EXIT_CODE.USAGE);return{defaultTimeoutSeconds,pmContextMode:parsePmContextMode(options.pmContext),runSelection,testsToRun:runSelection?.selected??tests}}async function executeSelectedLinkedTests(params){const{options,runOptions,pmRoot}=params;return options.run!==!0?[]:await runLinkedTests(runOptions.testsToRun,runOptions.defaultTimeoutSeconds,{progress:options.progress,envSet:options.envSet,envClear:options.envClear,sharedHostSafe:options.sharedHostSafe,pmContext:runOptions.pmContextMode,overrideLinkedPmContext:options.overrideLinkedPmContext,failOnContextMismatch:options.failOnContextMismatch,failOnEmptyTestRun:options.failOnEmptyTestRun,requireAssertionsForPm:options.requireAssertionsForPm,checkContext:options.checkContext,autoPmContext:options.autoPmContext,workspaceContext:options.workspaceContext,overrideLinkedWorkspaceContext:options.overrideLinkedWorkspaceContext,pmRoot,allowUntrustedLinkedTests:options.allowUntrustedLinkedTests,untrustedLinkedTestsPolicyEnabled:params.untrustedLinkedTestsPolicyEnabled,sourceRoots:{projectPmRoot:pmRoot,globalPmRoot:resolveGlobalPmRoot(process.cwd())}})}function buildTestWarnings(options,runSelection,runResults){const warnings=[];if(runSelection&&runSelection.selector!==null&&warnings.push(`linked_test_selection:${runSelection.selector}=${runSelection.requested};selected=${runSelection.selected_count};skipped=${runSelection.skipped_count};indexes=${runSelection.selected_indexes.join(",")}`),options.run===!0&&options.checkContext===!0){const preflight=summarizeContextPreflight(runResults);warnings.push(`context_preflight:checked_pm_commands=${preflight.checked_pm_commands};tracker_read_commands=${preflight.tracker_read_commands};mismatches=${preflight.mismatches};auto_remediated=${preflight.auto_remediated}`)}return warnings}function buildTrackedTestRunSummary(params){const summary=summarizeRunResultStatuses(params.runResults),parsedAttempt=Number.parseInt(process.env.PM_BACKGROUND_TEST_RUN_ATTEMPT?.trim()??"",10),resumedFrom=process.env.PM_BACKGROUND_TEST_RUN_RESUMED_FROM?.trim(),recordedAt=nowIso(),measurements=parseTestRunMeasurements(params.options.measure,recordedAt);return{run_id:resolveTrackedRunId("test"),kind:"test",status:summary.failed>0||params.failOnSkippedTriggered?"failed":"passed",started_at:params.runStartedAt,finished_at:recordedAt,recorded_at:recordedAt,attempt:Number.isFinite(parsedAttempt)&&parsedAttempt>=1?parsedAttempt:void 0,resumed_from:resumedFrom&&resumedFrom.length>0?resumedFrom:void 0,passed:summary.passed,failed:summary.failed,skipped:summary.skipped,fail_on_skipped_triggered:params.failOnSkippedTriggered?!0:void 0,measurements:measurements.length>0?measurements:void 0,executions:params.runResults.filter(result=>result.command?.trim()).slice(0,32).map(result=>({command:result.command.trim(),requested_pm_context_mode:result.execution_context?.requested_pm_context_mode,pm_context_mode:result.execution_context?.pm_context_mode,workspace_context_mode:result.execution_context?.workspace_context_mode,trust_reason:result.execution_context?.trust.reason}))}}async function recordTestRunSummary(params){const{options,pmRoot,settings,itemId,runStartedAt,runResults,failOnSkippedTriggered,warnings}=params;if(options.run!==!0||!runStartedAt)return;const entry=buildTrackedTestRunSummary({options,runStartedAt,runResults,failOnSkippedTriggered});if(settings.testing.record_results_to_items!==!0)return{entry,receipt:{recorded:!1,reason:"tracking_disabled",run_id:entry.run_id,recovery_command:"pm config project set test-result-tracking --policy enabled"}};try{return await appendTrackedTestRunSummary({pmRoot,settings,itemId,author:resolveAuthor(options.author,settings.author_default),message:`Track test run summary (${entry.run_id})`,entry}),{entry,receipt:{recorded:!0,reason:"recorded",run_id:entry.run_id}}}catch(error){return warnings.push(`test_result_tracking_failed:${itemId}:${error instanceof Error?error.message:String(error)}`),{entry,receipt:{recorded:!1,reason:"write_failed",run_id:entry.run_id}}}}function buildTestMeasurementProjection(options,runs,recordedRun){let metricBelow;if(options.metricBelow!==void 0){const separator=options.metricBelow.indexOf("="),name=options.metricBelow.slice(0,separator).trim(),thresholdText=options.metricBelow.slice(separator+1).trim(),threshold=Number(thresholdText);if(separator<=0||name.length===0||thresholdText.length===0||!Number.isFinite(threshold))throw new PmCliError("--metric-below must use name=value",EXIT_CODE.USAGE);metricBelow=queryTestRunMeasurementsBelow(runs,name,threshold)}return{measurements:recordedRun?.measurements,metric_below:metricBelow,metric_diff:options.metricDiff===void 0?void 0:diffTestRunMeasurements(runs,options.metricDiff)}}async function maybeAcknowledgeLinkedTests(options,pmRoot,tests){if(options.acknowledgeLinkedTests===!0)return acknowledgeLinkedTests(pmRoot,tests,nowIso())}function projectTestResult(input){const{item,runResults,failureCategories,runSelection,failOnSkippedTriggered,warnings,recording,measurementProjection}=input;return{ok:runResults.every(entry=>entry.status!=="failed")&&failOnSkippedTriggered!==!0,id:item.itemId,tests:item.tests,run_results:runResults,failure_categories:failureCategories,selection:runSelection?{selector:runSelection.selector,requested:runSelection.requested,selected_indexes:runSelection.selected_indexes,selected_count:runSelection.selected_count,skipped_count:runSelection.skipped_count}:void 0,fail_on_skipped_triggered:failOnSkippedTriggered?!0:void 0,warnings:warnings.length>0?warnings:void 0,changed:item.changed||recording?.receipt.recorded===!0,...recording?{evidence_recording:recording.receipt}:{},count:item.tests.length,...item.removed>0?{removed:item.removed}:{},...measurementProjection}}async function runTest(id,options,global2){const stdinResolver=createStdinTokenResolver(),pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot);if((options.measure?.length??0)>0&&options.run!==!0)throw new PmCliError("--measure requires --run",EXIT_CODE.USAGE);parseTestRunMeasurements(options.measure,"validation"),buildTestMeasurementProjection(options,[],void 0);const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations()),resolvedAdds=await stdinResolver.resolveList(options.add,"--add"),resolvedAddJsons=await stdinResolver.resolveList(options.addJson,"--add-json"),resolvedRemoves=await stdinResolver.resolveList(options.remove,"--remove"),parsedAdds=[...parseAddEntries(resolvedAdds),...parseAddJsonEntries(resolvedAddJsons)],adds=await attachLinkedTestMutationProvenance(parsedAdds,resolveAuthor(options.author,settings.author_default),nowIso())??[],removes=parseRemoveEntries(resolvedRemoves),removeIndexes=parseRemoveIndexes(options.removeIndex),item=await resolveLinkedTestItem({id,options,pmRoot,settings,typeToFolder:typeRegistry.type_to_folder,adds,removes,removeIndexes}),runOptions=resolveTestRunOptions(options,item.tests),trustAcknowledgement=await maybeAcknowledgeLinkedTests(options,pmRoot,item.tests),runStartedAt=options.run===!0?nowIso():void 0,runResults=await executeSelectedLinkedTests({options,runOptions,pmRoot,untrustedLinkedTestsPolicyEnabled:settings.testing.allow_untrusted_linked_tests}),failureCategories=countFailureCategories(runResults),failOnSkippedTriggered=options.run===!0&&options.failOnSkipped===!0&&runResults.some(entry=>entry.status==="skipped"),warnings=buildTestWarnings(options,runOptions.runSelection,runResults);trustAcknowledgement&&warnings.push(`linked_test_trust_acknowledged:${trustAcknowledgement.acknowledged}`);const recording=await recordTestRunSummary({options,pmRoot,settings,itemId:item.itemId,runStartedAt,runResults,failOnSkippedTriggered,warnings}),runs=recording?.receipt.recorded?buildTrackedTestRunHistory([...item.testRuns,recording.entry]):item.testRuns,measurementProjection=buildTestMeasurementProjection(options,runs,recording?.entry);return projectTestResult({item,runResults,failureCategories,runSelection:runOptions.runSelection,failOnSkippedTriggered,warnings,recording,measurementProjection})}const _testOnlyTestCommand={buildLinkedTestExecutionContext,buildPmContextMismatchHint,commandInvokesPmCli,commandInvokesPmTrackerReadCommand,commandUsesTestNameFilter,copyIntoSandboxIfPresent,countLinkedTestItemFiles,ensureScope,evaluateLinkedTestAssertions,endLinkedTestProgress,extractPmInvocationArgsFromSegment,firstDirectTestRunnerSubcommand,formatLinkedTestExecutionError,hasLinkedTestAssertions,initializeLinkedTestSandboxes,linkedTestsRequireTrackerData,parseAddJsonEntries,parseLinkedTestTimeoutSeconds,parsePmContextMode,readJsonPathValue,resolveAuthor,resolveDirectRunnerSubcommand,resolveLinkedTestEffectiveContextMode,resolveLinkedTestFailureExitCode,resolveLinkedTestRequestedContextMode,resolveTestRunOptions,resolveTrackedRunId,runLinkedTestCommand,seedMissingLinkedTestSettingsHistory,seedLinkedTestSandbox,seedLinkedTestTrackerData,segmentInvokesRecursiveTestAll,splitJsonPathSegments,summarizeRunResultStatuses};export{_testOnlyTestCommand,classifyLinkedTestCommandSafety,classifyLinkedTestFailure,countFailureCategories,extractReferencedPmItemIdsFromCommand,resolveLinkedTestFailureExitCode,runLinkedTests,runTest,summarizeContextPreflight};
7
8
  //# sourceMappingURL=execution.js.map
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3570c976-1b25-501e-b51a-5ecfd1b70c15")}catch(e2){}})();function splitJsonPathSegments(fieldPath){if(!/^(?:[^.[\]]+|\[\d+\])(?:\.[^.[\]]+|\[\d+\])*$/u.test(fieldPath)){return[]}const segments=[];const tokens=fieldPath.matchAll(/[^.[\]]+|\[\d+\]/g);for(const[token]of tokens){if(token.startsWith("[")&&token.endsWith("]")){const parsedIndex=Number.parseInt(token.slice(1,-1),10);if(!Number.isSafeInteger(parsedIndex)){return[]}segments.push(parsedIndex);continue}segments.push(token)}return segments}function readJsonPathValue(root,fieldPath){const normalizedPath=fieldPath.trim();if(normalizedPath.length===0){return{found:false,value:void 0}}const segments=splitJsonPathSegments(normalizedPath);if(segments.length===0){return{found:false,value:void 0}}let current=root;for(const segment of segments){if(typeof current!=="object"||current===null){return{found:false,value:void 0}}if(typeof segment==="number"&&(!Array.isArray(current)||segment>=current.length)){return{found:false,value:void 0}}const property=Object.getOwnPropertyDescriptor(current,segment);if(!property||!Object.hasOwn(property,"value")){return{found:false,value:void 0}}current=property.value}return{found:true,value:current}}export{readJsonPathValue,splitJsonPathSegments};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="92f73d30-eac7-5c84-a7be-133323d1f549")}catch{}})();function splitJsonPathSegments(fieldPath){if(!/^(?:[^.[\]]+|\[\d+\])(?:\.[^.[\]]+|\[\d+\])*$/u.test(fieldPath))return[];const segments=[],tokens=fieldPath.matchAll(/[^.[\]]+|\[\d+\]/g);for(const[token]of tokens){if(token.startsWith("[")&&token.endsWith("]")){const parsedIndex=Number.parseInt(token.slice(1,-1),10);if(!Number.isSafeInteger(parsedIndex))return[];segments.push(parsedIndex);continue}segments.push(token)}return segments}function readJsonPathValue(root,fieldPath){const normalizedPath=fieldPath.trim();if(normalizedPath.length===0)return{found:!1,value:void 0};const segments=splitJsonPathSegments(normalizedPath);if(segments.length===0)return{found:!1,value:void 0};let current=root;for(const segment of segments){if(typeof current!="object"||current===null)return{found:!1,value:void 0};if(typeof segment=="number"&&(!Array.isArray(current)||segment>=current.length))return{found:!1,value:void 0};const property=Object.getOwnPropertyDescriptor(current,segment);if(!property||!Object.hasOwn(property,"value"))return{found:!1,value:void 0};current=property.value}return{found:!0,value:current}}export{readJsonPathValue,splitJsonPathSegments};
2
2
  //# sourceMappingURL=json-path.js.map
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e69d7d9b-9ae8-5337-9ea3-a8e40a62d3af")}catch(e2){}})();import{readFileSync}from"node:fs";import path from"node:path";const PM_SUBCOMMANDS_WITH_ITEM_REFERENCE=new Set(["get","history","restore","update","close","delete","append","claim","release","comments","notes","learnings","files","docs","deps","test"]);const PM_GLOBAL_FLAGS_WITH_VALUE=new Set(["--pm-path","--path","--author"]);const PM_ITEM_REFERENCE_FLAGS_WITH_VALUE={get:new Set(["--depth","--fields","--tree-depth","--tree_depth","--at","--format"]),history:new Set(["--limit","--field","--format"]),restore:new Set(["--message"]),update:new Set(["--title","-t","--description","-d","--body","-b","--status","-s","--close-reason","--close_reason","--priority","-p","--type","--tags","--add-tags","--add_tags","--remove-tags","--remove_tags","--deadline","--estimated-minutes","--estimate","--estimated_minutes","--acceptance-criteria","--ac","--acceptance_criteria","--definition-of-ready","--definition_of_ready","--order","--rank","--goal","--objective","--value","--impact","--outcome","--why-now","--why_now","--message","--assignee","--parent","--reviewer","--risk","--confidence","--sprint","--release","--blocked-by","--blocked_by","--blocked-reason","--blocked_reason","--unblock-note","--unblock_note","--reporter","--severity","--environment","--repro-steps","--repro_steps","--resolution","--expected-result","--expected_result","--expected","--actual-result","--actual_result","--actual","--affected-version","--affected_version","--fixed-version","--fixed_version","--component","--regression","--customer-impact","--customer_impact","--dep","--dep-remove","--dep_remove","--comment","--note","--learning","--file","--test","--doc","--reminder","--event","--type-option","--type_option","--field","--unset","--body-file"]),close:new Set(["--reason","-r","--close-reason","--duplicate-of","-d","--message","-m","--validate-close","--resolution","--expected-result","--expected_result","--expected","--actual-result","--actual_result","--actual"]),delete:new Set(["--message"]),append:new Set(["--body","--text","--message"]),claim:new Set(["--assignee","--message","--type","--tag","--priority","--assignee-filter","--parent","--sprint","--release","--max-attempts"]),release:new Set(["--assignee","--message"]),comments:new Set(["--add","--body","--comment","--file","--edit","--delete","--limit","--message"]),notes:new Set(["--add","--file","--edit","--delete","--limit","--message"]),learnings:new Set(["--add","--file","--edit","--delete","--limit","--message"]),files:new Set(["--add","--add-glob","--remove","--migrate","--note","--message"]),docs:new Set(["--add","--add-glob","--remove","--migrate","--note","--message"]),deps:new Set(["--format","--max-depth","--collapse","--node-limit","--edge-limit","--token-budget","--cursor","--direction","--kind"]),test:new Set(["--add","--add-json","--remove","--match","--only-index","--timeout","--env-set","--env-clear","--pm-context","--message"])};const NPX_FLAGS_WITH_VALUE=new Set(["-p","--package"]);const NPX_COMMAND_STRING_FLAGS=new Set(["-c","--call"]);const PNPM_GLOBAL_FLAGS_WITH_VALUE=new Set(["-c","-C","--config","--dir","--filter","--workspace-dir"]);const NPM_GLOBAL_FLAGS_WITH_VALUE=new Set(["-C","--prefix","--userconfig","--cache"]);const YARN_GLOBAL_FLAGS_WITH_VALUE=new Set(["--cwd"]);const BUN_GLOBAL_FLAGS_WITH_VALUE=new Set(["--cwd"]);const NPM_EXEC_SUBCOMMANDS=new Set(["exec","x"]);const SCRIPT_RUN_SUBCOMMANDS=new Set(["run","run-script"]);const SCRIPT_RUN_FLAGS_WITH_VALUE=new Set(["-C","--dir","--cwd","-w","--workspace","--filter"]);function splitNormalizedCommandSegments(normalizedCommand){return normalizedCommand.split(/&&|\|\||\||;/).map(segment=>segment.trim()).filter(segment=>segment.length>0)}function extractPmInvocationArgsFromSegment(segment,cwd=process.cwd()){const tokens=stripLeadingEnvAssignments(segment.split(" ").filter(token=>token.length>0));if(tokens.length===0)return null;const[executable,...args]=tokens;if(isPmExecutableToken(executable)||isPmCliScriptToken(executable,cwd)){return args}if(executable==="node"&&args[0]&&isPmCliScriptToken(args[0],cwd)){return args.slice(1)}const invocation=executable==="npx"||executable==="bunx"?parseNpxCommand(args):executable==="pnpm"?parsePnpmDlxCommand(args):executable==="npm"?parseNpmExecCommand(args):null;return invocation&&(isPmExecutableToken(invocation.command)||isPmCliPackageToken(invocation.command))?invocation.args:null}const extractReferencedPmItemIdsFromCommand=(command,idPrefix="pm")=>{const lowered=idPrefix.trim().toLowerCase();let prefixEnd=lowered.length;while(prefixEnd>0&&lowered[prefixEnd-1]==="-")prefixEnd-=1;const normalizedPrefix=lowered.slice(0,prefixEnd);if(normalizedPrefix.length===0)return[];const normalizedCommand=command.trim().replaceAll("\\","/").replaceAll('"',"").replaceAll("'","").replaceAll(/\s+/g," ").toLowerCase();const ids=new Set;for(const segment of splitNormalizedCommandSegments(normalizedCommand)){const invocationArgs=extractPmInvocationArgsFromSegment(segment);const context=invocationArgs?resolvePmSubcommandContext(invocationArgs):null;const candidate=context&&PM_SUBCOMMANDS_WITH_ITEM_REFERENCE.has(context.subcommand)?firstPositionalToken(context.remaining,PM_ITEM_REFERENCE_FLAGS_WITH_VALUE[context.subcommand]):void 0;const normalizedCandidate=candidate?.trim().toLowerCase();if(normalizedCandidate?.startsWith(`${normalizedPrefix}-`)===true&&normalizedCandidate.length>normalizedPrefix.length+1){ids.add(candidate)}}return[...ids].sort((left,right)=>left.localeCompare(right))};function stripLeadingEnvAssignments(tokens){let start=0;if(tokens[start]==="env"){start+=1}while(start<tokens.length){const token=tokens[start];if(/^(?:[a-z_][a-z0-9_]*|\$env:[a-z_][a-z0-9_]*)=.*/.test(token)){start+=1;continue}break}return tokens.slice(start)}function firstPmSubcommand(args){let index=0;while(index<args.length){const token=args[index];if(token==="--"){index+=1;continue}if(token.startsWith("-")){if(PM_GLOBAL_FLAGS_WITH_VALUE.has(token)){index+=2;continue}index+=1;continue}return token}return void 0}function isPmExecutableToken(token){return token==="pm"||token==="pm.cmd"||token==="pm.exe"||token.endsWith("/pm")||token.endsWith("/pm.cmd")||token.endsWith("/pm.exe")}function normalizePackageSpecifier(token){const trimmed=token.trim();if(!trimmed.startsWith("@")){const versionSeparator2=trimmed.indexOf("@");return versionSeparator2===-1?trimmed:trimmed.slice(0,versionSeparator2)}const scopeSeparator=trimmed.indexOf("/");if(scopeSeparator===-1){return trimmed}const versionSeparator=trimmed.indexOf("@",scopeSeparator+1);return versionSeparator===-1?trimmed:trimmed.slice(0,versionSeparator)}function isPmCliPackageToken(token){const normalizedSpecifier=normalizePackageSpecifier(token);return normalizedSpecifier==="pm-cli"||normalizedSpecifier.endsWith("/pm-cli")||token==="pm-cli"||token.endsWith("/pm-cli")}function isPmCliScriptToken(token,cwd=process.cwd()){const normalized=token.replaceAll("\\","/");if(normalized!=="dist/cli.js"&&normalized!=="./dist/cli.js"&&!normalized.endsWith("/dist/cli.js")){return false}const scriptPath=path.resolve(cwd,token);try{const packageJson=JSON.parse(readFileSync(path.join(path.dirname(path.dirname(scriptPath)),"package.json"),"utf8"));return packageJson.name==="@unbrained/pm-cli"}catch{return false}}function parseNpxCommand(tokens){let index=0;while(index<tokens.length){const token=tokens[index];if(token==="--"){index+=1;break}if(!token.startsWith("-")){break}const inlineCommandMatch=/^(?:-c|--call)=(.*)$/.exec(token);if(inlineCommandMatch){const command2=inlineCommandMatch[1];return command2?{command:command2,args:tokens.slice(index+1)}:null}if(NPX_COMMAND_STRING_FLAGS.has(token)){index+=1;break}index+=NPX_FLAGS_WITH_VALUE.has(token)&&!token.includes("=")?2:1}const command=tokens[index];if(!command){return null}return{command,args:tokens.slice(index+1)}}function parseLauncherSubcommand(tokens,flagsWithValue){let index=0;while(index<tokens.length){const token=tokens[index];if(token==="--"){index+=1;continue}if(token.startsWith("-")){if(token.includes("=")){index+=1;continue}if(flagsWithValue.has(token)){index+=2;continue}index+=1;continue}return{subcommand:token,args:tokens.slice(index+1)}}return null}function parsePnpmDlxCommand(tokens){const parsed=parseLauncherSubcommand(tokens,PNPM_GLOBAL_FLAGS_WITH_VALUE);if(parsed?.subcommand!=="dlx"){return null}return parseNpxCommand(parsed.args)}function parseNpmExecCommand(tokens){const parsed=parseLauncherSubcommand(tokens,NPM_GLOBAL_FLAGS_WITH_VALUE);if(!parsed||!NPM_EXEC_SUBCOMMANDS.has(parsed.subcommand)){return null}return parseNpxCommand(parsed.args)}function resolvePmSubcommandContext(args){let index=0;while(index<args.length){const token=args[index];if(token==="--"){index+=1;continue}if(token.startsWith("-")){if(PM_GLOBAL_FLAGS_WITH_VALUE.has(token)){index+=2;continue}index+=1;continue}return{subcommand:token,remaining:args.slice(index+1)}}return null}function firstPositionalToken(tokens,flagsWithValue=new Set){for(let index=0;index<tokens.length;index+=1){const token=tokens[index];if(token==="--"){return tokens[index+1]}if(!token.startsWith("-")){return token}if(!token.includes("=")&&(PM_GLOBAL_FLAGS_WITH_VALUE.has(token)||flagsWithValue.has(token))){index+=1}}return void 0}export{BUN_GLOBAL_FLAGS_WITH_VALUE,NPM_EXEC_SUBCOMMANDS,NPM_GLOBAL_FLAGS_WITH_VALUE,NPX_COMMAND_STRING_FLAGS,NPX_FLAGS_WITH_VALUE,PM_GLOBAL_FLAGS_WITH_VALUE,PM_ITEM_REFERENCE_FLAGS_WITH_VALUE,PNPM_GLOBAL_FLAGS_WITH_VALUE,SCRIPT_RUN_FLAGS_WITH_VALUE,SCRIPT_RUN_SUBCOMMANDS,YARN_GLOBAL_FLAGS_WITH_VALUE,extractPmInvocationArgsFromSegment,extractReferencedPmItemIdsFromCommand,firstPmSubcommand,firstPositionalToken,isPmCliPackageToken,isPmCliScriptToken,isPmExecutableToken,normalizePackageSpecifier,parseLauncherSubcommand,parseNpmExecCommand,parseNpxCommand,parsePnpmDlxCommand,resolvePmSubcommandContext,splitNormalizedCommandSegments,stripLeadingEnvAssignments};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="597a781e-a00d-5083-8d57-3fae870f9ccd")}catch{}})();import{readFileSync}from"node:fs";import path from"node:path";const PM_SUBCOMMANDS_WITH_ITEM_REFERENCE=new Set(["get","history","restore","update","close","delete","append","claim","release","comments","notes","learnings","files","docs","deps","test"]),PM_GLOBAL_FLAGS_WITH_VALUE=new Set(["--pm-path","--path","--author"]),PM_ITEM_REFERENCE_FLAGS_WITH_VALUE={get:new Set(["--depth","--fields","--tree-depth","--tree_depth","--at","--format"]),history:new Set(["--limit","--field","--format"]),restore:new Set(["--message"]),update:new Set(["--title","-t","--description","-d","--body","-b","--status","-s","--close-reason","--close_reason","--priority","-p","--type","--tags","--add-tags","--add_tags","--remove-tags","--remove_tags","--deadline","--estimated-minutes","--estimate","--estimated_minutes","--acceptance-criteria","--ac","--acceptance_criteria","--definition-of-ready","--definition_of_ready","--order","--rank","--goal","--objective","--value","--impact","--outcome","--why-now","--why_now","--message","--assignee","--parent","--reviewer","--risk","--confidence","--sprint","--release","--blocked-by","--blocked_by","--blocked-reason","--blocked_reason","--unblock-note","--unblock_note","--reporter","--severity","--environment","--repro-steps","--repro_steps","--resolution","--expected-result","--expected_result","--expected","--actual-result","--actual_result","--actual","--affected-version","--affected_version","--fixed-version","--fixed_version","--component","--regression","--customer-impact","--customer_impact","--dep","--dep-remove","--dep_remove","--comment","--note","--learning","--file","--test","--doc","--reminder","--event","--type-option","--type_option","--field","--unset","--body-file"]),close:new Set(["--reason","-r","--close-reason","--duplicate-of","-d","--message","-m","--validate-close","--resolution","--expected-result","--expected_result","--expected","--actual-result","--actual_result","--actual"]),delete:new Set(["--message"]),append:new Set(["--body","--text","--message"]),claim:new Set(["--assignee","--message","--type","--tag","--priority","--assignee-filter","--parent","--sprint","--release","--max-attempts"]),release:new Set(["--assignee","--message"]),comments:new Set(["--add","--body","--comment","--file","--edit","--delete","--limit","--message"]),notes:new Set(["--add","--file","--edit","--delete","--limit","--message"]),learnings:new Set(["--add","--file","--edit","--delete","--limit","--message"]),files:new Set(["--add","--add-glob","--remove","--migrate","--note","--message"]),docs:new Set(["--add","--add-glob","--remove","--migrate","--note","--message"]),deps:new Set(["--format","--max-depth","--collapse","--node-limit","--edge-limit","--token-budget","--cursor","--direction","--kind"]),test:new Set(["--add","--add-json","--remove","--match","--only-index","--timeout","--env-set","--env-clear","--pm-context","--message"])},NPX_FLAGS_WITH_VALUE=new Set(["-p","--package"]),NPX_COMMAND_STRING_FLAGS=new Set(["-c","--call"]),PNPM_GLOBAL_FLAGS_WITH_VALUE=new Set(["-c","-C","--config","--dir","--filter","--workspace-dir"]),NPM_GLOBAL_FLAGS_WITH_VALUE=new Set(["-C","--prefix","--userconfig","--cache"]),YARN_GLOBAL_FLAGS_WITH_VALUE=new Set(["--cwd"]),BUN_GLOBAL_FLAGS_WITH_VALUE=new Set(["--cwd"]),NPM_EXEC_SUBCOMMANDS=new Set(["exec","x"]),SCRIPT_RUN_SUBCOMMANDS=new Set(["run","run-script"]),SCRIPT_RUN_FLAGS_WITH_VALUE=new Set(["-C","--dir","--cwd","-w","--workspace","--filter"]);function splitNormalizedCommandSegments(normalizedCommand){return normalizedCommand.split(/&&|\|\||\||;/).map(segment=>segment.trim()).filter(segment=>segment.length>0)}function extractPmInvocationArgsFromSegment(segment,cwd=process.cwd()){const tokens=stripLeadingEnvAssignments(segment.split(" ").filter(token=>token.length>0));if(tokens.length===0)return null;const[executable,...args]=tokens;if(isPmExecutableToken(executable)||isPmCliScriptToken(executable,cwd))return args;if(executable==="node"&&args[0]&&isPmCliScriptToken(args[0],cwd))return args.slice(1);const invocation=executable==="npx"||executable==="bunx"?parseNpxCommand(args):executable==="pnpm"?parsePnpmDlxCommand(args):executable==="npm"?parseNpmExecCommand(args):null;return invocation&&(isPmExecutableToken(invocation.command)||isPmCliPackageToken(invocation.command))?invocation.args:null}const extractReferencedPmItemIdsFromCommand=(command,idPrefix="pm")=>{const lowered=idPrefix.trim().toLowerCase();let prefixEnd=lowered.length;for(;prefixEnd>0&&lowered[prefixEnd-1]==="-";)prefixEnd-=1;const normalizedPrefix=lowered.slice(0,prefixEnd);if(normalizedPrefix.length===0)return[];const normalizedCommand=command.trim().replaceAll("\\","/").replaceAll('"',"").replaceAll("'","").replaceAll(/\s+/g," ").toLowerCase(),ids=new Set;for(const segment of splitNormalizedCommandSegments(normalizedCommand)){const invocationArgs=extractPmInvocationArgsFromSegment(segment),context=invocationArgs?resolvePmSubcommandContext(invocationArgs):null,candidate=context&&PM_SUBCOMMANDS_WITH_ITEM_REFERENCE.has(context.subcommand)?firstPositionalToken(context.remaining,PM_ITEM_REFERENCE_FLAGS_WITH_VALUE[context.subcommand]):void 0,normalizedCandidate=candidate?.trim().toLowerCase();normalizedCandidate?.startsWith(`${normalizedPrefix}-`)===!0&&normalizedCandidate.length>normalizedPrefix.length+1&&ids.add(candidate)}return[...ids].sort((left,right)=>left.localeCompare(right))};function stripLeadingEnvAssignments(tokens){let start=0;for(tokens[start]==="env"&&(start+=1);start<tokens.length;){const token=tokens[start];if(/^(?:[a-z_][a-z0-9_]*|\$env:[a-z_][a-z0-9_]*)=.*/.test(token)){start+=1;continue}break}return tokens.slice(start)}function firstPmSubcommand(args){let index=0;for(;index<args.length;){const token=args[index];if(token==="--"){index+=1;continue}if(token.startsWith("-")){if(PM_GLOBAL_FLAGS_WITH_VALUE.has(token)){index+=2;continue}index+=1;continue}return token}}function isPmExecutableToken(token){return token==="pm"||token==="pm.cmd"||token==="pm.exe"||token.endsWith("/pm")||token.endsWith("/pm.cmd")||token.endsWith("/pm.exe")}function normalizePackageSpecifier(token){const trimmed=token.trim();if(!trimmed.startsWith("@")){const versionSeparator2=trimmed.indexOf("@");return versionSeparator2===-1?trimmed:trimmed.slice(0,versionSeparator2)}const scopeSeparator=trimmed.indexOf("/");if(scopeSeparator===-1)return trimmed;const versionSeparator=trimmed.indexOf("@",scopeSeparator+1);return versionSeparator===-1?trimmed:trimmed.slice(0,versionSeparator)}function isPmCliPackageToken(token){const normalizedSpecifier=normalizePackageSpecifier(token);return normalizedSpecifier==="pm-cli"||normalizedSpecifier.endsWith("/pm-cli")||token==="pm-cli"||token.endsWith("/pm-cli")}function isPmCliScriptToken(token,cwd=process.cwd()){const normalized=token.replaceAll("\\","/");if(normalized!=="dist/cli.js"&&normalized!=="./dist/cli.js"&&!normalized.endsWith("/dist/cli.js"))return!1;const scriptPath=path.resolve(cwd,token);try{return JSON.parse(readFileSync(path.join(path.dirname(path.dirname(scriptPath)),"package.json"),"utf8")).name==="@unbrained/pm-cli"}catch{return!1}}function parseNpxCommand(tokens){let index=0;for(;index<tokens.length;){const token=tokens[index];if(token==="--"){index+=1;break}if(!token.startsWith("-"))break;const inlineCommandMatch=/^(?:-c|--call)=(.*)$/.exec(token);if(inlineCommandMatch){const command2=inlineCommandMatch[1];return command2?{command:command2,args:tokens.slice(index+1)}:null}if(NPX_COMMAND_STRING_FLAGS.has(token)){index+=1;break}index+=NPX_FLAGS_WITH_VALUE.has(token)&&!token.includes("=")?2:1}const command=tokens[index];return command?{command,args:tokens.slice(index+1)}:null}function parseLauncherSubcommand(tokens,flagsWithValue){let index=0;for(;index<tokens.length;){const token=tokens[index];if(token==="--"){index+=1;continue}if(token.startsWith("-")){if(token.includes("=")){index+=1;continue}if(flagsWithValue.has(token)){index+=2;continue}index+=1;continue}return{subcommand:token,args:tokens.slice(index+1)}}return null}function parsePnpmDlxCommand(tokens){const parsed=parseLauncherSubcommand(tokens,PNPM_GLOBAL_FLAGS_WITH_VALUE);return parsed?.subcommand!=="dlx"?null:parseNpxCommand(parsed.args)}function parseNpmExecCommand(tokens){const parsed=parseLauncherSubcommand(tokens,NPM_GLOBAL_FLAGS_WITH_VALUE);return!parsed||!NPM_EXEC_SUBCOMMANDS.has(parsed.subcommand)?null:parseNpxCommand(parsed.args)}function resolvePmSubcommandContext(args){let index=0;for(;index<args.length;){const token=args[index];if(token==="--"){index+=1;continue}if(token.startsWith("-")){if(PM_GLOBAL_FLAGS_WITH_VALUE.has(token)){index+=2;continue}index+=1;continue}return{subcommand:token,remaining:args.slice(index+1)}}return null}function firstPositionalToken(tokens,flagsWithValue=new Set){for(let index=0;index<tokens.length;index+=1){const token=tokens[index];if(token==="--")return tokens[index+1];if(!token.startsWith("-"))return token;!token.includes("=")&&(PM_GLOBAL_FLAGS_WITH_VALUE.has(token)||flagsWithValue.has(token))&&(index+=1)}}export{BUN_GLOBAL_FLAGS_WITH_VALUE,NPM_EXEC_SUBCOMMANDS,NPM_GLOBAL_FLAGS_WITH_VALUE,NPX_COMMAND_STRING_FLAGS,NPX_FLAGS_WITH_VALUE,PM_GLOBAL_FLAGS_WITH_VALUE,PM_ITEM_REFERENCE_FLAGS_WITH_VALUE,PNPM_GLOBAL_FLAGS_WITH_VALUE,SCRIPT_RUN_FLAGS_WITH_VALUE,SCRIPT_RUN_SUBCOMMANDS,YARN_GLOBAL_FLAGS_WITH_VALUE,extractPmInvocationArgsFromSegment,extractReferencedPmItemIdsFromCommand,firstPmSubcommand,firstPositionalToken,isPmCliPackageToken,isPmCliScriptToken,isPmExecutableToken,normalizePackageSpecifier,parseLauncherSubcommand,parseNpmExecCommand,parseNpxCommand,parsePnpmDlxCommand,resolvePmSubcommandContext,splitNormalizedCommandSegments,stripLeadingEnvAssignments};
2
2
  //# sourceMappingURL=linked-command-detection.js.map
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="c81415a5-81fa-57ed-936f-236841e5f066")}catch(e2){}})();import{EXIT_CODE,PmCliError}from"../runtime-primitives.js";const TEST_RUN_MEASUREMENT_LIMIT=32;function splitTestRunMeasurementSpecs(values){const specs=[];for(const raw of values??[]){let current=[];for(const segment of raw.split(",")){const key=segment.slice(0,segment.indexOf("=")).trim();if(current.length>0&&key!=="unit"&&key!=="threshold"){specs.push(current.join(","));current=[]}current.push(segment)}specs.push(current.join(","))}return specs}function parseTestRunMeasurements(values,recordedAt){const measurements=splitTestRunMeasurementSpecs(values).map(raw=>{const[metricPair,...attributes]=raw.split(",");const separator=metricPair.indexOf("=");const name=metricPair.slice(0,separator).trim();const valueText=metricPair.slice(separator+1).trim();const value=Number(valueText);if(separator<=0||name.length===0||valueText.length===0||!Number.isFinite(value)){throw new PmCliError(`Invalid --measure "${raw}"; expected name=value[,unit=...][,threshold=...]`,EXIT_CODE.USAGE)}let unit;let threshold;for(const attribute of attributes){const attributeSeparator=attribute.indexOf("=");const key=attribute.slice(0,attributeSeparator).trim();const attributeValue=attribute.slice(attributeSeparator+1).trim();if(key==="unit"&&attributeValue.length>0){unit=attributeValue}else if(key==="threshold"&&attributeValue.length>0&&Number.isFinite(Number(attributeValue))){threshold=Number(attributeValue)}else{throw new PmCliError(`Invalid --measure attribute "${attribute}"`,EXIT_CODE.USAGE)}}return{name,value,unit,threshold,recorded_at:recordedAt}});const deduplicated=new Map(measurements.map(measurement=>[measurement.name,measurement]));return[...deduplicated.values()].sort((left,right)=>left.name.localeCompare(right.name)).slice(0,TEST_RUN_MEASUREMENT_LIMIT)}function queryTestRunMeasurementsBelow(runs,name,threshold){return runs.flatMap(run=>(run.measurements??[]).filter(measurement=>measurement.name===name&&measurement.value<threshold).map(measurement=>({...measurement,run_id:run.run_id})))}function diffTestRunMeasurements(runs,name){const values=runs.flatMap(run=>run.measurements??[]).filter(measurement=>measurement.name===name).sort((left,right)=>right.recorded_at.localeCompare(left.recorded_at));const latest=values[0];const previous=values[1];return{name,latest:latest?.value??null,previous:previous?.value??null,delta:latest!==void 0&&previous!==void 0?latest.value-previous.value:null,unit:latest?.unit}}export{TEST_RUN_MEASUREMENT_LIMIT,diffTestRunMeasurements,parseTestRunMeasurements,queryTestRunMeasurementsBelow};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3e70310d-fc4f-5ea9-b9fb-7c519035301b")}catch{}})();import{EXIT_CODE,PmCliError}from"../runtime-primitives.js";const TEST_RUN_MEASUREMENT_LIMIT=32;function splitTestRunMeasurementSpecs(values){const specs=[];for(const raw of values??[]){let current=[];for(const segment of raw.split(",")){const key=segment.slice(0,segment.indexOf("=")).trim();current.length>0&&key!=="unit"&&key!=="threshold"&&(specs.push(current.join(",")),current=[]),current.push(segment)}specs.push(current.join(","))}return specs}function parseTestRunMeasurements(values,recordedAt){const measurements=splitTestRunMeasurementSpecs(values).map(raw=>{const[metricPair,...attributes]=raw.split(","),separator=metricPair.indexOf("="),name=metricPair.slice(0,separator).trim(),valueText=metricPair.slice(separator+1).trim(),value=Number(valueText);if(separator<=0||name.length===0||valueText.length===0||!Number.isFinite(value))throw new PmCliError(`Invalid --measure "${raw}"; expected name=value[,unit=...][,threshold=...]`,EXIT_CODE.USAGE);let unit,threshold;for(const attribute of attributes){const attributeSeparator=attribute.indexOf("="),key=attribute.slice(0,attributeSeparator).trim(),attributeValue=attribute.slice(attributeSeparator+1).trim();if(key==="unit"&&attributeValue.length>0)unit=attributeValue;else if(key==="threshold"&&attributeValue.length>0&&Number.isFinite(Number(attributeValue)))threshold=Number(attributeValue);else throw new PmCliError(`Invalid --measure attribute "${attribute}"`,EXIT_CODE.USAGE)}return{name,value,unit,threshold,recorded_at:recordedAt}});return[...new Map(measurements.map(measurement=>[measurement.name,measurement])).values()].sort((left,right)=>left.name.localeCompare(right.name)).slice(0,TEST_RUN_MEASUREMENT_LIMIT)}function queryTestRunMeasurementsBelow(runs,name,threshold){return runs.flatMap(run=>(run.measurements??[]).filter(measurement=>measurement.name===name&&measurement.value<threshold).map(measurement=>({...measurement,run_id:run.run_id})))}function diffTestRunMeasurements(runs,name){const values=runs.flatMap(run=>run.measurements??[]).filter(measurement=>measurement.name===name).sort((left,right)=>right.recorded_at.localeCompare(left.recorded_at)),latest=values[0],previous=values[1];return{name,latest:latest?.value??null,previous:previous?.value??null,delta:latest!==void 0&&previous!==void 0?latest.value-previous.value:null,unit:latest?.unit}}export{TEST_RUN_MEASUREMENT_LIMIT,diffTestRunMeasurements,parseTestRunMeasurements,queryTestRunMeasurementsBelow};
2
2
  //# sourceMappingURL=measurements.js.map
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7ea4de2f-42e2-5ef3-89b2-d15ba6eb252a")}catch(e2){}})();import{parseOptionalNumber}from"../../core/item/parse.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{splitCommaList}from"../../core/shared/split-comma-list.js";import{STRUCTURED_LINKED_TEST_KEYS}from"./entry.js";import{SCOPE_VALUES}from"../../types/index.js";import{SOURCE_CONTEXT_ACCESS_ENV,SOURCE_CONTEXT_WRITE_OVERRIDE_ENV}from"../environment/source-context.js";const LINKED_TEST_PROTECTED_ENV_KEYS=new Set(["PM_PATH","PM_GLOBAL_PATH","PM_SOURCE_PM_PATH","PM_SOURCE_WORKSPACE_ROOT",SOURCE_CONTEXT_ACCESS_ENV,SOURCE_CONTEXT_WRITE_OVERRIDE_ENV,"FORCE_COLOR"]);const LINKED_TEST_ENV_NAME_PATTERN=/^[A-Za-z_][A-Za-z0-9_]*$/;const LINKED_TEST_PM_CONTEXT_MODE_VALUES=["schema","tracker","auto","none"];const LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES=["source","isolated","snapshot"];function parseLinkedTestEnvSet(raw,optionName){if(!raw){return void 0}const assignments=raw.split(/[;\n]/).map(entry=>entry.trim()).filter(entry=>entry.length>0);if(assignments.length===0){throw new PmCliError(`${optionName} env_set must include at least one KEY=VALUE assignment`,EXIT_CODE.USAGE)}const envSet=Object.create(null);for(const assignment of assignments){const separatorIndex=assignment.indexOf("=");if(separatorIndex<=0){throw new PmCliError(`${optionName} env_set entries must use KEY=VALUE and be separated by semicolons. Example: env_set=PORT=0;PLAYWRIGHT_BASE_URL=http://127.0.0.1:4173`,EXIT_CODE.USAGE)}const key=assignment.slice(0,separatorIndex).trim();const value=assignment.slice(separatorIndex+1);if(!LINKED_TEST_ENV_NAME_PATTERN.test(key)){throw new PmCliError(`${optionName} env_set key "${key}" is invalid`,EXIT_CODE.USAGE)}if(LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())){throw new PmCliError(`${optionName} env_set key "${key}" is reserved for sandbox safety`,EXIT_CODE.USAGE)}envSet[key]=value}return Object.keys(envSet).length>0?envSet:void 0}function parseLinkedTestEnvClear(raw,optionName){if(!raw){return void 0}const keys=splitCommaList(raw,{separators:/[;,\n]/});if(keys.length===0){throw new PmCliError(`${optionName} env_clear must include at least one environment variable name`,EXIT_CODE.USAGE)}for(const key of keys){if(!LINKED_TEST_ENV_NAME_PATTERN.test(key)){throw new PmCliError(`${optionName} env_clear key "${key}" is invalid`,EXIT_CODE.USAGE)}if(LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())){throw new PmCliError(`${optionName} env_clear key "${key}" is reserved for sandbox safety`,EXIT_CODE.USAGE)}}return keys}function parseLinkedTestBoolean(raw,optionName,fieldLabel){if(!raw){return void 0}const value=raw.trim().toLowerCase();if(value==="true"||value==="1"||value==="yes"){return true}if(value==="false"||value==="0"||value==="no"){return false}throw new PmCliError(`${optionName} ${fieldLabel} must be one of true|false|1|0|yes|no`,EXIT_CODE.USAGE)}function parseLinkedTestContextMode(raw,optionName){if(!raw){return void 0}const value=raw.trim().toLowerCase();if(LINKED_TEST_PM_CONTEXT_MODE_VALUES.includes(value)){return value}throw new PmCliError(`${optionName} pm_context_mode must be one of: ${LINKED_TEST_PM_CONTEXT_MODE_VALUES.join(", ")}`,EXIT_CODE.USAGE)}function parseLinkedTestWorkspaceContextMode(raw,optionName){if(!raw){return void 0}const value=raw.trim().toLowerCase();if(LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES.includes(value)){return value}throw new PmCliError(`${optionName} workspace_context_mode must be one of: ${LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES.join(", ")}`,EXIT_CODE.USAGE)}function parseLinkedTestStringList(raw){if(!raw){return void 0}const values=splitCommaList(raw,{separators:/[;\n]/});return values.length>0?values:void 0}function parseLinkedTestRegexList(raw,optionName,fieldLabel){const values=parseLinkedTestStringList(raw);if(!values||values.length===0){return void 0}for(const pattern of values){try{new RegExp(pattern,"m")}catch(error){throw new PmCliError(`${optionName} ${fieldLabel} includes invalid regex "${pattern}": ${error instanceof Error?error.message:String(error)}`,EXIT_CODE.USAGE)}}return values}function parseLinkedTestMinLines(raw,optionName){if(!raw){return void 0}const parsed=parseOptionalNumber(raw,"assert_stdout_min_lines");if(!Number.isInteger(parsed)||parsed<0){throw new PmCliError(`${optionName} assert_stdout_min_lines must be an integer >= 0`,EXIT_CODE.USAGE)}return parsed}function parseLinkedTestAssertionEqualsMap(raw,optionName){if(!raw){return void 0}const assignments=raw.split(/[;\n]/).map(entry=>entry.trim()).filter(entry=>entry.length>0);if(assignments.length===0){throw new PmCliError(`${optionName} assert_json_field_equals must include at least one path=value assignment`,EXIT_CODE.USAGE)}const values=Object.create(null);for(const assignment of assignments){const separatorIndex=assignment.indexOf("=");if(separatorIndex<=0){throw new PmCliError(`${optionName} assert_json_field_equals entries must use path=value and be separated by semicolons`,EXIT_CODE.USAGE)}const key=assignment.slice(0,separatorIndex).trim();const value=assignment.slice(separatorIndex+1).trim();if(key.length===0||value.length===0){throw new PmCliError(`${optionName} assert_json_field_equals entries must include non-empty path and value`,EXIT_CODE.USAGE)}values[key]=value}return Object.keys(values).length>0?values:void 0}function parseLinkedTestAssertionGteMap(raw,optionName){if(!raw){return void 0}const assignments=raw.split(/[;\n]/).map(entry=>entry.trim()).filter(entry=>entry.length>0);if(assignments.length===0){throw new PmCliError(`${optionName} assert_json_field_gte must include at least one path=value assignment`,EXIT_CODE.USAGE)}const values=Object.create(null);for(const assignment of assignments){const separatorIndex=assignment.indexOf("=");if(separatorIndex<=0){throw new PmCliError(`${optionName} assert_json_field_gte entries must use path=value and be separated by semicolons`,EXIT_CODE.USAGE)}const key=assignment.slice(0,separatorIndex).trim();const valueRaw=assignment.slice(separatorIndex+1).trim();if(key.length===0||valueRaw.length===0){throw new PmCliError(`${optionName} assert_json_field_gte entries must include non-empty path and value`,EXIT_CODE.USAGE)}const value=Number(valueRaw);if(!Number.isFinite(value)){throw new PmCliError(`${optionName} assert_json_field_gte value for "${key}" must be numeric`,EXIT_CODE.USAGE)}values[key]=value}return Object.keys(values).length>0?values:void 0}const LINKED_TEST_JSON_KEY_SET=new Set(STRUCTURED_LINKED_TEST_KEYS);function isPlainObject(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function normalizeJsonEntryKeys(entry,fail){const normalized={};const unknownKeys=[];for(const[key,value]of Object.entries(entry)){const normalizedKey=key.toLowerCase();if(!LINKED_TEST_JSON_KEY_SET.has(normalizedKey)){unknownKeys.push(key);continue}if(Object.hasOwn(normalized,normalizedKey)){throw fail(`provides key "${key}" more than once after case normalization`)}normalized[normalizedKey]=value}if(unknownKeys.length>0){throw fail(`does not recognize key${unknownKeys.length>1?"s":""} ${unknownKeys.map(key=>`"${key}"`).join(", ")}. Allowed keys: ${STRUCTURED_LINKED_TEST_KEYS.join(", ")}.`)}return normalized}function readJsonEntryString(entry,key,fail){if(!Object.hasOwn(entry,key)){return void 0}const value=entry[key];if(value===void 0){return void 0}if(typeof value!=="string"){throw fail(`field "${key}" must be a JSON string`)}return value}function readJsonEntryStringList(entry,key,fail){if(!Object.hasOwn(entry,key)){return void 0}const value=entry[key];if(value===void 0){return void 0}const list=typeof value==="string"?[value]:value;if(!Array.isArray(list)||list.some(item=>typeof item!=="string")){throw fail(`field "${key}" must be a string or an array of strings`)}const values=list.filter(item=>item.length>0);return values.length>0?values:void 0}function readJsonEntryRegexList(entry,key,fail){const values=readJsonEntryStringList(entry,key,fail);if(!values){return void 0}for(const pattern of values){try{new RegExp(pattern,"m")}catch(error){throw fail(`field "${key}" includes invalid regex "${pattern}": ${error instanceof Error?error.message:String(error)}`)}}return values}function readJsonEntryNumber(value,key,fail){const parsed=typeof value==="number"?value:typeof value==="string"&&value.trim().length>0?Number(value.trim()):Number.NaN;if(typeof value==="boolean"||!Number.isFinite(parsed)){throw fail(`field "${key}" must be a finite number (or numeric string)`)}return parsed}function readJsonEntryTimeoutSeconds(entry,fail){const timeoutSecondsRaw=entry.timeout_seconds;const timeoutAliasRaw=entry.timeout;if(timeoutSecondsRaw===void 0&&timeoutAliasRaw===void 0){return void 0}const timeoutSeconds=timeoutSecondsRaw===void 0?void 0:readJsonEntryNumber(timeoutSecondsRaw,"timeout_seconds",fail);const timeoutAlias=timeoutAliasRaw===void 0?void 0:readJsonEntryNumber(timeoutAliasRaw,"timeout",fail);if(timeoutSeconds!==void 0&&timeoutAlias!==void 0&&timeoutSeconds!==timeoutAlias){throw fail("timeout and timeout_seconds must match when both are provided")}const timeout=timeoutSeconds??timeoutAlias;if(!Number.isInteger(timeout)||timeout<=0){throw fail("timeout_seconds must be a positive integer")}return timeout}function readJsonEntryScope(entry,fail){const value=readJsonEntryString(entry,"scope",fail);if(value===void 0){return"project"}if(!SCOPE_VALUES.includes(value)){throw fail(`field "scope" must be one of: ${SCOPE_VALUES.join(", ")}`)}return value}function readJsonEntryEnvSet(entry,fail){if(!Object.hasOwn(entry,"env_set")){return void 0}const value=entry.env_set;if(value===void 0){return void 0}if(!isPlainObject(value)){throw fail('field "env_set" must be a JSON object mapping environment names to string values')}const envSet=Object.create(null);for(const[key,entryValue]of Object.entries(value)){if(typeof entryValue!=="string"){throw fail(`field "env_set" value for "${key}" must be a string`)}if(!LINKED_TEST_ENV_NAME_PATTERN.test(key)){throw fail(`field "env_set" key "${key}" is invalid`)}if(LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())){throw fail(`field "env_set" key "${key}" is reserved for sandbox safety`)}envSet[key]=entryValue}return Object.keys(envSet).length>0?envSet:void 0}function readJsonEntryEnvClear(entry,fail){const keys=readJsonEntryStringList(entry,"env_clear",fail);if(!keys){return void 0}for(const key of keys){if(!LINKED_TEST_ENV_NAME_PATTERN.test(key)){throw fail(`field "env_clear" key "${key}" is invalid`)}if(LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())){throw fail(`field "env_clear" key "${key}" is reserved for sandbox safety`)}}return keys}function readJsonEntryBoolean(entry,key,fail){if(!Object.hasOwn(entry,key)){return void 0}const value=entry[key];if(value===void 0){return void 0}if(typeof value!=="boolean"){throw fail(`field "${key}" must be a JSON boolean (true or false)`)}return value}function readJsonEntryMinLines(entry,fail){if(!Object.hasOwn(entry,"assert_stdout_min_lines")){return void 0}const value=entry.assert_stdout_min_lines;if(value===void 0){return void 0}const parsed=readJsonEntryNumber(value,"assert_stdout_min_lines",fail);if(!Number.isInteger(parsed)||parsed<0){throw fail('field "assert_stdout_min_lines" must be an integer >= 0')}return parsed}function readJsonEntryEqualsMap(entry,fail){if(!Object.hasOwn(entry,"assert_json_field_equals")){return void 0}const value=entry.assert_json_field_equals;if(value===void 0){return void 0}if(!isPlainObject(value)){throw fail('field "assert_json_field_equals" must be a JSON object mapping field paths to expected values')}const values=Object.create(null);for(const[key,entryValue]of Object.entries(value)){if(key.trim().length===0){throw fail('field "assert_json_field_equals" keys must be non-empty field paths')}if(typeof entryValue!=="string"&&typeof entryValue!=="number"&&typeof entryValue!=="boolean"){throw fail(`field "assert_json_field_equals" value for "${key}" must be a string, number, or boolean`)}values[key]=String(entryValue)}return Object.keys(values).length>0?values:void 0}function readJsonEntryGteMap(entry,fail){if(!Object.hasOwn(entry,"assert_json_field_gte")){return void 0}const value=entry.assert_json_field_gte;if(value===void 0){return void 0}if(!isPlainObject(value)){throw fail('field "assert_json_field_gte" must be a JSON object mapping field paths to numeric minimums')}const values=Object.create(null);for(const[key,entryValue]of Object.entries(value)){if(key.trim().length===0){throw fail('field "assert_json_field_gte" keys must be non-empty field paths')}values[key]=readJsonEntryNumber(entryValue,`assert_json_field_gte.${key}`,fail)}return Object.keys(values).length>0?values:void 0}function parseLinkedTestJsonEntry(rawEntry,label,optionName){const fail=message=>new PmCliError(`${optionName} ${label} ${message}`,EXIT_CODE.USAGE);if(!isPlainObject(rawEntry)){throw fail(`must be a JSON object with linked-test fields. Allowed keys: ${STRUCTURED_LINKED_TEST_KEYS.join(", ")}.`)}const entry=normalizeJsonEntryKeys(rawEntry,fail);const commandValue=readJsonEntryString(entry,"command",fail);const cmdAlias=readJsonEntryString(entry,"cmd",fail);if(commandValue!==void 0&&cmdAlias!==void 0&&commandValue!==cmdAlias){throw fail("command and cmd must match when both are provided")}const command=commandValue??cmdAlias;if(command===void 0||command.trim().length===0){throw fail('requires a non-empty "command" string')}const pathValue=readJsonEntryString(entry,"path",fail);const pmContextModeValue=readJsonEntryString(entry,"pm_context_mode",fail);if(pmContextModeValue!==void 0&&!LINKED_TEST_PM_CONTEXT_MODE_VALUES.includes(pmContextModeValue)){throw fail(`field "pm_context_mode" must be one of: ${LINKED_TEST_PM_CONTEXT_MODE_VALUES.join(", ")}`)}const workspaceContextModeValue=parseLinkedTestWorkspaceContextMode(readJsonEntryString(entry,"workspace_context_mode",fail),`${optionName} ${label}`);const noteValue=readJsonEntryString(entry,"note",fail);return{command,path:pathValue!==void 0&&pathValue.length>0?pathValue:void 0,scope:readJsonEntryScope(entry,fail),timeout_seconds:readJsonEntryTimeoutSeconds(entry,fail),pm_context_mode:pmContextModeValue,workspace_context_mode:workspaceContextModeValue,env_set:readJsonEntryEnvSet(entry,fail),env_clear:readJsonEntryEnvClear(entry,fail),shared_host_safe:readJsonEntryBoolean(entry,"shared_host_safe",fail),assert_stdout_contains:readJsonEntryStringList(entry,"assert_stdout_contains",fail),assert_stdout_regex:readJsonEntryRegexList(entry,"assert_stdout_regex",fail),assert_stderr_contains:readJsonEntryStringList(entry,"assert_stderr_contains",fail),assert_stderr_regex:readJsonEntryRegexList(entry,"assert_stderr_regex",fail),assert_stdout_min_lines:readJsonEntryMinLines(entry,fail),assert_json_field_equals:readJsonEntryEqualsMap(entry,fail),assert_json_field_gte:readJsonEntryGteMap(entry,fail),note:noteValue!==void 0&&noteValue.trim().length>0?noteValue.trim():void 0}}function parseLinkedTestJsonEntries(raw,optionName){const trimmed=raw.trim();if(trimmed.length===0){throw new PmCliError(`${optionName} requires a JSON object or array of objects describing linked-test entries`,EXIT_CODE.USAGE)}let parsed;try{parsed=JSON.parse(trimmed)}catch(error){throw new PmCliError(`${optionName} value is not valid JSON: ${error instanceof Error?error.message:String(error)}. Provide a JSON object or array of objects, e.g. '{"command":"node scripts/check.js --flag value, with commas","timeout_seconds":120}'.`,EXIT_CODE.USAGE)}const entries=Array.isArray(parsed)?parsed:[parsed];if(entries.length===0){throw new PmCliError(`${optionName} array must include at least one linked-test entry object`,EXIT_CODE.USAGE)}return entries.map((entry,index)=>parseLinkedTestJsonEntry(entry,entries.length>1?`entry ${index+1}`:"entry",optionName))}const _testOnlyLinkedTestParsers={parseLinkedTestJsonEntry};export{LINKED_TEST_ENV_NAME_PATTERN,LINKED_TEST_PM_CONTEXT_MODE_VALUES,LINKED_TEST_PROTECTED_ENV_KEYS,LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES,_testOnlyLinkedTestParsers,parseLinkedTestAssertionEqualsMap,parseLinkedTestAssertionGteMap,parseLinkedTestBoolean,parseLinkedTestContextMode,parseLinkedTestEnvClear,parseLinkedTestEnvSet,parseLinkedTestJsonEntries,parseLinkedTestMinLines,parseLinkedTestRegexList,parseLinkedTestStringList,parseLinkedTestWorkspaceContextMode};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="dd87416a-25ec-5dfe-8c54-ef7f43529ecc")}catch{}})();import{parseOptionalNumber}from"../../core/item/parse.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{splitCommaList}from"../../core/shared/split-comma-list.js";import{STRUCTURED_LINKED_TEST_KEYS}from"./entry.js";import{SCOPE_VALUES}from"../../types/index.js";import{SOURCE_CONTEXT_ACCESS_ENV,SOURCE_CONTEXT_WRITE_OVERRIDE_ENV}from"../environment/source-context.js";const LINKED_TEST_PROTECTED_ENV_KEYS=new Set(["PM_PATH","PM_GLOBAL_PATH","PM_SOURCE_PM_PATH","PM_SOURCE_WORKSPACE_ROOT",SOURCE_CONTEXT_ACCESS_ENV,SOURCE_CONTEXT_WRITE_OVERRIDE_ENV,"FORCE_COLOR"]),LINKED_TEST_ENV_NAME_PATTERN=/^[A-Za-z_][A-Za-z0-9_]*$/,LINKED_TEST_PM_CONTEXT_MODE_VALUES=["schema","tracker","auto","none"],LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES=["source","isolated","snapshot"];function parseLinkedTestEnvSet(raw,optionName){if(!raw)return;const assignments=raw.split(/[;\n]/).map(entry=>entry.trim()).filter(entry=>entry.length>0);if(assignments.length===0)throw new PmCliError(`${optionName} env_set must include at least one KEY=VALUE assignment`,EXIT_CODE.USAGE);const envSet=Object.create(null);for(const assignment of assignments){const separatorIndex=assignment.indexOf("=");if(separatorIndex<=0)throw new PmCliError(`${optionName} env_set entries must use KEY=VALUE and be separated by semicolons. Example: env_set=PORT=0;PLAYWRIGHT_BASE_URL=http://127.0.0.1:4173`,EXIT_CODE.USAGE);const key=assignment.slice(0,separatorIndex).trim(),value=assignment.slice(separatorIndex+1);if(!LINKED_TEST_ENV_NAME_PATTERN.test(key))throw new PmCliError(`${optionName} env_set key "${key}" is invalid`,EXIT_CODE.USAGE);if(LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase()))throw new PmCliError(`${optionName} env_set key "${key}" is reserved for sandbox safety`,EXIT_CODE.USAGE);envSet[key]=value}return Object.keys(envSet).length>0?envSet:void 0}function parseLinkedTestEnvClear(raw,optionName){if(!raw)return;const keys=splitCommaList(raw,{separators:/[;,\n]/});if(keys.length===0)throw new PmCliError(`${optionName} env_clear must include at least one environment variable name`,EXIT_CODE.USAGE);for(const key of keys){if(!LINKED_TEST_ENV_NAME_PATTERN.test(key))throw new PmCliError(`${optionName} env_clear key "${key}" is invalid`,EXIT_CODE.USAGE);if(LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase()))throw new PmCliError(`${optionName} env_clear key "${key}" is reserved for sandbox safety`,EXIT_CODE.USAGE)}return keys}function parseLinkedTestBoolean(raw,optionName,fieldLabel){if(!raw)return;const value=raw.trim().toLowerCase();if(value==="true"||value==="1"||value==="yes")return!0;if(value==="false"||value==="0"||value==="no")return!1;throw new PmCliError(`${optionName} ${fieldLabel} must be one of true|false|1|0|yes|no`,EXIT_CODE.USAGE)}function parseLinkedTestContextMode(raw,optionName){if(!raw)return;const value=raw.trim().toLowerCase();if(LINKED_TEST_PM_CONTEXT_MODE_VALUES.includes(value))return value;throw new PmCliError(`${optionName} pm_context_mode must be one of: ${LINKED_TEST_PM_CONTEXT_MODE_VALUES.join(", ")}`,EXIT_CODE.USAGE)}function parseLinkedTestWorkspaceContextMode(raw,optionName){if(!raw)return;const value=raw.trim().toLowerCase();if(LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES.includes(value))return value;throw new PmCliError(`${optionName} workspace_context_mode must be one of: ${LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES.join(", ")}`,EXIT_CODE.USAGE)}function parseLinkedTestStringList(raw){if(!raw)return;const values=splitCommaList(raw,{separators:/[;\n]/});return values.length>0?values:void 0}function parseLinkedTestRegexList(raw,optionName,fieldLabel){const values=parseLinkedTestStringList(raw);if(!(!values||values.length===0)){for(const pattern of values)try{new RegExp(pattern,"m")}catch(error){throw new PmCliError(`${optionName} ${fieldLabel} includes invalid regex "${pattern}": ${error instanceof Error?error.message:String(error)}`,EXIT_CODE.USAGE)}return values}}function parseLinkedTestMinLines(raw,optionName){if(!raw)return;const parsed=parseOptionalNumber(raw,"assert_stdout_min_lines");if(!Number.isInteger(parsed)||parsed<0)throw new PmCliError(`${optionName} assert_stdout_min_lines must be an integer >= 0`,EXIT_CODE.USAGE);return parsed}function parseLinkedTestAssertionEqualsMap(raw,optionName){if(!raw)return;const assignments=raw.split(/[;\n]/).map(entry=>entry.trim()).filter(entry=>entry.length>0);if(assignments.length===0)throw new PmCliError(`${optionName} assert_json_field_equals must include at least one path=value assignment`,EXIT_CODE.USAGE);const values=Object.create(null);for(const assignment of assignments){const separatorIndex=assignment.indexOf("=");if(separatorIndex<=0)throw new PmCliError(`${optionName} assert_json_field_equals entries must use path=value and be separated by semicolons`,EXIT_CODE.USAGE);const key=assignment.slice(0,separatorIndex).trim(),value=assignment.slice(separatorIndex+1).trim();if(key.length===0||value.length===0)throw new PmCliError(`${optionName} assert_json_field_equals entries must include non-empty path and value`,EXIT_CODE.USAGE);values[key]=value}return Object.keys(values).length>0?values:void 0}function parseLinkedTestAssertionGteMap(raw,optionName){if(!raw)return;const assignments=raw.split(/[;\n]/).map(entry=>entry.trim()).filter(entry=>entry.length>0);if(assignments.length===0)throw new PmCliError(`${optionName} assert_json_field_gte must include at least one path=value assignment`,EXIT_CODE.USAGE);const values=Object.create(null);for(const assignment of assignments){const separatorIndex=assignment.indexOf("=");if(separatorIndex<=0)throw new PmCliError(`${optionName} assert_json_field_gte entries must use path=value and be separated by semicolons`,EXIT_CODE.USAGE);const key=assignment.slice(0,separatorIndex).trim(),valueRaw=assignment.slice(separatorIndex+1).trim();if(key.length===0||valueRaw.length===0)throw new PmCliError(`${optionName} assert_json_field_gte entries must include non-empty path and value`,EXIT_CODE.USAGE);const value=Number(valueRaw);if(!Number.isFinite(value))throw new PmCliError(`${optionName} assert_json_field_gte value for "${key}" must be numeric`,EXIT_CODE.USAGE);values[key]=value}return Object.keys(values).length>0?values:void 0}const LINKED_TEST_JSON_KEY_SET=new Set(STRUCTURED_LINKED_TEST_KEYS);function isPlainObject(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function normalizeJsonEntryKeys(entry,fail){const normalized={},unknownKeys=[];for(const[key,value]of Object.entries(entry)){const normalizedKey=key.toLowerCase();if(!LINKED_TEST_JSON_KEY_SET.has(normalizedKey)){unknownKeys.push(key);continue}if(Object.hasOwn(normalized,normalizedKey))throw fail(`provides key "${key}" more than once after case normalization`);normalized[normalizedKey]=value}if(unknownKeys.length>0)throw fail(`does not recognize key${unknownKeys.length>1?"s":""} ${unknownKeys.map(key=>`"${key}"`).join(", ")}. Allowed keys: ${STRUCTURED_LINKED_TEST_KEYS.join(", ")}.`);return normalized}function readJsonEntryString(entry,key,fail){if(!Object.hasOwn(entry,key))return;const value=entry[key];if(value!==void 0){if(typeof value!="string")throw fail(`field "${key}" must be a JSON string`);return value}}function readJsonEntryStringList(entry,key,fail){if(!Object.hasOwn(entry,key))return;const value=entry[key];if(value===void 0)return;const list=typeof value=="string"?[value]:value;if(!Array.isArray(list)||list.some(item=>typeof item!="string"))throw fail(`field "${key}" must be a string or an array of strings`);const values=list.filter(item=>item.length>0);return values.length>0?values:void 0}function readJsonEntryRegexList(entry,key,fail){const values=readJsonEntryStringList(entry,key,fail);if(values){for(const pattern of values)try{new RegExp(pattern,"m")}catch(error){throw fail(`field "${key}" includes invalid regex "${pattern}": ${error instanceof Error?error.message:String(error)}`)}return values}}function readJsonEntryNumber(value,key,fail){const parsed=typeof value=="number"?value:typeof value=="string"&&value.trim().length>0?Number(value.trim()):Number.NaN;if(typeof value=="boolean"||!Number.isFinite(parsed))throw fail(`field "${key}" must be a finite number (or numeric string)`);return parsed}function readJsonEntryTimeoutSeconds(entry,fail){const timeoutSecondsRaw=entry.timeout_seconds,timeoutAliasRaw=entry.timeout;if(timeoutSecondsRaw===void 0&&timeoutAliasRaw===void 0)return;const timeoutSeconds=timeoutSecondsRaw===void 0?void 0:readJsonEntryNumber(timeoutSecondsRaw,"timeout_seconds",fail),timeoutAlias=timeoutAliasRaw===void 0?void 0:readJsonEntryNumber(timeoutAliasRaw,"timeout",fail);if(timeoutSeconds!==void 0&&timeoutAlias!==void 0&&timeoutSeconds!==timeoutAlias)throw fail("timeout and timeout_seconds must match when both are provided");const timeout=timeoutSeconds??timeoutAlias;if(!Number.isInteger(timeout)||timeout<=0)throw fail("timeout_seconds must be a positive integer");return timeout}function readJsonEntryScope(entry,fail){const value=readJsonEntryString(entry,"scope",fail);if(value===void 0)return"project";if(!SCOPE_VALUES.includes(value))throw fail(`field "scope" must be one of: ${SCOPE_VALUES.join(", ")}`);return value}function readJsonEntryEnvSet(entry,fail){if(!Object.hasOwn(entry,"env_set"))return;const value=entry.env_set;if(value===void 0)return;if(!isPlainObject(value))throw fail('field "env_set" must be a JSON object mapping environment names to string values');const envSet=Object.create(null);for(const[key,entryValue]of Object.entries(value)){if(typeof entryValue!="string")throw fail(`field "env_set" value for "${key}" must be a string`);if(!LINKED_TEST_ENV_NAME_PATTERN.test(key))throw fail(`field "env_set" key "${key}" is invalid`);if(LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase()))throw fail(`field "env_set" key "${key}" is reserved for sandbox safety`);envSet[key]=entryValue}return Object.keys(envSet).length>0?envSet:void 0}function readJsonEntryEnvClear(entry,fail){const keys=readJsonEntryStringList(entry,"env_clear",fail);if(keys){for(const key of keys){if(!LINKED_TEST_ENV_NAME_PATTERN.test(key))throw fail(`field "env_clear" key "${key}" is invalid`);if(LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase()))throw fail(`field "env_clear" key "${key}" is reserved for sandbox safety`)}return keys}}function readJsonEntryBoolean(entry,key,fail){if(!Object.hasOwn(entry,key))return;const value=entry[key];if(value!==void 0){if(typeof value!="boolean")throw fail(`field "${key}" must be a JSON boolean (true or false)`);return value}}function readJsonEntryMinLines(entry,fail){if(!Object.hasOwn(entry,"assert_stdout_min_lines"))return;const value=entry.assert_stdout_min_lines;if(value===void 0)return;const parsed=readJsonEntryNumber(value,"assert_stdout_min_lines",fail);if(!Number.isInteger(parsed)||parsed<0)throw fail('field "assert_stdout_min_lines" must be an integer >= 0');return parsed}function readJsonEntryEqualsMap(entry,fail){if(!Object.hasOwn(entry,"assert_json_field_equals"))return;const value=entry.assert_json_field_equals;if(value===void 0)return;if(!isPlainObject(value))throw fail('field "assert_json_field_equals" must be a JSON object mapping field paths to expected values');const values=Object.create(null);for(const[key,entryValue]of Object.entries(value)){if(key.trim().length===0)throw fail('field "assert_json_field_equals" keys must be non-empty field paths');if(typeof entryValue!="string"&&typeof entryValue!="number"&&typeof entryValue!="boolean")throw fail(`field "assert_json_field_equals" value for "${key}" must be a string, number, or boolean`);values[key]=String(entryValue)}return Object.keys(values).length>0?values:void 0}function readJsonEntryGteMap(entry,fail){if(!Object.hasOwn(entry,"assert_json_field_gte"))return;const value=entry.assert_json_field_gte;if(value===void 0)return;if(!isPlainObject(value))throw fail('field "assert_json_field_gte" must be a JSON object mapping field paths to numeric minimums');const values=Object.create(null);for(const[key,entryValue]of Object.entries(value)){if(key.trim().length===0)throw fail('field "assert_json_field_gte" keys must be non-empty field paths');values[key]=readJsonEntryNumber(entryValue,`assert_json_field_gte.${key}`,fail)}return Object.keys(values).length>0?values:void 0}function parseLinkedTestJsonEntry(rawEntry,label,optionName){const fail=message=>new PmCliError(`${optionName} ${label} ${message}`,EXIT_CODE.USAGE);if(!isPlainObject(rawEntry))throw fail(`must be a JSON object with linked-test fields. Allowed keys: ${STRUCTURED_LINKED_TEST_KEYS.join(", ")}.`);const entry=normalizeJsonEntryKeys(rawEntry,fail),commandValue=readJsonEntryString(entry,"command",fail),cmdAlias=readJsonEntryString(entry,"cmd",fail);if(commandValue!==void 0&&cmdAlias!==void 0&&commandValue!==cmdAlias)throw fail("command and cmd must match when both are provided");const command=commandValue??cmdAlias;if(command===void 0||command.trim().length===0)throw fail('requires a non-empty "command" string');const pathValue=readJsonEntryString(entry,"path",fail),pmContextModeValue=readJsonEntryString(entry,"pm_context_mode",fail);if(pmContextModeValue!==void 0&&!LINKED_TEST_PM_CONTEXT_MODE_VALUES.includes(pmContextModeValue))throw fail(`field "pm_context_mode" must be one of: ${LINKED_TEST_PM_CONTEXT_MODE_VALUES.join(", ")}`);const workspaceContextModeValue=parseLinkedTestWorkspaceContextMode(readJsonEntryString(entry,"workspace_context_mode",fail),`${optionName} ${label}`),noteValue=readJsonEntryString(entry,"note",fail);return{command,path:pathValue!==void 0&&pathValue.length>0?pathValue:void 0,scope:readJsonEntryScope(entry,fail),timeout_seconds:readJsonEntryTimeoutSeconds(entry,fail),pm_context_mode:pmContextModeValue,workspace_context_mode:workspaceContextModeValue,env_set:readJsonEntryEnvSet(entry,fail),env_clear:readJsonEntryEnvClear(entry,fail),shared_host_safe:readJsonEntryBoolean(entry,"shared_host_safe",fail),assert_stdout_contains:readJsonEntryStringList(entry,"assert_stdout_contains",fail),assert_stdout_regex:readJsonEntryRegexList(entry,"assert_stdout_regex",fail),assert_stderr_contains:readJsonEntryStringList(entry,"assert_stderr_contains",fail),assert_stderr_regex:readJsonEntryRegexList(entry,"assert_stderr_regex",fail),assert_stdout_min_lines:readJsonEntryMinLines(entry,fail),assert_json_field_equals:readJsonEntryEqualsMap(entry,fail),assert_json_field_gte:readJsonEntryGteMap(entry,fail),note:noteValue!==void 0&&noteValue.trim().length>0?noteValue.trim():void 0}}function parseLinkedTestJsonEntries(raw,optionName){const trimmed=raw.trim();if(trimmed.length===0)throw new PmCliError(`${optionName} requires a JSON object or array of objects describing linked-test entries`,EXIT_CODE.USAGE);let parsed;try{parsed=JSON.parse(trimmed)}catch(error){throw new PmCliError(`${optionName} value is not valid JSON: ${error instanceof Error?error.message:String(error)}. Provide a JSON object or array of objects, e.g. '{"command":"node scripts/check.js --flag value, with commas","timeout_seconds":120}'.`,EXIT_CODE.USAGE)}const entries=Array.isArray(parsed)?parsed:[parsed];if(entries.length===0)throw new PmCliError(`${optionName} array must include at least one linked-test entry object`,EXIT_CODE.USAGE);return entries.map((entry,index)=>parseLinkedTestJsonEntry(entry,entries.length>1?`entry ${index+1}`:"entry",optionName))}const _testOnlyLinkedTestParsers={parseLinkedTestJsonEntry};export{LINKED_TEST_ENV_NAME_PATTERN,LINKED_TEST_PM_CONTEXT_MODE_VALUES,LINKED_TEST_PROTECTED_ENV_KEYS,LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES,_testOnlyLinkedTestParsers,parseLinkedTestAssertionEqualsMap,parseLinkedTestAssertionGteMap,parseLinkedTestBoolean,parseLinkedTestContextMode,parseLinkedTestEnvClear,parseLinkedTestEnvSet,parseLinkedTestJsonEntries,parseLinkedTestMinLines,parseLinkedTestRegexList,parseLinkedTestStringList,parseLinkedTestWorkspaceContextMode};
2
2
  //# sourceMappingURL=parsers.js.map
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e7f8a7ea-3ec2-521b-ad52-45b655208f06")}catch(e2){}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import os from"node:os";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{readAuthorEnvironment}from"../../core/shared/author.js";import{getBackgroundTestRunStatus,listBackgroundTestRuns,readBackgroundTestRunLogs,resumeBackgroundTestRun,runBackgroundTestRunWorker,spawnBackgroundTestRunWorker,startBackgroundTestRun,stopBackgroundTestRun}from"../../core/test/background-runs.js";import{resolveGlobalPmRoot,resolvePmRoot}from"../../core/store/paths.js";import{readSettings}from"../../core/store/settings.js";import{parseLimit}from"../../core/shared/numeric-parsers.js";const BACKGROUND_STATUS_VALUES=["queued","running","passed","failed","stopped","canceled"];const BACKGROUND_STREAM_VALUES=["stdout","stderr","both"];function normalizeStatus(value){if(value===void 0){return void 0}const normalized=value.trim().toLowerCase();if(BACKGROUND_STATUS_VALUES.includes(normalized)){return normalized}throw new PmCliError(`Invalid --status value "${value}"`,EXIT_CODE.USAGE)}function normalizeStream(value){if(value===void 0||value.trim().length===0){return"stderr"}const normalized=value.trim().toLowerCase();if(BACKGROUND_STREAM_VALUES.includes(normalized)){return normalized}throw new PmCliError(`Invalid --stream value "${value}"`,EXIT_CODE.USAGE)}function resolveWhoamiFallback(){try{const username=os.userInfo().username.trim();if(username.length>0){return username}}catch{}return void 0}function resolveRequestedBy(author,fallback){const candidates=[author,readAuthorEnvironment(),fallback,process.env.USER,process.env.LOGNAME,process.env.USERNAME,resolveWhoamiFallback()];for(const candidate of candidates){if(typeof candidate!=="string"){continue}const trimmed=candidate.trim();if(trimmed.length>0){return trimmed}}return"unknown"}async function ensureInitialized(pmRoot){await assertInitializedTracker(pmRoot)}async function runStartBackgroundRun(options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);const globalPmRoot=resolveGlobalPmRoot(process.cwd());await ensureInitialized(pmRoot);const settings=await readSettings(pmRoot);const requestedBy=resolveRequestedBy(options.author,settings.author_default);const started=await startBackgroundTestRun({pmRoot,globalPmRoot,kind:options.kind,commandArgs:options.commandArgs,requestedBy,targetId:options.targetId,statusFilter:options.statusFilter});if(!started.started){return{started:false,duplicate_of:started.duplicate_of,run:started.run}}const spawned=await spawnBackgroundTestRunWorker({pmRoot,runId:started.run.id,noExtensions:options.noExtensions===true});return{started:true,run:spawned}}async function runTestRunsList(options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await ensureInitialized(pmRoot);const status=normalizeStatus(options.status);const limit=parseLimit(options.limit,"limit");const runs=await listBackgroundTestRuns(pmRoot,{status,limit});return{runs,count:runs.length,filters:{status,limit}}}async function runTestRunsStatus(runId,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await ensureInitialized(pmRoot);const status=await getBackgroundTestRunStatus(pmRoot,runId);return{run:status.run,health:status.health}}async function runTestRunsLogs(runId,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await ensureInitialized(pmRoot);const stream=normalizeStream(options.stream);const tail=parseLimit(options.tail,"tail");const logs=await readBackgroundTestRunLogs(pmRoot,runId,stream,tail);return{run:logs.run,stream:logs.stream,tail:logs.tail,stdout:logs.stdout,stderr:logs.stderr}}async function runTestRunsStop(runId,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await ensureInitialized(pmRoot);const stopped=await stopBackgroundTestRun(pmRoot,runId,options.force===true);return{run:stopped.run,signal_sent:stopped.signal_sent}}async function runTestRunsResume(runId,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await ensureInitialized(pmRoot);const settings=await readSettings(pmRoot);const requestedBy=resolveRequestedBy(options.author,settings.author_default);const resumed=await resumeBackgroundTestRun(pmRoot,runId,requestedBy,options.noExtensions===true);return{resumed_from:runId,run:resumed}}async function runTestRunsWorker(runId,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await ensureInitialized(pmRoot);const finished=await runBackgroundTestRunWorker(pmRoot,runId,global2.noExtensions===true);return{id:finished.id,status:finished.status,exit_code:finished.exit_code}}export{runStartBackgroundRun,runTestRunsList,runTestRunsLogs,runTestRunsResume,runTestRunsStatus,runTestRunsStop,runTestRunsWorker};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="8e9a2374-d190-52e1-8afd-14e1954863f0")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import os from"node:os";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{readAuthorEnvironment}from"../../core/shared/author.js";import{getBackgroundTestRunStatus,listBackgroundTestRuns,readBackgroundTestRunLogs,resumeBackgroundTestRun,runBackgroundTestRunWorker,spawnBackgroundTestRunWorker,startBackgroundTestRun,stopBackgroundTestRun}from"../../core/test/background-runs.js";import{resolveGlobalPmRoot,resolvePmRoot}from"../../core/store/paths.js";import{readSettings}from"../../core/store/settings.js";import{parseLimit}from"../../core/shared/numeric-parsers.js";const BACKGROUND_STATUS_VALUES=["queued","running","passed","failed","stopped","canceled"],BACKGROUND_STREAM_VALUES=["stdout","stderr","both"];function normalizeStatus(value){if(value===void 0)return;const normalized=value.trim().toLowerCase();if(BACKGROUND_STATUS_VALUES.includes(normalized))return normalized;throw new PmCliError(`Invalid --status value "${value}"`,EXIT_CODE.USAGE)}function normalizeStream(value){if(value===void 0||value.trim().length===0)return"stderr";const normalized=value.trim().toLowerCase();if(BACKGROUND_STREAM_VALUES.includes(normalized))return normalized;throw new PmCliError(`Invalid --stream value "${value}"`,EXIT_CODE.USAGE)}function resolveWhoamiFallback(){try{const username=os.userInfo().username.trim();if(username.length>0)return username}catch{}}function resolveRequestedBy(author,fallback){const candidates=[author,readAuthorEnvironment(),fallback,process.env.USER,process.env.LOGNAME,process.env.USERNAME,resolveWhoamiFallback()];for(const candidate of candidates){if(typeof candidate!="string")continue;const trimmed=candidate.trim();if(trimmed.length>0)return trimmed}return"unknown"}async function ensureInitialized(pmRoot){await assertInitializedTracker(pmRoot)}async function runStartBackgroundRun(options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path),globalPmRoot=resolveGlobalPmRoot(process.cwd());await ensureInitialized(pmRoot);const settings=await readSettings(pmRoot),requestedBy=resolveRequestedBy(options.author,settings.author_default),started=await startBackgroundTestRun({pmRoot,globalPmRoot,kind:options.kind,commandArgs:options.commandArgs,requestedBy,targetId:options.targetId,statusFilter:options.statusFilter});return started.started?{started:!0,run:await spawnBackgroundTestRunWorker({pmRoot,runId:started.run.id,noExtensions:options.noExtensions===!0})}:{started:!1,duplicate_of:started.duplicate_of,run:started.run}}async function runTestRunsList(options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await ensureInitialized(pmRoot);const status=normalizeStatus(options.status),limit=parseLimit(options.limit,"limit"),runs=await listBackgroundTestRuns(pmRoot,{status,limit});return{runs,count:runs.length,filters:{status,limit}}}async function runTestRunsStatus(runId,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await ensureInitialized(pmRoot);const status=await getBackgroundTestRunStatus(pmRoot,runId);return{run:status.run,health:status.health}}async function runTestRunsLogs(runId,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await ensureInitialized(pmRoot);const stream=normalizeStream(options.stream),tail=parseLimit(options.tail,"tail"),logs=await readBackgroundTestRunLogs(pmRoot,runId,stream,tail);return{run:logs.run,stream:logs.stream,tail:logs.tail,stdout:logs.stdout,stderr:logs.stderr}}async function runTestRunsStop(runId,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await ensureInitialized(pmRoot);const stopped=await stopBackgroundTestRun(pmRoot,runId,options.force===!0);return{run:stopped.run,signal_sent:stopped.signal_sent}}async function runTestRunsResume(runId,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await ensureInitialized(pmRoot);const settings=await readSettings(pmRoot),requestedBy=resolveRequestedBy(options.author,settings.author_default),resumed=await resumeBackgroundTestRun(pmRoot,runId,requestedBy,options.noExtensions===!0);return{resumed_from:runId,run:resumed}}async function runTestRunsWorker(runId,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await ensureInitialized(pmRoot);const finished=await runBackgroundTestRunWorker(pmRoot,runId,global2.noExtensions===!0);return{id:finished.id,status:finished.status,exit_code:finished.exit_code}}export{runStartBackgroundRun,runTestRunsList,runTestRunsLogs,runTestRunsResume,runTestRunsStatus,runTestRunsStop,runTestRunsWorker};
2
2
  //# sourceMappingURL=runs.js.map