ADR-0005: Concurrency-Hardened Storage and Automated Schema Migration
Status
Accepted
Context
As PALEE vaults grow in complexity, notes may be created outside the CLI (by Obsidian plugins, manual text editing, or external sync engines) without the canonical palee_schema: 1 version attribute. Simultaneously, multi-process CLI operations, background automated tasks, and async command pipelines create high-frequency write contention where intra-process temporary file collisions and unhandled exception traces could degrade reliability.
Decision
We implemented a multi-layered storage hardening and schema migration strategy:
Entropy-Augmented Collision-Proof Temporary Files:
- In
atomicWrite(), temporary filenames are constructed using${targetPath}.tmp.${process.pid}.${crypto.randomBytes(4).toString('hex')}. - Eliminates intra-process race conditions where concurrent promises in the same process instance write to overlapping temporary filenames.
- Unlinks lingering temporary files in
finallyblocks on any write, fsync, or rename exception.
- In
Automated OCC Schema Migration (
palee migrate --fix):- Extends the
migrateCLI command with an automatic--fixflag. - Discovers notes containing a valid
palee_idbut missingpalee_schema. - Computes the pre-write SHA-256 fingerprint and applies
atomicWrite()with optimistic concurrency control (expectedFingerprint) to upgrade frontmatter topalee_schema: 1safely. - Tracks failed file paths in the validation report to guarantee atomic convergence.
- Extends the
CST (Concrete Syntax Tree) YAML Document Frontmatter Serializer:
- Replaced ad-hoc JSON array serialization with unified
yamlpackageDocumentCST formatting. - Ensures newly generated frontmatter arrays (
depends_on,tags) serialize as standard YAML block sequences (- item) instead of bracketed strings.
- Replaced ad-hoc JSON array serialization with unified
Timezone-Safe Local Calendar SM-2 Arithmetic:
- Decomposes
YYYY-MM-DDstrings into year, month, and day components and uses local date arithmetic with adue.setFullYear(year)guard to eliminate 1900-offset bugs for years0000–0099and negative-UTC-offset day shifts.
- Decomposes
Consequences
- Positive:
- Vault notes without schema versions can be repaired non-destructively in a single command (
palee migrate --fix). - High-concurrency async operations within a single Node.js runtime run without temp-file overwrites.
- Frontmatter formatting remains clean, readable, and 100% compliant with standard YAML parsers.
- Review intervals and due dates compute deterministically regardless of local timezone or historical dates.
- Vault notes without schema versions can be repaired non-destructively in a single command (
- Negative / Tradeoffs:
- Adds a small cryptographic entropy generation step per atomic write.
Alternatives Considered
- Implicit On-the-Fly Schema Upgrades during All Read Commands:
- Why Rejected: Automatic mutation on reading violates the read-only idempotency invariant of
next,plan, andprogresscommands.
- Why Rejected: Automatic mutation on reading violates the read-only idempotency invariant of
- Global Single-Threaded Write Mutex:
- Why Rejected: Unnecessarily serializes distinct file writes across separate subdirectories, degrading throughput on large vault batches.
