# Runbook

1. Build or refresh the JSON harness with `npm run prepare-json`.
2. Run strict validation gates before packaging.
3. Generate canonical artifacts through the builder scripts only.
4. Render reports from canonical data only.
5. Package upload artifacts only after the full gate passes or the output is explicitly audit-only.
6. Treat work as complete only when YAML, code, data artifacts, and validation evidence all exist together.
7. For calibration maintenance, run `npm run ops:calibration-backlog` or the Gitea schedule in `.gitea/workflows/calibration_backlog.yml`.
8. Promote a threshold to `PROVISIONAL` only when there is a recorded sample note and an explicit change note in `Temp/calibration_change_ledger_v4.json`.
9. Promote a threshold to `CALIBRATED` only when `sample_n >= 30`, a backtest note exists, and the validator still reports `overclaimed_count == 0`.
10. For human review, open `Temp/calibration_review_report_v1.md` after each backlog build.
11. For approval signoff, open `Temp/calibration_approval_list_v1.md` and approve only `source=PROVISIONAL` rows unless a new provisional review is explicitly requested.
12. For spreadsheet-like edits of `settings` and `account_snapshot`, run `npm run ops:snapshot-web` and validate with `npm run ops:snapshot-web-validate`.
13. Treat the snapshot admin web UI as the canonical edit surface for SQLite-backed manual maintenance; export JSON only when CI or downstream tooling needs a file artifact.
14. Keep `settings` and `account_snapshot` in the same workspace SQLite DB. Do not split them into separate files per sheet; use a separate SQLite DB only for the KIS collection pipeline.
15. Use the `KIS Collection` panel in snapshot admin to inspect the latest SQLite collection run, report status, source counts, and recent errors before you touch the editor.
16. Use the collection filter when you need to narrow runs, snapshots, or errors by ticker/source/status.
17. Use the change log filter when you need to audit a specific domain, action, or target reference.
18. Use `/collection` when you want the collection-only dashboard with raw JSON download.
19. Use `Export approval packet` in the snapshot admin UI to write `Temp/snapshot_admin_approval_packet_v1.json` and `Temp/snapshot_admin_approval_packet_v1.md` for review handoff.
20. For Synology external access, follow `docs/SYNOLOGY_SNAPSHOT_ADMIN_POC.md` and `tools/run_snapshot_admin_synology.sh`: keep the Python service on `127.0.0.1`, expose only the DSM reverse proxy `HTTPS` endpoint, and require the built-in Basic Auth gate.
21. Short balance ratio (`short_balance_ratio`) has no automatable path — confirmed 2026-06-22 by live-testing `pykrx.stock.get_shorting_balance()` (already used elsewhere in this repo for EOD prices), which returns `HTTP 400 LOGOUT` even with a properly bootstrapped session. This KRX "standard report" endpoint family requires actual KRX member login (`KRX_ID`/`KRX_PW`), unlike the basic OHLCV endpoints. Adding KRX login credentials is a new credential-management policy decision (same category as governance/rules/06-07) that requires explicit user approval — do not add it unilaterally. Until then, download the KRX 공매도종합포털 CSV weekly (every Monday before market open) and feed it via `--short-csv` to `build_qualitative_sell_inputs_v1.py`.
22. ETF NAV/iNAV/괴리율/추적오차/AUM has no automatable path either — same 2026-06-22 test confirmed `pykrx.stock.get_etf_price_deviation()`/`get_etf_tracking_error()` also return `HTTP 400 LOGOUT` (same KRX member-login gate as item 21). See `spec/16_data_gaps_roadmap.yaml` S4/S5 `automation_attempt_2026_06_22` for the full reproduction. Until a KRX login policy decision is made, keep feeding `etf_nav_manual` via `tools/import_etf_nav_manual.py` from manually downloaded KRX/KIND/운용사 CSV exports.
