From dbe048d0e23fbe563a6db41860adc9decf1ed7c7 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 16 Jun 2026 22:47:59 +0000 Subject: [PATCH] Make --quiet drop the batch --llm-reduce progress table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The global -q/--quiet already silences spinners, warnings, hints, and the banner, but the batch progress table ignored it. With --llm-reduce that table is routed to stderr as pure progress chrome (the reduce result goes to stdout), yet --quiet still rendered it — so a script asking to silence stderr chrome didn't get a clean stderr. Thread quiet into _progress_table and skip the live table when it's the stderr-bound reduce chrome. A non-reduce table is the run's stdout result, so --quiet leaves it alone — quiet silences chrome, not the output a script came for. Document the behavior in REFERENCE.md's reduce note. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_013sJ5Pcp1nMRjwY4RJLXPsj --- REFERENCE.md | 6 ++-- aai_cli/app/transcribe/batch.py | 12 +++++-- tests/test_transcribe_reduce.py | 56 +++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/REFERENCE.md b/REFERENCE.md index 6a89200b..7e38f234 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -88,9 +88,9 @@ With `--llm-reduce`, batch mode emits one final `{"type":"reduce","model","prompts","output"}` record after the per-source `result` records — the aggregate prompt(s) run once over every result, with the output printed to stdout (the progress table is routed to stderr so stdout stays -clean for piping). `--llm-reduce` is repeatable, each prompt running on the -previous one's output; for a single source it extends the `--llm` chain over -that transcript. +clean for piping; the global `-q`/`--quiet` drops that table entirely). `--llm-reduce` +is repeatable, each prompt running on the previous one's output; for a single +source it extends the `--llm` chain over that transcript. `assembly eval` takes the same `--llm`/`--llm-reduce` flags but emits one JSON object per dataset (not NDJSON; a single dataset is therefore one object): diff --git a/aai_cli/app/transcribe/batch.py b/aai_cli/app/transcribe/batch.py index 14a12a0e..0e192193 100644 --- a/aai_cli/app/transcribe/batch.py +++ b/aai_cli/app/transcribe/batch.py @@ -227,7 +227,9 @@ def _render_table(items: list[_Item]) -> Table: @contextmanager -def _progress_table(items: list[_Item], *, json_mode: bool, reduce_active: bool) -> Generator[None]: +def _progress_table( + items: list[_Item], *, json_mode: bool, reduce_active: bool, quiet: bool +) -> Generator[None]: """Render the batch as a live-updating table (human mode). Rich renders nothing while running on a non-interactive console and prints the @@ -235,8 +237,12 @@ def _progress_table(items: list[_Item], *, json_mode: bool, reduce_active: bool) mode skips Rich entirely — NDJSON per source is the output. When a --llm-reduce step will print the aggregate to stdout, the table goes to stderr so stdout carries only the reduce result. + + ``--quiet`` drops the table only when it's stderr progress chrome (the + --llm-reduce case); without --llm-reduce the table *is* the run's stdout result, + so it's left alone — quiet silences chrome, not the output a script came for. """ - if json_mode: + if json_mode or (quiet and reduce_active): yield return console = output.error_console if reduce_active else output.console @@ -380,7 +386,7 @@ def run_batch( """ items = [_Item(source) for source in sources] reduce_active = bool(transform.reduce_prompts) - with _progress_table(items, json_mode=json_mode, reduce_active=reduce_active): + with _progress_table(items, json_mode=json_mode, reduce_active=reduce_active, quiet=quiet): _drain( api_key, items, diff --git a/tests/test_transcribe_reduce.py b/tests/test_transcribe_reduce.py index 25dedce6..412b5be8 100644 --- a/tests/test_transcribe_reduce.py +++ b/tests/test_transcribe_reduce.py @@ -271,6 +271,62 @@ def test_batch_reduce_routes_table_to_stderr(mocker, monkeypatch, capsys): assert "https://a" in err +def test_quiet_drops_the_reduce_progress_table_but_keeps_the_result(mocker, monkeypatch, capsys): + """--quiet silences the stderr progress chrome; stdout still carries the reduce.""" + import assemblyai as aai + + _auth() + monkeypatch.setattr( + _TRANSCRIBE, lambda api_key, audio, *, config: _fake_transcript(mocker, audio) + ) + monkeypatch.setattr( + transcribe_batch.llm, + "run_chain", + lambda api_key, prompts, *, transcript_text, model, max_tokens: "AGGREGATE", + ) + transform = transcribe_run.TransformOptions( + prompts=[], model="m", max_tokens=10, reduce_prompts=["summarize"] + ) + transcribe_batch.run_batch( + "sk_live", + ["https://a"], + transcription_config=aai.TranscriptionConfig(), + concurrency=1, + force=False, + transform=transform, + json_mode=False, + quiet=True, + ) + out, err = capsys.readouterr() + assert "AGGREGATE" in out # the data a script came for survives --quiet + assert "https://a" not in err # the progress table chrome is gone + + +def test_quiet_keeps_the_non_reduce_table_since_it_is_the_result(mocker, monkeypatch, capsys): + """Without --llm-reduce the table is the run's stdout output, so --quiet leaves it.""" + import assemblyai as aai + + _auth() + monkeypatch.setattr( + _TRANSCRIBE, lambda api_key, audio, *, config: _fake_transcript(mocker, audio) + ) + transform = transcribe_run.TransformOptions( + prompts=[], model="m", max_tokens=10, reduce_prompts=[] + ) + transcribe_batch.run_batch( + "sk_live", + ["https://a"], + transcription_config=aai.TranscriptionConfig(), + concurrency=1, + force=False, + transform=transform, + json_mode=False, + quiet=True, + ) + out, _ = capsys.readouterr() + assert "https://a" in out # the result table still renders to stdout + + def test_batch_reduce_skips_when_nothing_to_reduce(mocker, monkeypatch, capsys): """An all-empty batch result must not fire a (billable) reduce call.""" import assemblyai as aai