trim을 clamp(±5%) 후 RateLimiter로 완만히 이동(rate≤1.0/min placeholder, 현장 calibrate). 과도/역전 시 trim→0 graceful. 49/49.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ColumnState UpperFrontBase/LowerFrontBase, 엔진 ApplyFront2Point(C=pivot temps[n-2], 느린 baseline 편차→중립 상태 정상/상승/하강)
- AdvisoryResult Upper/LowerFrontState·Metric + 컨트롤러 노출 + ff.js/css 표시
- 단위 3건(상/하 격리 perturb, metric 노출). 45/45. 2단계(trim)·3단계(조성base) 미구현
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- TI-6111D는 raw 환류온도(≤50°C)가 아니라 (상승 기상물+환류 비산액) 혼합으로 하부 대비 ~10°C 낮은 유효온도 → '오염' 폐기, 상부 front ΔT(C−D) 그대로 사용
- WP5 선행결정 확정: 조성=랩수동입력, clamp ±5%, role=LevelDriven유지(advisory만), 2-point front 부호 spec
- §10 D-제외는 '오염' 아닌 '환류 유량변동 민감 최대(이상탐지선 보수적 제외)'로 이유 정정
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- FeedforwardConfigStore: advisory_only를 GetBoolean(31)로 읽어 IndexOutOfRange (컬럼 31개=ordinal 0~30, advisory_only=30). 30으로 수정 → FF supervisor 루프 복구
- FeedforwardEngine.ApplyFront: front metric을 Delta(temps[0],temps[^1])=하단−상단으로 계산해 부호 반전(프론트 상승 시 trim 권고 역전). Delta(temps[^1],temps[0])=상단−하단으로 수정
- FeedforwardFrontTests: 엔진 경유 부호 회귀 테스트 2건 추가 (24/24 통과)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- FROM_at / TO_at / SUB_AREA 컬럼 추가 (헤더·행 렌더·추가행 입력란)
- SUB_AREA: tag_metadata upsert/delete로 직접 편집 가능 (빈 문자열 = 삭제)
- natural sort 수정: prefix 알파 → 숫자 정수값 → suffix 알파
(기존 TagNo.Length 기준 그루핑 제거 → TI-9217 다음 TI-10103 올바르게 정렬)
- 매핑 완료 시 태그명 badge 제거 → ✅ 버튼만 표시
- colgroup 퍼센트 비율로 컬럼 폭 고정 (table-layout:fixed)
- pid-table td/th overflow:hidden + text-overflow:ellipsis 적용
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- tagDcs backfill(Step-4)을 컬럼 존재 여부로 가드하여 최초 1회만 실행
- UpdatedAt EF 매핑 ValueGeneratedOnAddOrUpdate → ValueGeneratedOnAdd
- PropertyNameCaseInsensitive = true 추가
- PID 추출 결과 테이블에 '+ 추가' 버튼 및 빈 editable 행 (POST /api/pid)
- 태그번호 정렬: prefix → 길이 → case-insensitive natural sort
- 페이지네이션 표시 범위 ±3 → ±10
## 변경 내용
### pid.js — PREFIX 행 DCS 체크박스 완전 제거
- 각 prefix 행의 DCS 체크박스/토글 제거
- 그룹 섹션(DCS 태그 / 현장 계기) 자체가 DCS 여부를 명확히 표현
- 그룹 이동 필요 시: 삭제 후 반대 그룹에서 추가
- pidUpdatePrefixRule: tagDcs = 그룹(vcat)에서 결정, 행 입력 불필요
- isInstr 변수 제거 (미사용)
### PidExtractorService.cs — ClassifyTagClass 파라미터 정리
- 시그니처: (tagNo, category, tagDcs, hasExperionLink) → (category, tagDcs)
- tagNo: 새 로직에서 완전 미사용 → 제거
- hasExperionLink: tag_dcs 도입으로 역할 소멸 → 제거
- 3개 호출부 모두 갱신
- 로직: category=instrument이면 tagDcs→system/field, 그 외 null (2줄로 단순화)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## 변경 내용
### CATEGORY_META
- instrument → instrument_dcs / instrument_field 가상 키로 분할
- 각 가상 키에 dbCat/tagDcs 메타 추가 (DB에는 여전히 category='instrument')
- instrument 키는 장비 목록 배지용으로 유지
### CATEGORY_ORDER
- 'instrument' 제거 → 'instrument_dcs', 'instrument_field' 두 섹션으로 분리
### pidRefreshPrefixRules
- 그룹핑 로직: r.category==='instrument' → tagDcs로 분기
- 그룹 div에 data-vcat 속성 저장 (인덱스 기반 취약한 방식 제거)
- 추가 입력행: 그룹이 tagDcs 결정 → 별도 DCS 체크박스 없음
(placeholder도 그룹별 예시로 변경: FIC / FT / P-)
- 규칙 0건이어도 추가 입력행 항상 표시
- instrument 그룹 행: DCS 토글 표시 (체크 변경 후 수정 클릭 시 반대 그룹으로 이동)
- 비instrument 행: DCS 토글 없음
### pidResolveCat() 신규
- 가상 카테고리 키 → { category, tagDcs } 변환 헬퍼
### pidAddPrefixRule
- vcat 인자 사용, pidResolveCat()로 실제 DB 값 결정
- Add 행에 DCS 체크박스 없음 — 그룹이 결정
### pidUpdatePrefixRule
- data-vcat으로 그룹 인식 (기존 인덱스 기반 제거)
- instrument 행: DCS 토글 체크로 tagDcs 결정 (그룹 이동 가능)
- 비instrument 행: 그룹 기본값(false) 사용
## 결과
- DCS 태그 (FIC/TIC/PIC/LIC/FY/TY/PY/LY/FV/TV/PV/LV) 12건 별도 섹션
- 현장 계기 (FT/FCV/PSV/XV 등) 29건 별도 섹션
- 추가 시 자동으로 tagDcs 설정 — 혼동 없음
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## 변경 내용
### DB 스키마 (Boot DDL)
- pid_prefix_rules.tag_dcs BOOLEAN NOT NULL DEFAULT FALSE 추가
- DCS prefix 시드 마킹: FIC/TIC/PIC/LIC/FY/TY/PY/LY/FV/TV/PV/LV → tag_dcs=TRUE
- pid_equipment.tag_dcs BOOLEAN NOT NULL DEFAULT FALSE 추가
- 기존 행 backfill: instrument_type LIKE prefix% StartsWith 매칭 (FICQ/FICA 자동 포함)
### C# 도메인/서비스
- PidPrefixRule: TagDcs bool 프로퍼티 추가
- PidEquipment: TagDcs bool 프로퍼티 추가
- PidPrefixRuleDto (3개 record): TagDcs 추가
- PidExtractorService:
- ResolveTagDcsAsync() 신규 — StartsWith 매칭, 가장 긴 prefix 우선
- ClassifyTagClass() 재설계 — tagDcs 우선 (hasExperionLink 제거)
- 추출 저장 시 TagDcs 채우기
- ExportToExcelAsync() col18=DCS태그 추가 (col17=id 보호)
- ImportFromExcelAsync() col18 읽기 (hasDcsCol 감지)
- ApplyCategoriesToExistingAsync() 두 루프에 tag_dcs backfill 추가
- CreatePrefixRuleAsync/UpdatePrefixRuleAsync TagDcs 저장
### Web Controller
- PidController.GetPrefixRules: tagDcs: r.TagDcs 추가
### Web UI (pid.js)
- PREFIX 그룹 각 행에 DCS/현장 배지 + 체크박스
- Add/Update body에 tagDcs 전송
### MCP/LLM
- server.py: _DCS_PREFIXES frozenset 추가
- _classify_pid_tag(): tag_dcs 반환 필드 추가
- _DB_SCHEMA: pid_equipment 테이블 설명 추가
- upsert_pid_connection: tag_dcs 파라미터 + UPDATE/INSERT SQL 수정
- sql_prompt.py: pid_equipment 테이블 추가
- prompts/plant_context.md: tag_dcs 설명 + 쿼리 예시 추가
## 설계 결정
- FT 전송기는 Experion 연결 여부와 무관하게 현장 계기 (tag_dcs=FALSE)
- tag_dcs=TRUE: prefix rule이 ground truth → system 확정
- hasExperionLink는 TagClass 결정에서 제거 (연결 정보는 ExperionTagId FK로 보존)
- compound prefix (FICQ/FICA): LIKE StartsWith 매칭으로 자동 커버
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Program.cs: vLLM 클라이언트 포트 8001 → 8000 (현재 구동 모델과 일치)
- llmchat.js:
- paneInit에서 llm-type-select 초기값을 llmType(localStorage)으로 동기화 (HTML 기본값 ollama 보정)
- llmLoadModels(): vLLM 타입 시 llm-model.json 모델을 항상 드롭다운에 추가·선택 (갱신 버튼 포함)
- llmOnTypeChange(): async로 변경, await llmLoadModels() 후 llmLoadConfigToUI() 호출
- OllamaController.cs:
- 텍스트 도구 호출 감지: "params" 키 추가 (기존 parameters/arguments 에 params/args 병용)
- 배열 포맷 [{tool,params},{...}] 지원 — ExtractFirstJsonArray() 신규, 원소별 순차 실행 후 합산 결과 전달
- ExtractBalanced() 공통 메서드로 Object/Array 추출 로직 통합
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- GetRunBandsAsync: @area NULL 파라미터 타입 추론 실패(42P08) → @area::text 캐스트
- from/to UTC 정규화(ToUniversalTime)로 타임존 시프트 방지
- 검증: 동일 SQL bands 정상 반환, 연속 RUN은 next 이벤트 없으면 to까지 밴드
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 알람선(markLine HI/LO/SP)·운전음영(markArea RUN/TRIP)·듀얼커서Δ·자동집계/LTTB
- 슬롯 추가 절차, 기존 함수/엔드포인트/스키마, camelCase DTO 등 cold-start 자가완결
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- SuperviseAsync: catch(OperationCanceledException){break} 가 OPC SDK 연결 타임아웃
(TaskCanceledException=OCE 하위)을 '우리 취소'로 오인해 '중지됨'으로 영구정지되던
버그 수정 → when(ct.IsCancellationRequested) 가드, 그 외 OCE는 일반 오류처럼 재시도
- CreateSessionAsync: CancellationToken.None → 실제 토큰 전달
(죽은 서버 상대 세션생성이 SDK 기본 OperationTimeout ~2분 블로킹하던 원인 제거)
- 1회 연결 시도 10초 타임아웃(연결토큰 + WaitAsync 하드 백스톱)
- 재시도 주기 30s → 10s (리던던트 서버 전환 시 수분 단절도 빠르게 재포착)
- 라이브 검증: Experion kill→2.5분→revive 시 재연결 순환 유지 후 수동개입 0 자동 구독복구
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- ExportToExcelAsync: 17번째 컬럼 id(pid_equipment.id) 추가 (col1~16 위치 불변)
- ImportFromExcelAsync: id 우선 매칭 — id 있으면 그 행만 in-place UPDATE
(다중경로 보존), 빈 id면 INSERT, col17 헤더가 'id'가 아닌 옛 파일은 tag_no 폴백
- PidImportResult.RowsInserted 추가 + import 로그 신규건수 포함
- 구조설명-6-2차플랜트-byPBK.xlsx 문서규칙: upsert_pid_connection(9bcba0a) 연동
규칙으로 슬림화 (콤마=병렬 병합, 카테고리 매핑, 멱등/잠금/변경금지는 도구가 처리)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 웹UI-개선플랜-byQwen27B.md: app.js/index.html 분리 리팩토링 계획.
실코드 대조 감리 결과 §0.5 추가 — 치명 결함 3건(모듈레벨 상태/최상위
실행문 누락, 로더 기동 부재, async 파셜 배선 타이밍) 정정 및 정정 로더 포함
- 메타데이터업데이트/문서뷰어/커밋-브랜치정리 대화모음
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>