Refactor import and workflow services plus adapter seams

This commit is contained in:
Jarca
2026-07-03 08:25:01 +09:00
parent ac78e94571
commit f42bc4aa7d
53 changed files with 3420 additions and 2497 deletions
@@ -0,0 +1,23 @@
# BAT-012 Design
## Architecture summary
- Introduce `jarca_ledger_mcp/application/imports_service.py` as the single application-layer home for import preview/import/rollback orchestration.
- Introduce `jarca_ledger_mcp/infrastructure/parsers/` as the parser seam so application code no longer imports top-level parser implementations directly.
- Keep current top-level parser modules for compatibility if needed, but route application/shared usage through the infrastructure seam.
- Preserve `application/import_transfer_services.py` as the advanced workflow home; import-facing public functions become delegations into `imports_service.py`.
## Changed areas
- application import orchestration
- infrastructure parser seam
- service export surface / compatibility proxy
- import regression verification docs
## Key decisions
1. Parser relocation is seam-first, not algorithm rewrite.
2. Import account auto-linking/classification stays in the application layer, not in parser modules.
3. Public API/tool names remain unchanged.
## Verification focus
- Import preview/import/rollback regression
- Evidence field preservation
- No breakage in MCP discovery and public exports
@@ -0,0 +1,46 @@
# BAT-012 Implementation
## Plan summary
BAT-012 implements dcy-011 Phase 5 by extracting import preview/import/rollback orchestration into `application/imports_service.py`, introducing an `infrastructure/parsers/*` seam, and shrinking `application/import_transfer_services.py` toward advanced workflow ownership while preserving public contracts.
## Changed files
- `jarca_ledger_mcp/application/imports_service.py`
- `jarca_ledger_mcp/application/import_transfer_services.py`
- `jarca_ledger_mcp/application/shared.py`
- `jarca_ledger_mcp/application/__init__.py`
- `jarca_ledger_mcp/infrastructure/parsers/__init__.py`
- `jarca_ledger_mcp/infrastructure/parsers/kb_bank_pdf.py`
- `jarca_ledger_mcp/infrastructure/parsers/toss_bank_pdf.py`
- `jarca_ledger_mcp/infrastructure/parsers/toss_securities_pdf.py`
- `jarca_ledger_mcp/infrastructure/parsers/seoulpay_xlsx.py`
- `jarca_ledger_mcp/service.py`
- `docs/srs/index.md`
- `docs/srs/Non-Functional/req-016_import-pipeline-application-infrastructure-split.md`
- `docs/batches/index.md`
- `docs/batches/bat-012_20260703_import-pipeline-split/*`
- `docs/discovery/dcy-011_20260703_backend-refactor-phase4-write-import-workflow-adapter-narrowing.md`
## Execution log
- 2026-07-03 07:49 KST: dcy-011 Phase 5 범위로 `REQ-016`/`BAT-012`를 생성하고 승인 상태를 정리했다.
- 2026-07-03 07:50 KST: `application/import_transfer_services.py`의 AST function ranges를 추출해 import-owned 함수와 advanced workflow 함수를 기계적으로 분리할 준비를 했다.
- 2026-07-03 07:51 KST: `application/imports_service.py`를 생성하고 import preview/import/rollback + import-specific account/classification helpers를 이동했다.
- 2026-07-03 07:51 KST: `application/import_transfer_services.py`를 advanced workflow 중심 모듈로 축소하고 import-facing public functions는 compatibility delegation으로 전환했다.
- 2026-07-03 07:51 KST: `infrastructure/parsers/*` seam을 추가하고 `application/shared.py`가 top-level parser 구현 대신 infrastructure seam을 통해 parser를 가져오도록 정렬했다.
- 2026-07-03 07:52~07:53 KST: targeted import regression, full pytest, MCP discovery, export provenance를 검증했고 모두 PASS했다.
## Validation
- `python3 -m py_compile jarca_ledger_mcp/application/*.py jarca_ledger_mcp/infrastructure/parsers/*.py jarca_ledger_mcp/service.py` → PASS
- `pytest -q tests/test_kb_bank_pdf.py tests/test_seoulpay_xlsx.py tests/test_toss_securities_pdf.py tests/test_service.py` → PASS (`12 passed, 4 skipped`)
- `pytest -q` → PASS (`42 passed, 4 skipped`)
- `hermes mcp test jarca-ledger` → PASS (`Connected`, `Tools discovered: 56`)
- `python3` provenance check → PASS (all import preview/import/rollback exports resolve to `jarca_ledger_mcp.application.imports_service`)
## Remaining risks / follow-up notes
- `application/import_transfer_services.py`에는 cross-transfer review/matching advanced workflow가 아직 남아 있으며 Phase 6 배치에서 별도 분리해야 한다.
- parser relocation은 seam-first 방식이므로 top-level parser implementation files는 아직 compatibility/implementation 위치로 남아 있다. 필요 시 후속 cleanup은 adapter/baseline 갱신과 함께 진행한다.
- UI/adapter 표면 축소와 baseline 문서 갱신은 BAT-012 범위 밖이다.
@@ -0,0 +1,21 @@
# BAT-012 Import pipeline split
- Profile: standard
- Status: release-candidate
- Included REQ: REQ-016
- Discovery: dcy-011
- Owner: 렛저장인
- Date (KST): 2026-07-03
## 목표
REQ-016에 따라 import preview/import/rollback 경로를 `application/imports_service.py`와 `infrastructure/parsers/*` 중심으로 재배치하고, `application/import_transfer_services.py`는 advanced workflow 중심 모듈로 축소한다.
## Delivery checklist
- [ ] planning complete
- [ ] design complete
- [ ] implementation complete
- [ ] verification complete
- [ ] release-candidate promoted
- [ ] REQ sync complete
@@ -0,0 +1,28 @@
# BAT-012 Planning
## Scope
- Implement REQ-016 import pipeline split.
- Keep import contract/evidence fields stable while relocating parser access under `infrastructure/parsers/*`.
- Leave cross-transfer/reconciliation/advanced workflows in follow-up batches.
## Dependencies
- dcy-011 confirmed Discovery.
- REQ-016 Approved.
- BAT-011 write-service split baseline.
- Existing import regression tests and MCP discovery.
## Work plan
1. Create `application/imports_service.py` and move import preview/import/rollback + import-specific helpers there.
2. Create `infrastructure/parsers/*` wrappers or relocated parser modules and point application/shared imports to the infrastructure seam.
3. Shrink `application/import_transfer_services.py` to advanced workflow + compatibility delegation for import functions.
4. Run focused import regression, then full pytest and MCP discovery.
5. Update batch evidence and promote REQ/BAT if ACs pass.
## Design Gate
- Result: standard batch 유지.
- Reason: application/infrastructure seam 변경과 compatibility delegation, import evidence preservation, parser path relocation 검증이 함께 필요하다.
## Risks and mitigations
- Import evidence drift: preserve existing payload fields and run import-specific regression.
- Hidden helper coupling between import and advanced workflows: move only import-facing helpers in this batch and leave advanced helpers in place when not import-owned.
- Parser path breakage: add infrastructure parser wrappers first, then re-point shared/application imports.
@@ -0,0 +1,37 @@
# BAT-012 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-016
- AC-1: PASS — `application/imports_service.py`와 `infrastructure/parsers/*`가 생성됐고 import preview/import/rollback 구현이 이동했다.
- AC-2: PASS — public API/MCP tools/import response envelope and evidence fields remained stable; MCP discovery still reports 56 tools.
- AC-3: PASS — import-focused regression and full pytest PASS.
- AC-4: PASS — BAT-012 implementation/verification docs record actual changed files, commands, and outcomes.
## Requirement state decision
- REQ-016: Implemented.
## Validation evidence
- `python3 -m py_compile jarca_ledger_mcp/application/*.py jarca_ledger_mcp/infrastructure/parsers/*.py jarca_ledger_mcp/service.py` → PASS
- `pytest -q tests/test_kb_bank_pdf.py tests/test_seoulpay_xlsx.py tests/test_toss_securities_pdf.py tests/test_service.py` → PASS (`12 passed, 4 skipped`)
- `pytest -q` → PASS (`42 passed, 4 skipped`)
- `hermes mcp test jarca-ledger` → PASS (`Connected`, `Tools discovered: 56`)
- Python provenance check on import-facing exports → PASS
- preview/import/rollback APIs all resolve to `jarca_ledger_mcp.application.imports_service`
## Remaining issues
### Hard blockers
- None.
### Non-blocking follow-up
- cross-transfer / reconciliation / asset / workbench advanced workflow split
- MCP/Streamlit adapter surface narrowing and baseline docs update
@@ -0,0 +1,13 @@
# BAT-013 Design
## Architecture summary
- `cross_transfer_service.py` owns matching helpers and review queue APIs.
- `reconciliation_service.py` owns manual/partial-import balance reconciliation preview.
- `assets_service.py` owns manual asset CRUD, snapshot close/read, liquidity/net-worth reporting, and valuation helpers.
- `uncategorized_workbench_service.py` owns uncategorized list/summary/workbench/recommendation apply flows.
- Existing broad modules become thin compatibility layers or keep only their non-moved responsibilities.
## Verification focus
- workflow-specific regression for cross-transfer/assets/reconciliation/workbench
- full pytest and MCP discovery
- provenance checks that public exports resolve to the new owning modules
@@ -0,0 +1,48 @@
# BAT-013 Implementation
## Plan summary
BAT-013 implements dcy-011 Phase 6 by extracting advanced finance workflows into dedicated owning application services: `cross_transfer_service.py`, `reconciliation_service.py`, `assets_service.py`, and `uncategorized_workbench_service.py`. Existing broad modules remain as compatibility layers so MCP/service/dashboard callers keep their contracts.
## Changed files
- `jarca_ledger_mcp/application/assets_service.py`
- `jarca_ledger_mcp/application/asset_account_services.py`
- `jarca_ledger_mcp/application/cross_transfer_service.py`
- `jarca_ledger_mcp/application/import_transfer_services.py`
- `jarca_ledger_mcp/application/reconciliation_service.py`
- `jarca_ledger_mcp/application/transaction_report_services.py`
- `jarca_ledger_mcp/application/uncategorized_workbench_service.py`
- `jarca_ledger_mcp/application/categorization_services.py`
- `jarca_ledger_mcp/application/__init__.py`
- `jarca_ledger_mcp/service.py`
- `docs/srs/index.md`
- `docs/srs/Non-Functional/req-017_advanced-finance-workflow-service-split.md`
- `docs/batches/index.md`
- `docs/batches/bat-013_20260703_advanced-workflow-service-split/*`
- `docs/discovery/dcy-011_20260703_backend-refactor-phase4-write-import-workflow-adapter-narrowing.md`
## Execution log
- 2026-07-03 07:55 KST: dcy-011 Phase 6 범위로 `REQ-017`/`BAT-013`를 생성하고 Approved 상태를 확정했다.
- 2026-07-03 07:57~07:59 KST: AST-extracted function ranges를 기준으로 assets / cross-transfer / reconciliation / uncategorized workbench 흐름을 새 owning services로 이동했다.
- 2026-07-03 07:59 KST: `asset_account_services.py`, `import_transfer_services.py`, `transaction_report_services.py`, `categorization_services.py`를 compatibility delegation 레이어로 축소했다.
- 2026-07-03 08:00 KST: `application/__init__.py`와 `service.py` export/proxy surface를 새 owning modules까지 확장했다.
- 2026-07-03 08:00~08:01 KST: targeted workflow regression, full pytest, MCP discovery, provenance checks를 실행했고 모두 PASS했다.
## Validation
- `python3 -m py_compile jarca_ledger_mcp/application/*.py jarca_ledger_mcp/service.py` → PASS
- `pytest -q tests/test_cross_account_transfer_matching.py tests/test_asset_snapshots.py tests/test_categorization.py tests/test_contract_regression.py tests/test_service.py` → PASS (`24 passed`)
- `pytest -q` → PASS (`42 passed, 4 skipped`)
- `hermes mcp test jarca-ledger` → PASS (`Connected`, `Tools discovered: 56`)
- `python3` provenance check → PASS
- cross-transfer APIs → `jarca_ledger_mcp.application.cross_transfer_service`
- reconciliation API → `jarca_ledger_mcp.application.reconciliation_service`
- asset workflows → `jarca_ledger_mcp.application.assets_service`
- uncategorized workbench APIs → `jarca_ledger_mcp.application.uncategorized_workbench_service`
## Remaining risks / follow-up notes
- broad compatibility layers still exist by design; final dcy-011 batch should narrow MCP/Streamlit adapter imports and refresh baseline docs.
- top-level module names remain public to avoid breaking monkeypatch/tests; final cleanup should preserve this constraint.
@@ -0,0 +1,21 @@
# BAT-013 Advanced workflow service split
- Profile: standard
- Status: release-candidate
- Included REQ: REQ-017
- Discovery: dcy-011
- Owner: 렛저장인
- Date (KST): 2026-07-03
## 목표
REQ-017에 따라 cross-transfer, reconciliation, assets, uncategorized workbench를 owning application services로 분리하고 broad modules는 compatibility delegation으로 축소한다.
## Delivery checklist
- [ ] planning complete
- [ ] design complete
- [ ] implementation complete
- [ ] verification complete
- [ ] release-candidate promoted
- [ ] REQ sync complete
@@ -0,0 +1,28 @@
# BAT-013 Planning
## Scope
- Implement REQ-017 advanced workflow service split.
- Preserve public API and workflow response contracts while relocating owning helpers with their workflows.
- Leave adapter narrowing/baseline docs for the final dcy-011 batch.
## Dependencies
- dcy-011 confirmed Discovery.
- REQ-017 Approved.
- BAT-011/BAT-012 compatibility seams.
- Existing workflow regression tests.
## Work plan
1. Extract cross-transfer workflow from `import_transfer_services.py` into `cross_transfer_service.py`.
2. Extract reconciliation preview from `transaction_report_services.py` into `reconciliation_service.py`.
3. Extract manual asset/snapshot/liquidity workflows from `asset_account_services.py` into `assets_service.py`.
4. Extract uncategorized list/summary/workbench/recommendation flows from `categorization_services.py` into `uncategorized_workbench_service.py`.
5. Update application/service export surfaces, run focused workflow regression + full pytest, then record evidence.
## Design Gate
- Result: standard batch 유지.
- Reason: multiple domain modules and compatibility layers change together; broad-module decomposition needs explicit verification.
## Risks and mitigations
- Shared helper drift across moved workflows: move helper with first owner and verify with focused tests.
- Contract regressions in dashboard/MCP callers: preserve public names and run full pytest + MCP discovery.
- Partial extraction leaving dead imports: run py_compile and provenance check after relocation.
@@ -0,0 +1,36 @@
# BAT-013 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-017
- AC-1: PASS — `cross_transfer_service.py`, `reconciliation_service.py`, `assets_service.py`, `uncategorized_workbench_service.py` were created and now own their workflows.
- AC-2: PASS — service/MCP/dashboard contract remained stable; MCP discovery still reports 56 tools.
- AC-3: PASS — workflow-focused regression and full pytest both passed.
- AC-4: PASS — BAT-013 implementation/verification docs record the actual changed files, commands, and outcomes.
## Requirement state decision
- REQ-017: Implemented.
## Validation evidence
- `python3 -m py_compile jarca_ledger_mcp/application/*.py jarca_ledger_mcp/service.py` → PASS
- `pytest -q tests/test_cross_account_transfer_matching.py tests/test_asset_snapshots.py tests/test_categorization.py tests/test_contract_regression.py tests/test_service.py` → PASS (`24 passed`)
- `pytest -q` → PASS (`42 passed, 4 skipped`)
- `hermes mcp test jarca-ledger` → PASS (`Connected`, `Tools discovered: 56`)
- Python provenance check on advanced workflow exports → PASS
## Remaining issues
### Hard blockers
- None.
### Non-blocking follow-up
- MCP/Streamlit adapter surface narrowing
- dcy-011 baseline/final status refresh and QC evidence sync
@@ -0,0 +1,7 @@
# BAT-014 Design
## Architecture summary
- `adapters/mcp/tool_contracts.py` becomes the MCP adapter’s narrow contract dependency surface.
- `adapters/streamlit/{overview,assets,transactions,categorization,imports,accounts,transfers,reconciliation}_gateway.py` expose page/domain-sized call sets.
- `adapters/streamlit/service_gateway.py` remains a compatibility aggregator while `dashboard/app.py` shifts to page/domain gateway aliases.
- Baseline docs record the post-Phase-7 structure and runtime flow.
@@ -0,0 +1,43 @@
# BAT-014 Implementation
## Plan summary
BAT-014 implements dcy-011 Phase 7 by narrowing the remaining adapter surfaces without changing public MCP tool names or dashboard behavior. The MCP server now depends on `adapters/mcp/tool_contracts.py` instead of a broad direct `service` import, and the Streamlit dashboard now calls page/domain gateways under `adapters/streamlit/*_gateway.py` rather than a flat broad `service_gateway` namespace. `service_gateway.py` remains as a compatibility aggregator.
## Delivered changes
1. Added `jarca_ledger_mcp/adapters/mcp/tool_contracts.py` as the MCP adapter contract surface and repointed `adapters/mcp/server.py` wrappers to `contracts.*` callables.
2. Added page/domain Streamlit gateways:
- `overview_gateway.py`
- `assets_gateway.py`
- `transactions_gateway.py`
- `categorization_gateway.py`
- `transfers_gateway.py`
- `imports_gateway.py`
- `accounts_gateway.py`
- `reconciliation_gateway.py`
3. Reworked `adapters/streamlit/service_gateway.py` into a compatibility aggregator over the new gateway modules.
4. Repointed `dashboard/app.py` static call sites away from `service.*` to the owning page/domain gateway modules.
5. Preserved hot-reload fallback by changing `get_service_callable()` to reload the passed gateway module rather than a broad flat service namespace.
6. Refreshed `docs/project-structure.md` and `docs/runtime-flows.md` so the baseline reflects post-Phase-7 ownership and adapter seams.
## Compatibility notes
- MCP tool names, argument shapes, and response contracts were intentionally preserved.
- `adapters/streamlit/service_gateway.py` still exists as a compatibility surface for any legacy dashboard-side imports.
- No SQL/UI business-rule ownership was moved into the dashboard; the app still goes through adapter gateways.
## Files changed
- `jarca_ledger_mcp/adapters/mcp/tool_contracts.py`
- `jarca_ledger_mcp/adapters/mcp/server.py`
- `jarca_ledger_mcp/adapters/streamlit/__init__.py`
- `jarca_ledger_mcp/adapters/streamlit/service_gateway.py`
- `jarca_ledger_mcp/adapters/streamlit/*_gateway.py`
- `dashboard/app.py`
- `docs/project-structure.md`
- `docs/runtime-flows.md`
## Outcome
The repository now has explicit MCP contract and Streamlit page/domain gateway seams, satisfying the final dcy-011 narrowing target while preserving all public compatibility surfaces.
@@ -0,0 +1,12 @@
# BAT-014 Adapter narrowing and baseline refresh
- Profile: standard
- Status: release-candidate
- Included REQ: REQ-018
- Discovery: dcy-011
- Owner: 렛저장인
- Date (KST): 2026-07-03
## 목표
REQ-018에 따라 MCP/Streamlit adapter surfaces를 더 좁히고 baseline 문서를 갱신해 dcy-011을 완료한다.
@@ -0,0 +1,12 @@
# BAT-014 Planning
## Scope
- Implement REQ-018 adapter narrowing.
- Preserve MCP/tool/dashboard contracts while shifting adapter imports to helper/page gateways.
- Refresh structure/runtime baselines and finalize dcy-011 metadata.
## Work plan
1. Add MCP contract helper module and repoint `adapters/mcp/server.py` to it.
2. Add Streamlit page/domain gateway modules and repoint `dashboard/app.py` away from a flat broad gateway dependency.
3. Run AppTest/UI-adjacent regression, full pytest, MCP discovery, and one browser/HTTP smoke if needed.
4. Refresh `docs/project-structure.md`, `docs/runtime-flows.md`, and dcy-011 status.
@@ -0,0 +1,43 @@
# BAT-014 Verification
## Verification summary
Status: PASS
All required code-path checks for BAT-014 passed. A manual local browser-evidence launch was attempted but blocked by the runtime’s consent guard for long-running local server startup, so the close-out evidence uses AppTest + full pytest + MCP discovery + structural call-site verification. No production ledger DB or real financial files were used.
## Acceptance criteria evidence
### AC-1. MCP contract/helper seam and Streamlit page/domain gateways exist
- Evidence:
- `jarca_ledger_mcp/adapters/mcp/tool_contracts.py` added and `adapters/mcp/server.py` now calls `contracts.*`.
- `search_files('*_gateway.py')` under `adapters/streamlit` returned 9 gateway/aggregator files.
### AC-2. `dashboard/app.py` no longer uses a flat broad gateway surface
- Evidence:
- `search_files(pattern='service\\.', path='dashboard', file_glob='app.py')` returned 0 matches after rewiring.
- Dynamic hot-reload lookup now targets passed gateway modules (`categorization_gateway`, `transfers_gateway`) instead of a flat `service` binding.
### AC-3. Regression and adapter verification pass
- `python3 -m py_compile jarca_ledger_mcp/adapters/mcp/*.py jarca_ledger_mcp/adapters/streamlit/*.py dashboard/app.py` → PASS
- `pytest -q tests/test_dashboard_app.py` → PASS (`....`)
- `pytest -q` → PASS (`........................ss...............ss...`)
- `hermes mcp test jarca-ledger` → PASS, 56 tools discovered
### AC-4. Baseline docs and discovery metadata reflect completion
- Evidence:
- `docs/project-structure.md` updated with new owning services, parser seam, MCP contract helper, and Streamlit page/domain gateways.
- `docs/runtime-flows.md` updated with import/parser seam, MCP contract routing, and dashboard gateway flow.
- dcy-011 metadata and close-out notes updated to reference `REQ-015`~`REQ-018` / `BAT-011`~`BAT-014` completion.
## Browser evidence note
- Attempted: synthetic local dashboard browser/HTTP smoke.
- Result: blocked by terminal consent guard for long-running local server startup in this session.
- Impact: none on code correctness regression; AppTest remained green and no UI functional regression was detected in test coverage.
## Safety boundary
- Synthetic/temp DBs only.
- No destructive migration.
- No production ledger DB mutation.
+3
View File
@@ -19,3 +19,6 @@
| 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/) |
| BAT-011 | standard | release-candidate | REQ-015 | dcy-011 | [bat-011_20260703_transactional-write-service-split](bat-011_20260703_transactional-write-service-split/) |
| BAT-012 | standard | release-candidate | REQ-016 | dcy-011 | [bat-012_20260703_import-pipeline-split](bat-012_20260703_import-pipeline-split/) |
| BAT-013 | standard | release-candidate | REQ-017 | dcy-011 | [bat-013_20260703_advanced-workflow-service-split](bat-013_20260703_advanced-workflow-service-split/) |
| BAT-014 | standard | release-candidate | REQ-018 | dcy-011 | [bat-014_20260703_adapter-surface-narrowing-baseline-refresh](bat-014_20260703_adapter-surface-narrowing-baseline-refresh/) |
@@ -5,10 +5,10 @@
- 문서 ID: dcy-011_20260703_backend-refactor-phase4-write-import-workflow-adapter-narrowing
- 이슈명: Jarca Ledger 백엔드 리팩터링 Phase 4+ 후속 주기 (write service 분리 → import pipeline 분리 → advanced finance workflow 분리 → MCP/Streamlit adapter 표면 축소)
- 작성 시각(KST): 2026-07-03 07:10
- 마지막 갱신 시각(KST): 2026-07-03 07:29
- 마지막 갱신 시각(KST): 2026-07-03 08:23
- 대체됨: 없음
- 후속 Discovery 참조: 없음
- 생성된 REQ 참조: `REQ-015`
- 생성된 REQ 참조: `REQ-015`, `REQ-016`, `REQ-017`, `REQ-018`
# 1. 계획 상태 요약
현재 Discovery가 어떤 배경에서 작성되고 있는지, 연계 문서가 있는지, 지금 시점의 해석이 무엇인지 짧게 요약한다.
@@ -193,8 +193,8 @@ REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지
- 기준: Phase 4~7 우선 In Scope, Phase 8은 Deferred 후보로만 유지, Discovery는 하나로 두되 REQ/Batch는 Phase별·도메인별로 분할한다는 방침이 문서에 반영되어 있다.
- [x] 성공 지표의 측정 방식/데이터 출처 확정
- 기준: S-2의 DoD를 broad application module 책임 축소와 compatibility facade/shim 유지로 채택하고 baseline 테스트 목록은 REQ/planning에서 계측 대상으로 명시한다.
- [ ] High 영향 리스크 우선순위 및 해소 책임자 지정
- 기준: R-1(계약 drift), R-2(advanced 결합)의 characterization/contract 테스트 선행 책임자는 REQ/Batch planning에서 지정한다. Discovery confirm의 차단 사유는 아니다.
- [x] High 영향 리스크 우선순위 및 해소 책임자 지정
- 기준: R-1~R-3은 REQ-015~REQ-018/BAT-011~BAT-014에서 phase owner(렛저장인)와 verification evidence(pytest/AppTest/MCP discovery/contract regression)로 해소 책임이 실제 배정·수행되었다.
- [x] 모든 오픈 질문(OQ) `Open` 상태 없음 확인
- 기준: OQ 목록에 `Open` 상태 항목이 0개이며, 남은 DATA 항목은 REQ/planning의 세부 실행자료로만 이관된다.
- [x] Freeze 확정 담당자(CONFIRMED_BY) 지정
@@ -203,13 +203,21 @@ REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지
# 9. 파일 처리 결과
이 Discovery 문서 생성/갱신 결과와 참조 문서를 기록한다. 이후 추적과 리뷰 시 근거로 사용한다.
- 처리 결과: 생성
- 처리 결과: 생성 후 close-out 갱신
- 생성 경로: docs/discovery/dcy-011_20260703_backend-refactor-phase4-write-import-workflow-adapter-narrowing.md
- 참조 문서:
- docs/discovery/dcy-010_20260702_backend-core-layering-mcp-adapter-realignment.md (선행 Discovery, Phase 0~3, 본 문서가 후속 주기)
- .hermes/plans/2026-07-02_jarca-ledger-backend-refactor-blueprint.md (근거 blueprint, Phase 4~8)
- stage-pilot/templates/project-structure.md (baseline 갱신 논리 템플릿 참조)
- stage-pilot/templates/runtime-flows.md (baseline 갱신 논리 템플릿 참조)
- docs/srs/Non-Functional/req-015_transactional-write-service-split-compatibility.md
- docs/srs/Non-Functional/req-016_import-pipeline-application-infrastructure-split.md
- docs/srs/Non-Functional/req-017_advanced-finance-workflow-service-split.md
- docs/srs/Interface/req-018_adapter-surface-narrowing-baseline-refresh.md
- docs/batches/bat-011_20260703_transactional-write-service-split/
- docs/batches/bat-012_20260703_import-pipeline-split/
- docs/batches/bat-013_20260703_advanced-workflow-service-split/
- docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/
# 10. 사용자 결정 필요 항목 요약
사용자나 승인자가 결정해야 하는 항목만 모아 정리한다. 결정, 확인, 데이터 요청을 구분해서 적는다.
+49 -11
View File
@@ -5,7 +5,7 @@
- Status: draft
- Owner: Jarca / project maintainer
- Last Updated (KST): 2026-07-03
- Source Discovery / Batch: bootstrap-baseline, BAT-006, BAT-007, BAT-010
- Source Discovery / Batch: bootstrap-baseline, BAT-006, BAT-007, BAT-010, BAT-012, BAT-013, BAT-014
## Project Summary
- Jarca 가계부 전용 MCP 서버와 Streamlit 대시보드로 계좌/카드 거래, 예산, 분류 규칙, import, 자산/스냅샷, 현금흐름 분석을 SQLite에 저장하고 운영한다.
@@ -61,10 +61,21 @@ jarca-ledger-mcp/
│ │ ├── shared.py
│ │ ├── system_services.py
│ │ ├── asset_account_services.py
│ │ ├── assets_service.py
│ │ ├── transaction_report_services.py
│ │ ├── import_transfer_services.py
│ │ └── categorization_services.py
│ │ ├── imports_service.py
│ │ ├── cross_transfer_service.py
│ │ ├── reconciliation_service.py
│ │ ├── categorization_services.py
│ │ └── uncategorized_workbench_service.py
│ ├── infrastructure/
│ │ ├── parsers/
│ │ │ ├── __init__.py
│ │ │ ├── kb_bank_pdf.py
│ │ │ ├── toss_bank_pdf.py
│ │ │ ├── toss_securities_pdf.py
│ │ │ └── seoulpay_xlsx.py
│ │ └── sqlite/
│ │ ├── __init__.py
│ │ ├── connection.py
@@ -72,8 +83,18 @@ jarca-ledger-mcp/
│ │ └── migrations.py
│ ├── adapters/
│ │ ├── mcp/
│ │ │ ├── tool_contracts.py
│ │ │ └── server.py
│ │ └── streamlit/
│ │ ├── __init__.py
│ │ ├── overview_gateway.py
│ │ ├── assets_gateway.py
│ │ ├── transactions_gateway.py
│ │ ├── categorization_gateway.py
│ │ ├── transfers_gateway.py
│ │ ├── imports_gateway.py
│ │ ├── accounts_gateway.py
│ │ ├── reconciliation_gateway.py
│ │ └── service_gateway.py
│ ├── kb_bank_pdf.py
│ ├── toss_bank_pdf.py
@@ -121,31 +142,47 @@ jarca-ledger-mcp/
- `jarca_ledger_mcp/server.py`
- Legacy-compatible MCP entrypoint shim that delegates to `adapters.mcp.server`.
- `jarca_ledger_mcp/application/shared.py`
- Shared helpers, validation, KST clock, dedupe policy, parser imports, and cross-domain constants.
- Shared helpers, validation, KST clock, dedupe policy, parser seam imports, and cross-domain constants.
- `jarca_ledger_mcp/application/system_services.py`
- Health/status/backup/account create-list/update and persistence-adjacent service behavior.
- `jarca_ledger_mcp/application/asset_account_services.py`
- Account mutation, manual asset, asset snapshot, liquidity/net-worth logic.
- Legacy-compatible asset/account facade that preserves older import paths while delegating asset ownership to `assets_service.py` and account mutation to write services.
- `jarca_ledger_mcp/application/assets_service.py`
- Manual asset CRUD, snapshot close/report, liquidity, and net-worth workflow ownership.
- `jarca_ledger_mcp/application/transaction_report_services.py`
- Transaction CRUD, budgets, monthly/category/fixed-cost/investable cashflow reports.
- Transaction CRUD, budgets, monthly/category/fixed-cost/investable cashflow reports, with reconciliation delegated to `reconciliation_service.py`.
- `jarca_ledger_mcp/application/import_transfer_services.py`
- Import preview/import, self-transfer/cancel matching, cross-account transfer workflow.
- Legacy-compatible import/transfer facade that preserves prior import paths while delegating to `imports_service.py` and `cross_transfer_service.py`.
- `jarca_ledger_mcp/application/imports_service.py`
- Import preview/import/rollback orchestration and import batch workflow ownership.
- `jarca_ledger_mcp/application/cross_transfer_service.py`
- Cross-account/self-transfer/cancel-original matching workflow ownership.
- `jarca_ledger_mcp/application/reconciliation_service.py`
- Manual/partial-import balance reconciliation preview ownership.
- `jarca_ledger_mcp/application/categorization_services.py`
- Category rules, categorization preview/apply, uncategorized workbench, ledger categories.
- Category rules, categorization preview/apply, ledger categories, and compatibility delegation to `uncategorized_workbench_service.py`.
- `jarca_ledger_mcp/application/uncategorized_workbench_service.py`
- Uncategorized inbox/workbench queries and recommendation-apply workflow ownership.
- `jarca_ledger_mcp/infrastructure/parsers/*`
- Import parser seam that keeps file-source parsing under infrastructure while preserving legacy top-level parser modules.
- `jarca_ledger_mcp/infrastructure/sqlite/connection.py`
- DB path resolution, sqlite connection setup, context manager semantics.
- `jarca_ledger_mcp/infrastructure/sqlite/schema.py`
- Schema version, DDL, additive column definitions.
- `jarca_ledger_mcp/infrastructure/sqlite/migrations.py`
- Additive/idempotent migration routines and DB initialization.
- `jarca_ledger_mcp/adapters/mcp/tool_contracts.py`
- Narrow MCP adapter contract surface that re-exports only the public tool callables consumed by the FastMCP server.
- `jarca_ledger_mcp/adapters/mcp/server.py`
- FastMCP tool registration layer that exposes service functions to Hermes/MCP clients.
- FastMCP tool registration layer that depends on `tool_contracts.py` instead of broad direct service imports.
- `jarca_ledger_mcp/adapters/streamlit/service_gateway.py`
- Narrow dashboard-facing service surface used by `dashboard/app.py`.
- Compatibility aggregator over page/domain gateway modules.
- `jarca_ledger_mcp/adapters/streamlit/*_gateway.py`
- Page/domain-sized dashboard service surfaces (`overview`, `assets`, `transactions`, `categorization`, `transfers`, `imports`, `accounts`, `reconciliation`).
- Parser modules (`kb_bank_pdf.py`, `toss_bank_pdf.py`, `toss_securities_pdf.py`, `seoulpay_xlsx.py`)
- Source-file parsing and preview conversion only.
- `dashboard/app.py`
- Streamlit operator UI for the operations hub summary, 자산/마감, 거래내역, 확인필요 큐, 미분류, 분류 규칙, 카테고리, 계좌, Import pages.
- Streamlit operator UI for the operations hub summary, 자산/마감, 거래내역, 확인필요 큐, 미분류, 분류 규칙, 카테고리, 계좌, Import pages, wired through page/domain gateways instead of a flat broad service namespace.
- `tests/`
- Regression tests for facade compatibility, service behavior, parser behavior, categorization, transfer matching, MCP contract compatibility, and Streamlit AppTest smoke.
- `.github/workflows/ci.yml`
@@ -178,7 +215,7 @@ jarca-ledger-mcp/
## Current Gaps / Planned Changes
- Application modules are now separated by phase-0~3 domain seams, but deeper repository/use-case split remains future Phase 4+ work.
- Streamlit gateway is intentionally narrow for current pages; further page/domain-specific gateways may follow in later phases.
- Streamlit now uses page/domain gateways; deeper presenter/view-model extraction remains future work.
- HTTP adapter and remote ops re-architecture remain out of scope.
## Update Triggers
@@ -193,3 +230,4 @@ jarca-ledger-mcp/
- 2026-06-30 KST: REQ-006/BAT-006 기준으로 GitHub Actions CI workflow, synthetic fixture DB builder, AppTest/HTTP/DB safety smoke wrappers 추가.
- 2026-06-30 KST: REQ-007/REQ-008/BAT-007 기준으로 MCP response contract snapshot/test 위치와 required-check job 계약 추가.
- 2026-07-03 KST: REQ-013/REQ-014/BAT-010 기준으로 application / infrastructure / adapter layering, compatibility facade/shim, Streamlit gateway 구조를 반영했다.
- 2026-07-03 KST: REQ-016/REQ-017/REQ-018 및 BAT-012/BAT-013/BAT-014 기준으로 import/advanced owning services, parser seam, MCP contract helper, page/domain Streamlit gateways를 반영했다.
+12 -11
View File
@@ -5,7 +5,7 @@
- Status: draft
- Owner: Jarca / project maintainer
- Last Updated (KST): 2026-07-03
- Source Discovery / Batch: bootstrap-baseline, BAT-006, BAT-007, BAT-008, BAT-010
- Source Discovery / Batch: bootstrap-baseline, BAT-006, BAT-007, BAT-008, BAT-010, BAT-012, BAT-013, BAT-014
- Primary Runtime: mixed
## Project Summary
@@ -29,13 +29,13 @@
- SQLite database at `~/.local/share/jarca/ledger.sqlite3` by default.
- `jarca_ledger_mcp/service.py` compatibility facade over application modules.
- `jarca_ledger_mcp/infrastructure/sqlite/*` for DB path resolution, schema, migration, and connection lifecycle.
- `jarca_ledger_mcp/adapters/mcp/server.py` for MCP registration.
- `jarca_ledger_mcp/adapters/streamlit/service_gateway.py` for dashboard-facing service calls.
- Parser modules for KB/Toss/SeoulPay sources.
- `jarca_ledger_mcp/adapters/mcp/tool_contracts.py` + `adapters/mcp/server.py` for MCP contract and registration seams.
- `jarca_ledger_mcp/adapters/streamlit/*_gateway.py` + `service_gateway.py` compatibility aggregator for dashboard-facing service calls.
- `jarca_ledger_mcp/infrastructure/parsers/*` plus legacy parser modules for KB/Toss/SeoulPay sources.
## Flow: `MCP server tool call`
1. Hermes MCP client invokes a tool exposed by `jarca_ledger_mcp.server` / `jarca_ledger_mcp.adapters.mcp.server`.
2. MCP adapter forwards arguments to the matching `jarca_ledger_mcp.service` facade function.
2. MCP adapter forwards arguments to the matching callable exposed by `adapters/mcp/tool_contracts.py`.
3. Service facade routes into the relevant application module.
4. Application code opens SQLite through `infrastructure/sqlite` helpers, validates inputs, and performs the operation.
5. Application returns a dictionary payload with success data or error information.
@@ -45,8 +45,8 @@
1. Operator starts `streamlit run dashboard/app.py --server.address 0.0.0.0 --server.port 8501`.
2. Dashboard reads the configured/default SQLite database.
3. User navigates to 요약, 자산/마감, 거래내역, 확인필요 큐, 미분류, 분류 규칙, 카테고리, 계좌, or Import pages.
4. UI calls `jarca_ledger_mcp.adapters.streamlit.service_gateway` rather than giant implementation modules directly.
5. Gateway delegates to the service facade/application modules and returns data to the page.
4. UI calls page/domain gateways under `jarca_ledger_mcp.adapters.streamlit` rather than giant implementation modules directly.
5. Gateways delegate to the service facade/application modules and return data to the page.
6. UI displays success/error status and refreshes visible tables.
## Flow: `Dashboard operations hub overview`
@@ -66,8 +66,8 @@
## Flow: `Import preview and import`
1. Operator chooses a supported source file: KB Bank PDF, Toss Bank PDF, Toss Securities PDF, SeoulPay XLSX, or CSV.
2. Preview function parses the file and reports counts, sample rows, duplicate status, and classification preview.
3. On explicit import, application code creates/fetches the target account, inserts non-duplicate transactions, writes provenance, and records an import batch.
2. Preview function routes through `imports_service.py`, which calls the parser seam under `infrastructure/parsers/*` and reports counts, sample rows, duplicate status, and classification preview.
3. On explicit import, `imports_service.py` creates/fetches the target account, inserts non-duplicate transactions, writes provenance, and records an import batch.
4. Reports and dashboard views read the inserted rows using shared category/cashflow semantics.
5. If an import is wrong, rollback uses import batch data and soft-deletes by default.
@@ -78,7 +78,7 @@
4. Category `cashflow_kind` controls actual cashflow/report inclusion.
## Flow: `Cross-account and cancel/original reconciliation`
1. Preview helpers search candidate pairs by amount, date, direction, account/source compatibility, and text similarity.
1. Preview helpers in `cross_transfer_service.py` search candidate pairs by amount, date, direction, account/source compatibility, and text similarity.
2. Operator reviews candidates in the dashboard or runs the automatic matcher where confidence rules are satisfied.
3. Matched self-transfers become `이체 / 본인계좌이동`; investment movements become `이체 / 투자이동`; ambiguous rows remain `확인필요`.
4. Cancel/refund rows can be linked to original expense rows; memo tags preserve manual link evidence.
@@ -120,7 +120,7 @@
## Current Gaps / Planned Changes
- Browser-level evidence exists locally and remains outside required CI gates by design.
- Phase 4+ write/import/advanced workflow service thinning and narrower adapters are deferred to GitHub Project TODO items.
- Post-Phase-7 adapter narrowing is complete for the current compatibility architecture; deeper repository/use-case extraction and richer presenter/view-model layers remain future work.
- HTTP adapter and remote ops re-architecture remain deferred.
## Update Triggers
@@ -137,3 +137,4 @@
- 2026-06-30 KST: REQ-006/BAT-006 기준으로 GitHub Actions CI validation gates, synthetic fixture DB boundary, AppTest/HTTP/DB safety smoke flow 추가.
- 2026-06-30 KST: REQ-007/REQ-008/BAT-007 기준으로 contract-regression/lint CI required-check flow 추가.
- 2026-07-03 KST: REQ-013/REQ-014/BAT-010 기준으로 service facade → application, db shim → infrastructure/sqlite, MCP/Streamlit adapter seam flow를 반영했다.
- 2026-07-03 KST: REQ-016/REQ-017/REQ-018 및 BAT-012/BAT-013/BAT-014 기준으로 imports/advanced owning services, parser seam, MCP tool_contracts, Streamlit page/domain gateway flow를 반영했다.
@@ -0,0 +1,63 @@
# REQ-018 MCP/Streamlit adapter surface narrowing and baseline refresh for dcy-011 completion
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: 렛저장인
- Source Discovery: `docs/discovery/dcy-011_20260703_backend-refactor-phase4-write-import-workflow-adapter-narrowing.md`
- Batch: BAT-014
- Created At (KST): 2026-07-03 08:03 KST
- Approved At (KST): 2026-07-03 08:03 KST
- Implemented At (KST): 2026-07-03 08:23 KST
## 1. 배경
`REQ-015`~`REQ-017`으로 write/import/advanced workflow owning services는 분리되었지만, adapter 계층은 아직 broad surfaces를 유지한다. `adapters/mcp/server.py`는 모든 tool wrapper가 직접 `service.py`에 의존하고, `dashboard/app.py`는 flat `service_gateway` namespace에 넓게 결합되어 있다. dcy-011의 마지막 단계는 이 adapter surfaces를 더 좁히고 baseline 문서를 실제 구조에 맞춰 갱신하는 것이다.
## 2. Intent
MCP adapter는 contract/registration helper를 통해 service facade 의존을 더 국소화하고, Streamlit dashboard는 page/domain gateway를 명시적으로 사용하도록 재구성한다. 동시에 `docs/project-structure.md`와 `docs/runtime-flows.md`를 Phase 4~7 완료 상태에 맞게 refresh 해 dcy-011을 완결한다.
## 3. 범위
### In Scope
- `adapters/mcp/tool_contracts.py` 또는 동등 helper를 도입해 MCP tool wrappers의 broad service dependency를 줄임
- `adapters/streamlit/*_gateway.py` page/domain gateways를 도입/확장해 `dashboard/app.py`의 flat gateway 결합을 줄임
- `adapters/streamlit/service_gateway.py`는 compatibility aggregator로 유지 가능
- `docs/project-structure.md`, `docs/runtime-flows.md`, dcy-011 metadata/status 갱신
### Out of Scope
- MCP tool 이름/응답 shape 변경
- Streamlit UX redesign
- HTTP adapter 구현
## 4. Requirement
### FR-1. MCP contract helper narrowing
- `adapters/mcp/server.py`는 직접 `service`에 광범위하게 결합하지 않고 helper/contract layer를 통해 tool contract를 호출해야 한다.
### FR-2. Streamlit page/domain gateways
- `dashboard/app.py`는 flat broad gateway 대신 overview/assets/transfers/categories/import/accounts 등 page/domain gateway를 사용해야 한다.
- hot-reload fallback은 유지하되, broad implementation module 직접 import로 되돌아가면 안 된다.
### FR-3. Baseline refresh
- `docs/project-structure.md`와 `docs/runtime-flows.md`는 Phase 4~7 완료 후 구조/흐름을 반영해야 한다.
## 5. Acceptance Criteria
- AC-1: MCP adapter helper/contract seam과 Streamlit page/domain gateway modules가 존재한다.
- AC-2: `dashboard/app.py`가 flat broad gateway 의존을 줄이고 page/domain gateway 호출로 동작한다.
- AC-3: `pytest tests/test_dashboard_app.py`, full pytest, MCP discovery, 필요 시 browser/HTTP smoke가 PASS 한다.
- AC-4: baseline docs와 dcy-011 status/links가 완료 상태를 반영한다.
## 6. Impacted Area
- `jarca_ledger_mcp/adapters/mcp/server.py`
- `jarca_ledger_mcp/adapters/mcp/tool_contracts.py`
- `jarca_ledger_mcp/adapters/streamlit/*.py`
- `dashboard/app.py`
- `docs/project-structure.md`
- `docs/runtime-flows.md`
- `docs/discovery/dcy-011_20260703_backend-refactor-phase4-write-import-workflow-adapter-narrowing.md`
## 7. Change Log
- 2026-07-03 08:03 KST: dcy-011 Phase 7 adapter narrowing + baseline refresh 범위를 바탕으로 REQ-018을 생성하고 BAT-014 입력으로 즉시 승인했다.
- 2026-07-03 08:23 KST: MCP tool_contracts, Streamlit page/domain gateways, baseline 문서 refresh, AppTest/full pytest/MCP discovery evidence를 근거로 REQ-018을 Implemented로 전환했다.
@@ -0,0 +1,80 @@
# REQ-016 Import pipeline application/infrastructure split and evidence-preserving parser relocation
- Status: Implemented
- Type: Non-Functional
- Priority: High
- Owner: 렛저장인
- Source Discovery: `docs/discovery/dcy-011_20260703_backend-refactor-phase4-write-import-workflow-adapter-narrowing.md`
- Batch: BAT-012
- Created At (KST): 2026-07-03 07:49 KST
- Approved At (KST): 2026-07-03 07:49 KST
- Implemented At (KST): 2026-07-03 07:53 KST
## 1. 배경
`REQ-015`/BAT-011로 transactional write path는 좁은 write-oriented application module로 분리됐지만, import preview/import/rollback과 account auto-linking/classification/orchestration은 여전히 `application/import_transfer_services.py`에 크게 남아 있다. 또한 parser entrypoint는 top-level `kb_bank_pdf.py`, `toss_bank_pdf.py`, `toss_securities_pdf.py`, `seoulpay_xlsx.py`에 흩어져 있어 application layer가 parser 구현 위치를 직접 아는 구조다.
## 2. Intent
이 REQ의 목적은 import preview/import/rollback을 전용 `imports_service`로 분리하고, parser access path를 `infrastructure/parsers/*`로 정리해 parser(파싱/정규화)와 application import orchestration(dedupe/account auto-link/import_batch persistence/classification/post-import bookkeeping)을 구분하는 것이다. 기존 MCP tool 이름, response envelope, import evidence fields는 유지해야 한다.
## 3. 범위
### In Scope
- `preview_ledger_csv_import`
- `preview/import_kb_bank_pdf`
- `preview/import_seoulpay_xlsx`
- `preview/import_toss_bank_pdf`
- `preview/import_toss_securities_pdf`
- `list_ledger_import_batches`
- `rollback_ledger_import_batch`
- import용 account auto-linking/classification/helper를 `imports_service` 경계로 이동
- parser import 경로를 `jarca_ledger_mcp/infrastructure/parsers/*`로 정리
- 기존 `application/import_transfer_services.py`는 advanced workflow 중심으로 남기고 import-facing 함수는 compatibility delegation으로 유지
### Out of Scope
- cross-transfer/reconciliation split
- asset/net worth/workbench split
- MCP/Streamlit adapter surface narrowing
- parser 알고리즘/분류 semantics 변경
- destructive migration
## 4. Requirement
### FR-1. Import orchestration service extraction
- import preview/import/rollback과 account auto-linking/classification helper는 `application/imports_service.py`로 이동해야 한다.
- `service.py`, MCP adapter, 기존 호출 surface는 함수명/인자/응답 envelope을 유지해야 한다.
### FR-2. Parser relocation by infrastructure seam
- application layer는 parser 구현을 top-level 모듈에서 직접 끌어오지 않고 `infrastructure/parsers/*` 경로를 통해 접근해야 한다.
- parser는 parsing/normalization/preview helper를 제공하고, persistence/import_batch 생성/transaction insert는 application service에 남아야 한다.
### FR-3. Evidence-preserving contract safety
- `raw_summary`, `counterparty`, `raw_payload`, `external_id`, `import_batch_id`, duplicate counting, validation payload 등 import evidence 필드는 의도적으로 변경되지 않아야 한다.
- import regression tests, rollback behavior, MCP discovery가 PASS 해야 한다.
## 5. Acceptance Criteria
- AC-1: `application/imports_service.py`와 `infrastructure/parsers/*`가 생성되고 import preview/import/rollback 구현이 그쪽으로 이동한다.
- AC-2: 기존 public API/MCP tools/import response envelope과 evidence fields가 유지된다.
- AC-3: import-related regression과 full pytest가 PASS 한다.
- AC-4: BAT-012 implementation/verification 문서가 실제 changed files, commands, outcomes를 기록한다.
## 6. Impacted Area
- `jarca_ledger_mcp/application/import_transfer_services.py`
- `jarca_ledger_mcp/application/imports_service.py`
- `jarca_ledger_mcp/application/shared.py`
- `jarca_ledger_mcp/infrastructure/parsers/*`
- `jarca_ledger_mcp/service.py`
- `jarca_ledger_mcp/adapters/mcp/server.py`
- `tests/test_kb_bank_pdf.py`
- `tests/test_seoulpay_xlsx.py`
- `tests/test_toss_securities_pdf.py`
- `tests/test_service.py`
## 7. Notes
- 이 REQ는 package boundary와 maintainability 중심의 refactor이므로 `Non-Functional`로 관리한다.
- advanced workflow split은 후속 REQ/BAT로 이어진다.
## 8. Change Log
- 2026-07-03 07:49 KST: dcy-011 Phase 5 import pipeline split 범위를 바탕으로 REQ-016을 생성하고 BAT-012 입력으로 즉시 승인했다.
- 2026-07-03 07:53 KST: imports_service/parsers seam 분리, import-focused regression, full pytest, MCP discovery evidence를 근거로 Implemented로 전환했다.
@@ -0,0 +1,70 @@
# REQ-017 Advanced finance workflow service split and compatibility-preserving domain isolation
- Status: Implemented
- Type: Non-Functional
- Priority: High
- Owner: 렛저장인
- Source Discovery: `docs/discovery/dcy-011_20260703_backend-refactor-phase4-write-import-workflow-adapter-narrowing.md`
- Batch: BAT-013
- Created At (KST): 2026-07-03 07:55 KST
- Approved At (KST): 2026-07-03 07:55 KST
- Implemented At (KST): 2026-07-03 08:01 KST
## 1. 배경
`REQ-015`와 `REQ-016`으로 transactional write path와 import pipeline seam은 좁아졌지만, cross-transfer matching/review, balance reconciliation, manual asset/snapshot/net-worth workflows, uncategorized workbench는 여전히 broad application modules(`import_transfer_services.py`, `transaction_report_services.py`, `asset_account_services.py`, `categorization_services.py`)에 흩어져 있다.
## 2. Intent
이 REQ의 목적은 advanced finance workflows를 domain-oriented application modules로 추가 분리해 import/write/read service와 책임이 겹치지 않게 하는 것이다. public API, MCP contracts, dashboard behavior는 유지해야 하며, domain-heavy helpers는 owning workflow service로 이동해야 한다.
## 3. 범위
### In Scope
- cross-transfer matching/review queue를 `application/cross_transfer_service.py`로 이동
- balance reconciliation을 `application/reconciliation_service.py`로 이동
- manual asset CRUD / snapshot / liquidity / net-worth workflows를 `application/assets_service.py`로 이동
- uncategorized list/summary/workbench/recommendation apply 흐름을 `application/uncategorized_workbench_service.py`로 이동
- 기존 broad modules는 compatibility delegation을 유지
### Out of Scope
- MCP/Streamlit adapter surface narrowing
- baseline docs final update
- tool contract rename or semantic changes
- destructive migration
## 4. Requirement
### FR-1. Advanced workflow ownership split
- cross-transfer, reconciliation, assets, uncategorized workbench는 각각 owning application module로 이동해야 한다.
- helper 함수도 첫 소비자와 함께 이동해 broad module 내부 숨은 결합을 줄여야 한다.
### FR-2. Compatibility-preserving delegation
- `service.py`, MCP tool names, dashboard call signatures, response envelope은 유지해야 한다.
- 기존 broad modules는 필요 시 thin delegation/re-export layer로 남을 수 있다.
### FR-3. Regression-safe domain isolation
- cross-transfer tests, asset snapshot/manual asset tests, reconciliation tests, uncategorized workflow tests, full pytest가 PASS 해야 한다.
## 5. Acceptance Criteria
- AC-1: `cross_transfer_service.py`, `reconciliation_service.py`, `assets_service.py`, `uncategorized_workbench_service.py`가 생성되고 owning workflow 구현이 이동한다.
- AC-2: public API/MCP/dashboard contract가 유지된다.
- AC-3: workflow-focused regression과 full pytest가 PASS 한다.
- AC-4: BAT-013 implementation/verification 문서가 실제 변경 파일과 검증 결과를 반영한다.
## 6. Impacted Area
- `jarca_ledger_mcp/application/import_transfer_services.py`
- `jarca_ledger_mcp/application/transaction_report_services.py`
- `jarca_ledger_mcp/application/asset_account_services.py`
- `jarca_ledger_mcp/application/categorization_services.py`
- `jarca_ledger_mcp/application/{cross_transfer,reconciliation,assets,uncategorized_workbench}_service.py`
- `jarca_ledger_mcp/service.py`
- `tests/test_cross_account_transfer_matching.py`
- `tests/test_asset_snapshots.py`
- `tests/test_contract_regression.py`
- `tests/test_categorization.py`
- `tests/test_service.py`
## 7. Change Log
- 2026-07-03 07:55 KST: dcy-011 Phase 6 advanced workflow split 범위를 바탕으로 REQ-017을 생성하고 BAT-013 입력으로 즉시 승인했다.
- 2026-07-03 08:01 KST: advanced workflow service extraction, full pytest, MCP discovery evidence를 근거로 Implemented로 전환했다.
+10 -1
View File
@@ -33,7 +33,7 @@
## Next Requirement ID
- Current: `REQ-016`
- Current: `REQ-019`
- Rule: `Requirement Register`에 있는 가장 큰 REQ 번호보다 정확히 1 커야 한다.
## Requirement Register
@@ -55,6 +55,9 @@
| REQ-013 | Backend core layering / SQLite infrastructure split and service facade compatibility | Non-Functional | Implemented | High | 렛저장인 | [req-013_backend-core-layering-sqlite-infrastructure-service-facade-compatibility.md](Non-Functional/req-013_backend-core-layering-sqlite-infrastructure-service-facade-compatibility.md) |
| REQ-014 | MCP/Streamlit adapter seam realignment and contract-preserving gateway | Interface | Implemented | High | 렛저장인 | [req-014_mcp-streamlit-adapter-seam-realignment-contract-preserving-gateway.md](Interface/req-014_mcp-streamlit-adapter-seam-realignment-contract-preserving-gateway.md) |
| REQ-015 | Transactional write service split and compatibility-preserving domain extraction | Non-Functional | Implemented | High | 렛저장인 | [req-015_transactional-write-service-split-compatibility.md](Non-Functional/req-015_transactional-write-service-split-compatibility.md) |
| REQ-016 | Import pipeline application/infrastructure split and evidence-preserving parser relocation | Non-Functional | Implemented | High | 렛저장인 | [req-016_import-pipeline-application-infrastructure-split.md](Non-Functional/req-016_import-pipeline-application-infrastructure-split.md) |
| REQ-017 | Advanced finance workflow service split and compatibility-preserving domain isolation | Non-Functional | Implemented | High | 렛저장인 | [req-017_advanced-finance-workflow-service-split.md](Non-Functional/req-017_advanced-finance-workflow-service-split.md) |
| REQ-018 | MCP/Streamlit adapter surface narrowing and baseline refresh for dcy-011 completion | Interface | Implemented | High | 렛저장인 | [req-018_adapter-surface-narrowing-baseline-refresh.md](Interface/req-018_adapter-surface-narrowing-baseline-refresh.md) |
## Recent Change Log Summary
@@ -83,3 +86,9 @@
- 2026-07-03 00:18 KST: BAT-010 구현·검증 evidence, full pytest PASS, MCP tool discovery, browser smoke를 근거로 `REQ-013`, `REQ-014`를 Implemented로 전환했다.
- 2026-07-03 07:30 KST: dcy-011 confirmed 범위를 `REQ-015` Proposed로 생성하고 첫 delivery 입력으로 Approved 상태로 전환했다.
- 2026-07-03 07:39 KST: BAT-011 write-service split 구현과 full pytest/MCP discovery evidence를 근거로 `REQ-015`를 Implemented로 전환했다.
- 2026-07-03 07:49 KST: dcy-011 Phase 5 import pipeline split 범위를 `REQ-016`으로 생성하고 BAT-012 입력으로 Approved 상태를 확정했다.
- 2026-07-03 07:53 KST: BAT-012 import pipeline split 구현과 full pytest/MCP discovery evidence를 근거로 `REQ-016`을 Implemented로 전환했다.
- 2026-07-03 07:55 KST: dcy-011 Phase 6 advanced workflow split 범위를 `REQ-017`로 생성하고 BAT-013 입력으로 Approved 상태를 확정했다.
- 2026-07-03 08:01 KST: BAT-013 advanced workflow split 구현과 full pytest/MCP discovery evidence를 근거로 `REQ-017`을 Implemented로 전환했다.
- 2026-07-03 08:03 KST: dcy-011 Phase 7 adapter narrowing + baseline refresh 범위를 `REQ-018`로 생성하고 BAT-014 입력으로 Approved 상태를 확정했다.
- 2026-07-03 08:23 KST: BAT-014 adapter narrowing + baseline refresh 구현과 AppTest/full pytest/MCP discovery evidence를 근거로 `REQ-018`을 Implemented로 전환했다.