{
  "project": "AgriControl",
  "blueprint": {
    "title": "ESP32 Virtual Control Lab - Complete System Blueprint",
    "version": "1.0",
    "date": "2026-08-04",
    "source_file": "ESP32_Virtual_Control_Lab_Blueprint.pdf"
  },
  "updated_at": "2026-08-05T20:30:00+09:00",
  "public_dashboard_url": "https://phyowaisoe.com/agricontrol/taskmanagement/",
  "repository_url": "https://github.com/phyo-wai-soe-jp/AgriControl.git",
  "status_model": {
    "roadmap_and_gate_weights": {
      "todo": 0,
      "active": 0.45,
      "blocked": 0.15,
      "done": 1
    },
    "branch_weights": {
      "planned": 0,
      "drafted": 0.35,
      "implemented": 0.7,
      "verified": 1
    }
  },
  "metrics": {
    "overall_percent": 72,
    "roadmap_percent": 84,
    "branch_percent": 63,
    "gate_percent": 69,
    "control_loop_percent": 70
  },
  "stages": [
    { "id": 1, "name": "Foundations", "intent": "Board, wiring, use case, safe states, protocol, and acceptance tests." },
    { "id": 2, "name": "Pure logic", "intent": "Canonical state, decision rules, safety supervisor, and sequence tests." },
    { "id": 3, "name": "Local physical outputs", "intent": "OLED, NeoPixel, buzzer, servo, and output integration." },
    { "id": 4, "name": "ESP runtime", "intent": "Async runtime, shared state, events, stale data, recovery, and HTTP." },
    { "id": 5, "name": "First vertical slice", "intent": "Temperature input to ESP decision, servo, OLED, JSON response, and recovery." },
    { "id": 6, "name": "Browser and FastAPI", "intent": "Bridge, website controls, virtual window, event log, and endurance updates." },
    { "id": 7, "name": "Irrigation slice", "intent": "Soil, tank, rain, pump hysteresis, protections, virtual actuators, warnings." },
    { "id": 8, "name": "Scenario testing", "intent": "Preset scenarios with expected commands, alarm, mode, response time, and pass/fail." },
    { "id": 9, "name": "Closed-loop simulation", "intent": "Actuator feedback, delays, failed starts, stuck faults, and servo mismatch." },
    { "id": 10, "name": "Reliability", "intent": "Recording, replay, rule versions, endurance, watchdog decision, and limits." },
    { "id": 11, "name": "Physical migration", "intent": "Physical sensors, source selection, pump driver, and feedback evidence." },
    { "id": 12, "name": "Platform growth", "intent": "MQTT, multi-device, storage, authentication, remote access, and packaging." }
  ],
  "tasks": [
    { "id": 1, "stage": 1, "status": "done", "title": "Confirm the exact ESP32-C3 board." },
    { "id": 2, "stage": 1, "status": "done", "title": "Record the firmware toolchain and version." },
    { "id": 3, "stage": 1, "status": "done", "title": "Create the complete pin map." },
    { "id": 4, "stage": 1, "status": "done", "title": "Verify OLED, NeoPixel, buzzer, and servo wiring." },
    { "id": 5, "stage": 1, "status": "done", "title": "Define the first use case." },
    { "id": 6, "stage": 1, "status": "done", "title": "Define safe states." },
    { "id": 7, "stage": 1, "status": "done", "title": "Define the communication protocol." },
    { "id": 8, "stage": 1, "status": "done", "title": "Define acceptance tests." },
    { "id": 9, "stage": 2, "status": "done", "title": "Create canonical sensor structures." },
    { "id": 10, "stage": 2, "status": "done", "title": "Create system and actuator state structures." },
    { "id": 11, "stage": 2, "status": "done", "title": "Implement the stateful decision engine on the computer." },
    { "id": 12, "stage": 2, "status": "done", "title": "Implement the safety supervisor." },
    { "id": 13, "stage": 2, "status": "done", "title": "Test normal conditions." },
    { "id": 14, "stage": 2, "status": "done", "title": "Test exact boundaries." },
    { "id": 15, "stage": 2, "status": "done", "title": "Test conflicting rules." },
    { "id": 16, "stage": 2, "status": "done", "title": "Test state sequences." },
    { "id": 17, "stage": 3, "status": "done", "title": "Test OLED independently." },
    { "id": 18, "stage": 3, "status": "done", "title": "Test NeoPixel independently." },
    { "id": 19, "stage": 3, "status": "done", "title": "Test buzzer independently." },
    { "id": 20, "stage": 3, "status": "done", "title": "Test servo independently." },
    { "id": 21, "stage": 3, "status": "done", "title": "Test all outputs together." },
    { "id": 22, "stage": 3, "status": "todo", "title": "Connect hardcoded decisions to outputs." },
    { "id": 23, "stage": 3, "status": "done", "title": "Confirm servo power does not reset the ESP." },
    { "id": 24, "stage": 4, "status": "done", "title": "Build the asynchronous runtime." },
    { "id": 25, "stage": 4, "status": "done", "title": "Add shared state management." },
    { "id": 26, "stage": 4, "status": "done", "title": "Add the event system." },
    { "id": 27, "stage": 4, "status": "done", "title": "Add stale-data detection." },
    { "id": 28, "stage": 4, "status": "done", "title": "Add recovery logic." },
    { "id": 29, "stage": 4, "status": "done", "title": "Add the HTTP server." },
    { "id": 30, "stage": 4, "status": "done", "title": "Add request-size and validation limits." },
    { "id": 31, "stage": 5, "status": "done", "title": "Implement only virtual temperature." },
    { "id": 32, "stage": 5, "status": "done", "title": "Send temperature with curl." },
    { "id": 33, "stage": 5, "status": "done", "title": "Validate the message." },
    { "id": 34, "stage": 5, "status": "done", "title": "Calculate the window command." },
    { "id": 35, "stage": 5, "status": "done", "title": "Apply the servo command." },
    { "id": 36, "stage": 5, "status": "done", "title": "Display the reason on OLED." },
    { "id": 37, "stage": 5, "status": "done", "title": "Return the decision as JSON." },
    { "id": 38, "stage": 5, "status": "done", "title": "Test repeated messages." },
    { "id": 39, "stage": 5, "status": "done", "title": "Test invalid values." },
    { "id": 40, "stage": 5, "status": "done", "title": "Test timeout and recovery." },
    { "id": 41, "stage": 6, "status": "done", "title": "Create the local FastAPI bridge." },
    { "id": 42, "stage": 6, "status": "done", "title": "Forward temperature to the ESP." },
    { "id": 43, "stage": 6, "status": "done", "title": "Create the website connection panel." },
    { "id": 44, "stage": 6, "status": "done", "title": "Create one temperature slider." },
    { "id": 45, "stage": 6, "status": "done", "title": "Display the ESP response." },
    { "id": 46, "stage": 6, "status": "done", "title": "Display the virtual window." },
    { "id": 47, "stage": 6, "status": "done", "title": "Add an event log." },
    { "id": 48, "stage": 6, "status": "done", "title": "Run hundreds of updates." },
    { "id": 49, "stage": 7, "status": "done", "title": "Add soil moisture." },
    { "id": 50, "stage": 7, "status": "done", "title": "Add tank level." },
    { "id": 51, "stage": 7, "status": "done", "title": "Add rain." },
    { "id": 52, "stage": 7, "status": "done", "title": "Add pump hysteresis." },
    { "id": 53, "stage": 7, "status": "done", "title": "Add low-tank protection." },
    { "id": 54, "stage": 7, "status": "done", "title": "Add rain protection." },
    { "id": 55, "stage": 7, "status": "done", "title": "Add virtual pump and fan." },
    { "id": 56, "stage": 7, "status": "done", "title": "Connect LED and buzzer warnings." },
    { "id": 57, "stage": 7, "status": "done", "title": "Add corresponding OLED pages." },
    { "id": 58, "stage": 8, "status": "done", "title": "Add normal, hot, dry-soil, low-tank, rain, invalid-data, and communication-loss scenarios." },
    { "id": 59, "stage": 8, "status": "done", "title": "Define expected commands, mode, alarm, and response time." },
    { "id": 60, "stage": 8, "status": "done", "title": "Add automatic PASS/FAIL comparison." },
    { "id": 61, "stage": 9, "status": "done", "title": "Add simulated actuator feedback." },
    { "id": 62, "stage": 9, "status": "done", "title": "Add startup delays." },
    { "id": 63, "stage": 9, "status": "done", "title": "Add failed startup." },
    { "id": 64, "stage": 9, "status": "done", "title": "Add stuck-on and stuck-off faults." },
    { "id": 65, "stage": 9, "status": "done", "title": "Add incorrect virtual servo position." },
    { "id": 66, "stage": 9, "status": "done", "title": "Make the ESP respond to feedback faults." },
    { "id": 67, "stage": 10, "status": "done", "title": "Add recording and replay." },
    { "id": 68, "stage": 10, "status": "done", "title": "Add rule versioning." },
    { "id": 69, "stage": 10, "status": "done", "title": "Run long-duration tests." },
    { "id": 70, "stage": 10, "status": "todo", "title": "Add a watchdog only after runtime stability." },
    { "id": 71, "stage": 10, "status": "done", "title": "Document known limits." },
    { "id": 72, "stage": 11, "status": "todo", "title": "Add a real temperature sensor." },
    { "id": 73, "stage": 11, "status": "todo", "title": "Add per-sensor source selection." },
    { "id": 74, "stage": 11, "status": "todo", "title": "Add real soil, tank, and rain sensors." },
    { "id": 75, "stage": 11, "status": "todo", "title": "Add a properly driven pump." },
    { "id": 76, "stage": 11, "status": "todo", "title": "Add physical feedback where possible." },
    { "id": 77, "stage": 12, "status": "todo", "title": "Add MQTT." },
    { "id": 78, "stage": 12, "status": "todo", "title": "Add multiple ESP devices." },
    { "id": 79, "stage": 12, "status": "todo", "title": "Add persistent storage." },
    { "id": 80, "stage": 12, "status": "todo", "title": "Add authentication." },
    { "id": 81, "stage": 12, "status": "todo", "title": "Add remote access." },
    { "id": 82, "stage": 12, "status": "todo", "title": "Package the system as a reusable control and testing platform." }
  ],
  "branches": [
    { "id": 1, "status": "verified", "name": "Product definition", "purpose": "Mission, sensors, actuators, qualities, constraints." },
    { "id": 2, "status": "implemented", "name": "Website simulation", "purpose": "Virtual conditions, scenarios, faults, dashboards." },
    { "id": 3, "status": "implemented", "name": "FastAPI bridge", "purpose": "Browser-to-ESP communication, sessions, logs, replay, tests." },
    { "id": 4, "status": "implemented", "name": "Protocol", "purpose": "Stable messages and validation rules." },
    { "id": 5, "status": "implemented", "name": "ESP communication", "purpose": "Move data without deciding behavior." },
    { "id": 6, "status": "implemented", "name": "Sensor abstraction", "purpose": "Virtual and physical inputs become canonical state." },
    { "id": 7, "status": "implemented", "name": "State management", "purpose": "Authoritative sensor, system, and actuator state." },
    { "id": 8, "status": "implemented", "name": "Decision engine", "purpose": "Normal requested actions with reasons and rule IDs." },
    { "id": 9, "status": "implemented", "name": "Safety supervisor", "purpose": "Final authority and conflict resolution." },
    { "id": 10, "status": "implemented", "name": "Actuator abstraction", "purpose": "Requested, commanded, simulated, measured, and fault states." },
    { "id": 11, "status": "implemented", "name": "Physical outputs", "purpose": "OLED, LED, buzzer, and servo behavior." },
    { "id": 12, "status": "implemented", "name": "Observability", "purpose": "Meaningful events and state changes." },
    { "id": 13, "status": "implemented", "name": "Testing", "purpose": "Logic, integration, failure, endurance, and replay verification." },
    { "id": 14, "status": "implemented", "name": "Recording and replay", "purpose": "Experiment reproduction and regression comparison." },
    { "id": 15, "status": "planned", "name": "Physical expansion", "purpose": "Gradual replacement of virtual components." },
    { "id": 16, "status": "planned", "name": "Platform expansion", "purpose": "MQTT, multi-device, database, authentication, SaaS." }
  ],
  "completion_gates": [
    {
      "id": "A",
      "name": "First vertical slice",
      "criteria": [
        { "status": "done", "title": "Temperature message accepted and validated" },
        { "status": "done", "title": "Correct window command at all boundaries" },
        { "status": "done", "title": "Servo moves without resetting the ESP" },
        { "status": "done", "title": "OLED shows value and reason" },
        { "status": "done", "title": "Website receives the response" },
        { "status": "done", "title": "Timeout enters defined safe state" },
        { "status": "done", "title": "Recovery requires stable valid messages" }
      ]
    },
    {
      "id": "B",
      "name": "Greenhouse MVP",
      "criteria": [
        { "status": "done", "title": "Temperature, soil, tank, and rain supported" },
        { "status": "done", "title": "Pump hysteresis works" },
        { "status": "done", "title": "Low tank and rain override irrigation" },
        { "status": "done", "title": "OLED, LED, buzzer, and servo are coherent" },
        { "status": "done", "title": "Preset scenarios pass automatically" },
        { "status": "done", "title": "Commanded and simulated states are separate" }
      ]
    },
    {
      "id": "C",
      "name": "Test platform",
      "criteria": [
        { "status": "done", "title": "Actuator failures can be injected" },
        { "status": "done", "title": "Feedback faults change ESP behavior" },
        { "status": "done", "title": "Sessions can be recorded and replayed" },
        { "status": "done", "title": "Regression results compare firmware or rule versions" },
        { "status": "done", "title": "Endurance run completes without unrecovered failure" }
      ]
    },
    {
      "id": "D",
      "name": "Physical migration",
      "criteria": [
        { "status": "todo", "title": "At least one physical sensor can replace its virtual counterpart" },
        { "status": "todo", "title": "Per-sensor source selection works" },
        { "status": "todo", "title": "Decision and safety code does not require rewriting" },
        { "status": "todo", "title": "Virtual mode remains available for testing" }
      ]
    },
    {
      "id": "E",
      "name": "Platform expansion",
      "criteria": [
        { "status": "todo", "title": "Multiple devices justify MQTT" },
        { "status": "todo", "title": "Persistent history justifies a database" },
        { "status": "todo", "title": "Remote users justify authentication" },
        { "status": "todo", "title": "A repeatable customer workflow justifies SaaS packaging" }
      ]
    }
  ],
  "control_loop_steps": [
    { "id": 1, "title": "Create sensor conditions", "branches": [2] },
    { "id": 2, "title": "Transmit versioned sensor message", "branches": [3, 4] },
    { "id": 3, "title": "Validate packet", "branches": [4, 5] },
    { "id": 4, "title": "Update canonical sensor state", "branches": [6, 7] },
    { "id": 5, "title": "Calculate requested actions", "branches": [8] },
    { "id": 6, "title": "Apply safety priorities", "branches": [9] },
    { "id": 7, "title": "Generate final commands", "branches": [9, 10] },
    { "id": 8, "title": "Apply physical and virtual outputs", "branches": [10, 11, 2] },
    { "id": 9, "title": "Receive actuator feedback", "branches": [10] },
    { "id": 10, "title": "Detect mismatch or failure", "branches": [9, 10, 13] },
    { "id": 11, "title": "Update UI, outputs, and history", "branches": [11, 12, 2] },
    { "id": 12, "title": "Repeat without blocking", "branches": [5, 7, 13] }
  ],
  "next_tasks": [22, 70, 72, 73],
  "known_unknowns": [
    "Exact RC servo model at CN3 (power source stability is confirmed)",
    "Pump and fan GPIO/relay pin assignment (not built into the ESP32-C3M-TRY eval board)",
    "Exact PlatformIO platform/framework/Arduino-ESP32 core versions in use",
    "Real WiFi credentials for firmware/include/secrets.h",
    "Whether the placeholder runtime tuning constants (stale-data timeout, recovery threshold, max request body size) are acceptable for the real deployment",
    "Acceptable temperature validation range for firmware/src/vertical_slice.cpp (currently a placeholder -40C to 85C)",
    "Whether a spare tact switch (SW1/SW2/SW3) should be wired as a physical emergency-stop input",
    "The real ESP's IP address/hostname once it is on a reachable network, for AGRICONTROL_ESP_BASE_URL",
    "Whether firmware/src/irrigation_slice.cpp's NeoPixel color mapping (an interpretation of the manual's ambiguous status-color spec) and simplified single-tone buzzer pattern are acceptable"
  ]
}
