소스 정리

This commit is contained in:
2026-08-09 17:13:24 +09:00
parent 9400c0178c
commit 23f6b32b0c
335 changed files with 1 additions and 28323 deletions
@@ -1,37 +0,0 @@
# BAT-001 Implementation
## Status
- Status: implemented-qc-passed
- Last Updated (KST): 2026-06-26 23:41
## Changed Files
- `jarca_ledger_mcp/server.py`
- `delete_category_rule(rule_id: str)` MCP tool을 additive 등록했다.
- `dashboard/app.py`
- 분류 규칙 page의 `seed_default_category_rules`, `preview_categorization`, `apply_categorization_rules` 호출이 page-level `db_path`를 전달하도록 수정했다.
- `tests/test_category_rule_filters.py`
- category rule 삭제 성공, 삭제 후 list 제외, missing ID `not_found` regression을 추가했다.
- StagePilot 문서
- `docs/srs/Interface/req-001_category-rule-ops.md`
- `docs/srs/index.md`
- `docs/batches/bat-001_20260626_category-rule-ops/*`
- `docs/batches/index.md`
- `docs/discovery/dcy-001_20260626_streamlit-ux-e2e-categorization-refund-workflows.md`
## Execution Log
- 2026-06-26 23:31 KST: batch-lite 계획 수립.
- 2026-06-26 23:33 KST: MCP delete tool, Streamlit db_path 전달, deletion regression test 구현.
- 2026-06-26 23:36 KST: service/pytest/MCP/Streamlit AppTest smoke 검증 완료.
- 2026-06-26 23:41 KST: 검수관 QC gate `PASS_WITH_NOTES` 확인, blocker 없음.
## Validation During Implementation
- `python -m py_compile jarca_ledger_mcp/*.py dashboard/app.py`: pass.
- `pytest tests/test_category_rule_filters.py`: 3 passed.
- `pytest tests/test_cross_account_transfer_matching.py`: 3 passed.
- `pytest`: 17 passed, 4 skipped.
- `hermes mcp test jarca-ledger`: connected, 41 tools discovered, `delete_category_rule` discovered.
- Streamlit smoke: port 8502 synthetic fixture DB `/tmp/jarca-ledger-bat-001-smoke.sqlite3`; browser tool unavailable because local Chromium snap is not installed, so `streamlit.testing.v1.AppTest` was used. 분류 규칙 page rendered without exceptions; title/subheader/buttons/rule item were visible; preview/apply buttons ran without errors; default 운영 DB mtime unchanged.
## Remaining Risks
- Browser screenshot evidence was not captured because `/usr/bin/chromium-browser` requires the unavailable chromium snap. AppTest + HTTP 200 smoke was used as substitute evidence.
- Import/rollback and cancel/refund workflows remain outside BAT-001 and should be handled by later REQ/BAT.
@@ -1,35 +0,0 @@
# BAT-001: Category Rule Ops Safety
## 0. 문서 상태
- BAT ID: BAT-001
- Profile: batch-lite
- Status: release-candidate
- Source Discovery: dcy-001_20260626_streamlit-ux-e2e-categorization-refund-workflows
- Included REQ: REQ-001
- Created At (KST): 2026-06-26 23:31
- Last Updated (KST): 2026-06-26 23:41
## 1. Scope
분류 규칙 lifecycle 중 가장 작고 검증 가능한 운영 액션을 안정화한다.
### Included
- Streamlit 분류 규칙 seed/preview/apply 액션이 선택된 `db_path`를 사용하도록 수정.
- MCP tool surface에 `delete_category_rule` additive 등록.
- service-level category rule deletion regression test 추가.
- py_compile, pytest, MCP tool smoke, Streamlit screenshot/browser smoke 증거 기록.
### Excluded
- 신규 parser 추가.
- 파괴적 SQLite migration.
- 운영 원본 DB 직접 mutation.
- import/rollback 전체 E2E와 취소/환급 연결 workflow 구현.
## 2. Documents
- Planning: [planning.md](planning.md)
- Implementation: [implementation.md](implementation.md)
- Verification: [verification.md](verification.md)
## 3. Notes
- 단일 REQ, additive MCP tool, UI DB-path bug fix만 포함하므로 `batch-lite`로 진행한다.
- 구현 중 구조/런타임 flow 변화가 커지면 design 문서를 추가한다.
- 검수관 QC gate 결과 `PASS_WITH_NOTES`; blocker 없음. Browser screenshot은 Chromium snap 부재로 대체 smoke(AppTest) 증거를 사용했다.
@@ -1,21 +0,0 @@
# BAT-001 Planning
## 1. Goal
REQ-001의 분류 규칙 운영 액션을 작은 단위로 구현하고 검증한다.
## 2. Design Gate
- Decision: design.md 생략, batch-lite 유지.
- Rationale: schema 변경이나 신규 runtime flow 없이 기존 service function을 MCP에 additive 등록하고 dashboard 호출부의 `db_path` 전달 누락을 수정하는 국소 변경이다.
## 3. Implementation Plan
1. `server.py`에 `delete_category_rule(rule_id: str)` MCP tool을 추가한다.
2. `dashboard/app.py`의 분류 규칙 seed/update, preview, apply 호출에 `db_path=db_path`를 전달한다.
3. `tests/test_category_rule_filters.py`에 삭제 성공/삭제 후 list 제외/없는 ID 실패 regression을 추가한다.
4. 검증 명령을 실행하고 결과를 `verification.md`에 기록한다.
5. 검수관 QC gate PASS 후 REQ-001을 Implemented로 전환한다.
## 4. Risks and Mitigations
- Risk: Streamlit smoke 중 기본 운영 DB를 건드릴 수 있음.
- Mitigation: `JARCA_LEDGER_DB_PATH`를 tmp synthetic DB로 지정해 dashboard를 실행한다.
- Risk: MCP tool 목록이 캐시되어 신규 tool이 보이지 않을 수 있음.
- Mitigation: `hermes mcp test jarca-ledger`로 새 프로세스 기준 smoke를 수행한다.
@@ -1,47 +0,0 @@
# BAT-001 Verification
## Status
- Ready for Release: true
- QC Verdict: PASS_WITH_NOTES
- Last Updated (KST): 2026-06-26 23:41
## Acceptance Mapping
| REQ | AC | Evidence | Result |
| --- | --- | --- | --- |
| REQ-001 | AC-1 | `dashboard/app.py` diff: `seed_default_category_rules`, `preview_categorization`, `apply_categorization_rules` now receive `db_path=db_path`; Streamlit AppTest preview/apply smoke used `JARCA_LEDGER_DB_PATH=/tmp/jarca-ledger-bat-001-smoke.sqlite3` and default DB mtime stayed unchanged. | Pass |
| REQ-001 | AC-2 | `jarca_ledger_mcp/server.py` diff adds `delete_category_rule(rule_id: str)` MCP tool; `hermes mcp test jarca-ledger` discovered 41 tools including `delete_category_rule`. | Pass |
| REQ-001 | AC-3 | `pytest tests/test_category_rule_filters.py` includes `test_delete_category_rule_removes_rule_and_reports_missing_ids`; result: 3 passed. | Pass |
| REQ-001 | AC-4 | py_compile, targeted pytest, full pytest, and MCP smoke all passed; command outputs summarized below. | Pass |
| REQ-001 | AC-5 | Streamlit was run with synthetic fixture DB `/tmp/jarca-ledger-bat-001-smoke.sqlite3`; no original financial file/password/real account fixture used; `/root/.local/share/jarca/ledger.sqlite3` mtime before/after preview/apply smoke remained `1782190349`. | Pass with substitute smoke |
## Evidence Log
- `python -m py_compile jarca_ledger_mcp/*.py dashboard/app.py` → exit 0.
- `pytest tests/test_category_rule_filters.py` → `3 passed in 1.77s`.
- `pytest tests/test_cross_account_transfer_matching.py` → `3 passed in 1.92s`.
- `pytest` → `17 passed, 4 skipped in 17.63s`.
- `hermes mcp test jarca-ledger` → connected in 2460ms; 41 tools discovered; `delete_category_rule` listed.
- Streamlit server smoke:
- port 8501 was occupied, so port 8502 was used.
- `curl -I http://127.0.0.1:8502` → `HTTP/1.1 200 OK`.
- Browser tool failed before page load because Chromium snap is not installed: `Chrome exited early ... requires the chromium snap to be installed`.
- Substitute AppTest smoke output: `exceptions 0`, title `⚙️ 분류 규칙`, subheader `현재 분류 규칙`, buttons `추가`, `변경`, `삭제`, `기본 규칙 seed/update`, `규칙 preview`, `규칙 적용`, synthetic rule text `스모크상점` present.
- AppTest preview/apply output: `preview_exceptions 0`, info `스캔 0건 · 매칭 0건 · 미분류 0건`, `apply_exceptions 0`, success `0건 적용`, default DB mtime unchanged.
## Blocking Issues
- 없음.
## QC Gate
- Reviewer profile: `jarcaledgerqc` (검수관)
- Command: `jarcaledgerqc chat -q "QC gate 요청..."`
- Verdict: `PASS_WITH_NOTES`
- Blockers: 없음
- Notes:
- Browser-level screenshot evidence was unavailable because Chromium snap is not installed; AppTest + HTTP 200 was accepted as substitute evidence for this small BAT.
- Future Streamlit UX/E2E batches should restore real browser/screenshot evidence.
- Optional future strengthening: temp MCP subprocess create/delete/list actual tool-call E2E.
## Notes
- No destructive migration.
- No direct mutation of the original 운영 DB during smoke; only mtime check was performed on default DB.
- Browser screenshot evidence was attempted but blocked by missing Chromium; AppTest + HTTP 200 evidence is the recorded semi-automated substitute.
@@ -1,42 +0,0 @@
# BAT-002 Design
## Architecture Summary
BAT-002 adds a small operational-safety layer around the existing SQLite ledger without changing transaction schemas. The service layer produces metadata-only DB evidence, creates backups with SQLite's online backup API, lists backup files, and validates one backup file. MCP exposes only non-destructive backup/status operations. Restore remains a repo script/runbook workflow requiring explicit user approval before overwriting a target DB.
## Changed Areas
- `jarca_ledger_mcp/service.py`
- New constants: default backup directory and restore policy.
- New helpers: sha256, file metadata, read-only SQLite status, safe table counts, aggregate totals.
- New public functions: `get_ledger_db_status`, `create_ledger_backup`, `list_ledger_backups`, `get_ledger_backup_status`.
- `jarca_ledger_mcp/server.py`
- New additive MCP tools for backup/status/list/hash only.
- No restore MCP tool.
- `scripts/ledger_restore_smoke.py`
- Script-only restore smoke helper with explicit overwrite approval token.
- Docs/tests
- Synthetic tests and operational runbook/baseline docs.
## Key Decisions
1. Backup creation uses SQLite online backup API rather than raw copy so WAL-mode DBs are copied consistently.
2. Backup evidence returns metadata only: path, size, mtime, sha256, integrity result, table row counts, and aggregate totals by cashflow kind.
3. Retention policy implements "recent 30 days OR recent 20 files" by pruning only files that are both older than the retention window and outside the newest count.
4. Restore is deliberately excluded from MCP. The script exists for fixture/validation DB restore smoke and requires `RESTORE_APPROVED` for overwriting any existing target.
5. Existing success response shapes are preserved; all new response fields are additive under new tools/functions.
## Edge Cases
- Missing source DB: backup/status returns `not_found` rather than initializing or mutating a new DB.
- Empty backup directory: list returns success with zero backups.
- Invalid/corrupt backup: backup status includes integrity error metadata and restore smoke fails before copying.
- Existing target restore path: restore smoke fails unless `--allow-overwrite --approval-token RESTORE_APPROVED` are supplied.
- Sensitive row data: metadata collection never selects merchant, counterparty, account number, raw_payload, or raw financial file content.
## Architecture Impact
- runtime-flows: updated with backup/status and restore-restricted operational flow.
- data-model: updated with backup artifact and evidence policy notes.
- interface-contract: updated with new MCP tools and explicit no-restore-MCP rule.
## Reference Doc Update Plan
- Update `docs/runtime-flows.md` with operational backup/validation/restore-smoke flow and high-risk flow constraints.
- Update `docs/data-model.md` with backup artifact/evidence persistence boundary.
- Update `docs/interface-contract.md` with additive backup/status tools and restore non-exposure.
- Add `docs/runbooks/ledger-backup-restore.md`.
@@ -1,62 +0,0 @@
# BAT-002 Implementation
## Plan Summary
Implemented REQ-002 as a staged additive operational-safety change. No transaction schema migration, operating DB restore, or broad data rewrite was performed.
## Changed Files
- `jarca_ledger_mcp/service.py`
- Added metadata-only DB status helpers.
- Added SQLite online backup creation with retention enforcement.
- Added backup list/status/hash functions.
- Added explicit restore policy metadata (`mcp_restore_exposed: false`).
- `jarca_ledger_mcp/server.py`
- Added MCP tools: `get_ledger_db_status`, `create_ledger_backup`, `list_ledger_backups`, `get_ledger_backup_status`.
- Did not add any restore MCP tool.
- `scripts/ledger_restore_smoke.py`
- Added script-only restore smoke helper with overwrite approval token.
- `tests/test_backup_workflow.py`
- Added synthetic DB tests for metadata-only status, backup create/list/status/hash, retention pruning, and sensitive evidence exclusion.
- `docs/runbooks/ledger-backup-restore.md`
- Added operator runbook and QC checklist.
- `docs/runtime-flows.md`
- Added operational backup/validation/restore smoke runtime flow.
- `docs/data-model.md`
- Added `LedgerBackupArtifact` and metadata-only persistence notes.
- `docs/interface-contract.md`
- Added backup/status MCP contract and restore non-exposure rule.
- StagePilot docs
- `docs/srs/Non-Functional/req-002_operational-safety-backup-restore-validation-db.md`
- `docs/srs/index.md`
- `docs/discovery/dcy-002_20260627_operational-safety-backup-restore-validation-db.md`
- `docs/batches/index.md`
- `docs/batches/bat-002_20260627_operational-safety-backup-restore-validation-db/*`
## Execution Log
- RED test first:
- Command: `source .venv/bin/activate && pytest tests/test_backup_workflow.py -q`
- Initial result: failed with missing `service.get_ledger_db_status`, `create_ledger_backup`, `list_ledger_backups`, `get_ledger_backup_status` attributes.
- Implemented service/server/script/docs changes.
- Targeted test:
- Command: `source .venv/bin/activate && pytest tests/test_backup_workflow.py -q`
- Result: `3 passed`.
- Full syntax/test:
- Command: `source .venv/bin/activate && python -m py_compile jarca_ledger_mcp/*.py dashboard/app.py && pytest tests/test_backup_workflow.py -q && pytest -q`
- Result: backup tests passed, full suite passed with `...........ss.........ss [100%]`.
- Full pytest summary:
- Command: `source .venv/bin/activate && pytest -ra`
- Result: `20 passed, 4 skipped in 16.02s`; skips are sample KB/Toss PDF tests without sample files/passwords.
- Restore smoke:
- Command: created synthetic tmp DB, created backup via `service.create_ledger_backup`, then ran `python scripts/ledger_restore_smoke.py --backup <tmp backup> --target <tmp restored.sqlite3>`.
- Result: `success: true`, backup and restored target `integrity_check: ok`, table counts `{accounts: 1, transactions: 1, budgets: 0, import_batches: 0, category_rules: 0, ledger_categories: 0}`, health check `active_transactions: 1`.
- MCP surface check:
- Command: `source .venv/bin/activate && hermes mcp test jarca-ledger`
- Result: connected, `Tools discovered: 45`, including backup/status tools and no restore tool.
## Validation
- Synthetic DB tests confirmed no operating DB is needed for backup/status/list/hash verification.
- Restore smoke used `/tmp/...` source/target only, not `/root/.local/share/jarca/ledger.sqlite3`.
- Evidence captured only path, size, mtime, sha256, integrity, row counts, aggregate totals, and health/test results.
## Remaining Risks
- Real operating DB restore remains intentionally untested and requires separate explicit user approval.
- Browser/UI copy is not changed in this batch; operator safety guidance is runbook/MCP/script level only.
@@ -1,33 +0,0 @@
# BAT-002: 운영 안전 백업·복구·검증 DB 워크플로우
## Metadata
- BAT ID: BAT-002
- Profile: standard
- Status: release-candidate
- Source Discovery: dcy-002
- Included REQ: REQ-002
- Created At (KST): 2026-06-27 10:17
- Owner: 렛저장인
## Scope
- Add metadata-only DB status, backup create/list/status helpers.
- Expose backup/status/list/hash as additive MCP tools.
- Keep restore execution out of MCP and document script/runbook approval path.
- Verify with synthetic DB tests and safe restore smoke.
- Update runtime, data-model, and interface baseline docs.
## Out of Scope
- 실제 운영 DB restore 실행.
- 원본 운영 DB 직접 mutation.
- 파괴적 SQLite migration 또는 대량 data rewrite.
- 신규 금융기관 parser, CI/CD 구축, 배포 서비스화.
## Documents
- [planning.md](planning.md)
- [design.md](design.md)
- [implementation.md](implementation.md)
- [verification.md](verification.md)
## Notes
- Restore is intentionally script/runbook only; no `restore_*` MCP tool should be added.
- Evidence must remain metadata-only and exclude merchant/counterparty full dumps, raw_payload, account numbers, passwords, and source financial files.
@@ -1,34 +0,0 @@
# BAT-002 Planning
## Included REQ
- REQ-002: 운영 안전 백업·복구·검증 DB 워크플로우
## Delivery Plan
1. Add service helpers for non-sensitive DB status evidence and SQLite online backup creation.
2. Add additive MCP tools for backup creation, backup list, backup status/hash, and DB status.
3. Add a non-MCP restore smoke script requiring explicit approval for overwriting an existing target DB.
4. Add synthetic DB tests for status evidence, backup/list/status/hash, retention, and restore smoke policy.
5. Update runtime/data/interface docs and add a runbook.
6. Run targeted/full verification and request jarcaledgerqc QC gate.
## Dependencies
- Existing SQLite initialization and additive migration behavior in `jarca_ledger_mcp/db.py`.
- Existing service response convention: `{"success": True, ...}` and `fail(...)` error shape.
- Synthetic pytest tmp DBs for safe evidence.
## Design Gate
Design required: yes.
Reason: this batch changes the MCP interface surface and runtime/data safety baseline, and must explicitly preserve restore non-exposure and sensitive evidence restrictions.
## Milestones
- M1: REQ-002 Approved and BAT-002 scaffolded.
- M2: Backup/status/list/hash helpers and MCP tools implemented.
- M3: Restore smoke script and runbook documented without MCP restore surface.
- M4: Synthetic tests and docs evidence complete.
- M5: QC gate PASS/PASS_WITH_NOTES, then REQ-002 Implemented.
## Risks
- Accidentally exposing restore as MCP would violate dcy-002 policy.
- SQLite WAL copy must be consistent; implementation should use SQLite online backup API rather than raw file copy for backup creation.
- Evidence must not serialize sensitive row-level details.
@@ -1,111 +0,0 @@
# BAT-002 Verification
## Verification Status
- Status: approved
- Ready for Release: true
- Verified At (KST): 2026-06-27 10:33
- Verified By: 렛저장인
## Acceptance Mapping
### REQ-002 AC1
Backup creation must write timestamped SQLite files under `/root/.local/share/jarca/backups/ledger/` by default and return source/backup path, size, mtime, sha256, integrity, and table counts.
Evidence:
- `service.create_ledger_backup` uses default `DEFAULT_LEDGER_BACKUP_DIR = ~/.local/share/jarca/backups/ledger` and returns `source_db`, `backup`, `retention`, and `restore_policy`.
- `tests/test_backup_workflow.py::test_create_list_and_status_ledger_backup_with_retention` verifies backup file creation, sha256 presence, `integrity_check == "ok"`, and source/backup table count equality on synthetic DB.
Result: pass.
### REQ-002 AC2
Retention keeps recent 30 days or newest 20 backup files and reports pruned paths.
Evidence:
- `_apply_backup_retention` prunes only backups that are both outside newest count and older than day cutoff.
- `tests/test_backup_workflow.py::test_backup_retention_keeps_recent_count_and_prunes_older_extras` verifies retention with synthetic old backup files and checks `pruned_paths` length.
Result: pass.
### REQ-002 AC3
Backup list/status/hash is additive service/MCP surface and existing response shapes are preserved.
Evidence:
- New service functions: `list_ledger_backups`, `get_ledger_backup_status`, `get_ledger_db_status`.
- New MCP tools are additive in `server.py`.
- `hermes mcp test jarca-ledger` result: connected, `Tools discovered: 45`, including `get_ledger_db_status`, `create_ledger_backup`, `list_ledger_backups`, `get_ledger_backup_status`.
Result: pass.
### REQ-002 AC4
Restore execution is not MCP-exposed and is script/runbook only with explicit approval for overwrite.
Evidence:
- `server.py` contains no restore MCP tool.
- `hermes mcp test jarca-ledger` discovered backup/status tools and no restore tool.
- `scripts/ledger_restore_smoke.py` requires `--allow-overwrite --approval-token RESTORE_APPROVED` before overwriting an existing target.
- `docs/runbooks/ledger-backup-restore.md` documents restore as script-only and warns not to target the live operating DB without explicit user approval.
Result: pass.
### REQ-002 AC5
Validation uses synthetic fixture DB first; operating DB copy evidence is metadata-only if used.
Evidence:
- All tests use pytest `tmp_path` synthetic SQLite DBs.
- Restore smoke command used `/tmp/.../fixture.sqlite3`, `/tmp/.../backups/...sqlite3`, and `/tmp/.../restored.sqlite3`.
- No operating DB copy was needed.
Result: pass.
### REQ-002 AC6
Baseline docs reflect backup/status/list/hash/restore restrictions and sensitive evidence policy.
Evidence:
- `docs/runtime-flows.md` adds operational backup/validation/restore smoke flow and restore non-MCP constraint.
- `docs/data-model.md` adds `LedgerBackupArtifact` and metadata-only evidence notes.
- `docs/interface-contract.md` adds backup/status tools and restore non-exposure compatibility rule.
- `docs/runbooks/ledger-backup-restore.md` lists allowed/forbidden evidence and QC checklist.
Result: pass.
### REQ-002 AC7
Synthetic tests verify backup/status/list/hash/retention/restore smoke or health/status check without operating DB mutation.
Evidence:
- Command: `source .venv/bin/activate && pytest -ra`
- Result: `20 passed, 4 skipped in 16.02s`.
- Command: synthetic restore smoke with `scripts/ledger_restore_smoke.py`.
- Result: `success: true`, backup/target `integrity_check: ok`, matching table counts, `health_check.success: true`.
Result: pass.
### REQ-002 AC8
QC gate must verify operating DB mutation absence, restore MCP non-exposure, sensitive evidence absence, smoke evidence, tests/docs.
Evidence:
- This verification document and runbook include QC checklist.
- `jarcaledgerqc` QC gate returned `PASS`.
- QC summary confirmed no operating DB restore/direct mutation, backup/status/list/hash policy compliance, no restore MCP tool, synthetic restore smoke success, no real sensitive evidence exposure, and tests/docs evidence.
Result: pass.
## Evidence Summary
- Syntax: `python -m py_compile jarca_ledger_mcp/*.py dashboard/app.py` -> exit 0.
- Targeted tests: `pytest tests/test_backup_workflow.py -q` -> `3 passed`.
- Full tests: `pytest -ra` -> implementer `20 passed, 4 skipped in 16.02s`; QC rerun `20 passed, 4 skipped in 14.14s`.
- Restore smoke: synthetic tmp DB restore -> `success: true`, `integrity_check: ok`, table counts `{accounts: 1, transactions: 1, budgets: 0, import_batches: 0, category_rules: 0, ledger_categories: 0}`.
- MCP surface: `hermes mcp test jarca-ledger` -> connected, `Tools discovered: 45`, backup/status tools present, no restore tool listed.
## Sensitive Evidence Review
- No transaction row dumps, merchant/counterparty full dumps, account numbers, `raw_payload`, source financial files, or passwords were written into docs/tests/logs.
- Synthetic test data contains placeholder sentinel labels only and asserts those labels are not serialized in status evidence.
## QC Gate Result
- Verdict: PASS
- Reviewer: jarcaledgerqc
- Reviewed At (KST): 2026-06-27 10:33
- Summary: 검수관은 원본 운영 DB restore/direct mutation 없음, backup/status/list/hash 정책 정합성, restore MCP 비노출, synthetic restore smoke 성공, 민감정보 비노출, tests/docs evidence를 확인했다.
- Notes: 실제 backup MCP 호출은 운영 DB mutation을 피하기 위해 수행하지 않았고, service-level synthetic DB 테스트와 smoke로 대체 검증했다. 이는 비차단 참고사항이다.
## Blocking Issues
- None.
@@ -1,28 +0,0 @@
# BAT-003 Implementation
## 코드 변경
- `jarca_ledger_mcp/db.py`
- schema version 7
- `accounts.statement_status TEXT NOT NULL DEFAULT 'unknown'`
- 기존 DB용 additive column migration
- `jarca_ledger_mcp/service.py`
- `VALID_STATEMENT_STATUSES` 및 reconciliation 대상 상수
- `create_ledger_account`에 `statement_status` 입력 추가
- `update_ledger_account` 신규 추가
- `get_balance_reconciliation_report` 신규 추가
- `jarca_ledger_mcp/server.py`
- `create_ledger_account` signature 확장
- `update_ledger_account`, `get_balance_reconciliation_report` MCP tool 추가
- `dashboard/app.py`
- 계좌 화면에 statement 상태 표시/수정 UI 추가
- 최소 잔액대조 결과 표 추가
- `tests/test_service.py`
- schema version 7 반영
- statement status validation 및 balance reconciliation 테스트 추가
## 운영 안전
- 운영 DB 변경 전 dcy-002 백업 절차를 먼저 수행한다.
- 검증 DB에서 preview/reconcile 후 운영 DB에 반영한다.
- restore는 사용자의 명시 승인 없이 실행하지 않는다.
@@ -1,25 +0,0 @@
# BAT-003 Statement-unavailable 수동 증빙 및 잔액대조
- Profile: batch-lite
- Status: release-candidate
- Included REQ: REQ-003
- Discovery: dcy-003
- Owner: 렛저장인
- Date (KST): 2026-06-29
## 목표
statement 파일이 없거나 일부만 import 가능한 계좌를 `statement_status`로 구분하고, 수동 실행 가능한 잔액대조 report 및 계좌 화면 최소 UI를 제공한다.
## 산출물
- `accounts.statement_status` additive migration
- service 계좌 update 및 잔액대조 report
- MCP tool surface 추가
- dashboard 계좌 화면 표시/수정/대조 결과
- REQ-003 및 운영 문서 갱신
- pytest 기반 regression 검증
## 범위 제한
자동 스케줄링/알림, 전용 워크벤치 전체 신설, 자동 확정 mutation, 사용자 승인 없는 restore는 포함하지 않는다.
@@ -1,35 +0,0 @@
# BAT-003 Verification
## 검증 계획
1. Python 문법 검증
- `python3 -m py_compile jarca_ledger_mcp/db.py jarca_ledger_mcp/service.py jarca_ledger_mcp/server.py dashboard/app.py tests/test_service.py`
2. 대상 테스트
- `python3 -m pytest tests/test_service.py -q`
3. 전체 테스트
- 가능하면 `python3 -m pytest -q`
## Acceptance Mapping
- AC-1/2: `test_health_check_initializes_db`, `test_invalid_statement_status_rejected`
- AC-3/4: `test_statement_status_account_update_and_balance_reconciliation`
- AC-5: dashboard py_compile 및 계좌 page 코드 검증
- AC-6: server py_compile 및 tool 함수 추가 확인
- AC-7: REQ/batch/data-model/interface/runtime/runbook 문서 갱신
## 결과
최종 검증 결과(2026-06-29 KST):
- `python -m py_compile dashboard/app.py jarca_ledger_mcp/service.py jarca_ledger_mcp/server.py jarca_ledger_mcp/db.py` — PASS
- `pytest tests/test_service.py tests/test_categorization.py tests/test_uncategorized_workbench.py -q` — PASS (`12 passed`)
- `pytest -q` — PASS (`28 passed, 4 skipped`)
- Streamlit `AppTest.from_file('dashboard/app.py')` with synthetic temp DB and `?page=계좌` — PASS; account page rendered without exceptions and exposed `잔액대조 실행`.
검증 중 발견/수정:
- `tests/test_ledger_categories.py`의 schema version 기대값이 이전 버전 `6`으로 남아 있어 `7`로 갱신했다.
남은 범위 외 항목:
- dcy-004/dcy-005 문서는 현재 작업 범위가 아니므로 구현을 시작하지 않았다.
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 KiB

@@ -1,62 +0,0 @@
{
"success": true,
"base_url": "http://127.0.0.1:18501",
"output_dir": "/root/projects/jarca-ledger-mcp/docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-192835",
"fixture": {
"account_id": "acct_a4f4de4cdd0f",
"transaction_ids": [
"tx_cba36b3d2c33",
"tx_24fa1050eb2b",
"tx_8cd3af3d60b6"
],
"db_path": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-192835/fixture.sqlite3"
},
"chrome": "/usr/bin/google-chrome-stable",
"streamlit": ".venv/bin/streamlit",
"pages": [
{
"page": "분류 규칙",
"url": "http://127.0.0.1:18501/?page=%EB%B6%84%EB%A5%98%20%EA%B7%9C%EC%B9%99",
"screenshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-192835/rules.png",
"screenshot_bytes": 364876,
"snapshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-192835/rules.dom.html",
"snapshot_bytes": 174470,
"devtools_port": 19222,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\n메뉴\n요약\n거래내역\n확인필요 큐\n미분류\n분류 규칙\n카테고리\n계좌\nImport\nStop\nDeploy\n⚙️ Rule Engine\n분류 규칙\n\n반복되는 사용처와 거래 패턴을 규칙으로 관리해 분류 자동화 품질을 높입니다.\n\n자동 분류\nPreview\nSeed/Update\nkeyboard_arrow_right\n\n🟢 이자 · merchant/contains → 수입 / 이자 · p10 · income\n\nkeyboard_arrow_right\n\n🟢 환급 · merchant/contains → 수입 / 환급 · p10 · income\n\nkeyboard_arrow_right\n\n🟢 급여 · merchant/contains → 수입 / 급여 · p10 · income\n\nkeyboard_arrow_right\n\n🟢 KB카드출금 · merchant/contains → 금융 / 카드대금 · p20 · expense\n\nkeyboard_arro"
},
{
"page": "확인필요 큐",
"url": "http://127.0.0.1:18501/?page=%ED%99%95%EC%9D%B8%ED%95%84%EC%9A%94%20%ED%81%90",
"screenshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-192835/transfer-review.png",
"screenshot_bytes": 275792,
"snapshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-192835/transfer-review.dom.html",
"snapshot_bytes": 25551,
"devtools_port": 19223,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\n메뉴\n요약\n거래내역\n확인필요 큐\n미분류\n분류 규칙\n카테고리\n계좌\nImport\nStop\nDeploy\n🔁 Transfer Review\nKB↔토스뱅크 확인필요 큐\n\n날짜·금액·상대 기준으로 계좌 간 이동 후보를 대조하고, 드라이런 후 안전하게 매칭합니다.\n\n드라이런 우선\n본인계좌이동\n수동 검토\n📌\n확인필요 큐\n\n거래 ID: tx_8cd3af3d60b6\n\n2026-06-29 · SYNTHETIC_TRANSFER · 120,000원"
},
{
"page": "Import",
"url": "http://127.0.0.1:18501/?page=Import",
"screenshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-192835/import.png",
"screenshot_bytes": 297424,
"snapshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-192835/import.dom.html",
"snapshot_bytes": 23649,
"devtools_port": 19224,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\nStop\nDeploy\n\n토스증권 거래내역서 PDF를 업로드하면 투자계좌 거래로 가져옵니다. 매수/매도/환전/입출금은 이체/투자이동, 배당/이자는 실제 수입으로 분류합니다.\n\n토스뱅크 계좌 거래내역 PDF를 업로드하면 입출금/이체/카드결제를 가져옵니다. 타인 이체/출금은 이체/확인필요로 분류됩니다."
}
],
"server_command": [
".venv/bin/streamlit",
"run",
"dashboard/app.py",
"--server.address",
"127.0.0.1",
"--server.port",
"18501",
"--server.headless",
"true",
"--browser.gatherUsageStats",
"false"
],
"server_log_tail": ""
}
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 KiB

File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 291 KiB

@@ -1,62 +0,0 @@
{
"success": true,
"base_url": "http://127.0.0.1:18501",
"output_dir": "/root/projects/jarca-ledger-mcp/docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-195632",
"fixture": {
"account_id": "acct_7579e5091359",
"transaction_ids": [
"tx_22a85feba578",
"tx_04e500d0745c",
"tx_3ee6a6e14179"
],
"db_path": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-195632/fixture.sqlite3"
},
"chrome": "/usr/bin/google-chrome-stable",
"streamlit": ".venv/bin/streamlit",
"pages": [
{
"page": "분류 규칙",
"url": "http://127.0.0.1:18501/?page=%EB%B6%84%EB%A5%98%20%EA%B7%9C%EC%B9%99",
"screenshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-195632/rules.png",
"screenshot_bytes": 364622,
"snapshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-195632/rules.dom.html",
"snapshot_bytes": 190599,
"devtools_port": 19222,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\n메뉴\n요약\n거래내역\n확인필요 큐\n미분류\n분류 규칙\n카테고리\n계좌\nImport\nStop\nDeploy\n⚙️ Rule Engine\n분류 규칙\n\n반복되는 사용처와 거래 패턴을 규칙으로 관리해 분류 자동화 품질을 높입니다.\n\n자동 분류\nPreview\nSeed/Update\n📚\n현재 분류 규칙\nkeyboard_arrow_right\n\n🟢 급여 · merchant/contains → 수입 / 급여 · p10 · income\n\nkeyboard_arrow_right\n\n🟢 이자 · merchant/contains → 수입 / 이자 · p10 · income\n\nkeyboard_arrow_right\n\n🟢 환급 · merchant/contains → 수입 / 환급 · p10 · income\n\nkeyboard_arrow_right\n\n🟢 KB카드출금 · merchant/contains → 금융 / 카드대금 · p20 · expense\n\nke"
},
{
"page": "확인필요 큐",
"url": "http://127.0.0.1:18501/?page=%ED%99%95%EC%9D%B8%ED%95%84%EC%9A%94%20%ED%81%90",
"screenshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-195632/transfer-review.png",
"screenshot_bytes": 282069,
"snapshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-195632/transfer-review.dom.html",
"snapshot_bytes": 27701,
"devtools_port": 19223,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\n메뉴\n요약\n거래내역\n확인필요 큐\n미분류\n분류 규칙\n카테고리\n계좌\nImport\n\n새로고침\n\nStop\nDeploy\n🔁 Transfer Review\nKB↔토스뱅크 확인필요 큐\n\n날짜·금액·상대 기준으로 계좌 간 이동 후보를 대조하고, 드라이런 후 안전하게 매칭합니다.\n\n드라이런 우선\n본인계좌이동\n수동 검토\n\n미리보기(드라이런)\n\n자동 매칭 실행\n\n📌\n확인필요 큐\n\n거래 ID: tx_3ee6a6e14179\n\n2026-06-29 · SYNTHETIC_TRANSFER · 120,000원"
},
{
"page": "Import",
"url": "http://127.0.0.1:18501/?page=Import",
"screenshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-195632/import.png",
"screenshot_bytes": 298123,
"snapshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-195632/import.dom.html",
"snapshot_bytes": 15721,
"devtools_port": 19224,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\nStop\nDeploy\n\n토스증권 거래내역서 PDF를 업로드하면 투자계좌 거래로 가져옵니다. 매수/매도/환전/입출금은 이체/투자이동, 배당/이자는 실제 수입으로 분류합니다.\n\n토스뱅크 계좌 거래내역 PDF를 업로드하면 입출금/이체/카드결제를 가져옵니다. 타인 이체/출금은 이체/확인필요로 분류됩니다."
}
],
"server_command": [
".venv/bin/streamlit",
"run",
"dashboard/app.py",
"--server.address",
"127.0.0.1",
"--server.port",
"18501",
"--server.headless",
"true",
"--browser.gatherUsageStats",
"false"
],
"server_log_tail": ""
}
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

@@ -1,44 +0,0 @@
{
"success": true,
"base_url": "http://127.0.0.1:18501",
"output_dir": "/root/projects/jarca-ledger-mcp/docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260630-071603",
"fixture": {
"account_id": "acct_75c4cbc5a305",
"transaction_ids": [
"tx_2123d9b9c1f5",
"tx_a13db72f4885",
"tx_3edaa32c38ae",
"tx_fe176567300b",
"tx_d674d4ddbf1e"
],
"db_path": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260630-071603/fixture.sqlite3"
},
"chrome": "/usr/bin/google-chrome-stable",
"streamlit": ".venv/bin/streamlit",
"pages": [
{
"page": "요약",
"url": "http://127.0.0.1:18501/?page=%EC%9A%94%EC%95%BD",
"screenshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260630-071603/overview.png",
"screenshot_bytes": 300562,
"snapshot": "docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260630-071603/overview.dom.html",
"snapshot_bytes": 33871,
"devtools_port": 19222,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\n메뉴\n요약\n거래내역\n확인필요 큐\n미분류\n분류 규칙\n카테고리\n계좌\nImport\n\n새로고침\n\nStop\nDeploy\n📊 요약\n가계부 운영 대시보드\n\n이번 달 실제 현금흐름, 자산 유동성, 운영 경고를 우선순위대로 확인합니다.\n\nschema v8\nKST 이번 달\nlast_balance 기준 자산\n\nDB: /root/projects/jarca-ledger-mcp/docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260630-071603/fixture.sqlite3\n\n💎\n이번 달 수입/지출 현황\n\n기준: KST 현재 월 2026-06, transactions.transaction_date, ledger_categories.cashflow_kind 실제 현금흐름\n\n🏦\n자산 유동성 현황\n\n기준: accounts.liquidity_bucket"
}
],
"server_command": [
".venv/bin/streamlit",
"run",
"dashboard/app.py",
"--server.address",
"127.0.0.1",
"--server.port",
"18501",
"--server.headless",
"true",
"--browser.gatherUsageStats",
"false"
],
"server_log_tail": ""
}
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

@@ -1,33 +0,0 @@
# BAT-004 Implementation
## 코드 변경
- `scripts/streamlit_browser_evidence.py`
- synthetic fixture DB 생성.
- 운영 DB 기본 경로 사용 거부 안전장치.
- Streamlit local server 기동 및 HTTP 200 readiness 확인.
- `/usr/bin/google-chrome-stable` headless Chrome DevTools Protocol 연결.
- page별 DOM 텍스트 로드 확인 후 PNG screenshot 및 DOM snapshot 저장.
- manifest JSON에 evidence path/byte size/fixture DB/command 정보를 기록.
- `dashboard/app.py`
- Import page의 import batch 조회와 rollback 실행이 현재 dashboard `db_path`를 사용하도록 수정.
- 이 수정은 browser evidence fixture DB 원칙을 지키기 위한 안전 보완이며 운영 DB 누수를 막는다.
## 문서 변경
- `docs/srs/Testing/req-004_browser-streamlit-e2e-evidence-recovery.md`
- `docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/`
- `docs/runbooks/streamlit-browser-evidence.md`
- `docs/runtime-flows.md`
- `docs/interface-contract.md`
- `docs/project-structure.md`
- `docs/srs/index.md`
- `docs/batches/index.md`
- source Discovery의 생성된 REQ 참조
## 운영 안전
- evidence script는 `~/.local/share/jarca/ledger.sqlite3`를 fixture DB로 사용하는 것을 거부한다.
- fixture에는 `SYNTHETIC_*` 가짜 계좌/거래/상대명만 사용한다.
- 원본 금융 파일, 실제 계좌번호, 비밀번호, raw_payload는 screenshot/log/docs에 남기지 않는다.
- CI 통합은 이번 batch 범위가 아니며, 로컬 재현 절차만 제공한다.
@@ -1,24 +0,0 @@
# BAT-004 Browser/Streamlit E2E evidence 환경 복구
- Profile: batch-lite
- Status: release-candidate
- Included REQ: REQ-004
- Discovery: dcy-004
- Owner: 렛저장인
- Date (KST): 2026-06-29
## 목표
Streamlit UI batch 검증에서 AppTest/HTTP 200 대체 증거에 머물지 않도록, synthetic DB와 `/usr/bin/google-chrome-stable` 기반 로컬 browser screenshot/snapshot evidence 절차를 복구한다.
## 산출물
- `scripts/streamlit_browser_evidence.py` 로컬 evidence 수집 스크립트
- `docs/runbooks/streamlit-browser-evidence.md` 운영 runbook
- REQ-004 및 BAT-004 planning/implementation/verification 문서
- runtime/interface/project-structure 문서의 evidence gate 기준 갱신
- synthetic DB 기반 browser screenshot/snapshot evidence
## 범위 제한
CI 통합, Playwright/Selenium 도입, pixel-diff visual regression, Streamlit 신규 화면 기능 개발은 포함하지 않는다.
@@ -1,31 +0,0 @@
# BAT-004 Planning
## 구현 전략
1. `REQ-004`를 Testing 요구사항으로 정리한다.
2. 운영 DB와 실제 금융 파일을 배제한 synthetic fixture DB를 evidence script가 직접 생성한다.
3. Streamlit은 `JARCA_LEDGER_DB_PATH=<fixture.sqlite3>`로 기동한다.
4. `/usr/bin/google-chrome-stable` headless + Chrome DevTools Protocol로 대상 페이지를 열고, 화면 텍스트 로드 완료를 확인한 뒤 screenshot과 DOM snapshot을 저장한다.
5. UI/dashboard 영향 batch의 QC gate 기준을 문서화한다.
## Design Gate
- Profile: `batch-lite`
- 판단 근거: 신규 도메인 기능이나 DB schema 변경 없이 검증 스크립트와 문서 기준을 추가한다.
- 설계 문서 별도 작성 여부: 별도 `design.md`는 만들지 않는다. 구현 결정은 이 planning 및 REQ-004에 충분히 국소적으로 기록한다.
## Evidence Gate 기준
| Batch 유형 | 최소 evidence | Gate 판정 |
| --- | --- | --- |
| Streamlit UI 또는 `dashboard/app.py` 영향 | Browser screenshot + DOM snapshot + manifest | 누락 시 BLOCK 또는 재검증 |
| 비-UI service/MCP/parser 변경 | pytest/py_compile 중심, browser evidence 선택 | browser 누락은 비차단 |
| docs-only 변경 | 문서 diff/review | browser evidence 불필요 |
| Chrome 환경 장애가 입증된 UI 변경 | AppTest + HTTP 200 + 실패 원인 로그 | `PASS_WITH_NOTES`만 허용 |
## 리스크와 완화
- Chrome/DevTools 기동 실패: 실행 전 Chrome 경로를 검증하고 명확한 오류를 출력한다.
- Streamlit 렌더링 지연: HTTP 200 대기 후 CDP에서 page 제목 텍스트가 실제 DOM에 나타날 때까지 대기한다.
- 민감정보 노출: script가 기본 운영 DB 경로를 거부하고 synthetic fixture만 생성한다.
- dependency 증가: Playwright/Selenium을 추가하지 않고 현재 dashboard extra에 이미 존재하는 `websockets`를 사용한다.
@@ -1,43 +0,0 @@
# BAT-004 Verification
## 검증 계획
1. Python 문법 검증
- `.venv/bin/python -m py_compile scripts/streamlit_browser_evidence.py dashboard/app.py`
2. 대상 browser smoke
- `.venv/bin/python scripts/streamlit_browser_evidence.py`
- 확인 대상: `분류 규칙`, `확인필요 큐`, `Import`
3. 전체 테스트
- `.venv/bin/python -m pytest -q`
4. evidence 민감정보 검토
- manifest와 DOM snapshot에는 synthetic fixture 식별자만 포함되어야 한다.
- 운영 DB 기본 경로, 원본 금융 파일명, 비밀번호, 실제 raw_payload는 포함하지 않는다.
## Acceptance Mapping
- AC-1: `scripts/streamlit_browser_evidence.py`의 `assert_synthetic_db_path` 및 fixture 생성 로직.
- AC-2: py_compile 결과.
- AC-3: full pytest 결과.
- AC-4/5: browser evidence script manifest 및 screenshot/snapshot 파일.
- AC-6: `dashboard/app.py` Import page의 `db_path` 전달 수정.
- AC-7: REQ/BAT/runtime/interface/project-structure/runbook 문서 갱신.
## 결과
최종 검증 결과(2026-06-29 KST):
- `.venv/bin/python -m py_compile scripts/streamlit_browser_evidence.py dashboard/app.py jarca_ledger_mcp/db.py jarca_ledger_mcp/service.py jarca_ledger_mcp/server.py tests/test_service.py` — PASS.
- `.venv/bin/python -m pytest -ra` — PASS (`27 passed, 4 skipped in 27.37s`).
- `.venv/bin/python scripts/streamlit_browser_evidence.py` — PASS.
- Evidence directory: `docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-20260629-192835/`
- Manifest: `manifest.json` (`success: true`).
- Captured pages:
- `분류 규칙`: `rules.png` 364,876 bytes, `rules.dom.html` 174,470 bytes.
- `확인필요 큐`: `transfer-review.png` 275,792 bytes, `transfer-review.dom.html` 25,551 bytes.
- `Import`: `import.png` 297,424 bytes, `import.dom.html` 23,649 bytes.
## Sensitive Evidence Review
- Evidence DB path is the generated fixture path under BAT-004 evidence, not the operating DB default path.
- Fixture rows use `SYNTHETIC_*` labels and do not include real account numbers, real financial source filenames, passwords, or raw payloads.
- DOM/screenshot evidence was generated from synthetic fixture data only.
@@ -1,44 +0,0 @@
{
"success": true,
"base_url": "http://127.0.0.1:18501",
"output_dir": "/root/projects/jarca-ledger-mcp/docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-20260629-2111",
"fixture": {
"account_id": "acct_6cf9a9db8669",
"transaction_ids": [
"tx_f60380340545",
"tx_8c16f1387fb1",
"tx_445884ce8638",
"tx_ead36edf0c7e",
"tx_dc27408a7e81"
],
"db_path": "docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-20260629-2111/fixture.sqlite3"
},
"chrome": "/usr/bin/google-chrome-stable",
"streamlit": ".venv/bin/streamlit",
"pages": [
{
"page": "요약",
"url": "http://127.0.0.1:18501/?page=%EC%9A%94%EC%95%BD",
"screenshot": "docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-20260629-2111/overview.png",
"screenshot_bytes": 303341,
"snapshot": "docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-20260629-2111/overview.dom.html",
"snapshot_bytes": 30757,
"devtools_port": 19222,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\n메뉴\n요약\n거래내역\n확인필요 큐\n미분류\n분류 규칙\n카테고리\n계좌\nImport\nStop\nDeploy\n📊 요약\n가계부 운영 대시보드\n\n이번 달 실제 현금흐름, 자산 유동성, 운영 경고를 우선순위대로 확인합니다.\n\nschema v8\nKST 이번 달\nlast_balance 기준 자산\n\nDB: /root/projects/jarca-ledger-mcp/docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-20260629-2111/fixture.sqlite3\n\n💎\n이번 달 수입/지출 현황\n\n기준: KST 현재 월 2026-06, transactions.transaction_date, ledger_categories.cashflow_kind 실제 현금흐름\n\n🏦\n자산 유동성 현황\n\n기준: accounts.liqu"
}
],
"server_command": [
".venv/bin/streamlit",
"run",
"dashboard/app.py",
"--server.address",
"127.0.0.1",
"--server.port",
"18501",
"--server.headless",
"true",
"--browser.gatherUsageStats",
"false"
],
"server_log_tail": ""
}
@@ -1,44 +0,0 @@
{
"success": true,
"base_url": "http://127.0.0.1:18503",
"output_dir": "/root/projects/jarca-ledger-mcp/docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-check-20260630-073738",
"fixture": {
"account_id": "acct_d3b8cccfccb4",
"transaction_ids": [
"tx_4b8447f7aa07",
"tx_b2ca8a05ac82",
"tx_8c989e7c3b15",
"tx_f48e63972a9e",
"tx_4e20d08f8df3"
],
"db_path": "docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-check-20260630-073738/fixture.sqlite3"
},
"chrome": "/usr/bin/google-chrome-stable",
"streamlit": ".venv/bin/streamlit",
"pages": [
{
"page": "요약",
"url": "http://127.0.0.1:18503/?page=%EC%9A%94%EC%95%BD",
"screenshot": "docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-check-20260630-073738/overview.png",
"screenshot_bytes": 301342,
"snapshot": "docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-check-20260630-073738/overview.dom.html",
"snapshot_bytes": 29881,
"devtools_port": 19222,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\n메뉴\n요약\n거래내역\n확인필요 큐\n미분류\n분류 규칙\n카테고리\n계좌\nImport\nStop\nDeploy\n📊 요약\n가계부 운영 대시보드\n\n이번 달 실제 현금흐름, 자산 유동성, 운영 경고를 우선순위대로 확인합니다.\n\nschema v8\nKST 이번 달\nlast_balance 기준 자산\n\nDB: /root/projects/jarca-ledger-mcp/docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-check-20260630-073738/fixture.sqlite3\n\n💎\n이번 달 수입/지출 현황\n\n기준: KST 현재 월 2026-06, transactions.transaction_date, ledger_categories.cashflow_kind 실제 현금흐름\n\n🏦\n자산 유동성 현황\n\n기준: accou"
}
],
"server_command": [
".venv/bin/streamlit",
"run",
"dashboard/app.py",
"--server.address",
"127.0.0.1",
"--server.port",
"18503",
"--server.headless",
"true",
"--browser.gatherUsageStats",
"false"
],
"server_log_tail": ""
}
@@ -1,44 +0,0 @@
{
"success": true,
"base_url": "http://127.0.0.1:18501",
"output_dir": "/root/projects/jarca-ledger-mcp/docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-verify-20260629-215958",
"fixture": {
"account_id": "acct_86182dd8b283",
"transaction_ids": [
"tx_6e7d47621557",
"tx_546ed7a78004",
"tx_f40ec3aa2df0",
"tx_3207e5cdde0d",
"tx_fa79d639eda4"
],
"db_path": "docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-verify-20260629-215958/fixture.sqlite3"
},
"chrome": "/usr/bin/google-chrome-stable",
"streamlit": ".venv/bin/streamlit",
"pages": [
{
"page": "요약",
"url": "http://127.0.0.1:18501/?page=%EC%9A%94%EC%95%BD",
"screenshot": "docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-verify-20260629-215958/overview.png",
"screenshot_bytes": 303039,
"snapshot": "docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-verify-20260629-215958/overview.dom.html",
"snapshot_bytes": 32797,
"devtools_port": 19222,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\n메뉴\n요약\n거래내역\n확인필요 큐\n미분류\n분류 규칙\n카테고리\n계좌\nImport\n\n새로고침\n\nStop\nDeploy\n📊 요약\n가계부 운영 대시보드\n\n이번 달 실제 현금흐름, 자산 유동성, 운영 경고를 우선순위대로 확인합니다.\n\nschema v8\nKST 이번 달\nlast_balance 기준 자산\n\nDB: /root/projects/jarca-ledger-mcp/docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-verify-20260629-215958/fixture.sqlite3\n\n💎\n이번 달 수입/지출 현황\n\n기준: KST 현재 월 2026-06, transactions.transaction_date, ledger_categories.cashflow_kind 실제 현금흐름\n\n🏦\n자산 유동성 현황\n\n기"
}
],
"server_command": [
".venv/bin/streamlit",
"run",
"dashboard/app.py",
"--server.address",
"127.0.0.1",
"--server.port",
"18501",
"--server.headless",
"true",
"--browser.gatherUsageStats",
"false"
],
"server_log_tail": ""
}
@@ -1,37 +0,0 @@
# BAT-005 Implementation
## 코드 변경
- `jarca_ledger_mcp/db.py`
- schema version을 `8`로 올리고 `accounts.liquidity_bucket TEXT NOT NULL DEFAULT 'other'`를 schema 및 additive migration 목록에 추가한다.
- `jarca_ledger_mcp/service.py`
- `VALID_LIQUIDITY_BUCKETS`와 `normalize_liquidity_bucket` 검증을 추가한다.
- `create_ledger_account`/`update_ledger_account`에서 `liquidity_bucket`을 저장·수정한다.
- `get_asset_liquidity_report`를 추가해 `accounts.last_balance` 기반 버킷 합계, 총자산, 총부채, 순자산, 미입력 계좌를 반환한다.
- `jarca_ledger_mcp/server.py`
- MCP account create/update tool signature에 `liquidity_bucket`을 추가하고 `get_asset_liquidity_report` tool을 노출한다.
- `dashboard/app.py`
- 요약 화면을 REQ-005 운영 허브 순서로 재구성한다.
- KST 현재 월 기준 월간 실제 수입/지출/순현금흐름/저축률을 최상단에 표시한다.
- 자산 유동성, 자산 구성, 예산/지출, 운영 경고 섹션을 추가한다.
- 계좌 화면에 `liquidity_bucket` 표시/수정 control을 추가한다.
- `scripts/streamlit_browser_evidence.py`
- synthetic fixture에 `cash`, `investment`, `loan`, `real_estate` bucket 계좌와 월간 수입/지출/예산 데이터를 추가한다.
- `tests/test_service.py`
- schema version, liquidity bucket 검증, account flow, asset liquidity report regression을 추가한다.
## 문서 변경
- `docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/`
- `docs/batches/index.md`
- `docs/srs/Interface/req-005_dashboard-operations-hub-liquidity-monthly-cashflow.md`
- `docs/data-model.md`
- `docs/project-structure.md`
- `docs/runtime-flows.md`
- `docs/interface-contract.md`
## 운영 안전
- 운영 DB와 실제 금융 원본 파일은 사용하지 않는다.
- browser evidence는 synthetic fixture DB로만 생성한다.
- migration은 additive/idempotent이며 기존 계좌의 bucket은 `other` 기본값으로 안전하게 채워진다.
@@ -1,25 +0,0 @@
# BAT-005 Dashboard operations hub/liquidity/monthly cashflow
- Profile: standard
- Status: release-candidate
- Included REQ: REQ-005
- Discovery: dcy-005
- Owner: 렛저장인
- Date (KST): 2026-06-29
## 목표
REQ-005에 따라 Streamlit 요약 화면을 월중 운영 허브로 재구성하고, 계좌 단위 `liquidity_bucket`과 `last_balance`를 권위 소스로 하는 자산 유동성/구성/부채/순자산 뷰를 제공한다.
## 산출물
- `accounts.liquidity_bucket` additive/idempotent schema migration
- 계좌 create/list/update 및 MCP tool signature의 `liquidity_bucket` 지원
- `service.get_asset_liquidity_report` 자산 유동성/순자산 report
- `dashboard/app.py` 요약 운영 허브 및 계좌 liquidity bucket 편집 UI
- BAT-005 planning/implementation/verification 문서와 baseline 문서 갱신
- synthetic/validation DB 기반 Streamlit browser evidence
## 범위 제한
실시간 금융 연동, 자동 시세 평가, 별도 `asset_snapshots`/`manual_assets` 테이블, 거래/카테고리 단위 liquidity override, dcy-006 범위는 포함하지 않는다.
@@ -1,30 +0,0 @@
# BAT-005 Planning
## 구현 전략
1. REQ-005의 승인 상태를 입력 gate로 확인하고 BAT-005 batch 문서를 생성한다.
2. `accounts.liquidity_bucket`을 additive/idempotent column으로 추가한다. 허용값은 `cash`, `investment`, `deposit`, `real_estate`, `loan`, `other`이며 기존/미지정 계좌는 `other`로 폴백한다.
3. 서비스 계층에서 create/list/update 계좌 흐름에 `liquidity_bucket`을 노출하고 허용값 검증을 추가한다.
4. 자산 유동성 report는 `accounts.last_balance`만 사용한다. `last_balance`가 없는 비거래 자산/부채는 임의 추정하지 않고 missing warning으로 남긴다.
5. `page_overview`는 다음 순서로 재구성한다: 이번 달 수입/지출 현황 → 자산 유동성 현황 → 자산 구성 → 지출 구조/예산 → 운영 경고.
6. `scripts/streamlit_browser_evidence.py` synthetic fixture에 overview 검증용 자산/부채/예산/월간 현금흐름 데이터를 추가하고, BAT-005 evidence output directory로 실행한다.
## Design Gate
- Profile: `standard`
- 판단 근거: DB schema, service/MCP contract, Streamlit UI, tests, baseline docs가 함께 변하는 기능 batch다.
- 별도 `design.md`: planning에 설계 결정을 포함하고, 구현 상세는 `implementation.md`에서 추적한다.
## 핵심 설계 결정
- 유동성 권위 소스는 계좌 단위 `accounts.liquidity_bucket`으로 고정한다.
- 자산 평가는 `accounts.last_balance`를 사용하며, 거래 합계로 부동산/예적금/대출 현재가를 추정하지 않는다.
- `loan` 버킷은 자산 구성 비율 분모에서 제외하고 총부채/순자산 계산에만 반영한다.
- `last_balance`가 없는 계좌는 계산에서 제외하되 운영 경고에 표시한다.
## 검증 계획
- `py_compile` for changed Python files
- `pytest tests/test_service.py -q`
- full `pytest -q`
- `scripts/streamlit_browser_evidence.py --page 요약 --output-dir docs/batches/bat-005_.../evidence/run-...` with synthetic DB
@@ -1,44 +0,0 @@
# BAT-005 Verification
## 검증 계획
1. Python 문법 검증
- `.venv/bin/python -m py_compile jarca_ledger_mcp/db.py jarca_ledger_mcp/service.py jarca_ledger_mcp/server.py dashboard/app.py scripts/streamlit_browser_evidence.py tests/test_service.py`
2. 대상 service regression
- `.venv/bin/python -m pytest tests/test_service.py -q`
3. 전체 테스트
- `.venv/bin/python -m pytest -q`
4. Streamlit browser evidence
- `.venv/bin/python scripts/streamlit_browser_evidence.py --page 요약 --output-dir docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-<timestamp>`
5. 민감정보 검토
- evidence fixture는 synthetic 데이터만 포함한다.
- 운영 DB 기본 경로, 실제 금융 원본 파일명, 비밀번호, raw_payload는 포함하지 않는다.
## Acceptance Mapping
- AC-1: `db.py` schema/migration 및 schema version 8.
- AC-2: `normalize_liquidity_bucket`, create/update validation tests.
- AC-3: account create/list/update regression tests 및 MCP signature.
- AC-4: `dashboard/app.py` top section 월간 cashflow metrics.
- AC-5/6/7: `get_asset_liquidity_report` regression 및 overview asset/liability/missing balance sections.
- AC-8: overview operational warning metrics/caption.
- AC-9: pytest 및 browser evidence result.
- AC-10: baseline docs updated.
## 결과
최종 검증 결과(2026-06-29 KST):
- `source .venv/bin/activate && python -m py_compile jarca_ledger_mcp/db.py jarca_ledger_mcp/service.py jarca_ledger_mcp/server.py dashboard/app.py scripts/streamlit_browser_evidence.py tests/test_service.py tests/test_ledger_categories.py` — PASS.
- `source .venv/bin/activate && pytest tests/test_service.py -q` — PASS (`9 passed`).
- `source .venv/bin/activate && pytest -q` — PASS (`31 passed, 4 skipped`).
- `source .venv/bin/activate && python scripts/streamlit_browser_evidence.py --page 요약 --output-dir docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-20260629-2111` — PASS.
- Evidence directory: `docs/batches/bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/evidence/run-20260629-2111/`
- Manifest: `manifest.json` (`success: true`).
- Captured page: `요약` / `overview.png` 303,341 bytes / `overview.dom.html` 30,757 bytes.
- DOM evidence includes `schema v8`, `KST 이번 달`, `이번 달 수입/지출 현황`, and `자산 유동성 현황` from a synthetic fixture DB.
## Sensitive Evidence Review
- Evidence DB path is the generated fixture path under BAT-005 evidence, not the operating DB default path.
- Fixture rows use `Synthetic`/`SYNTHETIC_*` labels and do not include real account numbers, real financial source filenames, passwords, or raw payloads.
@@ -1,64 +0,0 @@
# BAT-006 Design
## Architecture Summary
BAT-006 introduces a CI safety layer around existing test and smoke assets. GitHub Actions becomes the external gate for PR/push validation, while CI wrapper scripts provide deterministic entrypoints for environment setup, synthetic fixture DB creation, Streamlit readiness checks, DB safety smoke invocation, timeout handling, cleanup, and sensitive-output control.
The required CI gates are pytest, Streamlit AppTest, dashboard HTTP smoke, and DB safety smoke. Browser screenshot E2E remains a local evidence workflow from dcy-004 and is intentionally excluded from the required CI blocker set.
## Changed Areas
- `.github/workflows/`
- New workflow for `pull_request`, `push` to `main`, and `workflow_dispatch`.
- Required jobs should have stable names so branch protection can reference them later.
- `scripts/`
- New or adapted CI wrapper entrypoint for dashboard HTTP smoke.
- New or adapted CI wrapper entrypoint for DB safety smoke using existing `ledger_restore_smoke.py` logic where appropriate.
- Wrapper logs must avoid dumping raw transactions, account numbers, `raw_payload`, source file names, passwords, or live DB paths.
- `tests/`
- Existing pytest and Streamlit AppTest assets are reused. Add fixture helpers only if needed to make CI deterministic.
- `pyproject.toml` / dependency setup
- Confirm CI installs the extras required for pytest and dashboard/AppTest execution.
- Docs
- `docs/project-structure.md`: CI workflow and wrapper responsibilities.
- `docs/runtime-flows.md`: PR/push -> CI jobs -> gate result flow and synthetic fixture DB boundary.
- `docs/runbooks/`: CI failure reproduction runbook if the workflow/wrapper commands need operator guidance.
## Key Decisions
1. CI platform is GitHub Actions, with `pull_request`, `push` to `main`, and optional `workflow_dispatch`.
2. Required blocker gates are pytest, Streamlit AppTest, dashboard HTTP smoke, and DB safety smoke.
3. HTTP smoke and DB safety smoke use CI-specific thin wrappers rather than ad-hoc shell snippets, so exit codes, logs, readiness, timeout, and cleanup are deterministic.
4. Every CI run creates or uses synthetic fixture/temporary validation DBs. The operating DB default path is not used.
5. Browser screenshot E2E is not a required CI gate. It remains a local/manual evidence path for UI-heavy changes.
6. Branch protection enforcement is external GitHub repository configuration; the batch stabilizes workflow/check names and documents the required-check expectation.
## CI Job Boundary
- `pytest` gate:
- Install project with test dependencies.
- Run the repository pytest suite using the standard project command.
- Fail the workflow on any test failure.
- `dashboard-app-test` gate:
- Prepare synthetic fixture DB.
- Run Streamlit AppTest coverage, especially `tests/test_dashboard_app.py`.
- Fail with test-level logs only.
- `dashboard-http-smoke` gate:
- Prepare synthetic fixture DB in runner temp space.
- Start Streamlit dashboard with that DB and deterministic port policy.
- Poll HTTP readiness until 200 or timeout.
- Terminate the server and fail if cleanup fails materially.
- `db-safety-smoke` gate:
- Prepare source/backup/target paths under runner temp space.
- Invoke DB restore/safety smoke without live DB paths.
- Fail if overwrite approval policy, integrity check, or fixture health check fails.
## Sensitive Evidence Boundary
CI output may include command names, job names, synthetic DB temp paths, test identifiers, exit status, row counts for synthetic fixtures, and high-level error messages. CI output must not include live account numbers, real balances, `raw_payload`, original financial file names, passwords, or full transaction row dumps.
## Reference Doc Update Plan
- Update `docs/project-structure.md` to replace the current "CI workflow ... not yet defined" baseline with the BAT-006 workflow and wrapper structure.
- Update `docs/runtime-flows.md` with the CI validation flow and the local browser evidence boundary.
- Add a `docs/runbooks/ci-smoke.md` or equivalent only if local reproduction commands are not already obvious from the workflow/wrappers.
@@ -1,106 +0,0 @@
# BAT-006 Implementation
## Implementation Status
- Status: completed-for-qc
- Completed At (KST): 2026-06-30 15:23:00 KST
- Scope: REQ-006 CI automation, synthetic fixture entrypoints, local CI smoke reproduction docs, and StagePilot evidence/state updates.
- Boundary: REQ-006 is not marked Implemented yet; QC by `jarcaledgerqc` is the next gate.
## Changed Files
### CI workflow
- `.github/workflows/ci.yml`
- Added GitHub Actions workflow triggers for `pull_request`, `push` to `main`, and `workflow_dispatch`.
- Added stable gate jobs/check names:
- `pytest-regression`
- `dashboard-app-test`
- `dashboard-http-smoke`
- `db-safety-smoke`
- Each job installs with `uv` and runs its narrow CI gate command.
### CI fixture and smoke wrappers
- `scripts/ci_fixture_db.py`
- Added deterministic synthetic fixture DB builder for CI/AppTest/smoke checks.
- Refuses the operating ledger DB default path and only allows CI fixture filenames.
- Seeds synthetic accounts, budget, and transactions, then verifies SQLite integrity.
- `scripts/ci_dashboard_http_smoke.py`
- Added dashboard HTTP smoke wrapper.
- Creates a temp synthetic fixture DB, starts Streamlit on loopback, polls for HTTP 200 readiness, and terminates/kills the process during cleanup.
- Emits status-only JSON with fixture/readiness/cleanup result.
- `scripts/ci_db_safety_smoke.py`
- Added DB safety wrapper.
- Creates temp synthetic source/backup/target DB paths, invokes `scripts/ledger_restore_smoke.py`, and refuses the operating DB path.
- Emits status-only JSON with restore/integrity/health result.
### Tests
- `tests/test_dashboard_app.py`
- Added Streamlit AppTest coverage that creates a synthetic fixture DB through `scripts/ci_fixture_db.py`, sets `JARCA_LEDGER_DB_PATH`, and checks core pages render without Streamlit exceptions.
- Existing transfer review helper tests remain covered in the dashboard AppTest command.
### Documentation
- `docs/project-structure.md`
- Documented `.github/workflows/ci.yml`, CI fixture builder, HTTP smoke wrapper, DB safety wrapper, stable gate names, and synthetic fixture policy.
- `docs/runtime-flows.md`
- Added `CI validation gates` flow and clarified that browser screenshot/DOM evidence remains local evidence, not a required CI gate.
- `docs/runbooks/ci-smoke.md`
- Added local reproduction commands, wrapper responsibilities, stable GitHub Actions job names, browser evidence boundary, and failure triage guidance.
- `docs/batches/bat-006_20260630_pytest-apptest-smoke-ci-automation/implementation.md`
- Replaced planned placeholder with actual implementation/evidence log.
- `docs/batches/bat-006_20260630_pytest-apptest-smoke-ci-automation/verification.md`
- Added AC-by-AC verification evidence and command results.
- `docs/batches/bat-006_20260630_pytest-apptest-smoke-ci-automation/index.md`
- Moved BAT-006 batch status from `planned` to `release-candidate` for QC.
- `docs/batches/index.md`
- Moved BAT-006 register status from `planned` to `release-candidate`.
## Execution Log
All commands below were run from `/root/projects/jarca-ledger-mcp`.
1. Pytest regression gate
- Command: `uv run pytest --ignore=tests/test_dashboard_app.py -q`
- Result: PASS, exit code 0.
- Output: `............ss...............ss... [100%]`
2. Streamlit AppTest gate
- Command: `uv run pytest tests/test_dashboard_app.py -q`
- Result: PASS, exit code 0.
- Output: `.... [100%]`
3. Dashboard HTTP smoke gate
- Command: `uv run python scripts/ci_dashboard_http_smoke.py --host 127.0.0.1 --port 18501 --timeout 45`
- Result: PASS, exit code 0.
- Output summary:
- `success: true`
- `gate: dashboard-http-smoke`
- `fixture: synthetic`
- `fixture_integrity: ok`
- `http_status: 200`
- `cleanup: terminated`
4. DB safety smoke gate
- Command: `uv run python scripts/ci_db_safety_smoke.py --timeout 45`
- Result: PASS, exit code 0.
- Output summary:
- `success: true`
- `gate: db-safety-smoke`
- `fixture: synthetic`
- `fixture_integrity: ok`
- `restore_smoke_exit_code: 0`
- `restored_exists: true`
- `restored_integrity: ok`
- `health_success: true`
- `operating_db_used: false`
## Validation Summary
- GitHub Actions workflow exists with required BAT-006 trigger shape and stable job names.
- CI/AppTest/HTTP/DB safety commands pass locally against synthetic/temp DBs.
- Wrapper output is status-only and does not expose real account identifiers, operating DB data, raw payloads, source financial filenames, or passwords.
- Browser screenshot/DOM evidence is intentionally not a required CI gate and remains covered by the local browser evidence runbook/flow.
## Remaining Risks / QC Notes
- Remote GitHub Actions has not been executed in this local handoff; QC should confirm the workflow on GitHub if remote runner access is available.
- Branch protection required-check enforcement is repository configuration outside this codebase.
- REQ-006 must remain not Implemented until `jarcaledgerqc` completes QC and the requirement implementation state is explicitly confirmed.
@@ -1,32 +0,0 @@
# BAT-006 pytest/AppTest/Smoke CI 자동화
- Profile: standard
- Status: release-candidate
- Included REQ: REQ-006
- Discovery: dcy-006
- Owner: 렛저장인
- Date (KST): 2026-06-30
## 목표
REQ-006에 따라 GitHub Actions 기반 CI 계약을 신설하고, push/PR에서 pytest 회귀 스위트, Streamlit AppTest, 대시보드 HTTP smoke, DB safety smoke를 synthetic fixture/임시 검증 DB로 자동 실행하는 필수 게이트를 구성한다.
## 산출물
- `.github/workflows/` 아래 GitHub Actions workflow
- CI 전용 얇은 smoke wrapper entrypoint: HTTP smoke와 DB safety smoke의 결정적 실행/종료코드/로그/정리 책임
- synthetic fixture DB 준비 흐름과 운영 DB 접근 차단 정책
- pytest/AppTest/HTTP/DB safety smoke CI job 구성
- `docs/project-structure.md`, `docs/runtime-flows.md`, 필요 시 `docs/runbooks/`의 CI 게이트/로컬 browser evidence 경계 문서화
- BAT-006 planning/design/implementation/verification 문서와 CI evidence
## 범위 제한
browser-screenshot/visual regression의 CI 필수 게이트화, CD/서비스 배포 자동화, 테스트 커버리지 퍼센트 강제, 성능 벤치마크 게이트, 운영 DB 또는 실거래/실계좌 데이터의 CI 반입은 포함하지 않는다.
## 문서
- `planning.md`: delivery plan, dependencies, design gate, risks
- `design.md`: CI architecture, job boundaries, wrapper policy, evidence boundaries
- `implementation.md`: 실제 변경 파일과 로컬 실행 로그 기록
- `verification.md`: REQ-006 AC별 검증 evidence 및 QC handoff 기록
@@ -1,41 +0,0 @@
# BAT-006 Planning
## Included REQ
- REQ-006: pytest/AppTest/Smoke CI 자동화
## Delivery Plan
1. REQ-006 승인 상태와 dcy-006 freeze 결정을 입력 gate로 확인한다.
2. GitHub Actions workflow를 `.github/workflows/` 아래에 신설하고 `pull_request`, `main` 대상 `push`, `workflow_dispatch` 트리거를 정의한다.
3. CI 실행 환경을 표준화한다: `uv`/Python 설치, project extras 설치, runner temp 경로 사용, 운영 DB 기본 경로 접근 금지.
4. pytest 회귀 스위트 job을 구성해 `tests/` 전체 또는 동일 의미의 표준 명령을 필수 게이트로 실행한다.
5. Streamlit AppTest job을 synthetic fixture DB 기준으로 실행한다.
6. HTTP smoke와 DB safety smoke용 CI wrapper를 추가한다. wrapper는 fixture 준비, 환경 변수 설정, readiness polling, timeout, cleanup, 민감정보 비출력 정책을 담당한다.
7. DB safety smoke는 임시 fixture/검증 DB에서만 실행하고 운영 DB 및 원본 금융 파일 경로를 사용하지 않는지 검증한다.
8. `docs/project-structure.md`와 `docs/runtime-flows.md`에 CI workflow, smoke wrapper, gate result flow, 로컬 browser evidence(dcy-004)와의 경계를 반영한다. 필요하면 `docs/runbooks/ci-smoke.md`를 추가한다.
9. 로컬에서 가능한 범위의 CI 등가 명령을 실행하고, GitHub Actions 실제 로그 또는 로컬 dry-run 한계를 verification에 명확히 기록한다.
## Dependencies
- 기존 pytest 설정: `pyproject.toml`의 `[tool.pytest.ini_options]`와 dev extra의 `pytest`.
- 기존 Streamlit AppTest 자산: `tests/test_dashboard_app.py`.
- 기존 smoke 자산: `scripts/ledger_restore_smoke.py`, `scripts/streamlit_browser_evidence.py` 내부 로직 중 CI에서 재사용 가능한 부분.
- dcy-002 운영 안전 원칙: 검증 DB/fixture 우선, 운영 DB restore/mutation 금지.
- dcy-004 evidence 경계: browser screenshot evidence는 로컬 보강 경로이며 CI 필수 게이트가 아니다.
## Design Gate
Design required: yes.
Reason: 이 batch는 CI workflow, wrapper entrypoint, fixture DB safety boundary, baseline runtime docs를 함께 정의한다. runner 환경·민감정보·운영 DB 접근 차단 규칙이 요구사항의 핵심이므로 구현 전 job 경계와 wrapper 책임을 설계 문서에 고정한다.
## Milestones
- M1: REQ-006 Approved 및 BAT-006 standard batch 생성.
- M2: CI workflow/job 구조와 wrapper contract 설계 완료.
- M3: Workflow와 wrapper 구현, synthetic fixture 실행 경로 연결.
- M4: pytest/AppTest/HTTP/DB safety smoke 로컬 등가 검증 통과.
- M5: baseline docs/runbook 갱신 및 verification evidence 작성.
- M6: QC gate PASS/PASS_WITH_NOTES 후 REQ-006 Implemented 전환.
## Risks
- Streamlit HTTP smoke가 readiness 대기/포트 충돌로 flaky해질 수 있다. 고정 또는 결정적 포트 할당, polling timeout, 프로세스 cleanup을 wrapper에서 표준화한다.
- CI 로그에 실계좌번호, 실잔액, `raw_payload`, 원본 파일명, 비밀번호가 노출될 수 있다. synthetic fixture만 사용하고 wrapper 출력은 요약/상태 중심으로 제한한다.
- GitHub Actions runner에는 로컬 browser evidence 환경이 없을 수 있다. browser-screenshot E2E는 CI 필수 게이트에서 제외하고 dcy-004 로컬 evidence 경로로 유지한다.
- 브랜치 보호 required check 설정은 저장소 외부 GitHub 설정이므로, 이 batch는 workflow/check 이름을 안정화하고 문서에 후속 운영 설정으로 기록한다.
@@ -1,154 +0,0 @@
# BAT-006 Verification
## Verification Status
- Status: PASS_WITH_NOTES
- Ready for Release: true
- Ready for QC: false
- Verified At (KST): 2026-06-30 15:29 KST
- Verified By: jarcaledgerqc
- QC Verdict: PASS_WITH_NOTES
- QC Boundary: satisfied
## Acceptance Mapping
### REQ-006 AC-1
`.github/workflows/` 아래에 GitHub Actions workflow가 생성되고, `pull_request`, `main` 대상 `push`, `workflow_dispatch` 트리거가 정의된다.
Evidence:
- Workflow file: `.github/workflows/ci.yml`.
- Trigger excerpt verified in file:
- `pull_request:`
- `push:` with `branches: [main]`
- `workflow_dispatch:`
- Stable job/check names in workflow:
- `pytest-regression`
- `dashboard-app-test`
- `dashboard-http-smoke`
- `db-safety-smoke`
Result: PASS.
### REQ-006 AC-2
CI에서 pytest 회귀 스위트가 자동 실행되고, 단일 테스트 실패 시 workflow가 실패 상태로 종료된다.
Evidence:
- Workflow job: `pytest-regression`.
- Workflow command: `uv run pytest --ignore=tests/test_dashboard_app.py`.
- Local equivalent command:
- `uv run pytest --ignore=tests/test_dashboard_app.py -q`
- Result: PASS, exit code 0.
- Output: `............ss...............ss... [100%]`
- GitHub Actions `run:` step uses normal shell exit-code behavior, so a pytest failure fails the job/workflow.
Result: PASS.
### REQ-006 AC-3
CI에서 Streamlit `AppTest`가 synthetic fixture DB 기준으로 자동 실행되고 통과/실패 결과가 로그에 남는다.
Evidence:
- Workflow job: `dashboard-app-test`.
- Workflow command: `uv run pytest tests/test_dashboard_app.py`.
- Test evidence: `tests/test_dashboard_app.py` calls `create_ci_fixture_db(tmp_path / "fixture.sqlite3")`, sets `JARCA_LEDGER_DB_PATH`, and runs Streamlit AppTest across core pages.
- Local equivalent command:
- `uv run pytest tests/test_dashboard_app.py -q`
- Result: PASS, exit code 0.
- Output: `.... [100%]`
- Fixture policy: `scripts/ci_fixture_db.py` refuses `DEFAULT_DB_PATH` and seeds synthetic data only.
Result: PASS.
### REQ-006 AC-4
CI에서 대시보드 HTTP smoke가 fixture DB 기준으로 Streamlit을 기동한 뒤 HTTP 200 응답을 확인하고, 종료 후 프로세스를 정리한다.
Evidence:
- Workflow job: `dashboard-http-smoke`.
- Workflow command: `uv run python scripts/ci_dashboard_http_smoke.py --host 127.0.0.1 --port 18501 --timeout 45`.
- Wrapper: `scripts/ci_dashboard_http_smoke.py` creates a temp synthetic fixture DB, starts Streamlit with `JARCA_LEDGER_DB_PATH`, polls a loopback URL for HTTP 200, and performs process cleanup.
- Local command:
- `uv run python scripts/ci_dashboard_http_smoke.py --host 127.0.0.1 --port 18501 --timeout 45`
- Result: PASS, exit code 0.
- Output summary: `success: true`, `fixture: synthetic`, `fixture_integrity: ok`, `http_status: 200`, `attempts: 3`, `cleanup: terminated`.
Result: PASS.
### REQ-006 AC-5
CI에서 DB safety smoke가 운영 DB 기본 경로를 사용하지 않고 임시 fixture/검증 DB에서 통과한다.
Evidence:
- Workflow job: `db-safety-smoke`.
- Workflow command: `uv run python scripts/ci_db_safety_smoke.py --timeout 45`.
- Wrapper: `scripts/ci_db_safety_smoke.py` creates temp `source`, `backup`, and `target` DB files and refuses `DEFAULT_DB_PATH` before invoking `scripts/ledger_restore_smoke.py`.
- Local command:
- `uv run python scripts/ci_db_safety_smoke.py --timeout 45`
- Result: PASS, exit code 0.
- Output summary: `success: true`, `fixture: synthetic`, `fixture_integrity: ok`, `restore_smoke_exit_code: 0`, `restored_exists: true`, `restored_integrity: ok`, `health_success: true`, `operating_db_used: false`.
Result: PASS.
### REQ-006 AC-6
HTTP smoke/DB safety smoke는 CI 전용 wrapper entrypoint를 통해 실행되며, wrapper가 종료코드·timeout·readiness·cleanup을 일관되게 처리한다.
Evidence:
- HTTP wrapper path: `scripts/ci_dashboard_http_smoke.py`.
- Readiness: polls URL until HTTP 200 or timeout.
- Timeout/failure: returns non-zero status with status-only JSON.
- Cleanup: terminates/kills Streamlit process and reports cleanup state.
- DB safety wrapper path: `scripts/ci_db_safety_smoke.py`.
- Timeout: catches `subprocess.TimeoutExpired` and returns non-zero status with timeout JSON.
- Exit code: reports restore smoke exit code and returns non-zero on failed restore/integrity/health conditions.
- Safety: refuses operating DB path and reports `operating_db_used: false` on pass.
- Local command results for both wrappers exited 0 and reported success JSON.
Result: PASS.
### REQ-006 AC-7
CI 로그·아티팩트에는 실계좌번호, 실잔액, `raw_payload`, 원본 금융 파일명, 비밀번호가 평문으로 포함되지 않는다.
Evidence:
- Fixture builder uses synthetic labels such as `CI Synthetic Checking`, `CI_SYNTHETIC_*`, and `ci synthetic ...`; it does not load real statement files or passwords.
- Wrapper outputs are status-only JSON. Observed local outputs include gate name, fixture type, integrity, HTTP status, cleanup, restore smoke status, and `operating_db_used: false`; they do not include account numbers, real balances, raw payloads, source financial filenames, or passwords.
- `scripts/ci_fixture_db.py` refuses the operating ledger DB default path.
Result: PASS.
### REQ-006 AC-8
`docs/project-structure.md`와 `docs/runtime-flows.md`가 CI 게이트와 로컬 browser evidence 경계를 반영한다.
Evidence:
- `docs/project-structure.md` documents `.github/workflows/ci.yml`, stable gate names, `scripts/ci_fixture_db.py`, `scripts/ci_dashboard_http_smoke.py`, `scripts/ci_db_safety_smoke.py`, and synthetic fixture policy.
- `docs/runtime-flows.md` includes `Flow: CI validation gates` and the constraints that CI gates use synthetic/temp DBs only.
- `docs/runbooks/ci-smoke.md` provides reproduction commands and failure triage.
Result: PASS.
### REQ-006 AC-9
browser-screenshot E2E는 CI 필수 차단 게이트에서 제외되고, dcy-004 로컬 evidence 절차와의 역할 분담이 문서에 명시된다.
Evidence:
- `.github/workflows/ci.yml` contains the four required CI jobs and no browser screenshot/visual regression required job.
- `docs/runtime-flows.md` states browser screenshot/DOM evidence is not a required GitHub Actions gate in BAT-006 and remains local evidence for visual/layout-sensitive dashboard changes.
- `docs/runbooks/ci-smoke.md` states `scripts/streamlit_browser_evidence.py` remains local evidence and is not a required GitHub Actions gate.
Result: PASS.
## Command Evidence Summary
All commands were run from `/root/projects/jarca-ledger-mcp`.
| Command | Result | Evidence |
| --- | --- | --- |
| `uv run pytest --ignore=tests/test_dashboard_app.py -q` | PASS, exit code 0 | `............ss...............ss... [100%]` |
| `uv run pytest tests/test_dashboard_app.py -q` | PASS, exit code 0 | `.... [100%]` |
| `uv run python scripts/ci_dashboard_http_smoke.py --host 127.0.0.1 --port 18501 --timeout 45` | PASS, exit code 0 | `success: true`, `http_status: 200`, `cleanup: terminated` |
| `uv run python scripts/ci_db_safety_smoke.py --timeout 45` | PASS, exit code 0 | `success: true`, `restored_integrity: ok`, `health_success: true`, `operating_db_used: false` |
## Sensitive Evidence Review
- No command output observed in this verification exposed real account numbers, operating DB balances, source financial filenames, passwords, or `raw_payload`.
- CI fixture/smoke paths are synthetic/temp paths and refuse the default operating ledger DB path.
- Remote GitHub Actions logs were not available in this local handoff; `jarcaledgerqc` recorded this as a note rather than a blocker because local equivalent commands passed and the workflow wiring is present.
## Blocking Issues
- None for local QC readiness.
- QC note: Remote GitHub Actions execution and branch protection required-check setup remain repository/remote configuration checks outside this local evidence update.
@@ -1,50 +0,0 @@
# BAT-007 Design
## Contract versioning design
- Active MCP success response contract version: `1.0`.
- Version format: `major.minor`.
- Runtime exposure: unexposed. MCP success payloads are not modified to add a common `contract_version` field.
- Source of truth: `docs/interface-contract.md`.
- Snapshot metadata: `tests/contract_snapshots/response_contract_v1_0.json`.
## Change classification
- Breaking / major: required key removal, required key type change, nested object/list shape change that breaks existing consumers.
- Additive / minor: optional field additions and documentation/test metadata additions that preserve existing response semantics.
- Every response-shape-changing REQ/BAT must record contract impact: none, additive minor, or breaking major.
## Contract regression design
Representative first-wave scopes:
- health/status: `service.health_check`, `service.get_ledger_db_status`
- list: `service.list_ledger_accounts`
- report: `service.get_monthly_cashflow_report`
- mutation success envelope: `service.create_ledger_account`
The pytest contract checker validates required keys and required types only. Additional keys are allowed, matching the additive policy.
Synthetic fixture policy:
- Test DB paths are created under pytest `tmp_path`.
- Fixture data uses synthetic names and amounts only.
- No operating DB path, source financial filename, password, raw payload, or real account identifier is used.
## CI design
Required-check contract job names:
- `pytest-regression`
- `dashboard-app-test`
- `dashboard-http-smoke`
- `db-safety-smoke`
- `contract-regression`
- `lint`
`.github/workflows/ci.yml` adds:
- `contract-regression`: `uv run pytest tests/test_contract_regression.py`
- `lint`: `uv run ruff check .`
Actual branch protection toggles remain external GitHub repository settings.
@@ -1,115 +0,0 @@
# BAT-007 Implementation
## Changed files
- `.github/workflows/ci.yml`
- Added stable required-check candidate jobs: `contract-regression`, `lint`.
- `pyproject.toml`, `uv.lock`
- Added `ruff` to dev dependencies and conservative `E9`/`F` initial lint config.
- `tests/test_contract_regression.py`
- Added representative MCP response contract regression tests.
- `tests/contract_snapshots/response_contract_v1_0.json`
- Added contract `1.0` metadata and required-subset schemas for health/status, list, report, and mutation success envelope scopes.
- `docs/interface-contract.md`
- Added MCP response contract `1.0` governance, breaking/additive classification, runtime exposure policy, version log, and CI required-check contract.
- `docs/project-structure.md`, `docs/runtime-flows.md`
- Updated baseline structure/flow docs for contract snapshots/tests, `contract-regression`, `lint`, branch-protection boundary, and synthetic-only invariant.
- `docs/batches/index.md`
- Registered BAT-007.
- `docs/batches/bat-007_20260630_mcp-response-contract-ci-versioning/{index,planning,design,implementation,verification}.md`
- Added standard batch delivery docs.
- `docs/srs/Interface/req-007_mcp-response-contract-versioning-governance.md`
- `docs/srs/Testing/req-008_ci-contract-regression-and-lint-required-checks.md`
- `docs/srs/index.md`
- Updated REQ state to Implemented after verification evidence.
## Implementation notes
- Runtime MCP success payloads were not changed.
- Contract version `1.0` is documented in `docs/interface-contract.md` and mirrored in `tests/contract_snapshots/response_contract_v1_0.json`.
- Contract regression is representative, not exhaustive.
- Lint gate uses conservative `ruff` rules: `E9`, `F`.
- All new test data uses pytest temp DBs and synthetic names/amounts only.
## Verification command log
Executed from `/root/projects/jarca-ledger-mcp`.
1. `uv sync --extra dev --extra dashboard`
Result:
```text
Resolved 72 packages in 1.37s
Building jarca-ledger-mcp @ file:///root/projects/jarca-ledger-mcp
Downloading ruff (11.0MiB)
Downloaded ruff
Built jarca-ledger-mcp @ file:///root/projects/jarca-ledger-mcp
Prepared 3 packages in 2.94s
Uninstalled 2 packages in 18ms
Installed 3 packages in 338ms
~ jarca-ledger-mcp==0.1.0 (from file:///root/projects/jarca-ledger-mcp)
- pytest==9.1.0
+ pytest==9.1.1
+ ruff==0.15.20
```
2. `uv run pytest tests/test_contract_regression.py`
Result:
```text
... [100%]
3 passed in 0.99s
```
3. `uv run ruff check .`
Result:
```text
All checks passed!
```
4. `uv run pytest --ignore=tests/test_dashboard_app.py`
Result:
```text
...............ss...............ss... [100%]
33 passed, 4 skipped in 29.37s
```
5. `uv run python scripts/ci_db_safety_smoke.py --timeout 45`
Result:
```json
{
"success": true,
"gate": "db-safety-smoke",
"fixture": "synthetic",
"fixture_integrity": "ok",
"restore_smoke_exit_code": 0,
"restored_exists": true,
"restored_integrity": "ok",
"health_success": true,
"operating_db_used": false
}
```
6. `uv run python scripts/ci_dashboard_http_smoke.py --host 127.0.0.1 --port 18501 --timeout 45`
Result:
```json
{
"success": true,
"gate": "dashboard-http-smoke",
"fixture": "synthetic",
"fixture_integrity": "ok",
"http_status": 200,
"attempts": 4,
"cleanup": "terminated"
}
```
@@ -1,32 +0,0 @@
# BAT-007 MCP response contract / CI contract versioning
- Profile: standard
- Status: release-candidate
- Included REQ: REQ-007, REQ-008
- Discovery: dcy-007
- Owner: 렛저장인
- Date (KST): 2026-06-30
## 목표
REQ-007/REQ-008에 따라 MCP 성공 응답 contract version `1.0` governance를 확정하고, representative contract regression과 `ruff` lint를 CI required-check 계약에 추가한다. 런타임 성공 응답 shape는 보존하며 `contract_version` 필드는 노출하지 않는다.
## 산출물
- `docs/interface-contract.md`의 versioning governance, change classification, version log, required-check contract
- `docs/project-structure.md`, `docs/runtime-flows.md` baseline gap 해소 및 CI/branch-protection/synthetic-only 경계 반영
- `tests/test_contract_regression.py`와 `tests/contract_snapshots/response_contract_v1_0.json`
- `.github/workflows/ci.yml`의 `contract-regression`, `lint` stable job 추가
- `pyproject.toml`의 `ruff` dev dependency 및 보수적 초기 lint rule set
- BAT-007 planning/design/implementation/verification 문서
## 범위 제한
모든 MCP 도구 100% snapshot 커버리지, 런타임 `contract_version` 노출, breaking response migration, 실제 GitHub branch protection setting 토글, browser visual regression CI gate는 포함하지 않는다.
## 문서
- `planning.md`: delivery plan, dependencies, risks
- `design.md`: contract governance and CI gate design
- `implementation.md`: changed files and actual execution evidence
- `verification.md`: AC별 검증 결과와 REQ state 판단
@@ -1,29 +0,0 @@
# BAT-007 Planning
## Scope
- Implement REQ-007: MCP response contract versioning governance.
- Implement REQ-008: representative contract regression and lint required checks.
- Preserve existing success response shapes; runtime `contract_version` remains unexposed.
- Use synthetic/temp data only for tests and evidence.
## Dependencies
- dcy-007 confirmed Discovery and approved REQ-007/REQ-008.
- Existing BAT-006 CI workflow and synthetic fixture policy.
- Existing service-layer functions that accept `db_path` for temp fixture tests.
## Work plan
1. Add BAT-007 standard batch docs and index entry.
2. Add contract version `1.0` governance and CI required-check contract to baseline docs.
3. Add representative contract snapshot metadata and pytest regression for health/status, list, report, and mutation success envelope scopes.
4. Add `ruff` dev dependency/config and CI `lint`/`contract-regression` jobs while preserving existing job names.
5. Run narrow local verification: contract pytest, ruff, targeted regression that includes the new test, then full pytest if narrow gates pass.
6. If evidence satisfies ACs, move REQ-007 and REQ-008 to Implemented.
## Risks and mitigations
- Over-strict snapshot failures: mitigate by required-subset/type checks so optional additive fields pass.
- Existing code lint churn: mitigate by conservative initial `ruff` rule set (`E9`, `F`).
- Branch protection cannot be toggled from code: document as external operator setting and keep stable job names.
@@ -1,48 +0,0 @@
# BAT-007 Verification
## Verification summary
Status: PASS
REQ-007 and REQ-008 have sufficient repository evidence to move from Approved to Implemented.
Evidence commands executed from `/root/projects/jarca-ledger-mcp`:
| Command | Result |
| --- | --- |
| `uv sync --extra dev --extra dashboard` | PASS; `ruff==0.15.20` installed and lockfile updated. |
| `uv run pytest tests/test_contract_regression.py` | PASS; `3 passed in 0.99s`. |
| `uv run ruff check .` | PASS; `All checks passed!`. |
| `uv run pytest --ignore=tests/test_dashboard_app.py` | PASS; `33 passed, 4 skipped in 29.37s`. |
| `uv run python scripts/ci_db_safety_smoke.py --timeout 45` | PASS; JSON `success: true`, `fixture: synthetic`, `operating_db_used: false`. |
| `uv run python scripts/ci_dashboard_http_smoke.py --host 127.0.0.1 --port 18501 --timeout 45` | PASS; JSON `success: true`, `fixture: synthetic`, `http_status: 200`. |
## Acceptance criteria mapping
### REQ-007
- AC-1: PASS. `docs/interface-contract.md` defines `major.minor` and initial `1.0` contract version.
- AC-2: PASS. Breaking vs additive rules cover key removal, type changes, nested structure changes, and optional field additions.
- AC-3: PASS. `docs/interface-contract.md` contains source-of-truth rules and a version log linking dcy-007/REQ-007/BAT-007.
- AC-4: PASS. Runtime `contract_version` exposure is explicitly unexposed for `1.0`.
- AC-5: PASS. Response-shape-changing REQ/BAT work must state contract impact: none, additive minor, or breaking major.
- AC-6: PASS. Runtime success payloads were not changed; contract tests assert existing representative shapes.
### REQ-008
- AC-1: PASS. `tests/test_contract_regression.py` covers health/status, list, report, and mutation success envelope representative scopes.
- AC-2: PASS. The checker fails on missing required keys, required type changes, and required nested structure changes; additive fields are allowed.
- AC-3: PASS. Tests use pytest `tmp_path` synthetic SQLite DBs and committed schema metadata only. Smoke evidence also reports `fixture: synthetic` and `operating_db_used: false` where applicable.
- AC-4: PASS. `.github/workflows/ci.yml` includes a `lint` job running `uv run ruff check .`; local ruff verification passed.
- AC-5: PASS. Required-check job names are documented and existing BAT-006 job names are preserved.
- AC-6: PASS. `docs/interface-contract.md`, `docs/project-structure.md`, and `docs/runtime-flows.md` reflect contract-regression/lint/required-check/synthetic-only boundaries.
- AC-7: PASS. Baseline docs state actual branch protection toggles are external operator-managed GitHub repository settings.
## Requirement state decision
- REQ-007: Implemented.
- REQ-008: Implemented.
## Blockers
None.
@@ -1,40 +0,0 @@
# BAT-008 Design
## Schema and persistence design
- Add `manual_assets` as a first-class table for non-transaction-derived assets/liabilities.
- Add `asset_snapshots` as an append-only history table keyed by basis date plus evaluated item identity.
- Migrations remain additive/idempotent; existing ledger/account flows must continue to operate when both tables are empty.
## Authority-source and valuation design
- Account-backed assets use `accounts.last_balance` as the live authority source.
- Non-transaction assets/liabilities use `manual_assets` as the live authority source.
- `asset_snapshots` is a historical record layer, not a competing primary input source.
- Net worth formula remains: asset buckets (`cash`, `investment`, `deposit`, `real_estate`, `other`) minus `loan`; missing valuations are excluded, not inferred.
## Read model design
- Service layer should expose:
- manual assets list/report helpers
- basis-date asset snapshot read helpers
- net-worth timeseries helpers
- shared valuation/fallback helpers consumed by both MCP and dashboard
- Snapshot read responses must expose basis date, bucket totals, liabilities, net worth, and inclusion/exclusion explanation fields.
- Manual assets read responses must expose item name, value, basis date, `liquidity_bucket`, and memo/source metadata.
## Dashboard alignment design
- `dashboard/app.py` should consume the same valuation helpers as the MCP read tools.
- If no manual assets/snapshots exist, dashboard behavior must safely fall back to REQ-005 account-based display.
- Excluded/unvalued items should be explainable instead of silently counted.
## Verification design
- Add targeted regression tests for:
- additive migration creation
- manual asset persistence and retrieval
- snapshot accumulation/read behavior
- net-worth formula / exclusion policy
- dashboard/MCP shared fallback behavior
- Prefer synthetic SQLite fixtures and temp DBs only.
@@ -1,104 +0,0 @@
# BAT-008 Implementation
## Plan summary
BAT-008 implemented the new valuation authority model in `service.py`/`db.py`, exposed read-only MCP tools in `server.py`, aligned the Streamlit overview with the shared valuation helper, and updated baseline docs to match the confirmed Discovery/REQ scope.
## Changed files
- `jarca_ledger_mcp/db.py`
- `SCHEMA_VERSION` → `9`
- additive/idempotent tables: `manual_assets`, `asset_snapshots`
- migration path updated so existing DBs create the new tables safely
- `jarca_ledger_mcp/service.py`
- shared valuation helpers for account/manual-asset/snapshot authority sources
- new service APIs: `create_manual_asset`, `list_manual_assets`, `create_asset_snapshot`, `get_asset_snapshot_report`, `get_net_worth_timeseries`
- `get_asset_liquidity_report` aligned to the same valuation policy while preserving REQ-005 fallback semantics
- `jarca_ledger_mcp/server.py`
- new read MCP tools: `list_manual_assets`, `get_asset_snapshot_report`, `get_net_worth_timeseries`
- `get_asset_liquidity_report` contract text updated for shared valuation source behavior
- `dashboard/app.py`
- overview asset section now explains the valuation authority source and shows `manual_assets` rows when present
- existing account-only fallback remains when new tables are empty
- Documentation
- `docs/data-model.md`
- `docs/interface-contract.md`
- `docs/runtime-flows.md`
- `docs/project-structure.md`
- Tests
- new: `tests/test_asset_snapshots.py`
- adjusted: `tests/test_service.py`
## Execution log
- 2026-06-30 21:26 KST: BAT-008 standard batch scaffold created from approved REQ-009/REQ-010.
- 2026-06-30 21:3x~21:4x KST: implementation landed in `db.py`, `service.py`, `server.py`, `dashboard/app.py`, docs, and regression tests via `jarcaledgerdev` handoff + local verification orchestration.
- 2026-06-30 21:40 KST: targeted compile/test validation passed.
- 2026-06-30 21:41 KST: MCP stdio contract smoke check passed and discovered the three new read tools.
- 2026-06-30 21:42 KST: synthetic end-to-end service probe confirmed live-authority fallback, snapshot read behavior, and net-worth timeseries output.
## Validation
### Command 1
```bash
cd /root/projects/jarca-ledger-mcp
source .venv/bin/activate
python -m py_compile jarca_ledger_mcp/*.py dashboard/app.py
pytest tests/test_asset_snapshots.py tests/test_service.py tests/test_contract_regression.py -q
```
Result:
- `................. [100%]`
- exit code `0`
### Command 2
```bash
cd /root/projects/jarca-ledger-mcp
source .venv/bin/activate
hermes mcp test jarca-ledger
```
Result:
- stdio connection success
- tools discovered: `51`
- new BAT-008 read tools discovered:
- `list_manual_assets`
- `get_asset_snapshot_report`
- `get_net_worth_timeseries`
### Command 3
```bash
cd /root/projects/jarca-ledger-mcp
source .venv/bin/activate
python - <<'PY'
from tempfile import TemporaryDirectory
from pathlib import Path
from jarca_ledger_mcp import service
with TemporaryDirectory() as td:
db_path = str(Path(td) / 'ledger.sqlite3')
service.create_ledger_account('현금', last_balance=1000000, last_synced_at='2026-06-30', liquidity_bucket='cash', db_path=db_path)
service.create_ledger_account('투자', type='investment', last_balance=2000000, liquidity_bucket='investment', db_path=db_path)
service.create_manual_asset('전세보증금', 300000000, '2026-06-30', 'real_estate', source_note='synthetic appraisal', db_path=db_path)
service.create_manual_asset('주담대', 120000000, '2026-06-30', 'loan', source_note='synthetic loan balance', db_path=db_path)
print(service.list_manual_assets(db_path=db_path))
print(service.get_asset_snapshot_report('2026-06-30', db_path=db_path))
service.create_asset_snapshot('2026-05-31', 'account', 'acct-a', '현금', 1000000, 'cash', source_note='synthetic', db_path=db_path)
service.create_asset_snapshot('2026-05-31', 'manual_asset', 'manual-home', '부동산', 200000000, 'real_estate', source_note='synthetic', db_path=db_path)
service.create_asset_snapshot('2026-05-31', 'manual_asset', 'manual-loan', '대출', 80000000, 'loan', source_note='synthetic', db_path=db_path)
print(service.get_asset_snapshot_report('2026-05-31', db_path=db_path))
print(service.get_net_worth_timeseries(start_date='2026-05-01', end_date='2026-06-30', db_path=db_path))
PY
```
Key result excerpts:
- `list_manual_assets` returned `count=2` and `authority_source='manual_assets'`
- live fallback snapshot report returned `source='live_authority'`, `total_assets=303000000`, `total_liabilities=120000000`, `net_worth=183000000`
- stored snapshot report returned `source='asset_snapshots'`, `snapshot_count=3`, `net_worth=121000000`
- timeseries returned `points[0].basis_date='2026-05-31'`, `points[0].net_worth=121000000`
## Remaining risks / follow-up notes
- Snapshot creation is intentionally service-only in BAT-008. MCP mutation exposure remains future scope by Discovery decision.
- Manual-asset edit/delete workflows and month-end operator UX are still procedural/document-driven rather than exposed as first-class CRUD flows.
- QC gate still needs to confirm REQ Implemented promotion before commit-stage handoff.
@@ -1,36 +0,0 @@
# BAT-008 Asset snapshots / manual assets / read MCP
- Profile: standard
- Status: release-candidate
- Included REQ: REQ-009, REQ-010
- Discovery: dcy-008
- Owner: 렛저장인
- Date (KST): 2026-06-30
## 목표
REQ-009/REQ-010에 따라 `asset_snapshots`/`manual_assets` 저장 모델을 additive/idempotent하게 도입하고, 월말 수동 스냅샷 정책을 수용하는 집계 계층과 조회성 MCP(기준일 스냅샷/순자산 시계열/수기 자산 조회)를 구현한다. 동시에 대시보드 자산/순자산 표시가 동일 권위 소스와 동일 산식을 사용하도록 정렬한다.
## 산출물
- `asset_snapshots`, `manual_assets` additive/idempotent schema migration
- 수기 자산 저장/조회, 스냅샷 누적, 순자산 시계열 집계 service 함수
- 조회성 MCP tool/응답 계약: 기준일 자산 스냅샷, 순자산 시계열, 수기 자산 조회
- `dashboard/app.py`의 자산/순자산 표시가 신규 모델과 안전 폴백을 함께 지원하도록 정렬
- `docs/data-model.md`, `docs/interface-contract.md`, `docs/project-structure.md`, `docs/runtime-flows.md` baseline 갱신
- BAT-008 planning/design/implementation/verification 문서와 synthetic-only 검증 evidence
## 범위 제한
- 외부 시세/부동산 자동 평가 연동
- 스냅샷 생성 mutation MCP
- 수기 자산 생성/수정/삭제 mutation MCP
- 투자 조언/리밸런싱/세금/수익률 계산
- 운영 DB 실데이터 기반 evidence
## 문서
- `planning.md`: delivery plan, dependency, risk, validation entry criteria
- `design.md`: schema/authority-source/fallback/read-contract design
- `implementation.md`: changed files, execution log, validation commands
- `verification.md`: AC mapping, PASS/FAIL, REQ Implemented decision
@@ -1,37 +0,0 @@
# BAT-008 Planning
## Scope
- Implement REQ-009: `asset_snapshots`/`manual_assets` valuation model, authority-source rule, month-end manual snapshot policy support.
- Implement REQ-010: asset snapshot read MCP, net-worth timeseries read MCP, manual assets read MCP, dashboard/MCP alignment.
- Preserve REQ-005 safety fallback when new tables are empty.
- Use synthetic/temp data only for tests and verification evidence.
## Dependencies
- dcy-008 confirmed Discovery and approved REQ-009/REQ-010.
- Existing REQ-005 dashboard liquidity/net-worth flow and `accounts.last_balance` authority-source baseline.
- Existing MCP server/service pattern in `jarca_ledger_mcp/server.py`, `jarca_ledger_mcp/service.py`, `jarca_ledger_mcp/db.py`.
- Additive/idempotent SQLite migration discipline and synthetic-only evidence policy.
## Work plan
1. Create BAT-008 standard batch docs and register entry.
2. Add schema/model support for `manual_assets` and `asset_snapshots` with safe empty-table fallback.
3. Add service-layer valuation helpers, snapshot accumulation/report functions, and dashboard alignment logic.
4. Add read-only MCP tool endpoints/contracts for snapshot read, net-worth timeseries, and manual assets read.
5. Update baseline docs (`docs/data-model.md`, `docs/interface-contract.md`, `docs/project-structure.md`, `docs/runtime-flows.md`).
6. Run narrow validation first (targeted tests / lint / smoke as applicable), then broader regression if narrow gates pass.
7. If evidence satisfies ACs, move BAT-008 to release-candidate and REQ-009/REQ-010 to Implemented.
## Design Gate
- Result: standard batch 유지.
- Reason: schema, service, MCP contract, dashboard alignment, baseline docs를 함께 변경하며 interface/data/fallback 설계가 필요하다.
## Risks and mitigations
- Authority-source drift between dashboard and MCP: mitigate by centralizing valuation helpers and writing shared regression tests.
- Empty new tables breaking existing REQ-005 flows: mitigate by explicit fallback tests and additive migrations only.
- Double counting between account-backed assets and manual assets: mitigate by clearly separating source responsibility and documenting inclusion/exclusion rules.
- Snapshot history ambiguity: mitigate by storing basis date, source type, and memo for every snapshot row.
@@ -1,64 +0,0 @@
# BAT-008 Verification
## Verification summary
Status: PASS
Evidence collected against synthetic/temp data only. No production ledger DB mutation or real financial files were used.
## Acceptance criteria mapping
### REQ-009
- AC-1: **PASS**
- Evidence: `tests/test_asset_snapshots.py::test_asset_snapshot_schema_is_additive_and_idempotent`
- `db.py` adds `manual_assets` and `asset_snapshots` via additive/idempotent schema + migration path.
- AC-2: **PASS**
- Evidence: `create_manual_asset`/`list_manual_assets` service path + synthetic probe output includes `name`, `valuation_amount`, `valuation_date`, `liquidity_bucket`, `source_note`.
- AC-3: **PASS**
- Evidence: `create_asset_snapshot` stores basis date/source target/amount/bucket/source note; `test_snapshot_rows_are_append_only_and_timeseries_uses_same_formula` proves append-only readback.
- AC-4: **PASS**
- Evidence: `valuation_policy` and `authority_source` fields distinguish `accounts.last_balance`, `manual_assets`, and `asset_snapshots`; docs updated in `docs/data-model.md` and `docs/runtime-flows.md`.
- AC-5: **PASS**
- Evidence: valuation helper formula is `asset_buckets - loan`; synthetic probe returned `303000000 - 120000000 = 183000000`; unvalued items are excluded rather than inferred.
- AC-6: **PASS**
- Evidence: `tests/test_asset_snapshots.py::test_asset_liquidity_report_empty_new_tables_preserves_req005_fallback` confirms empty new tables preserve REQ-005 path with `source='accounts.last_balance'`.
- AC-7: **PASS**
- Evidence: `docs/data-model.md`, `docs/runtime-flows.md`, and `docs/project-structure.md` now document the new tables, authority-source rule, and month-end snapshot flow.
### REQ-010
- AC-1: **PASS**
- Evidence: `server.py` exposes `get_asset_snapshot_report`; synthetic probe returned `basis_date`, per-bucket totals, liabilities, net worth, included/excluded items.
- AC-2: **PASS**
- Evidence: `server.py` exposes `get_net_worth_timeseries`; service/test coverage proves identical formula per basis date.
- AC-3: **PASS**
- Evidence: `server.py` exposes `list_manual_assets`; synthetic probe returned name/value/date/bucket/source note payloads.
- AC-4: **PASS**
- Evidence: `dashboard/app.py` caption explicitly states shared valuation helper; `service.py` centralizes calculation for dashboard + MCP.
- AC-5: **PASS**
- Evidence: same fallback regression test as REQ-009 AC-6 plus `get_asset_liquidity_report` preserves existing keys while adding optional explanatory fields.
- AC-6: **PASS**
- Evidence: `docs/interface-contract.md`, `docs/runtime-flows.md`, and `docs/project-structure.md` updated for read MCP contract and dashboard/MCP alignment.
## Requirement state decision
- REQ-009: Implemented promotion confirmed.
- REQ-010: Implemented promotion confirmed.
## Validation evidence
1. `python -m py_compile jarca_ledger_mcp/*.py dashboard/app.py` → pass
2. `pytest tests/test_asset_snapshots.py tests/test_service.py tests/test_contract_regression.py -q` → pass (`................. [100%]`)
3. `hermes mcp test jarca-ledger` → pass; stdio connected, 51 tools discovered, including the three new BAT-008 read tools
4. synthetic service probe → pass; confirmed live-authority fallback, stored-snapshot read path, and net-worth timeseries output
## Remaining issues
### Hard blockers
- None identified from the collected implementation evidence.
### Non-blocking follow-up
- jarcaledgerqc final re-check returned: `PASS, REQ-009/REQ-010은 이제 Implemented로 전환해도 됩니다.`
- fresh Streamlit browser smoke on `http://127.0.0.1:8511` rendered `schema v9`, `자산 유동성 현황`, and produced no browser console JS errors.
- Snapshot creation/manual-asset CRUD MCP mutations remain intentionally out of scope for BAT-008.
@@ -1,40 +0,0 @@
# BAT-009 Design
## Schema and persistence design
- Reuse `manual_assets` / `asset_snapshots` tables from BAT-008 and extend them only additively for write workflow metadata as needed.
- `manual_assets` write lifecycle must support create/update/deactivate without destroying prior snapshot traceability.
- `asset_snapshots` remains append-only; correction runs add new rows/metadata rather than overwriting prior close rows.
## Write workflow design
- Service layer should expose:
- manual asset create/update/deactivate helpers
- snapshot preview helper that returns write-free totals/warnings
- snapshot close helper that materializes authority-source rows for one `basis_date`
- correction helper/metadata so same-date re-close is represented as a correction append, not overwrite
- Close path must preserve `source_type`, `source_id`, display name, valuation amount, `liquidity_bucket`, memo/reason metadata.
## MCP and contract design
- `server.py` should expose mutation MCP tools for manual asset CRUD and snapshot preview/close.
- Success/error envelopes must match dcy-007 contract conventions.
- Preview responses expose `source='live_authority'`, `is_closed_snapshot=false`; close responses expose `source='snapshot'`, `is_closed_snapshot=true`.
- Correction close responses must identify that a correction run occurred.
## Dashboard/operator UX design
- `dashboard/app.py` should provide manual asset create/edit/deactivate flows and a month-end close panel.
- Preview and close actions must be visually distinct.
- Screen text should clarify whether displayed values are live authority estimates or closed snapshot values.
- Correction history should be explainable at least through summary metadata/messages.
## Verification design
- Add targeted regression tests for:
- manual asset update/deactivate lifecycle
- snapshot preview side-effect freedom
- append-only correction behavior for same `basis_date`
- mutation MCP contract envelope coverage
- dashboard/shared-helper fallback and source labeling
- Prefer temp DB + synthetic data + local Streamlit smoke only.
@@ -1,47 +0,0 @@
# BAT-009 Implementation
## Plan summary
BAT-009 extends the BAT-008 valuation/read foundation into a full write workflow: manual asset CRUD, month-end snapshot preview/close/correction, mutation MCP contracts, operator dashboard UX, and baseline doc alignment while preserving shared valuation rules and safe fallback behavior.
## Changed files
- `jarca_ledger_mcp/db.py`
- `jarca_ledger_mcp/service.py`
- `jarca_ledger_mcp/server.py`
- `dashboard/app.py`
- `tests/test_asset_snapshots.py`
- `tests/test_contract_regression.py`
- `tests/test_dashboard_app.py`
- `tests/test_ledger_categories.py`
- `tests/test_service.py`
- `tests/contract_snapshots/response_contract_v1_0.json`
- `docs/data-model.md`
- `docs/interface-contract.md`
- `docs/discovery/dcy-009_20260701_manual-asset-crud-month-end-snapshot-close-workflow.md`
- `docs/srs/Data/req-011_manual-asset-crud-month-end-snapshot-write-model.md`
- `docs/srs/Interface/req-012_manual-asset-crud-snapshot-close-mcp-and-operator-dashboard-alignment.md`
- `docs/srs/index.md`
- `docs/batches/index.md`
- `docs/batches/bat-009_20260701_manual-asset-crud-snapshot-close/index.md`
- `docs/batches/bat-009_20260701_manual-asset-crud-snapshot-close/verification.md`
## Execution log
- 2026-07-01 09:03 KST: BAT-009 standard batch scaffold created from approved REQ-011/REQ-012.
- 2026-07-01 10:52 KST: `manual_assets` write lifecycle(create/update/deactivate), `asset_snapshots` close/correction metadata, latest-run snapshot read selection, mutation MCP 5종, 대시보드 `자산/마감` 페이지, contract snapshot/test, baseline docs 정렬을 반영했다.
- 2026-07-01 10:52 KST: stale schema-version expectations(`8`/`9`)을 current schema version `10`에 맞게 `tests/test_ledger_categories.py`, `tests/test_service.py`에서 정렬했다.
## Validation
- `python3 -m py_compile jarca_ledger_mcp/*.py dashboard/app.py` → PASS
- `python3 -m pytest tests/test_asset_snapshots.py tests/test_contract_regression.py tests/test_dashboard_app.py -q` → PASS (`12 passed`)
- `python3 -m pytest -q` → PASS (`42 passed, 4 skipped`)
- `hermes mcp test jarca-ledger` → PASS (`Connected`, `Tools discovered: 56`)
- Browser smoke: Streamlit app on `http://127.0.0.1:18501/?page=자산/마감` rendered the new page with manual asset CRUD section and snapshot preview/close section; browser console JS errors 없음.
## Remaining risks / follow-up notes
- Correction metadata shape must remain compatible with existing read helpers and historical snapshots.
- Dashboard UX should not imply production-safe automation; this batch is still synthetic-evidence only.
- Automatic valuation feeds and scheduled month-end close remain explicitly out of scope for BAT-009.
@@ -1,36 +0,0 @@
# BAT-009 Manual asset CRUD / snapshot close
- Profile: standard
- Status: release-candidate
- Included REQ: REQ-011, REQ-012
- Discovery: dcy-009
- Owner: 렛저장인
- Date (KST): 2026-07-01
## 목표
REQ-011/REQ-012에 따라 `manual_assets` write lifecycle, month-end snapshot preview/close, append-only correction policy, mutation MCP, operator dashboard UX, source/is_closed 표기 정렬을 구현한다. 동시에 기존 BAT-008 read model/REQ-005 dashboard safety fallback/dcy-007 contract regression을 깨지 않도록 write/read 일관성을 유지한다.
## 산출물
- `manual_assets` create/update/deactivate write support and validation
- snapshot preview/close/correction service APIs and additive persistence metadata
- mutation MCP tools/contracts: manual asset CRUD, snapshot preview, snapshot close
- `dashboard/app.py` operator UX for manual asset management and month-end close preview/execute
- regression tests for write/read consistency, correction policy, contract envelope, dashboard fallback
- `docs/data-model.md`, `docs/interface-contract.md`, `docs/project-structure.md`, `docs/runtime-flows.md` baseline write-workflow updates
- BAT-009 planning/design/implementation/verification documents and synthetic-only evidence
## 범위 제한
- 외부 시세/부동산 자동 평가 연동
- 월말 자동 스케줄링/cron close
- 투자 조언/리밸런싱/세금/수익률 계산
- production ledger DB 실데이터 기반 evidence
## 문서
- `planning.md`: delivery plan, dependency, risks, validation entry criteria
- `design.md`: write-model/correction/MCP/UI design
- `implementation.md`: changed files, execution log, validation commands
- `verification.md`: AC mapping, PASS/FAIL, REQ Implemented decision
@@ -1,37 +0,0 @@
# BAT-009 Planning
## Scope
- Implement REQ-011: manual asset create/update/deactivate write model, snapshot preview/close persistence, append-only correction policy.
- Implement REQ-012: mutation MCP tools/contracts, operator dashboard UX, source/is_closed_snapshot alignment.
- Preserve REQ-005/REQ-010 safe fallback when manual asset write paths are unused or new write metadata is absent.
- Use synthetic/temp data only for tests and verification evidence.
## Dependencies
- dcy-009 confirmed Discovery and approved REQ-011/REQ-012.
- Existing BAT-008 read model in `jarca_ledger_mcp/db.py`, `service.py`, `server.py`, `dashboard/app.py`.
- Existing dcy-007 response contract / `tests/test_contract_regression.py` expectations.
- Additive/idempotent SQLite migration discipline and dcy-002 backup/approval safety policy.
## Work plan
1. Create BAT-009 standard batch docs and register entry.
2. Extend schema/service write path for manual asset update/deactivate and snapshot preview/close/correction metadata.
3. Add mutation MCP endpoints/contracts for manual asset CRUD and snapshot preview/close.
4. Add dashboard operator flows for manual asset management and month-end close preview/execute.
5. Update baseline docs (`docs/data-model.md`, `docs/interface-contract.md`, `docs/project-structure.md`, `docs/runtime-flows.md`).
6. Run narrow validation first (targeted tests / contract regression / synthetic service probe / dashboard smoke).
7. If evidence satisfies ACs, move BAT-009 to release-candidate and REQ-011/REQ-012 to Implemented.
## Design Gate
- Result: standard batch 유지.
- Reason: schema, service, MCP contract, dashboard UX, correction policy, baseline docs를 함께 바꾸므로 design/verification depth가 필요하다.
## Risks and mitigations
- Correction semantics drifting from read model: mitigate by explicit correction metadata, latest-valid-close selection tests, and read-after-close probes.
- Mutation contract drift vs dcy-007: mitigate by extending contract regression snapshots/tests for new tools.
- Dashboard operator flow accidentally mutating without preview clarity: mitigate by separate preview/close actions and source/is_closed labeling.
- Hard delete breaking historical traceability: mitigate by soft delete default plus tests asserting deactivated items do not erase prior snapshots.
@@ -1,48 +0,0 @@
# BAT-009 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-011
- AC-1: PASS — `manual_assets` create/update/deactivate write path and additive schema migration/correction columns implemented in `db.py`/`service.py`; full pytest PASS confirms existing/new DB initialization succeeds.
- AC-2: PASS — `preview_asset_snapshot_close` exists and targeted tests verify side-effect-free totals/warnings behavior.
- AC-3: PASS — `close_asset_snapshot` writes basis-date authority-source rows with close metadata and is covered by `tests/test_asset_snapshots.py`.
- AC-4: PASS — same-date re-close requires correction reasoning and appends correction rows via `snapshot_run_id` / `correction_of_run_id` / `is_correction`; targeted tests verify append-only behavior.
- AC-5: PASS — latest-run snapshot read selection plus shared valuation helpers keep read model/report consistency; targeted + full pytest PASS.
- AC-6: PASS — `docs/data-model.md` updated for write lifecycle, close/correction metadata, and latest-run read policy.
### REQ-012
- AC-1: PASS — MCP tools `create_manual_asset`, `update_manual_asset`, `deactivate_manual_asset` are exposed in `server.py`; `hermes mcp test jarca-ledger` discovered all 56 tools including BAT-009 additions.
- AC-2: PASS — `preview_asset_snapshot_close` MCP/service returns preview totals, warnings, `source='live_authority'`, `is_closed_snapshot=false`; targeted tests PASS.
- AC-3: PASS — `close_asset_snapshot` MCP/service returns close metadata and correction markers with `source='snapshot'`, `is_closed_snapshot=true`; targeted tests PASS.
- AC-4: PASS — `dashboard/app.py` adds `자산/마감` page with manual asset add/update/deactivate and snapshot preview/close UX; browser smoke rendered the page successfully.
- AC-5: PASS — browser/render + targeted tests confirm `source`/`is_closed_snapshot` aligned across preview/close/report flows and dashboard messaging.
- AC-6: PASS — `tests/test_contract_regression.py` and `tests/contract_snapshots/response_contract_v1_0.json` updated; `docs/interface-contract.md` updated; targeted/full pytest PASS.
## Requirement state decision
- REQ-011: Implemented.
- REQ-012: Implemented.
## Validation evidence
- `python3 -m py_compile jarca_ledger_mcp/*.py dashboard/app.py` → PASS
- `python3 -m pytest tests/test_asset_snapshots.py tests/test_contract_regression.py tests/test_dashboard_app.py -q` → PASS (`12 passed`)
- `python3 -m pytest -q` → PASS (`42 passed, 4 skipped`)
- `hermes mcp test jarca-ledger` → PASS (`Connected`, `Tools discovered: 56`)
- Browser smoke on Streamlit `자산/마감` page → PASS, JS errors 없음
## Remaining issues
### Hard blockers
- None.
### Non-blocking follow-up
- Automatic valuation feeds and scheduled month-end close remain explicitly out of scope for BAT-009.
@@ -1,50 +0,0 @@
# 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 유무 확인.
@@ -1,61 +0,0 @@
# 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이 필요하다.
@@ -1,37 +0,0 @@
# 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
@@ -1,34 +0,0 @@
# 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.
@@ -1,45 +0,0 @@
# 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,37 +0,0 @@
# BAT-011 Design
## Architecture summary
- Introduce dedicated write-oriented application modules under `jarca_ledger_mcp/application/` for accounts, transactions, budgets, and category rules/categories.
- Keep broad modules (`system_services.py`, `asset_account_services.py`, `transaction_report_services.py`, `categorization_services.py`) as compatibility aggregation layers for read/report/mixed responsibilities that are not yet in scope.
- Preserve `service.py` as a thin re-export facade and avoid MCP/Streamlit/dashboard call-site churn.
## Changed areas
- `jarca_ledger_mcp/application/accounts_write_services.py`
- `jarca_ledger_mcp/application/transactions_write_services.py`
- `jarca_ledger_mcp/application/budgets_write_services.py`
- `jarca_ledger_mcp/application/category_rules_write_services.py`
- Existing application modules that previously held these implementations
- `jarca_ledger_mcp/application/__init__.py`
- `jarca_ledger_mcp/service.py`
## Key decisions
- Move only mutation implementations in BAT-011; read/report/import/advanced workflow logic stays in place.
- Favor direct function relocation plus compatibility re-export over new abstraction layers to minimize contract risk.
- Keep shared helpers in `application/shared.py`; do not introduce storage-layer refactors in this batch.
## Edge cases
- `create_ledger_account` remains paired with `update_ledger_account` even though the old implementations lived in different modules.
- Category rule preview/apply remains out of BAT-011 scope if moving it would force read/workbench coupling; mutation extraction takes precedence.
- Any dashboard/MCP references must continue resolving through `service.py` without signature changes.
## Architecture Impact
- none
## Reference Doc Update Plan
- No baseline doc rewrite in BAT-011 unless the final module tree differs materially from the existing dcy-011/REQ-015 description.
@@ -1,51 +0,0 @@
# BAT-011 Implementation
## Plan summary
BAT-011 implements the first dcy-011 delivery slice by extracting transactional write paths into narrower application modules while preserving the top-level `service.py` facade, MCP tool contracts, and Streamlit/dashboard call signatures.
## Changed files
- `jarca_ledger_mcp/application/accounts_write_services.py`
- `jarca_ledger_mcp/application/transactions_write_services.py`
- `jarca_ledger_mcp/application/budgets_write_services.py`
- `jarca_ledger_mcp/application/category_rules_write_services.py`
- `jarca_ledger_mcp/application/__init__.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/categorization_services.py`
- `jarca_ledger_mcp/service.py`
- `docs/discovery/dcy-011_20260703_backend-refactor-phase4-write-import-workflow-adapter-narrowing.md`
- `docs/srs/index.md`
- `docs/srs/Non-Functional/req-015_transactional-write-service-split-compatibility.md`
- `docs/batches/index.md`
- `docs/batches/bat-011_20260703_transactional-write-service-split/index.md`
- `docs/batches/bat-011_20260703_transactional-write-service-split/planning.md`
- `docs/batches/bat-011_20260703_transactional-write-service-split/design.md`
- `docs/batches/bat-011_20260703_transactional-write-service-split/implementation.md`
- `docs/batches/bat-011_20260703_transactional-write-service-split/verification.md`
## Execution log
- 2026-07-03 07:29 KST: dcy-011에서 REQ-015를 생성하고 source Discovery 역참조/SRS index를 갱신했다.
- 2026-07-03 07:30 KST: REQ-015를 Approved로 전환하고 BAT-011 standard batch scaffold(index/planning/design/implementation/verification)를 생성했다.
- 2026-07-03 07:34 KST: `accounts_write_services.py`, `transactions_write_services.py`, `budgets_write_services.py`, `category_rules_write_services.py`를 추가하고 account/transaction/budget/category rule-category mutation 구현을 새 모듈로 이동했다.
- 2026-07-03 07:35 KST: 기존 broad modules(`system_services.py`, `asset_account_services.py`, `transaction_report_services.py`, `categorization_services.py`)를 compatibility re-export/delegation 레이어로 축소했다.
- 2026-07-03 07:35 KST: `service.py` proxy module set에 새 write modules를 추가해 helper monkeypatch/export propagation이 계속 동작하도록 정렬했다.
- 2026-07-03 07:36 KST: category create path에서 빠진 `infer_cashflow_kind` 정책을 `category_rules_write_services.py`에 보강해 category mutation 회귀를 복구했다.
- 2026-07-03 07:39 KST: targeted regression, full pytest, MCP discovery, service export provenance 검증이 모두 PASS하여 REQ-015를 Implemented로 승격했다.
## Validation
- `python3 -m py_compile jarca_ledger_mcp/application/*.py jarca_ledger_mcp/service.py` → PASS
- `pytest -q tests/test_service.py tests/test_category_rule_filters.py tests/test_ledger_categories.py tests/test_contract_regression.py` → PASS (`19 passed`)
- `pytest -q` → PASS (`42 passed, 4 skipped`)
- `hermes mcp test jarca-ledger` → PASS (`Connected`, `Tools discovered: 56`)
- `python3` provenance check → PASS (`service.create_ledger_account.__module__ == jarca_ledger_mcp.application.accounts_write_services`, transaction/budget/category mutation exports도 각각 새 write module을 가리킴)
## Remaining risks / follow-up notes
- `preview_categorization`, `apply_categorization_rules`, uncategorized workbench/read-side helper는 아직 `categorization_services.py`에 남아 있어 Phase 4 후속 또는 Phase 7 adapter narrowing에서 추가 분리가 가능하다.
- import preview/import/rollback 및 cross-transfer/reconciliation/advanced workflow 분리는 BAT-011 범위 밖이며 dcy-011 후속 REQ/BAT로 이어져야 한다.
- 이번 배치는 contract-preserving extraction이 목적이므로 data model semantics와 response envelope은 의도적으로 변경하지 않았다.
@@ -1,33 +0,0 @@
# BAT-011 Transactional write service split
- Profile: standard
- Status: release-candidate
- Included REQ: REQ-015
- Discovery: dcy-011
- Owner: 렛저장인
- Date (KST): 2026-07-03
## 목표
REQ-015에 따라 account / transaction / budget / category rule-category mutation 경로를 더 좁은 write-oriented application service로 분리한다. 기존 `service.py`, MCP adapter, Streamlit gateway, dashboard 호출부와 response contract는 유지한 채 Phase 4 첫 구현 슬라이스를 실제 코드와 검증 evidence로 마무리한다.
## 산출물
- `jarca_ledger_mcp/application/` write-oriented service modules
- 기존 broad application modules의 compatibility re-export / delegation 정리
- full pytest 및 contract-sensitive regression evidence
- BAT-011 planning/design/implementation/verification documents
## 범위 제한
- import preview/import/rollback split
- advanced workflow(cross-transfer/reconciliation/assets/workbench) 분리
- HTTP adapter 추가
- destructive migration
## 문서
- `planning.md`: Phase 4 첫 delivery plan, risks, validation gate
- `design.md`: write service boundary / delegation design
- `implementation.md`: changed files, execution log, validation commands
- `verification.md`: AC mapping, PASS/FAIL, REQ Implemented decision
@@ -1,32 +0,0 @@
# BAT-011 Planning
## Scope
- Implement REQ-015: transactional write path(account / transaction / budget / category rule-category mutation)를 더 좁은 write-oriented application module로 분리한다.
- Preserve top-level service facade, MCP adapter, Streamlit gateway, dashboard call signatures and response envelope contracts.
- Leave import/advanced workflow split for follow-up REQ/BAT under dcy-011.
## Dependencies
- dcy-011 confirmed Discovery and Approved REQ-015.
- BAT-010 application/adapters baseline.
- Existing pytest regression and contract-sensitive tests.
## Work plan
1. Create write-oriented application modules for accounts / transactions / budgets / category rules.
2. Move concrete mutation implementations into those modules and keep existing broad modules as compatibility delegation layers where needed.
3. Update `application/__init__.py` and `service.py` import surface to re-export the new modules without changing public API.
4. Run focused syntax + regression validation, then full pytest if focused checks remain green.
5. Update batch implementation/verification evidence and promote REQ/BAT state if ACs are satisfied.
## Design Gate
- Result: standard batch 유지.
- Reason: package boundary 변경, compatibility delegation, category/account/transaction write contract preservation, regression evidence 정리가 함께 필요하므로 planning/design/verification depth가 필요하다.
## Risks and mitigations
- Hidden import coupling after write extraction: mitigate by preserving re-export layers and running full pytest.
- Envelope drift on mutation responses: mitigate by preserving existing function signatures and contract-sensitive tests.
- Category rule/category mutation helpers may still share read-side helpers: mitigate by extracting only write-focused logic first and leaving broad read/report paths untouched in this batch.
@@ -1,43 +0,0 @@
# BAT-011 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-015
- AC-1: PASS — `jarca_ledger_mcp/application/` 아래에 `accounts_write_services.py`, `transactions_write_services.py`, `budgets_write_services.py`, `category_rules_write_services.py`가 생성됐고 account/transaction/budget/category rule-category mutation 구현이 그쪽으로 이동했다.
- AC-2: PASS — top-level `service.py` public API, MCP tools, Streamlit/dashboard call signatures and mutation envelope contracts are preserved. MCP discovery still reports 56 tools, and export provenance shows the write APIs now resolve to the new modules.
- AC-3: PASS — targeted regression (`tests/test_service.py`, `tests/test_category_rule_filters.py`, `tests/test_ledger_categories.py`, `tests/test_contract_regression.py`) PASS, plus full `pytest -q` PASS (`42 passed, 4 skipped`).
- AC-4: PASS — BAT-011 implementation/verification docs now record actual changed files, commands, and outcomes.
## Requirement state decision
- REQ-015: Implemented.
## Validation evidence
- `python3 -m py_compile jarca_ledger_mcp/application/*.py jarca_ledger_mcp/service.py` → PASS
- `pytest -q tests/test_service.py tests/test_category_rule_filters.py tests/test_ledger_categories.py tests/test_contract_regression.py` → PASS (`19 passed`)
- `pytest -q` → PASS (`42 passed, 4 skipped`)
- `hermes mcp test jarca-ledger` → PASS (`Connected`, `Tools discovered: 56`)
- Python provenance check on exported write APIs → PASS
- `create_ledger_account`, `update_ledger_account` → `accounts_write_services`
- `create/update/delete_ledger_transaction` → `transactions_write_services`
- `create_ledger_budget` → `budgets_write_services`
- `create/update/delete_category_rule`, `create/delete_ledger_category` → `category_rules_write_services`
## Remaining issues
### Hard blockers
- None.
### Non-blocking follow-up
- categorization preview/apply/workbench read-side extraction
- import pipeline split
- advanced finance workflow split
- narrower adapter surfaces under later dcy-011 batches
@@ -1,23 +0,0 @@
# 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
@@ -1,46 +0,0 @@
# 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 범위 밖이다.
@@ -1,21 +0,0 @@
# 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
@@ -1,28 +0,0 @@
# 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.
@@ -1,37 +0,0 @@
# 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
@@ -1,13 +0,0 @@
# 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
@@ -1,48 +0,0 @@
# 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.
@@ -1,21 +0,0 @@
# 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
@@ -1,28 +0,0 @@
# 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.
@@ -1,36 +0,0 @@
# 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
@@ -1,7 +0,0 @@
# 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.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

@@ -1,74 +0,0 @@
{
"success": true,
"base_url": "http://127.0.0.1:18501",
"output_dir": "/root/projects/jarca-ledger-mcp/docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358",
"fixture": {
"account_id": "acct_2e22ac8ac63a",
"transaction_ids": [
"tx_14dd02c2fe6c",
"tx_8a75d20fcd87",
"tx_88bdacc43404",
"tx_c0418db6d784",
"tx_7b21f4085a1d"
],
"db_path": "docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/fixture.sqlite3"
},
"chrome": "/usr/bin/google-chrome-stable",
"streamlit": ".venv/bin/streamlit",
"pages": [
{
"page": "요약",
"url": "http://127.0.0.1:18501/?page=%EC%9A%94%EC%95%BD",
"screenshot": "docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/overview.png",
"screenshot_bytes": 340145,
"snapshot": "docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/overview.dom.html",
"snapshot_bytes": 31902,
"devtools_port": 19222,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\n메뉴\n요약\n자산/마감\n거래내역\n확인필요 큐\n미분류\n분류 규칙\n카테고리\n계좌\nImport\n\n새로고침\n\nStop\nDeploy\n📊 요약\n가계부 운영 대시보드\n\n이번 달 실제 현금흐름, 자산 유동성, 운영 경고를 우선순위대로 확인합니다.\n\nschema v10\nKST 이번 달\nlast_balance 기준 자산\n\nDB: /root/projects/jarca-ledger-mcp/docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/fixture.sqlite3\n\n💎\n이번 달 수입/지출 현황\n\n기준: KST 현재 월 2026-07, transactions.transaction_date, ledger_categories.cashflow_kind 실제 현금흐름\n\n실제 수입\n\n0원\n\n실제 지출\n\n0원\n\n순"
},
{
"page": "분류 규칙",
"url": "http://127.0.0.1:18501/?page=%EB%B6%84%EB%A5%98%20%EA%B7%9C%EC%B9%99",
"screenshot": "docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/rules.png",
"screenshot_bytes": 366052,
"snapshot": "docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/rules.dom.html",
"snapshot_bytes": 165223,
"devtools_port": 19223,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\n메뉴\n요약\n자산/마감\n거래내역\n확인필요 큐\n미분류\n분류 규칙\n카테고리\n계좌\nImport\nStop\nDeploy\n⚙️ Rule Engine\n분류 규칙\n\n반복되는 사용처와 거래 패턴을 규칙으로 관리해 분류 자동화 품질을 높입니다.\n\n자동 분류\nPreview\nSeed/Update\nkeyboard_arrow_right\n\n🟢 환급 · merchant/contains → 수입 / 환급 · p10 · income\n\nkeyboard_arrow_right\n\n🟢 급여 · merchant/contains → 수입 / 급여 · p10 · income\n\nkeyboard_arrow_right\n\n🟢 이자 · merchant/contains → 수입 / 이자 · p10 · income\n\nkeyboard_arrow_right\n\n🟢 국민카드 · raw_summary/equals → 금융 / 카드대금 · p20 · expense\n\nkeyboard"
},
{
"page": "확인필요 큐",
"url": "http://127.0.0.1:18501/?page=%ED%99%95%EC%9D%B8%ED%95%84%EC%9A%94%20%ED%81%90",
"screenshot": "docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/transfer-review.png",
"screenshot_bytes": 303427,
"snapshot": "docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/transfer-review.dom.html",
"snapshot_bytes": 25158,
"devtools_port": 19224,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\n메뉴\n요약\n자산/마감\n거래내역\n확인필요 큐\n미분류\n분류 규칙\n카테고리\n계좌\nImport\n\n새로고침\n\nStop\nDeploy\n🔁 Transfer Review\nKB↔토스뱅크 확인필요 큐\n\n날짜·금액·상대 기준으로 계좌 간 이동 후보를 대조하고, 드라이런 후 안전하게 매칭합니다.\n\n드라이런 우선\n본인계좌이동\n수동 검토\n\n미리보기(드라이런)\n\n자동 매칭 실행\n\n📌\n확인필요 큐\n\n거래 ID: tx_7b21f4085a1d\n\n2026-06-29 · SYNTHETIC_TRANSFER · 120,000원"
},
{
"page": "Import",
"url": "http://127.0.0.1:18501/?page=Import",
"screenshot": "docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/import.png",
"screenshot_bytes": 298860,
"snapshot": "docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/import.dom.html",
"snapshot_bytes": 25118,
"devtools_port": 19225,
"inner_text_head": "💰 Jarca Ledger\n\n가계부 · 분류 · Import 운영 콘솔\n\n메뉴\n요약\n자산/마감\n거래내역\n확인필요 큐\n미분류\n분류 규칙\n카테고리\n계좌\nImport\nStop\nDeploy\n📥 Statement Import\nImport\n\nPDF/XLSX 거래내역을 먼저 Preview로 검증한 뒤 원장에 반영합니다.\n\nPreview 우선\n중복 skip\nImport 이력\n📈\n토스증권 거래내역 PDF 가져오기\n\n토스증권 거래내역서 PDF를 업로드하면 투자계좌 거래로 가져옵니다. 매수/매도/환전/입출금은 이체/투자이동, 배당/이자는 실제 수입으로 분류합니다.\n\n🏦\n토스뱅크 거래내역 PDF 가져오기\n\n토스뱅크 계좌 거래내역 PDF를 업로드하면 입출금/이체/카드결제를 가져옵니다. 타인 이체/출금은 이체/확인필요로 분류됩니다.\n\n🧾\nImport 이력"
}
],
"server_command": [
".venv/bin/streamlit",
"run",
"dashboard/app.py",
"--server.address",
"127.0.0.1",
"--server.port",
"18501",
"--server.headless",
"true",
"--browser.gatherUsageStats",
"false"
],
"server_log_tail": ""
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 KiB

@@ -1,43 +0,0 @@
# 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.
@@ -1,12 +0,0 @@
# 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을 완료한다.
@@ -1,12 +0,0 @@
# 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.
@@ -1,74 +0,0 @@
# BAT-014 Verification
## Verification summary
Status: PASS
All required code-path checks for BAT-014 passed, and local browser-level screenshot/DOM evidence was successfully captured against a synthetic fixture DB. No production ledger DB, real financial statement files, passwords, or raw financial payloads 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, adapter verification, and browser smoke 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
- `.venv/bin/python scripts/streamlit_browser_evidence.py` → PASS
- Output dir: `docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/`
- Artifacts: `overview.png`, `rules.png`, `transfer-review.png`, `import.png` plus matching `*.dom.html` and `manifest.json`
- Cleanup check: `search_files('chrome-profile-*')` under the run dir returned 0 results after the retry-cleanup fix
### AC-4. Baseline docs, discovery metadata, and BAT-local evidence tooling 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.
- `docs/runbooks/streamlit-browser-evidence.md` now points at the BAT-014 evidence root and includes `요약` in the default capture set.
- dcy-011 metadata and close-out notes updated to reference `REQ-015`~`REQ-018` / `BAT-011`~`BAT-014` completion.
## Browser evidence details
Evidence source: `docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/manifest.json`
### Captured pages
- `요약`
- Screenshot: `overview.png`
- DOM: `overview.dom.html`
- Evidence text included `📊 요약`, `가계부 운영 대시보드`, and the synthetic fixture DB path under the BAT-014 evidence directory.
- `분류 규칙`
- Screenshot: `rules.png`
- DOM: `rules.dom.html`
- Evidence text included `⚙️ Rule Engine`, `분류 규칙`, and seeded default categorization rules.
- `확인필요 큐`
- Screenshot: `transfer-review.png`
- DOM: `transfer-review.dom.html`
- Evidence text included `🔁 Transfer Review`, `KB↔토스뱅크 확인필요 큐`, and a synthetic transfer-review row for `2026-06-29` / `SYNTHETIC_TRANSFER` / `120,000원` / `이체` / `확인필요`.
- `Import`
- Screenshot: `import.png`
- DOM: `import.dom.html`
- Evidence text included `📥 Statement Import`, Toss Securities import copy, and Toss Bank import copy.
### Automation script close-out
- Script: `scripts/streamlit_browser_evidence.py`
- Behavior:
- Generates a synthetic fixture DB under the BAT-014 evidence run directory.
- Starts Streamlit against that fixture DB only.
- Uses local Chrome DevTools Protocol to capture screenshots and DOM snapshots.
- Writes `manifest.json` with page/url/path/byte-size evidence.
- Retries Chrome profile cleanup and leaves only the intended evidence artifacts in the final run directory.
## Safety boundary
- Synthetic/temp DBs only.
- No destructive migration.
- No production ledger DB mutation.
- No real statement files, passwords, or raw payloads in screenshots, DOM snapshots, or manifest output.

Some files were not shown because too many files have changed in this diff Show More