CORNER-TOPO-ADVISOR -- SEARCH ANALYSIS (search advisor record)

PROBLEM / REVISION / SOURCES / AUTHORIZED SCOPE
  Spec: probs/problem-corner-topo-advisor.lisp (accepted 2026-10-12; enumerator declarations
    added 2026-10-14, see SPEC CONSOLIDATION) with tech/beam-relay.lisp E2.
  Upstream: problem-analysis.txt (rev 2), spec-analysis.txt, spec-analysis-search-handoff.txt.
  Scope: phase 0 (read and reason only), 2026-10-12. No runs authorized yet.

OBJECTIVE
  Shortest plan (unit cost), connector names irrelevant; establish whether 15 is minimal.

PHASE 0 PROFILE (2026-10-12)
  Answer form: a sequence of actions (spec).
  Repeated states: yes; moves can be undone, 62% repeats pruned at depth 5 (spec record).
  Fixed length: no (spec).
  Interchangeable objects: connector1-3, already handled by symmetry pruning (spec record).
  Size: about 7-8 states generated per level to depth 5 (32,475 states at depth 5); connect
    choices dominate (spec record).
  Generic topology lower bound (source reading, tech/topo-lower-bound.lisp): the automatically
    registered term counts only location goals and the controllers of closed gates on the
    route.  Here: one move to location4, plus pickup and connect for receiver1 when no
    transmitter-to-receiver1 pairing path exists (one if a connector is held).  At most 3; the
    receiver2/receiver3 goals contribute nothing.  Under a cutoff it can only stop expansion in
    the last two or three levels.  Its gain is unknown and must be timed.
  Milestones: present (analysis hints) but not this advisor's strategy.

PRELIMINARY PROJECTION (deduction, not measured)
  At 3-8 distinct new states per level beyond depth 5, depth 15 means roughly 10^9 to 10^13
  states.  Heap is about 25 GB, so a graph search holds on the order of tens of millions of
  states.  A single depth-15 forward search is very likely impractical unless growth beyond
  depth 5 falls far below the measured shallow rate.

PROPOSED NEXT PROBE (awaiting approval)
  Growth probe: cutoffs 6, 7, 8 at 16 threads, min-length, on the accepted spec; record states,
  time and repeat percentage per cutoff.  Interpretation: growth ratio per level projects
  depth 15 time and memory; if it confirms impracticality, evaluate the direct alternatives
  (meet-in-the-middle from goal states first, per the spec handoff).

PHASE 1 GROWTH PROBE (2026-10-12, user, Windows, 16 threads, min-length, accepted spec)
  cutoff  program cycles  states processed  time     repeats  inconsistent abandoned
  5       --              32,475            0.3 s    --       298
  6       12,391          126,475           0.9 s    47.1%    1,847
  7       67,668          940,742           7.4 s    79.8%    18,702
  8       222,156         4,087,511         39.4 s   75.6%    151,105
  No solutions (expected).  Growth per level: time x3 to x8, cycles x3.3 to x5.5.
  Rate about 100,000 states per second at 16 threads.

FINDINGS
  Depth-15 forward search: seven more levels at x5 to x8 per level in time gives about one
    month to several years; stored states grow to roughly 10^9 to 10^10, far above what a 25 GB
    heap holds (bytes per state not measured here).  Impractical by orders of magnitude.
  Proving 15 minimal (exhausting depth 14) is the same scale.
  Topology lower bound: at most removes the last two or three levels for states with no
    pairing path to receiver1; realistically about one level.  Not enough.
  First-move splitting (*branch*): min-length per first move, then the best of them, keeps
    the shortest-plan guarantee, but the total work is unchanged.  Useful only to spread runs.

DIRECTION
  Evaluate the direct alternatives, meet-in-the-middle from generated goal states first.

RELAXATION (source reading, 2026-10-12)
  Derived facts (colors, receivers, gate, crossings) are functions of the base facts, so removing
    them from search merges no states; loosened preconditions (e.g. gate1 open replaced by a
    pairing-chain test) can only add states.  Saving is per-state propagation cost only (share
    unmeasured; at most a constant factor), against a gap of thousands.
  Relaxed rules admit every real plan, so the relaxed shortest length is a lower bound: a relaxed
    search exhausting depth 14 would prove 15 minimal -- but it is at least as large as the real one.
  The Talos techs propagate inside their own actions, so a relaxed variant needs problem-local
    replacements for all connector and move actions (spec-advisor work).
  Not recommended for this problem.
  Observation (corrected below): probs/problem-corner-relaxed.lisp's header reports a solution
    found in about 400 s at cutoff 14 -- a first find, not an exhausted search, on different
    geometry.  Its model has no put-without-connect, no retaining pickup and no 1-terminus connect
    (connect places the held connector), and its goal names the known answer's layout.

ENUMERATOR DECLARATIONS (analysis, 2026-10-12; nothing written or run)
  Base facts in this spec: has-location (agent1, connector1-3), holding (agent1 connector),
    paired (connector terminus).  Fixed apparatus has coordinates, not has-location.
  Declarations needed:
    has-location: connectors may be unassigned (held), at most one.
    holding: its own base relation, at most one connector, only one with no location.  Required
      because :on-assign does not set facts for an unassigned key, and pickup/put/connect
      preconditions read holding, so predecessors through those actions need it.
    paired: up to 3 per connector (matches *max-connector-pairings*); a held connector may keep
      pairings (retaining pickup), unlike the old model's declaration.
  Goal filter: none needed; the spec's own goal (agent at location4, receiver2 and receiver3
    active) is neutral.  The old corner filter named the known layout and is not reused.
  Size estimate: agent fixed at location4; per connector 4 locations or held, 64 pairing subsets
    (0-3 of 7 termini); about 3 x 10^7 combinations, about 5 x 10^6 after connector symmetry,
    each propagated once: roughly 15 minutes serial at ~170 us each.  Goal-state count unknown.
  Main risk: growth of the backward layers (forward branching here is 10-18 per level).
  Threads: enumerator steps not checked with threads; run them serially until checked.

ACTION-SET REDUCTION (analysis, 2026-10-12; nothing changed)
  Requirement: dropping an action keeps min-length meaningful only if every shortest plan using
    it has a replacement plan of the same length without it.  Without that argument a reduced
    model still yields valid plans (an upper bound), but not minimality.
  Single-terminus connect: cannot be dropped.  The known 15-action plan uses it (connector2 to
    transmitter1 at location4, the cutter beam).
  Retaining pickup: probably replaceable -- plain pickup, then connect at the destination to the
    same termini, costs the same two actions -- when the connector has at most 3 links in all and
    each terminus is connectable from there.  Exceptions (more than 3 links) exist; not proved.
    About 4% of successors at depth 3.
  Put without pairing: no general replacement.  Connecting instead creates beams that can cut
    others or change colors, and an unpaired placed connector can later be linked by another
    connector's connect.  Any proof would be geometry-specific.  At most about 15% of successors
    at depth 3 (moves and puts together).
  Conclusion: removing the replaceable actions saves perhaps 5-20%, not orders of magnitude.  The
    branching is in connect choices (70%), which the spec advisor found no sound way to narrow.
  Not recommended.  Direction: return to the enumerator meet-in-the-middle, which changes no rules.

GOAL-STATE ENUMERATION (2026-10-12, user, Windows, serial, problem-corner-topo-advisor-1.lisp)
  (find-goal-states), every: completed normally, 23 min 12 s, 162,028,700 program cycles,
    453,021 inconsistent abandoned; 31,188 goal states before connector-symmetry dedupe,
    5,828 after (25,360 dropped).  Holding (stored both ways) enumerated correctly.
  Sample goal state 1: connector2 at location3 red, connector1 at location2 blue, connector3 held
    with three retained pairings; receiver1 not active (consistent with the separation result).
  Display quirk: the end-of-search "minimum path" display tries to replay the enumerator's
    internal assignment steps and reports a REPLAY FAILURE; it does not affect the goal states.
  Open: goal states needing more than 3 pairings on one connector are not generated.
  Next: backward layer growth with find-predecessors, one layer at a time.  At 5,828 goal states,
    a 7-layer backward half is feasible only if backward branching is low (about 3 or less);
    a split such as forward 10-11 and backward 4-5 may be the practical one.

BACKWARD LAYER 1 (2026-10-12, user, Windows, serial)
  (find-predecessors): 5,641,504 candidates, 5,612,364 feasible, 0 validated, 859 s; reported
    "saturated".  Wrong: the known plan's last step (pickup of connector2 at location4) is a
    valid predecessor of a goal state.
  Cause 1 (source, src/ww-enumerator-run.lisp enum-action-in-family-p): predecessor action
    families are hard-coded to the old corner model's names -- move, pickup-connector,
    connect-to-1/2/3-terminus.  put-connector, connect-connector and
    pickup-connector-retaining-pairings are silently never considered.
  Cause 2 (unresolved): pickup-connector also validated nothing.  Errors during validation are
    caught and only counted (fps-forward-per-object-validate-leaf), so the reason is hidden.
    Not yet checked whether the known plan's final state is among the 5,828 goal states.
  Cost signal: about 970 candidates per goal state for two actions alone; connect predecessors
    would add many more.
  Status: engine capability gap.  Meet-in-the-middle cannot proceed on this spec without an
    engine change (authorization needed).

PREDECESSOR FIX, PHASE 1 (2026-10-12, engine edit approved; src/ww-enumerator-run.lisp)
  Single-state test (known final state as the only frontier, move + pickup-connector):
    before: 968 candidates, 0 validated (pickup never applicable; move applied 6 times, all to
    other locations).  No hidden errors.
  Move: no move predecessor exists for the known final state -- from location3 the agent cannot
    walk to location4 after connector2's pickup.  Correct, not a bug.
  Cause: the per-object CSP re-guessed one object at a time; undoing a pickup changes agent1's
    holding and connector2's location/pairings together.  Holding's unkeyed enumeration step was
    also dropped and its HOLDING1/HOLDING2 index facts never cleared.
  Fix: object sets (single key objects plus holder-held pairs for holding).  After the fix:
    63 pickup predecessors with connector2 at location4 and agent1 empty-handed, including the
    known one (paired connector2 transmitter1).  Pickup branching is inherent: it erases pairings,
    so any pairing set for the picked-up connector is a valid predecessor.
  Limitation: pairings from other connectors to the picked-up connector are not restored.

PREDECESSOR FIX, PHASE 2 (2026-10-12, engine edit approved; src/ww-enumerator-run.lisp)
  find-predecessors now tries every action in the spec (:actions narrows by name).
  Inferred modified base relations: pickup-connector, connect-connector (paired holding
    has-location); pickup-connector-retaining-pairings, put-connector, move (holding has-location).
  Single-state test (known final state, all 5 actions): raw 4,589, feasible 4,569, validated 64,
    all pickup-connector = every pairing set of up to 3 for connector2 among its 7 partners.

PARALLEL FIND-PREDECESSORS (2026-10-12, engine edit approved; src/ww-enumerator-run.lisp)
  Frontier states are shared out across *threads* workers; each worker keeps its own results,
  merged at the end.  Workers inherit the caller's package and print settings (keys are
  printed strings).  bw-normalize! now adds CURRENT-BEAMS only when the problem defines it.
  Test (layer 2 from the 64 layer-1 predecessors, all 5 actions):
    16 threads: 36.2 s real, 472 s CPU (92 s system), 447 GB consed
     0 threads: 201.3 s real, 201 s CPU, 447 GB consed
    both: 333 unique predecessors, raw 251,840, feasible 250,560, validated 2,131
  Speed-up 5.6x; limited by allocation contention (about 7 GB consed per frontier state) and
  the uneven finish of 64 tasks on 16 threads.

PHASE 3 RE-MEASUREMENT (2026-10-13, 16 threads)
  find-goal-states: 5,828 goal states (matches serial), 178 s real vs 23 min serial (7.8x),
    2,769 s CPU, 1.5 TB consed.
  Known final state is among the goal states only as a connector-renamed twin (plain base key
    misses it; enum-solution-state-key, the canonical key, matches 1).  Checks against the
    reachable set must use canonical keys.
  find-predecessors layer 1 (all 5 actions, from 5,828 goal states):
    raw 23,854,012, feasible 23,737,452, validated 20,659, 4,054 new unique (9,882 total),
    4,633.6 s (77 min).  The known plan's penultimate state is present (canonical match 1).
  Successor check by fact set (2026-10-13, engine edit approved; src/ww-enumerator-run.lisp):
    A profile showed fps-idb-base-prop-key (a printed sorted key built for every successor, only
    to compare with the frontier key) consed 5.0 of 6.4 GB per frontier state.  Replaced by
    fps-base-prop-set (once per frontier state) and fps-idb-base-props-match-p (stops at the
    first fact not in the frontier's set).  Results unchanged.
    Single state (known final state), serial: 11.8 s -> 4.9 s, 6.4 GB -> 1.39 GB consed.
    Layer 2 from the 64 layer-1 states, fresh image: serial 201.3 s -> 68.7 s (3.9 s system);
      16 threads 36.2 s -> 10.8 s (6.4x over serial, 14 s system); 447 GB -> 101 GB consed;
      333 unique, as before.
    Caution: in an image that had already run find-goal-states, layer 1 and two thread-count
      reloads, the same layer-2 test took 409 s serial / 129 s at 16 threads, with system time
      dominating (about 2.6 s per GB consed).  Time comparisons need a fresh image.

REPLAY DISPLAY AND FRONTIER FIXES (2026-10-13, engine edits approved; fresh image, 16 threads)
  Replay failure in find-goal-states' "minimum path" display: enum actions are built with no
    effect variables (install-enum-action), but their steps are recorded with an argument, so
    the replay's argument-count check failed at step 1.  New *enum-csp-search-active*
    (ww-enumerator-build.lisp), bound to T around ww-solve in %enumerate-state-csp;
    printout-solution prints a one-line "display skipped" note while it is set.  Verified.
  Frontier fix (%find-predecessors-fn): the next layer's frontier was every key in the layer
    table, including predecessors already reachable (already expanded earlier).  Now only keys
    not yet reachable, collected before the merge.
  Results:
    find-goal-states: 5,828, 177 s.
    Layer 1: raw 23,854,012, feasible 23,737,452, validated 20,659, 4,055 new (9,883 total),
      959 s (was 4,634 s before the fact-set fix).
    Layer 2: frontier 4,055 (was 5,527), raw 18,006,715, feasible 17,925,615, validated 38,670,
      3,125 new (13,008 total), 722 s (was 969 s).
  Run-to-run variation: layer 1 new count 4,054 / 4,043 / 4,055 over three runs with the same
    validated count.  Cause: canonical dedupe keeps whichever connector-renamed twin the
    parallel search records first, while the reachable set is keyed by the plain base key, so
    which predecessors collide with goal states varies.  The reachable set may also hold
    connector-renamed duplicates.  Not yet measured.

CANONICAL REACHABLE-SET KEYS (2026-10-13, engine edit approved; fresh image, 16 threads)
  Measured first: the 13,008-state plain-keyed reachable set held 8,493 distinct states up to
    connector renaming (35% twins).  Plain keys also risked missing meetings: goal states keep
    one twin per class, so a forward state that is a renamed twin of a backward state would
    not be found.
  Change (src/ww-enumerator-run.lisp): reachable set and layer tables keyed by
    enum-solution-state-key (canonical; same key as find-goal-states' dedupe), in seeding,
    forward store, backward direction and the meeting-point lookup.  Witnesses stay concrete,
    each paired with its own state.  Collision diagnostics now count validated predecessors.
  Results:
    Layer 1: raw 23,854,012, feasible 23,737,452, validated 20,659, 1,674 new (7,502 total),
      960 s.
    Layer 2: frontier 1,674, raw 7,109,082, feasible 7,075,602, validated 32,547, 991 new
      (8,493 total), 291 s (was 722 s).
  8,493 equals the measured canonical count of the plain-keyed set: no state class lost.
  Backward growth per layer: 5,828 goals, +1,674, +991.

BACKWARD LAYERS 1-5 (2026-10-13, canonical keys, fresh image, 16 threads)
  layer  frontier   new      total    validated   raw          time     new per frontier state
  1      5,828      1,674    7,502    20,659      23,854,012   966 s    0.29
  2      1,674        991    8,493    32,547       7,109,082   292 s    0.59
  3        991      2,113   10,606     6,462       4,440,443   196 s    2.1
  4      2,113     11,524   22,130    21,778       9,696,557   377 s    5.5
  5     11,524     77,224   99,354   146,767      52,423,874  1982 s    6.7
  Total about 63 min after find-goal-states.  Growth stays small for two layers (states near
  the goal configuration), then approaches forward branching (x5.5 to x6.7).  Time per frontier
  state about 0.17 s from layer 4 on.  Layer 6 projected: about 77k states x 0.17 s = 3.6 h,
  about 500k new states.

KNOWN-PLAN CHECK AGAINST THE 5-LAYER BACKWARD SET (2026-10-13)
  State after k steps of the known 15-step plan, looked up by canonical key; stored witness
  path lengths:
    k=8 none; k=9 (5 5 5 5); k=10..12 all 5; k=13 (5 5 5 5 4 4 4 4); k=14 (3 3 3 3 3 3 2 2);
    k=15 (2 2 2 2 2 2 2 2)
  k=9 first appears at layer 5: the state after 9 plan steps is at most 5 steps from a goal,
    so a plan of at most 14 steps exists (the known plan's last 6 steps are not shortest).
    "At most" because of the known missed-predecessor limitation (pickup's erased pairings
    to other connectors are not restored).
  Witness depths are wrong for k=13..15 (true depths <= 2, 1, 0): fps-complete-layer merges a
    layer's witnesses into entries that already exist, adding longer paths; the witness cap (8)
    keeps the newest, so the shortest (first-layer) witnesses are evicted.  The meeting-point
    goal and guided suffix use the maximum stored depth, so depths read high.

SHORTEST-WITNESS FIX (2026-10-13, engine edit approved; fps-complete-layer)
  fps-complete-layer adds only keys not yet reachable; an existing entry keeps the witnesses
  of the layer that first reached it (stored depth = shortest backward distance).
  Rerun, fresh image, 16 threads: layers 1-5 new/total counts unchanged (1,674 ... 99,354);
    layer times 968 / 292 / 197 / 376 / 1977 s.  (Layer 5 raw 52,424,528 vs 52,423,874 before,
    same validated and new counts: the frontier's concrete twin representatives vary.)
  Known plan, steps 8..15: (8 NIL) (9 5) (10 4) (11 3) (12 3) (13 2) (14 1) (15 0).
    Steps 11 and 12 are both 3 from the goal (one wasted step); the 9-step prefix plus 5
    backward steps gives a plan of at most 14 steps.
  Meet-in-the-middle implication: every path to the goal passes through a distance-5 state,
    so (solve-meeting-point :depth-cutoff 9 :min-backward-depth 5) should find a 14-step plan.

MEET-IN-THE-MIDDLE, FIRST RUN (2026-10-13, 16 threads, same image as the 5 layers)
  (solve-meeting-point :depth-cutoff 9 :solution-type first :min-backward-depth 5):
    1,196 s real, 9,987 s CPU (1,570 s system), 8.8 TB consed.  33,053 meeting solutions,
    none extended ("failed replaying all witness suffixes ... PRECONDITION-FAILURE").
  Guided suffix from the known plan's 9-step state (distance 5): 66 actions apply; the plan's
    step 10 reaches depth 4; the walk dies after 3 nodes (no depth-2 successor of a depth-3 state).
  Cause: the plan's 11-step state shares its canonical key with witness states in which agent1
    holds a connector, while in the plan state agent1 holds nothing.  holding is a bijective
    base relation stored only as index facts HOLDING1/HOLDING2; every base-fact extractor
    (enum-state-base-props, enum-canonical-base-key, fps-base-prop-set,
    fps-idb-base-props-match-p) keeps facts whose relation name is a base relation, so holding
    is invisible to every key and to the successor match.  States differing only in what the
    agent holds were merged, and predecessors were validated against holding-variants of the
    frontier state.  All goal-state and layer counts so far are affected.

HOLDING FIX TEST (2026-10-14, fresh image, 16 threads)
  enum-base-props-of: REL1 index facts -> (REL . args), so holding enters every key and the
  successor match.  Plan state after 9 steps now shows (HOLDING AGENT1 CONNECTOR1).
  find-goal-states: 5,828 goal states (canonical dedupe dropped 25,360); unchanged, so goal
    states were not affected by the merge.
  Backward layers (new unique / total, time):
    1: 3,855 / 9,683    1065 s   (23.9 M raw, 21,877 validated)
    2: 3,758 / 13,441    761 s
    3: 2,471 / 15,912    788 s
    4: 3,433 / 19,345    488 s
    5: 6,504 / 25,849    622 s   (total 3,724 s)
  Layer totals are about 1/4 of the pre-fix figures (99,354 at layer 5): the pre-fix runs
    validated predecessors against holding-variants of the frontier, admitting false ones.
  Known plan, steps 8..15: (8 NIL) (9 NIL) (10 5) (11 4) (12 3) (13 2) (14 1) (15 0).
    Each step has one depth and the depth falls by exactly 1 per step: plan steps 10..15
    are shortest.  Step 9 is beyond layer 5, so the earlier "plan of at most 14 steps"
    conclusion was an artifact of the holding-blind keys.  Distance of step 9 is 6
    (or a missed predecessor; see the pickup limitation).
  Holding fix: closed.

MEET-IN-THE-MIDDLE, DEPTH 10 (2026-10-14, same image as the 5 post-fix layers)
  (solve-meeting-point :depth-cutoff 10 :solution-type first :min-backward-depth 5):
    heap exhausted after about 2,550 s.  Last progress: 34.3 M states, 5.4 M closed entries,
    84% repeated, b* 5.56, 154 meeting solutions, none extended (extension runs only after
    the exhaustive search ends).
  Next: 6 backward layers (plan step 9 expected at depth 6), then depth-9 meeting run.
    Deferred until the backward set can be saved to and loaded from a file.

BACKWARD LAYER 6 (2026-10-14, fresh image, 16 threads, resumed from the saved 3-layer file)
  load-predecessors (corner-topo-advisor-1-predecessors-3.lisp) then find-predecessors to 6.
  Layer 6: 27,564,396 raw, 127,887 validated, 66,037 new unique (91,886 total), 1,227 s.
    Saved file: 252,833,898 bytes, 2.5 s.
  Layer 6 adds 10x the states of layer 5 (6,504): the backward frontier is widening fast,
    so further backward layers get expensive in states and file size.
  Known plan, steps 8..15: (8 NIL) (9 6) (10 5) (11 4) (12 3) (13 2) (14 1) (15 0).
    Step 9 is at distance 6 as expected; plan steps 9..15 are shortest.
  Next: (solve-meeting-point :depth-cutoff 9 :solution-type first :min-backward-depth 6).

MEET-IN-THE-MIDDLE, DEPTH 9 x 6 LAYERS (2026-10-14, 16 threads, same image as layer 6)
  (solve-meeting-point :depth-cutoff 9 :solution-type min-length), default min depth 6:
    forward search 781 s real, 9,376 s CPU, 8.35 TB consed; 13.0 M states, 76.9% repeated,
    1.62 M canonical duplicates pruned.  Whole call 788 s (extension about 7 s).
  92 meetings, all at forward depth 8; all 92 extended; shortest full plan 14 steps
    (8 forward + 6 backward), one step shorter than the known 15-step plan.
  Plan: pickup C1, walk L1-L2, connect C1 (R3 R1 T2), pickup C2, walk L2-L3,
    connect C2 (C1 R1 T1), pickup C3, walk L3-L4 via gate1, connect C3 (T1), walk L4-L3,
    pickup C2, connect C2 (C1 R2 T1), walk L3-L4, pickup-connector-retaining-pairings C3.
  The known plan meets distance 6 at step 9; this plan reaches it at step 8.
  Comparison: earlier forward search to depth 8 alone took 39 s, with x5..x8 per level, so a
    direct forward search to 14 was out of reach; backward 6 layers (about 1.4 h) plus a
    13-min forward search found it.
  solve-meeting-point-fn now returns T (solutions in *solution-paths*).

MEET-IN-THE-MIDDLE AS MIN-LENGTH (2026-10-14, fresh image, 16 threads, loaded 6-layer file)
  Change: solve-meeting-point-fn searches as MIN-LENGTH when min-length is requested, with a
    meeting goal that requires bridgeability (stored suffix reaches the original goal);
    bridge cache synchronized.  Other solution types still search as EVERY.
  (solve-meeting-point :depth-cutoff 9 :solution-type min-length):
    bounds printed: 9, then 8.  2 solutions recorded (depths 9 and 8), both extended.
    Forward search 181.5 s real, 2,321 s CPU, 2.05 TB consed; 3.60 M states, 78.0% repeated.
    Whole call 181.7 s.  Same 14-step plan.
  Against the exhaustive EVERY run (781 s, 13.0 M states, 8.35 TB): 4.3x faster, 3.6x fewer
    states, 4.1x less consing.  Once the depth-8 bound is set the search only seeks depth-7
    meetings, so the 14-step plan is shortest for this backward set.

MEET-IN-THE-MIDDLE AS FIRST (2026-10-14, fresh image, 16 threads, loaded 6-layer file)
  Change: FIRST also searches as itself, with the bridgeability meeting goal.
  (solve-meeting-point :depth-cutoff 9 :solution-type first):
    stopped at the first extendable meeting, forward depth 9: 58.2 s, 0.97 M states,
    0.62 TB consed.  15-step plan (9 + 6), different from the known 15-step plan.
  Summary of the three meeting modes at D = 9, L = 6:
    every       781 s  13.0 M states  92 meetings  shortest 14
    min-length  182 s   3.6 M states   2 meetings  14 (proved shortest for this set)
    first        58 s   1.0 M states   1 meeting   15

SPEC CONSOLIDATION (2026-10-14, user)
  problem-corner-topo-advisor-1.lisp renamed to problem-corner-topo-advisor.lisp, replacing
    the 2026-10-12 spec; *problem-name* is now corner-topo-advisor.  The only difference
    from the replaced spec is the enumerator declarations (has-location, holding, paired,
    consistent-holding) and a design note; rules and goal unchanged.
  Entries above naming corner-topo-advisor-1 refer to this same spec under its old name.
  Saved predecessor files carry the problem name and are checked on load, so files saved
    as corner-topo-advisor-1-predecessors-*.lisp no longer load; regenerate them.

PREDECESSOR SCREEN AND NORMALIZER (2026-10-17, user, Windows, fresh image, 16 threads)
  find-goal-states: 5,828 (unchanged).  Layer 1: 23,854,012 raw, 23,824,872 feasible,
    6,210 validated, 1,048 new (6,876 total), 720 s; was 21,877 validated, 3,855 new,
    1,065 s.
  Container check (12 random forward-walk states): every predecessor removed by the screen
    was "both held and assigned HAS-LOCATION" (eg holding connector2 with connector2 at
    location4); put-connector overwrites the stale location, so forward validation had
    accepted it.  The earlier backward layers 1-6, and meeting results stated relative to
    them ("proved shortest for this set"), rest on sets that include such states;
    regenerate before relying on them.  (Done the same day: next entry; the 14-step result
    is re-confirmed.)

BACKWARD LAYERS 1-6 AND MEETING, RE-RUN WITH SCREEN (2026-10-17, user, Windows, fresh image,
16 threads)
  find-goal-states 5,828; find-predecessors :layers 6 (new / total; pre-screen run in brackets):
    1: 1,048 / 6,876     [3,855 / 9,683]
    2:   250 / 7,126     [3,758 / 13,441]
    3:   372 / 7,498     [2,471 / 15,912]
    4: 1,341 / 8,839     [3,433 / 19,345]
    5: 4,095 / 12,934    [6,504 / 25,849]
    6: 16,164 / 29,098   [66,037 / 91,886]
  Saved files corner-topo-advisor-predecessors-1..6.lisp, layer 6 65 MB (was 253 MB).
  (solve-meeting-point :depth-cutoff 9 :solution-type min-length), min backward depth 6:
    178.8 s, 3.61 M states, 77.7% repeated, 2 solutions (as before: 181.5 s, 3.60 M).
    Same 14-step plan (8 forward + 6 backward), step for step; shortest for this backward set,
    now one containing only physically possible states.
