SPEC-0007: Onboarding (doctor, export, sync)
- Status: Accepted
- Date: 2026-06-28
- Capability: onboarding
- Source packages:
internal/cli(doctor.go,export.go,sync.go),internal/store(OpenReadOnly),internal/ingest,internal/imessage,internal/imageconv,internal/embed,internal/facts - Related ADRs: 📝 ADR-0015 (onboarding), 📝 ADR-0010 (privacy posture), 📝 ADR-0005 (iMessage), 📝 ADR-0014 (image converter)
Overview
Onboarding turns a fresh install into a populated, browsable archive with minimal
friction: a read-only doctor that diagnoses setup, an export that orchestrates
the upstream exporters with correct flags, and an all-in-one sync. Orchestration
runs the user's own local tools (no secrets stored, no network egress beyond the
single configured LLM endpoint); see 📝 ADR-0015 for the posture decision.
Requirements
REQ-0007-001: doctor read-only diagnostics
doctor MUST report setup health WITHOUT creating or modifying anything: data_dir
- DB presence and on-disk schema version (opened read-only, never migrated),
archive-root validity (including the "pointed at export/ itself" mistake),
attachment health (flagging absolute/out-of-archive paths with the copy-mode
re-export hint), image-converter presence, un-embedded count, and whether the
upstream exporters are on PATH. It MUST make no network calls except an opt-in
--check-llmTCP probe to the configuredllm.base_url. Exit non-zero only when a check fails.
Scenario: typo'd data_dir is reported, not created
- Given
--data-dirpoints at a nonexistent path - When
doctorruns - Then it reports the dir doesn't exist and creates nothing on disk.
(Implemented in PR #43.)
REQ-0007-002: export orchestrates the upstream exporters
export MUST run signal-export and/or imessage-exporter into the configured
archive roots with correct flags — iMessage MUST use copy mode (-c clone or
equivalent) so attachments are bundled. Each tool MUST be located on PATH or via
an explicit override (--signal-export-bin / --imessage-exporter-bin, or
config); a tool that is required but absent MUST be a clear error naming the
missing tool and how to install it. A --skip-on-error flag MUST let a failing
source be logged and skipped instead of aborting the run. msgbrowse MUST NOT store
secrets or read the Keychain itself (the invoked tool does, with user consent).
Scenario: missing exporter is a clear error
- Given
imessage-exporteris not on PATH and no--imessage-exporter-bin - When
exportruns for iMessage - Then it errors naming the missing tool + install hint (or, with
--skip-on-error, warns and continues with the other source).
Scenario: iMessage export bundles attachments
- Given
exportrunsimessage-exporter - Then it passes copy mode so attachment files land under the archive (avoiding the reference-only/absolute-path trap).
REQ-0007-003: sync end-to-end pipeline
sync MUST chain export → import (both sources) → media transcode → embed →
facts, honoring --skip-on-error and per-stage skip flags (e.g. --no-export,
--no-embed, --no-facts). LLM-dependent stages (embed, facts) MUST warn and
continue when no endpoint is reachable rather than failing the whole run. Each
stage MUST reuse the existing command logic (ingest/imessage/imageconv/embed/facts),
not reimplement it.
Scenario: one-command refresh
- Given configured archive roots and exporters on PATH
- When
syncruns - Then archives are re-exported, imported, HEIC transcoded, and (if an LLM is reachable) embeddings + facts updated — in one command.
Scenario: degrades without an LLM
- Given no reachable
llm.base_url - When
syncruns - Then export/import/media complete and embed/facts are skipped with a warning, exit success.