- Updated: OutboxPollerJob constructor now includes IDbConnectionFactory, AuditTrailConsumer
- Reason: DEBT-029 event-driven audit logging integration
- Impact: Tests now work with updated OutboxPollerJob signature
- Follows AGENTS.md v16.0: All test fixes validated
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Host 시작 완료 (포트 5002, Development 모드)
- Hangfire 8 workers 활성화
- Shadow Run API 요청 성공 (HTTP 202)
- Job ID 3227 생성 (2024-01-02 ~ 2024-09-10)
- 자동 실행 시작: 50-90 calendar days
- PBO/DSR/Crash recovery 자동 처리
문서 추가:
- docs/ROADMAP_FINAL_10_PERCENT.md (최종 10% WBS + 로드맵)
- 5개 Work Package (5a, 5a-M, 5b, 5c, 5d)
- AGENTS.md v16.0 13대 의사결정 기준 적용
- 성공 기준 & 의존성 명시
환경 설정 정정:
- KARTSELL_POSTGRES: Database=kartselldb, Password=kartsell4321@!
- ASPNETCORE_ENVIRONMENT=Development 필수
- appsettings.Development.json: Authentication Mode=DevelopmentHeader
모니터링:
- Hangfire Dashboard: http://127.0.0.1:5002/hangfire
- Job Status API: http://127.0.0.1:5002/api/shadow-runs/3227
Phase 1 진행률:
- 기간: 252+ 영업일 (50-90 calendar days)
- 상태: Queued → Running (자동)
- 다음 단계: Day 90 최종 사인오프
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Blocks submit, status, cancel, and settlement before HTTP or database writes and removes the KIS polling recurring job. Evidence: concrete adapter test 1/1 passed with zero HTTP calls. WBS remains IN_PROGRESS pending endpoint/startup override evidence.
Separates business holds from technical failures in the pure execution state machine. Evidence: targeted Release tests 3/3 passed; TRX SHA256 2F2CD06B1DFD3F76F336A0636598553599CD05CF7FA82E477DB160425975085F.
Adds a lease-loss/reacquire integration rehearsal and fixes Dapper due-schedule materialization with an explicit row DTO. Evidence: PostgreSQL test 1/1 passed; TRX SHA256 49627FF0180034D2A7A1E4393448C73D337D918E7CE47EA9FC2BDB144FBBA833.
Carries scheduledFor, catch-up policy, and maxCatchUp from the scheduler through the request model and transactional outbox. Evidence: targeted Release tests 5/5 passed; TRX SHA256 C1BF3EF274702305A29673D5B6A1C3A98D08B1716DA3CD8CB0EE710B5E6C12E6. Schedules remain disabled.
Systematic sweep of every *Handler registered in Program.cs (same
method that found DEBT-026/027) found ActivateModelHandler was the
last orphan in Features/ApprovalWorkflow/: no POST /approvals/{id}/activate
endpoint existed, so an Approved proposal could never reach Active -
the entire point of this maker-checker slice.
While wiring it up, found the handler's original call would have
overwritten the checker's approved_by/approval_notes with the
activating SRE's identity (it passed userEmail through
UpdateProposalStatusAsync's approvedBy parameter), and never set
activated_by/activated_at at all despite those columns existing since
migration 0036. Added a dedicated ApprovalWorkflowSql.ActivateProposalAsync
that only touches activation-specific columns, and a regression test
asserting the checker's approval record survives activation unchanged.
Also documents DEBT-029 (discovered, not fixed - genuine cross-cutting
scope): LogAuditEventCommandHandler is never called by any other
slice, so VS-27's audit trail is empty in production regardless of
activity even though its own tests pass. Downgraded AEG-VS-27-01 from
COMPLETED to BLOCKED in the tracker to reflect that honestly.
dotnet build KArtSell.sln -c Release: clean. Not run against a live
database this session.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
DEBT-022 previously only checked AuditSql/TradeSql/SellDecisionSql
(where the bug was first found) and left PortfolioReconciliation/
ApprovalWorkflow explicitly "not yet checked". This pass enumerates
every jsonb/inet column across db/migrations/*.sql (case-insensitive,
since several use JSONB/INET uppercase) and checks each for a C#
writer.
PortfolioReconciliation has no jsonb/inet columns at all.
ApprovalWorkflow's one jsonb column was already cast correctly.
Several other jsonb columns belong to unimplemented slices (no writer
yet, so no current bug surface).
Found one new, real instance of the bug: OpenDartService.CacheResultAsync
inserted a JSON string into opendata.opendart_cache.data_json JSONB
without a cast - same 42804 failure mode as the already-documented
cases, just never previously exercised. Fixed with @dataJson::jsonb.
dotnet build KArtSell.sln -c Release: clean. Not run against a live
database this session.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
PollTradeStatusHandler and ConfirmSettlementHandler were fully
implemented and registered in DI, but nothing in the running
application ever called them - no endpoint, no Hangfire job. A trade
submitted via POST /trades could reach Submitted and never progress:
KIS fills and settlement confirmations were never picked up. Same
class of gap as DEBT-026 (a complete handler with no caller).
Adds TradeStatusPollingJob, a Hangfire recurring job (every 2 minutes,
q-customer-sla queue) that polls Submitted/Accepted/PartiallyFilled
trades via PollTradeStatusHandler, then confirms settlement for
FullyFilled trades via ConfirmSettlementHandler. Registered in
Program.cs alongside the other recurring jobs.
dotnet build KArtSell.sln -c Release: clean. No dedicated test added
(thin orchestration over already-covered handlers; a fake
IKisTradeExecutionService/ITradeSql test double would be a new pattern
not used elsewhere in this codebase) and not run against a live
database or KIS - see TECH_DEBT_REGISTER.md DEBT-027.
Also corrected WBS_PROGRESS_TRACKER.csv's AEG-VS-28-01 row: the
trade-execution frontend UI agent actually succeeded on retry (it had
previously failed on the session spend limit) - the row still said
"failed, not resumed" from before the retry completed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
TradeExecution: TradeOutboxPublisher.PublishAsync replaced with
UpdateAndPublishAsync, which opens one connection/transaction, updates
trade status and writes the outbox message on it, then commits once.
Used by the 3 call sites that publish an event after a status update
(SubmitTradeHandler, PollTradeStatusHandler's FullyFilled branch,
ConfirmSettlementHandler).
PortfolioReconciliation: ReconcileTradeHandler now injects the
request-scoped IDbConnection (the same instance ReconciliationSql
already uses) instead of opening a second separate connection via
IDbConnectionFactory, begins one transaction shared by
ReconciliationEngine.ReconcileTradeAsync and the outbox writes, and
commits once. Required adding IDbTransaction-aware overloads of
GetHoldingAsync/UpsertHoldingAsync/InsertReconciliationLogAsync - the
read needed one too, since Npgsql throws if a command on a connection
with a pending transaction doesn't have it attached.
dotnet build KArtSell.sln -c Release: clean. Integration tests: 17
pure-logic tests pass, 13 DB-backed tests fail with the pre-existing
connection-refused error (no SSH tunnel in this environment) - the
transactional changes themselves are not yet verified against a live
database. Also corrected two WBS_PROGRESS_TRACKER.csv rows that
inaccurately said frontend UI work was "in progress" when the
background agents building VS-28/VS-29 UI had actually failed
(hit the session's spend limit) before committing anything.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
DEBT-026 (high impact): ProposeForReviewHandler + POST /approvals/{id}/propose
wires ApprovalWorkflowPolicy.CanProposeForReview, which previously had no
Handler/Endpoint calling it. Before this, a proposal created via POST
/approvals could never reach Approved/Active through the running application
- the maker-checker gate was not completable end-to-end via HTTP.
DEBT-025 (medium impact): GetApprovalByIdEndpoint (GET /approvals/{id}) +
ApprovalWorkflowSql.GetEvidenceForProposalAsync make evidence attached during
approval (PBO/DSR/OOS artifact links) readable via HTTP instead of only by
querying model_operations.approval_evidence directly.
Both discovered while resolving DEBT-017 earlier the same session. 4 new
tests added. dotnet build -c Release clean. Not verified against a live
database (no SSH tunnel open in this environment) - see
TECH_DEBT_REGISTER.md and WBS_PROGRESS_TRACKER.csv AEG-VS-26-01 for the
honest verification status; do not mark COMPLETED until a real Postgres
run passes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Merges the isolated-worktree agent's fix: stop committing Vite-generated
wwwroot/assets output, add frontend build step to the ci.yml publish job
so release zips still ship a real build.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
# Conflicts:
# CURRENT_ROADMAP.md