korace (구 cmods7) — 임베디드 특수주문 제작 관리 (handoff)
프로젝트 폴더 =
C:\dev\korace(26.8.7 개명, 구C:\dev\cmods7) · 계획서 전문 =C:\dev\korace\PLAN.md. 여기엔 상태만 둔다.
NOW (26.8.7 — korace 승격)
- 26.8.7 [페페] 지시 = 「프로젝트로 생성하고 이름은 korace. cmod s7 을 흡수한다」 + 5항목(①통합 관리 첫페이지 ②업체·업체별 프로젝트·기판 라이브러리 ③PFS 는 구조만 빌리고 색·UI 컨셉은 현재 유지 ④기판 라이브러리 100개 미만·카테고리/제조사/기능 필터·평균단가·신뢰도 점수·부속(BT·랜) 포함 ⑤기능 선택 → 조건(가성비/신뢰도) → 복수 추천 + 축별 점수). 울트라코드·에이전트 수집 지시.
- 그릴링 확정 7건 = 범위 FPGA+MCU+SBC+부속 전부 · 이름 korace · 업체 = 고객사 + 외주 협력업체(PCB·조립·케이스) · 추천 끝점 = 견적서 출력까지 · 추천 엔진 = 결정론 가중치 점수(LLM 0) · 화면 = 좌측 고정 메뉴 + 본문 · 부자재 12종 전부 채택.
- ✅폴더 개명 완료 + 회귀 전량 통과 — db 7 · toolchain 9 · device 15 · server 13 · UI 31 = 75 OK / 0 FAIL, 기기
up_to_date=True(빌드 FA·롬 E6F9·20칸). 예약작업cmods7_app→korace_app, HKCU Run 키도 교체. - 🔴개명 중 파일 5개 소실(코디 사고) — 상세·재발방지는 아래 「26.8.7 사고」 절.
- ✅부품 1차 수집 완료 = 에이전트 11 · 98개 / 8카테고리(FPGA보드12·MCU보드15·SBC8·무선12·유선12·LED디스플레이14·전원구동13·센서기타12), 감사 3종(가격 교차검증·누락중복·점수 일관성) 통과. 원본 = 세션 scratchpad
parts/*.json→ koracedata/로 옮기는 것이 다음 작업. - ✅앱 확장 — 서버·엔진·데이터 완료. 부품 107개(기판·모듈 95 + 부자재 12, 성능·내구성 점수 107/107) →
data/parts.json단일 출처. 신규 =parts.py(카탈로그·필터·결정론 추천 4축) ·quote.py(BOM·견적·스냅샷) ·db.py(+customer.kind·project.status·bom·quote, 멱등 마이그레이션) ·server.pyAPI 20여 개 ·static/index.html(좌측 메뉴 쉘) +ui/util.js. 첫 페이지 = 통합 관리, 벤치는/bench로 이동(벤치 UI 31 OK 그대로). - 🔑데이터 함정 3건 = ①태그
WiFi1건이WIFI12건과 다른 축으로 갈려 필터가 1건만 잡았다 → merge 에서 대문자 정규화 ②같은 부품이 파일마다 다른 id(ESP32 3종) → 명시 별칭으로 접음(이름 유사도 자동판정은 우노 R3/R4 를 오인한다) ③sim7600functions 공란. - 🔑추천 설계 = 가성비는 후보군 안에서만 뜻이 있어 그 조회의 최고를 100 으로 편다 · 단가를 모르면 0 으로 때리지 않고 축을 빼고 재정규화한다(0 으로 때리면 "비싸서"와 "몰라서"가 화면에서 구분이 안 된다) · 한 부품이 여러 기능을 덮으면
covers로 알려준다. - 검증 = merge 11 · parts 26 · quote 23 · db 12 · server 44(13→44 확장) · 벤치 UI 31 = 147 OK / 0 FAIL.
- ✅devplan 허브 등록 완료(페페 지시). 신규 페이지
devplan/korace.html(dwgcompare 골격 재사용 = 쉘·테마 규약 자동 충족) +projects.json카드(catapp·statusactive·sitehttp://127.0.0.1:8815/) +project_state.json(stage 3 실행·round 1·approval approved). ⚠project_state.py set은 기존 항목만 고친다 — 신규는 JSON 에 직접 넣고check로 통과시켜야 한다(approval 은approved|waiting|hold|done|standing만 받는다). 검증 = 게이트check_themeFAIL 0(65) ·check_fontFAIL 0 ·project_state check41건 통과 ·build_hubOK · 실브라우저 신설_check_korace_card.py11 OK/0 FAIL(허브 3개소 노출 = 최근목록·진행판 이름·진행판 보고 / 콘솔 0 · 13px 미만 0 · 가로스크롤 0) + 캡처 육안 2장. - ✅화면 6종 완성(대시보드·업체·프로젝트·견적·기판 라이브러리·부품 추천) — 에이전트 6 병렬 + 검증 2. 모듈은
static/ui/<id>.js가{title, render(el)}만 내보내면 붙는다(동적 import·라이브러리 0). 화면 추가 = 메뉴 배열 1줄 + 파일 1개. - 🔴검증 2단이 실제로 잡은 것 = 화면 사이가 끊겨 있었다. 견적 화면이 「기판 라이브러리에서 담기」로 보내는데 라이브러리엔 담기 버튼이 없었다(각 화면은 저마다 자체검사를 통과했다 — 화면 하나가 도는 것과 화면 사이가 이어지는 것은 다른 문제다). →
library.js상세 모달에+ 부품표에 담기이식(프로젝트가 안 정해졌으면 버튼을 아예 안 띄우고 뭘 하면 되는지 적는다 — 눌러보고 실패하게 두지 않는다) + 신설tools/check_flow.py가 그 흐름을 지킨다. - API 계약 대조 = 호출 29건 전부 일치(경로·메서드·필드명·sessionStorage 열쇠·금액 재계산 0) → 고칠 것 없음.
- ⚠병렬 작업 함정 2건 = ①에이전트들이 공유
catalog.db에 동시에 테스트 데이터를 쓰고 지워 서로 것을 날렸다(각자 원상복구는 했다) ②Playwright 공유 프로필(C:\dev\pw-chrome-profile)을 서로 점유해 몇몇은 실브라우저 검증을 못 하고 격리 인스턴스로 우회했다 → 다음엔 화면 에이전트에 격리 크로미움을 처음부터 지시. - ✅회귀 러너 한 줄 =
PYTHONUTF8=1 python tools/check_all.py(--fast면 브라우저 검사 제외). 합계 226 OK / 0 FAIL = merge 11 · db 12 · parts 26 · quote 23 · toolchain 9 · device 8 · server 44 · 벤치 UI 31 · hub 화면 47 · 통합 흐름 15. - 계획서 전문 =
C:\dev\korace\PLAN.md§10 · 소개 페이지 = devplan/korace.html. - 🆕26.8.8 [페페] 지시 = 「견적·부품리스트 다음에 기판 설계 페이지가 없다. 부품별 기판 그림과 기본적인 기능 추가가 들어간 설계 프로그램」 → 계획서
PLAN.md§11. - 그릴링 확정 7건 = 깊이 핀 단위 결선도 · 그림 실제 외형 비례 · 기능 4가지 전부(카탈로그 밖 부품 얹기·표준 블록 자동 제안·펌웨어 동작 지정·설계→BOM 역갱신) · 산출물 결선표+블록도 PNG · 그림은 파라메트릭 생성 · 핀 데이터는 자동 소스 있는 것 전부 먼저 · 나중에 팔 수도 있다 → CC-BY-SA 자산 배제.
- 🔴조사(5축+적대검증)가 판정을 뒤집었다. 원 조사 「wokwi-elements 15~20개 매칭」 → 적대검증 실측 13개, 품목의 절반이 허구(Pico·ESP32-S3/C3·ESP8266·STM32·릴레이모듈·A4988·MAX7219 element 자체가 없다, GitHub API 로 165파일 전수 대조). 게다가
lit이 정규 의존성이라 「SVG 만 발췌」는 부품당 수 시간 리버스엔지니어링. 결정타 = 우리가 돈 버는 카테고리(민웰 SMPS·DIN레일·DMX·픽셀컨트롤러·HUB75·SSR·안전절연 20여 개) 커버율 0% — 오픈소스가 덮는 건 취미보드뿐이다. 덤 = pinout.xyz 는 NC 아님(issue #481 로 CC-BY-SA 전환) · litegraph.js 가 후보 중 제일 깨끗(단일파일·의존성 0·MIT). - 🔑그래서 그림을 모으지 않고 데이터로 그린다(파라메트릭) — 부품마다
body(치수)·headers(핀헤더 줄)·blocks(USB·나사단자 등 표식)·pins(번호·이름·종류·전압)를 숫자로 넣으면 코드가 SVG 를 그린다. 비용이 「그림 그리기」→「치수 몇 개+핀 목록」으로 내려가고, 오픈소스에 없는 부품도 똑같이 그려지며, 축척·선굵기가 일관되고, 외부 자산 0 이라 라이선스 오염도 0. - ✅스키마·검증기
app/pins.py완성(pins selftest: 14 OK / 0 FAIL) —data/pins/<part_id>.json부품당 1파일, 없으면 화면이 「핀 미등록」으로 정직하게 표시. 전원 핀은 전압 필수(24V 계통에 5V 모듈 물리는 사고를 이걸로 잡는다) · 출처(source) 없는 데이터는 저장 거부 · 위반은 한꺼번에 모아서 돌려준다. - ✅핀 데이터 수집 완료(26.8.8) = 72/107 부품 · 1582핀 · 규격 위반 0 · 건너뜀 35(데이터시트에서 핀 배열을 못 찾은 것 — 모르면 만들지 마라 지시대로 안 만들었다. 화면이 「핀 미등록」으로 표시하고 블록 수준 연결만 허용한다). 미등록 = Arty A7 2종·Zybo·ESP32-C3·ESP8266·STM32 Blue Pill·오렌지보드·nRF52840-DK·W7500·Odroid-M2·Orange Pi 5B·LattePanda·CC2530·SIM7600·NB-IoT·PoE스플리터·MAX3232·ADUM3160·WS2812B/APA102 스트립 등.
- 🔴감사가 내 검증기 구멍을 짚었다 —
validate()가 헤더 자리 「넘침」만 보고 「모자람」을 안 봤다. 모자란 쪽이 더 위험하다(빈칸 뒤 핀이 통째로 한 칸씩 밀려 엉뚱한 핀에 선을 긋는다). 실제로 nRF52840 동글·DE10-Nano 에서 잡혔다 → 규칙 5개 추가(자리 수 일치·idx 중복·idx 범위·없는 헤더 참조·헤더도 좌표도 없는 핀),pins selftest14→20 OK. 강화 직후 실데이터 72개는 전부 통과했고, 대신 내 테스트의 임시 부품이 걸렸다(핀에 좌표가 없어 그릴 자리가 없었다 — 검증기가 제 몫을 했다). - 적대검증 = 표본 16개를 제조사 1차 PDF 로 재대조(WebFetch 요약이 표를 뭉개면
pypdf/pdfplumber로 직접 파싱). 핀 순서 뒤집힘 0 · 치수 날조 0 · 전압 오기 0 · 출처 날조 0. RS485 자동방향 모듈의 SC 핀 누락 1건만 보강. ⚠나머지 56개는 미검증(표본만) — 의심되면 같은 방식으로 추가 검증. - CC-BY-SA 출처 스캔 = 16개 파일이 Fritzing/pinout.xyz 를 언급했지만 전부 「안 썼다」는 배제 문구였다. 실제 사용 0건.
- 🔴감사가 내 검증기 구멍을 짚었다 —
- ~~진행 중 = 핀 데이터 수집~~ — 26.8.8 기준 72개 부품 · 1580핀 등록 · 규격 위반 0(아두이노 3종·ESP32 2종·Basys3·Cmod S7·Jetson·HUB75·민웰 MDR-60-24·Colorlight 5A-75B·L298N·BTS7960·DS3231 …). 🔑오픈소스에 그림이 없다던 민웰 SMPS·HUB75·Colorlight 가 실제로 들어왔다 = 데이터시트에서 치수·단자를 뽑는 방식이 통한다는 실증. 지시 = 모르면 만들지 마라(추측 치수·핀은 최악 — 화면이 「등록됨」으로 보여주고 사람이 믿고 배선한다) · CC-BY-SA 출처 금지(Fritzing·SparkFun·pinout.xyz·KiCad 공식 라이브러리).
- ✅P1 서버측 완료(26.8.8) — 신규
app/pins.py(기하·핀 스키마+검증, 14 OK) ·app/design.py(배치·배선·검사·결선표·BOM 되밀기, 29 OK) ·db.py+3표(design/design_node/design_wire, 14 OK) ·server.py설계 API 16개(61 OK, 13→44→61). 합계 195 OK / 0 FAIL(tools/check_all.py --fast).- 🔑전압 경고가 이 화면의 존재 이유 — 24V→5V 직결·전원 출력끼리 물림·신호핀에 고전압·로직 레벨 불일치를 그 자리에서 잡고, 고치는 법(강압/절연/레벨시프터)까지 적어준다. 막지는 않는다(사람이 알고 하는 예외가 늘 있다) — bad/warn/info 로 나눌 뿐.
- 🔑
suggest()가 그 경고를 부품으로 푼다 — 모아둔 부자재 12종(DCDC·ISOLATION·LEVEL_SHIFT·SAFETY·SURGE)이 여기서 값을 한다. - 🔑결선표는 서버가 만든다(견적 금액과 같은 이유). 넷(GND·+24V)은 from-to 를 억지로 만들지 않고 「그 넷에 붙은 핀 목록」으로 낸다 — 억지 from-to 는 실제 배선과 달라진다. 관례색(GND=검정·전원=빨강·AC=갈색) 자동.
- 🔑BOM 되밀기는 제안이지 덮어쓰기가 아니다 — 부품표 수량이 설계보다 많으면 줄이자고 안 한다(사람이 손으로 고친 값이다).
apply_to_bom(add_ids=…)로 고른 것만 반영. - 부품을 지우면 그 배선도 같이 지운다(남기면 어디에도 안 닿는 유령선) · 같은 연결은 방향만 바꿔도 두 번 안 들어간다 · 도면기호는 카테고리로 접두를 고른다(PS1=전원·U1=MCU·TB=단자대).
- 회귀 =
PYTHONUTF8=1 python tools/check_all.py --fast→ 202 OK / 0 FAIL(merge 11·db 14·parts 26·quote 23·pins 20·design 29·toolchain 9·device 8·server 62). 브라우저 포함하면--fast빼고(벤치 UI 31·hub 47·흐름 15 추가).
- ✅P1 화면 6개 완료(26.8.8) — 신규
ui/svgpart.js(파라메트릭 렌더러·기하 계산) ·ui/design.js(캔버스·배선·검사/제안·결선표·산출물·되밀기) ·ui/pins.js(핀 등록 편집기) + 메뉴 「설계」 그룹 2줄. 서버 코드 0줄 변경(API 가 이미 다 있었다).- ①렌더러 =
body+headers+blocks+pins→ SVG. 🔑글자만 배율의 역수로 그린다 — 확대·축소해도 이름표가 항상 13px(mm 로 그리면 축소할 때 글자가 먼저 사라진다). 핀 색이 곧 전기적 의미(전원 빨강·GND 검정·통신 파랑). - ②캔버스 = 휠 확대·빈 곳 끌기 이동·부품 끌기 배치(놓을 때만 PATCH)·90° 회전. 🔑회전축은 부품 중심 — 모서리를 축으로 돌리면 90° 누를 때마다 부품이 화면 밖으로 달아난다. 10mm 격자.
- ③핀 클릭 2단계 배선 = 핀 클릭 → 핀 클릭. 핀에 투명 큰 원을 겹쳐 클릭 판정(점은 0.6mm 라 못 누른다), 그 원이
pointerdown전파를 끊어 드래그와 안 부딪힌다. 넷은 GND·+5V·+3V3·+12V·+24V 빠른 버튼 + 직접 입력. - ④검사·제안 패널 = 서버
check/suggest를 그대로 그린다(위험/주의/알림 + 고치는 법) → [설계에 놓기] 한 번으로 강압·절연·레벨시프터가 도면에 들어온다. - ⑤산출물 = 결선표 인쇄(전용 iframe · A4 가로) · CSV(엑셀용 BOM 붙임) · 블록도 PNG(SVG 직렬화 → 이미지 → 캔버스 2배, 외부 라이브러리 0 · 10mm 눈금자 포함).
- ⑥핀 등록 = 부품 목록(미등록/등록됨/전체·검색) → 편집기(치수·로직전압·출처·헤더 줄·블록·핀 표 + 실시간 미리보기). 저장은 서버가 검증하고 위반을 전부 목록으로 돌려준다. 「헤더에 자동배치」로 idx 재정렬.
- 🔴저장이 조용히 데이터를 지울 뻔했다 — 화면이 안 쓰는 필드(
desc323건·블록label14건)를 새 문서로 다시 만들면서 날리는 구조였다 → 모르는 필드는 그대로 실어 보낸다. 숫자칸을 비우면 0 이 아니라 필드째 뺀다(0 은 「헤더 0번」·「좌표 0mm」라는 다른 뜻이다). - 🔴표 줄 클릭 + 줄 안 버튼 클릭이 겹쳐 편집기가 두 번 열렸다(저장 버튼이 2개로 보임) → 줄 안 버튼에서
stopPropagation. - 검증 = 신설
tools/check_design.py53 OK(캔버스에서 실제로 핀을 클릭해 잇고 → 24V→5V 경고 확인 → 제안 부품 놓기 → 넷 → 결선표·CSV·PNG 을 내려받아 픽셀로 백지 아님 확인 → 되밀기 반영 → 핀 등록 저장·규격 위반 표시, 끝에 전량 원상복구) +check_hub.py에 2화면 추가(47→61). 합계 362 OK / 0 FAIL. - 🔑13px 규칙을 SVG 에 그대로 적용하면 뜻이 없다 — SVG 글자는 px 가 아니라 사용자 단위다. 그래서 hub 검사는
svg안을 빼고, 설계 검사가 viewBox 배율을 곱해 화면 실제 px 로 잰다(≥13 확인).
- ①렌더러 =
- ✅실물 사진 107/107 + 핀 72→99 + 「사진 판독」 표시(26.8.8) — 페페 지시 「핀등록 안 된 부품은 사진 확보→구조 파악→SVG, 사진으로 그린 건 별도 표시, 등록 끝난 것까지 기기 사진 첨부해 SVG 와 대조 가능하게」. 페페 택1 = 사진은 로컬 참조 전용(출처 기록) · 수집은 에이전트 병렬.
- 신규 =
app/photos.py(사진 자산·출처 강제, 12 OK) ·tools/fetch_photo.py(수집 단일 창구) ·tools/audit_photos.py(28 OK) ·pins.pyevidence필드(23 OK) · 서버 사진 API 3개 · 화면(핀 등록 편집기 위 사진/아래 SVG · 라이브러리 상세 · 설계 선택패널). - 🔑「사진 판독」이 세 곳에 따라붙는다 — 목록 배지 · 캔버스 점선 테두리 · 결선표·인쇄본 경고문("배선 전에 실물 실크스크린과 대조"). 현장에 나가는 종이까지 가야 뜻이 있다.
- 🔑출처 없는 자산은 저장 거부(사진
source+credit/ 핀photo_note). ⚠라이선스 = 제조사·판매처 사진은 남의 저작물 → 판매·배포 패키지에서data/photos/통째 제외(data/photos/README.md에 박아둠, 사진 없어도 앱은 돈다). - 결과 = 사진 107/107(37MB) · 핀 99/107 · 2,123핀(72→+27) · 근거 데이터시트 78 / 혼합 17 / 사진 4. 미등록 8은 일부러 안 만들었다 — ODROID-M2·Orange Pi 5B(핀맵 미공개/위키가 CC-BY-SA) · LattePanda Mu·SIM7600(SO-DIMM·M.2 골드핑거라 표현할 접점 없음) · ESP32-C3 SuperMini(리비전마다 핀배치 다름) · 페라이트코어·전선·케이스(접점 자체가 없음).
- 🔴「다른 부품 사진」 함정이 실제로 3번 걸렸다 — TXS0108E(일반 클론↔SparkFun 정품) · STM32 Blue Pill(보드가 아니라 칩 단품 클로즈업) · DMX512(제조사 로고 이미지). 셋 다 에이전트가 눈으로 다시 보고 잡았다. 그래서 감사에 지문(sha256) 중복 검사를 넣었다 — 같은 이미지가 두 부품에 붙으면 둘 중 하나는 남의 사진이다.
- 🔴cody-vision 이 로고 이미지를 놓고 「MAX485·XLR·핀헤더가 보인다」고 좌표까지 붙여 환각했다(배치6). vision 결과는 사람이 한 번 더 봐야 한다 — 특히 "무엇이 보이나"가 아니라 "이게 그 부품이 맞나"는 vision 에 맡기면 안 된다.
- 검증 =
check_all.py418 OK / 0 FAIL(설계 화면 53→61, 사진 감사 28 신설). 감사가 실제로 잡은 것 = 너무 작은 사진 3건(224px·240px·200px → 재수집으로 해소). - ✅UI 3건 + 🔴외부 공개(26.8.8 페페 지시) — ①좌측 메뉴 그룹 이름 굵게(13px·ink 100%) ②벤치에서 돌아갈 길이 없었다 →
/bench좌상단 「← 홈」 버튼(벤치는 통합관리 밖 별도 페이지라 뒤로가기 말곤 길이 없었다) ③qahelper 버튼(42px + right 14px)이 「기기 없음」 배지를 덮었다 → 두 화면 header 에padding-right:68px(겹침 0 실측). - 🔴Tailscale Funnel 공개 =
https://poin-mini.tailc5d3c1.ts.net:8443/(페페 지시)./는 8788 이 이미 쓰고 korace 는 절대경로(/api/…)라 서브패스로 붙이면 깨진다 → 별도 포트 8443 루트로 올렸다(기존 funnel 경로 6개 무영향). - ⚠인증이 없다. 주소를 아는 누구나 업체·프로젝트·견적·설계를 읽고 고칠 수 있고
/api/build·/api/flash(기기에 롬 굽기)까지 부를 수 있다(굽기는confirm플래그만 요구). 육안 끝나면tailscale funnel --https=8443 off로 내리거나, 계속 열어둘 거면 인증 게이트가 먼저다. → ⏳페페 결정. - ✅프로젝트 시드 복원(26.8.8) — 26.8.7 폴더만
cmods7→korace로 바뀌고 user_brief 시드는projects/cmods7/에 남아 있었다 →git mv로projects/korace/이관(3파일 스냅샷 대조 = 소실 0) +docs_manifest.jsonid·project·title 갱신 +BRIEF.cmods7.md삭제 →BRIEF.korace.md재생성, manifest 238건 검증 통과. - 🔴낡은 상주 프로세스 함정(26.8.8) — 8815 에 떠 있던
pythonw는 26.8.7 23:02 기동분이라 그날 밤 추가된 설계 API 가 없었다(/api/pins404). 화면 JS 는 디스크에서 매번 읽지만 서버 코드는 재시작해야 반영된다 → 서버 파일을 고친 날은 상주 프로세스 기동시각을 먼저 본다(psutil.Process(pid).create_time()). - ⏳페페 몫 = 육안 1회(
http://127.0.0.1:8815/#design— 부품 끌어 배치·핀 클릭 배선·인쇄 미리보기는 헤드리스로 못 본다) + 판단 2건: ①devplan 카테고리를 「데스크톱·앱」 → 「가구·제조」 축으로 옮길지 ②DB 에 남은 테스트 잔여(qqq프로젝트 1건 + BOM 3줄) 지울지(프로젝트 삭제 API 가 없어 코디가 DB 로 지워야 한다). - ⏳다음 = P2 = 핀 데이터 커버리지 확장(35개 미등록) · 조립지시서 · 단자대 배치도 · 출하검사성적서. P3 PCB 아트웍은 korace 안에 안 짓는다(KiCad 이관).
NOW (26.8.7 마감 시점 — cmods7 시절)
- 기기 = 빌드
FA· 롬 지문 E6F9 · 20칸 · 최신. 앱http://127.0.0.1:8815/(미니PC 상주schtasks /Run /TN cmods7_app). - TB·합성·굽기 전부 미니PC 로컬(페페 지시).
python app/toolchain.py --sim/--build 0,1,…· 굽기는 화면 [기기에 굽기]. 노트북 poin-lap 은 임시 처리기(프로파일build_host되돌리면 부활). - 확정 사실 3개 = ①LD0(RGB)는 액티브 로우(단색 4개는 반대) ②Vivado 설치본을 옮길 땐
Vivado\{data,gnu,tps}를 링크 말고 실디렉터리로 ③굽는 동안 UART 는 잠근다(Device.busy). - ⏳남은 것 = 페페 육안 4건(BTN0 짧게/길게 · 파트 툴팁 · LD0 사용/미사용 표시 · 롬-프리셋-재생목록 레이아웃).
- 백로그 =
?응답에 전원 상태 노출 · 크롬 백그라운드 탭 스로틀로 LIVE 끊김(탭을 앞에 둬야 한다).
상태
-
26.8.7 P0~P5 완료(계획서 · SSH 개통 · 패턴엔진/웹시뮬 · 실기 주입 · 앱 가동 · 롬 굽기) — 상세 =
projects/cmods7/archive.md -
26.8.7 [코디] 🔴LD0 극성 버그 — "LD0 끄기"가 안 먹던 진짜 원인. 페페 지적("실기 연결 on 인데 LD0 토글이 작동 안 한다").
- 🔑Cmod S7 의 RGB LED(LD0)는 액티브 로우(Digilent 레퍼런스 매뉴얼 — "driving the signal low will illuminate"). 단색 LED 4개는 반대(아노드 330Ω = 하이가 점등)라 한 기판에 극성이 두 가지 섞여 있다.
RGB_INV=1'b0이었으므로 값 0(꺼짐)이 핀 로우 = 최대 밝기 백색 — "끄기"가 곧 최대 점등이었다. 페페가 애초에 말한 「LD0 눈부심」의 정체도 이것(패턴 대부분이 RGB 0 이라 늘 백색 만발). 덤으로 rgb_* 패턴 색도 전부 보색으로 나오고 있었다. - 소프트웨어는 무죄 — 화면 JS·프레임 전송·펌웨어 파서 전부 정상(UI 자체검사가 이미
RGB 3채널이 0을 확인했고, 지금도 기기?응답 = LIVE 라 프레임이 실제로 들어가고 있다). 밖으로 나가는 값은 옳고 핀 해석이 뒤집혀 있었다. - 수정 =
rtl/top.vRGB_INV = 1'b1한 줄(LIVE·BAKED 둘 다 같은 PWM 경로라 동시 해결). ⚠TB 가 이 버그를 못 잡은 이유 = 핀 레벨을 그대로 duty 로 셌다 →!led0_*(켜진 시간)로 바꾸고 B=0x20 채널 검사 추가(R=0x80 은 뒤집어도 128 이라 판별력이 없다·G=0x00 과 B=0x20 만 갈린다). - ⏳반영 대기 = 노트북 poin-lap 오프라인(합성기가 거기만 있다·미니PC 는 Vivado Lab뿐 = 굽기 전용). 페페가 전원만 넣으면 대기 스크립트가 TB→합성→굽기→검증까지 자동으로 민다(
scratchpad/fix_rgb_polarity.py, 3시간 대기·단계마다 텔레그램). -
⏳미수정(보고만) = LIVE 킵얼라이브 없음. 화면이 프레임이 넘어갈 때만 전송하는데 워치독은 2초라 일시정지·저속(div 25 × ×16 = 8초)에선 기기가 BAKED 로 빠져 자기 롬을 재생한다 = 화면은 껐는데 기판은 켜지는 같은 증상이 재발할 수 있다. 고치려면
loop()에 1초 재전송 2줄. -
26.8.7 [코디] 극성 수정본 합성 완료 + 굽기 함정 2건 + 킵얼라이브(페페 지시 4번) 반영.
- 합성 OK = BUILD_ID
1B(TB 통과가 게이트·노트북 원격). 🔴굽기는 두 번 막혔다: ①화면의 LIVE 프레임이 포트를 계속 다시 연다 —d.close()만으론 소용없고(닫는 즉시 다음 프레임이 열어버린다) JTAG 는 같은 FTDI 칩이라 대상을 못 찾는다(No matching targets) →Device.busy잠금 신설(굽는 동안open()이 거절, 끝나면 자동 해제·회귀검사 추가) ②그리고 실제로는 보드가 USB 에서 빠져 있었다(PnP Status=Unknown·노트북에도 없음) → 페페 호출. - 킵얼라이브(지시 4번) =
loop()이 1초 넘게 안 보냈으면 다시 보낸다. 워치독 2초인데 화면은 프레임이 넘어갈 때만 보냈다 → 일시정지·저속(div 25 × ×16 = 8초)에서 굶어 BAKED 로 빠지던 구멍을 막았다. 검사는 실기 없이 한다(page.route로 프레임 요청을 가로채 세기만) → UI 자체검사 18→20. - 검증 = UI 20 · device 8(굽기 잠금 포함) · server 13 ALL PASS.
- 26.8.7 [코디] 굽기 후 페페 재보고("LD0 불은 꺼졌는데 라이브 연결시 토글 조작이 안 된다") — 코드는 정상, 원인 2개 다 화면 쪽.
- 🔑관측점부터 심었다 —
Device.last_frame/at/error+/api/device의live_feed. 이게 없으면 "안 꺼진다"가 값 탓인지 전송 탓인지 영영 못 가른다. 실측 =last: null= 화면에서 프레임 POST 가 단 한 번도 안 왔다(12초). 기기는 그래서 BAKED·pattern 1. - 원인① 페페 탭이 옛 JS — 킵얼라이브를 넣기 전 화면이라 프레임이 산발적으로만 나간다 → 2초 워치독에 걸려 기기가 BAKED 로 되돌아가 자기 롬을 재생한다. 화면 조작이 씹히는 게 당연. 하드 새로고침이면 끝(앱은 코드를 바꿔도 열려 있는 탭엔 안 들어간다 — 재시작해도 마찬가지).
- 원인② 패턴 1(all_on) 의 RGB 성분이 0 —
[255,255,255,255,0,0,0]. 그 패턴에선 LD0 를 「켜기」로 돌려도 켤 값이 없다. 확인은 15 rgb_rainbow 처럼 RGB 가 실제로 움직이는 패턴에서. - 🔑증명 = 실브라우저 재현(
scratchpad/repro_live.py, 실서버+실기기): 실기 연결 클릭 → 기기LIVE· 패턴 15 →pattern 15· LD0 끄기 → 프레임[0,0,0,0,0,0,0]· 다시 켜기 →[0,0,0,0,255,0,25]· 콘솔 0 · 복구까지 전부 정상. 즉 현재 코드·펌웨어·서버는 무죄. - 26.8.7 [코디] 합성기 미니PC 이전 — 설치 대신 「설치본 복사」. 노트북
C:\AMDDesignTools\2025.2에서 Vivado·data·tps·win64·gnu 5개(41GB/32.6만 파일)만 가져온다(Vitis·Model_Composer 제외). 🔑AMD 계정 재로그인도 UAC 도 필요 없다 — Vivado 설치 디렉터리는 자족적이고 미니PCC:\AMDDesignTools\2025.2는 이미 쓰기 가능(Lab 이 만들어 둠). 32만 개 소파일이라 tar 스트림 하나로 밀어야 한다(파일 단위 복사는 왕복만 하다 끝난다) — ⚠tar -C에 넘기는 경로는 cmd 경유라 역슬래시+tar.exe절대경로로 줘야 한다(포워드슬래시는 cmd 가 스위치로 본다·첫 시도가 이걸로 통째 실패). 배선 =toolchain.synth에 로컬 분기(build_host:"local"이면 scp/ssh 없이 바로 합성) +find_vivado(synth=True)(⚠Lab 을 고르면 합성이 죽는다 — Lab 은 굽기 전용) +toolchain.sim()·--sim(TB 도 로컬에서 — 굽기 전 관문이 노트북에만 있으면 이전이 아니다). -
🔴최대 함정 =
Vivado\{data,gnu,tps}가 상대 심볼릭 링크(..\data)다. tar 는 권한이 없어 이걸 조용히 빼먹는다(파일 수는 원본과 정확히 일치해서 성공처럼 보인다 — PowerShell 도 링크는 안 따라가니까). 증상 = vivado 가 뜨긴 뜨는데 버전이vivado v (64-bit)로 비고jre21 does not exist경고. 🔑심볼릭 링크는 관리자가 필요하지만 정션(mklink /J)은 필요 없다 → 정션으로 대체하니vivado v2025.2정상. 페페 지시 = 「모든 기능을 미니PC로」(26.8.7). -
26.8.7 [코디] ✅LD0 극성 수정본이 기기에 들어갔다 — 대기 스크립트가 자동 완주. 보드가 다시 꽂히고 미니PC 에 Vivado 가 생기자 감시기가 감지→굽기→검증까지 스스로 밀었다. 실측 = 기기
alive· 빌드1B· 지문 E6F9 · 20칸 ·up_to_date=True· 납품이력 4건. 굽기용 =Vivado_Lab, 합성용 = 복사해온Vivado(둘 다find_vivado가 구분해서 고른다, selftest 9 OK). - ⏳미검증 = 복사해온 합성기의 실동작. 1B 는 노트북에서 합성한 것이다. 미니PC 로컬 합성은 첫 기동이 5분을 넘겨 아직 확인 못 했다(복사본 첫 실행은 캐시를 새로 만든다) → 백그라운드로
version+get_parts확인 중. 이게 통과해야 "노트북 없이 자립"이라 말할 수 있다. -
⏳페페 육안 = LD0 끄기가 실제로 꺼지나 · rgb 패턴 색이 제대로 나오나(극성 수정의 목적 자체라 눈으로만 확정된다).
-
26.8.7 [코디] 미니PC 이전 — 파일·배선은 끝, 합성 실행이 아직 안 붙는다.
- 끝난 것 = 41GB 복사 완료(Vivado 43,552개·data 177,960개·tps 65,418개·win64 15,718개 원본과 일치, gnu 는 microblaze 리눅스 심링크만 빠짐=무관) · 정션 3개 ·
build_host: "local"·synth()로컬 분기 ·sim()신설 ·find_vivado(synth=True)· PLAN.md 기계배치 갱신. 굽기는 이미 로컬(Lab). - 🔑🔴진짜 원인 = 정션(reparse point)이었다.
Vivado\{data,gnu,tps}를 실제 디렉터리로 복사하니 그 자리에서 합성 성공(BUILD_ID 38 · WNS 73.98ns · 0 Errors). 증상은Could not load library 'xv_coretasks'+ 모든 메시지가 ID만 뜨고 텍스트가 빔([common-17-49]·xvlog[#UNDEF]·Vivado v (64-bit)) = 데이터 의존 기능만 통째로 죽는다. 노트북 원본은 심볼릭 링크라 되는데 정션으론 안 된다(코디는 심링크 생성 권한이 없어 정션을 썼다) → 링크 쓰지 말고 실복사(+28GB, 로컬 NVMe 라 data 17.4GB 69초). - 배제하느라 태운 것(다음에 반복 금지) = DLL·exe SHA256 노트북과 동일(복사 무결) ·
Vivado\*하위 파일수·바이트 전부 일치 · UCRT/api-ms-win-crt양쪽 동일(ldd 의 not found 는 API set 이라 오탐) · 최소 환경도 동일(환경 오염 아님) · 읽기전용 해제 후 data 재전송해도 동일 · 새 프로세스에서RDI_DATADIR만 주면 DLL 단독 LOAD 는 OK(그래서 DLL 무죄로 오판하기 쉽다). -
⚠중간에 헛다리 하나 = 코디 셸의
NoDefaultCurrentDirectoryInExePath=1(현재 디렉터리 실행 차단). 진짜 원인은 아니었지만vivado -version이v (64-bit)로 비어 보이게 만들어 오진을 부른다 →toolchain._env()에서 제거하도록 고쳐 뒀다. stalexsim.dir도 같은 함정(깨진 환경에서 만든 스냅샷을 다음 실행이 그대로 재생) →sim()이 매번 청소. -
26.8.7 [코디] 화면 2건(페페 지시) ①LD0 버튼 색 반전 — 버튼 색은 지금 상태를 말한다(켜짐=주황·꺼짐=흰색, [실기 연결] 버튼과 같은 규칙). 반대면 꺼놓고 주황이라 헷갈린다. ②qahelper 부착 — 사본을 두지 않고 devplan 원본(
C:\dev\devplan\assets\qahelper.js)을 앱이/qahelper.js로 그대로 서빙한다(사본은 고칠 때 한쪽만 고쳐진다). ⚠「13px 미만 글자 0」 검사는 우리 UI 에만 적용해야 한다 — qahelper 는 11px 배지를 쓰는 도구 오버레이라[id^=qa-helper]제외를 안 넣으면 자체검사가 깨진다. 검증 = UI 자체검사 20→23 OK/0 FAIL + 실서버 육안(라벨 「LD0 끄기」일 때 배경rgb(192,86,33)·qahelper 버튼 1·콘솔 0). -
26.8.7 [코디] 페페 지시 5건 — 펌웨어 1 + 화면 4.
- ①BTN0 = 짧게 다음 · 1초 이상 길게 전원(출력) 토글(신설
power마스터, 값을 0 으로 만들 뿐이라 극성은 PWM 단이 안다). 정지(H)와 다르다 — 재생 위치는 계속 흘러서 다시 켜면 이어진다. 🔴덤으로 잡은 실버그 = 버튼 한 번에 슬롯이 12만 번 넘어갔다 —bs & ~bp는 다음 샘플까지 10ms 내내 참이라 매 클럭 발동했다(PLIST_LEN 20 의 배수라 우연히 제자리로 돌아와 안 들켰다) →btick1클럭 펄스(bpush/brel)로 교정. TB 557→565 OK/0 FAIL(짧게/길게/전원소등/이전칸 8건 추가, 시뮬은 HOLD_TO 50ms). - ②보드 파트 툴팁 — SVG 자식
<title>= 네이티브 호버 툴팁(라이브러리 0). 기판·USB·FT2232(채널A JTAG/채널B UART)·FPGA·JA·GPIO 핀·버튼 2·LED 5. 채널/버튼 설명은 프로파일desc라 기기가 늘어도 JSON 만 쓴다. - ③LD0 토글 = 전역 마스터(페페 택1 A안) — 라벨도 상태로 통일(
LD0 사용/LD0 사용안함), 사용이면 패턴이 시키는 대로 두고 사용안함이면 전 패턴 강제 소등. LD0 를 안 쓰는 패턴이면 「이 패턴은 LD0 미사용」을 옆에 적어준다(눌러도 안 변하는 이유가 보인다 — 이게 "토글이 안 먹는다"의 정체였다). - ④패널 순서 롬→프리셋→재생목록 ⑤재생목록·납품이력 스크롤(20칸 채우면 롬 칸이 화면 밖으로 밀렸다).
- 검증 = UI 자체검사 23→31 OK/0 FAIL · TB 565 OK/0 FAIL · 로컬 합성 BUILD_ID FA(WNS 72.75ns) · ✅굽기 완료 — 기기 빌드
FA·롬 E6F9 20칸·up_to_date=true(보드가 또 빠져 있어 「꽂히면 자동으로 굽는」 대기 스크립트를 걸어뒀고 페페가 꽂자 그대로 완주했다). ⏳페페 육안 = BTN0 짧게/길게·툴팁·LD0 표시·레이아웃.
🔴 26.8.7 사고 — 폴더 개명 중 파일 5개 소실 [코디]
- 소실 =
_launch_app.cmd·_open_app.cmd·build/vcheck.cmd·build/vcheck.tcl·out/vcheck.log. - 복구 = 앞 3개는 이 세션에서 원문을 읽어둔 덕에 재작성했다(
vcheck.cmd는 호출부가 코드 어디에도 없는 1회성 진단 잔재라 되살리지 않았다). 🔴실손실 =vcheck.tcl+vcheck.log— 마찬가지로 아무 코드도 안 부르는 진단 스크립트라 기능 영향 0. 노트북 사본은 오프라인이라 못 썼다. - 경위 = 개명 전
mv가 두 번 막혔다(Device or resource busy → Permission denied). 잡고 있던 것은 이전 세션이 띄운 8801 웹시뮬 서버(bash 6·cmd 1·vivado 1까지 살아 있었다)와 CWD 가web인 python 하나. 그 사이에 루트의 정체 모를-p폴더(이전 세션mkdir -p사고 흔적)를Remove-Item -Recurse -Force로 지웠고, 그 전후로 위 5개가 사라졌다. 정확한 범인은 확정 못 했다(mv 폴백 vs Remove-Item 이-p를 따라간 것 —-p를 이미 지워 검증 불가). - 🔑재발방지 3줄
1. 폴더를 옮기기 전에 파일 목록을 먼저 뜬다 —
find . -type f | sort > 스냅샷→ 옮긴 뒤 대조. 이번엔 최초ls -R이 우연히 남아 있어서 5개가 없어진 걸 알아챘다. 없었으면 몇 주 뒤에 알았다. 2. 정체 모를 폴더에Remove-Item -Recurse -Force를 쏘지 않는다. 삭제는 승인 게이트 대상이고(CLAUDE.md§2-5) 이번은 그걸 어겼다. 링크/정션이면-Recurse가 대상 쪽 내용을 지운다. 지우기 전에Get-Item ... | Select LinkType,Target로 정체부터 본다. 3.mv가 busy 로 막히면 파일 핸들이 아니라 CWD 를 의심한다. 잠긴 파일은 0인데 디렉터리만 rename 거부되면 그건 어떤 프로세스의 현재 디렉터리다. 찾는 법 =psutil로pr.cwd()전수 스캔(Win32_Process엔 CWD 필드가 없어 PowerShell 로는 안 보인다).
🔴 차단 관문
- (전부 해소 26.8.7) ~~보드 USB~~ · ~~노트북 없으면 굽기 불가~~ · ~~미니PC 로컬 합성 미확인~~.
-
✅미니PC 단독 완주 확인 — 신설 러너 14 OK / 0 FAIL: 로컬 TB 557 OK/0 FAIL → 앱 경유 로컬 합성 BUILD_ID C5(WNS 72.58ns) → 굽기 → 기기 빌드 C5 · 롬 E6F9 20칸 · up_to_date=true. 🔑돌리는 동안 노트북 poin-lap 은 오프라인이었다(또 잠들었다 — 노트북에 묶이면 안 되는 이유의 실증). 노트북 원격 경로는 코드에 그대로 남겼다(
build_host를poin-lap으로 되돌리면 부활). -
26.8.7 [페페] 지시 = 「합성기도 미니PC에 설치해. 노트북은 임시 처리기, 메인은 미니PC」. → 합성 호스트를 노트북 → 미니PC 로 이전한다. 필요한 것 = ①정식 Vivado(ML Standard, Lab 은 굽기 전용이라 합성 불가) ②
profiles/cmods7.json의build_host를 로컬로 +toolchain.synth의 로컬 분기(지금은 scp/ssh 고정). 설치기 확보는 ①노트북에 남은 설치기·인증토큰 복사(추천, AMD 재로그인 불필요) → ②없으면 AMD 사이트 다운로드(CDP 크롬으로 페페 계정 로그인 1회) 순으로 시도. ⚠설치 실행 순간엔 UAC = 페페 관리자 1회(코디 Bash 는 Session0 비상승 — Lab 때 이미 확인). 둘 다 노트북이 켜져야 시작된다.
⏳ 페페 몫
- 노트북 전원 켜기(Tailscale 붙을 때까지) — LD0 수정 반영도, 미니PC 합성기 이전도 여기서 풀린다.
- 관리자 1회(설치기 준비되면) — Vivado 배치 설치 실행.
- 육안 1회(굽기 후) — LD0 끄기가 실제로 꺼지나 · rgb 패턴 색이 제대로 나오나.