{
  "batch": "Design Coherence \u2014 Mechanical Concern Signals",
  "batch_index": 4,
  "assessments": {
    "design_coherence": 74.0
  },
  "dimension_notes": {
    "design_coherence": {
      "evidence": [
        "Command passthrough wrappers add non-functional indirection in language command modules: `languages/dart/commands.py` defines `_cmd_*_impl` plus thin `cmd_*` forwarders for each command (`cmd_large`, `cmd_complexity`, `cmd_deps`, `cmd_cycles`, `cmd_orphaned`, `cmd_dupes`).",
        "C# deps module mixes parsing, graph construction, CLI arg resolution, and terminal rendering in one file (`languages/csharp/detectors/deps.py` contains core graph builders and also `cmd_deps`/`cmd_cycles` UI handlers).",
        "Status rendering duplicates score-bar construction logic in two loops in `app/commands/status_parts/render.py` (same threshold/color/filled computation blocks around lines ~191-199 and ~223-231), increasing drift risk."
      ],
      "impact_scope": "subsystem",
      "fix_scope": "multi_file_refactor",
      "confidence": "high"
    }
  },
  "findings": [
    {
      "dimension": "design_coherence",
      "identifier": "passthrough_command_wrappers_add_low_leverage_layers",
      "summary": "Language command modules include thin forwarding wrappers with no behavioral value.",
      "related_files": [
        "desloppify/desloppify/desloppify/languages/dart/commands.py",
        "desloppify/desloppify/desloppify/languages/csharp/commands.py",
        "desloppify/desloppify/desloppify/languages/framework/commands_base.py"
      ],
      "evidence": [
        "`languages/dart/commands.py` creates `_cmd_*_impl` callables and then defines six `cmd_*` functions that only call the corresponding impl.",
        "`languages/csharp/commands.py` also keeps thin wrappers (`cmd_large`, `cmd_complexity`, `cmd_deps`, `cmd_cycles`) that forward directly to other callables.",
        "The framework already provides factory-returned callables; wrapper layers increase symbol count and call depth without adding policy."
      ],
      "suggestion": "Assign factory outputs directly to exported command names (or build the registry directly from generated callables) and keep wrappers only where they add language-specific behavior, validation, or formatting.",
      "confidence": "high",
      "impact_scope": "module",
      "fix_scope": "multi_file_refactor"
    },
    {
      "dimension": "design_coherence",
      "identifier": "csharp_deps_module_blends_core_and_cli_responsibilities",
      "summary": "C# dependency detector file combines analysis engine logic with CLI presentation.",
      "related_files": [
        "desloppify/desloppify/desloppify/languages/csharp/detectors/deps.py",
        "desloppify/desloppify/desloppify/languages/csharp/commands.py",
        "desloppify/desloppify/desloppify/languages/_shared/scaffold_detect_commands.py"
      ],
      "evidence": [
        "`languages/csharp/detectors/deps.py` includes internal graph/parsing functions (`_parse_project_assets_references`, `_build_dep_graph_roslyn`, `build_dep_graph`) and command handlers (`cmd_deps`, `cmd_cycles`) in the same module.",
        "`languages/csharp/commands.py` forwards to `cmd_deps_direct`/`cmd_cycles_deps`, meaning command routing depends on detector-module UI functions instead of a clean detector API.",
        "Other language paths use shared command scaffolding (`languages/_shared/scaffold_detect_commands.py`) that separates command shell concerns from graph/detection logic."
      ],
      "suggestion": "Split C# deps into `detectors/deps_core.py` (graph/parsing only) and command-facing adapters in `commands.py` (or scaffold factories), so detectors expose data and command modules own JSON/table rendering.",
      "confidence": "high",
      "impact_scope": "subsystem",
      "fix_scope": "architectural_change"
    },
    {
      "dimension": "design_coherence",
      "identifier": "status_bar_render_logic_duplicated_in_two_paths",
      "summary": "Status renderer repeats identical score-bar construction for mechanical and subjective rows.",
      "related_files": [
        "desloppify/desloppify/desloppify/app/commands/status_parts/render.py",
        "desloppify/desloppify/desloppify/app/output/scorecard_parts/projection.py"
      ],
      "evidence": [
        "`show_dimension_table` in `status_parts/render.py` computes `filled`, score thresholds, and colored bar in one loop for mechanical dimensions and repeats the same logic in a second loop for subjective entries.",
        "Duplicated threshold constants (`>=98`, `>=93`) and color composition appear in both blocks, creating a two-site maintenance point for one rendering policy."
      ],
      "suggestion": "Extract a shared `render_score_bar(score_val, bar_len)` helper (or move the row formatting policy into scorecard projection/output helpers) and reuse it for both loops to keep display semantics consistent.",
      "confidence": "high",
      "impact_scope": "module",
      "fix_scope": "single_edit"
    }
  ]
}