Model21:xx
New identity model: three tiers, the 1956 floor, 83 MECE collections
Goal
Rebuild how a watch is identified, with exactly one home per watch.
Method
- Define three identity tiers by year: 1956-1965 family + case code (case_code); 1966-1974 caliber + case built reference (caseback_ref); 1975-1998 sales code (sales_code).
- Set a 1956 floor with a new in_catalog column (0 for year below 1956; hidden everywhere).
- Define 83 MECE collections by caliber family.
- Move the old line column to likely_collection; add an empty collection column.
- Rebuild the Status page around three shares: Identified, Right name, Right collection.
Results
- 55 pre-1956 rows hidden (the 1932 catalog).
- Name coverage 67% (10,026 of 15,065 models); collection 0%; identified 0%.
- Names by era: 1956-65 = 0%; 1966-74 = 12% (651 of 5,258); 1975-98 = 96% (9,375 of 9,762).
- The collection filter now lists the real 81 collections.
backups .bak-20260815-likelycol and .bak-20260815-incatalog
Tagging20:xx
Collection audit: year-window check and tag fixes
Goal
Find watches tagged to a collection in a year that collection did not exist, and know per collection where we stand.
Method
- Build a production window per collection from all-collections.md and the horological record.
- Flag every watch whose catalog year sits outside its window.
- Spot-check each flagged set against the raw text.
- Move the confirmed mis-tags.
- Set windows for 5 Actus and Skyliner.
- Rebuild the Status page and add a missing-collections section.
Results
- 325 watches flagged across 5 collections; 34 passed; 3 unchecked (no window).
- Marvel after 1968 moved to Lord Marvel (28 rows).
- Laurel from 1980 moved to Laurel Quartz (210 rows).
- Marvel now 1956-1966 (14); Lord Marvel now 1967-1978 (57).
- Still flagged for review: Skyliner 1969-74 (21) and 5 Actus 1983-85 (13).
backup .bak-20260815-collfix
Tagging19:xx
Section headers leaked as watch names; a new tagging source
Goal
Stop catalog section headers showing as watch names, and use them to fill the empty collection.
Method
- Detect a section-header heading (it ends in Group or Series) and stop using it as a watch name (lib/identity.ts, isSectionHeader).
- Read the collection out of the header and write line for untagged rows, only where the header names a real collection.
- Add a /status page.
Results
- watch 2573 now reads Seiko 1970; zero headers leak as names.
- Tagged: 5 Actus 6 to 370; Avenue 0 to 668; Arctura 22; Kinetic 13.
- Reclassified 174 pre-1962 rows to family + year.
Rejected
Generic category headers (Business Group, Dress Watch Group, Calendar Group). They name a category, not a collection. Inventing a collection from them would break the never-invent-a-fact rule.
backup .bak-20260815-collections
Data17:0x
LinkUp API: jewel lookup works, sales-code lookup fails
Goal
Use the LinkUp API to resolve ambiguous calibers by jewel count, and sales codes to references.
Method
- Build a client pipeline/scripts/linkup.py that caches every answer and fixes the macOS certificate error.
- Store every answer and citation in data/sources/linkup/audit.jsonl and the table linkup_audit.
- Move 5 (jewels): match the printed jewel count to exactly one caliber (enrich_jewels.py).
- Move 2 (sales code): probe the reference with strict Boley rules.
Results
Move 5 done: 65 of 179 ambiguous rows resolved; wristwatch references 25,753 to 25,818.
Rejected
Move 2 stopped. Deep depth ($0.055 per query) invented text and returned generic references; standard depth found 0 of 20 rows; JDM order codes are not indexed on the web. We wrote nothing.
backup .bak-20260815-jewels
Data16:4x
Reclassify pre-1962; apply the held sales-code tier
Goal
Fix the tier of pre-1962 watches and apply the held sales-code references.
Method
- Set all 112 pre-1962 wristwatches to the tier pre_numbering, because the caliber-case system did not exist then.
- Measure coverage only over watches that can have a reference.
- Write the 168 held sales-code references (recover_salescode.py --include-unconfirmed).
Results
- 31 rows corrected from the wrong tier none.
- Coverage 70.4% (25,753 of 36,604).
- Wristwatch references 25,585 to 25,753.
backup .bak-20260815-moves34
Data16:3x
Sales-code self-join (safe tier)
Goal
Recover references by copying within the DB, using only safe matches.
Method
- recover_salescode.py. A sales code is a unique model id; if the same code carries a reference on another page, copy that reference.
- Use only codes that map to one reference.
- Write only the matches that are also in Boley.
Results
- 4,920 stuck rows have a sales code; 423 resolve by self-join (255 are also in Boley; 168 are self-consistent only).
- Wrote the safe 255; all gained parts.
- Coverage 25,330 to 25,585 (69.0% to 69.7%).
Rejected
Held the 168 self-consistent-only rows, because they are not proven outside our own data.
backup .bak-20260815-salescode
Data16:1x
Unified recovery pass (code grammar + JDM-0 + OCR repair)
Goal
Recover 1966-1975 references that are stored in the text but not decoded.
Method
- recover_refs.py: one Boley load, one DB scan, one write; every method checked against Boley's 38,142 references.
- code_grammar: the LM/KS/GS formula (56LMW to 5606) plus family+case that is unique in Boley.
- variant_jdm0: a Boley group resolved by the JDM region-0 rule.
- ocr_repair: a garbled caliber next to its own case bracket.
- Attach parts in the same pass with concurrent workers.
Results
- 279 references, all confirmed in Boley, all gained parts.
- variant_jdm0 holds fully: 0 of 238 break; 59 resolve; 179 stay ambiguous.
- Coverage 25,051 to 25,330 (68.2% to 69.0%).
- Boley-linked 18,598 to 18,877.
- The pass takes about 1 second.
Rejected
The numeric code form (61-5A). Family 61 has many calibers, so it is not safe.
backup .bak-20260815-recover
Data15:19
Caseback backfill from stored text
Goal
Raise strict caseback_ref coverage for wristwatches (start 23,659 of 36,716, 64%).
Method
- backfill_caseback.py, dry-run first, then --apply.
- Recover a missing caliber or case only from evidence tied to the same row: the 56LMW grammar, the row's own refs, or a bracket tied to the row's caliber.
- Re-link parts with boley_relink.py.
Results
- 1,392 references.
- Coverage 23,659 to 25,051 (64% to 68.2%).
- 1,282 watches gained parts; Boley-linked 17,316 to 18,598.
- Online check of 10 new references: every caliber real; 7 exact references confirmed; 3 not found exactly but each real; 0 fakes.
Rejected
A loose scan of the whole page. On multi-watch pages it took a neighbour's case number (6117 010, 012, 022 all became 6117-6010). It offered about 2,000 rows but made wrong ids. Precision before recall.
backup .bak-20260815-caseback