@startuml MAS-C4-Detailed
title MAS Architecture Detailed

!log Current 'STYLE' dvar: STYLE
!log About to include: styles/github-STYLE.puml
!include styles/github-STYLE.puml
!include external/C4_Component.puml

LAYOUT_LEFT_RIGHT()
' LAYOUT_WITH_LEGEND()

Person(user, "User", "Runs the platform via CLI, Streamlit, or CI workflows")
System(config, "Configuration", "Provides runtime settings for models, providers, prompts, datasets")

System_Boundary(agents_eval, "Agents-eval Platform") {
    Container(main_app, "Main Application", "Python", "CLI+GUI entrypoint, orchestrates agents/sessions")
    
    System_Boundary(eval_components, "Three tiered Evaluation System") {
        Container(traditional_eval, "Traditional Metrics", "Python", "text similarity, execution time, ...")
        Container(llm_judge, "LLM-as-a-Judge", "Python+LLM", "Review quality + agentic execution assessment") 
        Container(graph_analysis, "Graph Analysis", "Python", "Tool calls + agent interaction complexity")
        Container(composite_scorer, "Composite Scorer", "Python", "Final score: Results / Time / Complexity")
    }


    Container(agent_system, "Agent System", "Python/PydanticAI", "Multi-agent orchestration (Manager/Researcher/Analyst/Synthesizer)\nor Claude Code headless (--engine=cc)")

    note right of agent_system
      CC path (Sprint 10+):
      extract_cc_review_text() + cc_result_to_graph_trace()
      feed evaluate_comprehensive() directly.
      CompositeResult.engine_type = "cc_solo"|"cc_teams"
      Sprint 11: build_cc_query() for default prompts,
      resilient search tool wrapper (HTTP 403/429)
      Sprint 12: JSONL stream persisted per-run via RunContext
    end note

    Container(benchmark, "Benchmark", "Python", "SweepRunner: compositions × papers × repetitions\nSweepAnalyzer: mean/stddev per composition\nresults.json + summary.md")

    Container(datasets, "Dataset Integration", "Python+JSON", "Loads and provides access to benchmark datasets (e.g., PeerRead)")
    Container(reports, "Report Generation", "Python", "SuggestionEngine + ReportGenerator\nRule-based + optional LLM suggestions → Markdown")

    Container(run_context, "RunContext + ArtifactRegistry", "Python", "Per-run directory routing (runs/mas/ | runs/cc/)\nArtifact tracking, evaluation.json persistence")

    Container(security, "Security", "Python", "URL validation (SSRF), prompt sanitization,\nlog/trace scrubbing, path sanitization, input size limits")

    Container(review_storage, "Review Storage", "File System", "_Agents-eval/output/runs/ per-run directories\n+ traces.db (SQLite) shared index")
    Container(dataset_storage, "Dataset Storage", "File System", "_Agents-eval/datasets/peerread/ (JSON+PDF)")

    ' Enforce vertical stacking:
    main_app -[hidden]-> eval_components
    main_app -[hidden]-> agent_system
    main_app -[hidden]-> benchmark

    agent_system -[hidden]-> datasets
    eval_components -[hidden]-> datasets
    benchmark -[hidden]-> reports
    reports -[hidden]-> security

    datasets -[hidden]-> run_context
    run_context -[hidden]-> review_storage
    datasets -[hidden]-> dataset_storage
}

System_Boundary(external_providers, "External Providers") {
    System_Ext(llm_providers, "LLM Providers", "Anthropic, Cerebras, Groq, Gemini, Ollama, OpenRouter")
    System_Ext(tools, "Tools/Search APIs", "DuckDuckGo, Tavily, etc.")
    System_Ext(obs, "Observability", "WandB, Logfire, AgentOps")
    System_Ext(dataset_ext, "Dataset", "PeerRead")

    llm_providers  -[hidden]-> tools
    tools-[hidden]-> obs
    obs-[hidden]-> dataset_ext
}

' Relationships (example)
Rel(user, main_app, "Submits review generation tasks", "CLI/Streamlit")
Rel(user, config, "Adjusts for tasks", "CLI/Streamlit")
Rel(config, main_app, "Provides runtime settings", "JSON")
Rel(main_app, agent_system, "Initiates agent tasks", "PydanticAI")
Rel(main_app, eval_components, "Initiates evaluation tasks", "PydanticAI")
Rel(main_app, benchmark, "Run sweep", "SweepConfig")
Rel(benchmark, agent_system, "Run composition", "compositions × papers × repetitions")
Rel(benchmark, eval_components, "Collect CompositeResult", "per run")
Rel(agent_system, datasets, "Provides papers/data", "Dataset API")
Rel(eval_components, datasets, "Provides papers/data", "Dataset API")
Rel(datasets, review_storage, "Saves reviews", "File I/O")
Rel(datasets, dataset_storage, "Saves datasets", "File I/O")
Rel(main_app, reports, "Generate report", "CompositeResult → Markdown")
Rel(main_app, run_context, "Route outputs", "per-run directory")
Rel(main_app, security, "Validates", "URLs, prompts, inputs")

' Three tiered eval system
Rel(composite_scorer, traditional_eval, "Traditional scores", "Data")
Rel(composite_scorer, llm_judge, "Judge scores", "Data")
Rel(composite_scorer, graph_analysis, "Complexity scores", "Data")

' Dotted relations for external services
Rel_D(eval_components, llm_providers, "Queries", "LLM-as-a-Judge")
Rel_D(agent_system, llm_providers, "Queries", "chat/completion")
Rel_D(agent_system, tools, "Queries", "API")
Rel_D(agent_system, obs, "Sends", "logger, introspection")
Rel_D(datasets, dataset_ext, "Gets", "http")

' SHOW_LEGEND()
@enduml
