Skip to content

S26: wire execution-target placement in shadow mode (SHIP_PLACEMENT=shadow) - #48

Merged
im-tyler merged 1 commit into
mainfrom
claude/w4-placement-wiring
Oct 4, 2026
Merged

im-tyler merged 1 commit into
mainfrom
claude/w4-placement-wiring

Conversation

@im-tyler

@im-tyler im-tyler commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Changes

  • New src/placement-shadow.ts: flag SHIP_PLACEMENT=shadow (default off, any other value is off), conservative declared capabilities (os linux, arch UNKNOWN sentinel, no browser/desktop/services/gpu, static credentials; resources and run cap "very large" and finite), optional operator declarations via SHIP_PLACEMENT_TARGETS (JSON keyed by host URL), SHIP_PLACEMENT_REQUIRE (deployment-wide requirement) and SHIP_PLACEMENT_DRAINING. Appends one JSON line per decision to placement-shadow.jsonl in the state dir (SHIP_PLACEMENT_SHADOW_FILE overrides). Additive JSONL only, no tables.
  • src/sandbox-pool.ts: optional placementShadow option. create/createFrom compute placeRun from the pre-attempt state, then record it against the host actually used. Host choice is untouched. New observeHostLoss(handle).
  • src/durable.ts: optional ExecutorProvider.observeHostLoss, called (try/catch) in the C5 !alive branch just before the unchanged throw. No step added or changed.
  • src/cli.ts: passes the shadow to the pool when the flag is on; new teploy-ship placement shadow-report [--json].

Checks

  • pnpm run lint clean. After rm -rf dist, build + node --test --experimental-test-isolation=none "dist/**/*.test.js": 2002 pass, 0 fail. scripts install-stage + smoke-e2e: 13 pass. Skipped grader-sensitivity and pj-b grader (fixed port 8901; CI runs them).
  • 19 new tests through the real SandboxPool: arch, unknown arch, browser, draining, quota, per-project quota, cooldown/cooling pass, failover, createFrom, host loss, the real durable C5 path, on/off identical placement, throwing sink, env parsing, report.
  • Negative controls (code broken, test failed, restored): UNKNOWN_ARCH set to amd64 (1 fail); draining ignored (2 fail); durable hook removed (1 fail). The pool itself is the naive least-loaded/first-healthy choice and shows disagreements on arch, browser, draining and quota.

Not verified / still open

  • Shadow only; no live pool or real multi-host fleet. Nothing enforces placement.
  • Ship records no per-run arch/browser needs, so requirements come only from limits, warm repo, and the operator's SHIP_PLACEMENT_REQUIRE.
  • The pool has no drain concept: draining comes only from config.
  • A failed liveness probe cannot be told apart from container TTL expiry; host-loss records both clean and dirty tree bounds, and treat no snapshot as known.
  • A failover to a second host is recorded as a benign different-choice. A create that fails everywhere records nothing.
  • Per-project counts cover only runs this process placed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VqsBNqvaWezf1DwQrAnVgX


Generated by Claude Code

…hadow)

SandboxPool.create/createFrom compute placeRun beside the existing
least-loaded choice, and the C5 liveness failure records what onHostLoss
would have done. Both only append to placement-shadow.jsonl; the chosen host
and the failure are unchanged. Default off. Adds 'placement shadow-report'.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VqsBNqvaWezf1DwQrAnVgX
@im-tyler
im-tyler merged commit 59579f4 into main Oct 4, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants