커밋 그래프

231 커밋

작성자 SHA1 메시지 날짜
2ceeb966d8 feat(prediction): Phase 1-2 detection model registry + snapshot 관찰 보강
- models_core 패키지 신설 — BaseDetectionModel / ModelContext / ModelResult
  + Registry (ACTIVE 버전 인스턴스화, DAG 순환 검출, topo 플랜)
  + DAGExecutor (PRIMARY→ctx.shared 주입, SHADOW persist-only 오염 차단)
  + params_loader (5분 TTL 캐시), feature_flag (PREDICTION_USE_MODEL_REGISTRY)
- V034 스키마 정합성 사전 검증 + silent error 3건 선제 방어
  · model_id VARCHAR(64) 초과 시 __init__ 에서 즉시 ValueError
  · metric_key VARCHAR(64) 초과는 경고 후 drop (다른 metric 는 저장)
  · persist 가 ctx.conn 재사용 (pool maxconn=5 고갈 방지)
- scheduler.py — 10단계 feature flag 분기 (기본 0, 구 경로 보존)
- partition_manager — detection_model_run_outputs 월별 파티션 자동 생성/DROP
- 유닛테스트 15 케이스 전체 통과 (DAG 순환, SHADOW 오염 차단, 길이 검증)
- snapshot 스크립트 (hourly/diagnostic) 개선
  · spoofing gt0/gt03/gt05/gt07 세분화 — 'silent fault' vs 'no signal' 구분
  · V030 gear_identity_collisions 원시 섹션 (CRITICAL 51건 OPEN 포착)
  · V034 detection_model_* 모니터링 섹션 (Phase 2 대비)
  · stage timing 집계 + stats_hourly vs events category drift 감시

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 08:07:29 +09:00
d8fe1ef202 Merge pull request 'docs: 2026-04-20 릴리즈 후속 정적 문서 최신화' (#91) from feature/docs-refresh-2026-04-20 into develop 2026-04-20 07:12:32 +09:00
f913953562 docs: 릴리즈 노트 업데이트 2026-04-20 07:11:01 +09:00
04d4b12c50 docs: 2026-04-20 릴리즈 후속 정적 문서 최신화
Phase 0-1/0-2/0-3 + Phase 1-1 V034 반영 + Phase 1-2 재개 포인트 명시.

### 변경
- architecture.md — 27→29 보호 경로, /illegal-fishing + /transshipment 라우트 추가
- sfr-traceability.md
  - Flyway V001~V030 → V001~V034 (34 마이그레이션)
  - Database 51 → 56 테이블 (V034 detection_model_* 5종 + 뷰 1, 반영 대기)
  - Prediction 섹션에 stage_runner 사이클 에러 경계 (Phase 0-1) 추가
  - SFR-09: TransshipmentDetection(V033/PR #86) 페이지 추가
  - SFR-10: IllegalFishingPattern(V032/PR #85) 페이지 추가
  - 부록 A: 신규 화면 파일 경로 반영
- sfr-user-guide.md — SFR-10 하위에 "불법 조업 이벤트" + "환적 의심 탐지" 2개 신규 페이지 사용자 가이드 섹션 신설
- system-flow-guide.md — V030 미반영 경고를 V030~V034 노드 일괄 미반영으로 확장 (detection_models / detection_model_versions / detection_model_run_outputs / detection_model_metrics / dag_executor / shadow_runner / api.detection_models_* / ui.illegal_fishing / ui.transshipment_detection / ui.detection_model_management)
- prediction-analysis.md — P1 권고 4건 중 3건 완료 표시
  -  사이클 스테이지 에러 경계 (PR #83)
  - 🟡 임계값 외부화 (V034 스키마 머지, Phase 1-2 대기)
  -  ILLEGAL_FISHING_PATTERN 전용 페이지 (PR #85)
  -  환적 전용 페이지 (PR #86)
  - 변경 이력에 2026-04-20 행 추가

### 범위 밖
- memory/* 는 세션 로컬 경로, 저장소 외
- prediction/backend 코드 변경 없음 — 문서만
2026-04-20 07:10:48 +09:00
31a138e4ab Merge pull request 'docs: 릴리즈 노트 정리 (2026-04-20 sync to develop)' (#90) from release/2026-04-20 into develop 2026-04-20 06:56:28 +09:00
be315f59aa docs: 릴리즈 노트 정리 (2026-04-20) 2026-04-20 06:52:25 +09:00
30abe6a951 Merge pull request 'feat(db): Detection Model Registry 스키마 (V034, Phase 1-1)' (#87) from feature/phase1-1-detection-models-schema into develop 2026-04-20 06:49:02 +09:00
82ffe7cb06 Merge branch 'develop' into feature/phase1-1-detection-models-schema 2026-04-20 06:48:43 +09:00
afde36480d Merge pull request 'fix(ui): 모니터링/디자인시스템 런타임 에러 해소' (#88) from fix/runtime-errors-monitoring-designsystem into develop 2026-04-20 06:36:32 +09:00
d971624090 docs: 릴리즈 노트 업데이트 2026-04-20 06:31:33 +09:00
eee9e79818 fix(ui): 모니터링/디자인시스템 런타임 에러 해소
### SystemStatusPanel TypeError
- 증상: /monitoring 에서 Uncaught TypeError: Cannot read properties of undefined (reading 'toLocaleString')
- 원인: stats 객체는 존재하나 total 필드가 undefined 인 경우 (백엔드 응답이 기대 shape 와 다를 때) 크래시
- 수정: stats?.total != null ? ... / stats.critical ?? 0 식 null-safe 전환 (total/clusterCount/gearGroups/critical/high/medium/low 전부)

### CatalogBadges 렌더링 오류
- 증상: /design-system.html 에서
  (1) Each child in a list should have a unique "key" prop
  (2) Objects are not valid as a React child (found: object with keys {ko, en})
- 원인: PERFORMANCE_STATUS_META 의 meta 는 {intent, hex, label: {ko, en}} 형식. code 필드 없고 label 이 객체.
  - Object.values() + <Trk key={meta.code}> 로 undefined key 중복
  - getKoLabel 이 meta.label (객체) 그대로 반환해 Badge children 에 객체 주입
  다른 카탈로그는 fallback: {ko, en} 패턴이라 문제 없음 (performanceStatus 만 label 객체)
- 수정:
  - Object.entries() 로 순회해 Record key 를 안정적 식별자로 사용
  - AnyMeta.label 타입을 string | {ko,en} 확장
  - getKoLabel/getEnLabel 우선순위: fallback.ko → label.ko → label(문자열) → code → key
  - PERFORMANCE_STATUS_META 자체는 변경 안 함 (admin 페이지들이 label.ko/label.en 직접 참조 중)

### 검증
- npx tsc --noEmit 통과
- pre-commit tsc+ESLint 통과
2026-04-20 06:31:11 +09:00
410d0da9cf docs: 릴리즈 노트 업데이트 2026-04-20 06:22:58 +09:00
dae7aea861 feat(db): Detection Model Registry 스키마 (V034, Phase 1-1)
prediction 의 17 탐지 알고리즘을 "명시적 모델 단위" 로 분리하고 프론트엔드에서
파라미터·버전을 관리할 수 있도록 하는 기반 인프라의 DB 계층.

기존 V014 correlation_param_models 패턴을 일반화:
- JSONB params + is_active(V014) → model_id × version × role×status (V034)
- 한 모델을 여러 파라미터 셋으로 동시 실행 지원 (PRIMARY/SHADOW/CHALLENGER)
- Compare API 기반 제공 (PRIMARY vs SHADOW diff 집계)

### 스키마 (테이블 4 + 뷰 1)

1. detection_models — 모델 카탈로그 (model_id PK, tier 1~5, category, entry_module/callable, is_enabled)
2. detection_model_dependencies — 모델 간 DAG 엣지 (self-loop 금지, input_key 포함)
3. detection_model_versions — 파라미터 스냅샷 + 라이프사이클 + role
   - status: DRAFT / TESTING / ACTIVE / ARCHIVED
   - role: PRIMARY / SHADOW / CHALLENGER (ACTIVE 일 때만)
   - UNIQUE partial index: model_id 당 PRIMARY×ACTIVE 최대 1건
   - SHADOW/CHALLENGER×ACTIVE 는 N건 허용 (병렬 비교)
   - parent_version_id 로 fork 계보 추적
4. detection_model_run_outputs — 버전별 실행 결과 원시 snapshot
   - PARTITION BY RANGE (cycle_started_at)
   - 초기 2개월(2026-04, 2026-05) 파티션 + 이후 월별 자동생성 TODO (Phase 1-2)
   - input_ref JSONB GIN index — 같은 입력 기준 PRIMARY×SHADOW JOIN 용
5. detection_model_metrics — 사이클 단위 집계 메트릭 (cycle_duration_ms 등)
6. v_detection_model_comparison — PRIMARY×SHADOW 같은 입력으로 JOIN 한 VIEW

### 권한
- auth_perm_tree: 'ai-operations:detection-models' (parent=admin, nav_sort=250)
- ADMIN 5 ops / OPERATOR READ+UPDATE / ANALYST·VIEWER READ

### 후속 (Phase 1-2)
- partition_manager 에 detection_model_run_outputs 월별 자동 생성/만료 로직 추가
- 기본 retention 7일 (SHADOW 대량 누적 대비)

### 검증
- Flyway 자동 적용 (백엔드 재빌드+배포)
- 이후 Python Model Registry 가 이 스키마 위에서 동작
2026-04-20 06:22:25 +09:00
2395ef1613 Merge pull request 'feat(detection): 환적 의심 전용 탐지 페이지 신설 (Phase 0-3)' (#86) from feature/phase0-3-transshipment-detection into develop 2026-04-20 05:52:05 +09:00
a8ce9a4ea9 docs: 릴리즈 노트 업데이트 2026-04-20 05:51:25 +09:00
cbfed23823 feat(detection): 환적 의심 전용 탐지 페이지 신설 (Phase 0-3)
docs/prediction-analysis.md §7 P1 권고의 "UI 미노출 탐지" 해소 중 두 번째.
prediction algorithms/transshipment.py 5단계 필터 파이프라인 결과를 전체 목록·
집계·상세 수준으로 조회하는 READ 전용 대시보드.

### 배경
기존 features/vessel/TransferDetection.tsx 는 선박 상세 수준(특정 MMSI 의 환적
이력)이고, 환적 의심 선박 전체 목록을 보려면 ChinaFishing 의 탭 중 하나를 거쳐야
했다. /api/analysis/transship 엔드포인트는 이미 존재하나 전용 페이지가 없었음.

### 변경
- frontend/src/features/detection/TransshipmentDetection.tsx 신설 (405 라인)
  - PageContainer + PageHeader(ArrowLeftRight) + KPI 5장
    (Total / Transship tier CRITICAL/HIGH/MEDIUM / Risk CRITICAL)
  - DataTable 8컬럼 (analyzedAt / mmsi / pairMmsi / duration / tier / risk / zone)
  - features.transship_tier 읽어 Badge 로 심각도 표시
  - 필터: hours(1/6/12/24/48) / riskLevel / mmsi 검색
  - 상세 패널: 분석 피처 JSON 원본 + 좌표 + transship_score
  - 기존 analysisApi.getTransshipSuspects 재사용 — backend 변경 없음
- index.ts + componentRegistry.ts 등록
- detection.json (ko/en) transshipment.* 네임스페이스 추가 (각 44키)
- common.json (ko/en) nav.transshipment 추가
- V033__menu_transshipment_detection.sql
  - auth_perm_tree(detection:transshipment, nav_sort=910)
  - ADMIN 5 ops + OPERATOR/ANALYST/FIELD/VIEWER READ

### 권한 주의
/api/analysis/transship 의 @RequirePermission 은 현재 detection:dark-vessel.
이 메뉴 READ 만으로는 API 호출 불가. 현행 운영자 역할(OPERATOR/ANALYST/FIELD)
은 dark-vessel READ 도 보유하므로 실용 동작.
향후 VesselAnalysisController.listTransshipSuspects 의 @RequirePermission 을
detection:transshipment 로 교체하는 권한 일관화는 별도 MR (후속).

### 검증
- npx tsc --noEmit 통과
- pre-commit tsc + ESLint 통과 예정
- Flyway V033 자동 적용 (백엔드 재배포 필요)
2026-04-20 05:51:06 +09:00
f2d145c9a2 Merge pull request 'feat(detection): 불법 조업 이벤트 전용 페이지 신설 (Phase 0-2)' (#85) from feature/phase0-2-illegal-fishing-pattern into develop 2026-04-20 05:47:17 +09:00
214f063f1e docs: 릴리즈 노트 업데이트 2026-04-20 05:46:34 +09:00
e49ab0f4e8 feat(detection): 불법 조업 이벤트 전용 페이지 신설 (Phase 0-2)
docs/prediction-analysis.md §7 P1 권고의 "UI 미노출 탐지" 해소. event_generator
가 생산하는 카테고리 중 불법 조업 관련 3종을 READ 전용 대시보드로 통합.

대상 카테고리:
- GEAR_ILLEGAL   — G-01 수역·어구 / G-05 고정어구 drift / G-06 쌍끌이
- EEZ_INTRUSION  — 영해 침범 / 접속수역 + 고위험
- ZONE_DEPARTURE — 특정수역 진입 (risk ≥ 40)

### 변경
- frontend/src/services/illegalFishingPatternApi.ts 신설
  - 기존 /api/events 를 category 다중 병렬 조회 후 머지 (backend 변경 없음)
  - category '' 이면 3 카테고리 통합, 지정 시 단일 카테고리만
  - size 기본 200 × 3 categories = 최대 600건, occurredAt desc 정렬
  - byCategory / byLevel 집계 포함
- frontend/src/features/detection/IllegalFishingPattern.tsx 신설 (391 라인)
  - PageContainer + PageHeader(Ban 아이콘) + Section + KPI 5장 + 카테고리별 3장
  - DataTable (occurredAt/level/category/title/mmsi/zone/status 7컬럼)
  - 필터: category / level / mmsi (최근 DEFAULT_SIZE 건 범위)
  - 상세 패널: JSON features 포함, EventList 로 네비게이션 링크
  - design-system SSOT 준수: Badge intent, Select aria-label, text-* 시맨틱 토큰
- index.ts + componentRegistry.ts export/lazy 등록
- detection.json (ko/en) illegalPattern.* 네임스페이스 추가 (각 60키)
- common.json (ko/en) nav.illegalFishing 추가
- V032__menu_illegal_fishing_pattern.sql
  - auth_perm_tree 엔트리 (rsrc_cd=detection:illegal-fishing, nav_sort=920)
  - ADMIN 5 ops + OPERATOR/ANALYST/FIELD/VIEWER READ
  - READ 전용 페이지 (처리 액션은 EventList 경유)

### 검증
- npx tsc --noEmit 통과 (0 에러)
- 백엔드 변경 없음 (기존 /api/events category 필터 재사용)
- Flyway V032 자동 적용 (백엔드 재배포 필요)
2026-04-20 05:46:13 +09:00
2e674ccc5b Merge pull request 'fix(db): candidate_source 컬럼 VARCHAR(30)→(100) 확장 (V031)' (#84) from fix/candidate-source-length into develop 2026-04-17 11:53:08 +09:00
2b25dc1c92 docs: 릴리즈 노트 업데이트 2026-04-17 11:52:08 +09:00
0f4a9cb7d6 fix(db): candidate_source 컬럼 VARCHAR(30)→(100) 확장 (V031)
gear_group_parent_candidate_snapshots.candidate_source 의 VARCHAR(30) 제약
때문에 prediction gear_correlation 스테이지가 매 사이클 실패하던 문제 해소.

원인:
- prediction/algorithms/gear_parent_inference.py:875 의
  candidate_source = ','.join(sorted(meta['sources']))
  가 복수 source 라벨 (CORRELATION/EPISODE/LABEL/LINEAGE/MATCH) 을 쉼표 join
  하며 최대 약 39자. VARCHAR(30) 초과 시 psycopg2.errors.StringDataRightTruncation
  을 유발해 _insert_candidate_snapshots 전체 ROLLBACK.

발견 경위:
- Phase 0-1 (PR #83) 의 stage_runner + logger.exception 전환 후 journal 에
  찍힌 풀 스택트레이스로 드러남. 기존에는 logger.warning 한 줄 ("gear
  correlation failed: ...") 만 남아 원인 특정 불가.

영향 범위:
- 백엔드 JPA 엔티티 미참조 → 재빌드·재배포 불필요
- Flyway 자동 적용 (백엔드 기동 시)
- prediction 재기동만 필요 (기존 코드 그대로, 이제 INSERT 성공 기대)

검증:
- 재배포 후 journalctl 에서 'gear correlation failed' 로그 사라짐 확인
- kcg.gear_group_parent_candidate_snapshots 에 최근 15분 건수 증가 확인
2026-04-17 11:51:35 +09:00
3e29bc9995 Merge pull request 'refactor(prediction): 사이클 스테이지 에러 경계 도입 (Phase 0-1)' (#83) from feature/phase0-cycle-error-boundary into develop 2026-04-17 11:30:17 +09:00
a32d09f75a docs: 릴리즈 노트 업데이트 2026-04-17 11:28:58 +09:00
197da13826 refactor(prediction): 사이클 스테이지 에러 경계 도입 (Phase 0-1)
docs/prediction-analysis.md P1 권고 반영. 5분 사이클의 각 스테이지를
한 try/except 로 뭉친 기존 구조를 스테이지 단위로 분리해 실패 지점을
명시적으로 특정하고 부분 실패 시에도 후속 스테이지가 계속 돌아가도록 개선.

- prediction/pipeline/stage_runner.py 신설
  - run_stage(name, fn, *args, required=False, **kwargs) 유틸
  - required=True 면 예외 re-raise (상위 사이클 try/except 가 잡도록)
  - required=False 면 logger.exception 으로 stacktrace 보존 + None 반환
  - 지속시간 로깅 포함

- prediction/scheduler.py run_analysis_cycle() 수정
  - 출력 단계 6모듈을 각각 run_stage() 로 분리:
    violation_classifier / event_generator / kpi_writer /
    stats_aggregate_hourly / stats_aggregate_daily / alert_dispatcher
  - upsert_results / cleanup_old 도 run_stage 로 래핑 (upsert 는 required=True)
  - 내부 try/except 의 logger.warning → logger.exception 으로 업그레이드
    (fetch_dark_history, gear collision event promotion, group polygon,
     gear correlation, pair detection, chat cache)
  - 스테이지 실패 시 journalctl -u kcg-ai-prediction 에서 stacktrace 로
    원인 바로 특정 가능 (기존은 "failed: X" 한 줄만 남아 디버깅 불가)

검증:
- python3 -c "import ast; ast.parse(...)" scheduler.py / stage_runner.py 통과
- run_stage smoke test (정상/실패 흡수/required 재raise 3가지) 통과

범위 밖 (후속):
- Phase 0-2 ILLEGAL_FISHING_PATTERN 전용 페이지 (다음 MR)
- Phase 0-3 Transshipment 전용 페이지 (다음 MR)
2026-04-17 11:28:30 +09:00
bae2dbde08 Merge pull request 'docs: prediction-analysis 신규 + 루트/SFR 문서 drift 해소' (#82) from feature/docs-refresh-2026-04-17 into develop 2026-04-17 11:22:41 +09:00
451f38036a docs: 릴리즈 노트 업데이트 2026-04-17 11:21:56 +09:00
b37e18d952 docs: prediction-analysis 신규 + 루트/SFR 문서 drift 해소
- docs/prediction-analysis.md 신설 — opus 4.7 독립 리뷰 기반 prediction 구조/방향 심층 분석
  (9개 섹션: 아키텍처·5분 사이클·17 알고리즘·4대 도메인 커버리지·6축 구조 평가·개선 제안 P1~P4·임계값 전수표)
- AGENTS.md / README.md — V001~V016→V030, Python 3.9→3.11+, 14→17 알고리즘 모듈
- docs/architecture.md — /gear-collision 라우트 추가 (26→27 보호 경로)
- docs/sfr-traceability.md — V029→V030, 48→51 테이블, SFR-10 에 GEAR_IDENTITY_COLLISION 추가
- docs/sfr-user-guide.md — 어구 정체성 충돌 페이지 섹션 신설
- docs/system-flow-guide.md — 노드 수 102→115, V030 manifest 미반영 경고
- backend/README.md — "Phase 2 예정" 상태 → 실제 운영 구성 + PR #79 hotfix 요구사항 전면 재작성
2026-04-17 11:20:53 +09:00
ddcb493160 Merge pull request 'docs: 릴리즈 노트 정리 (2026-04-17.4)' (#80) from release/2026-04-17.4 into develop 2026-04-17 07:42:57 +09:00
b0d9630dde docs: 릴리즈 노트 정리 (2026-04-17.4) 2026-04-17 07:42:44 +09:00
b1bd6e507a Merge pull request 'fix(backend): Spring 6.1 RestClient bean 모호성 기동 실패 해소' (#79) from hotfix/backend-parameters-flag into develop 2026-04-17 07:42:10 +09:00
f07d68b43f fix(backend): Spring 6.1 RestClient bean 모호성 기동 실패 해소
증상: rocky-211 의 kcg-ai-backend 가 `No qualifying bean of type RestClient,
but 2 were found: predictionRestClient, signalBatchRestClient` 로 기동 실패 반복.
PR #A 의 RestClientConfig 도입 이후 잠복해 있던 문제로, PredictionProxyController /
VesselAnalysisProxyController 의 필드 @Qualifier 가 Lombok `@RequiredArgsConstructor`
가 만든 constructor parameter 로 복사되지 않아 Spring 6.1 의 bean 이름 fallback 이
실패한 것.

- backend/pom.xml — default-compile / default-testCompile 의 configuration 에
  `<parameters>true</parameters>` 추가. spring-boot-starter-parent 기본값을 executions
  override 과정에서 덮어쓰지 않도록 명시.
- backend/src/main/java/lombok.config — `lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier`.
  Lombok 이 필드의 @Qualifier 를 생성된 constructor parameter 로 복사해야 Spring 이
  파라미터 레벨 annotation 으로 해당 bean 을 식별할 수 있음.

검증: javap 로 PredictionProxyController 생성자의 RuntimeVisibleParameterAnnotations 에
@Qualifier("predictionRestClient") 가 실제 복사되었는지 확인, 재빌드/재배포 후 rocky-211
기동 성공("Started KcgAiApplication in 7.333 seconds") + Tomcat 18080 정상 리스닝.
2026-04-17 07:40:57 +09:00
28be92047b Merge pull request 'docs: 릴리즈 노트 정리 (2026-04-17.3)' (#78) from release/2026-04-17.3 into develop 2026-04-17 07:35:23 +09:00
f92810b1b4 docs: 릴리즈 노트 정리 (2026-04-17.3) 2026-04-17 07:34:27 +09:00
b106113e47 Merge pull request 'docs: 절대 지침 섹션 추가 (develop 동기화 + design-system 준수)' (#76) from docs/claude-md-absolute-rules into develop 2026-04-17 07:29:28 +09:00
9a9388c37a docs: 릴리즈 노트 업데이트 2026-04-17 07:28:14 +09:00
48794e6962 docs: 절대 지침 섹션 추가 (develop 동기화 + design-system 준수) 2026-04-17 07:23:58 +09:00
485743c0e1 Merge pull request 'docs: 릴리즈 노트 정리 (2026-04-17.2)' (#74) from release/2026-04-17.2 into develop 2026-04-17 07:18:29 +09:00
ed48735310 docs: 릴리즈 노트 정리 (2026-04-17.2) 2026-04-17 07:18:19 +09:00
e0af0e089d Merge pull request 'feat(detection): GEAR_IDENTITY_COLLISION 탐지 패턴 추가 + docs 정비' (#73) from feature/gear-identity-collision into develop 2026-04-17 07:14:08 +09:00
a4e29629fc feat(detection): GEAR_IDENTITY_COLLISION 탐지 패턴 추가
동일 어구 이름이 서로 다른 MMSI 로 같은 5분 사이클에 동시 AIS 송출되는
공존 케이스를 신규 탐지 패턴으로 분리해 기록·분류한다. 부수 효과로
fleet_tracker.track_gear_identity 의 PK 충돌로 인한 사이클 실패도 해소.

Prediction
- algorithms/gear_identity.py: detect_gear_name_collisions + classify_severity
- fleet_tracker.py: 공존/교체 분기 분리, UPSERT helper, savepoint 점수 이전
- output/event_generator.py: run_gear_identity_collision_events 추가
- scheduler.py: track_gear_identity 직후 이벤트 승격 호출

Backend (domain/analysis)
- GearIdentityCollision 엔티티 + Repository(Specification+stats)
- GearIdentityCollisionService (@Transactional readOnly / @Auditable resolve)
- GearCollisionController /api/analysis/gear-collisions (list/stats/detail/resolve)
- GearCollisionResponse / StatsResponse / ResolveRequest (record)

DB
- V030__gear_identity_collision.sql: gear_identity_collisions 테이블
  + auth_perm_tree 엔트리(detection:gear-collision nav_sort=950) + 역할별 권한

Frontend
- shared/constants/gearCollisionStatuses.ts + catalogRegistry 등록
- services/gearCollisionApi.ts (list/stats/get/resolve)
- features/detection/GearCollisionDetection.tsx (PageContainer+Section+DataTable
  + 분류 액션 폼, design system SSOT 준수)
- componentRegistry + feature index + i18n detection.json / common.json(ko/en)
2026-04-17 06:53:12 +09:00
831045ace9 docs: 프로젝트 산출문서 2026-04-17 기준 정비
- docs/architecture.md: shared/components/ui 9개·i18n 네임스페이스 갱신
- docs/sfr-traceability.md: v3.0 전면 재작성 (운영 상태 기반 531 라인)
- docs/sfr-user-guide.md: 헤더 + SFR-01/02/09/10/11/12/13/17 구현 현황 갱신
- docs/data-sharing-analysis.md / next-refactoring.md / page-workflow.md: stale 3건 제거
2026-04-17 06:52:51 +09:00
760bceed32 Merge pull request 'docs: 릴리즈 노트 정리 (2026-04-17)' (#71) from release/2026-04-17 into develop 2026-04-17 05:38:19 +09:00
fe43f6b022 docs: 릴리즈 노트 정리 (2026-04-17) 2026-04-17 05:37:39 +09:00
38c97686fc Merge pull request 'refactor(design-system): 하드코딩 색상 라이트/다크 대응 + raw HTML → 공통 컴포넌트 치환' (#70) from refactor/design-system-ssot into develop 2026-04-16 17:10:10 +09:00
5731fa30a1 docs: 릴리즈 노트 업데이트 (PR #C 디자인시스템 정비) 2026-04-16 17:09:32 +09:00
c1cc36b134 refactor(design-system): 하드코딩 색상 라이트/다크 대응 + raw button/input 공통 컴포넌트 치환
30개 파일 전 영역에 동일한 패턴으로 SSOT 준수:

**StatBox 재설계 (2파일)**:
- RealGearGroups, RealVesselAnalysis 의 `color: string` prop 제거
- `intent: BadgeIntent` prop + `INTENT_TEXT_CLASS` 매핑 도입

**raw `<button>` → Button 컴포넌트 (다수)**:
- `bg-blue-600 hover:bg-blue-500 text-on-vivid ...` → `<Button variant="primary">`
- `bg-orange-600 ...` / `bg-green-600 ...` → `<Button variant="primary">`
- `bg-red-600 ...` → `<Button variant="destructive">`
- 아이콘 전용 → `<Button variant="ghost" aria-label=".." icon={...} />`
- detection/enforcement/admin/parent-inference/statistics/ai-operations/auth 전영역

**raw `<input>` → Input 컴포넌트**:
- parent-inference (ParentReview, ParentExclusion, LabelSession)
- admin (PermissionsPanel, UserRoleAssignDialog)
- ai-operations (AIAssistant)
- auth (LoginPage)

**raw `<select>` → Select 컴포넌트**:
- detection (RealGearGroups, RealVesselAnalysis, ChinaFishing)

**커스텀 탭 → TabBar/TabButton (segmented/underline)**:
- ChinaFishing: 모드 탭 + 선박 탭 + 통계 탭

**raw `<input type="checkbox">` → Checkbox**:
- GearDetection FilterCheckGroup

**하드코딩 Tailwind 색상 라이트/다크 쌍 변환 (전영역)**:
- `text-red-400` → `text-red-600 dark:text-red-400`
- `text-green-400` → `text-green-600 dark:text-green-400`
- blue/cyan/orange/yellow/purple/amber 동일 패턴
- `text-*-500` 아이콘도 `text-*-600 dark:text-*-500` 로 라이트 모드 대응
- 상태 dot (bg-red-500 animate-pulse 등)은 의도적 시각 구분이므로 유지

**에러 메시지 한글 → t('error.errorPrefix') 통일**:
- detection/parent-inference/admin 에서 `에러: {error}` 패턴 → `t('error.errorPrefix', { msg: error })`

**결과**: tsc 0 errors / eslint 0 errors (84 warnings 기존)
2026-04-16 17:09:14 +09:00
2c23049c8e Merge pull request 'refactor(i18n): alert/confirm/aria-label 하드코딩 한글 제거' (#69) from refactor/i18n-alert-aria-confirm into develop 2026-04-16 16:33:22 +09:00
03f2ea08db docs: 릴리즈 노트 업데이트 (PR #B i18n 정비) 2026-04-16 16:32:53 +09:00
8af693a2df refactor(i18n): alert/confirm/aria-label 하드코딩 한글 제거
공통 번역 리소스 확장:
- common.json 에 aria / error / dialog / success / message 네임스페이스 추가
- ko/en 양쪽 동일 구조 유지 (aria 36 키 + error 7 키 + dialog 4 키 + message 5 키)

alert/confirm 11건 → t() 치환:
- parent-inference: ParentReview / LabelSession / ParentExclusion
- admin: PermissionsPanel / UserRoleAssignDialog / AccessControl

aria-label 한글 40+건 → t() 치환:
- parent-inference (group_key/sub_cluster/정답 parent MMSI/스코프 필터 등)
- admin (역할 코드/이름, 알림 제목/내용, 시작일/종료일, 코드 검색, 대분류 필터, 수신 현황 기준일)
- detection (그룹 유형/해역 필터, 관심영역, 필터 설정/초기화, 멤버 수, 미니맵/재생 닫기)
- enforcement (확인/선박 상세/단속 등록/오탐 처리)
- vessel/statistics/ai-operations (조회 시작/종료 시각, 업로드 패널 닫기, 전송, 예시 URL 복사)
- 공통 컴포넌트 (SearchInput, NotificationBanner)

MainLayout 언어 토글:
- title 삼항분기 → t('message.switchToEnglish'/'switchToKorean')
- aria-label="페이지 내 검색" → t('aria.searchInPage')
- 토글 버튼 자체에 aria-label={t('aria.languageToggle')} 추가
2026-04-16 16:32:37 +09:00