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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ user opts in with `/plugin enable`; an existing install is never flipped by cata
- [`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, route resolved domain language to the domain-driven-design glossary steward, explore the design space, stress-test adversarially, and produce a structured implementation plan with an approval gate.
- [`domain-driven-design`](plugins/domain-driven-design) — Domain-driven-design practice skills. Today: actively maintains a consuming project's ubiquitous-language glossary — resolves ambiguous or overloaded terms, records canonical language and rejected synonyms, sharpens what-it-IS definitions, and routes entries to already-known bounded contexts without discovering boundaries.
- [`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.
- [`naming`](plugins/naming) — Generates and evaluates fresh name candidates for anything — an identifier, file, module, skill, repo, or domain term — by distilling a structured context brief, fanning out blind, fresh-context generators from distinct lenses (responsibility-literal, moment-of-use, domain-lore), then scoring a shortlist against a research-ordered criteria priority resolved from 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
4 changes: 2 additions & 2 deletions plugins/naming/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"$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.",
"version": "0.2.0",
"description": "Generates and evaluates fresh name candidates for anything — an identifier, file, module, skill, repo, or domain term — by distilling a structured context brief, fanning out blind, fresh-context generators from distinct lenses (responsibility-literal, moment-of-use, domain-lore), then scoring a shortlist against a research-ordered criteria priority resolved from 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"
Expand Down
38 changes: 38 additions & 0 deletions plugins/naming/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,44 @@
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.2.0]

### Changed

- **Structured context brief.** The loose "distill a brief" step is now a
brief with named fields — responsibility, firing/usage context, scope
boundaries (what it is NOT), collision vocabulary, and word-level
blocklist (with reasons) — mirroring the replicated concept → word →
structure naming model. The generators receive this brief, and only this
brief; rejected incumbent NAMES stay on the main-thread reject list and
never enter it.
- **Declared criteria priority.** The fallback general criteria are now
research-ordered — semantic accuracy (anti-misleading) > scope fit >
comprehensibility > trigger/evocative utility — and this ordering governs
scoring and judging. A consuming project's declared conventions still
override it.

### Added

- **Rejection-reason iteration protocol.** A rejected candidate's REASON is
captured as an explicit new brief constraint (a word-level blocklist
entry, a scope-boundary correction, or a criteria reweight) and fed into
the next blind round; rejected names and words never re-enter.
- **Modality layer.** Criteria split into a universal semantic layer and a
modality/vendor-specific syntactic layer; documented style conflicts
(abbreviation policy, acronym casing, casing style) route to the
consuming ecosystem's own style guide rather than a house verdict. For
Claude Code skills, the description — not the name — drives discovery, so
the name optimises for human semantic accuracy.
- **Strengthened domain-concept pointer.** When the target is a domain
concept, route to a domain-modelling capability to settle what it IS
before naming it (pointer only).
- **Research grounding.** `context/sources.md` adds the primary empirical
sources behind the criteria priority (Feitelson TSE 2022, Alpern 2024
reproduction, Avidan & Feitelson 2017, Hofmeister 2017) and the modality
layer (clig.dev, Claude Code skills docs, the conflicting style guides),
and honestly marks paywalled book sources as Tier-2-for-verification.

## [0.1.0]

### Added
Expand Down
14 changes: 9 additions & 5 deletions plugins/naming/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ lenses, then hand the human a scored shortlist to choose from.
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
a structured context brief (responsibility, firing context, scope
boundaries, collision vocabulary, word-level blocklist — rejected NAMES
stay on the main thread's reject list, never in the brief), each
working a distinct lens (responsibility-literal, moment-of-use,
Comment thread
kyle-sexton marked this conversation as resolved.
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`.
Expand All @@ -37,9 +40,10 @@ presents it as such.
- **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
it points to). When none is declared, it falls back to a research-ordered
general criteria priority — semantic accuracy first, trigger utility last
— 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
Expand Down
135 changes: 116 additions & 19 deletions plugins/naming/skills/name-it-better/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,81 @@ its own context, never from a baked-in path:
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.
[`context/sources.md`](context/sources.md), applied in this
research-ordered priority — a higher tier breaks ties over every tier
below it:
1. **Semantic accuracy (anti-misleading).** The name must not lie about
what the thing does. A misleading name is empirically worse than a
vague or meaningless one, so this outranks everything below.
2. **Scope fit.** Length and detail scale with the thing's scope and
lifetime; never repeat information the surrounding context (package,
type, module) already supplies.
3. **Comprehensibility.** Prefer full, intention-revealing words over
abbreviations — bounded: established idioms and conventionally short
names (loop `i`, a receiver) are not penalised.
4. **Trigger / evocative utility.** How well the name cues recall at the
moment of use — a genuine tiebreaker, but the lowest-priority one.

This ordering governs the scoring and judging steps. It is the fallback
only: a consuming project's declared criteria (rule 1) override it
wherever the two differ.

## Semantic vs syntactic — the modality layer

Naming criteria split in two. The **semantic layer** — accuracy, scope
fit, no collisions, noun-for-a-thing / verb-for-an-action — carries across
every modality, and is what the generators and judges optimise. The
**syntactic layer** — casing, length budgets, separator and affix
conventions — is modality- and vendor-specific; apply it as a final
shaping pass over the semantic winners, never as a scoring axis that
overrides meaning. Shaping can change the string, so RE-RUN the full
merge-step filter set — dedupe, collision, reject-list, word-blocklist —
on the shaped forms: two distinct candidates can normalize to one string
(`SessionStore` and `session-store` → `session_store`), a normalization
can recreate an existing sibling or a rejected incumbent, and a required
affix can introduce a blocked word (`Order` → `OrderManager`) that the
pre-scoring filters could not match.

- **Route documented conflicts out; do not pick a side.** Where authorities
genuinely disagree — abbreviation policy, acronym casing, camelCase vs
snake_case — this skill takes no house position. Defer to the consuming
ecosystem's own style guide (rule 1's declared conventions); the
conflicting primaries are catalogued in
[`context/sources.md`](context/sources.md).
- **Claude Code skills are the sharp special case.** For a skill, the
DESCRIPTION — not the name — is what drives model-side discovery. So
optimise the name for human semantic accuracy, and put the trigger
phrases and example requests in the description, not the name.

## 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.
1. **Build the structured context brief.** This brief — NOT the
conversation — is all the generators receive, so it must carry every
field they need, each captured by name:
Comment thread
kyle-sexton marked this conversation as resolved.
- **Target modality** — what KIND of thing is being named (function,
type, module, file, CLI command, skill, domain term): it fixes
noun-for-a-thing vs verb-for-an-action and tells the final shaping
pass which syntactic conventions apply.
Comment on lines +87 to +90

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Carry resolved syntax constraints in the generator brief

For a request whose convention is not determined by the target kind (for example, a function in a Python versus JavaScript project), target modality alone cannot select casing, separators, affixes, or length limits. The replacement brief no longer includes the old hard language constraints, and generators receive only this brief, so neither they nor the final shaping pass are instructed with the consuming ecosystem's resolved syntactic convention; this can emit names in the wrong required form. Include the language/ecosystem or the resolved syntactic constraints as a brief field.

Useful? React with 👍 / 👎.

- **Responsibility** — what the thing DOES, in one line.
- **Firing / usage context** — when it is reached for, and how it reads
at the call site.
- **Scope boundaries** — what it is NOT: the adjacent things it must not
be confused with or blur into.
- **Collision vocabulary** — the existing sibling names it must not
duplicate.
- **Word-level blocklist** — individual words ruled out, each WITH its
reason (overloaded, misleading, collides, already rejected).

Rejected incumbent NAMES deliberately stay out of the brief — the main
thread holds them as its reject list and disqualifies matches at merge
time (anti-anchoring: a generator shown a rejected name re-derives it).
Only the abstracted REASON a name failed enters the brief, as a
blocklist entry or scope-boundary correction.

The brief mirrors the replicated concept → word → structure naming model
(grounded in [`context/sources.md`](context/sources.md)): the named
fields fix the concepts and constraints; the generators then choose the
words per concept and arrange the structure.
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:
Expand All @@ -57,13 +120,37 @@ its own context, never from a baked-in path:
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.
generators — that contains a word-level blocklist entry (a generator
can miss the brief's constraint; the merge step enforces it), or that
Comment thread
kyle-sexton marked this conversation as resolved.
collides with the existing vocabulary. Score every
surviving candidate against the criteria resolved above, breaking ties
by their declared priority order.
Comment thread
kyle-sexton marked this conversation as resolved.
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.

## Iterate on the rejection reason

If the human rejects the shortlist or a specific candidate, the rejection
is data, not a dead end. Capture the REASON as an explicit new constraint
and fold it into the next round's brief before regenerating:

- a word that drew the objection becomes a **word-level blocklist** entry,
carrying that reason;
- a "wrong scope / wrong thing" objection becomes a **scope-boundary**
correction;
- a "these all miss what matters" objection **reweights the criteria** for
the next round — but only within the space the consuming project's
declared conventions leave open. Declared conventions still win: a
rejection that contradicts them routes upstream as a proposed convention
change, never a silent local reweighting.

Rejected names and rejected words never re-enter — the reject list and the
word-level blocklist only grow across rounds. Each new round is a fresh
blind fan-out seeded with the corrected brief, never a patch of the last
round's candidates.

## `tournament` action

When `$ARGUMENTS` contains `tournament`, run this in place of the default
Expand All @@ -75,10 +162,11 @@ models), then run elimination rounds with independent scoring judges until
one candidate remains, and present it plus the runners-up for the human
choice.

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 reject-list, word-level-blocklist, and collision disqualification from
the default pass's merge step still apply: pool the widened candidates and
disqualify any that match the rejected incumbent, contain a blocklisted
word, or collide with the existing vocabulary BEFORE the elimination
rounds begin — a rejected, blocklisted, or colliding name must never enter
the bracket, let alone reach the finalist.

HONEST FRAMING: a "naming tournament / bracket" is NOT a documented
Expand All @@ -89,10 +177,13 @@ 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.
- **The target is a domain concept.** Naming a domain term well depends on
first settling what the concept IS, not just its label. Route that to a
domain-modelling capability, then name the settled concept once it
returns. Pointer only — this skill does not do the domain modelling.
- **A rename is already decided.** Sweeping references after the fact →
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.
Expand All @@ -106,6 +197,9 @@ degrade to prose guidance when it is absent.
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.
- **Does not pick a house side on documented style conflicts** —
abbreviation policy, acronym casing, and casing style route to the
consuming ecosystem's own style guide, never a baked-in verdict.

## Gotchas

Expand All @@ -118,5 +212,8 @@ degrade to prose guidance when it is absent.
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.
- A rejected candidate's REASON must become a brief constraint (a blocklist
word, a scope correction, a criteria reweight) before the next round, or
the blind fan-out re-derives the same reject.
- `tournament` costs several generators plus judges; reserve it for names
that are genuinely expensive to change, not routine locals.
Loading
Loading