ADR-005: Dry-Run Preview

Status

Accepted

Context

Importing content into a personal knowledge base is inherently risky: a misconfigured setting or a changed template could overwrite hundreds of notes. Users need a way to preview what an import will do before any files are actually created, modified, moved, or deleted.

Two approaches were considered:

  1. Diff-on-demand after import — Import first, then show a diff of what changed. This is simple but irreversible.
  2. Dry-run preview before import — Compute the full import plan without writing anything, show the plan, and let the user decide whether to proceed.

Decision

Tetromino implements a full dry-run preview mode that runs the entire sync pipeline — fetching, rendering, diffing, and planning — but skips all vault write operations (vault.create, vault.modify, vault.rename, vault.createBinary).

The dry-run produces a complete SyncResult identical in structure to a real sync, with dryRun: true, which is then displayed in the same SyncSummaryModal used for real imports.

Rationale

  1. Safety first. Users can experiment with new settings (templates, attachment storage, banner fields) and see the exact impact without touching their vault. This builds confidence and reduces support requests.

  2. Determinism makes dry-run trustworthy. Because output is deterministic ([[ADR-003]]), the dry-run diff is guaranteed to match what a real import would do immediately afterward. There is no race condition or hidden state that would cause the preview to diverge from reality.

  3. Shared code path. The dry-run and real import share the same SyncEngine methods. The only difference is a boolean flag (dryRun) that gates the actual vault.* calls. This ensures the preview is not a separate, potentially buggy simulation.

  4. User workflow alignment. Manual import ([[ADR-002]]) means the user is already present and attentive. Offering a preview step before the real action fits naturally into this workflow: preview → review → commit.

How Dry-Run Differs from Commit

Aspect Dry-Run Real Import
vault.create Skipped Executed
vault.modify Skipped Executed
vault.rename Skipped Executed
vault.createBinary Skipped Executed
mapping.lastSyncedAt Not updated Updated to current time
syncRecords Not persisted Updated and saved
Are.na/import-history.md Not written Appended with results
SyncResult.dryRun true false

Despite skipping writes, the dry-run still:

Consequences

Positive

Negative

Implementation Notes


Last updated: 2026-06-26