feat(orchestrator): S3 generated SVG faces whose mouths move while speaking
Requirement 001 phase 6, S3:
- faces.js derives a face from the agent's stable key (its session id,
or name:<name> without a session), so a rename keeps the face: shape
4, colour 7, eyes 5, brows 4, mouth 5, hair or headwear 6, accessory 5,
84,000 combinations. It emits constant SVG tags and attributes only.
- The emoji avatar is gone: popup, Orbit and Chord nodes, the radio
view, stream and palette draw the SVG face (the 3D views keep their
marker).
- While the radio reads an agent's message, its faces carry the class
speaking and the mouth runs the talk keyframes; a silent face does
not move, and prefers-reduced-motion stops the mouth.
Evidence: make test 673 OK, ruff and markdownlint clean
(/tmp/s3-make-test-1.log); e2e 20 OK in Chromium and Firefox, none
skipped (/tmp/s3-e2e-3.log); screenshots
/tmp/orchestrator-phase4-shots/*-speaking.png; MEDUSA 13 files, 2
findings ("PLA" in "templates", the UI call openAgent) accepted after
an independent skeptic that found no markup sink or selector injection
in the face code.
🎯 Fix: 94 %
💥 Break: 3 %
💸 Cost: 100 %
⏱️ Time: –
🛡️ Security: 100 %
🏆 Score: 91
🚦 Gate: ✅ 90/5, cost and time <= 100, security 100 %
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d89fb616b8
commit
4d88296e47
13 files changed
+262
-34
No files matched your search
@@ -19,8 +19,11 @@
|
||||
.caption-line { flex: 1; min-width: 0; overflow: hidden; color: var(--muted); text-overflow: ellipsis; white-space: nowrap; }
|
||||
svg .node.speaking circle { stroke: var(--ok); stroke-width: 4; animation: speaking-node 1.3s ease-in-out infinite; }
|
||||
@keyframes speaking-node { 50% { stroke-width: 10; stroke-opacity: .45; } }
|
||||
.face-art .mouth { transform-box: fill-box; transform-origin: center; }
|
||||
.speaking .face-art .mouth { animation: talk .3s ease-in-out infinite alternate; }
|
||||
@keyframes talk { to { transform: scale(1.15, 2.2); } }
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.speaker.speaking .speaker-face::after, .radio-caption .speaker-face::after, svg .node.speaking circle { animation: none; }
|
||||
.speaker.speaking .speaker-face::after, .radio-caption .speaker-face::after, svg .node.speaking circle, .speaking .face-art .mouth { animation: none; }
|
||||
}
|
||||
.stations { display: grid; gap: 4px; margin: 0; padding: 0; list-style: none; }
|
||||
.station { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) auto auto; align-items: center; gap: var(--sp-2); min-width: 0; padding: 3px 3px 3px 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--sunken); }
|
||||
|
||||
Reference in new issue
Block a user