fix(team): clean single traveling pulse + delegations start at the architect
- The pulse is now one dash with an effectively infinite gap, animated origin→target→off with fill:forwards — no wrap-around second bar and no snap-back to origin when it arrives (fixes the ghost bar). Slower, ease-in-out so it eases out of the origin card and into the target's last branch. - Real delegation/review pulses now originate at the ARCHITECT (the root's single child), not the CEO above it — so a task assigned to an agent no longer visibly starts from the CEO. Cuts a 3-edge cascade to 2 for a PO-level agent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
c2939966b5
commit
1bb18d96b5
@ -278,7 +278,7 @@ export function renderTeamHtml(cwd: string): string {
|
|||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var NS = 'http://www.w3.org/2000/svg';
|
var NS = 'http://www.w3.org/2000/svg';
|
||||||
var SEG = 680, EDGE_DUR = 1500;
|
var SEG = 720, EDGE_DUR = 1850;
|
||||||
var connDot = document.getElementById('conn-dot');
|
var connDot = document.getElementById('conn-dot');
|
||||||
var edgeMap = {}; // nodeId -> { fwd, rev } path from its parent
|
var edgeMap = {}; // nodeId -> { fwd, rev } path from its parent
|
||||||
var parentOf = {}; // nodeId -> parent nodeId
|
var parentOf = {}; // nodeId -> parent nodeId
|
||||||
@ -334,28 +334,41 @@ export function renderTeamHtml(cwd: string): string {
|
|||||||
p.setAttribute('d', dir === 'up' ? e.rev : e.fwd);
|
p.setAttribute('d', dir === 'up' ? e.rev : e.fwd);
|
||||||
svg.appendChild(p);
|
svg.appendChild(p);
|
||||||
var len = p.getTotalLength();
|
var len = p.getTotalLength();
|
||||||
p.style.strokeDasharray = '20 ' + (len + 20);
|
// One dash with an effectively infinite gap → no second dash can wrap
|
||||||
p.style.strokeDashoffset = String(len + 20);
|
// around onto the path. It travels origin(0) → target(len) → off, and
|
||||||
|
// fill:forwards holds the off-path end so it never snaps back to origin.
|
||||||
|
p.style.strokeDasharray = '20 100000';
|
||||||
|
p.style.strokeDashoffset = '0';
|
||||||
var done = function() {
|
var done = function() {
|
||||||
try { p.remove(); } catch (_) {}
|
try { p.remove(); } catch (_) {}
|
||||||
// Only the final destination lights up — waypoints (e.g. CEO on a
|
// Only the final destination lights up — waypoints (e.g. CEO on a
|
||||||
// peer-to-peer handoff) are just passed through, not "involved".
|
// peer-to-peer handoff) are just passed through, not "involved".
|
||||||
if (doFlash) flash(dir === 'up' ? nodeById(parentOf[nodeId]) : nodeById(nodeId));
|
if (doFlash) flash(dir === 'up' ? nodeById(parentOf[nodeId]) : nodeById(nodeId));
|
||||||
};
|
};
|
||||||
if (p.animate) { p.animate([{ strokeDashoffset: len + 20 }, { strokeDashoffset: 0 }], { duration: EDGE_DUR, easing: 'cubic-bezier(.4,0,.5,1)' }).onfinish = done; }
|
if (p.animate) {
|
||||||
else setTimeout(done, EDGE_DUR);
|
// ease-in-out: slower leaving the origin card and arriving at the target's last branch.
|
||||||
|
p.animate([{ strokeDashoffset: 0 }, { strokeDashoffset: -(len + 24) }],
|
||||||
|
{ duration: EDGE_DUR, easing: 'cubic-bezier(.5,0,.5,1)', fill: 'forwards' }).onfinish = done;
|
||||||
|
} else setTimeout(done, EDGE_DUR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A pulse that travels the whole path root→node (down) or node→root (up).
|
// The delegation hub = the architect (the root's single child), so real
|
||||||
function pulsePath(nodeId, dir) {
|
// pulses originate at the architect, not the CEO above it.
|
||||||
var chain = []; var cur = nodeId;
|
function hubId() {
|
||||||
while (cur && edgeMap[cur]) { chain.push(cur); cur = parentOf[cur]; } // node → topChild
|
var root = document.querySelector('.node[data-parent=""]') || document.querySelector('.node[data-node-id]');
|
||||||
if (dir === 'down') chain.reverse(); // topChild → node
|
if (!root) return null;
|
||||||
chain.forEach(function(id, i) { setTimeout(function() { firePulseEdge(id, dir, i === chain.length - 1); }, i * SEG); });
|
var rid = root.getAttribute('data-node-id');
|
||||||
|
var kids = document.querySelectorAll('.node[data-parent="' + rid + '"]');
|
||||||
|
return kids.length === 1 ? kids[0].getAttribute('data-node-id') : rid;
|
||||||
}
|
}
|
||||||
function pulseToAgent(agent, dir) {
|
function pulseToAgent(agent, dir) {
|
||||||
|
var hub = hubId();
|
||||||
|
if (!hub) return;
|
||||||
document.querySelectorAll('.node[data-agent="' + (agent||'').replace(/"/g,'') + '"]').forEach(function(n) {
|
document.querySelectorAll('.node[data-agent="' + (agent||'').replace(/"/g,'') + '"]').forEach(function(n) {
|
||||||
pulsePath(n.getAttribute('data-node-id'), dir);
|
var id = n.getAttribute('data-node-id');
|
||||||
|
if (id === hub) return;
|
||||||
|
if (dir === 'down') pulseBetween(hub, id); // architect → agent (delegation)
|
||||||
|
else pulseBetween(id, hub); // agent → architect (review)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user