Files
Pier_v1/Code/교각모델링앱/tools/patches/2026-10-13_patch_scope_web.py
T
ahnyongjooandClaude Sonnet 5.5 964a841de1 chore(rebar): Pier_T_rebar 작업 폴더 초기 구성 및 외부 의존 파일 통합
- 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>
2026-10-28 11:20:18 +09:00

106 lines
5.4 KiB
Python

"""Patch (2026-10-13, Ulsan P1): per-pier gate scope in the web app and the report.
Gates outside params["scope"] are not listed / run / required; the previous gate of a gate is the previous gate
in scope; optional sections (params.piles for a pier without piles) are not required for confirmation."""
from pathlib import Path
APP = Path(__file__).resolve().parents[2]
def patch(rel, reps):
p = APP / rel
s = p.read_text(encoding="utf-8")
for a, b in reps:
assert s.count(a) == 1, (rel, a[:70])
s = s.replace(a, b)
p.write_text(s, encoding="utf-8")
patch("web/store.py", [
(""" def gate_requirements(self, gate):
need = COMMON + GATE_SECTIONS[gate]
return [dict(file=f, key=k, **self.section_state(f, k)) for f, k in need]""",
""" def gate_requirements(self, gate):
need = COMMON + GATE_SECTIONS[gate]
P = self.load("params")
need = [(f, k) for f, k in need if not ((f, k) in OPTIONAL and k not in P)]
return [dict(file=f, key=k, **self.section_state(f, k)) for f, k in need]
def scope(self):
\"\"\"Gates modelled for this pier (params["scope"], default all five).\"\"\"
sc = self.load("params").get("scope")
return [g for g in ("G1", "G2", "G3", "G4", "G5") if not sc or g in sc]"""),
("""GATE_SECTIONS = {""", """OPTIONAL = {("params", "piles")} # a pier on a spread footing has no piles (Ulsan P1)
GATE_SECTIONS = {"""),
])
patch("web/app.py", [
(""" gates = [dict(id=g, name=GATE_NAMES[g], **p.gate_status(g)) for g in gate_ids()]""",
""" gates = [dict(id=g, name=GATE_NAMES[g], **p.gate_status(g)) for g in p.scope()]"""),
(""" out = []
for g in gate_ids():
for r in p.gate_requirements(g):""",
""" out = []
for g in p.scope():
for r in p.gate_requirements(g):"""),
(""" k = gate_ids().index(gate)
if k > 0 and not p.gate_status(gate_ids()[k - 1])["approved"]:
out.append(f"{gate_ids()[k - 1]} 미승인")""",
""" ids = p.scope()
if gate not in ids:
return [f"{gate}는 이 교각의 범위 밖"]
k = ids.index(gate)
if k > 0 and not p.gate_status(ids[k - 1])["approved"]:
out.append(f"{ids[k - 1]} 미승인")"""),
(""" todo = [g for g in gate_ids() if not p.gate_status(g)["approved"]]
if not todo:""",
""" todo = [g for g in p.scope() if not p.gate_status(g)["approved"]]
if not todo:"""),
(""" for g in gate_ids()]
for r in rows:""",
""" for g in p.scope()]
for r in rows:"""),
(""" todo=[g for g in gate_ids() if not p.gate_status(g)["approved"]])""",
""" todo=[g for g in p.scope() if not p.gate_status(g)["approved"]],
out_of_scope=[g for g in gate_ids() if g not in p.scope()])"""),
(""" if not any(p.gate_status(g)["report"] for g in gate_ids()):""",
""" if not any(p.gate_status(g)["report"] for g in p.scope()):"""),
(""" stale = {g for g in gate_ids() if p.gate_status(g)["stale"]}
out = report_files.write(p.dir, p.run_dir, request.form.get("by", "").strip(), stale)""",
""" stale = {g for g in p.scope() if p.gate_status(g)["stale"]}
out = report_files.write(p.dir, p.run_dir, request.form.get("by", "").strip(), stale,
[g for g in gate_ids() if g not in p.scope()])"""),
(""" todo=[g["id"] for g in gates if not g["approved"]], running=anything_running(p),""",
""" todo=[g["id"] for g in gates if not g["approved"]], running=anything_running(p),
out_of_scope=[g for g in gate_ids() if g not in p.scope()],"""),
])
patch("web/templates/gates.html", [
("""<h2>일괄 승인 (필요하면 실행)</h2>""",
"""{% if out_of_scope %}<p class="muted">이 교각의 범위 밖 게이트: {{ out_of_scope|join(', ') }} (실행·승인 대상 아님)</p>{% endif %}
<h2>일괄 승인 (필요하면 실행)</h2>"""),
])
patch("web/templates/pier.html", [
("""<h2>3. 게이트</h2>""",
"""<h2>3. 게이트</h2>
{% if out_of_scope %}<p class="muted">범위 밖: {{ out_of_scope|join(', ') }} — 이 교각에서는 모델링하지 않습니다.</p>{% endif %}"""),
])
patch("engine/report_files.py", [
("""def write(pier_dir, run_dir, author="", stale=()):""", """def write(pier_dir, run_dir, author="", stale=(), out_of_scope=()):"""),
(""" md, d = report.build(pier_dir, run_dir, author, today, stale)""",
""" md, d = report.build(pier_dir, run_dir, author, today, stale, out_of_scope)"""),
])
patch("engine/report.py", [
("""def build(pier_dir, run_dir, author="", today=None, stale=()):""",
"""def build(pier_dir, run_dir, author="", today=None, stale=(), out_of_scope=()):"""),
(""" all_ok = all(gates[g] and gates[g]["verdict"] == "PASS" and appr.get(g, {}).get("decision") == "승인"
for g in gate_ids())""",
""" all_ok = all(gates[g] and gates[g]["verdict"] == "PASS" and appr.get(g, {}).get("decision") == "승인"
for g in gate_ids() if g not in out_of_scope)"""),
(""" rows.append([g, gname, "입력 변경 — 무효(재실행 필요)" if g in stale else "미실행", "-", "-", "-"])""",
""" rows.append([g, gname, "범위 밖" if g in out_of_scope else
("입력 변경 — 무효(재실행 필요)" if g in stale else "미실행"), "-", "-", "-"])"""),
])
print("patched")