MarkdownDB¶
Frozen legacy Markdown-to-SQLite reconciliation abstraction retained for pre-seal compatibility and migration inspection.
Details¶
MarkdownDB is Work Buddy's former Markdown-canonical two-way synchronisation abstraction. It lives in work_buddy/markdown_db/ and was extracted from the bespoke task reconciler in obsidian/tasks/sync.py. It is no longer an approved authority pattern.
The model¶
In the legacy model, Markdown was canonical and SQLite was a queryable projection. In-code writes touched both surfaces and periodic reconciliation consumed out-of-band file edits. Authority seals now prevent those paths from running for migrated domains. Native SQLite revisions and explicit Co-work bindings provide one writable body per role.
Subclassing¶
A subclass declares a list of FieldSpecs (one per reconcilable field), table_name / pk_column, and implements parse_all_from_markdown, write_entity_to_markdown, markdown_path_for. The base class supplies orphan handling, the generic per-field drift loop, conflict resolution, dual-surface mutation, and materialize_from_store (the one-time store->markdown flip). FieldSpec carries optional hooks for shapes that are not a clean value mirror: equivalent (custom in-sync predicate — the task checkbox is a lossy projection of the 5-valued state) and extra_store_fields (derived columns written in lockstep — deadline_date keeps has_deadline consistent).
Conflict resolution¶
Pluggable Resolver. Default lww_markdown_wins: newer timestamp wins; on a tie or missing timestamps the markdown surface wins. Isolating resolution behind one callable is the cheap CRDT-smoothing move — a richer resolver is a one-symbol swap.
The lww_meta sidecar¶
WriteProvenance (actor as an OR-set frozenset honestly encoding partial observability; open-vocabulary process / from_surface) is stamped per write event into an append-only lww_meta table. SqliteLwwLog persists it INSIDE each entity's own DB so it travels with the architecture/backups tarball. The table is genuinely append-only (autoincrement id PK) — it serves LWW today and is replayable as an op log if a CRDT resolver is ever introduced. NullLwwLog (the default) makes a MarkdownDB behave as pure markdown-canonical with no LWW history.
Concrete subclasses¶
TaskMarkdownDB (obsidian/tasks/markdown_db.py) describes the retired task
master-list projection. ProjectMarkdownDB (projects/markdown_db.py) parses
the legacy one-file-per-project layout for pre-seal import/reconciliation.
Neither is a native product authority, and their old vault-directory settings
are not setup requirements for database-only domains.
Mass-delete circuit-breaker¶
"Markdown is canonical" means a store row absent from the parse is soft-deleted — correct only if the parse is trustworthy. reconcile_drift refuses any single-pass orphan-delete batch larger than max(20, 50% of the live store), so a degraded read (a bridge blink, a partial/truncated read, a parser/ID-scheme regression) can never silently wipe the store. A refusal skips ONLY the delete loop (creates + field-drift still run), sets ReconcileReport.aborted_bulk_delete = (would_delete, live_count), logs at ERROR, and surfaces as a task_sync status of "degraded" (not the healthy "ok"/"synced"). The next reconcile retries with hopefully-sane input.
Status¶
Frozen compatibility code. Native Task authority does not call
TaskMarkdownDB. Projects may use ProjectMarkdownDB only before their
SQLite authority seal; the authority-aware wrapper returns disabled with
zero writes after seal. Scheduled reconciliation is retired once the live
cohort is certified. The lww_meta tables remain historical audit data and
travel with their domain backups, but they do not authorize dual writes.