Bladeren bron

fix: ci run without build lib for snapshot

imccyu 3 maanden geleden
bovenliggende
commit
aff657cc28

+ 1 - 1
packages/workflow/workflow-workerthread/README.md

@@ -8,7 +8,7 @@ Workflow scripts are **model-written** — the same trust level as the model's e
 
 - **The host never blocks**: `start()` returns without running any script code on the host; a synchronous spin anywhere in the script occupies the worker's loop, not the harness's.
 - **Termination is real**: a script that outlives its post-cancel grace is `worker.terminate()`d — nothing of it survives `dispose()`, where an in-process engine could only abandon the spin on its own loop.
-- **No ambient credentials**: the worker spawns with an EMPTY environment (`env: {}` plus hermetic `execArgv`, the same stance as `dsh-code-runtime-worker`), so an escapee reading `process.env` finds no harness secrets — ambient-channel hardening only; the process-wide privileges above (fs and the rest) remain, so a genuine sandbox is still the engine swap.
+- **No ambient credentials**: the worker spawns with an EMPTY environment (`env: {}` plus hermetic `execArgv`, the same stance as `dsh-code-runtime-worker`; the unbuilt dev shape forwards exactly one loader variable, `TSX_TSCONFIG_PATH` — path plumbing, not a secret), so an escapee reading `process.env` finds no harness secrets — ambient-channel hardening only; the process-wide privileges above (fs and the rest) remain, so a genuine sandbox is still the engine swap.
 - **Serialization by construction**: everything crossing the thread is structured-clone data, and plain JSON before that — the `materializeFromRealm` walk rejects loud what JSON cannot carry, which is also what makes every postMessage hop total.
 
 What the seam guarantees regardless, because benign scripts hit these constantly: `result` never rejects, a dropped hook promise never becomes an unhandled rejection, values JSON cannot carry are rejected **loud** instead of silently mangled, and hook misuse is fatal instead of dissolving into a per-item `null`. Genuine sandboxing (containing what an escaped script may touch) remains an isolated-vm/separate-process engine swap behind the seam, still deferred.

+ 16 - 5
packages/workflow/workflow-workerthread/src/host.ts

@@ -64,9 +64,11 @@ import type { ChildStartRequest, WorkerInit } from './types.ts'
  * (`DEEPSEEK_API_KEY` et al.) must not ride along — the same stance as
  * `dsh-code-runtime-worker`, stronger than the scrubbed env the
  * defensive-patterns rule requires for spawned commands (a shell needs PATH;
- * this worker needs nothing). This closes the AMBIENT channel only — an
- * escapee still holds process-wide privileges like fs access (the README's
- * trust premise stands).
+ * this worker needs nothing). Sole exception: the unbuilt shape forwards
+ * `TSX_TSCONFIG_PATH` when the parent carries it (loader plumbing the paths
+ * map depends on outside the repo cwd, not a secret). This closes the
+ * AMBIENT channel only — an escapee still holds process-wide privileges
+ * like fs access (the README's trust premise stands).
  * @param init - the run payload, passed as `workerData`.
  * @returns the entry URL and the Worker options to spawn it with.
  */
@@ -76,10 +78,19 @@ function resolveWorkerSpawn(init: WorkerInit): { entry: URL; options: WorkerOpti
     return { entry: new URL('./worker.js', import.meta.url), options: { workerData: init, env: {}, execArgv: [] } }
   }
   // Lazy tsx resolution: only the unbuilt shape needs it, so the built
-  // bundle never requires tsx to be installed.
+  // bundle never requires tsx to be installed. TSX_TSCONFIG_PATH is the one
+  // variable forwarded through the scrub: tsx finds a tsconfig by searching
+  // UP from the worker's cwd, and a parent running with its cwd outside the
+  // repo (the ACP snapshot harness pins the tsconfig through this exact
+  // variable) would otherwise lose the dsh-* paths map and resolve workspace
+  // imports to unbuilt lib/ bundles. Loader plumbing, not a secret.
   return {
     entry: new URL('./worker.ts', import.meta.url),
-    options: { workerData: init, env: {}, execArgv: ['--import', fileURLToPath(import.meta.resolve('tsx'))] },
+    options: {
+      workerData: init,
+      env: process.env.TSX_TSCONFIG_PATH === undefined ? {} : { TSX_TSCONFIG_PATH: process.env.TSX_TSCONFIG_PATH },
+      execArgv: ['--import', fileURLToPath(import.meta.resolve('tsx'))],
+    },
   }
 }