testsAndMisc/python_pkg/archwiki_rag
Krzysztof kuhy Rudnicki adf2e402df Grade against 3.14 too, not just run on it
`requires-python` and the CI pin already said 3.14, but ruff, mypy and pylint
were still grading `meta/` against 3.10 -- three tools judging an interpreter
nothing runs any more, and ruff withholding the pyupgrade fixes that only
become safe at the newer target. `pin_ci_python.py` rewrites these three knobs.

What the stale target was hiding: `datetime.timezone.utc` where `datetime.UTC`
is now correct (UP017), and ruff's stable formatter applying PEP 758 --
`except (A, B):` becomes `except A, B:`. That makes the source 3.14-only at the
syntax level, which is what `requires-python = ">=3.14"` already promised; kuhy
chose it deliberately over holding ruff a release back (2026-08-29).

Also drops a comment in `wsg_grabber/models.py` that the bump makes false: it
explained why the file used ``str, Enum`` instead of ``StrEnum`` under mypy at
3.10, sitting directly above a ``class Verdict(StrEnum)`` that had already
stopped obeying it.

ruff, ruff-format, mypy --strict and pylint all clean at the new target.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SfnJmxxsZ534AKk16rC2Gr
2026-08-29 11:50:39 +02:00
..
tests Fix a test that only passed in a directory named testsAndMisc 2026-08-23 14:53:29 +02:00
__init__.py archwiki_rag: offline semantic search over the Arch Wiki 2026-08-10 15:33:18 +02:00
__main__.py archwiki_rag: offline semantic search over the Arch Wiki 2026-08-10 15:33:18 +02:00
_reindex_entry.py archwiki_rag: offline semantic search over the Arch Wiki 2026-08-10 15:33:18 +02:00
cli.py archwiki_rag: offline semantic search over the Arch Wiki 2026-08-10 15:33:18 +02:00
constants.py archwiki_rag: offline semantic search over the Arch Wiki 2026-08-10 15:33:18 +02:00
convert.py archwiki_rag: offline semantic search over the Arch Wiki 2026-08-10 15:33:18 +02:00
install.sh archwiki_rag: offline semantic search over the Arch Wiki 2026-08-10 15:33:18 +02:00
README.md archwiki_rag: offline semantic search over the Arch Wiki 2026-08-10 15:33:18 +02:00
reindex.py Grade against 3.14 too, not just run on it 2026-08-29 11:50:39 +02:00
sync.py archwiki_rag: offline semantic search over the Arch Wiki 2026-08-10 15:33:18 +02:00

archwiki_rag

Offline Arch Wiki corpus for the knowledge-rag MCP server. Gives Claude semantic search across the whole ArchWiki without a network round-trip, so questions can be asked by symptom rather than by page title:

why doesn't my systemd user unit see DISPLAY under i3

Why this exists

The only Arch-specific MCP server in the wild (nihalxkumar/arch-mcp) fetches wiki pages over the network and bundles pacman install/remove/update, PKGBUILD checks and system stats that duplicate the local yay-mcp. This package uses the arch-wiki-docs dump that is already on disk instead, and does nothing but search.

Usage

# One-time setup: dependencies, corpus, MCP config, pacman hook.
./install.sh

# Manual refresh.
PYTHONPATH=~/testsAndMisc python3 -m python_pkg.archwiki_rag sync --reindex

# Query it.
claude-archwiki

Then, in the session, search_knowledge("...") against the archwiki server.

Design notes

Three non-obvious constraints shaped this package. All three come from reading the knowledge-rag source rather than its docs.

Markdown, not text. knowledge-rag chunks .md files with a heading-aware splitter and everything else with a blind fixed-width one. ArchWiki pages are heavily sectioned, so emitting real ##/### headings is what makes chunk boundaries land on section breaks instead of mid-sentence. HTML is not a supported suffix at all, so conversion is mandatory regardless.

Never rewrite an unchanged file. The incremental reindex decides a document is current by comparing stored mtime and size, not content. arch-wiki-docs regenerates all ~2500 files on every release, so writing unconditionally would bump every mtime and re-embed the entire corpus on each upgrade. sync.py compares rendered output against what is on disk and skips identical pages; this is the single most load-bearing behaviour in the package, and test_sync.py asserts it directly.

Subpages are nested. Systemd/User lives at en/Systemd/User.html, not en/Systemd_User.html. A non-recursive glob silently misses 164 pages, many of them the most useful ones. iter_pages uses rglob and the documents tree mirrors the dump's layout.

Store isolation

The corpus lives in its own store, ~/.local/share/knowledge-rag-archwiki, not the shared ~/.local/share/knowledge-rag. Roughly 27k Arch chunks would otherwise dominate both the BM25 index and the embedding space of any other corpus kept there. claude-rag and claude-archwiki are separate sessions against separate indexes.

Refresh guards

The pacman hook fires unattended, so reindex.py refuses to run when either:

  • a claude-archwiki session already holds the store's instance lock (knowledge-rag's own lock is taken only by its main(), so importing the orchestrator directly would bypass it), or
  • the machine is already under load (1-minute load average above 1.5 per core).

The load guard, not a GPU one: knowledge-rag ships the CPU-only onnxruntime build, whose execution providers are AzureExecutionProvider and CPUExecutionProvider. There is no CUDA provider, so despite the 3090 in this box the embedding pass runs on the CPU and saturates roughly every core for several minutes. A VRAM check would have looked reassuring and never fired.

Deferring is safe: the converted Markdown is already on disk, so the next run picks up exactly where this one stopped.