# Session learnings — 2925 account pool + Luban SMS + reporting guardrails (2026-05-11) ## 2925 provider decision BOSS decided to abandon POP3/SMTP/IMAP forwarding from 2925 to ClawEmail. Use 2925 Webmail directly with a local account pool. Hard invariant: ```text selected account: chickliu2021@2925.com allowed alias: chickliu2021xxxxxx@2925.com reader mailbox: chickliu2021@2925.com ``` Never generate an alias from one account local-part and read codes from another account. Before polling, verify both: ```text alias.localPart startsWith selectedAccount.localPart displayedMailboxEmail == selectedAccount.email ``` If the displayed mailbox mismatches, clear cookies for `2925.com`, `www.2925.com`, `mail2.xiyouji.com` and force-login the selected account. BOSS-provided pool is stored locally at: ```text ~/.hermes/secrets/mail2925_accounts.txt ``` Mode must be `0600`; passwords must never be printed or committed. Helper: ```bash python3 scripts/mail2925_pool.py selftest python3 scripts/mail2925_pool.py pick --dry-run # preview without changing rotation state python3 scripts/mail2925_pool.py pick # allocate and update lastUsedAt python3 scripts/mail2925_pool.py list ``` Use `--dry-run` for probes/reviews so verification does not pollute production rotation state. Real registration allocation should use plain `pick` and persist the selected account + generated alias together for the rest of that OpenAI attempt. Boundary: the helper only guarantees alias/account binding at generation time. The Webmail automation must still gate on `displayedMailboxEmail == selectedAccount.email` before clearing inbox or polling mail; otherwise a stale browser session could still read the wrong mailbox. ## Luban SMS provider Luban API docs: `https://lubansms.com/api_docs/`. Requests without a browser-like `User-Agent` can return HTTP 403. The helper `scripts/luban_sms.py` must send a Chrome UA. Core provider mapping: ```text balance -> /getBalance service list -> /List buy -> /getNumber poll -> /getSms reject/cancel -> /setStatus?status=reject success finish -> local no-op ``` The API key is stored in `~/.hermes/env/codex_oauth_onboarding.env` as `LUBAN_SMS_API_KEY`; never print it. ## Reporting guardrail A tool-writing step once ended with an empty assistant response, and BOSS explicitly asked to process tool results and continue. For this skill class, after tool calls always return a visible checkpoint: what changed, what was verified, and any remaining next action. Do not leave BOSS with an empty result after tools.