Files
2026-02-24 12:10:13 +01:00

110 lines
6.4 KiB
Plaintext

{
"batch": "Cross-cutting Sweep",
"batch_index": 1,
"assessments": {
"error_consistency": 74.0
},
"dimension_notes": {
"error_consistency": {
"evidence": [
"cmd/scrape.go uses `wrapErr` for YAML fallback parsing but returns `%w` with outer `err` (`return fmt.Errorf(\"parse sources file: %w\", err)`), which can misreport or drop the actual parse failure.",
"cmd/ask.go drops `localErr` (`localRanked = nil`) and later reports only live fetch errors, so a failed local retrieval path is silently omitted from the returned error contract.",
"internal/search/engine.go frequently returns raw errors from filesystem/JSON boundaries (`return nil, err`) while nearby modules like internal/indexer/indexer.go and cmd/serve.go consistently wrap with operation context.",
"internal/quality/plugins/go/analyzers/test_coverage.go returns `nil, nil` for missing `go` tool and missing `coverage.out`, but returns hard errors for other failures, creating mixed silent-skip vs fail-fast behavior in one detector family.",
"internal/quality/plugins/go/plugin.go panics in package init on registration failure, while command entrypoints use returned errors + controlled process exit (cmd/root.go), producing inconsistent failure modes across startup paths."
],
"impact_scope": "subsystem",
"fix_scope": "multi_file_refactor",
"confidence": "high"
}
},
"findings": [
{
"dimension": "error_consistency",
"identifier": "wrong_error_wrapped_in_sources_fallback_parse",
"summary": "Fallback YAML parse wraps the wrong error variable, losing true parse context.",
"related_files": [
"cmd/scrape.go",
"internal/config/config.go"
],
"evidence": [
"cmd/scrape.go:153-155 checks `wrapErr` but returns `%w` with `err` from a different scope.",
"internal/config/config.go consistently wraps the current failing error with `%w` at parse/read boundaries, showing intended local convention."
],
"suggestion": "In cmd/scrape.go, change the return to `fmt.Errorf(\"parse sources file: %w\", wrapErr)` so the emitted error always preserves the actual fallback parse failure.",
"confidence": "high",
"impact_scope": "module",
"fix_scope": "single_edit"
},
{
"dimension": "error_consistency",
"identifier": "local_ask_retrieval_error_is_silently_dropped",
"summary": "Local retrieval failures are discarded, so final errors hide one failing path.",
"related_files": [
"cmd/ask.go",
"cmd/serve.go"
],
"evidence": [
"cmd/ask.go:122-125 sets `localRanked = nil` on `localErr` and does not append/report that error.",
"cmd/ask.go:145-147 returns only `fetchErrors` for failure messaging, excluding local retrieval failure cause.",
"cmd/serve.go wraps and propagates lower-level errors with operation context (`run devour_ask search: %w`), showing a stricter error propagation pattern at adjacent boundary code."
],
"suggestion": "Capture `localErr` into the same error aggregation path (or return immediately with context) so both local and live retrieval failures are visible to callers.",
"confidence": "high",
"impact_scope": "subsystem",
"fix_scope": "multi_file_refactor"
},
{
"dimension": "error_consistency",
"identifier": "search_engine_drops_operation_context_on_io_errors",
"summary": "Search engine returns raw IO/JSON errors without operation context at key boundaries.",
"related_files": [
"internal/search/engine.go",
"internal/indexer/indexer.go"
],
"evidence": [
"internal/search/engine.go returns bare errors at several boundaries (e.g., MkdirAll/listDocFiles/os.ReadFile/json.Unmarshal paths).",
"internal/indexer/indexer.go wraps errors with explicit operation strings (`failed to generate embeddings`, `failed to add to vector store`), improving traceability."
],
"suggestion": "Wrap engine boundary errors with operation-specific context (`fmt.Errorf(\"ensure index metadata: %w\", err)`, etc.) consistently across Rebuild/EnsureIndexed/Search.",
"confidence": "medium",
"impact_scope": "subsystem",
"fix_scope": "multi_file_refactor"
},
{
"dimension": "error_consistency",
"identifier": "test_coverage_detector_mixes_silent_skip_and_hard_failure",
"summary": "Coverage detector silently skips some environment failures but fails hard on others.",
"related_files": [
"internal/quality/plugins/go/analyzers/test_coverage.go",
"internal/quality/scanner.go"
],
"evidence": [
"internal/quality/plugins/go/analyzers/test_coverage.go:39-41 returns `nil, nil` if `go` is unavailable; lines 50-51 also return `nil, nil` when profile is missing.",
"The same detector returns hard errors for command execution failures (`failed to run test coverage`) and parse failures, yielding mixed failure contracts.",
"internal/quality/scanner.go aggregates detector errors, so silent `nil,nil` prevents scanner-level visibility for some failure modes."
],
"suggestion": "Standardize detector contract: either return explicit typed 'skipped' metadata/finding for non-actionable environment gaps, or return wrapped errors consistently so scanner can report them predictably.",
"confidence": "high",
"impact_scope": "subsystem",
"fix_scope": "architectural_change"
},
{
"dimension": "error_consistency",
"identifier": "plugin_registration_uses_panic_while_cli_paths_return_errors",
"summary": "Plugin init panics on registration failure instead of using returned error flow.",
"related_files": [
"internal/quality/plugins/go/plugin.go",
"cmd/root.go"
],
"evidence": [
"internal/quality/plugins/go/plugin.go:360-363 panics in `init()` when registration fails.",
"cmd/root.go:41-45 follows controlled error propagation (`Execute` prints error and exits), indicating a different process-level failure strategy."
],
"suggestion": "Replace panic-based registration with explicit initialization returning errors (or a centralized startup validation step) so failures follow the same surfaced error path as other startup errors.",
"confidence": "medium",
"impact_scope": "subsystem",
"fix_scope": "architectural_change"
}
]
}