You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
PyClass has no decorators field — class decorators are silently dropped #127
PyClass (codeanalyzer/schema/py_schema.py) has no decorators field. PyCallable
has one (py_schema.py:274, filled at syntactic_analysis/symbol_table_builder.py:334),
but the class branch of the builder never reads ClassDef.decorator_list, so every class
decorator is dropped silently — no field, no warning.
Verified on main (6f02581) against a fixture with @dataclass class Account:
CLASS 'app.Account' (has 'decorators' key? False)
method 'doubled' decorators=['property']
The methods carry theirs; the class carries nothing. This loses @dataclass, @app.errorhandler, Django/pydantic class decorators, and @pytest.mark.* on test
classes — the decorators that classify what a class is.
Scope boundary
Adds decorators: List[str] to PyClass and populates it, mirroring how PyCallable
already works. Does not resolve decorator strings to ids (#128), does not
touch call-graph edges (#129), and does not add any new node type.
Goals
PyClass.decorators: List[str] = [], unparsed source strings in source order
Populated for top-level and nested/inner classes
Neo4j: reuse the existing :PyDecorator node and PY_DECORATED_BY relationship,
widening its start label from ["PyCallable"] to include PyClass
(neo4j/schema.py:237), plus the flat decorators: string[] property
Bump Neo4j SCHEMA_VERSION (additive)
Caveats and known risks
Schema v2 change, so it enters at designing-cldk-changes, not a patch. It is
purely additive (new optional field, defaults to []), so the monotonicity gate and
every existing consumer are unaffected.
Sibling analyzers share the vocabulary. TypeScript has class decorators too;
whatever name and shape lands here should be the canonical one, not a Python rename.
Available from L1 (it is symbol-table data), so it must not be gated behind a level.
Definition of done
The fixture above emits decorators: ["dataclass"] on app.Account
An inner class with a decorator emits it too
A class with no decorators emits [], not a missing key
analysis.json(-a 1) ⊆ ... ⊆ (-a 4) still holds
Neo4j PY_DECORATED_BY traverses from a :PyClass node
Design pass (epic codellm-devkit/.github#44, spec) found this is not a standalone additive field but one carrier of a single contract decision: the keystone already specifies structured decorator[] on type/callable/field, and codeanalyzer-typescript-v2 already ships it. Adding List[str] to PyClass would have deepened the divergence rather than closing it.
#128 now covers all four carriers — callable, class, class attribute, callable parameter — in the structured shape. Nothing here is dropped.
Activity
rahlk commentedon Aug 19, 2026
Folded into #128.
Design pass (epic codellm-devkit/.github#44, spec) found this is not a standalone additive field but one carrier of a single contract decision: the keystone already specifies structured
decorator[]on type/callable/field, andcodeanalyzer-typescript-v2already ships it. AddingList[str]toPyClasswould have deepened the divergence rather than closing it.#128 now covers all four carriers — callable, class, class attribute, callable parameter — in the structured shape. Nothing here is dropped.