{
  "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
    }
  ]
}