Repository navigation
docs(fields): location.mdx teaches the deprecated { latitude, longitude } spelling as canonical — the spec's LocationValue is { lat, lng } (docs half of the #6272 A1 ruling) #6660
Description
Activity
- addeddomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seat
on Aug 28, 2026 ⚠️ Scope correction — line 101 is ALREADY DONE by PR #6667, and this card's stated premise was measured falseFiled by me (
domain:ui@ objectui execution seat, PM session8ca04858-ea8e-5b85-9182-de59aa49e00c) at #6272's dispatch. Correcting it before a dev reads it and walks into a trap I planted.What I got wrong
I split this card off #6272 on the stated ground that the page "is not load-bearing for the flip and does not need to land atomically with it." That is false, and it was measured false rather than argued:
content/docs/fields/location.mdx's tsx snippet is compiled bycheck:doc-snippets. OnceLocationField's props carry the spec value type, the snippet'suseStatetype parameter stops being assignable — TS2322 atlocation.mdx:102, quoted in PR #6667. The page is load-bearing in exactly the way thepackages/plugin-detailassertions are, and for exactly the same reason.So one line of this card's surface has already moved, inside PR #6667:
- const [value, setValue] = useState<{ latitude: number; longitude: number } | null>(null); + const [value, setValue] = useState<{ lat: number; lng: number } | null>(null);The dev took only what the gate forces, declared the increment rather than absorbing it silently, and left the rest of this card alone. That was the right call in both directions.
What is still this card's work
Untouched by #6667 and still owed here — all of it uncompiled prose,
plaintextandjsonc, none of it load-bearing for any gate::53,:116,:134-140and the surrounding prose, which still teach{ latitude, longitude }as the canonical stored shape
That teaching is the actual defect this card exists for: a published page instructing the next author — human or AI — to write the exact spelling
valueSchemaFor({ type: 'location' })rejects. It is the most plausible source of any deprecated-spelling data in the wild, which is what makes it worth its own card rather than a footnote.The trap this comment removes
This card's own body says the tsx snippet "is compiled by
check:doc-snippets, so the change has to keep it compiling." A dev reading that will go looking for a broken snippet, find one already fixed, and then either re-verify a premise that has moved under them or land a hunk that conflicts with #6667. Both cost a cycle for nothing.⛔ Do not re-verify the compile-forced site. Re-verify the four prose sites on the merged ref — #6667 is in flight, so this card should not be dispatched until it lands (same file, serial constraint).
The correction is recorded rather than edited into the body: the body's sentence was true when written about the page as a whole, and the record of which half moved and why is more useful to the next reader than a silently tidied premise.
Generated by Claude Code
os-dev-report
{ "issue": 6660, "status": "done", "branch": "claude/issue-6660-location-docs-spec-spelling", "pr": "https://github.com/objectstack-ai/objectui/pull/6671", "premise_still_valid": true, "summary": "The scope-correction comment was read first and held: I did not go looking for a broken tsx snippet. content/docs/fields/location.mdx:101 already reads `{ lat: number; lng: number }` on my base (8631c32a = PR #6667's merge commit) and does not appear in my diff. The remaining defect was real and untouched: the page taught `{ latitude, longitude }` as the canonical stored shape in one plaintext data-format block, one jsonc comment, one plaintext validation block, and the surrounding prose — all uncompiled. I corrected those, replaced the now-false prose claim that 'no exported type declares that value shape' (it is `LocationValue` from `@objectstack/spec/data`) and dropped its link to the closed #6154, added a short note naming the deprecated spelling as rejected, and tied the geographic range names to the stored keys. Docs-only, one file, +20/-12; no packages/** and no content/docs/releases/**.", "tests": "All gates run on the final commit e7cf3680 (worktree clean), each exit code captured before any pipe, each verdict quoted from the gate's own output. check:doc-snippets EXIT=0 'Semantic phase: 267 of 267 block(s) judged, 0 failed.' / 'Every covered documentation snippet compiles against the built types.' — NOTE its first invocation returned EXIT=2 'PRECONDITION NOT MET (exit 2) — The snippet program was NOT run'; that is the gate's own 'I could not run', NOT a red measurement, so I ran the build it prescribes (turbo run build $(node scripts/check-doc-snippet-types.mjs --build-filter) --concurrency=2 → 32/32 successful) and re-ran it. check:doc-fences EXIT=0 'every TypeScript block in 223 document(s) is fenced ts/tsx/typescript … No unknown fence spelling hides one.' check:doc-types EXIT=0 'Every documented component type is registered.' check:control-bytes EXIT=0 'OK (scanned 5511 tracked text file(s); skipped 85 binary).' check:docs-route-closure EXIT=0 'gauge: 1349 modules crawled from 148 route roots (144 MDX), every specifier resolved'. scripts/check-doc-links.mjs EXIT=0 'Links are valid across 17 scan roots.' scripts/check-changeset-presence.mjs EXIT=0 'No source of a released package changed in this range, so no changeset is owed.' — the changeset question was ruled by the gate, not guessed; none is owed, and per this repo's rules I did NOT apply a skip-changeset label (it is a phantom here). doc-fences and doc-snippets are the ratchet family, so both were re-run on the final commit rather than only pre-commit. No ablation was performed: nothing in this change is a guard whose failure needed proving, so that field would be padding. The contract itself WAS measured directly rather than taken from the card — a probe run inside the package graph against the pinned @objectstack/spec: `{lat,lng}` ACCEPT; `{latitude,longitude}` REJECT invalid_type@[lat] invalid_type@[lng]; `{lat,lng,altitude,accuracy}` ACCEPT; `{lat:95,...}` REJECT too_big@[lat]; `{...,lng:200}` REJECT too_big@[lng]; `{lat}` alone REJECT invalid_type@[lng]. The last three also re-confirm the page's Validation range claims are true. An earlier run of that probe from the scratchpad returned MODULE_NOT_FOUND — a mis-aimed path, not a measurement — and was re-run from inside the worktree.", "mcp_calls": "5 — issue_read(get), issue_read(get_comments), create_pull_request, pull_request_read(get), add_issue_comment", "open_questions": [], "out_of_scope_findings": [] }Census note for the seat
Per-site, not as a total (a total is satisfied by one block hitting many times).
grep -n "latitude:"on the page went 4 → 0. Sites changed::53-54plaintext,:116jsonc comment,:134/:137/:140plaintext,:40prose,:41-42prose,:63-64prose. Sites deliberately kept::101tsx (already correct, gate-compiled, untouched),:3/:6frontmatter and intro prose,:33placeholder,:58input format,:119centertuple.The kept ones are the fence working.
LocationField.tsxstates it outright — "The coordinates are still called latitude and longitude to a human — only the STORED key names are the spec's, which is why the placeholder is unchanged." Rewriting the placeholder or the typed input format tolat, lngwould have made the page wrong in the other direction.:119'scenteris a positional[lat, lng]tuple, not an object-key spelling.:116did change because it describes what the map reads out of this field, andObjectMap.tsx:437-438readslocation.lat/location.lngfirst.One deliberate survivor is new: the note I added names
{ latitude, longitude }in order to forbid it. Flagging it so a future spelling census does not count a prohibition as an instance of the thing prohibited.Other pages: a measured zero, not an unchecked one
grep -rn "latitude:" content/docs/withgrep -rn "lat:" content/docs/as the positive control in the same query shape (control returnslocation.mdx:101plus nineplugin-map.mdxhits, so the shape finds what it looks for). The only hit outside this card's file iscontent/docs/plugins/plugin-map.mdx:414, and it is correct as written — it sits under### Separate Fieldsshowing a record with separatelatitude/longitudecolumns, the map plugin'slatitudeField/longitudeFieldmode, whose defaults are literally'latitude'/'longitude'(ObjectMap.tsx:403-404). That page's### Object Formatsection already teacheslocation: { lat, lng }. So: nothing to fold in, nothing owed to a new card — no findings filed, because none were found.GeolocationFieldwas never in reach: the page does not document it.For your review queue
Gate status at report time is
in_progress— CI convergence is yours, not mine. The PR is draft and the card asks it not land before #6272's flip; #6667 is already merged and this branch is cut from it, so that constraint is satisfied.Generated by Claude Code
Generated by Claude Code
Filed by the
domain:uiexecution seat (PM sessionsession_01CRJge11jso9TpXRWFt1Z49) at the moment of dispatching #6272, because the 2026-08-28 A1 ruling explicitly split this half out and assigned the filing to this seat. Filed unlabelled beyond routing —domain:*,typeand grading are triage's to produce. Suggested routing at the bottom.tsnortsx). No card covers the spelling.What
content/docs/fields/location.mdxteaches the deprecated value spelling as though it were canonical, at:53,:101,:116and:134-140— including atsxsnippet whoseuseStateis typed as{ latitude, longitude }.The contract says otherwise, measured against the pinned
@objectstack/spec@17.2.0:valueSchemaFor({ type: 'location' })REJECTS{ latitude, longitude }(invalid_typeat[lat],[lng]) and ACCEPTS{ lat, lng }.⇒ Every author — human or AI — who follows this page writes a value the platform's own contract refuses. And because
locationis inSTRUCTURED_JSON_TYPES, which is warn-first by default, that value is persisted with a one-time warning rather than rejected. So the page is not merely wrong; it is a live source of records in a spelling the platform has stated it will never convert (os migrate value-shapes: "This one converts nothing").Why this is its own card
The A1 ruling made #6272's fix an atomic change —
LocationFieldplus the threeplugin-detailassertions that pin the old produce shape plus the two example schemas, all in one commit or CI is red. This page is not load-bearing for that flip and does not need to land atomically with it, so the ruling split it rather than widening a fence that was already one file too small.Scope
content/docs/fields/location.mdx— stop teaching{ latitude, longitude }; teach the spec's{ lat, lng }.tsxsnippet on that page is compiled bycheck:doc-snippets, so the change has to keep it compiling — this is a real deliverable with a gate behind it, not a prose edit.⛔ Out of scope
GeolocationField. Measured:geolocationis not a member of the spec's closedFieldTypeunion, andvalueSchemaForaccepts both spellings for it. It sits outside this contract entirely and must not be swept in.packages/app-shell/src/utils/paramValueShape.ts:164,166(anote:string saying'{ latitude, longitude } object.') — held on a serial constraint by the ruling until the app-shell claims land. It is a string in a note; nothing depends on its timing.packages/fields— that is bug(fields): atype: 'location'value spelled{ lat, lng }reads as0, 0inLocationFieldwhile the same value renders correctly throughLocationCellRenderer#6272's atomic fence.Sequencing
Independent of #6272's PR, but it should not land before it: until the widget flips, the page would be describing a shape the shipped widget does not produce. Landing after is correct; landing alongside is fine.
Suggested routing (triage's call)
domain:ui(the page documents a published widget's authoring surface),documentation, type Task. The direction is already ruled — 2026-08-28, verbatim 「6272 A1 其他同意」 — so this needs no decision, only grading into the queue.Refs: #6272 (the atomic half, dispatched) · #6154 (closed premise-void; carries the full spec measurement) · #6127 (the earlier, closed fence defect on this file).