fix(map): overlap between containers is resolved, not negotiated - #585
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Code diff size+117 / −0 across 1 file (net +117)
Source files under |
angel-manuel
pushed a commit
that referenced
this pull request
Aug 28, 2026
`translateCluster` moved positions and left targets where they were, so the ring spring went on pulling towards where the cluster used to be. Whether that shows depends on how far the correction moved it: the freeze — `sp < 5 && am < 30` — absorbs the pull-back for a small correction, which is every correction the fixtures produce, but past roughly 170 units of displacement the spring stays above that bar and the cluster creeps back until it crosses the slop and is corrected out again. A settled map that twitches, once a second, forever. Targets move with the positions now, which is what the code already does for a cluster a human drags. Not added to `manualTargets`, though: that set exists so a *gesture* outlives a fleet refetch, and this is derived from the layout, so it should be re-derived from the next one. Found by Seer on #585.
angel-manuel
pushed a commit
that referenced
this pull request
Aug 28, 2026
`translateCluster` moved positions and left targets where they were, so the ring spring went on pulling towards where the cluster used to be. Whether that shows depends on how far the correction moved it: the freeze — `sp < 5 && am < 30` — absorbs the pull-back for a small correction, which is every correction the fixtures produce, but past roughly 170 units of displacement the spring stays above that bar and the cluster creeps back until it crosses the slop and is corrected out again. A settled map that twitches, once a second, forever. Targets move with the positions now, which is what the code already does for a cluster a human drags. Not added to `manualTargets`, though: that set exists so a *gesture* outlives a fleet refetch, and this is derived from the layout, so it should be re-derived from the next one. Found by Seer on #585.
angel-manuel
force-pushed
the
fix/live-map-container-overlap-projection
branch
from
August 28, 2026 09:52
f0775a8 to
d1b272e
Compare
angel-manuel
pushed a commit
that referenced
this pull request
Aug 28, 2026
`translateCluster` moved positions and left targets where they were, so the ring spring went on pulling towards where the cluster used to be. Whether that shows depends on how far the correction moved it: the freeze — `sp < 5 && am < 30` — absorbs the pull-back for a small correction, which is every correction the fixtures produce, but past roughly 170 units of displacement the spring stays above that bar and the cluster creeps back until it crosses the slop and is corrected out again. A settled map that twitches, once a second, forever. Targets move with the positions now, which is what the code already does for a cluster a human drags. Not added to `manualTargets`, though: that set exists so a *gesture* outlives a fleet refetch, and this is derived from the layout, so it should be re-derived from the next one. Found by Seer on #585.
angel-manuel
force-pushed
the
fix/live-map-container-overlap-projection
branch
from
August 28, 2026 10:10
d1b272e to
d063fc9
Compare
angel-manuel
pushed a commit
that referenced
this pull request
Aug 28, 2026
…rlap `separateBoxes` adds `BOX_GAP` before testing, so it acts on any pair closer than the clearance rather than only on a pair already overlapping — the same convention the force uses, and deliberate, because two containers touching read no better than two overlapping. The doc comment said "anything still overlapping", which describes a stricter function than the one below it and invites the reading that the `+ BOX_GAP` is a mistake. `ox`/`oy` renamed to `needX`/`needY`: they are how far the pair has to move to reach the clearance, which is also what makes `SEPARATION_SLOP` sit right next to them — the slop is a floor on movement worth making, not on overlap worth caring about. No behaviour change. Raised by Seer on #585, which read the comment and reported the code for disagreeing with it.
angel-manuel
pushed a commit
that referenced
this pull request
Aug 28, 2026
`translateCluster` moved positions and left targets where they were, so the ring spring went on pulling towards where the cluster used to be. Whether that shows depends on how far the correction moved it: the freeze — `sp < 5 && am < 30` — absorbs the pull-back for a small correction, which is every correction the fixtures produce, but past roughly 170 units of displacement the spring stays above that bar and the cluster creeps back until it crosses the slop and is corrected out again. A settled map that twitches, once a second, forever. Targets move with the positions now, which is what the code already does for a cluster a human drags. Not added to `manualTargets`, though: that set exists so a *gesture* outlives a fleet refetch, and this is derived from the layout, so it should be re-derived from the next one. Found by Seer on #585.
angel-manuel
pushed a commit
that referenced
this pull request
Aug 28, 2026
…rlap `separateBoxes` adds `BOX_GAP` before testing, so it acts on any pair closer than the clearance rather than only on a pair already overlapping — the same convention the force uses, and deliberate, because two containers touching read no better than two overlapping. The doc comment said "anything still overlapping", which describes a stricter function than the one below it and invites the reading that the `+ BOX_GAP` is a mistake. `ox`/`oy` renamed to `needX`/`needY`: they are how far the pair has to move to reach the clearance, which is also what makes `SEPARATION_SLOP` sit right next to them — the slop is a floor on movement worth making, not on overlap worth caring about. No behaviour change. Raised by Seer on #585, which read the comment and reported the code for disagreeing with it.
angel-manuel
force-pushed
the
fix/live-map-container-overlap-projection
branch
from
August 28, 2026 10:54
1de4cc6 to
c46f6ce
Compare
added 3 commits
August 28, 2026 11:39
The box-vs-box spring could only ever reach the point where it balanced whatever pulled the other way, and every cluster is held to a slot on a ring whose radius knows nothing about how big that cluster grew. Since services joined containers a fleet can be several times the size the ring was spaced for, so two of them on adjacent slots settle with their boxes a few units into each other and stop. The push was working. It had an opponent, and drew. The last word is positional now. `computeBoxes` has just rebuilt the rectangles from this frame's positions; anything still overlapping is separated by translating whole clusters, and `draw` strokes the corrected result. A contact constraint cannot be out-pulled the way a force can, so "containers do not overlap" stops being a tendency and becomes true of every frame. Velocity is deliberately untouched: this is a correction, not a shove, and handing the cluster momentum would make it overshoot and swing back. The spring still does all the smooth work — this only removes the residue it cannot. `SEPARATION_SLOP` keeps that from becoming a per-frame shimmer, since the ring spring pulls back a fraction of a unit every frame and would otherwise be corrected straight back out forever. A cluster under the pointer is never the one that moves; if both boxes are held, neither does.
`translateCluster` moved positions and left targets where they were, so the ring spring went on pulling towards where the cluster used to be. Whether that shows depends on how far the correction moved it: the freeze — `sp < 5 && am < 30` — absorbs the pull-back for a small correction, which is every correction the fixtures produce, but past roughly 170 units of displacement the spring stays above that bar and the cluster creeps back until it crosses the slop and is corrected out again. A settled map that twitches, once a second, forever. Targets move with the positions now, which is what the code already does for a cluster a human drags. Not added to `manualTargets`, though: that set exists so a *gesture* outlives a fleet refetch, and this is derived from the layout, so it should be re-derived from the next one. Found by Seer on #585.
…rlap `separateBoxes` adds `BOX_GAP` before testing, so it acts on any pair closer than the clearance rather than only on a pair already overlapping — the same convention the force uses, and deliberate, because two containers touching read no better than two overlapping. The doc comment said "anything still overlapping", which describes a stricter function than the one below it and invites the reading that the `+ BOX_GAP` is a mistake. `ox`/`oy` renamed to `needX`/`needY`: they are how far the pair has to move to reach the clearance, which is also what makes `SEPARATION_SLOP` sit right next to them — the slop is a floor on movement worth making, not on overlap worth caring about. No behaviour change. Raised by Seer on #585, which read the comment and reported the code for disagreeing with it.
angel-manuel
force-pushed
the
fix/live-map-container-overlap-projection
branch
from
August 28, 2026 11:39
c46f6ce to
1be38fb
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reported against the merged #583 with a screenshot of three containers lying
across each other. Reproduced, and it turned out to be two separate things —
#584 (now merged) was the first, this is the second.
Why a force could not finish it
Measured on a fixture matching the report — three users whose clusters are made
of services rather than agents, one of them owning six, which is the shape
none of the earlier fixtures had:
The box-vs-box spring reaches the point where it balances whatever pulls the
other way, and every cluster is held to a slot on a ring —
R_USER = 250—whose radius knows nothing about how big that cluster grew. Since #582 put
services inside containers, a fleet can be several times the size the ring was
spaced for. Two of them on adjacent slots settle a few units into each other and
stop. Raising the constant only moves where it draws.
The fix
The last word is positional.
computeBoxeshas just rebuilt the rectangles fromthis frame's positions; any pair closer than
BOX_GAP— touching reads nobetter than overlapping — is separated by translating whole clusters, and
drawstrokes the corrected result. A contact constraint cannot be out-pulled the way
a force can, so this stops being a tendency the spring is arguing for and
becomes true of every frame.
The spring still does all the smooth work; this only removes the residue it
cannot reach. Velocity is deliberately untouched — a correction, not a shove;
momentum here would overshoot and swing back. Targets move with the positions,
so the ring spring has nothing left to pull back to.
SEPARATION_SLOPkeeps apair already at the clearance from being nudged, and a cluster under the pointer
is never the one that moves.
Verification
Same fixture, three builds.
Before #584 — as reported
#584 — a sliver left
This PR
It also settles: two frames captured five seconds apart on the finished layout
are pixel-identical, which they could not be if nearby clusters were being
nudged every frame.
Worth knowing
The reported screenshot has two containers both labelled
amanuelmartincanto@gmail.com— two user identities sharing one email, whichis the condition #581 ("one actor per human per org") exists to prevent. That is
pre-existing data on dev rather than anything the map does, and it is not
addressed here, but it is worth a look: the map is showing it because it is true.