VibeVM
Contents
On this page
en
Publisher
org.vibevm.ai-native
Version
1.0.0latest
Audiences
Reading time
6 min
Rendered
Read aloud
never

CARD: rule-closed-vocabulary-naming — A cell's name is computed from its manifest

01Discipline v0.2 · BETA · T2 · Rust (lineage home of the shared rule; the checker serves Go too)

Band 1 — Identity & Recognition

02Classification: layer=B (names & tokens) + H (weak-reader); mechanism=rule. The slug names the broader R3-004 aspiration ("closed-vocabulary naming"). The SHIPPED checker enforces one half of it — the name is COMPUTED from the manifest; the closed-vocabulary, one-referent, and no-synonym/shadow halves are named below as unbuilt, not hidden.

03Intent: a cell's canonical type name is not chosen freely but COMPUTED from its manifest — Pascal(variant) followed by the seam SPELLED AS WRITTEN — so the type announces which variant of which seam it is, and a rename rides a compiler-checked edit of the manifest, not an author's memory.

04Also Known As: computed-cell-name; cell-name-is-computed; the WalFreshnessCheck house style; R3-004 (composition half); B-038 fork №1.

05Applicability / Recognition: an item carries a cell(seam = "…", variant = "…") manifest attr — the Rust frontend lowers #[cell(seam = "…", variant = "…")] into it VERBATIM, and the Go extract bridge renders //spec:cell seam=… variant=… into the SAME cell(seam = "…", variant = "…") string (the single place the rust notation is born for Go) — and the declared type name's final path segment is not the composed name. Detector seed: for each item with a cell(…) attr, read variant and seam, compose Pascal(variant) (split the variant on _ and -, title-case each word, keep the rest as written) concatenated with seam verbatim — never re-cased — and compare it to the declared name's last :: segment (SatDepSolver, not SatDepsolver). A manifest missing either key composes nothing and is skipped (the vacuity guard — it never reds).

Band 2 — Justification & Tradeoffs

06Motivation: a struct named Sat behind a #[cell(seam = "DepSolver", variant = "sat")] manifest hides which seam-variant it is — a reader must open the manifest to learn it, and the next author renames the type without touching the manifest, so the two drift. Computing the name (SatDepSolver) puts the announcement in the type itself, and a rename tracks a manifest edit through the compiler. The WalFreshnessCheck family already lived this way before the rule — variant = "wal-freshness" + seam = "Check"WalFreshnessCheck — so the convention was house style in the largest cell family; the rule makes it machine-checked rather than remembered.

07Structure & Participants: the conform fact Fact::Item { symbol, attrs, … } — the Rust frontend lowers the #[cell] manifest into attrs verbatim; the Go bridge renders the //spec:cell directive into the same cell(seam = "…", variant = "…") string, dropping the extra keys (replaces, flag) the Go directive carries — → cell-name-is-computed extracts seam and variant through one parser both attr shapes feed, composes Pascal(variant) + seam, and compares the declared name's final segment; a divergent name is one finding naming both names. Fingerprints key on (file, declared_name), never line — the stop.rs lesson: a line-keyed baseline rots on any edit above the cell.

08Collaborations: rides the same conform gate, SARIF output, and ratchet baseline as the other structural rules; one engine rule serves Rust AND Go — both drivers mount CellNameIsComputed, so the Go convention (practised by hand until now, with no machine check anywhere) is closed in the same move rather than left as an asymmetry; the rust-ai-native codemod add-cell scaffolds from the same pascal, so the rule and the codemod agree on every name; every finding renders through the one req_message renderer (Class-F grammar, R3-011).

09Goals / Non-Goals: Goals: enforce that a cell's type name IS its manifest composed — Pascal(variant) + the seam as written. Non-Goals (the honest boundary): the rule checks COMPOSITION ONLY. It does NOT check — and the tree contains ZERO of — a closed vocabulary of structural tokens, one-name-one-referent repo-wide, or synonym/shadow detection on contract surfaces. Those are the other halves of R3-004, and this section is their record — they are specified and not built, and they are not built because they were not chosen: the owner's fork №1 took computed names over the closed-vocabulary variant that would have needed all three. Building them later needs a token vocabulary (none exists in the tree, neither as data nor as a constant) plus a referent/uniqueness checker; both are absent by decision, not by oversight. The rule is also NOT a general naming linter and does NOT touch items without a cell manifest.

10Consequences: (+) a cell's name announces its seam-variant at every call site; (+) renames are compiler-checked, riding a manifest edit; (+) one rule reads two languages through one attr string, so a second grammar form never appears. (−) a multi-word seam must already be spelled in the casing the name should carry (DepSolver, not depsolver) — the rule substitutes it verbatim by design, so a sloppily-cased seam reads oddly in the composed name, which is the price of the seam surviving intact; (−) the rule is near-vacuum where the convention already held (14 of 40 cells were pre-compliant), so its value is holding the line, not red-ing today.

11Alternatives: free naming plus a separate vocabulary/uniqueness lint — the closed-vocabulary variant the owner did not take; it needs a token vocabulary that does not exist in the tree. Pascal-both-halves composition (SatDepsolver) — mangles a multi-word seam and was explicitly rejected by fork №1. No check at all — the pre-rule state for Go: a convention held by memory, which decays (the failure mode this discipline exists to close).

12Risks & Assumptions: assumes the manifest's seam is already in the spelling the name should carry, since the rule substitutes it verbatim and never re-cases it; assumes variant words compose cleanly under Pascal-case (the pascal splits on _ and -). Sunset: if cell names become un-representable except through the codemod (the codemod as the sole authoring path makes a divergent name impossible to write), or if the manifest gains a richer naming scheme the composer must follow, the composition check is subsumed and this card retires with its checker (R-050).

13Evidence & Transfer-strength: checker shipped (cell-name-is-computed, doctested in core-ai-native-conform/src/rules/naming.rs, mounted in rust-ai-native-conform and go-ai-native-conform); R3-004. Exhibited on fixtures — Go clean FormalGreeting / dirty Wrongplanner, Rust test cells brought to their computed names. Measurement (boss, whole tree, B-038 fork №1): 40 manifest-bearing cells; 14 already compliant (all of vibe-checkWalFreshnessCheck, so the convention was house style before the rule); 13 production renames in host crates/ (vibe-resolver ×5, vibe-mcp ×4, vibe-registry ×2, vibe-index ×2), the rest test fixtures and regenerated .vibe/cache/**; no name is wire-visible (MCP tool names are separate string literals), so every rename is compiler-checked and internal. Portability: Rust + Go (both mount the rule); TypeScript carries a recorded reason — it has no cell manifest, so there is nothing to compute, held by the parity law spec://org.vibevm.ai-native/core-ai-native/00-MANIFESTO#PARITY-GAP-IS-NEVER-SILENT, not in silence. Tag: [E-mid] — the convention's pre-existence as house style is the strongest part of the evidence, but the comprehension gain is unmeasured (parallel to rule-position-is-a-resource).

Band 3 — Operation

14trigger: WHEN an item carries a cell(seam = "…", variant = "…") manifest attr (Rust #[cell] lowered verbatim; Go //spec:cell rendered by the extract bridge into the same attr) whose declared type name's final segment is not Pascal(variant) + seam-as-written, THEN apply
mode: gate            # a conform rule: runs over the scanned file set at conform time (per-merge), not per-edit (inline) or on a schedule (raid) — the finding arrives through the normal gate, like invariant-comment-position
routine:
  1. Read the finding: it names the declared name and the computed name (Pascal(variant) + the seam verbatim).
  2. Rename the type to the computed name — the manifest is the source of truth; the name follows it, never the reverse.
  3. Keep the seam's spelling intact: the rule substitutes it verbatim (DepSolver, not Depsolver); do not re-case it.
  4. Re-run `rust-ai-native conform check --scope <crate>` (or `go-ai-native conform check`); the finding clears and the baseline only shrinks.
  5. If the computed name itself looks wrong, fix the manifest (seam/variant) — the name is derived, so the manifest is always the edit site.
checker: cell-name-is-computed (core-ai-native-conform, T-syn over Item cell attrs; mounted in rust-ai-native-conform and go-ai-native-conform; composition only)
raid_role: layer=conform; order=after:cell-closure; batch=cell
budget: active_rules=1; first_signal=conform scan (content-addressed, cached; <1s/file warm)

For an agent

This page has a machine mirror. The citation carries the version rather than latest, so what an agent quotes does not move under it.

spec://org.vibevm.ai-native/rust-ai-native-lang@1.0.0/cards/rule-closed-vocabulary-naming

.md.xmlllms.txt