Skip to content

🤖 fix: verify-xum names the umask fix, fails fast on a lost leader, keeps the guard from agent-browser - #7917

Merged
ThomasK33 merged 4 commits into
mainfrom
verify-xum-launch-hints
Nov 4, 2026
Merged

ThomasK33 merged 4 commits into
mainfrom
verify-xum-launch-hints

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Nov 4, 2026 •

Copy link
Copy Markdown
Member

Summary

This PR adds three small verify-xum follow-ups from the #7914 advisor. On a umask 002 host, the git-dir refusal now names the folder and how to fix it. Launch fails within seconds when the new server group cannot record its id, instead of waiting out the deadline. Cleanup's agent-browser calls no longer inherit the launch guard, so they cannot block later launches. Only files under .xum/skills/verify-xum/ change.

Background

  • 🤖 fix: harden verify-xum launch, cleanup and recipes (follow-up to #7895) #7914 made every command refuse a git dir, or a folder above it, that group or others can write. Under umask 002, the default on Debian and Ubuntu, which give each user a private group, git creates a clone's folder, .git and .git/worktrees/<name> with mode 0775. So every command refused, and the message did not say what to do.
  • 🤖 fix: harden verify-xum launch, cleanup and recipes (follow-up to #7895) #7914 made the new group's leader exit before make when it cannot append its id to state.env. Launch still waited for the whole VERIFY_XUM_READY_TIMEOUT (default 300 s) before it failed.
  • launch_failed runs cleanup while it holds the launch guard on fd 9. Cleanup's agent-browser calls inherited that fd, so any daemon they started would hold the flock and block every later launch from the checkout.

Implementation

  • require_private_dir and require_safe_ancestors take an optional fix text. The git-dir rule passes one that names the refused folder: "run chmod g-w,o-w (git makes its folders group-writable under umask 002), or use a checkout made under umask 022". SKILL.md says the same next to the rule. The folder in that command is quoted with printf %q and inserted by splitting the text at @DIR@, not by ${var//pat/rep}, because bash 5.2's patsub_replacement undoes the quoting of & and \ (review: quote the directory, preserve escaping). A folder with a space, a glob character, & or \ can then be fixed by copying the command.
  • The launch wait loop keeps $!. When that process is gone and no process carries VERIFY_XUM_SERVER_OF=<run id> (the leader has it from its start, also when setsid forked), the loop reads state.env once more. If no id is there, it fails with "the server's process group exited before it wrote its id to …/state.env (a read-only file or a full disk?)".
  • agent-browser session list and close in cleanup run with 9>&-.

Validation

Each proof compares this branch with main at 26b8c8f.

  • umask 002 checkout: a fixture made with git init and git worktree add under umask 002 had the repo, .git and .git/worktrees/wt at 0775.
    • Main refuses with "…/.git/worktrees/wt is writable by group or others (mode 775)" and gives no fix.
    • This branch names each folder in turn, with the chmod fix: worktrees/wt, worktrees, .git, then the repo. After the four chmod commands it names, env reaches "no run at …", so the git-dir checks pass.
    • With checkouts at $F/Xum Repo*, $F/amp&ersand and $F/back\slash, each printed command exits 0, and env then passes. Before the quoting, the printed command failed for the first. With replacement-based quoting, the & case ran ersand/.git as a second command and the \ case failed.
  • Failed PGID write: a wrapper setsid made state.env read-only just before the leader appends its id (VERIFY_XUM_READY_TIMEOUT=20).
    • Main failed after 20 s with "launch did not finish in 20 s".
    • This branch failed after 2 s with the new message. No process was left with the run's id.
  • Guard after a failed launch: a wrapper agent-browser started a stand-in daemon (sleep, with its stdio on /dev/null, keeping every inherited fd) on session list.
    • On main, the stand-in kept the guard after the failed launch. The next launch failed after 20 s with "another verify-xum launch from this checkout holds …/verify-xum.lock.guard".
    • On this branch, the guard was free, and the next launch went straight on to its own failure.
    • With agent-browser 0.33.2, session list and close of an unknown session left no process holding a test flock. The stand-in shows what the change prevents. It is not a failure I saw with 0.33.2.
  • Full token-mode proof of SKILL.md and every features/*.md recipe: 184 PASS, 0 FAIL (at cdcce43, before the merge of main and the quoting fix, which changes only the refusal text).
  • make static-check, plus shellcheck 0.8.0 (CI's version).

Risks

The risk is low. Only the agent-facing verify-xum skill changes. The fail-fast check runs only after $! has exited without an id in state.env, and it reads state.env once more before it fails. A leader that wrote its id and then died is still handled by the startup checks that follow.


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: xhigh • Cost: $186.72

…eeps the guard from agent-browser

Under umask 002 git makes a clone's folder, .git and .git/worktrees/<name>
0775, so every command refused without saying what to do. The git-dir
refusals now name the folder and the fix (chmod g-w,o-w on it, or a
checkout made under umask 022), and SKILL.md says so next to the rule.

A leader that cannot write its id to state.env exits before make, but
launch waited for the whole deadline. The wait loop now stops when the
leader is gone and no process carries the run's id, and says why.

From launch_failed, cleanup runs agent-browser with the launch guard on
fd 9. Those calls now close fd 9, so an agent-browser daemon started there
cannot hold the flock and block every later launch.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `xhigh` • Cost: `$186.72`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh costs=186.72 -->
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 4, 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-11-04T14:37:31.201990Z 2f9b548 Manual request
🔒 Security Review ✅ Completed 2026-11-04T14:40:25.072213Z 2f9b548 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.

@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: 1b3afd7df1

ℹ️ 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".

The umask fix printed the folder as is, so a folder with a space or a
glob character gave a command that split or expanded the path. The fix
now quotes the folder with printf %q, so the command can be copied as
printed.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `xhigh` • Cost: `$186.72`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh costs=186.72 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@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: 8dc5c63a5a

ℹ️ 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".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 8dc5c63a5a

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Bash 5.2's patsub_replacement reads & and \ in the replacement of
${var//pat/rep} again, so the printf %q quoting of a folder named
amp&ersand or back\slash was undone and the printed chmod command ran
shell syntax or missed the folder. The fix text is now split at @dir@
and the folder is printed with %q between the two parts.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `xhigh` • Cost: `$186.72`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh costs=186.72 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 2f9b54853b

ℹ️ 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".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 2f9b54853b

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33
ThomasK33 added this pull request to the merge queue Nov 4, 2026
Merged via the queue into main with commit 6b7ea27 Nov 4, 2026
25 of 26 checks passed
@ThomasK33
ThomasK33 deleted the verify-xum-launch-hints branch November 4, 2026 17:51
yermakoffivan pushed a commit to yermakoffivan/mux that referenced this pull request Nov 4, 2026
…ly for your own folders (coder#7919)

## Summary

Every verify-xum launch on a host whose `/usr/bin/date` is uutils
coreutils 0.8 failed at the 300 s deadline. This PR fixes that: launch
now reads its start time from `node -p 'Date.now()'`. It also adds one
coder#7917 advisor follow-up: the `chmod` fix in the git-dir refusal now
appears only for a folder the user owns. Only files under
`.xum/skills/verify-xum/` change.

## Background

- Launch waits for a build stamp newer than its own start (`t0`).
`scripts/build-main-watch.js` writes that stamp as `Date.now()` in
milliseconds. `t0` came from `date +%s%3N`.
- uutils date 0.8.0 ignores the `3` in `%3N` and prints nanoseconds. On
this host, `date +%s%3N` printed `1793814151776897404` (19 digits).
- No 13-digit stamp is ever newer than that, so launch never saw a fresh
build.
- coder#7917 added a `chmod g-w,o-w <folder>` fix to the refusals for
group-writable git dirs and the folders above them. For a folder the
user does not own, such as a root-owned, group-writable folder above the
checkout, that command fails with "Operation not permitted".

## Implementation

- `t0=$(node -p 'Date.now()')` takes the stamp's own clock and unit.
`node` is already a launch requirement. `t0` is the only millisecond
timestamp in the skill. The run id's `date -u +%Y%m%d-%H%M%S` has no
width flag.
- In `require_safe_ancestors`, a writable folder that the user does not
own gets "use a checkout under folders you own" instead of the `chmod`
fix. `refusal_fix` now also prints a fix text that names no folder.
SKILL.md says the same next to the umask 002 note.

## Validation

- **Launch on this host**, with `VERIFY_XUM_READY_TIMEOUT=120`,
comparing main (96216fc) with this branch:

  | `date` on PATH | `date +%s%3N` prints | main | this branch |
  | --- | --- | --- | --- |
| uutils 0.8.0 (`/usr/bin/date`) | 19 digits | fails at the deadline
after 122 s: "launch did not finish in 120 s" | ready after 19 s |
| GNU coreutils 9.7 (`/usr/bin/gnudate`, linked as `date` on PATH) | 13
digits | ready after 13 s | ready after 13 s |

- **Folder you do not own:** a repo made under umask 002, below a
root-owned 0775 folder (created with `sudo` for the test).
- Main printed `run chmod g-w,o-w $B/rootdir` for the root-owned folder.
That command failed with "Operation not permitted", and every later run
printed it again.
- This branch still prints the `chmod` fix for the user's own `.git` and
repo folder, and those commands exit 0. For the root-owned folder it
says "use a checkout under folders you own".
- **Full token-mode proof** of SKILL.md and every `features/*.md`
recipe, on this host with uutils date: 184 PASS, 0 FAIL at 15e96ea
(and at d9ce137 before the merge of coder#7917).
- `make static-check`, plus shellcheck 0.8.0 (CI's version) over all 46
shell scripts.

## Risks

The risk is low. Only the agent-facing verify-xum skill changes. `t0`
now comes from the same clock that writes the build stamp. The refusal
change only alters the text of a message that already refuses.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking:
`xhigh` • Cost: `$213.46`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh
costs=213.46 -->
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