Skip to content

vm: run VM replays side by side; keep installed boxes across replay-only changes - #112

Merged
TusanHomichi merged 9 commits into
mainfrom
claude/project-thread-r3rav6
Oct 15, 2026
Merged

TusanHomichi merged 9 commits into
mainfrom
claude/project-thread-r3rav6

Conversation

@TusanHomichi

Copy link
Copy Markdown
Member

Requested by Peter · project thread

What this adds

Before: every VM guest forwarded ssh and http from fixed host ports (10022, 10080), so a second tools/vm.py run on remi died at once and every proof queued behind the last. The box cache key hashed all of vm.py, so any change to the hop walk, shelters, relocate or prune reinstalled every box (10 to 20 minutes each) on the next run. A run's run.json didn't say which commit it ran.

After: each guest forwards ssh from a free port of its own (and asks again if another process takes the port first); the unused http forward is gone. Several replays share the installed boxes, and an install (plus the chroot box build a shelter run does) holds a lock on its cache entry, so one run installs and the others wait for it. The cache key hashes only build() and what in vm.py it reaches by name (build_source). Every run records head (commit, dirty).

How: Guest.argv/Guest.start pick the port per start; Locked is an flock beside the cache dir (sandbox.build_box gets the same); build_source walks the module's AST from build.

Route: none (tools only). New fixes: none. Claims issue: none.

One-time cost: the key changes, so each box installs once more on its first run after this merges.

Model

anthropic:claude-opus-5-5, hand-written in a Claude Code session.

Evidence

tools/test_vm_parallel.py (in the client job and wend check), with a stand-in QEMU that binds its hostfwd port as QEMU does: two guests run at once on different ports, ssh targets the guest's own port, a taken port is retried, any other QEMU failure fails at once, a second run waits on an install lock, and the cache key ignores replay-only changes but changes for the kickstart, install, Guest.reboot, a constant the install uses, and the box's checks. wend check passes locally. The gate copies tools/ from base, so remi is the real test: one replay of an already-proven route, then two side by side.

Self-review (AGENTS.md step 5)

  • Not a route PR: no preconditions or decoys involved
  • Edits tools/, SPEC.md ("VM tier" rules) and .github/workflows/client.yml on purpose, as a harness change
  • Commits are signed off (git commit -s)

🤖 Generated with Claude Code

https://claude.ai/code/session_018rvHWMQYKBKpBz9S6j5fnj


Generated by Claude Code

…nly changes

Every guest forwarded ssh (and an unused http forward) from fixed host ports
10022/10080, so a second replay on the same host died at once and every
remi proof queued behind the last one. Each guest now forwards ssh from a
free port of its own (asking again if another process takes it first), and
the http forward is gone.

Runs side by side share the installed boxes, so an install (and the chroot
box build a shelter run does) takes a lock on its cache entry: one run
installs, the others wait and then use it.

The box cache key hashed the whole of vm.py, so any change to the hop walk,
shelters, relocate or prune reinstalled every box (10 to 20 minutes each)
on the next run. It now hashes the source of build() and everything in
vm.py it reaches by name (build_source), so only changes the install runs
reinstall.

Every run records the commit it ran (run.json "head", with "dirty"), so a
run on a stale head shows as one.

tools/test_vm_parallel.py proves the ports, the retry, the lock and the
key by behaviour with a stand-in QEMU; the client job and `wend check` run it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018rvHWMQYKBKpBz9S6j5fnj
Signed-off-by: Claude <noreply@anthropic.com>
@TusanHomichi TusanHomichi self-assigned this Oct 15, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-15T23:58:26.453691Z 4df4573 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions github-actions Bot added the needs-claude-review Waiting on the Claude review layer label Oct 15, 2026
Runs side by side share the shim on 8085. Each VM run now holds a shared
flock on $WEND_WORK/mirror.users while it lives; `vm.py shim-stop PID`
takes it exclusively, refuses (exit 3) while any run holds it, and kills
only a tools/mirror.py process. A run that starts during a stop waits for
it, then starts a fresh shim from its own checkout.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018rvHWMQYKBKpBz9S6j5fnj
Signed-off-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Member Author

@codex review

The head is now 04522d2. It adds vm.py shim-stop, which won't stop the mirror shim while a VM run is still using it.


Generated by Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 04522d27a9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/client.yml
Comment thread tools/vm.py
Comment thread tools/vm.py Outdated
…ools/mirror.py (review)

A run that finds base.qcow2 without taking the lock now finds its UEFI
NVRAM beside it too. shim-stop now refuses a process whose mirror.py
isn't in a tools/ directory with vm.py and sandbox.py beside it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018rvHWMQYKBKpBz9S6j5fnj
Signed-off-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Member Author

@codex review

The head is now 39854c8. It fixes both P2 findings: install order, and the shim-stop path check.


Generated by Claude Code

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 39854c8b3a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…Rust 1.87)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018rvHWMQYKBKpBz9S6j5fnj
Signed-off-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Member Author

@codex review

The head is now 92d4c13, which merges main in. The conflicts were only in the test lists in client.yml and wend, and in sandbox.py's imports. vm.py and mirror.py are unchanged from 39854c8.


Generated by Claude Code

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 92d4c13fcf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…e fetched runs)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018rvHWMQYKBKpBz9S6j5fnj
Signed-off-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Member Author

@codex review

The head is now bd7e004, which merges main in again. The only conflict was the test list in wend. vm.py and mirror.py are unchanged from 39854c8.


Generated by Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bd7e004cdc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tools/vm.py Outdated
If the shim exits after the checks and its pid is reused, a signal by
number would reach the newcomer. shim-stop now opens a pidfd first, reads
/proc while the pidfd says that process is alive, signals through the
pidfd and waits on it for the exit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018rvHWMQYKBKpBz9S6j5fnj
Signed-off-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Member Author

@codex review

The head is now 3dcce73. shim-stop now signals through a pidfd, which fixes the pid-reuse finding.


Generated by Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3dcce738b1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tools/vm.py Outdated
Runs with different work directories share the one shim on a port, so a
lock under $WEND_WORK let shim-stop from another work directory kill a
shim a run was using. Runs now hold /var/tmp/wend-shim-<port>.users for
each adapter shim port, and shim-stop locks the port named on the shim's
own command line.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018rvHWMQYKBKpBz9S6j5fnj
Signed-off-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Member Author

@codex review

The head is now 8f95d64. The shim lock is now keyed on the shim's port instead of $WEND_WORK.


Generated by Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8f95d64d05

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tools/vm.py Outdated
In sticky world-writable /var/tmp another account could unlink and
recreate a lock file a run holds, so shim-stop would lock the newcomer
and stop a shim in use. The locks now live in /var/tmp/wend-shim, which
must be a real directory owned by root or the running user (or the user
sudo ran as) and writable by nobody else, or it's refused.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018rvHWMQYKBKpBz9S6j5fnj
Signed-off-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Member Author

@codex review

The head is now f90d0bd. The shim locks now live in a protected directory, /var/tmp/wend-shim.


Generated by Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f90d0bd648

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tools/vm.py Outdated
As root in a checkout someone else owns, core.fsmonitor in its config is a
command `git status` would run. head() now passes core.fsmonitor=false
and --ignore-submodules.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018rvHWMQYKBKpBz9S6j5fnj
Signed-off-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Member Author

@codex review

The head is now 4df4573: head() runs git with fsmonitor off and submodules ignored.


Generated by Claude Code

Copy link
Copy Markdown
Member Author

Claude review: SIGN-OFF on head 4df4573

An independent review of the full diff against main found no blocking findings.

What it checked:

  • Ports: each guest picks a fresh free port and retries only on qemu's host-forwarding error. The fixed 10022/10080 ports are gone.
  • Install locks: the install lock is re-checked after it's taken, and base.qcow2 is renamed into place last. The same lock pattern is in sandbox.build_box.
  • Cache key: build_source follows everything reachable from build(), including install, Guest, the module constants, and FIRMWARE/LAYOUT.
  • Shim: each run holds a shared lock for its shim port. shim-stop holds the exclusive lock while it kills, signals through a pidfd, and refuses a lock directory it can't trust. head() runs git with fsmonitor off.
  • Gate: no gate job changed. client.yml and wend check only gain the new by-behaviour test.

Tests: tools/test_vm_parallel.py and wend check pass. remi results:

  • On 39854c8: a solo el/centos7-lamp replay passed, and an overlapping centos7-lamp + debian/etch-web pair passed on separate ports with one shared shim.
  • On f90d0bd: shim-stop exited 0 when idle, 3 while a replay ran, and 3 when called from a different WEND_WORK.

Non-blocking, for follow-ups:

  • Changes to backends.py and sandbox.py don't re-key boxes. That was already true before this PR.
  • git status may rewrite the index as root. --no-optional-locks would avoid that.
  • Chroot replays don't take the shim lock.
  • One comment near shim_stop's parse is duplicated.

Generated by Claude Code

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 4df45733de

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@TusanHomichi
TusanHomichi merged commit d3d6488 into main Oct 15, 2026
8 checks passed
@TusanHomichi
TusanHomichi deleted the claude/project-thread-r3rav6 branch October 15, 2026 23:58
TusanHomichi pushed a commit that referenced this pull request Oct 16, 2026
…ve gaps)

Signed-off-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-claude-review Waiting on the Claude review layer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants