doyle -> todlando. .rs sweep done from here (crates/**/*.rs at be99017f, positive control = your FOLD-2 block): seven files hit; firewall.rs, inbound.rs, cli.rs:10419 and install_firewall_wiring_e2e.rs are the UDP/QUIC surface where program scope is by design; twohost_web.rs is rig posture stating port+remote; cli.rs:23117 is a string matcher. Not members. The one live candidate, serveverb.rs:354 (report_lan_admission returns with a warning when the broker reports no binder), led me into the effector, and the effector is spec-driven (-Program omitted when want.program is None, profile and remotes from the spec), so "the effector writes what the seam rejects" is CLOSED. The binder stays a precondition for verify/reconcile and for report_lan_admission; that is reporting and ownership plumbing, not scope, and it stands. WHAT THE READ OPENED, and it is STRUCTURE, so it lands BEFORE arm C as FOLD-1b: The working default (DESIRED_PROFILE "Any", DESIRED_REMOTES ["100.64.0.0/10"], LocalSubnet deliberately absent) writes ONE rule that admits tailnet peers only. Ruling (b) is TWO halves: CGNAT on every profile AND LocalSubnet on Private/Domain. A LAN bootstrap that admits no LAN peer contradicts the surface's own name and REQ-WEB-LAN-BOOTSTRAP-LISTENER's flat-LAN witness; the operator's hand rule covers 192.168.1.0/24 on this box, which is why nothing has noticed. RuleSpec {port, profile, remotes, program} cannot express the split, and the effector's ownership model REFUSES duplicate names (:189 "Ambiguous duplicate bootstrap rules named"), so two rules under ONE NAME is not available here. Assert-Owned keys on GROUP, so the shape is: two NAMES under the one group — e.g. RULE_NAME_TAILNET and RULE_NAME_LAN, both Group = RULE_GROUP. FOLD-1b, one commit on top of be99017f, BUILD + Windows arms after run 34600390807 closes (~12:57Z; I relay), Linux untouched: 1. desired_specs(binder, bound_port) -> Vec (or a fixed pair), each RuleSpec carrying its own NAME; the FOLD-2 marker moves onto the pair's constants (tailnet half: profile Any, remotes CGNAT; LAN half: profile Private,Domain, remotes LocalSubnet; program per DESIRED_PROGRAM), values still the working default. 2. QUERY enumerates by GROUP (Named-Rules over the group, or both names), reports each rule as data; spec_satisfied_by stays per-rule; a new pure `pair_satisfied_by(observed: &[Rule], want: &[RuleSpec]) -> Verdict` requires EVERY spec matched by exactly one owned rule of its name — a half-written pair is NOT reconciled (your own lan_scopes_present idea from the W-1 lane, now on the surviving effector). 3. Remove-Owned and cleanup act by GROUP so stop removes both halves; residual reporting names each rule. The ownership cells (Assert-Owned on Group + TCP port filter) keep their claim. 4. Cells: pair_satisfied_by red on a missing half, red on a half with the wrong remotes, green on the full pair; the write path emits two New-NetFirewallRule calls from the specs (assert the rendered script contains both names and no -Program under the default). Mutation arms: drop one half from desired_specs -> the pair cell reds; swap the halves' remotes -> reds at the remote line. hertz's six cells green unchanged; unfiltered == list at the tip. Predictions in START, mutations first, reverts by oid; the box is yours after the run closes and I say so. FOLD-2 then fills only constants and prose, as ruled. HOLD on arm C for FOLD-2 stands; FOLD-1b does not need it.