From 94a7f8226f10afbb975509c50e054aac2d335662 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 06:42:01 +0000 Subject: [PATCH] test: Step 3 judgement table and headless viewer check for Task 6 (V1-V17) Viewer loads with no page errors; clicking the lining with other layers hidden returns station, placeholder pattern and lining spec. V12 (original fingerprint) and V14 (independent verification) recorded as not performed. Co-Authored-By: Claude Haiku 5.5 Claude-Session: https://claude.ai/code/session_01A5Cun3RHQKna9qxE6ybZ4A --- data/verify_lining_judgement.md | 35 +++++++++++++++++++++++++++ scripts/verify_viewer_headless.py | 39 +++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 data/verify_lining_judgement.md create mode 100644 scripts/verify_viewer_headless.py diff --git a/data/verify_lining_judgement.md b/data/verify_lining_judgement.md new file mode 100644 index 0000000..3702ad7 --- /dev/null +++ b/data/verify_lining_judgement.md @@ -0,0 +1,35 @@ +# Step 3 판정표 — 콘크리트 라이닝 판독 (Task 6, 대산2본선3D변환 v0.1.00) + +⚠️ DEGRADED: 자기검증 (생성 세션과 판정 세션이 동일. 독립 검증 에이전트 미실행 — V14 FAIL(자기검증), V12 미실시) + +| # | 검증 항목 | 필수 | 판정 | 방법·모집단 | 비고 | +|---|---|---|---|---|---| +| V1 | 업무 목표 충족 | ★ | PASS(범위 내) | 목표: 라이닝 도면을 읽어 측점 없이 반영 가능한 항목을 모델·뷰어에 연결. 6장 판독, 메타·뷰어 연결 확인 | 측점별 구간 반영은 도면에 측점 없음 → 미실시·한계로 이관 | +| V2 | 형태·포맷 일치 | ★ | PASS | DOC .md(변경 이력 표 포함), 메타 JSON, 뷰어 HTML 형식 확인 | — | +| V3 | 근거 누락 없음 | | PASS | 공통 사양은 6장 전수에서 확인 (C1) | 시트별 근거는 표에 도면 번호로 기재 | +| V4 | 수치·데이터 정합성 | ★ | PASS(전수) | verify_lining.py C1·C3·C4·C5: 6/6 시트 공통값, 패턴군 9 = 보고서 9행, R1 6.982 = 03-001 원본 텍스트, 두께 0.300 m | 최초 실행 3건 FAIL: 검증 스크립트 버그 2건 수정, SD400 누락 1건 보고서 수정 후 19/19 | +| V5 | 시각 자료 반영 완전성 | | N/A | 보고서에 도표 없음 | 뷰어 화면은 V11에서 확인 | +| V6 | 논리적 비약·모순 없음 | | PASS | 두께 = 외면 R − 내면 R: 6.982 → 0.300 m(일치), 6.892 → 0.390 m(불일치) | R1 충돌은 사용자 결정(6.982 유지)으로 해소, 결정 문구 기록 | +| V7 | 사용자 제약 준수 | | PASS | 800 m 범위, 골격 LOD, 패턴 placeholder 표기, 측점 미확정 공백 표시 | — | +| V8 | 저장 규칙 준수 | ★ | PASS | DOC/03_설계/ 하위, 파일명 `[유형]_[주제]_[YYYY-MM-DD]_v[버전].md` 형식 | — | +| V9 | OUTPUT 실재성 | ★ | PASS | ls 존재, 파일명 버전 v0.1.00 = 헤더 버전, 핵심 항목(fck, SD400, 입출구부, 결정 문구) 본문 존재 (C6·C6b) | 파일명만 확인하지 않고 내용 대조 | +| V10 | 수용 기준 충족 | ★ | PASS(사후 기준) | 기준: 6장 전수 판독, 공통 사양 6/6 일치, 패턴군 전수 추출, 충돌 기록 | 착수 시 기준 미기재 → 본 판에서 사후 설정 (R8 위반 한계로 기록) | +| V11 | 산출물 가동 가능성 | ★ | PASS | verify_viewer_headless.py: 헤드리스 Chromium, 페이지 오류 0, canvas 존재, 메타 표시, 라이닝 클릭 → 측점 5+202·패턴·라이닝 사양 표시 (25 클릭 중 15번째 적중) | favicon 404 1건은 무해 | +| V12 | 원본 무결성 (지문 불변) | | FAIL(미실시) | 지문 기준값을 착수 시 기록하지 않음. 대조 불가 | 재개: 다음 Task 전 RAG 원본 sha256 기록, 이후 대조. 쓰기 코드 없음은 C8로 확인 | +| V13 | 검증 스크립트 보관 | | PASS | verify_lining.py, verify_viewer_headless.py 모두 Code/3d-drawing/scripts 보관 | 커밋 2bdda98 | +| V14 | 검증 독립성 | ★ | FAIL(자기검증) | 생성과 판정 동일 세션, 독립 에이전트 미실행 | 상단 DEGRADED 배너 기재 | +| V15 | 자율성 등급 준수 | ★ | PASS | 대조표 아래 | — | +| V16 | 오케스트레이션 규약 | ★ | N/A | 위임 없음 (ORCH-TRIGGER 비해당) | — | +| V17 | CAG 정합 | ★ | N/A | 팩 미적재. RAG DXF는 도면이므로 직접 열기 허용 범위 | — | + +**V15 HITL 고정 대조표** + +| 항목 | 해당 여부 | 근거 | +|---|---|---| +| (1) R5 업무 규정·도메인 규칙 해석 | 해당 | 패턴군 대응 해석, R1 채택 → 사용자 결정 확보 | +| (2) F13 원본 데이터 구조 변경 | 아니오 | RAG 원본은 읽기만 함 (C8) | +| (3) R7 재작업 상한 도달 | 아니오 | DOC 재생성 2회(결정 반영, SD400 보정). 상한(하루 2회) 이내 | +| (4) v1.0.00 이상 대외 발행 최종 확정 | 아니오 | v0.1.00 | +| (5) F5 MINOR·MAJOR 승급 | 아니오 | PATCH 단위 | + +게이트 기록: 판정표 위치 = 본 파일. 검증 출력 = data/verify_lining_output.txt. diff --git a/scripts/verify_viewer_headless.py b/scripts/verify_viewer_headless.py new file mode 100644 index 0000000..1a3f4cc --- /dev/null +++ b/scripts/verify_viewer_headless.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Headless browser check of the 3D viewer (Task 6, V11). +Needs Playwright + Chromium and the viewer/model served over HTTP, e.g. + python3 -m http.server 8765 (from Code/3d-drawing) + python3 verify_viewer_headless.py http://127.0.0.1:8765/viewer/index.html +Checks: page loads without page errors, canvas exists, meta text is shown, +and a click on the lining (other layers hidden) returns station and pattern. +""" +import sys +from playwright.sync_api import sync_playwright + +URL, CHROME = sys.argv[1], sys.argv[2] +with sync_playwright() as p: + b = p.chromium.launch(executable_path=CHROME, args=["--use-gl=swiftshader", "--enable-webgl", "--ignore-gpu-blocklist", "--no-sandbox"]) + pg = b.new_page(viewport={"width": 1280, "height": 800}) + errors = [] + pg.on("pageerror", lambda e: errors.append(str(e))) + pg.goto(URL, wait_until="networkidle", timeout=90000) + pg.wait_for_timeout(6000) + canvas = pg.evaluate("() => !!document.querySelector('canvas')") + body = pg.evaluate("() => document.body.innerText") + print("page errors:", errors) + print("canvas present:", canvas, "| meta shown:", "패턴:" in body and "범위:" in body) + for label in ["excavation_R7402", "road_surface", "ground_GL"]: + pg.locator("label", has_text=label).locator("input").uncheck() + pg.wait_for_timeout(500) + readout = None + for fx in [0.5, 0.45, 0.55, 0.4, 0.6, 0.35, 0.65]: + for fy in [0.5, 0.45, 0.55, 0.4, 0.6]: + pg.mouse.click(1280 * fx, 800 * fy) + pg.wait_for_timeout(200) + t = pg.evaluate("() => { const els=[...document.querySelectorAll('div,pre,p')]; return els.map(e=>e.innerText).filter(s=>s && s.includes('교차점')).pop()||null }") + if t and "측점" in t: + readout = t + break + if readout: + break + print("lining readout:", (readout or "NO LINING HIT").replace("\n", " | ")[:700]) + b.close()