Files
KArtSell.Aegis/CURRENT_ROADMAP.md
T
kjh2064 769d188701 fix: stop committing generated frontend build output (wwwroot rehash noise)
Root cause (CURRENT_ROADMAP.md item #3): wwwroot/assets/* and
wwwroot/index.html under KArtSell.Host are 100% Vite build output (no
hand-authored files in there) but were committed to git. Every local
dotnet build re-triggers pnpm build via the BuildFrontend MSBuild
target, which produces new content-hashed filenames even when no
frontend source changed, and the old hashed files were never cleaned
up (4 of the 6 committed asset files were already orphaned/unreferenced
before this fix, confirmed by diffing wwwroot/index.html's script/link
tags against what was actually on disk).

Investigated whether the committed output was load-bearing for
deployment before picking a fix:
- .gitea/workflows/deploy.yml (the real production deploy path) already
  wipes wwwroot and rebuilds it fresh from pnpm build on every deploy,
  so the committed files were never actually used there.
- .gitea/workflows/ci.yml's `publish` job (Gitea Release zip) was the
  only place actually depending on the committed wwwroot contents,
  since it runs `dotnet publish` without ever building the frontend.

Given that, committing the hashed output was pure architectural
mistake with no deployment benefit, and the smaller/more correct fix
is to stop tracking it rather than bolt MSBuild Inputs/Outputs
incrementality onto the BuildFrontend target (which would also be
fragile: git checkouts/worktrees can normalize file mtimes in ways
that defeat timestamp-based up-to-date checks).

Fix:
- .gitignore: ignore src/KArtSell.Host/wwwroot/assets/ and
  wwwroot/index.html (generated by BuildFrontend target locally and by
  deploy.yml in production).
- git rm --cached the 7 previously-tracked generated files.
- ci.yml publish job: add the same pnpm install/build + wipe-and-copy
  step deploy.yml already uses, so the release zip still ships a real
  frontend build instead of losing it now that git no longer carries it.
- Left the BuildFrontend MSBuild target itself unchanged (still runs
  pnpm build on every local `dotnet build`) since re-running it is no
  longer a problem now that its output isn't tracked.

Verified (not just asserted):
- `dotnet build KArtSell.sln -c Release` run twice in a row: `git
  status`/`git diff --stat` identical after both runs (only the 9
  intentional lines in .gitignore/ci.yml), even though wwwroot/assets
  on disk got fresh hashed filenames both times.
- Reverted to pre-fix state and ran a single `dotnet build` with zero
  source changes: reproduced the bug exactly as described -
  wwwroot/index.html showed a 13-line diff and 2 new untracked hash
  files appeared, with the old stale ones left behind. Then restored
  the fix and re-verified the two-consecutive-build check above.
- `cd frontend && pnpm install --frozen-lockfile && pnpm typecheck &&
  pnpm build` all pass cleanly on their own.
- `dotnet test tests/KArtSell.ModelOperations.UnitTests` still 54/54
  passing after the build changes.

Separate, out-of-scope finding recorded in CURRENT_ROADMAP.md: ~130
frontend/src/**/*.js files compiled from .ts/.vue siblings (plus
tsconfig.tsbuildinfo, vite.config.js) are also committed and also
regenerate on every `pnpm build` via `vue-tsc -b`, because
tsconfig.json has no `noEmit: true`. Same class of problem, not fixed
here to keep this PR to one goal.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 12:55:43 +09:00

11 KiB

🚀 K-ArtSell Aegis v16.0 - 현재 진행 로드맵

최종 갱신: 2026-08-07 (이 문서의 이전 버전은 2026-08-03 상태로 정체되어 있었고, 그 사이 병합된 115개 커밋을 반영하지 못했습니다. 이번 갱신은 실제 코드/테스트를 직접 확인한 결과입니다.)

상태 요약: VS-03(승인 워크플로우), VS-04(감사 추적), VS-10(매도 결정), VS-12(거래 실행), VS-14(포트폴리오 대사) 백엔드 구현 + 테스트 완료. Phase 1 Shadow Run(Gate 5a, 252+ 거래일 검증)은 아직 시작되지 않음 (과거 "RUNNING" 기록은 허위였음이 이미 문서로 정정됨). 상세 항목별 상태는 docs/CURRENT/CATALOGS/WBS_PROGRESS_TRACKER.csv 참조.


⚠️ 알려진 문서 정합성 문제 (DECISION_REQUIRED)

  1. VS 번호 체계 충돌: docs/CURRENT/CATALOGS/WBS_MASTER.csv(원 계획)와 실제 구현/WBS_PROGRESS_TRACKER.csv(실행 트래커) 사이에 VS-03/VS-04/VS-12/VS-14 번호가 서로 다른 기능을 가리키는 충돌이 있습니다. 이번 세션에서 발견했고, 사용자 결정에 따라 기존 트래커 번호를 유지하고 충돌 사실만 각 행에 명시했습니다. 근본 해결(재번호 부여 또는 WBS_MASTER 공식 대체)은 아직 미결정입니다.
  2. DbUp 마이그레이션 테스트 DB 권한 문제: kartsell DB 사용자가 kartsell_migration_test 데이터베이스의 소유자가 아니어서 DbUpMigrationTests(12건)가 로컬에서 실패합니다. 코드 문제가 아니라 DBA 조치(소유권 부여)가 필요합니다.
  3. [해결됨 2026-08-08] frontend 빌드 산출물 재해시: dotnet build를 실행할 때마다 pnpm build가 재실행되어 wwwroot/assets/* 해시 파일명이 바뀌고 git에 불필요한 변경이 쌓이는 구조적 문제가 있었습니다. 근본 원인: wwwroot/assets/*, wwwroot/index.html은 100% Vite 생성 산출물(수작업 파일 없음)인데도 git에 커밋되어 있었고, 재빌드마다 콘텐츠 해시가 바뀌어 stale 파일이 삭제되지 않고 계속 누적됨(실제로 6개 커밋 파일 중 4개가 이미 orphan 상태였음이 확인됨). 조사 결과 .gitea/workflows/deploy.yml(실제 프로덕션 배포)은 이미 매 배포마다 wwwroot를 지우고 새로 빌드하므로 커밋된 산출물이 배포에 전혀 쓰이지 않았음 — 유일하게 의존하던 곳은 .gitea/workflows/ci.ymlpublish(Gitea Release zip 생성) 잡뿐이었음. 조치: wwwroot/assets/, wwwroot/index.html.gitignore에 추가하고 git rm --cached로 추적 해제했으며, ci.ymlpublish 잡에 deploy.yml과 동일한 패턴(pnpm install → build → wwwroot 비우고 복사)을 추가해 release zip도 신선한 산출물을 갖도록 함. MSBuild의 BuildFrontend 타겟(로컬 dotnet build 시 항상 pnpm build 재실행)은 변경하지 않음 — 산출물이 더 이상 git 추적 대상이 아니므로 재실행 자체는 더 이상 문제가 아님. 검증: dotnet build KArtSell.sln -c Release를 연속 2회 실행해 git status가 두 번 모두 동일(무관 변경 없음)함을 확인했고, 수정 전 코드로 되돌려 동일한 무변경 빌드를 1회 실행하면 wwwroot/index.html이 13줄 diff로 수정되고 신규 해시 파일 2개가 untracked로 생기는 것을 재현해 대조 확인함.
    • 별도 발견(미해결, 범위 밖): frontend/src/**/*.vue.js, frontend/src/features/*/api.js 등 TS 소스 옆에 나란히 존재하는 .js 파일(약 130개)과 frontend/tsconfig.tsbuildinfo, frontend/vite.config.js도 전부 git에 커밋되어 있고, pnpm build(vue-tsc -b)를 실행할 때마다 매번 재생성되어 같은 종류의 불필요한 diff를 만듭니다. 근본 원인은 frontend/tsconfig.json"noEmit": true가 없어 vue-tsc -b(프로젝트 빌드 모드, outDir 미지정)가 소스 옆에 컴파일 결과를 그대로 방출하기 때문입니다(pnpm typecheck가 쓰는 vue-tsc --noEmit은 문제없음). 이번 PR 범위(wwwroot/assets 재해시)와는 별개의 구조적 문제라 이번에는 손대지 않았습니다.

완료 (Backend 구현 + 테스트, 2026-08-07 기준 검증됨)

VS-03: 모델 승인 워크플로우 (Maker-Checker Governance)

  • 위치: src/KArtSell.Modules.ModelOperations/ApprovalWorkflow/
  • 테스트: 20/20 PASS (격리 실행 기준)
  • 미완료: 프런트엔드 UI 없음
  • 이번 세션에서 발견/수정한 결함: ApprovalSql이 Dapper로 DateOnly 파라미터를 바인딩하지 못해 승인 제안서 생성이 실 DB 환경에서 100% 실패하던 버그 — 병합 이후 실 DB로 한 번도 검증되지 않아 발견되지 않고 있었음

VS-04: 불변 감사 추적 (Audit Trail / GDPR)

  • 위치: src/KArtSell.Modules.ModelOperations/Compliance/
  • 테스트: 5/5 PASS (격리 실행 기준)
  • 미완료: 프런트엔드 UI 없음
  • 이번 세션에서 발견/수정한 결함: ip_address/kis_response류 컬럼의 Dapper 타입 캐스팅 실패, GdprRetention.RetentionEndsAtDATE 컬럼인데 DateTime으로 선언되어 있던 문제, 그리고 KArtSell.BuildingBlocks[ModuleInitializer]가 우연히 로드되지 않으면 모든 snake_case 컬럼이 null로 매핑되던 레이스 컨디션

VS-10: 매도 결정 엔진 (Sell Decision Engine)

  • 위치: src/KArtSell.Modules.ModelOperations/SellDecision/, frontend/src/features/sell-decision/
  • 테스트: 32/32 PASS (격리 실행 기준)
  • 완료도: Backend + Frontend 모두 존재 (VS-03/04/12/14 중 유일)
  • ⚠️ 미검증 사항: 코드/테스트 완료 ≠ PBO/DSR 프로덕션 검증 완료. 실 시장 데이터 기반 검증은 Phase 1 Shadow Run 완료 후에만 가능

VS-12: 거래 실행 시스템 (Trade Execution, KIS 연동)

  • 위치: src/KArtSell.Modules.ModelOperations/TradeExecution/
  • 테스트: 13/13 PASS (격리 실행 기준)
  • 미완료: 프런트엔드 UI 없음
  • 이번 세션에서 발견/수정한 결함 (심각): UpdateTradeStatusAsyncstatus/kis_response/error_message만 저장하고 kis_order_id, executed_quantity, unit_price, commission, net_proceeds, 체결/정산 타임스탬프는 병합 이후 매번 조용히 유실시키던 버그. 거래 체결·정산 데이터가 실제로는 저장되고 있지 않았음

VS-14: 포트폴리오 대사 (Portfolio Reconciliation)

  • 위치: src/KArtSell.Modules.ModelOperations/PortfolioReconciliation/
  • 테스트: 18/18 PASS (격리 실행 기준)
  • 미완료: 프런트엔드 UI 없음
  • 참고: 이 슬라이스가 포함된 PR(#28)이 병합 당일 model_operations.models 테이블 누락으로 신규 DB 마이그레이션을 전부 깨뜨리는 채로 병합되었고, 같은 날 별도 PR(#29)로 긴급 수정됨 — 병합 전 fresh-install 리허설이 실제로 이루어지지 않았음을 시사

AEG-X-009: 외부 데이터 소스 통합 (KRX/OpenDart/KIS)

  • 위치: src/KArtSell.Modules.ModelOperations/Infrastructure/, market_data 스키마
  • 완료: 소스 카탈로그/거버넌스 정책(Workstream D/E/F) + 실 API 연동(Workstream G: KRX OpenAPI/OpenDart/KIS 서비스, 일일 스케줄링, 에러 분류, LKG 폴백)

그 외 완료 항목 (VS-00 플랫폼 부트스트랩, VS-01/VS-02 슬라이스 스펙, 보안/Outbox/OpenAPI 게이트 등)

상세는 docs/CURRENT/CATALOGS/WBS_PROGRESS_TRACKER.csv의 AEG-X-001008, AEG-VS-00-0107, AEG-VS-01-01, AEG-VS-02-01 행 참조.


🔴 실제로 블로킹 중인 것 (Phase 1 Shadow Run)

PHASE-1-SHADOW-RUN: 252+ 거래일 검증 (Gate 5a)

  • 상태: BLOCKED실행 중이 아님
  • 근거: docs/CURRENT/PHASE-1_SHADOW_RUN_STATUS_CORRECTION.md에 이미 정정되어 있음 — 과거 세션들의 "Job 893/976 RUNNING, ~20+시간 경과" 등의 기록은 실제로는 POST /api/shadow-runsPostgresException 23514(check_status 제약조건 위반)로 500 에러를 반환하며 실패한 것이었고, Job이 실제로 시작된 적이 없음
  • 차단 사유: 서버 측 dataset_manifest, model_version_registry, evidence_snapshot, release_evidence_bundle에 승인/동결된 행이 없어 RunId/JobId를 생성할 수 없음. 승인된 VersionSet 대기 중
  • 재개 절차: PHASE-1_SHADOW_RUN_STATUS_CORRECTION.md의 5단계 참조 (① check_status 제약조건 정합 ② 승인된 테스트 DB에서 fresh/upgrade/재실행/실패복구 리허설 ③ 증거 보존 ④ 명시적 승인 획득 ⑤ 신규 Run ID/Job ID로 재큐잉)
  • 이 상태가 바뀌려면: 실제 RunId/JobId가 존재해야 하며, 문서에 "RUNNING"이라고 다시 적으려면 그 근거를 반드시 명시해야 함 (과거의 허위 기록을 반복하지 말 것)

이 게이트는 달력 시간이 필요한 작업입니다 (252+ 거래일 시뮬레이션은 컴퓨팅으로 앞당길 수 없음). "최적 전략적으로 빨리 끝내기"의 대상이 될 수 없고, 남은 유일한 실행 가능 조치는 위 재개 절차를 밟아 실제로 큐잉하는 것뿐입니다.


📚 관련 문서

  • WBS 트래커 (항목별 상세 상태): docs/CURRENT/CATALOGS/WBS_PROGRESS_TRACKER.csv
  • WBS 원 계획 (번호 충돌 있음, 주의): docs/CURRENT/CATALOGS/WBS_MASTER.csv
  • Phase 1 상태 정정 기록: docs/CURRENT/PHASE-1_SHADOW_RUN_STATUS_CORRECTION.md
  • Architecture: docs/03_ARCHITECTURE_BE_FE.md
  • Code Guidelines: CLAUDE.md
  • Tech Debt: TECH_DEBT_REGISTER.md

📝 이 문서를 다시 갱신할 때

  1. git log를 먼저 확인하세요. 이 문서와 main이 얼마나 벌어졌는지 (git log --oneline <이-문서-마지막-커밋>..main) 확인하지 않고 문서만 읽고 "현재 상태"를 판단하지 마세요.
  2. 테스트는 격리 실행으로 확인하세요. 전체 스위트 실행에서 통과했다고 해서 개별 기능이 안정적으로 통과하는 것은 아닙니다 (이번 세션에서 AuditSql이 정확히 이 이유로 놓칠 뻔했습니다 — --filter로 단일 클래스만 돌려서 재확인하세요).
  3. "완료"라고 쓰기 전에 실제 파일 경로와 테스트 결과를 직접 확인하세요. 이 저장소에는 검증 없이 "COMPLETE"/"100%"라고 선언한 문서가 매우 많습니다 (EXECUTION_COMPLETE_FINAL.md, WORK_COMPLETION_CERTIFICATE.md 등). 그 패턴을 반복하지 마세요.
  4. Phase 1 Shadow Run은 달력 시간 게이트입니다. 실제로 큐잉되어 진행 중이라는 구체적 증거(RunId/JobId) 없이 "진행 중"이라고 쓰지 마세요.