fix(atlas): keep the UniqueId, and make a landmark value name one landmark
Two defects the Phase 16b re-verify found in the released v1.2.1 bundle, both of which make a shipped feature unusable and neither of which any test saw. ## The aggregator discarded the UniqueId `shard_spawn_points.unique_id` was NULL on all 6,455 rows of a stock 57.4 tree. `listSpawners` filters `unique_id IS NOT NULL`, so `uo.options.spawners` was an empty dropdown -- and it is the ONLY option source for the Phase 12b object-property leases, so no `Spawner.MaxCount` / `MinDelay` / `MaxDelay` lease could be authored at all, with nothing on the form to say why. Every part of the path was already right except one line. The spawn files carry `<UniqueId>` (~6,374 of them), `parsePoints` returns it, the column exists and the insert passes `p.uniqueId || null`. `buildAtlas` rebuilds each point from an explicit field list and `uniqueId` was not on it -- the word appears nowhere in that file. `PARSER_VERSION = 4`'s own note says "a spawn point keeps its UniqueId, which is what a property lease targets", so the intent shipped as a comment while the code dropped the field one function later. `PARSER_VERSION` goes to 5 because the bump is the only thing that re-reads an already-imported tree: `sameSources` compares the tree's hashes, which have not changed -- only what is kept from them. Confirmed on the rig, where the boot after the fix logged `spawn atlas refreshed` on an unchanged tree and the manual import then correctly answered `unchanged`. ## A landmark option value named 23 places at once A stock tree has 558 landmarks under 320 distinct `facet/name` pairs. `Trammel/Entrance` is 23 different dungeons -- Blighted Grove, Covetous, Deceit, Despise, Destard and so on -- and `landmarkPoint` resolved with `.find()`, so 22 of the 23 were unreachable. An author who picked "Entrance - Destard" got Blighted Grove, and the run succeeded with no warning. The group was already the disambiguator: it was shown in the dropdown and left out of the value. The value is now `facet/group/name`, which is distinct across all 558. `landmarkPoint` tries that form first and keeps the two-part read as a fallback, because every event published before this fix stores `facet/name` and a published version is immutable -- refusing to parse those would break runs rather than correct them. The fallback keeps the old first-match behaviour deliberately: it is imprecise in exactly the way it always was, and silently relocating a live event's spawn point is worse than repeating a known imprecision. A three-part value whose group is gone REFUSES rather than falling back to the name, because it asked for one particular place. ## Verification On the released-artefact rig (installer -> bundle 2026.09.10 -> stock 57.4 tree -> protocol-7 sidecar -> core at main with this module): spawn points 6455 rows, 6364 with a unique_id (was 0) uo.options.spawners 100 options, and `?q=orc` searches them (was 0) uo.options.landmarks 558 options, 558 distinct values (was 320) suite 625 pass, 0 fail Each new test was confirmed to FAIL without its fix. The atlas one asserts the field on the AGGREGATOR's output rather than the parser's, which is the whole point of it -- and the test fixture had no `<UniqueId>` at all until now, which is exactly why a green suite said nothing. The landmark one asserts an INEQUALITY between two resolved points rather than a literal value string, so it survives another change of format as long as two options still address two places. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
This commit is contained in:
@@ -180,8 +180,13 @@ function hashSources(root) {
|
||||
* targets (Phase 12b). The bump is what re-reads a tree the boot path
|
||||
* would otherwise skip on an unchanged hash — the source files have not
|
||||
* changed, only what is kept from them.
|
||||
* 5 — and it did NOT keep it: version 4 bumped the parser and the aggregator
|
||||
* below still discarded the field, so the intent above shipped as a
|
||||
* comment. This bump is what makes an already-imported tree re-read now
|
||||
* that the mapping keeps it; without it `sameSources` sees an unchanged
|
||||
* tree and every existing install stays empty.
|
||||
*/
|
||||
const PARSER_VERSION = 4
|
||||
const PARSER_VERSION = 5
|
||||
|
||||
/** True when two source fingerprints describe the same tree. */
|
||||
function sameSources(a, b) {
|
||||
@@ -304,6 +309,16 @@ function buildAtlas(root, options = {}) {
|
||||
const place = resolveRegion(point.x, point.y, point.facet, placement, resolveOpts)
|
||||
return {
|
||||
name: point.name,
|
||||
// **The field this whole `PARSER_VERSION` note was about, and it was
|
||||
// dropped right here.** The parser has produced it since Phase 12b and
|
||||
// the column and the query have both been waiting for it, but this
|
||||
// mapping rebuilds each point from an explicit field list and `uniqueId`
|
||||
// was not on it — so every row landed with `unique_id` NULL, and
|
||||
// `listSpawners`, whose WHERE is `unique_id IS NOT NULL`, could only ever
|
||||
// answer empty. That made `uo.options.spawners` an empty dropdown and
|
||||
// every Phase 12b object-property lease unauthorable, with nothing on the
|
||||
// form to say why. Found by the Phase 16b walk against a released bundle.
|
||||
uniqueId: point.uniqueId,
|
||||
facet: point.facet,
|
||||
x: point.x,
|
||||
y: point.y,
|
||||
|
||||
Reference in New Issue
Block a user