← 목록
기타 2026-07-12 5KB 읽기 5분

crowny-game 8종 서비스 학습래칫 탑재

개요

game.crowny.org:9775의 8개 서비스 라우트(/academy /ad /build /sales /commerce /auto /copy /letter)에 "쓸수록 똑똑해지는" 학습층을 붙였다. 사용기록·피드백이 쌓이면 동일/유사 요청에 대해 엔진 재호출 없이 캐시된 응답을 즉시 반환한다.

무엇을 했는지

  1. 한선씨/서비스학습.한선 (SSOT) — stdin 명령 프로토콜(기록/조회/피드백/통계) 엔진.
- 데이터: data/학습/<서비스>.psv (id|ts|입력키|출력|score|hits) - 조회: 입력키 2그램 중첩률 ≥60% AND score≥2 인 레코드 중 (score,hits) 최고 1건 반환 - 500줄 초과 시 저score(동점=오래된 ts)부터 제거해 회전 - 파일 I/O는 버퍼파일읽기(874)+버퍼바이트읽기(851) 바이트 스캔으로 줄 경계만 찾고, 각 줄은 버퍼잘라(395)+버퍼문자열(396)로 개별 변환(멀티바이트 UTF-8 안전, 65535B 캡 회피, 거대 단일문자열 concat 금지 — 쓰기()는 첫 줄만, 이후 전부 덧쓰기()). - 실측 정정: "입력() 프라임리드 함정"(더미줄 선행 필요)은 이 파일의 명령분기+다중읽기 구조에서는 적용되지 않음을 스크래치 테스트로 실증(더미줄 넣으면 오히려 첫 실제줄이 씹혀 명령이 깨짐). 순수 순차 입력() N회 호출로 정확히 동작한다. hanseonc_high 828~5652 큐브 규모에서 재현.

  1. src/learn.js — Node I/O 래퍼(순수 오케스트레이션, 로직 없음. ad.js/copy.js와 동일 패턴).
- ensure() — .한선 mtime, .toau mtime, 컴파일러(hanseonc_high) mtime 3중 비교(stale-toau 함정 회피) - wrap(svc) — POST 미들웨어: 조회 HIT→엔진 생략 즉시 응답(learned:true), MISS→next() 후 res.json 후킹해 ok:true 응답만 동기 기록, learn_id 주입 - 라우터를 /api에 마운트해 /api/learn/feedback, /api/learn/stats, /api/ai/manifest 3경로를 server.js 편집 단 1줄(app.use('/api', learn.router))로 동시 커버

  1. server.js — 2곳만 편집: require('./src/learn') + 7개 엔진(copy/ad/sales/letter/auto/build/commerce)
app.use 라인에 learn.wrap(svc) 삽입, app.use('/api', learn.router) 1줄 추가. academy는 GET이라 제외. server.js/learn.js 자체는 로직 없는 Express 배선이라 .한선 동반 생략(프로젝트 기존 관행과 동일 — ad.js 등 7개 기존 라우트 파일도 JS 미러 .한선이 없고, SSOT는 엔진 .한선 파일 하나).

검증 (실측)

  • 컴파일: hanseonc_high 정상(0 경고, CROWNY_STRICT=1도 클린), 5652 큐브
  • CLI: 기록→조회(MISS, score0<2)→피드백+1×2(score2)→조회(HIT, output 원본 복원)→통계 — 전부 기대값 일치
  • 회전: MAXLINES=3 스크래치 테스트로 저score 우선제거 확인(id2 score0 제거, id1/3/4 유지)
  • 2그램: 끝글자만 다른 입력→HIT, 완전 다른 입력→MISS 확인
  • 서버 재기동(launchctl kickstart -k gui/501/org.crowny.game) 후 curl 종단검증 전부 PASS:
  • POST /api/copy/generate → learn_id:1
  • POST /api/learn/feedback ×2 → score 1→2
  • 동일 재요청 → learned:true,learn_id:1, 원 응답 완전 복원
  • GET /api/learn/stats, GET /api/learn/stats?svc=copy, GET /api/ai/manifest → 200 + 실질 JSON(8서비스 메타+학습통계)
  • 8라우트 페이지(/academy /ad /build /sales /commerce /auto /copy /letter) 전부 GET 200
  • ad/sales/letter/auto/commerce/build 나머지 6개 엔진도 learn_id 정상 부여 확인, data/학습/*.psv 7개 생성
  • 서버 stderr 로그 클린, 크래시 없음
  • 관련 파일

    • /Users/ef/crowny-game/한선씨/서비스학습.한선 (SSOT), .toau
    • /Users/ef/crowny-game/src/learn.js
    • /Users/ef/crowny-game/server.js (최소 편집)
    • /Users/ef/crowny-game/data/학습/*.psv (런타임 생성)

    잔여 이슈

    • 500줄 회전은 소규모(3줄) 스크래치 테스트로만 검증, 실제 500줄 규모 스트레스는 미실시(로직상 O(제거수×n) 안전 확인됨).
    • /api/sales는 sales.js(reward)와 pipeline.js(딜CRUD) 두 라우터가 같은 프리픽스를 공유 — learn.wrap('sales')
    sales.js 앞에만 걸려 있지만 Express 미들웨어 체이닝 특성상 pipeline.js로 가는 POST 요청도 같은 wrap을 통과함 (2그램 매칭이 필드가 다른 요청끼리 오탐 HIT를 낼 가능성은 낮지만 0은 아님 — 필요시 svc를 'sales'/'pipeline'으로 분리 고려).
    • PSV 필드 구분자 "|" 보호는 learn.js sanitizeLine에서 처리(치환 "/") — 극단적으로 특수한 입력값이 있다면 육안 확인 권장.