Skip to content

feat(extract): extract call-form event.listen registrations (events v2)#33

Merged
v0ropaev merged 1 commit into
masterfrom
feat/events-call-form
Jul 8, 2026
Merged

feat(extract): extract call-form event.listen registrations (events v2)#33
v0ropaev merged 1 commit into
masterfrom
feat/events-call-form

Conversation

@v0ropaev

@v0ropaev v0ropaev commented Jul 8, 2026

Copy link
Copy Markdown
Owner

What

The events extractor now also extracts module-level SQLAlchemy event.listen(Target, "event", fn) statements — the v1 KNOWN GAP — as a new registration family sqlalchemy_listen.

  • fn must resolve to a first-party top-level function (same module, or imported — reusing the calls.py import-table machinery, lifted to module level with thin class delegates, the _caller_scan_root precedent). Precision-first: unresolvable fn (lambda / attribute / non-first-party) is skipped, never guessed.
  • The registration attaches to the handler's artifact (event:{fn_fq}) — which may live in another module than the listen() call — and the artifact gains a grounding edge on the registering file's module span (new role registration_site). Wiring in a third module grounds one artifact across three files: handler + target class + registration site.
  • Only module-level calls are extracted (they run deterministically at import time → the claim honestly holds at confidence 1.0). listen(...) inside a function/class body, lambda listeners, and the bare from sqlalchemy.event import listen form are documented gaps.
  • Registrations gained form/registration_module/registration_line; call-form registrations sort before merging so full and incremental indexing stay byte-identical.

Version bump

events extractor_version 1 → 2: all event_handler ids recompute on the next index (idempotent re-index; orphaned rows go to the deferred GC); kb describe regenerates event-handler descriptions on its next run. Purely-decorator handlers keep semantically identical payloads. Identity rules in kb.ids untouched.

Gate

Tier-1 events oracle: the call-form known-gap test inverts into a positive test; EXPECTED_EVENTS gains two sqlalchemy_listen tuples; new tests: three-file provenance (hooks.py + db.py + wiring.py), function-body listen gap, lambda-listener gap (9 → 12 tests). Headline HARD gates stay fifteen.

Local: ruff clean, mypy --strict clean, pytest -q → 115 passed, 1 skipped.

The events extractor now also extracts module-level SQLAlchemy
event.listen(Target, "event", fn) statements - the v1 KNOWN GAP - as a
new registration family sqlalchemy_listen. fn must resolve to a
first-party top-level function of the same module or an imported one
(reusing the calls.py import-table machinery, lifted to module level);
the registration attaches to the HANDLER's artifact, which may live in
another module than the listen() call, and the artifact gains a
grounding edge on the registering file's module span (new role
registration_site) - wiring in a third module grounds ONE artifact
across THREE files (handler + target class + registration site).

Only module-level calls are extracted: they run deterministically at
import time, so the registration claim holds at confidence 1.0.
listen() inside a function/class body, lambda/attribute listeners and
the bare from-import form are documented gaps, never a wrong guess.
Registrations gained form/registration_module/registration_line
payload fields; call-form registrations are sorted before merging so
full and incremental indexing stay byte-identical.

events extractor_version 1 -> 2: all event_handler ids recompute on
the next index (idempotent); purely-decorator handlers keep
semantically identical payloads. Tier-1 events gate: the call-form
known-gap test becomes a positive test, plus three-file provenance and
two new gap assertions (9 -> 12 tests). Headline HARD gates stay
fifteen.
@v0ropaev v0ropaev merged commit dffd2bd into master Jul 8, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant