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/) |