feat(config): config 디렉터리 기반 설정 관리 (--config-path/--env-file, trex-orb-v1 정합, BAT-026)

REQ-048/010 change-req. `--config` 를 이름으로 해석 + `--config-path <dir>`
(기본 ./config) + resolve_config_toml(슬래시 포함 값은 하위호환 명시 경로).
`.env` 를 config-dir 결정적 해석(--env-file 우선, 없으면 <config_dir>/.env,
CWD 무관) + config/.env.example + .gitignore config/* 허용목록. 운영자 CLI 도
--config-path/--env-file 동일 적용. from_env() legacy 루트 .env 폴백 유지로
완전 하위호환.

단위 23 + 전체 375 passed, ruff clean, 라이브 스모크(name·path 동일).
REQ-048/010 → Implemented.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 23:45:08 +09:00
co-authored by Claude Opus 4.8
parent 6e8e79660c
commit 8b2c26c04c
14 changed files with 531 additions and 32 deletions
@@ -0,0 +1,34 @@
# BAT-026: config 디렉터리 기반 설정 관리 — `--config-path`/`--env-file` + config-dir `.env` 공용화 (trex-orb-v1 정합)
- Status: release-candidate
- Profile: batch-lite
- Source Discovery: 없음 (trex-orb-v1 설정 관리 정합 — change-req 주도)
- Included REQ: REQ-048 (CHG-20260609-01), REQ-010 (CHG-20260609-01)
- Excluded REQ: 없음
## Summary
- trex-orb-v1의 config 디렉터리 기반 설정 관리(`--config <name>` + `--config-path <dir>` + config-dir `.env`)를 trex-core 에 이식한다.
- 핵심: `resolve_config_toml(name, config_path)`(이름→`<dir>/<name>.toml`, `.toml` 자동 부착, **슬래시 포함 값은 하위호환 명시 경로**)(REQ-048), `.env` 를 config-dir 기준 결정적 해석(`--env-file` 우선 → `<config_dir>/.env`)으로 변경 + `config/.env.example` + `.gitignore` `config/*` 허용목록(REQ-010). 데몬·운영자 CLI 양쪽에 `--config-path`/`--env-file` 적용.
- 안전: `from_env()` 의 legacy `.env` 로드(루트 `.env` 폴백)를 유지 → config/.env 부재 시에도 기존 루트 `.env` 로 동작(완전 하위호환). config/.env 존재 시 먼저 로드돼 우선(`override=False`).
## Scope
- In Scope:
- `resolve_config_toml` + `DEFAULT_CONFIG_DIR` (REQ-048)
- `_load_dotenv(config_path, env_file)` config-dir 결정적 해석 + legacy 폴백 (REQ-010)
- 데몬 `main` argparse `--config-path`/`--env-file` + `from_config(toml_path, env_file)`
- 운영자 CLI `--config-path`/`--env-file` + `_resolve_instance` 통일
- `.gitignore` `config/*` 허용목록, `config/.env.example` 신규
- Out of Scope:
- 실제 `.env` → `config/.env` 물리 이동(운영 배포 절차 — 루트 `.env` 폴백으로 무중단)
- TOML/env 레이어링 정책(키 우선순위) 변경 — 기존 유지
## Documents
- Planning: [planning.md](./planning.md)
- Design: none (batch-lite with no architecture impact)
- Implementation: [verification.md](./verification.md) 에 구현 요약 포함 (batch-lite)
- Verification: [verification.md](./verification.md)
## Notes
- Profile **batch-lite**: 국소 변경(config.py/daemon.py/cli.py + .gitignore + config 예제). 신규 런타임 흐름·계약 필드 없음(인자·해석 규칙 추가). `--config` 의미 확장은 인터페이스 영향이라 정식 change-req(REQ-048/010 CHG-20260609-01) 경유 → **Design Gate: no**.
- REQ-048/010 은 CHG-20260609-01 로 **Approved**(신규 AC 미구현). 본 batch release-candidate + confirm-req-implemented 로 **Implemented** 복귀.
- 발견 근거: 사용자 요청(trex-orb-v1 설정 관리 형태 정합).
@@ -0,0 +1,32 @@
# BAT-026 Planning
- Status: confirmed
- Batch: BAT-026
- Profile: batch-lite
## Included REQ
- REQ-048 (CHG-20260609-01) — `--config` 이름 해석 + `--config-path` + `resolve_config_toml`
- REQ-010 (CHG-20260609-01) — config-dir `.env` 결정적 해석 + `--env-file` + `config/.env.example` + `.gitignore`
## Delivery Plan
1. `config.py`: `DEFAULT_CONFIG_DIR` + `resolve_config_toml(name, config_path)`(슬래시 포함=명시 경로 하위호환). `_load_dotenv(config_path=None, env_file=None)` — `--env-file` 우선 → `<config_dir>/.env` → (config 컨텍스트 없으면) legacy `find_dotenv(usecwd=True)` 폴백. `from_config(toml_path, env_file=None)` 가 config-dir `.env` 선로드 후 `from_env()`.
2. `daemon.py main`: `--config-path`/`--env-file` argparse + `resolve_config_toml` + `from_config(path, env_file)`.
3. `cli.py`: `_add_common` 에 `--config-path`/`--env-file`; `_resolve_instance` 가 `resolve_config_toml` 경유; `main` 이 from_env 전 config-dir `.env` 선로드.
4. `.gitignore` `config/*` 허용목록(`*.example.toml`/`.env.example`), `config/.env.example` 신규.
5. 테스트: resolve_config_toml(이름/.toml/config-path/경로형), _load_dotenv(env-file/config-dir/override/부재/CWD무관), daemon·cli 인자.
## Dependencies
- Internal: `from_env()` 의 legacy `.env` 로드 유지가 하위호환의 핵심.
- External: 없음.
## Design Gate
- Design Required Before Implementation: no
- Reason: 국소 변경(3개 런타임 파일 + .gitignore + config 예제). 신규 계약 필드/런타임 흐름 없음. `--config` 의미 확장은 change-req(CHG-20260609-01)로 이미 정합.
## Milestones
1. config.py/daemon.py/cli.py + .gitignore + config/.env.example 구현.
2. 단위(resolve/dotenv/인자) green + 전체 회귀 + ruff.
## Risks
- R-1: config/.env 부재 시 키 미로드로 기동 실패. 대응: `from_env()` legacy 루트 `.env` 폴백 유지 → 무중단(완전 하위호환).
- R-2: `--config` 경로형 사용처 회귀. 대응: 슬래시 포함 값 명시 경로 폴백 + 회귀 테스트.
@@ -0,0 +1,45 @@
# BAT-026 Verification
- Status: approved
- Batch: BAT-026
- Profile: batch-lite
## Acceptance Mapping
### REQ-048 (CHG-20260609-01) — `--config` 이름 해석 + `--config-path`
| AC | Evidence |
|----|----------|
| AC-7: `--config <name> [--config-path <dir>]` → `<dir or ./config>/<name>.toml`(.toml 자동 부착) | `tests/runtime/test_config_resolution.py::test_resolve_name_default_dir` / `::test_resolve_appends_toml` / `::test_resolve_with_config_path` → PASS |
| AC-8: 슬래시 포함(경로형) 값은 명시 경로로 그대로 사용(하위호환) | `::test_resolve_path_form_passthrough` → PASS. 라이브: `trex-core universe --config config/test.toml` 정상(name 형태와 동일 결과) |
| AC-9: 운영자 CLI 도 `--config-path` 수용, `_resolve_instance` 동일 규칙 | `::test_cli_resolve_instance_honors_config_path` → PASS. 라이브: `--config test --config-path config` → instance=test 라우팅 |
### REQ-010 (CHG-20260609-01) — config-dir `.env` + `--env-file`
| AC | Evidence |
|----|----------|
| AC-1(갱신): `<config_dir>/.env`(또는 `--env-file`) 로드 → dsn 반영 | `::test_dotenv_loaded_from_config_dir_cwd_independent` → PASS |
| AC-2: OS env 우선(`override=False`) | `::test_dotenv_os_env_takes_precedence` + 기존 `test_config_dotenv.py::test_os_env_takes_precedence_over_dotenv` → PASS |
| AC-3: `.env` 부재 시 회귀 없음 | `::test_dotenv_absent_is_noop` + 기존 `test_no_dotenv_uses_os_env_only` → PASS |
| AC-4: `.gitignore` `config/*` 무시 + `*.example.toml`/`.env.example` 추적 | `test_instance_config.py::test_gitignore_excludes_instance_toml`(갱신) → PASS |
| AC-6: CWD 무관 결정적 로드 | `::test_dotenv_loaded_from_config_dir_cwd_independent`(다른 CWD 로 chdir 후 config-dir `.env` 로드) → PASS |
| AC-7: `--env-file` 우선 | `::test_dotenv_env_file_wins` → PASS |
## 하위호환 (R-1/R-2)
- `from_env()` 의 legacy `.env` 로드(루트 `.env` CWD 폴백) 유지 → config/.env 부재에도 기존 루트 `.env` 로 동작. 기존 `test_config_dotenv.py` 6건 전부 green(무회귀).
- 경로형 `--config` 무중단: 라이브 스모크에서 `--config config/test.toml` 와 `--config test --config-path config` 가 **byte 동일 스냅샷** 반환(instance=test).
## 검증 명령/결과
- 단위(config): `pytest tests/runtime/test_config_resolution.py test_config_dotenv.py test_instance_config.py -q` → **23 passed**.
- 전체 회귀: `pytest -q --deselect tests/adapters/broker/test_kis.py::test_sandbox_token_and_submit` → **375 passed, 35 skipped, 1 deselected**.
- lint: `ruff check`(config.py/daemon.py/cli.py + 신규/갱신 테스트) → All checks passed.
- 라이브 스모크: 실행 중 test 데몬에 `trex-core universe --config test --config-path config --json` 와 `--config config/test.toml --json` → 동일 응답(instance=test, 라우팅·.env 폴백 정상).
## Baseline 문서 동기화
- `config/.env.example` 신규(공유 인프라 키 + config-dir 해석 헤더). `docs/project-structure.md` 설정 계층 서술은 후속 정합(흐름 변화 없음 — 인자/해석 규칙 추가) — 구조 영향 없음(Design Gate: no).
## 결과 요약
- REQ-048 AC-7/8/9 + REQ-010 AC-1/2/3/4/6/7 전부 단위 PASS + 라이브 스모크 무회귀.
- **Ready for Release: true.**
## 미검증/한계
- 데몬 진입점(`daemon.py:main`)은 `# pragma: no cover`(프로세스 진입점) — `resolve_config_toml`/`from_config(env_file)` 단위 + CLI 라이브 스모크로 동등 경로 커버.
- 실제 `.env` → `config/.env` 물리 이동은 운영 배포 절차(루트 `.env` 폴백으로 무중단) — 본 batch 범위 밖.
+1
View File
@@ -33,3 +33,4 @@
| BAT-023 | standard | released | REQ-017 (CHG-20260608-02), REQ-019 (CHG-20260608-02), REQ-029 (CHG-20260608-01), REQ-030 (CHG-20260608-01, Approved→Implemented) | dcy-018 | [bat-023](./bat-023_20260608_ledger-cash-position-writeback-option-d/) |
| BAT-024 | batch-lite | release-candidate | REQ-032 (CHG-20260609-01) | dcy-016 (issue #17) | [bat-024](./bat-024_20260609_operator-enter-forced-close-at/) |
| BAT-025 | standard | release-candidate | REQ-002 (CHG-20260609-01), REQ-003 (CHG-20260609-01), REQ-006 (CHG-20260609-01), REQ-007 (CHG-20260609-01), REQ-009 (CHG-20260609-01) | dcy-019 (issue #18) | [bat-025](./bat-025_20260609_slot-entry-count-and-closed-reallocation/) |
| BAT-026 | batch-lite | release-candidate | REQ-048 (CHG-20260609-01), REQ-010 (CHG-20260609-01) | 없음 (trex-orb-v1 정합) | [bat-026](./bat-026_20260609_config-dir-env-and-config-path/) |