From d1be9e5efe2ffe0cfb481fed6e46330036bb4870 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 3 Aug 2026 09:00:29 -0400 Subject: [PATCH 1/5] Add GitHub Actions workflow for codespell on v8 --- .github/workflows/codespell.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/codespell.yml diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 0000000000..6d28abebf5 --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,23 @@ +# Codespell configuration is within pyproject.toml +--- +name: Codespell + +on: + push: + branches: [v8] + pull_request: + branches: [v8] + +permissions: + contents: read + +jobs: + codespell: + name: Check for spelling errors + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v6 + - name: Codespell + uses: codespell-project/actions-codespell@8f01853be192eb0f849a5c7d721450e7a467c579 # v2.2 From 895545d08bcb98b823d5219498e6e5ebdb029589 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 3 Aug 2026 09:00:29 -0400 Subject: [PATCH 2/5] Add rudimentary codespell config --- pyproject.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index c9b5509831..c623806186 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -150,3 +150,10 @@ select = ["E9", "F63", "F7", "F82"] include = ["graphify", "tests"] pythonVersion = "3.10" typeCheckingMode = "basic" + +[tool.codespell] +# Ref: https://github.com/codespell-project/codespell#using-a-config-file +skip = '.git,.gitignore,.gitattributes,*.svg,*.lock' +check-hidden = true +# ignore-regex = '' +# ignore-words-list = '' From 3da3491fc08d58eb6e2cae37f36c0cb7e350844a Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 3 Aug 2026 09:01:02 -0400 Subject: [PATCH 3/5] Add pre-commit definition for codespell --- .pre-commit-config.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5e762eb4d5..cc770ae062 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,3 +20,9 @@ repos: hooks: - id: ruff args: ["--config", "pyproject.toml"] + + - repo: https://github.com/codespell-project/codespell + # Configuration for codespell is in .pre-commit-config.yaml + rev: v2.4.2 + hooks: + - id: codespell From 02e9842ca5c90785bdec57f251d6fb47b7dc7015 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 3 Aug 2026 09:09:05 -0400 Subject: [PATCH 4/5] Tune codespell config: skip translations/worked, add ignore-words-list - Skip worked/ (sample outputs whose truncated identifiers extracted from scanned repos aren't typos in this codebase) and translations/ (foreign- language README variants that codespell (English-only) misreads). - Add ignore-words-list for domain terms, code identifiers, and short variable names (unparseable, bloc, inout, dependant, inh, datas, nd, bu, anc, ans, oder, ist) with per-word rationale in comments. - Fix wrong config-file reference in .pre-commit-config.yaml (was self- referential; codespell config lives in pyproject.toml). - Add tomli additional_dependency to the codespell pre-commit hook so it can read pyproject.toml on Python <3.11 (project supports 3.10+). - Protect the "hel" trigram in shingle test / plan example with inline codespell:ignore pragmas rather than whitelisting the word globally. Co-Authored-By: Claude Code 2.1.220 / Claude Opus 4.7 (1M context) --- .pre-commit-config.yaml | 4 +++- .../2026-05-04-incremental-updates-dedup.md | 2 +- pyproject.toml | 22 ++++++++++++++++--- tests/test_dedup.py | 2 +- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cc770ae062..ae8cbbc06f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,9 @@ repos: args: ["--config", "pyproject.toml"] - repo: https://github.com/codespell-project/codespell - # Configuration for codespell is in .pre-commit-config.yaml + # Configuration for codespell is in pyproject.toml rev: v2.4.2 hooks: - id: codespell + additional_dependencies: + - tomli; python_version<'3.11' diff --git a/docs/superpowers/plans/2026-05-04-incremental-updates-dedup.md b/docs/superpowers/plans/2026-05-04-incremental-updates-dedup.md index 488591b8dc..83c4d78713 100644 --- a/docs/superpowers/plans/2026-05-04-incremental-updates-dedup.md +++ b/docs/superpowers/plans/2026-05-04-incremental-updates-dedup.md @@ -101,7 +101,7 @@ def test_entropy_empty_string(): def test_shingles_produces_trigrams(): s = _shingles("hello") - assert "hel" in s + assert "hel" in s # codespell:ignore hel assert "ell" in s assert "llo" in s diff --git a/pyproject.toml b/pyproject.toml index c623806186..15504fd9aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -153,7 +153,23 @@ typeCheckingMode = "basic" [tool.codespell] # Ref: https://github.com/codespell-project/codespell#using-a-config-file -skip = '.git,.gitignore,.gitattributes,*.svg,*.lock' +# worked/ contains sample outputs (graph.json/html snapshots from real repos) +# whose truncated string identifiers extracted from source are not typos in +# the codebase itself. translations/ (basename glob, matches docs/translations/) +# hosts foreign-language README variants that codespell (English-only) misreads. +skip = '.git,.gitignore,.gitattributes,*.svg,*.lock,worked,translations' check-hidden = true -# ignore-regex = '' -# ignore-words-list = '' +# Per-word rationale for ignore-words-list (single TOML string, per-entry +# comments are not possible inside the value): +# unparseable - consistent alternate spelling used across graphify/ (35x) +# bloc - Dart BLoC pattern (Business Logic Component), not "block" +# inout - SQL PROCEDURE param mode / Verilog keyword (not "input") +# dependant - FastAPI class name shown in README example output +# inh - test-local variable holding "inherits" edge set (tests/) +# datas - matches edge_datas() function name from graphify.build +# nd - short variable for graph node data (wiki.py, engine.py) +# bu - short variable for Bedrock usage dict (llm.py) +# anc - short variable for ancestor path (resolution.py) +# ans - short variable for answer file path (tests/test_reflect.py) +# oder,ist - German stopwords in serve.py's stopword list +ignore-words-list = 'unparseable,bloc,inout,dependant,inh,datas,nd,bu,anc,ans,oder,ist' diff --git a/tests/test_dedup.py b/tests/test_dedup.py index e1370fc7a5..36fc80c159 100644 --- a/tests/test_dedup.py +++ b/tests/test_dedup.py @@ -20,7 +20,7 @@ def test_entropy_empty_string(): def test_shingles_produces_trigrams(): s = _shingles("hello") - assert "hel" in s + assert "hel" in s # codespell:ignore hel assert "ell" in s assert "llo" in s From 092f48bddc22bf8789d740819483137a9e3b1512 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 3 Aug 2026 09:09:38 -0400 Subject: [PATCH 5/5] [DATALAD RUNCMD] Fix non-ambiguous typos flagged by codespell Fixed via `codespell -w`: - Patters -> Patterns (graphify/extractors/dart.py: comment) - browseable -> browsable (graphify/tree_html.py: module docstring) - implementor -> implementer (graphify/llm.py: docstring) - pre-empts -> preempts (graphify/extract.py: comment) All hits are in prose (comments/docstrings), not code identifiers. Co-Authored-By: Claude Code 2.1.220 / Claude Opus 4.7 (1M context) === Do not change lines below === { "chain": [], "cmd": "uvx codespell -w", "exit": 0, "extra_inputs": [], "inputs": [], "outputs": [], "pwd": "." } ^^^ Do not change lines above ^^^ --- graphify/extract.py | 2 +- graphify/extractors/dart.py | 2 +- graphify/llm.py | 2 +- graphify/tree_html.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/graphify/extract.py b/graphify/extract.py index 30f31d329e..1e45d25a43 100644 --- a/graphify/extract.py +++ b/graphify/extract.py @@ -5510,7 +5510,7 @@ def _has_import_evidence(candidate_id: str) -> bool: # `indirect_call` and ONLY when the target is a real callable def — # never a same-named data symbol. Stays INFERRED even with import # evidence: the name is referenced as a value here, not invoked. Dedup - # is call-aware (an existing direct `calls` edge pre-empts it; a benign + # is call-aware (an existing direct `calls` edge preempts it; a benign # `imports` edge to the same symbol does NOT suppress it). if tgt != caller and (caller, tgt) not in call_like_pairs and tgt in callable_nids and tgt not in class_nids: call_like_pairs.add((caller, tgt)) diff --git a/graphify/extractors/dart.py b/graphify/extractors/dart.py index acbe195836..200f6528e8 100644 --- a/graphify/extractors/dart.py +++ b/graphify/extractors/dart.py @@ -480,7 +480,7 @@ def _find_matching_brace(text: str, start_pos: int) -> int: add_node(bloc_nid, bloc_name, source_file=None) add_edge(nid, bloc_nid, "references", context="bloc_lookup") - # Universal Navigation Patters (GoRouter, AutoRoute, Navigator) + # Universal Navigation Patterns (GoRouter, AutoRoute, Navigator) for nm in re.finditer(r"\b(?:go|push|goNamed|pushNamed|replace|replaceNamed)\s*\(\s*(?:context\s*,\s*)?['\"]([a-zA-Z0-9_/?=&%-]+)['\"]", func_body): route_path = nm.group(1) route_nid = _make_id("route", route_path.replace("/", "_").replace("?", "_").replace("=", "_").replace("&", "_")) diff --git a/graphify/llm.py b/graphify/llm.py index 30d7a6d6f4..e9e5c903c9 100644 --- a/graphify/llm.py +++ b/graphify/llm.py @@ -470,7 +470,7 @@ def _thinking_disabled_via_env() -> bool: Edge direction rule — source is always the ACTOR, target is the ACTED-UPON: - calls: source = the function/method that CONTAINS the call site; target = the function/method BEING CALLED. Never reverse this. - imports/references: source = the file/entity that imports or references; target = the thing imported or referenced. -- implements/inherits: source = the subclass/implementor; target = the base class/interface. +- implements/inherits: source = the subclass/implementer; target = the base class/interface. Hyperedges: if 3 or more nodes clearly participate together in a shared concept, flow, or pattern that is not captured by pairwise edges alone, add a hyperedge to the top-level `hyperedges` array (e.g. all classes implementing one protocol, all functions in one auth flow even if they don't all call each other, all concepts from a paper section forming one coherent idea). Use sparingly — only when the group relationship adds information beyond the pairwise edges. Maximum 3 hyperedges per chunk. diff --git a/graphify/tree_html.py b/graphify/tree_html.py index 1dc658ff18..b77157f9c1 100644 --- a/graphify/tree_html.py +++ b/graphify/tree_html.py @@ -1,6 +1,6 @@ """tree_html — emit a D3 v7 collapsible-tree HTML view of a graph. -A self-contained printable / browseable tree-of-modules view +A self-contained printable / browsable tree-of-modules view intended to complement the existing force-directed ``graph.html``. Key visual elements: