ConversionViewModel.onInputPicked(uri: Uri) and .save(destination: Uri) are both (Uri) -> Unit, so swapping the two launcher callbacks at ConverterScreen.kt:70 and :83 compiles, renders, and passed the entire suite. Picking a file would attempt a save to it; choosing a destination would load it as input.
That is exactly the defect class ScreenWiringTest exists for, on the one pair it declines to cover — it drives converterActions directly and says the launcher-backed actions stay parameters. Right about the actions seam, and it leaves the edge above that seam unpinned.
Join's equivalents (JoinScreen.kt:45, :55) are List<Uri> and Uri, so they are not transposable and get no such test.
The mechanics were spiked before the assertions were written
Neither is used anywhere else in the suite, and #200 said to verify them first:
mechanic
result
shadowOf(activity).nextStartedActivityForResult
reads the launched Intent, EXTRA_MIME_TYPES intact
shadowOf(activity).receiveResult(...)
reaches ComponentActivity's ActivityResultRegistry and fires the rememberLauncherForActivityResult callback
Both work. createAndroidComposeRule for AdaptiveShellTest's reason: the screens compose real ViewModels through viewModel(), and the plain rule supplies no ViewModelStoreOwner.
Picker filter rides along
ConverterScreen.kt:65-67 records why the all-types wildcard is load-bearing rather than lazy — the photo picker offers no audio at all and won't reliably surface .mkv/.flac/.webm. Narrowing it would make every audio conversion unreachable from the picker, and nothing would have gone red.
One incidental worth knowing: a KDoc cannot contain that wildcard, because its second half closes the block comment. The literal is spelled only in the assertion, and the KDoc says why.
Acceptance: mutations run and restored
mutation
result
transpose onInputPicked and save
red
narrow the converter picker to video only
red
widen the join picker to every type
red
Verification
testDebugUnitTest (full suite) + ktlintCheck + detekt + lintDebug — green, production tree clean.
Closes #200.
## The hazard
`ConversionViewModel.onInputPicked(uri: Uri)` and `.save(destination: Uri)` are **both `(Uri) -> Unit`**, so swapping the two launcher callbacks at `ConverterScreen.kt:70` and `:83` compiles, renders, and **passed the entire suite**. Picking a file would attempt a save to it; choosing a destination would load it as input.
That is exactly the defect class `ScreenWiringTest` exists for, on the one pair it declines to cover — it drives `converterActions` directly and says the launcher-backed actions stay parameters. Right about the `actions` seam, and it leaves the edge above that seam unpinned.
Join's equivalents (`JoinScreen.kt:45`, `:55`) are `List<Uri>` and `Uri`, so they are **not** transposable and get no such test.
## The mechanics were spiked before the assertions were written
Neither is used anywhere else in the suite, and #200 said to verify them first:
| mechanic | result |
|---|---|
| `shadowOf(activity).nextStartedActivityForResult` | reads the launched `Intent`, `EXTRA_MIME_TYPES` intact |
| `shadowOf(activity).receiveResult(...)` | reaches `ComponentActivity`'s `ActivityResultRegistry` and fires the `rememberLauncherForActivityResult` callback |
Both work. `createAndroidComposeRule` for `AdaptiveShellTest`'s reason: the screens compose real ViewModels through `viewModel()`, and the plain rule supplies no `ViewModelStoreOwner`.
## Picker filter rides along
`ConverterScreen.kt:65-67` records why the all-types wildcard is load-bearing rather than lazy — the photo picker offers no audio at all and won't reliably surface `.mkv`/`.flac`/`.webm`. Narrowing it would make every audio conversion unreachable from the picker, and nothing would have gone red.
One incidental worth knowing: **a KDoc cannot contain that wildcard**, because its second half closes the block comment. The literal is spelled only in the assertion, and the KDoc says why.
## Acceptance: mutations run and restored
| mutation | result |
|---|---|
| transpose `onInputPicked` and `save` | **red** |
| narrow the converter picker to video only | **red** |
| widen the join picker to every type | **red** |
## Verification
`testDebugUnitTest` (full suite) + `ktlintCheck` + `detekt` + `lintDebug` — green, production tree clean.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.
Closes #200.
The hazard
ConversionViewModel.onInputPicked(uri: Uri)and.save(destination: Uri)are both(Uri) -> Unit, so swapping the two launcher callbacks atConverterScreen.kt:70and:83compiles, renders, and passed the entire suite. Picking a file would attempt a save to it; choosing a destination would load it as input.That is exactly the defect class
ScreenWiringTestexists for, on the one pair it declines to cover — it drivesconverterActionsdirectly and says the launcher-backed actions stay parameters. Right about theactionsseam, and it leaves the edge above that seam unpinned.Join's equivalents (
JoinScreen.kt:45,:55) areList<Uri>andUri, so they are not transposable and get no such test.The mechanics were spiked before the assertions were written
Neither is used anywhere else in the suite, and #200 said to verify them first:
shadowOf(activity).nextStartedActivityForResultIntent,EXTRA_MIME_TYPESintactshadowOf(activity).receiveResult(...)ComponentActivity'sActivityResultRegistryand fires therememberLauncherForActivityResultcallbackBoth work.
createAndroidComposeRuleforAdaptiveShellTest's reason: the screens compose real ViewModels throughviewModel(), and the plain rule supplies noViewModelStoreOwner.Picker filter rides along
ConverterScreen.kt:65-67records why the all-types wildcard is load-bearing rather than lazy — the photo picker offers no audio at all and won't reliably surface.mkv/.flac/.webm. Narrowing it would make every audio conversion unreachable from the picker, and nothing would have gone red.One incidental worth knowing: a KDoc cannot contain that wildcard, because its second half closes the block comment. The literal is spelled only in the assertion, and the KDoc says why.
Acceptance: mutations run and restored
onInputPickedandsaveVerification
testDebugUnitTest(full suite) +ktlintCheck+detekt+lintDebug— green, production tree clean.🤖 Generated with Claude Code