Skip to content

explain truncation hides listeners on high-degree nodes: 3 of 7 identifiable (PE-80043) #69

Description

@filipechagas

Filed from LawnStarter adoption ticket PE-80043 (api.lawnstarter.com), graded run at CLI 0.9.40, fork v8 @ 5e9d95c11837aeabbbb5d90cb45544f49dc58ca4.

Summary

graphify explain truncates its connection list at 20 entries. On a Laravel event class with degree 31, the 20-entry window is filled mostly by test-file imports edges, so only 3 of the 7 real listeners are identifiable from the output. The remaining listener files appear in the "Grouped by file" rollup, but the rollup gives only a connection count per file — it does not say which of those connections is the handle() reference that makes the file a listener. A consumer cannot answer "what listens to this event?" from the output.

docs already note "explain truncates on high-degree nodes … use affected for full fan-in". This issue is that the truncation is not signalled as lossy for the question being asked: the output looks complete because the rollup lists every file, and there is no hint that the per-edge relation labels were dropped.

Reproduction

Corpus: api.lawnstarter.com @ 382fe1a2c1 (private LawnStarter repo, PHP/Laravel, 6,224 files).

graphify update .
graphify explain "BackgroundCheckStatusChanged"

Expected

The 7 listeners registered for the event, each identifiable as a listener.

Ground truth by grep — app/Providers/EventServiceProvider.php:134-142 registers exactly these, and each declares handle(BackgroundCheckStatusChanged $event):

app/Listeners/BackgroundCheck/PropagateBackgroundCheckStatusOnChange.php:21
app/Listeners/BackgroundCheck/DetectBackgroundCheckSubmitted.php:14
app/Listeners/BackgroundCheck/DetectBackgroundCheckPassed.php:14
app/Listeners/BackgroundCheck/DetectBackgroundCheckFailed.php:14
app/Listeners/BackgroundCheck/DetectBackgroundCheckActionNeeded.php:14
app/Listeners/BackgroundCheck/DetectBackgroundCheckExpired.php:14
app/Listeners/BackgroundCheckEvent/LogBackgroundCheckStatusChangedEvent.php:21

Actual

Node: BackgroundCheckStatusChanged
  Degree:    31

Connections (31):
  ...
  <-- .handle() [references] app/Listeners/BackgroundCheck/DetectBackgroundCheckActionNeeded.php:L14
  <-- .handle() [references] app/Listeners/BackgroundCheck/DetectBackgroundCheckSubmitted.php:L14
  <-- .handle() [references] app/Listeners/BackgroundCheckEvent/LogBackgroundCheckStatusChangedEvent.php:L21
  <-- DetectBackgroundCheckActionNeeded.php [imports] ...
  <-- DetectBackgroundCheckExpired.php [imports] ...
  ... and 11 more
  Grouped by file:
    <-- app/Listeners/BackgroundCheck/DetectBackgroundCheckFailed.php: 2 connections
    <-- app/Listeners/BackgroundCheck/DetectBackgroundCheckPassed.php: 2 connections
    ...

3 of 7 listeners carry an explicit .handle() [references] label. The other 4 are inside "... and 11 more".

Nine of the twenty shown connections are test-file imports, which crowd out the signal-bearing edges.

The full set is in the graph and the workaround works:

$ graphify affected "BackgroundCheckStatusChanged" --relation references --depth 1
- .handle() [references] app/Listeners/BackgroundCheck/DetectBackgroundCheckActionNeeded.php:L14
- .handle() [references] app/Listeners/BackgroundCheck/DetectBackgroundCheckExpired.php:L14
- .handle() [references] app/Listeners/BackgroundCheck/DetectBackgroundCheckFailed.php:L14
- .handle() [references] app/Listeners/BackgroundCheck/DetectBackgroundCheckPassed.php:L14
- .handle() [references] app/Listeners/BackgroundCheck/DetectBackgroundCheckSubmitted.php:L14
- .handle() [references] app/Listeners/BackgroundCheck/PropagateBackgroundCheckStatusOnChange.php:L21
- .handle() [references] app/Listeners/BackgroundCheckEvent/LogBackgroundCheckStatusChangedEvent.php:L21

7/7, exact lines, no wrong nodes.

Suggestions

  1. When truncating, prefer edges by relation informativeness rather than by traversal order — references/calls before bulk imports.
  2. Make the truncation notice actionable, e.g. ... and 11 more (relation labels omitted — run 'graphify affected "X" --relation references' for the full set).
  3. Add a --limit N / --all flag to explain so a caller can opt out of the 20-cap.

Related

Separately, this repo has no listens_to relation at all — EventServiceProvider::$listen produces zero edges (checked: the provider's 24 outbound edges are all imports, none to the BackgroundCheck listeners). The listeners are discoverable only by accident, because they happen to type-hint the event. Happy to split that into its own issue if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentFully specified, ready for an AFK agent

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions