From 07f2408f7e5fff37d33be10520b948c5aeef6fd3 Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Fri, 11 Sep 2026 18:46:34 +0200 Subject: [PATCH] Re-point paths for the ~ reorganisation (home-tidy) Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01AwtowrowDXx6ccmWVPkCaF --- .github/workflows/python-tests.yml | 2 +- .pre-commit-config.yaml | 4 +-- AGENTS.md | 6 ++--- DOCS-free-days.md | 4 +-- DOCS-phone-alarm.md | 2 +- DOCS-vmbox.md | 2 +- TODO-file-length-250.md | 6 ++--- TODO-hardening-continue.md | 6 ++--- phone_app/lib/services/free_day_pool.dart | 2 +- phone_app/pubspec.yaml | 2 +- prompts/TODO-dopamine-ux-wake-alarm.md | 30 +++++++++++------------ scripts/check_dependency_freshness.sh | 6 ++--- scripts/check_file_length.sh | 6 ++--- scripts/check_md_naming.sh | 6 ++--- scripts/check_no_crdt_sync_override.sh | 2 +- scripts/free_days_interop/check.sh | 6 ++--- scripts/free_days_interop/verify.py | 2 +- scripts/vmbox/harness.sh | 6 ++--- 18 files changed, 50 insertions(+), 50 deletions(-) diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index 3a9643d..6b7dfe4 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -23,7 +23,7 @@ jobs: - name: Run tests with coverage run: python -m pytest -v - # The Dart free-day rules are a port of ~/utils/freedays. This is the + # The Dart free-day rules are a port of ~/src/utils/freedays. This is the # cross-language gate (scripts/free_days_interop/check.sh): it needs both # Flutter and the Python package, which the pre-commit job does not have, # so it runs here and the pre-commit job SKIPs that one hook. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4402ed8..81ef8f0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -147,7 +147,7 @@ repos: language: system pass_filenames: false always_run: true - # The Dart free-day rules are a port of ~/utils/freedays; this replays + # The Dart free-day rules are a port of ~/src/utils/freedays; this replays # one edit sequence through both and fails on any semantic disagreement. # Only fires when either implementation's inputs change. - id: free-days-interop @@ -171,7 +171,7 @@ repos: # Four markdown namespaces (README / CLAUDE* / DOCS* / TODO*), plus the # rule that a TODO carries "REMOVE ME AFTER FINISH" and nothing else may. - # Shared gate in ~/utils owns the namespaces and the exemption list, so + # Shared gate in ~/src/utils owns the namespaces and the exemption list, so # one repo's idea of a valid name cannot drift from every other repo's. - id: md-naming name: markdown naming convention diff --git a/AGENTS.md b/AGENTS.md index 9423712..1d18e88 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -69,7 +69,7 @@ can reach the two-minute floor or the five-minute bypass. More, including everything that is a hard crash or a silent no-ring: **`DOCS-phone-alarm.md`**. -**Free days.** On a day in the shared pool (`~/utils/freedays`) the phone +**Free days.** On a day in the shared pool (`~/src/utils/freedays`) the phone does not ring at all: `AlarmReceiver` checks a native cache Dart rewrites after every mark/release/sync. Picker, cache and its fail-closed contract: **`DOCS-free-days.md`**. @@ -176,8 +176,8 @@ site-packages: directory — it is editable, so a later `git pull` in that clone updates the running production code. From `/tmp` or via `pip install "wake_alarm @ git+..."` you get a snapshot frozen at that commit, and the next push silently does not -reach the running service. Convention: `~/wake-alarm`, mirroring -`~/screen-locker`. +reach the running service. Convention: `~/src/wake-alarm`, mirroring +`~/src/screen-locker`. If you add a dependency and only install it into a dev venv, the service fails with `ModuleNotFoundError` on its next run — this exact gap caused a 3-day diff --git a/DOCS-free-days.md b/DOCS-free-days.md index aca8a09..6825ace 100644 --- a/DOCS-free-days.md +++ b/DOCS-free-days.md @@ -1,6 +1,6 @@ # Free days — the phone picker for the shared pool -The pool itself is `~/utils/freedays` (Python): one global set of days on +The pool itself is `~/src/utils/freedays` (Python): one global set of days on which every gate app stands down, 35 per calendar year, declared for today or later, never backdated, refunded only while still in the future. Read its README for the rules. This file covers the phone half, which lives in this @@ -55,7 +55,7 @@ are never the reference: comparing them to what Python reads from Dart's file cannot see a drift in what Dart *writes*. Proved on 2026-09-11 by dropping the sticky `consumed` from `release` — the gate reported `remaining: dart=33 python=32`. Needs the freedays venv -(`~/utils/freedays/install.sh`). +(`~/src/utils/freedays/install.sh`). ## Do NOT diff --git a/DOCS-phone-alarm.md b/DOCS-phone-alarm.md index 0a5f951..1662022 100644 --- a/DOCS-phone-alarm.md +++ b/DOCS-phone-alarm.md @@ -168,7 +168,7 @@ channel and arms nothing. Do not "clean these up" without replacing the capability. Emulator: `wake_alarm_api36` (Pixel 6a profile, API 36). The SDK tools are at -`~/Android/Sdk` but **not on PATH** — export `ANDROID_HOME` and add +`~/sdk/Android/Sdk` but **not on PATH** — export `ANDROID_HOME` and add `cmdline-tools/latest/bin`, `emulator` and `platform-tools` yourself. The phone (Pixel 6a, `23181JEGR08034`) holds a **release-signed** build, so `phone_deploy.sh` needs `--release` or the install fails with diff --git a/DOCS-vmbox.md b/DOCS-vmbox.md index 9159246..914e344 100644 --- a/DOCS-vmbox.md +++ b/DOCS-vmbox.md @@ -3,7 +3,7 @@ `scripts/vmbox/harness.sh` is this repo's default gate for the shell and system pieces — `install.sh`, the systemd units, `shutdown-wrapper.sh`, the power-key inhibitor and the re-fire path. It provisions a throwaway Arch guest -(`~/utils/vmbox`), installs this repo into it exactly the way a real machine +(`~/src/utils/vmbox`), installs this repo into it exactly the way a real machine does, runs the cases, and returns a host-side verdict. ```bash diff --git a/TODO-file-length-250.md b/TODO-file-length-250.md index 31ffb0e..faf1364 100644 --- a/TODO-file-length-250.md +++ b/TODO-file-length-250.md @@ -74,7 +74,7 @@ an exempt extension, no `# noqa`-style suppressions. A refactor without a gate silently regrows. Before this task is done: -1. Wire the shared gate `~/utils/scripts/check_file_length.sh` into this repo's +1. Wire the shared gate `~/src/utils/scripts/check_file_length.sh` into this repo's `.pre-commit-config.yaml` as a local hook. If the repo has no pre-commit config, add a minimal one. 2. The hook checks **files in the commit** (not the whole tree), so unrelated @@ -85,7 +85,7 @@ A refactor without a gate silently regrows. Before this task is done: ## Done condition -- `bash ~/utils/scripts/check_file_length.sh --all` from this repo root exits 0. +- `bash ~/src/utils/scripts/check_file_length.sh --all` from this repo root exits 0. - The repo's own test suite and coverage bar are still green. - `pre-commit run --files ` passes. - A deliberately over-250-line test file, staged, makes `git commit` **fail**. @@ -101,7 +101,7 @@ This repo ran a LOCAL `scripts/check_file_length.py` with `MAX_LINES = 500`, under a hook named "Max file length (500 lines)". It reported "gated" while permitting files every other repo rejects -- so the cap looked enforced and nothing ever failed. The hook now delegates to the shared 250-line gate in -`~/utils`, which reports 17 real violations. +`~/src/utils`, which reports 17 real violations. Done condition is now an exit code, not a count: diff --git a/TODO-hardening-continue.md b/TODO-hardening-continue.md index 5d01fe6..08604d0 100644 --- a/TODO-hardening-continue.md +++ b/TODO-hardening-continue.md @@ -33,7 +33,7 @@ starting; this file deliberately does not duplicate it. tag 1 → 25 steps + 2 min → tag 2 → 3 challenges. 2. **Item 8, mutual gating.** Phone half is now in place. This is the phase that legitimately touches `_sync.py`, so it carries that split (see below). -3. **Item 13, black screen.** Different repo (`~/testsAndMisc/ +3. **Item 13, black screen.** Different repo (`~/src/testsAndMisc/ linux_configuration`), host-only, blocks nothing. ### Verified end to end on the Pixel 6a, 2026-08-27 @@ -150,7 +150,7 @@ Two harness traps found while testing this, worth keeping: Stream at all. Re-arm therefore needs three explicit hooks — startup, BOOT_COMPLETED, dismiss — and dropping any one makes the alarm ring once and then silently stop forever. -- **The Android SDK was never missing, only unexported.** `~/Android/Sdk` has +- **The Android SDK was never missing, only unexported.** `~/sdk/Android/Sdk` has `cmdline-tools`, `emulator` and `platform-tools`; only `adb` was on PATH. Export `ANDROID_HOME` rather than installing anything. - **A permission declared in the manifest is not a permission granted.** @@ -171,7 +171,7 @@ Two harness traps found while testing this, worth keeping: `test_state.py` 314. Budget for it. `test_trigger.py` is now split and under. - **`morning_routine/_orchestrator.py:39` hardcodes `"wake_alarm._alarm"`** - (different repo, `~/testsAndMisc`). Any module-path change updates it in the + (different repo, `~/src/testsAndMisc`). Any module-path change updates it in the *same* commit. This exact omission caused a month-long silent outage. Keep `main()` in `_alarm.py`. - **Splitting a test file loses its fixtures.** `_make_mock_tk`, diff --git a/phone_app/lib/services/free_day_pool.dart b/phone_app/lib/services/free_day_pool.dart index 20832b1..407b575c 100644 --- a/phone_app/lib/services/free_day_pool.dart +++ b/phone_app/lib/services/free_day_pool.dart @@ -8,7 +8,7 @@ import 'package:wake_alarm_sync/services/alarm_sync_service.dart'; /// The shared free-day pool, as the phone sees it. /// -/// A Dart port of `~/utils/freedays` (Python), which owns the rules: one +/// A Dart port of `~/src/utils/freedays` (Python), which owns the rules: one /// global pool for every gate app, 35 days per calendar year resetting on /// Jan 1, declared for today or later and never backdated, releasing refunds /// only a day that has not arrived, and `consumed` is sticky. The record diff --git a/phone_app/pubspec.yaml b/phone_app/pubspec.yaml index 7c99712..f16bc04 100644 --- a/phone_app/pubspec.yaml +++ b/phone_app/pubspec.yaml @@ -55,7 +55,7 @@ flutter: uses-material-design: true # Launcher icon generation. Source art is produced by the shared generator: -# PYTHONPATH=~/testsAndMisc python3 -m python_pkg.app_icons generate --app +# PYTHONPATH=~/src/testsAndMisc python3 -m python_pkg.app_icons generate --app # then run: dart run flutter_launcher_icons flutter_launcher_icons: android: true diff --git a/prompts/TODO-dopamine-ux-wake-alarm.md b/prompts/TODO-dopamine-ux-wake-alarm.md index a0e33f2..07b61c6 100644 --- a/prompts/TODO-dopamine-ux-wake-alarm.md +++ b/prompts/TODO-dopamine-ux-wake-alarm.md @@ -2,8 +2,8 @@ > "do dopamine-ux-wake-alarm". It is self-contained -- it needs no context from > any other session. > -> Canonical copy: `~/utils/dopamine-ux/09-wake-alarm.md` (source of truth; this is a -> distributed copy). Running order and cross-prompt rules: `~/utils/dopamine-ux/00-INDEX.md`. +> Canonical copy: `~/src/utils/dopamine-ux/09-wake-alarm.md` (source of truth; this is a +> distributed copy). Running order and cross-prompt rules: `~/src/utils/dopamine-ux/00-INDEX.md`. > Generated 2026-08-16 from a survey of this repo -- line numbers are accurate > as of that date; **anchor on the symbol names, not the line numbers.** @@ -19,10 +19,10 @@ Do **both**, in the same session that completes the work: Do not leave a finished prompt lying in the repo -- a stale prompt is indistinguishable from a pending one, and the next session will re-run it. -2. **Log completion in the canonical index**, in `~/utils` (a *different* repo, +2. **Log completion in the canonical index**, in `~/src/utils` (a *different* repo, so it needs its own commit): ```bash - cd ~/utils + cd ~/src/utils # append to the "Completion log" table in dopamine-ux/00-INDEX.md: # | 09-wake-alarm.md | DONE | | | git add dopamine-ux/00-INDEX.md @@ -49,7 +49,7 @@ Add motion and haptics to the wake-alarm phone app ## what -`~/wake-alarm/phone_app` is the smallest surface in this project: 12 Dart files, +`~/src/wake-alarm/phone_app` is the smallest surface in this project: 12 Dart files, a sync companion that sets a time, syncs it, and hands off to the system clock app. It has **zero motion, zero haptics, zero audio, zero progress feedback** — verified 2026-08-16. Its settings screen is a 56-line `StatelessWidget` with two @@ -63,7 +63,7 @@ project's sharpest hazard — see `must not` about alarm audio. ## where -Repo: `~/wake-alarm`. Flutter app: `~/wake-alarm/phone_app` (**underscore**, not +Repo: `~/src/wake-alarm`. Flutter app: `~/src/wake-alarm/phone_app` (**underscore**, not `phone-app`). The repo root is a Python package; the Flutter app is only the `phone_app/` subdirectory. @@ -116,12 +116,12 @@ Primary: - To add any toggle here you must do three things the other apps do not require: (a) convert `SettingsScreen` from `StatelessWidget` to `StatefulWidget`, (b) create a preferences class — there is no `AppSettings` equivalent; model it - on `~/todo/lib/data/app_settings.dart`, and note `shared_preferences: ^2.3.0` + on `~/src/todo/lib/data/app_settings.dart`, and note `shared_preferences: ^2.3.0` is **already a dependency**, (c) add the `SwitchListTile` to the `ListView`. **Both steps:** -- must not: **touch anything under `~/wake-alarm/wake_alarm/`.** That is the +- must not: **touch anything under `~/src/wake-alarm/wake_alarm/`.** That is the desktop Python daemon that produces the real alarm noise — sine-tone WAVs via `paplay` → `aplay` → `speaker-test` (`_audio.py`, `_play_on_all_sinks` ~:218, pcspkr evdev fallback `_beep_pcspkr` ~:81), escalating 440Hz → 1000Hz → loud in @@ -145,10 +145,10 @@ Primary: time that was set. 2. Page transitions use the shared motion tokens; no inline animation `Duration` remains (the 3s intent timeout stays). -3. `cd ~/wake-alarm/phone_app && flutter analyze` is clean. -4. `cd ~/wake-alarm/phone_app && flutter test` passes. +3. `cd ~/src/wake-alarm/phone_app && flutter analyze` is clean. +4. `cd ~/src/wake-alarm/phone_app && flutter test` passes. 5. With OS "remove animations" enabled, the app works and durations are zero. -6. `git diff` shows **no changes under `~/wake-alarm/wake_alarm/`**. +6. `git diff` shows **no changes under `~/src/wake-alarm/wake_alarm/`**. 7. The summary states whether sound was added or deliberately skipped. ## verify @@ -157,7 +157,7 @@ Primary: ``` adb devices # confirm 23181JEGR08034 -cd ~/wake-alarm/phone_app +cd ~/src/wake-alarm/phone_app flutter build apk --release adb install -r build/app/outputs/flutter-apk/app-release.apk ``` @@ -180,9 +180,9 @@ involves the desktop daemon and real noise. including the timeout and the `_status` string handling. - `phone_app/lib/ui/theme.dart` — note what it does **not** declare before writing any widget. -- `~/todo/lib/data/app_settings.dart` — the preferences-class pattern, only if +- `~/src/todo/lib/data/app_settings.dart` — the preferences-class pattern, only if you decide to do step 2. -- `~/utils/unified-design-system/motion.md` — vocabulary from prompt 01. +- `~/src/utils/unified-design-system/motion.md` — vocabulary from prompt 01. **Prompt 01 must have run first.** ## context you would otherwise rediscover @@ -191,7 +191,7 @@ involves the desktop daemon and real noise. `assets:` block; `assets/` contains only launcher icons. It fires an Android `SET_ALARM` intent and the **system Clock app** rings. The desktop Python daemon is an entirely separate program on a different machine. -- The repo root (`~/wake-alarm/wake_alarm/`, `wake_alarm.egg-info`) is the Python +- The repo root (`~/src/wake-alarm/wake_alarm/`, `wake_alarm.egg-info`) is the Python package. Only `phone_app/` is Flutter. - This app has **no `design_system` dependency** and the thinnest local theme in the fleet. Adding the dependency is out of scope here (see prompt 07 for what diff --git a/scripts/check_dependency_freshness.sh b/scripts/check_dependency_freshness.sh index 5cb0d78..7715d3c 100755 --- a/scripts/check_dependency_freshness.sh +++ b/scripts/check_dependency_freshness.sh @@ -3,7 +3,7 @@ # ============================================================================ # Fail if any dependency in the commit is behind its ecosystem's newest stable. # -# Thin delegate to the shared gate in ~/utils, which owns the registry +# Thin delegate to the shared gate in ~/src/utils, which owns the registry # adapters, the pre-release rules and the allowlist semantics. Copying that # logic here is what lets one repo's idea of "current" drift from every other # repo's -- so this script only locates the shared checker and forwards its @@ -18,12 +18,12 @@ set -euo pipefail -readonly SHARED_GATE="${UTILS_ROOT:-$HOME/utils}/scripts/check_dependency_freshness.sh" +readonly SHARED_GATE="${UTILS_ROOT:-$HOME/src/utils}/scripts/check_dependency_freshness.sh" main() { if [[ ! -x "$SHARED_GATE" ]]; then echo "Error: shared dependency-freshness gate not found at $SHARED_GATE" >&2 - echo " Clone github.com/kuhyx/utils to ~/utils, or set" >&2 + echo " Clone github.com/kuhyx/utils to ~/src/utils, or set" >&2 echo " UTILS_ROOT to where it lives." >&2 exit 1 fi diff --git a/scripts/check_file_length.sh b/scripts/check_file_length.sh index b58a32c..8f3cab2 100755 --- a/scripts/check_file_length.sh +++ b/scripts/check_file_length.sh @@ -3,7 +3,7 @@ # ============================================================================ # Fail if any file in the commit exceeds the shared 250-line cap. # -# Thin delegate to the shared gate in ~/utils, which owns the cap and the +# Thin delegate to the shared gate in ~/src/utils, which owns the cap and the # exemption list (generated / vendored / data files). This repo previously ran # a LOCAL check_file_length.py with its own higher limit, so it reported # "gated" while permitting files every other repo rejects -- which is why its @@ -16,12 +16,12 @@ set -euo pipefail -readonly SHARED_GATE="${UTILS_ROOT:-$HOME/utils}/scripts/check_file_length.sh" +readonly SHARED_GATE="${UTILS_ROOT:-$HOME/src/utils}/scripts/check_file_length.sh" main() { if [[ ! -x "$SHARED_GATE" ]]; then echo "Error: shared file-length gate not found at $SHARED_GATE" >&2 - echo " Clone github.com/kuhyx/utils to ~/utils, or set" >&2 + echo " Clone github.com/kuhyx/utils to ~/src/utils, or set" >&2 echo " UTILS_ROOT to where it lives." >&2 exit 1 fi diff --git a/scripts/check_md_naming.sh b/scripts/check_md_naming.sh index 50deaa0..7847c56 100755 --- a/scripts/check_md_naming.sh +++ b/scripts/check_md_naming.sh @@ -3,7 +3,7 @@ # ============================================================================ # Fail if any markdown file breaks the shared naming convention. # -# Thin delegate to the shared gate in ~/utils, which owns the four namespaces +# Thin delegate to the shared gate in ~/src/utils, which owns the four namespaces # (README / CLAUDE* / DOCS* / TODO*), the "REMOVE ME AFTER FINISH" marker rule # and the exemption list. Copying that logic here is what lets one repo's idea # of a valid name drift from every other repo's -- so this script only locates @@ -16,12 +16,12 @@ set -euo pipefail -readonly SHARED_GATE="${UTILS_ROOT:-$HOME/utils}/scripts/check_md_naming.sh" +readonly SHARED_GATE="${UTILS_ROOT:-$HOME/src/utils}/scripts/check_md_naming.sh" main() { if [[ ! -x "$SHARED_GATE" ]]; then echo "Error: shared markdown-naming gate not found at $SHARED_GATE" >&2 - echo " Clone github.com/kuhyx/utils to ~/utils, or set" >&2 + echo " Clone github.com/kuhyx/utils to ~/src/utils, or set" >&2 echo " UTILS_ROOT to where it lives." >&2 exit 1 fi diff --git a/scripts/check_no_crdt_sync_override.sh b/scripts/check_no_crdt_sync_override.sh index 967e6c8..e945a0d 100755 --- a/scripts/check_no_crdt_sync_override.sh +++ b/scripts/check_no_crdt_sync_override.sh @@ -5,7 +5,7 @@ # # The apps depend on crdt_sync as a *git dependency pinned to a tag*, so what # CI builds is whatever that tag points at. A `dependency_overrides:` entry -# pointing at ~/utils/crdt_sync_dart is invaluable while developing an unreleased +# pointing at ~/src/utils/crdt_sync_dart is invaluable while developing an unreleased # library change -- and catastrophic if it survives the commit: local tests go # green against code CI has never seen, and the failure is silent in both # directions. diff --git a/scripts/free_days_interop/check.sh b/scripts/free_days_interop/check.sh index d8ceda2..7f95d33 100755 --- a/scripts/free_days_interop/check.sh +++ b/scripts/free_days_interop/check.sh @@ -4,13 +4,13 @@ # Cross-language gate for the free-day pool. # # phone_app/lib/services/free_day_pool.dart reimplements the rules that -# ~/utils/freedays (Python) owns. Two implementations of one policy drift, +# ~/src/utils/freedays (Python) owns. Two implementations of one policy drift, # and a Dart-only test cannot see it: it is self-consistent with the port. # This writes a pool through the Dart rules and reads it back through the # Python ones, and fails on any disagreement about what is free, what is # spent and how many days are left. # -# Requires the freedays venv that install.sh in ~/utils/freedays creates. +# Requires the freedays venv that install.sh in ~/src/utils/freedays creates. # # Usage: scripts/free_days_interop/check.sh # ============================================================================ @@ -32,7 +32,7 @@ trap cleanup EXIT validate_requirements() { if [[ ! -x "$FREEDAYS_PYTHON" ]]; then - echo "Error: no freedays venv at $FREEDAYS_PYTHON (run ~/utils/freedays/install.sh)" >&2 + echo "Error: no freedays venv at $FREEDAYS_PYTHON (run ~/src/utils/freedays/install.sh)" >&2 exit 1 fi command -v flutter >/dev/null || { echo "Error: flutter not on PATH" >&2; exit 1; } diff --git a/scripts/free_days_interop/verify.py b/scripts/free_days_interop/verify.py index 2c6b9ec..d99e068 100644 --- a/scripts/free_days_interop/verify.py +++ b/scripts/free_days_interop/verify.py @@ -1,6 +1,6 @@ """Replay the fixture's edits through the Python rules and compare the pools. -The Dart port in phone_app is a second implementation of ~/utils/freedays' +The Dart port in phone_app is a second implementation of ~/src/utils/freedays' policy, so it is checked against the original rather than against itself. Comparing Dart's *own* count to what Python reads from Dart's file cannot catch a drift in what Dart writes -- both sides would agree on the wrong diff --git a/scripts/vmbox/harness.sh b/scripts/vmbox/harness.sh index 048000f..3eb6d80 100755 --- a/scripts/vmbox/harness.sh +++ b/scripts/vmbox/harness.sh @@ -69,7 +69,7 @@ step() { validate_requirements() { command -v vm >/dev/null 2>&1 || - die "vmbox is not installed. Run: bash ~/utils/vmbox/install.sh" + die "vmbox is not installed. Run: bash ~/src/utils/vmbox/install.sh" [[ -f "$REPO_DIR/install.sh" ]] || die "cannot find install.sh; run this from the wake-alarm repo" } @@ -114,7 +114,7 @@ run_install() { # a guest ImportError through as a pass, and the three cases downstream # then failed with no hint that the install was the cause. vm run "$VM_NAME" \ - 'cd ~/wake-alarm && bash install.sh && echo INSTALL-OK' \ + 'cd ~/src/wake-alarm && bash install.sh && echo INSTALL-OK' \ >/tmp/wa-install.log 2>&1 || true if ! grep -q 'INSTALL-OK' /tmp/wa-install.log; then tail -20 /tmp/wa-install.log >&2 @@ -130,7 +130,7 @@ run_cases() { step "Running the guest cases" local output output="$(vm run "$VM_NAME" \ - 'bash ~/wake-alarm/scripts/vmbox/guest_cases.sh all' 2>&1)" + 'bash ~/src/wake-alarm/scripts/vmbox/guest_cases.sh all' 2>&1)" echo "$output" grep -q "$GUEST_OK_SENTINEL" <<<"$output" }