Skip to content

feat(bin): open local review files in tmux and wezterm surfaces#105

Open
MerpGoaterman wants to merge 6 commits into
kunchenguid:mainfrom
MerpGoaterman:fm/tmux-file-open-p2
Open

feat(bin): open local review files in tmux and wezterm surfaces#105
MerpGoaterman wants to merge 6 commits into
kunchenguid:mainfrom
MerpGoaterman:fm/tmux-file-open-p2

Conversation

@MerpGoaterman

Copy link
Copy Markdown

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

  • Added 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-8 file:// link list in one real WezTerm tab, and --lavish routes 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.
  • Updated AGENTS.md, README.md, docs/scripts.md, and CONTRIBUTING.md to document when to use the tmux, WezTerm, or Lavish surface for captain-facing artifacts and to register the new script and its test.
  • Added 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.sh passes 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.

Firstmate review links

1. ^[]8;;file:///private/tmp/fmopen-e2e.hZ3Es1/home/data/fix-login-k3/report.md^[\data/fix-login-k3/report.md^[]8;;^[\
2. ^[]8;;file:///private/tmp/fmopen-e2e.hZ3Es1/home/.lavish/plan.html^[\.lavish/plan.html^[]8;;^[\
3. ^[]8;;file:///private/tmp/fmopen-e2e.hZ3Es1/home/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)
Firstmate review links

1. �]8;;file:///private/tmp/fmopen-e2e.hZ3Es1/home/data/fix-login-k3/report.md�\data/fix-login-k3/report.md�]8;;�\
2. �]8;;file:///private/tmp/fmopen-e2e.hZ3Es1/home/.lavish/plan.html�\.lavish/plan.html�]8;;�\
3. �]8;;file:///private/tmp/fmopen-e2e.hZ3Es1/home/data/audit-x9/report.md�\data/audit-x9/report.md�]8;;�\

Press Enter to close this tab.
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)

# Login fix report
Reproduced the 500 on empty password. Root cause in auth.go:42.
/private/tmp/fmopen-e2e.hZ3Es1/home/data/fix-login-k3/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 0

### Rejection / safety contract (end-user CLI behavior)

$ fm-open-file.sh data/fix-login-k3/nope.md
error: not a regular file: data/fix-login-k3/nope.md
  -> exit 1

$ fm-open-file.sh browsedir
error: directories are not supported: browsedir
  -> exit 1

$ fm-open-file.sh /tmp/fmopen-e2e.hZ3Es1/outside.md
error: path is outside firstmate home; pass --allow-outside only for an explicitly chosen safe file
  -> exit 1

$ fm-open-file.sh 
usage: fm-open-file.sh [--allow-outside] [--lavish] [--tmux] <path> [<path>...]
  -> exit 2

$ fm-open-file.sh --lavish data/fix-login-k3/report.md
error: --lavish expects an HTML file
  -> exit 1

$ fm-open-file.sh --lavish .lavish/plan.html data/audit-x9/report.md
error: --lavish expects exactly one HTML file
  -> exit 1

### Opt-in escape hatch for an explicitly chosen outside file
$ fm-open-file.sh --allow-outside /tmp/fmopen-e2e.hZ3Es1/outside.md
opened: /private/tmp/fmopen-e2e.hZ3Es1/outside.md in tmux tab file-outside
  -> exit 0

Pipeline

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 the trap &#39;... EXIT&#39; that runs inside the spawned WezTerm shell. If spawn_wezterm_tab fails (wezterm not on PATH at line 193, or wezterm cli spawn fails at line 194), the function calls exit 1 in 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.md twice -> tabs report-fix and report-fix-2, focus restored
  • tmux capture-pane -t firstmate:report-fix -> report rendered in the review tab
  • Multi-target run bin/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, --lavish non-HTML, --lavish multi-file all exit non-zero; --allow-outside opens an explicit outside file
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

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