2026-08-06 11:29:00 +09:00

137 lines
8.2 KiB
Markdown

# 작업일지 — 2026-08-03
## 1. 하네스 점검 및 재구축
### 배경
`/harness` 로 기존 하네스 점검 요청. 감사 결과 **하네스 전체가 호출 불가 상태**였음.
### 발견된 결함과 조치
| # | 결함 | 조치 |
|---|---|---|
| D1 | `.ubisam_agent/` 는 Claude Code가 로딩하지 않는 경로 — 에이전트 3·스킬 4가 사장 | `.claude/` 로 `git mv`, `.gitignore` 에 `!.claude/agents/` 예외 추가 |
| D2 | `ubisam-deliverable` 이 참조하는 팀원 3명이 어디에도 없음 | `ubisam-analyst`·`ubisam-producer`·`ubisam-qa` 신규 작성 |
| D3 | `ubisam-deliverable` ↔ `ubisam-deliverables` 한 글자 차이로 트리거 충돌 | `ubisam-deliverable-rebuild` 로 리네임 + 4개 스킬 상호 경계표 |
| D4 | CLAUDE.md 하네스 포인터 불완전 | 라우팅표 + `docs/harness-ubisam.md` 신규 |
| D5 | `TeamCreate`/`TeamDelete` 는 이 환경에 **없는 도구** | `Agent`+`SendMessage`+`TaskCreate` 로 교체 |
| D6 | `CLAUDE.md` 의 `@import X` 는 잘못된 문법 — **규약 문서 5건이 세션에 로딩되지 않고 있었음** | `@X` 로 정정 |
| D7 | `set PYTHONUTF8=1 &&` 는 bash에서 무효(`PYTHONUTF8=None`, stdout cp949) | `PYTHONUTF8=1 py` 접두형으로 9건 정정 |
| D8 | `ubisam-ppt-make` description이 `#4A8DCB` 의 `#` 때문에 **YAML 주석으로 파싱돼 "blue"에서 절단** | `>-` 블록 스칼라로 전환 |
| D9 | `build_02설계_xlsx.py` 가 `os.makedirs` 부재로 4종 전부 `FileNotFoundError` | 4개 저장 지점에 추가 (실행으로 4/4 생성 확인) |
### 소스와 어긋나 있던 하네스 기술
2026-06-18 리네임·마이그레이션이 하네스에 반영되지 않아 **없는 파일·심볼**을 진실원으로 지목하고 있었음.
| 하네스 기술 | 실제 |
|---|---|
| `SeqAutoRunPrismaticScanner.cs` | `SeqAutoRunPrismatic.cs` |
| `PAIX_PrismaticScanner.cs` | `Device/IO/PAIX_PTOP.cs` |
| `PLCController.Config.cs` | `PLCContoller.Config.cs` (**저장소 오탈자**) |
| `Views/Recipe|Manual|Monitoring/` | `Views/` 하위는 `Main`·`Model` 둘뿐 (나머지는 공유 컴포넌트, `EquipmentSetup.cs` 등록부) |
| "네임스페이스는 `ILSOS_PrismaticScanner`" | `ILSOS_PrismaticRD_PTOP.*` — 옛 이름 **0건** |
| `MotorIds` | 없음 (`DeviceIds`/`SequenceIds`/`SettingIds`/`StreamMessageNames`) |
| `PAGE_VERIFY_DELAY_MS`·`WELD_START_DELAY_MS` | 소스에 **0건** |
| `PLC_HEAVY_ALARM_STATUS` 처리 = `SeqAutoRunPTOP.cs` | 정의는 `PLCController.Address.cs:20`, **처리는 `SeqAlarmMonitor.cs:199`** |
| `#if SIMULATION` 조건부 컴파일 | **0건.** 시뮬은 런타임 `isSimul` 플래그. `Simulation\|x64` 는 `ILSOS_All.sln:413-416` 에서 `Release\|x64` 매핑 |
| pptx 캔버스 배경 `BG_SOFT` | `build_deck.py:55-73` 은 `WHITE` (`BG_SOFT` 는 패널·표 fill 전용) |
> **동명 심볼 함정** (하네스에 명시): 공유 클래스 `WeldingCommon.Devices.Laser.PAIX_PrismaticScanner` 와
> `WeldingComponents/.../PLCController.Config.cs`(오탈자 없음)는 **개명되지 않고 그대로 존재**한다.
> 머신 쪽과 혼동하면 안 됨. `SeqTestRun.cs:32` 가 공유 쪽을 참조.
### 환각 방지 설계
보고서 템플릿에 실측인 척하는 수치(빌드 45s/60s, `T+50ms`, PLC `M10`)가 박혀 있어 에이전트가 복사할
위험이 있었음 → 전부 플레이스홀더 + `미측정`/`불명확 — 확인 필요` 표기 규칙으로 교체.
`ubisam-format-map` 에는 **타 프로젝트 값**(`LGIT_구미_FMM`, PL명, 계약일)이 "이 프로젝트 고정값"으로
박혀 있었음 — 잔재 소탕이 목적인 하네스가 스스로 잔재를 공급하고 검증가가 정답으로 대조하는 구조라 삭제.
`M70000`/`D70000` 계열 PLC 주소는 `.cs` 소스에 **0건**이고 근거 분석 문서 2건이 서로 다르게 기술 →
빌드 스크립트 출력에 `(제안)` 부착 + 재확인 경고 삽입.
### 채점 (서브에이전트 2인 독립, 6라운드)
| 라운드 | 감사관 | 드라이런 |
|---|---|---|
| 1 | 64 | 45 |
| 2 | 73 | 68 |
| 3 | 72 | 72 |
| 4 | 78 | 76 |
| 5 | 77 | 76 |
| 6 | 79 | 80 |
최종 상태: 에이전트 6 / 스킬 11, dead link 0, frontmatter 절단 0, 200줄 초과 0,
CI YAML 파싱 OK, 빌드 스크립트 4종 컴파일·실행 OK.
---
## 2. Serena 제거
`rules.md` #3("코드 분석은 serena를 통해서")과 `.ubisam_agent/settings.json` 의 serena 플러그인
등록이 이미 제거된 상태여서, 남아 있던 `.serena/` 폴더(47MB)를 정리함.
### 보관 가치가 있던 설정 (폴더 삭제 전 기록)
`memories/` 폴더는 없었고 직접 작성한 메모도 없음. `project.yml` 은 전부 기본값이며
**프로젝트 고유 설정은 아래 3개뿐**이다. 나중에 Serena를 다시 도입하면 이 값만 넣으면 된다.
```yaml
project_name: "LGES-OC5-PtoP-Welder"
language_servers:
- csharp # C# 프로젝트이므로
ls_workspace_folders:
- . # 저장소 루트 전체 인덱싱
```
- `encoding: utf-8`, `ignore_all_files_in_gitignore: true` 등 나머지는 Serena 기본값 그대로였음.
- `project.local.yml` 은 주석만 있는 빈 파일.
- `cache/csharp/*.pkl`(47MB, 2026-06-26 생성)은 재생성 가능한 파생물이라 보관 불필요.
- `.serena/` 는 `.gitignore:43` 으로 추적 제외 상태였으므로 삭제해도 git 이력에 영향 없음.
---
## 3. Laser Recipe Save 교차 오염 분석 (17:38~17:48)
> 이 절은 2026-08-04에 소급 기록했다. 당일 산출물은 있으나 일지 누락 상태였음.
### 증상
Laser Recipe를 Save하면 **어쩌다 한 번씩** Active 레시피의 Page·Param이 현재 선택된 레시피에
덮어써진다. 저장 경로 `D:\ILSOSConfig\ILSOS_PrismaticRD_PTOP\_config_recipe`.
### 디스크 증거 (확정)
`_config_recipe` 전수 해시 대조 — `U_Frame_Welding` 과 `U_Frame_Back_Welding` 의
`TeachingEditor.json`·`FieldHelper.json` 이 **바이트 단위 동일**(703,563 B, 08-01 19:34:11 / 19:34:36,
25초 간격). backup 판본은 서로 달라 **원래는 별개 레시피였다.**
### 근본 원인
저장 **대상**(경로)과 저장 **내용**(전역 싱글톤)이 별개이고 둘을 묶는 불변식이 없다.
| 역할 | 실체 |
|---|---|
| 내용 | `LASA/GUI/DB/Dao.cs:7` `static RecipeWeldingLines WeldingLinesRecipe` |
| Page | `LASA/GUI/DB/RecipeFieldScan.cs:18-22` `Instance` |
| 대상 | `WeldingCommon/Utils/RecipeHelper.cs:18` `static SelectedRecipe` |
`MainPage.SaveRecipe(fullpath)`(`MainPage.cs:425-434`)는 전역 메모리를 지정 경로에 덤프할 뿐
신원을 확인하지 않는다. 확인 수단(`DB.Dao.SystemRecipe.WorkRecipeFile`)은 이미 있는데 조회조차 안 한다.
`UCScannerObjectTeachingViewModel.OnSaved(id, recipeName)`(`:202`)은 **인자를 버리고** static을 쓴다.
### 살아있는 발생 경로
1. **정상 경로의 부분 실패(최유력)** — `RecipeHelper.cs:76-78`·`UCScanner…VM.cs:165-166`·`:172-173`
셋 다 대상을 먼저 바꾸고 내용을 나중에 로드(비원자적). `ReloadRecipe` 가 throw 하거나
**무예외 무동작**(`Recipe.cs:64`)이면 desync가 남고 다음 Save가 교차 복사.
2. **PLC 전환 시 역방향 오염** — `UCScanner…VM.cs:155-156` 이 1홉 시점에 저장, 메모리 갱신은 2홉 뒤.
3. 신규 레시피 생성 시 메모리 미갱신 저장 (`UCScanner…VM.cs:114-115`).
### 반증된 가설 (`ptop-developer` 적대적 교차검증)
- `RMSHandlerForPTOP` 원인설 → **REFUTED.** `RegisterRmsHandler` 호출은 `EquipmentSetup.cs:95-97`
3줄뿐이며 **전부 주석**. 죽은 코드다.
- "PLC Word 읽기로 메모리에 Active가 남는다" 인과 → **REFUTED.** `SeqAutoRunPTOP.cs:346-425`는
`OnActiveReloaded()`로 대상·내용을 함께 갱신한다.
- `EquipmentSetup.cs:282` `RollbackRecipe()` 주석 해제 → **의미론적 no-op.** 백업 필드가 0건이라
되돌릴 원본이 없다.
### 산출물
- `docs/분석/2026/08/03/173852_Laser_Recipe_Save_교차오염_분석.md` (본문)
- `docs/분석/2026/08/03/173852_Laser_Recipe_Save_교차오염_부록.md` (desync 전수표·검증 이력)
- `작업지시서_2026-08-03_Laser_Recipe_Save_교차오염.txt` (바탕화면 — 4단계 적용 절차·검증 시나리오)
**상태: 소스 미수정.** 전 조치가 `WeldingComponents/` 하위라 사전 승인 필요 (`rules.md` #2).