# 給 agent 的守則（events / 城市活動蒐集器）

先讀完 `README.md`（設計與操作細節，兼作本專案的 DESIGN）與 `STATUS.md`（現況），再動手。

## 鐵律：改了網頁就要當場發佈到兩邊，並驗證

報表有兩個發佈管道：VPN 內（Caddy sites 目錄）與公網（Cloudflare Pages）。
**只要動到 `src/<pkg>/report.py`、樣式、JS、或 `report/` 下任何東西，
同一次工作內就必須跑：**

```bash
deploy/publish.sh
```

它會重新產生 `report/`、複製到 Caddy 目錄、上傳 Cloudflare Pages，
然後把兩邊的 `index.html` 抓回來跟本機比對，不一樣就失敗。
看到最後一行 `== 兩邊都已更新` 才算做完；回報時要把這行的結果講出來。

- **不可以**只發其中一邊、也不可以說「等下次自動 pipeline 會更新」——使用者要的是當場生效。
- 不用重新產生（例如只是重推現有 `report/`）用 `deploy/publish.sh --no-build`。
- 憑證、VPN 網址、Pages 的細節在 `README.md`「部署與發佈」一節。

## Git 工作流程

這個 repo 只有一位維護者，沒有 code review，也沒有 CI gate。**永遠直接在 `master` 上工作並提交。**
不要開 feature branch、不要開 PR、不要用 worktree——`master` 是唯一的開發線，分支只會讓變更卡在旁邊沒被部署。

- 提交前跑 `PYTHONPATH=src python3 -m unittest discover -s tests -p 'test_*.py'`，全綠才提交。
  注意環境沒有 pytest，`python3 -m pytest` 會失敗，用 unittest。
- 一個邏輯變更一個 commit，訊息用英文祈使句，與既有歷史一致。
- 提交前更新 `README.md` 頂部的「最後更新」日期與部署基準 commit。
- 預設不 push；要推到 `origin` 時由使用者明講。
- **這是公開 repo**：任何新檔、commit 都會隨下次 push 公開，不放個資與秘密（憑證在 `~/.config/`）。

## 抓站門檻：個人用

這個專案只是個人用，每天抓幾頁不算真正的爬蟲。站方 `robots.txt` 本身讀不到（403／404）但內容頁正常時，不要直接判「不能用」：把事實講清楚（沒有規則 vs. 明確 `Disallow`）、建議 gentle profile（5 秒間隔、每日 ≤ 8 次、只抓清單頁）讓使用者決定。明確寫 `Disallow` 或 `ClaudeBot Disallow` 的站仍然不碰。robots 核對的事實記錄在 `config/gentle_sources.md`。

## 文件維護

**專案相關的發現一律寫進 repo（設計與操作細節進 `README.md`、現況進 `STATUS.md`；跨專案的基礎設施寫進 `~/projects/INFRA.md`），不得只留在 AI 助手的 memory 或對話裡。** 假設下一個接手的是另一個 AI 或另一個人：他只會讀 repo 裡的檔案。判斷標準是「這件事如果忘了，會不會重踩一次」——會的就寫，包含失敗的嘗試與原因。

- 新增 scraper、修改 Event/Session/schema、改 stage 邊界、CLI 或任何不變量時，必須同步更新 `README.md` 及 `tests/test_readme.py`。提交前更新 README 頂部日期與最後 commit；如果目錄仍非 Git repository，明寫 N/A，不得捏造 hash。
- 做完一段就更新 `STATUS.md`；它照 `~/projects/DESIGN.md` §4 的規則維護（最近做完的事只留 5 條，結案的整段搬 `STATUS-ARCHIVE.md`）。
- 失敗／異常通知推共用的告警 topic、標題帶 project 名；慣例見 `~/projects/INFRA.md`。
