Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,12 @@
"category": "design",
"tags": ["planning", "wayfind", "decision-map", "brainstorm", "prd", "interview", "domain-modeling", "ubiquitous-language", "glossary", "design", "design-handoff", "devils-advocate", "architect", "stress-test", "skill"]
},
{
"name": "naming",
"source": "./plugins/naming",
"category": "design",
"tags": ["naming", "name", "rename", "identifier", "candidates", "anti-anchoring", "skill"]
},
{
"name": "review",
"source": "./plugins/review",
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Browse and manage with `/plugin`. To refresh after updates: `/plugin marketplace
- [`architecture`](plugins/architecture) — Scans an existing codebase for module-level architecture friction — shallow modules, seam leaks, and locality gaps — using Ousterhout's deep-module lens, presents candidates as a self-contained HTML report, and runs an interview loop on the selected candidate before handing off for planning.
- [`prototype`](plugins/prototype) — Builds throwaway code to answer a design question before committing to architecture — a logic facet (an interactive terminal app over a portable state model) and a UI facet (radically different visual variants on one route).
- [`planning`](plugins/planning) — Pre-implementation planning pipeline: chart a too-big, foggy effort as a decision map, diverge on candidate approaches, lock product intent and the engineering contract, actively maintain resolved domain language, explore the design space, stress-test adversarially, and produce a structured implementation plan with an approval gate.
- [`naming`](plugins/naming) — Generates and evaluates fresh name candidates for anything — an identifier, file, module, skill, repo, or domain term — by fanning out blind, fresh-context generators from distinct lenses (responsibility-literal, moment-of-use, domain-lore), then scoring a shortlist against the consuming org's naming criteria. The human always picks; it never auto-locks a name. An optional tournament mode adds elimination rounds with independent judges for high-stakes, hard-to-refactor names.
- [`event-storming`](plugins/event-storming) — EventStorming for domain discovery — a methodology skill (Big Picture / Process Modeling / Design-Level facilitation reference, notation, patterns) and a simulation skill (agentic multi-persona workshops that produce a structured-markdown model by default; a live Miro-board rendering path is available when the first-party miro plugin is enabled).
- [`miro`](plugins/miro) — Miro board management over the Model Context Protocol: create and manage boards, sticky notes, shapes, frames, connectors, and tags for EventStorming, brainstorming, and diagramming. Bundles a local stdio MCP server (single self-contained Node artifact); installs disabled — opt in and supply a Miro API token.

Expand Down
12 changes: 12 additions & 0 deletions plugins/naming/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "naming",
"version": "0.1.0",
"description": "Generates and evaluates fresh name candidates for anything — an identifier, file, module, skill, repo, or domain term — by fanning out blind, fresh-context generators from distinct lenses (responsibility-literal, moment-of-use, domain-lore), then scoring a shortlist against the consuming org's naming criteria. The human always picks; it never auto-locks a name. An optional tournament mode adds elimination rounds with independent judges for high-stakes, hard-to-refactor names.",
"author": {
"name": "Melodic Software",
"email": "info@melodicsoftware.com"
},
"license": "MIT",
"keywords": ["naming", "name", "rename", "identifier", "candidates", "anti-anchoring", "skill"]
}
18 changes: 18 additions & 0 deletions plugins/naming/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Changelog

All notable changes to the `naming` plugin are documented here. Format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning.

## [0.1.0]

### Added

- **Initial release.** `/naming:name-it-better` — generate fresh name
candidates by fanning out blind, fresh-context generators from distinct lenses
(responsibility-literal, moment-of-use, domain-lore), score a shortlist against
the consuming org's naming criteria, and recommend — the human always picks,
never an auto-locked name. Optional `tournament` action adds elimination rounds
with independent judges for high-stakes, hard-to-refactor names.
- Repo-agnostic: scores against the consuming project's declared naming
conventions when present, degrading to the general criteria grounded in the
skill's `context/sources.md` when none is declared.
60 changes: 60 additions & 0 deletions plugins/naming/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# naming

A Claude Code plugin for generating and evaluating name candidates. One
skill, one job: when a name was just rejected — or none exists yet — break
the anchor by fanning out blind, fresh-context generators from distinct
lenses, then hand the human a scored shortlist to choose from.

| Skill | What it does |
|---|---|
| `/naming:name-it-better` | Generate fresh name candidates from blind lenses, score them, recommend a shortlist — the human picks |

## Why blind generators

The dominant trigger is a reactive retry: a name was suggested and
rejected, and the same context that produced it will only produce more of
the same. So the generators run BLIND to the conversation, seeded only with
a distilled context brief, each working a distinct lens
(responsibility-literal, moment-of-use, domain-lore). Diverge widely from
independent perspectives, then converge once — and keep the first-seen
suggestion from anchoring the choice. The method grounding is in the
skill's `context/sources.md`.

**The human always picks.** The skill narrows and recommends; it never
auto-locks a name.

```shell
/naming:name-it-better # blind lenses → scored shortlist → human picks
/naming:name-it-better tournament # ~5 generators + elimination rounds for high-stakes names
```

`tournament` is an honest adaptation of elimination brackets plus pairwise
social-choice scoring — not a documented naming technique; the skill
presents it as such.

## Consumer conventions

- **Criteria source of truth.** The skill scores against the consuming
organization's naming and domain-language conventions when the project
declares them (its `CLAUDE.md` / `.claude/rules/` or a standards source
it points to). When none is declared, it falls back to the general
naming criteria grounded in the skill's `context/sources.md`. A criterion
the user wants that is missing from their conventions flows UP into those
conventions, not into the skill.
- **Adjacent capabilities.** Resolving what a domain concept IS routes to a
domain-modelling capability; propagating a chosen name across call sites
routes to a rename-references capability — each invoked through its slash
command when present, degrading to prose guidance when absent.

## Install

```shell
/plugin marketplace add melodic-software/claude-code-plugins
/plugin install naming@melodic-software
```

## Configuration

No `userConfig`. No persistent state. Network: the generators are
subagents; `context/sources.md` carries external reference links for the
method, not fetched at runtime.
122 changes: 122 additions & 0 deletions plugins/naming/skills/name-it-better/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
name: name-it-better
description: "Generate and evaluate fresh name candidates for anything — a variable, function, file, module, skill, repo, or domain term — then let the human pick. Use when the target name is still UNDECIDED: 'name it better', 'better name', 'that name is wrong', 'suggest names', 'what should I call this', 'need a name for', 'come up with a name', 'help me rename this to something better'. Not for an already-decided rename ('rename X to Y', 'I renamed X') — that routes to the rename-references sweep. Spawns blind fresh-context generators from distinct lenses; never auto-locks a name. Optional 'tournament' arg for high-stakes, hard-to-refactor names."
argument-hint: "[tournament]"
user-invocable: true
---

# Name it better

## Purpose

Produce better name candidates for anything that needs one — an
identifier, file, module, skill, repo, or domain term — and hand the
human a scored shortlist to choose from. The dominant trigger is a
reactive retry: a name was just suggested and rejected, and the same
context that produced it will only produce more of the same. So the
generators run BLIND to the conversation, from distinct lenses, to break
the anchor. A blank-slate naming request is the same machinery without a
rejected incumbent.

**The human always picks.** This skill narrows and recommends; it never
auto-locks a name.

## Criteria — cite the source of truth, do not copy it

Score against the consuming organization's naming criteria, resolved from
its own context, never from a baked-in path:

1. **Declared conventions win.** When the consuming project names where its
naming and domain-language conventions live — its `CLAUDE.md`,
`.claude/rules/`, a shared standards source it points to — score against
THAT. Read the criteria there; do not restate them here. A criterion the
user wants that is missing from those conventions flows UP into them
(their standards change), not hardcoded into this skill.
2. **None declared → the general criteria** grounded in
[`context/sources.md`](context/sources.md): intention-revealing and
semantically accurate to the responsibility, evolution-safe (the name
sets scope and bounds), context-sensitive, free of overloaded or
disinformative terms, and drawn from the domain's ubiquitous language.

## Default pass

1. **Distill a context brief.** Capture, in a few lines: the
responsibility of the thing, its scope and lifetime, hard constraints
(language casing rules, length, collisions to avoid), the existing
surrounding vocabulary, and a blocklist of overloaded terms to avoid.
This brief — NOT the conversation — is all the generators receive.
2. **Fan out blind generators.** Spawn ~3 fresh-context subagents, each
seeded ONLY with the brief (blind to this conversation and to each
other), each working a distinct lens:
- **responsibility-literal** — name exactly what it does;
- **moment-of-use** — name for how it reads at the call site;
- **domain-lore** — name from the domain's ubiquitous language.

Running them blind and independent is deliberate anti-anchoring; the
method grounding is in [`context/sources.md`](context/sources.md).
3. **Merge and score.** Pool the candidates, dedupe, and disqualify any
candidate that matches the rejected incumbent (if any) — carried by the
main thread as an explicit reject list, never shared with the
generators — or that collides with the existing vocabulary. Score every
surviving candidate against the criteria resolved above.
4. **Shortlist + recommend.** Present a short ranked list with a
one-line rationale per candidate and a single RECOMMENDED pick, marked
and listed first.
5. **Human picks.** Stop and let the user choose. Do not apply the name.

## `tournament` action

When `$ARGUMENTS` contains `tournament`, run this in place of the default
pass.

`/naming:name-it-better tournament` — for a high-stakes name that will be
hard to refactor later. Widen to ~5 generators (optionally different
models), then run elimination rounds with independent scoring judges until
one candidate remains, and present it plus the runners-up for the human
choice.
Comment thread
kyle-sexton marked this conversation as resolved.

The reject-list and collision disqualification from the default pass's
merge step still apply: pool the widened candidates and disqualify any that
match the rejected incumbent or collide with the existing vocabulary BEFORE
the elimination rounds begin — a rejected or colliding name must never enter
the bracket, let alone reach the finalist.

HONEST FRAMING: a "naming tournament / bracket" is NOT a documented
software-naming technique. This mode ADAPTS elimination brackets plus
pairwise social-choice scoring as a convergence mechanism — see
[`context/sources.md`](context/sources.md). Present it as such, not as an
established standard.

## Adjacent skills — hand off, do not overlap

- Resolving what a domain concept IS (not just its label) → a
domain-modelling capability. Hand a settled domain term there.
- Sweeping references after a rename is decided → a rename-references
capability. This skill picks the name; that one propagates it.

Invoke an adjacent capability through its slash command when present;
degrade to prose guidance when it is absent.

## What this skill does NOT do

- **Never auto-locks a name.** It always ends at a human choice.
- **Does not apply the rename.** Propagating a chosen name across call
sites is a rename-references capability's job.
- **Does not copy or invent criteria.** It scores against the resolved
source of truth; missing criteria route upstream, not into the skill.
- **Does not claim tournament mode is a documented technique** — it is an
adaptation, flagged as one.

## Gotchas

- If the generators are fed the conversation instead of just the brief,
the anti-anchoring purpose is defeated — they will re-derive the
rejected name. Seed them with the brief ONLY.
- A blind generator can still independently re-derive the rejected
incumbent (common for generic labels like `Manager` or `Context`). That
is not a blinding failure — the main thread's reject list disqualifies
it at merge time regardless of how a candidate was produced.
- A candidate that scores well but collides with existing vocabulary is
disqualified, not shortlisted — collision-check before scoring.
- `tournament` costs several generators plus judges; reserve it for names
that are genuinely expensive to change, not routine locals.
94 changes: 94 additions & 0 deletions plugins/naming/skills/name-it-better/context/sources.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Method sources — name-it-better

The naming CRITERIA are owned elsewhere (the consuming org's conventions —
see the skill body). This file grounds the skill's METHOD: how candidates
are generated, why generators run blind, and what the `tournament` mode is
actually adapted from. Read it only when judging a method question or
extending the skill. Tiers: PRIMARY = author's own words / official
spec; AUTHORITATIVE = faithful canonical write-up by the originators or
their collaborators; SECONDARY = derivative.

## Naming as a process (staged refinement)

The backbone of the default pass's distinct lenses. A name is refined
through stages rather than guessed in one shot: from missing/misleading,
to obvious-nonsense, to honest, to completely-honest, to
does-the-right-thing, to intent-revealing, to domain-abstraction. The
"responsibility-literal → moment-of-use → domain-lore" lenses map onto
the honest → intent → domain-abstraction progression.

- Origin, Arlo Belshee ("Read by Refactoring"):
`https://arlobelshee.com/good-naming-is-a-process-not-a-single-step/` —
PRIMARY. Flag: this host was DNS-unreachable during research, so Belshee's exact
per-stage prose is corroborated by the Deep Roots rewrite below rather
than quoted from the origin.
- Canonical rewrite, Tim Ottinger + Llewellyn Falco: [deeproots-series]
and [deeproots-path] — AUTHORITATIVE. Confirm the ordered stages and the
three-phase structure.

## Naming criteria lineage (Ottinger / Clean Code)

Backs the scoring rubric's shape (the authoritative criteria source of
truth is the consuming org's conventions).

- Ottinger's Rules: [ottinger-rules] — AUTHORITATIVE. Intention-revealing,
avoid disinformation, pronounceable, no encodings, one word per concept,
meaningful in context.
- Clean Code, ch. 2 "Meaningful Names" (Martin, with Ottinger):
`https://www.oreilly.com/library/view/clean-code-a/9780136083238/chapter02.xhtml`
— PRIMARY.

## Domain language

Backs the domain-lore lens and the "name from the shared domain
vocabulary" criterion.

- DDD Reference (Eric Evans): [ddd-reference] — PRIMARY.
- Ubiquitous Language (Fowler): [fowler-ubiquitous] — AUTHORITATIVE.

## Blind generation → human convergence (anti-anchoring)

Why generators run BLIND to the conversation and the human always makes
the final pick: diverge widely from independent perspectives, then
converge once — and keep the first-seen suggestion from anchoring the
choice.

- Double Diamond (diverge/converge), UK Design Council: [double-diamond]
— AUTHORITATIVE.
- Anchoring bias, Tversky & Kahneman (1974), "Judgment under Uncertainty":
`https://www.science.org/doi/10.1126/science.185.4157.1124`
(open PDF: [tk-1974-pdf]) — PRIMARY. First value seen biases
the final judgment; independent-before-shared review reduces it.

## `tournament` mode — adapted, NOT a documented naming technique

HONEST FLAG: there is no primary source describing a "naming tournament"
or "naming bracket" method for choosing identifiers. The mode is an
ADAPTATION, presented as a local convergence mechanism, not an
established naming standard. It borrows two documented, unrelated things:

- Elimination brackets (single/double elimination): [elim-bracket] —
SECONDARY (generic, not naming).
- Pairwise social-choice aggregation (Condorcet / Copeland / Minimax) for
turning head-to-head judgements into a ranking: [condorcet] — the
rigorous basis if judges score candidates pairwise.

## Framework / style-guide naming (supporting)

- .NET naming guidelines (Microsoft): [dotnet-naming] — PRIMARY.
- Kevlin Henney, "Seven Ineffective Coding Habits" (naming): [henney] —
PRIMARY. Meaning over word-count; "adding words is not adding meaning".
- Google style guides (per-language naming): [google-style] — PRIMARY.

[deeproots-series]: https://www.digdeeproots.com/articles/naming-process/naming-as-a-process/
[deeproots-path]: https://www.digdeeproots.com/articles/naming-process/naming-as-a-process-learning-path/
[ottinger-rules]: https://exelearning.org/wiki/OttingersNaming/
[ddd-reference]: https://www.domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf
[fowler-ubiquitous]: https://martinfowler.com/bliki/UbiquitousLanguage.html
[double-diamond]: https://en.wikipedia.org/wiki/Double_Diamond_(design_process_model)
[tk-1974-pdf]: https://www.cs.tufts.edu/comp/150AIH/pdf/TverskyKa74.pdf
[elim-bracket]: https://en.wikipedia.org/wiki/Double-elimination_tournament
[condorcet]: https://en.wikipedia.org/wiki/Condorcet_method
[dotnet-naming]: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines
[henney]: https://www.infoq.com/presentations/7-ineffective-coding-habits/
[google-style]: https://google.github.io/styleguide/
Loading
Loading