- cafe.py: room 2 now invites the lowest-affection candidate instead of highest (room 1 unchanged), plus OCR'd invited-student name logging - exit_game.py: alert (AP_ALERT: log tag, picked up by ba_cron_run.sh's Discord alerting) if AP is still unspent above threshold when the game closes - login.py: re-check window_exists() after the stabilization wait to catch a startup window-flicker race that could crash a run - config.py/mapping.md: supporting constants and reference-mapping updates Also rewrites plan.md: retires the phase-by-phase changelog (now fully superseded by CLAUDE.md's own documentation) down to forward-looking backlog items, and adds a performance-improvement plan from a cron-log time analysis (lesson.py's per-cell screenshot redundancy, event_sweep's multi-call design). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
8.7 KiB
ba-auto-daily implementation plan
Personal Blue Archive JP daily-automation project. CLAUDE.md is the authoritative, actively-maintained reference for architecture, deployment, conventions, and the incident history behind current design decisions — read it first. This file is intentionally scoped to forward-looking work only: the not-yet-implemented backlog and active improvement plans. It no longer carries a phase-by-phase changelog; that history (30+ phases of live-testing retrospectives) has been retired now that every feature it covered has shipped and CLAUDE.md's "Existing features" section carries the load-bearing lessons from it.
The reference implementation lives at ~/repo/baas-reference/ (read-only — study and adapt, never edit). See ba_auto/reference_notes/mapping.md for the current, maintained local-feature → reference-module mapping table.
Currently implemented (for context, not a todo list)
login, mailbox, cafe, stamina, gem_shop, circle, battle_pass, story_sweep/story_sweep_force, story_sweep_hard/story_sweep_hard_force, event_sweep, shop_common, shop_tactical, lesson, arena, bounty, scrimmage, exit_game — see ba_daily.py's TASKS dict for the exact CLI surface and CLAUDE.md's "Existing features" section for behavior/known gaps.
Backlog — not yet implemented
Commissions (Base Defense + Item Retrieval)
Reference: ~/repo/baas-reference/module/clear_special_task_power.py
Local target: ba_auto/tasks/commission.py
Two sub-dungeons. OCR: port the reference's approach if it uses OCR here — do not default to a fixed-target workaround just to avoid OCR (see CLAUDE.md's OCR policy).
Crafting
Reference: ~/repo/baas-reference/module/create.py
Local target: ba_auto/tasks/crafting.py
Very complex — material selection, priority lists, rarity tiers, stepper/quantity UI, filtering/sorting, OCR-like decision points. Do not start until there's a concrete need; this is the most complex remaining reference module.
Momo Talk
Reference: ~/repo/baas-reference/module/momo_talk.py
Local target: ba_auto/tasks/momo_talk.py
Runs on a different cadence from daily reset, which is why it's still worth doing despite being low-value. Likely no OCR — mostly state scanning and click flow.
Main story push (new-stage clearing, not sweeping)
Reference: ~/repo/baas-reference/module/main_story.py, ~/repo/baas-reference/module/explore_tasks/explore_task.py
Distinct from story_sweep/story_sweep_hard (which only re-sweep already-cleared stages). Low priority — full grid-mode support needs a lot of per-stage scripting; a simple auto-fight-only mode could be a smaller first cut. No reusable auto-fight primitive exists yet — arena.py implements its battle-commit/result-detection inline rather than as a shared module, so this would either need extracting that or building fresh.
Group Story / Mini Story
Reference: ~/repo/baas-reference/module/group_story.py, ~/repo/baas-reference/module/mini_story.py
Convenience only, low priority.
Event content beyond the AP sweep panel
event_sweep.py already covers the sweep panel for a currently-running event (see CLAUDE.md). Still not built: explore_activity_story/explore_activity_mission/explore_activity_challenge (walking the event's map / fighting stages manually — only needed for a stage that hasn't been SSS-cleared yet) and exchange_reward (the reward-exchange shop). Event-specific content expires, so any calibration work here (stage-count, row positions) is only valid for whichever event is running at the time.
Daily Free Power
Reference: ~/repo/baas-reference/module/collect_daily_free_power.py
Deliberately deferred, not merely unstarted — its entry point is a real-money purchase menu, and automating it needs explicit user confirmation before any implementation attempt.
Skip list
| Feature | Why skip |
|---|---|
| Total Assault / Raid | Low value and risky to automate. Reference support may be limited/stubbed. |
| Joint Firing Drill | Not worth prioritizing for JP if reference has server-specific limitations. |
| De-clothes localization toggle | CN-only / irrelevant. |
| Restart / refresh-uiautomator2 | Android/ADB backend maintenance, not applicable to PC/Steam/Proton. |
| Auto-unfriend | Risky, low value, destructive. |
| Daily minigame dispatcher | Event-specific and unstable. Handle ad hoc only. |
Performance improvement plan (opened 2026-08-14)
Prompted by a request to review real cron run logs (scratchpad/ba_logs/{daily,q4h}.log, pulled from nik-gpu, covering 3 q4h runs + 2 daily runs on 2026-08-14) for where automation time actually goes and what's worth speeding up. Timestamps come from the per-line logging added in the "timestamped log output" work (see git history / CLAUDE.md's log-format notes).
Measured totals
| Run | Total | Notes |
|---|---|---|
| q4h #1 (10:00) | 9m56s | |
| q4h #2 (13:00) | 8m45s | |
| q4h #3 (17:00) | 9m13s | |
| daily #1 (03:30) | 15m32s | |
| daily #2 (04:30) | 27m20s | full run, 7 lesson tickets spent |
Finding 1 (top priority, not yet implemented): lesson.py re-screenshots per cell instead of per region
In the 27m20s daily run, lesson alone took 9m50s (36% of the run), and ~7 minutes of that is the "scanning all regions" phase — 12 regions × ~30-38s each — that runs before any ticket is spent, just to build the priority queue.
Root cause, confirmed by reading the code: _scan_open_grid_cells (ba_auto/tasks/lesson.py:196) loops 3 rows × 3 cols × 3 slots = 27 cells per region, and _read_slot_affection (lesson.py:185) calls both detector.region_contains_color (checkmark check) and, if not done, detector.read_int_on_heart_badge (OCR). Both independently call driver.read_screenshot(), and read_screenshot() fires a brand-new scrot capture every call (ba_auto/driver.py:97-127) — there's no reuse of a prior frame. That means a single region scan can trigger up to ~50 fresh scrot processes against a screen that hasn't changed at all between them (no clicks happen mid-scan, per _scan_all_regions's own docstring: "a pure read, spends no tickets").
Proposed fix: take one screenshot per region (or even once for the whole scan pass, if nothing changes on-screen until a click happens), decode it once, and pass the decoded image into the per-cell checkmark/OCR reads instead of each one re-capturing. This is a pure efficiency fix — the detection logic itself (color masking thresholds, heart-badge OCR contamination handling) doesn't change at all, so it doesn't touch anything CLAUDE.md's OCR policy cares about. Expected to cut the scan phase from ~7 minutes to well under a minute.
Scope note: _run_queue's actual ticket-spending clicks (lesson.py:306) happen between scans, so only the scan phase's screenshots are provably safe to batch this way — anything read after a click still needs a fresh capture.
Finding 2 (secondary, informational — do not touch without care): event_sweep is called 2-4x per run by design
ba_daily.py's daily preset calls event_sweep four times, q4h twice (ba_daily.py:132-144) — deliberately, per the preset's own comment, "to re-check a rotating target" as AP regenerates from circle/gem_shop/battle_pass claims during the run. Each call that doesn't short-circuit on insufficient AP costs 56s-153s in the logs, mostly navigation to the event badge/page. Total event_sweep cost across a run's multiple calls ranged from ~112s (2 skips + 2 clean 56s sweeps) to ~430s (3 calls, one hitting the slow "wrong page" retry path) in the sampled runs.
This is not recommended as a fix target right now: the retry/settle budget the "wrong page" path uses (badge-carousel navigation, cold-start OCR settle time) was tuned across many rounds of real live-testing failures before it reached its current reliability — shrinking it risks reintroducing missed/silently-failed sweeps, which is a strictly worse outcome than a slow-but-correct run. If run time here ever needs to come down, the safer lever is reducing how many times event_sweep is invoked per run (e.g. consolidating to fewer, better-timed calls once AP-granting tasks have run) rather than shrinking any per-call retry/wait constant.
Other observations (not action items)
cafe's pat-loop panning cost (~4-5 min/run) is inherent to the sparkle-hunt approach and matches reference behavior — not a target.shop_common's full-grid OCR name scan costs ~100-120s/run when most/all configured items are sold out — inherent to the OCR-based item-identification fix from the sold-out-reordering incident (seeCLAUDE.md's Common Shop notes); not a target without changing correctness guarantees.