{
  "assessments": {
    "error_consistency": 47.2
  },
  "dimension_notes": {
    "error_consistency": {
      "evidence": [
        "Multiple analyzers silently suppress parse/read failures instead of returning contextual errors (internal/quality/plugins/go/analyzers/detectors.go:112-114, 240-245; internal/quality/plugins/go/analyzers/test_coverage.go:211-214).",
        "Scraper entrypoints mix contextual wrapping and raw passthrough in similar boundary operations (internal/scraper/openapi.go:43-50 returns raw err; internal/scraper/github.go:29-37 returns raw err; internal/scraper/external/nuxtdocs.go:39-45 wraps with %w).",
        "Several paths collapse structured errors into joined strings, reducing traceability and unwrapping (internal/scraper/web.go:259; internal/scraper/localsearch.go:143; cmd/ask.go:320,340).",
        "Some runtime errors are dropped and processing continues without durable signal (internal/server/server.go:213 ignores encode error; internal/scraper/local.go:90-93 drops file parse errors; internal/search/engine.go:134-137 skips parse failures)."
      ],
      "impact_scope": "subsystem",
      "fix_scope": "multi_file_refactor",
      "confidence": "high",
      "unreported_risk": ""
    }
  },
  "findings": [
    {
      "dimension": "error_consistency",
      "identifier": "silent_parse_failures_in_analyzers",
      "summary": "Analyzer parse/read errors are silently converted to no findings.",
      "related_files": [
        "internal/quality/plugins/go/analyzers/detectors.go",
        "internal/quality/plugins/go/analyzers/test_coverage.go",
        "internal/quality/scanner.go"
      ],
      "evidence": [
        "GodStructDetector.analyzeFile returns nil on parser.ParseFile error (detectors.go:112-114).",
        "DebugLogDetector.analyzeFile also returns nil on parse failure (detectors.go:240-241).",
        "UntestedFuncDetector returns (nil, nil) when coverage.out read fails (test_coverage.go:211-214), making failure indistinguishable from success.",
        "Scanner loop logs detector failure and continues (scanner.go:77-79), so detector internals that swallow errors become invisible."
      ],
      "suggestion": "Standardize detector contract: return wrapped errors for parse/read failures (`fmt.Errorf(\"parse %s: %w\", path, err)`) and let scanner classify them as detector execution errors instead of empty findings.",
      "confidence": "high",
      "impact_scope": "module",
      "fix_scope": "multi_file_refactor"
    },
    {
      "dimension": "error_consistency",
      "identifier": "mixed_error_wrapping_at_scraper_boundaries",
      "summary": "Scrapers mix raw error passthrough with contextual wrapping.",
      "related_files": [
        "internal/scraper/openapi.go",
        "internal/scraper/github.go",
        "internal/scraper/external/nuxtdocs.go"
      ],
      "evidence": [
        "OpenAPI scraper returns raw `err` from readSpec/parseOpenAPISpec (openapi.go:43-50).",
        "GitHub scraper returns raw resolveRepo/MkdirTemp errors (github.go:29-37).",
        "Nuxt external scraper wraps fetch/parse failures with operation context and `%w` (nuxtdocs.go:39-45)."
      ],
      "suggestion": "Adopt one boundary rule for scraper packages: every external I/O or parse failure should be wrapped with operation context and `%w` before returning.",
      "confidence": "high",
      "impact_scope": "subsystem",
      "fix_scope": "multi_file_refactor"
    },
    {
      "dimension": "error_consistency",
      "identifier": "string_aggregated_errors_lose_causal_chain",
      "summary": "Aggregated scrape failures are flattened to strings, losing unwrap support.",
      "related_files": [
        "internal/scraper/web.go",
        "internal/scraper/localsearch.go",
        "cmd/ask.go"
      ],
      "evidence": [
        "Web scraper returns `fmt.Errorf(\"web scrape failed: %s\", strings.Join(scrapeErrors, \"; \"))` (web.go:259).",
        "Local search scraper similarly returns joined string error text (localsearch.go:143).",
        "ask command accumulates URL/term errors as formatted strings (ask.go:320,340), not typed/wrapped errors."
      ],
      "suggestion": "Store and return structured error sets (e.g., `[]error` wrapped via a multi-error type) and only stringify at CLI presentation boundaries.",
      "confidence": "medium",
      "impact_scope": "subsystem",
      "fix_scope": "architectural_change"
    },
    {
      "dimension": "error_consistency",
      "identifier": "error_drop_and_continue_without_signal",
      "summary": "Some failures are intentionally ignored with no traceable signal.",
      "related_files": [
        "internal/server/server.go",
        "internal/scraper/local.go",
        "internal/search/engine.go"
      ],
      "evidence": [
        "Server ignores encode error when writing parse-error RPC response (`_ = out.Encode(...)`) (server.go:213).",
        "Local scraper drops file conversion errors by returning nil in walk callback (local.go:90-93).",
        "Search engine skips parseDocFile errors with `continue` and no reporting (engine.go:134-137)."
      ],
      "suggestion": "When continuing after non-fatal errors, emit a consistent warning/collector path (counter + sampled log + optional returned diagnostics) so operators can detect degraded runs.",
      "confidence": "high",
      "impact_scope": "subsystem",
      "fix_scope": "multi_file_refactor"
    }
  ],
  "review_quality": {
    "batch_count": 1,
    "dimension_coverage": 1.0,
    "evidence_density": 1.0,
    "high_score_without_risk": 0,
    "finding_pressure": 9.74,
    "dimensions_with_findings": 1
  }
}
