Cupertino 1.4.0
Version 1.4.0 ·
Added
Maps can write, and does it without an Apple Event.
apple_maps_add_favoriteandapple_maps_remove_favoriteship behindAPPLE_MAPS_ALLOW_WRITES, making Maps the first surface here whose writes send no Apple Event at all —usesAppleEventsstays false.Maps has no scripting dictionary and no App Intents registered on macOS, so the write is SQL into its Core Data store. The one thing that cannot be synthesised is the GEO place record, so it is never synthesised: the place is opened through the
maps://URL scheme, Maps mints the record into Recents, and it is copied. The insert needs three tables — not the eight the app touches — and Core Data mirrors it to iCloud by itself, confirmed on a second device.Two costs the tools state rather than hide: adding a place the store does not know leaves an entry in the user's Recents, and because the store is CloudKit-mirrored the write reaches every device on the account. There is no local-only insert here.
apple_maps_list_unfiled_placesreaches the saved places that are in no Guide. Resolving collection membership exposed a gap it could not close: 30 collection items, 18 filed in a Guide, 12 in none — and no tool could list the 12.apple_maps_list_collectionsreported the 18 and said nothing about the rest, so the counts simply did not add up.They are not debris.
Z_PRIMARYKEY.Z_MAXequals the live count for bothCollection(10) andCollectionItem(30), so Core Data has never deleted either — the leftovers theory is disproved by the store. Correlated against the rest of it, 7 of the 12 exist nowhere else: not a favourite, not in another Guide, not in recents. Those were reachable only by guessing a search term.apple_maps_list_collectionsnow also carries anunfiledcount so the shortfall is visible rather than silent.The filter guards its subquery —
NOT INis false for EVERY row once the subquery yields a single NULL, so an unguarded version reports "no unfiled places" whatever the store holds. A test inserts a NULL join row and fails without the guard.Maps can list the places in a Guide. Collection membership turned out to be
Z_6PLACES(Z_6COLLECTIONS, Z_7PLACES), a Core Data MANY-TO-MANY join table —Z_PRIMARYKEYdecodes ordinal 6 asCollectionand 7 asCollectionItem. Because a many-to-many leaves no column on either entity, the four names guessed from Core Data convention (ZCOLLECTION,ZCOLLECTION1,ZPARENTCOLLECTION,ZOWNINGCOLLECTION) could not have contained the answer, andapple_maps_list_collection_placesreturned nothing for every one of the 10 Guides.The key is now DISCOVERED BY RUNNING THE JOIN and scored against
ZPLACESCOUNT, Maps' own count per Guide, accepting only a candidate that reproduces all ten numbers exactly. That bar is the point:ZCOLLECTIONITEM.ZMAPITEMjoinsZCOLLECTIONfor 3 of 10 collections purely because map-item and collection row ids are both small integers, so a resolver picking the best-covered joinable column — the rule this file already uses for coordinates — would have filed places under the wrong Guides and looked like it worked. Scoring also survives Apple renaming the relationship, which a hard-codedZ_6PLACESwould not.Membership being many-to-many, one place can sit in several Guides, so the query asks
IN (SELECT ...)rather than joining. 30 item rows, 18 of them in a Guide; the other 12 belong to no collection at all.Apple's own schema says so, which is the confirmation: Core Data maintains
ZPLACESCOUNTwith a trigger that countsZ_6PLACES.Z_6COLLECTIONS. The oracle is therefore DERIVED from the mechanism, so an exact match is guaranteed for the real relationship and coincidental for everything else.scripts/probe-maps.mjsnever asked the question — it enumerated columns but notZ_*tables, so the join table was invisible to it. It now scores every mechanism againstZPLACESCOUNTand prints the winner. The offline fixture was the second reason this survived: it was HAND-WRITTEN and declared aZCOLLECTIONcolumn the real store does not have, so the suite proved membership worked against a column that never existed — the same shape as theZMUIDoverflow below, a comfortable fixture passing while the real store failed. It is now captured bypnpm probe:maps --write, and recapturing it turned 24 green tests red — every one of them a test that had been proving something about a schema Apple does not ship.Captured fixtures no longer carry Core Data's triggers.
writeFixtureomits them. Maps' store has eight that maintain derived columns by callingNSCoreDataDATriggerUpdatedAffectedObjectValue, a private function that exists only inside Core Data, so replaying them intonode:sqlitemade every INSERT into a triggered table fail with "no such function" — 18 tests at once, none of whose messages named the cause. A fixture replays SHAPE; the behaviour those triggers implement is Core Data's, not the store's. The header records how many were dropped, and the fingerprint still counts every object.Maps refs are now stable across an iCloud re-sync.
ZIDENTIFIER, a Core Data UUID, is set and distinct on every favourite, collection, collection item and recent on a real store, so refs carry it instead of the Core Data row id and survive the renumbering a re-sync causes. A store without it falls back to row ids and keeps the old session-scoped caveat. The column is adopted only when it is populated AND distinct on every row — a partially populated one would give durable refs for newly saved places and fail silently for everything already there.It was found by DIFFING THE STORE WHILE MAPS SAVED A PLACE, not by reading the schema.
pnpm probe:mapsnever reported it, because a probe can only report columns somebody thought to look for.
Changed
The read-only verdict was retracted, and the measurement that produced it kept.
pnpm probe:maps-write(scripts/probe-maps-write.mjs) snapshots the store, waits for a place to be saved by hand, and diffs. Saving one place moves eight tables and bumps tenZ_MAXcounters, including a ~1.2 KB GEO protobuf and two ~3 KB encodedCKRecords, plus theNSPersistentHistoryTrackingrows the CloudKit exporter reads to decide what to upload.mapssyncdholds the store open even with Maps quit, so there is no quiet moment either.That measurement is what closed the lane, and closing it was the wrong inference: it recorded what Maps does, and a write only has to do what Maps requires. Three of those eight tables are all it takes, once the GEO record is minted by Maps itself through the
maps://URL scheme rather than synthesised. Reading the first number as the second is the mistake, and it was made three times before it was caught.The App Intents lane was checked too and stays closed: Maps ships strings for
Add Places to ListandRemove Places From List, but the actions are not registered in Shortcuts on macOS 26.6 — Maps is a Catalyst app carrying the iOS resource bundle, so the strings ship regardless. The Accessibility lane is open and simply unbuilt: with a place card open Maps exposes named, pressableFavoriteandAddcontrols, 219 of its 236 pressable elements carry names, and the grants inherit into the app's servers. All four lanes are recorded in docs/maps.md with what would have to change for each answer to flip.
Fixed
The social card said "8 Apple apps".
SPELLEDin apps/website/src/config.ts ran out at "seven" the day Maps shipped, and its fallback isString(length)— so the one heading rendered intoog-image.pngused the exact spec-sheet digit that array exists to prevent. Nothing in CI reads a picture, so it was invisible to every gate. The list is padded past the current count on purpose: one that ends at today's number fails silently again on the ninth surface.