Skip to content

Retire the pre-request convergence settlement chain and land the four-case gate #1761

Description

@pinin4fjords

Parent: #1745

Predecessor: #1754 and its stacked draft PR, which made convergence grant application a mechanical recipe materializer and completed Seed 77.

Prototype evidence: draft PR #1743 and checkpoint 3f11f175.

Retrieving the prototype: git fetch origin refs/pull/1743/head:pr-1743-checkpoint, then read files with git show 3f11f1758f16341ace6b1409eff53a36a36ec715:<path>. Never check that branch out into your worktree.

Outcome

Retire the pre-request legacy convergence settlement chain on main so the cohort plan is the first and only owner of the coordinates it migrates, and land the complete four-case acceptance gate: Seed 15, Seed 77, opposing bypass, and stacked collector pass together, here, once.

Estimate: 4-8 focused hours, hard maximum one working day. If any single legacy pass cannot be subsumed within budget, stop and split by pass family with a documented boundary; each split half must still transfer and delete together.

Starting evidence

On main, the legacy settlement chain runs BEFORE the request producer, so the old owner decides trunk/landing coordinates first and the cohort request reads the post-settlement value. The competing owners (all src/nf_metro/layout/routing/convergences.py): _pack_cotravelling_corridor_runs, _separate_distinct_cotravelling_trunks, _separate_distinct_counter_running_trunks, _lane_trunk_runs, _settle_shared_opening_pivots (2120), _settle_shared_source_openings (2163), _settle_opposing_landing_channels (2212), _move_trunk_flank, _move_landing_opening, _reseat_landing_opening, _reseat_landing_cross, _settle_shared_trunk_channels, and any remaining _move_trunk_axis caller left after #1754 retired the grant path. Note: _settle_reserved_trunk_axes is NOT on main (checkpoint-branch-only); nothing may create it.

These passes resolve real, gate-triage-documented conflicts, including feasibility refusals (#1712). Subsumption means the typed relations and grants from #1751/#1752/#1754 express the same conflicts constructively; the new model must refuse the same infeasible cases, not silently accept them.

Scope

  • For each legacy pass above: either subsume it (its conflict resolution becomes typed relations and grants, and it is deleted in this PR) or explicitly retain it with cited evidence that it cannot write a coordinate a grant controls. Record every decision in the PR body under "Coordinates transferred / setters deleted in this PR".
  • Land the four-case gate, spelled by test id, re-deriving geometric expectations against this stack's settled geometry (checkpoint coordinates are not copied blindly).
  • Add the trace-independent opposing-bypass geometry lock. This is where it first becomes mandatory: on examples/topologies/opposing_bypass_corridor.mmd, the two opposite-running lines hold distinct, direction-qualified lane coordinates one pitch apart (the checkpoint content was top_crossings == {"ribo": {692.0}, "rnaseq": {696.0}}; re-derive exact values from this stack's geometry). Name it test_opposing_bypass_lines_hold_separated_direction_qualified_lanes. Materialize accepted grants once through owner frames #1756, Publish and enforce the cohort-final freeze #1757, and Run the aggregate checkpoint with the mechanical ownership audit #1758 must preserve it.

The four-case gate, spelled by test id

pytest -q -n 0 \
  "tests/test_member_geometry.py::test_seed_15_routes_split_siblings_as_independent_members" \
  "tests/test_member_geometry.py::test_seed_15_wraps_u_bypass_above_crossing_merge_trunk" \
  "tests/test_member_geometry.py::test_seed_77_shortfall_requests_one_atomic_corridor_aperture" \
  "tests/test_member_geometry.py::test_reservation_reroute_reseats_port_peeloff_after_reconciliation" \
  "tests/test_corridor_cohort_integration.py::test_opposing_bypass_lines_hold_separated_direction_qualified_lanes" \
  "tests/test_corridor_cohort_integration.py::test_no_solver_owner_contains_opposite_running_claims"

Port the seed and collector locks from the checkpoint (tests/test_member_geometry.py:222, :284, :985, :1017 at 3f11f175). Confirm the collected count matches six before believing a pass; no test name contains "opposing" or "stacked", so -k opposing and -k stacked silently select nothing. main's test_stacked_collector_reuses_three_lanes_across_twelve_claims in tests/test_route_reservations.py is unrelated.

Non-goals

Acceptance

  • The four-case gate above passes together, including the opposing-bypass geometry lock.
  • Every subsumed pass is deleted in this PR; every retained pass has cited evidence it cannot write a granted coordinate.
  • No granted trunk-axis coordinate is re-set by any retained legacy pass.
  • Feasibility refusals the legacy chain enforced are still refused, with typed provenance.
  • Opposite-running routes remain distinct and unbundled.
  • The behavior-changing stacked PR runs CI and the authoritative render diff; it remains draft and unmerged until the complete stack is green.

Verification

pytest -q -n 0 tests/test_convergence_corridor_grants.py
pytest -q -n 0 tests/test_member_geometry.py -k 'seed_15 or seed_77 or reservation_reroute_reseats'
pytest -q -n 0 tests/test_corridor_cohort_integration.py -k 'opposing_bypass or opposite_running'
pytest -q -n 0 tests/test_hash_seed_determinism.py
ruff check src/nf_metro/layout/routing/convergences.py src/nf_metro/layout/routing/planning.py
ruff format --check src/nf_metro/layout/routing/convergences.py src/nf_metro/layout/routing/planning.py
mypy

Check the collected count on every -k run; zero collected exits 5, which reads like success. Behavioral children also refresh the derived corpora (hash pins, python scripts/routing_gate_coverage.py --write, guard goldens via python tests/test_guard_registry_golden.py) and declare the churn in the PR body.

#1653 guardrail and stop condition

Deletion is part of the ownership transfer. If removing a legacy pass exposes missing coverage, stop and repair the earlier owner model (the missing relationship belongs in #1751/#1752); do not retain dual ownership, add a post-pass, or weaken a gate.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    layoutLayout engine, phases, ordering (layout/)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions