diff --git a/docs/archify/obsidian-sorter.architecture.json b/docs/archify/obsidian-sorter.architecture.json new file mode 100644 index 0000000..9d99866 --- /dev/null +++ b/docs/archify/obsidian-sorter.architecture.json @@ -0,0 +1,289 @@ +{ + "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 + } + ] +} \ No newline at end of file diff --git a/docs/diagrams/obsidian-sorter-flow.png b/docs/diagrams/obsidian-sorter-flow.png new file mode 100644 index 0000000..a044b34 Binary files /dev/null and b/docs/diagrams/obsidian-sorter-flow.png differ diff --git a/docs/obsidian-sorter-flow.mmd b/docs/obsidian-sorter-flow.mmd new file mode 100644 index 0000000..1f5a89f --- /dev/null +++ b/docs/obsidian-sorter-flow.mmd @@ -0,0 +1,16 @@ +flowchart LR + A["Sam writes a note"] --> B["010 inbox/"] + B --> C{"Watcher
systemd user service
polls every 10s"} + C --> D["Tier 1 - rules
folder + keyword hints
user tags win"] + D -->|"confident"| F["Proposal"] + D -->|"unsure"| E["Tier 2 - TypeSafe JEV
bucket + folder + tags"] + E --> F + F --> G["Proposal written
into the note frontmatter"] + G --> H["Sam reviews in Obsidian"] + H -->|"ticks approved"| I["Writer"] + H -->|"edits folder first"| G + I --> J["Destination folder"] + I --> K["Table of Contents"] + + click C "https://maps.lab.audasmedia.com.au/obsidian-sorter/docs/obsidian-sorter-map.html" "View Archify Map" + click E "https://docs.typesafe.ai" "TypeSafe JEV documentation" diff --git a/docs/obsidian-sorter-map.html b/docs/obsidian-sorter-map.html new file mode 100644 index 0000000..197886e --- /dev/null +++ b/docs/obsidian-sorter-map.html @@ -0,0 +1,13678 @@ + + + + + + + Obsidian Sorter — Note Filing Pipeline Diagram + + + + + + + + + + + +
+ +
+
+
+

Obsidian Sorter — Note Filing Pipeline

+
+
+ + + + + + +
+ + Obsidian Sorter — Note Filing Pipeline + A architecture diagram generated by Archify. + + + + + + + + + + + + + + + + + + + + + + + + + sorter code — zero third-party dependencies + + + + + + + + + + + + + + + + Sam · writes a note · Architecture component + + + + Sam + writes a note + + + + 010 inbox/ · unsorted notes · Architecture component + + + + 010 inbox/ + unsorted notes + + + + Watcher · systemd · 10s poll · sorter code — zero third-party dependencies · watch.py + + + + Watcher + systemd · 10s poll + watch.py + + + + Tier 1 — Rules · folder + keyword hints · sorter code — zero third-party dependencies · classify.py + + + + Tier 1 — Rules + folder + keyword hints + classify.py + + + + TypeSafe JEV · bucket · folder · tags · Architecture component · remote API + + + + TypeSafe JEV + bucket · folder · tags + remote API + + + + Proposal · written into the note · Architecture component · frontmatter + + + + Proposal + written into the note + frontmatter + + + + Obsidian · owner ticks approved · Architecture component · human gate + + + + Obsidian + owner ticks approved + human gate + + + + Writer · atomic move · sorter code — zero third-party dependencies · writer.py + + + + Writer + atomic move + writer.py + + + + Destination · type follows folder · Architecture component + + + + Destination + type follows folder + + + + Table of Contents · index updated · Architecture component + + + + Table of Contents + index updated + + + + + + save + + + + poll + + + + classify + + + + confident + + + + unsure + + + + verdict + tags + + + + review or edit folder + + + + approved + + + + file + + + + index + + + + + Legend + + + Backend + + + + Database + + + + Cloud + + + + External + + + +

+ + + + + + + + +
+ + +
+ +
+ +
+ + + +