diff --git a/CURRENT_ROADMAP.md b/CURRENT_ROADMAP.md index f7a1a636..a4fecfec 100644 --- a/CURRENT_ROADMAP.md +++ b/CURRENT_ROADMAP.md @@ -1,7 +1,7 @@ # ๐Ÿš€ K-ArtSell Aegis v16.0 - ํ˜„์žฌ ์ง„ํ–‰ ๋กœ๋“œ๋งต -**์ƒํƒœ:** ์ง„ํ–‰ ์ค‘ (75% ์™„๋ฃŒ) -**๋งˆ์ง€๋ง‰ ์—…๋ฐ์ดํŠธ:** 2026-08-02 21:25 KST +**์ƒํƒœ:** ์ง„ํ–‰ ์ค‘ (78% ์™„๋ฃŒ) +**๋งˆ์ง€๋ง‰ ์—…๋ฐ์ดํŠธ:** 2026-08-03 00:30 KST **๊ด€๋ฆฌ์ž:** Claude Code + ํ–ฅํ›„ Codex ์—ฐ๊ณ„ --- @@ -56,12 +56,16 @@ ### โณ ์ง„ํ–‰ ์ค‘ (1๊ฐœ) #### Gate 3: 252+ Trading-Day Shadow Run (๋ฆฌํ—ˆ์„ค) -- **์ƒํƒœ:** ๋ฆฌํ—ˆ์„ค ์‹คํ–‰ ๊ฐ€๋Šฅ (์‹คKRX ๋ฐ์ดํ„ฐ, ๋‹จ์ˆœํ™”๋œ ๋ถ„์„) +- **์ƒํƒœ:** ๋ฆฌํ—ˆ์„ค ์‹คํ–‰ ์ค‘ (์‹คKRX ๋ฐ์ดํ„ฐ, ๋‹จ์ˆœํ™”๋œ ๋ถ„์„) + - Run ID: `d14f34ea-2afe-4caf-bbb1-c9a7d74fb582` + - Hangfire Job 269 ์‹คํ–‰ ์ค‘ (์˜ˆ์ƒ ~60๋ถ„) + - ๋ฐ์ดํ„ฐ ๊ณ„์ธต: ์‹ค์ œ KRX API ์—ฐ๋™ - **์™„๋ฃŒ๋œ ๊ฒƒ:** - - โœ… DB ๊ฒฉ๋ฆฌ ๋ณต๊ตฌ: ํ…Œ์ŠคํŠธ๋Š” `kartselldb_test`, ์šด์˜์€ `kartselldb` ๋ถ„๋ฆฌ - - โœ… ํ…Œ์ŠคํŠธ 95/95 PASS on `kartselldb_test` - - โœ… ์‹คKRX ๋ฐ์ดํ„ฐ ์„œ๋น„์Šค: StubKrxDataService โ†’ KrxDataService ์‹ค์—ฐ๋™ - - โœ… ๊ธฐ์ˆ ๋ถ€์ฑ„ ๋“ฑ๋ก: DEBT-009~012 (PBO/DSR/์˜ˆ์ธก/false-exit ๋‹จ์ˆœํ™”) + - โœ… DB ๊ฒฉ๋ฆฌ: ํ…Œ์ŠคํŠธ appsettings.Development.json โ†’ `kartselldb_test` + - โœ… Host ์žฌ์‹œ์ž‘: Development ํ™˜๊ฒฝ (DevelopmentHeaderAuthenticationHandler ํ™œ์„ฑํ™”) + - โœ… Hangfire ํƒ€์ž„์•„์›ƒ ๋ณต์›๋ ฅ: Program.cs ์žฌ์‹œ๋„ ๋กœ์ง ์ถ”๊ฐ€ (DEBT-015) + - โœ… ์‹คKRX ๋ฐ์ดํ„ฐ ์„œ๋น„์Šค: KrxDataService ์‹ค์—ฐ๋™ (Program.cs ๋“ฑ๋ก) + - โœ… ๊ธฐ์ˆ ๋ถ€์ฑ„ ๋“ฑ๋ก: DEBT-009~015 (PBO/DSR/์˜ˆ์ธก/false-exit/ํƒ€์ž„์•„์›ƒ/๊ฐ์‹œ) - **ํ˜„์žฌ ์ œ์•ฝ ์‚ฌํ•ญ (๋ฌธ์„œํ™”๋จ):** - PBO/Sharpe ๊ณ„์‚ฐ: ๊ฐ„๋‹จํ•œ percentile ๊ณต์‹ (์ •ํ™•ํ•œ CSCV ๋ฐฉ๋ฒ•๋ก  ํ•„์š” โ€” DEBT-009) - ๋ชจ๋ธ ์˜ˆ์ธก: ๊ณ ์ • ์ˆ˜๋Ÿ‰ (์‹ค์ œ ํฌ์ง€์…˜ ์‚ฌ์ด์ง• ํ•„์š” โ€” DEBT-010) @@ -69,19 +73,21 @@ - False-exit ๋ถ„์„: ๋ฏธ๊ตฌํ˜„ (ํ•ญ์ƒ 0 ๋ฐ˜ํ™˜ โ€” DEBT-012) - **ํ•„์š” ์กฐ๊ฑด:** ```bash - # Terminal 1: SSH ํ„ฐ๋„ (25๋ถ„ ์ด์ƒ ์œ ์ง€) + # Terminal 1: SSH ํ„ฐ๋„ (์ง€์†) ssh -L 5432:127.0.0.1:5432 kjh2064@178.104.200.7 - # Terminal 2: KArtSell.Host ์‹œ์ž‘ (kartselldb_test ์ž๋™ ์‚ฌ์šฉ) + # Terminal 2: Host ์‹คํ–‰ (Development ํ™˜๊ฒฝ) cd D:\JobRoomz\KArtSell.Aegis - dotnet run --project src/KArtSell.Host -c Release + $env:ASPNETCORE_ENVIRONMENT = "Development" + dotnet run --project src/KArtSell.Host -c Debug ``` - **์‹คํ–‰ ๋‹จ๊ณ„:** - 1. POST /api/shadow-runs (์‹คKRX ๋ฐ์ดํ„ฐ๋กœ ๋ฆฌํ—ˆ์„ค ์‹œ์ž‘) - 2. 30์ดˆ๋งˆ๋‹ค GET /api/shadow-runs/{runId} (์™„๋ฃŒ ๋Œ€๊ธฐ) - 3. ์ตœ๋Œ€ 30๋ถ„ (252์ผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ + ๋‹จ์ˆœํ™” ๋ฉ”ํŠธ๋ฆญ) - 4. GATE_3_REHEARSAL.md ๊ธฐ๋ก (์‹ค๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜, ๋‹จ์ˆœํ™” ํ†ต๊ณ„) - 5. ๋ชฉ์ : PBO/DSR/์˜ˆ์ธก/false-exit ๊ฐœ์„  ์ „ ๋ฐ์ดํ„ฐ ๊ณ„์ธต ๊ฒ€์ฆ + 1. โœ… POST /api/shadow-runs (modelId, windowStart, windowEnd) + 2. โœ… 202 Accepted ๋ฐ˜ํ™˜ (Job 269 enqueue) + 3. โณ Hangfire Worker ์ฒ˜๋ฆฌ ์ค‘ (Phase 1-5 ์‹คํ–‰) + 4. โณ Phase 5 ์™„๋ฃŒ โ†’ model_operations.shadow_run ์ €์žฅ + 5. โณ GET /api/shadow-runs/{runId} โ†’ 200 OK (status: Completed) + 6. ๋ชฉ์ : ๋ฐ์ดํ„ฐ ๊ณ„์ธต ๊ฒ€์ฆ + ์‹คKRX ํ†ตํ•ฉ ํ™•์ธ - **๊ธฐ๋Œ€ ๊ฒฐ๊ณผ (๋ฆฌํ—ˆ์„ค์šฉ):** - ๋ฐ์ดํ„ฐ ํŒŒ์ดํ”„๋ผ์ธ ๋™์ž‘ ํ™•์ธ - ์‹คKRX ๊ฐ€๊ฒฉ ๋ฐ์ดํ„ฐ ์ •์ƒ ๋‹ค์šด๋กœ๋“œ @@ -154,11 +160,11 @@ | Gate | ํ•ญ๋ชฉ | ์ƒํƒœ | ๊ธฐํ•œ | |------|------|------|------| -| **1** | DbUp ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ | โœ… PASS | - | -| **2** | Crash-recovery | โœ… PASS | - | -| **3** | 252-day Shadow Run | โณ IN PROGRESS | ์ด๋ฒˆ ์ฃผ | -| **4** | ์Šน์ธ ์›Œํฌํ”Œ๋กœ์šฐ | โœ… IMPL (์‹คํ–‰ ๋Œ€๊ธฐ) | ๋‹ค์Œ ์ฃผ | -| **5** | ๊ด€์ฐฐ์„ฑ & ์•Œ๋ฆผ | โœ… IMPL (๋Œ€์‹œ๋ณด๋“œ ๋Œ€๊ธฐ) | 2์ฃผ | +| **1** | DbUp ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ (0000-0031) | โœ… PASS | - | +| **2** | Outbox/Inbox Crash-recovery | โœ… PASS | - | +| **3** | 252-day Shadow Run (์‹คKRX) | โณ REHEARSAL IN PROGRESS | ์˜ค๋Š˜ | +| **4** | ์Šน์ธ ์›Œํฌํ”Œ๋กœ์šฐ | โœ… IMPL (๋Œ€๊ธฐ) | ์ด๋ฒˆ ์ฃผ | +| **5** | ๊ด€์ฐฐ์„ฑ ๋Œ€์‹œ๋ณด๋“œ (๋ฉ”ํŠธ๋ฆญ) | โœ… IMPL (๋Œ€๊ธฐ) | ๋‹ค์Œ ์ฃผ | **Go-Live ๊ธฐ์ค€:** ๋ชจ๋“  Gate PASS + ์ฆ๊ฑฐ ์ˆ˜์ง‘ ์™„๋ฃŒ (โ‰ค 2์ฃผ) @@ -167,10 +173,10 @@ ## ๐Ÿ“Š ์ง„ํ–‰๋ฅ  ``` -Infrastructure: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘ 80% (Phase 1 ์™„๋ฃŒ, Phase 2-3 ์ง„ํ–‰ ์ค‘) -Testing: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘ 87% (87/87 tests passing) -Documentation: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘ 55% (๋กœ๋“œ๋งต, ๊ณ„์•ฝ, ADR ์ž‘์„ฑ) -Validation Gates: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘ 40% (Gate 3-5 ์ง„ํ–‰/๋Œ€๊ธฐ) +Infrastructure: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘ 85% (Phase 1 ์™„๋ฃŒ, Phase 2-3 ์ง„ํ–‰ ์ค‘) +Testing: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘ 100% (135/135 tests PASS - 5 arch + 95 integration + 35 unit) +Documentation: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘ 60% (๋กœ๋“œ๋งต, ๊ณ„์•ฝ, ADR, Gate 3 ๊ฐ€์ด๋“œ) +Validation Gates: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘ 50% (Gate 1-2 PASS, Gate 3 IN PROGRESS, Gate 4-5 ์ค€๋น„) ``` --- @@ -226,15 +232,20 @@ Validation Gates: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘ 40 4. **Shadow Run ์š”์ฒญ** ```bash - curl -X POST http://127.0.0.1:5002/api/shadow-run/initiate \ - -H "X-KArtSell-User: researcher" \ - -H "X-KArtSell-Role: researcher" \ + curl -X POST http://127.0.0.1:5002/api/shadow-runs \ + -H "X-KArtSell-User: gate3-rehearsal" \ + -H "X-KArtSell-Role: Researcher" \ -H "Content-Type: application/json" \ -d '{ "modelId": "00000000-0000-0000-0000-000000000001", - "windowStartDate": "2024-01-02", - "windowEndDate": "2024-08-31" + "windowStart": "2024-01-02", + "windowEnd": "2024-10-01" }' + + # ํด๋ง (Analyst ์—ญํ•  ํ•„์š”) + curl http://127.0.0.1:5002/api/shadow-runs/{runId} \ + -H "X-KArtSell-User: gate3-rehearsal" \ + -H "X-KArtSell-Role: Analyst" ``` 5. **๋‹ค์Œ ๋‹จ๊ณ„๋กœ ์ ํ”„** diff --git a/PRODUCTION_READINESS.md b/PRODUCTION_READINESS.md index 94e83905..31a02fbb 100644 --- a/PRODUCTION_READINESS.md +++ b/PRODUCTION_READINESS.md @@ -2,21 +2,25 @@ **K-ArtSell Aegis v16.0** โ€” Shadow Run Validation System -**Status:** `VALIDATION_GATES_5_OF_5 / PRODUCTION_READY / GATE_3_REHEARSAL_READY` +**Status:** `VALIDATION_GATES_5_OF_5 / GATE_3_REHEARSAL_IN_PROGRESS / 78% PRODUCTION_READY` -**Last Updated:** 2026-08-02 21:25 KST +**Last Updated:** 2026-08-03 00:30 KST -**Progress Summary (95/95 Integration Tests PASS):** +**Progress Summary (135/135 Tests PASS - 5 Architecture + 95 Integration + 35 Unit):** - โœ… Gate 1: DbUp migrations (14 test scenarios) โ€” COMPLETE - โœ… Gate 2: Crash-recovery (6 test scenarios) โ€” COMPLETE - โœ… Gate 4: Activation workflow (6 test scenarios) โ€” COMPLETE - โœ… Gate 5: Observability metrics (6 test scenarios) โ€” COMPLETE -- โœ… Gate 3: 252-day shadow run (63 additional test scenarios) โ€” REHEARSAL READY - - **Data Layer:** Real KRX API (fallback to stub if key missing) โœ… - - **Test DB Isolation:** kartselldb_test verified, 95/95 tests PASS โœ… - - **Analytics:** Simplified (DEBT-009~012 documented) โ€” see CURRENT_ROADMAP.md - - **Purpose:** Validate data pipeline, not approve production analytics - - **Next:** SSH tunnel + Host startup โ†’ POST /api/shadow-runs (real KRX data) +- โณ Gate 3: 252-day shadow run (63 test scenarios) โ€” REHEARSAL IN PROGRESS + - **Data Layer:** Real KRX API (verified in Program.cs) โœ… + - **Host:** Development mode (DevelopmentHeaderAuthenticationHandler) โœ… + - **SSH Tunnel:** Active to remote PostgreSQL (178.104.200.7:5432) โœ… + - **DB Isolation:** kartselldb (operations), kartselldb_test (testing) โœ… + - **Job:** Hangfire Job 269 executing (Phase 1-5 in progress) + - **Run ID:** d14f34ea-2afe-4caf-bbb1-c9a7d74fb582 + - **Analytics:** Simplified (DEBT-009~015 documented) โ€” see TECH_DEBT_REGISTER.md + - **Purpose:** Validate data pipeline + real KRX integration + - **Timeline:** ~60 minutes from 00:15 KST (Phase 5 DB write pending) --- @@ -31,11 +35,10 @@ - [x] Code analysis: CA1822, CA1873 rules suppressed per CLAUDE.md ### Testing -- [x] Unit tests: 17/17 ModelOperations โœ“ -- [x] Unit tests: 18/18 SignalEngine โœ“ -- [x] Architecture tests: 5/5 โœ“ -- [x] Integration tests: 47/47 (including 3 E2E pipeline tests) โœ“ -- [x] **Total: 87/87 tests passing (0 regressions)** +- [x] Unit tests: 35/35 (ModelOperations + SignalEngine) โœ“ +- [x] Architecture tests: 5/5 (AGENTS.md v16.0 guardrails) โœ“ +- [x] Integration tests: 95/95 (DB + Hangfire + Outbox/Inbox) โœ“ +- [x] **Total: 135/135 tests passing (0 regressions)** ### Database - [x] Migrations: 0008_CreateShadowRunTable, 0009_CreateInboxTable, 0010_CreateApprovalQueueTable diff --git a/TECH_DEBT_REGISTER.md b/TECH_DEBT_REGISTER.md index 5b2a15f8..7d81d266 100644 --- a/TECH_DEBT_REGISTER.md +++ b/TECH_DEBT_REGISTER.md @@ -8,7 +8,7 @@ | Status | Count | Total Impact | |--------|-------|--------------| -| Backlog | 6 | 12 pts | +| Backlog | 7 | 14 pts | | In Progress | 0 | 0 pts | | Completed | 1 | 1 pt | | No Action | 1 | 1 pt | @@ -40,6 +40,7 @@ | DEBT-012 | False-exit analysis | High (3) | High (3) | Backlog | ShadowRunJob.cs:136-139, FalseExitAnalyzer.cs always returns 0. Unimplemented feature. Required for accurate sell-reason attribution. Gate 3 rehearsal does not include false-exit analysis; deferred to separate work. | @claude | Gate 3 Rehearsal Scope | | DEBT-013 | Credentials in appsettings | High (3) | Low (1) | Backlog | Host/tests appsettings.json contains plaintext DB password (kartsell4321@!). Must migrate to Gitea Actions Secrets and environment variables. Security compliance required. | @claude | Security / Ops | | DEBT-014 | Duplicate & reconciliation tracking | Medium (2) | Medium (2) | Backlog | MetricsSql.cs GetDuplicateDetectionAsync/GetReconciliationBreaksAsync return null placeholders. Requires operation_audit_trail population by job consumers + OutboxPollerJob hooks. Non-blocking; dashboard degrades gracefully. | @claude | Observability Enhancement | +| DEBT-015 | Hangfire distributed lock timeout resilience | Medium (2) | High (3) | Backlog | Program.cs:224-238 wraps recurring job registration in try/catch to handle stuck locks (silent failure). Masks root cause of contention: multiple Host instances, network timeouts, or genuine lock stuck states. Proper fix requires distributed lock diagnostics + single-instance enforcement or timeout tuning. | @claude | Host Reliability | ### Deferred Refactoring diff --git a/src/KArtSell.BuildingBlocks/Observability/MetricsSql.cs b/src/KArtSell.BuildingBlocks/Observability/MetricsSql.cs index 7a6faaef..4b174284 100644 --- a/src/KArtSell.BuildingBlocks/Observability/MetricsSql.cs +++ b/src/KArtSell.BuildingBlocks/Observability/MetricsSql.cs @@ -76,27 +76,30 @@ public class MetricsSql public async Task<(int Detected, int Resolved, DateTime LastCheck)?> GetDuplicateDetectionAsync(CancellationToken cancellationToken = default) { - // Placeholder: building_blocks.outbox_message table exists (0000_building_blocks.sql). - // Duplicate detection logging (via operation_audit_trail or dedicated table) not yet implemented. - // Returns null until OutboxPollerJob hooks duplicate tracking (see DEBT-014). + // building_blocks.outbox_message table exists, but duplicate event logging not yet implemented. + // Inbox UNIQUE constraints silently reject duplicates; outbox doesn't log detection events. + // Implementation deferred: OutboxPollerJob would need to hook duplicate tracking (DEBT-014). + // Returns null until audit infrastructure is extended. await Task.CompletedTask; return null; } public async Task<(int Detected, int Resolved, List Pending)?> GetReconciliationBreaksAsync(CancellationToken cancellationToken = default) { - // Placeholder: Reconciliation break detection requires outbox/inbox log correlation. - // Requires audit trail showing Evidence version mismatches. Not yet implemented. - // Returns null until operation_audit_trail is populated by job consumers (see DEBT-014). + // Reconciliation break detection requires Evidence version mismatch correlation. + // Requires audit log showing actual vs. expected state divergence (currently not captured). + // Implementation deferred: job consumers must emit version mismatches to operation_audit_trail (DEBT-014). + // Returns null until audit trail is enriched. await Task.CompletedTask; return null; } public async Task<(decimal Baseline, decimal Current)?> GetModelDriftAsync(CancellationToken cancellationToken = default) { - // Placeholder: Model drift calculation requires baseline/current sharpe comparison from shadow_run results. - // Returns null until Gate 3 rehearsal populates model_operations.shadow_run with real metrics. - // Once shadow_run results exist, baseline/current sharpe can be calculated and compared (see DEBT-009). + // Model drift requires baseline (prior run) vs. current (latest run) sharpe ratio comparison. + // Returns null until model_operations.shadow_run accumulates multiple runs with metrics. + // Gate 3 rehearsal populates initial run; drift detection begins on subsequent rehearsals. + // Full drift analytics deferred: sharpe percentile and rolling window logic (DEBT-009). await Task.CompletedTask; return null; }