Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
1c410a1
feat(vocabulary): split a name into its words
Oct 23, 2026
60c3148
feat(vocabulary): classify words
Oct 23, 2026
26fee22
feat(vocabulary): roles and weights
Oct 23, 2026
c5bfa7a
docs(plan): split, classes and roles as built
Oct 23, 2026
d7106bc
feat(core): qualified kinds in the lexicon
Oct 25, 2026
b99d104
feat(vocabulary): split the qualifier off a name
Oct 25, 2026
cde7ed3
feat(vocabulary): aggregate into vocabulary.json
Oct 25, 2026
9df387b
test(fixtures): vocabulary.json snapshots
Oct 25, 2026
2b1bdf3
docs(plan): qualifiers, aggregation, artifact as built
Oct 25, 2026
302606e
feat(vocabulary): drift against business terms
Oct 26, 2026
274d394
feat(vocabulary): an operation's words on demand
Oct 26, 2026
1fb328f
feat(vocabulary): read a technical list from text
Oct 26, 2026
8ae0aaf
refactor(cli): share the view label
Oct 26, 2026
9257657
feat(cli): codegraph vocabulary
Oct 26, 2026
6a0ebcd
docs: codegraph vocabulary and vocabulary.json
Oct 26, 2026
294e5cc
docs(plan): the vocabulary command as built
Oct 26, 2026
3799f70
fix(vocabulary): machinery words leaked as domain
Oct 26, 2026
666a3ec
docs(plan): the vocabulary coverage measured
Oct 26, 2026
d652f80
feat(vocabulary): lay out a word cloud
Oct 26, 2026
53e6f51
feat(vocabulary): draw a cloud as SVG
Oct 26, 2026
d975f1d
feat(cli): codegraph vocabulary --svg
Oct 26, 2026
97d13d3
docs: the vocabulary cloud and its demo image
Oct 26, 2026
9ba26fa
docs(plan): the vocabulary cloud as built
Oct 26, 2026
d528809
refactor(vocabulary): one reading rule per entity
Oct 26, 2026
15ca436
feat(vocabulary): the carriers of a scope's term
Oct 26, 2026
26f20e6
feat(vocabulary): a browser entry for the cloud
Oct 26, 2026
d5b2b41
feat(cli): serve the vocabulary and its carriers
Oct 26, 2026
7e5e0d9
feat(cli): the app's job builds the vocabulary
Oct 26, 2026
5f3bce2
feat(navigator-ui): the Vocabulary tab
Oct 26, 2026
0fa83e2
docs: the Vocabulary tab and the carriers lookup
Oct 26, 2026
14a97a0
docs(plan): the tab and the carriers as built
Oct 26, 2026
1888780
feat(cli): vocabulary:<word> as a city metric
Oct 26, 2026
1a07e3a
fix(viz): help no longer says height is code
Oct 26, 2026
18a2899
docs: vocabulary:<word> in the city's metrics
Oct 26, 2026
d265d2a
docs: the vocabulary demo images in the README
Oct 26, 2026
7c6c761
docs(website): the navigator tutorial's six tabs
Oct 26, 2026
8ec53a8
docs(plan): the city channel as built
Oct 26, 2026
512210d
test(vocabulary): closure check asserts once
Oct 27, 2026
f169f0c
merge: the closure check asserts once
Oct 27, 2026
449f2fc
merge: the closure check asserts once
Oct 27, 2026
d5969eb
merge: the closure check asserts once
Oct 27, 2026
c1016c7
merge: the closure check asserts once
Oct 27, 2026
75da384
merge: the closure check asserts once
Oct 27, 2026
665db83
feat(vocabulary): the words a definition asks for
Oct 27, 2026
d44c24e
feat(insights): words and glossary on the blocks
Oct 27, 2026
70504f9
feat(insights): a record's words, projected
Oct 27, 2026
87856f3
feat(insights): words to define in the prompt
Oct 27, 2026
5e0335f
feat(cli): explain asks for the words
Oct 27, 2026
e6484fb
feat(cli): the estimate states the word costs
Oct 27, 2026
f1e22cd
docs: words and glossary in explain
Oct 27, 2026
cacfd63
docs(plan): the words in explain as built
Oct 27, 2026
a07bf74
test(insights): build record arbitraries once
Oct 27, 2026
62b51cd
merge: record arbitraries built once
Oct 27, 2026
fb2adf3
merge: record arbitraries built once
Oct 27, 2026
d2c43e3
merge: record arbitraries built once
Oct 27, 2026
ddcd9e3
merge: record arbitraries built once
Oct 27, 2026
78af733
merge: record arbitraries built once
Oct 27, 2026
68af5f5
merge: record arbitraries built once
Oct 27, 2026
4c9113e
merge: record arbitraries built once
Oct 27, 2026
631c682
test(extractor-typescript): 30 s test timeout
Oct 27, 2026
bf884fa
merge: extractor tests state their timeout
Oct 27, 2026
dde0b12
merge: extractor tests state their timeout
Oct 27, 2026
2efa407
merge: extractor tests state their timeout
Oct 27, 2026
94f7140
merge: extractor tests state their timeout
Oct 27, 2026
67ae45d
merge: extractor tests state their timeout
Oct 27, 2026
04ed6c0
merge: extractor tests state their timeout
Oct 27, 2026
eb0fab4
merge: extractor tests state their timeout
Oct 27, 2026
bc9554e
feat(insights): store version 2, insight_word
Oct 27, 2026
9c75ef0
test(cli): a version-1 store, refused, migrated
Oct 27, 2026
6b9eb28
docs: the version-2 insights store
Oct 27, 2026
c8403a3
docs(plan): the store at version 2 as built
Oct 27, 2026
9882ae0
feat(insights): word readers over the store
Oct 27, 2026
81e95a6
feat(cli): the insights word readers
Oct 27, 2026
b94cafd
docs: the word readers
Oct 27, 2026
3eedf37
feat(insights): every word entry from the store
jgrodziski Oct 28, 2026
013d2b1
feat(vocabulary): the list against the model
jgrodziski Oct 28, 2026
bf7a075
feat(cli): vocabulary --drift-insights
jgrodziski Oct 28, 2026
0b00395
docs: vocabulary --drift-insights
jgrodziski Oct 28, 2026
79e8d19
docs(plan): drift-insights as built
jgrodziski Oct 28, 2026
1b2715e
feat(insights): a word's glossary under a scope
jgrodziski Oct 28, 2026
b43ba2d
feat(cli): serve's /glossary.json
jgrodziski Oct 28, 2026
caa436f
refactor(navigator-ui): one remembered lookup
jgrodziski Oct 28, 2026
680c279
feat(navigator-ui): the glossary in both panels
jgrodziski Oct 28, 2026
1db44a1
docs: the glossary in the page
jgrodziski Oct 28, 2026
bbdf663
docs(plan): the glossary in the page as built
jgrodziski Oct 28, 2026
912de96
test(cli): no-key test ignores the shell's keys
jgrodziski Oct 29, 2026
1efdc86
fix(insights): refit the completion estimate
jgrodziski Oct 29, 2026
caaf52e
docs: the estimate's measured figures
jgrodziski Oct 29, 2026
60b323f
docs(plan): the PetClinic measurement
jgrodziski Oct 29, 2026
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
25 changes: 19 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ packages/navigator/ @codegraph/navigator — the navigator MODEL: the browsable
tree (modules → types → operations/attributes) plus one
classified dependency row per base edge, carrying member,
provenance and anchor included. Pure computation.
packages/vocabulary/ @codegraph/vocabulary — the words of the model's NAMES
(never source): the universal splitter driven by each
profile's lexicon, the word classes (domain, technical,
keyword, short) and the role weights; the cloud's layout
and SVG; the carriers lookup (which names carry a word).
Pure computation. Its `./cloud` entry is the layout alone
and imports nothing: the one value a frontend may take.
packages/insights/ @codegraph/insights — the bottom-up EXPLANATION walk: units
(operations → types → modules), SCC-condensed walk order,
context packs, prompts, Merkle fingerprints, plan/run, the
Expand All @@ -82,16 +89,20 @@ packages/viz/ @codegraph/viz — Three.js code city: renders a laid-out
ONLY package that may import three. Exports ONE thing,
`mountCityView(host)`, which navigator-ui embeds; its own
Vite app is the standalone page (replay/history).
packages/navigator-ui/ @codegraph/navigator-ui — React model navigator, five
packages/navigator-ui/ @codegraph/navigator-ui — React model navigator, six
tabs: Navigate (virtualized tree + fan-in/fan-out
evidence), City (the viz view, full-width, a building's
panel opens it in Navigate), Graph (Cytoscape+fcose
dependency graph, module/type modes), Cycles (the
artifact's precomputed tangle report), Coupling (ranked
metrics). Reads navigator.json + city.json (guard-enforced),
plus ONE lookup, `insight.json?id=…`: the selected type's or
module's LLM explanation, shown as an inference, never a fact.
It imports @codegraph/insights not even for types.
metrics), Vocabulary (the selected scope's words as a
cloud and a table). Reads navigator.json + city.json +
vocabulary.json (guard-enforced), plus TWO lookups:
`insight.json?id=…`, the selected type's or module's LLM
explanation, shown as an inference, never a fact; and
`carriers.json?term=…`, the names that carry a word.
It imports @codegraph/insights not even for types, and
@codegraph/vocabulary for types plus its `./cloud` layout.
The ONLY package that may import react and cytoscape; the
city comes through @codegraph/viz, never through three.
Vite app, no library.
Expand All @@ -107,7 +118,7 @@ fixtures/ Reference corpora + expected model.jsonl snapshots.

### Hard boundaries (convenience does not override architecture)

- **`core`, `analyzer`, `city` and `navigator` never import Three.js or React**
- **`core`, `analyzer`, `city`, `navigator` and `vocabulary` never import Three.js or React**
— they must run in Node with no DOM. `viz` reads the city model and
`navigator-ui` the navigator model; neither mutates its model and neither
re-derives graph facts the analyzer already computes.
Expand Down Expand Up @@ -230,6 +241,8 @@ node scripts/homebrew/render.mjs --version X.Y.Z --sums SHA256SUMS [--npm-sha256
# role "pass" (codegraph-metrics): claims no files, runs `<pass> <model> --src <dir>` after the extractor
./bin/codegraph city model.jsonl --layout --out city.json # the artifacts alone
./bin/codegraph navigator model.jsonl --out navigator.json
./bin/codegraph vocabulary model.jsonl [--level module|type] [--scope ID] [--drift FILE] [--svg FILE] # the names' words
./bin/codegraph serve model.jsonl --height vocabulary:order --height-scale sqrt # where one word lives, in the city
./bin/codegraph explain model.jsonl --src DIR --dry-run # the walk plan, no call
./bin/codegraph explain model.jsonl --src DIR --estimate --price-in 0.10 --price-out 0.60 # tokens in/out + cost, no call
OPENROUTER_API_KEY=… ./bin/codegraph explain model.jsonl --src DIR [--max-calls N] [--yes]
Expand Down
8 changes: 5 additions & 3 deletions METAMODEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ implemented* (robustness test of the schema).
| `kinds` | `Record<kind, {required: TraitName[], optional: TraitName[]}>` | the licit trait compositions per entity kind |
| `edges` | EdgeKind[] | edge kinds this language can emit |
| `notes` | string[] | documented static-analysis blind spots (reflection, `Class.forName`, dynamic `require`, macros pre-expansion, …) |
| `lexicon` | `{keywords, conventional, technical?, fileKinds?, interfacePrefix?}` | the language's words, for the vocabulary (§5.3): reserved words, names the language dictates, plumbing words, kinds whose name is a file path, C#'s interface marker |
| `lexicon` | `{keywords, conventional, technical?, fileKinds?, qualified?, interfacePrefix?}` | the language's words, for the vocabulary (§5.3): reserved words, names the language dictates, plumbing words, kinds whose name is a file path or a qualified path, C#'s interface marker |

**Validation** of an entity against its profile:
1. `kind` exists in the profile;
Expand Down Expand Up @@ -437,14 +437,16 @@ lexicon, optional on a profile and present on every shipped one:
| `conventional` | whole identifiers the language or its runtime dictates — overrides, protocol members, operators (`toString`, `__init__`, `<=>`). Their words say nothing about the domain, so such a name contributes none |
| `technical` | plumbing words of the language beyond the vocabulary's shared list, spelled as the splitter yields them (lowercase letters and digits) |
| `fileKinds` | kinds whose name is a file path (TypeScript's `module`, Ruby's `file`): the extension is not a word |
| `qualified` | kinds the language names by a qualified path, each with the separator that ends the qualifier: a Java `package` by `.`, a Ruby `class` by `::`, every file kind by `/`. The words before the last separator name a container (`AcmeOrder::` of `AcmeOrder::Order`), so they weigh as incidental words — still counted, never dropped |
| `interfacePrefix` | `true` in C# alone: `IOrderService` names an interface `OrderService` |

`validateProfile` rejects an entry that could never do what its list says:
listed twice (`lexicon-duplicate`); a keyword with no letter or a name holding
whitespace, a technical entry the splitter cannot yield (`lexicon-not-a-word`);
a conventional name or technical word a keyword already claims
(`lexicon-keyword-overlap`); a file kind the profile does not define
(`lexicon-unknown-kind`). The lexicon is not on the wire: `schemas/` is
(`lexicon-keyword-overlap`); a file or qualified kind the profile does not
define (`lexicon-unknown-kind`); a separator that is empty or holds a letter, a
mark or a digit (`lexicon-not-a-separator`). The lexicon is not on the wire: `schemas/` is
unchanged by it.

---
Expand Down
Loading
Loading