> ## Documentation Index
> Fetch the complete documentation index at: https://agentconcepts.io/llms.txt
> Use this file to discover all available pages before exploring further.

# half-renamed-codebase

> Terminology lag as project-maturation signal; the lagging name surfaces an unabsorbed mental model that the project has structurally outgrown.

<Badge>computer-science</Badge>

# Half renamed codebase

## Description

A specialization of [graduation-promotion](/concepts/graduation-promotion) where the lagging-rename pattern is
itself diagnostic: the project's new structural shape is visible in the code,
but the old name is still in the directory tree / config keys / function
signatures / docs. The mismatch surfaces an UNABSORBED mental model — the
maintainer's reflexes haven't caught up to where the code has already moved.

The diagnostic move: when you notice you're working around an old name, ask
"what mental model would I be using if the name matched the code?" The gap
usually points to a structural simplification or a missing abstraction.

Structural shape:

1. Project starts with a name N₀ encoding mental-model M₀.
2. Iteration produces a structurally different system better described by M₁.
3. Code reflects M₁ in shape; surfaces (file names, identifiers, docs) still
   reflect N₀.
4. Working on the codebase requires translation between the old vocabulary and
   the new reality on every read.
5. The translation cost is the load-bearing signal that the rename is overdue.

## Triggers

Surface this concept when reading code and noticing:

* A directory tree, config key, identifier, or doc heading whose name no longer
  describes what's underneath, and the mental translation happens on every read.
* A migration that "completed" at the structural level but where the old name
  still ships everywhere — package names, env-var prefixes, OAuth scopes,
  branch references in CI scripts.
* A name that requires explanatory comments to use correctly ("this is called
  X but really represents Y now").
* Two reviewers disagreeing on what a name means because one is reading it
  through the M0 lens and the other through the M1 lens.

## Exclusions

The diagnostic question category-mismatches in three situations:

* **Aesthetic-only renames.** A product rebrand where the old name lingers in
  surfaces but the underlying architecture and vocabulary are unchanged. The
  lag is decorative, not a structural-outgrowth signal — there's no M0 → M1
  shift to translate against.
* **Load-bearing back-compat aliases.** The old name persists because it IS
  the public API contract that callers depend on; the new name is an
  internal-only refactor. The persistence is a feature, not lag — the new
  name lives in the implementation, the old name lives in the interface, and
  both are correct at their respective layers.
* **Pipeline-locked vocabulary.** Mismatches caused by generated stubs, schema
  files, or external systems where the local code can't unilaterally rename
  without coordinated upstream change (e.g., protobuf field names encoding wire
  compatibility). The lag reflects coupling cost, not an unabsorbed mental
  model the maintainer could address with a local refactor.

## Structure

<img src="https://mintcdn.com/agentconcepts/ieIdiBIzgUbZJDV3/concepts/_assets/half-renamed-codebase-slots.svg?fit=max&auto=format&n=ieIdiBIzgUbZJDV3&q=85&s=df5af131eeb1872f1363d63e47d394b7" alt="Internal structure of half-renamed-codebase: a table of its component slots and the concepts that fill them." style={{ width: "100%" }} width="763" height="313" data-path="concepts/_assets/half-renamed-codebase-slots.svg" />

## Relationships

<img src="https://mintcdn.com/agentconcepts/2m6FqiBdTXWWaX5O/concepts/_assets/half-renamed-codebase-neighborhood.svg?fit=max&auto=format&n=2m6FqiBdTXWWaX5O&q=85&s=fcbfe37cddab91f57e488e1a1a2ffcc0" alt="Relationship neighborhood of half-renamed-codebase: a graph of the concepts it connects to and the concepts it is a part of." style={{ width: "100%" }} width="956" height="884" data-path="concepts/_assets/half-renamed-codebase-neighborhood.svg" />

## Examples

<AccordionGroup>
  <Accordion title="Git `master` → `main` default-branch rename (initiated industry-wide 2020; Git 2.28 added `init.defaultBranch` config in July 2020 to warn users to set a preference) · computer-science" defaultOpen={true}>
    After the industry-wide push starting in 2020 to rename the default Git branch from `master` to `main`, the rename completed at the surface of new projects almost immediately — GitHub, GitLab, and CircleCI defaulted new repositories to `main`, and developer tutorials updated quickly. But the lagging-name pattern persists years later in tooling that hardcoded the old name before the rename: GitHub Actions workflows pinned to `uses: actions/checkout@master` break silently when an action repository renames its branch, because GitHub Actions does not follow branch redirects for the `uses:` reference. CI scripts with hardcoded `git push origin master` or paths like `./dist/master.zip` continue to ship in older container images and enterprise monorepos that haven't been refactored.

    **Inference**: The translation cost is concentrated at the seam between the old code and any newer system it touches. A developer onboarding to a codebase that says `master` everywhere has to maintain a running mental translation against documentation, CI defaults, and colleagues' git commands that all assume `main`. The persistence isn't merely a rename TODO — the surface name encodes an obsolete mental model of "which branch is canonical," and reading the code requires translating into the current one on every encounter.
  </Accordion>

  <Accordion title="Python 2 → Python 3 string-handling migration (Python 3.0 released December 2008; Python 2 sunset January 2020) · computer-science" defaultOpen={true}>
    The Python 2 → 3 transition was nominally complete by 2020, but a distinctive lagging-name pattern persists in code that was mechanically ported rather than re-conceived. Python 2's `str` was bytes by default; text was the exception (`unicode`). Python 3 inverts this: `str` is text; bytes are the exception (`bytes`). Code carrying the Python 2 mental model often shows up as defensive `.encode('utf-8')` and `.decode('utf-8')` calls scattered through functions that never touch a network or file boundary, type annotations that conflate `str` and `bytes`, or variable names like `string_data` holding bytes (or vice versa). The functions work; the naming reflects a world where "string means bytes" was correct.

    The translation cost surfaces at every type boundary. A reader has to ask "does `str` here mean Python 3 `str`, or does this developer mean what Python 2 called `str`?" — and the answer often requires reading the function body to find out. The surface vocabulary still encodes M0 (bytes-as-default); the code's correctness depends on M1 (text-as-default). Resolving the lag is not a mechanical rename; it requires re-deriving which values are actually text and which are actually bytes.
  </Accordion>

  <Accordion title="jQuery → React/Vue component-model migration (React released 2013; large-scale migrations from jQuery codebases through the late 2010s and early 2020s) · computer-science">
    Codebases migrated from jQuery to React or Vue commonly carry vestigial jQuery vocabulary in their component code. Variable names prefixed with `$` (a jQuery convention indicating a jQuery-wrapped DOM element) persist in React components where the value is no longer a wrapped DOM node but a ref or a piece of state. "Selector" identifiers — `selectFooBar`, `getElementSelector`, `fooSelector` — appear in code that no longer queries the DOM imperatively but composes declaratively-rendered components. Helper functions named `bindEvents` or `attachHandlers` remain in code where event binding is a prop on a JSX element, not a separate lifecycle step.

    The mental-model gap is that jQuery's model was *the DOM as a queryable, mutable surface*; React's model is *the DOM as a derived output of declarative component state*. The lagging vocabulary keeps inviting the reader to ask "where's the selector that finds this element?" — a question the code's actual shape has rendered nonsensical, because the element exists only as a function of state and is never queried at all. Reading the code requires translating each `$el` or `selector` identifier into "the state value that determines whether this element renders," every time.
  </Accordion>

  <Accordion title="Twitter → X rebrand (July 2023); developer-ecosystem terminology lag observable through 2026 · computer-science">
    Twitter rebranded to X in July 2023, but the developer-facing surface lagged the structural change. As of 2026, the primary advertised endpoint is `api.x.com` and the official first-party SDKs ship under an "XDK" brand, yet the most widely-used community libraries — `tweepy` in Python, `twitter-api-v2` in TypeScript — still carry the old name in their package identifiers, README headers, and import paths. The `api.twitter.com` domain itself persists as a legacy redirect, and environment-variable conventions in deployed codebases still use the `TWITTER_API_KEY` / `TWITTER_BEARER_TOKEN` prefix even though new documentation has moved to `X_API_KEY`.

    The translation cost shows up on every read: a developer touching an OAuth flow has to mentally translate "Twitter app credentials" into "X developer-portal app credentials," and a debugger watching outbound HTTP traffic sees `api.twitter.com` requests succeed via redirect to a service whose canonical name is now `X`. The old name describes the company that no longer exists; the code's behavior is governed by an organization with a different mental model of what the platform is.
  </Accordion>
</AccordionGroup>
