# LANGUAGE — Naming-consistency lens

This lens asks: **does the codebase use the same word for the same
thing?** Do field names match domain language? Is CONTEXT.md's
"aliases to avoid" list violated anywhere?

Naming inconsistency is invisible until you trip over it. A reader who
hits `userId` in one file and `user_id` in another, or `account` in
the UI and `customer` in the backend, has to mentally translate
between vocabularies — and that translation cost accumulates across
every code review and every onboarding.

## Red flags this lens surfaces

### Same concept, two names
The codebase has `user`, `account`, and `customer` referring to the
same entity in different layers. Pick one and rename. CONTEXT.md's
"aliases to avoid" field is the canonical place to record which name
won.

### Same name, two concepts
The codebase has two distinct `Session` types — one for an auth
session and one for a chat session. Disambiguate with a domain prefix
(`AuthSession`, `ChatSession`) so a reader doesn't have to import the
right one based on file location.

### Field-name drift across layers
The backend stores `created_at`, the API returns `createdAt`, the UI
displays `Date created`. The serialization layer becomes a translation
graveyard. Standardize across all three layers.

### Implementation-detail names
Field or symbol names that describe *how* something is stored or
computed rather than *what* it represents. `is_processed_boolean` vs
`is_processed`. `temp_holder_arr` vs `pending_items`.

### CONTEXT.md violations
If `CONTEXT.md` declares "Plan thread" with aliases-to-avoid: "Plan
session, plan chat", any code in the area that calls it a "plan
session" or "plan chat" is a violation. Grep CONTEXT.md aliases as
part of this lens.

## Apply in Phase 1

When the explore step scans the named area:

1. Read `CONTEXT.md` (if present) — every term-block's `Aliases to
   avoid` field becomes a grep target.
2. Grep the area for each alias. Each hit is a candidate.
3. Look for the 4 other red flags above by inspection.
4. Note in the inventory: `{File}:{Line} — uses {wrong-term} for
   {canonical-term} ({CONTEXT.md reference if applicable})`.

## Apply in Phase 3 (deepening loop)

When the user picks a LANGUAGE candidate, the deepening loop should
write the canonical decision into CONTEXT.md via `apt-tools context
write`:

```
apt-tools context write . \
  --term "{canonical}" \
  --definition "{one-line}" \
  --aliases-to-avoid "{loser1}, {loser2}"
```

This is the cycle: LANGUAGE lens surfaces conflations → user picks the
canonical term → CONTEXT.md upserts the term-block → future LANGUAGE
passes use CONTEXT.md as the grep source.

## Distinguishing this from DEEPENING and INTERFACE-DESIGN

A symbol can have a perfectly good name and still be the wrong depth
(DEEPENING) or sit behind the wrong boundary (INTERFACE-DESIGN).
LANGUAGE is orthogonal — it asks "regardless of where this lives or
how big it is, does its name match the codebase's vocabulary?"

## Deletion test (Phase 2 prep)

The deletion test for LANGUAGE candidates is unusual: deleting the
*wrong* name doesn't help unless you replace it with the right one. So
the Phase-2 priority rubric for LANGUAGE candidates is:

> Number of call sites that read with friction × cost of rename
> divided by ergonomic gain.

High-call-site, cheap-rename, real-confusion candidates are
high-priority. One-off conflations that aren't blocking anyone are
low-priority — record them in CONTEXT.md and move on.

## What this lens does NOT cover

- Abstraction depth → `DEEPENING.md`
- Boundary shape → `INTERFACE-DESIGN.md`

LANGUAGE is read-only of the symbol's *name*, not its *shape*.
