---
name: clawlint-interpreting-results
description: Use when reading clawlint output — understanding the diagnostic JSON schema, severity semantics, categories, origin/scope fields, needs_judgment flag, and how to tell a real finding from a false positive. Dispatch when the user asks "what does this diagnostic mean", "how should I read this clawlint output", or when a clawlint report is already in context and needs analysis.
---

# Interpreting clawlint diagnostics

clawlint emits a canonical JSON envelope:

```json
{
  "schema_version": 1,
  "diagnostics": [
    {
      /* one per finding */
    }
  ]
}
```

## Diagnostic shape

```json
{
  "rule_id": "agent-file-size",
  "category": "agent-file-health",
  "severity": "warn",
  "feasibility": "deterministic",
  "scope": { "file": { "path": "CLAUDE.md" } },
  "origin": "project",
  "message": "CLAUDE.md is 4123 tokens (threshold 3000)",
  "metadata": { "tokens": 4123, "threshold": 3000 },
  "needs_judgment": false
}
```

### Fields

- **`rule_id`** — stable, never renamed. Cite this when filing bugs or
  suppressing.
- **`category`** — one of `agent-file-health`, `best-practices-adherence`,
  `skills-hooks-gaps`, `context-management`.
- **`severity`** — `error` (broken/contradictory), `warn` (real problem),
  `info` (style / nudge).
- **`feasibility`** — `deterministic` (rule is mechanical) or `heuristic`
  (rule guesses; may need `--llm-assist` to adjudicate).
- **`scope`** — where the finding lives:
  - `{ "file": { "path": "…" } }` — a single file
  - `{ "project": { "root": "…" } }` — whole project
  - `"global"` — `~/.claude/` or `~/CLAUDE.md`
  - `{ "session": { "id": "…", "path": "…" } }` — transcript (Phase 3)
- **`origin`** — `project` or `global`. Lets you filter CLI output via
  `--scope` and TUI via `a`/`p`/`g`.
- **`metadata`** — rule-specific structured data. Thresholds, counts,
  matched substrings, etc. Useful for jq filters.
- **`needs_judgment`** — set by judgment-heavy rules. Only meaningful
  under `--llm-assist`; the LLM either confirms or suppresses the
  diagnostic.

### LLM-related metadata

When `--llm-assist` runs:

- **`metadata.llm_reasoning`** — the LLM's one-sentence confirmation.
  The diagnostic was kept because the LLM agreed the finding is real.
- **`metadata.llm_model`** — which model adjudicated (cache key).
- **`metadata.llm_note`** — escalation fell open. Missing
  `ANTHROPIC_API_KEY`, network error, or malformed response. The
  diagnostic is passed through unjudged.

## Triage playbook

1. **Errors first.** These usually mean the config doesn't parse or
   contradicts itself (e.g., `tool-permissions-redundant-deny`).
2. **Warnings that touch context budget.** `agent-file-size`,
   `output-style-token-heavy`, `agent-file-no-headings` — these silently
   cost tokens on every turn.
3. **Warnings that touch discoverability.** `skill-description-vague`,
   `skill-missing-when-not-to-use`, `overlapping-skill-triggers` — Claude
   can't pick the right skill if the metadata is mushy.
4. **Info accumulations.** A single info finding is usually safe to
   ignore. Ten of them in one file is a pattern and worth a pass.

## False-positive smell test

A clawlint finding is probably a false positive when:

- The rule is `feasibility: heuristic` and the region it flagged has a
  clear, stated reason for deviating from the heuristic (cite the reason
  in a suppression comment).
- The rule says "stale path" but the path is interpolated at runtime
  (`${VAR}/config`) — a known limitation until we add interpolation
  awareness.
- The rule says "unused skill" but the skill is intentionally dormant
  (e.g., scaffolded but not yet wired). Suppress with a note.

A finding is almost certainly _real_ when:

- Severity is `error`.
- Rule is `feasibility: deterministic` and you can reproduce the signal
  by reading the file yourself.
- The metadata counts line up with what you see (e.g., `tokens: 4123`
  and you can confirm the file is large).

## Reading at the CLI

```bash
# just errors
clawlint check --format json | jq '.diagnostics[] | select(.severity == "error")'

# one category
clawlint check --format json | jq '.diagnostics[] | select(.category == "agent-file-health")'

# grouped counts
clawlint check --format json | jq '.diagnostics | group_by(.rule_id) | map({rule: .[0].rule_id, n: length})'
```

## When in doubt

`clawlint explain <rule-id>` → the canonical per-rule doc. If the rule's
behaviour surprised you, the catalog rationale will usually clarify.
