Files
Pier_v1/RAG/design-model-box-sample_2/tools/revalidate_inner_wall_visibility.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

69 lines
3.8 KiB
Python

"""Recheck installed wall tubes and persist the viewer's containment receipt.
This does not change any bar coordinate, count or approval.
"""
import argparse
import copy
import json
import os
from pathlib import Path
import sys
import tempfile
import time
root = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(root/'src/backend' if (root/'src/backend').is_dir() else root))
def run(job_id, apply=False):
import server
server.require_modeling_rules()
if len(job_id) != 24 or any(c not in '0123456789abcdef' for c in job_id):
raise ValueError('invalid job')
path = Path('/tmp/drawing-model-studio-8097-jobs')/(job_id+'.json')
raw = path.read_bytes(); job = json.loads(raw); original = job['result']
if job.get('status') == 'running': raise ValueError('running job')
plan = copy.deepcopy(original)
hosts = {c['id']: c for c in plan['concrete_components']}
reports = []
for group in plan['rebar_groups']:
assembly = group.get('cad_cycle_assembly', {})
if not assembly.get('wall_station_sources'): continue
paths = group['instance_paths_m']; owners = group['occurrence_instance_ids']
if (len(paths) != len(owners) or len(paths) != group['count']
or len(assembly['occurrences']) != len(paths)
or not group['fabrication_measurement']['fixed_length_pass']):
raise ValueError('path and occurrence evidence differ')
outside = sum(server.tube_path_outside_component_union([bar], group['diameter_mm'],
[hosts[k] for k in owner.split('+')])[0] for bar, owner in zip(paths, owners))
if outside: raise ValueError('wall tube leaves its host: '+group['id'])
assembly.update(containment_checked=True, tested_path_count=len(paths))
group['section_projection_check'] = dict(pass_=True, tube_outside_samples=0,
scope='rechecked physical host tube samples; not engineering approval')
group['section_projection_check']['pass'] = group['section_projection_check'].pop('pass_')
if group['count'] != group['schedule_count']:
group['installation_line_review'] = True
group['engineering_review_required'] = True
reports.append(dict(id=group['id'], count=group['count'], outside_samples=0,
schedule_count=group['schedule_count'], material_count_matched=group['count']==group['schedule_count']))
if apply and reports:
assert plan['concrete_components'] == original['concrete_components']
assert [g['instance_paths_m'] for g in plan['rebar_groups']] == [g['instance_paths_m'] for g in original['rebar_groups']]
preview = plan.get('drawingEvidence', {}).get('preview_geometry')
if isinstance(preview, dict): preview['rebar_groups'] = copy.deepcopy(plan['rebar_groups'])
plan['geometryRevision'] = 'inner-wall-visibility-'+str(time.time_ns())
plan['innerWallVisibilityAudit'] = dict(reports=reports, geometry_changed=False, full_model_approved=False)
job['result'] = plan
if path.read_bytes() != raw: raise ValueError('job changed')
path.with_name(path.stem+'.before-wall-visibility-'+str(time.time_ns())+'.json').write_bytes(raw)
with tempfile.NamedTemporaryFile(mode='w', dir=path.parent, delete=False, encoding='utf8') as output:
json.dump(job, output, ensure_ascii=False, allow_nan=False); temporary = output.name
os.replace(temporary, path)
print(json.dumps(dict(job=job_id, reports=reports, applied=apply), ensure_ascii=False), flush=True)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('jobs', nargs='+'); parser.add_argument('--apply', action='store_true')
args = parser.parse_args()
for job_id in args.jobs: run(job_id, args.apply)