- createDrainageSide(host) — 종단쪽 이음은 DrainagePanelCallbacks 약속으로만 · setVisible · 켜고 끄는 단추
- 관 보고 만들기를 _Report 로 · DrainagePipeReport 형을 _Panel_Types 에 이름 붙임 · 관 요청 몸통 pipeRequest 하나로
- 시험: 종단 · B06 를 안 가져옴 · 700줄 · 관 보고 셈 · 켜고 끄는 창구
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019BVZd1M6WUf1YEy9gbAE1G
- 원인: 가파른 지형(옆경사 평균 67 %)에서 4 m 링크의 14 %뿐이 상한 안 · 반지름 규칙까지 지키는 길이 없어 풂(상한 29 %) · 풂 탐색 벌점(1 m 당 500 × 넘은 비율)이 목표(1 m 당 평균 1)를 덮어 네 갈래가 「넘은 기울기 합 최소」 한 길로 · 탐색 목표(4 m 링크)와 비교값(측점 20 m · 절성토)이 어긋나 벌점만 낮춰도 순서가 안 맞음 · follow 는 이격 최소 탐색이라 초기값과 다름
- 후보 묶음(목표 비중 셋 × 벌점 50 · 5 + 센 벌점 기준 길 · 엄격하면 비중마다 상한 단계)을 한 번 짜고 갈래는 비교값으로 고름 — 토공 최소 = 절성토 합 최소 · 기울기 순한 = 최대(같으면 평균) 최소 · 비중 = 이격 · 절성토 · 기울기를 후보 범위로 정규화한 가중합 · 기준 길보다 못 지킨 곳이 많은 후보는 뺌
- follow = build_planned_polyline(예상노선) — planned_route_initial.csv 와 같은 선(1078.01 m) · 넘은 곳은 「예상노선 추적」 사유로 목록
- 탐색을 B05_Profile_Engine_RouteInitial_Search.py 로 나눔 · 상태 그래프 한 번만 짜고 탐색마다 간선만 거름 · 막는 기울기 이분 탐색은 BFS · 후보 묶음은 같은 입력이면 프로세스 메모리에서 다시 씀
- initial_route 를 B05_Profile_Router_RouteInitial.py 로 나눔(Router_Replan 712 → 630줄, 같은 router 에 등록) · 없는 프로젝트 500 → 404
- 시험 test_route_initial 20(추종 = 초기값 · 갈래별 목적 순서 · 랩탑_보조 실데이터 갈래 차이)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ACSGaHdLgnkEkoA4LDtMU
- 고정 한 벌 — 시점 · 종점(기본 고정) · 교각점을 한 칸 줄로 봄 · 저장 · 읽기는 _RouteEdit_Lock.ts(readRouteLocks = 초기노선 계산에 넘길 한 곳)
- 곧은 선은 양 끝 · 호는 교각점과 앞뒤 점이 모두 고정일 때 고정 색(--map-route-locked · 밝음 #db2777 · 어두움 #f472b6) · 고정 점도 같은 색
- 시점 · 종점을 누르면 고정 단추만 뜸 · 풀면 끌어 옮김 · 고정이면 끌기 · 지우기 막힘
- 되돌리기 · [취소] · 다시 열기 · [확인] 뒤에도 고정 유지(pref 통 · 좌표로 되짚음) · [확인] 몸통은 그대로
- 시험 test_b05_routeedit_lock 5건
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BU9gbNE3aWFUvE61pS2WGt
- 측점 라벨 글자 상자를 그릴 때 기록(drawStationTicks 의 onLabel · B04 지도 · 배수유역도 동작 그대로)
- stationAtScreen 이 눈금 다음 라벨 상자를 봄 · 솎여 안 보이는 눈금은 안 잡음
- 곡선 호 점열(curveArcVertices)과 점-호 판정(arcAtScreen) 더함
- 시험 resources/tester/test_b05_routeedit_pick.py 8건
- RouteEdit.ts 배선은 sub6 나누기 뒤 새 파일에 잇는 다음 커밋
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EauA2ATmqNRbeV48s9CcBr
- 도구 막대: 추천 묶음을 빼고 「1m 등고선」 왼쪽에 구분선 + [노선 추천] 하나 · 「연 상태로」 뺌 · 「현재 추천: ○○」 표시
- 모달(_Recommend): 알약 넷(예상노선 추적 기본) · 비중 슬라이더 · 제약 칸 · 미리 보기 지도 · 비교값 · 못 지킨 구간 · [적용] · [닫기]
- [초기화]: 재계산 없이 GET /route/plan 의 initial_route(전처리 초기값 노선)를 놓음
- 서버: GET /route/plan 에 initial_route(노드 · 곡선) 추가
- 시험: 헬퍼 · 왕복 시험 갱신(추적 표기 · initial_route · 지도 선)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019BVZd1M6WUf1YEy9gbAE1G
- 시설 폼 칸에 옵션 키 표식(data-option-keys) · 끈 키의 칸은 가림 · 칸이 다 가려진 줄은 줄째
- 키가 여럿인 칸(본체 규격 · 유입구 구조)은 키가 다 꺼졌을 때만 가림 · 독립 기슭막이는 유입 · 유출 채널 키로 넓힘
- 숨긴 칸은 칸 값(제안값 채우기 포함)이 아니라 폼이 받은 옛 값을 저장에 그대로 실음 · 이 폼에는 필수 검사가 없음
- 가리기 코드는 새 파일(_Facility_Hidden)로 분리해 Facility.ts 700줄 아래 유지
- 시험 3개 추가
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TULoa94ZFL26KU6ZqVpjkF
- 흠 2 고치는 구조물의 집계 항목 지정 · 해제는 필수 옵션 · 측점 검증을 거치지 않고 기록에 바로 반영(commitSummaryOnly) · 관 · 새 항목은 종전 흐름
- 흠 3 배수유역 화면이 들어올 때 세션 초안 관 목록이 있으면 그것으로 세움(초안이 없으면 종전대로 정본)
- 시험 2개 추가(집계 항목 전용 반영 · 초안 우선 진입)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TULoa94ZFL26KU6ZqVpjkF
- 나무 화살표 · 줄 수와 항목 고르기의 흐린 글을 var(--color-text-secondary) 로 — 밝은 테마 대비 3.08 → 6.3 이상
- M01 왼쪽 목록 줄 수도 같은 공용 클래스(ui-tree__count)로 — 밝은 테마 2.64 → 5.41
- 항목 고르기: 잎 툴팁 = 층 이름 + 키 · 「새 분류N」 자리표는 이름 · 나무 이름에서 뺌 · 관리 화면 단추는 개인 항목만(확인)
- ghost 단추는 두 테마 모두 6.85 이상이라 색 변경 없음 — 다크 1.06 은 ORCA 탭이 색 전환을 멈춰 생긴 측정값
- 자료 시험에 자리표 · 툴팁 추가
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K7JS47SacjPxZ718QsZKyr
- 표 부품 — 열 0 이면 [열 더하기] 가 켜져 첫 열을 만들고 머리 글 고치기를 바로 엶(종류/분류 는 / 로 이음)
- 표 부품 `readOnly` — 단추 줄 · 안내 글 숨김 · 칸 · 머리 · 층 이름 고치기 · 열 너비 끌기 · Delete 막음 · M02 가 읽기만일 때 넘김
- 시험 test_m02_layer_screen.py 7(첫 열 Node 실행 · 읽기만 자리)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Kyw9qnkJ94pC1A4PfpDtA
- GET /api/m02/items?all=1 = [{layer, owner, items}] 를 줄마다 layer · owner 를 붙여 폄 · 404 갈래와 ui_template_item_picker_fake.ts 지움
- 보이는 항목 이름 = 종류 + 분류1~3 (열은 집계표 열 id) · summary_item.name 도 같은 이름
- 폴더 줄은 서버 names{일위대가 · 자재조합 · 도번 · 면적번 · 재료번} 이름을 보임(키는 툴팁) · 이름이 없으면 키를 작은 글로
- 복사 응답 {key} 의 개인 항목을 바로 고름
- 자료 시험을 서버 줄 모양으로 다시 씀
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K7JS47SacjPxZ718QsZKyr
- 폼 옵션 아래 「집계 항목」 줄(이름 · 미지정 · [고르기] · [해제]) — 구조물 · 관 계열 하위 폼 · B05 · B06 한 코드
- 옵션 `visible:false` 는 폼에서 숨김(정의 · 옛 값 그대로) · [수정]은 폼이 그린 칸만 갈아 끼우고 안 그린 칸(상세 · 숨긴 칸) 보존 — 옵션 덮어쓰기 흠 고침
- 목록 줄 `.is-assigned` 색 · 툴팁 항목 이름 · 캐시는 지금 초안 기록 칸(structures · pipes) 안 summary_item
- 미지정이면 칸을 안 실음 · 관은 서버 응답에 칸이 없으면 같은 측점에서 화면이 이어받음
- 항목 고르기 모달은 21-5 가 오기 전까지 같은 이름의 임시 함수 · Structures_Panel 700줄 넘어 옵션 그리기를 Panel_Options 로 나눔
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TULoa94ZFL26KU6ZqVpjkF
- Store · Matset · Branch 가 지금 층 폴더(store.at · 기본 시스템 층)를 봄 — 시스템 층 동작 · 옛 길 그대로
- 회사 · 개인 층 첫 진입 때 빈 뼈대(집계표 열 0 · 조합 장부 다음 1 · 자재 조합 빈 표)
- /api/m02/layers/{layer}/… 집계표 길(번호 · 조합 장부 · 구조물 새로 · 복사 · 조합 갈라 내기 · 자재 조합) · 권한 = 시스템 SYSTEM_ADMIN · 회사 관리자 · 개인 본인
- 층 양식 저장(시스템 · 회사 · 개인)은 집계표 규칙(새 열 파일 · 번호 · SS) 거침 · 시스템 층 쓰기는 SYSTEM_ADMIN · 쓰는 양식 지우기 409
- GET /api/m02/items(한 층 · ?all=1 세 층) · POST /api/m02/layers/personal/items/copy · 회사 없음 409 「회사부터 등록」
- 시험 test_m02_layers_store
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EUypcnp5d1gU2aeKh9F2H7
- summary_item 칸: StructureInstance · pipe_points 점 기록(options 밖) — 모양 검사 한 벌 common_util_summary_item(층 system·company·personal · owner null·{회사}·{회사}/{사용자} · key SS+6자리 · name) · 없으면 null(옛 파일 호환) · 관 요청 모양 틀림 400
- 저장 스냅샷 M02_Item_Snapshot: PUT /route/structures · PUT /drainage/pipe-points 뒤 지정 항목마다 templates/items/{layer}_{owner}_{key}/ 에 집계(SS 줄 + 열 정의) · 도면 · 면적 · 재료 · 자재조합 · 일위대가(UA 줄 + 담은 로직 줄) · manifest(원본 · 판 · 적용일 · 쓰는 구조물) — 있는 폴더는 다시 안 씀(원본이 바뀌어도 프로젝트 값 그대로) · 안 쓰는 폴더 지움 · 실패해도 저장 유지
- 채움 fill_table = 지정 항목 모드: 구조물이 고른 열(묶음)에만 · 미지정 · 복사본 없음은 안 셈 + 알림 · 스냅샷 열 정의 사용 · 회사 · 개인 항목은 열id@폴더 새 열 · 자동 맞춤은 fill_document 기본으로만 남음
- 관 시설 되붙이기가 summary_item 도 옮김
- [초기화]는 templates/ 를 안 건드림 · 복제 도구는 폴더 통째 복사 — 손댈 것 없음(시험으로 지킴)
- 시험: test_structures_summary_snapshot 17 · 옛 채움 시험은 자동 맞춤 길(fill_document)로 · 층 라우트 채움 시험은 새 규칙(미지정 관 = 줄 없음)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RrQ65VtGZbae2VKgYVMhmc
- ui_template_tree: M01 renderTree 를 공용으로 올림(M01 은 같은 이름으로 그대로 부름) · 기본 줄 createTreeRow · 클래스 ui-tree__*
- ui_template_item_picker: openItemPicker({current, canCopy}) → apply(summary_item) | clear | cancel · 왼쪽 마스터 · 회사 · 개인 → 종류 → 분류1 → 항목 나무 + 찾기 · 오른쪽 폴더 모양(키는 툴팁) · 개인용으로 복사 · 관리 화면 이동
- 목록 GET /api/m02/items?all=1 · 복사 POST /api/m02/layers/personal/items/copy — 서버가 없으면(404) 21-1 모양 가짜 응답
- 자료 쪽(나무 · 찾기 · 폴더 줄)은 화면 없는 모듈로 나눠 시험
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K7JS47SacjPxZ718QsZKyr
PLAN 20장 소수 측점 횡단(sub6). 사용자 확정: 관 · 구조물이 놓인 소수 측점(예 119.8)에 그 자리 횡단을
따로 둠 · 백엔드 · 파일 · 저장값은 소수 그대로 · 화면 표기만 「측점 + 거리」의 거리를 정수로(5+20).
- 이름 규칙 한 벌(B05_Profile_Engine_Sections): cross_key · cross_filename · parse_cross_key ·
CROSS_KEY_PATTERN — 정수 m 는 옛 이름 그대로(cross_00120m) · 소수 측점은 cross_00119.80m.
find_cross_file = 읽기용(새 이름이 없으면 옛 정수 m 이름) · prune_stale_cross_files 도 이것으로
가려 옛 프로젝트의 정수 이름 파일을 지우지 않음
- generate_sections: 정수 m 격자 붙임을 풂 — 같은 이름이 되는 0.005m 안 겹침만 하나로
- B06: 찾기 · 패치 입력(Router_Design 둘) · 샘플 넓힘(SampleExtend)이 find_cross_file ·
DB 설계 찾기 · 병합(get_cross_section_design · merge_…_by_round)은 ROUND(chainage_m)=정수 →
0.005m 안 매칭
- B07: 도면 id · 장 id(cross_{key}m · cross_s{key}m) 정규식 · 측점 키(cross_station — 정수는 int
그대로라 옛 id · 수량표 키 안 바뀜) · 측점은 파일 속 값으로(옛 정수 이름 파일도) · 횡단 파일 찾기
- 화면 표기 한 벌 common_util/common_util_station.ts(stationLabel · stationPartsLabel · 순수 함수) —
common_util_svg 가 다시 내보내고 B05 formatStation 을 대신함(B05 목록 · 표시 · 폼 범위 · 계획노선
편집 · 비정규 측점 라벨 · B06 카드 · 종단 · 유토) · 입력 칸 · 저장값은 소수 그대로
- B05_Profile_UI_Structures_Panel 700줄 → 690(순수 도우미 셋을 Panel_Types 로)
- M02_Table_Fill 관연장 찾기는 이미 측점 값(정확 먼저 · 0.5m 안)이라 그대로
시험: test_b05_station_roundtrip(표기 5+20 · 옛 정수 이름 찾기 · 안 지움 · 119.8 과 120 따로) ·
test_b05_extra_stations_supplier(새 규칙) · test_b06_patch_station(119.8 한 건) ·
test_b05_b06_save_roundtrip(보낸 관 측점마다 소수 이름 횡단 파일 있음) 등 고친 대상 108 통과 ·
test_b05_station_merge 통과 · 타입검사 통과.
ORCA(IP 5181 · 사본 프로젝트 sub6_검증 — 끝나고 DB 행 · 폴더 지움 · 원본 안 씀): 노출형 횡단수로를
5+19.8 에 놓고 저장 → structures.json 119.8 · 종단 측점 119.8(irregular) + 120 · 파일
cross_00119.80m.json 과 cross_00120m.json · B05 목록 「5+20」 · B06 카드 「5+20 · 119.8m」 열림.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVM3xZ1aUPcUTuW2WZSnwg
- 공통 제약 기준값 확정(9-29 사용자 결정) — 후보 표 임시값 그대로 기본값, 화면에서 프로젝트마다 바꿀 수 있음
- 로직 단추 옆 제약 네 칸(비우면 placeholder 로 기본값) · 채운 칸만 POST /route/initial 몸통 criteria 로 실어 보냄
- [확인]의 initial.criteria 에도 실어 성공하면 initial_choice.json 에 겹친 칸만 남김(빈 칸은 기본값이라 안 담김)
- 다시 열 때 current_initial.criteria 로 그 칸만 복원 · 캐시가 서버 갈래·비중·제약과 다르면 버림(sameBase)
- 서버: generate_initial_route/_SearchGrid 가 stream_offset_m·grade_smooth_m 겹침을 받아 탐색·비교값에 반영
- 응답 criteria.pending 은 이제 늘 빈 목록 — 화면의 「후보 · 사용자 확정 대기」 글 삭제
시험: test_route_initial(+2) · test_b05_routeedit_initial(criteria 겹침·확정 표시 삭제) ·
test_b05_routeedit_initial_roundtrip(+1, 사본에서 계류 이격 30m 겹침 왕복)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sCeZz8z8YnbovsKgn7HK7
- 비교값 줄 아래 「제약 못 지킨 구간 N곳: No.9 16.4%(지형상 불가능) · …」(없으면 「모두 지킴」 · 5곳 넘으면 「외 N곳」 · 풍선에 전부와 사유)
- relaxed 면 「지형상 14.0% 로 못 이어져 상한을 29.1% 로 풂」(경고 색)
- 공통 제약 줄에 서버 grade_smooth_m 을 「기울기 잴 지반 5m 고름」으로
- 시험 — 글 만들기(test_b05_routeedit_initial) · 사본 왕복에서 목록 · 풂 · 고름 칸이 화면 줄에(test_b05_routeedit_initial_roundtrip)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sCeZz8z8YnbovsKgn7HK7
- 종단기울기 상한 넘는 링크 · 계류 버퍼 안 나란히 달리기는 탐색에서 뺌(추종 갈래 포함)
- 최소 곡선반지름: 이웃 방향으로만 꺾고 접선 길이만큼 곧게 간 뒤 다시 꺾음 · 노드마다 원호
- 길이 없을 때만 막은 기울기(규칙 지키는 어떤 길도 넘어야 하는 값)를 이분 탐색해 그 위는 막고 넘긴 곳을 metrics.violations 에
- over_limit 수 = 목록 수 · 종단기울기는 5 m 로 고른 지반의 측점 20 m 기울기(탐색 · 비교값 같은 잣대)
- 비교값 · 목록은 새 파일 B05_Profile_Engine_RouteInitial_Metrics.py
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TULoa94ZFL26KU6ZqVpjkF
- 원인: B06 [저장]은 관 측점 비정규 측점을 종단에 싣지 않아(확정은 상단측만) 옮긴 관 자리에 DB 행이 없고, merge_cross_section_designs 가 행 없는 수정을 버림
- 고침(서버 한 곳): 저장 · 확정이 행 없는 측점의 수정을 받으면 ensure_structure_stations — [측점 만들기]와 같은 조건(샘플링 기록)으로 구조물 측점을 세움 → 기존 _rowless_station_chainages 가 기본 설계 행을 만들고 수정이 그 위에 얹힘
- 판정: 화면이 행을 만들려면 지표 샘플링 · 횡단 파일이 필요해 서버만 할 수 있음 — 서버 한 곳으로 충분
- B06_Section_Router_Stations: 측점 다시 뜨기를 _regenerate_structure_stations 로 떼어 단추 · 저장이 같이 씀
- 시험: test_b06_patch_station(부르는 조건) · sub8 왕복 시험 [B06] 통과(프로젝트 사본 · DB 읽기만)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RrQ65VtGZbae2VKgYVMhmc
- 데스크탑_메인 storage 사본 · DB 읽기 전용 · 재계산 체인은 성공만 돌려주는 가짜
- 추종 · 토공 최소 · 기울기 순한 · 비중 50/25/25 마다 /route/initial → 화면 코드로 [확인] 몸통 → /route/replan → /route/plan
- 현재 초기값 = 보낸 것 · 다시 연 노드 = 보낸 노드 · [초기화] = 마지막 초기값(캐시 없으면 서버가 같은 노드) · 비교값 다 있음
- 화면 셈은 helper_b05_routeedit_initial_apply.cjs 가 화면 코드 그대로
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sCeZz8z8YnbovsKgn7HK7
PLAN 19장 남은 차이(sub8 왕복 시험): 관 440.24 · 619.71 · 720.44 · 899.91 이 저장 뒤 종단 측점에서
440 · 620 · 720 · 900 으로 붙음(generate_sections 의 정수 m 격자 붙이기). 판정 (다) 유지 — 횡단 파일
이름(cross_{정수m}m)은 그대로 한 정수 m 에 한 장, 측점 값은 관 · 구조물 자체 측점 그대로:
- 같은 정수 m 에 격자 측점이 있으면 격자 대신 관 · 구조물 측점을 씀(kind irregular · 라벨 그대로)
- 시 · 종점 격자는 그대로 두고 라벨만 얹음(노선 끝 측점이 사라지지 않게)
- 비정규끼리 같은 정수 m 면 앞선 것만(종전과 같음 · 파일 한 장)
시험 — test_b05_b06_save_roundtrip[B05] 통과(관 측점 차이 0 · 사본 storage · 읽기 전용 DB) ·
test_b05_extra_stations_supplier(옛 「격자 우선」 기대를 새 규칙으로 · 시 · 종점 하나 더함) ·
test_b05_station_roundtrip · test_regeneration_extra_stations 통과. [B06] 경우의 「횡단 patch 263.47 —
받을 행이 없어 DB 가 버림」은 고치기 전 코드에서도 같게 실패(이번 변경과 무관 · 보고함).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVM3xZ1aUPcUTuW2WZSnwg
- /route/plan 의 current_initial {logic, weights} 를 읽어 이름 · 비중 슬라이더에 보임(없으면 예상노선 추종)
- 캐시가 서버와 다른 갈래 · 비중이면 캐시를 버림(서버가 정본 — [확인] 때만 적힘)
- 노드 없이 이름만 아는 초기값의 [초기화]는 그 갈래를 서버에 물어 노드를 실음
- 시험 test_b05_routeedit_initial.py — 서버 초기값 펴기 · 캐시 견주기
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sCeZz8z8YnbovsKgn7HK7