mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
feat(motion,runtime): wire the three craft capabilities to the video-authoring dev (#544)
Playwright, the taste-skill design bar, and hyperframes were all implemented — and each stopped one hop short of the hands doing video work: playwright reached only fe-qa/ux-qa, the design bar's web-UI dials actively pointed a video task at 'dense product UI -> motion 2-3', and hyperframes' agent-facing doctrine never reached any agent. Three wires: - vendor the official HyperFrames agent skills (hyperframes-core, -keyframes, -creative) under motion/skills/ at a pinned upstream commit (Apache-2.0, attribution headers; prose reflowed to house style, re-vendor note in each header); README and the dev video prompt block point at them - register the playwright MCP for a ux-dev spawned onto a source=video task (_is_video_authoring_spawn: fail-closed role/team/task-source probe) so the composition author can watch their HTML live in a real browser between renders — gating-only, agent-ux already bakes the browser; QA gating unchanged, be-qa/ordinary ux-dev still excluded - design bar video-mode override in the ux_ui team prompt: video tasks are films, the web dials do not apply — use the cinematography bar and the vendored doctrine instead Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
"""The `playwright` MCP server (CEO round-3 note on the Playwright QA-image
|
||||
work) is role-gated to fe-qa/ux-qa only — it must never appear for be-qa
|
||||
(same role, different team) or ux-dev (same image as ux-qa, different role),
|
||||
"""The `playwright` MCP server is gated to fe-qa/ux-qa, plus exactly one
|
||||
non-QA case: a ux-dev spawned onto a source=video authoring task (probed via
|
||||
``_is_video_authoring_spawn``), so the composition author can preview their
|
||||
HTML in a real browser. It must never appear for be-qa (same role, different
|
||||
team — no chromium in that image) or for a ux-dev outside a video task,
|
||||
since the binary + wrapper entrypoint are only baked into agent-qa-fe /
|
||||
agent-ux via docker/agent-qa-fe.Dockerfile / docker/agent-ux.Dockerfile.
|
||||
"""
|
||||
@@ -9,15 +11,19 @@ from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from roboco.runtime.orchestrator import AgentOrchestrator
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import pytest
|
||||
|
||||
_ENTRYPOINT = "/app/scripts/playwright-mcp-entrypoint.sh"
|
||||
|
||||
|
||||
async def _servers_for(agent_slug: str) -> dict[str, dict]:
|
||||
async def _servers_for(agent_slug: str, task_id: str | None = None) -> dict[str, dict]:
|
||||
orch = AgentOrchestrator.__new__(AgentOrchestrator)
|
||||
config_path = await orch._generate_mcp_config(agent_slug)
|
||||
config_path = await orch._generate_mcp_config(agent_slug, task_id=task_id)
|
||||
config = json.loads(Path(config_path).read_text())
|
||||
servers: dict[str, dict] = config["mcpServers"]
|
||||
return servers
|
||||
@@ -44,7 +50,33 @@ async def test_be_qa_does_not_get_playwright_mcp() -> None:
|
||||
|
||||
async def test_ux_dev_does_not_get_playwright_mcp() -> None:
|
||||
"""Shares agent-ux's image with ux-qa (same Dockerfile, same baked
|
||||
browser) but is a `developer`, not `qa` — the gating is role-based, not
|
||||
image-based, so ux-dev must not see the tool."""
|
||||
browser) but is a `developer` with no video task — must not see the
|
||||
tool for ordinary UI work."""
|
||||
servers = await _servers_for("ux-dev-1")
|
||||
assert "playwright" not in servers
|
||||
|
||||
|
||||
async def test_ux_dev_on_video_task_gets_playwright_mcp(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""The one non-QA case: ux-dev spawned onto a source=video task previews
|
||||
the composition in a real browser (the image already bakes chromium)."""
|
||||
|
||||
async def _video(
|
||||
_self: AgentOrchestrator, agent_id: str, _agent_role: str, task_id: str | None
|
||||
) -> bool:
|
||||
return agent_id == "ux-dev-1" and task_id == "t-video"
|
||||
|
||||
monkeypatch.setattr(AgentOrchestrator, "_is_video_authoring_spawn", _video)
|
||||
servers = await _servers_for("ux-dev-1", task_id="t-video")
|
||||
assert "playwright" in servers
|
||||
assert servers["playwright"]["command"] == _ENTRYPOINT
|
||||
|
||||
|
||||
async def test_video_probe_guards_role_and_team() -> None:
|
||||
"""Early-outs need no DB: non-developer roles, non-ux teams, and a
|
||||
missing task id all refuse before any lookup."""
|
||||
orch = AgentOrchestrator.__new__(AgentOrchestrator)
|
||||
assert await orch._is_video_authoring_spawn("ux-qa", "qa", "t1") is False
|
||||
assert await orch._is_video_authoring_spawn("fe-dev-1", "developer", "t1") is False
|
||||
assert await orch._is_video_authoring_spawn("ux-dev-1", "developer", None) is False
|
||||
|
||||
Reference in New Issue
Block a user