Skip to content

test: kill surviving mutants in config/output/microphone/transcribe_render#57

Merged
alexkroman merged 7 commits into
mainfrom
claude/overnight-codebase-improvements-r6e5ld
Jun 10, 2026
Merged

test: kill surviving mutants in config/output/microphone/transcribe_render#57
alexkroman merged 7 commits into
mainfrom
claude/overnight-codebase-improvements-r6e5ld

Conversation

@alexkroman

Copy link
Copy Markdown
Collaborator

Whole-package mutation sweep (scripts/mutation_gate.py's engine, run over every
line rather than just the diff) surfaced lines whose covering tests passed even
when the line was broken. Fortify them:

  • config.py: assert the exit_code=2 (usage) on invalid profile / invalid TOML /
    invalid shape / empty --api-key errors, and add a _dump test whose config dir's
    parents don't exist yet (pins mkdir parents=True).
  • output.py: assert is_agentic() returns True when stdout is not a TTY.
  • microphone.py: pin the rate > 0 boundary (keep a 1 Hz reading) and the
    blocksize max(1, ...) floor for a tiny sample rate.
  • transcribe_render.py: mark the chapter start/end getattr fallbacks
    # pragma: no mutate -- equivalent mutants (_fmt_ms(0) == _fmt_ms(1)).

Tests only (plus one pragma); no behavior change.

claude added 7 commits June 10, 2026 12:53
…ender

Whole-package mutation sweep (scripts/mutation_gate.py's engine, run over every
line rather than just the diff) surfaced lines whose covering tests passed even
when the line was broken. Fortify them:

- config.py: assert the exit_code=2 (usage) on invalid profile / invalid TOML /
  invalid shape / empty --api-key errors, and add a _dump test whose config dir's
  parents don't exist yet (pins mkdir parents=True).
- output.py: assert is_agentic() returns True when stdout is not a TTY.
- microphone.py: pin the `rate > 0` boundary (keep a 1 Hz reading) and the
  blocksize max(1, ...) floor for a tiny sample rate.
- transcribe_render.py: mark the chapter start/end getattr fallbacks
  `# pragma: no mutate` -- equivalent mutants (_fmt_ms(0) == _fmt_ms(1)).

Tests only (plus one pragma); no behavior change.
Continue the whole-package mutation sweep, fortifying the command layer:

- init.py: pin _pick_template's stdin/stdout `or` (either stream piped -> usage
  error) and that error's exit_code; the missing-questionary exit_code; the
  agents-host derivation replacing only the FIRST "streaming" (replace count=1);
  the [:300] install-error truncation; and the DIRECTORY/--here conflict
  exit_code. Mark the don't-launch `False` on the install-failure branch
  `# pragma: no mutate` -- run_init exits on the failed step before consulting it.
- llm.py: assert `-o json` forces JSON output without the global --json flag.
- transcripts.py: assert an errored transcript surfaces its own error message,
  not the generic fallback.
- setup.py: assert subprocess capture_output, the 300s/120s skill timeouts, the
  install-hint command slice, the remove failure-detail fallback, _copy_tree's
  mkdir parents/exist_ok, and best-effort rmtree(ignore_errors). FakeRun now
  records per-call kwargs so timeouts/flags are assertable.

Tests only (plus one pragma); no behavior change.
- runner.py: pin find_free_port's bind-to-port-0 (OS-assigned ephemeral port),
  the port-range error message bounds and its exit_code, the 0.2s poll interval
  in wait_for_port, run_setup's success sentinel returncode, and the
  capture_output/check/text kwargs passed to subprocess.run.
- scaffold.py: assert the unknown-template / template-missing exit_codes, that a
  nested target's parent dirs are created (target.mkdir parents=True), and that a
  re-scaffold over an existing tree is tolerated (exist_ok). The two _copy_tree
  mkdir parents=True flags are marked `# pragma: no mutate` -- equivalent mutants,
  since the copy walk always creates a node's parent before the node.

Tests only (plus two pragmas); no behavior change.
- auth/loopback.py: assert the callback server thread is a daemon and that the
  cleanup join uses the bounded 5s timeout (spying threading.Thread while the
  server really serves, so shutdown() doesn't block).
- agent/audio.py: pin the DuplexAudio blocksize max(1, rate//10) floor for a tiny
  device rate.
- agent/session.py: pin the bounded 10s wait on ready_event in the send loop, and
  that the capture thread is a daemon.

Tests only; no behavior change.
- macos.py: assert the missing-swiftc / compile-failure exit_codes, the swiftc
  subprocess capture_output/text/check kwargs, the cache-dir mkdir parents (nested
  path) and exist_ok (pre-existing dirs), the _cleanup_process terminate guard +
  2s wait backstops + stderr-pipe close, the `returncode >= 0` boundary, and the
  chunk-frames = sample_rate//10 helper arg. The module-cache mkdir parents=True
  is `# pragma: no mutate` (equivalent: cache_dir is created the line before).
- render.py: assert a turn event missing end_of_turn reads as a partial (False).
- session.py: assert the parallel source workers are daemons; the 0.1s join poll
  interval is `# pragma: no mutate` (a responsiveness/CPU tradeoff, not behavior).

Tests only (plus two pragmas); no behavior change.
…-summary

Two follow-ups found by a full re-sweep after the rebase:

- setup.py _run: also assert the subprocess.run text=True and check=False kwargs
  (capture_output was already pinned) so all three are mutation-covered.
- config.py _validation_summary: mark exc.errors(include_url/include_input=False)
  `# pragma: no mutate` -- equivalent mutants, since the summary reads only loc+msg
  and never the url/input fields those flags toggle.

Tests only (plus one pragma); no behavior change.
Developer-experience follow-up. The mutation gate is diff-scoped, so auditing
existing code against its bar meant rebuilding a throwaway sweep script each time.
Promote it to scripts/mutation_sweep.py: it reuses the gate's own
collect/cover/survive engine over every line of the named files (or the whole
package), reports surviving mutants (exit 1) and an UNCOVERED bucket separately,
and is robust to the line-number shifts that make per-line checks brittle.

Document the workflow in AGENTS.md next to the diff-scoped gate, including the
reminder to pass `--timeout` to the coverage-refresh pytest run — the default
suite leaves per-test timeouts opt-in, so a deadlocked test otherwise wedges the
whole run instead of failing fast.
@alexkroman alexkroman merged commit 9ca6584 into main Jun 10, 2026
11 checks passed
@alexkroman alexkroman deleted the claude/overnight-codebase-improvements-r6e5ld branch June 10, 2026 13:35
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.

2 participants