chore(jarca-ledger): finalize approved batch docs, dashboard, and CI smoke updates

This commit is contained in:
Jarca
2026-06-30 16:06:47 +09:00
parent 67d8d4871b
commit 4929e52189
75 changed files with 8367 additions and 252 deletions
@@ -0,0 +1,28 @@
# 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는 사용자의 명시 승인 없이 실행하지 않는다.
@@ -0,0 +1,25 @@
# 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는 포함하지 않는다.
@@ -0,0 +1,35 @@
# 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.

After

Width:  |  Height:  |  Size: 290 KiB

@@ -0,0 +1,62 @@
{
"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.

After

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

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

After

Width:  |  Height:  |  Size: 291 KiB

@@ -0,0 +1,62 @@
{
"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.

After

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

@@ -0,0 +1,44 @@
{
"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.

After

Width:  |  Height:  |  Size: 294 KiB

@@ -0,0 +1,33 @@
# 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 범위가 아니며, 로컬 재현 절차만 제공한다.
@@ -0,0 +1,24 @@
# 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 신규 화면 기능 개발은 포함하지 않는다.
@@ -0,0 +1,31 @@
# 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`를 사용한다.
@@ -0,0 +1,43 @@
# 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.
@@ -0,0 +1,44 @@
{
"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": ""
}
@@ -0,0 +1,44 @@
{
"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": ""
}
@@ -0,0 +1,44 @@
{
"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": ""
}
@@ -0,0 +1,37 @@
# 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` 기본값으로 안전하게 채워진다.
@@ -0,0 +1,25 @@
# 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 범위는 포함하지 않는다.
@@ -0,0 +1,30 @@
# 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
@@ -0,0 +1,44 @@
# 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.
@@ -0,0 +1,64 @@
# 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.
@@ -0,0 +1,106 @@
# 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.
@@ -0,0 +1,32 @@
# 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 기록
@@ -0,0 +1,41 @@
# 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 이름을 안정화하고 문서에 후속 운영 설정으로 기록한다.
@@ -0,0 +1,154 @@
# 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.
+4
View File
@@ -10,3 +10,7 @@
| --- | --- | --- | --- | --- | --- |
| BAT-001 | batch-lite | release-candidate | REQ-001 | dcy-001 | [bat-001_20260626_category-rule-ops](bat-001_20260626_category-rule-ops/) |
| BAT-002 | standard | release-candidate | REQ-002 | dcy-002 | [bat-002_20260627_operational-safety-backup-restore-validation-db](bat-002_20260627_operational-safety-backup-restore-validation-db/) |
| BAT-003 | batch-lite | release-candidate | REQ-003 | dcy-003 | [bat-003_20260629_statement-unavailable-reconciliation](bat-003_20260629_statement-unavailable-reconciliation/) |
| BAT-004 | batch-lite | release-candidate | REQ-004 | dcy-004 | [bat-004_20260629_browser-streamlit-e2e-evidence](bat-004_20260629_browser-streamlit-e2e-evidence/) |
| BAT-005 | standard | release-candidate | REQ-005 | dcy-005 | [bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow](bat-005_20260629_dashboard-operations-hub-liquidity-monthly-cashflow/) |
| BAT-006 | standard | release-candidate | REQ-006 | dcy-006 | [bat-006_20260630_pytest-apptest-smoke-ci-automation](bat-006_20260630_pytest-apptest-smoke-ci-automation/) |