Test scenario: an office session, end to end, on your own machine
The scripted form of docs/office-sessions.md's "what the run showed": a
scratch Postgres, the real next start, the real handsel-worker.mjs, a
real claude process, a git fixture whose add() subtracts. Nothing is
seeded — the user and agent rows are what sign-up creates — and no chain is
touched: the tasks are internal, so no escrow is posted and no money can
move.
Prerequisites
- Postgres you can point
DATABASE_URLat (a scratch cluster; the tables self-create) and the schema fromnode scripts/migrate.mjs. claudeon PATH and signed in. Under root, start the worker with--no-preflight(the one-shot preflight asks forbypassPermissions; session runs useacceptEditsand do not need it).- No LLM key on the platform is fine: the reviewer answers "unavailable" and the default policy sends the task to you instead of passing it.
Environment
export DATABASE_URL=postgres://…/handsel_e2e
export API_KEY_ENCRYPTION_SECRET=$(openssl rand -hex 32)
export BETTER_AUTH_SECRET=$(openssl rand -hex 32)
export PUBLIC_ORIGIN=http://localhost:3111
export OFFICE_SESSION_HEARTBEAT_TIMEOUT_MS=45000 # prove a crash in a minute, not five
export OFFICE_SESSION_PICKUP_TIMEOUT_MS=45000
The fixture
mkdir repo && cd repo && git init
cat > package.json <<'EOF'
{ "name": "fixture", "private": true, "type": "module", "scripts": { "test": "node --test" } }
EOF
mkdir lib && printf 'export function add(a, b) {\n return a - b\n}\n' > lib/math.js
cat > math.test.js <<'EOF'
import test from 'node:test'; import assert from 'node:assert/strict'; import { add } from './lib/math.js'
test('add adds', () => assert.equal(add(2, 3), 5))
EOF
printf '.handsel/\n' > .gitignore && git add -A && git commit -qm fixture
The run
npx next build && npx next start -p 3111 & # the real routes
E="npx tsx scripts/office-session-e2e.ts"
$E setup $PWD/repo "npm test" # user, agent, grant → TOKEN=…
node public/handsel-worker.mjs --token <TOKEN> --workdir $PWD/repo --harness claude --no-preflight &
$E start $PWD/repo "math.test.js fails because add() subtracts. Fix add() so npm test passes." default
$E wait <SESSION> 300 completed,waiting_on_approval,failed
$E status <SESSION> # tasks, runs, checkpoints, approvals, event counts, replay integrity
$E approve <SESSION> # when it is waiting on you
What to check, in order:
git statusin the fixture shows onlylib/math.js; nothing outside the workdir changed.statuslists adiff, adeliverableand atest_reportartifact by sha256, and the task'stests=pass.- Under the default policy the approval is
REQUIRE_OWNER(no reviewer), and nothing settles untilapprove. Passlenienttostartinstead and the same task settles by policy (ALLOW_WITH_LOG) with nobody clicking. integrity: replay matches materialized state.
The crash
Start a session, wait for the first CHECKPOINT_CREATED in
office_session_event (it lands seconds after the first edit), kill -9
the worker, wait past the heartbeat timeout, tick, restart the worker, wait.
Expect: run 1 timed_out, run 2 finished with resumedFrom=<checkpoint>,
attempts=2, one TASK_SETTLED, and git status still showing one
file. The transcript of exactly this is in docs/office-sessions.md.