feat(bin): open local review files in tmux and wezterm surfaces - #105
MerpGoaterman wants to merge 6 commits into
Conversation
maaz-codes
left a comment
There was a problem hiding this comment.
Reviewed by building and running it, not just reading the diff.
Reproduced first: copied frontend/ to a scratch tree, chmod -R 0700, built main's Dockerfile from it. Every asset out of public/ came out 700 and answered 403 — tileset, background.mp4, the UI kit, the showcase JSON, favicon — with index.html fine at 644, exactly as you described. nginx's log says open() ... failed (13: Permission denied).
Built your version from the same tree: all 36 files 644, all 7 dirs 755, and every one of those paths 200.
Checked the a+rX argument rather than taking it, since it is the reason for the shape. From the 0700 tree chmod -R a+rX leaves the 31 files from public/ at 755 — every PNG and MP4 executable — while the bundler's 5 stay 644. Your form gives a byte-identical mode listing from the 0700 tree and from an ordinary one; main's differs on 31 files. find /usr/share/nginx/html -type f -perm -u+x is empty on your image.
Ordinary tree unaffected: same modes as before your change, SPA fallback still 200. Then the full stack — docker compose build and up under my own project name and ports — sign-up through to the world screen, sprites and tilemap rendering, console clean.
One thing I did not know before your write-up: that +X sets execute only where a bit already exists is the sort of detail that reads as equivalent until it silently makes the image host-dependent. I would have written the a+rX version.
Two small notes, neither worth changing. The directories in the image are already 755 — Vite creates dist/assets/** itself, so only the copied files arrive at 700; the directory half is insurance rather than the fix, and costs nothing. And the extra layer rewrites what it touches, so a 0700 build goes 113MB to 133MB while an ordinary build stays 113MB because the layer is empty — the cost lands only on the machine with the problem.
Could not test real exFAT either, same as you, so Raphael's run on the drive is still the confirming one.
Intent
The developer was building firstmate tooling so that local report and file references become reviewable in the captain's terminal UI instead of being dead, unclickable paths in chat. They wanted a new helper script (bin/fm-open-file.sh) plus updated AGENTS.md/README/docs guidance covering when to use tmux, WezTerm, or Lavish surfaces, with rules for renderer preference, safe window naming, path rejection, preserving orchestrator focus, and concise output. This was a relaunch continuing existing branch fm/tmux-file-open-p2, and the key correction was that multiple review links should open as a clickable list in a single real WezTerm tab (not tmux windows), while single targets open directly in the appropriate surface and tmux is reserved for explicit requests or terminal-text review. They also instructed the agent to verify with shell syntax checks and a test on an existing report, commit on that branch, and then push the change through the no-mistakes gate, including a workaround of deleting and recreating the gate ref and reconfiguring the fork as the push target after an upstream 403 push failure.
What Changed
bin/fm-open-file.sh, a helper that turns local report/file paths into reviewable terminal surfaces: a single Markdown/text target opens directly in a tmux review tab, multiple targets open as a clickable OSC-8file://link list in one real WezTerm tab, and--lavishroutes a single HTML file to Lavish. It validates paths (rejecting missing, directory, out-of-home, and bare invocations unless--allow-outside), uses safe collision-suffixed window names, and restores the orchestrator's focus after opening.AGENTS.md,README.md,docs/scripts.md, andCONTRIBUTING.mdto document when to use the tmux, WezTerm, or Lavish surface for captain-facing artifacts and to register the new script and its test.tests/fm-open-file.test.sh(4 cases) covering surface selection and path rejection; fixed a temp link-list leak on the WezTerm spawn-failure path and resolved shellcheck SC2209/SC2012 warnings.Risk Assessment
✅ Low: A well-bounded new helper script plus matching docs and hermetic tests; the only prior finding (temp-file leak on WezTerm spawn failure) is correctly fixed with a parent-side EXIT trap, and no further substantiated issues remain.
Testing
Baseline
bash tests/fm-open-file.test.shpasses 4/4. Beyond the stubbed unit tests I ran the helper end-to-end against real tmux and a real generated link list: a single report opened in a focus-preserving, collision-safe tmux tab and rendered in-pane (via less, since glow/bat are absent); three review targets produced one WezTerm tab whose link list contains a real OSC-8 file:// hyperlink per target with clean relative-path labels, satisfying the core correction that multiple links open as a clickable list in a single WezTerm tab; and a CLI transcript confirms missing/directory/out-of-home/bare/bad-lavish inputs are rejected while --allow-outside is the explicit opt-in. No file content leaked into any printed line. Because this is a terminal-hyperlink surface, the reviewer-visible artifact is the captured OSC-8 link-list bytes plus the tmux pane capture rather than a GUI screenshot (a headless WezTerm GUI tab cannot be screenshotted here). Transient fixtures and the temporary tmux session were removed; the worktree is clean.Evidence: Generated WezTerm clickable link list (raw OSC-8 hyperlink bytes via cat -v)
Firstmate review links 1. ^[]8;;file:///.../data/fix-login-k3/report.md^[\data/fix-login-k3/report.md^[]8;;^[ 2. ^[]8;;file:///.../.lavish/plan.html^[.lavish/plan.html^[]8;;^[ 3. ^[]8;;file:///.../data/audit-x9/report.md^[\data/audit-x9/report.md^[]8;;^[ Press Enter to close this tab.Evidence: Raw .ansi link list (terminal renders these as clickable file:// links)
Evidence: Single report rendered in the tmux review tab
# Login fix report Reproduced the 500 on empty password. Root cause in auth.go:42. /private/tmp/.../report.md (END)Evidence: Path-rejection / safety CLI transcript
missing path -> exit 1; directory -> exit 1; outside-home -> exit 1; bare -> usage exit 2; --lavish non-HTML -> exit 1; --lavish multi-file -> exit 1; --allow-outside outside.md -> opened in tmux tab file-outside, exit 0Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 1 issue found → auto-fixed ✅
bin/fm-open-file.sh:232- In the multi-path WezTerm branch, the temp link-list file is created at line 232 but its only cleanup is thetrap '... EXIT'that runs inside the spawned WezTerm shell. If spawn_wezterm_tab fails (wezterm not on PATH at line 193, orwezterm cli spawnfails at line 194), the function callsexit 1in the parent before that shell ever starts, leaking the mktemp file. Add a parent-side cleanup (e.g. a parent EXIT trap that rm's $list_file, or rm on the spawn error path) so the file is removed when the tab never opens.🔧 Fix: fix temp link-list leak on WezTerm spawn failure
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
bash tests/fm-open-file.test.sh(4/4 pass)Real tmux:bin/fm-open-file.sh data/fix-login-k3/report.mdtwice -> tabs report-fix and report-fix-2, focus restoredtmux capture-pane -t firstmate:report-fix-> report rendered in the review tabMulti-target runbin/fm-open-file.sh report.md plan.html report.md-> single WezTerm tab 'links-fix' with one OSC-8 file:// hyperlink per target (inspected generated link-list bytes)Rejection transcript: missing path, directory, out-of-home, bare invocation,--lavishnon-HTML,--lavishmulti-file all exit non-zero;--allow-outsideopens an explicit outside file✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.