test: kill surviving mutants in config/output/microphone/transcribe_render#57
Merged
Merged
Conversation
…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.
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.
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:
invalid shape / empty --api-key errors, and add a _dump test whose config dir's
parents don't exist yet (pins mkdir parents=True).
rate > 0boundary (keep a 1 Hz reading) and theblocksize max(1, ...) floor for a tiny sample rate.
# pragma: no mutate-- equivalent mutants (_fmt_ms(0) == _fmt_ms(1)).Tests only (plus one pragma); no behavior change.