Wikantik Development News
A narrative of recent development on Wikantik — the six weeks from mid-April to
the end of May 2026. In that span the project crossed from `1.1.x` to its `2.0`
line (six tagged releases, `2.0.0` through `2.0.5`), went live on real
infrastructure, and shifted its center of gravity from "a wiki that an AI can
read" to "a wiki built, operated, and consumed with AI agents as first-class
citizens."
---
The through-line: an agent-grade knowledge base
The dominant story of these weeks is making the corpus genuinely useful to
retrieval-augmented agents — not as an afterthought, but as a designed surface.
**Hybrid retrieval (mid-to-late April).** The window opens with hybrid search
landing in earnest: BM25 lexical scoring fused with dense vector similarity via
weighted reciprocal-rank fusion. A `QueryEmbedder` wraps the embedding client
with a cache, a timeout, and a hand-rolled circuit breaker so a slow or failing
embedding backend degrades to lexical search instead of taking the page down. An
in-memory chunk-vector index served the first dense top-k, and a retrieval
**experiment harness** with reproducible eval reports let us pick fusion weights
from evidence rather than intuition. This shipped as `v1.1.6`.
**Agent-grade content and the structural spine (late April).** From there the
work turned structural. A `ContextRetrievalService` was extracted as the single
seam through which search, the REST API, and the tool servers all retrieve —
collapsing several near-duplicate read paths into one. On top of it came the
**structural spine**: rename-stable canonical IDs, cluster/hub membership, and a
machine-queryable `/api/structure/*` index with matching MCP tools, all enforced
at save time. Pages gained **verification metadata** — `verified_at`,
`verified_by`, a computed `confidence` (authoritative / provisional / stale), and
an `audience` flag — backed by a trusted-authors registry, a `mark_page_verified`
tool, and an operator triage view. The **`/for-agent` projection** was born here
too: a token-budgeted view of any page (summary, key facts, headings outline,
recent changes, tool hints, verification state) that an agent can consume without
pulling the full markdown body. To keep all of this honest, a **retrieval-quality
CI** runner began scoring a curated query set with nDCG, Recall, and MRR across
retrieval modes and persisting the aggregates.
**Knowledge-graph inclusion policy (late April).** As the LLM-extracted knowledge
graph grew, it needed a governance story. A cluster-primary inclusion/exclusion
policy arrived with an admin dashboard, a CLI, per-page frontmatter overrides, and
an audit trail — defaulting to exclude, so entities are opted in deliberately.
**Page Graph vs. Knowledge Graph (early May).** A naming and conceptual cleanup
that paid for itself many times over: formally separating the **Page Graph**
(edges are real page-to-page wikilinks) from the **Knowledge Graph** (nodes are
extracted entities, edges are co-mention or typed relations). Packages, routes,
admin navigation, and tool descriptions were all disambiguated; the typed
`relations:` frontmatter experiment was retired; and identity normalization
(`NodeSignature` / `EdgeSignature`, NFC + predicate-synonym folding) tightened
entity dedup. A staged machine/human validation tier and a `/knowledge-graph`
viewer (mirroring the existing `/page-graph` reader) rounded it out.
**Derived agent hints (mid-May).** The projection got smarter without adding
author burden: derived `prefer_tools` and `prefer_pages` hints ranked across a
page and its cluster hub, a hub-summary synthesizer that overlays a Top-3
highlight when an authored hub summary is generic, a `read_pages` batch tool to
amortize the per-page read tax, and an agent-grade audit report for weak signals.
**Knowledge-graph curation (mid-May).** Curators got real tools: edge-curation v0
in the admin UI with an append-only audit table and one-click human-curated
elevation, then a full bulk curation surface on the MCP server (inspect / review /
curate nodes and edges), admin-bypass read paths so curators see freshly created
entities, and a closed `node_type` / `relationship_type` vocabulary enforced at
write time.
---
Under the hood: decomposition and a hard look at scaling
**Subsystem decomposition (early May).** A multi-phase architectural campaign
broke `wikantik-main` into typed subsystem factories, deleted the old
service-locator manager registry on `WikiEngine` in favor of typed fields,
decomposed the 800-line `WikiContext` into scoped sub-objects, and finished with
two static-analysis sweeps (SpotBugs + PMD) that split the worst god classes and
cleared real bugs. The result is a codebase where subsystem wiring is explicit
and testable in isolation.
**The scaling characterization study (third week of May).** Rather than guess at
performance, we ran a deliberate JFR-instrumented load study and let it drive the
fixes. The headline finding: the ceiling was not CPU but a per-request
DB-connection tax and a chain of shared-lock hotspots. The response was a sweep of
targeted surgeries — short-TTL caches for API-key verification, user lookup, and
KG mentions (removing per-request connections); hoisting shared JDK objects
(`Collator`, `DateTimeFormatter`, `SecureRandom`) off the hot path; a read/write
lock on the versioning file provider to kill per-search contention; an
event-manager dispatch-outside-the-lock fix; and a fixed-permit **backpressure
semaphore** that sheds load with a clean 503 before the thread pool saturates.
**Dense retrieval, productionized.** The brute-force in-memory vector scan — about
60% of search CPU — was replaced with selectable ANN backends: an in-process
**Lucene HNSW** index (now the production default, reading metadata via DocValues
rather than stored fields) and a server-side **pgvector HNSW** option for split-DB
topologies, each gated behind a retrieval-quality parity test so the speed-up
couldn't silently degrade relevance. These landed across `2.0.1` and `2.0.2`.
---
From code to a running product
**Operations and packaging (early-to-mid May).** The project grew the trappings of
something meant to be run by others: a community documentation set (CONTRIBUTING,
SECURITY, code of conduct, a definitive operations handbook), a `bin/container.sh`
wrapper over Docker Compose, a release-on-tag workflow, and — the big one — a
`bin/remote.sh` single entry point for deploying and administering Wikantik on a
remote host over SSH (image transfer, pages rsync, health-polled deploys with
auto-rollback). `2.0.0` was cut and the stack went live in Docker on its first
real host.
**Observability, handed off.** An in-repo Prometheus + Grafana overlay was built
and then deliberately **retired** in favor of an external monitoring stack
(jakemon) that scrapes the container's `/metrics`; a k6 load-test harness with a
`--verify` gate that confirms dashboard panels actually moved was added alongside.
**Off-box backup and disaster recovery (third week of May).** A 3-2-1 backup
posture arrived as a pull model: a NAS reaches in and pulls read-only snapshots on
a daily timer, with restore drills, per-tier Prometheus metrics, and a
`dr-restore.sh` that stands a fresh host up from a verified snapshot with a single
command.
**SSO and account lifecycle (late May).** A dedicated SSO hardening test suite
closed SAML and edge-case gaps — multi-valued claim normalization, fail-closed
identity-collision handling, session rotation against fixation, configurable
identity claims — and **Google OIDC went live** in production, with SAML support
and self-service account deletion alongside published privacy and terms pages.
This was `2.0.3`.
**Go-to-market (late May).** A static marketing site for `www.wikantik.com` was
built and shipped — hero, problem framing, comparison table, hosting options, an
"ask your wiki" terminal moment, and a lead-capture form wired to a serverless
backend — together with SEO fixes (correct sitemap domain, per-page titles,
JSON-LD). Releases `2.0.4` and `2.0.5` carried these out.
---
Reading, writing, and owning pages
The last stretch of the window returned to the everyday reader and author
experience.
**Anchored comments (last week of May).** A Google-Docs-style commenting system —
threads anchored to selected text via robust text-quote selectors, a reader-side
drawer with highlights, re-anchoring that survives edits, reply/resolve/reopen,
and admin-only thread deletion — built on new `comment_threads` / `comments`
tables and a fresh REST surface, capped by a comment UX overhaul.
**Personalization and blogging (29 May).** A personalized left-navigation "me
zone" with a recently-viewed list that updates live across instances, plus a round
of blog read-path and delete-UI fixes.
**Page ownership (30 May).** A page-ownership admin surface — orphaned-page triage
and reassign-by-user — gained a consistent data model when AI-agent-authored pages
(whose frontmatter author is an agent name, not a login) were given a default
owner: a dedicated `agents` service account, configurable and backfilled across
the corpus, so ownership is never silently null. The ownership table also began
showing each page's current name beside its canonical ID.
---
*This page is a narrative summary; the authoritative record of every change is the
git history and the per-release `CHANGELOG`.*