Implement the interactive measurement controller for Stage 3. This is the most complex stage — the Rust backend spawns chartread -u and maintains a bidirectional pipe. The frontend presents a state-machine-driven UI that reacts to stdout prompts and lets the user inject keystrokes via stdin.
Toolchain Context
Backend: Rust (Tauri 2) — uses ProcessManager::spawn() for bidirectional IPC, ProcessManager::send_stdin() for keystroke injection
Frontend: Vanilla JS with window.__TAURI__.core.listen() for real-time event streaming
Upstream: Uses the custom chartread -u flag from gronod/argyllcms for JSON streaming
Implementation Plan
Backend (Rust)
New Tauri commandcommands::run_chartread(app, state, config):
Spawn via ProcessManager; the existing stdout/stderr line readers in process_manager.rs automatically emit process:stdout events
Structured event routing: Add a new event emitter emit_json_row(app, id, json_str) in events.rs that fires process:json_row when a stdout line matches the ROW_COLORS_JSON: prefix. This separates structured data from human-readable prompts.
Stdin relay: The existing commands::send_stdin() command is sufficient — the frontend sends " \n" (space+newline) for calibrate, "s\n" for skip, "q\n" for quit.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Description
Implement the interactive measurement controller for Stage 3. This is the most complex stage — the Rust backend spawns
chartread -uand maintains a bidirectional pipe. The frontend presents a state-machine-driven UI that reacts to stdout prompts and lets the user inject keystrokes via stdin.Toolchain Context
ProcessManager::spawn()for bidirectional IPC,ProcessManager::send_stdin()for keystroke injectionwindow.__TAURI__.core.listen()for real-time event streamingchartread -uflag from gronod/argyllcms for JSON streamingImplementation Plan
Backend (Rust)
commands::run_chartread(app, state, config):ChartreadConfigstruct:{ basename: String, extra_args: Vec<String> }["-v", "-u", <basename>]ProcessManager; the existing stdout/stderr line readers inprocess_manager.rsautomatically emitprocess:stdouteventsemit_json_row(app, id, json_str)inevents.rsthat firesprocess:json_rowwhen a stdout line matches theROW_COLORS_JSON:prefix. This separates structured data from human-readable prompts.commands::send_stdin()command is sufficient — the frontend sends" \n"(space+newline) for calibrate,"s\n"for skip,"q\n"for quit.Frontend (JavaScript)
src/js/chartread.js):process:stdoutlines parsed for prompt keywords to drive state transitionsprocess:json_rowevents parsed as JSON and dispatched to the swatch grid rendererprocess:exittransitions to FINISHEDsend_stdin(" \n")send_stdin(" \n")send_stdin("s\n")kill_process("chartread")New/Modified Files
[MODIFY]src-tauri/src/commands.rs— addrun_chartreadcommand[MODIFY]src-tauri/src/events.rs— addemit_json_rowwithprocess:json_rowevent type[MODIFY]src-tauri/src/process_manager.rs— add ROW_COLORS_JSON prefix detection in stdout reader[MODIFY]src/index.html— expand Stage 3 panel with state-driven UI, button cluster, prompt area[NEW]src/js/chartread.js— state machine, event listeners, stdin commands[MODIFY]src/styles/main.css— state machine panel stylesAcceptance Criteria
process:json_rowevents.ti3file and transitions to Stage 4References