diff --git a/docs/plans/sync-field-meta-overhaul.md b/docs/plans/sync-field-meta-overhaul.md index fd2a67fcb..36c106ba4 100644 --- a/docs/plans/sync-field-meta-overhaul.md +++ b/docs/plans/sync-field-meta-overhaul.md @@ -157,7 +157,17 @@ _Wird befüllt während der Ausführung._ | F4-robust (Endpoint) | `099cac4a0` | F4-Bootstrap robuster gemacht via expliziten Endpoint `POST /api/v1/me/bootstrap-singletons` in mana-auth. Beide Bootstrap-Funktionen (`bootstrapUserSingletons`, `bootstrapSpaceSingletons`) sind jetzt idempotent (existence-check vor INSERT) und geben `boolean` zurück. Endpoint ruft beide auf — userContext für den Caller, kontextDoc für jeden Space, in dem der Caller Member ist. Webapp `(app)/+layout.svelte` callt den Endpoint einmal pro Boot vor `createUnifiedSync`, fire-and-forget am Client. Signup-Hooks (`databaseHooks.user.create.after`, `organizationHooks.afterCreateOrganization`) bleiben als happy-path; Endpoint ist Reconciliation belt-and-suspenders. | | F4-fu (Fallback-Origin) | `ae6a14fb7` | Punkt 4 abgeschwächt: `getOrCreateLocalDoc()` in userContextStore + kontextStore bleibt (Race zwischen "Endpoint provisioniert in mana_sync" und "First-Pull landet in IndexedDB" lässt sich nicht eliminieren — ohne Fallback würden Writes im Race-Window silently in `update(missing-id, diff)` no-ops verloren gehen). Aber: Fallback-Insert ist jetzt in `runAsAsync(makeSystemActor(SYSTEM_BOOTSTRAP), ...)` gewrappt. Neue Konstante `SYSTEM_BOOTSTRAP = 'system:bootstrap'` in `@mana/shared-ai`, mappt via `originFromActor` auf `origin='system'` — strukturell äquivalent zum Server-Bootstrap. Wenn der Server-Pull später ankommt, beide Rows tragen `origin: 'system'`, conflict-gate bleibt ruhig. User-Writes danach stempeln `origin: 'user'` wie immer. | | Punkt 5 (Backend updated_at) | _closed-as-non-orphan_ | Survey aller 17 Backend-Drizzle-Schemas (mana-mail/-media/-auth/-analytics/-research/-events/-subscriptions/-credits + apps/api/{unlisted,website,traces,presi,todo}) zeigt: 3 Spalten (`research.providerConfigs.updatedAt`, `unlisted.snapshots.updatedAt`, `website.customDomains.updatedAt`) werden aktiv vom Service gelesen/geschrieben. Die übrigen 14 sind "AUTO-ONLY" — Drizzle stempelt sie via `defaultNow()` / `$onUpdate(() => new Date())`, kein Service-Code liest sie. Aber: das sind keine Sync-Orphans — F3's Notiz ("pure server-internal columns, not touched") war korrekt. Die AUTO-ONLY Spalten sind DB-Level Audit-Zeitstempel die für Postgres-Forensik nützlich bleiben (`ORDER BY updated_at DESC` für "welche Row zuletzt geändert"). Sie stammen NICHT aus dem alten Sync — sie sind Standard-Drizzle-Convention. Kein Cleanup nötig. | -| Punkt 12 (Integration tests) | _pending_ | 6 neue Integration-Tests im sync.test.ts cross-cutting block: `deriveUpdatedAt` returns max field-meta `at` + handles legacy/null records · Dexie creating-hook stamps `__fieldMeta` + `_updatedAtIndex` · updating-hook bumps nur changed fields + `_updatedAtIndex` · SYSTEM_BOOTSTRAP-stamped local insert produces `origin='system'` · bootstrap-twin race scenario (local SYSTEM_BOOTSTRAP row + server insert) feuert keinen Conflict. 35/35 Tests grün (29 vorher + 6 neue). | +| Punkt 12 (Integration tests) | `275130f8a` | 6 neue Integration-Tests im sync.test.ts cross-cutting block: `deriveUpdatedAt` returns max field-meta `at` + handles legacy/null records · Dexie creating-hook stamps `__fieldMeta` + `_updatedAtIndex` · updating-hook bumps nur changed fields + `_updatedAtIndex` · SYSTEM_BOOTSTRAP-stamped local insert produces `origin='system'` · bootstrap-twin race scenario (local SYSTEM_BOOTSTRAP row + server insert) feuert keinen Conflict. 35/35 Tests grün (29 vorher + 6 neue). | + +## Commit-Log Corrections + +Zwei Commit-Artifacts aus der Multi-Terminal-Sprint-Phase, die nicht ohne destruktiven `git rebase -i` + force-push korrigiert werden können (28+ Commits seit F1 sind bereits gepusht — der Rewrite würde shared history auf `origin/main` umschreiben). Beide sind annotiert via Git-Tag (`git tag -l "sync-field-meta-*"`): + +- **F1 (`7766ea502`) Title misnamed.** Visible commit title: `docs(plans): mark llm-fallback-aliases SHIPPED, add M-by-M commit table`. Realer Inhalt: F1-Implementation der gesamten Field-Meta-Überholung (27 Files inkl. `shared-ai/field-meta.ts`, `database.ts` Hooks, `sync.ts` Wire-Format `{value, at}`, mana-sync Go DB-Schema-Reset, mana-ai Projections, MCP `sync-db.ts`, plus Tests + Plan-Dokument). Ein paralleler Terminal-Session-Commit hat sich beim Stage-und-commit den Titel "geklaut" — der eigentliche llm-fallback-aliases-Doc-Update war ein anderer Commit. Tag: `sync-field-meta-overhaul-F1`. + +- **F3 (`6bb9d77be`) DragType-Beimischung.** Der F3-Commit "feat(sync): F3 — drop updatedAt as a synced data field" enthält eine Ein-Zeilen-Ergänzung in `packages/shared-ui/src/dnd/types.ts`: `+ | 'last'`. Diese Zeile gehört zum Lasts-Modul (`bf3bca268`), nicht zur F3-Sweep-Logik. Sie wurde versehentlich mit dem regex-codemod über Local-prefixed Types erfasst und ins F3-Commit gepullt. Funktional harmlos (DragType-Union ist additiv), aber der Commit enthält damit semantisch zwei unrelated Changes. Tag: `sync-field-meta-overhaul-F3`. + +Beide Tags zeigen das richtige Commit. Ein zukünftiger Reader, der nach dem F1-Commit sucht, findet ihn via `git log --decorate sync-field-meta-overhaul-F1` oder `git show sync-field-meta-overhaul-F1`. Tags lokal; werden nicht automatisch gepusht — `git push --tags` wenn shared-Sichtbarkeit erwünscht. ## F1 — Implementation Notes