25 KiB
Port-policy revision experiment design — 2026-09-12
Status: source/design proposal only for root-owned issue16. No policy, compiler, native application or production file changed. The executed 7e25b3d CapacityAware policy is not adoptable. Preserve its implementation, the passed foundational gates, and the failed a95db10 falsifiers as comparison evidence.
The next useful experiment is stable per-port fallback preferences plus obstacle-aware placement within side intervals, over frozen owner bounds. Compare stable preferences alone as an attribution control. A bounded repair that only changes sides and calls the existing position allocator is insufficient: the near-corner case below predicts a repair stall even though a readable placement exists on the same side. Do not introduce a general port-to-slot matching framework or repeated inverse/routing feedback loop at this point.
Executed evidence read
Read native-qa/resize-falsifiers-a95-01/run.json and both full case logs. Exact core 7e25b3d3907693cbbf03bb51b5e08b01d743a934, exact tests a95db10ce73d639f59eb1ec1153de26f4967881c; both tests exited101 at their intended prospective assertions, with unchanged stamped inputs and binary. These are observed candidate failures, not hypothetical failures or harness errors.
| Actual comparison | Current | SameSidesAdaptSpacing | CapacityAware |
|---|---|---|---|
| 20 ports, authored height259.9→260→260.1, adjacent side changes | [0,0] |
[0,0] |
[12,0] |
| Visible height at259.9 | 568 | 259.9 | 259.9 |
| Minimum same-side center separation at259.9→260 | 27.99997→27.99997 | 11.78421→11.789459 | 31.985703→28 |
| Total routed length at259.9→260 | 36976→36976 | 39145.004→39143.996 | 41393.008→41410 |
| Total bends at259.9→260 | 42→42 | 54→54 | 54→55 |
| Eight-port unrelated-top-obstacle blocked mandatory stubs / warnings | 0 / 0 | 0 / 0 | 1 / 1 |
In the obstacle case, port 956a2026-0912-4000-8000-00000000006a crosses obstacle ...002a; its real exchange ...03ee reports NoClearPath. Controls keep all eight Right exits. Candidate uses L/R/T/B counts1/5/1/1 and the offending Top endpoint (112,0).
These routes are synthetic measurements, not a complete readability score. The candidate's threshold route is approximately5.7% longer than spacing-only at259.9, despite its better separation. The logs do not measure crossings or label collisions. The separation metric measures same-side center distance; 14-unit component glyph width explains why the spacing-only20-port result is a problem, but it does not make center spacing a text/readability proof.
Underlying requirements remain ergonomic modern graphical/textual editing and maintainability (PROJECT_GOAL.md:38–71,110), not preserving the failed allocator. Frozen authored/content bounds, exact eight-handle geometry, source/API parity, exact manual anchors and unrelated automatic-side stability remain the boundary established in resize-port-policy-20260912.md.
Source facts that constrain revisions
At the experimental base, projection/port_layout.rs computes peer-facing/semantic preferences and automatic shadow sides independently of authored anchors. It then applies the anchors and uses automatic_positions to spread automatic ports around fixed fractions. CapacityAware's ranked orders fallback sides by current occupancy (port_capacity_experiment.rs:34–52); recomputing that ranking after one new preferred-side slot shifts many subsequent choices. Stable IDs make this repeatable, not stable during resizing.
clear_exit tests only the side midpoint against connected peers (port_layout.rs:80–119). Simply including every visible obstacle fixes the executed Top case but leaves the offset-specific defect below. Actual routing uses the projected port and its18-unit outward stub, inflates obstacles by12, and rejects a blocked mandatory stub before path search (routing.rs:377–390,627–647,735–747). Its ancestor/header exceptions matter; a new projection checker must not invent a different interpretation of traversable containing nodes.
The existing position allocator puts the first and last automatic ports at the usable interval ends when more than one occupies an interval. With no authored anchors, those ends are18 and length−18 (port_layout.rs:336 onward). Removing one port from a side normally redistributes all remaining ports on that side. This coupling is why testing only the moved port during repair is invalid.
Third falsifier: clear midpoint, blocked actual corner exit
This is a new source-derived prediction, not yet executed. Reuse the typed eight-port/right-peer fixture from the successful falsifier harness, changing only the unrelated actor placement:
| Placement | Authored bounds |
|---|---|
| Owner, eight Standard/Unset ports | (0,0) / 224×160 |
| Distant SystemActor peer, one port, eight BoundaryExchanges | (1908,336) / 184×132 |
| Unrelated visible SystemActor, no containment/exchange to owner | (230,−120) / 184×132 |
The obstacle's inflated rectangle is x [218,426], y [-132,24]. Right midpoint (224,80) and its outward stub are clear. CapacityAware places five Right ports at y18,49,80,111,142. The first port's stub from (224,18) to (242,18) intersects the inflated obstacle. An all-visible-midpoint predicate still approves Right.
A same-side nominal-gap witness exists: y24.01,53.5075,83.005,112.5025,142, approximately29.4975 separation. The tiny24.01 safety margin avoids depending on boundary-equality conventions. These five positions are only an analytic witness; the experiment must obtain actual positions from its candidate projector, route the real edges, and independently check all stubs.
This case also falsifies a tempting repair: move the first blocked Right port to another side, then rerun unchanged automatic_positions. As long as at least two Right ports remain, a different Right port becomes the first at y18 and is blocked. A one-port move does not decrease the number of blocked stubs. A strictly improving single-move repair stalls; a non-strict repair walks identities between sides without addressing the position rule. Reducing Right from five ports to one could clear it, but would discard four useful preferred-side slots although all five fit readably there. Swapping IDs on sides does not solve the first-slot problem either.
Expect the original Current and spacing-only controls to expose the same near-corner weakness, because they too start Right ports at y18. This is a deliberately shared baseline defect, unlike the executed Top spillover regression. The new candidate should improve it using the explicit same-side witness. Keep the distinction in results.
Material alternatives
| Revision | What it can establish | Limitation / complexity |
|---|---|---|
| Fixed fallback order per port, no dynamic occupancy ranking; existing placement | Removes the demonstrated overflow phase-reset mechanism without changing the source model | Cannot repair actual blocked exits. All ports using one global fallback order can still cascade when multiple side capacities change. Necessary attribution control, insufficient policy. |
| Stable per-port ranking plus all-visible midpoint tests and one-pass side repair after actual placement | Small addition to the existing four-side allocator; can recover the executed Top spillover by selecting another side | Midpoints miss the new corner case. Moving one blocked port can block another on the same side. Repeated strictly improving side-only moves cannot solve the supplied feasible witness. Do not select this as the final position policy. |
| Stable ranking plus bounded position-aware shadow repair: re-pack an affected side, then try one-port relocation and re-pack both sides | Can solve the near-corner case by shifting the five Right positions together; can leave uncomplicated owners on the existing fast path | Requires the same clear-interval geometry/packing as the next row, plus a repair order and stopping policy. A locally unsuccessful repair is not a global impossibility proof. Worth a narrow control if it materially reduces integration work. |
| Stable per-port ranking plus clear side intervals and obstacle-aware same-side packing | Directly addresses actual endpoint positions, uses free portions of preferred sides, can keep the five near-corner Right ports, and leaves owner bounds fixed | Needs a real interval placement function and shared obstacle semantics. Per-port differences and manual anchors must be handled honestly; raw interval capacities are not a proof of global feasibility. Leading next experiment. |
| Explicit global slots, ports matched to individually legal slots with deterministic costs | Represents slot clearance and occupancy together; can support per-port clear masks and finite matching oracles | A fixed lattice can miss a legal shifted placement; regenerated slots may move/renumber at resize thresholds. More machinery, and port ordering/crossings are not solved by feasibility matching. Defer unless the smaller interval experiment fails a concrete per-port scarcity example. |
Stable preference detail and its limits
Retain peer-facing and semantic preferences as preferences. Rank remaining sides by a reproducible function of the port identity and side, independent of current side counts and the number of previously overflowed ports. Use an explicitly specified mixer/ranking, not a runtime-randomized hash or the ordinal within the overflow list. Stable semantic IDs are already the layout tie breaker. Do not key layout to display names or aliases.
Test a simple fixed per-port rotation/ranking first; there is no need for an allocator service or new schema. Record the exact function and ties in experimental code. A port's rank among all ports would be resize-stable but changes when an earlier port is inserted/reidentified; identity-derived ranking avoids that particular collective phase shift. It can still change the reidentified port and induce capacity reassignment. This is a measurable tradeoff, not an identity-invariance claim.
The20-port case has spare fallback capacity, so taking one additional preferred slot should require only the newly admitted port to change side. Stable rankings plausibly accomplish that. They do not prove a global one-change bound: scarce admissible sets may require an alternating chain, several side capacities may change together, and every port may share a normalized peer-facing threshold. Include randomized stable IDs and a near-diagonal facing threshold, not just the chosen consecutive IDs. If a change causes many switches for negligible geometric advantage, investigate the preference cost before adding gesture state or silently authored anchors.
Why intervals need more care than a new capacity formula
The strongest modest repair candidate first computes the stable nominal-capacity shadow assignment and ordinary shadow positions. It detects blocked actual stubs; for each affected side in a fixed order it tries clear-interval packing with the same membership, then at most a fixed set of one-port relocations into other sides, re-packing and revalidating every affected side. A trial may not sacrifice previously clear stubs or degrade the chosen gap tier, and must decrease the remaining blocked-stub count. Accepting only such progress bounds accepted repairs by the number of initially blocked ports. Exhausting trials produces an explicit unresolved result, not a claim of capacity infeasibility. Manual overrides remain absent throughout these side-changing trials.
Unlike side-only repair, this position-aware candidate can solve the supplied corner witness in its first same-side attempt. Its limitation is local search: another feasible layout may require moving a currently clear port first, or a temporary neutral exchange among sides. Do not add ever-larger repair loops to evade that boundary. Compare such a case with the common-interval capacity allocation or a bounded small oracle before deciding a more complete matcher is needed.
The proposed interval-first candidate computes capacities from actual common clear spans before assigning sides, then places the accepted memberships using those spans. It avoids assigning nominal capacity to the wholly blocked Top side in the executed obstacle case and avoids a second side-repair state machine. Both candidates need the same interval geometry and packing; the main tradeoff is upfront side capacity knowledge versus a smaller fast path followed by bounded unresolved repairs. Prefer interval-first for the next implementation, because the helper is required either way and the existing four-bin assignment can consume corrected capacities directly. Keep the position-aware repair definition as a concrete competing candidate, not as a dismissed midpoint-only strawman.
For flat ordinary nodes with common obstacle semantics, project each inflated obstacle crossed by the18-unit outward corridor onto the side's coordinate axis. Subtract the union of forbidden coordinates from the usable [18, length−18] span. This tests every potential endpoint along the border, not a representative midpoint. On the near-corner Right side it leaves approximately [24,142].
At a requested gap, pack positions within the legal union while maintaining the gap across interval boundaries, then distribute remaining slack without leaving legal space. Do not blindly sum floor(interval_length/gap)+1: points in two nearby intervals can violate the gap across their intervening forbidden segment. Left-to-right earliest legal packing gives a useful common-interval capacity/witness for equal minimum separation. This small one-dimensional evaluator can be checked against a bounded enumeration before being combined with side allocation.
An arbitrary fixed28-unit slot lattice is an insufficient oracle: legal positions may require shifting the lattice, as at the near-corner boundary. Recomputing evenly spread slots independently for every tentative assignment can also recreate discontinuities. Keep the actual placement witness alongside the accepted counts and validate it after all overrides; do not assume that a count accepted by one formula will be realized by a different spreading function.
Extend the existing automatic_positions interval concept rather than introduce a parallel positioning subsystem. It already builds usable intervals around authored anchor exclusions. The experiment can supply an additional legal border-span set, intersect it with those exclusions, then preserve the current stable peer-coordinate/ID ordering while distributing automatic positions. The original allocator's cross-interval assumptions need explicit tests when real obstacle spans are introduced. Anchor-free shadow placement passes no manual exclusions; final placement passes the authored exclusions. These are two calls to the same geometric helper, not two rules for assigning sides.
For nested diagrams, obstacles are not necessarily identical for every port. A port's multiple incident edges can have different ancestor/header exceptions. The prospective layout must satisfy each applicable outward-stub check. A conservative union can be used for an explicitly scoped experiment, but failure under that union is unresolved under the conservative policy, not proof that no legal model layout exists. Extract/share a pure obstacle-rule helper with routing only when implementation is authorized; do not duplicate its containment semantics into a second planner. The first interval comparison can deliberately use the existing flat fixtures to isolate the question.
Visibility, folds and the shared obstacle boundary
Use the actual projection stage, not every authored placement. project_diagram_impl first excludes wrong-layer/projection/state-machine placements and descendants hidden under a collapsed visual ancestor (projection.rs:305 onward). Folded exchanges can be promoted to visible ancestors and lose unavailable semantic port endpoints. Dedicated state views skip component-port layout entirely. Reintroducing hidden descendants as obstacles would make invisible geometry constrain resize layouts.
Port layout then intentionally consumes all eligible projected edges before presentation filters; projection.rs:535 onward filters edges only after port geometry is settled. In the inspected source, these final presentation filters remove edges, not the projected node vector. Thus a hidden line/category must not change port-side assignment, while a true fold or change of shown placements can change the applicable node/endpoint geometry. Do not derive layout clearance from only the final displayed edge set: that would violate the existing filter-stability contract.
The router starts from the supplied visible projected nodes, but those full rectangles are not the final obstacle geometry for every edge. It shortens ancestors of either endpoint to their header rectangles, applies the correct ordinary/state header height, inflates by12, and ignores the source/target owner for its respective mandatory exit (routing.rs:414–425,455–466,627–647,735–747). Promotion also suspends authored pins and produces a specific warning. A candidate must preserve these distinctions when testing a semantic port's own stub; checking every full visible rectangle would falsely block valid exits through containing bodies.
The maintainable production direction is to extract/reuse the actual pure obstacle geometry/eligibility kernel used by routing, given frozen projected nodes and one eligible projected edge. The interval helper then derives forbidden endpoint coordinates from those effective rectangles and the same boundary tolerance. Keep the independently implemented slab oracle only in tests as a cross-check for flat scenes, not as an alternative production collision policy. No route search, occupied-segment cost or authored-pin mutation belongs in this shared kernel.
Required boundary fixtures before adoption: hide an exchange/category without changing ports; fold/unfold a parent so its hidden descendants stop contributing obstacles; port-to-ancestor and port-to-sibling edges with a traversable body but blocked header; a port serving edges with different ancestor chains; a promoted folded endpoint without an available semantic port; and the dedicated state-view bypass. Parent enclosure and actual visible obstacle eligibility must be established before computing clear border intervals.
Manual anchors and priorities
Compute shadow sides and shadow clear positions for all ports, including anchored ports, without reading authored anchor fractions/sides. Any capacity/repair decision capable of changing unrelated automatic sides must use that shadow layout. Then apply exact authored anchors. Final automatic ports may reposition within their already chosen sides, taking both legal intervals and manual exclusion gaps into account. No final repair may move an unrelated automatic port to another side because an authored anchor changed.
This contract rules out promising unconditional clearance and28/14 separation for arbitrary anchors. Coincident anchors or an anchor placed into an obstacle are valid authored choices; a manual port can also consume the only clear positions on an automatic port's fixed side. Preserve anchor metadata and exact fractions. Report actual crowded/blocked outcomes using the existing route warnings plus experimental diagnostics; do not reinterpret the resize as invalid or secretly grow the frame. A final placement failure after manual overrides must remain visible in the experiment even if the anchor-free shadow succeeded.
Candidate priority for automatic placements is: frozen node geometry and exact authored metadata; clear mandatory stubs when available; target28 separation; readable fallback at least14 where nominal space is insufficient; then deterministic degraded spacing/route diagnostics when these cannot coexist. Try clear28 capacity across sides before degrading to14. At14, a same-side center-gap check only establishes square-glyph separation, not labels. Manual conflicts are a documented exception, not an excuse to ignore avoidable crowding in an all-automatic fixture.
Concrete next experiment, with stop conditions
- Preserve
7e25b3danda95db10. In a newly authorized isolated source branch, add a small experimental stable-ranking mode, with unchanged placement. Re-run the exact two falsifiers and add the near-corner case before changing the position algorithm. Expected attribution: threshold improves; obstacle/corner tests still fail. Retain first failures. - Add one interval-placement candidate using the same stable ranking and frozen geometry. Keep ordinary Current, spacing-only and original CapacityAware as controls. Initially use the flat common-obstacle fixtures, typed ports, real source roundtrips and real router. Reuse a narrow one-dimensional interval helper for shadow and final automatic positioning; do not create a generic global slot graph. If the implementer finds the bounded position-aware repair path materially smaller, compare it on the same fixtures using that same helper; do not implement two full architectures just for symmetry. Record the delta in code/operations and any unresolved repair witness before changing the selected experiment.
- In the next serialized gate, require the20-port threshold bound; both executed obstacle controls; the near-corner actual same-side witness; eight forbidden/outward-geometry cases;100-port target-gap case; and the existing narrow-gap/manual fractions/stability cases. Record exact arrays and actual routes. If interval placement cannot keep the five clear Right positions without excessive side movement, preserve the failure and revise that helper before expanding architecture.
- Sweep small height changes around capacities for8/20/100 ports, multiple fixed UUID sets, reverse movement and a near-diagonal peer-facing threshold. Include insertion/removal and one Reidentify, aliases/names, source roundtrip and construction order. Compare side changes and total displacement, not determinism alone. First use a bounded set of values; broad randomized testing follows only a concrete concern.
- Evaluate per-port/admissibility scarcity separately. Extend the existing abstract four-bin oracle only enough to check the revised rank/matching behavior; keep its assignment-only status. If realistic nested/partial-obstacle fixtures require per-port interval matching that the small helper cannot represent, use those fixtures to decide whether explicit slot matching is justified. Do not infer completeness from a green flat interval suite.
For every comparison, record owner bounds, inactive authored fields, manual anchor metadata, exact ports, same-side separation, independent mandatory-stub intersections, route warnings, total length, bends, proper crossings and coincident overlap lengths. Route cost is an after-projection evaluator, not an input to an iterative layout/router feedback cycle. Record adjacent-frame route/label displacement where available. Compare crossings/labels on realistic multipeer scenes; the one-shared-peer fixture naturally produces shared portions and cannot establish general crossing quality.
Count interval creation/packing operations and projections for increasing port/obstacle sets, and measure elapsed time later. A direct port-by-obstacle construction can cost O(P×O); sorting/merging side intervals and ordinary side allocation should remain bounded and shared where obstacle rules agree. A post-placement trial that reroutes the whole view for every candidate move is outside this experiment. Any stricter asymptotic/performance claim awaits implementation and measurement.
Do not call scarcity a minimum-size result. If this bounded candidate cannot find a readable clear placement, retain the exact requested rectangle and classify the actual limitation (manual conflict, proven insufficient common interval capacity, or unresolved assignment). This is separate from the semantic/content minima used by the resize planner.
Promotion boundary
No mode is selected for production by this report. Stable ranking is a low-cost candidate correction for a demonstrated mechanism; interval positioning is the smallest justified next extension because side-only repair has a concrete structural counterexample. A general slot matcher remains a fallback experiment, not a required architecture.
Before policy adoption, root still needs enclosure/fold/state and ancestor/header cases, authored route pins, realistic route/label and native readability, source/API/Undo interaction, and upgrade rendering comparisons. Removing capacity-driven growth changes old views even when source is untouched. Preserve historical Current snapshots separately; comparing two entrypoints into the same modified projector does not prove historical compatibility. Changing automatic layout must not silently normalize authored placements, persist automatic pins, introduce a gesture-only regime or weaken complete eight-handle editing.
This proposal stops at the candidate experiment. No compiler, native work or implementation is authorized or performed by the report itself.