From the v1 whole-branch review (epic #1). Two confirmed defects, one shared root cause — the RPC rollup logic is triplicated across report.py, htmlmap.py, and system_tools.py:
service_graph_tool includes self-loop rows (client == host) that report/htmlmap exclude; its docstring says cross-service.
- All three surfaces build the
hosts map discarding the HOSTS edge's provenance — a wiring-only (INFERRED) host binding renders as DERIVED-STATIC, violating the grounding gate ('never present an INFERRED edge as fact').
Fix: factor one shared cocoa/system/topology.py helper (hosts + HANDLES fallback + provenance compounded across RPC_CALLS/HANDLES/HOSTS, self-loops excluded) consumed by all three surfaces.
From the v1 whole-branch review (epic #1). Two confirmed defects, one shared root cause — the RPC rollup logic is triplicated across report.py, htmlmap.py, and system_tools.py:
service_graph_toolincludes self-loop rows (client == host) that report/htmlmap exclude; its docstring says cross-service.hostsmap discarding the HOSTS edge's provenance — a wiring-only (INFERRED) host binding renders as DERIVED-STATIC, violating the grounding gate ('never present an INFERRED edge as fact').Fix: factor one shared
cocoa/system/topology.pyhelper (hosts + HANDLES fallback + provenance compounded across RPC_CALLS/HANDLES/HOSTS, self-loops excluded) consumed by all three surfaces.