Files
wehub-resource-sync 26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:30 +08:00

6.4 KiB
Raw Permalink Blame History

Journey 22 — Code Health: Clean Code as a Token-Cost Lever

You ship with an AI agent every day and your provider bill keeps climbing. A big, quiet driver is code the agent must re-read to understand — tangled, cryptically named, tightly coupled functions that get loaded and reasoned about on every turn that touches them. This journey covers the Code Health Engine: the navigability score, the quality tax in USD, and every surface that turns code health into a measurable token-cost lever.

Source files referenced here:

  • rust/src/core/code_health/ — the engine: score.rs (navigability + USD tax), cognitive.rs (S3776), naming.rs, coupling.rs, analyze.rs, annotate.rs, delta.rs, gate.rs, scan.rs, persist.rs (health.json), fabric.rs (BM25 / graph / knowledge fan-out + pruning)
  • rust/src/tools/ctx_quality.rs, rust/src/tools/registered/ctx_quality.rs — the MCP tool
  • rust/src/cli/health_cmd.rs — the lean-ctx health command
  • rust/src/core/gain/gain_score.rs — the navigability gain component
  • rust/src/hook_handlers/edit_health.rs — the native-edit PostToolUse notice
  • rust/src/core/config/sections.rsCodeHealthConfig

0. The principle

Clean code is cheaper for a model to read for the same reason it is cheaper for a human: less to hold in working memory. LeanCTX already compresses how code reaches the model; the Code Health Engine attacks the intrinsic cost of the code itself. It reuses the same tree-sitter AST (26 languages) as the rest of code intelligence, so the score is computed once per index build and read (never recomputed) everywhere else.


1. The signals → one navigability score

The navigability score (0100) rolls up three AST-grounded signals:

Signal What it measures
Cognitive complexity How hard a function is to follow — nesting, breaks in linear flow, boolean tangles. SonarSource's S3776, not cyclomatic count.
Naming quality Cryptic / single-letter / meaningless identifiers that force re-reads to infer intent.
Module coupling Afferent / efferent coupling and instability — how entangled a file is with the repo.

A function whose cognitive complexity crosses the threshold (default 15) is a hotspot. The engine also estimates a quality tax in USD — the recurring token cost of the hotspots, priced with the same model-pricing table the gain report uses.


2. Compute once, fan out everywhere

persist.rs writes health.json next to the graph index and recomputes only when the indexed source set changed (fingerprint-gated — a no-op touch never rescans). fabric.rs then weaves the result into the long-term stores as a replace-source:

top hotspots  → BM25 chunks + knowledge facts (searchable, recallable)
every over-threshold fn → property-graph `health_hotspot` edge (cc = edge weight)

Stale signals are pruned on every refresh, so a fixed hotspot disappears instead of lingering. This is what lets ctx_semantic_search find hotspots and ctx_callgraph annotate a risky symbol with its complexity.


3. ctx_quality — the on-demand report (MCP)

ctx_quality action=report                  # whole-project score + hotspots + USD tax
ctx_quality action=file path=src/auth.rs   # one file, function by function
ctx_quality action=delta                   # health change vs the last baseline
ctx_quality action=report format=json      # machine-readable

Read-only, in the standard profile — it never costs a write-permission prompt.


4. lean-ctx health — the terminal & CI command

lean-ctx health                 # navigability score + top hotspots + quality tax
lean-ctx health src/            # scope to a path
lean-ctx health --json          # machine-readable
lean-ctx health --gate          # non-zero exit if the project is over its floor

--gate makes "don't let the codebase get less navigable" a scriptable CI line, the same way doctor overhead --gate guards the context budget.


5. Read annotations & the edit-gate

In signatures / map reads, over-threshold functions are annotated inline (sparse, deterministic):

fn process_request(...)            · cc=23 (over)

Both ctx_edit and ctx_patch run a complexity-delta check before writing:

⚠ code-health: process_request cognitive complexity 18 → 27 (+9, over threshold 15)

The same advisory notice fires from the PostToolUse hook for the host's native Edit / MultiEdit, so the signal follows the agent regardless of edit path. The top hotspots are surfaced once in a compact session-start block.


6. It feeds the gain score

The gain score gains a fifth component, navigability, so a cleaner codebase lifts the headline number:

Score: 84/100  (compression 71, cost 90, quality 76, consistency 80, navigability 84)

When no health data exists the score falls back to its original four-component weighting — you are never penalised for a signal that has not been computed.


7. Configuration

All knobs live under [code_health]:

Key Default Meaning
cognitive_threshold 15 Complexity above which a function is a hotspot.
gate "warn" Edit-gate behaviour: "warn" (annotate), "block" (refuse clean→over-threshold), "off".
annotate_reads true Inline cc= annotations in signatures / map reads.
naming true Run the naming-quality heuristic.
inject_context false Emit [CODE HEALTH] notices as additionalContext in PostToolUse hook stdout. Off by default to prevent prompt-cache invalidation on Anthropic models (#778). When off, notices route to ctx_knowledge + dashboard. Override: LEAN_CTX_INJECT_CONTEXT=1.

8. Determinism

Every health output is a deterministic function of (file content, mode, threshold) — no timestamps, counters or random elements in tool-output bodies. That byte-stability keeps provider prompt caching (Anthropic up to 90%, OpenAI 50%) applying, so the signal adds insight without breaking the cache discount it is meant to protect (#498).


See also

  • Journey 11 — Analytics, Insights & Reporting (the gain score and quality tax)
  • Journey 4 — Code Intelligence (the graph/impact tools the engine shares its AST with)
  • Journey 19 — Customization & Governance ([code_health] knobs and enforcement)