Files
KArtSell.Aegis/AGENTS.md
T
kjh2064 74ddd95a05
ci / backend (push) Failing after 0s
ci / static (push) Failing after 6s
ci / backend (pull_request) Failing after 1s
ci / static (pull_request) Failing after 7s
Build & Test with Secrets / build (pull_request) Failing after 1s
ci / frontend (push) Failing after 48s
Build & Test with Secrets / security-scan (pull_request) Successful in 5s
Build & Test with Secrets / frontend (pull_request) Failing after 1m23s
ci / frontend (pull_request) Failing after 1m32s
Build & Test with Secrets / notification (pull_request) Failing after 2s
테스트 DB 계약과 실행 안전성 정렬
2026-08-02 17:37:12 +09:00

307 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# K-ArtSell Aegis AI Coding Constitution v12.0
1. 자동주문과 KIS 제출 Capability는 OFF다. 별도 승인 Release 전 구현·활성화·우회하지 않는다.
2. 채팅과 생성 코드는 Source of Truth가 아니다. 모든 변경은 Source / Assumption / Unknown / Decision Required를 표시한다.
3. 한 PR은 한 Vertical Slice 또는 한 동작보존 리팩터링 목적만 가진다.
4. Endpoint→Application→Pure Policy→Dapper SQL→Outbox→Tests 경계를 지킨다.
5. Domain Policy는 시간·랜덤·네트워크·DB·DI Container를 직접 읽지 않는다.
6. Generic Repository, God Service, Service Locator, Job 내 비즈니스 정책, 조기 Microservice 분리를 금지한다.
7. 모듈은 다른 모듈 Source Table을 직접 조회하지 않는다. 승인된 Contract/Read Model만 사용한다.
8. `DateTime.Now/UtcNow`를 직접 사용하지 않고 IClock과 MarketCalendar를 사용한다.
9. 금융값은 decimal, 명시적 rounding, 단위 계약을 사용한다. 모델 내부 double은 경계에서 변환한다.
10. `SellRatioOfLot`, `SellQuantity`, `TargetPortfolioWeightAfter`, `StrategicCoreFloorWeight`를 혼용하지 않는다.
11. EvidenceSnapshot·DatasetId·Model/Config/Code SHA 없이 Decision/Recommendation을 저장하지 않는다.
12. Command/Job는 IdempotencyKey/JobRunId/Watermark를 갖고 replay를 견딘다.
13. Evidence/Decision/Audit는 update/delete하지 않고 append/correction event로 보존한다.
14. Write Model은 정규화·append·revision, 화면은 version/watermark/rebuild가 있는 Read Model이다.
15. 서버 상태는 TanStack Query가 소유한다. Pinia에 API 응답을 복제하지 않는다.
16. FE request/response는 Zod로 runtime validation하고 같은 retry에 같은 Idempotency-Key를 재사용한다.
17. `/internal/*` Endpoint는 Roles 또는 Policies를 선언하며 익명 접근을 허용하지 않는다.
18. 알고리즘 변경은 Policy ID, Golden, Frozen OOS, cost×2, false-exit/reentry/ES, ModelCard를 동반한다.
19. 새 library/pattern/table/threshold는 ADR/Issue 승인 없이 도입하지 않는다.
20. 실행하지 못한 build/test/migration을 통과했다고 기록하지 않는다.
21. AI 생성 Migration은 fresh/upgrade/re-run/failure rehearsal 및 DBA 승인 없이는 병합하지 않는다.
22. 실고객 데이터·실계좌·실주문 키·secret를 prompt/fixture/log/trace에 넣지 않는다.
23. Metric·Alert·Runbook·Rollback·Owner/Secondary가 없으면 Done이 아니다.
## v12.1 execution-readiness delta
- Every change must cite Requirement/Slice/Policy/Data/API/DB/Job/UI/Test IDs.
- Production commands load Evidence/Model/Config from approved server-side PIT context; never trust client-supplied evidence.
- Write models are normalized and append/correction based. Denormalization is allowed only in versioned, rebuildable read models.
- Outbox/Inbox/JobRun/Projection operations require scope, idempotency, watermark, hashes, and replay evidence.
- No generic repository, God service, reflection plugin framework, premature microservice, or unapproved threshold.
- Refactoring and policy changes must be separate PRs with characterization or Golden tests first.
- Never claim a build, migration, test, Shadow period, PBO, or DSR result that was not executed and preserved as evidence.
## v12.2 strategic data-semantics delta
- `CurrentSecurityPortfolioWeight`, `CurrentLotPortfolioWeight`, `SellRatioOfLot`, and `StrategicCoreFloorWeight` are distinct units. Never reintroduce the ambiguous `CurrentPortfolioWeight` into active decision code.
- A lot-relative sell changes security weight by `CurrentLotPortfolioWeight * SellRatioOfLot`.
- Persist the ordered policy trace with Applied/Blocked/NotApplicable dispositions; do not expose raw internal scores directly to customers.
- Prior migrations are immutable. v12.2 changes belong in migration `0014` or later.
- The six current-session attachments and their SHA-256 values are part of the release evidence.
- Use the reviewed templates under `templates/`; do not bulk-generate unapproved modules or placeholder implementations.
## v12.3 execution and semantic-version delta
- `weight_semantics_version=1` contexts are legacy ambiguous data and must never enter active decisions; rebuild them as version 2 from explicit security and lot weights.
- A positive opportunity edge with a zero or missing requested sell ratio is BLOCKED. Never clamp missing intent to a minimum sell.
- Policy IDs, priorities and thresholds must match `contracts/policies/sell-policy-contract.v1.json`; drift blocks G2.
- Decision/API/Event/DB evidence must preserve `decision_contract_version` and `policy_trace_schema_version`.
- Outcome metrics must name a definition version, population, numerator, denominator, window and aggregation. Do not equate 63-session research output with an annual target without approval.
- `scripts/scaffold_slice.py` is dry-run by default, refuses overwrite and produces SCAFFOLD_ONLY code. Generated files are not approved implementation.
- The seven cumulative attachments and their SHA-256 values are part of v12.3 release evidence.
## v12.4 Model Operations Constitution
- Scheduler automation is limited to EVALUATION_ONLY, PROPOSAL_ONLY and DRILL_ONLY.
- Never generate or merge automatic model promotion, rollback, threshold mutation, code change, automatic order or KIS submission paths.
- Every evaluation request freezes Dataset/Model/Config/Code/Contract VersionSet from an approved server-side context.
- Metric changes require a versioned numerator, denominator, window, aggregation, PIT/revision rule and Golden/OOS impact.
- Improvement proposals are documents and records only; they do not edit model, policy, configuration or source files.
- Drift thresholds, false-exit definition and retention policy are DECISION_REQUIRED until approved.
## v14.0 UI / Model Feedback non-negotiables
- Feature code MUST NOT import PrimeVue or AG Grid directly. Use shared UI ports and screen types.
- UI provider changes require contract, accessibility, visual, state-matrix and performance evidence.
- Model operation automation stops at evaluation/proposal. Model activation is human change approval only.
- J39 and every new schedule remain disabled until their source, calendar, ownership and alert contracts are approved.
- Never claim .NET, pnpm, PostgreSQL, Playwright or Shadow evidence passed unless the actual artifact is attached.
## v16.0 Gitea API & CI/CD Automation
### Environment Setup
**Gitea API Token:**
```bash
# Set GITEA_TOKEN_TAXBAIK environment variable
# This token enables:
# - Pull request automation (labels, milestones, comments)
# - Issue management (create, update, close)
# - Release management (tags, release notes)
# - CI/CD pipeline integration
# On Windows (PowerShell):
$env:GITEA_TOKEN_TAXBAIK = "your-token-here"
# On macOS/Linux (bash):
export GITEA_TOKEN_TAXBAIK="your-token-here"
# Verify:
echo $GITEA_TOKEN_TAXBAIK
```
### Gitea API Patterns
**Common endpoints (https://gitea.taxbaik.com/api/v1):**
```bash
# Create a PR comment
curl -X POST \
-H "Authorization: token $GITEA_TOKEN_TAXBAIK" \
-H "Content-Type: application/json" \
-d '{"body":"Verification complete: 41/41 tests passed"}' \
https://gitea.taxbaik.com/api/v1/repos/kjh2064/KArtSell.Aegis/issues/{issue_id}/comments
# Add labels to PR
curl -X POST \
-H "Authorization: token $GITEA_TOKEN_TAXBAIK" \
-d '["architecture","verified"]' \
https://gitea.taxbaik.com/api/v1/repos/kjh2064/KArtSell.Aegis/issues/{pr_number}/labels
# Create release with notes
curl -X POST \
-H "Authorization: token $GITEA_TOKEN_TAXBAIK" \
-H "Content-Type: application/json" \
-d '{"tag_name":"v16.0.1","body":"Release notes..."}' \
https://gitea.taxbaik.com/api/v1/repos/kjh2064/KArtSell.Aegis/releases
# Query PR/Issue
curl -H "Authorization: token $GITEA_TOKEN_TAXBAIK" \
https://gitea.taxbaik.com/api/v1/repos/kjh2064/KArtSell.Aegis/pulls?state=open
```
### CI/CD Integration (Gitea Actions)
**Leverage in `.gitea/workflows/ci.yml`:**
```yaml
- name: Comment on PR with test results
if: github.event_name == 'pull_request'
run: |
curl -X POST \
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
-H "Content-Type: application/json" \
-d "{\"body\":\"Build: ✅ Tests: 41/41 PASS\"}" \
https://gitea.taxbaik.com/api/v1/repos/kjh2064/KArtSell.Aegis/issues/${{ github.event.pull_request.number }}/comments
```
### Automation Best Practices (from v16.0)
- **PR Labels:** Auto-label based on affected module (e.g., `ModelOperations`, `SignalEngine`)
- **Milestones:** Link PRs to quarterly sprints for burndown tracking
- **Comments:** Post verification results (build, test, security scan) directly on PR
- **Releases:** Tag with semver + architecture contract version (e.g., `v16.0.1-contract-v3.0`)
- **Issue Linking:** Reference debt IDs, ADRs, decision logs in commits (e.g., `TECH-001: Fix CA1822`)
---
## v16.0 Strategic Architecture & Engineering Excellence
### Decision Criteria for All Work
Every task — code change, refactor, new feature, tooling, infrastructure — must be evaluated against these dimensions before implementation:
#### 1. SOLID 원칙
- **S**ingle Responsibility: One class, one reason to change. Vertical Slice boundaries are trust boundaries.
- **O**pen/Closed: Open for extension (new Policies, new decision gates); closed for modification (immutable Evidence, append-only migrations).
- **L**iskov Substitution: Handlers, Policies, Adapters are swappable; never break contract.
- **I**nterface Segregation: IClock ≠ IDateTime; IOutboxWriter ≠ IEventBus. Ports are narrow.
- **D**ependency Inversion: Depend on abstractions (IClock, ILogger, IOutboxWriter); inject concretions at composition root only.
- **적용:** 모듈 경계 설계, 인터페이스 분리, 스태틱 메서드 vs 인스턴스 메서드 판단.
#### 2. 코드 리팩토링 (Code Mass & Complexity)
- Cyclomatic Complexity ≤ 10 per method (Policy는 예외: decision trees는 복잡해질 수 있음).
- Characterize → Isolate → Transform → Verify → Simplify → Observe → Close Debt (정공법).
- Dead code, unused flags, unreachable branches는 즉시 삭제. "혹시 필요할까봐"는 금지.
- Performance refactor와 기능 변경은 분리된 PR. 동시 변경은 회귀 탐지 불가.
#### 3. 데이터 정합성 (Data Integrity & Audit)
- **PIT (Point-in-Time):** `WHERE published_at <= cutoff AND revision = latest` 필수. 시간 여행 쿼리는 audit 목적만.
- **Revision Tracking:** update/delete 금지. 새 버전을 append로 저장. 수정은 correction event로 보존.
- **Audit Trail:** EvidenceSnapshot, DatasetId, Model/Config/Code SHA는 Decision과 함께 저장. Trace 불가능하면 미완성.
- **적용:** 모든 쓰기는 append/correction 패턴. 읽기는 PIT 조건. 마이그레이션은 회원가입 없음.
#### 4. 과유불급 (Necessity-Driven, No Gold-Plating)
- "혹시 나중에 필요하면"으로 코드를 추가하지 않는다. 근거 없는 추상화 금지.
- 한 곳에서만 쓰면 분리하지 않는다. 세 곳에서 반복되면 그때 abstract.
- Feature flag, backward-compat shim, deprecation layer는 근거 있을 때만. 사용하지 않는 코드는 삭제.
- **적용:** 새 service/interface/config 도입 전에 "이것이 정말 필요한가?" 자문.
#### 5. 정규화 & 역정규화 (Normalization Strategy)
- **Write Models:** 3NF + append + revision. 중복 없음, 관계 명확, 이상 불가.
- **Read Models:** Denormalized projections. 1NF 위반 허용 (성능, 접근성). 모든 Read는 versioned, rebuildable.
- **경계:** Write는 Dapper로 스키마-규정. Read는 쿼리 최적화. 양쪽 스키마 감시.
- **적용:** 새 column 추가 전에 "이것은 3NF 위반인가? 그렇다면 projection으로."
#### 6. 프로세스 단순화 (Simplicity & Clarity)
- 한 번에 한 가지만 한다. 다중 책임 = 다중 이해 실패 = 버그.
- "왜 이 순서인가?" 묻지 않아도 명확한 코드. 숨겨진 전제 금지.
- Circular dependency, magic numbers, implicit state 제거.
- **적용:** 코드 흐름이 위→아래로 읽혀야 함. 뒤로 돌아가며 읽어야 하면 리팩터.
#### 7. 패턴화, 표준화, 구조화 (Patterns & Standards)
- Vertical Slice는 단일 패턴. Endpoint → Handler → Policy → Dapper → Outbox.
- Job은 단일 책임. 비즈니스 정책은 들어가지 않음. 승인된 Command만 실행.
- Event schema는 contract-first. 구독자가 없으면 이벤트도 없음.
- **표준 컴포넌트:** QueryStateBoundary, CrudForm, PermissionGuard 등은 모든 화면에서 재사용. 직접 import 금지.
- **적용:** 새 pattern/component 도입 전 팀 검토. 코드 사본 3개 = abstract 신호.
#### 8. 바이브코딩 & 홀루시네이션 통제 (AI Guardrails)
- AI 생성 코드는 근거 없음. Source/Assumption/Decision 반드시 기록.
- **금지:** 근거 없는 Policy ID, threshold, DB column, API endpoint.
- SQL은 schema owner, PIT 조건, index, execution plan 검토 필수.
- 알고리즘 변경은 Golden/Frozen OOS diff 없이 병합 금지.
- **적용:** "이 값은 어디서 나왔나?" 묻는 습관. 답 없으면 DECISION_REQUIRED 표시.
#### 9. 현장감, 재현성, 이력성 (Traceability & Reproducibility)
- **현장감:** Build/test/migration artifact는 보존. "통과했다고 주장"하되 증거 없으면 거짓.
- **재현성:** 동일 input → 동일 output. Random, network, system time 의존은 격리. Mock 금지, integration test로.
- **이력성:** Commit message는 "왜"를 기록. "버그 수정"은 불충분. "X 기능에서 Y 조건에서 Z 버그 → 원인: 로직 오류" 기록.
- **적용:** CI/CD 결과물 저장, 회귀 테스트 잠금, ADR에 의사결정 기록.
#### 10. 안정성 (Reliability & Safety)
- Idempotency: 같은 요청 → 같은 결과. 두 번 실행해도 안전.
- Rollback 불가능한 변경 금지. Migration도 down script 필수.
- Failure mode: 각 Job/Endpoint은 실패했을 때 상태를 명확히. "실패했는데 부분 성공?" 금지.
- **적용:** Command/Job는 IdempotencyKey, Watermark 필수. DB constraint, NOT NULL 검증.
#### 11. 고도화 & 컴포넌트화 (Componentization & Maturity)
- 한 번 제대로. 임시방편 금지. 기술부채는 Debt register에 기록.
- 구현 전 contract/schema/test 먼저. "하면서 배운다"는 설계 부실의 신호.
- 버전 관리: 기능이 아닌 contract 버전. API/Event/DB schema 버전 분리.
- **적용:** Release note에는 contract version, breaking change, migration step 명시.
#### 12. 정공법 (Right Way, Not Shortcuts)
- 안 되는 길에 시간 낭비하지 말되, 편한 길도 피한다 (--no-verify, force push).
- 문제 근본 해결. Symptom 치료는 debt 증가.
- 리뷰어가 "이게 최선인가?" 묻는 코드는 재작성. "충분히 좋다" ≠ "최선".
- **적용:** Build 실패 → --no-verify X, 원인 파악. Merge conflict → cherry-pick X, rebase 제대로.
#### 13. 기술부채 관리 (Tech Debt Registry)
- 부채는 기록하는 순간부터 이자 발생. 미루지 말 것.
- **Debt ID:** TECH-001 등으로 추적. PR/commit에서 참조.
- **우선순위:** Impact (얼마나 큰가) × Effort (고치는 데 드는 비용). 고영향 저비용 우선.
- **Paydown:** 분기마다 debt 20% 감축 목표. 신규 debt > paydown이면 질식.
- **적용:** README.md의 TECH_DEBT_REGISTER 매월 검토. 3개월 미해결 = 리팩터 스프린트 필요.
### Work Decision Checklist
모든 task에 대해 다음을 자문:
- [ ] **SOLID:** 이 변경이 단일 책임인가? Dependency inversion을 지킬 것인가?
- [ ] **Complexity:** 함수/메서드 복잡도는 10 이하인가? (Policy 예외)
- [ ] **Audit:** Evidence/Revision 추적 가능한가? PIT 쿼리 있는가?
- [ ] **Necessity:** 근거 있는 변경인가? "혹시 필요하면" 아닌가?
- [ ] **Normalization:** 쓰기는 3NF, 읽기는 projection인가?
- [ ] **Simplicity:** 위→아래로 읽혀야 하는가? 숨겨진 전제 없는가?
- [ ] **Pattern:** 표준 Slice/Job/Component 따르는가? 새 패턴 도입은 검증됐는가?
- [ ] **Guardrails:** 근거 있는가? "왜"를 기록했는가?
- [ ] **Traceability:** Artifact 보존되는가? Reproduction 가능한가? ADR/Issue 링크 있는가?
- [ ] **Safety:** Idempotent인가? Rollback 가능한가? 부분 실패 케이스 처리했는가?
- [ ] **Maturity:** 임시방편 아닌가? Contract/schema/test 먼저 했는가?
- [ ] **Right Way:** Shortcut (--no-verify, force) 안 썼는가? 근본 해결했는가?
- [ ] **Debt:** 새로운 debt 만들지 않는가? 기존 debt 감축하는가?
### Anti-Patterns (금지)
- ❌ "일단 만들고 나중에 리팩터" → Feature 초기부터 정공법
- ❌ "혹시 필요할까봐 추상화" → Necessity-driven만
- ❌ SELECT * / Generic Repository → Explicit columns, explicit logic
- ❌ "이건 작은 변경이라 테스트 스킵" → 모든 경로 characterize
- ❌ Timestamp를 직접 DateTime.Now → IClock 주입
- ❌ Policy 로직이 Job/Handler에 → Domain Policy만
- ❌ "나중에 monitoring 추가" → 배포 전 Metric/Alert/Runbook 필수
- ❌ Magic number → 근거 있는 상수, Policy ID로 추적
- ❌ "다른 모듈 테이블 조회" → Contract/Read Model만
- ❌ 스킵된 테스트 기록 안 함 → Debt register에 DECISION_REQUIRED
## Execution Protocol Addendum
### Before Any Change
- Read the current Source of Truth first: user-provided configuration, current schema, active contracts, and existing tests.
- Record `Source / Assumption / Unknown / Decision Required` in the Slice note before editing.
- Preserve user-fixed development and production configuration values. Never replace them with compose defaults, environment fallbacks, or guessed credentials.
- Classify the change as exactly one Vertical Slice or one behavior-preserving refactoring. Do not mix policy, schema, configuration, and unrelated cleanup.
### Database Test Routing
- Unit tests do not connect to a database.
- Integration and migration tests use the configured test database from the test project's Development settings.
- Production database access is read-only diagnostics only unless an explicitly approved production release step says otherwise.
- Before any destructive test-database operation, parse and verify the database name is the approved test database. Refuse all other names.
- Do not infer schema from a legacy migration file. Compare active runtime SQL, tests, and the current database schema first.
### Time and Timezone
- Persist instants in UTC with timezone-aware database types where the contract permits.
- Convert to KST only at display, reporting, scheduling, or MarketCalendar boundaries.
- Keep `IClock.UtcNow` as the application clock contract. A KST conversion requires an explicit contract and characterization test.
- Never change a timezone or reinterpret existing timestamps without a documented data-meaning decision and rehearsal evidence.
### Blockers Must Be Actionable
- Do not repeatedly report that work is blocked without a concrete resolution proposal.
- For each blocker, state: exact cause, safe options, recommended option, required command or approval, and the evidence that will be produced.
- If the user has provided the required authority or test resource, proceed within that scope instead of asking for the same approval again.
- If an external prerequisite is missing, perform all safe read-only checks first, then give one precise request to unblock the next Slice.
### Evidence and Completion
- Never claim completion from an intended command. Record the actual command result and artifact path.
- For migrations, preserve fresh-install, upgrade, re-run, and failure-rehearsal evidence before calling the Slice complete.
- When a change fails validation, revert or isolate the failed draft before starting the next Slice; do not leave an unapplied journal or partial scaffold as if it were approved.