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:
@@ -10,18 +10,21 @@
|
||||
|
||||
## Requirement
|
||||
- `DaemonConfig.from_env()` 가 `os.environ` 을 읽기 전에 `.env`(있으면)를 로드한다. python-dotenv 를 의존성에 추가하고, `.env` 는 `.gitignore` 에 등록해 커밋되지 않게 하며, `.env.example` 를 참고용으로 제공한다. `.env` 가 없거나 dotenv 미설치여도 기존 동작(os.environ 단독)을 유지한다(회귀 없음).
|
||||
- (CHG-20260609-01, trex-orb-v1 정합) `.env` 해석은 **config 디렉터리 기준 결정적**이다 — `--env-file <path>` 우선, 없으면 `<config_dir>/.env`(TOML 옆). CWD 의존 상향 탐색(`find_dotenv(usecwd=True)`)을 사용하지 않는다. `.env` 는 `config/.env` 로 공용화하고 `config/.env.example` 를 제공하며, `.gitignore` 는 `config/*` 를 무시하되 `*.example.toml`/`.env.example` 만 추적한다. `override=False`(실제 OS env 우선)는 유지한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given CWD 에 `.env`(`TREX_POSTGRESQL_DSN=...`)가 있고 해당 OS env 가 미설정, When `DaemonConfig.from_env()`, Then `.env` 값이 로드되어 `dsn` 에 반영된다.
|
||||
2. Given OS env 와 `.env` 에 같은 키가 다른 값으로 존재, When `from_env()`, Then OS env 값이 우선한다(.env 가 덮어쓰지 않음).
|
||||
3. Given `.env` 가 없음, When `from_env()`, Then 기존처럼 `os.environ` 만으로 동작한다(회귀 없음).
|
||||
4. Given 저장소, When `.gitignore` 확인, Then `.env` 가 무시 대상이며 `.env.example` 은 추적된다.
|
||||
5. Given `broker=paper` 이고 `.env`/OS env 에 `TREX_PAPER_FILL_AFTER_POLLS`/`TREX_PAPER_QTY_PER_POLL`/`TREX_PAPER_REJECT_SYMBOLS` 가 설정, When `DaemonConfig.from_env()` 후 `_build_broker`, Then paper 더블이 해당 시나리오(지연/부분/거부, REQ-011 AC-2)로 구성된다. 미설정이면 `PaperBroker()` 기본(즉시 전량 체결·거부 없음)과 byte-for-byte 동일하다(회귀 없음).
|
||||
1. (CHG-20260609-01 갱신) Given `<config_dir>/.env`(또는 `--env-file`)에 `TREX_POSTGRESQL_DSN=...` 가 있고 해당 OS env 가 미설정, When 설정 로드, Then `.env` 값이 로드되어 `dsn` 에 반영된다.
|
||||
2. Given OS env 와 `.env` 에 같은 키가 다른 값으로 존재, When 로드, Then OS env 값이 우선한다(.env 가 덮어쓰지 않음, `override=False`).
|
||||
3. Given `.env` 가 없음, When 로드, Then 기존처럼 `os.environ` 만으로 동작한다(회귀 없음).
|
||||
4. Given 저장소, When `.gitignore` 확인, Then `config/*` 가 무시 대상이며 `config/*.example.toml`·`config/.env.example` 은 추적된다.
|
||||
5. Given `broker=paper` 이고 `.env`/OS env 에 `TREX_PAPER_FILL_AFTER_POLLS`/`TREX_PAPER_QTY_PER_POLL`/`TREX_PAPER_REJECT_SYMBOLS` 가 설정, When `DaemonConfig.from_env()` 후 `_build_broker`, Then paper 더블이 해당 시나리오(지연/부분/거부, REQ-011 AC-2)로 구성된다. 미설정이면 `PaperBroker()` 기본과 동일(회귀 없음).
|
||||
6. (CHG-20260609-01) Given CWD 를 바꿔 실행, When 설정 로드, Then `<config_dir>/.env` 가 CWD 와 무관하게 결정적으로 로드된다(상향 탐색 없음).
|
||||
7. (CHG-20260609-01) Given `--env-file <path>`, When 로드, Then `<config_dir>/.env` 대신 그 파일이 로드된다(우선).
|
||||
|
||||
## Impacted Area
|
||||
- Docs: 없음(baseline 구조/인터페이스/런타임 흐름 변경 없음 — minor-change)
|
||||
- Modules: pyproject.toml(python-dotenv), trex_core/runtime/config.py(load_dotenv, PaperBrokerConfig), trex_core/runtime/daemon.py(_build_broker paper 주입), .gitignore, .env.example(신규 + paper 튜닝 키)
|
||||
- Tests: tests/runtime/test_config_dotenv.py (로드/우선순위/부재 회귀, paper 튜닝 기본/파싱)
|
||||
- Docs: (CHG-20260609-01) `config/.env.example`(신규, 공유 인프라 키), `.env`→`config/.env` 이동
|
||||
- Modules: pyproject.toml(python-dotenv), trex_core/runtime/config.py(load_dotenv→`_load_dotenv(config_path, env_file)` config-dir 해석, PaperBrokerConfig), trex_core/runtime/daemon.py(_build_broker paper 주입, `--env-file`), cli.py(`--env-file`), .gitignore(config/* 허용목록), .env.example(paper 튜닝 키)
|
||||
- Tests: tests/runtime/test_config_dotenv.py (로드/우선순위/부재 회귀, paper 튜닝 기본/파싱, config-dir·`--env-file`·CWD 무관)
|
||||
|
||||
## Notes
|
||||
- minor-change fast path: 단일 저위험 Configuration REQ, 구조/인터페이스/런타임 흐름 영향 없음(기동 시 env 소스 추가뿐). batch-lite 로 처리, design 불요.
|
||||
@@ -235,3 +238,81 @@
|
||||
|
||||
#### Validation Plan
|
||||
- BAT-009 verification evidence 재참조로 충분.
|
||||
|
||||
### CHG-20260609-01
|
||||
|
||||
- Date: 2026-06-09
|
||||
- Author: Justin Ko
|
||||
|
||||
#### Change Summary
|
||||
|
||||
- (change-req, trex-orb-v1 설정 관리 정합) `.env` 해석을 **config 디렉터리 기준 결정적**으로 변경한다 — `--env-file <path>` 가 우선, 없으면 **`<config_dir>/.env`**(TOML 옆). 기존 `find_dotenv(usecwd=True)`(CWD 의존 상향 탐색)를 제거해 실행 위치와 무관하게 동일 `.env` 를 로드한다. `.env` 를 repo 루트 → **`config/.env`** 로 이동(공용화), `config/.env.example` 신설, `.gitignore` 를 `config/*` 무시 + `*.example.toml`/`.env.example` 만 추적하는 형태로 전환. `override=False`(실제 OS env 우선)는 유지. `config_dir` 는 REQ-048 CHG-20260609-01 의 `--config-path` 로 제공된다.
|
||||
|
||||
#### Intent
|
||||
|
||||
- 어디서 실행하든 동일한 **공유 인프라 `.env`**(DSN/RabbitMQ/KIS/portfolio-hub 등)를 결정적으로 로드한다. 다중 인스턴스가 같은 broker/DSN/hub 를 공유하도록 `.env` 를 인스턴스 TOML 과 분리해 config 디렉터리에 공용화(12-factor).
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
|
||||
- Added:
|
||||
- AC-6: `.env` 는 `<config_dir>/.env`(TOML 옆)에서 **CWD 와 무관하게** 결정적으로 로드된다. dotenv 미설치/`.env` 부재 시 no-op(회귀 없음).
|
||||
- AC-7: `--env-file <path>` 가 주어지면 `<config_dir>/.env` 대신 그 파일을 로드한다(우선).
|
||||
- AC-8: `.gitignore` 는 `config/*` 를 무시하되 `config/*.example.toml` 과 `config/.env.example` 은 추적한다(실제 `.env`/인스턴스 TOML 비커밋).
|
||||
- Updated:
|
||||
- AC-1: "CWD 의 `.env`" → "`<config_dir>/.env`"(또는 `--env-file`) 로 로드 소스 변경.
|
||||
- Removed: none
|
||||
|
||||
#### Impacted Area Delta
|
||||
|
||||
- Modules: `trex_core/runtime/config.py`(`_load_dotenv(config_path, env_file)` — config-dir 결정적 해석, `find_dotenv(usecwd=True)` 제거), `trex_core/runtime/daemon.py`·`cli.py`(`--env-file` 인자 전달)
|
||||
- Docs: `config/.env.example`(신규, 공유 인프라 키), `.gitignore`(config/* 허용목록), `.env`(루트→`config/.env` 이동)
|
||||
- Tests: `tests/runtime/test_config_dotenv.py`(config-dir 로드/`--env-file` 우선/CWD 무관/`override=False` 회귀/부재 no-op)
|
||||
|
||||
#### Delivery Trace Delta
|
||||
|
||||
- Batches: 신규 batch-lite(REQ-048 CHG-20260609-01 과 동일 배치)
|
||||
- Releases: none
|
||||
|
||||
#### Revalidation Impact
|
||||
|
||||
- Reverification Needed: yes (신규 batch 에서 AC-6/7/8 + AC-1 변경 검증)
|
||||
- Existing Implementation Invalidated: yes (`.env` 해석 위치가 CWD → config-dir 로 변경되어 기존 루트 `.env` 의존 동작이 바뀜 — 운영 배포 시 `.env` 이동 필요)
|
||||
- Status Recommendation: Implemented → Approved (신규/변경 AC 미구현 — batch 재검증 후 Implemented 복귀)
|
||||
- Follow-up Action: draft-batch(batch-lite) → run-batch-implementation → verification → confirm-req-implemented
|
||||
|
||||
#### Validation Plan
|
||||
|
||||
- 신규 BAT: `<config_dir>/.env` 결정적 로드(CWD 변경해도 동일), `--env-file` 우선, OS env 우선(`override=False`) 회귀, `.env` 부재 no-op 단위. `.gitignore` config/* 허용목록 가드.
|
||||
|
||||
### CHG-20260609-02
|
||||
|
||||
- Date: 2026-06-09
|
||||
- Author: Justin Ko
|
||||
|
||||
#### Change Summary
|
||||
|
||||
- Status 변경: Approved → Implemented. BAT-026 release-candidate verification evidence 기반(CHG-20260609-01 AC-1/2/3/4/6/7).
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
|
||||
- Added/Updated/Removed: 없음
|
||||
|
||||
#### Impacted Area Delta
|
||||
|
||||
- Docs/Modules/Tests: 없음
|
||||
|
||||
#### Delivery Trace Delta
|
||||
|
||||
- Batches: BAT-026 (release-candidate)
|
||||
- Releases: none
|
||||
|
||||
#### Revalidation Impact
|
||||
|
||||
- Reverification Needed: no (BAT-026 에서 완료)
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: Implemented
|
||||
- Follow-up Action: 운영 배포 시 `.env`→`config/.env` 이동(루트 `.env` 폴백으로 무중단). release 단계 별도 진행.
|
||||
|
||||
#### Validation Plan
|
||||
|
||||
- tests/runtime/test_config_resolution.py(config-dir `.env`/`--env-file`/CWD 무관/override) + test_config_dotenv.py 6건 무회귀 + `.gitignore` 가드. 전체 375 passed, ruff clean.
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
- `config.py` 에 `DaemonInstanceConfig` dataclass(`instance_key: str`, `portfolio_hub_token: str`)와 `from_toml(path)` 로더를 추가한다(stdlib `tomllib` 사용).
|
||||
- `DaemonConfig` 구성 시 `--config <path>.toml` 의 TOML 값을 `from_env()` 결과와 병합하는 팩토리(예: `from_config(toml_path)`)를 추가한다. `portfolio_hub_token` 은 TOML 값을 사용해 `PortfolioHubConfig.token` 에 주입한다.
|
||||
- 데몬 기동 진입점은 `--config` 를 **필수 인자**로 받는다. 인자 없이 기동하면 오류 메시지를 출력하고 비정상 종료(exit code ≠ 0)한다. 기본값 fallback 없음(OQ-2 Answered).
|
||||
- (CHG-20260609-01, trex-orb-v1 정합) `--config` 는 **이름**으로 받고 `--config-path <dir>`(기본 `./config`)로 config 디렉터리를 분리한다. `resolve_config_toml(name, config_path)` 가 `<config_dir>/<name>.toml` 로 해석하며 `.toml` 을 자동 부착한다. **하위호환**: 슬래시 포함(경로형) `--config` 값은 명시 경로로 그대로 사용한다. 운영자 CLI(`trex-core`)도 `--config-path` 를 동일 규칙으로 수용한다.
|
||||
- `instance_key` 와 `portfolio_hub_token` 은 `.env`/OS env 에서 읽지 않는다. TOML 미존재/필수 필드 누락 시 명확한 오류로 종료한다.
|
||||
- `.gitignore` 에 인스턴스 TOML 경로 패턴(예: `*.toml` 또는 `config/*.toml`)을 추가해 설정 파일이 커밋되지 않게 한다. 토큰/instance_key 는 로그에 평문 출력하지 않는다(NFR-4).
|
||||
|
||||
@@ -25,14 +26,18 @@
|
||||
4. Given TOML 에 필수 필드(`instance_key`) 누락, When `from_toml`/`from_config`, Then 명확한 오류로 실패한다(조용한 기본값 금지).
|
||||
5. Given 저장소, When `.gitignore` 확인, Then 인스턴스 TOML 경로 패턴이 무시 대상이다.
|
||||
6. Given 데몬 기동 로그, When 출력 확인, Then `portfolio_hub_token` 평문이 로그에 노출되지 않는다.
|
||||
7. (CHG-20260609-01) Given `--config <name> [--config-path <dir>]`, When `resolve_config_toml`, Then `<dir or ./config>/<name>.toml` 로 해석되고 `.toml` 이 없으면 자동 부착된다.
|
||||
8. (CHG-20260609-01) Given 슬래시 포함(경로형) `--config` 값, When 해석, Then `--config-path` 와 무관하게 명시 경로로 그대로 사용된다(하위호환).
|
||||
9. (CHG-20260609-01) Given 운영자 CLI 가 `--config-path` 와 함께 호출, When `_resolve_instance`, Then 동일 `resolve_config_toml` 규칙으로 TOML 을 찾아 instance_key 를 해석한다.
|
||||
|
||||
## Impacted Area
|
||||
|
||||
- Docs:
|
||||
- `docs/project-structure.md` — 설정 파일 계층(TOML + env) (REQ-051 처리)
|
||||
- Modules:
|
||||
- `trex_core/runtime/config.py` — `DaemonInstanceConfig` + `from_toml` + `from_config` 병합
|
||||
- 데몬 진입점(`trex_core/runtime/daemon.py:main` 또는 `__main__`) — `--config` 필수 파싱(argparse)
|
||||
- `trex_core/runtime/config.py` — `DaemonInstanceConfig` + `from_toml` + `from_config` 병합, (CHG-20260609-01) `resolve_config_toml`/`DEFAULT_CONFIG_DIR`
|
||||
- 데몬 진입점(`trex_core/runtime/daemon.py:main` 또는 `__main__`) — `--config` 필수 파싱(argparse), (CHG-20260609-01) `--config-path`
|
||||
- 운영자 CLI `trex_core/runtime/cli.py` — (CHG-20260609-01) `--config-path` + `_resolve_instance` 통일
|
||||
- `.gitignore` — 인스턴스 TOML 패턴
|
||||
- Tests:
|
||||
- `tests/runtime/` — TOML 로더 파싱/필수 인자/토큰 주입/누락 오류
|
||||
@@ -186,3 +191,81 @@
|
||||
#### Validation Plan
|
||||
|
||||
- BAT-018: from_toml 기본값(KST/00:00) + TOML 값 from_config 전파 단위.
|
||||
|
||||
### CHG-20260609-01
|
||||
|
||||
- Date: 2026-06-09
|
||||
- Author: Justin Ko
|
||||
|
||||
#### Change Summary
|
||||
|
||||
- (change-req, trex-orb-v1 설정 관리 정합) `--config` 를 **경로 대신 이름**으로 받고 `--config-path <dir>`(기본 `./config`)로 config 디렉터리를 분리한다. `resolve_config_toml(name, config_path)` 추가 — `<config_dir>/<name>.toml`(`.toml` 자동 부착). **하위호환**: 슬래시 포함(경로형) `--config` 값은 명시 경로로 그대로 사용(기존 운영 기동 스크립트 무중단). 운영자 CLI(`trex-core`)에도 `--config-path` 를 적용해 인스턴스 라우팅을 동일 규칙으로 통일. 데몬·CLI 진입점 argparse 갱신.
|
||||
|
||||
#### Intent
|
||||
|
||||
- trex-orb-v1 과 동일한 config 디렉터리 기반 설정 관리로 통일 — CWD 독립·이름 기반 인스턴스 선택. 공유 `.env`(REQ-010 CHG-20260609-01)의 해석 기준 디렉터리(`config_dir`)를 `--config-path` 로 제공한다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
|
||||
- Added:
|
||||
- AC-7: `--config <name> [--config-path <dir>]` → `<dir or ./config>/<name>.toml` 로 해석되고 `.toml` 확장자가 없으면 자동 부착된다(`resolve_config_toml`).
|
||||
- AC-8: 슬래시를 포함한(경로형) `--config` 값은 `--config-path` 와 무관하게 **명시 경로**로 그대로 사용된다(하위호환 — 기존 `--config config/test.toml` 무중단).
|
||||
- AC-9: 운영자 CLI(`trex-core`)도 `--config-path` 를 수용하며, `_resolve_instance` 가 동일 `resolve_config_toml` 규칙으로 TOML 을 찾는다.
|
||||
- Updated:
|
||||
- AC-2(필수 인자)는 유지 — `--config` 는 여전히 필수다(이름 또는 경로).
|
||||
- Removed: none
|
||||
|
||||
#### Impacted Area Delta
|
||||
|
||||
- Modules: `trex_core/runtime/config.py`(`resolve_config_toml`, `DEFAULT_CONFIG_DIR`), `trex_core/runtime/daemon.py`(`main` argparse `--config-path`), `trex_core/runtime/cli.py`(`--config-path` + `_resolve_instance` 통일)
|
||||
- Docs: `docs/project-structure.md`(설정 파일 계층 — config 디렉터리/이름 해석), `config/instance.example.toml`
|
||||
- Tests: `tests/runtime/`(resolve_config_toml: 이름/.toml 부착/config-path/경로형 폴백, 데몬·CLI `--config-path` 라우팅)
|
||||
|
||||
#### Delivery Trace Delta
|
||||
|
||||
- Batches: 신규 batch-lite(REQ-010 CHG-20260609-01 과 동일 배치)
|
||||
- Releases: none
|
||||
|
||||
#### Revalidation Impact
|
||||
|
||||
- Reverification Needed: yes (신규 batch 에서 AC-7/8/9 검증)
|
||||
- Existing Implementation Invalidated: no (경로형 `--config` 는 하위호환 유지, 이름 해석은 additive) — 단 신규 AC 미구현
|
||||
- Status Recommendation: Implemented → Approved (신규 AC-7/8/9 미구현 — batch 재검증 후 Implemented 복귀)
|
||||
- Follow-up Action: draft-batch(batch-lite) → run-batch-implementation → verification → confirm-req-implemented
|
||||
|
||||
#### Validation Plan
|
||||
|
||||
- 신규 BAT: `resolve_config_toml("test")`→`config/test.toml`, `("test.toml")`→`config/test.toml`, `("prod","/etc/trex")`→`/etc/trex/prod.toml`, 경로형(`config/test.toml`)→그대로 단위. 데몬·CLI `--config-path` 기동/라우팅 단위. 기존 경로형 `--config` 회귀.
|
||||
|
||||
### CHG-20260609-02
|
||||
|
||||
- Date: 2026-06-09
|
||||
- Author: Justin Ko
|
||||
|
||||
#### Change Summary
|
||||
|
||||
- Status 변경: Approved → Implemented. BAT-026 release-candidate verification evidence 기반(CHG-20260609-01 AC-7/8/9).
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
|
||||
- Added/Updated/Removed: 없음
|
||||
|
||||
#### Impacted Area Delta
|
||||
|
||||
- Docs/Modules/Tests: 없음
|
||||
|
||||
#### Delivery Trace Delta
|
||||
|
||||
- Batches: BAT-026 (release-candidate)
|
||||
- Releases: none
|
||||
|
||||
#### Revalidation Impact
|
||||
|
||||
- Reverification Needed: no (BAT-026 에서 완료)
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: Implemented
|
||||
- Follow-up Action: release 단계 별도 진행
|
||||
|
||||
#### Validation Plan
|
||||
|
||||
- tests/runtime/test_config_resolution.py(resolve_config_toml/경로형 폴백/CLI `--config-path` 라우팅) + 라이브 스모크(name·path 형태 동일 결과). 전체 375 passed, ruff clean.
|
||||
|
||||
Reference in New Issue
Block a user