Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions .agents/skills/visual-qa/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ For Skin V1 interface work, Dashboard is the canonical visual authority. A targe

1. Inspect the requested rendered screen and viewport, including the full three-column relationship when present.
2. For Skin V1 surface work, require both the canonical Dashboard evidence and the target-surface evidence. Compare Dashboard against the target directly rather than approving each screen in isolation.
3. Check typography and hierarchy, clipping, overlap, legibility, contrast, spacing rhythm, alignment, shell/panel measure, border treatment, control density, palette vocabulary, control visibility, responsive behavior, and continuity with adjacent screens.
4. When the host provides `.artifacts/visual-readiness/visual-director-report.json`, read its findings before declaring visual work complete. Treat `blocker` findings as required repairs. Treat `advisory` findings as explicit developer guidance that must be acknowledged or intentionally justified.
5. Convert differences into concrete corrections. Prefer statements such as “reduce competing headings,” “reuse Dashboard panel width,” “return padding to the four-pixel Skin V1 rhythm,” or “replace this local colour with the canonical Skin token” over a bare pass/fail verdict.
6. Compare before/after or cross-screen states only when the host provides both states or a safe path to observe them.
7. Report each finding with location, visible symptom, user impact, evidence, expected Dashboard/Skin V1 treatment, and confidence. Separate definite rendered defects from subjective polish suggestions.
8. Prefer screenshots and direct rendered facts. If the host exposes `browser_evaluate`, use it only to confirm rendered layout facts such as dimensions, visibility, overflow, position, or computed presentation; never use it to infer hidden product intent or story state.
9. Never approve a Skin V1 target solely because it matches its own previous baseline. Regression stability and cross-surface visual continuity are separate questions, and both must pass.
10. When the evidence is insufficient, request another viewport/state rather than inventing a visual defect.
3. Check typography and hierarchy, clipping, overlap, legibility, contrast, spacing rhythm, alignment, shell/panel measure, border treatment, control density, palette vocabulary, control visibility, responsive behavior, and continuity with adjacent screens. Also inspect the whole composition for abnormally large dead/unused regions, broken or unloaded media, duplicated application shells/navigation, stacked legacy/current regions, and primary workspaces pushed out of the active viewport.
4. Use Dashboard as the locked authority and the complete governed WebMCP surface set as supplemental peer evidence for structural norms. Peer agreement never overrides Dashboard, but it should help identify a target whose composition is an outlier from the established PlotPickle surface family.
5. When the host provides `.artifacts/visual-readiness/visual-director-report.json`, read its findings before declaring visual work complete. Treat `blocker` findings as required repairs. Treat `advisory` findings as explicit developer guidance that must be acknowledged or intentionally justified.
6. Convert differences into concrete corrections. Prefer statements such as “reduce competing headings,” “reuse Dashboard panel width,” “return padding to the four-pixel Skin V1 rhythm,” or “replace this local colour with the canonical Skin token” over a bare pass/fail verdict.
7. Compare before/after or cross-screen states only when the host provides both states or a safe path to observe them.
8. Report each finding with location, visible symptom, user impact, evidence, expected Dashboard/Skin V1 treatment, and confidence. Separate definite rendered defects from subjective polish suggestions.
9. Prefer screenshots and direct rendered facts. If the host exposes `browser_evaluate`, use it only to confirm rendered layout facts such as dimensions, visibility, overflow, position, or computed presentation; never use it to infer hidden product intent or story state.
10. Never approve a Skin V1 target solely because it matches its own previous baseline. Regression stability and cross-surface visual continuity are separate questions, and both must pass.
11. When the evidence is insufficient, request another viewport/state rather than inventing a visual defect.

## Completion rule

Expand Down
2 changes: 1 addition & 1 deletion app/skin-v1/matrix-story-map-surface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export default function MatrixStoryMapSurface({

if (!project) return <p role="status">Opening Story Map…</p>;
return (
<div data-skin-v1-story-map-review="true" onClickCapture={handleClickCapture}>
<div data-canonical-project-id={project.id} data-skin-v1-story-map-review="true" onClickCapture={handleClickCapture}>
<StoryCardFoundationBoard project={project} onProjectChange={setProject} />
<ProgressiveStoryMap project={project} />

Expand Down
4 changes: 3 additions & 1 deletion app/skin-v1/uat-guide-panel.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,14 @@

.current {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: var(--pp-skin-space-2);
}

.current span {
display: grid;
min-width: 0;
overflow-wrap: anywhere;
gap: var(--pp-skin-space-1);
padding: var(--pp-skin-space-2);
border: var(--pp-skin-border-thin) solid var(--pp-skin-line);
Expand Down
38 changes: 24 additions & 14 deletions app/skin-v1/uat-guide-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,10 @@ type Payload = {
const AFTERGLOW_UAT_SOURCE_ID = "afterglow-v9";
const AFTERGLOW_UAT_TITLE = "Afterglow: Reflections of Sentience";

const TESTED_SURFACES = [
{ label: "Story Cards", href: "/?workspace=dashboard&block=17&mini=1" },
{ label: "Write", href: "/write?block=17&mini=1" },
{ label: "Outline", href: "/?workspace=dashboard&block=17&mini=1" },
{ label: "Storyboard", href: "/storyboard?block=17&mini=1" },
{ label: "Previs", href: "/previs?block=17&mini=1" },
{ label: "Scene Workspace", href: "/storyboard?block=17&mini=1&view=timeline" },
{ label: "Production inspection", href: "/storyboard?block=17&mini=1#production-inspection" },
const PREPRODUCTION_UAT_BUCKETS = [
{ id: "outline", label: "Outline", href: "/?workspace=dashboard&block=17&mini=1" },
{ id: "storyboard", label: "Storyboard", href: "/storyboard?block=17&mini=1" },
{ id: "previs", label: "Previs", href: "/previs?block=17&mini=1" },
] as const;

async function json<T>(response: Response): Promise<T> {
Expand Down Expand Up @@ -130,6 +126,7 @@ export default function UatGuidePanel() {
const [startPending, setStartPending] = useState(false);
const [message, setMessage] = useState("");
const [workingCopy, setWorkingCopy] = useState("");
const [workingProjectId, setWorkingProjectId] = useState("");
const [comment, setComment] = useState("");

const refresh = useCallback(async () => {
Expand All @@ -142,7 +139,18 @@ export default function UatGuidePanel() {
}
}, []);

useEffect(() => { void refresh(); }, [refresh]);
useEffect(() => {
const existing = listLibraryProjects().find((item) => (
!item.archivedAt
&& item.sourceKind === "example"
&& item.sourceId === AFTERGLOW_UAT_SOURCE_ID
));
if (existing) {
setWorkingCopy(existing.title);
setWorkingProjectId(existing.id);
}
void refresh();
}, [refresh]);
useEffect(() => {
if (payload?.status?.status !== "running" && !startPending) return;
const timer = window.setInterval(() => void refresh(), 1200);
Expand All @@ -169,6 +177,7 @@ export default function UatGuidePanel() {
setMessage("Preparing the persistent Afterglow working copy before semantic testing starts…");
const prepared = await ensureAfterglowWorkingCopy(csrf);
setWorkingCopy(prepared.project.title);
setWorkingProjectId(prepared.project.id);
const response = await fetch("/api/auth/uat-guide", {
method: "POST",
credentials: "same-origin",
Expand Down Expand Up @@ -245,6 +254,7 @@ export default function UatGuidePanel() {
<span><b>Reference</b>Afterglow v9</span>
<span><b>Story address</b>{status?.current?.storyAddress || "Block 17 / Mini-Block 1"}</span>
<span><b>Working copy</b>{workingCopy || AFTERGLOW_UAT_TITLE}</span>
<span><b>Project ID</b>{workingProjectId || "Prepared on start"}</span>
</div>

<p className={styles.boundary}>Semantic UAT only · persistent Human working copy · immutable Afterglow reference · synthetic verification isolation · no cloud spend · deterministic verification owns PASS/FAIL.</p>
Expand Down Expand Up @@ -295,12 +305,12 @@ export default function UatGuidePanel() {

<section className={styles.surfaces} aria-labelledby="uat-tested-surfaces-title">
<div>
<p>OPEN TESTED SURFACES</p>
<h3 id="uat-tested-surfaces-title">Inspect the loaded Afterglow working copy</h3>
<span>The working copy remains active after UAT. Open any stage to inspect what PlotPickle projected or populated and use that stage's normal visual actions where available.</span>
<p>PRE-PRODUCTION UAT BUCKETS</p>
<h3 id="uat-tested-surfaces-title">Confirm the same Afterglow project in each current bucket</h3>
<span>Human UAT currently checks three pre-production buckets: Outline, Storyboard and Previs. Confirm the story, Project ID and Block 17 / Mini-Block 1 remain the same in each. This explicit bucket list can expand as the planned five-bucket pre-production model becomes canonical.</span>
</div>
<nav aria-label="Afterglow UAT tested surfaces">
{TESTED_SURFACES.map((surface) => <Link href={surface.href} key={surface.label}>{surface.label}</Link>)}
<nav aria-label="Afterglow pre-production UAT buckets" data-uat-project-id={workingProjectId || undefined}>
{PREPRODUCTION_UAT_BUCKETS.map((surface) => <Link data-uat-bucket={surface.id} href={surface.href} key={surface.id}>{surface.label}</Link>)}
</nav>
</section>

Expand Down
14 changes: 14 additions & 0 deletions config/verification/ownership-map.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,20 @@
"navigation"
]
},
{
"id": "visual-qa-skill",
"classification": "production",
"include": [
".agents/skills/visual-qa/SKILL.md"
],
"ownerLayer": "agent-runtime",
"riskTokens": [
"agent",
"visual",
"surface",
"mcp"
]
},
{
"id": "sage-brinewick-skill",
"classification": "production",
Expand Down
Loading
Loading