The Session Registry (Lokacje/)¶
Nerthus.Core (until cutover). This page describes the frozen system that runs today and is deleted at cutover. Replaced by: not yet written.
Lokacje/ is a generated directory tree at the lore-repository root: one directory per
known place, one generated Sesje.md in each, holding the sessions that placed there
in chronological order. It is a derived projection of the session model
— the hand-authored sources stay exactly where they are, and the registry is rebuilt
from them. This page owns the registry's contracts: the ownership boundary, the tree
shape, root resolution, the unplaced pile, pruning, and idempotency. The plain-language
statement for operators is in Record a session.
The ownership boundary¶
The daemon owns exactly one filename in the tree — Sesje.md — plus the directory
skeleton. Every Sesje.md is generated and regenerated wholesale; an edit to one is
overwritten without warning, by design. Every other file in those directories is
foreign, first-class, and never created, modified, or deleted by the daemon. That
boundary is what makes the tree usable for future hand-authored content — an NPC
roster or notes can sit beside a Sesje.md and the generator will never touch them.
Two marks carry the contract in-band:
- the machine sentinel
<!-- nerthus:generated:session-registry -->— a stable token on every generated file. The pruner acts only onSesje.mdfiles that carry it; aSesje.mdwithout it was written by something else and is never modified or deleted, only reported. - the banner — two Polish lines pointing at the operator article. The banner is documentation and may be reworded; the sentinel is contract and may not.
Each session block also carries a provenance comment, <!-- nerthus:sesja <hash> -->,
holding the source session's content hash — the registry sits outside the integrity
scan (below), so the hash is what lets a cheap check answer "is this mirror current"
without scanning the tree.
The tree shape¶
The tree is driven by the location model, not by which sessions placed:
- First level — one directory per outerior root: every distinct value the
@outeriortags reference (tag schema), plus the reservedNieprzypisane/root. - Second level — one directory per active
Lokacjacarrying that@outerior. A location whose@outeriorhistory names several roots keeps a directory under each, so pre-move sessions keep a home. - One
Sesje.mdper directory, empty ones included. A place with no sessions gets a banner-only file — a positive statement that the place is known and nothing has been recorded there yet. Empty and stale are different states (see Pruning).
Directory names are the entity names in canonical Polish — never transliterated,
never slugged. Sanitization replaces / and NUL, strips trailing dots and spaces, and
fails loudly if two distinct names would collapse into one segment.
Root resolution¶
Every session location token resolves through one total function — an answer or an explicit reason, never silence — in this order:
- Explicit
Parent/Interiorin the token: the parent, canonicalized through the alias fold table (KH→Karka-han), must name a root in the universe. An unknown parent falls through to the interior's own@outeriorbefore refusing (UnknownRoot). @outerioron the resolvedLokacja, as of the session's own date — the tag is temporal, and the registry respects a location that moves between roots.- The from-date clamp: a session dated before its location's
(YYYY-MM:)from-date still places under that root. The from-date records when the fact was first written down, not when it became true, so dropping those sessions would punish late bookkeeping. The report counts them separately (OuteriorClamped). - Unplaced, with a closed reason:
UnknownLocation,AmbiguousLocation,NoOuterior, orUnknownRoot.
A token that names a root itself places at the root's own Sesje.md. A root need not
be an entity: a value like Pełne morze that real locations reference materializes as
a root regardless, classified Tabela in the report; entity-backed roots classify as
Lokacja, Mapa, or Region.
A session naming several locations places under the first token that resolves;
the other roots it touched are recorded on the placement as SecondaryRoots.
Registering the block under every root would multiply the duplication the registry
exists to manage, and the tree would stop being a partition.
The unplaced pile¶
- A session whose location line resolves to no root registers as a full block under
Lokacje/Nieprzypisane/— visible and actionable (fix the tag, or give the location an@outerior). - A session with no location line at all is counted in the report (
NoLocation) and materializes nothing — a registry of places has nowhere honest to file it.
The accounting reconciles by contract: placed + registered-unplaced + no-location = sessions considered. The counts, split by source and by reason, are the regeneration response body — see the API reference.
Pruning — the one scoped physical delete¶
Everywhere else in the system removal is a @status: Usunięty transition, never a
physical delete (architecture). The registry is the one scoped
exception, because a derived tree must be able to shed directories its model no longer
maps. The rule, exactly:
- Only files named
Sesje.md, only underLokacje/, are ever deleted — and only when they carry the machine sentinel. - Empty is not stale. A live location with no sessions keeps its banner-only
Sesje.md. Stale means the directory no longer maps to a location: its sentineledSesje.mdis deleted and the empty directory removed bottom-up. - A directory holding any foreign file is never removed. The owned
Sesje.mdgoes if the rule says so; the foreign content and the directory stay, and the case is reported (KeptForeign). - Pruning runs only after the full intended tree wrote successfully — a failed write pass aborts with the written and pending sets in the error body, and the next regeneration repairs the tree.
The deletions are recoverable by construction: everything under Lokacje/ is a copy of
a hand-authored original, so a pruning mistake costs a regeneration, not data.
Idempotency and determinism¶
Regenerating twice is byte-identical, and the guarantee is constructed, not observed:
- every collection is sorted with an ordinal comparer — Polish diacritics collate differently per culture, and the same tree must come out of any host;
- source-file enumeration order is never relied on: the session scanner sorts files
ordinally within each root, and root order is intentional —
Świat gryfirst, so a location's own chronicle outranks the character-diary copies in dedup (session model); - the rendered block is the winning source block verbatim minus the tool-managed
@Plikisection — the registry copy is not a distribution target, and a mirrored@Plikiwould read as a close-state signal; - no timestamps, counters, or host names appear in the output, and a file whose bytes already match is not rewritten.
The tree is materialized by adoption: POST /import generates it in the same pass that
emits the index and stamps the schema version, and reports it back as SessionRegistry
(API reference). From then on every model rebuild
refreshes it through the same seam every write path already funnels through — gated like
any lore write, and logged rather than raised, so a rebuild still completes. An explicit
POST /session-registry/regenerate stays available as the repair: it answers with the
same accounting and rewrites whatever drifted, on a repository whose tree was deleted,
hand-mangled, or generated by a daemon older than the model it now serves.
What the tree is not¶
- Not an input. The session scanner reads exactly four roots —
Wątki/,Organizacje/,Postaci/,Świat gry/(session metadata) — andLokacje/must never join them, though its files are named exactly what the scanner looks for. Adding it would give every session a secondFilesentry, andTest-NerthusSessionDistributedcounts entries: the entire backlog would silently read as distributed-and-closed, reminders would stop, and the generated copy could win dedup and invert the direction of derivation. A test locks the four roots. - Not scanned, so not integrity-checked. The content-hash machinery never sees the tree; the per-block provenance hash is the staleness signal instead.
- Not hand-editable in its
Sesje.mdfiles — though the directories accept any other file. This is the one place in the repository where overwriting a hand edit is the correct behavior. - Never an
@reftarget. A generatedSesje.mdis overwritten wholesale, so a reference reading properties from one would be reading from a file the generator rewrites at will (entity model). - Not written by anything but the generator. Session authoring and distribution
refuse any target resolving under
Lokacje/— a distributed copy inside the registry would be a foreign file the pruner must leave forever.
Cmdlet surface¶
Invoke-NerthusSessionRegistryRegenerate — routes, parameters, and the response shape are in
the API reference.
See also¶
- Record a session — the operator statement of the overwrite contract
- Session model — the header key, dedup precedence, distribution
- Session metadata — the four scan roots, the location line grammar
- Location model — how
@outerioris derived - Architecture — the data-owner contract this page carves its one exception from