gap: the vaarwegmarkeringen vocabularies are wider than the census the parser was built on #213
Labels
No labels
agent
agent:ci
agent:done
agent:failed
agent:needs-input
agent:refined
agent:refining
agent:running
agent:shipped
agent:skip
autonomous
autopilot
driven
local
plan
proposal
qa
qa-gap
research
retro
ship
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jeroen/cartopolis#213
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
docs/notes/navigation-marks.md:58-91records a census of 998 floating and 260 fixed marks over five boxes, and rests the whole design decision — parse by rule, not from a lookup table — on it (docs/notes/navigation-marks.md:60-62). The QA pass censused the whole register (10,105 floating, 8,369 fixed) and the vocabularies are wider than that sample. Three of the consequences are defects against the module's own stated rules; two are scope decisions.Bruinis a seventh body colour, and it is silently substituted rather than dropped.MarkColour::parse(crates/geo/src/nav_marks.rs:94-105) has arms for six body colours plusAmber; nothing matchesBruin.ColourPattern::parsedrops unreadable bands and keeps the rest (crates/geo/src/nav_marks.rs:153), so:Bruin→ empty pattern →read_featurereturnsNone(crates/cartopolis/src/systems/map/nav_marks.rs:349-352). 3 fixed marks undrawn.Rood/Bruin,Geel/Bruin→ a one-band pattern, drawn as a plain red or plain yellow mark. 4 fixed marks drawn as a different mark.The second one contradicts the module's own doctrine — "Drop, never substitute … a mark drawn as the wrong shape says the wrong thing" (
crates/geo/src/nav_marks.rs:26-37,crates/geo/src/nav_marks.rs:809-812) — and the doc comment asserting the vocabulary is{Rood, Groen, Geel, Wit, Zwart, Grijs}(crates/geo/src/nav_marks.rs:127-133) is now known false.Blauwis an unread light colour.lightcomes fromlicht_klr/licht_klthroughMarkColour::parse(crates/cartopolis/src/systems/map/nav_marks.rs:364-366); with no arm it reads asNoneand the lantern is not built (crates/geo/src/nav_marks.rs:469-480). One fixed mark.The note's
opgehevenfact is false.docs/notes/navigation-marks.md:87-88states it is#on all 1,258 sampled and that the API is not serving historical versions. Nationally five fixed features carry a date. The shipped check handles them correctly (crates/cartopolis/src/systems/map/nav_marks.rs:341-343,is_absentat:91-93), so the code is right and the note is wrong — and the note is the thing that would talk someone into deleting the check.Two vocabulary gaps that are decisions, not defects.
MarkShape::parse(crates/geo/src/nav_marks.rs:194-203) has no arm forton(1) orafwijkend(4);FixedForm::parse(crates/geo/src/nav_marks.rs:236-249) has no arm for 12 values totalling 136 features. Both currently fall toNoneand are dropped, which is the documented behaviour for a value from a newer register (crates/geo/src/nav_marks.rs:227-234) — but it puts real navigation marks (Geleidelicht,Stuurlicht,Verkeerssein,Mistlichten,Wadpaal zonder licht) in the same bucket as the deliberately-excluded verge lighting. See Open questions.Approach
crates/geo/src/nav_marks.rs— the vocabularies and geometry:MarkColour::BrownandMarkColour::Blue, with arms inparseand tones inrgb(:94-124). Tones follow the module's stated rule (:16-24): muted signal colours, knocked back from the real paint, and distinct from all existing tones underevery_colour_has_its_own_tone(:1004-1013) — that test'sallarray is enumerated by hand and must be extended.ColourPatterndoc comment's vocabulary list (:127-133) and theMarkColour::Amber"only ever a light colour" comment (:86) ifBlueshares that property.every_observed_colour_pattern_parses(:702-783) with the newly-observed values, and note in its doc comment which census the list comes from.crates/cartopolis/src/systems/map/nav_marks.rs— the cache tables:COLOURS(:112-120) — append, never renumber, per the rule at:97-99, which is what keepscache_key'sv1(:295-297) valid and means already-cached cells stay readable. The array length annotation changes with it.docs/notes/navigation-marks.md— "The vocabularies, censused" (:58-91):Pilaarwarning at:64-66, the missing-comma topmark at:71-73, the two-keys-for-one-vocabulary traps at:74-78, the three absent sentinels at:82-83).opgehevenclaim (:87-88) with the true one: dates do occur, the check earns its keep, do not delete it.33 of 260 sampled(:147) andThree of 260(:150), and the matching in-code counts atcrates/geo/src/nav_marks.rs:33-35,:186-190,:216-223.Acceptance criteria
MarkColour::parse("Bruin")andMarkColour::parse("bruin")answer a colour;ColourPattern::parse("Rood/Bruin").bands.len() == 2.MarkColour::parse("Blauw")answers a colour, and a fixed feature with"licht_kl":"Blauw"produceslight: Some(_)throughparse_items.every_colour_has_its_own_tone,crates/geo/src/nav_marks.rs:1004), with the new variants added to itsallarray.COLOURS(crates/cartopolis/src/systems/map/nav_marks.rs:112); no existing index moves andcache_key'sv1is unchanged. A test asserts a cell encoded before the change still decodes to the same marks — the existingthe_cached_form_round_trips(:625) does not cover this, so it needs a literal-JSON companion.docs/notes/navigation-marks.mdno longer claimsopgehevenis#on every feature, and says the check must stay.docs/notes/navigation-marks.md's vocabulary section states the census bbox, date and paging method, and itsupdated:front-matter is bumped.:147and:150, and in the code comments atcrates/geo/src/nav_marks.rs:33-35,:186-190,:216-223— is either restated against the national census or marked as a sample.cargo fmt --checkis clean workspace-wide (the CI gate is workspace-wide; see the standing note in CLAUDE.md).Criteria for the
naut_functandobj_vormadditions are deliberately absent — see Open questions.Verification
Re-running the census is the measurement this pass may not take. It is the command in the issue body — cursor-paged, following the
nextlink, national bbox3.0,50.6,7.4,55.7,limit=1000; ~20 pages, ~28 MB, under a minute. Whoever implements this runs it and pastes the resulting vocabulary counts into the note, rather than copying the issue's table.Not checkable here: colour is not evidence on this container's software rasteriser (
docs/notes/headless-shots-software-renderer.md), so whether a brown band reads as brown against the furniture base, and whether it is distinguishable from red at the Furniture fade distance, wants a workstation. The geometry half is assertable —nav_marksin--dump-state(crates/cartopolis/src/systems/dev/shot_harness.rs:640) counts marks in the loaded cells, so a Waal-at-Nijmegen capture (cell 8458, 5422) before and after shows whether the count moved. This container cannot run--shot, so that is a workstation step too.Out of scope
sign_kar/sign_perioare still not read; the lantern is painted in the registered colour and stops (crates/geo/src/nav_marks.rs:40-45,docs/notes/navigation-marks.md:133-138).obj_hoogteremains zero on every fixed mark, so a light tower stays the same post as a groyne mark.FurnitureInstance(docs/notes/navigation-marks.md:151-154).surveyed.rs'sPROP_KINDSandcrops'CATEGORIES; that is a separate ticket if anyone wants it.COLOURSdoes not need one, and doing it would throw away every cached cell for nothing.Open questions
Do any of the 12 unmatched
naut_functvalues become marks, and as whichFixedForm? The existing three forms areGroyneMark,Beacon,LightPost(crates/geo/src/nav_marks.rs:215-224). Several of the 12 map ontoLightPostwith no invention (Geleidelicht1,Stuurlicht24,Mistlichten14,Verkeerssein30) andWadpaal zonder licht1 ontoBeacon— but the stated reason for the existing exclusions is specifically that the BGT already surveys street lighting column by column (crates/geo/src/nav_marks.rs:50-54), and that reason does not decideDukdalf(10, a mooring dolphin — a structure, not a mark),Ballenlijn aansluitpunt(34),Meetpaal(2) orNautofoon(1). I am not willing to guess which of these the map should assert. If any needs new geometry rather than a reuse, note thatMARK_MAX_BYTES(crates/geo/src/nav_marks.rs:413) assumes at most two segments per body and would have to be raised.ton(1) andafwijkend(4) — drop, or draw?MarkShapeis a shape vocabulary;tonmeans "buoy" andafwijkendmeans "non-standard", so neither names a shape. Drawing them requires picking one, which is exactly the substitutionan_unknown_form_is_dropped_rather_than_guessed(crates/geo/src/nav_marks.rs:810-812) exists to forbid. My reading is that dropping 5 features nationally is the right answer and the note should say so explicitly instead of leaving them looking like an oversight — but that is a call about what the map claims, so it is yours.Should an unreadable band drop the whole mark? Adding
Bruinfixes the seven known cases, but the class of bug survives for the 27th value:ColourPattern::parse(crates/geo/src/nav_marks.rs:153) will keep drawing anA/<unknown>mark as a plainAone. Making it drop the mark instead matches "drop, never substitute", and costs the marks whose pattern is only partly readable. Fix the class or just the instance?Branch:
fix/213-nav-marks-vocabulary-gapOriginal request
Found by the QA pass on #210, walking what #206/#207 shipped.
What I did
docs/notes/navigation-marks.mdjustifies parsing the register by rule rather than from a lookup table, and rests that on a census of 998 floating and 260 fixed marks over five boxes:So I censused the whole register instead — all 10,105 floating and 8,369 fixed features, national bbox, cursor-paged — and applied the shipped match arms (
MarkShape::parse,FixedForm::parse,MarkColour::parse,is_absent) to every one.What happened
The rule does not cover the register. Nationally the vocabularies are 7 / 26 / 21 values where the note records 5 / 14 / 15.
Floating — 10,100 of 10,105 drawn. Two
obj_vormvalues the census never saw:tonafwijkendFixed — 7,608 of 8,369 drawn. 625 of the 761 dropped are the four kinds the note deliberately excludes (
Bermverlichting443,Bordverlichting121,Walkast34,Aanstraalverlichting27), which is working as designed. The remaining 136 are values the census never saw, and they fall into the sameNonebucket as the deliberate ones:naut_functBallenlijn aansluitpuntVerkeersseinStuurlichtMistlichtenDukdalfLuchtvaartverlichtingMeetpaalNoodverlichtingHeliverlichtingWadpaal zonder lichtGeleidelichtNautofoonAnd three more tails:
Bruinis a seventh colour.MarkColour::parsehas no arm for it, so 3 fixed marks paintedBruinare not drawn at all (the pattern comes back empty), and 4 more —Rood/Bruin,Geel/Bruin— are drawn with the brown band silently missing. On a layer whose own note says "the colour is the meaning", dropping a band is the failure the module is written to avoid.Blauwis a light colour, on one fixed mark. Unread, so that mark draws without its lantern colour.opgehevenreally does carry dates. The note says:Nationally five fixed features carry
17.11.2015(×3),07.04.2015and01.01.2022. The shipped check handles them correctly —is_absentsays no andread_featuredrops them — so the defensive check earns its keep, and the note's standing fact is simply false and should be corrected before someone deletes the check on the strength of it.What a user would see
About 130 registered objects nationally, of ~18,500: a handful of buoys and a scatter of lights and poles missing, plus seven fixed marks in the wrong colour. Nothing dramatic, and no user would spot it in a given cell. What is worth deciding is that the reason for parsing by rule is stated as a measurement, and the measurement was taken over 7% of the register.
Where the seam is
crates/geo/src/nav_marks.rs—MarkShape::parse,FixedForm::parse,MarkColour::parsedocs/notes/navigation-marks.md— "The vocabularies, censused"How to re-run it
The register pages by cursor, not by
offset(anoffset=query is a 400). Follow thenextlink:20 pages, ~28 MB, under a minute. It is cheap enough that the census could be a note that says when it was last re-run rather than one that says what the vocabularies are.
Filed by the QA pass on #210. Not
autonomous— a person decides whether this becomes work.🤖 Refined by the viberfox issue agent. Reply with @agent refine and what is wrong to have this rewritten.
🤖 Promoted into the build lane by the 3-day retrospective (#218) —
autonomous+ship.Why this one, of the four gaps the QA pass on #210 filed:
docs/notes/navigation-marks.mdjustifies parsing by rule rather than from a lookup table, and rests that on a census of 1,258 features. The census over all 18,474 says the rule does not cover the register: 7 / 26 / 21 vocabulary values against the recorded 5 / 14 / 15. A standing fact indocs/notes/is false, and the next person to trust it will delete theis_absentcheck on the strength of it.WireMarkis the on-disk cache format undercache/features/marks/v1/, notNetMessage—PROTOCOL_HISTORYis untouched, and there is no migration. Bump thev1path segment if the shape changes.Scope it to what the ticket measured: the missing
MarkShape/FixedForm/MarkColourarms (ton,afwijkend,Bruin,Blauw, and thenaut_functvalues the ticket marks as real marks), then correct the note's census section and record the date it was re-run.Bermverlichtingand the other three deliberate exclusions stay excluded.The two gaps left unpromoted are #212 and #215; the retrospective's reasoning for leaving them is on #218.
🤖 Refining this before anything gets built — reading the code, no branch, no commits. If it turns out I'd have to guess at the requirements I'll stop and ask instead.
🤖 This needs a decision before I build anything. The open questions are in the description above.
Answer them and reply with @agent refine to have the spec rewritten, or @agent to make me implement it as it stands.
🤖 viberfox issue agent on the VPS — 11 turns · $1.82 · session
0d0a394b-93b6-45d7-9ca2-b17b6e54f2e3. Reply with @agent to continue this session.Stuck, waiting for you: nonewhile three tickets wait for a person #270