#342: a settings change in the shadow vault was written to the local
`.obsidian/app.json` but never reached the remote, so the next
session's pull found nothing and the change "evaporated". Only the
remote→local half (pullSharedObsidianConfig) existed.
- ShadowVaultBootstrap.pushSharedObsidianConfig: symmetric to pull —
reads each local shared file, JSON-validates (a half-written file
must not clobber a healthy remote copy), writes verbatim to remote;
{pushed,skipped,errored} so a failed push surfaces instead of
silently losing settings.
- SharedConfigWatcher: watches the shadow vault's local config dir and
debounce-pushes divergent shared files. Catches BOTH adapter and
direct-fs writes (the shadow `.obsidian/` is local disk). Echo-
suppressed via markSynced so the pull's own writes / identical
re-saves don't bounce back; a failed push is retried (not masked
as synced).
- main.ts: after the connect pull, seed markSynced with the pulled
bytes, start the watcher (flush = pushSharedObsidianConfig via the
patched adapter, Notice on errored); stop it on disconnect and on
reconnect-failed.
Tests: pushSharedObsidianConfig (verbatim / absent-skip / invalid-
JSON-not-pushed / write-fail-errored) + SharedConfigWatcher (debounce,
echo-suppress, diverge-pushes, burst-coalesce, non-shared-ignored,
null-filename, stop-cancels, failed-push-retried). Full suite 1059
passed/1 skipped; typecheck + lint clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>