@unbrained/pm-cli 2026.8.21 → 2026.8.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +44 -0
  3. package/dist/cli/error-guidance.d.ts +22 -4
  4. package/dist/cli/error-guidance.js +73 -16
  5. package/dist/cli/main.d.ts +3 -0
  6. package/dist/cli/main.js +51 -9
  7. package/dist/cli/register-mutation.js +6 -6
  8. package/dist/cli/register-operations.d.ts +73 -0
  9. package/dist/cli/register-operations.js +39 -14
  10. package/dist/cli/register-setup.js +3 -3
  11. package/dist/cli/schema-registration-helpers.d.ts +8 -1
  12. package/dist/cli/schema-registration-helpers.js +14 -5
  13. package/dist/cli-bundle/bundle-manifest.json +149 -149
  14. package/dist/cli-bundle/chunks/chunk-3ENVHX6C.js +36 -0
  15. package/dist/cli-bundle/chunks/{chunk-LOVTQ52Z.js → chunk-DW2CGEMU.js} +2 -2
  16. package/dist/cli-bundle/chunks/chunk-EG6CLDZT.js +5 -0
  17. package/dist/cli-bundle/chunks/{chunk-LARJJ3RK.js → chunk-F3AI2JFL.js} +2 -2
  18. package/dist/cli-bundle/chunks/{chunk-N3DSV4CH.js → chunk-HWZ6CELB.js} +8 -8
  19. package/dist/cli-bundle/chunks/chunk-HZBMLSZI.js +201 -0
  20. package/dist/cli-bundle/chunks/chunk-JB4KZWBF.js +3 -0
  21. package/dist/cli-bundle/chunks/chunk-KPH73XXJ.js +2 -0
  22. package/dist/cli-bundle/chunks/{chunk-BKYB45NQ.js → chunk-KXPMB2YL.js} +50 -50
  23. package/dist/cli-bundle/chunks/{chunk-BUNIEJNE.js → chunk-QDVHNHAQ.js} +2 -2
  24. package/dist/cli-bundle/chunks/chunk-TFI5V5N2.js +13 -0
  25. package/dist/cli-bundle/chunks/{register-list-query-F57EWDEF.js → register-list-query-UJB5FMV2.js} +2 -2
  26. package/dist/cli-bundle/chunks/register-mutation-NX5XE4VX.js +20 -0
  27. package/dist/cli-bundle/chunks/register-operations-RXIJIYXC.js +2 -0
  28. package/dist/cli-bundle/chunks/{register-setup-HXU7IZZD.js → register-setup-GFUZEKRE.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-F4YEW5I2.js → chunk-37Z4OEAP.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/chunk-3UPTYG44.js +8 -0
  31. package/dist/cli-bundle/focused-chunks/chunk-5S7E72FY.js +16 -0
  32. package/dist/cli-bundle/focused-chunks/{chunk-4ERLO7QD.js → chunk-AUFH5H35.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/chunk-E7X25GC3.js +2 -0
  34. package/dist/cli-bundle/focused-chunks/chunk-FQCSTBWE.js +4 -0
  35. package/dist/cli-bundle/focused-chunks/{chunk-FH6DYED3.js → chunk-FZS4H32O.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/chunk-IFLWKY2R.js +156 -0
  37. package/dist/cli-bundle/focused-chunks/{chunk-YKBKIEAJ.js → chunk-JOWDB2MH.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/chunk-LYVSW5VM.js +2 -0
  39. package/dist/cli-bundle/focused-chunks/chunk-MRCNF3U6.js +2 -0
  40. package/dist/cli-bundle/focused-chunks/{chunk-UZE7XUZK.js → chunk-OFVUGTLJ.js} +2 -2
  41. package/dist/cli-bundle/focused-chunks/{chunk-FJ22HNRP.js → chunk-OGLQBL46.js} +2 -2
  42. package/dist/cli-bundle/focused-chunks/chunk-OY7QAV4Y.js +51 -0
  43. package/dist/cli-bundle/focused-chunks/chunk-QGFNI65N.js +26 -0
  44. package/dist/cli-bundle/focused-chunks/{chunk-KDNG7TKQ.js → chunk-R27IDGHD.js} +2 -2
  45. package/dist/cli-bundle/focused-chunks/chunk-UYRFYCDQ.js +5 -0
  46. package/dist/cli-bundle/focused-chunks/{chunk-2NIY5NKG.js → chunk-ZHVA42R5.js} +9 -9
  47. package/dist/cli-bundle/main.js +13 -13
  48. package/dist/cli-bundle/sdk-authoring.js +1 -1
  49. package/dist/cli-bundle/sdk-contracts.js +2 -2
  50. package/dist/cli-bundle/sdk-core.js +40 -40
  51. package/dist/cli-bundle/sdk-governance.js +1 -1
  52. package/dist/cli-bundle/sdk-graph.js +1 -1
  53. package/dist/cli-bundle/sdk-merge.js +33 -32
  54. package/dist/cli-bundle/sdk-query.js +1 -1
  55. package/dist/cli-bundle/sdk-runtime.js +1 -1
  56. package/dist/cli-bundle/sdk-testing.js +1 -1
  57. package/dist/cli-bundle/sdk.js +5 -5
  58. package/dist/core/config/nested-settings.js +8 -2
  59. package/dist/core/config/positional-value.d.ts +1 -1
  60. package/dist/core/config/positional-value.js +5 -2
  61. package/dist/core/extensions/extension-hook-runtime.js +22 -20
  62. package/dist/core/extensions/extension-types.d.ts +8 -1
  63. package/dist/core/extensions/extension-types.js +2 -2
  64. package/dist/core/extensions/loader.js +7 -3
  65. package/dist/core/extensions/service-ownership.d.ts +8 -0
  66. package/dist/core/extensions/service-ownership.js +20 -0
  67. package/dist/core/history/history.js +3 -3
  68. package/dist/core/item/id.js +20 -5
  69. package/dist/core/item/item-format.js +81 -2
  70. package/dist/core/reproducibility/context.d.ts +4 -0
  71. package/dist/core/reproducibility/context.js +14 -8
  72. package/dist/core/shared/author.d.ts +55 -1
  73. package/dist/core/shared/author.js +333 -16
  74. package/dist/core/shared/constants.js +3 -2
  75. package/dist/core/shared/errors.d.ts +4 -0
  76. package/dist/core/shared/errors.js +2 -2
  77. package/dist/core/store/settings-validator.d.ts +1 -0
  78. package/dist/core/store/settings-validator.js +6 -3
  79. package/dist/core/store/settings.js +5 -2
  80. package/dist/mcp/server.d.ts +1 -1
  81. package/dist/mcp/server.js +30 -9
  82. package/dist/sdk/agent/identity-config.d.ts +63 -0
  83. package/dist/sdk/agent/identity-config.js +107 -0
  84. package/dist/sdk/agent/refusal-corpus-contracts.d.ts +76 -0
  85. package/dist/sdk/agent/refusal-corpus-contracts.js +194 -0
  86. package/dist/sdk/agent/refusal-reachability.d.ts +1 -1
  87. package/dist/sdk/authoring.d.ts +1 -1
  88. package/dist/sdk/authoring.js +2 -2
  89. package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +77 -0
  90. package/dist/sdk/cli-contracts/agent-output-contracts.js +326 -2
  91. package/dist/sdk/cli-contracts/commander-mutation-options.js +3 -3
  92. package/dist/sdk/cli-contracts/enum-contracts.d.ts +4 -0
  93. package/dist/sdk/cli-contracts/enum-contracts.js +9 -2
  94. package/dist/sdk/cli-contracts/flag-contracts.js +9 -2
  95. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +4 -4
  96. package/dist/sdk/cli-contracts/registration-helpers.js +5 -2
  97. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +3 -1
  98. package/dist/sdk/cli-contracts/runtime-contracts.js +4 -3
  99. package/dist/sdk/cli-contracts/tool-parameter-tables.js +22 -2
  100. package/dist/sdk/cli-contracts/tool-schema.d.ts +1 -1
  101. package/dist/sdk/cli-contracts/tool-schema.js +14 -3
  102. package/dist/sdk/cli-contracts.d.ts +4 -4
  103. package/dist/sdk/cli-contracts.js +5 -5
  104. package/dist/sdk/config.d.ts +6 -1
  105. package/dist/sdk/config.js +119 -14
  106. package/dist/sdk/context-intent-contracts.js +4 -2
  107. package/dist/sdk/core-governance.d.ts +1 -1
  108. package/dist/sdk/core-governance.js +3 -3
  109. package/dist/sdk/extension/install-sources.d.ts +1 -1
  110. package/dist/sdk/extension/install-sources.js +6 -3
  111. package/dist/sdk/extension/output-ownership.d.ts +1 -0
  112. package/dist/sdk/extension/output-ownership.js +3 -2
  113. package/dist/sdk/extension/scaffold.js +11 -5
  114. package/dist/sdk/flag-invocation-contracts.js +4 -2
  115. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +74 -2
  116. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +87 -26
  117. package/dist/sdk/governance/assurance-action.js +30 -10
  118. package/dist/sdk/governance/health.d.ts +3 -0
  119. package/dist/sdk/governance/health.js +39 -7
  120. package/dist/sdk/governance/hierarchy-validation.d.ts +29 -0
  121. package/dist/sdk/governance/hierarchy-validation.js +109 -0
  122. package/dist/sdk/governance/validate.d.ts +3 -9
  123. package/dist/sdk/governance/validate.js +84 -111
  124. package/dist/sdk/graph/assembly.d.ts +6 -1
  125. package/dist/sdk/graph/assembly.js +16 -22
  126. package/dist/sdk/graph/governance-contracts.d.ts +1 -1
  127. package/dist/sdk/graph/governance-contracts.js +8 -2
  128. package/dist/sdk/graph/governance.js +46 -2
  129. package/dist/sdk/graph/hierarchy-integrity.d.ts +94 -0
  130. package/dist/sdk/graph/hierarchy-integrity.js +311 -0
  131. package/dist/sdk/graph/index.d.ts +2 -1
  132. package/dist/sdk/graph/index.js +3 -2
  133. package/dist/sdk/graph/remediation.js +32 -2
  134. package/dist/sdk/graph/run.d.ts +31 -2
  135. package/dist/sdk/graph/run.js +80 -31
  136. package/dist/sdk/graph/workspace-relationship-kind-registry.d.ts +8 -0
  137. package/dist/sdk/graph/workspace-relationship-kind-registry.js +28 -0
  138. package/dist/sdk/index.d.ts +8 -3
  139. package/dist/sdk/index.js +9 -4
  140. package/dist/sdk/item-children.js +21 -8
  141. package/dist/sdk/lifecycle/create.js +129 -97
  142. package/dist/sdk/lifecycle/hierarchy-mutation-lock.d.ts +15 -0
  143. package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +25 -0
  144. package/dist/sdk/lifecycle/update.d.ts +2 -0
  145. package/dist/sdk/lifecycle/update.js +174 -84
  146. package/dist/sdk/merge/three-way.js +105 -26
  147. package/dist/sdk/query/complete-list.d.ts +3 -3
  148. package/dist/sdk/query/complete-list.js +46 -3
  149. package/dist/sdk/query/list.d.ts +4 -3
  150. package/dist/sdk/query/list.js +89 -49
  151. package/dist/sdk/read-output-budget.d.ts +21 -0
  152. package/dist/sdk/read-output-budget.js +39 -2
  153. package/dist/sdk/read-output-contracts.d.ts +10 -4
  154. package/dist/sdk/read-output-contracts.js +105 -32
  155. package/dist/sdk/relationship-context.js +3 -4
  156. package/dist/sdk/relationships.js +17 -10
  157. package/dist/sdk/reproducibility/process.d.ts +19 -0
  158. package/dist/sdk/reproducibility/process.js +88 -0
  159. package/dist/sdk/runtime-primitives.d.ts +1 -1
  160. package/dist/sdk/runtime-primitives.js +3 -3
  161. package/dist/sdk/runtime.d.ts +3 -2
  162. package/dist/sdk/runtime.js +7 -5
  163. package/dist/sdk/test/batch.d.ts +6 -0
  164. package/dist/sdk/test/batch.js +26 -6
  165. package/dist/sdk/test/entry.d.ts +1 -1
  166. package/dist/sdk/test/entry.js +3 -2
  167. package/dist/sdk/test/execution.d.ts +28 -3
  168. package/dist/sdk/test/execution.js +201 -34
  169. package/dist/sdk/test/parsers.d.ts +6 -0
  170. package/dist/sdk/test/parsers.js +21 -2
  171. package/dist/sdk/test/trust.d.ts +33 -0
  172. package/dist/sdk/test/trust.js +207 -0
  173. package/dist/types.d.ts +34 -0
  174. package/dist/types.js +2 -2
  175. package/docs/AGENT_PROVENANCE_ADR.md +41 -5
  176. package/docs/AGENT_UX_CONTRACTS.md +20 -4
  177. package/docs/COMMANDS.md +29 -14
  178. package/docs/CONFIGURATION.md +4 -0
  179. package/docs/DEPENDENCY_KIND_CONTRACT.md +31 -3
  180. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +115 -0
  181. package/docs/EXTENSIONS.md +2 -1
  182. package/docs/MERGE_SAFETY.md +15 -1
  183. package/docs/README.md +1 -0
  184. package/docs/READ_OUTPUT_CONTRACTS.md +19 -2
  185. package/docs/RELATIONSHIP_GRAPH.md +6 -3
  186. package/docs/REPRODUCIBLE_WORKSPACES.md +42 -8
  187. package/docs/SDK.md +9 -0
  188. package/docs/SDK_AGENT_SESSION_CONTEXT.md +6 -4
  189. package/docs/SDK_EVIDENCE_TRACEABILITY.md +1 -1
  190. package/docs/TESTING.md +83 -1
  191. package/docs/agent-task-token-baseline.json +2 -2
  192. package/docs/generated/FLAG_LEXICON_BUDGETS.md +2 -2
  193. package/marketplace.json +2 -2
  194. package/package.json +2 -2
  195. package/packages/pm-beads/package.json +1 -1
  196. package/packages/pm-calendar/package.json +1 -1
  197. package/packages/pm-command-kit/package.json +1 -1
  198. package/packages/pm-digital-twin/package.json +1 -1
  199. package/packages/pm-governance-audit/package.json +1 -1
  200. package/packages/pm-guide-shell/package.json +1 -1
  201. package/packages/pm-kanban/package.json +1 -1
  202. package/packages/pm-lifecycle-hooks/package.json +1 -1
  203. package/packages/pm-linked-test-adapters/package.json +1 -1
  204. package/packages/pm-search-advanced/package.json +1 -1
  205. package/packages/pm-templates/package.json +1 -1
  206. package/packages/pm-todos/package.json +1 -1
  207. package/packages/pm-vcs/package.json +1 -1
  208. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  209. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  210. package/sdk/public-surface.json +1021 -53
  211. package/dist/cli-bundle/chunks/chunk-2MA6ZQVZ.js +0 -197
  212. package/dist/cli-bundle/chunks/chunk-3AFAUHUE.js +0 -2
  213. package/dist/cli-bundle/chunks/chunk-7VHZS727.js +0 -5
  214. package/dist/cli-bundle/chunks/chunk-JSLOFXGA.js +0 -3
  215. package/dist/cli-bundle/chunks/chunk-OCLPLFAY.js +0 -35
  216. package/dist/cli-bundle/chunks/chunk-S4IRYKBU.js +0 -13
  217. package/dist/cli-bundle/chunks/register-mutation-7IY2D5KO.js +0 -20
  218. package/dist/cli-bundle/chunks/register-operations-FALL3YTU.js +0 -2
  219. package/dist/cli-bundle/focused-chunks/chunk-7WZRLCYF.js +0 -50
  220. package/dist/cli-bundle/focused-chunks/chunk-CKKQSJNN.js +0 -2
  221. package/dist/cli-bundle/focused-chunks/chunk-EEFKYMDR.js +0 -16
  222. package/dist/cli-bundle/focused-chunks/chunk-F2A56DHV.js +0 -8
  223. package/dist/cli-bundle/focused-chunks/chunk-FV5ACOK7.js +0 -2
  224. package/dist/cli-bundle/focused-chunks/chunk-JEAVFOWM.js +0 -2
  225. package/dist/cli-bundle/focused-chunks/chunk-NJ63LOP6.js +0 -155
  226. package/dist/cli-bundle/focused-chunks/chunk-NXRTQ7HI.js +0 -2
  227. package/dist/cli-bundle/focused-chunks/chunk-TJ7EMJ46.js +0 -4
  228. package/dist/cli-bundle/focused-chunks/chunk-ZOSEELYJ.js +0 -26
@@ -4,10 +4,10 @@
4
4
  * Implements the pm test command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="2354c553-3a81-59d8-9c0a-3d19cd3cedd2")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7659721c-21f5-55da-8cce-31b290de5bfb")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
9
  import { spawn } from "node:child_process";
10
- import { cp, mkdir, mkdtemp, open, readdir, rm } from "node:fs/promises";
10
+ import { cp, mkdir, mkdtemp, open, readdir, rm, symlink, } from "node:fs/promises";
11
11
  import { tmpdir } from "node:os";
12
12
  import path from "node:path";
13
13
  import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
@@ -25,12 +25,13 @@ import { readSettings } from "../../core/store/settings.js";
25
25
  import { appendTrackedTestRunSummary, buildTrackedTestRunHistory, } from "../../core/test/item-test-run-tracking.js";
26
26
  import { runInit } from "../init.js";
27
27
  import { looksLikeStructuredLinkedTestEntry, normalizeStructuredLinkedTestEntry, } from "./entry.js";
28
- 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, } from "./parsers.js";
28
+ 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";
29
29
  import { parseOnlyIndexValue, resolveLinkedTestRunSelection, } from "../../core/test/run-selectors.js";
30
30
  import { SCOPE_VALUES } from "../../types/index.js";
31
31
  import { diffTestRunMeasurements, parseTestRunMeasurements, queryTestRunMeasurementsBelow, } from "./measurements.js";
32
32
  import { withHostEnvironmentBoundary } from "../environment/host-environment-errors.js";
33
33
  import { SOURCE_CONTEXT_ACCESS_ENV } from "../environment/source-context.js";
34
+ import { acknowledgeLinkedTests, attachLinkedTestMutationProvenance, resolveLinkedTestSourceRef, resolveLinkedTestSourceWorkspaceRoot, resolveLinkedTestTrust, } from "./trust.js";
34
35
  const TEST_OUTPUT_MAX_BUFFER_BYTES = 20 * 1024 * 1024;
35
36
  const DEFAULT_LINKED_TEST_TIMEOUT_FORCE_KILL_DELAY_MS = 3000;
36
37
  const DEFAULT_LINKED_TEST_HEARTBEAT_INTERVAL_MS = 10000;
@@ -170,6 +171,15 @@ function parsePmContextMode(raw) {
170
171
  }
171
172
  throw new PmCliError(`Invalid --pm-context value "${raw}". Expected one of: ${PM_CONTEXT_MODE_VALUES.join(", ")}`, EXIT_CODE.USAGE);
172
173
  }
174
+ function parseWorkspaceContextMode(raw) {
175
+ return parseLinkedTestWorkspaceContextMode(raw ?? "source", "--workspace-context");
176
+ }
177
+ function resolveLinkedTestWorkspaceContextMode(linkedTest, runLevelMode, overrideLinkedMode) {
178
+ if (overrideLinkedMode) {
179
+ return runLevelMode;
180
+ }
181
+ return (parseLinkedTestWorkspaceContextMode(linkedTest.workspace_context_mode, "linked test") ?? runLevelMode);
182
+ }
173
183
  function resolveLinkedTestRequestedContextMode(linkedTest, runLevelMode, overrideLinkedPmContext) {
174
184
  if (overrideLinkedPmContext) {
175
185
  return runLevelMode;
@@ -460,6 +470,7 @@ function parseAddEntry(entry) {
460
470
  scope: ensureScope(kv.scope),
461
471
  timeout_seconds: parseLinkedTestTimeoutSeconds(trimLinkedTestEntryField(kv.timeout_seconds), trimLinkedTestEntryField(kv.timeout)),
462
472
  pm_context_mode: parseLinkedTestContextModeValue(trimLinkedTestEntryField(kv.pm_context_mode), "--add"),
473
+ workspace_context_mode: parseLinkedTestWorkspaceContextMode(trimLinkedTestEntryField(kv.workspace_context_mode), "--add"),
463
474
  env_set: parseLinkedTestEnvSetValue(trimLinkedTestEntryField(kv.env_set), "--add"),
464
475
  env_clear: parseLinkedTestEnvClearValue(trimLinkedTestEntryField(kv.env_clear), "--add"),
465
476
  shared_host_safe: parseLinkedTestBooleanValue(trimLinkedTestEntryField(kv.shared_host_safe), "--add", "shared_host_safe"),
@@ -760,9 +771,9 @@ function waitForLinkedTestChildClose(child) {
760
771
  });
761
772
  });
762
773
  }
763
- function createLinkedTestChild(command, env, stdoutFd, stderrFd) {
774
+ function createLinkedTestChild(command, env, stdoutFd, stderrFd, cwd) {
764
775
  return spawn(command, {
765
- cwd: process.cwd(),
776
+ cwd,
766
777
  env,
767
778
  shell: true,
768
779
  windowsHide: true,
@@ -791,7 +802,7 @@ async function readLinkedTestCapture(capturePath) {
791
802
  await handle.close();
792
803
  }
793
804
  }
794
- async function runLinkedTestCommand(command, timeoutMs, env, progressContext, progressMode) {
805
+ async function runLinkedTestCommand(command, timeoutMs, env, progressContext, progressMode, cwd = process.cwd()) {
795
806
  const startedAt = Date.now();
796
807
  const captureRoot = await mkdtemp(path.join(tmpdir(), "pm-linked-test-output-"));
797
808
  try {
@@ -803,7 +814,7 @@ async function runLinkedTestCommand(command, timeoutMs, env, progressContext, pr
803
814
  ]);
804
815
  let child;
805
816
  try {
806
- child = createLinkedTestChild(command, env, stdoutHandle.fd, stderrHandle.fd);
817
+ child = createLinkedTestChild(command, env, stdoutHandle.fd, stderrHandle.fd, cwd);
807
818
  }
808
819
  finally {
809
820
  await Promise.all([stdoutHandle.close(), stderrHandle.close()]);
@@ -902,6 +913,7 @@ export function classifyLinkedTestFailure(result) {
902
913
  function createEmptyFailureCategoryCounts() {
903
914
  return {
904
915
  infra_collision: 0,
916
+ trust_refusal: 0,
905
917
  assertion_failure: 0,
906
918
  empty_run: 0,
907
919
  timeout: 0,
@@ -1264,8 +1276,48 @@ function createLinkedTestSandboxLayout(sandboxRoot) {
1264
1276
  schemaGlobalPmPath: path.join(sandboxRoot, "schema", "global"),
1265
1277
  trackerProjectPmPath: path.join(sandboxRoot, "tracker", "project", ".agents", "pm"),
1266
1278
  trackerGlobalPmPath: path.join(sandboxRoot, "tracker", "global"),
1279
+ workspaceSnapshotRoot: path.join(sandboxRoot, "workspace", "project"),
1280
+ workspaceIsolatedRoot: path.join(sandboxRoot, "workspace", "isolated"),
1267
1281
  };
1268
1282
  }
1283
+ function linkedTestsRequireWorkspaceSnapshot(tests, runLevelMode, overrideLinkedMode) {
1284
+ return tests.some((linkedTest) => resolveLinkedTestWorkspaceContextMode(linkedTest, runLevelMode, overrideLinkedMode) === "snapshot");
1285
+ }
1286
+ async function seedLinkedTestWorkspaceSnapshot(layout, sourceWorkspaceRoot) {
1287
+ const excludedSegments = new Set([
1288
+ ".agents",
1289
+ ".git",
1290
+ ".nyc_output",
1291
+ ".turbo",
1292
+ "coverage",
1293
+ "node_modules",
1294
+ ]);
1295
+ await mkdir(path.dirname(layout.workspaceSnapshotRoot), { recursive: true });
1296
+ await cp(sourceWorkspaceRoot, layout.workspaceSnapshotRoot, {
1297
+ recursive: true,
1298
+ force: true,
1299
+ filter(source) {
1300
+ const relative = path.relative(sourceWorkspaceRoot, source);
1301
+ if (!relative) {
1302
+ return true;
1303
+ }
1304
+ return !relative
1305
+ .split(path.sep)
1306
+ .some((segment) => excludedSegments.has(segment));
1307
+ },
1308
+ });
1309
+ const sourceNodeModules = path.join(sourceWorkspaceRoot, "node_modules");
1310
+ if (await pathExists(sourceNodeModules)) {
1311
+ await symlink(sourceNodeModules, path.join(layout.workspaceSnapshotRoot, "node_modules"), process.platform === "win32" ? "junction" : "dir");
1312
+ }
1313
+ }
1314
+ async function bindSnapshotTracker(snapshotRoot, sandboxPmPath) {
1315
+ const agentsRoot = path.join(snapshotRoot, ".agents");
1316
+ const target = path.join(agentsRoot, "pm");
1317
+ await mkdir(agentsRoot, { recursive: true });
1318
+ await rm(target, { recursive: true, force: true });
1319
+ await symlink(sandboxPmPath, target, process.platform === "win32" ? "junction" : "dir");
1320
+ }
1269
1321
  async function initializeLinkedTestSandboxes(layout, initialize = runInit, includeTrackerData = true) {
1270
1322
  const initOptions = { defaults: true, agentGuidance: "skip" };
1271
1323
  await initialize(undefined, { path: layout.schemaProjectPmPath }, initOptions);
@@ -1326,6 +1378,12 @@ function buildLinkedTestExecutionContext(params) {
1326
1378
  const selectedSandboxGlobalItemCount = trackerMode
1327
1379
  ? params.counts.trackerGlobalItemCount
1328
1380
  : params.counts.schemaGlobalItemCount;
1381
+ const workingDirectory = params.workspaceContextMode === "snapshot"
1382
+ ? params.layout.workspaceSnapshotRoot
1383
+ : params.workspaceContextMode === "isolated"
1384
+ ? params.layout.workspaceIsolatedRoot
1385
+ : params.sourceWorkspaceRoot;
1386
+ const exposedSourceWorkspaceRoot = params.workspaceContextMode === "isolated" ? "" : workingDirectory;
1329
1387
  return {
1330
1388
  requested_pm_context_mode: params.requestedPmContextMode,
1331
1389
  pm_context_mode: params.effectivePmContextMode,
@@ -1346,9 +1404,14 @@ function buildLinkedTestExecutionContext(params) {
1346
1404
  params.counts.sourceGlobalItemCount !== selectedSandboxGlobalItemCount),
1347
1405
  project_extensions_seeded: Boolean(params.sourceRoots),
1348
1406
  global_extensions_seeded: Boolean(params.sourceRoots),
1407
+ requested_workspace_context_mode: params.requestedWorkspaceContextMode,
1408
+ workspace_context_mode: params.workspaceContextMode,
1409
+ working_directory: workingDirectory,
1410
+ source_workspace_root: exposedSourceWorkspaceRoot,
1411
+ trust: params.trust,
1349
1412
  };
1350
1413
  }
1351
- function resolveLinkedTestCommandContext(params) {
1414
+ async function resolveLinkedTestCommandContext(params) {
1352
1415
  const linkedOverridePmContextMode = typeof params.linkedTest.pm_context_mode === "string" &&
1353
1416
  params.linkedTest.pm_context_mode.trim().length > 0
1354
1417
  ? parsePmContextMode(params.linkedTest.pm_context_mode)
@@ -1366,6 +1429,15 @@ function resolveLinkedTestCommandContext(params) {
1366
1429
  ? "auto"
1367
1430
  : resolveLinkedTestRequestedContextMode(params.linkedTest, params.runLevelPmContextMode, params.options?.overrideLinkedPmContext === true);
1368
1431
  const effectivePmContextMode = resolveLinkedTestEffectiveContextMode(requestedPmContextMode, isPmTrackerReadCommand);
1432
+ const selectedSandboxProjectPmPath = effectivePmContextMode === "tracker"
1433
+ ? params.layout.trackerProjectPmPath
1434
+ : params.layout.schemaProjectPmPath;
1435
+ if (params.workspaceContextMode === "snapshot") {
1436
+ await bindSnapshotTracker(params.layout.workspaceSnapshotRoot, selectedSandboxProjectPmPath);
1437
+ }
1438
+ const trust = params.options?.pmRoot
1439
+ ? await resolveLinkedTestTrust(params.options.pmRoot, params.linkedTest, params.currentSourceRef)
1440
+ : await resolveLinkedTestTrust(params.layout.root, params.linkedTest, params.currentSourceRef);
1369
1441
  return {
1370
1442
  linkedOverridePmContextMode,
1371
1443
  executionContext: buildLinkedTestExecutionContext({
@@ -1377,6 +1449,10 @@ function resolveLinkedTestCommandContext(params) {
1377
1449
  requestedPmContextMode,
1378
1450
  effectivePmContextMode,
1379
1451
  autoPmContextApplied,
1452
+ requestedWorkspaceContextMode: params.requestedWorkspaceContextMode,
1453
+ workspaceContextMode: params.workspaceContextMode,
1454
+ sourceWorkspaceRoot: params.sourceWorkspaceRoot,
1455
+ trust,
1380
1456
  }),
1381
1457
  };
1382
1458
  }
@@ -1401,14 +1477,47 @@ function buildLinkedTestAssertionFailureResult(linkedTest, executionContext, err
1401
1477
  error,
1402
1478
  };
1403
1479
  }
1404
- function resolveLinkedTestPreflightResult(params) {
1480
+ function buildLinkedTestTrustRefusalResult(linkedTest, executionContext, error) {
1481
+ return {
1482
+ command: linkedTest.command,
1483
+ path: linkedTest.path,
1484
+ status: "failed",
1485
+ exit_code: 1,
1486
+ failure_category: "trust_refusal",
1487
+ execution_context: executionContext,
1488
+ error,
1489
+ };
1490
+ }
1491
+ /** Build the fail-closed result for a command this clone has not trusted. */
1492
+ function resolveLinkedTestTrustPreflightResult(params) {
1493
+ if (params.executionContext.trust.trusted)
1494
+ return null;
1495
+ const overrideRequested = params.options?.allowUntrustedLinkedTests === true;
1496
+ const policyEnabled = params.options?.untrustedLinkedTestsPolicyEnabled === true;
1497
+ if (overrideRequested && policyEnabled)
1498
+ return null;
1499
+ const recovery = policyEnabled
1500
+ ? "Retry with --allow-untrusted-linked-tests for this invocation, or acknowledge the current commands with --acknowledge-linked-tests."
1501
+ : "Set testing.allow_untrusted_linked_tests=true, then retry with --allow-untrusted-linked-tests; alternatively acknowledge the current commands with --acknowledge-linked-tests.";
1502
+ 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}`);
1503
+ }
1504
+ /** Resolve missing-command and runtime-safety skips before policy checks. */
1505
+ function resolveLinkedTestSafetyPreflightResult(params) {
1405
1506
  if (!params.linkedTest.command) {
1406
1507
  return buildLinkedTestSkippedResult(params.linkedTest, params.executionContext, "No command configured for this linked test.");
1407
1508
  }
1408
1509
  const runtimeSafetySkipReason = getRuntimeSafetySkipReason(params.linkedTest.command);
1409
- if (runtimeSafetySkipReason) {
1410
- return buildLinkedTestSkippedResult(params.linkedTest, params.executionContext, runtimeSafetySkipReason);
1411
- }
1510
+ return runtimeSafetySkipReason
1511
+ ? buildLinkedTestSkippedResult(params.linkedTest, params.executionContext, runtimeSafetySkipReason)
1512
+ : null;
1513
+ }
1514
+ function resolveLinkedTestPreflightResult(params) {
1515
+ const safetyFailure = resolveLinkedTestSafetyPreflightResult(params);
1516
+ if (safetyFailure)
1517
+ return safetyFailure;
1518
+ const trustFailure = resolveLinkedTestTrustPreflightResult(params);
1519
+ if (trustFailure)
1520
+ return trustFailure;
1412
1521
  const failOnMismatchByDefault = params.executionContext.pm_context_mode === "schema" &&
1413
1522
  params.executionContext.is_pm_tracker_read_command &&
1414
1523
  params.executionContext.mismatch_detected;
@@ -1451,11 +1560,20 @@ function buildLinkedTestExecutionEnv(params) {
1451
1560
  executionEnv.FORCE_COLOR = "0";
1452
1561
  executionEnv.PM_PATH = params.executionContext.sandbox_project_pm_path;
1453
1562
  executionEnv.PM_GLOBAL_PATH = params.executionContext.sandbox_global_pm_path;
1454
- executionEnv.PM_SOURCE_WORKSPACE_ROOT =
1455
- process.env.PM_SOURCE_WORKSPACE_ROOT ?? process.cwd();
1456
- executionEnv.PM_SOURCE_PM_PATH =
1457
- params.executionContext.source_project_pm_path;
1458
- executionEnv[SOURCE_CONTEXT_ACCESS_ENV] = "read_only";
1563
+ if (params.executionContext.workspace_context_mode === "isolated") {
1564
+ delete executionEnv.PM_SOURCE_WORKSPACE_ROOT;
1565
+ delete executionEnv.PM_SOURCE_PM_PATH;
1566
+ delete executionEnv[SOURCE_CONTEXT_ACCESS_ENV];
1567
+ }
1568
+ else {
1569
+ executionEnv.PM_SOURCE_WORKSPACE_ROOT =
1570
+ params.executionContext.source_workspace_root;
1571
+ executionEnv.PM_SOURCE_PM_PATH =
1572
+ params.executionContext.workspace_context_mode === "snapshot"
1573
+ ? params.executionContext.sandbox_project_pm_path
1574
+ : params.executionContext.source_project_pm_path;
1575
+ executionEnv[SOURCE_CONTEXT_ACCESS_ENV] = "read_only";
1576
+ }
1459
1577
  return executionEnv;
1460
1578
  }
1461
1579
  function buildLinkedTestPassedResult(linkedTest, executionContext, execution) {
@@ -1518,7 +1636,7 @@ async function runSingleLinkedTest(params) {
1518
1636
  total: params.total,
1519
1637
  timeoutMs,
1520
1638
  command,
1521
- }, params.progressMode);
1639
+ }, params.progressMode, params.executionContext.working_directory);
1522
1640
  const passed = execution.exitCode === 0 &&
1523
1641
  !execution.timedOut &&
1524
1642
  !execution.maxBufferExceeded;
@@ -1532,23 +1650,36 @@ export async function runLinkedTests(tests, defaultTimeoutSeconds, options) {
1532
1650
  const sandboxRoot = await mkdtemp(path.join(tmpdir(), "pm-linked-test-"));
1533
1651
  const layout = createLinkedTestSandboxLayout(sandboxRoot);
1534
1652
  const runLevelPmContextMode = parsePmContextMode(options?.pmContext);
1653
+ const runLevelWorkspaceContextMode = parseWorkspaceContextMode(options?.workspaceContext);
1535
1654
  const progressMode = options?.progress === true ? "always" : "auto";
1536
1655
  const runtimeDirectives = resolveRuntimeDirectives(options?.envSet, options?.envClear, options?.sharedHostSafe);
1537
1656
  const sourceRoots = options?.sourceRoots;
1657
+ const sourceWorkspaceRoot = resolveLinkedTestSourceWorkspaceRoot();
1538
1658
  const includeTrackerData = linkedTestsRequireTrackerData(tests, runLevelPmContextMode, options);
1659
+ const includeWorkspaceSnapshot = linkedTestsRequireWorkspaceSnapshot(tests, runLevelWorkspaceContextMode, options?.overrideLinkedWorkspaceContext === true);
1660
+ const currentSourceRef = await resolveLinkedTestSourceRef(sourceWorkspaceRoot);
1539
1661
  try {
1540
1662
  await initializeLinkedTestSandboxes(layout, runInit, includeTrackerData);
1663
+ await mkdir(layout.workspaceIsolatedRoot, { recursive: true });
1541
1664
  await seedLinkedTestSandboxesFromSource(layout, sourceRoots, includeTrackerData);
1665
+ if (includeWorkspaceSnapshot) {
1666
+ await seedLinkedTestWorkspaceSnapshot(layout, sourceWorkspaceRoot);
1667
+ }
1542
1668
  const counts = await countLinkedTestSandboxItems(layout, sourceRoots);
1543
1669
  for (let index = 0; index < tests.length; index += 1) {
1544
1670
  const linkedTest = tests[index];
1545
- const commandContext = resolveLinkedTestCommandContext({
1671
+ const workspaceContextMode = resolveLinkedTestWorkspaceContextMode(linkedTest, runLevelWorkspaceContextMode, options?.overrideLinkedWorkspaceContext === true);
1672
+ const commandContext = await resolveLinkedTestCommandContext({
1546
1673
  linkedTest,
1547
1674
  layout,
1548
1675
  counts,
1549
1676
  sourceRoots,
1550
1677
  runLevelPmContextMode,
1551
1678
  options,
1679
+ requestedWorkspaceContextMode: runLevelWorkspaceContextMode,
1680
+ workspaceContextMode,
1681
+ currentSourceRef,
1682
+ sourceWorkspaceRoot,
1552
1683
  });
1553
1684
  const preflightResult = resolveLinkedTestPreflightResult({
1554
1685
  linkedTest,
@@ -1602,7 +1733,8 @@ function linkedTestsHaveSameIdentity(left, right) {
1602
1733
  return (left.command === right.command &&
1603
1734
  left.path === right.path &&
1604
1735
  left.scope === right.scope &&
1605
- left.pm_context_mode === right.pm_context_mode);
1736
+ left.pm_context_mode === right.pm_context_mode &&
1737
+ left.workspace_context_mode === right.workspace_context_mode);
1606
1738
  }
1607
1739
  function appendMissingLinkedTests(current, additions) {
1608
1740
  const next = [...current];
@@ -1635,21 +1767,29 @@ function applyLinkedTestMutations(previous, adds, removes, removeIndexes) {
1635
1767
  return removeLinkedTestsBySelector(appendMissingLinkedTests(previous, adds), removes, removeIndexes);
1636
1768
  }
1637
1769
  function hasTestRuntimeDirectiveFlags(options) {
1638
- return ((options.envSet?.length ?? 0) > 0 ||
1639
- (options.envClear?.length ?? 0) > 0 ||
1640
- options.sharedHostSafe === true ||
1641
- options.pmContext !== undefined ||
1642
- options.overrideLinkedPmContext === true ||
1643
- options.failOnContextMismatch === true ||
1644
- options.failOnSkipped === true ||
1645
- options.failOnEmptyTestRun === true ||
1646
- options.requireAssertionsForPm === true ||
1647
- options.checkContext === true ||
1648
- options.autoPmContext === true);
1770
+ return [
1771
+ (options.envSet?.length ?? 0) > 0,
1772
+ (options.envClear?.length ?? 0) > 0,
1773
+ options.sharedHostSafe === true,
1774
+ options.pmContext !== undefined,
1775
+ options.overrideLinkedPmContext === true,
1776
+ options.failOnContextMismatch === true,
1777
+ options.failOnSkipped === true,
1778
+ options.failOnEmptyTestRun === true,
1779
+ options.requireAssertionsForPm === true,
1780
+ options.checkContext === true,
1781
+ options.autoPmContext === true,
1782
+ options.workspaceContext !== undefined,
1783
+ options.overrideLinkedWorkspaceContext === true,
1784
+ options.allowUntrustedLinkedTests === true,
1785
+ ].some(Boolean);
1649
1786
  }
1650
1787
  function assertTestRunFlagUsage(options) {
1651
1788
  if (hasTestRuntimeDirectiveFlags(options) && options.run !== true) {
1652
- throw new PmCliError("--env-set, --env-clear, --shared-host-safe, --pm-context, --override-linked-pm-context, --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);
1789
+ 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);
1790
+ }
1791
+ if (options.acknowledgeLinkedTests === true && options.run === true) {
1792
+ throw new PmCliError("--acknowledge-linked-tests records trust without executing commands; run it separately before --run", EXIT_CODE.USAGE);
1653
1793
  }
1654
1794
  const hasSelectorFlags = options.match !== undefined ||
1655
1795
  options.onlyIndex !== undefined ||
@@ -1749,6 +1889,11 @@ async function executeSelectedLinkedTests(params) {
1749
1889
  requireAssertionsForPm: options.requireAssertionsForPm,
1750
1890
  checkContext: options.checkContext,
1751
1891
  autoPmContext: options.autoPmContext,
1892
+ workspaceContext: options.workspaceContext,
1893
+ overrideLinkedWorkspaceContext: options.overrideLinkedWorkspaceContext,
1894
+ pmRoot,
1895
+ allowUntrustedLinkedTests: options.allowUntrustedLinkedTests,
1896
+ untrustedLinkedTestsPolicyEnabled: params.untrustedLinkedTestsPolicyEnabled,
1752
1897
  sourceRoots: {
1753
1898
  projectPmRoot: pmRoot,
1754
1899
  globalPmRoot: resolveGlobalPmRoot(process.cwd()),
@@ -1791,6 +1936,16 @@ function buildTrackedTestRunSummary(params) {
1791
1936
  skipped: summary.skipped,
1792
1937
  fail_on_skipped_triggered: params.failOnSkippedTriggered ? true : undefined,
1793
1938
  measurements: measurements.length > 0 ? measurements : undefined,
1939
+ executions: params.runResults
1940
+ .filter((result) => result.command?.trim())
1941
+ .slice(0, 32)
1942
+ .map((result) => ({
1943
+ command: result.command.trim(),
1944
+ requested_pm_context_mode: result.execution_context?.requested_pm_context_mode,
1945
+ pm_context_mode: result.execution_context?.pm_context_mode,
1946
+ workspace_context_mode: result.execution_context?.workspace_context_mode,
1947
+ trust_reason: result.execution_context?.trust.reason,
1948
+ })),
1794
1949
  };
1795
1950
  }
1796
1951
  async function recordTestRunSummary(params) {
@@ -1846,6 +2001,12 @@ function buildTestMeasurementProjection(options, runs, recordedRun) {
1846
2001
  : diffTestRunMeasurements(runs, options.metricDiff),
1847
2002
  };
1848
2003
  }
2004
+ /** Acknowledge current linked commands only when the dedicated mode is active. */
2005
+ async function maybeAcknowledgeLinkedTests(options, pmRoot, tests) {
2006
+ if (options.acknowledgeLinkedTests !== true)
2007
+ return undefined;
2008
+ return acknowledgeLinkedTests(pmRoot, tests, nowIso());
2009
+ }
1849
2010
  /** Implements run test for the public runtime surface of this module. */
1850
2011
  export async function runTest(id, options, global) {
1851
2012
  const stdinResolver = createStdinTokenResolver();
@@ -1861,10 +2022,11 @@ export async function runTest(id, options, global) {
1861
2022
  const resolvedAdds = await stdinResolver.resolveList(options.add, "--add");
1862
2023
  const resolvedAddJsons = await stdinResolver.resolveList(options.addJson, "--add-json");
1863
2024
  const resolvedRemoves = await stdinResolver.resolveList(options.remove, "--remove");
1864
- const adds = [
2025
+ const parsedAdds = [
1865
2026
  ...parseAddEntries(resolvedAdds),
1866
2027
  ...parseAddJsonEntries(resolvedAddJsons),
1867
2028
  ];
2029
+ const adds = (await attachLinkedTestMutationProvenance(parsedAdds, resolveAuthor(options.author, settings.author_default), nowIso())) ?? [];
1868
2030
  const removes = parseRemoveEntries(resolvedRemoves);
1869
2031
  const removeIndexes = parseRemoveIndexes(options.removeIndex);
1870
2032
  const item = await resolveLinkedTestItem({
@@ -1878,17 +2040,22 @@ export async function runTest(id, options, global) {
1878
2040
  removeIndexes,
1879
2041
  });
1880
2042
  const runOptions = resolveTestRunOptions(options, item.tests);
2043
+ const trustAcknowledgement = await maybeAcknowledgeLinkedTests(options, pmRoot, item.tests);
1881
2044
  const runStartedAt = options.run === true ? nowIso() : undefined;
1882
2045
  const runResults = await executeSelectedLinkedTests({
1883
2046
  options,
1884
2047
  runOptions,
1885
2048
  pmRoot,
2049
+ untrustedLinkedTestsPolicyEnabled: settings.testing.allow_untrusted_linked_tests,
1886
2050
  });
1887
2051
  const failureCategories = countFailureCategories(runResults);
1888
2052
  const failOnSkippedTriggered = options.run === true &&
1889
2053
  options.failOnSkipped === true &&
1890
2054
  runResults.some((entry) => entry.status === "skipped");
1891
2055
  const warnings = buildTestWarnings(options, runOptions.runSelection, runResults);
2056
+ if (trustAcknowledgement) {
2057
+ warnings.push(`linked_test_trust_acknowledged:${trustAcknowledgement.acknowledged}`);
2058
+ }
1892
2059
  const recordedRun = await recordTestRunSummary({
1893
2060
  options,
1894
2061
  pmRoot,
@@ -1964,4 +2131,4 @@ export const _testOnlyTestCommand = {
1964
2131
  summarizeRunResultStatuses,
1965
2132
  };
1966
2133
  //# sourceMappingURL=execution.js.map
1967
- //# debugId=2354c553-3a81-59d8-9c0a-3d19cd3cedd2
2134
+ //# debugId=7659721c-21f5-55da-8cce-31b290de5bfb
@@ -20,6 +20,10 @@ export declare const LINKED_TEST_ENV_NAME_PATTERN: RegExp;
20
20
  export declare const LINKED_TEST_PM_CONTEXT_MODE_VALUES: readonly ["schema", "tracker", "auto"];
21
21
  /** Restricts linked test pm context mode values accepted by command, SDK, and storage contracts. */
22
22
  export type LinkedTestPmContextMode = (typeof LINKED_TEST_PM_CONTEXT_MODE_VALUES)[number];
23
+ /** Supported values accepted by the linked test workspace context contract. */
24
+ export declare const LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES: readonly ["source", "isolated", "snapshot"];
25
+ /** Restricts source-workspace modes accepted by command and storage contracts. */
26
+ export type LinkedTestWorkspaceContextMode = (typeof LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES)[number];
23
27
  /** Implements parse linked test env set for the public runtime surface of this module. */
24
28
  export declare function parseLinkedTestEnvSet(raw: string | undefined, optionName: string): Record<string, string> | undefined;
25
29
  /** Implements parse linked test env clear for the public runtime surface of this module. */
@@ -28,6 +32,8 @@ export declare function parseLinkedTestEnvClear(raw: string | undefined, optionN
28
32
  export declare function parseLinkedTestBoolean(raw: string | undefined, optionName: string, fieldLabel: string): boolean | undefined;
29
33
  /** Implements parse linked test context mode for the public runtime surface of this module. */
30
34
  export declare function parseLinkedTestContextMode(raw: string | undefined, optionName: string): LinkedTest["pm_context_mode"] | undefined;
35
+ /** Parse one linked-test source-workspace context mode. */
36
+ export declare function parseLinkedTestWorkspaceContextMode(raw: string | undefined, optionName: string): LinkedTest["workspace_context_mode"] | undefined;
31
37
  /** Implements parse linked test string list for the public runtime surface of this module. */
32
38
  export declare function parseLinkedTestStringList(raw: string | undefined): string[] | undefined;
33
39
  /** Implements parse linked test regex list for the public runtime surface of this module. */
@@ -4,7 +4,7 @@
4
4
  * Implements the pm linked test parsers command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="74163bed-a473-543e-ae6a-0d5091b3b3a9")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="64adcc3c-3646-5990-9442-4c4374a2dc7d")}catch(e){}}();
8
8
  import { parseOptionalNumber } from "../../core/item/parse.js";
9
9
  import { EXIT_CODE } from "../../core/shared/constants.js";
10
10
  import { PmCliError } from "../../core/shared/errors.js";
@@ -43,6 +43,12 @@ export const LINKED_TEST_PM_CONTEXT_MODE_VALUES = [
43
43
  "tracker",
44
44
  "auto",
45
45
  ];
46
+ /** Supported values accepted by the linked test workspace context contract. */
47
+ export const LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES = [
48
+ "source",
49
+ "isolated",
50
+ "snapshot",
51
+ ];
46
52
  /** Implements parse linked test env set for the public runtime surface of this module. */
47
53
  export function parseLinkedTestEnvSet(raw, optionName) {
48
54
  if (!raw) {
@@ -119,6 +125,17 @@ export function parseLinkedTestContextMode(raw, optionName) {
119
125
  }
120
126
  throw new PmCliError(`${optionName} pm_context_mode must be one of: ${LINKED_TEST_PM_CONTEXT_MODE_VALUES.join(", ")}`, EXIT_CODE.USAGE);
121
127
  }
128
+ /** Parse one linked-test source-workspace context mode. */
129
+ export function parseLinkedTestWorkspaceContextMode(raw, optionName) {
130
+ if (!raw) {
131
+ return undefined;
132
+ }
133
+ const value = raw.trim().toLowerCase();
134
+ if (LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES.includes(value)) {
135
+ return value;
136
+ }
137
+ throw new PmCliError(`${optionName} workspace_context_mode must be one of: ${LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES.join(", ")}`, EXIT_CODE.USAGE);
138
+ }
122
139
  /** Implements parse linked test string list for the public runtime surface of this module. */
123
140
  export function parseLinkedTestStringList(raw) {
124
141
  if (!raw) {
@@ -476,6 +493,7 @@ function parseLinkedTestJsonEntry(rawEntry, label, optionName) {
476
493
  !LINKED_TEST_PM_CONTEXT_MODE_VALUES.includes(pmContextModeValue)) {
477
494
  throw fail(`field "pm_context_mode" must be one of: ${LINKED_TEST_PM_CONTEXT_MODE_VALUES.join(", ")}`);
478
495
  }
496
+ const workspaceContextModeValue = parseLinkedTestWorkspaceContextMode(readJsonEntryString(entry, "workspace_context_mode", fail), `${optionName} ${label}`);
479
497
  const noteValue = readJsonEntryString(entry, "note", fail);
480
498
  return {
481
499
  command,
@@ -483,6 +501,7 @@ function parseLinkedTestJsonEntry(rawEntry, label, optionName) {
483
501
  scope: readJsonEntryScope(entry, fail),
484
502
  timeout_seconds: readJsonEntryTimeoutSeconds(entry, fail),
485
503
  pm_context_mode: pmContextModeValue,
504
+ workspace_context_mode: workspaceContextModeValue,
486
505
  env_set: readJsonEntryEnvSet(entry, fail),
487
506
  env_clear: readJsonEntryEnvClear(entry, fail),
488
507
  shared_host_safe: readJsonEntryBoolean(entry, "shared_host_safe", fail),
@@ -524,4 +543,4 @@ export const _testOnlyLinkedTestParsers = {
524
543
  parseLinkedTestJsonEntry,
525
544
  };
526
545
  //# sourceMappingURL=parsers.js.map
527
- //# debugId=74163bed-a473-543e-ae6a-0d5091b3b3a9
546
+ //# debugId=64adcc3c-3646-5990-9442-4c4374a2dc7d
@@ -0,0 +1,33 @@
1
+ import type { LinkedTest } from "../../types/index.js";
2
+ /** Classification of one linked-test command against the current clone. */
3
+ export interface LinkedTestTrustDecision {
4
+ /** Stable hash binding the decision to command, context, and provenance. */
5
+ fingerprint: string;
6
+ /** Whether execution may proceed without an untrusted-command override. */
7
+ trusted: boolean;
8
+ /** Machine-readable reason for the decision. */
9
+ reason: "legacy" | "local_mutation" | "local_source_ref" | "acknowledged" | "invalid_provenance" | "foreign_source_ref";
10
+ /** Source ref recorded when the command entered tracker data. */
11
+ source_ref?: string;
12
+ /** Current source ref used for the local decision. */
13
+ current_source_ref?: string;
14
+ }
15
+ /** Resolve the current Git branch without invoking a shell. */
16
+ export declare function resolveLinkedTestSourceRef(cwd?: string): Promise<string | undefined>;
17
+ /** Resolve the source checkout shared by linked-test provenance and execution. */
18
+ export declare function resolveLinkedTestSourceWorkspaceRoot(cwd?: string): string;
19
+ /** Attach immutable author/time/ref provenance to newly stored commands. */
20
+ export declare function attachLinkedTestProvenance(tests: LinkedTest[] | undefined, author: string, createdAt: string, sourceRef: string | undefined): LinkedTest[] | undefined;
21
+ /** Attach provenance while avoiding Git inspection for an empty mutation. */
22
+ export declare function attachLinkedTestMutationProvenance(tests: LinkedTest[] | undefined, author: string, createdAt: string): Promise<LinkedTest[] | undefined>;
23
+ /** Produce the clone-local trust identity for one linked-test entry. */
24
+ export declare function linkedTestTrustFingerprint(test: LinkedTest): string;
25
+ /** Resolve whether one stored command is trusted by this clone. */
26
+ export declare function resolveLinkedTestTrust(pmRoot: string, test: LinkedTest, currentSourceRef?: string): Promise<LinkedTestTrustDecision>;
27
+ /** Resolve a collection with one ledger read for validation and batch runs. */
28
+ export declare function resolveLinkedTestTrustBatch(pmRoot: string, tests: LinkedTest[], currentSourceRef?: string): Promise<LinkedTestTrustDecision[]>;
29
+ /** Persist explicit clone-local acknowledgement for selected linked tests. */
30
+ export declare function acknowledgeLinkedTests(pmRoot: string, tests: LinkedTest[], acknowledgedAt: string): Promise<{
31
+ acknowledged: number;
32
+ fingerprints: string[];
33
+ }>;