// 主体机 JSON 桥入口:DeepSeek Harness 插件(dsh-plugin-pyroduct)在 Node 下
// 运行本程序,传**一个**以 '{' 开头的 JSON 请求参数,从 stdout 读一行 JSON
// 回信。请求形如 { "kind": "petri" };未给 kind 时默认 "report"(与 CLI 的
// 缺省一致)。桥使插件保持纯 spawner:全部模型语义留在 MoonBit 侧,随本模
// 块一起定版与门禁(参照 moonbit_static_analysis/src/jsoncli 的先例)。
//
// 支持的 kind = faces() 清单:机器本体(report/slots/loop/mermaid/dot/
// genesis/course/naming/principle/spec)+ 多主体与涌现(multi/group/society)
// + agent 层(evolution/cycle/intuition/association)+ 因果与审计(dmlref/
// causal/audit/fleet/mutants/ml/ml-export)+ 协调器 + 五条分析面(pathsum/
// algebra/petri/aho/buchi)。可视化合成页(viz/journey/嵌套视图)与 all
// 组合不走桥——它们是呈现层,不是模型事实。

///|
/// 回信信封:rendered 是报告全文;faces 是支持的 kind 清单(防漂移)。
struct Reply {
  ok : Bool
  error : String?
  kind : String
  rendered : String
  faces : Array[String]
} derive(ToJson)

///|
struct Request {
  kind : String?
} derive(FromJson)

///|
/// 本机分析面的稳定清单(新增面时同步此表、cmd/main 与插件 README)。
fn faces() -> Array[String] {
  [
    "report", "slots", "loop", "multi", "group", "society", "evolution", "cycle",
    "coordinator", "dmlref", "causal", "audit", "fleet", "mutants", "mbti", "mermaid",
    "dot", "genesis", "course", "naming", "principle", "intuition", "ml", "ml-export",
    "spec", "association", "pathsum", "algebra", "petri", "aho", "buchi",
  ]
}

///|
fn ok_reply(kind : String, rendered : String) -> Reply {
  { ok: true, error: None, kind, rendered, faces: faces(), }
}

///|
fn err_reply(msg : String) -> Reply {
  { ok: false, error: Some(msg), kind: "", rendered: "", faces: faces(), }
}

///|
fn render_kind(kind : String) -> String raise {
  match kind {
    "report" => @sm.render_report()
    "slots" => @sm.render_slots()
    "loop" => @sm.render_loop_report()
    "multi" => @multi.render_multi_report()
    "group" => @group.render_group_report()
    "society" => @society.render_report()
    "evolution" => @evolution.render_report()
    "cycle" => @evolution.render_cycle_report(@evolution.demo_cycle())
    "coordinator" => @coordinator.render_report()
    "dmlref" => @dmlref.render_report()
    "causal" => @causal.render_report()
    "audit" => @audit.render_report()
    "fleet" => @audit.render_fleet_report()
    "mutants" => @audit.render_mutation_report()
    "mbti" => @audit.render_iface_report(@audit.scan_snapshot())
    "mermaid" => @sm.render_mermaid()
    "dot" => @sm.render_dot()
    "genesis" => @sm.render_genesis()
    "course" => @sm.render_course()
    "naming" => @sm.render_naming_table()
    "principle" => @sm.revision_principle()
    "intuition" => @evolution.intuition_principle()
    "ml" => @ml.render_ml_report(@ml.default_ml_plan())
    "ml-export" => @ml.csv_preview(@ml.make_dataset(200, 1.5, 7), 12)
    "spec" => @sm.spec_json()
    "association" => @evolution.render_association_report()
    "pathsum" => @sm.render_pathsum_report()
    "algebra" => @sm.render_algebra_report()
    "petri" => @sm.render_petri_report()
    "aho" => @sm.render_aho_report()
    "buchi" => @sm.render_buchi_report()
    _ => ""
  }
}

///|
/// 请求 JSON 是以 '{' 开头的那一个参数(运行器在它之前的参数被忽略)。
fn find_request_arg(args : Array[String]) -> String? {
  for s in args {
    if s.trim_start().has_prefix("{") {
      return Some(s)
    }
  }
  None
}

///|
fn handle(raw : String) -> Reply {
  try {
    let request : Request = @json.from_json(@json.parse(raw))
    let kind = request.kind.unwrap_or("report")
    match kind {
      k if faces().contains(k) => ok_reply(k, render_kind(k))
      other =>
        err_reply("unknown kind '\{other}'(faces: \{faces().join(", ")})")
    }
  } catch {
    err => err_reply("bad request: \{err.to_string()}")
  }
}

///|
fn main {
  let args : Array[String] = @env.args()
  match find_request_arg(args) {
    None =>
      println(
        @json.to_json(err_reply("missing request argument (a JSON object)")).stringify(),
      )
    Some(raw) => println(@json.to_json(handle(raw)).stringify())
  }
}