Add BAT-014 browser evidence artifacts
This commit is contained in:
+241
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
|
After Width: | Height: | Size: 292 KiB |
+74
@@ -0,0 +1,74 @@
|
|||||||
|
{
|
||||||
|
"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": ""
|
||||||
|
}
|
||||||
+241
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
|
After Width: | Height: | Size: 332 KiB |
+869
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
|
After Width: | Height: | Size: 358 KiB |
+241
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
|
After Width: | Height: | Size: 296 KiB |
+38
-7
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
Status: PASS
|
Status: PASS
|
||||||
|
|
||||||
All required code-path checks for BAT-014 passed. A manual local browser-evidence launch was attempted but blocked by the runtime’s consent guard for long-running local server startup, so the close-out evidence uses AppTest + full pytest + MCP discovery + structural call-site verification. No production ledger DB or real financial files were used.
|
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
|
## Acceptance criteria evidence
|
||||||
|
|
||||||
@@ -18,26 +18,57 @@ All required code-path checks for BAT-014 passed. A manual local browser-evidenc
|
|||||||
- `search_files(pattern='service\\.', path='dashboard', file_glob='app.py')` returned 0 matches after rewiring.
|
- `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.
|
- Dynamic hot-reload lookup now targets passed gateway modules (`categorization_gateway`, `transfers_gateway`) instead of a flat `service` binding.
|
||||||
|
|
||||||
### AC-3. Regression and adapter verification pass
|
### 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
|
- `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 tests/test_dashboard_app.py` → PASS (`....`)
|
||||||
- `pytest -q` → PASS (`........................ss...............ss...`)
|
- `pytest -q` → PASS (`........................ss...............ss...`)
|
||||||
- `hermes mcp test jarca-ledger` → PASS, 56 tools discovered
|
- `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 and discovery metadata reflect completion
|
### AC-4. Baseline docs, discovery metadata, and BAT-local evidence tooling reflect completion
|
||||||
- Evidence:
|
- Evidence:
|
||||||
- `docs/project-structure.md` updated with new owning services, parser seam, MCP contract helper, and Streamlit page/domain gateways.
|
- `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/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.
|
- dcy-011 metadata and close-out notes updated to reference `REQ-015`~`REQ-018` / `BAT-011`~`BAT-014` completion.
|
||||||
|
|
||||||
## Browser evidence note
|
## Browser evidence details
|
||||||
|
|
||||||
- Attempted: synthetic local dashboard browser/HTTP smoke.
|
Evidence source: `docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-20260703-100358/manifest.json`
|
||||||
- Result: blocked by terminal consent guard for long-running local server startup in this session.
|
|
||||||
- Impact: none on code correctness regression; AppTest remained green and no UI functional regression was detected in test coverage.
|
### 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
|
## Safety boundary
|
||||||
|
|
||||||
- Synthetic/temp DBs only.
|
- Synthetic/temp DBs only.
|
||||||
- No destructive migration.
|
- No destructive migration.
|
||||||
- No production ledger DB mutation.
|
- No production ledger DB mutation.
|
||||||
|
- No real statement files, passwords, or raw payloads in screenshots, DOM snapshots, or manifest output.
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ cd /root/projects/jarca-ledger-mcp
|
|||||||
기본 산출물 위치:
|
기본 산출물 위치:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-YYYYMMDD-HHMMSS/
|
docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence/run-YYYYMMDD-HHMMSS/
|
||||||
├── fixture.sqlite3
|
├── fixture.sqlite3
|
||||||
├── manifest.json
|
├── manifest.json
|
||||||
|
├── overview.png
|
||||||
|
├── overview.dom.html
|
||||||
├── rules.png
|
├── rules.png
|
||||||
├── rules.dom.html
|
├── rules.dom.html
|
||||||
├── transfer-review.png
|
├── transfer-review.png
|
||||||
@@ -45,6 +47,7 @@ docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence/run-YYYYMM
|
|||||||
|
|
||||||
기본 대상:
|
기본 대상:
|
||||||
|
|
||||||
|
- `요약`
|
||||||
- `분류 규칙`
|
- `분류 규칙`
|
||||||
- `확인필요 큐`
|
- `확인필요 큐`
|
||||||
- `Import`
|
- `Import`
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ import websockets
|
|||||||
from jarca_ledger_mcp import service
|
from jarca_ledger_mcp import service
|
||||||
from jarca_ledger_mcp.db import init_db
|
from jarca_ledger_mcp.db import init_db
|
||||||
|
|
||||||
DEFAULT_PAGES = ["분류 규칙", "확인필요 큐", "Import"]
|
DEFAULT_PAGES = ["요약", "분류 규칙", "확인필요 큐", "Import"]
|
||||||
DEFAULT_CHROME = "/usr/bin/google-chrome-stable"
|
DEFAULT_CHROME = "/usr/bin/google-chrome-stable"
|
||||||
DEFAULT_STREAMLIT = Path(".venv/bin/streamlit")
|
DEFAULT_STREAMLIT = Path(".venv/bin/streamlit")
|
||||||
DEFAULT_OUTPUT_ROOT = Path("docs/batches/bat-004_20260629_browser-streamlit-e2e-evidence/evidence")
|
DEFAULT_OUTPUT_ROOT = Path("docs/batches/bat-014_20260703_adapter-surface-narrowing-baseline-refresh/evidence")
|
||||||
|
|
||||||
|
|
||||||
def parse_args() -> argparse.Namespace:
|
def parse_args() -> argparse.Namespace:
|
||||||
@@ -181,6 +181,16 @@ def wait_for_devtools(port: int, timeout_seconds: int = 15) -> str:
|
|||||||
raise SystemExit(f"Chrome DevTools endpoint did not become ready on port {port}: {last_error}")
|
raise SystemExit(f"Chrome DevTools endpoint did not become ready on port {port}: {last_error}")
|
||||||
|
|
||||||
|
|
||||||
|
def remove_tree_with_retries(path: Path, attempts: int = 5, delay_seconds: float = 0.5) -> None:
|
||||||
|
for attempt in range(1, attempts + 1):
|
||||||
|
shutil.rmtree(path, ignore_errors=True)
|
||||||
|
if not path.exists():
|
||||||
|
return
|
||||||
|
time.sleep(delay_seconds * attempt)
|
||||||
|
if path.exists():
|
||||||
|
raise SystemExit(f"temporary Chrome profile cleanup failed: {path}")
|
||||||
|
|
||||||
|
|
||||||
class CdpClient:
|
class CdpClient:
|
||||||
def __init__(self, ws: websockets.ClientConnection) -> None:
|
def __init__(self, ws: websockets.ClientConnection) -> None:
|
||||||
self.ws = ws
|
self.ws = ws
|
||||||
@@ -265,7 +275,8 @@ def capture_page(chrome: str, base_url: str, page: str, output_dir: Path, devtoo
|
|||||||
chrome_proc.wait(timeout=8)
|
chrome_proc.wait(timeout=8)
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
chrome_proc.kill()
|
chrome_proc.kill()
|
||||||
shutil.rmtree(profile_dir, ignore_errors=True)
|
chrome_proc.wait(timeout=5)
|
||||||
|
remove_tree_with_retries(profile_dir)
|
||||||
|
|
||||||
if not screenshot.exists() or screenshot.stat().st_size <= 0:
|
if not screenshot.exists() or screenshot.stat().st_size <= 0:
|
||||||
raise SystemExit(f"Screenshot was not created for {page}: {screenshot}")
|
raise SystemExit(f"Screenshot was not created for {page}: {screenshot}")
|
||||||
|
|||||||
Reference in New Issue
Block a user