refactor(jarca-ledger): implement BAT-010 backend core layering

This commit is contained in:
Jarca
2026-07-03 07:03:17 +09:00
parent 02380a88ab
commit 7ac25a6cf7
36 changed files with 4892 additions and 4113 deletions
@@ -0,0 +1,50 @@
# BAT-010 Design
## Layering design
- `jarca_ledger_mcp/application/shared.py`
- 공통 helper, validation, clock, dedupe, parser imports, shared policy를 보유한다.
- `jarca_ledger_mcp/application/system_services.py`
- health/status/backup/account create-list 등 system/persistence-adjacent service를 담당한다.
- `jarca_ledger_mcp/application/asset_account_services.py`
- account update, manual asset, snapshot, liquidity/net-worth read/write helper를 담당한다.
- `jarca_ledger_mcp/application/transaction_report_services.py`
- transaction CRUD, budgets, monthly/category/fixed-cost/reporting helper를 담당한다.
- `jarca_ledger_mcp/application/import_transfer_services.py`
- import preview/import, self-transfer/cancel reconciliation, cross-transfer matching을 담당한다.
- `jarca_ledger_mcp/application/categorization_services.py`
- category rules, preview/apply, uncategorized workbench, ledger categories를 담당한다.
## Persistence design
- `jarca_ledger_mcp/infrastructure/sqlite/connection.py`
- DB path resolution, sqlite connect, `db()` context manager를 담당한다.
- `jarca_ledger_mcp/infrastructure/sqlite/schema.py`
- schema version, DDL, additive column maps를 보유한다.
- `jarca_ledger_mcp/infrastructure/sqlite/migrations.py`
- idempotent/additive migration과 `init_db()`를 담당한다.
- top-level `jarca_ledger_mcp/db.py`는 compatibility shim으로 유지한다.
## Adapter / gateway design
- `jarca_ledger_mcp/adapters/mcp/server.py`
- 실제 FastMCP registration 위치.
- top-level `jarca_ledger_mcp/server.py`
- CLI entrypoint shim.
- `jarca_ledger_mcp/adapters/streamlit/service_gateway.py`
- dashboard가 실제로 사용하는 service surface만 재노출한다.
- `dashboard/app.py`
- gateway import를 통해 backend core를 호출한다.
## Compatibility design
- top-level `service.py`는 public API를 그대로 재노출한다.
- monkeypatch 관성을 위해 `service._current_kst_datetime` 변경이 shared/application modules에 전파되도록 module proxy를 유지한다.
- 기존 tests/import callers는 `from jarca_ledger_mcp import service` / `from jarca_ledger_mcp.db import init_db` 경로를 그대로 쓴다.
## Verification design
- `python -m py_compile`로 새 package tree syntax check.
- `pytest -q`로 full regression 및 AppTest 포함 회귀 검증.
- `hermes mcp test jarca-ledger`로 MCP tool discovery/registration 확인.
- Browser smoke로 synthetic fixture DB 기반 `요약`, `자산/마감` 렌더 및 console JS error 유무 확인.
@@ -0,0 +1,61 @@
# BAT-010 Implementation
## Plan summary
BAT-010 implements the confirmed dcy-010 Phase 0~3 scope by extracting application services, SQLite infrastructure, and thin MCP/Streamlit adapter seams while preserving legacy import paths and response contracts.
## Changed files
- `jarca_ledger_mcp/service.py`
- `jarca_ledger_mcp/db.py`
- `jarca_ledger_mcp/server.py`
- `jarca_ledger_mcp/application/__init__.py`
- `jarca_ledger_mcp/application/shared.py`
- `jarca_ledger_mcp/application/system_services.py`
- `jarca_ledger_mcp/application/asset_account_services.py`
- `jarca_ledger_mcp/application/transaction_report_services.py`
- `jarca_ledger_mcp/application/import_transfer_services.py`
- `jarca_ledger_mcp/application/categorization_services.py`
- `jarca_ledger_mcp/infrastructure/__init__.py`
- `jarca_ledger_mcp/infrastructure/sqlite/__init__.py`
- `jarca_ledger_mcp/infrastructure/sqlite/connection.py`
- `jarca_ledger_mcp/infrastructure/sqlite/schema.py`
- `jarca_ledger_mcp/infrastructure/sqlite/migrations.py`
- `jarca_ledger_mcp/adapters/__init__.py`
- `jarca_ledger_mcp/adapters/mcp/__init__.py`
- `jarca_ledger_mcp/adapters/mcp/server.py`
- `jarca_ledger_mcp/adapters/streamlit/__init__.py`
- `jarca_ledger_mcp/adapters/streamlit/service_gateway.py`
- `dashboard/app.py`
- `docs/discovery/dcy-010_20260702_backend-core-layering-mcp-adapter-realignment.md`
- `docs/project-structure.md`
- `docs/runtime-flows.md`
- `docs/srs/index.md`
- `docs/srs/Non-Functional/req-013_backend-core-layering-sqlite-infrastructure-service-facade-compatibility.md`
- `docs/srs/Interface/req-014_mcp-streamlit-adapter-seam-realignment-contract-preserving-gateway.md`
- `docs/batches/index.md`
- `docs/batches/bat-010_20260703_backend-core-layering-phase-0-3/index.md`
- `docs/batches/bat-010_20260703_backend-core-layering-phase-0-3/planning.md`
- `docs/batches/bat-010_20260703_backend-core-layering-phase-0-3/design.md`
- `docs/batches/bat-010_20260703_backend-core-layering-phase-0-3/implementation.md`
- `docs/batches/bat-010_20260703_backend-core-layering-phase-0-3/verification.md`
## Execution log
- 2026-07-03 00:15 KST: BAT-010 standard batch scaffold and REQ-013/REQ-014 문서를 생성하고 승인 상태로 정리했다.
- 2026-07-03 00:17 KST: `service.py` giant implementation을 application modules로 분리하고 top-level facade compatibility / monkeypatch proxy를 추가했다.
- 2026-07-03 00:17 KST: `db.py` responsibilities를 `infrastructure/sqlite`로 분리하고 기존 init/commit/rollback semantics를 유지하는 shim을 추가했다.
- 2026-07-03 00:18 KST: MCP adapter package, Streamlit gateway, baseline docs를 반영하고 regression fixes(`SCHEMA_VERSION import`, `db()` init semantics, underscore helper imports, service monkeypatch proxy)를 정리했다.
## Validation
- `python -m py_compile jarca_ledger_mcp/*.py jarca_ledger_mcp/application/*.py jarca_ledger_mcp/infrastructure/sqlite/*.py jarca_ledger_mcp/adapters/mcp/*.py jarca_ledger_mcp/adapters/streamlit/*.py dashboard/app.py` → PASS
- `pytest -q` → PASS (`42 passed, 4 skipped`)
- `hermes mcp test jarca-ledger` → PASS (`Connected`, `Tools discovered: 56`)
- Browser smoke: synthetic fixture DB(`/tmp/fixture.sqlite3`)로 Streamlit `요약`과 `자산/마감` 페이지 렌더 확인, console JS errors 없음.
## Remaining risks / follow-up notes
- Phase 4+ write/import/advanced workflow의 더 세밀한 domain/service 분리는 아직 TODO다.
- Streamlit gateway는 현재 필요한 surface만 노출하지만, 후속 phase에서 page/domain 기준으로 더 세분화할 수 있다.
- application modules는 여전히 큰 편이므로 후속 phase에서 deeper repository/use-case split이 필요하다.
@@ -0,0 +1,37 @@
# BAT-010 Backend core layering (Phase 0~3)
- Profile: standard
- Status: release-candidate
- Included REQ: REQ-013, REQ-014
- Discovery: dcy-010
- Owner: 렛저장인
- Date (KST): 2026-07-03
## 목표
REQ-013/REQ-014에 따라 `service.py` giant implementation과 `db.py` persistence 집중을 application / infrastructure / adapter seam으로 분리한다. 동시에 top-level facade/shim 호환, MCP tool contract, Streamlit 핵심 화면, additive migration discipline을 유지해 Phase 4+ 분리의 안전한 기반을 만든다.
## 산출물
- `jarca_ledger_mcp/application/` phase-0~3 service modules + shared helpers
- `jarca_ledger_mcp/infrastructure/sqlite/` connection/schema/migration split
- `jarca_ledger_mcp/adapters/mcp/server.py` + top-level `server.py` shim
- `jarca_ledger_mcp/adapters/streamlit/service_gateway.py` + dashboard import seam 정렬
- `service.py` / `db.py` compatibility facade & shim
- full pytest / MCP discovery / browser smoke evidence
- `docs/project-structure.md`, `docs/runtime-flows.md` baseline updates
- BAT-010 planning/design/implementation/verification documents
## 범위 제한
- Phase 4+ transactional write/import/advanced workflow 분리
- 신규 HTTP adapter 추가
- response envelope, tool names, dashboard IA 재설계
- destructive DB migration
## 문서
- `planning.md`: Phase 0~3 delivery plan, risks, validation gate
- `design.md`: layering/seam/shim design
- `implementation.md`: changed files, execution log, validation commands
- `verification.md`: AC mapping, PASS/FAIL, REQ Implemented decision
@@ -0,0 +1,34 @@
# BAT-010 Planning
## Scope
- Implement REQ-013: application/infrastructure split, SQLite persistence extraction, service/db compatibility facade.
- Implement REQ-014: MCP adapter split, Streamlit service gateway, contract-preserving verification.
- Update architecture baseline docs to reflect the new layering and remaining Phase 4+ TODOs.
- Use synthetic/temp data only for verification evidence.
## Dependencies
- dcy-010 confirmed Discovery and approved/implemented REQ-013/REQ-014.
- Existing BAT-009 runtime behavior, response contract expectations, and Streamlit dashboard pages.
- Additive/idempotent SQLite migration discipline from REQ-002.
## Work plan
1. Split `service.py` implementation into application modules and preserve top-level facade compatibility.
2. Split `db.py` responsibilities into `infrastructure/sqlite` and preserve existing import paths.
3. Introduce MCP adapter package and Streamlit service gateway.
4. Update baseline docs (`docs/project-structure.md`, `docs/runtime-flows.md`).
5. Run py_compile, full pytest, MCP discovery, and browser smoke against synthetic fixture DB.
6. If evidence satisfies ACs, mark BAT-010 release-candidate and REQ-013/REQ-014 Implemented.
## Design Gate
- Result: standard batch 유지.
- Reason: package boundary 변화, compatibility shim, MCP adapter seam, Streamlit browser verification, baseline docs가 함께 변경되므로 planning/design/verification depth가 필요하다.
## Risks and mitigations
- Hidden helper coupling after module split: mitigate by full pytest, monkeypatch compatibility, and targeted smoke on boundary-sensitive flows.
- DB initialization drift after infrastructure split: mitigate by preserving init/commit/rollback semantics and verifying schema initialization through tests.
- MCP/dashboard contract drift: mitigate by `hermes mcp test jarca-ledger`, Streamlit AppTest/full pytest, and browser smoke on key pages.
@@ -0,0 +1,45 @@
# BAT-010 Verification
## Verification summary
Status: PASS
Evidence was collected against synthetic/temp data only. No production ledger DB mutation or real financial files were used.
## Acceptance criteria mapping
### REQ-013
- AC-1: PASS — `jarca_ledger_mcp/application/` 아래 shared/system/asset-account/transaction-report/import-transfer/categorization modules가 생성됐다.
- AC-2: PASS — `jarca_ledger_mcp/infrastructure/sqlite/` 아래 connection/schema/migrations split이 생성됐고 top-level `db.py` shim이 유지된다.
- AC-3: PASS — `jarca_ledger_mcp/service.py`는 compatibility facade로 축소됐으며 현재 40 lines 수준이다(실질 구현은 application modules로 이동).
- AC-4: PASS — `pytest -q` full regression PASS (`42 passed, 4 skipped`), 기존 `service`/`db` import paths 유지.
- AC-5: PASS — `docs/project-structure.md`와 `docs/runtime-flows.md`가 새 계층 구조와 shim/gateway 흐름을 반영한다.
### REQ-014
- AC-1: PASS — `jarca_ledger_mcp/adapters/mcp/server.py` 도입 후 `hermes mcp test jarca-ledger` PASS, tools discovered 56.
- AC-2: PASS — `jarca_ledger_mcp/adapters/streamlit/service_gateway.py` 도입 후 `dashboard/app.py`가 gateway import를 사용한다.
- AC-3: PASS — full pytest PASS로 Streamlit AppTest / contract regression 포함 회귀가 유지된다.
- AC-4: PASS — local browser smoke에서 `요약`과 `자산/마감` 페이지 렌더를 확인했고 console JS errors가 없었다.
- AC-5: PASS — baseline docs와 BAT-010 implementation/verification 문서가 새 adapter seam을 반영한다.
## Requirement state decision
- REQ-013: Implemented.
- REQ-014: Implemented.
## Validation evidence
- `python -m py_compile jarca_ledger_mcp/*.py jarca_ledger_mcp/application/*.py jarca_ledger_mcp/infrastructure/sqlite/*.py jarca_ledger_mcp/adapters/mcp/*.py jarca_ledger_mcp/adapters/streamlit/*.py dashboard/app.py` → PASS
- `pytest -q` → PASS (`42 passed, 4 skipped`)
- `hermes mcp test jarca-ledger` → PASS (`Connected`, `Tools discovered: 56`)
- Browser smoke on Streamlit `요약` / `자산/마감` → PASS, JS errors 없음
## Remaining issues
### Hard blockers
- None.
### Non-blocking follow-up
- Phase 4+ transactional write services, import pipeline deeper split, advanced workflow separation, narrower adapter surfaces remain tracked as GitHub Project TODO items.
+1
View File
@@ -17,3 +17,4 @@
| BAT-007 | standard | release-candidate | REQ-007, REQ-008 | dcy-007 | [bat-007_20260630_mcp-response-contract-ci-versioning](bat-007_20260630_mcp-response-contract-ci-versioning/) |
| BAT-008 | standard | release-candidate | REQ-009, REQ-010 | dcy-008 | [bat-008_20260630_asset-snapshots-manual-assets-read-mcp](bat-008_20260630_asset-snapshots-manual-assets-read-mcp/) |
| BAT-009 | standard | release-candidate | REQ-011, REQ-012 | dcy-009 | [bat-009_20260701_manual-asset-crud-snapshot-close](bat-009_20260701_manual-asset-crud-snapshot-close/) |
| BAT-010 | standard | release-candidate | REQ-013, REQ-014 | dcy-010 | [bat-010_20260703_backend-core-layering-phase-0-3](bat-010_20260703_backend-core-layering-phase-0-3/) |