1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
//! Dispatch tables — Phase β joint-stubs.
//!
//! This module defines [`DispatchTables`], the per-snapshot side-table store
//! that Plan B (graph-fidelity planner correctness, WS2 — see
//! `docs/superpowers/plans/2026-05-25-graph-fidelity-planner-correctness-dag.toml`)
//! will populate with virtual / interface / duck-typed / structural /
//! promiscuous-elided dispatch resolutions.
//!
//! The type lands as part of the V12 schema bump alongside Plan A's
//! [`super::framework_routes::FrameworkRouteMetadata`] so a single V11 → V12
//! upconvert covers both surfaces.
//!
//! # Population frontier
//!
//! The MCP `resolved_via` filter param and the `Predicate::ResolvedViaEq`
//! planner predicate that ship in this same PR are **complete capabilities**
//! — `Predicate::ResolvedViaEq` walks outgoing `Calls` edges and accepts
//! the node iff at least one edge carries a `resolved_via` value in the
//! requested set (see `sqry-db/src/planner/execute.rs`
//! `CompiledPredicate::ResolvedViaEq`). All 8 `ResolvedVia` variants
//! evaluate today. The 3 pre-existing variants
//! (`Direct` / `TypeMatch` / `BindingPlane`) are populated in production
//! by `pass5b_c_indirect`; the 5 new variants
//! (`VirtualDispatch` / `InterfaceDispatch` / `DuckTyped` / `Structural`
//! / `PromiscuousElided`) light up as Plan B's downstream resolver PRs
//! (`U_WS2_2` … `U_WS2_7`) emit edges carrying them. Coverage in
//! `sqry-db/tests/phase_beta_predicate_evaluation.rs` exercises empty /
//! match / non-match / multi-target / AND-composition paths against
//! fixture graphs that emit the new variants directly.
//!
//! What is *not* in this PR is the **aggregate per-node bookkeeping**
//! captured by [`DispatchTables`] — no resolver pass in `sqry-core`
//! populates it yet. The aggregate store is reserved for the dispatch
//! resolvers' lookup tables, fan-out cap hits, and ambiguity sets.
//!
//! # Why a separate side-table, not new `EdgeKind` variants
//!
//! Plan B SPEC §3.2 carries the new resolution provenances on the existing
//! `EdgeKind::Calls.resolved_via` field — the dispatch *resolver* writes its
//! per-edge resolution into the edge metadata, while [`DispatchTables`] holds
//! the *aggregate* per-node bookkeeping (lookup tables, fan-out cap hits,
//! ambiguity sets) that the resolver needs across edges. Storing both in the
//! same place keeps planner index reuse intact (see Plan B U_WS2_7
//! critical decision: "per-edge filter, not separate edge kind; preserves
//! planner index reuse").
use BTreeMap;
use ;
use NodeId;
/// Per-node dispatch-resolution side tables — Plan B 02_DESIGN §3.7
/// (line 279) shape.
///
/// Populated by Plan B's WS2 resolvers (JVM virtual / interface dispatch, Go
/// interface dispatch, Python duck-typed dispatch, TypeScript structural
/// dispatch, promiscuous-cap elision). Empty in the joint-stubs PR.
///
/// # Per-language plane
///
/// Each plane is a `BTreeMap` keyed by the call-site `NodeId`. The
/// per-plane entry types are minimal in the joint-stubs PR; downstream
/// WS2 resolver PRs extend them with concrete fields (vtable index,
/// interface witness set, structural shape hash, etc. — DESIGN §3.7
/// line 287). The wire envelope is V12-stable; resolver PRs only add
/// fields to the entry structs, not new top-level keys.
///
/// # Determinism
///
/// All collection fields are `BTreeMap` (not `HashMap`) so postcard-encoded
/// snapshots are bit-for-bit deterministic across `HashMap` iteration order
/// — the same discipline used elsewhere in this codebase (cf. the iterative
/// Tarjan SCC determinism fix, commit `b6bec9fc0`).
/// JVM virtual / abstract method dispatch entry.
///
/// Joint-stub shape: empty. Plan B `pass5c_jvm_virtual` populates with
/// concrete fields (vtable index, candidate `NodeId` set, fan-out,
/// was-elided). DESIGN §3.3 line 247-253.
/// Go interface dispatch entry.
///
/// Joint-stub shape: empty. Plan B `pass5d_go_interface` populates with
/// concrete fields (interface signature, candidate method-set superset
/// types, fan-out). DESIGN §3.4 line 256-260.
/// Python duck-typed dispatch entry.
///
/// Joint-stub shape: empty. Plan B `pass5e_python_duck` populates with
/// concrete fields (method name, arity, candidate `NodeId` set,
/// fan-out). DESIGN §3.5 line 263-270.
/// TypeScript structural dispatch entry.
///
/// Joint-stub shape: empty. Plan B `pass5f_ts_structural` populates with
/// concrete fields (declared interface superset, structural shape hash,
/// candidate set, fan-out). DESIGN §3.6 line 272-275.
/// Fan-out cap-hit diagnostic — Plan B DESIGN §3.7 (`cap_hits`).
///
/// Recorded by every resolver when `CALLSITE_PROMISCUOUS` is exceeded.
/// The resolver still emits a `Calls { resolved_via: PromiscuousElided }`
/// self-edge for the call-site so MCP filters that look for elided edges
/// see a uniform surface; the [`CapHit`] entry carries the structured
/// per-cap-hit context (which resolver, candidate count, contributing
/// receiver shape).
///
/// Joint-stub shape: minimal. Plan B's resolver PRs (`U_WS2_2_*` ...)
/// extend this with concrete fields.
/// Back-compat alias for the joint-stubs PR.
///
/// The previous joint-stub shape exposed a single `entries: BTreeMap<NodeId,
/// DispatchEntry>` field; the V12 surface lifts the per-plane maps to
/// top-level fields matching DESIGN §3.7. This alias preserves the
/// `DispatchEntry` type name (re-exported through `sqry_core::schema`) so
/// downstream PRs that pre-dated the rewrite can continue to refer to a
/// per-node opaque entry type. Plan B's resolver PRs will switch their
/// imports to the per-plane entry types (`JvmDispatchEntry`,
/// `GoDispatchEntry`, ...) over time.
pub type DispatchEntry = JvmDispatchEntry;