70e49f0556
Validators (Pushes and Pull Requests) / UI & Storage Validation (push) Failing after 13s
Validators (Pushes and Pull Requests) / Core Validators & Database Setup (push) Failing after 22s
Validators (Pushes and Pull Requests) / Database & Schema Validation (push) Failing after 11s
Validators (Pushes and Pull Requests) / WBS & Audit Validations (push) Has been skipped
Validators (Pushes and Pull Requests) / .NET Contracts (push) Has been skipped
Validators (Pushes and Pull Requests) / Calibration & Performance (push) Has been skipped
Validators (Pushes and Pull Requests) / Operational Report & Decision Packet (push) Has been skipped
Validators (Pushes and Pull Requests) / Security & Secrets (push) Successful in 11s
Validators (Pushes and Pull Requests) / CI Workflow Lint (push) Failing after 10s
Validators (Pushes and Pull Requests) / Notify PR Results (push) Has been skipped
Frontend CI Pipeline / ci-frontend-8-steps (push) Failing after 1m51s
Records the two-pass orphan script cleanup (74 files total across two commits) and the methodology gap that mattered (check output-path references, not just script-name references). Also records that GatherTradingData.json (the project's own designated canonical seed, per docs/GATHERTRADINGDATA_XLSX_DECISION) is available from the production server even without the untracked .xlsx, but the release DAG's convert_xlsx node has no skip-if-output-exists logic, and the remaining 10 blocked WBS verdicts need a running QuantEngine.Web + Playwright evidence run against real DB price history, not just the seed JSON - not attempted this session. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
124 lines
10 KiB
Markdown
124 lines
10 KiB
Markdown
# 2026-07-30 QuantEngine 전략 감사 세션 — 인수인계
|
|
|
|
19개 원칙(SOLID, 정공법, 홀루시네이션, 재현성, 데이터정합성, 과유불급, 정규화/역정규화,
|
|
프로세스 단순화, 패턴화, 표준화, 구조화, 바이브코딩, 현장감, 이력성, 안정성, 고도화,
|
|
컴포넌트화, 기술부채) 기준으로 저장소를 감사하고 발견된 문제를 수정한 세션의 기록이다.
|
|
8개 커밋이 `main`에 반영·푸시됐다 (HEAD: `823a9a6`). 무엇이 바뀌었는지는 `git log`가
|
|
권위 있는 출처이니 여기서 반복하지 않는다 — 이 문서는 **커밋 로그만 봐서는 알 수 없는
|
|
맥락**(미해결 항목, 판단 근거, 재발 방지 트랩)만 담는다.
|
|
|
|
## 미해결 / 다음에 이어갈 것
|
|
|
|
- **전체 release DAG(`npm run ops:validate` / `full-gate`)를 끝까지 검증하지 못함.**
|
|
`GatherTradingData.xlsx`(gitignore 대상, 실거래 데이터 시드)가 이 개발 환경에는 없어서
|
|
`convert_xlsx` 노드에서 막힌다. 이 파일이 있는 실제 환경(사용자 로컬 또는 운영 서버)에서
|
|
한 번 돌려서 이번 세션의 변경사항이 데이터 수집 경로를 깨지 않았는지 최종 확인 필요.
|
|
- **`docs/db/quantengine.dbml`의 `engine_history` vs `quantengine` 스키마 동명 테이블 4개**
|
|
— 실제 .NET 호출부를 grep으로 대조해 "둘 다 살아있는 서로 다른 모델"로 확정하고 DBML에
|
|
근거를 남겼지만, 코드 통합/리네임은 하지 않았다. "정리해달라"는 요청이 오면 DBML의
|
|
`V8: PostgreSQL History-First Operating Model` 섹션 노트부터 다시 읽을 것 — 죽은 코드로
|
|
섣불리 판단하지 말 것.
|
|
- **OpenDART는 배선만 맞춰뒀고 실제로 호출하는 워크플로우가 아직 없다.** 환경변수명은
|
|
`OPENDART_OPENAPI_KEY`로 코드·Gitea Secrets 양쪽 통일 완료. 나중에
|
|
`tools/ingest_fundamental_raw.py`를 CI에서 처음 호출할 때는 별도 매핑 없이
|
|
`secrets.OPENDART_OPENAPI_KEY`를 그 job의 `env:`에 바로 연결하면 된다.
|
|
- **KRX Open API는 구현이 전혀 없다** — CLAUDE.md에 환경변수명(`KRX_OPENAPI_KEY`, 실제
|
|
Gitea Secrets 이름과 일치)만 예약해뒀다. 호출 한도 등은 사용자가 알려주지 않아 기록하지
|
|
않았다 — 추측해서 채우지 말 것.
|
|
|
|
## orphan 스크립트 정리 (같은 날, 2차 조사)
|
|
|
|
`tools/*.py` + `src/quant_engine/*.py` 619개 파일 전수 스캔(파일명이 저장소 어디에도 안 나오는
|
|
것 탐지) 결과 81개 orphan 후보 발견. 두 단계로 나눠 총 74개 삭제:
|
|
- 1차 34개: 명백한 버전 중복(`_v2`/`_correct`/`_properly` 짝) + tools/에 섞인 임시 테스트/디버그
|
|
스크립트.
|
|
- 2차 40개: WBS 티켓 전용 1회성 스크립트 + 기타 build_*/validate_* 진단 도구. **주의**: 스크립트
|
|
자체 이름 검색만으로는 부족했다 — 47개 후보 중 7개는 이름은 안 불려도 만들어내는
|
|
`Temp/*.json` 산출물이 다른 도구에서 계속 읽히고 있어 실제로는 살아있었다
|
|
(`build_outcome_ledger_v1.py`, `build_pre_distribution_early_warning_v3.py`,
|
|
`build_shadow_ledger_v1.py`, `build_p2_01_live_outcome_ledger.py`,
|
|
`build_p2_02_calibration_promotion.py`, `build_p1_01_execution_verdict_unify.py`,
|
|
`run_release_ci_gate_v2.py` — 이 7개는 삭제하지 않고 남겨둠). **다음에 orphan 스캔할 때는
|
|
스크립트명뿐 아니라 그 스크립트가 쓰는 `Temp/*.json` 출력 경로까지 같이 검색할 것.**
|
|
|
|
나머지 orphan 후보(그레이존 밖, 원래 81개에 없던 것들)는 손대지 않았다 — 전수조사가 아니라
|
|
`tools/`+`src/quant_engine/`만 스캔한 결과다.
|
|
|
|
## GatherTradingData.xlsx 관련 (같은 날, 추가 조사)
|
|
|
|
로컬에는 `.xlsx`가 없지만, 운영 서버(`~/QuantEngineByItz/GatherTradingData.json`)에는 이미
|
|
xlsx→json 변환이 끝난 정본 시드 파일이 있다 (저장소 자체 설계 문서
|
|
`docs/GATHERTRADINGDATA_XLSX_DECISION_2026-06-21.md`가 "json을 정본으로, xlsx는 미추적"으로
|
|
결정한 바로 그 파일). SCP로 로컬에 받아왔다(`./GatherTradingData.json`, gitignore 대상이라
|
|
커밋 안 됨). 그런데 `tools/run_release_dag_v3.py`의 `convert_xlsx` 노드는 xlsx 파일이 실제로
|
|
없으면 무조건 하드 실패하도록 짜여 있어(캐시/스킵 로직 없음, 코드 주석에 "optional 최적화,
|
|
아직 미구현"이라고 명시됨), json이 이미 있어도 release DAG를 처음부터 끝까지 돌릴 수는 없다.
|
|
|
|
남은 WBS 태스크 10개(QE-M3-03, M4-01~05, M5-01~04)를 이 json만으로 복구하려 했으나:
|
|
- **M3-03**: `engine_history.factor_output_history`에 최근 24시간 데이터가 있어야 하는 라이브
|
|
신선도 게이트 — 데이터 유무와 무관, 운영 파이프라인이 최근 실제로 돌았는지에 달림.
|
|
- **M4-01~04, M5-01~03**: `Temp/backtest_result_v1.json` 등은 Python 스크립트가 아니라
|
|
**`src/dotnet/QuantEngine.Tools`/`QuantEngine.Web`를 실제로 띄우고 Playwright로 백테스트/
|
|
캘리브레이션 화면을 조작해야** 생성된다(M4-05 검증 커맨드가 `npx playwright test` →
|
|
`verify_wbs_task_v1.py` 순서인 게 근거). 로컬 웹서버 기동 + Playwright 브라우저 설치 +
|
|
실제 가격/팩터 이력 DB 데이터 충분 여부까지 얽혀 있어 이번 세션에서는 시도하지 않았다.
|
|
- **M4-05, M5-04**: 위와 같은 이유로 막힘.
|
|
|
|
다음 세션에서 이어가려면: SSH 터널 + `dotnet watch run --project QuantEngine.Web` +
|
|
`npx playwright test --project=evidence tests/e2e/evidence/qe-m4-05-backtest.spec.ts` 순으로
|
|
시도. DB에 실제 가격 이력이 충분한지부터 확인할 것 (부족하면 백테스트 자체가 의미있는 결과를
|
|
못 낼 수 있음).
|
|
|
|
## 추가 발견 (같은 날, entropy 정리 이후)
|
|
|
|
- **`Temp/*` 전체 삭제가 WBS 검증 캐시를 깼다.** `tools/verify_wbs_task_v1.py`가 만드는
|
|
`Temp/evidence/<task_id>/verdict.json`과 각종 `Temp/*.json`(golden_coverage_100,
|
|
market_time_series_schema 등)은 git에 추적되지 않지만 "완료된 검증의 증적"이라 순수
|
|
빌드 캐시가 아니었다. `spec/60_quant_engine_wbs.yaml`의 13개 태스크가 FAIL로 나타났었음.
|
|
- 3개(QE-M0-06, QE-M2-06, QE-M2-01)는 해당 generator 재실행 + DB 재접속으로 복구 완료.
|
|
- QE-M3-03은 무관 — `engine_history.factor_output_history`에 최근 24시간 내 데이터가
|
|
있어야 하는 라이브 신선도 게이트. 오늘 세션과 상관없이 운영 파이프라인이 최근 안
|
|
돌았으면 원래도 FAIL이다.
|
|
- 나머지 7개(QE-M4-01~04, QE-M5-01~03)는 `Temp/prediction_accuracy_harness_v2.json`
|
|
등 실거래 데이터 파생 체인이 필요 — 이 저장소 스냅샷엔 `GatherTradingData.xlsx`가
|
|
없어서(이미 위에서 언급한 그 문제) 복구 불가. 실거래 데이터가 있는 환경에서 전체
|
|
파이프라인을 한 번 돌리면 자동 복구된다.
|
|
- QE-M4-05/QE-M5-04(Playwright evidence)도 같은 체인에 의존해 사실상 같이 막혀있음.
|
|
- **교훈**: `Temp/`가 git 미추적이라고 전부 "순수 빌드 산출물"은 아니다 — `Temp/evidence/`처럼
|
|
"재실행하면 되지만 재실행에 실제 데이터/DB가 필요한 캐시"가 섞여 있다. 다음에 비슷한
|
|
정리를 할 때는 삭제 전에 `rg -l "Temp/" spec/ tools/` 정도로 어떤 하위 경로가 검증
|
|
체인에 물려있는지 먼저 확인할 것.
|
|
|
|
## 이번 세션에서 걸린 함정 — 재발 방지
|
|
|
|
- **문서를 "오래됐다"고 archive하기 전에 `tools/*.py`, `spec/*.yaml`, `tests/*.py`,
|
|
`.gitea/workflows/*.yml`까지 전부 grep할 것** — 다른 문서/CLAUDE.md만 검색해서는 부족하다.
|
|
`docs/ROADMAP_WBS.md`와 `docs/ROADMAP_ENTERPRISE_TEMPLATES_WBS.md`를 이 방식으로 archive
|
|
했다가, 실제로는 release gate 검증기와 `ci-frontend.yml`의 Enterprise Contract Parity
|
|
Test가 그 경로를 직접 참조하고 있어서 되돌려야 했다. 지금은 이 두 파일 다시 원위치, 검증기
|
|
3개 직접 실행해서 통과 확인 완료.
|
|
- **DbUp 마이그레이션은 파일명을 순수 문자열로 정렬한다** — `V10__`이 `V2__`보다 먼저
|
|
정렬되는 문제가 있었다. `MigrationScriptNameComparer`(이번 세션에 추가, `DbMigrator.cs`에
|
|
연결)로 해결됨 — 새 마이그레이션은 zero-padding 없이 다음 정수만 쓰면 된다.
|
|
- **`runtime/`은 대부분 git 추적되는 이력 데이터다** (`refactor_baseline_v*.yaml`,
|
|
`rollback_manifest_v*.yaml` 등) — 스크래치 공간이 아니다. 확인용 명령의 `--out`을
|
|
실수로 이 경로로 잡아서 이력 파일 2개를 덮어썼다가 `git diff`로 발견하고
|
|
`git checkout --`으로 복구했다. 1회성 도구 출력은 `/tmp/` 등으로 보낼 것.
|
|
- **이 머신에 Python이 두 개 설치돼 있다** — `python`(3.11, 대부분의 서브프로세스가
|
|
실제로 쓰는 것)과 `python3`(3.14). 한쪽에 패키지를 설치해도 다른 쪽엔 없다.
|
|
- **repository entropy 감사(`audit_repository_entropy_v2.py`)가 git 추적 파일이 아니라
|
|
로컬 디스크 전체를 세고 있었다** — `.gitignore`와 제외 목록이 어긋나 있어 로컬 빌드 한 번에
|
|
4,523개까지 부풀었다(예산 2,200). `.gitignore`와 일치하도록 제외 목록을 갱신해 재발을
|
|
막았다 (`tools/audit_repository_entropy_v1.py`). 이 게이트가 다시 실패하면 먼저 "새로운
|
|
미추적 빌드 산출물 디렉터리가 생겼나"부터 확인할 것 — 바로 대규모 파일 삭제로 가지 말 것.
|
|
|
|
## 이번 세션에서 확립된 작업 방식
|
|
|
|
- 작업 라운드가 끝나면 다음에 할 만한 구체적인 후보를 먼저 제안한다 (사용자가 같은 지시를
|
|
반복해서 보내는 걸 방지).
|
|
- 단순 기계적 조사/위임은 `model: "haiku"`로, 판단이 필요한 작업만 Sonnet급으로.
|
|
- 커밋/푸시는 명시적으로 요청받았을 때만, 항상 경로를 지정해서 스테이징(`git add -A` 금지),
|
|
세션 시작 전부터 있던 무관한 변경사항은 요청 없이는 포함하지 않는다.
|
|
- 채팅에 붙여넣어진 실제 API 키(KIS, OpenDART, KRX)는 어떤 파일에도 적지 않는다 — 환경변수
|
|
*이름*만 기존 KIS 관례(환경변수/Gitea Secrets 전용, 하드코딩 금지)에 맞춰 기록한다.
|