# F-008: The five components have four naming schemes, and one display name maps to a repo that shares no name with it category: structural-drift confidence: high evidence: - Slugs verified against git.lab with `git ls-remote` (see `analysis/SCOPE.md` §3): `threadnet-call`, `thread-net-git`, `threadnet-operating`, `ThreadNet-Web`, `axion1337.chat-gitops`. - `thread-net-git` breaks the `threadnet-*` pattern of its siblings; `https://git.lab/axion1337.chat/threadnet-git.git` returns "project could not be found". - `ThreadNet-Web` is the only CamelCase slug. `ThreadNet-Web` and `threadnet-web` return byte-identical ref lists (same project via GitLab's case-insensitive path handling), and the repo's own documents use both plus a lowercase registry path `registry.git.lab/axion1337.chat/threadnet-web/desktop-build` (`hosts/overmind.md:54`). `hosts/matrix.md:20` uses the Gitea spelling `sorb/ThreadNet-Web`. - "ThreadNet Server Suite" = `axion1337.chat-gitops` rests on a single sentence, `CLAUDE.md:6`. The slug contains no ThreadNet element; nothing else in the repo repeats the equation. This session had to ask the human to confirm it (Phase-0 STOP, question 3). - `vision/threadnet.md:9-11` lists the product line as "ThreadNet-Web …, threadnet-call …, thread-net-git, threadnet-operating" — four names in three casings, and the fifth component is absent from the vision that defines the line. impact: Nothing in the repo lets a reader or an agent get from a display name to a repository deterministically. This session could not, and the Phase-0 scope freeze existed partly to resolve it. Every automation that iterates over "the ThreadNet repos" needs a hand-maintained table, and the case-insensitive redirect hides the inconsistency until something case-sensitive (a container path, a CI cache key, a `git clone` into a case-sensitive filesystem) meets it. root-cause pattern: **Rule declared repo-wide, applied to a subset** — the branding decision in `shared/branding.md` fixes what the *product* is called on every surface, and was carried through thoroughly there, but repository names were never part of that sweep. neckbeard mechanism: **Gap in neckbeard**, with a near-miss worth noting. `schema.yaml` enforces naming as a first-class rule for artifacts — `filename: "^\\d{4}-[a-z0-9-]+\\.md$"` for ADRs and issues, `"^[a-z0-9-]+\\.md$"` for wiki pages — and `scripts/validate.py` reports "filename does not match" plus "id does not match filename prefix". The framework therefore already holds the position that names must be mechanically derivable. It applies that only inside one repo; a multi-repo project has no equivalent, and neckbeard has no artifact type that declares "these are the components and this is what they are called". Session 2 needs one; today `analysis/SCOPE.md` §3 is the only such table that exists.