T-4HBC-app-harness-scratch-platform
State: closed/done · Impact: high · Complexity: large
One launcher for running any of our apps against a scratch root, with a post-boot check that
proves no state path reaches the real home. It replaces the per-suite serve-*.ts copies.
| Location | Role today |
|---|---|
solutions/determined/tests/ui/serve-*.ts | Eight launchers. Seven (backup, fitness, notes, polish, polish-lint, smoke, vaults) copy or build a vault, pass --state-dir, and spawn cargo run with raw spawn. serve-sdf.ts is a Bun.serve fixture that fakes SDF’s /api |
solutions/determined/products/agent-pants/tests/serve*.ts | Six launchers plus serve.ts, over a shared serve-harness.ts module |
solutions/determined/tests/ui/backup/harness.ts | Backup suite helpers; reads the scratch path back from a tmp file |
solutions/ontological/lib/util/command.ts | The command seam, with spawnRunnerAsync for long-lived processes |
dev-ports.yaml | Port registry. The backup suite ran on 15106, which belongs to exp-polish-storybook-capture; 15070 and 15071 are the dev servers |
packages/ts/ | No harness package |
Proposed
Section titled “Proposed”packages/ts/app-harness (@sksizer/app-harness) exports
withScratchApp({ name, fixtures, homes, spawn, ready, port }), returning
{ baseURL, root, path(), restart(), stop() }. It creates the root, sets FLEET_ROOT and any
FLEET_<HOME>_DIR from homes, and TMPDIR. It takes the port from dev-ports.yaml with an env
override, or leases the next free one in the band (nextFree, the per-worktree port T-2MBO
asks for). It spawns through the command seam, waits for ready, then reads the backend’s
resolved paths. Every path must lie inside a root the harness made or was given; a path outside
them, or under the real home, aborts the run. It removes the root on
stop and sweeps stale roots on start. It ships a Playwright fixture and a webServer helper.
solutions/determined/tests/ui/harness/platform.ts exports
scratchPlatform({ product, vaultFixture, homes, schedule }), which wraps platform-server argv
(--vault, --dist, --backup-schedule) over withScratchApp and reads the introspection
endpoint from T-NNAG.
Approach
Section titled “Approach”- Scaffold the package per S-0001-co-locate-first-promote-when-shared and add it to
docs/LIBRARIES.md. - Root creation, env, port lookup, spawn via the command seam, readiness poll.
- The isolation assertion against the introspection endpoint.
homesvalues of'shared'map to a stable scratch path, never the real home. - Cleanup on stop, signal handlers, stale-root sweep by name prefix and age.
- Playwright fixture and
webServerhelper. scratchPlatformadapter.- Self-test: boot platform-server with one home deliberately pointed at the real home and confirm the harness aborts.
| Area | Note |
|---|---|
packages/ts/app-harness/ | New package |
solutions/determined/tests/ui/harness/ | Determined adapter |
docs/LIBRARIES.md | Roster entry |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
scratchPlatform({ product: 'backup', ... })boots platform-server and every resolved path from the introspection endpoint lies under the scratch root. - AC-2: The self-test with one home at the real home fails with a message naming the home and path.
- AC-3: After
stop(), the scratch root is gone. A root left by a killed run is swept on the next start. - AC-4: The harness spawns only through the command seam.
Out of scope
Section titled “Out of scope”- Migrating existing suites (
T-VEK2for backup,T-GXNHfor the other platform-server suites). - The Tauri-app adapter (
scratchTauriApp), which lands withT-UU4J.
Dependencies
Section titled “Dependencies”T-NNAGforFLEET_ROOTsupport and the introspection endpoint.
Discovery context
Section titled “Discovery context”- The launchers isolate different subsets of state and drift from each other. See the anti-examples in S-0020-desktop-apps-tested-web-first-in-scratch-root.
Depends on
Section titled “Depends on”T-NNAG