{
  "schemaVersion": 2,
  "name": "science-research",
  "description": "Bounded science-research graph with round-scoped working state, per-superstep collection of parallel branch results, assistant-only shared debate messages, prompt preflight budgets, compact cross-round memory, and artifact-backed final reports.",
  "entry": "planner",
  "reducers": {
    "working.branch_results": "collect"
  },
  "initialState": {
    "research": {
      "confidence_threshold": 0.7,
      "max_iterations": 3
    },
    "control": {},
    "memory": {},
    "working": {},
    "result": {}
  },
  "nodes": {
    "planner": {
      "type": "agent",
      "description": "GENERATE: propose 3 distinct, discriminating investigation angles. Revisited across refinement rounds via a thread session.",
      "reads": [
        "memory.last_integration"
      ],
      "prompt": "You are the research Planner. Propose exactly 3 DISTINCT investigation angles labeled A, B, C. Use the prior integration summary from Selected shared state when present; target its weakest or most contested claim.\n\nResearch question:\n{{input.task}}\n\nSoft iteration budget: {{research.max_iterations}}.\n\nReturn JSON with EXACTLY: {\"angles\": [{\"label\": \"A\", \"target\": \"...\", \"bears_on\": \"...\", \"discriminating\": true}]} (three entries A/B/C).",
      "readOnly": true,
      "tools": [],
      "output": "working.plan",
      "response": {
        "format": "json",
        "maxBytes": 8192
      },
      "thinking": "off",
      "context": {
        "mode": "thread",
        "threadKey": "planner"
      },
      "limits": {
        "timeoutMs": 120000,
        "maxTurns": 6,
        "maxTokens": 15000,
        "maxCostUsd": 0.3,
        "maxPromptBytes": 18432
      }
    },
    "scope_gate": {
      "type": "human",
      "kind": "select",
      "description": "HUMAN GATE: approve the plan to start parallel investigation, or choose 'refine' to have the planner regenerate. Runs before any branch executes; once approved, refinement rounds skip this gate.",
      "prompt": "Review the plan below. Choose 'approve' to start investigation, or 'refine' to return it to the planner.\n\nResearch question:\n{{input.task}}\n\nPlan:\n{{working.plan}}",
      "options": [
        "approve",
        "refine"
      ],
      "output": "control.scope_decision"
    },
    "branch_a": {
      "type": "agent",
      "description": "TEST angle A in an isolated session.",
      "reads": [
        "working.plan"
      ],
      "prompt": "You are an isolated research Branch Worker. Investigate ONLY angle A from the plan in Selected shared state, using established scientific knowledge.\n\nResearch question:\n{{input.task}}\n\nReturn compact JSON with EXACTLY: {\"angle\": \"A\", \"conclusion\": \"...\", \"evidence\": [{\"claim\": \"...\", \"quality\": \"low|moderate|high\", \"directness\": \"direct|indirect\"}], \"hypothesis_impacts\": [{\"hypothesis\": \"...\", \"relation\": \"supports|contradicts|inconclusive\", \"strength\": \"weak|moderate|strong\", \"rationale\": \"...\"}], \"limitations\": [\"...\"]}.",
      "readOnly": true,
      "tools": [],
      "output": "working.branch_results",
      "response": {
        "format": "json",
        "maxBytes": 8192
      },
      "thinking": "off",
      "context": {
        "mode": "isolated"
      },
      "retry": {
        "maxAttempts": 2,
        "backoffMs": 800
      },
      "idempotent": true,
      "onError": {
        "strategy": "continue"
      },
      "limits": {
        "timeoutMs": 120000,
        "maxTurns": 6,
        "maxTokens": 18000,
        "maxCostUsd": 0.3,
        "maxPromptBytes": 18432
      }
    },
    "branch_b": {
      "type": "agent",
      "description": "TEST angle B in an isolated session.",
      "reads": [
        "working.plan"
      ],
      "prompt": "You are an isolated research Branch Worker. Investigate ONLY angle B from the plan in Selected shared state, using established scientific knowledge.\n\nResearch question:\n{{input.task}}\n\nReturn compact JSON with EXACTLY: {\"angle\": \"B\", \"conclusion\": \"...\", \"evidence\": [{\"claim\": \"...\", \"quality\": \"low|moderate|high\", \"directness\": \"direct|indirect\"}], \"hypothesis_impacts\": [{\"hypothesis\": \"...\", \"relation\": \"supports|contradicts|inconclusive\", \"strength\": \"weak|moderate|strong\", \"rationale\": \"...\"}], \"limitations\": [\"...\"]}.",
      "readOnly": true,
      "tools": [],
      "output": "working.branch_results",
      "response": {
        "format": "json",
        "maxBytes": 8192
      },
      "thinking": "off",
      "context": {
        "mode": "isolated"
      },
      "retry": {
        "maxAttempts": 2,
        "backoffMs": 800
      },
      "idempotent": true,
      "onError": {
        "strategy": "continue"
      },
      "limits": {
        "timeoutMs": 120000,
        "maxTurns": 6,
        "maxTokens": 18000,
        "maxCostUsd": 0.3,
        "maxPromptBytes": 18432
      }
    },
    "branch_c": {
      "type": "agent",
      "description": "TEST angle C in an isolated session.",
      "reads": [
        "working.plan"
      ],
      "prompt": "You are an isolated research Branch Worker. Investigate ONLY angle C from the plan in Selected shared state, using established scientific knowledge.\n\nResearch question:\n{{input.task}}\n\nReturn compact JSON with EXACTLY: {\"angle\": \"C\", \"conclusion\": \"...\", \"evidence\": [{\"claim\": \"...\", \"quality\": \"low|moderate|high\", \"directness\": \"direct|indirect\"}], \"hypothesis_impacts\": [{\"hypothesis\": \"...\", \"relation\": \"supports|contradicts|inconclusive\", \"strength\": \"weak|moderate|strong\", \"rationale\": \"...\"}], \"limitations\": [\"...\"]}.",
      "readOnly": true,
      "tools": [],
      "output": "working.branch_results",
      "response": {
        "format": "json",
        "maxBytes": 8192
      },
      "thinking": "off",
      "context": {
        "mode": "isolated"
      },
      "retry": {
        "maxAttempts": 2,
        "backoffMs": 800
      },
      "idempotent": true,
      "onError": {
        "strategy": "continue"
      },
      "limits": {
        "timeoutMs": 120000,
        "maxTurns": 6,
        "maxTokens": 18000,
        "maxCostUsd": 0.3,
        "maxPromptBytes": 18432
      }
    },
    "evidence_critic": {
      "type": "agent",
      "purpose": "reviewer",
      "description": "REVIEW: at the barrier, assess evidence quality, conflicts, and limitations across all branch results. Flags critical conflicts to trigger an adversarial debate.",
      "reads": [
        "working.branch_results"
      ],
      "prompt": "You are the Evidence Critic. Review the current-round branch cards in Selected shared state for evidence quality, cross-branch conflicts, and limitations. Do not invent evidence. Return compact JSON with EXACTLY: {\"strongest_evidence\": [\"...\"], \"conflicts\": [\"...\"], \"key_limitations\": [\"...\"], \"has_critical_conflicts\": <boolean>, \"quality_assessment\": \"...\"}.",
      "readOnly": true,
      "tools": [],
      "output": "working.reviewed_evidence",
      "response": {
        "format": "json",
        "maxBytes": 8192
      },
      "thinking": "off",
      "context": {
        "mode": "isolated"
      },
      "retry": {
        "maxAttempts": 2,
        "backoffMs": 800
      },
      "idempotent": true,
      "limits": {
        "timeoutMs": 120000,
        "maxTurns": 6,
        "maxTokens": 26000,
        "maxCostUsd": 0.3,
        "maxPromptBytes": 24576
      }
    },
    "reset_debate": {
      "type": "set",
      "description": "Remove any prior debate transcript/verdict before starting a fresh bounded debate.",
      "assign": [
        {
          "path": "working.debate",
          "mode": "unset"
        }
      ]
    },
    "devil_advocate": {
      "type": "agent",
      "description": "DEBATE (shared channel): argues the skeptic position against the leading interpretation of the evidence. Writes to the shared debate transcript.",
      "reads": [
        "working.reviewed_evidence"
      ],
      "prompt": "You are the Devil's Advocate. Use the reviewed evidence in Selected shared state and return the strongest grounded skeptic case. Return JSON with EXACTLY: {\"position\": \"skeptic\", \"strongest_objection\": \"...\", \"weakest_link\": \"...\", \"alternative_interpretation\": \"...\"}.",
      "readOnly": true,
      "tools": [],
      "response": {
        "format": "json",
        "maxBytes": 4096,
        "storeOutput": false
      },
      "thinking": "off",
      "context": {
        "mode": "shared",
        "messagesPath": "working.debate.messages",
        "capture": "assistant-only",
        "maxMessages": 4,
        "maxPromptBytes": 8192,
        "maxStoredMessages": 4
      },
      "retry": {
        "maxAttempts": 2,
        "backoffMs": 800
      },
      "idempotent": true,
      "limits": {
        "timeoutMs": 120000,
        "maxTurns": 5,
        "maxTokens": 18000,
        "maxCostUsd": 0.3,
        "maxPromptBytes": 18432
      }
    },
    "defender": {
      "type": "agent",
      "description": "DEBATE (shared channel): reads the skeptic's argument from the shared transcript and mounts a grounded defense of the leading interpretation.",
      "reads": [
        "working.reviewed_evidence"
      ],
      "prompt": "You are the Defender. The shared transcript contains the skeptic's prior final position. Use it together with reviewed evidence in Selected shared state. Concede what must be conceded and rebut only what the evidence supports. Return JSON with EXACTLY: {\"position\": \"defender\", \"concessions\": [\"...\"], \"rebuttals\": [\"...\"], \"residual_risk\": \"...\"}.",
      "readOnly": true,
      "tools": [],
      "response": {
        "format": "json",
        "maxBytes": 4096,
        "storeOutput": false
      },
      "thinking": "off",
      "context": {
        "mode": "shared",
        "messagesPath": "working.debate.messages",
        "capture": "assistant-only",
        "maxMessages": 4,
        "maxPromptBytes": 8192,
        "maxStoredMessages": 4
      },
      "retry": {
        "maxAttempts": 2,
        "backoffMs": 800
      },
      "idempotent": true,
      "limits": {
        "timeoutMs": 120000,
        "maxTurns": 5,
        "maxTokens": 18000,
        "maxCostUsd": 0.3,
        "maxPromptBytes": 18432
      }
    },
    "arbiter": {
      "type": "agent",
      "purpose": "reviewer",
      "description": "DEBATE: reads the full shared debate transcript plus reviewed evidence and rules whether the conflict is resolved, producing an adjusted verdict.",
      "reads": [
        "working.reviewed_evidence",
        "working.debate.messages"
      ],
      "prompt": "You are the Debate Arbiter. Read the compact reviewed evidence and the assistant-only debate transcript in Selected shared state. Return JSON with EXACTLY: {\"resolved\": <boolean>, \"resolution\": \"...\", \"adjusted_confidence\": \"weak|moderate|strong\", \"fatal_conflict\": <boolean>}.",
      "readOnly": true,
      "tools": [],
      "output": "working.debate.verdict",
      "response": {
        "format": "json",
        "maxBytes": 6144
      },
      "thinking": "off",
      "context": {
        "mode": "isolated"
      },
      "retry": {
        "maxAttempts": 2,
        "backoffMs": 800
      },
      "idempotent": true,
      "limits": {
        "timeoutMs": 120000,
        "maxTurns": 5,
        "maxTokens": 20000,
        "maxCostUsd": 0.3,
        "maxPromptBytes": 24576
      }
    },
    "integrator": {
      "type": "agent",
      "description": "INTEGRATE: maps reviewed evidence (and debate verdict, if any) onto hypotheses, assigns confidence bands, and decides sufficiency. Thread node: revisits across refinement rounds.",
      "reads": [
        "working.reviewed_evidence",
        "working.debate.verdict",
        "research.confidence_threshold"
      ],
      "prompt": "You are the Evidence Integrator. Use Selected shared state to map evidence and any debate verdict onto hypotheses and decide whether reporting is justified. Return compact JSON with EXACTLY: {\"hypotheses\": [{\"claim\": \"...\", \"confidence\": \"unsupported|weak|plausible|moderate|strong\", \"net_support\": \"supports|contradicts|inconclusive\"}], \"leading\": \"...\", \"sufficient\": <boolean>, \"fatal_conflict\": <boolean>, \"open_questions\": [\"...\"], \"refinement_summary\": \"what the next round must resolve\"}.",
      "readOnly": true,
      "tools": [],
      "output": "working.integration",
      "response": {
        "format": "json",
        "maxBytes": 8192
      },
      "thinking": "off",
      "context": {
        "mode": "thread",
        "threadKey": "integrator"
      },
      "limits": {
        "timeoutMs": 120000,
        "maxTurns": 6,
        "maxTokens": 26000,
        "maxCostUsd": 0.3,
        "maxPromptBytes": 24576
      }
    },
    "bump_round": {
      "type": "set",
      "description": "Archive one compact integration summary, then remove the entire round-scoped working state before replanning.",
      "assign": [
        {
          "path": "memory.last_integration",
          "from": "working.integration",
          "mode": "overwrite"
        },
        {
          "path": "working",
          "mode": "unset"
        }
      ]
    },
    "reporter": {
      "type": "agent",
      "description": "REPORT: synthesizes the final research report from the integrated hypotheses, reviewed evidence, and debate verdict.",
      "reads": [
        "working.integration",
        "working.reviewed_evidence",
        "working.debate.verdict"
      ],
      "prompt": "You are the Research Reporter. Produce the final Markdown report using the compact integration, reviewed evidence, and optional debate verdict in Selected shared state.\n\nResearch question:\n{{input.task}}\n\nStructure: lead conclusion and confidence; supporting evidence; limitations/conflicts; open questions. Use honest scientific hedging.",
      "readOnly": true,
      "tools": [],
      "output": "result.report_artifact",
      "thinking": "off",
      "context": {
        "mode": "isolated"
      },
      "retry": {
        "maxAttempts": 2,
        "backoffMs": 800
      },
      "idempotent": true,
      "limits": {
        "timeoutMs": 120000,
        "maxTurns": 6,
        "maxTokens": 26000,
        "maxCostUsd": 0.3,
        "maxPromptBytes": 24576
      },
      "response": {
        "format": "text",
        "maxBytes": 65536,
        "storage": "artifact",
        "mediaType": "text/markdown",
        "previewBytes": 4096
      }
    }
  },
  "edges": [
    {
      "from": [
        "branch_a",
        "branch_b",
        "branch_c"
      ],
      "to": "evidence_critic"
    },
    {
      "from": "reset_debate",
      "to": "devil_advocate"
    },
    {
      "from": "devil_advocate",
      "to": "defender"
    },
    {
      "from": "defender",
      "to": "arbiter"
    },
    {
      "from": "arbiter",
      "to": "integrator"
    },
    {
      "from": "bump_round",
      "to": "planner"
    },
    {
      "from": "reporter",
      "to": "__end__"
    }
  ],
  "routes": [
    {
      "from": "planner",
      "cases": [
        {
          "when": {
            "path": "control.scope_decision",
            "op": "eq",
            "value": "approve"
          },
          "to": [
            "branch_a",
            "branch_b",
            "branch_c"
          ]
        }
      ],
      "default": "scope_gate"
    },
    {
      "from": "scope_gate",
      "cases": [
        {
          "when": {
            "path": "control.scope_decision",
            "op": "eq",
            "value": "approve"
          },
          "to": [
            "branch_a",
            "branch_b",
            "branch_c"
          ]
        }
      ],
      "default": "planner"
    },
    {
      "from": "evidence_critic",
      "cases": [
        {
          "when": {
            "path": "working.reviewed_evidence.has_critical_conflicts",
            "op": "eq",
            "value": true
          },
          "to": "reset_debate"
        }
      ],
      "default": "integrator"
    },
    {
      "from": "integrator",
      "cases": [
        {
          "when": {
            "all": [
              {
                "path": "working.integration.sufficient",
                "op": "eq",
                "value": true
              },
              {
                "not": {
                  "path": "working.integration.fatal_conflict",
                  "op": "truthy"
                }
              }
            ]
          },
          "to": "reporter"
        },
        {
          "when": {
            "all": [
              {
                "path": "working.integration.sufficient",
                "op": "eq",
                "value": true
              },
              {
                "path": "working.integration.fatal_conflict",
                "op": "truthy"
              }
            ]
          },
          "to": "reset_debate"
        }
      ],
      "default": "bump_round"
    }
  ],
  "limits": {
    "maxSteps": 30,
    "maxNodeRuns": 48,
    "maxConcurrency": 3,
    "maxCostUsd": 5,
    "maxTokens": 400000,
    "timeoutMs": 3000000,
    "maxStateBytes": 98304,
    "maxPromptBytes": 36864
  },
  "policy": {
    "allowNonInteractive": true,
    "allowNonInteractiveMutations": false
  },
  "result": {
    "paths": [
      "result.report_artifact",
      "working.integration"
    ],
    "includeState": false,
    "maxBytes": 8192
  },
  "statePolicy": {
    "paths": {
      "working.plan": {
        "maxBytes": 8192
      },
      "working.branch_results": {
        "maxBytes": 28672
      },
      "working.reviewed_evidence": {
        "maxBytes": 8192
      },
      "working.debate": {
        "maxBytes": 16384
      },
      "working.integration": {
        "maxBytes": 8192
      },
      "result.report_artifact": {
        "maxBytes": 8192
      }
    }
  }
}
