Skip to content

feat(sandbox): thin cos onto createos-cli's offload/matrix/fork --count - #30

Open
pratikbin wants to merge 1 commit into
mainfrom
feat/full-sandbox-surface
Open

feat(sandbox): thin cos onto createos-cli's offload/matrix/fork --count#30
pratikbin wants to merge 1 commit into
mainfrom
feat/full-sandbox-surface

Conversation

@pratikbin

Copy link
Copy Markdown
Contributor

Summary

Sub-project C of the sandbox-surface work: thins scripts/cos onto the compositions createos-cli just shipped (createos-cli#84), and adds the matrix verb the plugin didn't have before.

  • cos offload now delegates to createos sandbox offload <dir> -- <cmd> instead of a ~65-line hand-rolled stage/push/exec/keepalive/pull/destroy sequence. Same flags (minus -w, see below), same UX, less code to maintain, and it inherits the Go implementation's retry-on-connection-failure and no-billable-leak-on-teardown-failure behavior for free.
  • cos fanout now delegates to createos sandbox matrix <dir> --job ... --job ... (no --prepare) — each job runs on a fork of one staged box rather than an independently staged box. Same isolation (every job started from an identical staged state either way), faster (fork is a ~1s server-side copy).
  • New cos matrix / /createos-sandbox:matrixfanout plus -P '<setup>', which runs once on the golden box before it forks. For the case two or more jobs share the same dependency install or toolchain prep.
  • cos fork keeps its own pause-then-resume orchestration around the project box (legitimate — it's forking a box it owns, on request), but the fork step and id resolution now delegate to createos sandbox fork -o json, which returns the new id directly. This deletes the comm-diff-against-sandbox ls hack and the multibyte/set -u trap that came with it (see the removed comment in the old code). Gained -c N for direct N-way cloning.
  • -w/--swap dropped from offloaddevbox:1 can't swapon a file added post-boot from most shapes anyway, so the flag bought little for the maintenance cost. Documented as something to compose into the command string instead ('fallocate -l 4G /swapfile && mkswap /swapfile && swapon /swapfile && <cmd>').
  • Docs updated throughout — skill, references, command frontmatter, README — for the new/changed verbs, and to correct a stale "2 concurrent boxes" quota claim to the actually-observed number (10).

A real bug found and fixed along the way

Live-testing this against createos-cli's feat/sandbox-compositions branch (five scenarios in tmux, drawn from the product's own use-case catalog — untrusted-code offload, independent-job fanout, shared-setup matrix, project-box fork, and a background job self-deleting via the loopback signal endpoint) caught a real bug: fork <sandbox> --count 2 silently created one clone instead of two, with no error.

Root cause: Go's stdlib flag package (under urfave/cli) stops parsing at the first non-flag argument. fork <sandbox> --count 2 — sandbox id first, the order every caller actually writes, cos included — never has --count parsed as a flag at all; it lands unread in c.Args(), and c.Int("count") silently returns the flag's default (1). The existing regression test for --count validation only ever wrote --count before the id, so it never exercised this path.

Fixed on the createos-cli side (feat/sandbox-compositions, now pushed to createos-cli#84) by reusing the raw-argv fallback already built for process run --cwd (commit 8c1f7ac) — confirmed fixed with a new regression test using the natural argument order, and reconfirmed live before writing this description.

Test plan

  • bash -n + shellcheck -x clean on scripts/cos
  • Live, via COS_CLI=/tmp/createos-dev against createos-cli#84: offload (locked egress, blocked reaching an unlisted host), fanout (4 independent jobs, correct mixed exit codes), matrix -P (3 jobs, prepare output identical across all forks — proves it ran once), fork -c N (2 clones from one call, after the count fix), self-signal (curl 127.0.0.1:1029/self/delete from inside a cos run job — confirmed via sandbox get showing status: destroyed)
  • No sandboxes leaked across any of the above — verified against account sandbox count before/after, including cleanup of a few stragglers from debugging the count bug itself

scripts/cos's offload and fanout bodies (stage, push, exec, keepalive,
pull, destroy — one copy per verb) are replaced with thin delegates to
`createos sandbox offload` and `createos sandbox matrix`, which already
do this composition in Go with retry, no billable leaks on failure, and
a teardown failure that fails the command instead of hiding it.

- `cos offload` -> `createos sandbox offload <dir> -- <cmd>`
- `cos fanout` -> `createos sandbox matrix <dir> --job ... --job ...`
  (no --prepare) — a fork of one staged box per job, not an
  independently-staged box per job. Same isolation, faster.
- new `cos matrix` / `/createos-sandbox:matrix` — fanout plus -P
  '<setup>' to run once on the golden box before forking, for the case
  every job shares the same dependency install or toolchain prep.
- `cos fork` keeps its own pause-then-resume orchestration around the
  project box (legitimate: it is forking a box it owns, on request),
  but the fork step itself and id resolution now delegate to
  `createos sandbox fork -o json`, which returns the new id directly.
  This deletes the comm-diff-against-`sandbox ls` hack and the
  documented multibyte/set -u trap that came with it. Gained -c N for
  direct N-way cloning of the project box.
- -w/--swap dropped from offload (per discussion): devbox:1 can't
  swapon a file added post-boot anyway, so the flag bought little.
  Documented as something to compose into the command string instead.

Docs updated throughout (skill, references, command frontmatter, README)
for the new/changed verbs and to correct a stale "2 concurrent boxes"
quota claim to the observed number (10).

Verified live via tmux against createos-cli's feat/sandbox-compositions
branch (COS_CLI override), running five scenarios pulled from the
product's own use-case catalog: untrusted-code offload with locked
egress, independent-job fanout, shared-setup matrix (-P ran exactly
once across all forks), project-box fork -c N, and a background job
ending its own box via the loopback self-signal endpoint.

That live run caught a real bug in createos-cli: `fork <sandbox>
--count 2` silently created one clone instead of two, with no error —
Go's stdlib flag parser stops at the first non-flag argument, so
--count written after the sandbox id (the order every caller actually
writes, cos included) was never parsed at all. Fixed on the
createos-cli side (feat/sandbox-compositions, reusing the raw-argv
fallback already built for `process run --cwd`) and confirmed fixed
here before writing this up.
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.

1 participant