Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions PUBLIC_EXPORT_MANIFEST.json
Original file line number Diff line number Diff line change
Expand Up @@ -21679,9 +21679,9 @@
},
{
"path": "apps/worker/package.json",
"sourceObjectId": "d7a484ac8fb49132203bfc4d1ab01b1d6d975739",
"sha256": "b357357c037bd4c33c50d75618437ff36dc461365eac63d74355de1740de348c",
"size": 869
"sourceObjectId": "5ec25291ef2c22baf7a1645e1637aa0b3a482b38",
"sha256": "27cbb6671976805125a86ddc207d693fde0d88377014123a4bb64a955f5d798e",
"size": 1056
},
{
"path": "apps/worker/src/activities.ts",
Expand Down Expand Up @@ -22075,9 +22075,9 @@
},
{
"path": "apps/worker/tests/room-continuation-fixture.ts",
"sourceObjectId": "340e964e081d823a43250f2bd780f741fe79a3ba",
"sha256": "12face2dddea89e0b7493db6d0a8b8b75a59f36ec6fca3369b30918fe8f5b530",
"size": 2688
"sourceObjectId": "eb3c01cc4807143a029f58c2ec9d4f201ee2bbf0",
"sha256": "852f8db31bb49d69f6ad0e1db6cf4a713310a481efab5ad3722eb32853ccd750",
"size": 2873
},
{
"path": "apps/worker/tests/room-supervisor-continuation.test.ts",
Expand Down Expand Up @@ -22514,8 +22514,8 @@
{
"path": "package-lock.json",
"sourceObjectId": "1ea4513f4be841459363186921c3695db73cfd0a",
"sha256": "f6c745fb50ff3c0301e5f7dec24815438f86470f7e7e668496a755d0100d5c1a",
"size": 419142
"sha256": "86689a35e8302bce8fa35b3a98140353bef8817adfad5b561a8bd475885f1905",
"size": 419955
},
{
"path": "package.json",
Expand Down
6 changes: 5 additions & 1 deletion apps/worker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"start": "node dist/worker.js",
"build": "tsc -p tsconfig.json",
"check": "tsc -p tsconfig.json --noEmit",
"test": "vitest run"
"test": "vitest run",
"temporal:record-histories": "node scripts/record-temporal-histories.mjs"
},
"dependencies": {
"@space/codex-app-server": "0.2.5",
Expand All @@ -26,6 +27,9 @@
"undici": "8.10.2"
},
"devDependencies": {
"@temporalio/common": "1.24.0",
"@temporalio/proto": "1.24.0",
"@temporalio/testing": "1.24.0",
"typescript": "^5.9.3",
"vitest": "^4.1.12"
},
Expand Down
17 changes: 17 additions & 0 deletions apps/worker/scripts/record-temporal-histories.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";

const workerDirectory = fileURLToPath(new URL("../", import.meta.url));
const vitest = fileURLToPath(new URL("../../../node_modules/vitest/vitest.mjs", import.meta.url));
const result = spawnSync(process.execPath, [vitest, "run",
"tests/temporal-dot-goal.test.ts",
"tests/temporal-supervisor.test.ts",
"tests/temporal-turn-memory.test.ts"
], {
cwd: workerDirectory,
env: { ...process.env, SPACE_RECORD_TEMPORAL_HISTORIES: "1" },
stdio: "inherit"
});
if (result.error) throw result.error;
if (result.signal) throw new Error(`History recording interrupted by ${result.signal}`);
process.exitCode = result.status ?? 1;
44 changes: 44 additions & 0 deletions apps/worker/tests/fixtures/workflow-histories/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Temporal workflow replay baselines

These JSON histories contain synthetic inputs from the real, time-skipping
Temporal test server. They cover all eight production workflow types, including
supervisor runs with and without `room-background-continuation-v1`. The tests
import the production implementations without replacing Temporal APIs.

`npm test -w @space/worker` runs the real-sandbox scenarios and replays every
committed JSON history with `Worker.runReplayHistories`. The public test command
and public CI include this workspace automatically. Replay failures identify the
history file. A negative test adds a timer in a test-only workflow and requires
`DeterminismViolationError`, proving that the gate detects incompatible changes.

No database, Docker, AI account or provider credentials are used. The SDK downloads
its official ephemeral test-server binary on first use; subsequent runs use its
local cache. Tests communicate only with their disposable local server. Use the
repository's supported Node 22 runtime.

## Recording histories

From the repository root, after installing the locked dependencies:

```sh
npm run build -w @space/contracts
npm run temporal:record-histories -w @space/worker
npm test -w @space/worker
```

Normal test runs never write fixtures. Recording is an explicit operation and
runs the same asserted scenarios. Worker/client identities and exception stack
traces are scrubbed so contributor hostnames and local paths are not committed;
replay-relevant inputs, events and results are preserved.

After the initial baseline, **re-record only together with a deliberate,
replay-safe `patched()` workflow change**. Preserve an old history for each
supported branch and replay both old and new histories before submission.
Never re-record histories simply to make a failing replay pass: that discards
the evidence of an incompatible change. A fixture diff must be reviewed as
carefully as the workflow change it accompanies.

The pre-patch supervisor fixture is recorded from the unmodified implementation
using SDK 1.24's `patchActivationCallback`, which leaves only the named patch
inactive and records no marker for it. Ordinary replays use the current source
and the history's actual patch markers; the callback does not override replay.
Loading