The library

Rendered from docs/reports/2026-09-26_k-docker-image-plan-review.md; the markdown file is the record.

  1. Critical — Container self-checks invoke the wrong entrypoint. docker run hearsay:latest python -c ... passes python -c to run_pipeline.py, because the image has an exec-form ENTRYPOINT. Step 9 and the smoke self-checks therefore fail argument parsing. Use --entrypoint /opt/venv/bin/python for Python checks and PCM hashing, and include --network none.

  2. Critical — Cache recovery does not repair the interrupted file. Ignoring a corrupt final JSONL line leaves those bytes on disk; the next append either joins onto that fragment or turns it into corruption in the middle of the file. Truncate to the last valid record before appending. Test interruption → resume → append → second resume, including a complete JSON record without its terminating newline.

  3. Critical — Cache fingerprints omit score-changing inputs. M1’s configuration omits backbone content and preprocessing identity; Spectra’s weight hash disappears outside the image; handcrafted and speech-gate fingerprints are unspecified. Reusing /out after a rebuild or changing hc_selected can silently reuse stale scores. Define fingerprints covering each model bundle, weights, preprocessing/gate configuration and implementation version, and test invalidation for each.

  4. Critical — Fusion dependencies are checked against supported detectors, not selected detectors. A bundle requiring Spectra can pass validation while the default --detectors m1b runs only M1, yielding fallback scores for every file. Before loading models, require all bundle detectors to be selected or automatically select them. Also reject a detector selection without M1 when no bundle is supplied.

  5. Critical — Bundled identity fusion disagrees with the existing exporter. scripts/fuse.py defines alone:<d> on the standardized logit, then fits its Platt map on that standardized value. The proposed bundled identity feeds the raw logit into that calibration. Specify standardized identity, or explicitly transform its calibration coefficients; keep the no-bundle M1 formula separate. Add parity against the exporter with nonzero mean and nonunit standard deviation.

  6. Critical — Fusion validation can still allow invalid final scores. Checking keys alone does not reject zero standard deviations, nonfinite coefficients, invalid priors or malformed rule dimensions. The proposed NaN-only input check and range-only output check also miss cases such as infinities and NaN produced during fusion; write_submission then aborts. Validate numerical bundle invariants before scoring and apply an explicit finite-and-in-range check to final probabilities.

  7. Critical — The parity gate cannot reliably validate its planned inputs. T4 compares a 50-row TSV with a 1,671-row reference, while compare specifies rejecting ID mismatches before applying --n. Define subset comparison explicitly, requiring every requested ID exactly once. Reject nonfinite scores and undefined Spearman results explicitly so an all-fallback output cannot pass through NaN comparison behavior.

  8. Critical — Completion omits the required submission log row. Keeping append_log outside the image is appropriate, but step 10 never performs the host-side logging promised by D10, and the spec excludes submissions/ from changes. Add an explicit host-side acceptance step recording the new full TSV, applicable outer-holdout and clean-only scores, and EER. If the full run remains unfinished at the cutoff, name that blocker rather than treating partial parity output as the completed deliverable.

  9. Suggestion — Default-policy validation is weaker than parity validation. T4/T7 disable the speech gate, although production enables it and can change rankings. The “nothing is modelled” waiver does not establish that this policy preserves the quoted validation scores. Verify the production policy on the existing generator/speaker outer holdout, report clean-only minDCF/EER and gated counts, and include available telephony/laundering stress cases while retaining the physical-replay limitation.

  10. Suggestion — Several tests contradict the proposed implementation. L9 expects a template-listed README.txt to produce decode_error, but the audio-only index makes it missing_file. O6 expects a scorer returning 1.5 to be out of range, although scorers return unrestricted logits. The fake backbone also lacks the .config accessed by truncation. Resolve these contracts first; inject an invalid final probability for O6 and give the fake model the required configuration.

  11. Suggestion — The time box has no contingency for the image gates. The listed work consumes roughly the entire approval-to-hard-stop window even with runner tests written alongside implementation, before allowing for build completion, parity, smoke checks or fixes. Start the image build once its inputs are ready, define intermediate stop points, and reserve time to report incomplete acceptance gates at 10:00.