Skip to content

Commit 82d7b36

Browse files
author
jgstern-agent
committed
fix: orchestration hub ranking floor + event edge weights
Two fixes to symbol ranking, both identified by DEEP bakeoff LLM assessments (alertmanager + prometheus scored symbol_ranking 2/5): 1. Orchestration floor: functions with out-degree >= 20 get minimum effective in-degree of sqrt(out) * 0.8. Without this, within-file dampening (0.3x) and per-file cap (5) crushed alertmanager's `run` (in=9 all same-file, out=128) to effective_in=0.90, burying it at rank #45. Now ranks #1. 2. Edge type weights: event_subscribes and event_publishes added at 0.8 (were defaulting to 0.5); dispatches_to added at 0.6. Event callbacks are call-equivalent edges and should weight like routes_to. Signed-off-by: jgstern-agent <josh-agent@iterabloom.com>
1 parent 538515e commit 82d7b36

4 files changed

Lines changed: 118 additions & 4 deletions

File tree

.ci/affected-tests.txt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
# Test selection manifest
2-
# Generated by smart-test at 2026-04-10T11:12:24-04:00
2+
# Generated by smart-test at 2026-04-10T12:07:46-04:00
33
# Mode: targeted
44
# Baseline: e2fb9e02102c793608778dce538cc121418600fc
5-
# Changed files: 7
6-
# Changed source files: 2
7-
# Selected tests: 50
5+
# Changed files: 9
6+
# Changed source files: 3
7+
# Selected tests: 54
88
#
99
# === CHANGED_SOURCE_FILES ===
1010
packages/hypergumbo-core/src/hypergumbo_core/cli.py
1111
packages/hypergumbo-core/src/hypergumbo_core/framework_patterns.py
12+
packages/hypergumbo-core/src/hypergumbo_core/ranking.py
1213
# === SELECTED_TESTS ===
14+
packages/hypergumbo-core/tests/BRANCHES_test_compact.py
1315
packages/hypergumbo-core/tests/BRANCHES_test_framework_patterns.py
1416
packages/hypergumbo-core/tests/test_build_grammars.py
1517
packages/hypergumbo-core/tests/test_cli_basic.py
@@ -25,6 +27,7 @@ packages/hypergumbo-core/tests/test_cli_search.py
2527
packages/hypergumbo-core/tests/test_cli_symbols.py
2628
packages/hypergumbo-core/tests/test_cli_test_coverage.py
2729
packages/hypergumbo-core/tests/test_cli_verify_claims.py
30+
packages/hypergumbo-core/tests/test_compact.py
2831
packages/hypergumbo-core/tests/test_fastapi_patterns.py
2932
packages/hypergumbo-core/tests/test_file_excludes.py
3033
packages/hypergumbo-core/tests/test_framework_patterns.py
@@ -34,10 +37,12 @@ packages/hypergumbo-core/tests/test_locale.py
3437
packages/hypergumbo-core/tests/test_max_tier.py
3538
packages/hypergumbo-core/tests/test_no_first_party_priority.py
3639
packages/hypergumbo-core/tests/test_profile.py
40+
packages/hypergumbo-core/tests/test_ranking.py
3741
packages/hypergumbo-core/tests/test_run_behavior_map.py
3842
packages/hypergumbo-core/tests/test_schema_compliance.py
3943
packages/hypergumbo-core/tests/test_sketch.py
4044
packages/hypergumbo-core/tests/test_sketch_sanity.py
45+
packages/hypergumbo-core/tests/test_slice.py
4146
packages/hypergumbo-core/tests/test_slice_tier_filter.py
4247
packages/hypergumbo-core/tests/test_stable_shape_ids.py
4348
packages/hypergumbo-core/tests/test_supply_chain.py

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ This changelog tracks the **tool version** (package releases). The **schema vers
6767

6868
### Fixed
6969

70+
#### Symbol ranking
71+
72+
- **Orchestration hub floor for high-out-degree functions**: functions with out-degree >= 20 (main/run/app orchestration hubs) get a minimum effective in-degree of `sqrt(out_degree) * 0.8`, preventing within-file dampening and per-file capping from burying them. On alertmanager, `run` (in=9 all same-file, out=128) was ranked #45 with effective_in=0.90 after 0.3x within-file weight and max_per_file_in=5; now ranks #1 with floor=9.05. Does not affect functions with fewer than 20 outgoing edges.
73+
- **`event_subscribes` and `event_publishes` added to `DEFAULT_EDGE_TYPE_WEIGHTS` at 0.8**: event-driven callback edges previously defaulted to 0.5 weight, under-counting the centrality of event handlers. Now weighted at 0.8, matching `routes_to` and `message_dispatch`. Also added `dispatches_to` at 0.6 for interface dispatch edges.
74+
7075
#### Dead code analysis
7176

7277
- **`dead-code-maybe` BFS follows `dispatches_to`, `routes_to`, and `wraps` edges**: the reachability BFS only followed `calls` edges, so interface dispatch targets (Go `Notifier.Notify` implementations), HTTP route handlers, and middleware-wrapped functions were all flagged as dead code. On alertmanager, this fix reduced false positives from 781 to 634 (147 functions correctly reclassified as reachable), and eliminated all 16 `Notifier.Notify` false positives. The BFS now follows the same call-flow edge types that the slice BFS uses.

packages/hypergumbo-core/src/hypergumbo_core/ranking.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,14 @@ class RankedFile:
189189
"ipc_event": 0.9,
190190
"wasm_bridge": 0.9,
191191
"grpc_calls": 0.9,
192+
"event_subscribes": 0.8,
193+
"event_publishes": 0.8,
192194
"routes_to": 0.8,
193195
"crdt_publishes": 0.8,
194196
"message_dispatch": 0.8,
195197
"crypto_flow": 0.8,
196198
"renders_component": 0.7,
199+
"dispatches_to": 0.6,
197200
"imports": 0.3,
198201
"imports_module": 0.2,
199202
"module_exports": 0.1,
@@ -255,6 +258,13 @@ def compute_centrality(
255258
prevents a utility function called 50 times from 2 files from outranking
256259
an architecturally important function called 15 times from 15 files.
257260
261+
**Orchestration floor:** symbols with out-degree >= 20 (orchestration
262+
hubs like ``main``/``run``/``app``) get a minimum effective in-degree
263+
of ``sqrt(out_degree) * 0.8``. Without this, within-file dampening
264+
and per-file capping crush hubs whose few in-edges all originate from
265+
the same file (e.g., ``run`` called only from ``main()`` in the same
266+
``main.go``).
267+
258268
Scores are normalized to 0-1 after computation.
259269
260270
Args:
@@ -334,6 +344,20 @@ def compute_centrality(
334344
else:
335345
effective_in = ind
336346

347+
# Orchestration floor: genuinely high-out-degree functions
348+
# (main/run/app — typically out >= 20) get a minimum effective
349+
# in-degree proportional to their out-degree. Without this,
350+
# within-file dampening and per-file capping crush orchestration
351+
# hubs: alertmanager's `run` (in=9 all same-file, out=128) got
352+
# effective_in=0.90 after 0.3x within-file weight and
353+
# max_per_file_in=5, burying it at rank 45 below symbols with
354+
# moderate in-degree from many files. The threshold prevents
355+
# the floor from affecting normal functions with a few out-edges.
356+
_ORCHESTRATION_OUT_THRESHOLD = 20
357+
if outd >= _ORCHESTRATION_OUT_THRESHOLD:
358+
orchestration_floor = math.sqrt(outd) * 0.8
359+
effective_in = max(effective_in, orchestration_floor)
360+
337361
# Pure sinks (out_degree=0) get a dampened multiplier (0.5) vs
338362
# the normal floor of 1.0. This penalizes popular leaf utilities
339363
# (e.g., Elm map with in=71, out=0) that accumulate high in-degree

packages/hypergumbo-core/tests/test_ranking.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3807,3 +3807,83 @@ def test_custom_weight(self):
38073807
centrality, [gen_sym], generated_weight=0.1
38083808
)
38093809
assert result[gen_sym.id] == pytest.approx(0.1)
3810+
3811+
3812+
class TestEventSubscribesEdgeWeight:
3813+
"""event_subscribes edges should be weighted as call-flow edges, not defaults."""
3814+
3815+
def test_event_subscribes_in_default_weights(self):
3816+
"""event_subscribes should be in DEFAULT_EDGE_TYPE_WEIGHTS at >= 0.8."""
3817+
from hypergumbo_core.ranking import DEFAULT_EDGE_TYPE_WEIGHTS
3818+
3819+
assert "event_subscribes" in DEFAULT_EDGE_TYPE_WEIGHTS
3820+
assert DEFAULT_EDGE_TYPE_WEIGHTS["event_subscribes"] >= 0.8
3821+
3822+
def test_event_publishes_in_default_weights(self):
3823+
"""event_publishes should also be weighted."""
3824+
from hypergumbo_core.ranking import DEFAULT_EDGE_TYPE_WEIGHTS
3825+
3826+
assert "event_publishes" in DEFAULT_EDGE_TYPE_WEIGHTS
3827+
assert DEFAULT_EDGE_TYPE_WEIGHTS["event_publishes"] >= 0.8
3828+
3829+
3830+
class TestOrchestrationHubRanking:
3831+
"""Orchestration hubs (low in, very high out) should not be buried by dampening.
3832+
3833+
alertmanager's `run` function (in=9 all from same file, out=128) scored
3834+
raw centrality 5.27 vs NewAlertmanagerClient's 26.4 because within-file
3835+
dampening (0.3x) and per-file cap (5) crushed its effective in-degree
3836+
from 9 to 0.90. The out-degree boost (ln-scale) couldn't compensate.
3837+
"""
3838+
3839+
def test_orchestration_hub_ranks_above_moderate_connector(self):
3840+
"""A function with out=128 and in=2 (cross-file) should rank higher
3841+
than one with in=8 (cross-file) and out=9."""
3842+
# Orchestration hub: called from 2 files, calls 50 others
3843+
hub = make_symbol("run", path="main.go", kind="function", language="go")
3844+
# Moderate connector: called from 8 different files, calls 9
3845+
connector = make_symbol("NewClient", path="client.go", kind="function",
3846+
language="go")
3847+
# Create callers for both
3848+
targets = [make_symbol(f"t{i}", path=f"pkg{i}/mod.go", kind="function",
3849+
language="go")
3850+
for i in range(50)]
3851+
3852+
hub_callers = [
3853+
make_symbol("main", path="main.go", kind="function", language="go"),
3854+
make_symbol("init", path="init.go", kind="function", language="go"),
3855+
]
3856+
conn_callers = [
3857+
make_symbol(f"caller{i}", path=f"pkg{i}/use.go", kind="function",
3858+
language="go")
3859+
for i in range(8)
3860+
]
3861+
3862+
all_symbols = [hub, connector] + targets + hub_callers + conn_callers
3863+
3864+
edges = []
3865+
# hub called by 2 callers (1 same-file, 1 cross-file)
3866+
edges.append(make_edge(hub_callers[0].id, hub.id)) # same-file (main.go)
3867+
edges.append(make_edge(hub_callers[1].id, hub.id)) # cross-file
3868+
3869+
# hub calls 50 targets
3870+
for t in targets:
3871+
edges.append(make_edge(hub.id, t.id))
3872+
3873+
# connector called by 8 callers (all cross-file)
3874+
for c in conn_callers:
3875+
edges.append(make_edge(c.id, connector.id))
3876+
3877+
# connector calls 9 targets
3878+
for t in targets[:9]:
3879+
edges.append(make_edge(connector.id, t.id))
3880+
3881+
ranked = rank_symbols(all_symbols, edges)
3882+
rank_by_name = {rs.symbol.name: rs.rank for rs in ranked}
3883+
3884+
# run (the orchestration hub) should rank higher (lower rank number)
3885+
# than NewClient
3886+
assert rank_by_name["run"] < rank_by_name["NewClient"], (
3887+
f"run rank={rank_by_name['run']} should be < "
3888+
f"NewClient rank={rank_by_name['NewClient']}"
3889+
)

0 commit comments

Comments
 (0)