Layout: Wiki.Core (domain, nine ports, dependency-free vault parsing), Wiki.Application (sync with hash diff and per-model backfill, coordinator, rank, status), adapters for Gitea (note store, fact sink), llama.cpp embeddings, file-backed vector index and document catalog; Wiki.Host (composition root from appsettings, /health, /ready, /api/v1/status, /rank and /webhook shape-compatible with the Python service, POST /api/v1/sync behind an API key, Authentik-header and API-key auth, MudBlazor status page), Dockerfile, Woodpecker test and release pipelines. Contract suites in test/Wiki.Contracts run against every adapter. 80 tests, warnings as errors.
Parity (phase 1 acceptance): the host run locally against Gitea and the in-cluster wiki-embed, 40 labelled queries, same commit as the Python wiki-index: hit rate @1/@5/@10/@20 = 0.425/0.85/0.875/0.95 on both; MRR 0.604 vs 0.606; 35 of 40 identical top-10 sets.
Found and fixed: Gitea reset the keep-alive TLS connection twice during the 3094-document initial sync; the Gitea adapter now retries idempotent reads with backoff and recycles pooled connections.
Not in this PR: cluster manifests (homelab repo), TypeSafe and Anthropic adapters (later phases).
Design: homelab `kubernetes/PROPOSAL-wiki-web-api.md` (PR #939).
**Layout**: `Wiki.Core` (domain, nine ports, dependency-free vault parsing), `Wiki.Application` (sync with hash diff and per-model backfill, coordinator, rank, status), adapters for Gitea (note store, fact sink), llama.cpp embeddings, file-backed vector index and document catalog; `Wiki.Host` (composition root from `appsettings`, `/health`, `/ready`, `/api/v1/status`, `/rank` and `/webhook` shape-compatible with the Python service, `POST /api/v1/sync` behind an API key, Authentik-header and API-key auth, MudBlazor status page), Dockerfile, Woodpecker test and release pipelines. Contract suites in `test/Wiki.Contracts` run against every adapter. 80 tests, warnings as errors.
**Parity** (phase 1 acceptance): the host run locally against Gitea and the in-cluster wiki-embed, 40 labelled queries, same commit as the Python wiki-index: hit rate @1/@5/@10/@20 = 0.425/0.85/0.875/0.95 on both; MRR 0.604 vs 0.606; 35 of 40 identical top-10 sets.
**Found and fixed**: Gitea reset the keep-alive TLS connection twice during the 3094-document initial sync; the Gitea adapter now retries idempotent reads with backoff and recycles pooled connections.
Not in this PR: cluster manifests (homelab repo), TypeSafe and Anthropic adapters (later phases).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Batches requests (default size 2, matching llama-server's limits for long
notes), sorts responses by index, and normalises vectors to unit length.
CheckAsync prefers GET /health, falling back to a one-word embed call when
the server doesn't expose it. Registers as a keyed IEmbeddingModel so
multiple models can be wired up under different names.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
FileVectorIndex persists one binary file per model under index/ with
atomic tmp+rename writes; FileDocumentCatalog persists a single
catalog.json, rebuilding the link graph via WikiLinks.Extract on every
upsert. Both start empty and report health Ok with a reset detail if
their file on disk is corrupt, rather than crashing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
INoteStore reads the vault straight from Gitea (branch HEAD, a paged
recursive tree listing, raw file reads); IFactSink appends a new raw/
file via the contents API, numbering around any path collision. Both
verified against the live gitea.renner.uno API for response shape
rather than the swagger doc.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A long sync over one keep-alive connection to Gitea behind Traefik saw a
TLS connection reset after ~1000 documents and aborted the whole run.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
Design: homelab
kubernetes/PROPOSAL-wiki-web-api.md(PR #939).Layout:
Wiki.Core(domain, nine ports, dependency-free vault parsing),Wiki.Application(sync with hash diff and per-model backfill, coordinator, rank, status), adapters for Gitea (note store, fact sink), llama.cpp embeddings, file-backed vector index and document catalog;Wiki.Host(composition root fromappsettings,/health,/ready,/api/v1/status,/rankand/webhookshape-compatible with the Python service,POST /api/v1/syncbehind an API key, Authentik-header and API-key auth, MudBlazor status page), Dockerfile, Woodpecker test and release pipelines. Contract suites intest/Wiki.Contractsrun against every adapter. 80 tests, warnings as errors.Parity (phase 1 acceptance): the host run locally against Gitea and the in-cluster wiki-embed, 40 labelled queries, same commit as the Python wiki-index: hit rate @1/@5/@10/@20 = 0.425/0.85/0.875/0.95 on both; MRR 0.604 vs 0.606; 35 of 40 identical top-10 sets.
Found and fixed: Gitea reset the keep-alive TLS connection twice during the 3094-document initial sync; the Gitea adapter now retries idempotent reads with backoff and recycles pooled connections.
Not in this PR: cluster manifests (homelab repo), TypeSafe and Anthropic adapters (later phases).
🤖 Generated with Claude Code