[
     {
          "Id": "d20a112f2ec3de330792fc940ac9df20d6a3c904fe7b521d1e3264852ac77129",
          "Created": "2026-08-08T03:10:44.439137231+03:00",
          "Path": "/usr/bin/tini",
          "Args": [
               "--",
               "/bin/sh",
               "-c",
               "[ -n \"${HOME-}\" ] || { echo 'agent_cred: HOME unset in container' >&2; exit 10; }\nagent_cred_target=\"${HOME%/}/.codex/auth.json\"\ntrap 'rm -f \"$agent_cred_target\"' EXIT HUP INT TERM\nmkdir -p \"${agent_cred_target%/*}\" || { echo 'agent_cred: cannot create credential directory' >&2; exit 10; }\n[ -r '/sandbox-secrets/codex/auth.json' ] || { echo 'agent_cred: staging mount missing: /sandbox-secrets/codex/auth.json' >&2; exit 10; }\ncp '/sandbox-secrets/codex/auth.json' \"$agent_cred_target\" || { echo 'agent_cred: credential copy failed' >&2; exit 10; }\nchmod 600 \"$agent_cred_target\" || { echo 'agent_cred: cannot restrict credential mode' >&2; exit 10; }\n\"$@\"",
               "sh",
               "codex",
               "exec",
               "--sandbox",
               "danger-full-access",
               "--skip-git-repo-check",
               "-m",
               "gpt-5.6-luna",
               "-c",
               "model_reasoning_effort=high",
               "Work ONLY inside the git worktree /home/user/Projects/overdeck/.worktrees/seathatch (never in /home/user/Projects/overdeck itself). Do not touch modules/sandbox/**, any Containerfile, or modules/workstation/claude/bin/local-dispatch-guard.\n\nGOAL: remove the env-var fail-open HARNESS_SEAT_REMOTE=0 from the harness remote-seat path, so that no environment variable can bring a headless agent seat back onto the workstation. The canonical denial mechanism already exists and stays authoritative: ~/.claude/bin/local-dispatch-guard (exit 97, \"headless agent dispatch on this workstation is denied\"), which every wrapper (claude.sh:75-83, codex.sh:163-171, ca.sh:136-144) calls before spawning the engine. Its rule: a TTY on fd 0/1/2 (a human is attached) allows local execution; headless does not. That IS the human escape hatch — do NOT invent another one, and do NOT add any new env var.\n\nEXACT CHANGES — implement all of them, nothing else:\n\n1. modules/harness/seat/remote-seat.mjs\n   In adapterRemotable(), delete the line:\n     if (process.env.HARNESS_SEAT_REMOTE === \"0\") return { ok: false, reason: \"kill-switch HARNESS_SEAT_REMOTE=0\" };\n   Nothing else in this file changes. Leave the HARNESS_SEAT_CONTAINER branch at line ~342 alone.\n\n2. modules/harness/wrappers/lib/remote-seat.sh\n   Delete the line:  [[ \"${HARNESS_SEAT_REMOTE:-}\" == \"0\" ]] && return 1\n   Update the header comment so it states the truth: enable/disable is CONFIG (modules/harness/seat/seat-remote.json) only; there is no env kill switch; when the launcher says run-locally, local execution is still subject to local-dispatch-guard, which denies a headless dispatch with exit 97. Keep the comment SHORT (comments describe what the code does, never reasoning/history).\n\n3. modules/harness/seat/README.md\n   Line ~34: delete the \"HARNESS_SEAT_REMOTE=0 -> kill switch\" bullet. Replace with one line stating that remoting is switched off only in seat-remote.json / build-remote.json and that a headless local dispatch is refused with exit 97 by local-dispatch-guard. Keep the HARNESS_SEAT_CONTAINER bullet.\n\n4. modules/harness/seat/test/seat-contract.test.sh\n   Replace the two lines\n     HARNESS_SEAT_REMOTE=0 node \"$LAUNCHER\" --check codex >/dev/null 2>&1\n     check \"HARNESS_SEAT_REMOTE=0 kill switch forces local\" \"$?\" 1\n   with a REGRESSION assertion that the hatch is gone: the same command must now exit 0 (\"HARNESS_SEAT_REMOTE=0 no longer forces local\"). Everything else in this file is unchanged.\n\n5. modules/harness/wrappers/claude-classification.test.sh\n   This suite currently relies on HARNESS_SEAT_REMOTE=0 to stop the wrapper from dispatching a real remote seat. Replace that with a fixture that removes the seat shim instead of setting an env var:\n   - after $tmp is created, do: cp -r \"$root\" \"$tmp/wrappers\" ; rm -f \"$tmp/wrappers/lib/remote-seat.sh\"\n     ($root is the wrappers dir; claude.sh computes SKILL_DIR=\"$(dirname $0)/..\" and only uses it for \"$SKILL_DIR/wrappers/lib/remote-seat.sh\", guarded by `if [[ -f ... ]]`, so the copied wrapper takes the local path with byte-identical code under test.)\n   - run_case must invoke  bash \"$tmp/wrappers/claude.sh\"  instead of  bash \"$root/claude.sh\".\n   - delete HARNESS_SEAT_REMOTE=0 from the env list. Keep everything else (HOME, PATH, CLAUDE_TEST_MODE, _CLAUDE_ENGINE_BIN, the stubbed local-dispatch-guard).\n   The suite must still pass unchanged in its assertions.\n\n6. NEW FILE modules/harness/seat/test/seat-hatch.test.sh (executable, bash, same PASS/FAIL/check helper style as seat-contract.test.sh, exits nonzero if any check fails). It must prove the hatch is closed END TO END through the real wrapper — not by unit-testing a function. Build in $tmp:\n   - $tmp/home/.claude/bin/local-dispatch-guard  = a COPY of the real modules/workstation/claude/bin/local-dispatch-guard from this repo (resolve its path relative to the test file). Not a stub.\n   - $tmp/bin/claude = a stub that does `touch \"$SENTINEL\"` and prints {\"is_error\":false,\"session_id\":\"s\",\"result\":\"ok\"} then exits 0, where SENTINEL is passed via env SEAT_HATCH_SENTINEL. It must also answer `auth status --json` with {\"status\":\"ok\"} exit 0 (claude.sh health-checks it).\n   - $tmp/ws = a git repo (git init, one commit) used as --workspace.\n   - a disabled seat config $tmp/seat-remote-off.json  = a copy of modules/harness/seat/seat-remote.json with \"enabled\": false.\n   - a transport config $tmp/build-remote.json with hosts [\"seat-hatch-unreachable.invalid\"], port 2222, ssh_user \"user\", remote_root \"/home/user/builds\", identity_file \"~/.ssh/id_ed25519_buildbox\", local_fallback false, local_only [], max_remote_jobs 1.\n   Run the REAL modules/harness/wrappers/claude.sh (so the seat shim IS present) with env -i, HOME=$tmp/home, PATH=\"$tmp/bin:/usr/bin:/bin\", and assert three cases:\n   A) HARNESS_SEAT_REMOTE=0 set, real (enabled) seat config, BUILD_REMOTE_CONFIG=$tmp/build-remote.json, headless (stdin/stdout/stderr are pipes/files):\n      the sentinel file must NOT exist afterwards and rc must not be 0 — the seat was still routed remotely and failed on the unreachable host instead of running on this machine.\n   B) HARNESS_SEAT_REMOTE=0 AND HARNESS_SEAT_CONFIG=$tmp/seat-remote-off.json, headless:\n      rc must be 97 and the sentinel must NOT exist — with remoting switched off the local path is refused by local-dispatch-guard.\n   C) same as B but with a real pty so a human-at-a-terminal is simulated: run it under `script -qec \"<command>\" /dev/null` (util-linux script; quote carefully, keep env via a small generated runner script in $tmp so nothing depends on shell quoting) — rc must be 0 and the sentinel MUST exist. This proves the human escape still works and that the deny in B is the TTY rule, not a blanket failure.\n   Case C must be skipped with a printed SKIP (not a FAIL) only if `script` is not installed. Every case must clean the sentinel before running.\n\n7. Wire the new test into whatever runner already runs modules/harness/seat/test/seat-contract.test.sh (find it; e.g. a run-tests.sh / test list). If seat-contract.test.sh is discovered by glob, nothing to do — say so.\n\nCONSTRAINTS:\n- No new env var, no new flag, no fallback that could execute the engine on the workstation.\n- Do not weaken or delete any existing assertion to make a suite pass; if something fails, fix the code, not the test.\n- Do not run anything that forks heavily, no builds, no network beyond the intentional DNS miss to the .invalid host.\n- Run and report the ACTUAL output of: bash modules/harness/seat/test/seat-contract.test.sh ; bash modules/harness/seat/test/seat-hatch.test.sh ; bash modules/harness/wrappers/claude-classification.test.sh ; bash modules/harness/wrappers/ca-identity.test.sh\n- Report honestly: exact pass/fail counts per suite, and anything you could not verify. Do not claim a green you did not observe.\n- Commit nothing. Leave the changes in the worktree."
          ],
          "State": {
               "OciVersion": "1.2.1",
               "Status": "exited",
               "Running": false,
               "Paused": false,
               "Restarting": false,
               "OOMKilled": false,
               "Dead": false,
               "Pid": 0,
               "ExitCode": 0,
               "Error": "",
               "StartedAt": "2026-08-08T03:10:44.762676862+03:00",
               "FinishedAt": "2026-08-08T03:16:49.349198216+03:00",
               "CheckpointedAt": "0001-01-01T00:00:00Z",
               "RestoredAt": "0001-01-01T00:00:00Z"
          },
          "Image": "b1f0e605dca88041db84124d554a87c90f1e67b0afd39a1e6eb5fdd69b2333ef",
          "ImageDigest": "sha256:a04c8666e3eb0dfed42cd16d577c383649555d1d05f214546c06d9377ef7a456",
          "ImageName": "localhost/overdeck-agent-sandbox:c257a4c3027b",
          "Rootfs": "",
          "Pod": "",
          "ResolvConfPath": "/run/user/1000/containers/overlay-containers/d20a112f2ec3de330792fc940ac9df20d6a3c904fe7b521d1e3264852ac77129/userdata/resolv.conf",
          "HostnamePath": "/run/user/1000/containers/overlay-containers/d20a112f2ec3de330792fc940ac9df20d6a3c904fe7b521d1e3264852ac77129/userdata/hostname",
          "HostsPath": "/run/user/1000/containers/overlay-containers/d20a112f2ec3de330792fc940ac9df20d6a3c904fe7b521d1e3264852ac77129/userdata/hosts",
          "StaticDir": "/home/user/.local/share/containers/storage/overlay-containers/d20a112f2ec3de330792fc940ac9df20d6a3c904fe7b521d1e3264852ac77129/userdata",
          "OCIConfigPath": "/home/user/.local/share/containers/storage/overlay-containers/d20a112f2ec3de330792fc940ac9df20d6a3c904fe7b521d1e3264852ac77129/userdata/config.json",
          "OCIRuntime": "crun",
          "ConmonPidFile": "/run/user/1000/containers/overlay-containers/d20a112f2ec3de330792fc940ac9df20d6a3c904fe7b521d1e3264852ac77129/userdata/conmon.pid",
          "PidFile": "/run/user/1000/containers/overlay-containers/d20a112f2ec3de330792fc940ac9df20d6a3c904fe7b521d1e3264852ac77129/userdata/pidfile",
          "Name": "overdeck-sandbox-seathatch-2b31de2c9650",
          "RestartCount": 0,
          "Driver": "overlay",
          "MountLabel": "",
          "ProcessLabel": "",
          "AppArmorProfile": "",
          "EffectiveCaps": null,
          "BoundingCaps": null,
          "ExecIDs": [],
          "GraphDriver": {
               "Name": "overlay",
               "Data": {
                    "LowerDir": "/home/user/.local/share/containers/storage/overlay/d49a100797e83202ba1ecfc6175b67d1fe8e5fe75f54da3ee4262308a916622b/diff:/home/user/.local/share/containers/storage/overlay/d43056af101e2d4cdc651cfdf040d6f107c81620d77808f41223f6f9991ce581/diff:/home/user/.local/share/containers/storage/overlay/c438e503bc1c229234bb171b4b77992a7423bd688d9f96fee535288d2c85060f/diff:/home/user/.local/share/containers/storage/overlay/48792945e4e1b9f4c26265b925061931e57a2748839cbbd458091e793b01c483/diff:/home/user/.local/share/containers/storage/overlay/4219c648e7a6ce168560334375bcf7ebe4d60674c7e0ed1d2133bf7c0a2403ce/diff:/home/user/.local/share/containers/storage/overlay/a7dd58a7a982534dd1c90283ee4304eabae7b47cdaae59a8260c9dfab477d11d/diff:/home/user/.local/share/containers/storage/overlay/2ca4754021bf0d5cfbb2854036b912ad2e5707084c80bd8d188e438201b8e52e/diff:/home/user/.local/share/containers/storage/overlay/ca1f4233d2b0487eac3cf4495286478f0c62d9aa65a38723143748143eabb908/diff:/home/user/.local/share/containers/storage/overlay/e715b54c9641f9e832d1a136ae3cf414ffa2ada20630de35a799e6198d6110f4/diff:/home/user/.local/share/containers/storage/overlay/4e167893ba2f7243ffacc715fa832ddbb596f0a83fa1e1dcfcc7480a05dd6b72/diff:/home/user/.local/share/containers/storage/overlay/cd7010618e91c57771c4e70c076ca7ebed5051f2dadd9cf3594c39535026152a/diff:/home/user/.local/share/containers/storage/overlay/7249826692473065bd49c116884f426135dc4b7a6375219adc1527c5eb880e3b/diff:/home/user/.local/share/containers/storage/overlay/f000331b42681cdec47aebef7ef03be564c1f7d756aae241cec523a997b8ada3/diff:/home/user/.local/share/containers/storage/overlay/45fc035401d0739c04295700f1a0956d14007b33830e7df90d24e6e2ed6e6925/diff:/home/user/.local/share/containers/storage/overlay/33abc4ad76e2099a56041549ac0643312ed831660ea7f28e07f05bc228e12f78/diff",
                    "UpperDir": "/home/user/.local/share/containers/storage/overlay/3e6e0e203eea904ec134787dc923f41fca6bb7ebfe76e03e0488f5c84bcc264f/diff",
                    "WorkDir": "/home/user/.local/share/containers/storage/overlay/3e6e0e203eea904ec134787dc923f41fca6bb7ebfe76e03e0488f5c84bcc264f/work"
               }
          },
          "Mounts": [
               {
                    "Type": "bind",
                    "Source": "/home/user/sandbox",
                    "Destination": "/sandbox",
                    "Driver": "",
                    "Mode": "",
                    "Options": [
                         "rbind"
                    ],
                    "RW": true,
                    "Propagation": "rprivate"
               },
               {
                    "Type": "bind",
                    "Source": "/home/user/.local/share/overdeck-sandbox/secrets/e2e_key",
                    "Destination": "/sandbox-secrets/e2e_key",
                    "Driver": "",
                    "Mode": "",
                    "Options": [
                         "rbind"
                    ],
                    "RW": false,
                    "Propagation": "rprivate"
               },
               {
                    "Type": "bind",
                    "Source": "/home/user/.local/share/overdeck-sandbox/secrets/e2e_known_hosts",
                    "Destination": "/sandbox-secrets/e2e_known_hosts",
                    "Driver": "",
                    "Mode": "",
                    "Options": [
                         "rbind"
                    ],
                    "RW": false,
                    "Propagation": "rprivate"
               },
               {
                    "Type": "bind",
                    "Source": "/home/user/cdx-offload/git-common/overdeck-73dd7c243420",
                    "Destination": "/home/user/cdx-offload/git-common/overdeck-73dd7c243420",
                    "Driver": "",
                    "Mode": "",
                    "Options": [
                         "rbind"
                    ],
                    "RW": true,
                    "Propagation": "rprivate"
               },
               {
                    "Type": "bind",
                    "Source": "/home/user/cdx-offload/git-common/overdeck-73dd7c243420/worktrees/seathatch",
                    "Destination": "/home/user/cdx-offload/git-common/overdeck-73dd7c243420/worktrees/seathatch",
                    "Driver": "",
                    "Mode": "",
                    "Options": [
                         "rbind"
                    ],
                    "RW": true,
                    "Propagation": "rprivate"
               },
               {
                    "Type": "bind",
                    "Source": "/home/user/.local/state/overdeck-sandbox/creds/1786147833928152880-3212288-23735/codex/auth.json",
                    "Destination": "/sandbox-secrets/codex/auth.json",
                    "Driver": "",
                    "Mode": "",
                    "Options": [
                         "rbind"
                    ],
                    "RW": false,
                    "Propagation": "rprivate"
               }
          ],
          "Dependencies": [],
          "NetworkSettings": {
               "EndpointID": "",
               "Gateway": "",
               "IPAddress": "",
               "IPPrefixLen": 0,
               "IPv6Gateway": "",
               "GlobalIPv6Address": "",
               "GlobalIPv6PrefixLen": 0,
               "MacAddress": "",
               "Bridge": "",
               "SandboxID": "",
               "HairpinMode": false,
               "LinkLocalIPv6Address": "",
               "LinkLocalIPv6PrefixLen": 0,
               "Ports": {},
               "SandboxKey": "",
               "Networks": {
                    "pasta": {
                         "EndpointID": "",
                         "Gateway": "",
                         "IPAddress": "",
                         "IPPrefixLen": 0,
                         "IPv6Gateway": "",
                         "GlobalIPv6Address": "",
                         "GlobalIPv6PrefixLen": 0,
                         "MacAddress": "",
                         "NetworkID": "pasta",
                         "DriverOpts": null,
                         "IPAMConfig": null,
                         "Links": null
                    }
               }
          },
          "Namespace": "",
          "IsInfra": false,
          "IsService": false,
          "KubeExitCodePropagation": "invalid",
          "lockNumber": 0,
          "Config": {
               "Hostname": "sandbox-seathatch-2b31de2c9650",
               "Domainname": "",
               "User": "agent",
               "AttachStdin": false,
               "AttachStdout": false,
               "AttachStderr": false,
               "Tty": false,
               "OpenStdin": true,
               "StdinOnce": false,
               "Env": [
                    "PLAYWRIGHT_BROWSERS_PATH=/ms-playwright",
                    "SANDBOX_IMAGE=localhost/overdeck-agent-sandbox:c257a4c3027b",
                    "SANDBOX_E2E_TARGET=user@host.containers.internal",
                    "container=podman",
                    "BASH_ENV=/etc/overdeck-sandbox/toolgap.bash",
                    "SANDBOX_TOOLGAP_FILE=/sandbox/toolgap/gaps.jsonl",
                    "LANG=C.UTF-8",
                    "HOME=/sandbox/home",
                    "PNPM_HOME=/sandbox/home/.local/share/pnpm",
                    "DEBIAN_FRONTEND=noninteractive",
                    "DISABLE_AUTOUPDATER=1",
                    "SANDBOX_ID=seathatch-2b31de2c9650",
                    "PATH=/usr/local/node/bin:/sandbox/home/.local/share/pnpm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                    "COREPACK_ENABLE_DOWNLOAD_PROMPT=0",
                    "PNPM_STORE_DIR=/sandbox/store/pnpm",
                    "PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1",
                    "SANDBOX_E2E_PORT=2222",
                    "HOSTNAME=sandbox-seathatch-2b31de2c9650"
               ],
               "Cmd": [
                    "/bin/sh",
                    "-c",
                    "[ -n \"${HOME-}\" ] || { echo 'agent_cred: HOME unset in container' \u003e\u00262; exit 10; }\nagent_cred_target=\"${HOME%/}/.codex/auth.json\"\ntrap 'rm -f \"$agent_cred_target\"' EXIT HUP INT TERM\nmkdir -p \"${agent_cred_target%/*}\" || { echo 'agent_cred: cannot create credential directory' \u003e\u00262; exit 10; }\n[ -r '/sandbox-secrets/codex/auth.json' ] || { echo 'agent_cred: staging mount missing: /sandbox-secrets/codex/auth.json' \u003e\u00262; exit 10; }\ncp '/sandbox-secrets/codex/auth.json' \"$agent_cred_target\" || { echo 'agent_cred: credential copy failed' \u003e\u00262; exit 10; }\nchmod 600 \"$agent_cred_target\" || { echo 'agent_cred: cannot restrict credential mode' \u003e\u00262; exit 10; }\n\"$@\"",
                    "sh",
                    "codex",
                    "exec",
                    "--sandbox",
                    "danger-full-access",
                    "--skip-git-repo-check",
                    "-m",
                    "gpt-5.6-luna",
                    "-c",
                    "model_reasoning_effort=high",
                    "Work ONLY inside the git worktree /home/user/Projects/overdeck/.worktrees/seathatch (never in /home/user/Projects/overdeck itself). Do not touch modules/sandbox/**, any Containerfile, or modules/workstation/claude/bin/local-dispatch-guard.\n\nGOAL: remove the env-var fail-open HARNESS_SEAT_REMOTE=0 from the harness remote-seat path, so that no environment variable can bring a headless agent seat back onto the workstation. The canonical denial mechanism already exists and stays authoritative: ~/.claude/bin/local-dispatch-guard (exit 97, \"headless agent dispatch on this workstation is denied\"), which every wrapper (claude.sh:75-83, codex.sh:163-171, ca.sh:136-144) calls before spawning the engine. Its rule: a TTY on fd 0/1/2 (a human is attached) allows local execution; headless does not. That IS the human escape hatch — do NOT invent another one, and do NOT add any new env var.\n\nEXACT CHANGES — implement all of them, nothing else:\n\n1. modules/harness/seat/remote-seat.mjs\n   In adapterRemotable(), delete the line:\n     if (process.env.HARNESS_SEAT_REMOTE === \"0\") return { ok: false, reason: \"kill-switch HARNESS_SEAT_REMOTE=0\" };\n   Nothing else in this file changes. Leave the HARNESS_SEAT_CONTAINER branch at line ~342 alone.\n\n2. modules/harness/wrappers/lib/remote-seat.sh\n   Delete the line:  [[ \"${HARNESS_SEAT_REMOTE:-}\" == \"0\" ]] \u0026\u0026 return 1\n   Update the header comment so it states the truth: enable/disable is CONFIG (modules/harness/seat/seat-remote.json) only; there is no env kill switch; when the launcher says run-locally, local execution is still subject to local-dispatch-guard, which denies a headless dispatch with exit 97. Keep the comment SHORT (comments describe what the code does, never reasoning/history).\n\n3. modules/harness/seat/README.md\n   Line ~34: delete the \"HARNESS_SEAT_REMOTE=0 -\u003e kill switch\" bullet. Replace with one line stating that remoting is switched off only in seat-remote.json / build-remote.json and that a headless local dispatch is refused with exit 97 by local-dispatch-guard. Keep the HARNESS_SEAT_CONTAINER bullet.\n\n4. modules/harness/seat/test/seat-contract.test.sh\n   Replace the two lines\n     HARNESS_SEAT_REMOTE=0 node \"$LAUNCHER\" --check codex \u003e/dev/null 2\u003e\u00261\n     check \"HARNESS_SEAT_REMOTE=0 kill switch forces local\" \"$?\" 1\n   with a REGRESSION assertion that the hatch is gone: the same command must now exit 0 (\"HARNESS_SEAT_REMOTE=0 no longer forces local\"). Everything else in this file is unchanged.\n\n5. modules/harness/wrappers/claude-classification.test.sh\n   This suite currently relies on HARNESS_SEAT_REMOTE=0 to stop the wrapper from dispatching a real remote seat. Replace that with a fixture that removes the seat shim instead of setting an env var:\n   - after $tmp is created, do: cp -r \"$root\" \"$tmp/wrappers\" ; rm -f \"$tmp/wrappers/lib/remote-seat.sh\"\n     ($root is the wrappers dir; claude.sh computes SKILL_DIR=\"$(dirname $0)/..\" and only uses it for \"$SKILL_DIR/wrappers/lib/remote-seat.sh\", guarded by `if [[ -f ... ]]`, so the copied wrapper takes the local path with byte-identical code under test.)\n   - run_case must invoke  bash \"$tmp/wrappers/claude.sh\"  instead of  bash \"$root/claude.sh\".\n   - delete HARNESS_SEAT_REMOTE=0 from the env list. Keep everything else (HOME, PATH, CLAUDE_TEST_MODE, _CLAUDE_ENGINE_BIN, the stubbed local-dispatch-guard).\n   The suite must still pass unchanged in its assertions.\n\n6. NEW FILE modules/harness/seat/test/seat-hatch.test.sh (executable, bash, same PASS/FAIL/check helper style as seat-contract.test.sh, exits nonzero if any check fails). It must prove the hatch is closed END TO END through the real wrapper — not by unit-testing a function. Build in $tmp:\n   - $tmp/home/.claude/bin/local-dispatch-guard  = a COPY of the real modules/workstation/claude/bin/local-dispatch-guard from this repo (resolve its path relative to the test file). Not a stub.\n   - $tmp/bin/claude = a stub that does `touch \"$SENTINEL\"` and prints {\"is_error\":false,\"session_id\":\"s\",\"result\":\"ok\"} then exits 0, where SENTINEL is passed via env SEAT_HATCH_SENTINEL. It must also answer `auth status --json` with {\"status\":\"ok\"} exit 0 (claude.sh health-checks it).\n   - $tmp/ws = a git repo (git init, one commit) used as --workspace.\n   - a disabled seat config $tmp/seat-remote-off.json  = a copy of modules/harness/seat/seat-remote.json with \"enabled\": false.\n   - a transport config $tmp/build-remote.json with hosts [\"seat-hatch-unreachable.invalid\"], port 2222, ssh_user \"user\", remote_root \"/home/user/builds\", identity_file \"~/.ssh/id_ed25519_buildbox\", local_fallback false, local_only [], max_remote_jobs 1.\n   Run the REAL modules/harness/wrappers/claude.sh (so the seat shim IS present) with env -i, HOME=$tmp/home, PATH=\"$tmp/bin:/usr/bin:/bin\", and assert three cases:\n   A) HARNESS_SEAT_REMOTE=0 set, real (enabled) seat config, BUILD_REMOTE_CONFIG=$tmp/build-remote.json, headless (stdin/stdout/stderr are pipes/files):\n      the sentinel file must NOT exist afterwards and rc must not be 0 — the seat was still routed remotely and failed on the unreachable host instead of running on this machine.\n   B) HARNESS_SEAT_REMOTE=0 AND HARNESS_SEAT_CONFIG=$tmp/seat-remote-off.json, headless:\n      rc must be 97 and the sentinel must NOT exist — with remoting switched off the local path is refused by local-dispatch-guard.\n   C) same as B but with a real pty so a human-at-a-terminal is simulated: run it under `script -qec \"\u003ccommand\u003e\" /dev/null` (util-linux script; quote carefully, keep env via a small generated runner script in $tmp so nothing depends on shell quoting) — rc must be 0 and the sentinel MUST exist. This proves the human escape still works and that the deny in B is the TTY rule, not a blanket failure.\n   Case C must be skipped with a printed SKIP (not a FAIL) only if `script` is not installed. Every case must clean the sentinel before running.\n\n7. Wire the new test into whatever runner already runs modules/harness/seat/test/seat-contract.test.sh (find it; e.g. a run-tests.sh / test list). If seat-contract.test.sh is discovered by glob, nothing to do — say so.\n\nCONSTRAINTS:\n- No new env var, no new flag, no fallback that could execute the engine on the workstation.\n- Do not weaken or delete any existing assertion to make a suite pass; if something fails, fix the code, not the test.\n- Do not run anything that forks heavily, no builds, no network beyond the intentional DNS miss to the .invalid host.\n- Run and report the ACTUAL output of: bash modules/harness/seat/test/seat-contract.test.sh ; bash modules/harness/seat/test/seat-hatch.test.sh ; bash modules/harness/wrappers/claude-classification.test.sh ; bash modules/harness/wrappers/ca-identity.test.sh\n- Report honestly: exact pass/fail counts per suite, and anything you could not verify. Do not claim a green you did not observe.\n- Commit nothing. Leave the changes in the worktree."
               ],
               "Image": "localhost/overdeck-agent-sandbox:c257a4c3027b",
               "Volumes": null,
               "WorkingDir": "/sandbox/workspaces/seathatch-2b31de2c9650",
               "Entrypoint": [
                    "/usr/bin/tini",
                    "--"
               ],
               "OnBuild": null,
               "Labels": {
                    "io.buildah.version": "1.43.2"
               },
               "Annotations": {
                    "io.container.manager": "libpod",
                    "io.podman.annotations.cid-file": "/home/user/.local/share/overdeck-sandbox/runs/seathatch-2b31de2c9650/cid",
                    "io.podman.annotations.pids-limit": "512",
                    "io.podman.annotations.userns": "keep-id",
                    "org.opencontainers.image.stopSignal": "15",
                    "org.systemd.property.KillSignal": "15",
                    "org.systemd.property.TimeoutStopUSec": "uint64 10000000"
               },
               "StopSignal": "SIGTERM",
               "HealthcheckOnFailureAction": "none",
               "HealthLogDestination": "local",
               "HealthcheckMaxLogCount": 5,
               "HealthcheckMaxLogSize": 500,
               "CreateCommand": [
                    "podman",
                    "run",
                    "--replace",
                    "--interactive",
                    "--cidfile",
                    "/home/user/.local/share/overdeck-sandbox/runs/seathatch-2b31de2c9650/cid",
                    "--name",
                    "overdeck-sandbox-seathatch-2b31de2c9650",
                    "--hostname",
                    "sandbox-seathatch-2b31de2c9650",
                    "--userns=keep-id",
                    "--cap-drop=ALL",
                    "--security-opt=no-new-privileges",
                    "--pids-limit",
                    "512",
                    "--memory",
                    "12g",
                    "--memory-swap",
                    "12g",
                    "--cpus",
                    "4",
                    "--cpu-shares",
                    "256",
                    "--volume",
                    "/home/user/sandbox:/sandbox:rw",
                    "--volume",
                    "/home/user/.local/share/overdeck-sandbox/secrets/e2e_key:/sandbox-secrets/e2e_key:ro",
                    "--volume",
                    "/home/user/.local/share/overdeck-sandbox/secrets/e2e_known_hosts:/sandbox-secrets/e2e_known_hosts:ro",
                    "--volume",
                    "/home/user/cdx-offload/git-common/overdeck-73dd7c243420:/home/user/cdx-offload/git-common/overdeck-73dd7c243420:rw",
                    "--volume",
                    "/home/user/cdx-offload/git-common/overdeck-73dd7c243420/worktrees/seathatch:/home/user/cdx-offload/git-common/overdeck-73dd7c243420/worktrees/seathatch:rw",
                    "--volume",
                    "/home/user/.local/state/overdeck-sandbox/creds/1786147833928152880-3212288-23735/codex/auth.json:/sandbox-secrets/codex/auth.json:ro",
                    "--workdir",
                    "/sandbox/workspaces/seathatch-2b31de2c9650",
                    "--env",
                    "SANDBOX_ID=seathatch-2b31de2c9650",
                    "--env",
                    "SANDBOX_IMAGE=localhost/overdeck-agent-sandbox:c257a4c3027b",
                    "--env",
                    "SANDBOX_E2E_TARGET=user@host.containers.internal",
                    "--env",
                    "SANDBOX_E2E_PORT=2222",
                    "localhost/overdeck-agent-sandbox:c257a4c3027b",
                    "/bin/sh",
                    "-c",
                    "[ -n \"${HOME-}\" ] || { echo 'agent_cred: HOME unset in container' \u003e\u00262; exit 10; }\nagent_cred_target=\"${HOME%/}/.codex/auth.json\"\ntrap 'rm -f \"$agent_cred_target\"' EXIT HUP INT TERM\nmkdir -p \"${agent_cred_target%/*}\" || { echo 'agent_cred: cannot create credential directory' \u003e\u00262; exit 10; }\n[ -r '/sandbox-secrets/codex/auth.json' ] || { echo 'agent_cred: staging mount missing: /sandbox-secrets/codex/auth.json' \u003e\u00262; exit 10; }\ncp '/sandbox-secrets/codex/auth.json' \"$agent_cred_target\" || { echo 'agent_cred: credential copy failed' \u003e\u00262; exit 10; }\nchmod 600 \"$agent_cred_target\" || { echo 'agent_cred: cannot restrict credential mode' \u003e\u00262; exit 10; }\n\"$@\"",
                    "sh",
                    "codex",
                    "exec",
                    "--sandbox",
                    "danger-full-access",
                    "--skip-git-repo-check",
                    "-m",
                    "gpt-5.6-luna",
                    "-c",
                    "model_reasoning_effort=high",
                    "Work ONLY inside the git worktree /home/user/Projects/overdeck/.worktrees/seathatch (never in /home/user/Projects/overdeck itself). Do not touch modules/sandbox/**, any Containerfile, or modules/workstation/claude/bin/local-dispatch-guard.\n\nGOAL: remove the env-var fail-open HARNESS_SEAT_REMOTE=0 from the harness remote-seat path, so that no environment variable can bring a headless agent seat back onto the workstation. The canonical denial mechanism already exists and stays authoritative: ~/.claude/bin/local-dispatch-guard (exit 97, \"headless agent dispatch on this workstation is denied\"), which every wrapper (claude.sh:75-83, codex.sh:163-171, ca.sh:136-144) calls before spawning the engine. Its rule: a TTY on fd 0/1/2 (a human is attached) allows local execution; headless does not. That IS the human escape hatch — do NOT invent another one, and do NOT add any new env var.\n\nEXACT CHANGES — implement all of them, nothing else:\n\n1. modules/harness/seat/remote-seat.mjs\n   In adapterRemotable(), delete the line:\n     if (process.env.HARNESS_SEAT_REMOTE === \"0\") return { ok: false, reason: \"kill-switch HARNESS_SEAT_REMOTE=0\" };\n   Nothing else in this file changes. Leave the HARNESS_SEAT_CONTAINER branch at line ~342 alone.\n\n2. modules/harness/wrappers/lib/remote-seat.sh\n   Delete the line:  [[ \"${HARNESS_SEAT_REMOTE:-}\" == \"0\" ]] \u0026\u0026 return 1\n   Update the header comment so it states the truth: enable/disable is CONFIG (modules/harness/seat/seat-remote.json) only; there is no env kill switch; when the launcher says run-locally, local execution is still subject to local-dispatch-guard, which denies a headless dispatch with exit 97. Keep the comment SHORT (comments describe what the code does, never reasoning/history).\n\n3. modules/harness/seat/README.md\n   Line ~34: delete the \"HARNESS_SEAT_REMOTE=0 -\u003e kill switch\" bullet. Replace with one line stating that remoting is switched off only in seat-remote.json / build-remote.json and that a headless local dispatch is refused with exit 97 by local-dispatch-guard. Keep the HARNESS_SEAT_CONTAINER bullet.\n\n4. modules/harness/seat/test/seat-contract.test.sh\n   Replace the two lines\n     HARNESS_SEAT_REMOTE=0 node \"$LAUNCHER\" --check codex \u003e/dev/null 2\u003e\u00261\n     check \"HARNESS_SEAT_REMOTE=0 kill switch forces local\" \"$?\" 1\n   with a REGRESSION assertion that the hatch is gone: the same command must now exit 0 (\"HARNESS_SEAT_REMOTE=0 no longer forces local\"). Everything else in this file is unchanged.\n\n5. modules/harness/wrappers/claude-classification.test.sh\n   This suite currently relies on HARNESS_SEAT_REMOTE=0 to stop the wrapper from dispatching a real remote seat. Replace that with a fixture that removes the seat shim instead of setting an env var:\n   - after $tmp is created, do: cp -r \"$root\" \"$tmp/wrappers\" ; rm -f \"$tmp/wrappers/lib/remote-seat.sh\"\n     ($root is the wrappers dir; claude.sh computes SKILL_DIR=\"$(dirname $0)/..\" and only uses it for \"$SKILL_DIR/wrappers/lib/remote-seat.sh\", guarded by `if [[ -f ... ]]`, so the copied wrapper takes the local path with byte-identical code under test.)\n   - run_case must invoke  bash \"$tmp/wrappers/claude.sh\"  instead of  bash \"$root/claude.sh\".\n   - delete HARNESS_SEAT_REMOTE=0 from the env list. Keep everything else (HOME, PATH, CLAUDE_TEST_MODE, _CLAUDE_ENGINE_BIN, the stubbed local-dispatch-guard).\n   The suite must still pass unchanged in its assertions.\n\n6. NEW FILE modules/harness/seat/test/seat-hatch.test.sh (executable, bash, same PASS/FAIL/check helper style as seat-contract.test.sh, exits nonzero if any check fails). It must prove the hatch is closed END TO END through the real wrapper — not by unit-testing a function. Build in $tmp:\n   - $tmp/home/.claude/bin/local-dispatch-guard  = a COPY of the real modules/workstation/claude/bin/local-dispatch-guard from this repo (resolve its path relative to the test file). Not a stub.\n   - $tmp/bin/claude = a stub that does `touch \"$SENTINEL\"` and prints {\"is_error\":false,\"session_id\":\"s\",\"result\":\"ok\"} then exits 0, where SENTINEL is passed via env SEAT_HATCH_SENTINEL. It must also answer `auth status --json` with {\"status\":\"ok\"} exit 0 (claude.sh health-checks it).\n   - $tmp/ws = a git repo (git init, one commit) used as --workspace.\n   - a disabled seat config $tmp/seat-remote-off.json  = a copy of modules/harness/seat/seat-remote.json with \"enabled\": false.\n   - a transport config $tmp/build-remote.json with hosts [\"seat-hatch-unreachable.invalid\"], port 2222, ssh_user \"user\", remote_root \"/home/user/builds\", identity_file \"~/.ssh/id_ed25519_buildbox\", local_fallback false, local_only [], max_remote_jobs 1.\n   Run the REAL modules/harness/wrappers/claude.sh (so the seat shim IS present) with env -i, HOME=$tmp/home, PATH=\"$tmp/bin:/usr/bin:/bin\", and assert three cases:\n   A) HARNESS_SEAT_REMOTE=0 set, real (enabled) seat config, BUILD_REMOTE_CONFIG=$tmp/build-remote.json, headless (stdin/stdout/stderr are pipes/files):\n      the sentinel file must NOT exist afterwards and rc must not be 0 — the seat was still routed remotely and failed on the unreachable host instead of running on this machine.\n   B) HARNESS_SEAT_REMOTE=0 AND HARNESS_SEAT_CONFIG=$tmp/seat-remote-off.json, headless:\n      rc must be 97 and the sentinel must NOT exist — with remoting switched off the local path is refused by local-dispatch-guard.\n   C) same as B but with a real pty so a human-at-a-terminal is simulated: run it under `script -qec \"\u003ccommand\u003e\" /dev/null` (util-linux script; quote carefully, keep env via a small generated runner script in $tmp so nothing depends on shell quoting) — rc must be 0 and the sentinel MUST exist. This proves the human escape still works and that the deny in B is the TTY rule, not a blanket failure.\n   Case C must be skipped with a printed SKIP (not a FAIL) only if `script` is not installed. Every case must clean the sentinel before running.\n\n7. Wire the new test into whatever runner already runs modules/harness/seat/test/seat-contract.test.sh (find it; e.g. a run-tests.sh / test list). If seat-contract.test.sh is discovered by glob, nothing to do — say so.\n\nCONSTRAINTS:\n- No new env var, no new flag, no fallback that could execute the engine on the workstation.\n- Do not weaken or delete any existing assertion to make a suite pass; if something fails, fix the code, not the test.\n- Do not run anything that forks heavily, no builds, no network beyond the intentional DNS miss to the .invalid host.\n- Run and report the ACTUAL output of: bash modules/harness/seat/test/seat-contract.test.sh ; bash modules/harness/seat/test/seat-hatch.test.sh ; bash modules/harness/wrappers/claude-classification.test.sh ; bash modules/harness/wrappers/ca-identity.test.sh\n- Report honestly: exact pass/fail counts per suite, and anything you could not verify. Do not claim a green you did not observe.\n- Commit nothing. Leave the changes in the worktree."
               ],
               "Umask": "0022",
               "Timeout": 0,
               "StopTimeout": 10,
               "Passwd": true,
               "sdNotifyMode": "container"
          },
          "HostConfig": {
               "Binds": [
                    "/home/user/sandbox:/sandbox:rw,rprivate,rbind",
                    "/home/user/.local/share/overdeck-sandbox/secrets/e2e_key:/sandbox-secrets/e2e_key:ro,rprivate,rbind",
                    "/home/user/.local/share/overdeck-sandbox/secrets/e2e_known_hosts:/sandbox-secrets/e2e_known_hosts:ro,rprivate,rbind",
                    "/home/user/cdx-offload/git-common/overdeck-73dd7c243420:/home/user/cdx-offload/git-common/overdeck-73dd7c243420:rw,rprivate,rbind",
                    "/home/user/cdx-offload/git-common/overdeck-73dd7c243420/worktrees/seathatch:/home/user/cdx-offload/git-common/overdeck-73dd7c243420/worktrees/seathatch:rw,rprivate,rbind",
                    "/home/user/.local/state/overdeck-sandbox/creds/1786147833928152880-3212288-23735/codex/auth.json:/sandbox-secrets/codex/auth.json:ro,rprivate,rbind"
               ],
               "CgroupManager": "systemd",
               "CgroupMode": "private",
               "ContainerIDFile": "/home/user/.local/share/overdeck-sandbox/runs/seathatch-2b31de2c9650/cid",
               "LogConfig": {
                    "Type": "journald",
                    "Config": null,
                    "Path": "",
                    "Tag": "",
                    "Size": "-1B"
               },
               "NetworkMode": "pasta",
               "PortBindings": {},
               "RestartPolicy": {
                    "Name": "no",
                    "MaximumRetryCount": 0
               },
               "AutoRemove": false,
               "AutoRemoveImage": false,
               "Annotations": {
                    "io.container.manager": "libpod",
                    "io.podman.annotations.cid-file": "/home/user/.local/share/overdeck-sandbox/runs/seathatch-2b31de2c9650/cid",
                    "io.podman.annotations.pids-limit": "512",
                    "io.podman.annotations.userns": "keep-id",
                    "org.opencontainers.image.stopSignal": "15",
                    "org.systemd.property.KillSignal": "15",
                    "org.systemd.property.TimeoutStopUSec": "uint64 10000000"
               },
               "VolumeDriver": "",
               "VolumesFrom": null,
               "CapAdd": [],
               "CapDrop": [
                    "CAP_CHOWN",
                    "CAP_DAC_OVERRIDE",
                    "CAP_FOWNER",
                    "CAP_FSETID",
                    "CAP_KILL",
                    "CAP_NET_BIND_SERVICE",
                    "CAP_SETFCAP",
                    "CAP_SETGID",
                    "CAP_SETPCAP",
                    "CAP_SETUID",
                    "CAP_SYS_CHROOT"
               ],
               "Dns": [],
               "DnsOptions": [],
               "DnsSearch": [],
               "ExtraHosts": [],
               "HostsFile": "",
               "GroupAdd": [],
               "IpcMode": "shareable",
               "Cgroup": "",
               "Cgroups": "default",
               "Links": null,
               "OomScoreAdj": 0,
               "PidMode": "private",
               "Privileged": false,
               "PublishAllPorts": false,
               "ReadonlyRootfs": false,
               "SecurityOpt": [
                    "no-new-privileges"
               ],
               "Tmpfs": {},
               "UTSMode": "private",
               "UsernsMode": "private",
               "IDMappings": {
                    "UidMap": [
                         "0:1:1000",
                         "1000:0:1",
                         "1001:1001:64536"
                    ],
                    "GidMap": [
                         "0:1:1000",
                         "1000:0:1",
                         "1001:1001:64536"
                    ]
               },
               "ShmSize": 65536000,
               "Runtime": "oci",
               "ConsoleSize": [
                    0,
                    0
               ],
               "Isolation": "",
               "CpuShares": 256,
               "Memory": 12884901888,
               "NanoCpus": 4000000000,
               "CgroupParent": "user.slice",
               "BlkioWeight": 0,
               "BlkioWeightDevice": null,
               "BlkioDeviceReadBps": null,
               "BlkioDeviceWriteBps": null,
               "BlkioDeviceReadIOps": null,
               "BlkioDeviceWriteIOps": null,
               "CpuPeriod": 100000,
               "CpuQuota": 400000,
               "CpuRealtimePeriod": 0,
               "CpuRealtimeRuntime": 0,
               "CpusetCpus": "",
               "CpusetMems": "",
               "Devices": [],
               "DiskQuota": 0,
               "KernelMemory": 0,
               "MemoryReservation": 0,
               "MemorySwap": 12884901888,
               "MemorySwappiness": -1,
               "OomKillDisable": false,
               "PidsLimit": 512,
               "Ulimits": [
                    {
                         "Name": "RLIMIT_NOFILE",
                         "Soft": 524288,
                         "Hard": 524288
                    },
                    {
                         "Name": "RLIMIT_NPROC",
                         "Soft": 127162,
                         "Hard": 127162
                    }
               ],
               "CpuCount": 0,
               "CpuPercent": 0,
               "IOMaximumIOps": 0,
               "IOMaximumBandwidth": 0,
               "CgroupConf": null
          },
          "UseImageHosts": false,
          "UseImageHostname": false
     }
]
