Skip to content

GDR-0026 to 0028: the Watch, the word of the day's bar, Wiktionary; University modules 12–14 - #64

Open
ChaliceForAuri wants to merge 1 commit into
mainfrom
companion-records
Open

ChaliceForAuri wants to merge 1 commit into
mainfrom
companion-records

Conversation

@ChaliceForAuri

@ChaliceForAuri ChaliceForAuri commented Oct 18, 2026 •

Copy link
Copy Markdown
Owner

Renumbered on 2026-10-21: main took GDR-0024 and GDR-0025 in #74 and #75 while this stack was open, so the three records here are 0026 to 0028 and the stack is rebased on main.

What this is

The records for what was decided on 2026-10-18, on top of GDR-0023 (the Library), plus the University modules those records rest on. No code: the engine (TimbreCore, the Library, the daily pick, Spell it) is the next PR, with its ADR, as GDR-0023 decision 4 says.

Records

  • GDR-0026 — Apple Watch: the to-do key on the wrist, the Library at a glance, and no model needed there. Extends GDR-0023's companion to the wrist. Records what the watchOS 27 SDK on the dev Mac actually contains (EventKit yes; Speech and SpeechAnalyzer no; FoundationModels present, eligibility unproven on hardware) and two rules: deterministic on the wrist, the model elsewhere; an iPhone without Apple Intelligence shows the Library and the word and says so. Four test devices named.
  • GDR-0027 — The word of the day: the bar is Vocabulary.com and the widget apps, and the word is yours first. Four properties that must hold at launch: the pick is yours first and deterministic; practice is spoken; it is ambient (menu bar, Lock Screen, complication) and marks itself met from polished text without storing the sentence; the entry is deep, with facts labelled by source and model-written lines labelled as the model's.
  • GDR-0028 — Bundled word content from a Wiktionary extract, under CC BY-SA 4.0; the model writes only examples. Attribution in the app, the extract and its scripts published as data under the same licence, the app's code under GDR-0005's terms. The lists in order: tier-two general English; software and product; healthcare, law, finance, design; phrases and idioms.

Index: GDR-0002's row now reads "no iOS app" superseded by 0023 and 0026; dictation stays macOS-only. The record itself is untouched.

Product map

Status line points at the new records; a Watch row joins §2; §5 and §7 reference GDR-0026–0028.

University

Three modules, in the existing fragment format, listed in manifest.json before the glossary (now module 15):

  • 12 · Spaced repetition and the Library — the forgetting curve, SM-2 then FSRS, strength as retrievability, events not numbers, met in the wild, what Vocabulary.com does and why Timbre need not, open data and share-alike.
  • 13 · iCloud and CloudKit — the claim and the daemon, the three iCloud mechanisms, CloudKit's shapes and CKSyncEngine, designing for a union merge with tombstones, entitlements and the schema that is forever, Advanced Data Protection, testing without a server.
  • 14 · The other Apple platforms — one language, three sandboxes; what iOS gives (App Intents, WidgetKit Controls, ActivityKit, share extensions); watchOS checked against the SDK; gestures and text input on the Watch; packages and platform floors; App Store versus Developer ID.

docs/learning/README.md and the layout block in CLAUDE.md now say the University's living home is web/src/lib/university.

Verified

  • pnpm run sync:docs regenerated records.json (38 records) and design.json; the three new records parse with status note implementation pending and their Builds on relations resolved.
  • pnpm run check: 0 errors. pnpm run build: clean.
  • Run with pnpm 9 explicitly, so the lockfile is untouched (see Pin pnpm 9 for web/ so installs cannot drift the lockfile #61).

🤖 Generated with Claude Code

@vercel

vercel Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
timbre Ignored Ignored Preview Oct 21, 2026 8:59pm UTC

Request Review

…y; three University modules

GDR-0023 took the product map's five decisions. These three extend it with
what was decided on 2026-10-18:

- GDR-0026 — Apple Watch: the to-do key on the wrist, the Library at a
  glance, and nothing on the wrist needs the model. Records what the
  watchOS 27 SDK actually contains (EventKit yes, Speech no,
  FoundationModels present but eligibility unproven) and the rules for an
  iPhone without Apple Intelligence.
- GDR-0027 — The word of the day's bar: Vocabulary.com for substance, the
  iPhone widget apps for presence, and four properties that must hold at
  launch: the word is yours first, practice is spoken, it is ambient and
  marks itself met, and the entry is deep with facts labelled by source.
- GDR-0028 — Bundled word content comes from a curated Wiktionary extract
  under CC BY-SA 4.0, attributed in the app and published as data; the
  model writes only example sentences and the "why today" line, labelled.

The index annotates GDR-0002 ("no iOS app" superseded by 0023 and 0026;
dictation stays macOS-only). The product map gains the Watch surface and
points at the new records. Backstage's JSON is regenerated.

Timbre University gains modules 12–14, the foundations these records rest
on: spaced repetition and the Library (the forgetting curve, FSRS, events
not numbers, met in the wild, open data); iCloud and CloudKit (the claim
and the daemon, the three mechanisms, designing for a union merge, the
schema that is forever); the other Apple platforms (what iOS and watchOS
give and withhold, checked against the SDKs, packages and platform
floors, App Store versus Developer ID). The glossary becomes module 15.
docs/learning/README.md and CLAUDE.md say where the University now lives.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@ChaliceForAuri ChaliceForAuri changed the title GDR-0024 to 0026: the Watch, the word of the day's bar, Wiktionary; University modules 12–14 GDR-0026 to 0028: the Watch, the word of the day's bar, Wiktionary; University modules 12–14 Oct 21, 2026

@ChaliceForAuri ChaliceForAuri left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Timbre review · pass

Head b400e8efc0ee9ce64fe322f5c1b6e5a07738c128 (companion-records → main)
Model claude-fable-5-1 · $4.43
Checklist docs/design/review.md @ d8c2b15a3317 · inventory @ f2445ceb5571
Tool tools/review.sh @ 2278c840573d
Run 2026-10-23T00:35:32Z on Hugos-MacBook-Air-M5 by @ChaliceForAuri

Gates

Gate Result Time
swift-format lint pass 1s
Backstage JSON is regenerated pass 1s
Architecture model generates pass 2s
Site type-checks pass 3s
Site builds pass 4s

CI at review time: App build: success, TimbreKit tests: success, Web check + build: success, Vercel Preview Comments: success, Supabase Preview: skipped, Vercel: success

Compliance (review.md §4–5)

  • Personal data: touched · Network: none · Storage or logging: none · Third party: none
  • Real data in the repo: no · User-facing copy: unchanged · Rights: unaffected · Inventory current: yes

No code changes; the records design flows the inventory already carries: §1 Library (met events with date and app, Watch provenance), §1 the word-of-the-day notification (cites GDR-0027), §2 the Watch's text input and the to-do queue in transit. Wiktionary and kaikki.org are content licensors under CC BY-SA, not processors, and no personal data flows to them. The University and the records render under /backstage behind the owner allowlist in hooks.server.ts, so no copy a user sees changes; the inventory is not in this tree but its rows already match these records, with the two gaps named in the findings.

Summary

The pull request adds GDR-0026 to GDR-0028 (the Watch, the word of the day's bar, the Wiktionary extract), amends the index row for GDR-0002, extends the product map, adds three University modules to the manifest, and points CLAUDE.md and a new docs/learning/README.md at web/src/lib/university as the University's living home; it changes no code. Every record link target exists, the GDR-0023 decision numbers the records cite are correct, GDR-0002 does say "No iOS app" so the index note is accurate, the numbering follows main's 0025, records.json and design.json are regenerated, and TodoParser imports Foundation only, which supports GDR-0026's claim that it can move to TimbreCore. Four things should change before or soon after merge: GDR-0026 does not say that the Watch's system dictation may use Apple's servers, which the inventory's Watch row and gap 4 require of the Watch copy (C9); GDR-0027 never states that the notification is off by default although the inventory cites it for exactly that (C2); Module 13 says release.sh already embeds a provisioning profile, which tools/release.sh does not do; and web/README.md plus the index.ts comment still say new modules are written in mdsvex, contradicting the new CLAUDE.md and README. The SDK claims in GDR-0026 and Module 14 (Speech absent, FoundationModels present, ActivityKit absent on watchOS 27) could not be verified from the review environment because the SDK probe was declined; the human should confirm them per A10. This tree predates GDR-0030 (no docs/design/review.md or data-inventory.md), so the decisions index and records.json will need sync:docs re-run after a rebase on current main. Verdict: pass, with the should-fix findings on the record.

Findings (7)

should-fix

  • docs/decisions/gdr/0026-apple-watch-the-wrist-key.md:57 — GDR-0026 does not say the Watch's system dictation may use Apple's servers (records). The record's rule reads: "The Watch's speech input is the system's dictation, which returns text; SpeechAnalyzer is not on the platform", and later "Zero network requests from the Watch binary, as from every other." Both are true of our code, but the inventory's row for the Watch's text input says "Apple's dictation may use Apple's servers under the user's own Siri & Dictation setting; the Watch app's copy says so", and §6 gap 4 asks for that copy. Review C9 requires the record to name which Apple service is on-device and which may not be. This is the record that will constrain the Watch app, and it is immutable after merge, so the requirement belongs here. Module 14 (the-other-apple-platforms.html line 46) describes the same text input without the caveat. Add one sentence to the "Deterministic on the wrist" rule: "The system's dictation is Apple's and may use Apple's servers under the user's own Siri & Dictation setting; the Watch app says so where the key is first used." Add the same clause to Module 14's text-input paragraph.
  • docs/decisions/gdr/0027-word-of-the-day-the-bar.md:57 — GDR-0027 does not state that the notification is off by default (privacy). Decision 3 reads: "A menu bar item and a notification on the Mac; a widget and a Lock Screen control on iPhone; a complication and a Smart Stack card on the Watch (GDR-0026)." Nothing in the record says the notification is opt-in or where it is turned off. The inventory's row "The word-of-the-day notification ... Off (GDR-0027)" cites this record for a default the record does not contain, and review C2 requires notifications to be off by default and described plainly, with C3 requiring the off switch in the same place. Add to decision 3: "The notification is off by default; it is turned on, and off again, in Settings, in plain words." Then the inventory's citation is supported.
  • web/src/lib/university/icloud-and-cloudkit.html:62 — Module 13 says release.sh already embeds a provisioning profile; it does not (docs). The module states: "it needs a provisioning profile embedded in the bundle, which is signing plumbing release.sh already handles (GDR-0010)." tools/release.sh contains no provisioning-profile step; its only "profile" is the notarytool keychain profile TimbreNotary. GDR-0010 (status: implementation pending) lists the embedded profile as a consequence still to come: "an embedded provisioning profile join release.sh". The module presents pending work as done. Change to: "which is signing plumbing GDR-0010 assigns to release.sh when sync ships."
  • web/README.md:15 — web/README.md and index.ts still say new modules are written in mdsvex (docs). This pull request's CLAUDE.md and docs/learning/README.md say "New modules are written there [web/src/lib/university] and listed in web/src/lib/university/manifest.json", and the three new modules are HTML fragments loaded by import.meta.glob('./*.html'). web/README.md line 15 still reads "new modules are written in mdsvex", and web/src/lib/university/index.ts lines 11 to 13 say "New modules are written in mdsvex instead; these stay faithful to the source." Review A6 asks that docs follow the change. docs/design/backstage.md §(public)/university describes mdsvex pages under a public route the code does not have; that drift predates this change but the same pass can fix it. Update web/README.md line 15 and the index.ts comment to say new modules are HTML fragments in web/src/lib/university listed in manifest.json; note the Backstage design doc's University section in the same pass or in the next one.

nit

  • docs/decisions/gdr/0027-word-of-the-day-the-bar.md:87 — "It adds no storage" contradicts decision 3's "The Library stores that it was met and when" (records). The consequence reads: "Met detection runs in the polisher's path on the Mac and in practice on the phone ... It adds no storage and no capture." Decision 3 says the Library stores the met event and its time. The intent is that no new store is created and no sentence is kept, but the sentence as written is literally false, and the record is immutable after merge. Reword to: "It adds no new store and no capture: the met event is one more Library event, and the sentence is never kept."
  • web/src/lib/university/icloud-and-cloudkit.html:73 — The Advanced Data Protection claim depends on which CloudKit fields the engine uses (docs). The module says: "By default Apple holds the keys to most iCloud data, including third-party apps' CloudKit data ... With Advanced Data Protection turned on by the user, that data is end-to-end encrypted and Apple cannot read it." Apple's end-to-end protection for third-party CloudKit data applies to fields written through CKRecord.encryptedValues and to assets, not to plain record fields; whether the Library's records qualify depends on the engine's ADR, which does not exist yet. The inventory's §3 row makes the same claim, so the copy matches today. Apple's exact scope could not be verified from this tree. Add "for fields the app stores encrypted" to the sentence, and have the engine's ADR pin that Library records use encrypted fields so the inventory's claim stays true.
  • web/src/lib/university/icloud-and-cloudkit.html:81 — The "In Timbre" boxes describe TimbreCore and sync in the present tense before they exist (docs). Module 13's box reads: "LibrarySync is a protocol in TimbreCore ... Sync is off by default, described plainly, and syncs the Library and the profile", and Module 12's box says "strength(of:at:) is pure and lives in TimbreCore with a corpus beside it." packages/ contains only TimbreKit in this tree; the description says the engine is the next pull request. The University is behind the Backstage gate today, so no user reads this, but once it is public the boxes would claim shipped behaviour. Open each box with "As GDR-0023 designs it (the engine lands with its ADR):", or leave as is if the engine's pull request merges in the same sitting.

Posted by tools/review.sh (GDR-0030). The gates ran on the maintainer's Mac; the model advises; the maintainer approves by merging.

The rules that make the degraded cases designed rather than discovered:

- **Deterministic on the wrist, the model elsewhere.** The Watch's speech
input is the system's dictation, which returns text; `SpeechAnalyzer` is

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should-fix · records — GDR-0026 does not say the Watch's system dictation may use Apple's servers

The record's rule reads: "The Watch's speech input is the system's dictation, which returns text; SpeechAnalyzer is not on the platform", and later "Zero network requests from the Watch binary, as from every other." Both are true of our code, but the inventory's row for the Watch's text input says "Apple's dictation may use Apple's servers under the user's own Siri & Dictation setting; the Watch app's copy says so", and §6 gap 4 asks for that copy. Review C9 requires the record to name which Apple service is on-device and which may not be. This is the record that will constrain the Watch app, and it is immutable after merge, so the requirement belongs here. Module 14 (the-other-apple-platforms.html line 46) describes the same text input without the caveat.

Add one sentence to the "Deterministic on the wrist" rule: "The system's dictation is Apple's and may use Apple's servers under the user's own Siri & Dictation setting; the Watch app says so where the key is first used." Add the same clause to Module 14's text-input paragraph.

2. **Practice is spoken.** The drill attached to the word is Spell it, Say
it or Explain it (GDR-0023, decision 5), scored on-device. No multiple
choice.
3. **It is ambient, and it marks itself.** A menu bar item and a notification

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should-fix · privacy — GDR-0027 does not state that the notification is off by default

Decision 3 reads: "A menu bar item and a notification on the Mac; a widget and a Lock Screen control on iPhone; a complication and a Smart Stack card on the Watch (GDR-0026)." Nothing in the record says the notification is opt-in or where it is turned off. The inventory's row "The word-of-the-day notification ... Off (GDR-0027)" cites this record for a default the record does not contain, and review C2 requires notifications to be off by default and described plainly, with C3 requiring the off switch in the same place.

Add to decision 3: "The notification is off by default; it is turned on, and off again, in Settings, in plain words." Then the inventory's citation is supported.


<h3 id="m13-schema">Entitlements, environments, and a schema that is forever</h3>

<p>Three entitlements: the iCloud container identifiers, <code>icloud-services</code> set to CloudKit, and push notifications if you want to be told about changes rather than polling on launch. A Developer ID app can use iCloud; it needs a provisioning profile embedded in the bundle, which is signing plumbing <code>release.sh</code> already handles (GDR-0010). The App Store builds for iPhone and Watch carry their own.</p>

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should-fix · docs — Module 13 says release.sh already embeds a provisioning profile; it does not

The module states: "it needs a provisioning profile embedded in the bundle, which is signing plumbing release.sh already handles (GDR-0010)." tools/release.sh contains no provisioning-profile step; its only "profile" is the notarytool keychain profile TimbreNotary. GDR-0010 (status: implementation pending) lists the embedded profile as a consequence still to come: "an embedded provisioning profile join release.sh". The module presents pending work as done.

Change to: "which is signing plumbing GDR-0010 assigns to release.sh when sync ships."

general English.
- *Met* detection runs in the polisher's path on the Mac and in practice on
the phone: a whole-word, case-insensitive match against today's word in
text that is already in memory. It adds no storage and no capture.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit · records — "It adds no storage" contradicts decision 3's "The Library stores that it was met and when"

The consequence reads: "Met detection runs in the polisher's path on the Mac and in practice on the phone ... It adds no storage and no capture." Decision 3 says the Library stores the met event and its time. The intent is that no new store is created and no sentence is kept, but the sentence as written is literally false, and the record is immutable after merge.

Reword to: "It adds no new store and no capture: the met event is one more Library event, and the sentence is never kept."


<h3 id="m13-adp">Advanced Data Protection</h3>

<p>By default Apple holds the keys to most iCloud data, including third-party apps' CloudKit data, so that account recovery is possible. With Advanced Data Protection turned on by the user, that data is end-to-end encrypted and Apple cannot read it. Timbre cannot turn that on for anyone; it can say, in the sync setting, that the Library lives in <em>your</em> iCloud, under <em>your</em> protection setting, and link to Apple's explanation. GDR-0010 asked for exactly that copy.</p>

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit · docs — The Advanced Data Protection claim depends on which CloudKit fields the engine uses

The module says: "By default Apple holds the keys to most iCloud data, including third-party apps' CloudKit data ... With Advanced Data Protection turned on by the user, that data is end-to-end encrypted and Apple cannot read it." Apple's end-to-end protection for third-party CloudKit data applies to fields written through CKRecord.encryptedValues and to assets, not to plain record fields; whether the Library's records qualify depends on the engine's ADR, which does not exist yet. The inventory's §3 row makes the same claim, so the copy matches today. Apple's exact scope could not be verified from this tree.

Add "for fields the app stores encrypted" to the sentence, and have the engine's ADR pin that Library records use encrypted fields so the inventory's claim stays true.


<div class="box good">
<p class="box-title">In Timbre</p>
<p><code>LibrarySync</code> is a protocol in <code>TimbreCore</code>; the CloudKit implementation lives where the framework is. Events are immutable records in a custom zone of the private database; merge is a union; edits take the latest; deletions are tombstones. Sync is off by default, described plainly, and syncs the Library and the profile — never a dictation, a capture or a usage count.</p>

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit · docs — The "In Timbre" boxes describe TimbreCore and sync in the present tense before they exist

Module 13's box reads: "LibrarySync is a protocol in TimbreCore ... Sync is off by default, described plainly, and syncs the Library and the profile", and Module 12's box says "strength(of:at:) is pure and lives in TimbreCore with a corpus beside it." packages/ contains only TimbreKit in this tree; the description says the engine is the next pull request. The University is behind the Backstage gate today, so no user reads this, but once it is public the boxes would claim shipped behaviour.

Open each box with "As GDR-0023 designs it (the engine lands with its ADR):", or leave as is if the engine's pull request merges in the same sitting.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant