cli.py carried 40 pragmas over whole command bodies and app.py a
class-level one over all 412 statements, while tests/test_cli.py already
drove 29 commands through CliRunner. The pragmas hid lines the suite
executed, so the 100% gate understated real coverage and gave new CLI code
no scrutiny.
Both are measured now. 38 CLI tests stub HaikuRAGApp and assert the parsed
arguments reach the right method; 60 app tests stub the client and record
the console, pinning what each command asks for and what it prints. The only
pragma left in either file is cli() under __main__. The omit list is back to
the two Textual TUIs.
Three defects the coverage surfaced:
haiku-rag settings masked only top-level secret-named fields, so nested ones
printed in full — lancedb.api_key, providers.docling_serve.api_key, WebDAV
source passwords. It uses redact_secrets, which walks the dump.
chat guarded the wrong thing: haiku.rag.chat imports without Textual, and
run_chat raises when it imports ChatApp, so the missing extra escaped as an
ImportError. The guard is on the call. inspector raises at module import
instead, so inspect keeps its guard on the import; each has a test that
fails the way the real installation fails.
search --limit/--search-type and history --limit default to None so the
config resolves the default. Now pinned.
CI passed --cov=haiku while pyproject declares source = ["haiku_rag_slim"];
pass --cov and let the config decide. build-docs.yml only ran on push to
main, so a broken docs build merged and failed at deploy: build on pull
requests, with configure-pages, upload-pages-artifact and deploy gated to
push, and a per-ref concurrency group.
get_config() builds its instance on first use, so the branch was covered
only when a worker happened to call it before set_config(). Under xdist that
depends on how cases shard across workers, which varies with the core count:
covered locally, uncovered on the two-core runner. Assert it directly.
setup-uv v4 bundles a cache client the GitHub cache service now rejects with
400, so the uv cache never restored and every wheel was redownloaded. Bump
to v9 across all four workflows (build-docs was already drifting at v5).
setup-python read requires-python (">=3.12") and installed 3.14, which uv
then ignored in favour of .python-version (3.13) and downloaded itself.
Point it at .python-version so the interpreter it installs is the one used.
The Qwen tokenizer and cross-encoder pre-downloads call the HF metadata
API to revalidate even on a cache hit; a 429 there propagates instead of
falling back to the cached files, failing CI on HF throttling.
Skip the pre-download steps when the cache is restored and run pytest
with HF_HUB_OFFLINE/TRANSFORMERS_OFFLINE on a hit, so cached models are
used without any network revalidation; allow online on a miss so a fresh
cache key still populates. Rename the cache key so the snapshot
re-populates with every test model (the old key predated the
cross-encoder step and never cached it).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>