vault_sync_daemon: mirror full /vault structure forward, not just JD-shaped folders

Forward (/vault->/data) mirroring was gated to only AREA/CATEGORY/ID-shaped
names, so arbitrary sub-structure Ryan creates inside an ID (e.g. dated trip
folders under F.21.21) never propagated to /data. Removed the name-shape
gate; the existing parent-must-exist check is sufficient safety, plus an
explicit '0 System area' exclusion since that tree has no /data root at all.
This commit is contained in:
Hermes
2026-09-19 13:40:56 -04:00
parent d89aeb7d26
commit 90fbc240af
+20 -8
View File
@@ -167,11 +167,24 @@ def _under_data_exempt(rel_path):
def handle_vault_created(path): def handle_vault_created(path):
""" """
A new AREA/CATEGORY/ID-shaped folder appeared in /vault (e.g. created A new folder appeared in /vault (e.g. created via Obsidian, not the
via Obsidian, not the `vault` CLI) with no /data counterpart yet. `vault` CLI). Mirror it: create the matching empty folder in /data.
Mirror it: create the matching empty folder in /data. This is the This is the forward-create leg that was missing — only move/delete
forward-create leg that was missing — only move/delete were wired up were wired up originally, so a brand-new folder (like "R.6 Test")
originally, so a brand-new folder (like "R.6 Test") never propagated. never propagated.
Full 1:1 structural mirror, NOT limited to JD-shaped (AREA/CATEGORY/ID)
names (confirmed with Ryan 2026-09-19): once inside an ID's territory
Ryan organizes arbitrary sub-structure (e.g. dated trip folders under
an ID like "F.21.21 All short trips"), and expects /data to match that
structure too, not just the JD skeleton. The only safety gate is that
the /data PARENT must already exist — this naturally still excludes
"0 System area" (which has no /data root at all, by design) and any
other genuinely orphaned branch, without needing a name-shape check.
Reverse (/data -> /vault) intentionally keeps its stricter JD-shape-only
gate (see handle_data_created) — /data is the hand-sorted blob side
with far more incidental subfolders, so stubbing a /vault note for
every one of those would be noise; there's no such asymmetry forward.
""" """
if not os.path.isdir(path): if not os.path.isdir(path):
return return
@@ -180,9 +193,8 @@ def handle_vault_created(path):
if not _debounced("vault_created", path): if not _debounced("vault_created", path):
return return
rel = os.path.relpath(path, VAULT) rel = os.path.relpath(path, VAULT)
base = os.path.basename(path) if rel.split(os.sep)[0] == vl.SYSTEM_META:
if not (ID_RE.match(base) or CAT_RE.match(base) or vl.AREA_RE.match(base)): return # "0 System area" never mirrors to /data, by design
return # not a JD-shaped folder — ignore (e.g. "Documents" subfolder)
data_path = os.path.join(DATA, rel) data_path = os.path.join(DATA, rel)
if os.path.isdir(data_path): if os.path.isdir(data_path):
return # already mirrored (duplicate event or pre-existing) return # already mirrored (duplicate event or pre-existing)