Skip to content

Per-terminal CLI device pins (retire eval $(device connect)) + CI report/daemon hardening#145

Merged
handstandsam merged 7 commits into
mainfrom
more-may-31
Jun 1, 2026
Merged

Per-terminal CLI device pins (retire eval $(device connect)) + CI report/daemon hardening#145
handstandsam merged 7 commits into
mainfrom
more-may-31

Conversation

@handstandsam
Copy link
Copy Markdown
Collaborator

@handstandsam handstandsam commented May 31, 2026

Summary

The headline change moves device pinning away from the eval $(trailblaze device connect …) env-var dance to per-terminal, file-based device pins. Also bundled: CI report generation driven entirely off the prebuilt uber JAR, a bounded Playwright video finalizer, a shorter daemon run-poll timeout, and a regression test for the workspace trailmap-shadowing CI hang.

Per-terminal device pinning

trailblaze device connect no longer needs eval $(...) to export TRAILBLAZE_DEVICE / TRAILBLAZE_TARGET into the shell. The binding is now written to a per-terminal pin file (~/.trailblaze/shell-device-pins-<port>.json) keyed by the shell PID the trailblaze wrapper forwards as TRAILBLAZE_SHELL_PID. Subsequent commands in the same terminal inherit the device (and target) automatically; other terminals stay independent.

  • New ShellDevicePinStore — a small JSON store mapping shellPid → {device, target}, with kernel-level advisory file locking plus an in-JVM monitor for safe read-modify-write, atomic tempfile + rename writes, lazy GC of dead-PID entries, and port-scoped files for multi-daemon isolation. The liveness probe is injectable so eviction logic is unit-testable.
  • New resolver tier in resolveDeviceWithAutodetect: --device flag → TRAILBLAZE_DEVICE (manual override) → this terminal's file-pin → single-device autodetect. The pin is validated against the live device list and evicted with a clear message when its device is gone, then falls through to autodetect.
  • Target persistence: the connect-time --target is stored alongside the device so it survives trailblaze app --stop && app start instead of living only in the daemon's in-memory registry. --target=clear now also clears the pin's target field (previously only the daemon side was cleared, so the pin silently re-established it).
  • Agent / CI guidance: the wrapper sets TRAILBLAZE_INTERACTIVE from a tty check; device connect warns non-interactive callers (Claude Code, Cursor, Codex, CI — each command is a fresh shell with a different PID) that the pin won't carry, and points them at --device per call.
  • device connect / disconnect / rebind updated to read and write the pin; disconnect and rebind also resolve the device from the pin when no flag/env is supplied. Legacy eval $(trailblaze device disconnect) keeps working — the unset lines are still emitted on stdout for users mid-migration, but are now vestigial.
  • trailblaze run gains the file-pin tier so device connect X followed by run … inherits the device. Trails deliberately do not inherit the terminal's target pin — a trail declares its own target to stay deterministic across developers and CI.
  • Docs + help: README, getting_started, index, the MCP page, and docs/CLI.md are rewritten to drop eval $(...); a single DEVICE_OPTION_DESCRIPTION constant now backs the -d/--device help on every action command, and the CLI help baselines are regenerated.

CI report generation off the prebuilt uber JAR

Both pr_generate_trailblaze_report.sh and pr_generate_report_assets.sh now drive the trailblaze report CLI off the prebuilt uber JAR — which already bundles the WASM report template (the build-uber-jar job invokes Gradle with -Ptrailblaze.wasm=true). This drops the separate :trailblaze-ui:wasmJsBrowserProductionWebpack / :trailblaze-report:run / generateReportTemplate Gradle steps. The index script renames report.htmltrailblaze_report.html in place so downstream artifact/upload paths stay unchanged.

Daemon / capture hardening

  • Playwright video finalizer (PlaywrightVideoRecordDir.runFinalizer) now runs on a bounded single-thread daemon executor with a 30s timeout. A wedged Playwright-affinity dispatcher can no longer deadlock the daemon's run-status pipeline (the historical 1800s-timeout symptom); on timeout we drop the in-flight flush and fall back to the on-disk .webm.
  • Run-poll timeout lowered from 30 min → 10 min so a wedged daemon fails fast and the next CI cycle starts sooner, while keeping 3–5× headroom over the honest happy-path runtime.

Tests

  • ShellDevicePinStoreTest — cold-start, set→resolve round-trip, dead-PID eviction, concurrent terminals coexisting, opportunistic GC, concurrent-writer file locking, port scoping, and corrupted-file tolerance.
  • AppTargetDiscoveryTest — regression for the OSS CI hang: a cwd workspace that owns a colliding wikipedia trailmap id must not shadow the TRAILBLAZE_CONFIG_DIR-pointed workspace's target and YAML tools.
  • DaemonClientPollResilienceTest — comment updated for the new poll timeout.

@handstandsam handstandsam changed the title More Upstream 5/31 Per-terminal CLI device pins (retire eval \$(device connect)) + CI report/daemon hardening May 31, 2026
@handstandsam handstandsam changed the title Per-terminal CLI device pins (retire eval \$(device connect)) + CI report/daemon hardening Per-terminal CLI device pins (retire eval $(device connect)) + CI report/daemon hardening May 31, 2026
@handstandsam handstandsam merged commit 31be6be into main Jun 1, 2026
10 of 13 checks passed
@handstandsam handstandsam deleted the more-may-31 branch June 1, 2026 01:24
handstandsam added a commit that referenced this pull request Jun 1, 2026
* Stop tracking generated trailmap build artifacts under examples/wikipedia

The bundled SDK (`trails/.trailblaze/`) and daemon-compiled target YAMLs (`trails/config/dist/`) are regenerated build output, not source. They were committed in #145 because the OSS .gitignore rules were root-anchored (`/trails/...`) and missed `examples/*/trails/...`. Re-anchor both rules to `**/` to match the internal repo, and drop the artifacts that slipped in.

* Upstream sync

* CLI output tweaks

* alarm clock trail tweak
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