diff --git a/ba_daily.py b/ba_daily.py index f9cb8a6..d07ae2d 100644 --- a/ba_daily.py +++ b/ba_daily.py @@ -39,6 +39,26 @@ TASKS = { # already logged in, not a risky blind click every single day. DEFAULT_ORDER = ["login", "mailbox", "cafe", "stamina", "gem_shop", "circle"] +# Named multi-task sequences, run via `./ba_dailies.sh ` -- +# distinct from DEFAULT_ORDER (the plain no-args flow, deliberately kept to +# free/no-decision tasks only, see the comment above). A preset is an +# explicit, named choice the user opts into, so unlike DEFAULT_ORDER it's +# free to include resource-spending tasks and repeat tasks (e.g. event_sweep +# multiple times, to re-check a rotating target). Ported directly from the +# user's own `~/.bashrc` `ba_daily()` wrapper (which looped +# `./ba_dailies.sh "$task"` once per task, a fresh Python process every +# time, stopping on the first failure) -- Python owns the loop here +# instead, matching CLAUDE.md's "Python owns automation logic" rule, and +# `_run_task`'s existing try/finally means an uncaught exception from one +# task still halts the whole sequence exactly like the bash `|| return` did. +PRESETS = { + "daily": [ + "login", "event_sweep", "cafe", "event_sweep", "circle", "lesson", + "arena", "shop_common", "shop_tactical", "event_sweep", "bounty", + "mailbox", "stamina", "event_sweep", + ], +} + # How many times _ensure_home retries navigation.return_to_home as a whole # (not to be confused with that function's own internal # RETURN_HOME_MAX_ROUNDS press-loop) before giving up, and how long it waits @@ -129,27 +149,37 @@ def _run_task(name): print(f"[{name}] warning: could not confirm return to home screen after task finished") +def _run_sequence(names): + for name in names: + _run_task(name) + print("All done.") + + def main(argv): args = argv[1:] if args and args[0] == "--list-commands": # Machine-readable command list for shell completion (see - # completions/ba_dailies.bash) -- kept as a thin read of TASKS - # itself so the completion list can never drift from what's - # actually dispatchable. - print(" ".join(TASKS.keys())) + # completions/ba_dailies.bash) -- kept as a thin read of TASKS/ + # PRESETS themselves so the completion list can never drift from + # what's actually dispatchable. + print(" ".join(list(TASKS.keys()) + list(PRESETS.keys()))) return 0 if not args: - for name in DEFAULT_ORDER: - _run_task(name) - print("All done.") + _run_sequence(DEFAULT_ORDER) return 0 command = args[0] + + if command in PRESETS: + _run_sequence(PRESETS[command]) + return 0 + if command not in TASKS: print(f"Unknown phase: {command}", file=sys.stderr) print(f"Valid phases: {' '.join(TASKS.keys())}", file=sys.stderr) + print(f"Valid presets: {' '.join(PRESETS.keys())}", file=sys.stderr) return 1 _run_task(command) diff --git a/plan.md b/plan.md index 7dcdd73..c58b52c 100644 --- a/plan.md +++ b/plan.md @@ -792,6 +792,16 @@ Added as the very first step in `ba_daily.py`'s `DEFAULT_ORDER`, ahead of mailbo **Not yet live-confirmed**: the infrequent 業務復帰ログインボーナス welcome-back login bonus card from the user's own reference screenshots (account wasn't in that state during calibration) -- expected to fall through to the same generic-Enter path already confirmed for the attendance card and network notice, but not yet exercised for real; and the automatic kill+relaunch recovery path (`_recover`) has only been exercised once, manually, not yet triggered by `login.py`'s own `LOGIN_TIMEOUT_SECONDS` budget hitting a real stuck state on its own. +### Phase 18 follow-up: named task presets (2026-07-16) + +Requested directly by the user, who already had a personal `~/.bashrc` `ba_daily()` wrapper function looping `./ba_dailies.sh "$task" || return` once per task (a fresh Python process per task) over a fixed list. Wanted the same "run one named sequence" convenience built into the project itself (`./ba_dailies.sh daily`, with `morning`/`evening`/`weekly`/`raid` as future examples of the same mechanism), rather than kept as a personal shell alias outside the repo. + +Per CLAUDE.md's Bash policy (`ba_dailies.sh` is a thin launcher only, no loops/sequences in Bash), this was **not** built as the `case`-statement-in-`ba_dailies.sh` the user's own sketch initially proposed -- it went into `ba_daily.py` instead, alongside the existing `DEFAULT_ORDER`. Added a `PRESETS` dict (`{"daily": [...]}`, exactly the user's own bashrc task list, ported verbatim -- notably it does NOT include `gem_shop`, which was preserved as-is rather than "corrected," since guessing at the user's intent for a resource-adjacent list wasn't this change's place) and a small `_run_sequence` helper shared between `DEFAULT_ORDER`'s no-args flow and any `PRESETS` entry, dispatched via `./ba_dailies.sh ` in `main()`. Python owns the loop directly now instead of the bash wrapper's repeated `./ba_dailies.sh "$task"` re-invocation (avoiding a fresh process/game-refocus per task) -- `_run_task`'s existing bare `try/finally` already means an uncaught exception from one task halts the whole sequence, matching the bash version's `|| return` semantics with no extra code needed. + +`--list-commands` (drives `completions/ba_dailies.bash`'s tab-completion) now lists preset names alongside task names, and the "Unknown phase" error path lists both separately. Per explicit user direction, only the `daily` preset was defined for now -- `morning`/`evening`/`weekly`/`raid` are left undefined until the user specifies their task lists, rather than guessed at (several candidate tasks spend real resources: arena tickets, bounty tickets, lesson tickets, event_sweep/AP). + +**Verified on nik-gpu without spending anything**: `--list-commands` includes `daily`; requesting a bogus phase name correctly lists both valid phases and valid presets and exits 1. The `daily` preset's actual task sequence (which includes `event_sweep`/`arena`/`lesson`/`bounty`/`shop_common`/`shop_tactical`, all real-resource-spending) has not been run for real yet -- needs explicit user go-ahead before that first live run, per this project's own established live-testing discipline for resource-spending tasks. + ## Prerequisites ### OCR