Repository navigation
Stream run progress to stderr in the mic CLI - #31
Merged
Merged
Conversation
mic run now shows progress while it streams instead of staying silent until the end. On a terminal, each case prints one line when its last trial finishes (trial marks, slowest-trial time, generic failure kinds), and a single status line is redrawn in place with counts, running trials, throughput, elapsed time, a long-running trial, and reading/finishing/cancelling phases. Off a terminal, Mic prints the header, failed and rejected cases, and periodic status lines with no escapes. -v shows every case with score means; -q shows nothing. The display is built on the internal run observer, renders from its own thread, writes only to stderr, and always clears the status line before the summary, errors, or "interrupted" print. Application print() output is kept off the status line while it is shown. No dependencies are added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Executive summary
mic runnow shows progress while it streams instead of printing nothing until the end. In a terminal, each case prints one line when its last trial finishes, and a status line at the bottom is redrawn in place. Outside a terminal (CI, redirects), Mic prints plain lines with no escape codes.-vshows every case with its score means, and-qturns progress off. The stdout summary and--jsonoutput are unchanged.After Ctrl-C, the status line becomes
cancelling · waiting for 2 running trials to return (rows 2, 3). Cases that were cancelled or never run are then listed, followed bymic: interrupted.Why
A multi-minute run looked hung and then printed everything at once. This is option D from the design discussion: one line per case in scrollback plus a sticky status footer. The design recommendations were accepted: no running score means in the footer,
sys.stdout/sys.stderrwrapped while the footer is shown, and summary formatting changes deferred to a separate PR.Design and implementation
src/mic/reporters/live.pyuses only the standard library and has three parts:ProgressStateimplements the internalRunObserverfrom Add internal run progress observer hooks to the engine #30. It turns notifications into finished lines and status text. It holds a case only until that case's last admitted trial finishes, so memory is bounded by concurrency, not dataset size.LiveDisplayredraws from a daemon thread about 10 times a second, so elapsed time and the slow-trial callout stay current even if a task blocks the event loop.sys.stdout(if it's a terminal) andsys.stderrare wrapped: the footer is erased before application output, and incomplete lines are held until their newline (or 4 KiB).PlainDisplayprints new lines every 0.5s, a status line every 30s, and a status line when the run starts cancelling or finishing.TERMisn'tdumb, and ANSI support is available. On Windows this is enabled throughSetConsoleMode, falling back to plain if that fails.NO_COLORis unset.?. A label can't move the cursor or inject escape codes.cli.py):runnow calls the privateexecute(..., observer=...)through the existingrun_synchelper, inside awith progress(...)block. Closing that block clears the footer before the summary,Evidence …, a config error, ormic: interruptedprints.-qand-vare mutually exclusive.docs/cli.mdcovers behavior, the non-terminal mode, flags,NO_COLOR, the ASCII fallback, cancellation, and the logging-handler limitation. The README run example now shows the progress lines.Verification and confidence
ProgressStatetests check exact strings for: trials finishing out of order; grouped failures with scorer names; several evaluations and sources; verbose means with missing scores; quiet mode showing only problems; rejected records; cases flushed at close that were cancelled or never run.--limit, the slow-trial callout past both thresholds, cancelling (with and without running trials), finishing sinks.fithandles wide characters; a label containing\x1b[2J\nis printed safely; the footer stays within the requested width.LiveDisplaytest on a fake terminal: application output appears whole after an erase, unterminated output is completed on close,sys.stderris restored, and no status line is left behind.ProgressStatehooks forced to raise, the run still completes normally and the error text isn't shown.--jsoncontaminatedRuntimeErrorbut not the exception message, and stdout is unchanged.-qleaves stderr empty, and-q -vexits with code 2.print()s in task code, and a two-evaluation suite), I checked:-v;mic: interrupted, exit 130).scripts/verify.py: 778 tests, 0 failures. Strict and authoring typing, lint, format and the coverage gates all pass.scripts/verify_packaging.pypasses.live.pyhas 93% in-process coverage. The uncovered lines are the Windows console path and terminal-detection fallbacks; the live path also runs in the pty subprocess test, whose coverage isn't counted.Compatibility and risks
-q/--quietand-v/--verbosetorun, and prints progress on stderr. Scripts that require an empty stderr frommic runwill now see progress lines; they can pass-q. The stdout summary,--json, exit codes and evidence are unchanged._runtimemodules from Add internal run progress observer hooks to the engine #30.logginghandler created before the run holds the original stderr and bypasses the wrapper, so a log line can share a line with the footer until the next redraw (within 100ms).