P2~P7 리노컷 캐스트 원화·리그와 세션 활성화

- 추천 원화(P2 b·P3 v2b·P4 v2b·P5 v2a·P6 v2b·P7 v2b)로 얼굴 없는 기본형·몸 원본 codex 편집, 정렬·정규화 후 공통 파이프라인 실행
- 게시 자산 apps/web/public/avatar/v3/p2~p7, 리그 rigs/p2Rig~p7Rig
- 세션 레지스트리 P1~P7 전원 활성, Lab은 생성된 리그 자동 수집
- P3·P6 기본 눈 감김을 줄여 중립 렌더를 원화 눈매에 맞춤
- 표정 E2E를 v3 렌더러 기대로 갱신(검사 의도 유지)
This commit is contained in:
Yun Chan 2026-10-01 22:38:45 +09:00
parent 98577cf4ae
commit ded312acdc
258 changed files with 18463 additions and 32 deletions

View file

@ -53,26 +53,35 @@ test.describe("avatar expression lab", () => {
);
await expect(panel.locator('[data-expression-card="true"]')).toHaveCount(28);
const cardRenderers = panel.locator(
'.axl__card .vg-avatar [data-avatar-renderer="linocut"]',
);
await expect(cardRenderers).toHaveCount(28);
await expect
.poll(
async () =>
cardRenderers.evaluateAll(
(els) => els.filter((el) => el.getAttribute("data-load-state") === "ready").length,
),
{ timeout: 20_000 },
)
.toBe(28);
const sectionMetrics = await panel.evaluate((el) => {
const avatars = Array.from(el.querySelectorAll<HTMLElement>(".axl__card .vg-avatar"));
const invalid = avatars
.map((avatar) => {
const neck = avatar.querySelector<SVGGraphicsElement>('[data-avatar-neck="true"]');
const svg = avatar.querySelector("svg");
const renderer = avatar.querySelector<HTMLElement>('[data-avatar-renderer="linocut"]');
const svg = avatar.querySelector(".linocut-avatar");
return {
affect: avatar.getAttribute("data-affect"),
primitives: avatar.querySelectorAll("svg path, svg ellipse, svg circle, svg line, svg rect")
.length,
neckBox: neck?.getBoundingClientRect().toJSON(),
loadState: renderer?.getAttribute("data-load-state"),
svgBox: svg?.getBoundingClientRect().toJSON(),
};
})
.filter((item) => {
return (
item.primitives < 12 ||
!item.neckBox ||
item.neckBox.width <= 8 ||
item.neckBox.height <= 14 ||
item.loadState !== "ready" ||
!item.svgBox ||
item.svgBox.width <= 0 ||
item.svgBox.height <= 0