digraph ReflowArchitecture {
  rankdir=LR;
  graph [fontname="Helvetica", labelloc=t, label="Reflow architecture", fontsize=20, pad=0.2];
  node [shape=box, style="rounded,filled", fillcolor="#f8fafc", color="#475569", fontname="Helvetica"];
  edge [color="#64748b", fontname="Helvetica"];

  user [label="User\nCLI / Python / notebook", fillcolor="#dbeafe"];
  workflow [label="Workflow\nvalidation • dispatch • submission", fillcolor="#e0f2fe"];
  flow [label="Flow\ndefinition layer"];
  params [label="params.py\nParam / Result / RunDir"];
  manifest [label="manifest.py\nManifestCodec\ntyped descriptions", fillcolor="#ede9fe"];
  cache [label="cache.py\nidentity / input / output hashes", fillcolor="#fef3c7"];
  store [label="stores/sqlite.py\nSqliteStore", fillcolor="#dcfce7"];
  records [label="stores/records.py\nRunRecord / TaskInstanceRecord", fillcolor="#dcfce7"];
  executor [label="executors\nSlurmExecutor / LocalExecutor", fillcolor="#fde68a"];
  backend [label="Backend\nSlurm / local process", fillcolor="#fde68a"];
  worker [label="Worker\nexecute task function\nstore output + state", fillcolor="#fce7f3"];
  db [shape=cylinder, label="manifest.db", fillcolor="#ecfccb"];
  files [shape=folder, label="run_dir / outputs", fillcolor="#ecfccb"];

  user -> workflow;
  workflow -> flow;
  workflow -> params;
  workflow -> manifest;
  workflow -> cache;
  workflow -> store;
  store -> records;
  store -> db;
  workflow -> executor;
  executor -> backend;
  backend -> worker;
  worker -> store;
  worker -> files;
  worker -> workflow [label="dispatch pass"];
  cache -> store [label="cache lookup"];
  manifest -> store [label="typed payloads"];
}
