feat(deployment): simplify runtime paths to run directly from the git checkout

This commit is contained in:
Nik Afiq 2026-07-18 22:04:17 +09:00
parent 976f0f7241
commit b8ac8db01e
6 changed files with 86 additions and 58 deletions

View File

@ -188,25 +188,15 @@ There is no reliable local execution path on macOS. Anything that interacts with
During iteration, files are pushed from `nik-macbookair` to `nik-gpu`. During iteration, files are pushed from `nik-macbookair` to `nik-gpu`.
Typical paths on `nik-gpu`: **The runtime runs directly out of the git checkout at `~/repo/ba-auto-daily/` on nik-gpu.** (Changed 2026-07-18 -- see below for the old model this replaced.) There is no separate copy of the code anywhere else. Typical paths on `nik-gpu`:
```text ```text
~/ba_dailies.sh ~/repo/ba-auto-daily/ # the checkout -- ba_dailies.sh, ba_daily.py, ba_auto/, assets/ all live here and run in place
~/ba_daily.py ~/.venvs/ba-auto-daily/ # Python venv -- genuinely host-level, not repo content
~/ba_auto/ ~/ba_logs/ # cron run logs + the cron lock file -- genuinely runtime state, not repo content
~/ba_assets/
~/.venvs/ba-auto-daily/
``` ```
The current setup may still contain older paths such as: `ba_dailies.sh`, `ba_cron_run.sh`, and `completions/ba_dailies.bash` all resolve their own directory via `BASH_SOURCE`/`dirname` rather than assuming a fixed install path -- they work correctly wherever the checkout lives, so nothing needs to be copied out of it. `ba_auto/config.py`'s `ASSET_DIR`/`SCRATCHPAD_DIR` are likewise resolved relative to the checkout (`PROJECT_ROOT`, two levels up from `config.py`), not a fixed path outside it.
```text
~/ba_scripts/detect_and_click.py
```
When refactoring, prefer consolidating Python code into `ba_auto/`.
`setup.sh` should bootstrap or update the runtime layout on `nik-gpu`.
For a fresh checkout on `nik-gpu`, run from the repo root: For a fresh checkout on `nik-gpu`, run from the repo root:
@ -214,6 +204,8 @@ For a fresh checkout on `nik-gpu`, run from the repo root:
./setup.sh ./setup.sh
``` ```
`setup.sh` only installs the venv and host-level tab-completion now -- it does NOT copy any project files anywhere. Re-running it after a `rsync`/`git pull` is still fine (idempotent, also re-checks host tools/venv), but no longer strictly necessary for code changes to take effect, since there's nothing left to propagate -- the checkout IS the runtime.
After initial setup, individual changes may be pushed with `scp` or `rsync`. After initial setup, individual changes may be pushed with `scp` or `rsync`.
Prefer syncing the project from the repository root: Prefer syncing the project from the repository root:
@ -232,19 +224,19 @@ rsync -av \
Do not sync Claude Code internal temporary folders. Do not sync Claude Code internal temporary folders.
**The rsync target and the runtime paths are two different locations that can drift.** `rsync` above only updates the git checkout at `~/repo/ba-auto-daily/` on nik-gpu -- it does NOT touch `~/ba_dailies.sh`/`~/ba_daily.py`/`~/ba_auto/`, the actual fixed paths cron (see below) and any manually-run `~/ba_dailies.sh` invocation use. After rsyncing code changes, re-run `./setup.sh` from within `~/repo/ba-auto-daily/` on nik-gpu to propagate them to the runtime paths (it's idempotent -- safe to re-run any time, also re-checks host tools/venv/assets). Confirmed live (2026-07-16): the two locations had drifted (runtime paths were missing a same-day `ba_daily.py` edit) before this was caught and fixed by re-running `setup.sh`. **Older model, replaced 2026-07-18:** this project used to copy code out to fixed paths (`~/ba_dailies.sh`, `~/ba_daily.py`, `~/ba_auto/`, `~/ba_assets/`, `~/ba_cron_run.sh`, `~/.ba_dailies_completion.bash`) via `setup.sh`, separate from the `~/repo/ba-auto-daily/` checkout `rsync` updates -- meaning a code change could be rsynced to the checkout but never reach the copies cron/manual runs actually used, unless `setup.sh` was re-run afterward. This bit for real, twice: once on 2026-07-16 (a same-day `ba_daily.py` edit missing from the runtime paths, caught and fixed by re-running `setup.sh`), and again on 2026-07-18 (the newly-added `exit_game` task/preset entries were completely absent from a real `q4h` cron run -- confirmed via the run's own log, which dispatched `login`/`cafe`/`mailbox`/`stamina`/`event_sweep` then stopped, no `exit_game` line at all -- root-caused to the exact same drift). Per explicit user request ("keep the home directory clean"), the copy step was removed entirely rather than just re-synced again, closing off this whole class of bug instead of continuing to hit it. If you ever see `~/ba_dailies.sh`/`~/ba_daily.py`/`~/ba_auto/`/`~/ba_assets/` existing again on nik-gpu outside the checkout, that's stale leftover from this old model, not the current architecture -- don't assume anything reads from them.
### Scheduled runs (cron) ### Scheduled runs (cron)
As of 2026-07-16, `ba_dailies.sh` presets run unattended on a schedule via cron on nik-gpu, not just via manual/CLI invocation. `crontab -l` on nik-gpu is the source of truth; as installed: As of 2026-07-16, `ba_dailies.sh` presets run unattended on a schedule via cron on nik-gpu, not just via manual/CLI invocation. `crontab -l` on nik-gpu is the source of truth; as installed:
```text ```text
30 3 * * * /home/nik/ba_cron_run.sh daily 30 3 * * * /home/nik/repo/ba-auto-daily/ba_cron_run.sh daily
30 4 * * * /home/nik/ba_cron_run.sh daily 30 4 * * * /home/nik/repo/ba-auto-daily/ba_cron_run.sh daily
0 1,5,9,13,17,21 * * * /home/nik/ba_cron_run.sh q4h 0 1,5,9,13,17,21 * * * /home/nik/repo/ba-auto-daily/ba_cron_run.sh q4h
``` ```
Times are nik-gpu's local system time (`Asia/Tokyo`/JST). `ba_cron_run.sh` (repo root, deployed to `~/ba_cron_run.sh`) wraps `~/ba_dailies.sh <preset>` in a shared, non-blocking `flock` (`~/ba_logs/ba_dailies.lock`) so overlapping fire times can never launch concurrent `xdotool`/`scrot` sessions against the same game window, and logs each run to its own `~/ba_logs/<preset>.log` (`daily.log`/`q4h.log`, never interleaved). It contains no game-automation logic -- pure locking/logging plumbing, same category as `ba_dailies.sh` itself. To check whether a scheduled run actually worked: `grep -E 'FAILED|SKIPPED' ~/ba_logs/*.log` -- every run logs one of `OK`/`FAILED (exit N)`/`SKIPPED (previous run still in progress)`, deliberately distinct outcomes (a lock-skip and a genuinely crashed task both exit 1, so the wrapper checks lock acquisition as its own explicit step rather than folding it into the wrapped command's exit code). Times are nik-gpu's local system time (`Asia/Tokyo`/JST). `ba_cron_run.sh` (repo root, run directly from the checkout -- see "Deployment model" above) wraps `ba_dailies.sh <preset>` (resolved as the sibling file next to its own `BASH_SOURCE`) in a shared, non-blocking `flock` (`~/ba_logs/ba_dailies.lock`) so overlapping fire times can never launch concurrent `xdotool`/`scrot` sessions against the same game window, and logs each run to its own `~/ba_logs/<preset>.log` (`daily.log`/`q4h.log`, never interleaved). It contains no game-automation logic -- pure locking/logging plumbing, same category as `ba_dailies.sh` itself. To check whether a scheduled run actually worked: `grep -E 'FAILED|SKIPPED' ~/ba_logs/*.log` -- every run logs one of `OK`/`FAILED (exit N)`/`SKIPPED (previous run still in progress)`, deliberately distinct outcomes (a lock-skip and a genuinely crashed task both exit 1, so the wrapper checks lock acquisition as its own explicit step rather than folding it into the wrapped command's exit code).
This means: resources (AP, tickets, currency) may already be spent by the time a session starts, independent of anything done in that session -- check `~/ba_logs/` before assuming a given game state is from manual testing. The `daily`/`q4h` preset definitions themselves live in `ba_daily.py`'s `PRESETS` dict (see `plan.md`'s Phase 18 follow-ups for the full writeup), not here -- keep this section in sync if the schedule or preset names change. This means: resources (AP, tickets, currency) may already be spent by the time a session starts, independent of anything done in that session -- check `~/ba_logs/` before assuming a given game state is from manual testing. The `daily`/`q4h` preset definitions themselves live in `ba_daily.py`'s `PRESETS` dict (see `plan.md`'s Phase 18 follow-ups for the full writeup), not here -- keep this section in sync if the schedule or preset names change.

View File

@ -6,10 +6,17 @@ XAUTHORITY = "/run/user/1000/gdm/Xauthority"
ENV = {**os.environ, "DISPLAY": DISPLAY, "XAUTHORITY": XAUTHORITY} ENV = {**os.environ, "DISPLAY": DISPLAY, "XAUTHORITY": XAUTHORITY}
WINDOW_NAME = "BlueArchive" WINDOW_NAME = "BlueArchive"
ASSET_DIR = os.path.expanduser("~/ba_assets")
# Resolved relative to wherever this checkout physically lives (two levels
# up from ba_auto/config.py) rather than a fixed path outside the repo --
# the runtime now runs directly out of the git checkout (no more separate
# ~/ba_assets/~/ba_auto copies to drift out of sync with it, see CLAUDE.md's
# "Deployment model"), so assets/scratchpad live wherever the repo does.
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ASSET_DIR = os.path.join(PROJECT_ROOT, "assets")
# Runtime working files (probe/detection screenshots); never /tmp, per CLAUDE.md. # Runtime working files (probe/detection screenshots); never /tmp, per CLAUDE.md.
SCRATCHPAD_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "scratchpad") SCRATCHPAD_DIR = os.path.join(PROJECT_ROOT, "scratchpad")
os.makedirs(SCRATCHPAD_DIR, exist_ok=True) os.makedirs(SCRATCHPAD_DIR, exist_ok=True)
# Refined from (1726, 60): that coordinate sat on the edge of the icon's # Refined from (1726, 60): that coordinate sat on the edge of the icon's

View File

@ -21,6 +21,14 @@
# originally) rather than folded into the wrapped command's own exit code. # originally) rather than folded into the wrapped command's own exit code.
set -uo pipefail set -uo pipefail
# Resolves its own directory (same pattern ba_dailies.sh itself already
# uses) rather than assuming a fixed ~/ba_dailies.sh copy -- the runtime
# now runs directly out of this git checkout, so cron's own crontab entry
# points straight at this file's real path (see CLAUDE.md's "Deployment
# model") and this always calls the ba_dailies.sh sitting right next to it,
# wherever the checkout lives.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PRESET="${1:?usage: ba_cron_run.sh <preset>}" PRESET="${1:?usage: ba_cron_run.sh <preset>}"
LOG_DIR="$HOME/ba_logs" LOG_DIR="$HOME/ba_logs"
LOG_FILE="$LOG_DIR/$PRESET.log" LOG_FILE="$LOG_DIR/$PRESET.log"
@ -35,7 +43,7 @@ mkdir -p "$LOG_DIR"
fi fi
echo "=== $(date -Iseconds) starting $PRESET ===" echo "=== $(date -Iseconds) starting $PRESET ==="
"$HOME/ba_dailies.sh" "$PRESET" "$SCRIPT_DIR/ba_dailies.sh" "$PRESET"
status=$? status=$?
if [ "$status" -eq 0 ]; then if [ "$status" -eq 0 ]; then
echo "=== $(date -Iseconds) finished $PRESET OK (exit 0) ===" echo "=== $(date -Iseconds) finished $PRESET OK (exit 0) ==="

View File

@ -1,16 +1,19 @@
# Bash tab-completion for ba_dailies.sh's subcommand argument. # Bash tab-completion for ba_dailies.sh's subcommand argument.
# #
# Installed automatically by setup.sh (copied to # Installed automatically by setup.sh (a `source ~/repo/ba-auto-daily/
# ~/.ba_dailies_completion.bash and sourced from ~/.bashrc) -- not meant to # completions/ba_dailies.bash` line added to ~/.bashrc) -- resolves its own
# be sourced manually from the repo checkout, since it shells out to the # directory via BASH_SOURCE, same pattern ba_dailies.sh/ba_cron_run.sh
# deployed ~/ba_dailies.sh, not this file's own location. # already use, rather than assuming a fixed ~/ba_dailies.sh copy. The
# runtime runs directly out of this git checkout (see CLAUDE.md's
# "Deployment model"), so this always calls the ba_dailies.sh one directory
# up from wherever it was actually sourced from.
# #
# The command list is queried from ba_daily.py itself (--list-commands) # The command list is queried from ba_daily.py itself (--list-commands)
# rather than duplicated here, so it can never drift from the real TASKS # rather than duplicated here, so it can never drift from the real TASKS
# dict when a task is added, renamed, or removed. # dict when a task is added, renamed, or removed.
_ba_dailies_completions() { _ba_dailies_completions() {
local cur local cur script_dir
cur="${COMP_WORDS[COMP_CWORD]}" cur="${COMP_WORDS[COMP_CWORD]}"
# Only the first argument is a phase name; ba_dailies.sh doesn't take # Only the first argument is a phase name; ba_dailies.sh doesn't take
@ -19,12 +22,12 @@ _ba_dailies_completions() {
return 0 return 0
fi fi
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
local commands local commands
commands="$("$HOME/ba_dailies.sh" --list-commands 2>/dev/null)" commands="$("$script_dir/ba_dailies.sh" --list-commands 2>/dev/null)"
COMPREPLY=($(compgen -W "$commands" -- "$cur")) COMPREPLY=($(compgen -W "$commands" -- "$cur"))
} }
# Registered under every literal form CLAUDE.md documents running this as. # Registered under every literal form CLAUDE.md documents running this as.
complete -F _ba_dailies_completions ba_dailies.sh complete -F _ba_dailies_completions ba_dailies.sh
complete -F _ba_dailies_completions ./ba_dailies.sh complete -F _ba_dailies_completions ./ba_dailies.sh
complete -F _ba_dailies_completions ~/ba_dailies.sh

45
plan.md
View File

@ -87,18 +87,18 @@ This is the intended direction. It does not have to be completed all at once.
## Runtime paths on nik-gpu ## Runtime paths on nik-gpu
Preferred runtime layout: **Changed 2026-07-18** (see plan.md's "Runtime deployment simplification" phase below for the full writeup): the runtime now runs directly out of the checkout, not a separate copy.
| Path | What it is | | Path | What it is |
|---|---| |---|---|
| `nik-gpu:~/ba_dailies.sh` | Thin launcher. | | `nik-gpu:~/repo/ba-auto-daily/` | The checkout. `ba_dailies.sh`/`ba_cron_run.sh`/`completions/ba_dailies.bash` all resolve their own directory via `BASH_SOURCE`, and `ba_auto/config.py`'s `ASSET_DIR`/`SCRATCHPAD_DIR` resolve relative to the checkout root -- everything runs in place, nothing is copied out. |
| `nik-gpu:~/ba_daily.py` | Python CLI entry point. | | `nik-gpu:~/.venvs/ba-auto-daily/` | Python virtual environment -- genuinely host-level, not repo content. |
| `nik-gpu:~/ba_auto/` | Python package copied from this repo. | | `nik-gpu:~/ba_logs/` | Cron run logs + the cron lock file -- genuinely runtime state, not repo content. |
| `nik-gpu:~/ba_assets/` | Runtime assets/templates. |
| `nik-gpu:~/.venvs/ba-auto-daily/` | Python virtual environment. |
`nik-gpu:~/ba_scripts/` may still contain `detect_and_click.py` and `ba_dailies_legacy.sh` left over from before both mailbox and cafe were migrated off them. Neither is deployed or referenced by anything anymore (`setup.sh` stopped copying them once Phase 6 landed) — safe to delete manually on `nik-gpu`, just not automated here. `nik-gpu:~/ba_scripts/` may still contain `detect_and_click.py` and `ba_dailies_legacy.sh` left over from before both mailbox and cafe were migrated off them. Neither is deployed or referenced by anything anymore (`setup.sh` stopped copying them once Phase 6 landed) — safe to delete manually on `nik-gpu`, just not automated here.
`nik-gpu:~/ba_dailies.sh`/`~/ba_daily.py`/`~/ba_auto/`/`~/ba_assets/`/`~/ba_cron_run.sh`/`~/.ba_dailies_completion.bash` were the old copy-to-`$HOME` runtime paths (2026-07-16 through 2026-07-18) — removed for real on nik-gpu as part of the same change, not just superseded in docs. If any of them show up again, they're stale leftovers, not the current architecture.
## Implementation strategy ## Implementation strategy
For each feature: For each feature:
@ -916,6 +916,31 @@ One real bug found and fixed before any live test, while reasoning through what
**Confirmed live**: a standalone `./ba_dailies.sh exit_game` run, user-reported "works well" -- `navigation.is_modal_open`'s generic dim-probe correctly detected the exit-confirmation dialog after Escape, and Enter closed the game cleanly (`driver.window_exists()` verified false). Not yet exercised as the tail end of a full `daily`/`q4h` preset run specifically (only standalone so far). **Confirmed live**: a standalone `./ba_dailies.sh exit_game` run, user-reported "works well" -- `navigation.is_modal_open`'s generic dim-probe correctly detected the exit-confirmation dialog after Escape, and Enter closed the game cleanly (`driver.window_exists()` verified false). Not yet exercised as the tail end of a full `daily`/`q4h` preset run specifically (only standalone so far).
### Phase 20: Runtime deployment simplification -- run directly from the checkout (2026-07-18)
Direct consequence of Phase 19's own deploy: the real `q4h` cron fire right after Phase 19 landed showed no `[exit_game]` line at all in `~/ba_logs/q4h.log` -- the sequence went straight from `event_sweep` to `"All done."`. Diagnosed by reading the log and grepping the runtime `~/ba_daily.py` for `exit_game`: zero matches, and `~/ba_auto/tasks/exit_game.py` didn't even exist at that path. Root cause: this project's deploy model kept the git checkout (`~/repo/ba-auto-daily/`, what `rsync` updates) and the actual runtime paths (`~/ba_dailies.sh`/`~/ba_daily.py`/`~/ba_auto/`, what `setup.sh` copied files to and what cron/manual runs actually executed) as two separate locations that could silently drift -- confirmed for the second time in three days (the first was 2026-07-16's cron-setup phase, see Phase 18 follow-up #2). Fixed immediately for that instance by re-running `setup.sh` to resync.
The user then asked to remove the whole class of bug rather than keep re-syncing it: change the runtime to run directly out of `~/repo/ba-auto-daily/`, eliminating the separate copies entirely ("keep the home directory clean").
Changes made:
- `ba_auto/config.py`: `ASSET_DIR` was a hardcoded `os.path.expanduser("~/ba_assets")`. Changed to a new `PROJECT_ROOT` (two levels up from `config.py`, the same resolution `SCRATCHPAD_DIR` already used) + `os.path.join(PROJECT_ROOT, "assets")` -- now reads the repo's own `assets/` directly, no copy needed.
- `ba_cron_run.sh`: called `"$HOME/ba_dailies.sh" "$PRESET"`. Changed to resolve its own `SCRIPT_DIR` via `BASH_SOURCE` (same pattern `ba_dailies.sh` itself already used) and call `"$SCRIPT_DIR/ba_dailies.sh"` instead -- works wherever the checkout lives, no fixed path assumed.
- `completions/ba_dailies.bash`: hardcoded `$HOME/ba_dailies.sh` for its `--list-commands` query. Changed to resolve `script_dir` via `BASH_SOURCE` the same way, and dropped the now-nonexistent `~/ba_dailies.sh` completion registration.
- `setup.sh`: removed the "copy `ba_dailies.sh`/`ba_daily.py`/`ba_auto`/assets to `$HOME`" steps entirely (`chmod +x` in place instead of `cp`). Tab-completion install now sources `completions/ba_dailies.bash` from the checkout directly (`source "$REPO_DIR/completions/ba_dailies.bash"` added to `~/.bashrc`) rather than copying it to `~/.ba_dailies_completion.bash` first. Host-tool checks and venv setup unchanged -- those are genuinely host-level, not repo content.
- `CLAUDE.md`'s "Deployment model"/"Runtime paths on nik-gpu"/"Scheduled runs (cron)" sections rewritten to document the new single-location model, with the old copy-to-`$HOME` model kept as an explicit "replaced" note (both real drift incidents named) rather than deleted outright, so a future session that sees a stray `~/ba_dailies.sh` lying around understands it's dead leftover, not a second live copy.
Live steps taken on nik-gpu (not just docs):
1. Rsynced the updated repo to `~/repo/ba-auto-daily/`, then re-ran `./setup.sh` there (venv/tab-completion only now, confirmed idempotent).
2. Verified `~/repo/ba-auto-daily/ba_daily.py`/`ba_auto/tasks/exit_game.py` matched the local copies exactly.
3. Updated the live crontab (`crontab -l` / `crontab -` round-trip) so all three entries call `/home/nik/repo/ba-auto-daily/ba_cron_run.sh <preset>` instead of `/home/nik/ba_cron_run.sh <preset>` -- same schedule/times, only the path changed.
4. Deleted the now-obsolete runtime copies on nik-gpu: `~/ba_dailies.sh`, `~/ba_daily.py`, `~/ba_auto/`, `~/ba_assets/`, `~/ba_cron_run.sh`, `~/.ba_dailies_completion.bash`, and fixed the stale `source ~/.ba_dailies_completion.bash` line left in `~/.bashrc` from the old `setup.sh`.
`~/.venvs/ba-auto-daily/` and `~/ba_logs/` were deliberately left in `$HOME` -- genuine runtime state/build output (venv packages, cron logs + lock file), not duplicated code, so they don't reintroduce the drift problem this phase was meant to close off.
**Verification**: a standalone `~/repo/ba-auto-daily/ba_dailies.sh --list-commands` / task dispatch through the new path, plus confirming the crontab's next fire actually reaches `exit_game`, are the two things worth checking to fully close this out -- see plan.md's "Immediate next steps"-style follow-up once the next scheduled `q4h`/`daily` fire happens.
## Prerequisites ## Prerequisites
### OCR ### OCR
@ -1354,17 +1379,17 @@ python3 -m py_compile ba_auto/*.py
python3 -m py_compile ba_auto/tasks/*.py python3 -m py_compile ba_auto/tasks/*.py
``` ```
On `nik-gpu`: On `nik-gpu` (runs directly from the checkout since 2026-07-18 -- see "Runtime paths on nik-gpu"):
``` ```
~/ba_dailies.sh mailbox ~/repo/ba-auto-daily/ba_dailies.sh mailbox
~/ba_dailies.sh cafe ~/repo/ba-auto-daily/ba_dailies.sh cafe
``` ```
After migration: After migration:
``` ```
~/ba_dailies.sh ~/repo/ba-auto-daily/ba_dailies.sh
``` ```
should run the default daily sequence. should run the default daily sequence.

View File

@ -5,13 +5,15 @@
# not from macOS, since it installs into nik-gpu-local paths. # not from macOS, since it installs into nik-gpu-local paths.
# #
# It does NOT touch the game or take any screenshots; it only installs the # It does NOT touch the game or take any screenshots; it only installs the
# venv and copies files to the fixed paths ba_dailies.sh/ba_daily.py/ba_auto # venv (host-level, genuinely outside the repo -- ~/.venvs/ba-auto-daily/)
# expect (outside the repo, per the two-machine deploy convention in # and tab-completion. The runtime runs directly out of this checkout (see
# CLAUDE.md). # CLAUDE.md's "Deployment model") -- there is no separate copy step for
# ba_dailies.sh/ba_daily.py/ba_auto/assets, so re-running this after a
# `git pull`/rsync can't drift out of sync with the code the way the old
# copy-to-$HOME model could.
set -e set -e
VENV_DIR="$HOME/.venvs/ba-auto-daily" VENV_DIR="$HOME/.venvs/ba-auto-daily"
ASSETS_DIR="$HOME/ba_assets"
echo "== Checking host tools ==" echo "== Checking host tools =="
missing=0 missing=0
@ -62,21 +64,12 @@ fi
"$VENV_DIR/bin/python3" -c "import cv2, numpy; print('opencv', cv2.__version__, '/ numpy', numpy.__version__)" "$VENV_DIR/bin/python3" -c "import cv2, numpy; print('opencv', cv2.__version__, '/ numpy', numpy.__version__)"
"$VENV_DIR/bin/python3" -c "import pytesseract; print('pytesseract', pytesseract.get_tesseract_version())" "$VENV_DIR/bin/python3" -c "import pytesseract; print('pytesseract', pytesseract.get_tesseract_version())"
echo "== Deploying assets to fixed paths ==" chmod +x ba_dailies.sh ba_cron_run.sh
mkdir -p "$ASSETS_DIR"
cp assets/cafe_sparkle.png "$ASSETS_DIR/cafe_sparkle.png"
echo "== Deploying Python-first entry point =="
cp ba_dailies.sh "$HOME/ba_dailies.sh"
chmod +x "$HOME/ba_dailies.sh"
cp ba_daily.py "$HOME/ba_daily.py"
rm -rf "$HOME/ba_auto"
cp -r ba_auto "$HOME/ba_auto"
echo "== Installing tab completion ==" echo "== Installing tab completion =="
cp completions/ba_dailies.bash "$HOME/.ba_dailies_completion.bash" REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
COMPLETION_LINE='source "$HOME/.ba_dailies_completion.bash"' COMPLETION_LINE="source \"$REPO_DIR/completions/ba_dailies.bash\""
if [ -f "$HOME/.bashrc" ] && ! grep -qF ".ba_dailies_completion.bash" "$HOME/.bashrc"; then if [ -f "$HOME/.bashrc" ] && ! grep -qF "completions/ba_dailies.bash" "$HOME/.bashrc"; then
printf '\n# Added by ba-auto-daily setup.sh\n%s\n' "$COMPLETION_LINE" >> "$HOME/.bashrc" printf '\n# Added by ba-auto-daily setup.sh\n%s\n' "$COMPLETION_LINE" >> "$HOME/.bashrc"
echo "Added source line to ~/.bashrc" echo "Added source line to ~/.bashrc"
else else
@ -85,5 +78,5 @@ fi
echo "Run 'source ~/.bashrc' or open a new shell to pick up completion" echo "Run 'source ~/.bashrc' or open a new shell to pick up completion"
echo "== Done ==" echo "== Done =="
echo "Run with: ~/ba_dailies.sh [mailbox|cafe|stamina|story_sweep|shop_common|shop_tactical|lesson]" echo "Run with: $REPO_DIR/ba_dailies.sh [mailbox|cafe|stamina|story_sweep|shop_common|shop_tactical|lesson]"
echo "(requires the game already running, window titled 'BlueArchive')" echo "(requires the game already running, window titled 'BlueArchive')"