{
  "nodes": [
    {
      "id": "methodology-rto",
      "label": "RTO ops",
      "sub": "precedence 1",
      "type": "sot",
      "group": "methodology",
      "path": "methodology/Documentation/Real_Time_Operations/",
      "tooltip": "Precedence 1. Live ops notes, tweet archive, ranking/relevance worked examples.",
      "x": 40,
      "y": 40,
      "w": 120,
      "h": 48
    },
    {
      "id": "methodology-sma-outfits",
      "label": "SMA-outfits",
      "sub": "precedence 2",
      "type": "sot",
      "group": "methodology",
      "path": "methodology/SMA-outfits/README.md",
      "tooltip": "Precedence 2. Outfit period tables, Systems, parameter limit 1–999, executive definitions.",
      "x": 180,
      "y": 40,
      "w": 120,
      "h": 48
    },
    {
      "id": "methodology-unfairmarket",
      "label": "UnfairMarket",
      "sub": "study only",
      "type": "sot",
      "group": "methodology",
      "path": "methodology/Documentation/UnfairMarket_Method/",
      "tooltip": "Precedence 3. External reverse-engineering study only. Not ops SoT.",
      "x": 320,
      "y": 40,
      "w": 120,
      "h": 48
    },
    {
      "id": "methodology",
      "label": "methodology/",
      "sub": "SoT corpus",
      "type": "sot",
      "group": "methodology",
      "path": "methodology/",
      "tooltip": "Single source of truth for outfits, ranking, penny, timeframes, reporting grain. Methodology wins over code on conflict.",
      "x": 160,
      "y": 110,
      "w": 160,
      "h": 52
    },
    {
      "id": "shared-outfits",
      "label": "outfits.txt",
      "sub": "shared/",
      "type": "runtime_config",
      "group": "shared",
      "path": "shared/outfits.txt",
      "tooltip": "Runtime outfit ladders: NAME|p1,p2,…. Loaded by wick-hasher and csv-report. Manual promote only.",
      "x": 80,
      "y": 200,
      "w": 130,
      "h": 48
    },
    {
      "id": "shared-universe",
      "label": "universe_symbols",
      "sub": "shared/",
      "type": "runtime_config",
      "group": "shared",
      "path": "shared/universe_symbols.txt",
      "tooltip": "Scan/fetch universe. Primary consumer: tick-fetch. Not used by csv-report aggregation.",
      "x": 230,
      "y": 200,
      "w": 140,
      "h": 48
    },
    {
      "id": "webull-api",
      "label": "Webull API",
      "sub": "external",
      "type": "external",
      "group": "external",
      "path": null,
      "tooltip": "Public HTTP search + batched realtime quotes via system curl. Close-driven fields only; no O/H/L into ticks.",
      "x": 420,
      "y": 200,
      "w": 120,
      "h": 48
    },
    {
      "id": "influx-optional",
      "label": "InfluxDB v2",
      "sub": "optional",
      "type": "external",
      "group": "external",
      "path": null,
      "tooltip": "Optional OHLC source for wick-hasher only. Not required for default CSV pipeline.",
      "x": 560,
      "y": 200,
      "w": 120,
      "h": 48
    },
    {
      "id": "tick-fetch",
      "label": "tick-fetch",
      "sub": "service · C11",
      "type": "service",
      "group": "tick-fetch",
      "path": "tick-fetch/",
      "tooltip": "Poll Webull → append-only tick + multi-TF bar CSVs. Single writer. Optional EOD spawn of csv-report. No Influx writes.",
      "x": 420,
      "y": 290,
      "w": 140,
      "h": 52
    },
    {
      "id": "tf-universe",
      "label": "universe",
      "sub": "module",
      "type": "module",
      "group": "tick-fetch",
      "path": "tick-fetch/src/universe.c",
      "tooltip": "Load, uppercase, safe-gate, dedupe tickers.",
      "x": 280,
      "y": 290,
      "w": 110,
      "h": 44
    },
    {
      "id": "tf-webull",
      "label": "webull",
      "sub": "curl HTTP",
      "type": "module",
      "group": "tick-fetch",
      "path": "tick-fetch/src/webull.c",
      "tooltip": "Resolve symbols; batch realtime quotes (80/batch).",
      "x": 420,
      "y": 365,
      "w": 100,
      "h": 44
    },
    {
      "id": "tf-quote",
      "label": "quote",
      "sub": "JSON parse",
      "type": "module",
      "group": "tick-fetch",
      "path": "tick-fetch/src/quote.c",
      "tooltip": "Parse close/volume/chg/pct. No O/H/L passthrough.",
      "x": 540,
      "y": 365,
      "w": 100,
      "h": 44
    },
    {
      "id": "tf-spike",
      "label": "spike",
      "sub": "30% gate",
      "type": "module",
      "group": "tick-fetch",
      "path": "tick-fetch/src/spike.c",
      "tooltip": "Reject prints >30% vs prior accepted close (5 min anchor).",
      "x": 660,
      "y": 365,
      "w": 100,
      "h": 44
    },
    {
      "id": "tf-market-hours",
      "label": "market_hours",
      "sub": "RTH / ET",
      "type": "module",
      "group": "tick-fetch",
      "path": "tick-fetch/src/market_hours.c",
      "tooltip": "RTH 09:30–16:00 ET; session-anchored bar floors and stamps.",
      "x": 280,
      "y": 365,
      "w": 110,
      "h": 44
    },
    {
      "id": "tf-ohlc-agg",
      "label": "ohlc_agg",
      "sub": "17 TFs",
      "type": "module",
      "group": "tick-fetch",
      "path": "tick-fetch/src/ohlc_agg.c",
      "tooltip": "Close-driven OHLC bars for default 17 timeframes. Emit on bucket roll / flush.",
      "x": 540,
      "y": 430,
      "w": 110,
      "h": 44
    },
    {
      "id": "tf-csv-store",
      "label": "csv_store",
      "sub": "append-only",
      "type": "module",
      "group": "tick-fetch",
      "path": "tick-fetch/src/csv_store.c",
      "tooltip": "Append complete \\n lines; fflush each cycle. Multi-reader safe.",
      "x": 660,
      "y": 430,
      "w": 110,
      "h": 44
    },
    {
      "id": "data-ticks",
      "label": "data/ticks/",
      "sub": "CSV",
      "type": "data",
      "group": "data",
      "path": "data/ticks/",
      "tooltip": "ts_ms,ticker,close,volume,chg,pct — day files YYYY-MM-DD.csv (ET).",
      "x": 800,
      "y": 365,
      "w": 120,
      "h": 48
    },
    {
      "id": "data-bars",
      "label": "data/bars/{tf}/",
      "sub": "OHLC CSV",
      "type": "data",
      "group": "data",
      "path": "data/bars/",
      "tooltip": "ticker,timeframe,ts_ms,open,high,low,close — shared by hasher and report.",
      "x": 800,
      "y": 430,
      "w": 130,
      "h": 48
    },
    {
      "id": "wick-hasher",
      "label": "wick-hasher",
      "sub": "service · C11",
      "type": "service",
      "group": "wick-hasher",
      "path": "wick-hasher/",
      "tooltip": "Wick H/L penny SMA hits, four-tuple keys, dens_n live board / report. Default: CSV bars-dir.",
      "x": 980,
      "y": 290,
      "w": 140,
      "h": 52
    },
    {
      "id": "wh-outfits",
      "label": "outfits",
      "sub": "load ladders",
      "type": "module",
      "group": "wick-hasher",
      "path": "wick-hasher/src/outfits.c",
      "tooltip": "Parse NAME|p1,p2,…; period→outfit map for multi-outfit credit.",
      "x": 960,
      "y": 365,
      "w": 100,
      "h": 44
    },
    {
      "id": "wh-csv-bars",
      "label": "csv_bars",
      "sub": "load / tail",
      "type": "module",
      "group": "wick-hasher",
      "path": "wick-hasher/src/csv_bars.c",
      "tooltip": "Load bars tree; incomplete-line skip; drop active bar.",
      "x": 1080,
      "y": 365,
      "w": 100,
      "h": 44
    },
    {
      "id": "wh-influx",
      "label": "influx",
      "sub": "optional",
      "type": "module",
      "group": "wick-hasher",
      "path": "wick-hasher/src/influx.c",
      "tooltip": "Flux multi-TF fetch via curl. Read-only.",
      "x": 1200,
      "y": 365,
      "w": 100,
      "h": 44
    },
    {
      "id": "wh-sma",
      "label": "sma",
      "sub": "closes",
      "type": "module",
      "group": "wick-hasher",
      "path": "wick-hasher/src/sma.c",
      "tooltip": "Rolling SMA of closes; min_periods=period; 1–999.",
      "x": 960,
      "y": 430,
      "w": 90,
      "h": 44
    },
    {
      "id": "wh-penny",
      "label": "penny",
      "sub": "banker's",
      "type": "module",
      "group": "wick-hasher",
      "path": "wick-hasher/src/penny.c",
      "tooltip": "Banker's half-to-even equality for hit and side geometry.",
      "x": 1065,
      "y": 430,
      "w": 90,
      "h": 44
    },
    {
      "id": "wh-hits",
      "label": "hits",
      "sub": "H/L entry",
      "type": "module",
      "group": "wick-hasher",
      "path": "wick-hasher/src/hits.c",
      "tooltip": "Wick entry on H/L; classify_side LONG/SHORT; path override for ranking.",
      "x": 1170,
      "y": 430,
      "w": 90,
      "h": 44
    },
    {
      "id": "wh-hash-key",
      "label": "hash_key",
      "sub": "4-tuple",
      "type": "module",
      "group": "wick-hasher",
      "path": "wick-hasher/src/hash_key.c",
      "tooltip": "Format [periods][tf][equity][SIDE price SMA N]. First leaf = periods.",
      "x": 1000,
      "y": 500,
      "w": 100,
      "h": 44
    },
    {
      "id": "wh-rank",
      "label": "rank",
      "sub": "dens_n",
      "type": "module",
      "group": "wick-hasher",
      "path": "wick-hasher/src/rank.c",
      "tooltip": "Frequency + dens_n board sort (dens first, then TF/recency/score).",
      "x": 1120,
      "y": 500,
      "w": 100,
      "h": 44
    },
    {
      "id": "wh-board",
      "label": "live board",
      "sub": "terminal",
      "type": "output",
      "group": "wick-hasher",
      "path": "wick-hasher/src/main.c",
      "tooltip": "Terminal dens_n board (live) or one-shot report lines.",
      "x": 1240,
      "y": 500,
      "w": 110,
      "h": 44
    },
    {
      "id": "csv-report",
      "label": "csv-report",
      "sub": "service · C11",
      "type": "service",
      "group": "csv-report",
      "path": "csv-report/",
      "tooltip": "Closing-hour dens_n HTML from bar CSVs. Outfit bias + ticker ranking implemented; Systems/magnetized placeholders.",
      "x": 980,
      "y": 590,
      "w": 140,
      "h": 52
    },
    {
      "id": "cr-window",
      "label": "report_window",
      "sub": "15–16 ET",
      "type": "module",
      "group": "csv-report",
      "path": "csv-report/src/report_window.c",
      "tooltip": "Half-open [15:00, 16:00) ET → UTC ms.",
      "x": 860,
      "y": 665,
      "w": 110,
      "h": 44
    },
    {
      "id": "cr-csv-bars",
      "label": "csv_bars",
      "sub": "load tree",
      "type": "module",
      "group": "csv-report",
      "path": "csv-report/src/csv_bars.c",
      "tooltip": "Load bars; drop active; IXIC cleanup.",
      "x": 990,
      "y": 665,
      "w": 100,
      "h": 44
    },
    {
      "id": "cr-outfits",
      "label": "outfits",
      "sub": "load",
      "type": "module",
      "group": "csv-report",
      "path": "csv-report/src/outfits.c",
      "tooltip": "Load shared outfits for expand map.",
      "x": 1110,
      "y": 665,
      "w": 90,
      "h": 44
    },
    {
      "id": "cr-hits",
      "label": "report_hits",
      "sub": "touches",
      "type": "module",
      "group": "csv-report",
      "path": "csv-report/src/report_hits.c",
      "tooltip": "Window-overlap SMA touches; side; dens; outfit expand.",
      "x": 920,
      "y": 735,
      "w": 110,
      "h": 44
    },
    {
      "id": "cr-agg",
      "label": "report_agg",
      "sub": "TOTAL boards",
      "type": "module",
      "group": "csv-report",
      "path": "csv-report/src/report_agg.c",
      "tooltip": "Top-20 outfit bias + ticker ranking (TOTAL desc, dens_n tie-break).",
      "x": 1050,
      "y": 735,
      "w": 110,
      "h": 44
    },
    {
      "id": "cr-templates",
      "label": "templates/",
      "sub": "HTML shells",
      "type": "asset",
      "group": "csv-report",
      "path": "csv-report/templates/",
      "tooltip": "base.html + section templates for report layout.",
      "x": 860,
      "y": 805,
      "w": 110,
      "h": 44
    },
    {
      "id": "cr-html",
      "label": "report_html",
      "sub": "render",
      "type": "module",
      "group": "csv-report",
      "path": "csv-report/src/report_html.c",
      "tooltip": "Fill {{placeholders}} into full HTML document.",
      "x": 990,
      "y": 805,
      "w": 110,
      "h": 44
    },
    {
      "id": "reports-html",
      "label": "reports/*.html",
      "sub": "output",
      "type": "output",
      "group": "output",
      "path": "reports/",
      "tooltip": "HTML dens_n scoreboard. Prefer YYYY-MM-DD-csv.html when coexisting with Python reports.",
      "x": 1120,
      "y": 805,
      "w": 130,
      "h": 48
    },
    {
      "id": "ci-fixtures",
      "label": "ci/fixtures",
      "sub": "synthetic bars",
      "type": "data",
      "group": "ci",
      "path": "ci/fixtures/bars/",
      "tooltip": "Committed synthetic bars for offline e2e.",
      "x": 40,
      "y": 520,
      "w": 120,
      "h": 48
    },
    {
      "id": "ci-e2e",
      "label": "ci_e2e.sh",
      "sub": "offline e2e",
      "type": "script",
      "group": "ci",
      "path": "scripts/ci_e2e.sh",
      "tooltip": "Run wick-hasher + csv-report on fixtures → reports/ci-e2e.html.",
      "x": 40,
      "y": 590,
      "w": 120,
      "h": 48
    },
    {
      "id": "launchers",
      "label": "root launchers",
      "sub": ".bat / .ps1",
      "type": "script",
      "group": "ops",
      "path": "*.bat / *.ps1",
      "tooltip": "tick-fetch, wick-hasher, csv-report launchers at repo root.",
      "x": 40,
      "y": 665,
      "w": 120,
      "h": 48
    },
    {
      "id": "agents-md",
      "label": "AGENTS.md",
      "sub": "agent rules",
      "type": "docs",
      "group": "ops",
      "path": "AGENTS.md",
      "tooltip": "Non-negotiable engineering rules for coding agents.",
      "x": 40,
      "y": 735,
      "w": 120,
      "h": 48
    }
  ],
  "edges": [
    {
      "id": "e1",
      "source": "methodology-rto",
      "target": "methodology"
    },
    {
      "id": "e2",
      "source": "methodology-sma-outfits",
      "target": "methodology"
    },
    {
      "id": "e3",
      "source": "methodology-unfairmarket",
      "target": "methodology"
    },
    {
      "id": "e4",
      "source": "methodology",
      "target": "shared-outfits"
    },
    {
      "id": "e5",
      "source": "shared-universe",
      "target": "tf-universe"
    },
    {
      "id": "e6",
      "source": "tf-universe",
      "target": "tick-fetch"
    },
    {
      "id": "e7",
      "source": "webull-api",
      "target": "tf-webull"
    },
    {
      "id": "e8",
      "source": "tick-fetch",
      "target": "tf-webull"
    },
    {
      "id": "e9",
      "source": "tf-webull",
      "target": "tf-quote"
    },
    {
      "id": "e10",
      "source": "tf-quote",
      "target": "tf-spike"
    },
    {
      "id": "e11",
      "source": "tf-market-hours",
      "target": "tick-fetch"
    },
    {
      "id": "e12",
      "source": "tf-spike",
      "target": "tf-csv-store"
    },
    {
      "id": "e13",
      "source": "tf-spike",
      "target": "tf-ohlc-agg"
    },
    {
      "id": "e14",
      "source": "tf-market-hours",
      "target": "tf-ohlc-agg"
    },
    {
      "id": "e15",
      "source": "tf-ohlc-agg",
      "target": "tf-csv-store"
    },
    {
      "id": "e16",
      "source": "tf-csv-store",
      "target": "data-ticks"
    },
    {
      "id": "e17",
      "source": "tf-csv-store",
      "target": "data-bars"
    },
    {
      "id": "e18",
      "source": "shared-outfits",
      "target": "wh-outfits"
    },
    {
      "id": "e19",
      "source": "data-bars",
      "target": "wh-csv-bars"
    },
    {
      "id": "e20",
      "source": "influx-optional",
      "target": "wh-influx"
    },
    {
      "id": "e21",
      "source": "wick-hasher",
      "target": "wh-csv-bars"
    },
    {
      "id": "e22",
      "source": "wh-outfits",
      "target": "wh-hits"
    },
    {
      "id": "e23",
      "source": "wh-csv-bars",
      "target": "wh-sma"
    },
    {
      "id": "e24",
      "source": "wh-influx",
      "target": "wh-sma"
    },
    {
      "id": "e25",
      "source": "wh-sma",
      "target": "wh-hits"
    },
    {
      "id": "e26",
      "source": "wh-penny",
      "target": "wh-hits"
    },
    {
      "id": "e27",
      "source": "wh-hits",
      "target": "wh-hash-key"
    },
    {
      "id": "e28",
      "source": "wh-hash-key",
      "target": "wh-rank"
    },
    {
      "id": "e29",
      "source": "wh-hits",
      "target": "wh-rank"
    },
    {
      "id": "e30",
      "source": "wh-rank",
      "target": "wh-board"
    },
    {
      "id": "e31",
      "source": "shared-outfits",
      "target": "cr-outfits"
    },
    {
      "id": "e32",
      "source": "data-bars",
      "target": "cr-csv-bars"
    },
    {
      "id": "e33",
      "source": "csv-report",
      "target": "cr-window"
    },
    {
      "id": "e34",
      "source": "cr-window",
      "target": "cr-hits"
    },
    {
      "id": "e35",
      "source": "cr-csv-bars",
      "target": "cr-hits"
    },
    {
      "id": "e36",
      "source": "cr-outfits",
      "target": "cr-hits"
    },
    {
      "id": "e37",
      "source": "cr-hits",
      "target": "cr-agg"
    },
    {
      "id": "e38",
      "source": "cr-agg",
      "target": "cr-html"
    },
    {
      "id": "e39",
      "source": "cr-templates",
      "target": "cr-html"
    },
    {
      "id": "e40",
      "source": "cr-html",
      "target": "reports-html"
    },
    {
      "id": "e41",
      "source": "tick-fetch",
      "target": "csv-report"
    },
    {
      "id": "e42",
      "source": "ci-e2e",
      "target": "ci-fixtures"
    },
    {
      "id": "e43",
      "source": "ci-fixtures",
      "target": "wh-csv-bars"
    },
    {
      "id": "e44",
      "source": "ci-fixtures",
      "target": "cr-csv-bars"
    },
    {
      "id": "e45",
      "source": "ci-e2e",
      "target": "wick-hasher"
    },
    {
      "id": "e46",
      "source": "ci-e2e",
      "target": "csv-report"
    },
    {
      "id": "e47",
      "source": "launchers",
      "target": "tick-fetch"
    },
    {
      "id": "e48",
      "source": "launchers",
      "target": "wick-hasher"
    },
    {
      "id": "e49",
      "source": "launchers",
      "target": "csv-report"
    },
    {
      "id": "e50",
      "source": "agents-md",
      "target": "methodology"
    }
  ],
  "flows": [
    {
      "id": "flow-live-ingest",
      "name": "Live tick ingest",
      "primary": true,
      "description": "Poll Webull during RTH, filter spikes, append ticks and multi-TF OHLC bars under data/.",
      "steps": [
        {
          "node": "shared-universe",
          "action": "Load universe symbols"
        },
        {
          "node": "tf-universe",
          "action": "Parse, uppercase, safe-gate, dedupe"
        },
        {
          "node": "tick-fetch",
          "action": "Orchestrate poll loop"
        },
        {
          "node": "webull-api",
          "action": "HTTP search + realtime"
        },
        {
          "node": "tf-webull",
          "action": "Resolve + batch quotes"
        },
        {
          "node": "tf-quote",
          "action": "Parse close-driven fields"
        },
        {
          "node": "tf-spike",
          "action": "Reject 30% spikes"
        },
        {
          "node": "tf-market-hours",
          "action": "RTH gate; bar floors"
        },
        {
          "node": "tf-ohlc-agg",
          "action": "Close-driven multi-TF bars"
        },
        {
          "node": "tf-csv-store",
          "action": "Append + fflush"
        },
        {
          "node": "data-ticks",
          "action": "Persist ticks CSV"
        },
        {
          "node": "data-bars",
          "action": "Persist bars CSV"
        }
      ]
    },
    {
      "id": "flow-live-board-csv",
      "name": "Live wick board (CSV)",
      "primary": true,
      "description": "wick-hasher live-tails data/bars, detects wick hits, ranks by dens_n, prints board.",
      "steps": [
        {
          "node": "shared-outfits",
          "action": "Load outfit ladders"
        },
        {
          "node": "wh-outfits",
          "action": "Parse periods; expand map"
        },
        {
          "node": "data-bars",
          "action": "Bars from tick-fetch"
        },
        {
          "node": "wh-csv-bars",
          "action": "Load/tail; drop active"
        },
        {
          "node": "wick-hasher",
          "action": "Live poll cycle"
        },
        {
          "node": "wh-sma",
          "action": "SMA(period) on closes"
        },
        {
          "node": "wh-penny",
          "action": "Banker's H/L equality"
        },
        {
          "node": "wh-hits",
          "action": "Wick entry + side"
        },
        {
          "node": "wh-hash-key",
          "action": "Format four-tuple key"
        },
        {
          "node": "wh-rank",
          "action": "dens_n rollup + sort"
        },
        {
          "node": "wh-board",
          "action": "Print live board"
        }
      ]
    },
    {
      "id": "flow-live-board-influx",
      "name": "Live wick board (Influx)",
      "primary": false,
      "description": "Alternate OHLC source when bars-dir is not used.",
      "steps": [
        {
          "node": "shared-outfits",
          "action": "Load outfit ladders"
        },
        {
          "node": "wh-outfits",
          "action": "Parse periods"
        },
        {
          "node": "influx-optional",
          "action": "Influx v2 OHLC"
        },
        {
          "node": "wh-influx",
          "action": "Flux multi-TF fetch"
        },
        {
          "node": "wick-hasher",
          "action": "Live poll cycle"
        },
        {
          "node": "wh-sma",
          "action": "SMA on closes"
        },
        {
          "node": "wh-penny",
          "action": "Penny equality"
        },
        {
          "node": "wh-hits",
          "action": "Detect wick hits"
        },
        {
          "node": "wh-hash-key",
          "action": "Format keys"
        },
        {
          "node": "wh-rank",
          "action": "Rank dens_n"
        },
        {
          "node": "wh-board",
          "action": "Print board"
        }
      ]
    },
    {
      "id": "flow-closing-report",
      "name": "Closing-hour HTML report",
      "primary": true,
      "description": "csv-report dens_n touches in 15:00–16:00 ET → outfit bias + ticker ranking HTML.",
      "steps": [
        {
          "node": "shared-outfits",
          "action": "Load ladders"
        },
        {
          "node": "cr-outfits",
          "action": "Period expand map"
        },
        {
          "node": "data-bars",
          "action": "Minute+ TF bars"
        },
        {
          "node": "cr-csv-bars",
          "action": "Load tree; cleanup"
        },
        {
          "node": "csv-report",
          "action": "CLI orchestration"
        },
        {
          "node": "cr-window",
          "action": "[15:00,16:00) ET"
        },
        {
          "node": "cr-hits",
          "action": "Window touches + expand"
        },
        {
          "node": "cr-agg",
          "action": "TOTAL boards"
        },
        {
          "node": "cr-templates",
          "action": "Section shells"
        },
        {
          "node": "cr-html",
          "action": "Render HTML"
        },
        {
          "node": "reports-html",
          "action": "Write reports/"
        }
      ]
    },
    {
      "id": "flow-eod-auto-report",
      "name": "EOD auto-report",
      "primary": false,
      "description": "After 16:00 ET, tick-fetch flushes bars and spawns csv-report if it saw live RTH.",
      "steps": [
        {
          "node": "tick-fetch",
          "action": "Detect RTH end"
        },
        {
          "node": "tf-ohlc-agg",
          "action": "Flush open bars"
        },
        {
          "node": "tf-csv-store",
          "action": "fflush bar files"
        },
        {
          "node": "data-bars",
          "action": "Final session bars"
        },
        {
          "node": "csv-report",
          "action": "Spawn --date <ET day>"
        },
        {
          "node": "cr-window",
          "action": "Closing-hour window"
        },
        {
          "node": "cr-hits",
          "action": "Detect dens_n"
        },
        {
          "node": "cr-agg",
          "action": "Build boards"
        },
        {
          "node": "cr-html",
          "action": "Render"
        },
        {
          "node": "reports-html",
          "action": "Write HTML"
        }
      ]
    },
    {
      "id": "flow-full-day-pipeline",
      "name": "Full day pipeline",
      "primary": true,
      "description": "End-to-end ops: ingest → live board → closing report.",
      "steps": [
        {
          "node": "methodology",
          "action": "SoT precondition"
        },
        {
          "node": "shared-outfits",
          "action": "Runtime ladders"
        },
        {
          "node": "shared-universe",
          "action": "Fetch universe"
        },
        {
          "node": "webull-api",
          "action": "Live quotes"
        },
        {
          "node": "tick-fetch",
          "action": "Poll + write CSV"
        },
        {
          "node": "data-ticks",
          "action": "Ticks store"
        },
        {
          "node": "data-bars",
          "action": "Bars store"
        },
        {
          "node": "wick-hasher",
          "action": "Live dens_n board"
        },
        {
          "node": "wh-board",
          "action": "Operator view"
        },
        {
          "node": "csv-report",
          "action": "Closing report"
        },
        {
          "node": "reports-html",
          "action": "HTML output"
        }
      ]
    },
    {
      "id": "flow-methodology-to-runtime",
      "name": "Methodology → runtime",
      "primary": false,
      "description": "Human corpus update. Never auto-promote ladders from live data.",
      "steps": [
        {
          "node": "methodology-rto",
          "action": "Ops examples"
        },
        {
          "node": "methodology-sma-outfits",
          "action": "Period tables"
        },
        {
          "node": "methodology",
          "action": "Corpus decision"
        },
        {
          "node": "shared-outfits",
          "action": "Manual file update"
        },
        {
          "node": "wh-outfits",
          "action": "Hasher reloads"
        },
        {
          "node": "cr-outfits",
          "action": "Report reloads"
        }
      ]
    },
    {
      "id": "flow-ci-e2e",
      "name": "CI offline e2e",
      "primary": false,
      "description": "scripts/ci_e2e.sh on committed fixtures; no Webull or live data/.",
      "steps": [
        {
          "node": "ci-e2e",
          "action": "Start checks"
        },
        {
          "node": "shared-outfits",
          "action": "Contract outfits"
        },
        {
          "node": "ci-fixtures",
          "action": "Synthetic bars"
        },
        {
          "node": "wick-hasher",
          "action": "Board on fixtures"
        },
        {
          "node": "csv-report",
          "action": "HTML on fixtures"
        },
        {
          "node": "reports-html",
          "action": "ci-e2e.html artifact"
        }
      ]
    },
    {
      "id": "flow-hit-detect-core",
      "name": "Wick hit detection core",
      "primary": false,
      "description": "H/L entry, penny, side geometry, dens_n contribution.",
      "steps": [
        {
          "node": "data-bars",
          "action": "OHLC candles"
        },
        {
          "node": "wh-sma",
          "action": "SMA of closes"
        },
        {
          "node": "wh-penny",
          "action": "Half-to-even cents"
        },
        {
          "node": "wh-hits",
          "action": "H/L entry + side rules"
        },
        {
          "node": "wh-hash-key",
          "action": "Emit four-tuple"
        },
        {
          "node": "wh-rank",
          "action": "dens_n accumulate"
        }
      ]
    },
    {
      "id": "flow-hash-key-contract",
      "name": "Hash key contract",
      "primary": false,
      "description": "Four-tuple leaf order is non-negotiable. First leaf = underscore-joined periods.",
      "steps": [
        {
          "node": "methodology",
          "action": "SoT ranking form"
        },
        {
          "node": "wh-outfits",
          "action": "Periods for leaf 1"
        },
        {
          "node": "wh-hits",
          "action": "SIDE + price + period"
        },
        {
          "node": "wh-hash-key",
          "action": "[p…][tf][EQ][SIDE…]"
        },
        {
          "node": "wh-rank",
          "action": "Count by full key"
        },
        {
          "node": "wh-board",
          "action": "Show best_key"
        }
      ]
    }
  ]
}