FAB 실연동 — 허위배선 제거, 라이브 프로브로 전환
개요
fab.crowny.org:8200(크라우니FAB, 블록체인 기가팩토리 네트워크 운영계층)의
GET /api/link/status가 EV·factory를 실제로 프로브하지 않고 하드코딩 정적
메타데이터만 반환하는 허위배선이었다(메모리 feedback_동반장식_적대감사_페이지배선
껍데기 안티패턴). manifest의 connects도 선언뿐이었다. FAB는 네트워크 운영계층인데
factory 실데이터를 전혀 끌어오지 않고 있었다.
문제
/Users/ef/crowny-fab/서버.한선_처리link_status(구 318~325행): EV/factory에
_처리manifest의connects:["ev.crowny.org:9616","factory.crowny.org:8300"]
- factory가 노출하는
GET /api/fab/card(avgReadiness·autoGradeCount·cards 배열)를
무엇을 했는지
정본 패턴 = /Users/ef/crowny-factory/서버.한선 _처리ev_pull(1011~1046행):
체계("curl -s --connect-timeout 2 -m 5 '...' 2>/dev/null </dev/null") →
빈 문자열이면 503 정직실패, 아니면 _JSON값류 헬퍼로 파싱. 원시소켓 직접호출은
쓰지 않음(소켓받기 recv 타임아웃 없음 함정 회피).
이 패턴을 FAB 서버.한선에 그대로 미러:
GET /api/link/status→ 진짜 라이브 프로브로 전환. 공용 헬퍼
_프로브(베이스, 경로)가 체계()+curl로 EV(127.0.0.1:9616/api/health)와
factory(127.0.0.1:8300/api/health)를 각각 호출. up은 기본값 "false"로
시작해, 응답이 비어있지 않고 _JSON필드추출(raw,"ok")=="1"일 때만 "true"로
덮어씀(하드코딩 없음 — grep 증거로 확인됨). 응답:
{"ok":1,"ev":{"host":..,"port":9616,"up":true|false},"factory":{...},"checkedAt":<현재시간()>}.
- 신규
GET /api/factory/rollup— factory/api/fab/card를 동일 프로브 헬퍼로
"factory 연결 실패(factory.crowny.org:8300) — 폴백 없음").
성공 시 avgReadiness·autoGradeCount를 _JSON필드추출로 뽑아 그대로 전달하고,
raw카드수는 응답 안 "id": 등장 횟수를 세는 신규 헬퍼 _부분개수(s,sub)로 근사
(라이브 검증에서 실제 cards 배열 길이 10과 정확히 일치 확인).
- manifest
connects갱신 — 문자열 배열 대신 실엔드포인트 명시 객체 배열로:
- 디스패치 등록 —
요청처리()에/api/factory/rollup행 추가(기존 처리됨 플래그 규약). - 함수 순서 정리 —
_JSON필드추출을 신규 프로브 함수들보다 앞으로 이동
관련 파일
/Users/ef/crowny-fab/서버.한선—_EV베이스/_FACTORY베이스상수,_프로브,
_처리link_status(재작성), _부분개수(신규), _처리factory_rollup(신규),
_처리manifest(connects 갱신), 요청처리 디스패치.
/Users/ef/crowny-fab/서버.toau— 재컴파일 산출물.- 정본 참조:
/Users/ef/crowny-factory/서버.한선_처리ev_pull(1011~1046행).
종단 실측 (2026-07-20, 라이브)
$ curl -s -m 5 http://127.0.0.1:8200/api/health
{"ok":true,"service":"crowny-fab","port":8200}
$ curl -s -m 5 http://127.0.0.1:8200/api/link/status
{"ok":1,"ev":{"host":"ev.crowny.org","port":9616,"up":true},
"factory":{"host":"factory.crowny.org","port":8300,"up":true},
"checkedAt":1784556289}
$ curl -s -m 5 http://127.0.0.1:8200/api/factory/rollup
{"ok":1,"source":"factory.crowny.org:8300","avgReadiness":54,
"autoGradeCount":2,"raw카드수":10,"pulledAt":1784556289}
$ curl -s -m 5 http://127.0.0.1:8300/api/fab/card | python3 -c \
"import json,sys;print(len(json.load(sys.stdin)['cards']))"
10 # raw카드수(10)와 정확히 일치
STRICT 컴파일: CROWNY_STRICT=1 hanseonc_high 서버.한선 → 경고 0.
정직성 grep 증거: up 변수는 "false" 리터럴로 시작해 `글자수(raw)>0 그리고
_JSON필드추출(raw,"ok")=="1" 조건을 통과할 때만 "true"`로 덮어씀 — 하드코딩된
up:true 없음. /api/factory/rollup도 동일하게 curl 빈 응답 시 503 정직실패
경로 보유(죽은 포트 8399 프로브로 빈 응답 확인 완료).
잔여 이슈
raw카드수는"id":등장 횟수 근사치(정확 파싱 아님) — BOM/슬롯 상세까지
_fab카드1 필드별 파싱 헬퍼 이식 필요(선택 사항, 이번
범위 아님으로 보류).
- factory가 실제로 죽었을 때의 503 경로는 죽은 포트(8399) 프로브로 간접 검증만
심화 (2026-07-20 2차) — 롤업을 슬롯/KPI/체인 상세까지 확장
사용자 선택("FAB 롤업 심화")에 따라 GET /api/factory/rollup을 avgReadiness·autoGradeCount 수준에서 factory 실데이터 다중 pull로 확장. 주간한도차단 신호로 서브에이전트 팬아웃 대신 메인 세션 직접 확장(결정형 패턴 재사용).
무엇을
- slots 실pull(factory /api/slots): total·andon(phase-1)·materialWait(phase-2)·shipped(phase1)·evLinked("EV 주문 연동") 집계 + 원본 슬롯 리스트 passthrough. 라이브 실측: total5/andon1/materialWait1/shipped1/evLinked1 — factory 원본과 정확 일치.
- kpi 롤업(factory /api/kpi): 신규 헬퍼 _앵커다음값(라벨 다음 첫 따옴표값 추출)로 헤드라인 4종(이번주생산 "1 / 4대"·라인가동률 "67%"·FPY "96.5%"·노하우 "84건") — factory 실값 일치.
- chain(파생·정직): fab data/*.db는 5월자 Python 레거시 SQLite(바이너리)라 한선씨에서 정직 파싱 불가 → 가짜 원장 읽기 대신 evAnchorable=EV연동 슬롯수(앵커가능 생산이벤트)로 파생 표기 + note에 "라이브 체인원장 엔드포인트 부재" 명시. 허위배선 금지 준수.
검증
- CROWNY_STRICT=1 컴파일 0경고. launchctl kickstart 재기동 후 health 200.
- /api/factory/rollup 라이브: slots/kpi/chain 전부 실값. 한글 슬롯 리스트 완전 통과(Connection:close·Content-Length 생략 → 한글 절단 함정 회피 확인).
- 함정 회피: _앵커다음값 헬퍼를 롤업 함수보다 앞에 정의(전방참조 회피 — feedback_hanseon_함수전방참조), phase 부분문자열 오매칭 없음("phase":1이 "phase":-1에 오매칭 안 됨 실증).
학습 래칫
- FAB_팩토리롤업_슬롯KPI체인확장 / 한선씨_KPI배열_앵커다음값추출 (다음부터 토큰0).
잔여
- KPI 나머지 섹션(supply/jig/train/iqc/asm/ship/flow) 심화는 필요 시. 라이브 체인원장은 factory가 체인 엔드포인트 노출 시 실pull 전환(현재 파생값).