{ "schema_version": 1, "diagram_type": "architecture", "meta": { "title": "Obsidian Sorter \u2014 Note Filing Pipeline", "output": "docs/obsidian-sorter-map.html", "visual_preset": "blueprint", "animation": "trace", "quality_profile": "showcase", "views": [ { "id": "intake", "label": "Intake", "focus": [ "author", "inbox", "watcher" ], "note": "A note lands in the inbox and the watcher picks it up." }, { "id": "classification", "label": "Classification", "focus": [ "watcher", "rules", "jev", "proposal" ], "note": "Rules decide first; anything unclear escalates to the JEV model." }, { "id": "approval", "label": "Human approval", "focus": [ "proposal", "obsidian", "writer" ], "note": "Nothing moves until the owner ticks the checkbox." }, { "id": "filing", "label": "Filing", "focus": [ "writer", "folder", "toc" ], "note": "The note moves to its folder and the index is updated." } ] }, "components": [ { "id": "author", "type": "external", "label": "Sam", "sublabel": "writes a note", "pos": [ 40, 340 ], "size": [ 120, 60 ] }, { "id": "inbox", "type": "database", "label": "010 inbox/", "sublabel": "unsorted notes", "pos": [ 220, 340 ], "size": [ 130, 60 ] }, { "id": "watcher", "type": "backend", "label": "Watcher", "sublabel": "systemd \u00b7 10s poll", "pos": [ 410, 340 ], "size": [ 140, 62 ], "tag": "watch.py" }, { "id": "rules", "type": "backend", "label": "Tier 1 \u2014 Rules", "sublabel": "folder + keyword hints", "pos": [ 620, 170 ], "size": [ 160, 62 ], "tag": "classify.py" }, { "id": "jev", "type": "cloud", "label": "TypeSafe JEV", "sublabel": "bucket \u00b7 folder \u00b7 tags", "pos": [ 620, 500 ], "size": [ 160, 62 ], "tag": "remote API" }, { "id": "proposal", "type": "database", "label": "Proposal", "sublabel": "written into the note", "pos": [ 850, 340 ], "size": [ 150, 62 ], "tag": "frontmatter" }, { "id": "obsidian", "type": "external", "label": "Obsidian", "sublabel": "owner ticks approved", "pos": [ 1060, 340 ], "size": [ 150, 62 ], "tag": "human gate" }, { "id": "writer", "type": "backend", "label": "Writer", "sublabel": "atomic move", "pos": [ 1270, 340 ], "size": [ 150, 62 ], "tag": "writer.py" }, { "id": "folder", "type": "database", "label": "Destination", "sublabel": "type follows folder", "pos": [ 1490, 220 ], "size": [ 150, 62 ] }, { "id": "toc", "type": "database", "label": "Table of Contents", "sublabel": "index updated", "pos": [ 1490, 460 ], "size": [ 150, 62 ] } ], "boundaries": [ { "kind": "region", "label": "sorter code \u2014 zero third-party dependencies", "wraps": [ "watcher", "rules", "writer" ], "pad": 26 } ], "connections": [ { "id": "save", "from": "author", "to": "inbox", "label": "save", "labelDy": -22 }, { "id": "poll", "from": "inbox", "to": "watcher", "label": "poll", "labelDy": -22 }, { "id": "classify", "from": "watcher", "to": "rules", "label": "classify", "labelDx": -30 }, { "id": "confident", "from": "rules", "to": "proposal", "label": "confident", "labelDx": 20 }, { "id": "unsure", "from": "rules", "to": "jev", "label": "unsure", "labelAt": [ 700, 250 ] }, { "id": "verdict", "from": "jev", "to": "proposal", "label": "verdict + tags", "labelDx": 20 }, { "id": "review", "from": "proposal", "to": "obsidian", "label": "review or edit folder", "labelDy": -24 }, { "id": "approved", "from": "obsidian", "to": "writer", "label": "approved", "labelDy": -22 }, { "id": "file", "from": "writer", "to": "folder", "label": "file", "labelDx": 24 }, { "id": "index", "from": "writer", "to": "toc", "label": "index", "labelDx": 24 } ] }