Root cause: run_cmd uses exec() which blocks until the child exits. The
direct VLC binary forks its GUI process and exits — exec returns and the
post_script begins. The old post_script polled for VLC focus (up to 10s)
then sent Cmd+F, which fired mid-playback and stopped the video.
Fix 1 — nohup + &: detaches VLC from exec immediately so run_cmd returns
in ~0ms. This decouples the launcher flow from VLC's lifecycle.
Fix 2 — --fullscreen flag: VLC opens fullscreen directly via CLI option.
Eliminates the Cmd+F keystroke that was the proximate cause of the stop.
Fix 3 — > /dev/null 2>&1: silences VLC's verbose logging to prevent
exec's 1MB stdout buffer from overflowing and killing the process.
post_script simplified to a single `tell application "VLC" activate`
to bring VLC to the foreground after the 3s startup delay.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All app post-scripts called activate once before the poll loop, then only
checked `frontmost` passively. When Electron retains focus (common when the
app is spawned via run_cmd), macOS focus-stealing prevention blocks the one-
shot activate and VLC/PowerPoint/etc. never come to front. The poll loop
times out and fires the keystroke at Electron instead.
Fix: move activate inside the repeat loop so it re-fires every 0.5s until
macOS yields focus. Also bumped VLC post_delay_ms 1000→2000 and iterations
15→20 for slow conference machines.
Affected profiles: VLC (mac), PowerPoint (mac), LibreOffice (mac+win),
Acrobat (mac+win).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- macOS: Uses direct binary path (/Applications/VLC.app/Contents/MacOS/VLC)
with --no-play-and-exit --play-and-pause flags and AppleScript fullscreen toggle.
Confirmed working: pause on last frame, stays in window.
- Linux: Uses shell command (vlc --no-play-and-exit --play-and-pause).
Known issue: not going fullscreen, not pausing on end. Deferred for later
investigation of flag interpretation vs launcher execution layer.
- Created separate profile constants: VLC_MIRROR_MAC_PROFILE and
VLC_MIRROR_LINUX_PROFILE in ae_launcher__default_launch_profiles.ts
- Updated TODO__Agents.md with Linux VLC issue for future debugging
Files: ae_launcher__default_launch_profiles.ts, documentation/TODO__Agents.md
`open -a App` returns immediately; a fixed delay is unreliable for cold starts.
Each post_script now polls every 500 ms (up to 7.5 s) until the target process is
frontmost before firing the automation keystroke. Keynote polls document count
instead of frontmost since start(front document) requires the file to be loaded.
Mac profiles: post_delay_ms 2000 → 1000. Win/Parallels profiles: 3000 → 1500.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
URL files: event_file.filename = 'https://...' is now a first-class
file type in the launcher.
- is_url derived rune detects https/http filename prefix
- URL branch in handle_open_file() runs before cache/native branches
(no download, no temp copy, no hash)
- Offline guard: warns and blocks click if navigator.onLine is false;
online/offline listeners registered only for URL rows (no-op on files)
- Native mode: opens via native.open_external({ url, app: 'chrome' })
with silent fallback to default browser
- Browser mode: window.open() with noopener
- display_mode default: 'mirror' (URLs typically just need the screen
mirrored, not extended presenter view)
- Button badge shows Link2 icon + WifiOff warning when offline
- Button text uses event_file.title as label (falls back to URL)
- Test mode popup: skips Steps 1-2 (N/A), shows open_external call
DEFAULT_LAUNCH_PROFILES: add 'url' key (display_mode: 'mirror')
Electron TODO: added set_display_layout / displayplacer per-device
config task to aether_app_native_electron/documentation/TODO_AGENTS.md
with full contract details and resources
- Add ae_launcher__default_launch_profiles.ts with LaunchProfile interface,
DEFAULT_LAUNCH_PROFILES constant, and resolve_launch_profile() helper.
Covers pptx/ppt/key/odp/pdf, all VLC media formats, Windows/Parallels
variants (pptxwin/pptwin/odpwin/pdfwin), and a catch-all 'default'.
- Replace get_launch_script_template() with get_launch_profile() in
launcher_file_cont.svelte. Override priority: device API config >
local persistent config > built-in defaults > 'default' catch-all.
- Rewrite handle_open_file() native branch with 9-step profile-driven flow:
copy_from_cache_to_temp → resolve profile → set_display_layout (silent fail)
→ open (run_cmd or OS default) → sleep(post_delay_ms) → run post_script
→ fallback to OS default on open failure → surface status/error detail.
- Add open_file_error_detail state var; show error pre block in status
alert for native error state, show fallback note for fallback state.
- Add display override toggle button in event_file_meta (visible when
trusted_access + is_native): cycles null → extend → mirror → null,
PATCHes event_file.cfg_json.display_override via V3 CRUD.