What claude-obsidian does better
AgriciDaniel/claude-obsidian
spends its single largest module (claude_obsidian/transaction.py, 4,680 lines)
on one contract, stated honestly in its own docstring:
Multi-file filesystem updates cannot be truly atomic on common filesystems.
This module therefore provides a stronger, honest contract: one process-held
mutation lock, precondition hashes, a durable journal, atomic per-file
replace, and deterministic rollback/recovery for the complete operation.
The operator-visible shape is: read every target and record its expected
SHA-256 → merge the whole change into one bundle → transaction inspect →
transaction apply → and, after an interrupted run,
transaction recover [--force-stale-lock]. A changed target is a conflict,
never a silent overwrite.
The gap in omind
omind has the first half and not the second. OmiStore gives us same-dir temp
os.replace, an advisory flock write lock, and version preconditions — all
good. What is missing is the journal and the rollback, so a multi-note
operation interrupted midway leaves partial state with no recovery path.
store.create_and_disable_sources (the omind consolidate --apply write path)
concedes exactly this in its own docstring:
All versions and the target's nonexistence are checked before the first
write [...] A process crash can still leave extra recoverable copies,
never a hard-deleted source.
That is a fair trade — it fails toward keeping data — but "extra recoverable
copies" still means a human has to notice and reconcile by hand. The same shape
applies to mesh merges and any future migration that rewrites many notes.
Proposed scope
Generalize what omind consolidate already prototypes (it has machine-local
JSON plans and an explicit --apply PLAN_ID that revalidates both source
versions) into a store-level primitive:
- A
Transaction that collects (path, expected_version, new_content) writes.
- A durable journal in the state dir recording every target's prior bytes/hash
before the first os.replace.
- Commit under the existing single
write_lock(), atomic per file.
omind recover — replay the journal backwards if an apply did not reach its
commit record; no-op when the journal is clean.
Callers to migrate: create_and_disable_sources, the mesh merge driver, and
omind migrate.
Deliberately not copying
claude-obsidian additionally requires the operator to echo an
approved_plan_sha256 back to --apply. That is right for a product whose
mutations are driven by an LLM against a research vault; for omind it would put
a hash-copying step in front of routine memory writes. Keep plan/apply for
consolidate, keep the journal everywhere, skip the hash handshake.
What claude-obsidian does better
AgriciDaniel/claude-obsidianspends its single largest module (
claude_obsidian/transaction.py, 4,680 lines)on one contract, stated honestly in its own docstring:
The operator-visible shape is: read every target and record its expected
SHA-256 → merge the whole change into one bundle →
transaction inspect→transaction apply→ and, after an interrupted run,transaction recover [--force-stale-lock]. A changed target is a conflict,never a silent overwrite.
The gap in omind
omind has the first half and not the second.
OmiStoregives us same-dir tempos.replace, an advisoryflockwrite lock, and version preconditions — allgood. What is missing is the journal and the rollback, so a multi-note
operation interrupted midway leaves partial state with no recovery path.
store.create_and_disable_sources(theomind consolidate --applywrite path)concedes exactly this in its own docstring:
That is a fair trade — it fails toward keeping data — but "extra recoverable
copies" still means a human has to notice and reconcile by hand. The same shape
applies to mesh merges and any future migration that rewrites many notes.
Proposed scope
Generalize what
omind consolidatealready prototypes (it has machine-localJSON plans and an explicit
--apply PLAN_IDthat revalidates both sourceversions) into a store-level primitive:
Transactionthat collects(path, expected_version, new_content)writes.before the first
os.replace.write_lock(), atomic per file.omind recover— replay the journal backwards if an apply did not reach itscommit record; no-op when the journal is clean.
Callers to migrate:
create_and_disable_sources, the mesh merge driver, andomind migrate.Deliberately not copying
claude-obsidian additionally requires the operator to echo an
approved_plan_sha256back to--apply. That is right for a product whosemutations are driven by an LLM against a research vault; for omind it would put
a hash-copying step in front of routine memory writes. Keep plan/apply for
consolidate, keep the journal everywhere, skip the hash handshake.