Skip to content

Add scalar APERTURE provenance and one-batch handoff #1753

Description

@pinin4fjords

Parent: #1745

Predecessor: #1752 and its stacked draft PR. Also requires #1759 (deferred final route guards): once this issue publishes CORRIDOR_COHORT_APERTURE requirements at discovery, final-checkpoint route guards must defer to the settled chokepoint or they would fire on pre-settlement geometry across the corpus. #1759 is based on main and independently mergeable; before this issue starts, it must be present in the base (merged to main and refreshed in, or stacked beneath this branch).

Prototype evidence: draft PR #1743 and checkpoint 3f11f175, including typed CorridorClearanceShortfall, CorridorCohortObstacleProvenance, and CORRIDOR_COHORT_APERTURE stage scaffolding.

Direct partial-work links: CorridorCohortFailure, obstacle provenance, and resolved_shortfall, _corridor_cohort_aperture_requirements, render CORRIDOR_COHORT_APERTURE settlement, and the Seed 77 atomic aperture test.

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

Map every failed member/scalar component to exact row/column boundary provenance and settle the complete shortage set in one APERTURE batch.

Estimate: 4-8 focused hours, hard maximum one day. Use a fresh worktree based on the predecessor PR.

Starting reproduction

pytest -q -n 0 tests/test_member_geometry.py -k 'aperture or shortfall' --collect-only -q   # 0 collected on the predecessor
git grep -n 'BoundaryClearanceRequirementKind' -- src                                       # prints nothing

BoundaryClearanceRequirementKind does not exist on main. src/nf_metro/layout/settlement_demand.py defines BoundaryClearanceRequirement with exactly axis, boundary, owner_id, required, negative_section_ids, positive_section_ids, description; there is no kind field. This issue ADDS the BoundaryClearanceRequirementKind enum with GENERAL and CORRIDOR_COHORT_APERTURE members plus the kind field, defaulting to GENERAL so existing producers are unaffected.

Scope

  • corridor_cohort_integration.py: retain relation-native boundary, negative owner, positive owner, witness, obstacle, axis, side, and deficit provenance for member and scalar failures.
  • member_geometry.py: map member claim IDs and scalar owner IDs through their own typed provenance; scalar IDs must not impersonate reservation claims.
  • settlement_demand.py: add the BoundaryClearanceRequirementKind enum and kind field as above.
  • Render _settle_render_geometry: emit exact GENERAL/APERTURE requirements, reject incomplete batches, and emit the APERTURE_SETTLEMENT trace event from Trace final settlement and resolve seed-72 routing defects #1746's vocabulary.

The checkpoint's negative evidence for the provenance gates: its clearance_shortfall returned None unless every blocking obstacle arrived with a shift sign, and its resolved_shortfall returned nothing if any blocking obstacle lacked provenance, which is exactly how Seed 15's scalar component became "infeasible without a complete typed shortfall". Every failed component must produce a typed shortage; a silent None is a defect.

Reuse guidance

Reuse the checkpoint's sign-aware row/column mapping and one-batch render stage. Do not port raw target-only sensitivity logic or the rejected sensitivity-aware aperture projection. (landing-obstacle| appears in earlier drafts of this programme but exists neither on main nor at 3f11f175; ignore it.)

Re-establish test_seed_77_shortfall_requests_one_atomic_corridor_aperture and test_aperture_grant_has_one_ordered_planning_transition, rewriting the latter's stage discrimination onto #1746's trace vocabulary (the checkpoint discriminated intent from final via finalized_owned_segments is None, which this stack never creates). This issue does not freeze or materialize the accepted plan; the mechanical-grant, persistence, and freeze successors own those transfers.

Non-goals

  • No repeated APERTURE cycle, convergence grant application, or freeze.

Code expected to become obsolete

None on main. Connector-direction boundary inference (the checkpoint read the connector's target section to pick the boundary) is never introduced; a test must fail if boundary selection consults connector source/target direction.

Acceptance

  • Exact side, sign, deficit, owner, obstacle, connector, region, and boundary provenance is preserved.
  • Every failed component in the intent has a typed shortage before any batch is accepted.
  • Intent failure publishes no patches, grants, accepted plan, or owner changes.
  • Member and scalar shortages are aggregated, settled once, then followed by one final solve.
  • Exactly one final solve follows settlement; a second shortage fails loudly without retrying.
  • A boundary move is emitted only when the relation's typed boundary ownership makes the shortage satisfiable; no target-only guess.
  • Connector source/target direction is never used to infer the boundary carrier.
  • A missing or ambiguous mapping fails closed.
  • At most two compiles per render (intent and final), asserted through Trace final settlement and resolve seed-72 routing defects #1746's trace.
  • 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_member_geometry.py -k 'aperture or shortfall'
pytest -q -n 0 tests/test_corridor_cohort_integration.py -k 'aperture or clearance or provenance'
pytest -q -n 0 tests/test_deferred_final_guards.py
ruff check src/nf_metro/layout/routing/corridor_cohort_integration.py src/nf_metro/layout/routing/member_geometry.py src/nf_metro/layout/settlement_demand.py src/nf_metro/render/svg.py
ruff format --check src/nf_metro/layout/routing/corridor_cohort_integration.py src/nf_metro/layout/routing/member_geometry.py src/nf_metro/layout/settlement_demand.py src/nf_metro/render/svg.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, gate coverage, guard goldens) and declare the churn in the PR body.

#1653 guardrail and stop condition

At most one APERTURE batch is permitted. If the final solve asks for more space, stop and treat it as an ownership/provenance defect; do not retry or tune the demand.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions