Name resolution¶
Nerthus.Core (until cutover). This page describes the frozen system that runs today and is deleted at cutover. Replaced by: not yet written.
Every name in the lore is Polish and inflected — a session note writes Erastera, Lordowi Tussalowi, Opatowi Perrinowi, and the resolver maps each surface form back to the canonical entity. It runs a seven-stage pipeline (exact → computed alias → declension → consonant alternation → title strip → annotated lemma → fuzzy) over an in-memory name index built from the entity model. This page covers resolving one name, resolving a batch, inspecting a single index token, and rebuilding the index. The examples use the canonical session fixtures: the characters Eraster and Lord Tussal, and the NPC Opat Perrin.
Resolution reads need entity.read; rebuilding the index needs admin.index. Every
example runs against a live daemon — see how the reference is tested. The
resolution model is specified in
name resolution.
Routes¶
| Method | Path | Cmdlet | Cap | Write |
|---|---|---|---|---|
| POST | /resolve |
Resolve-NerthusName |
entity.read |
— |
| POST | /resolve/batch |
Resolve-NerthusName (array input) |
entity.read |
— |
| GET | /name-index/lookup/{token} |
— (raw index diagnostic; not a resolver) | entity.read |
— |
| POST | /name-index/rebuild |
— (in-memory rebuild) | admin.index |
— |
Cap is the required capability (— = public, no token); Write (✓) marks routes that pass the write gate; a — in Cmdlet is reached directly, no wrapper. Paths are relative to /v1/api; the cross-cutting contract — middleware, envelopes, status codes — is on the API reference index.
POST /resolve body: name (or queries[] on /resolve/batch), typ (alias type), within, activeOn, noFuzzy, topN, maxDistance — resolver semantics in Name resolution.
Resolve one name¶
POST /v1/api/resolve takes { name } and returns the winning owner:
{ name, typ, plik, stage, confidence, ambiguous, candidates }. stage records which
pipeline step matched (exact here); ambiguous is true only when a homonymous token
has more than one owner. An unresolvable name returns 200 with a null body.
Response 200:
{ "name": "Eraster", "typ": "Postać", "plik": null, "stage": "exact",
"confidence": 1.0, "ambiguous": false, "candidates": ["Eraster"] }
Resolve a multi-word name¶
The full canonical form resolves at the exact stage too — the whole string is a
priority-1 token in the index.
Response 200:
{ "name": "Lord Tussal", "typ": "Postać", "stage": "exact",
"confidence": 1.0, "ambiguous": false, "candidates": ["Lord Tussal"] }
Resolve a batch¶
POST /v1/api/resolve/batch takes { queries } and returns the { count, items }
envelope, one { token, resolved, typ, stage } per query in request order. A miss keeps
its token with resolved: null and stage: "miss". Here all three resolve.
Response 200:
{ "count": 3, "items": [
{ "token": "Eraster", "resolved": "Eraster", "typ": "Postać", "stage": "exact" },
{ "token": "Lord Tussal", "resolved": "Lord Tussal", "typ": "Postać", "stage": "exact" },
{ "token": "Opat Perrin", "resolved": "Opat Perrin", "typ": "NPC", "stage": "exact" }
] }
Inspect an index token¶
GET /v1/api/name-index/lookup/{token} reads one raw token straight out of the index,
without running the pipeline — it returns { source, ambiguous, owners }. The index is
case-insensitive, so the lowercase eraster finds the Eraster token.
Response 200:
{ "source": "Eraster", "ambiguous": false,
"owners": [{ "name": "Eraster", "type": "Postać", "priority": 1 }] }
Rejected: token not indexed¶
A token that is not a surface form of any entity is 404 — the lookup is a direct index
probe, not a fuzzy search.
Response 404:
What the lookup is for, and what it is not for¶
It answers which blocks own this literal token, and nothing else. It never runs the
resolver, so every inflected form of an indexed name is a 404 — including forms
POST /resolve finds without difficulty. Driven against one entity that the index holds
unambiguously enough to be a fair test:
| request | answer |
|---|---|
GET /name-index/lookup/vanda |
200 — Vanda, ambiguous, owned by a Postać and a Gracz |
GET /name-index/lookup/vandy |
404 — the genitive |
GET /name-index/lookup/vando |
404 — the vocative |
GET /name-index/lookup/vandzia |
404 — the diminutive |
POST /resolve finds all three: two by declension and one — wrongly — by fuzzy, onto a
place. So a 404 here is not evidence that a form is unresolvable, and a caller that
reads it that way will conclude the opposite of the truth.
Use it to debug the index: to see whether a token was written down at all, which blocks
claim it, and whether they collide. Use POST /resolve for every
question about a form a person actually wrote, because that is the route that runs the
pipeline. Widening the lookup to run the pipeline would destroy the one question it answers
cleanly, and would duplicate /resolve.
Rebuild the index¶
POST /v1/api/name-index/rebuild re-parses the entity model and rebuilds the index in
place, returning { rebuiltAt, buildMs, indexStats } — where indexStats carries the
token and stem counts. It needs admin.index.
Response 200: