{
  "assessments": {
    "error_consistency": 56.5
  },
  "dimension_notes": {
    "error_consistency": {
      "evidence": [
        "Error wrapping is inconsistent across neighboring call paths: `cmd/serve.go` wraps many failures with operation context (e.g. `run devour_query search`), while `runServe` and `handleServeMethod` still return raw errors directly from `loadAppConfig` (`cmd/serve.go:45`, `cmd/serve.go:75`).",
        "Several lower-level functions return bare underlying errors without context (`internal/scraper/local.go:49`, `internal/scraper/local.go:57`, `internal/config/config.go:207`, `internal/config/config.go:364`) while sibling code in the same files uses contextual wrapping.",
        "Error classification is string-based in `cmd/ask.go` (`strings.Contains(fetchErr.Error(), \"persistence warning:\")` at line 191), making behavior dependent on message text rather than typed/sentinel error contracts.",
        "At least one path suppresses error details entirely (`countLOC` returns `0` on read failure in `internal/quality/plugins/go/plugin.go:353-356`), while other analyzer code returns explicit detector errors."
      ],
      "impact_scope": "subsystem",
      "fix_scope": "multi_file_refactor",
      "confidence": "high",
      "unreported_risk": ""
    }
  },
  "findings": [
    {
      "dimension": "error_consistency",
      "identifier": "mixed_wrapped_and_bare_error_propagation",
      "summary": "Adjacent layers mix contextual wrapping and bare error returns",
      "related_files": [
        "cmd/serve.go",
        "internal/config/config.go",
        "internal/scraper/local.go",
        "cmd/scrape.go"
      ],
      "evidence": [
        "`cmd/serve.go:87-109` wraps errors with operation labels, but `cmd/serve.go:45` and `cmd/serve.go:75` return raw `loadAppConfig` errors.",
        "`internal/config/config.go:207` and `:364` return bare errors, while nearby code uses contextual `fmt.Errorf(...: %w)`.",
        "`internal/scraper/local.go:49`, `:57`, `:104`, `:154`, `:164` return raw errors despite other branches adding context and joins."
      ],
      "suggestion": "Adopt a single propagation rule for non-boundary layers: always wrap external/I-O failures with operation context (e.g., `fmt.Errorf(\"load config path: %w\", err)`). Apply this consistently in `cmd/serve.go`, `internal/config/config.go`, and `internal/scraper/local.go`.",
      "confidence": "high",
      "impact_scope": "subsystem",
      "fix_scope": "multi_file_refactor"
    },
    {
      "dimension": "error_consistency",
      "identifier": "string_based_error_classification_in_ask_flow",
      "summary": "Ask flow branches on error message text instead of typed categories",
      "related_files": [
        "cmd/ask.go",
        "cmd/scrape.go",
        "internal/server/server.go"
      ],
      "evidence": [
        "`cmd/ask.go:379` and `:384` encode category in message prefix (`\"persistence warning:\"`).",
        "`cmd/ask.go:191` uses `strings.Contains(fetchErr.Error(), \"persistence warning:\")` for control flow, coupling behavior to mutable message strings.",
        "Other modules treat errors opaquely and pass through generic text (`internal/server/server.go:256` returns `err.Error()` to RPC clients), amplifying inconsistency in downstream handling."
      ],
      "suggestion": "Introduce typed/sentinel errors for recoverable warning classes (e.g., `var ErrPersistenceWarning`) and use `errors.Is`/`errors.As` in `cmd/ask.go` instead of string matching. Keep human-readable text separate from machine classification.",
      "confidence": "high",
      "impact_scope": "module",
      "fix_scope": "multi_file_refactor"
    },
    {
      "dimension": "error_consistency",
      "identifier": "analyzer_error_handling_policy_is_incoherent",
      "summary": "Analyzer/plugin paths alternate between explicit, wrapped, and silent failures",
      "related_files": [
        "internal/quality/plugins/go/analyzers/detectors.go",
        "internal/quality/plugins/go/analyzers/advanced.go",
        "internal/quality/plugins/go/plugin.go"
      ],
      "evidence": [
        "`internal/quality/plugins/go/analyzers/detectors.go:46-60` converts read failures into synthetic findings (`detector_error`) rather than returning an error.",
        "`internal/quality/plugins/go/analyzers/advanced.go:242` returns raw parse errors from helper methods without context.",
        "`internal/quality/plugins/go/plugin.go:353-356` swallows file read failures in `countLOC` by returning `0`, losing failure provenance entirely."
      ],
      "suggestion": "Define a consistent analyzer failure contract: either (a) report detector-execution issues as standardized `detector_error` findings with metadata, or (b) return wrapped errors; do not silently coerce errors to default values. Refactor `countLOC` to return `(int, error)` and propagate classification consistently.",
      "confidence": "medium",
      "impact_scope": "subsystem",
      "fix_scope": "architectural_change"
    }
  ],
  "review_quality": {
    "batch_count": 1,
    "dimension_coverage": 1.0,
    "evidence_density": 1.333,
    "high_score_without_risk": 0,
    "finding_pressure": 7.244,
    "dimensions_with_findings": 1
  }
}
