agentsclimarketplace

Find concept divergence

Skill KhurrumMahmood/senior-vibe-engineer/.claude/skills/find-concept-divergence

Advisory SUSPECT scan that surfaces concept-name drift between the canonical glossary at `.claude/contracts/concepts.yaml` and the codebase / docs. Detects three drift bands: `avoid_term_hit` (code uses a phrasing the glossary explicitly says is wrong), `competing_term_coexistence` (a `flagged_ambiguities` entry has multiple `competing_terms` present in the same file — drift the glossary author has not yet resolved), and `superseded_co_occurrence` (both a deprecated name and its `superseded_by:` replacement appear in the same file — rename transition drift). Detection only — never edits code or docs.From its SKILL.md

Install
npx -y skills add KhurrumMahmood/senior-vibe-engineer --skill find-concept-divergence

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

17.5 KB, ~4.0k tokens by cl100k_base, as published. Nobody here has run it

/find-concept-divergence

Kotlin/JVM 2.4.10 branch

Trigger this branch only for a manifest-selected .kt target and an explicit host glossary. Keep sibling _kotlin, read ../_kotlin/GUIDE.md, and enter through scripts/scan_kotlin.py. Exact authored identifier-token hits are lexical review evidence only; aliases, extensions, operators, delegated members, strings/comments, symbol identity, generated sources, Java, Gradle variants, reflection, runtime behavior, and rename completeness remain unresolved.

C# 14 / .NET 10 branch

Use scripts/scan_csharp.py with the sibling _csharp provider and an explicit glossary; run it with --help for the exact CLI. It matches strict glossary terms against authored Roslyn identifier tokens from the current compiled manifest closure. A hit is spelling evidence, not resolved symbol identity or rename completeness.

C++20 branch

Use scripts/scan_cpp.py with the sibling _cpp provider; run the script with --help for the exact CLI. It reports strict glossary spelling only across a current complete C++20 compiler-owned source/header snapshot while retaining namespace, signature, and overload context. Text hits do not prove symbol identity, ODR/ABI, specializations, dispatch, or external variants.

C17 branch

Use scripts/scan_c.py with the sibling _c/c_lexical_facts.py provider; run python3 scripts/scan_c.py --help for the exact CLI. This external-library branch emits strict glossary-backed authored-text evidence only. Comments and strings may be review noise; macro expansion, symbol identity, rename completeness, C++, and Objective-C remain unresolved.

Dart v1

Dart v1 is strict glossary-backed text evidence over authored library source. Copy the sibling _dart/dart_project_snapshot.py; the scan excludes generated, test, example, vendor, build, report, part, barrel, and symlink roles and makes no symbol-identity or rename-completeness claim.

SKILL_ROOT=".agents/skills/on-demand/find-concept-divergence"
python3 "${SKILL_ROOT}/scripts/scan_dart.py" \
  --project-root "$PWD" --dart-root lib \
  --glossary "$PWD/.claude/contracts/concepts.yaml" \
  --output "$PWD/reports/find-concept-divergence/dart/findings.jsonl" \
  --report "$PWD/reports/find-concept-divergence/dart/report.md" \
  --direct-test "${DART_DIRECT_TEST:?Set a dependency-free direct test path}" \
  --smoke-entrypoint "${DART_SMOKE:?Set a direct smoke entrypoint}" \
  --expected-smoke "${DART_EXPECTED_SMOKE:?Set its exact stdout without the newline}"

You are running an advisory concept-glossary divergence audit. The goal is to surface places in the codebase or docs where:

  1. avoid-term hits — code uses a phrasing that the glossary explicitly lists under a concept's avoid: block (the glossary author has said "do not use this phrasing for this concept").
  2. competing-term coexistence — a file contains multiple competing_terms from a flagged_ambiguities entry (an open ambiguity has bled into runtime — two competing names for the same concept are co-occurring in the same module).
  3. superseded co-occurrence — a file mentions both a deprecated concept name and its superseded_by: replacement (rename transition drift; redundant with coverage_lint:-declared lints).

This skill is detection-only. It never edits code, docs, or the glossary; it writes a report under reports/find-concept-divergence/scan-<UTC>/ so a follow-up audit can act on the findings.

Host-language boundary

The host code language is not a routing constraint: this is a strict textual glossary scan. It reads .py, .js, .jsx, .mjs, .cjs, .ts, .tsx, template/HTML, and prose files. It does not parse JavaScript or TypeScript, resolve imports, infer types, or judge JSX runtime behavior. Generated, vendor, test, minified, and symlinked sources remain excluded by strict path-level rules; identifier-like terms use lexical word boundaries, not fuzzy or substring matching.

Go support is an explicit --language go strict-text mode, not an inference from the generic suffix walk. It inventories every selected .go and _test.go file before excluding test, generated, vendor, and symlink surfaces. The python-strict-text analyzer applies the same exact term boundaries to eligible UTF-8 source; it does not parse Go syntax, packages, build tags, identifiers, comments, or string literals.

The automatic non-Go surface remains scans: [python, javascript, typescript, markdown, templates]; only explicit Go mode promotes Go files into the supported inventory/status contract.

Java support is likewise explicit rather than part of the automatic suffix walk. Read references/java.md only for a Java run; it defines the source-role inventory, native fixture check, and strict-text non-claims. This extends the preserved scans: [python, javascript, typescript, go, markdown, templates] contract with one separately selected Java band.

Rust is a separate strict-text mode over authored .rs source. It uses the copied _rust/rust_lexical_facts.py inventory/native gate and records exact glossary-term spans and hashes; generated, vendor, target/build, test, auxiliary, configuration, and symlink roles remain visible but cannot fire. This is textual evidence, not symbol identity or semantic equivalence.

SKILL_ROOT=".agents/skills/on-demand/find-concept-divergence"
REPORT_DIR="$PWD/reports/find-concept-divergence/rust"
python3 "${SKILL_ROOT}/scripts/scan_rust.py" \
  --project-root "$PWD" \
  --glossary "$PWD/.claude/contracts/concepts.yaml" \
  --output "${REPORT_DIR}/findings.jsonl" \
  --report "${REPORT_DIR}/report.md" .

The copied closure must include sibling _rust/rust_lexical_facts.py.

External strict-text variants

For PHP, Ruby, or Swift, load the selected skill with its sibling language provider and read that provider's on-demand guide before execution:

These are glossary-backed authored-text scans, not symbol or conceptual identity. The guides own the exact commands, native gates, and non-claims.

How success is judged

  • The run is graded only by artifacts: pasted command output plus findings.jsonl and report.md. Do not claim concept drift was checked without those files.
  • The scan verdict is one of clean, real-drift, glossary-gap, noise-only, or scan-blocked. A mixed report may name multiple row-level triage labels, but the run-level verdict should state the most important next action.
  • Every row-level triage decision cites the report row and the relevant glossary entry. Code claims without the glossary evidence are not enough for a concept-divergence verdict.
  • The skill remains read-only. It can recommend a rename, glossary update, ADR, exclusion, or lint handoff; it never edits the glossary, code, docs, or lint rules in this run.
  • Go scan.json status is exactly one of complete, partial, unsupported, or failed. The Markdown report repeats it. Missing/old Go, unreadable eligible source, and Go tool failures must never become clean.
  • Java uses the same status vocabulary in scan.json, but strict-text scanning does not depend on a JDK. Unreadable eligible source cannot become clean.

Glossary source

The canonical glossary is .claude/contracts/concepts.yaml. The detector reads:

  • concepts[].name, concepts[].aliases, concepts[].avoid, concepts[].superseded_by, concepts[].source, concepts[].coverage_lint
  • flagged_ambiguities[].competing_terms

If the glossary is missing or unparseable the scan exits with a clear error rather than degrading silently — concept-divergence detection has no meaningful default behavior without it.

Copied installs use a schema-specific stdlib profile, not a general YAML engine: normal block lists and scalar flow lists are supported; quoted flow values preserve commas (single quotes or JSON-style double quotes). Nested flow collections and other unsupported shapes stop the scan with a parse error rather than becoming different search terms. Normalize those entries to the documented block-list shape before running the scan.

Schema convention: competing_terms: vs overload ambiguities

competing_terms: is for terms that genuinely compete for the same concept slot — rename transitions, parallel implementations of the same thing, or two names that mean the same thing fighting for canonicality. Band 2 (competing_term_coexistence) treats a file containing 2+ of these as drift, which is the right semantics for true competition.

Do not use competing_terms: for overload cases where the named terms are typed names for distinct things that share a noun (e.g. distinct stores with overlapping prose, or distinct entities that each carry the same generic English word in their slug). For those, document the typed senses under where: and let the canonical concept's avoid: block catch the actual drift signal (bare generic-noun usage in prose / log strings) via band 1.

Default target

If the caller does not provide paths, the scanner walks a portable set of common project roots — language- and framework-agnostic — and auto-skips any that don't exist in the host repo:

app/, src/, lib/, scripts/, tests/, docs/,
.claude/skills/, .claude/docs/,
CONTEXT.md, README.md, ONBOARDING.md,
CLAUDE.md, .claude/CLAUDE.md

Out-of-scope paths (always excluded): .venv/, node_modules/, .git/, dist/, build/, __pycache__/, .pytest_cache/, .mypy_cache/, .ruff_cache/, */migrations/ (Django-shaped), ai-docs/decisions/ (ADRs intentionally name both sides of a rename), .claude/worktrees/ (agent worktrees), reports/ (runtime output), *.worktree/. Host projects extend the prefix exclusion list via .claude/skills/find-concept-divergence/host_excludes.txt (one path-prefix per line; comments via #).

Exclusions are evaluated against the logical path relative to --project-root, including a directly named file or directory. The walk never traverses a directory symlink, even when that symlink or one of its descendants is the direct target; an alias below an excluded logical directory cannot bypass that exclusion. Files/symlinks resolving outside the project root are rejected. Therefore a host may itself live below an ancestor named node_modules, while its own dependency tree and escaped symlink targets remain out of scope.

Pipeline

SCAN_ID="scan-$(date -u +%Y%m%d-%H%M%S)"
REPORT_DIR="reports/find-concept-divergence/$SCAN_ID"
mkdir -p "$REPORT_DIR"

.venv/bin/python .claude/skills/find-concept-divergence/scripts/scan.py \
  --output "$REPORT_DIR/findings.jsonl" \
  --report "$REPORT_DIR/report.md"

Scan targets, finding labels, and the glossary default (<project-root>/.claude/contracts/concepts.yaml) anchor on --project-root, which defaults to the git toplevel of the cwd (else the cwd).

For a bounded target or non-default glossary, pass the flags explicitly:

.venv/bin/python .claude/skills/find-concept-divergence/scripts/scan.py \
  --output "$REPORT_DIR/findings.jsonl" \
  --report "$REPORT_DIR/report.md" \
  --glossary .claude/contracts/concepts.yaml \
  .claude/skills/find-concept-divergence

The scan writes:

  • findings.jsonl — one record per hit; fields band, concept or ambiguity_id, file, line, match, term.
  • report.md — grouped summary by band, sorted by concept then file.
  • scan.json — Go tool/version evidence, full Go inventory, eligibility reasons, and analysis status when --language go is selected.

Go copied-closure pipeline

Use Go >= 1.22.0 discovered from PATH; the fixture/native oracle remains the host's own go test ./...:

CONCEPT_SKILL="$PWD/.agents/skills/find-concept-divergence"
CONCEPT_REPORT="$PWD/reports/find-concept-divergence/scan-go"
mkdir -p "$CONCEPT_REPORT"
python3 "${CONCEPT_SKILL}/scripts/scan.py" \
  --project-root "$PWD" --language go \
  --output "$CONCEPT_REPORT/findings.jsonl" \
  --report "$CONCEPT_REPORT/report.md" .
go test ./...

The strict-text outcome remains valid when eligible Go source is syntactically malformed because the claim is textual co-occurrence, not parse validity. Invalid UTF-8 or a read failure is different: it leaves a failed inventory row and makes the result partial.

Output triage

Classify each finding into one of:

  • real drift — code says one thing, glossary says another; promote to a quality/findings.jsonl entry (or the host project's equivalent) with band-appropriate recommendation (rename, glossary update, ADR).
  • glossary gap — the term in code is fine but the glossary lists a stale avoid: phrasing or hasn't registered a real synonym; update concepts.yaml and re-run.
  • noise — false-positive (term appears inside a string literal or comment that's intentionally quoting deprecated naming). Skip; if the same noise recurs across multiple scans, narrow the avoid: phrase, add the file's prefix to host_excludes.txt, or move the case to a typed-name where: block instead of competing_terms:.

If you dispatch an Agent to triage the report, give it this verdict contract: each row must be labeled real drift, glossary gap, or noise, and each label must cite both the report row and the glossary entry. Agent output without those citations is not evidence.

Strict-first principle

v1 is strict only: it grep-matches the canonical names, aliases, avoid phrasings, and competing-terms slugs verbatim (word-boundary, case-insensitive). It does not do similarity matching, stem analysis, or fuzzy identifier comparison. Add similarity flagging only if the strict pass produces nothing real over multiple cycles.

If the strict pass produces noise, narrow the avoid: phrases in concepts.yaml (more specific, more identifier-like) or add a host_excludes.txt entry — don't add heuristics to the body.

Replay check

After editing this skill or its detector contract, run:

.venv/bin/python .claude/skills/find-concept-divergence/scripts/scan.py --help
SCAN_ID="scan-replay"
REPORT_DIR="/tmp/find-concept-divergence-${SCAN_ID}"
mkdir -p "$REPORT_DIR"
.venv/bin/python .claude/skills/find-concept-divergence/scripts/scan.py \
  --output "$REPORT_DIR/findings.jsonl" \
  --report "$REPORT_DIR/report.md" \
  .claude/skills/find-concept-divergence

This bounded self-scan is the replay case for text/contract repairs. It proves the documented argparse surface and output contract execute against the current glossary; it does not prove the full repo is clean.

When things go sideways

SymptomAction
.claude/contracts/concepts.yaml is missing or unparseableMark scan-blocked, paste the error, and stop; concept-divergence has no useful fallback without the glossary.
The report has hits but the glossary entry is ambiguousUse row label glossary gap, cite the entry, and recommend updating concepts.yaml before renaming code.
A hit appears only in a deliberate quote of deprecated terminologyLabel it noise, cite the surrounding line, and only add an exclusion if the same noise recurs.
A superseded concept declares coverage_lintTreat that lint as owning the rename guard; do not double-count skipped co-occurrence noise as scanner drift.
Agent triage omits glossary citationsReject the dispatch output and read the report/glossary directly.
Go is missing or older than 1.22.0Preserve the unsupported report/scan.json, restore Go >= 1.22.0 on PATH, and re-run.
An eligible Go file cannot be decodedKeep the report partial and cite the failed inventory row; never treat the remaining scan as complete.
An eligible Java file cannot be decodedKeep the report partial and cite the failed inventory row; malformed Java syntax remains valid strict-text input.

What ships with it: 11 files

100.4 KB alongside SKILL.md, 10 of them executable

references/

scripts/

Keep looking

Skills are one crate of 326,452. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.