Repository navigation
feat(vocabulary): split, classify, weight (M19a) - #27
Open
jgrodziski wants to merge 4 commits into
Open
jgrodziski wants to merge 4 commits into
jgrodziski wants to merge 4 commits into
Conversation
New package @codegraph/vocabulary (PLAN.md §20.1). splitIdentifier(name, kind, lexicon) breaks on every character that is not a letter, a mark or a digit, then on camel-case boundaries read from Unicode categories: lower→Upper, digit→Upper, and an Upper run before Upper+lower. A digit run stays with its word (utf8, md5, v2); a piece of digits only is dropped and counted. The lexicon adds the conventional names skipped whole, the file kinds whose extension is no word, and C#'s I prefix. Hand tables per language, read through each shipped lexicon, the unicode fixture, and fast-check properties: words are lowercase slices of the name, a separator splits a name into its parts' words. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
createClassifier(lexicon, technical) tags each word, in this order: keyword (the lexicon reserves it), short (one letter or digit, marks excluded), technical (the shared list ∪ the profile's), else domain. A keyword the splitter never yields whole (`defined?`, `__FILE__`) classifies nothing: the `file` of `upload_file` is not `__FILE__`. DEFAULT_TECHNICAL is the plumbing every language shares. Words two or more lexicons listed (args, opts, ctx, err, callback, json, str, mutex, mixin, async, repo) move into it and out of the profiles, as METAMODEL §5.3 already says a profile's list is what lies beyond the shared one; a test keeps the two disjoint. The website profiles page is regenerated from the CLI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
roleOf(entity, slots) reads traits, never the kind: TModule → module, TType → type, TInvocable → operation, TStructural → parameter or local when an entity lists it in parameters[] / localVariables[], else attribute. A named entity with none of these (a TS namespace, a PHP code file, a Python decorator) is `other`: principle 1 says its words still count. DEFAULT_WEIGHTS: module and type 8, attribute 4, operation 3, parameter, local and other 1. On the fixtures, every listed parameter and local resolves; the C# indexer's parameter is listed nowhere (a property has no TWithParameters in that profile), weighs as an attribute, and is pinned by id until the model lists it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
§20.1 states the digit and caseless-letter rules of the split, the properties as tested, the keyword spellings that classify nothing, the shared technical list (125 words, disjoint from every profile's), the `other` role and the C# indexer parameter the model lists nowhere. §20.4 ticks the three modules and keeps aggregate, artifact and drift open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
codegraph | c5bfa7a | Commit Preview URL Branch Preview URL |
Oct 23 2026, 10:54 PM |
This was referenced Oct 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second step of the word cloud / glossary (#6), milestone M19a in PLAN.md §20. Stacked on #26: review that one first; this PR's diff is the four commits after it.
It adds a new package,
@codegraph/vocabulary, that turns one name into the words it is made of, tags each word, and says how much a word weighs given what carries the name. Pure computation over the model's names (never source), depending on@codegraph/corealone. Nothing calls it yet: PR 3 aggregates over a model with it, PR 4 adds the CLI command.Splitting a name
splitIdentifier(name, kind, lexicon)→{tokens, numeric, conventional}.toString,__init__,handle_call) gives no word, and says so.fileKindsloses its extension (order_service.rb→order_service); a leading dot (.eslintrc) is not one.interfacePrefixdrops theIofIOrderService, never ofIOorIOError.<=>,this[],::and/need no per-language separator list.HTTPServer→http,server. Digits stay with their word (utf8,i18n); a piece of digits only is dropped and counted innumeric. A caseless letter (注,𠀀) counts as lower; a combining mark never splits.Tests: a hand table per language (all eleven), the
fixtures/unicodecorpus (no U+FFFD, no lone surrogate), and fast-check properties (words only, lowercase, slices of the lowered name, deterministic,a + sep + bsplits asathenb, conventional names give nothing). Removing the acronym rule fails 8 tests, removing the interface prefix fails 10.Classifying a word
createClassifier(lexicon, technical?)tags each word, in this order:keyword: the lexicon reserves it. A keyword that is not a word (Ruby__FILE__) can never match, so thefileofupload_filestays a domain word.short: one letter or digit, counted in code points.id,io,dbare words.technical: the sharedDEFAULT_TECHNICALlist (125 words, the PLAN seed included) ∪ the profile's owntechnical.domain: everything else.Nothing is filtered: a consumer decides what to show (PLAN §20 principle 3). The shared list is overridable whole; the profile's own words still apply.
Shared words moved out of the profiles. Eleven words some profiles listed are plumbing in every language:
args,async,callback,ctx,err,json,mixin,mutex,opts,repo,str. They now live once inDEFAULT_TECHNICAL, and a test keeps it disjoint from every profile's own list. Without the move, a Java corpus would countargsandjsonas domain words. (repowas Elixir's alone; it moved becauserepositoryis already shared. The commit body of 60c3148 says otherwise, wrongly.) The website profiles page is regenerated.Roles and weights
roleOf(entity, slots)reads the role from traits, never the kind, first match wins:TModule→ module,TType→ type,TInvocable→ operation,TStructural→ parameter / local / attribute (by whether some entity'sparametersorlocalVariableslists it), elseother. A property test pins that the kind is never read.other. Five shipped kinds have no role trait:clj:implBlock,php:codeFile,python:decorator,rust:impl,ts:namespace. Three of them are named, and every name's words count, so they weigh 1. One consequence: a PHP code file weighs 1, while Ruby and Elixir files weigh 8 as modules, because that is what their traits say.this[int index]is a child of itsproperty, and the C# profile gives a property noTWithParameters, so no list names it and it weighs as an attribute. The fixture test pins that one id rather than guessing from the kind; the fix belongs in the C# profile and extractor.Also
eslint.config.js: the package is inside the no-DOM boundary; CLAUDE.md lists it withcore,analyzer,city,navigator.aggregate.ts,artifact.tsanddrift.tsas still to do.Verification
pnpm -r buildandpnpm -r typecheckgreen; lint clean on touched files;pnpm run gen:schemasleavesschemas/unchanged.node:sqlite; theexplainno-key test withOPENROUTER_API_KEYset).Part of #6.
🤖 Generated with Claude Code