- Code\rebar_pipeline, review_pipeline, pier-program을 정션에서 실제 폴더로 전환 - Code\rhino_mcp 및 CLAUDE_rhino배경.md 추가, .mcp.json은 PYTHONPATH로 새 위치 사용 - pier-program 내부 .git 제거(이력은 backup\pier-program_20261028.bundle에 보관) - worktree 가이드 반영(CLAUDE.local.md, HANDOFF.md) - D:\Rhino-MCP 경로 참조를 새 위치로 치환 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
42 lines
2.1 KiB
Python
42 lines
2.1 KiB
Python
"""Helpers shared by the web tests (2026-10-19)."""
|
|
from pathlib import Path
|
|
|
|
_APP = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def pier_dir(name):
|
|
"""data/<name>, or the newest recycle-bin copy of a pier that was deleted in real use (운곡교p2 on 2026-10-19). Read only; exact case
|
|
(Windows globbing is case-insensitive: 운곡교p2 must not pick 운곡교P2_*)."""
|
|
d = _APP / "data" / name
|
|
if (d / "params.json").exists():
|
|
return d
|
|
trash = sorted(t for t in (_APP / "data" / "_휴지통").glob(f"{name}_*") if t.name.startswith(name + "_") and (t / "params.json").exists())
|
|
return trash[-1] if trash else d
|
|
|
|
|
|
def confirm_required(client, webapp, store, pier, by, why="시험"):
|
|
"""Confirm every required, unconfirmed bundle of a pier one by one through the section confirm route.
|
|
The old one-click bulk route is gone; a bundle the app check does not report as 일치 needs a reason, so one is always sent."""
|
|
for f, k in webapp.unconfirmed(store.Pier(pier)):
|
|
client.post(f"/pier/{pier}/section/{f}/{k}/confirm", data={"by": by, "why": why})
|
|
|
|
|
|
def _approved(d):
|
|
"""the pier folder has a recorded G5 result AND an approval of G5 (the whole gate chain was approved)"""
|
|
import json
|
|
try:
|
|
ap = json.loads((d / "runs" / "current" / "approvals.json").read_text(encoding="utf-8"))
|
|
except (OSError, ValueError):
|
|
return False
|
|
return (d / "runs" / "current" / "G5_gate.json").exists() and ap.get("G5", {}).get("decision") == "승인"
|
|
|
|
|
|
def verified_pier(name):
|
|
"""The copy of a pier whose gates G1..G5 were all approved (data/<name>, else the newest recycle-bin copy): a pier may be deleted and made again from
|
|
the template in real use (운곡교P4 on 2026-10-20) and is half-updated while it is being modelled. None when there is none."""
|
|
d = _APP / "data" / name
|
|
if _approved(d):
|
|
return d
|
|
trash = sorted(t for t in (_APP / "data" / "_휴지통").glob(f"{name}_*") if t.name.startswith(name + "_") and _approved(t))
|
|
return trash[-1] if trash else None
|