Run The Cross-Repo Harness Against Rada-Weather
Use this harness when you need to verify that the HTTP contract between
yaya-engine and the sibling rada-weather repository actually works end to
end — not just that yaya-engine's own Pest suite passes, but that
rada-weather's real ETL client can talk to a really-running yaya-engine
server and get back data that round-trips correctly. This matters because
the contract spans two separate codebases: yaya-engine owns the /api/v1
endpoints, rada-weather owns the client that calls them, and neither repo's
own test suite alone can catch a contract drift between the two.
What it proves¶
harness/test_cross_repo_flow.py is a standalone script, not part of
phpunit.xml/Pest — it is invoked directly with python3. It owns the
entire server lifecycle itself: run migrate:fresh, seed fixture towns, boot
php artisan serve in its own process group, poll /up until the server
answers, run five "seams" of real HTTP requests, then tear the server down
and re-poll the port to confirm it actually died [@harness-script]. The five
seams are documented in the script's module docstring: forecast bulk-insert
followed by a latest-per-town read (checking null-vs-zero preservation and
model dedup), observation bulk-insert into forecast-accuracy scoring, a
season → event → scheduled-alert → nested-history read chain, a
threshold/forecast-config/dispatch-mode PUT+GET+audit round trip, and a
request with no bearer token asserting a 401 [@harness-script].
Precondition: a sibling rada-weather checkout¶
The harness imports rada-weather's actual ETL client module directly:
[@harness-script]. RADA_DIR defaults to
/Users/Koldan/Documents/atram/dev/rada-v2-worktrees/rada-weather-int and
can be overridden with the RADA_WEATHER_DIR environment variable
[@harness-script]. This means the harness cannot run from yaya-engine alone —
you need a checked-out rada-weather repo (or worktree) on disk with
etl/clients/yaya_engine.py present, and the default path is a specific
developer's machine layout, so most environments will need
RADA_WEATHER_DIR set explicitly.
The script also reads ADMIN_API_TOKEN out of yaya-engine's own .env file
and points the client at the locally booted server via
YAYA_ENGINE_API_BASE_URL / YAYA_ENGINE_ADMIN_TOKEN, so it exercises the
same bearer-token auth used in production, not a test-only bypass
[@harness-script].
Running it¶
# from the yaya-engine repo root
RADA_WEATHER_DIR=/path/to/rada-weather python3 harness/test_cross_repo_flow.py
PHP_BIN (default /opt/homebrew/opt/php@8.4/bin/php) and HARNESS_PORT
(default 8011) can also be overridden if your environment needs a
different PHP binary or the default port is taken [@harness-script].
Before booting the server, the harness runs migrate:fresh --force against
your local database, then runs harness/seed_towns.php as a standalone
bootstrap script — it loads bootstrap/app.php directly rather than going
through artisan db:seed [@seed-towns]. migrate:fresh means this harness
resets your local database; do not point it at anything you care about.
seed_towns.php seeds four fixed towns via Town::updateOrCreate keyed on
hardcoded Supabase-issued IDs: Nairobi (500001), Mombasa (500002), Kisumu
(500003), and Bogota Centro (500101), each with yellow/orange/red thresholds
[@seed-towns]. Kisumu is deliberately left unreferenced by any alert the
harness creates later, so it isolates the forecast-accuracy seam's scoring
from the event-chain seam's alert [@seed-towns]. This file is kept out of
database/seeders/ on purpose — it is fixture data whose fixed IDs the
Python script's assertions hardcode, not general-purpose application seed
data.
Verifying success¶
The script prints a [PASS]/[FAIL] line per check as it runs, then a
summary block at the end:
==================== SUMMARY ====================
N/M checks passed
FAILED:
- <check name>
=================================================
and exits with status 0 only if every check passed [@harness-script]. Read
individual [FAIL] lines rather than just the pass count — each failing
check names the exact seam and assertion that broke, which is usually enough
to tell you whether the break is on the yaya-engine side (an /api/v1
response shape changed) or the rada-weather side (the client's request
payload changed).
Recovery notes¶
If the server never comes up, the harness prints the tail of
harness/server.log before failing the server booted on port check
[@harness-script] — check that log first; a common cause is the configured
PHP_BIN not matching an installed PHP version, or HARNESS_PORT already
being in use by a leftover artisan serve process from a previous run.
The teardown() step kills the whole process group with SIGTERM, escalates
to SIGKILL if needed, and then re-polls /up to confirm the port was
actually released [@harness-script]. If a prior run crashed before reaching
teardown(), you may find a stray artisan serve still bound to the
harness port; kill it manually before re-running.
For background on why yaya-engine's own geography/alert data is moving into
its own Postgres instead of staying in the separate Supabase database this
harness's /api/v1 seams ultimately serve, see
Rada v2 Collapse. For the exact
/api/v1 endpoints the harness exercises, see
API v1 Surface.