Subject: Public API depends on an internal declaration¶
A public declaration's own contract secretly depends on a private/internal declaration -- reachable only through the L5 source-graph evidence tier, including how the detector reconciles a dependency that was merely renamed or moved rather than truly removed.
15 case(s). ← back to all subjects
The pattern¶
This is the L5 source-graph evidence tier's own subject: a public declaration's contract can depend on a private one through a channel no artifact-level diff (binary, debug info, or even headers alone) can see -- a private base class, a private field's type, an inline function's body referencing an internal constant, or an ordinary function's internal call graph. case160/187/188/189/190/191 each demonstrate one such channel; case192/193 show the same reachability question applied to suppression (a call-graph-reachable break can survive a suppression rule aimed at the wrong symbol) and to a negative case (an internal call that genuinely is not publicly reachable, so nothing should fire). case194-197 then test the detector's own precision under a compound edit: when the internal target is renamed, moved, or merely re-identified across a header change, does the reconciliation logic correctly recognize "same dependency, moved" rather than reporting a false removal-and-addition pair? case161/162/181 round out the family with the build-topology and audit-mode variants of the same underlying question -- did a dependency's source, not just its presence, change. The throughline for a maintainer: a public API's real dependency surface is not what its own header declares, it is everything reachable from that header -- and demonstrating that reachability, correctly and without false positives on an unrelated rename, is what this entire evidence tier exists to prove.
Cases¶
| Case | Title | Verdict | Category |
|---|---|---|---|
| case160_public_api_internal_dep_added | Public API Gains an Internal Dependency | 🟡 COMPATIBLE_WITH_RISK | Risk |
| case161_target_dependency_added | New Inter-Target Build/Link Dependency | 🟡 COMPATIBLE_WITH_RISK | Risk |
| case162_symbol_source_owner_changed | Exported Symbol's Declaring File Moved | 🟡 COMPATIBLE_WITH_RISK | Risk |
| case181_xcheck_public_to_internal_dependency | Public API Reaches an Internal Declaration | 🟢 COMPATIBLE | Quality (Compatible) |
| case187_public_struct_private_field_type | Public Struct Field Retyped to an Internal Type | 🔴 BREAKING | Breaking |
| case188_public_class_private_base_class | Public Class Gains a Private Base Class | 🔴 BREAKING | Breaking |
| case189_public_function_private_parameter_type | Public Function Parameter Retyped to an Internal Type | 🔴 BREAKING | Breaking |
| case190_public_inline_function_references_internal_constant | Public Inline Function References Internal Constant | 🟡 COMPATIBLE_WITH_RISK | Risk |
| case191_header_only_graph_field_type | Public Struct Gains a Field of a Private Type (Header-Only Graph) | 🔴 BREAKING | Breaking |
| case192_call_graph_break_survives_suppression | Call-Graph-Reachable Break Survives Suppression | 🔴 BREAKING | Breaking |
| case193_ordinary_exported_fn_call_not_reachable | Ordinary Exported Function's Internal Call Is Not Public-Reachable | 🔴 BREAKING | Breaking |
| case194_header_graph_rename_reconciled | Internal Dependency Target Renamed, Safely Reconciled | 🟡 COMPATIBLE_WITH_RISK | Risk |
| case195_header_graph_ambiguous_rename_not_reconciled | Ambiguous Simultaneous Rename, Correctly Not Reconciled | 🟡 COMPATIBLE_WITH_RISK | Risk |
| case196_header_graph_move_reconciled | Declaration Reconciled as Moved Across a Compound Edit | 🟡 COMPATIBLE_WITH_RISK | Risk |
| case197_header_graph_identity_reconciled | Declaration Reconciled as Identity-Reconciled (Header Unchanged) | 🟡 COMPATIBLE_WITH_RISK | Risk |