From 62c5b90c56205ea86b73fc8daed81f17ea69461b Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 20:16:22 -0400 Subject: [PATCH 01/19] check-bench reads absent_text; the skill says what exit 4 means bug-garden/tools/check-bench.mjs ignored the `absent_text` the harness enforces, so bench-delete-plant passed without checking Aloe Vera was gone, and it matched case-sensitively where the harness does not. It now does both as the harness does. The skill's exit-4 line said a skip meant "no build, no matching device". Both of those are refused at enqueue (exit 2 or 5) and never run; exit 4 is a job that was claimed and reported `skipped:`. Regenerated SKILL.md. seed-schedules: the comment counted three explore schedules (there are four) and still expected the TV one to wait for a Fire TV test; Fire TV is parked. Co-Authored-By: Claude Opus 5.5 --- bug-garden/tools/check-bench.mjs | 24 +++++++++++++++--------- collector/scripts/seed-schedules.ts | 4 ++-- fleet/src/skill.ts | 3 ++- skills/fleet-runner/SKILL.md | 2 +- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/bug-garden/tools/check-bench.mjs b/bug-garden/tools/check-bench.mjs index 1afe7b1..73a7ff4 100644 --- a/bug-garden/tools/check-bench.mjs +++ b/bug-garden/tools/check-bench.mjs @@ -6,17 +6,19 @@ * adb exec-out uiautomator dump /dev/tty | node check-bench.mjs - * * Exit 0 and "PASS" when every part of the mission's `check` holds, exit 1 and - * "FAIL" with what was missing otherwise. + * "FAIL" with what was wrong otherwise. * * The rules, which are the ones README.md states for the harness: - * text every string must be a substring (case-sensitive) of some + * text every string must be a substring (case-insensitive) of some * node's text OR content-desc. Content-desc counts because an * icon button's label is its content-desc (the Settings icon on * Home is "Ajustes" in Spanish). + * absent_text no node's text or content-desc may contain any of these + * strings (case-insensitive): "the plant is gone". * screen some node has resource-id "screen_". The bug garden * tags every screen's root that way. * focused_label some node with focused="true" has the string in its text or - * content-desc. + * content-desc (case-insensitive). * * Standalone on purpose: no imports from the collector, so it can be pointed * at a dump from any device without building anything. @@ -40,7 +42,7 @@ const nodes = []; for (const m of xml.matchAll(/]*?)\/?>/g)) { const a = {}; for (const kv of m[1].matchAll(/([\w:-]+)="([^"]*)"/g)) a[kv[1]] = unescape(kv[2]); - nodes.push({ text: a.text ?? "", desc: a["content-desc"] ?? "", id: a["resource-id"] ?? "", focused: a.focused === "true" }); + nodes.push({ text: (a.text ?? "").toLowerCase(), desc: (a["content-desc"] ?? "").toLowerCase(), id: a["resource-id"] ?? "", focused: a.focused === "true" }); } if (nodes.length === 0) { console.log(`FAIL ${mission.id}: the dump has no nodes`); @@ -48,20 +50,24 @@ if (nodes.length === 0) { } const check = mission.check ?? {}; +const shows = (n, t) => n.text.includes(t.toLowerCase()) || n.desc.includes(t.toLowerCase()); const missing = []; for (const t of check.text ?? []) { - if (!nodes.some((n) => n.text.includes(t) || n.desc.includes(t))) missing.push(`text ${JSON.stringify(t)}`); + if (!nodes.some((n) => shows(n, t))) missing.push(`missing text ${JSON.stringify(t)}`); +} +for (const t of check.absent_text ?? []) { + if (nodes.some((n) => shows(n, t))) missing.push(`still shows ${JSON.stringify(t)}`); } if (check.screen && !nodes.some((n) => n.id === `screen_${check.screen}`)) { const on = nodes.find((n) => n.id.startsWith("screen_"))?.id ?? "no tagged screen"; - missing.push(`screen ${check.screen} (on ${on})`); + missing.push(`missing screen ${check.screen} (on ${on})`); } -if (check.focused_label && !nodes.some((n) => n.focused && (n.text.includes(check.focused_label) || n.desc.includes(check.focused_label)))) { - missing.push(`focused ${JSON.stringify(check.focused_label)}`); +if (check.focused_label && !nodes.some((n) => n.focused && shows(n, check.focused_label))) { + missing.push(`missing focus on ${JSON.stringify(check.focused_label)}`); } if (missing.length) { - console.log(`FAIL ${mission.id}: missing ${missing.join(", ")}`); + console.log(`FAIL ${mission.id}: ${missing.join(", ")}`); process.exit(1); } console.log(`PASS ${mission.id}`); diff --git a/collector/scripts/seed-schedules.ts b/collector/scripts/seed-schedules.ts index d176226..b93e8ac 100644 --- a/collector/scripts/seed-schedules.ts +++ b/collector/scripts/seed-schedules.ts @@ -258,8 +258,8 @@ const SCHEDULES: Record = { // Overnight exploratory QA (src/workloads/explore). The night slot the plan // proposes is 22:00-00:30, before Dozehound's video queue takes the Studio's // memory; the window constraint keeps a late claim from running into it. - // All three arrive switched off like every schedule here, and the TV one - // should stay off until the plan's phase-3 test says a model can drive a TV. + // All four arrive switched off like every schedule here. The TV one targets + // Fire TV, which is parked (WB-297): the TV question is answered on tvOS. "nightly-explore-greenfolio": { "cron": "0 22 * * *", "template": { diff --git a/fleet/src/skill.ts b/fleet/src/skill.ts index ae604c6..a08443e 100644 --- a/fleet/src/skill.ts +++ b/fleet/src/skill.ts @@ -15,7 +15,8 @@ const EXIT_MEANING: Record = { failed: "failed, mixed or cancelled: read `failing_step` and `error` before doing anything else", usage: "usage error or invalid spec: fix the flags or the spec; `--validate` names each problem", pending: "still running when `--timeout` ran out: `fleetr wait ID` picks it up again", - skipped: "skipped: nothing ran (no build for the device, no matching device). Never report this as a pass", + skipped: + "skipped: the job was claimed but reported `skipped:` instead of running (the app is not installed, the device was locked by another job, no attached device matched a host job, the host was under memory pressure, no Roku password on the host). Never report this as a pass. A spec nothing can run is refused before it runs instead: exit 2 from validation, or 5 when the collector refuses it at enqueue", error: "refused or unreachable: no permission, unknown workload or job, or no collector. Report it; do not work around it", }; diff --git a/skills/fleet-runner/SKILL.md b/skills/fleet-runner/SKILL.md index b020ab1..a43684c 100644 --- a/skills/fleet-runner/SKILL.md +++ b/skills/fleet-runner/SKILL.md @@ -66,7 +66,7 @@ job) or `running`. `fleetr run`, `job`, `wait` and `retry --wait` exit with: - **1** failed, mixed or cancelled: read `failing_step` and `error` before doing anything else. - **2** usage error or invalid spec: fix the flags or the spec; `--validate` names each problem. - **3** still running when `--timeout` ran out: `fleetr wait ID` picks it up again. -- **4** skipped: nothing ran (no build for the device, no matching device). Never report this as a pass. +- **4** skipped: the job was claimed but reported `skipped:` instead of running (the app is not installed, the device was locked by another job, no attached device matched a host job, the host was under memory pressure, no Roku password on the host). Never report this as a pass. A spec nothing can run is refused before it runs instead: exit 2 from validation, or 5 when the collector refuses it at enqueue. - **5** refused or unreachable: no permission, unknown workload or job, or no collector. Report it; do not work around it. From 267f37f3af1d8165f0dff985ac90d4bd70cbebe9 Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 20:16:22 -0400 Subject: [PATCH 02/19] docs: catch up with 0.8.0 and the explore work The 0.8.0 changelog left out everything merged before the cut that was not the control API: exploratory QA (#70, #73, #74, #77, #78), the device art (#69) and the two runner-android fixes (#75, #76). They get an "Also in this release" section with their not-verified items. A read of every page against the code found ~60 stale spots. The main ones: - Explore: card counts, Holo4's measured status, tool_choice and json_schema requirements, the real gateway-key lookup order and env vars, Fire TV parked for tvOS, the night-queue jobs and priorities, budgets, auth on POST /findings. - Front door: Explore in the README, index and getting-started; 34 workloads, not 28; "no authentication, by design" now says by default and links the opt-in tokens; the Roku driver; strict validation is /api/v1 only; CI-verified items in platforms; ultra and the S8+ in the lab runbook; #45's caveat removed (fixed in 0.6.1). - API and integration: undocumented routes and /metrics, the guards under FLEET_AUTH, CLI flags and env vars, the /api/v1-only owner and shell checks stated plainly. Guides lead with fleetr instead of the deprecated routes, say what ci-enqueue gets wrong (a skip exits 0; no token), add the required app.build to examples, and split an array "enqueue" no endpoint accepts into three specs. - A tvloop section in workloads/host.md, which the catalog already linked. - mkdocs nav listed the ultra runbook twice; it stays under Exploratory QA and the Deploy overview links it. Not done here: the three mermaid diagrams in the explore pages, the 28- workload figure and the pre-device-art dashboard screenshots. They need figures rendered, not text edits. Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 5 +- CHANGELOG.md | 62 +++++++++++++++ CONTRIBUTING.md | 8 +- README.md | 38 +++++---- bug-garden/README.md | 27 ++++--- collector/README.md | 63 +++++++++++---- docs/agents.md | 54 +++++++++++-- docs/api.md | 64 +++++++++++---- docs/concepts.md | 7 ++ docs/dashboard.md | 28 ++++++- docs/deploy/alerts.md | 25 ++++-- docs/deploy/auth.md | 36 +++++++-- docs/deploy/explore-on-ultra.md | 22 ++++-- docs/deploy/headless.md | 4 +- docs/deploy/index.md | 51 +++++++++--- docs/explore/findings.md | 6 +- docs/explore/index.md | 18 +++-- docs/explore/internals.md | 6 +- docs/explore/job.md | 41 +++++++--- docs/explore/missions.md | 6 +- docs/explore/models.md | 7 +- docs/explore/safety.md | 5 +- docs/explore/surfaces.md | 3 +- docs/getting-started.md | 31 ++++++-- docs/index.md | 21 +++-- docs/install/docker.md | 5 +- docs/install/index.md | 6 +- docs/integration/add-a-workload.md | 15 +++- docs/integration/add-your-app.md | 38 +++++++-- docs/integration/cookbook.md | 40 +++++++--- docs/integration/first-job.md | 112 ++++++++++++++++++++++----- docs/integration/index.md | 18 +++-- docs/integration/publish-on-merge.md | 74 ++++++++++++------ docs/lab.md | 23 ++++-- docs/platforms.md | 12 ++- docs/protocol.md | 33 +++++++- docs/workloads/host.md | 83 +++++++++++++++++++- docs/workloads/index.md | 12 ++- docs/workloads/machine.md | 4 +- fleet/README.md | 29 ++++--- mkdocs.yml | 1 - runner-android/README.md | 19 ++++- runner-machine/README.md | 16 +++- 43 files changed, 937 insertions(+), 241 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index a1c68e6..35d170b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,11 +9,14 @@ from an agent, see [`skills/fleet-runner/SKILL.md`](skills/fleet-runner/SKILL.md | Path | What | |---|---| | `collector/` | The brain: Fastify + `node:sqlite`, the queue, the dashboard (`dash/`), the host executor | +| `collector/src/workloads/explore/` | Exploratory QA: a vision model drives an app from mission cards (`collector/examples/missions/`); see `docs/explore/internals.md` | | `collector/src/api/v1/` | The control API. `routes.ts` is the single route table: it registers the routes, generates `openapi.json` and the typed client | | `collector/src/client/` | The generated client (`api.gen.ts`) and its transport. The CLI and the MCP server use nothing else | | `fleet/` | The `fleet` / `fleetr` command: runs a brain or a runner, plus the work commands, `fleet mcp` and the remote gateway | -| `runner-machine/`, `runner-android/`, `runner-ios/`, `runner-roku/`, `desktop/` | Runners. They speak the runner protocol (`/devices/register`, `/devices/:id/next-job`, `/results`), not `/api/v1` | +| `desktop/` | A Tauri menu-bar app around `fleet`. A front door, not a runner; compiled in CI and never launched | +| `runner-machine/`, `runner-android/`, `runner-ios/`, `runner-roku/`, `collector/runner-web/` | Runners. They speak the runner protocol (`/devices/register`, `/devices/:id/next-job`, `/results`), not `/api/v1` | | `skills/fleet-runner/` | The agent skill. Its tables are generated | +| `bug-garden/` | An Android fixture app with twenty planted defects, for scoring exploratory QA | | `docs/` | The mkdocs site. Built with `--strict`, so a broken link fails CI | ## Suites diff --git a/CHANGELOG.md b/CHANGELOG.md index 4506e4e..b1b6bbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,11 @@ a CI job fails when they disagree. the bundle gains a directory the installers do not copy. The installers are fetched from `main`, so re-running the install command fixes an existing 0.8.0 install; no new release is needed. +- **`bug-garden/tools/check-bench.mjs` passed `bench-delete-plant` without + checking the plant was gone.** The card's `check` gained `absent_text`, which + the harness enforces and the standalone checker ignored; it also matched + case-sensitively where the harness does not. It now reads `absent_text` and + matches case-insensitively, as the bug garden's README says. ## [0.8.0] — 2026-10-15 @@ -126,6 +131,63 @@ pull request that touches them: unversioned routes with hand-written types ([#83](https://github.com/addisdev/fleet-runner/issues/83)). +### Also in this release + +These merged into `develop` before 0.8.0 was cut and shipped in it, but were +left out of the notes above on release day. + +- **Exploratory QA, the `explore` workload.** A vision model works through + mission cards on tonight's build, driving a device the way a person would, + while the harness checks every step for crashes, ANRs, frozen and blank + screens, dead controls, accessibility and visual defects. Each candidate is + replayed twice on a clean install and only what reproduces is filed; a crash + stands on its log. See [Exploratory QA](docs/explore/index.md). + ([#70](https://github.com/addisdev/fleet-runner/pull/70)) +- **Findings, verdicts and a morning digest.** `POST /findings` merges repeats + by fingerprint; the dashboard's Findings page has Real, Duplicate, Not a bug + and Agent's mistake. A check under 30% precision after ten verdicts is + switched off for that app (crashes and ANRs never are). GitHub issues stay a + dry run unless `FLEET_GITHUB_ISSUES=1` and a token are set, and the collector + only ever creates them. ([#70](https://github.com/addisdev/fleet-runner/pull/70)) +- **What it drives:** Android phones, tablets, Android TV and Fire TV over adb; + iOS and tvOS through FleetDriver, a new XCUITest command server in + `runner-ios`; a Roku through tvloop. The leash refuses delete, purchase, + invite and sign-out controls unless a card allows them and never types into + a password field. ([#70](https://github.com/addisdev/fleet-runner/pull/70)) +- **The bug garden**, an Android fixture app with twenty planted defects, a + scoring rule and scorer, and twenty bench cards for scoring a model without + a judge. Its screenshot walks capture each screen in the base, dark, Spanish + and large-text settings. ([#70](https://github.com/addisdev/fleet-runner/pull/70), + [#74](https://github.com/addisdev/fleet-runner/pull/74)) +- **Nights on ultra.** `scripts/explore-night.ts` is the night-queue command: + it boots the devices, opens its own tunnel to the brain, runs one job and + exits with its result. `nightly-builds.sh` builds GreenFolio iOS and + Dozehound tvOS from `origin/develop`; the tvOS and iOS nights run after the + products' own night jobs. Holo4 35B-A3B measured 100 of 100 on pointing and + a median step of 6.8 s. Fire TV is parked and the TV question is answered on + tvOS. ([#73](https://github.com/addisdev/fleet-runner/pull/73), + [#77](https://github.com/addisdev/fleet-runner/pull/77), + [#78](https://github.com/addisdev/fleet-runner/pull/78)) +- **The dashboard draws each device as the object it is**: 22 drawings + (phones, tablets, TV boxes and sticks, computers, watches, a headset, a + board, a browser) instead of seven silhouettes, chosen from the model string + first because older agents report a Roku as `android` and an Apple TV or a + watch as `ios`. ([#69](https://github.com/addisdev/fleet-runner/pull/69)) +- **The Android runner starts on Android 7.0 and 7.1.** `RunnerService` called + `startForegroundService`, which exists from API 26, so API 24 and 25 threw + `NoSuchMethodError`; it uses `startService` there now. + ([#75](https://github.com/addisdev/fleet-runner/pull/75)) +- **The Android runner is linted in CI.** The `android.hardware.type.watch` + feature line that failed `lintDebug` is gone; the runner still detects a + watch at run time. ([#76](https://github.com/addisdev/fleet-runner/pull/76)) + +Not verified, from those pull requests: a physical iPhone or Apple TV through +FleetDriver; a real Roku (its developer password is not on the host yet); any +model-driven night on an Apple surface (the iOS and tvOS simulators were driven +without a model); the GreenFolio Android cards; the Android 7 fix on a real +API 24 or 25 device (Robolectric only); and any Wear device, before or after +the lint change. + ## [0.7.2] — 2026-09-30 ### Fixed diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f5e7d56..835d0a2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,7 +11,7 @@ that is not on this shelf is data this repository does not have. ## Running the suites -Four components, four suites. Only run the one you touched. +Five components, five suites. Only run the one you touched. === "collector" @@ -80,7 +80,7 @@ Four components, four suites. Only run the one you touched. npm install && npm test ``` - 122 tests, about a second. This is the easiest component to contribute to + About a second. This is the easiest component to contribute to and the reference implementation of the protocol. ## Things this project learned the hard way @@ -162,7 +162,9 @@ the others. One version covers every component, so a release is one number everywhere. 1. On a branch from `develop`, run `node scripts/version.mjs set X.Y.Z`. It - writes `VERSION` and every component's own version. Then run + writes `VERSION` and every component's own version except the desktop + app's (`desktop/src-tauri/Cargo.toml` and `tauri.conf.json` are not among + the places it writes, and still say 0.5.0). Then run `npm --prefix collector run gen:api`, because `openapi.json` carries the version and CI fails when it is stale. Android's `versionCode` is not derived from it; bump that by hand if the Play Store build needs it. diff --git a/README.md b/README.md index 9ab2b35..c46f42b 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,10 @@ One queued job installs a build on every attached device, runs a UI suite across them, benchmarks llama.cpp on real silicon, classifies a few hundred images through Core ML and LiteRT, screenshots a website on two real phone screens and diffs it against a baseline, or drains a battery on purpose and -plots the curve. Everything lands in one results database with one dashboard -in front of it. +plots the curve. Overnight, a local vision model can use tonight's build the +way a person would and leave a short list of bugs that reproduced on a clean +install. Everything lands in one results database with one dashboard in front +of it. Built to answer a question I could not otherwise answer: **would on-device machine learning actually be good enough to ship in my apps, and on which @@ -27,7 +29,7 @@ hardware?** It turned out to be yes, and the fleet is how I know. | **Problem** | Mobile tests and ML benchmarks are only useful when they run on the hardware, under conditions, and with the exact artifacts a product will ship. | | **System** | One collector owns the registry, queue, leases, artifacts, results and dashboard; independently implemented agents claim work through one tested JSON protocol. | | **Reach** | Five runner implementations across TypeScript, Swift, Kotlin, JavaScript and BrightScript, plus host-driven iOS and Android workloads. | -| **Workloads** | 28 workload types spanning UI tests, visual regression, llama.cpp, Core ML, LiteRT, battery experiments, builds and deployment. | +| **Workloads** | 34 workload types spanning UI tests, visual regression, exploratory QA by a vision model, llama.cpp, Core ML, LiteRT, battery experiments, builds and deployment. | | **Proof** | The first production question found an int8 CPU model faster to load and run than its fp32 GPU alternative while preserving useful accuracy. | **What this demonstrates:** distributed systems, mobile platforms, protocol @@ -40,8 +42,8 @@ trade-offs. ![The Overview while one fan-out benchmark is claimed by three agents at once: the queue fills, three rows appear under running now, and the done count climbs as each reports back](docs/img/fanout.gif) -One `POST /jobs` with `"fanout": true`, and every agent the expression matches -claims its own child job. Above: a laptop and two browser runners on a collector +One job with `"fanout": true`, and every agent the expression matches claims +its own child job. Above: a laptop and two browser runners on a collector that did not exist a minute earlier. Nothing there is staged — it is the shipping agents against a real collector, recorded a frame every 250 ms. @@ -63,8 +65,9 @@ curl -fsSL https://raw.githubusercontent.com/addisdev/fleet-runner/main/install. > The installer verifies the download against the release's `SHASUMS256.txt` and > refuses to install if it does not match. It needs Node 22.13 or newer and > carries no runtime of its own. **`fleet up` itself has been watched to work on -> macOS/arm64 only** -- CI runs the suites on Windows and Linux, which is not the -> same as somebody having run a fleet on one. +> macOS only**, on Apple silicon and on a 2016 Intel Mac that runs this lab's +> brain -- CI runs the suites on Windows and Linux, and starts the container and +> the systemd unit, which is not the same as somebody having run a fleet on one. > **[docs/install/](https://addisdev.github.io/fleet-runner/install/)** is honest > per platform. @@ -137,15 +140,16 @@ something a runner can do without the collector shipping a release. ![Twenty-eight workloads in three columns by who claims them: on the device, on a host, and on a machine](docs/img/workloads.png) -Twenty-eight workloads, and the column a workload sits in is the answer to -"who can physically do this". A benchmark runs inside the app on the phone. An +Thirty-four workloads (the figure predates six of them, `explore` and `tvloop` +among them), and the column a workload sits in is the answer to "who can +physically do this". A benchmark runs inside the app on the phone. An install needs a cable and a Mac. A build needs a checkout and a toolchain. Each has [its own page](https://addisdev.github.io/fleet-runner/workloads/), saying what it measures and what it refuses to guess. ## What is in here -Seven projects in one repository, in three groups: **one brain**, **five +Eight projects in one repository, in three groups: **one brain**, **five runners** that speak its protocol and share no code with each other or with it, and **two front doors** onto the whole thing. They ship independently but they are versioned together, because the protocol is the thing that breaks and a @@ -155,7 +159,7 @@ change to it touches three of them at once. | | What it is | |---|---| -| **[collector/](collector)** | Device registry, job queue with leases, artifact store, results database, scheduler, alert engine, and the dashboard above. Node + Fastify + SQLite, no broker, no cloud. It also holds the host executor, which drives phones from outside over adb, simctl and devicectl. | +| **[collector/](collector)** | Device registry, job queue with leases, artifact store, results database, scheduler, alert engine, and the dashboard above. Node + Fastify + SQLite, no broker, no cloud. It also holds the host executor, which drives phones from outside over adb, simctl and devicectl, and the [exploratory QA](https://addisdev.github.io/fleet-runner/explore/) workload a vision model drives. | **The runners** -- five hand-written implementations of one protocol, in five languages, sharing not one line @@ -175,6 +179,13 @@ languages, sharing not one line | **[fleet/](fleet)** | The CLI. `fleet up` runs this machine's components under a supervisor that backs off and gives up loudly rather than restarting a broken component forever; `fleet doctor` says what the machine can run and why not; `fleet service install` keeps it up. It wraps the three programs above and reimplements none of them. | | **[desktop/](desktop)** | A Tauri menu-bar app around that CLI: a tray menu, role switches, the dashboard in a window, and a notification when a component gives up. It exists to test one hypothesis about macOS local-network permissions, and **it has never been launched**: CI compiles its Rust and that is all -- read its README before believing anything in it. | +**Alongside them** + +| | What it is | +|---|---| +| **[skills/fleet-runner/](skills/fleet-runner)** | The agent skill `fleet skill install` copies into a coding agent: which commands to run in what order. Its tool and exit-code tables are generated from the code. | +| **[bug-garden/](bug-garden)** | An Android app with twenty planted defects, so exploratory QA has something with a known answer to be scored against. | + Each directory has its own README, its own tests and its own CI job, filtered by path so a change to a phone runner does not build the dashboard. @@ -272,8 +283,9 @@ that is not on this shelf is data this repository does not have. the handful of things this project learned the hard way. Behaviour is covered by the [Contributor Covenant](CODE_OF_CONDUCT.md). -**There is no authentication, by design** — the collector is built for a home -LAN or a tailnet. [`SECURITY.md`](SECURITY.md) says what that does and does not +**By default there is no authentication** — the collector is built for a home +LAN or a tailnet, and [scoped tokens](https://addisdev.github.io/fleet-runner/deploy/auth/) +are opt-in. [`SECURITY.md`](SECURITY.md) says what that does and does not cover before you report it. ## License diff --git a/bug-garden/README.md b/bug-garden/README.md index a7712d7..a3ef1ae 100644 --- a/bug-garden/README.md +++ b/bug-garden/README.md @@ -21,8 +21,10 @@ mission and before a replay) puts it back exactly where it started. | `android/` | The app. Kotlin, Jetpack Compose, minSdk 26, AndroidX only. | | `defects.json` | The twenty defects: class, which check should catch it, screen, how to reach it, what it looks like, and a match pattern. | | `tools/check-bench.mjs` | Checks a bench mission's `check` block against a `uiautomator dump`, with no model. | +| `tools/verify-on-device.sh` | Walks to every defect on a device and checks each one still fires; see [Proving it on a device](#proving-it-on-a-device). | | `../collector/examples/missions/bug-garden/` | Seven exploration missions and twenty bench missions (`bench-*`). | -| `../collector/examples/flows/bug-garden/` | `sign-in.yaml` (the missions' setup flow), `smoke.yaml`, and `bench/`, a scripted answer to each bench mission. | +| `../collector/examples/flows/bug-garden/` | `sign-in.yaml` (the missions' setup flow), `smoke.yaml`, `bench/` (a scripted answer to each bench mission), `probes/` (a walk to each defect), and the `t1-*.yaml` walks that take one screenshot of each screen in the base, dark, Spanish and large-text settings. | +| `../collector/scripts/explore-bench/garden-score.ts` | Scores a night's findings against `defects.json` by the rule under [Scoring](#scoring). | ## Build and install @@ -89,7 +91,7 @@ in any of the three languages. ## The defects -Twenty, in eight classes. `defects.json` has the steps for each; in brief: +Twenty, in nine classes. `defects.json` has the steps for each; in brief: | Id | Class | Check | Screen | Defect | |---|---|---|---|---| @@ -202,9 +204,15 @@ with quantity 3", "Change the language to Spanish"), defects off (`launch_args: ["garden_defects=false"]`), and a `check` block a harness evaluates against the final `uiautomator dump`: -- `text`: every string is a case-sensitive substring of some node's `text` or - `content-desc`. (Content-desc counts: the Settings icon on Home is labelled - "Ajustes" in Spanish, so the Spanish check passes on Home or on Settings.) +- `text`: every string is a case-insensitive substring of some node's `text` + or `content-desc`. (Content-desc counts: the Settings icon on Home is + labelled "Ajustes" in Spanish, so the Spanish check passes on Home or on + Settings.) +- `absent_text`: no node's `text` or `content-desc` contains any of these + strings. `bench-delete-plant` uses it to check that Aloe Vera is gone, not + just that the list is one plant shorter. +- `focused_label`: the focused node's label contains the string. The TV cards + use it, since a D-pad screen's state is where focus sits. - `screen`: some node has `resource-id="screen_"`. The checks only use text that the seed data cannot produce by itself. No seeded @@ -213,11 +221,10 @@ the Office, so "Qty 3" can only come from the plant the mission added. Where a check names no screen, it holds on both the plant list and the plant's detail page, which is where a model doing the task naturally ends. -One limit: the check block has no way to say text must be absent, so -`bench-delete-plant` checks for "8 plants" (one fewer than the seed) rather -than for Aloe Vera's absence. - -`tools/check-bench.mjs` implements exactly these rules: +`tools/check-bench.mjs` implements these rules. The one difference from the +harness is `screen`: the harness matches the screen map's name for the final +screen, while the tool, which has only a dump, looks for the bug garden's +`screen_` tag. To check a dump by hand: ```sh adb exec-out uiautomator dump /dev/tty > /tmp/dump.xml diff --git a/collector/README.md b/collector/README.md index 6f40b81..f44d9fd 100644 --- a/collector/README.md +++ b/collector/README.md @@ -1,8 +1,9 @@ # collector *Part of [Fleet Runner](../README.md), alongside the -[Android](../runner-android), [iOS](../runner-ios) and -[desktop](../runner-machine) runners.* +[Android](../runner-android), [iOS](../runner-ios), +[desktop](../runner-machine), [Roku](../runner-roku) and +[web](runner-web) runners.* The brain of **Fleet Runner**: a personal device lab that turns a shelf of old phones into something you can send work to. It holds the device registry, the @@ -12,10 +13,12 @@ One queued job can install a build on every attached device, run a Maestro or XCUITest suite across them, benchmark llama.cpp on real silicon, classify a few hundred images through Core ML and LiteRT, screenshot a website on two real phones and diff it against a baseline, or drain a battery on purpose and -plot the curve. The runners are separate apps — -[iOS](../runner-ios) and -[Android](../runner-android) — that speak a -shared JSON protocol, not shared code. +plot the curve. The runners are separate programs — +[iOS](../runner-ios) (with a tvOS target), +[Android](../runner-android), the [machine](../runner-machine) agent for +laptops and desktops, a [web](runner-web) runner this collector serves at +`/runner`, and a [Roku](../runner-roku) channel — that speak a shared JSON +protocol, not shared code. Node + Fastify + SQLite in WAL mode. No build step for the server, no broker, no cloud. @@ -33,7 +36,7 @@ APK or tapping through a UI test is not something an app can do to itself. ## Run it -Needs Node 22 or newer. Nothing else. +Needs Node 22.13 or newer. Nothing else. ```bash npm install @@ -45,7 +48,7 @@ build a runner from one of the app repos, point it at this address, and enqueue a job: ```bash -curl -X POST http://127.0.0.1:8788/jobs -H 'content-type: application/json' -d '{ +curl -X POST http://127.0.0.1:8788/api/v1/jobs -H 'content-type: application/json' -d '{ "schema": 1, "job_id": "bench-1", "workload": "benchmark", "executor": "device", "backend": "synthetic", "params": { "prompt_tokens": 256, "gen_tokens": 64, "measure_iters": 3 }, @@ -53,6 +56,10 @@ curl -X POST http://127.0.0.1:8788/jobs -H 'content-type: application/json' -d ' }' ``` +Or, with the `fleet` CLI installed, `fleetr run benchmark --backend synthetic +--pool ml-capable --param prompt_tokens=256 ...`, which validates, queues, +waits, and exits with the verdict. + ```bash npm test # typecheck, build the dashboard, run the suite npm run executor # host executor: claims host jobs, drives devices @@ -86,6 +93,15 @@ so it never touches a real fleet's history. | `llm-eval` | machine | Scores what a device generated against an eval set — exact, regex, JSON-shape and model-judged rules — so a quantisation is measured for whether it is still RIGHT, not only how fast it is wrong | | `self-check` | host, machine | The fleet inspects its own hosts: disk, tool versions, clock drift, agents actually loaded | | `archive` / `digest` | host | Pull store reviews and Search Console data; then have the shelf summarize its own reviews using its own models | +| `enrol` | host | Point every attached device's runner at a collector, without anybody typing | +| `explore` | host | A vision model explores a build and files reproduced crashes, hangs, dead controls and accessibility defects as findings | +| `tvloop` | host | tvloop's hardware suite on a Roku the fleet has locked: doctor, sideload, contract tests, a JUnit replay of its flows | +| `model-convert` / `dataset-prep` | machine | A checkpoint into GGUF, Core ML or TFLite; an eval set that carries its licence and source | +| `serve` / `shell` | machine | Host a model for the length of a lease; run a script whose hash the machine's owner pinned by hand | + +That is all 34 shipped workloads. `GET /api/v1/workloads` (or `fleetr +workloads`) lists them with their params and an example spec, plus anything a +registered agent declares that the collector does not know. Full reference, including every parameter and the failure modes worth knowing: **[the documentation](https://addisdev.github.io/fleet-runner/)**. @@ -93,6 +109,16 @@ Start at [Concepts](https://addisdev.github.io/fleet-runner/concepts/) for how the queue thinks, or [Workloads](https://addisdev.github.io/fleet-runner/workloads/) for what it can be asked to do. +## Control API + +Scripts, CI, the `fleet` CLI and AI agents use the versioned API under +`/api/v1`: devices, workloads, jobs (enqueue, validate, wait, cancel, retry), +results and artifacts. `GET /api/v1/openapi.json` describes it, and +`GET /metrics` serves the fleet in Prometheus text format. The older +unversioned routes still work and answer with a `Deprecation` header. Runners +speak the separate runner protocol. See +[the HTTP API](https://addisdev.github.io/fleet-runner/api/). + ## Status and threat model Built and running: every phase of the original plan, a dashboard with live @@ -101,13 +127,20 @@ an [on-device plant-ID evaluation](evals/greenfolio-plant-id.md) across both platforms — 77% top-1 at 7 ms per image on a phone, which answered a product question that had been guesswork. -**There is no authentication, by design.** The collector is reachable on a home -LAN and is meant to stay that way; anyone who can reach it can enqueue a job. -`FLEET_DASH_TOKEN` guards the dashboard's mutations, but that is a speed bump -against a stray browser tab, not an access control — `POST /jobs` stays open so -`curl` and CI keep working. Do not put this on the internet. If you want to, -the honest starting point is that every endpoint would need to be re-thought, -not that a token would need to be added. +**There is no authentication by default.** The collector is reachable on a +home LAN and is meant to stay that way; anyone who can reach it can enqueue a +job. `FLEET_DASH_TOKEN` guards the dashboard's mutations, but that is a speed +bump against a stray browser tab, not an access control — `POST /jobs` stays +open so `curl` and CI keep working. + +Scoped bearer tokens are opt-in: `FLEET_AUTH=tokens` requires one on the +control API, and `FLEET_AUTH_PROTOCOL=token` also on the runner protocol, for +fleets whose runners can send one (the phone, TV and browser runners cannot). +See [Authentication](https://addisdev.github.io/fleet-runner/deploy/auth/). +With tokens on, still serve the collector over TLS or keep it on a private +network: tokens are bearer secrets with no proof of possession, and unless +`FLEET_AUTH_PROTOCOL=token` is set the runner protocol answers anyone who can +reach it. That posture depends on every agent being on the same LAN, which stops being true the moment one of them is a laptop that leaves the house. `FLEET_BIND` diff --git a/docs/agents.md b/docs/agents.md index 17b0836..5c703e8 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -21,22 +21,55 @@ fleetr devices # what is online fleetr workloads benchmark # params and an example spec fleetr run benchmark --pool phones --validate # check without queueing fleetr run benchmark --pool phones # queue, wait, print the verdict -fleetr artifact --out ./artifacts +mkdir -p artifacts && fleetr artifact --out ./artifacts ``` +`--out` is a directory only if it already exists (and has no extension in its +name); then the file lands there under the artifact's own name. Otherwise it is +the file name to write. `--out -` writes to stdout. + - `--json` on every command prints the API's answer and nothing else; progress goes to stderr. - The exit code is the verdict: **0** passed, **1** failed (or mixed, cancelled), **2** usage error or invalid spec, **3** still running when `--timeout` ran out, **4** skipped (nothing ran), **5** refused or unreachable. So `fleetr run ... && deploy` means what it says. -- `fleetr run` takes a workload and flags (`--device`, `--pool`, `--match`, - `--app`, `--param key=value`, `--fanout`) or a whole spec (`--spec FILE`, - `-` for stdin), and validates before it queues. +- `fleetr run` takes a workload and flags, or a whole spec (`--spec FILE`, + `-` for stdin) that the flags then add to, and validates before it queues. + Validation is the control API's, so an unknown top-level field in the spec + is an error. + +| `fleetr run` flag | | +|---|---| +| `--device ID` · `--pool P` · `--match EXPR` | `targets.device_id`, `.pool`, `.match` | +| `--target k=v` | Any other `targets` field; repeatable, dotted keys nest | +| `--exclusive` | `targets.exclusive: true` | +| `--app NAME` | `app.name`, with `--build` and `--sha256` (both default `latest`) and `--platform` | +| `--param k=v` | A workload param; repeatable, dotted keys nest, values parsed as JSON where they parse | +| `--fanout` | One child job per matching device | +| `--backend B` · `--priority N` · `--id JOB_ID` | The spec fields of the same names; `--id` is an idempotency key | +| `--validate` | Validate, print where it would land, and stop | +| `--no-validate` | Skip the dry run and let the enqueue refuse it instead | +| `--no-wait` | Print the job id and exit 0 | +| `--timeout S` | How long to wait for the verdict; default 1800. Exit 3 if it runs out | + +| Other commands | | +|---|---| +| `fleetr devices [--all] [--platform P] [--pool P]` | Online devices, or the whole shelf | +| `fleetr workloads [NAME] [--available]` | What the fleet can run; NAME prints the params schema and an example spec | +| `fleetr job ID` · `fleetr wait ID [--timeout S]` | The verdict now, or when it finishes (default 1800 s); exits with the verdict | +| `fleetr cancel ID [--reason R]` | Cancel; cascades over a fan-out and fails whatever waited on it | +| `fleetr retry ID [--device ID] [--pool P] [--wait]` | Run again under a new id; `--wait` waits and exits with the verdict | +| `fleetr results [JOB] [--device] [--workload] [--job] [--failures] [--limit N]` | Result rows, final rows only unless a job is named; default 20 | +| `fleetr flaky [--device ID] [--app NAME]` | Builds that both passed and failed on one device | +| `fleetr whoami` | Which collector, its auth mode, who you are to it and your scopes | +| `fleetr login [--url U] [--token T]` · `fleetr logout [--url U]` | Save a token for a collector (from `--token` or stdin), or forget it | Which collector: `--url`, then `FLEET_RUNNER_URL`, then `FLEET_URL`, then `~/.fleet/config.json`. Which token: `--token`, then `FLEET_RUNNER_TOKEN`, then -`FLEET_TOKEN`, then what `fleetr login` saved for that URL. +`FLEET_TOKEN`, then what `fleetr login` saved for that URL. `FLEET_SOURCE` +overrides the `source` recorded on jobs (`cli` by default), for example +`FLEET_SOURCE=ci` in a workflow. ## The skill @@ -63,7 +96,9 @@ suite, so they cannot fall behind the binary. } ``` -Add `"--url", "http://host:8788"` to the args to point at another collector. +Add `"--url", "http://host:8788"` to the args to point at another collector, +and `"--token", "fr_..."` if it has tokens on (or set `FLEET_RUNNER_TOKEN` in +the server's `env`; a saved `fleetr login` for that URL also works). Tools: `fleet_devices`, `fleet_workloads`, `fleet_validate`, `fleet_run`, `fleet_job`, `fleet_cancel`, `fleet_retry`, `fleet_results`, `fleet_flaky`, `fleet_artifact`, `fleet_whoami`. Each carries read-only and destructive @@ -71,8 +106,11 @@ annotations and, where it returns a summary, an output schema. Screenshots come back as images. Jobs, workloads, devices and artifacts are also readable as resources (`fleet://job/{id}` and so on). -`fleet_run` waits for the verdict by default (up to 15 minutes locally); pass -`wait: false` and follow with `fleet_job` for anything longer. +`fleet_run` waits for the verdict by default: `timeout_s` defaults to 900 +(15 minutes) locally and is capped at 3600; through the remote gateway it +defaults to 45 s and is capped at 55. Pass `wait: false` and follow with +`fleet_job`, whose `wait_s` holds the call up to 120 s (55 remotely; default 0, +answer now). ## The remote gateway diff --git a/docs/api.md b/docs/api.md index b6b4083..38bf3db 100644 --- a/docs/api.md +++ b/docs/api.md @@ -20,8 +20,8 @@ disagree: the test suite fails if they do. | `GET /api/v1/devices` · `/devices/{id}` | read | The shelf, with status (`online`, `stale`, `offline`) and current job | | `GET /api/v1/workloads` · `/workloads/{name}` | read | What the fleet can run: executor, params schema, a valid example spec, how many live agents can take it | | `GET /api/v1/templates` | read | Saved job templates | -| `GET /api/v1/jobs` | read | Jobs; filter by `status`, `workload`, `device`, `pool`, `source`, `requested_by`, `mine=true`, `from`/`to` | -| `POST /api/v1/jobs` | run | Enqueue. 201 with the job id, its status, and links to its summary and wait URLs | +| `GET /api/v1/jobs` | read | Jobs; filter by `status`, `workload`, `executor` (`device` or `host`), `device`, `pool`, `source`, `requested_by`, `mine=true`, `q` (substring of the job id), `from`/`to` | +| `POST /api/v1/jobs` | run | Enqueue. 201 with the job id, its status, and links to its summary and wait URLs. 422 `no_capable_agent` when no live agent declares the workload (or backend); 400 `no_matching_devices` for a fan-out that matches nothing, and 400 `no_build` when `latest` names no published build | | `POST /api/v1/jobs/validate` | run | Dry run: schema errors by path, the devices it would land on, warnings. Always 200 | | `GET /api/v1/jobs/{id}` | read | One job, with its spec | | `GET /api/v1/jobs/{id}/summary` | read | The verdict across every device, per-device outcomes and artifact refs. Works for a fan-out parent | @@ -31,6 +31,7 @@ disagree: the test suite fails if they do. | `GET /api/v1/artifacts/{sha256}` · `/content` | read | What an artifact is, and its bytes. Active types (HTML, SVG) are served as attachments with a sandbox CSP | | `GET /api/v1/schedules` · `/alerts` | read | Recurring jobs and open alerts | | `GET /api/v1/audit` | admin | Who did what, when tokens are on | +| `GET /metrics` | read | The fleet in Prometheus text format: devices by status, jobs by status, oldest queued job, per-device success ratio over 24 h, open alerts, artifact counts. Computed from the database on each scrape. Not under `/api/v1` and not in the OpenAPI document | **Lists** are `{items, page, per_page, total, pages}` with `page` and `per_page` (≤ 500) query parameters. @@ -45,7 +46,8 @@ disagree: the test suite fails if they do. **Job specs are validated strictly** against `job.schema.json`: an unknown top-level field is refused rather than ignored, so a typo is an error and not a setting that silently did nothing. A workload's params are checked against -its manifest. +its manifest. This is `/api/v1/jobs` (and so `fleetr run`) only: the legacy +`POST /jobs` and `POST /api/jobs` do not refuse unknown fields. **Verdicts** in a summary: `passed`, `failed`, `mixed`, `skipped` (nothing ran, never folded into passed), `cancelled`, and while unfinished `queued`, @@ -57,10 +59,13 @@ unverified; with tokens on, `requested_by` is the token's name, or the person a `delegate` token names in `X-Fleet-Actor`. See [Authentication](deploy/auth.md). **The older routes are deprecated, not removed.** `GET /api/devices`, -`/api/jobs`, `/api/results`, `/devices`, `/schedules`, `GET /jobs/{id}` and +`GET /api/devices/{id}`, `GET /api/jobs`, `GET /api/jobs/{id}`, +`GET /api/results`, `GET /devices`, `GET /schedules`, `GET /jobs/{id}` and `POST /jobs` · `/api/jobs` answer with `Deprecation` (RFC 9745) and a -`Link: <...>; rel="successor-version"` header. There is no sunset date. The -runner protocol is not deprecated. +`Link: <...>; rel="successor-version"` header. Only those exact routes carry +the headers: `/api/devices/{id}/beacons`, `/api/results/bench` and the rest of +the dashboard's read API do not. There is no sunset date. The runner protocol is +not deprecated. Timestamps are ISO-8601 **UTC with a `Z`**. SQLite stores `YYYY-MM-DD HH:MM:SS` with no zone marker, which JavaScript parses as local @@ -69,8 +74,12 @@ Every list is bounded. ## Agent API -Never guarded, whatever `FLEET_DASH_TOKEN` is set to — the fleet has to keep -running whether or not anyone has a token in a browser. +Not guarded by `FLEET_DASH_TOKEN`, with the one exception marked below — the fleet has to keep running whether or +not anyone has a token in a browser. Open by default even with +`FLEET_AUTH=tokens`; with `FLEET_AUTH_PROTOCOL=token` as well, every call here +needs a token with the `agent` scope (a `read` token may still download +artifacts). See [the protocol](protocol.md#authentication-optional) and +[Authentication](deploy/auth.md). | Method & path | Purpose | |---|---| @@ -81,9 +90,15 @@ running whether or not anyone has a token in a browser. | `POST /artifacts` | Upload bytes; returns `sha256` | | `GET /artifacts/:sha256` | Download, supports Range | | `POST /findings` | An `explore` finding from an executor; merged on its fingerprint. See [Findings and verdicts](explore/findings.md#the-api) | +| `POST /api/jobs/:id/mirror` | One raw JPEG frame from an executor driving a device, for the live view. Kept in memory only (the last three frames), never stored; 2 MB cap per frame. The one row here that `FLEET_DASH_TOKEN` does guard; the `explore` workload sends it | ## Queue +With `FLEET_AUTH=tokens`: `POST /jobs` needs `run`; `/jobs/:id/release`, +`/locks/*` and `/events/*` are runner protocol, so they follow +`FLEET_AUTH_PROTOCOL` like the table above; any other GET needs `read` and +anything else `admin`. With auth off, all of it is open. + | Method & path | Purpose | |---|---| | `POST /jobs` | Enqueue. 409 on duplicate `job_id`; the reply's `status` says whether it queued or is `waiting` on `depends_on` | @@ -97,6 +112,8 @@ running whether or not anyone has a token in a browser. | `PATCH /schedules/:id` · `DELETE /schedules/:id` | Enable, disable or remove | | `POST /schedules/tick` | Force an evaluation; fires due schedules at most once a minute | | `POST /power/:pool/:state` | Fire a pool's smart-plug webhook | +| `GET /devices` | The raw registry: descriptor, pools, capabilities, last beacon. Deprecated; `GET /api/v1/devices` replaces it | +| `GET /status-reports` | The last 100 commit-status rows, raw. `GET /api/status-reports` is the dashboard's version | ## Read API @@ -129,6 +146,9 @@ Every endpoint is `GET` and side-effect free. | `GET /api/peers` | Other brains this one knows about, with liveness and device counts | | `GET /api/peers/:id/*` | One peer's read API, fetched server to server. GET only, and only the endpoints on an allow-list | | `GET /api/status-reports` | The commit-status audit trail, posted or not | +| `GET /api/templates` | Saved job templates, with their specs | +| `GET /api/events` · `/api/events/:topic?limit=` | Pipeline-event topics with counts, and one topic's newest events (≤ 500) | +| `GET /api/jobs/:id/mirror` · `/mirror/status` | The live view of a host job as an MJPEG stream (404 when nothing is streaming), and whether a stream exists without opening it | | `GET /api/stream` | SSE | ### `/api/stream` carries a nudge, not a payload @@ -157,15 +177,27 @@ From the [`explore`](explore/index.md) workload. Full shapes and replies are in ## Mutations +With `FLEET_AUTH=tokens`, `POST /api/jobs`, `/api/jobs/preview-targets` and +`/api/jobs/:id/cancel` · `/retry` need `run`, and unlike their `/api/v1` +equivalents they do not check that the job is yours (see +[Authentication](deploy/auth.md#tokens-on-the-collector)). The GET here needs +`read`, `/api/session` needs no token up front, and everything else needs +`admin`. + | Endpoint | Purpose | |---|---| | `POST /api/jobs` | Enqueue; forwards to `POST /jobs` so validation and fan-out have one implementation | -| `POST /api/jobs/:id/cancel` · `/retry` | Cancel, or clone the spec under `-r2` | +| `POST /api/jobs/:id/cancel` · `/retry` | Cancel, or clone the spec under `-r2` (body may set `pool`, `device_id`, `priority`) | | `PATCH /api/jobs/:id` | Set `priority` | | `POST /api/jobs/preview-targets` | "N devices match", using the matcher fan-out uses | | `PATCH /api/devices/:id` | Name, notes, pool override (`pools: null` clears it) | | `DELETE /api/devices/:id` | Forget a device; refuses while it is running a job | | `POST /api/devices/:id/release-lock` | Drop a stuck lock | +| `POST /api/templates` · `DELETE /api/templates/:id` | Save a job template (`id`, `name`, `spec` without a `job_id`), or delete one | +| `POST /api/schedules` · `PATCH` · `DELETE /api/schedules/:id` | Forwarded to `/schedules` | +| `POST /api/schedules/:id/run` | Fire one schedule now, as `-manual-`, without touching its own next firing | +| `POST /api/power/:pool/:state` | Forwarded to `POST /power/:pool/:state` | +| `POST /api/session` · `DELETE /api/session` | Exchange a token for the dashboard's read-only cookie, or clear it. See [Authentication](deploy/auth.md#tokens-on-the-collector) | | `POST /api/visual/baselines/accept` | Set the baseline for (suite, page, profile) | | `GET /api/artifacts/gc-candidates?days=` | Artifacts nothing references | | `DELETE /api/artifacts/:sha256` | Delete one; refuses while referenced or pinned | @@ -177,8 +209,11 @@ From the [`explore`](explore/index.md) workload. Full shapes and replies are in `GET /api/peers/:id/*` proxies rather than letting the browser call the other brain directly, and that is a security decision rather than a convenience. -There is no authentication: opening the read API cross-origin would let any -website in the operator's browser read their whole fleet from any tab. The +There is no authentication by default (see [Authentication](deploy/auth.md)): +opening the read API cross-origin would let any website in the operator's +browser read their whole fleet from any tab. With `FLEET_AUTH=tokens` the proxy +needs `read` like any other GET. It sends no token to the peer, so a peer that +has tokens on answers 401 through it. The proxy keeps one origin, one token, and one place that decides what may be asked for — an **allow-list** of endpoints, because the failure of a deny-list is that the next endpoint somebody adds is exposed by default. @@ -211,10 +246,13 @@ report; both stay visible in `GET /api/devices`. ## The guard `FLEET_DASH_TOKEN` guards every mutation above: set it and the dashboard must -send `X-Fleet-Token`. +send `X-Fleet-Token`. With `FLEET_AUTH=tokens` it steps aside: the scoped token +has already been checked, and every mutation needs `run` or `admin` (see +[Authentication](deploy/auth.md)). **It is deliberately unset on the reference deployment.** The collector is LAN -and tailnet only, `POST /jobs` is open anyway so `curl` and CI keep working, and +and tailnet only with auth off, `POST /jobs` is open then anyway so `curl` and +CI keep working, and the token buys protection against a stray browser tab at the cost of a paste in every browser — not a trade worth making on a home network. It is a speed bump, not an access control. [The network is the access diff --git a/docs/concepts.md b/docs/concepts.md index 44fe2e7..d2718ea 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -66,6 +66,12 @@ registered agent declares.** Anything else is a 422 naming the missing capability, at enqueue time, rather than a job that sits queued forever with nothing to explain why. +Through [`/api/v1/jobs`](api.md#control-api-apiv1) (and so `fleetr run`) the +spec is also validated strictly: an unknown top-level field is refused as +`invalid_spec` rather than ignored, so a typo is an error instead of a setting +that silently did nothing. The older `POST /jobs` does not check for unknown +fields. + That is what lets a new runner add a workload the collector has never heard of without a release in the collector. [Writing a runner](writing-a-runner.md) is the other half of it. @@ -336,6 +342,7 @@ a function in the middle of the executor. | `adb` | Android phones, tablets, TV sticks, headsets and watches — one driver, every Android shape | | `simctl` | booted Apple simulators: iOS, tvOS, watchOS, visionOS | | `devicectl` | cabled or paired Apple hardware: iPhone, iPad, Apple TV, Watch, Vision Pro | +| `roku` | Roku players and Roku TVs on the LAN, found over SSDP and spoken to over ECP. It discovers and launches; it does not install | Every target carries both `platform` (what it is) and `driver` (what reaches it), because the two do not line up: one adb drives four shapes that all call diff --git a/docs/dashboard.md b/docs/dashboard.md index 1c7c1a5..eeb6c64 100644 --- a/docs/dashboard.md +++ b/docs/dashboard.md @@ -6,12 +6,15 @@ SQLite file. One thing to keep alive, one URL, no CORS. | | | |---|---| | ![Overview](img/overview.png) | ![Devices](img/devices.png) | -| **Overview** — the fleet and the queue at a glance, and what is running now | **Devices** — every phone on the shelf with battery, thermal state and what it is doing | +| **Overview** — the fleet and the queue at a glance, and what is running now | **Devices** — every device on the shelf with battery, thermal state and what it is doing | | ![Jobs](img/jobs.png) | ![Results](img/results.png) | | **Jobs** — the queue, with a composer and cancel/retry | **Results** — benchmark trends, eval accuracy, UI-test matrices, drain curves | | ![Visual](img/visual.png) | ![Alerts](img/alerts.png) | | **Visual** — every page across every profile, diffed against its accepted baseline | **Alerts** — one row per condition for as long as it holds, with acknowledge and snooze | +These screenshots are from 2026-09-05. They predate the device drawings +described below, and there is none of the Findings screen. + ## Building it The dashboard is a Preact app with its own `package.json`, built by Vite, and @@ -36,6 +39,13 @@ button for each one. Device detail has a 24 h battery and thermal chart; job detail has per-device results, beacons and artifacts. +**The Devices screen draws each device as the object it is**: one of 22 +drawings, from phones and tablets through Roku boxes and sticks, an Apple TV, +laptops, watches and a headset to a board and a browser. The drawing is chosen +from the model string first, because agents that predate the `platform` field +are reported as `ios` or `android`, so a Roku arrives as `android` and an +Apple TV or Apple Watch as `ios`. + **Filters live in the URL**, so a filtered view is a link you can send. Jobs can be composed, enqueued, cancelled, retried and reprioritised; devices can be renamed, annotated and re-pooled; schedules enabled, fired now and deleted; @@ -43,7 +53,21 @@ artifacts uploaded and garbage-collected. Alerts appear as a banner on every screen. The layout works on a phone, and `?` lists the keyboard shortcuts — `g j` jobs, `g d` devices, `g f` findings, `g n` new job, -`/` search. +`/` search, and on a finding `r`, `d`, `n` or `a` for its verdict (real, +duplicate, not a bug, the agent's mistake). + +## When the collector wants a token + +If the collector runs with `FLEET_AUTH=tokens`, or has `FLEET_DASH_TOKEN` set, +and this browser holds no token, every screen shows a banner with a field to +paste one. With `FLEET_AUTH=tokens` nothing can be seen or changed without it; +`fleet token create NAME --scope read` on the collector's host makes one, and +`run` or `admin` lets you change things too. With only `FLEET_DASH_TOKEN`, +reads work and the banner asks for that value before anything can be changed. +The token is kept in the browser's local storage and sent as `X-Fleet-Token`. +With tokens on it is also exchanged for an HttpOnly session cookie that the +collector honours for reads only, so images and the live stream work. See +[Authentication](deploy/auth.md). ## Naming devices diff --git a/docs/deploy/alerts.md b/docs/deploy/alerts.md index 85d9249..0119178 100644 --- a/docs/deploy/alerts.md +++ b/docs/deploy/alerts.md @@ -1,6 +1,6 @@ # Alerts -Evaluated every 60 seconds. **Alerts are state, not events**: one row per (rule, +Evaluated every 60 seconds (`FLEET_ALERT_TICK_MS`). **Alerts are state, not events**: one row per (rule, subject) for as long as the condition holds, resolved when it stops. A device offline for six hours is one row with a rising `seen_count`, not 360 notifications — and nothing is notified twice, ever. @@ -16,12 +16,16 @@ notifications — and nothing is notified twice, ever. | `thermal-critical` | A device still reporting is thermally critical | | `low-battery` | Below `FLEET_ALERT_LOW_BATTERY_PCT` (default 15) and not charging | | `job-failed` | A job failed in the last 24 h | -| `job-stuck` | Claimed, lease still being renewed, but no result rows after 2× the lease TTL | -| `benchmark-regressed` | Decode throughput fell more than `FLEET_ALERT_REGRESSION_PCT` (10%) against its own 7-day median | +| `job-stuck` | Claimed, lease still being renewed, but no result rows after `FLEET_ALERT_STUCK_LEASE_MULTIPLE` (default 2) × the lease TTL | +| `benchmark-regressed` | Decode throughput fell more than `FLEET_ALERT_REGRESSION_PCT` (10%) against its own `FLEET_ALERT_REGRESSION_DAYS` (7) day median | | `cold-start-regressed` | Launch time rose past the same threshold against its own median | | `batch-regressed` | Top-1 accuracy fell past the same threshold | -| `schedule-missed` | An enabled schedule that has run before missed its firing by 5 min | -| `db-size` / `log-size` | Past `FLEET_ALERT_DB_BYTES` / `FLEET_ALERT_LOG_BYTES` | +| `schedule-missed` | An enabled schedule that has run before missed its firing by `FLEET_ALERT_SCHEDULE_LATE_S` (default 5 min) | +| `db-size` / `log-size` | Past `FLEET_ALERT_DB_BYTES` (default 2 GiB) / `FLEET_ALERT_LOG_BYTES` (200 MiB) | + +Every threshold is read once, at collector start; a value that is not a +positive number falls back to the default. `job-failed`'s 24-hour window is +fixed. `job-stuck` is the case the lease sweep cannot see: beacons keep renewing the claim, so the job never lapses, and without this rule a runner that is alive but @@ -37,8 +41,9 @@ The comparison key matters more than the threshold. Two runs are only comparable on the same device with the same model, quant and backend, and **comparing across any of those is how a "regression" turns out to be a different model**. -The baseline is the median of the trailing seven days, needs at least four prior -runs, and the alert's subject is keyed on the same tuple the comparison was — so +The baseline is the median of the trailing seven days +(`FLEET_ALERT_REGRESSION_DAYS`), needs at least four prior runs +(`FLEET_ALERT_REGRESSION_MIN_SAMPLES`), and the alert's subject is keyed on the same tuple the comparison was — so a device that has genuinely got slower is one alert with a rising `seen_count`, not a new one every night. @@ -62,6 +67,12 @@ host. Point `FLEET_ALERT_WEBHOOK` at the collector's own loopback port and let [the tunnel's](networking.md) reverse forward deliver it — loopback at both ends, so the alert never crosses the LAN and never leaves the house. +## Reading them + +The Alerts screen, `GET /api/v1/alerts` (`?state=open,acked,snoozed,resolved`; +all but resolved by default, `read` scope when tokens are on), and the +`fleet_alerts_open` gauge on [`GET /metrics`](../api.md#control-api-apiv1). + ## Quieting one **Acknowledge** keeps an alert listed but stops it nagging. **Snooze** quiets it diff --git a/docs/deploy/auth.md b/docs/deploy/auth.md index c496f55..b644a06 100644 --- a/docs/deploy/auth.md +++ b/docs/deploy/auth.md @@ -24,11 +24,15 @@ environment or in the `env` object of `~/.fleet/config.json` (`"env": {"FLEET_AUTH": "tokens"}`). The token file is re-read when it changes, so creating and revoking need no restart. +The file is `$FLEET_DATA_DIR/tokens.json` (`~/.fleet/data/tokens.json` under +`fleet up`). `FLEET_TOKENS_FILE` moves it for the collector, and +`fleet token ... --tokens-file PATH` points the command at the same place. + | Scope | Allows | |---|---| | `read` | Every GET: devices, jobs, results, artifacts, the dashboard's data | -| `run` | Enqueue and validate jobs; cancel or retry the jobs this token started | -| `admin` | Everything else: other people's jobs, devices, schedules, the audit log | +| `run` | Enqueue and validate jobs; cancel or retry the jobs this token started (checked on `/api/v1` only, see below) | +| `admin` | Everything else: other people's jobs, devices, schedules, the audit log, and the `shell` workload | | `agent` | The runner protocol, when `FLEET_AUTH_PROTOCOL=token` | | `delegate` | Name the person a request is for (`X-Fleet-Actor`). For a gateway only | @@ -36,6 +40,17 @@ changes, so creating and revoking need no restart. `delegate`, because a token that can put a name on a job can put *anyone's* name on it. +**Two checks are made on `/api/v1` only, and not yet on the older routes.** +`POST /api/v1/jobs/{id}/cancel` and `/retry` refuse a `run` token acting on a +job somebody else started; the dashboard's `POST /api/jobs/:id/cancel` and +`/retry` need `run` and check nothing more, so any `run` token can cancel or +retry any job there. Likewise `POST /api/v1/jobs` refuses the `shell` workload +to a token without `admin`, but `POST /jobs` and `POST /api/jobs` accept it +from any `run` token. Both are gaps in the code, not intended behaviour. Until +they close, treat `run` as able to stop anyone's job. For `shell`, what bounds +it is each machine's own allowlist of script hashes: a machine with no +allowlist file never declares `shell`, so nothing can be sent to it. + **Runners stay open unless you close them.** Phones, TVs and the browser runner do not send tokens, so with `FLEET_AUTH=tokens` the runner protocol still answers without one. `FLEET_AUTH_PROTOCOL=token` requires the `agent` @@ -43,10 +58,12 @@ scope; set it only when every runner can send `FLEET_TOKEN` (runner-machine and the host executor can). **People** run `fleetr login` once per collector; the token is saved to -`~/.fleet/credentials.json` (mode 0600), keyed by URL. **The dashboard** asks -for a token in a banner and exchanges it for an HttpOnly, SameSite=Strict -cookie that is honoured for reads only, so a link on another site cannot -make the browser change anything. +`~/.fleet/credentials.json` (mode 0600), keyed by URL. `fleetr whoami` shows +what the collector makes of it and `fleetr logout` forgets it; which token wins +when several are set is in [AI agents and automation](../agents.md#the-cli). +**The dashboard** asks for a token in a banner and exchanges it for an +HttpOnly, SameSite=Strict cookie that is honoured for reads only, so a link on +another site cannot make the browser change anything. **Every change is audited**: who, through which front door (`source`), what, and the result, readable at `GET /api/v1/audit` with `admin`. @@ -95,6 +112,10 @@ stateless, so any number of replicas can sit behind one. | Flag | Environment | Default | | |---|---|---|---| +| `--url` | `FLEET_RUNNER_URL`, `FLEET_URL` | the config | The collector, resolved the way the CLI resolves it | +| `--token` | `FLEET_RUNNER_TOKEN`, `FLEET_TOKEN` | saved login | The gateway's own collector token (`run,delegate`) | +| `--host` | `FLEET_MCP_HOST` | `127.0.0.1` | Address to listen on. `0.0.0.0` behind a proxy | +| `--port` | `FLEET_MCP_PORT` | 8790 | | | `--issuer` | `FLEET_MCP_ISSUER` | | The IdP's issuer, exactly as in the token's `iss` | | `--audience` | `FLEET_MCP_AUDIENCE` | | This resource, as in `aud`. Required with `--issuer` | | `--jwks` | `FLEET_MCP_JWKS` | discovered | Signing keys URL, if not at the issuer's OpenID configuration | @@ -107,7 +128,8 @@ stateless, so any number of replicas can sit behind one. | `--no-auth` | | | Development only; refused off loopback | Endpoints: `POST /mcp`, `GET /.well-known/oauth-protected-resource/mcp` -(RFC 9728: tells a client which IdP to sign in with), `GET /healthz`. A +(RFC 9728: tells a client which IdP to sign in with; also answered without the +`/mcp` suffix), `GET /healthz`. A request without a valid token gets a 401 whose `WWW-Authenticate` header points at that metadata, which is how an MCP client discovers where to log in. diff --git a/docs/deploy/explore-on-ultra.md b/docs/deploy/explore-on-ultra.md index 34d0ad6..fdd7323 100644 --- a/docs/deploy/explore-on-ultra.md +++ b/docs/deploy/explore-on-ultra.md @@ -106,8 +106,10 @@ Serve it two ways and keep the faster one behind the gateway name `pilot`: ``` Merge `deploy/explore/litellm-pilot.yaml` into the gateway's `model_list`. -`pilot` has no cloud fallback on purpose. Then put the gateway key in the -Keychain, where the workload reads it: +`pilot` has no cloud fallback on purpose. On ultra the gateway key is the file +`~/.config/harness/keys/fleet.key` (see the table at the top: nothing started +over SSH or by launchd can write the login Keychain there). On a laptop, the +Keychain works: ```bash security add-generic-password -s fleet-explore-gateway -a gateway -w @@ -180,10 +182,12 @@ replayed real-build findings marked real. Under 30% real: switch the judge off ## Phase 3: the TV question The fake Roku first (`npx @tvloop/fakeroku --agent`), then the real Roku once -its developer password is in fleet-host's Keychain, then Fire TV through adb -D-pad keys. The TV cards are in `examples/missions/fakeroku/` and -`examples/missions/dozehound-tv/`; each bench card's end state is a focused -element the harness can read. +its developer password is in fleet-host's Keychain (WB-101). Fire TV was the +next step and is parked (WB-297, above), so the question is answered on a tvOS +simulator with the Dozehound stub catalog: the `fleet-explore-tv` night. The TV +cards are in `examples/missions/fakeroku/`, `examples/missions/dozehound-tv/` +and `examples/missions/dozehound-tvos/`; each bench card's end state is a +focused element the harness can read. **Exit:** the better of Holo4 and plain Qwen completes at least half of 20 navigation missions. If neither does, TVs keep scripted tvloop replays with the @@ -213,7 +217,8 @@ FLEET_URL=http://127.0.0.1:18788 npm run seed:schedules ultra is on the Mini's side of the home network and cannot route to fleet-host's 192.168.50.x address, so the tunnel goes over the tailnet (`fleet-ts`). Turn `nightly-explore-greenfolio` on from the Schedules page after -phase 2 passes; leave `nightly-explore-dozehound-tv` off until phase 3 does. +phase 2 passes. Leave `nightly-explore-dozehound-tv` off: it is the Fire TV +schedule, parked with Fire TV itself. On the brain, set `FLEET_FINDINGS_DIGEST_AT=07:30` for the morning digest through the alert webhook. GitHub issues stay dry-run until both @@ -222,7 +227,8 @@ through the alert webhook. GitHub issues stay dry-run until both `/api/findings/issues` shows what would have been filed. **Exit:** seven nights in a row without help, morning triage under ten minutes, -and no night over five new findings per app. +and no night over five new findings per app (the bug garden's night allows 25 +on purpose and does not count). ## Guards diff --git a/docs/deploy/headless.md b/docs/deploy/headless.md index 8b6a06a..d149b17 100644 --- a/docs/deploy/headless.md +++ b/docs/deploy/headless.md @@ -14,8 +14,8 @@ a Mac collector reachable at all. `collector/deploy/install-agent.sh` and `runner-machine/deploy/install-agent.sh` are superseded by [`fleet service install`](index.md#keeping-it-up-fleet-service), which writes - one unit running `fleet up` instead of one unit per component. They ship one - more release and are then removed. + one unit running `fleet up` instead of one unit per component. Deprecated + since 0.5.0, they still ship in 0.8.0 and no removal date is set. They are documented here rather than deleted because they have more mileage: `fleet service install` now runs a real fleet's brain under launchd diff --git a/docs/deploy/index.md b/docs/deploy/index.md index e9feb26..8760078 100644 --- a/docs/deploy/index.md +++ b/docs/deploy/index.md @@ -65,9 +65,9 @@ depends on the machine: Also run, on macOS, are the older per-component plists in `collector/deploy/` and `runner-machine/deploy/`. Those are what the reference deployment actually uses today, and they are documented in - [headless hosts](headless.md). They are deprecated -- they ship one more - release and are then removed in favour of `fleet service` -- but they are - the ones with mileage on them. + [headless hosts](headless.md). They have been deprecated in favour of + `fleet service` since 0.5.0 and still ship in 0.8.0, with no removal date + set, because they are the ones with mileage on them. **One unit, not five.** The old deployment had a plist each for the collector, the executor, the iOS executor, the tunnel and the agent. One unit is the @@ -100,10 +100,11 @@ supervisor, which is the right division of labour. ## Binding and exposure -**There is no authentication, by design.** Anyone who can reach the collector +**There is no authentication by default.** Anyone who can reach the collector can enqueue a job. `FLEET_DASH_TOKEN` guards the dashboard's mutations but -`POST /jobs` stays open so `curl` and CI keep working. **Do not put this on the -internet.** +`POST /jobs` stays open so `curl` and CI keep working. Scoped tokens are opt-in +(`FLEET_AUTH=tokens`, and `FLEET_AUTH_PROTOCOL=token` for the runners): see +[Authentication](auth.md). With auth off, **do not put this on the internet.** The network is the access control, and `FLEET_BIND` is what decides which network that is. It takes a comma-separated list of addresses to answer on and @@ -121,6 +122,35 @@ wifi, no guest network. That matters more than it looks, because the LAN-only assumption stops being true the moment one of your agents is a laptop that leaves the house. +### The other collector settings + +`fleet up` sets the paths below from `~/.fleet`; started by hand, the +collector resolves the relative defaults against its working directory. The +port, bind list, tailnet allowlist, data and artifact directories and +`FLEET_NAME` are covered above and in [Install](../install/index.md). + +| Variable | Default | | +|---|---|---| +| `FLEET_DISCOVERY` | off (`fleet up` passes `collector.discovery`) | `1` advertises the collector over mDNS, below | +| `FLEET_PEERS` | none | Comma-separated base URLs of other collectors, for [more than one brain](#more-than-one-brain) | +| `FLEET_POWER_CONFIG` | `power.json` | The pool-to-smart-plug map, see [Energy](#energy) | +| `FLEET_SWEEP_MS` | 15000 | How often expired leases are swept | +| `FLEET_SCHEDULER_TICK_MS` | 20000 | How often schedules are evaluated | +| `FLEET_DASH_DIST` | `dash/dist` | The built dashboard. Missing, the collector serves a placeholder rather than failing | +| `FLEET_LOG` | `info` | Log level | +| `FLEET_LOG_FILE` | `~/Library/Logs/fleet-collector.log`; `~/.fleet/logs/collector.log` under `fleet up` | Where the service manager sends the collector's output. The collector does not write it; it reports its size and alerts on it (`log-size`) | +| `FLEET_TOKENS_FILE` | `$FLEET_DATA_DIR/tokens.json` | See [Authentication](auth.md) | + +Alert thresholds are `FLEET_ALERT_*`, listed in [Alerts](alerts.md). + +Three more belong to the machine agent, not the collector: + +| Variable | Default | | +|---|---|---| +| `FLEET_DEVICE_TTL_S` | unset: a permanent shelf device | Registers with `ttl_s`, for an agent whose absence is normal. See [the protocol](../protocol.md#ttl_s-if-you-are-temporary). `fleet up` passes `agent.ttlS` | +| `FLEET_SHELL_ALLOWLIST` | `$FLEET_CACHE_DIR/shell-allowlist.txt` (`~/.fleet/cache/` under `fleet up`) | The sha256 list of scripts the `shell` workload may run. No file, no `shell` capability | +| `FLEET_SERVE_BIND` | `loopback` | Where the `serve` workload's model server listens when the job does not say: `loopback`, `tailnet`, or this machine's tailnet address. Never a wildcard or a LAN address | + ### mDNS advertising is off by default `fleet config set collector.discovery true` makes a collector announce itself as @@ -189,9 +219,9 @@ brain A is A's job and lands in A's database, whatever device ran it. `GET /api/peers` lists other brains and `/api/peers/:id/*` proxies one peer's read API server to server, which the dashboard's brain switcher uses. The proxy -rather than CORS is a security decision: there is no authentication, so opening -the read API cross-origin would let any website in the operator's browser read -the whole fleet from any tab. Peers are addressed by stable id rather than URL, +rather than CORS is a security decision: there is no authentication by default +(see [Authentication](auth.md)), so opening the read API cross-origin would let +any website in the operator's browser read the whole fleet from any tab. Peers are addressed by stable id rather than URL, so a link cannot be turned into a request to an arbitrary host by editing the address bar; only an allow-list of endpoints is proxied; and nothing that mutates is proxied at all. @@ -294,5 +324,8 @@ Three things are deliberate and worth knowing before you trust a figure: - **[Networking](networking.md)** -- the SSH tunnel, why it exists, and network shaping. - **[The iOS executor](ios-executor.md)** -- standing one up on a Mac with Xcode. +- **[Exploratory QA on ultra](explore-on-ultra.md)** -- the executor, emulator, + simulators and model gateway behind the overnight explore jobs. Listed under + Exploratory QA in the navigation. - **[Alerts](alerts.md)** -- the rules, and getting a notification somewhere you will see it. diff --git a/docs/explore/findings.md b/docs/explore/findings.md index 8f0267e..52dc2d7 100644 --- a/docs/explore/findings.md +++ b/docs/explore/findings.md @@ -98,8 +98,10 @@ fact created. ### `POST /findings` -From executors. Open, like `POST /results`: the collector's access control for -executors is the network, not the dashboard token. The body is an +From executors. A protocol route, like `POST /results`: by default the +collector's access control for executors is the network, not the dashboard +token, and with `FLEET_AUTH_PROTOCOL=token` it needs a token with the `agent` +scope ([Authentication](../deploy/auth.md)). The body is an `ExploreFinding`: ```json diff --git a/docs/explore/index.md b/docs/explore/index.md index 30b7689..378041f 100644 --- a/docs/explore/index.md +++ b/docs/explore/index.md @@ -138,9 +138,15 @@ a second report. Your verdicts decide which checks keep running. ## Honest status -Built and tested on 2 October 2026, before the Mac Studio it is meant to run on -had arrived. Every real-device run so far used **Qwen3.5-2B** as a stand-in -model on a laptop, so those runs say the harness works and say nothing about how -good the intended model is. The intended driver is **Holo4 35B-A3B** (Apache -2.0); every Holo4 number in these pages is the vendor's own until -[the measurements](measuring.md) are taken on ultra. +Built and tested on 2 October 2026 on a laptop, with **Qwen3.5-2B** standing in +for the real model. Those runs say the harness works and nothing about how good +the intended model is. + +On 8 October the intended driver, **Holo4 35B-A3B** (Apache 2.0), was +[measured on ultra](../deploy/explore-on-ultra.md#measured-on-8-october-2026): +100 of 100 pointing targets, a median whole step of 6.8 s, and a tool call on +all 40 steps of a mission once `tool_choice` was `required`. Its first +bug-garden mission filed BG-01 and BG-03, and a night through the brain filed +BG-16, each reproduced 2/2. That is one model on one fixture app. No +model-driven night has run on an Apple surface yet, and the phase exits in the +[ultra runbook](../deploy/explore-on-ultra.md) are still the bar. diff --git a/docs/explore/internals.md b/docs/explore/internals.md index c1ad7f0..85e1561 100644 --- a/docs/explore/internals.md +++ b/docs/explore/internals.md @@ -30,8 +30,12 @@ collector/scripts/explore-run.ts missions on a device, no collec collector/scripts/explore-bench/ pointing, steptime, image-size, bakeoff, garden-score collector/scripts/explore-apple-check.ts FleetDriver end to end on a simulator collector/scripts/explore-tv-check.ts the TV actuators end to end +collector/scripts/explore-night.ts ultra's night-queue command: devices, tunnel, one job collector/examples/missions/ mission cards -collector/deploy/explore/ gateway names, Holo4 fetch, night device script +collector/examples/jobs/explore-*-ultra.json the specs ultra's nights run +collector/deploy/explore/ gateway names, Holo4 fetch, night-devices.sh +collector/deploy/explore/nightly-builds.sh tonight's iOS and tvOS builds from origin/develop +collector/deploy/explore/night/ the four night-queue manifests and their priorities ``` ## The contract diff --git a/docs/explore/job.md b/docs/explore/job.md index 4766967..916b819 100644 --- a/docs/explore/job.md +++ b/docs/explore/job.md @@ -25,14 +25,14 @@ And the weekly mission bench: | `bench` | `false` | Run only `bench-` cards, with no judge; file nothing; report end states reached | | `model` | see [below](#models) | The driver | | `judge` | see below | The second model, or `false` for none | -| `minutes` | 150 | The night's budget, per device | +| `minutes` | 150 | The night's budget, per device (1 to 600) | | `steps` | | Cap every card at this many steps, for a short trial night | -| `findings_per_night` | 5 | New findings filed per app per night | +| `findings_per_night` | 5 | New findings filed per app per night (0 to 50) | | `replay_attempts` | 2 | Clean-install replays per candidate (1 to 5) | | `confirm_per_mission` | 6 | Candidates replayed per mission, worst first | | `conditions` | `["baseline"]` | Rotated across the night's missions; see [below](#conditions) | -| `changed` | | `{repo, since}` reads `git log`; `{files: [...]}` takes a list. Puts matching cards first | -| `previous_app` | | `{sha256}` of the previous build; each reproduced finding is replayed on it too | +| `changed` | | `{repo, since}` reads `git log` (`since` is a sha or a git date, default `24 hours ago`); `{files: [...]}` takes a list. Puts matching cards first | +| `previous_app` | | `{sha256, build?}` of the previous build; each reproduced finding is replayed on it too | | `surface` | from the device | `touch` or `dpad`. Android TV, Fire TV, Roku and tvOS default to `dpad` | | `credentials` | | `{account, email_var, password_var}` for setup flows; the password comes from the host's Keychain | | `mirror` | `true` | Stream each step's screenshot to the job's live view on the dashboard | @@ -54,8 +54,11 @@ And the weekly mission bench: | `extra_body` | | Merged into every request, for server-specific switches | The API key is never in the spec (the collector refuses specs carrying -`api_key` or `token`). It comes from the executor's environment -(`FLEET_EXPLORE_API_KEY`) or its Keychain: +`api_key` or `token`). The executor looks for it in this order: +`FLEET_EXPLORE_API_KEY`, then `HARNESS_KEY` (what ultra's night queue hands +its jobs), then the file `FLEET_EXPLORE_API_KEY_FILE` (default +`~/.config/harness/keys/fleet.key`; a process started over SSH or by launchd +cannot write the login Keychain), then the Keychain: ```bash security add-generic-password -s fleet-explore-gateway -a gateway -w @@ -88,11 +91,14 @@ the judge which language to expect, so English left in a Spanish build is a | Variable | Default | | |---|---|---| -| `FLEET_EXPLORE_BASE_URL` | `http://ultra.local:4000` | The gateway | +| `FLEET_EXPLORE_BASE_URL` | `HARNESS_GATEWAY`, then `http://ultra.local:4000` | The gateway | | `FLEET_EXPLORE_MODEL` | `pilot` | The driver's name on it | | `FLEET_EXPLORE_JUDGE_MODEL` | `vision` | The judge's name on it | -| `FLEET_EXPLORE_API_KEY` | | Otherwise the Keychain item `fleet-explore-gateway` | -| `FLEET_MISSIONS_DIR` | `examples/missions` | Mission cards | +| `FLEET_EXPLORE_API_KEY` | | Otherwise `HARNESS_KEY`, the key file, then the Keychain item `fleet-explore-gateway` | +| `FLEET_EXPLORE_API_KEY_FILE` | `~/.config/harness/keys/fleet.key` | The key as a file | +| `FLEET_KEYCHAIN_SERVICE` | `fleet-ui-test` | The Keychain service holding the sign-in passwords `credentials` names | +| `FLEET_DASH_TOKEN` | | Sent with live-view frames, when the brain guards the dashboard with one | +| `FLEET_MISSIONS_DIR` | `examples/missions` in the working directory, then beside the bundle | Mission cards | | `FLEET_FLOWS_DIR` | `examples/flows` | Setup flows | | `FLEET_STATE_DIR` | `~/.fleet` | Screen maps and last-run times live under `explore//` | | `FLEET_TVLOOP_DIR` | `~/tvloop` | A built tvloop checkout, for Rokus | @@ -159,6 +165,21 @@ recommended: a night that died halfway should not start again at 3 a.m. | Schedule | When | What | |---|---|---| | `nightly-explore-greenfolio` | 22:00 daily, window 22–01 | GreenFolio Android on ultra, 100 minutes, six conditions, aimed at the day's commits | -| `nightly-explore-dozehound-tv` | 23:45 daily | Dozehound on Fire TV, D-pad, 40 minutes. Leave off until a model passes the TV test | +| `nightly-explore-dozehound-tv` | 23:45 daily | Dozehound on Fire TV, D-pad, 40 minutes. Parked: the Fire TV app needs the production backend, which is the owner's call (WB-297); the TV question is being answered on tvOS instead | | `weekly-explore-shelf` | Wednesdays 23:00 | GreenFolio on the Galaxy S8+ (Android 9) through fleet-host's executor | | `weekly-explore-bench` | Sundays 22:00 | The bug garden's bench cards, for a weekly model score | + +The nights that actually run today do not come from these schedules. On ultra +the harness's night queue runs `scripts/explore-night.ts` from the manifests in +`collector/deploy/explore/night/`, each with a job spec from +`examples/jobs/`: + +| Night job | Priority | Spec | +|---|---|---| +| `fleet-explore-builds` | 19 | none: `deploy/explore/nightly-builds.sh` builds GreenFolio iOS and Dozehound tvOS from `origin/develop` and uploads them | +| `fleet-explore` | 20 | `explore-garden-ultra.json`, the bug garden on the Android emulator | +| `fleet-explore-tv` | 85 | `explore-dozehound-tvos-ultra.json` and the two tvOS bench specs, on a tvOS simulator | +| `fleet-explore-apple` | 86 | `explore-greenfolio-ios-ultra.json`, on an iOS simulator | + +A lower number runs earlier; the products' own night jobs sit between 20 and +85. [Running it on ultra](../deploy/explore-on-ultra.md) has the setup. diff --git a/docs/explore/missions.md b/docs/explore/missions.md index 3948da1..781ffa1 100644 --- a/docs/explore/missions.md +++ b/docs/explore/missions.md @@ -119,8 +119,8 @@ evaluate without a model: | `focused_label` | The focused element's label contains it (TV cards) | | `screen` | The final screen's name contains it | -Bench cards run only in bench mode (`params.bench: true`) and exploration cards -only outside it. Bench missions run with no judge and file nothing; the number +Bench cards run only in bench mode (`params.bench: true`), unless `missions` +names them, and exploration cards only outside it. Bench missions run with no judge and file nothing; the number that comes out is how many end states the model reached. See [Measuring a model](measuring.md#the-mission-bench-b4). @@ -132,5 +132,5 @@ that comes out is how many end states the model reached. See | `greenfolio/` | 3 Android: the sign-in gate, forgot password, a read-only signed-in tour | | `greenfolio-ios/` | 2 iOS, offline: the sign-in gate, creating an account with no network | | `dozehound-tv/` | Android TV / Fire TV: 3 exploration, 10 bench | -| `dozehound-tvos/` | tvOS: 1 exploration, 1 bench (its end-state text is unverified) | +| `dozehound-tvos/` | tvOS: 1 exploration, 10 bench, end states taken from a hand walk on a tvOS 26.5 simulator | | `fakeroku/` | 10 bench, for tvloop's fake Roku | diff --git a/docs/explore/models.md b/docs/explore/models.md index 0313138..aab84b8 100644 --- a/docs/explore/models.md +++ b/docs/explore/models.md @@ -16,6 +16,11 @@ to agree with itself. as `{...}`, or as a bare JSON object with `name` and `arguments`, are accepted too, so a model is not marked down for where its chat template puts them. +- **`tool_choice: "required"`.** The loop sends it on every turn. Holo4 under + `auto` sometimes answered its second turn in prose; a server that ignores the + field gets the same failure. +- **For the judge, `response_format` of type `json_schema`.** The judge asks + for a schema, not `json_object`, because LM Studio refuses `json_object`. - **About 16k tokens of context** by the middle of a mission, more with `keep_shots` raised. @@ -156,7 +161,7 @@ On a laptop that cannot hold Holo4, these were used: | Model | Size (Q4 + projector) | Licence | Notes | |---|---|---|---| -| Qwen3.5-2B | 1.3 GB + 0.7 GB | Apache-2.0 | Drove every real-device run so far. Needs `tree_hints` | +| Qwen3.5-2B | 1.3 GB + 0.7 GB | Apache-2.0 | Drove the laptop runs. Needs `tree_hints` | | Holo2-4B | 2.7 GB + 0.5 GB | Apache-2.0 | H Company's earlier GUI model; a reasoning model, so slow | | GUI-Owl-1.5-2B | 1.1 GB + 0.4 GB | MIT | A GUI-specialised small model | diff --git a/docs/explore/safety.md b/docs/explore/safety.md index b300afc..e7849f9 100644 --- a/docs/explore/safety.md +++ b/docs/explore/safety.md @@ -94,8 +94,9 @@ file an issue, or change a check; those are your verdicts. - **Debug builds and test accounts only.** A card whose build talks to production blocks anything that writes; see [production data](missions.md#production-data). -- **Budgets.** Steps and minutes per card, minutes per night, and at most five - new findings per app per night. +- **Budgets.** Steps and minutes per card, minutes per night, and a cap on new + findings per app per night: five by default, raised to 25 for the bug garden, + whose whole point is to be found. - **It files and never closes.** Even with GitHub issues armed, the collector only ever creates issues. - **No cloud fallback for the driver.** The `pilot` gateway name has none, so diff --git a/docs/explore/surfaces.md b/docs/explore/surfaces.md index 6e5d14b..2e55535 100644 --- a/docs/explore/surfaces.md +++ b/docs/explore/surfaces.md @@ -37,7 +37,8 @@ What it uses, all over adb: | Launch | The launcher activity, or the leanback launcher's on a TV; launch arguments become string extras | | Crashes | `logcat -b crash` for the package, as a running total; `logcat -b events` for `am_anr` | -**A TV** is recognised by the `android.software.leanback` feature. It gets +**A TV** is recognised by the `android.software.leanback` or +`android.hardware.type.television` feature. It gets `surface: "dpad"`, no touch tools, and a **focus line**: the focused node, named by its own label or, on Compose, the text inside it, with the labels of the containers around it. diff --git a/docs/getting-started.md b/docs/getting-started.md index 5e961c1..13bf3aa 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -127,7 +127,7 @@ than one brain needs. `~/.fleet/logs/agent.log`: ``` -[machine-macbookpro] fleet-runner-machine 0.5.0-dev on darwin/arm64, collector http://127.0.0.1:8788 +[machine-macbookpro] fleet-runner-machine 0.8.0 on darwin/arm64, collector http://127.0.0.1:8788 [machine-macbookpro] registered with http://127.0.0.1:8788; capabilities: benchmark, build, build:gradle, build:xcode, build:npm, self-check, llm-eval ``` @@ -175,6 +175,23 @@ curl -s http://127.0.0.1:8788/jobs/hello-fleet `queued` → `claimed` → `done`, in a few seconds. +!!! tip "The same with the CLI" + + `curl` is here because it shows exactly what goes over the wire, and these + unversioned routes keep working. Day to day, `fleetr` (installed beside + `fleet`, the same program) does steps 4 and 5 in one command, validating + the spec against [`/api/v1`](api.md#control-api-apiv1) first and waiting for + the verdict: + + ```bash + fleetr run benchmark --backend synthetic --pool machines \ + --param prompt_tokens=256 --param gen_tokens=64 \ + --param warmup_iters=1 --param measure_iters=3 + ``` + + Its exit code is the verdict: 0 passed, 1 failed, 4 skipped because nothing + ran. [AI agents and automation](agents.md) has the rest of the commands. + !!! tip "`targets.pool` has to match" The machine agent registers into `machines`. Ask for `ml-capable` -- the pool @@ -349,7 +366,7 @@ FLEET_URL=http://127.0.0.1:8788 npm start ``` ``` -[machine-your-hostname] fleet-runner-machine 0.5.0-dev on darwin/arm64, collector http://127.0.0.1:8788 +[machine-your-hostname] fleet-runner-machine 0.8.0 on darwin/arm64, collector http://127.0.0.1:8788 [machine-your-hostname] registered with http://127.0.0.1:8788; capabilities: benchmark, build, build:npm, self-check, llm-eval ``` @@ -365,7 +382,11 @@ it needs on `PATH`. - **[Concepts](concepts.md)** -- leases, capabilities and targeting, which is what you need before writing a job spec that does something interesting. -- **[Workloads](workloads/index.md)** -- the other twenty-odd things it can run. +- **[Workloads](workloads/index.md)** -- the other thirty-odd things it can run. +- **[Exploratory QA](explore/index.md)** -- a vision model using tonight's build + overnight, and the bugs it reproduces. +- **[AI agents and automation](agents.md)** -- `fleetr`, the skill and the MCP + tools, for scripts, CI and coding agents. - **[Adding devices](install/devices.md)** -- phones, televisions, Rokus, browsers. - **[Wire in your app](integration/index.md)** -- publish builds on merge and run @@ -375,8 +396,8 @@ it needs on `PATH`. !!! warning "Before you put it on a network" - There is no authentication, by design -- anyone who can reach the collector - can enqueue a job. `fleet up` binds every interface and warns that it did. + By default there is no authentication -- anyone who can reach the collector + can enqueue a job. Scoped tokens are opt-in ([Authentication](deploy/auth.md)). `fleet up` binds every interface and warns that it did. `FLEET_BIND` (or `fleet config set collector.bind`) decides which networks it answers on, and loopback plus your tailnet address is the configuration most people want. [Deploy](deploy/index.md#binding-and-exposure) has the detail. diff --git a/docs/index.md b/docs/index.md index 713bb7e..109ac8e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -49,7 +49,14 @@ fleet on. The answer is macOS; the suites run on all three. --- - All 28 of them, what each measures, and what each refuses to guess. + All 34 of them, what each measures, and what each refuses to guess. + +- __[Exploratory QA](explore/index.md)__ + + --- + + A vision model uses tonight's build the way a person would, and files + only the bugs that reproduce on a clean install. - __[The protocol](protocol.md)__ @@ -96,21 +103,23 @@ of phones. ## A warning worth reading before you deploy anything -**There is no authentication, by design.** The collector is meant for a home -LAN or a tailnet, and anyone who can reach it can enqueue a job. This is stated +**By default there is no authentication.** The collector is meant for a home +LAN or a tailnet, and anyone who can reach it can enqueue a job. Scoped tokens +and an audit log are opt-in with `FLEET_AUTH=tokens` +([Authentication](deploy/auth.md)); the default does not change. This is stated as a posture rather than apologised for, and [the security policy](https://github.com/addisdev/fleet-runner/blob/main/SECURITY.md) describes what that does and does not cover. Do not put it on the internet. ## Where things live -The code is one repository with seven components that ship independently and +The code is one repository with eight components that ship independently and share no code, only the protocol. One brain -- [`collector/`](https://github.com/addisdev/fleet-runner/tree/main/collector), -which also holds the host executor and the browser runner it serves at -`/runner`. +which also holds the host executor, the [exploratory QA](explore/index.md) +workload, and the browser runner it serves at `/runner`. Five runners, in five languages, sharing not one line: [`runner-android/`](https://github.com/addisdev/fleet-runner/tree/main/runner-android) diff --git a/docs/install/docker.md b/docs/install/docker.md index eb6d5cf..7f07282 100644 --- a/docs/install/docker.md +++ b/docs/install/docker.md @@ -91,7 +91,10 @@ objection to QEMU does not apply here. and a loopback bind would make the published port answer nothing at all. Everything in [binding and exposure](../deploy/index.md#binding-and-exposure) still applies to the *host* side of that mapping. **There is no - authentication.** + authentication by default**. [Authentication](../deploy/auth.md) turns it + on: `-e FLEET_AUTH=tokens`, and the first token created inside the container, + `docker exec node /app/bin/fleet.mjs token create ops --scope admin`, + so it lands on the volume. Nobody has done that in a container yet. - **A `HEALTHCHECK` that asks `/api/health`** rather than checking the process is alive. A collector whose port is bound but whose database will not open is exactly the failure that looks healthy from the outside. diff --git a/docs/install/index.md b/docs/install/index.md index e1cf6a1..de6d590 100644 --- a/docs/install/index.md +++ b/docs/install/index.md @@ -50,7 +50,7 @@ written into both files: `SHASUMS256.txt` cannot be fetched at all.** There is no `--force` past this. 4. Unpack into `~/.fleet` (`FLEET_INSTALL_DIR` moves it), replacing only the entries a release owns -- `bin`, `runner-web`, `dash`, `examples`, - `schemas`. It never removes the directory itself, because + `schemas`, `skills`. It never removes the directory itself, because `~/.fleet` is also where `config.json`, `data/`, `artifacts/` and `logs/` live, and an upgrade that deletes your results is worse than one that fails. 5. Run `fleet version` from the thing it just installed. If the bundle is @@ -69,7 +69,7 @@ something is wrong; stop and read it. ``` ~/.fleet/ config.json what fleet up reads; `fleet config set` writes it - bin/ fleet.mjs, and a `fleet` symlink (a fleet.cmd shim on Windows) + bin/ fleet.mjs, with `fleet` and `fleetr` symlinks (fleet.cmd and fleetr.cmd on Windows) data/ fleet.db, and collector.json -- this brain's name and id artifacts/ build products, screenshots, everything a job published logs/ one per supervised component @@ -107,3 +107,5 @@ to. browser to a fleet that is already running. - **[Deploy](../deploy/index.md)** -- keeping it up, and the network gotcha that costs an evening. +- **[AI agents and automation](../agents.md)** -- `fleet skill install` and + `fleet mcp`, so a coding agent can run jobs on the fleet. diff --git a/docs/integration/add-a-workload.md b/docs/integration/add-a-workload.md index 58662f3..a835ffa 100644 --- a/docs/integration/add-a-workload.md +++ b/docs/integration/add-a-workload.md @@ -5,10 +5,17 @@ collector. ## Why this works at all -`POST /jobs` accepts the workload names the collector and host executor ship -with, **plus any workload some registered agent declares in its capabilities**. -Anything else is a 422 naming the missing capability, at enqueue time, rather -than a job that sits queued forever with nothing to explain why. +`POST /api/v1/jobs` (and the older `POST /jobs`) accepts the workload names +the collector and host executor ship with, **plus any workload some registered +agent declares in its capabilities**. Anything else is a 422, +`no_capable_agent`, naming the missing capability, at enqueue time, rather than +a job that sits queued forever with nothing to explain why. + +`fleetr workloads` (`GET /api/v1/workloads`) lists an agent-declared workload +alongside the shipped ones, with the summary "Declared by N live agents; the +collector publishes no description or params for it." Its `params` are +therefore not validated by the collector: the agent is the only thing that +checks them, so it should refuse bad ones with a result that says why. So the entire path is: implement it in an agent, add it to that agent's route table, restart the agent. The job becomes enqueueable the moment it registers. diff --git a/docs/integration/add-your-app.md b/docs/integration/add-your-app.md index 70e6c1a..35f8b17 100644 --- a/docs/integration/add-your-app.md +++ b/docs/integration/add-your-app.md @@ -8,11 +8,15 @@ the code. | | Directory | Override | |---|---|---| -| Maestro flows | `collector/flows//` | `FLEET_FLOWS_DIR` | -| Playwright specs | `collector/web-specs//` | `FLEET_WEB_SPECS_DIR` | -| Visual capture manifests | `collector/web-specs//shots.json` | | -| Audit config | `collector/web-specs//audit.json` | | - +| Maestro flows | `collector/examples/flows//` | `FLEET_FLOWS_DIR` | +| Playwright specs | `collector/examples/web-specs//` | `FLEET_WEB_SPECS_DIR` | +| Visual capture manifests | `collector/examples/web-specs//shots.json` | | +| Audit config | `collector/examples/web-specs//audit.json` | | + +The defaults are `examples/flows` and `examples/web-specs`, resolved from the +directory the collector and executor run in, which is `collector/` for +`npm start`. Set the overrides to keep your own flows and specs outside the +checkout. [`examples/`](https://github.com/addisdev/fleet-runner/tree/main/collector/examples) has working versions of each, including a neutral `fleetrunner/smoke.yaml` you can copy as a starting point. @@ -36,7 +40,7 @@ Then: ```json { "workload": "ui-test", "executor": "host", - "app": { "name": "your-app-android", "sha256": "latest" }, + "app": { "name": "your-app-android", "build": "latest", "sha256": "latest" }, "suite": { "kind": "maestro", "flows": "your-app/smoke.yaml" }, "targets": { "exclusive": true } } ``` @@ -60,7 +64,7 @@ not a test. ```json { "workload": "ui-test", "executor": "host", - "app": { "name": "your-app-ios", "sha256": "latest" }, + "app": { "name": "your-app-ios", "build": "latest", "sha256": "latest" }, "suite": { "kind": "xcuitest", "bundle": "YourAppUITests-Runner.app" }, "targets": { "executor": "mac-xcode" } } ``` @@ -116,7 +120,18 @@ accurate and a match is a statement about what the job needs: { "targets": { "match": "os ~ 'android' && ram_mb >= 3000" } } ``` -Check what a match would select before you schedule it: +Check what a match would select before you schedule it. `--validate` runs +every check an enqueue makes and lists the devices the job would land on, +without queueing it: + +```bash +fleetr run --spec job.json --validate +fleetr run benchmark --match "os ~ 'android' && ram_mb >= 3000" --validate +``` + +That is `POST /api/v1/jobs/validate` underneath, which takes a whole spec. The +older `POST /api/jobs/preview-targets` still answers for a bare `targets` +object: ```bash curl -s -X POST http://fleet-host.local:8788/api/jobs/preview-targets \ @@ -132,6 +147,13 @@ into your app repository. It builds, then calls `ci-enqueue`, which exits non-zero on a red suite — so the check fails whether or not [commit statuses](index.md#commit-statuses) are armed. +`ci-enqueue` also exits 0 on a job that was skipped because nothing ran, and +sends no token, so it fails against a collector with `FLEET_AUTH=tokens` +([details](first-job.md#or-in-one-step-with-ci-enqueue)). For a check that +should block a merge, replace that step with `ci-upload` followed by +`fleetr run --spec job.json`, which exits 1 on a red suite and 4 on a skip, +and fails the step on either. + Give the job a unique `job_id` built from the pull request number, the run attempt and the sha. A duplicate is a 409, which is the correct answer but not the one you want on a re-run. diff --git a/docs/integration/cookbook.md b/docs/integration/cookbook.md index a2cc755..6000240 100644 --- a/docs/integration/cookbook.md +++ b/docs/integration/cookbook.md @@ -5,13 +5,27 @@ verbatim from [`collector/examples/jobs/`](https://github.com/addisdev/fleet-runner/tree/main/collector/examples/jobs) and validated against [`job.schema.json`](https://github.com/addisdev/fleet-runner/blob/main/collector/schemas/job.schema.json) -by `npm test`.** If one stops validating, CI fails — so what you copy from here -is what the collector accepts. +by `npm test`** (`scripts/check-examples.ts`). If one stops validating, CI +fails. That check is the schema file only. `/api/v1/jobs`, and so `fleetr run`, +is stricter: it refuses unknown top-level fields and checks `params` against +the workload's manifest where there is one. Every example passes both today, +but only the first is enforced. -Post any of them to `POST /jobs`: +Run any of them with `fleetr`: ```bash -curl -X POST http://fleet-host.local:8788/jobs \ +fleetr run --spec collector/examples/jobs/benchmark.json --validate # where it would land +fleetr run --spec collector/examples/jobs/benchmark.json --id bench-$(date +%s) +``` + +The examples carry fixed `job_id`s, so the second run of the same file is +refused with `duplicate_job` unless `--id` gives it a new one. `--spec` takes +one job; a chain is several files, enqueued in dependency order (see +[the chain below](#a-chain-build-install-test)). Without `fleetr`, post the same +file to `POST /api/v1/jobs`: + +```bash +curl -X POST http://fleet-host.local:8788/api/v1/jobs \ -H 'content-type: application/json' \ --data-binary @collector/examples/jobs/benchmark.json ``` @@ -182,8 +196,11 @@ shrinking the matrix. ``` `account` names a Keychain item on the executor host. The secret itself is never -in the spec — `POST /jobs` is unauthenticated, so a spec is not a place a -credential could safely live. +in the spec: a spec is stored, served by the API and shown on the dashboard to +anyone who can read jobs, and the collector has no authentication by default +(see [Authentication](../deploy/auth.md)). Enqueue enforces it, refusing with +`secret_in_spec` any spec in which `password`, `passwd`, `secret`, `token`, +`api_key` or `apikey` appears as a key (or as a whole string value). ### `digest` @@ -208,9 +225,14 @@ idle five minutes, rather than starting an Xcode build while somebody is typing. --8<-- "collector/examples/jobs/chain-build-install-test.json" ``` -Post `build.json`, `install.json` and this, and the last two arrive as -`waiting`. `${jobs.build-903.artifact}` is substituted at promotion with the -real hash the build uploaded. A failed build fails both waiters, naming the +This is the last link of three. Post `build.json`, then an `install` job with +`"job_id": "install-903"` and `"depends_on": ["build-903"]`, then this, in that +order, because a dependency must exist before the job that names it. The +`install.json` example above is a standalone nightly install +(`install-nightly`), not that middle link; [Publish on +merge](publish-on-merge.md#chaining-a-build-to-its-own-test) has all three +specs. The last two arrive as `waiting`. `${jobs.build-903.artifact}` is +substituted at promotion with the real hash the build uploaded. A failed build fails both waiters, naming the cause, rather than leaving them parked forever. ### `model-convert` diff --git a/docs/integration/first-job.md b/docs/integration/first-job.md index 0cfee0f..ab14c7d 100644 --- a/docs/integration/first-job.md +++ b/docs/integration/first-job.md @@ -6,42 +6,100 @@ the result. This assumes a collector running — [Get started](../getting-started.md) if not — and at least one agent registered. -## 1. Enqueue with curl +## 1. Enqueue with fleetr + +`fleetr` is installed beside `fleet` and is the same program. Point it at the +collector with `--url`, or set `FLEET_RUNNER_URL` once: + +```bash +export FLEET_RUNNER_URL=http://fleet-host.local:8788 + +fleetr devices # what is online; a job can only land on these +fleetr workloads benchmark # its params and a valid example spec +fleetr run benchmark --backend synthetic --match "os ~ 'android'" \ + --param prompt_tokens=256 --param gen_tokens=64 --param measure_iters=3 +``` + +`fleetr run` validates the spec against [`/api/v1`](../api.md#control-api-apiv1) +before it queues anything, waits for the verdict, prints it per device, and +**exits with it**: 0 passed, 1 failed, 2 usage error or invalid spec, 3 still +running when `--timeout` ran out, 4 skipped (nothing ran), 5 refused or +unreachable. Add `--validate` to see where a job would land without queueing +it, and `--no-wait` to print the job id and return; `fleetr wait ` +picks it up later. + +**A `job_id` you set must be unique.** Leave it out and the collector +generates one. Set it (`--id`, or `job_id` in a spec) and it is an idempotency +key: a second enqueue with the same id is refused with `duplicate_job` (a 409), +deliberately, so a retried CI step cannot silently overwrite an earlier +verdict. Building it from the commit sha and the run attempt is the pattern the +templates use. + +If the job sits `waiting` rather than `queued`, it has a `depends_on` that has +not closed yet. If nothing ever claims it, the usual cause is a `targets` +clause no registered device satisfies, which `--validate` shows before you +queue. + +### The same with curl + +Where `fleetr` is not installed, the control API takes the same spec: ```bash -curl -X POST http://fleet-host.local:8788/jobs \ +curl -s -X POST http://fleet-host.local:8788/api/v1/jobs \ -H 'content-type: application/json' \ -d '{ - "schema": 1, - "job_id": "smoke-'"$(date +%s)"'", "workload": "benchmark", "executor": "device", "backend": "synthetic", "params": { "prompt_tokens": 256, "gen_tokens": 64, "measure_iters": 3 }, "targets": { "match": "os ~ '\''android'\''" } }' -``` -```json -{ "ok": true, "job_id": "smoke-1788635539", "status": "queued" } +curl -s 'http://fleet-host.local:8788/api/v1/jobs//wait?timeout_s=120' +curl -s 'http://fleet-host.local:8788/api/v1/devices' ``` -**`job_id` must be unique** — a duplicate is a 409, deliberately, so a retried -CI step cannot silently overwrite an earlier verdict. Building it from the -commit sha and the run attempt is the pattern the templates use. +The first answers 201 with `job_id`, `status` and `links`; the second holds +for up to 120 seconds and returns the summary, whose `verdict` is `passed`, +`failed`, `mixed`, `skipped` or `cancelled` once `finished` is true. A collector +running with tokens on (see [Authentication](../deploy/auth.md)) also wants +`-H "authorization: Bearer $FLEET_TOKEN"`. The older `POST /jobs` and +`GET /api/devices` still answer, with a `Deprecation` header. -If the reply says `waiting` rather than `queued`, the job has a `depends_on` -that has not closed yet. If nothing ever claims it, the usual cause is a -`targets` clause no registered device satisfies: +## 2. Upload a build and test it + +Publish the build, then run the suite against it. From the collector's +checkout: ```bash -curl -s 'http://fleet-host.local:8788/api/devices' | grep -o '"device_id":"[^"]*"' +npx tsx scripts/ci-upload.ts \ + --collector http://fleet-host.local:8788 \ + --app your-app-android --build local --platform android \ + --artifact app/build/outputs/apk/debug/app-debug.apk + +cat > job.json <<'JSON' +{ + "workload": "ui-test", + "executor": "host", + "app": { "name": "your-app-android", "build": "latest", "sha256": "latest" }, + "suite": { "kind": "maestro", "flows": "your-app/smoke.yaml" }, + "targets": { "exclusive": true }, + "lease": { "ttl_s": 1200 } +} +JSON + +fleetr run --spec job.json ``` -## 2. Upload a build and test it +`"latest"` resolves at enqueue to the newest build published under that app +name, which from your own terminal is the one you just uploaded. Where two +uploads can race (two pull requests building at once), put the hash +`ci-upload` printed in `app.sha256` instead. + +### Or in one step with `ci-enqueue` -`ci-enqueue` is the script CI runs, and it works perfectly well from your own -terminal, which is where you should try it first. +`collector/scripts/ci-enqueue.ts` uploads, enqueues and polls in one command, +and the example workflow uses it: ```bash cat > job.json <<'JSON' @@ -64,9 +122,23 @@ npx tsx scripts/ci-enqueue.ts \ --timeout 1200 ``` -It uploads the artifact, rewrites `app.sha256` with the returned hash, enqueues, -polls to a verdict, and **exits 0 or 1**. That exit code is the whole contract — -everything else is detail. +It uploads the artifact, writes the returned hash into `app.sha256`, posts the +spec to the deprecated `POST /jobs`, polls `GET /jobs/` every ten seconds, +and exits 0 when the job is `done`, 1 when it failed or timed out, and 2 on a +usage error. `"replaced-by-upload"` is only a placeholder for the script to +overwrite: it is not a hash, so `fleetr run --spec` and `/api/v1/jobs` refuse +it. Know three things before you let it block a pull request: + +- **A skipped job exits 0.** A job where nothing ran (its `last_error` starts + `skipped:`) is still `done`, so the check goes green. `fleetr run` exits 4 + for the same job. +- **It sends no token**, so against a collector with `FLEET_AUTH=tokens` the + enqueue is refused and the step fails. +- **A duplicate `job_id` is not an error to it.** It prints "already queued" + and reports the earlier job's verdict. + +For a check that blocks a merge, prefer `ci-upload` followed by +`fleetr run --spec`. ## 3. Watch it on the dashboard diff --git a/docs/integration/index.md b/docs/integration/index.md index 4409e46..111e5c3 100644 --- a/docs/integration/index.md +++ b/docs/integration/index.md @@ -9,7 +9,10 @@ a verdict that can block a pull request. `ci-enqueue` and `ci-upload` are **verified standalone**: they upload, they enqueue, they poll to a verdict and they exit 0 or 1, and the artifact and `"latest"` resolution behind them are covered end to end by the collector's - test suite. + test suite. `ci-enqueue` predates `/api/v1`: it counts a skipped job as a + pass and sends no token ([details](first-job.md#or-in-one-step-with-ci-enqueue)). + `fleetr run`, which validates against `/api/v1` and exits 4 on a skip, is + the supported way to block on a verdict. **The GitHub Actions path has never run on a real GitHub runner.** The workflow templates below document a contract that is implemented on the @@ -21,7 +24,7 @@ a verdict that can block a pull request. | | | |---|---| -| **[Your first job](first-job.md)** | `curl`, then the CI script standalone, then the dashboard. No CI involved. | +| **[Your first job](first-job.md)** | `fleetr` (or `curl`), then a build and a suite, then the dashboard. No CI involved. | | **[Publish on merge](publish-on-merge.md)** | Every merge publishes a build the nightly can ask for by name. | | **[Add your app](add-your-app.md)** | Flows, suites, visual baselines, and targeting the right devices. | | **[Add a workload](add-a-workload.md)** | Teach the fleet something new without a collector release. | @@ -64,13 +67,18 @@ Arming it makes a red nightly block a pull request. That is the point, and it is also a decision with consequences for everyone who pushes, so it stays off until somebody chooses it deliberately. -Note that `ci-enqueue` already exits non-zero on a red suite, so the check fails -whether or not statuses are armed. Arming adds the status on the *nightly's* +Note that `ci-enqueue` and `fleetr run` already exit non-zero on a red suite, +so the check fails whether or not statuses are armed. Arming adds the status on the *nightly's* commit, which is the part a scheduled run cannot get any other way. ## What the runner needs to reach -The collector is LAN or tailnet only and has no authentication, so a +The collector is LAN or tailnet only and has no authentication by default +(tokens are opt-in; see [Authentication](../deploy/auth.md)), so a GitHub-hosted runner cannot reach it and should not be able to. The workflows below assume a **self-hosted runner on the same tailnet**, with the collector's address in a `FLEET_COLLECTOR_URL` secret. + +If the collector runs with `FLEET_AUTH=tokens`, give CI a token with the `run` +scope (`fleet token create ci --scope run`) in another secret and pass it to +`fleetr` as `FLEET_RUNNER_TOKEN`. `ci-enqueue` cannot send one. diff --git a/docs/integration/publish-on-merge.md b/docs/integration/publish-on-merge.md index c049d62..a604127 100644 --- a/docs/integration/publish-on-merge.md +++ b/docs/integration/publish-on-merge.md @@ -33,6 +33,16 @@ curl -X POST http://fleet-host.local:8788/artifacts \ Those headers are what stamp the publish ordering that `latest` reads. There is no `/artifacts/:sha/publish` endpoint and none is needed. +`POST /artifacts` is a runner-protocol route, so it stays open even with +`FLEET_AUTH=tokens` unless the collector also sets `FLEET_AUTH_PROTOCOL=token` +(see [Authentication](../deploy/auth.md)). Then it needs a token with the +`agent` scope (or `admin`; `run` is not enough): send +`-H "authorization: Bearer "` with curl. `ci-upload` has no bearer +option; it sends `FLEET_DASH_TOKEN` from its environment as `x-fleet-token`, +which the collector also accepts as a token, so put the `agent` token in that +variable. That route has been read from the code, not run against a +protocol-gated collector. + !!! note "An app with no published build is skipped, not failed" If nothing has ever been published for an app name, its nightly is @@ -89,16 +99,20 @@ names. ```json { "schema": 1, - "job_id": "nightly-ui", "workload": "ui-test", "executor": "host", - "app": { "name": "your-app-android", "sha256": "latest" }, + "app": { "name": "your-app-android", "build": "latest", "sha256": "latest" }, "suite": { "kind": "maestro", "flows": "your-app/smoke.yaml" }, "targets": { "match": "os ~ 'android'", "exclusive": true }, "lease": { "ttl_s": 1800 } } ``` +This is the schedule's template. It needs no `job_id`: each firing is enqueued +as `-`, and one in the template would be replaced. +`"build": "latest"` is there because the schema requires `app.build`; the +collector records the build string the published artifact carries. + Put it in [`scripts/seed-schedules.ts`](https://github.com/addisdev/fleet-runner/blob/main/collector/scripts/seed-schedules.ts) rather than only in the database, and `npm run seed:schedules`. That is @@ -109,27 +123,41 @@ watched it run once by hand. ## Chaining a build to its own test -If a machine agent does your building, the whole thing can be one enqueue — -[job chains](../concepts.md#job-chains) do the waiting: +If a machine agent does your building, [job chains](../concepts.md#job-chains) +do the waiting. Nothing accepts a list of jobs in one request, so enqueue them +one at a time, in dependency order, and let `depends_on` hold the later ones in +`waiting`: -```json -[ - { "job_id": "build-903", "workload": "build", "executor": "device", - "params": { "repo": "git@github.com:you/app.git", "ref": "main", - "kind": "gradle", "task": "assembleDebug", "app": "your-app-android" } }, - - { "job_id": "install-903", "workload": "install", "executor": "host", - "depends_on": ["build-903"], - "app": { "name": "your-app-android", "build": "903", - "sha256": "${jobs.build-903.artifact}" } }, - - { "job_id": "ui-903", "workload": "ui-test", "executor": "host", - "depends_on": ["install-903"], - "app": { "name": "your-app-android", "build": "903", - "sha256": "${jobs.build-903.artifact}" }, - "suite": { "kind": "maestro", "flows": "your-app/smoke.yaml" } } -] +```json title="build-903.json" +{ "job_id": "build-903", "workload": "build", "executor": "device", + "params": { "repo": "git@github.com:you/app.git", "ref": "main", + "kind": "gradle", "task": "assembleDebug", "app": "your-app-android" } } +``` + +```json title="install-903.json" +{ "job_id": "install-903", "workload": "install", "executor": "host", + "depends_on": ["build-903"], + "app": { "name": "your-app-android", "build": "903", + "sha256": "${jobs.build-903.artifact}" } } +``` + +```json title="ui-903.json" +{ "job_id": "ui-903", "workload": "ui-test", "executor": "host", + "depends_on": ["build-903", "install-903"], + "app": { "name": "your-app-android", "build": "903", + "sha256": "${jobs.build-903.artifact}" }, + "suite": { "kind": "maestro", "flows": "your-app/smoke.yaml" } } +``` + +```bash +fleetr run --spec build-903.json --no-wait +fleetr run --spec install-903.json --no-wait +fleetr run --spec ui-903.json --no-wait +fleetr wait ui-903 # exits with the UI test's verdict ``` -A broken build fails the install and the UI test with it, naming the cause, -rather than leaving them in `waiting` until somebody notices next week. +The ids are fixed here because the later specs name the earlier ones. A +dependency has to exist when its dependent is enqueued, which is why the order +matters, and a `${jobs..artifact}` reference may only name a job listed in +`depends_on`, which is why `ui-903` lists the build as well as the install. A broken build fails the install and the UI test with it, naming the +cause, rather than leaving them in `waiting` until somebody notices next week. diff --git a/docs/lab.md b/docs/lab.md index 161257b..bd0d54c 100644 --- a/docs/lab.md +++ b/docs/lab.md @@ -18,6 +18,7 @@ and nothing said which of them held the iPhone. | **runner-host** | MacBook Pro (Mac14,10), macOS 26.7, Xcode 27 | **Nothing of Fleet Runner's, since 2026-09-22.** It runs the GitHub Actions runner farm, which is its own project | `ssh runner-host` | | **the dev MacBook** | M1 Pro, 16 GB, macOS 27, Xcode 27 | A machine agent and the `mac-dev` executor in pool `personal`, plus the SSH tunnel and the alert receiver. Its executor refuses heavy work above load 50 or under 2 GB of free swap (`FLEET_MAX_LOAD`, `FLEET_MIN_FREE_SWAP_MB`) | it is the machine you are on | | **the mini** | Mac mini M4, macOS 15.6.1, up 224 days | Nothing fleet-related | `ssh mini`, over the tailnet | +| **ultra** | Mac Studio, M5 Ultra, 96 GB, macOS 27 | The exploratory QA nights: the `ultra` executor, its Android emulator and Apple simulators, and the model gateway they call. Its night queue runs them, not the brain's schedules; [Running it on ultra](deploy/explore-on-ultra.md) is its runbook | `ssh ultra`; it reaches the brain through its own tunnel | **Why the brain is the oldest machine.** It is on the shelf's subnet, and it is macOS 12, which has no local-network gate. Every other Mac here is macOS 26 or @@ -149,6 +150,12 @@ Three things have to be true for a status to appear: MacBook it reaches the brain through the tunnel, the same as the agent does. A result whose error starts with `skipped:` means nothing ran. +From 0.8.0 there is also `fleetr`, whose exit code is the verdict, and a skill +(`fleet skill install`) that tells an agent which commands to run in what +order. [AI agents and automation](agents.md) has both. The brain here is still +on 0.7.2, so neither `/api/v1` nor the new commands work against it until it is +upgraded. + ## The suites are not in git `~/fleet-collector/flows/` and `~/fleet-collector/web-specs/` on fleet-host hold @@ -185,7 +192,7 @@ Five enabled. All times local to fleet-host. |---|---|---|---| | `nightly-synthetic-shelf` | 02:00 | fanout, pool `machines` | A machine's throughput moved, or an agent is not claiming. This is the comparison table | | `nightly-self-check` | 02:15 | fanout, pool `machines` | Disk, clock drift, a tool that vanished, or the agent is not supervised | -| `nightly-fleet-ui-smoke` | 02:30 | `fleet-host`, an Android device | **Red since 2026-08-21.** Since 09-16 it is `no targets attached` — the Galaxy S8+ is unplugged | +| `nightly-fleet-ui-smoke` | 02:30 | `fleet-host`, an Android device | **Red since 2026-08-21.** From 09-16 to early October it was `no targets attached`. The Galaxy S8+ is plugged in again and the suite now runs on it, and fails, every night; why is not diagnosed yet | | `nightly-aliquant-shots` | 04:15 | `fleet-host`, `chromium` and `mobile-chrome` | Green. The baseline was re-accepted on 2026-09-22 from fleet-host's own captures, after Aliquant's sign-in page gained a "Forgot password?" link; the old one had diverged 2.7% on desktop and 6.1% on mobile since 09-10. The `webkit` and `mobile-safari` baselines are still the August ones, because nothing runs those projects now | | `nightly-tvloop-hardware` | 05:00 | `fleet-host`, the Roku, exclusive | tvloop's doctor, install, contract tests and flow replay. `skipped:` until the Roku password is in fleet-host's Keychain. Red from doctor means the Roku is asleep, off the network, or out of developer mode | @@ -216,15 +223,14 @@ that pool here. ```bash ssh fleet-host -fleet service status # says "running" even when the brain has given up — see below +fleet service status # names a component that gave up, and exits non-zero tail -40 ~/.fleet/logs/fleet.log curl -s localhost:8788/api/health ``` -`fleet service status` reports on the launchd job, not on what the supervisor is -doing, so it says `running` while the supervisor has permanently given up on the -brain. Read `fleet.log` for `GAVE UP`. Tracked in -[#45](https://github.com/addisdev/fleet-runner/issues/45). +Since 0.6.1 `fleet service status` reads the supervisor's own state, so a +component it has given up on shows as `GAVE UP at … after N restarts` rather +than `running`. `fleet.log` has the restarts that led there. ### Restarting it @@ -269,8 +275,9 @@ from, so a restore does not have to guess. ## What is not done, and who it needs -- **The shelf is unplugged.** No phone, tablet, TV or stick has been on the - fleet since 2026-08-18. That needs a powered USB hub and cables. +- **Most of the shelf is unplugged.** The Galaxy S8+ is back on fleet-host; + no other phone, tablet, TV or stick has been on the fleet since 2026-08-18. + That needs a powered USB hub and cables. - **The Roku's developer password is not in fleet-host's Keychain**, so the tvloop nightly skips. Developer mode is on. - **An Apple TV 4K** is paired to the dev MacBook and has never run the tvOS diff --git a/docs/platforms.md b/docs/platforms.md index 8d20453..094a2a9 100644 --- a/docs/platforms.md +++ b/docs/platforms.md @@ -14,7 +14,7 @@ that says which ones somebody has watched register is worth something. | Android phone, tablet | `runner-android` | `adb install`, or sideload | **yes** — the original shelf | | iPhone, iPad | `runner-ios` | Xcode, TestFlight internal | **yes** | | iOS simulator | `runner-ios` | `simctl install` | **yes** | -| macOS, Linux, Windows | `runner-machine` | `fleet up`, or `npm start`, or a LaunchAgent / systemd unit | **macOS yes, on both architectures** — an Apple M1 Pro and a 2016 Intel i7 both registered, passed `npm run conformance`, and produce comparable synthetic numbers with matching digests; both run under `fleet service`. Linux and Windows run their suite in CI on x64 and arm64. On Linux x64 the agent also registers, inside the Docker image in CI, against the collector beside it; Windows has never registered against a real collector — see [what each one reports](#what-a-cloud-runner-actually-reports) | +| macOS, Linux, Windows | `runner-machine` | `fleet up`, or `npm start`, or a LaunchAgent / systemd unit | **macOS yes, on both architectures** — an Apple M1 Pro and a 2016 Intel i7 both registered, passed `npm run conformance`, and produce comparable synthetic numbers with matching digests; both run under `fleet service`. Linux and Windows run their suite in CI on x64 and arm64, and CI installs `fleet service` as a systemd user unit on Linux, waits for the collector it starts, and uninstalls it; the launchd unit is only proven by this lab's own Macs and the Windows scheduled task has never been installed. On Linux x64 the agent also registers, inside the Docker image in CI, against the collector beside it; Windows has never registered against a real collector — see [what each one reports](#what-a-cloud-runner-actually-reports) | | Android emulator | `runner-android` | `adb install` to the emulator | **yes** | ## What Wave 5 added @@ -22,10 +22,10 @@ that says which ones somebody has watched register is worth something. | Platform | Runner | How it joins | Verified | |---|---|---|---| | **Any browser** | `collector/runner-web/` | open `http:///runner` | **yes** — driven end to end by a real Chromium against a real collector, both backends, digest checked | -| **Android TV, Google TV, Fire TV** | `runner-android` | `adb connect`, then `adb install` | **partly** — the built APK declares a leanback launcher and a banner, checked with `aapt2 dump badging`. No TV has run it | +| **Android TV, Google TV, Fire TV** | `runner-android` | `adb connect`, then `adb install` | **partly** — the built APK declares a leanback launcher and a banner, checked with `aapt2 dump badging`. No TV has run it. (Exploratory QA has driven an Android TV emulator from outside, over adb; that is the executor, not this runner — see [what it can drive](explore/index.md#what-it-can-drive)) | | **Meta Quest** | `runner-android` | sideload via `adb` | **no** — Quest is Android 12 and reports `UI_MODE_TYPE_NORMAL`, so the runner identifies it by the VR feature flag. Never run on one | | **Wear OS** | `runner-android` | `adb install` over Wi-Fi debugging | **no** — the watch feature flag is read at run time; the manifest deliberately does not declare it (that would make the APK a Wear-only app in a store). Never run on one | -| **Apple TV (tvOS)** | `runner-ios`, `FleetRunnerTV` target | `devicectl` or `simctl` | **builds** — `xcodebuild -scheme FleetRunnerTV` succeeds. No Apple TV has run it | +| **Apple TV (tvOS)** | `runner-ios`, `FleetRunnerTV` target | `devicectl` or `simctl` | **builds** — `xcodebuild -scheme FleetRunnerTV` succeeds. No Apple TV has run it. (Exploratory QA drives tvOS 26.5 simulators through FleetDriver, a separate UI-test bundle) | | **Vision Pro (visionOS)** | `runner-ios`, `FleetRunnerVision` target | `devicectl` or `simctl` | **no** — the target is written and has never been compiled; the visionOS platform is not installed on the machine it was written on | | **Raspberry Pi, Jetson, Steam Deck** | `runner-machine` | `install-agent.sh`, or the Docker image | **no** — but arm64 Linux in CI reports a nearly complete descriptor, so a board should register cleanly. No board has | | **Anything with Docker** | `fleet/Dockerfile` | `docker run ghcr.io/addisdev/fleet` | **in CI** — every release publishes linux/amd64 and linux/arm64. CI starts the amd64 image on every pull request that touches it and waits for its own machine agent to register; the arm64 image has not been started | @@ -37,6 +37,10 @@ that says which ones somebody has watched register is worth something. | **Roku player, Roku TV** | `runner-roku` | `build.sh --install `, then an ECP launch | **no** -- and less verified than anything above it. No Roku was available and no Roku emulator exists, so the channel has never run. CI compiles it with brighterscript's `bsc` on every pull request that touches it; the firmware's own compiler has never seen it. See [Roku: the one that has never run](#roku-the-one-that-has-never-run) | | **Roku, from the executor** | `collector/src/drivers/roku.ts` | SSDP discovery on the LAN | **partly** -- the SSDP and device-info parsers are checked against recorded response shapes in `drivers.test.ts`; the UDP socket path is exercised by nothing, and no Roku has answered it | +The desktop app is not a runner, but it is the other thing here that has never +been run: `desktop / cargo check` compiles its Rust on macOS on every pull +request that touches it, and nobody has launched it. + ## Android: one APK, every shape The Android agent is a foreground service and a text field. Nothing in it needs @@ -224,7 +228,7 @@ It deliberately does **not** install. That needs HTTP digest auth, which Node's something that looks finished and fails the first time somebody has a Roku. `runner-roku/build.sh` installs with `curl --digest` instead, reading the developer password from the executor host's Keychain -- never from a job spec, -which is unauthenticated and rendered on the dashboard. +which anyone who can enqueue can read, and which the dashboard renders. ## What a cloud runner actually reports diff --git a/docs/protocol.md b/docs/protocol.md index 7a884f6..f96a45c 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -294,6 +294,30 @@ Uploading with `x-artifact-app`, `x-artifact-build` and `x-artifact-platform` stamps the upload as a published build, which is what makes `"sha256": "latest"` resolvable. There is no separate publish call. +## Authentication (optional) + +Off by default, and off for the runner protocol even when the control API has +tokens on (`FLEET_AUTH=tokens`): phones, TVs, Rokus and the browser runner send +no token. With `FLEET_AUTH_PROTOCOL=token` as well, every call on this page +needs + +``` +Authorization: Bearer fr_... +``` + +from a token with the `agent` scope (or `admin`, which implies it). No token +is a 401; a token without the scope is a 403. `GET /artifacts/{sha256}` also +accepts a `read` token, so a person can open a screenshot. runner-machine and +the host executor send `FLEET_TOKEN` from their environment when it is set; +the Android, iOS, Roku and browser runners do not, so do not turn this on while +any of them is on the shelf. See [Authentication](deploy/auth.md). + +The same rule covers the protocol's smaller routes, which a minimal agent never +calls: `POST /jobs/{id}/release`, `POST /locks/acquire` · `/release`, +`POST /events/{topic}` and `GET /events/{topic}/poll`, `POST /findings` (an +`explore` finding from an executor) and `POST /api/jobs/{id}/mirror` (a live +JPEG frame). + ## Writing your own agent The contract above is the whole thing. [Writing a runner](writing-a-runner.md) @@ -313,6 +337,9 @@ Worth stating, because each of these is a design decision rather than a gap: which makes the next beacon return `lease_renewed: false`. Work in flight finishes; nothing new starts. - **It carries no secrets in job specs.** A job names a credential; the agent - reads it from its own environment or Keychain. This is enforced by the design - rather than by validation — `POST /jobs` is unauthenticated, so a spec is not - a place a secret could safely live. + reads it from its own environment or Keychain. Enqueue refuses, with 400 + `secret_in_spec`, any spec containing a key (or string value) named + `password`, `passwd`, `secret`, `token`, `api_key` or `apikey`, in any case. + The check is a backstop, not the reason: a spec is stored, served by the API + and shown on the dashboard, and `POST /jobs` is unauthenticated by default, + so a spec is not a place a secret could safely live. diff --git a/docs/workloads/host.md b/docs/workloads/host.md index 984fd33..b61db8b 100644 --- a/docs/workloads/host.md +++ b/docs/workloads/host.md @@ -179,6 +179,79 @@ Native libraries group **per ABI** rather than as one `lib/`. `lib/` being huge tells you nothing you did not know; `lib/arm64-v8a` being 18 MB of it tells you what to split. +## `tvloop` + +Runs [tvloop](../explore/surfaces.md#roku-through-tvloop)'s hardware suite +against a Roku on the executor host's network. tvloop is the Roku development +CLI and already has a hardware nightly, aimed at a self-hosted Actions runner +nobody carries; this workload runs the same steps on the fleet instead. +**tvloop drives, the fleet lends**: tvloop knows how to talk to a Roku, and the +fleet's part is the device lock, the address, the password and filing what came +back. + +```json +{ "schema": 1, "job_id": "tvloop-1", "workload": "tvloop", "executor": "host", + "targets": { "match": "os ~ 'roku'", "exclusive": true }, + "params": { "steps": ["doctor", "install", "hardware", "replay"] } } +``` + +| Step | What runs | | +|---|---|---| +| `doctor` | `tvloop doctor --json` | A failure stops the run | +| `install` | `tvloop install --force` | Sideloads the checkout's channel into the Roku's one dev slot, **replacing whatever is there**. A failure stops the run | +| `spike` | `tools/m0-spike.mjs --full` | Opt-in, not in the default: ten sideloads, slow | +| `hardware` | tvloop's vitest suite with `--testNamePattern hardware` | | +| `replay` | `tvloop replay --reporter junit` | The JUnit counts become the row's test counts | + +The default is doctor, install, hardware, replay. `params.flows` picks which +flows to replay (default: all of the checkout's `tests/flows`), and +`params.dir` the checkout, which must be built: `FLEET_TVLOOP_DIR`, then +`~/tvloop`. A host with no built checkout **fails** the job and says how to +build one, because that is misconfiguration. + +**`exclusive` matters more here than anywhere.** A Roku holds exactly one dev +channel, so two jobs sideloading onto it at once is a corrupted run, and the +lock is held around the whole suite. + +**The developer password is a Keychain item on the executor host**: service +`fleet-roku-dev` (`FLEET_ROKU_KEYCHAIN_SERVICE` to change), account `rokudev`. + +```bash +security add-generic-password -s fleet-roku-dev -a rokudev -w +``` + +Without it a job of only Rokus is **skipped, not failed**: its row reads +"skipped: no Roku developer password on this host" with that command, because +it is a setup step nobody has done yet rather than a broken build. A Keychain +that refuses access fails the job. The password is passed to tvloop in its +environment and scrubbed from every log and report before upload, since the +artifact store is readable by anyone who can open the dashboard. + +Only one executor should report the Rokus as its own devices: the host started +with `FLEET_ROKU=1`. + +### Fire TV and Android TV + +With `params.androidtv: { "package": "com.example.app.debug" }`, adb devices +that declare leanback run alongside the Rokus, each through a generated +`tvloop.toml`. Only `doctor` and `replay` run on them (install, spike and +hardware are the Roku adapter's), and they need no Roku password. +`params.androidtv.flows` replays a different set on the TVs. + +A green TV row says less than a Roku row. tvloop's Android TV adapter reads no +logcat, so `assert noErrors` cannot fail there; its launch is `monkey` with +one random event, so a replay can start with a stray key; and a flow that +asserts focus or visibility always fails, because it has no Android UI tree. + +### What is not proven + +The fleet's Roku has never run this suite: its developer password is not in +the host's Keychain, so no run from the fleet has got past the skip. The step +sequencing, the skip, the scrubbing and the Android TV path are covered by +unit tests that fake each step's exit code; the Android TV adapter's caveats +above were seen driving an Android TV emulator through tvloop, not from this +workload on a real TV. + ## `ui-test` Maestro flows or an XCUITest bundle, per device, with the JUnit report parsed @@ -192,7 +265,8 @@ back into results and uploaded as an artifact. "lease": { "ttl_s": 1200 } } ``` -Flows resolve relative to `flows/` (`FLEET_FLOWS_DIR` to change). `exclusive` +Flows resolve relative to `examples/flows/` in the executor's working +directory (`FLEET_FLOWS_DIR` to change). `exclusive` takes a device lock for the run, because two suites tapping the same phone is not a test. @@ -342,8 +416,11 @@ is kept forever. review pulls must run daily.** A lazy cadence loses data permanently. Credentials are Keychain items on the executor host. The job spec names the -account only, never the secret — `POST /jobs` is unauthenticated, so a spec is -not a place a credential could safely live. Until the Keychain item exists the +account only, never the secret: a spec is stored and shown to anyone who can +read jobs, and the collector has no authentication by default (see +[Authentication](../deploy/auth.md)), so a spec is not a place a credential +could safely live. Enqueue refuses a spec carrying a `password`, `token` or +similar key as `secret_in_spec`. Until the Keychain item exists the job fails with instructions rather than silently producing nothing. ## `digest` diff --git a/docs/workloads/index.md b/docs/workloads/index.md index 226b38f..0f9084c 100644 --- a/docs/workloads/index.md +++ b/docs/workloads/index.md @@ -4,7 +4,13 @@ What the fleet can be asked to do. A workload is the `workload` field of a job spec, and which agent claims it is decided by [capabilities](../concepts.md#capabilities) rather than by anything hardcoded. -![Twenty-eight workloads in three columns by who claims them: on the device, on a host, and on a machine](../img/workloads.png) +![The workloads in three columns by who claims them: on the device, on a host, and on a machine](../img/workloads.png) + +The collector ships 34 workloads. `GET /api/v1/workloads` (or +`fleetr workloads`) lists the same set with each one's params and an example +spec, and marks three more names as reserved: `push-latency`, `camera-eval` and +`desktop-ui-test` are accepted, but no runner in this repository implements +them yet. | Workload | Runs on | What it measures | |---|---|---| @@ -24,6 +30,9 @@ spec, and which agent claims it is decided by | [`a11y-audit`](host.md#a11y-audit) | host | The accessibility tree diffed against a baseline at the largest dynamic type | | [`locale-shots`](host.md#locale-shots) | host | A screenshot flow under every locale, including RTL, as a contact sheet | | [`explore`](host.md#explore) | host | A vision model explores tonight's build; reproduced crashes, hangs, dead controls, accessibility and visual defects, filed as findings | +| [`upgrade-test`](host.md#upgrade-test) | host | Install the version users have, seed it, upgrade in place, and check the data survived | +| [`size-report`](host.md#size-report) | host | Download, installed and archive size of a published build, with native libraries per ABI | +| [`tvloop`](host.md#tvloop) | host | tvloop's hardware suite on a Roku the fleet has locked; Fire TV and Android TV replay its flows too when asked | | [`web-test`](host.md#web-test) | host | Playwright suites, including on real phone screens | | [`web-shots`](host.md#web-shots) | host | Visual regression captures diffed against an accepted baseline | | [`web-audit`](host.md#web-audit) | host | Crawl-and-audit with a real browser | @@ -37,6 +46,7 @@ spec, and which agent claims it is decided by | [`dataset-prep`](machine.md#dataset-prep) | machine | An eval set, carrying its licence and source on the row | | [`serve`](machine.md#serve) | machine | Host a model for the length of a lease and announce its endpoint | | [`shell`](machine.md#shell) | machine | A pinned script, behind an allowlist the owner controls | +| [`llm-eval`](machine.md#llm-eval) | machine | Scores what a device generated against an eval set, so a fast quantised model is also shown to be right | | [`self-check`](machine.md#self-check) | host, machine | The fleet inspecting its own hosts: disk, tool versions, clock drift | ## How to read these pages diff --git a/docs/workloads/machine.md b/docs/workloads/machine.md index 188c35b..52d1468 100644 --- a/docs/workloads/machine.md +++ b/docs/workloads/machine.md @@ -78,7 +78,9 @@ to the one anybody asked for. ## `shell` Runs a pinned script. This is the one workload that cannot take the collector's -word for anything, because `POST /jobs` is unauthenticated by design. +word for anything, because by default `POST /jobs` is unauthenticated, and even +with [tokens](../deploy/auth.md) on, only `/api/v1` asks for `admin` before it +queues a `shell` job. The gating, in order: diff --git a/fleet/README.md b/fleet/README.md index 1afbaa0..4f55b71 100644 --- a/fleet/README.md +++ b/fleet/README.md @@ -45,10 +45,12 @@ once and then cannot start the fleet. |---|---| | `fleet up [--role brain,agent,executor] [--join ] [--port N]` | This machine's components, supervised. Roles are a list because the first machine this exists for is a brain and a runner at once | | `fleet collector` / `fleet agent` / `fleet executor` | Just the one component, in this process | -| `fleet join ` | Run a runner pointed at a brain elsewhere, and write that down | +| `fleet join ` / `fleet join --discover` | Run a runner pointed at a brain elsewhere, and write that down. `--discover` looks for a brain advertising over mDNS instead (off on the brain by default: `collector.discovery`) | | `fleet status` | What this fleet looks like right now: devices online, jobs by state, per collector | | `fleet doctor` | What this machine can and cannot run, **and why not** — adb, full Xcode against the Command Line Tools, Playwright, Maestro, and the capability list the agent would actually declare | | `fleet dash` | Open the dashboard | +| `fleet mcp [--url U] [--token T]` | The lab as MCP tools over stdio, for a coding agent on this machine. See below | +| `fleet mcp --http --issuer --audience ` | The same tools as a remote MCP server behind your identity provider's OAuth | | `fleet service install\|uninstall\|start\|stop\|status\|logs` | Start at login and stay up: launchd, systemd or a scheduled task, whichever this machine has | | `fleet config` / `config get ` / `config set ` | Read and write `~/.fleet/config.json` | | `fleet version` | | @@ -60,17 +62,19 @@ somebody put it in. ### Work commands Running jobs rather than running the fleet. Each calls `/api/v1` through the generated -client in `collector/src/client/`, takes `--url`, `--token` and `--json`, and exits with the -verdict: **0** passed, **1** failed, **2** usage or invalid spec, **3** still running, **4** -skipped (nothing ran), **5** refused or unreachable. +client in `collector/src/client/`, takes `--url`, `--token` and `--json` (except that +`token` reads the tokens file, `--tokens-file`, rather than calling a collector, and +`skill` and `logout` ignore `--token`), and exits with the verdict: **0** passed, **1** +failed, **2** usage or invalid spec, **3** still running, **4** skipped (nothing ran), +**5** refused or unreachable. | | | |---|---| | `fleet devices` / `fleet workloads [NAME]` | What is on the shelf; what it can run, with an example spec | -| `fleet run WORKLOAD [--device\|--pool\|--match] [--param k=v] [--spec FILE]` | Validate, queue, wait, print the verdict. `--validate` checks only; `--no-wait` prints the id | +| `fleet run WORKLOAD [--device\|--pool\|--match] [--app NAME] [--param k=v] [--target k=v] [--fanout] [--spec FILE\|-] [--timeout S]` | Validate, queue, wait (default 1800 s), print the verdict. `--validate` checks only; `--no-wait` prints the id. The full flag list is in [AI agents and automation](../docs/agents.md#the-cli) | | `fleet job ID` / `fleet wait ID` | A verdict now, or when it finishes | | `fleet cancel ID` / `fleet retry ID` | | -| `fleet results` / `fleet flaky` / `fleet artifact SHA [--out FILE]` | What ran, what flips, and the files it left | +| `fleet results` / `fleet flaky` / `fleet artifact SHA [--out FILE\|DIR\|-]` | What ran, what flips, and the files it left. `--out` is a directory only if it already exists | | `fleet login` / `logout` / `whoami` | Save a token for a collector (`~/.fleet/credentials.json`, 0600) | | `fleet token create\|list\|revoke` | On the brain's host: the collector's tokens, for `FLEET_AUTH=tokens` | | `fleet skill show\|install` | The agent skill, into Cursor, Claude Code and Codex | @@ -104,8 +108,11 @@ fleet skill install ``` It finds the brain the way the agent does -- `--url`, then `FLEET_RUNNER_URL` or -`FLEET_URL`, then the config -- and adds nothing the HTTP API does not already do: one -scheduler, one set of device locks, and nothing an agent can do that curl could not. +`FLEET_URL`, then the config -- and its token the way every work command does: `--token`, +then `FLEET_RUNNER_TOKEN`, then `FLEET_TOKEN`, then what `fleet login` saved for that URL. +`FLEET_SOURCE` overrides the `source` label jobs are recorded with. It adds nothing the +HTTP API does not already do: one scheduler, one set of device locks, and nothing an agent +can do that curl could not. `fleet mcp --http` is the same tools as a remote MCP server behind your identity provider's OAuth, for chat clients and people without `fleet` installed. See @@ -153,7 +160,7 @@ is almost always that. ### The settings this file has no key for -The three programs read about twenty `FLEET_*` variables and the config names six. The rest +The three programs read many more `FLEET_*` variables than the config has keys for. The rest are per-deployment facts with no good home — where this host's Maestro flows live, where its Playwright specs live, which Xcode project the generic iOS bundle builds from, whether web workloads are enabled here, where alerts go. `env` carries them: @@ -191,7 +198,9 @@ and which will otherwise restart a broken collector every ten seconds forever. ## Status -What has actually been watched to work, on **macOS/arm64 and nowhere else**: +What has actually been watched to work on **macOS/arm64**. The one other machine with +mileage is an Intel Mac on macOS 12 running a real brain under `fleet service` (below); +Windows and Linux have CI coverage only: - `fleet up` starting a supervised brain and agent, and a synthetic benchmark running end to end through them — from a checkout, and from the bundled release. diff --git a/mkdocs.yml b/mkdocs.yml index 2b67042..3c8a399 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -139,7 +139,6 @@ nav: - Headless hosts: deploy/headless.md - Networking: deploy/networking.md - The iOS executor: deploy/ios-executor.md - - Exploratory QA on ultra: deploy/explore-on-ultra.md - Alerts: deploy/alerts.md - Authentication and MCP gateway: deploy/auth.md - This lab: lab.md diff --git a/runner-android/README.md b/runner-android/README.md index 510a76a..48a1533 100644 --- a/runner-android/README.md +++ b/runner-android/README.md @@ -10,6 +10,12 @@ to: llama.cpp and LiteRT benchmarks, batch inference, and image-classification evals, with a telemetry beacon reporting battery, charging and thermal state every 60 seconds. +The same APK installs on Android TV, Google TV and Fire TV, on a Meta Quest +and on Wear OS, and works out at run time which of those it is on. That is +less proven than it sounds: the APK declares a leanback launcher and a banner +(checked with `aapt2 dump badging`) but no TV has run it, and no Quest or Wear +device ever has. [Platforms](../docs/platforms.md) has the state of each. + Old hardware is the point. A phone too slow for an LLM still runs the synthetic backend and still produces a comparable number, which is what makes a drawer of retired handsets useful as a test matrix instead of e-waste. @@ -41,7 +47,7 @@ Open the app, keep the default `http://127.0.0.1:8788`, tap **Start agent**, then enqueue a job: ``` -curl -X POST http://127.0.0.1:8788/jobs -H 'content-type: application/json' -d '{ +curl -X POST http://127.0.0.1:8788/api/v1/jobs -H 'content-type: application/json' -d '{ "schema": 1, "job_id": "bench-synthetic-1", "workload": "benchmark", "executor": "device", "backend": "synthetic", "params": { "prompt_tokens": 256, "gen_tokens": 64, "warmup_iters": 1, "measure_iters": 3 }, @@ -62,6 +68,11 @@ SM-X930, not an emulator. `benchmark`, `batch`, `batch:litert`, `pipeline`, dispatched from the same table, so the collector is never offered work this runner would bounce back. +**Android 7.0 and 7.1 (API 24-25) start the runner service with +`startService`**, because `startForegroundService` only exists from API 26 and +threw `NoSuchMethodError` there. That fix is covered by a Robolectric test and +has not run on a real API 24 or 25 device. + **There is no offline result queue.** Results retry through the agent loop's backoff and nothing else, so a device that loses the collector for longer than that loses those rows. This is the one gap worth knowing about before you trust @@ -77,6 +88,12 @@ the suite with no NDK installed: ./gradlew :app:testDebugUnitTest -Pfleet.skipNative ``` +CI also runs `./gradlew :app:lintDebug -Pfleet.skipNative`. Passing it meant +dropping the manifest's `android.hardware.type.watch` feature line, which lint +rejects as not-required and which a store reads as Wear-only; the runner still +detects a watch at run time. No Wear device has run the APK before or after +that change. + ## License MIT — see [LICENSE](LICENSE). llama.cpp, LiteRT, and the terms they carry are diff --git a/runner-machine/README.md b/runner-machine/README.md index a742a33..bea0461 100644 --- a/runner-machine/README.md +++ b/runner-machine/README.md @@ -29,11 +29,19 @@ deploy/install-agent.sh com.addisdev.fleet-runner-machine.plist # or the .serv | `benchmark` | `llama.cpp` | Model fetched by content hash and verified, then `llama-bench`: prefill/decode tok/s, load time, peak memory with the method named | | `build` | `gradle`, `xcode`, `npm` | Checks out `params.ref`, builds it, and publishes the product as the app's latest build. Reports `build_s` and `artifact_bytes` | | `self-check` | — | Disk, tool versions, NTP offset and whether the installed agent is the one running. Reports `disk_free_gb`, `clock_offset_ms`, `checks_failed` plus a per-check breakdown | +| `llm-eval` | — | Scores what a device generated against an eval set: exact, regex and JSON-shape rules, plus a model judge at an endpoint the job names | +| `model-convert` | `gguf`, `coreml`, `tflite` | A checkpoint into GGUF, Core ML or TFLite, declared per format whose toolchain resolves here; each output is uploaded for a dependent job | +| `dataset-prep` | — | An eval set, carrying its licence and source on the row. Declared only when a converter resolves | +| `serve` | — | `llama-server` for the length of a lease, bound to loopback or the tailnet, with its endpoint announced | +| `shell` | — | A script whose sha256 the owner pinned in `FLEET_SHELL_ALLOWLIST` (default `shell-allowlist.txt` in the data directory). Not declared without a non-empty allowlist | + +Each is described in [the machine workloads page](../docs/workloads/machine.md). Capabilities are declared only when honest: `benchmark:llama.cpp` needs a resolvable `llama-bench`, `benchmark:mlx` needs `import mlx_lm` to exit 0, `build:gradle`/`build:xcode`/`build:npm` each need -their binary (`gradle`, `xcodebuild`, `node`) to resolve, and a machine with none of it still -declares `benchmark` and `self-check`, both of which need nothing installed. +their binary (`gradle`, `xcodebuild`, `node`) to resolve, `model-convert:` and +`dataset-prep` need a converter toolchain, `serve` needs `llama-server`, and a machine with none +of it still declares `benchmark`, `self-check` and `llm-eval`, which need nothing installed. Bare `build` rides along with any kind — the collector matches a claim on the workload name and a build's kind lives in `params` where `capabilityMatches` cannot see it, so a machine declaring only `build:gradle` would never claim a build at all. @@ -76,6 +84,10 @@ against a throwaway collector, as are `build` (success, failure, log upload, pub against `kind: "npm"` only — the gradle and xcode command lines are unit-tested but have never run a real compiler, and the `.app` zip path and the `xcodegen` step with them. +`model-convert`, `dataset-prep` and `serve` have never run against a real toolchain: none of the +converters resolves on the development machine, the probes correctly decline to declare them, and +the command lines are unit-tested only. + The llama.cpp backend is unit-tested against llama-bench's documented JSON shape but never run against a real binary; the Windows probes are untested on Windows; `benchmark:mlx` has no backend yet; and off Linux `mem_method` says `max_rss`, a value the From 95436588174412b368a0a1251831f53f0d83a8aa Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 20:45:19 -0400 Subject: [PATCH 03/19] docs: hand-placed figures replace the last mermaid diagrams The explore docs' night flowchart, one mission's sequence and the code map were the only mermaid left. They are now figures in docs/figures/ (explore-night, explore-step, explore-code) on brand.css and symbols.js, rendered by `npm run assets` to PNG at 2x, every label checked against the code (replay_attempts 2, PRECISION_FLOOR 0.3 with ten judged, the pilot and vision gateway defaults, fileable() filing crash logs unreplayed). The docs workflow now fails on a mermaid fence under docs/, and mkdocs.yml drops the mermaid custom fence. workloads.html shows all 34 shipped catalog entries (adds enrol, explore, upgrade-test, size-report, tvloop, llm-eval), so the README loses its "the figure predates six of them" aside. devices.png (the PR #69 device drawings) and a new findings.png come from the lab's running brain via a new read-only `npm run shoot:live`, filtered to online devices and the bug-garden fixture app; brand.md records why a throwaway collector cannot honestly make either. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/docs.yml | 10 ++++ CHANGELOG.md | 14 +++++ README.md | 7 ++- collector/package.json | 1 + collector/scripts/shoot-live.ts | 45 ++++++++++++++++ docs/brand.md | 25 +++++++-- docs/dashboard.md | 2 + docs/explore/findings.md | 2 + docs/explore/how-it-works.md | 27 +--------- docs/explore/index.md | 13 +---- docs/explore/internals.md | 17 +----- docs/figures/explore-code.html | 88 +++++++++++++++++++++++++++++++ docs/figures/explore-night.html | 90 ++++++++++++++++++++++++++++++++ docs/figures/explore-step.html | 86 ++++++++++++++++++++++++++++++ docs/figures/workloads.html | 64 ++++++++++++++--------- docs/img/devices.png | Bin 75004 -> 110112 bytes docs/img/explore-code.png | Bin 0 -> 183937 bytes docs/img/explore-night.png | Bin 0 -> 197419 bytes docs/img/explore-step.png | Bin 0 -> 271025 bytes docs/img/findings.png | Bin 0 -> 202567 bytes docs/img/workloads.png | Bin 129369 -> 144575 bytes docs/workloads/index.md | 2 +- mkdocs.yml | 6 +-- 23 files changed, 405 insertions(+), 94 deletions(-) create mode 100644 collector/scripts/shoot-live.ts create mode 100644 docs/figures/explore-code.html create mode 100644 docs/figures/explore-night.html create mode 100644 docs/figures/explore-step.html create mode 100644 docs/img/explore-code.png create mode 100644 docs/img/explore-night.png create mode 100644 docs/img/explore-step.png create mode 100644 docs/img/findings.png diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index dd68603..59aa5a3 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -41,6 +41,16 @@ jobs: - run: pip install -r requirements-docs.txt + # Diagrams are hand-placed figures in docs/figures/, rendered to PNG + # (docs/brand.md says why). mkdocs.yml no longer has a mermaid fence, so + # one would build as a plain code block rather than fail; this makes it fail. + - name: No mermaid + run: | + if grep -rn --include='*.md' '^ *```mermaid' docs/; then + echo "::error::mermaid diagram under docs/: draw it as a figure in docs/figures/ instead (docs/brand.md)" + exit 1 + fi + # The cookbook includes collector/examples/jobs/*.json verbatim via the # snippets extension, so a missing or renamed example fails the build # here as well as failing the collector's own suite. diff --git a/CHANGELOG.md b/CHANGELOG.md index b1b6bbf..fbeaeb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,20 @@ a CI job fails when they disagree. ## [Unreleased] +### Changed + +- **The explore docs' three diagrams are drawn, not generated.** The night, + one mission's sequence and the code map were mermaid blocks; they are now + figures in `docs/figures/` rendered to PNG like the rest + (`explore-night`, `explore-step`, `explore-code`). The docs workflow fails on + a mermaid fence under `docs/`, and `mkdocs.yml` no longer configures one. +- **The workloads figure shows all 34 shipped workloads.** It had 28; `enrol`, + `explore`, `upgrade-test`, `size-report`, `tvloop` and `llm-eval` are added. +- **`devices.png` is the new device drawings, and there is a `findings.png`.** + Both are captured read-only from a running brain by the new + `npm run shoot:live`, filtered to what was online and to the `bug-garden` + fixture app; docs/brand.md says why a throwaway collector cannot make them. + ### Fixed - **`fleet skill` failed on an installed 0.8.0.** The 0.8.0 archives carry diff --git a/README.md b/README.md index c46f42b..76957e9 100644 --- a/README.md +++ b/README.md @@ -138,11 +138,10 @@ something a runner can do without the collector shipping a release. ## What it can run -![Twenty-eight workloads in three columns by who claims them: on the device, on a host, and on a machine](docs/img/workloads.png) +![Thirty-four workloads in three columns by who claims them: on the device, on a host, and on a machine](docs/img/workloads.png) -Thirty-four workloads (the figure predates six of them, `explore` and `tvloop` -among them), and the column a workload sits in is the answer to "who can -physically do this". A benchmark runs inside the app on the phone. An +Thirty-four workloads, and the column a workload sits in is the answer to +"who can physically do this". A benchmark runs inside the app on the phone. An install needs a cable and a Mac. A build needs a checkout and a toolchain. Each has [its own page](https://addisdev.github.io/fleet-runner/workloads/), saying what it measures and what it refuses to guess. diff --git a/collector/package.json b/collector/package.json index 57ba697..acb267d 100644 --- a/collector/package.json +++ b/collector/package.json @@ -26,6 +26,7 @@ "chaos": "tsx scripts/chaos.ts", "assets": "tsx scripts/render-assets.ts", "shoot:dash": "tsx scripts/shoot-dash.ts", + "shoot:live": "tsx scripts/shoot-live.ts", "shoot:motion": "tsx scripts/shoot-motion.ts" }, "dependencies": { diff --git a/collector/scripts/shoot-live.ts b/collector/scripts/shoot-live.ts new file mode 100644 index 0000000..3fc9e94 --- /dev/null +++ b/collector/scripts/shoot-live.ts @@ -0,0 +1,45 @@ +// The two dashboard screenshots a throwaway collector cannot honestly produce, +// captured read-only from a running brain. +// +// npm run shoot:live -- --url http://127.0.0.1:18788 +// +// shoot-dash.ts starts a fresh collector with one machine agent, so its Devices +// screen is a single laptop and its Findings screen is empty: the device +// drawings need a shelf of real devices, and findings need a real explore night +// with a real model. Seeding either would be inventing data. This script only +// opens two pages on a brain that already has both, and writes nothing to it. +// +// Both views are filtered, and the filter is visible in the picture: +// devices.png status=online, so the shelf shows what is plugged in now +// findings.png app=bug-garden, the fixture app whose defects are planted on +// purpose; findings against a real product stay out of the docs +import path from "node:path"; +import { chromium } from "playwright"; + +const at = process.argv.indexOf("--url"); +const BASE = (at === -1 ? process.env.FLEET_URL : process.argv[at + 1])?.replace(/\/$/, ""); +if (!BASE) { + console.error("usage: npm run shoot:live -- --url http://brain:8788"); + process.exit(2); +} +const OUT = path.resolve(import.meta.dirname, "../../docs/img"); + +const SHOTS: [route: string, name: string][] = [ + ["/dash/devices?status=online", "devices"], + ["/dash/findings?app=bug-garden", "findings"], +]; + +const browser = await chromium.launch(); +try { + const page = await browser.newPage({ viewport: { width: 1440, height: 900 }, deviceScaleFactor: 1 }); + await page.emulateMedia({ colorScheme: "dark" }); + for (const [route, name] of SHOTS) { + await page.goto(`${BASE}${route}`, { waitUntil: "networkidle" }); + // The dashboard renders from its own fetches, not from the document. + await page.waitForTimeout(2000); + await page.screenshot({ path: path.join(OUT, `${name}.png`) }); + console.log(`wrote ${name}.png from ${BASE}${route}`); + } +} finally { + await browser.close(); +} diff --git a/docs/brand.md b/docs/brand.md index 9b8e7dd..4abce47 100644 --- a/docs/brand.md +++ b/docs/brand.md @@ -72,12 +72,16 @@ dependency, so nothing new is installed. | `img/architecture.png` | 2560×1280 | `figures/architecture.html` | | `img/lifecycle.png` | 2560×1360 | `figures/lifecycle.html` | | `img/protocol.png` | 2560×1120 | `figures/protocol.html` | -| `img/workloads.png` | 2560×1200 | `figures/workloads.html` | +| `img/workloads.png` | 2560×1360 | `figures/workloads.html` | | `img/platforms.png` | 2560×1400 | `figures/platforms.html` | +| `img/explore-night.png` | 2560×1400 | `figures/explore-night.html` | +| `img/explore-step.png` | 2560×2040 | `figures/explore-step.html` | +| `img/explore-code.png` | 2560×1384 | `figures/explore-code.html` | | `img/first-result.png`, `alerts.png`, `visual.png` | 1440 wide | `npm run shoot:dash` | | `img/fanout.gif` | 1280 wide, 18 s | `npm run shoot:motion` | | `img/shelf-banner.jpg`, `shelf-social.jpg` | 2560×1280, JPEG | `figures/shelf-banner.html`, `figures/shelf-social.html` — **skipped until [the photograph](#the-shelf-photograph) exists** | -| `img/overview.png`, `devices.png`, `jobs.png`, `results.png` | | Dashboard pages, captured with Playwright against a running collector | +| `img/overview.png`, `jobs.png`, `results.png` | | Dashboard pages, captured with Playwright against a running collector | +| `img/devices.png`, `findings.png` | 1440×900 | `npm run shoot:live -- --url `, read-only against the lab's running brain | | `img/runner-web.png` | | `npm run shoot:runner-web`, against a throwaway collector | | `runner-ios/.../AppIcon.appiconset/icon-1024.png` | 1024×1024, no alpha | `img/icon-source.svg` | | `runner-android/.../mipmap*/ic_launcher.xml` | vector | Drawn as Android vector drawables from the same geometry | @@ -99,7 +103,8 @@ The diagrams are placed by hand rather than generated by mermaid because a layout engine is for people who do not want to place boxes, and a diagram somebody will look at for ten seconds is placed boxes. Mermaid also renders in GitHub's own theme, which is the one thing on the page that cannot be made to -match the rest. +match the rest. No page uses it any more: the docs workflow fails on a +mermaid fence anywhere under `docs/`, and the site no longer loads it. ### The live captures @@ -194,9 +199,9 @@ holds. gets believed and turns out to be invented costs more than a missing picture. -!!! note "Two of these were captured against different fleets, on purpose" +!!! note "These were captured against different fleets, on purpose" - `overview.png`, `devices.png` and `jobs.png` show a **live** two-device + `overview.png` and `jobs.png` show a **live** two-device fleet — a laptop and an iPhone simulator, both running the real agents, with a thermal run in progress and a `self-check` correctly failing because the agent was started by hand rather than by launchd. They were captured @@ -207,6 +212,16 @@ holds. captured while the laptop was on a different network from the shelf. That set was honest and read as abandoned. + **`devices.png` and `findings.png` are from the lab's running brain**, on + 15 October 2026, because a throwaway collector cannot have either: the + device drawings need a shelf of real hardware, and a finding needs a real + `explore` night with a real model. `npm run shoot:live` only opens the two + pages; it writes nothing. Devices is filtered to what was online (five of + twenty registered), and Findings to `bug-garden`, the fixture app whose + defects are planted on purpose, so no real product's open bugs are + published. Both filters are visible in the picture. The four open alerts in + the banner are real too: shelf devices that had not checked in. + **`results.png` is deliberately not from that fleet.** It shows real llama.cpp measurements from an SM-X930 — 125.0 prefill and 47.4 decode tok/s on a Dimensity 9400 — which is stored history a fresh database cannot diff --git a/docs/dashboard.md b/docs/dashboard.md index eeb6c64..65d56af 100644 --- a/docs/dashboard.md +++ b/docs/dashboard.md @@ -11,6 +11,8 @@ SQLite file. One thing to keep alive, one URL, no CORS. | **Jobs** — the queue, with a composer and cancel/retry | **Results** — benchmark trends, eval accuracy, UI-test matrices, drain curves | | ![Visual](img/visual.png) | ![Alerts](img/alerts.png) | | **Visual** — every page across every profile, diffed against its accepted baseline | **Alerts** — one row per condition for as long as it holds, with acknowledge and snooze | +| ![Findings](img/findings.png) | | +| **Findings** — what an [`explore`](explore/index.md) night reproduced, with a verdict for each | | These screenshots are from 2026-09-05. They predate the device drawings described below, and there is none of the Findings screen. diff --git a/docs/explore/findings.md b/docs/explore/findings.md index 52dc2d7..56ca534 100644 --- a/docs/explore/findings.md +++ b/docs/explore/findings.md @@ -6,6 +6,8 @@ What a night leaves behind, and how your judgement of it steers the next one. **Findings** in the dashboard's top bar, or g f. +![The Findings page filtered to the bug-garden fixture app: 59 open findings, none triaged yet, each row with its severity, check, title and screen, how often and on how many builds it was seen, "reproduced 2/2", and when it was first and last seen](../img/findings.png) + The **list** can be filtered by app, check and status (open, triaged, all). Each row shows severity, check, title, screen, how many times and on how many builds it has been seen, how it replayed ("reproduced 2/2", "flaky 1/2", diff --git a/docs/explore/how-it-works.md b/docs/explore/how-it-works.md index 6302881..a7fdf54 100644 --- a/docs/explore/how-it-works.md +++ b/docs/explore/how-it-works.md @@ -4,32 +4,7 @@ One `explore` job is one night on one or more devices. For each device it runs mission cards in order until the night's budget is spent, then confirms what it found and files what holds up. -```mermaid -sequenceDiagram - participant E as Executor (explore) - participant D as Device (actuator) - participant M as Model (driver) - participant J as Judge - participant C as Collector - E->>D: reset (install, clear data, launch, sign in) - loop each step, until answer, budget, time or stuck - E->>D: observe (screenshot, tree, foreground, focus) - E->>E: screen map, oracle checks - E-->>J: new screen? judge it (once per screen) - E->>M: screenshot + harness notes - M-->>E: tool calls - E->>E: snap and leash each action - E->>D: act, settle - E->>D: crashes since last step - E-->>C: beacon (renews the lease) - end - E->>J: goal met? (cards with a success line) - loop each candidate, worst first - E->>D: reset, replay the steps, ask the check again (x2) - end - E->>C: POST /findings (reproduced, or a crash) - E->>C: result row with metrics -``` +![One mission as a sequence between the executor, the device, the model, the judge and the collector: reset the device; then each step observe, place the screen and run the checks, have the judge look at a new screen, send the model the screenshot and get tool calls back, snap and leash the actions, act, read the crashes and beacon the collector; after the mission ask the judge whether the goal was met, replay each candidate twice, and post the findings and the result row](../img/explore-step.png) ## Before the first step diff --git a/docs/explore/index.md b/docs/explore/index.md index 378041f..871414e 100644 --- a/docs/explore/index.md +++ b/docs/explore/index.md @@ -10,18 +10,7 @@ in Spanish. A model reads each screenshot and picks the next action; the harness checks that action, performs it, and looks for trouble after every step. Nothing it sees is believed until it happens again on a clean install. -```mermaid -flowchart TD - A[Tonight's build] --> B[Mission cards] - B --> C{{"Look, decide, act
(the model)"}} - C --> D[Checks after every step] - D -->|candidate| E[Replay twice on a clean install] - E -->|reproduced| F[Finding] - E -->|not reproduced| X[Dropped] - F --> G[Findings page, digest, optional issue] - G -->|your verdict| H[Precision per check] - H -->|under 30%| D -``` +![One night of exploratory QA: tonight's build and the mission cards go to the model, which looks, decides and acts while checks look for trouble after every step; a candidate is replayed twice on a clean install and becomes a finding only if it reproduces at least once or was a crash with a log, otherwise it is dropped; findings go to the Findings page, the digest and optionally an issue, and your verdicts give each check a precision that switches it off for that app under 30% once ten are judged](../img/explore-night.png) ## What you get in the morning diff --git a/docs/explore/internals.md b/docs/explore/internals.md index 85e1561..eb08788 100644 --- a/docs/explore/internals.md +++ b/docs/explore/internals.md @@ -47,22 +47,7 @@ The model speaks 0–1000; `convertCall` maps to pixels; each actuator maps pixels to its own input units (device pixels on Android, points on Apple devices). -```mermaid -flowchart TB - subgraph Executor - IDX[index.ts
per device, per mission] --> LOOP[loop.ts
runMission / confirm] - LOOP --> MODEL[model.ts
Conversation] - LOOP --> JUDGE[judge.ts] - LOOP --> LEASH[leash.ts] - LOOP --> MAP[screenmap.ts] - LOOP --> ACT{{actuators/}} - IDX --> REP[report.ts, replay.ts] - end - ACT --> ADB[adb] & FD[FleetDriver over HTTP] & TV[tvloop adapter] - MODEL & JUDGE --> GW[(gateway
pilot / vision)] - IDX -->|POST /findings, /results, /artifacts| COL[(Collector)] - COL --> DASH[Findings page] -``` +![The explorer's code map: index.ts calls loop.ts and report.ts and replay.ts; loop.ts uses model.ts, judge.ts, leash.ts and screenmap.ts each step and actuators/ to reach the device over adb, FleetDriver or tvloop; model.ts and judge.ts call the gateway's pilot and vision models; index.ts posts findings, results and artifacts to the collector and its Findings page](../img/explore-code.png) ## Tests diff --git a/docs/figures/explore-code.html b/docs/figures/explore-code.html new file mode 100644 index 0000000..a254fd0 --- /dev/null +++ b/docs/figures/explore-code.html @@ -0,0 +1,88 @@ + + +explore-code + + +
+ + + + + + + + index.ts + per device, per mission; confirm, file + + + report.ts · replay.ts + steps in words, the replay flow + + + + loop.ts + runMission · confirm + + + + each step + + + model.ts + + judge.ts + + leash.ts + + screenmap.ts + + + + + actuators/ + android.ts · apple.ts · roku.ts + + + types.ts is the contract every file here agrees on. + Outside model.ts, every coordinate is in screenshot pixels. + the executor · collector/src/workloads/explore/ + + + + findings, results, artifacts + + + collector + the findings store + + + + Findings page + where your verdicts go + + + + gateway + pilot drives · vision judges + + + + the device + adb + Android, Fire TV + FleetDriver + Apple, over HTTP + tvloop + Roku + + +
+ diff --git a/docs/figures/explore-night.html b/docs/figures/explore-night.html new file mode 100644 index 0000000..4290455 --- /dev/null +++ b/docs/figures/explore-night.html @@ -0,0 +1,90 @@ + + +explore-night + + +
+ + + One night, per device. Nothing the model or a check sees is believed until it happens again on a clean install. + + + + tonight's build + installed, data cleared + + + mission cards + today's changes first + + + look · decide · act + the model reads the screen + + + checks after every step + crash · dead control · the judge + + + + + + + leashed action + + next screenshot + + + + candidate + + + replay twice + clean install, the same steps + + + at least 1 of 2, + or a crash log + + + finding + screenshot, steps, a flow + + + + + Findings page · digest · issue + a repeat raises a count, not a second report + + + + not reproduced + + dropped + counted in explore_not_reproduced + + + + your verdict + + + precision per check + Real · Duplicate · Not a bug · Agent's mistake + + + + under 30% once ten are judged: switched off for that app from the next night + crashes and ANRs are never switched off; their evidence is the platform's own log + +
+ diff --git a/docs/figures/explore-step.html b/docs/figures/explore-step.html new file mode 100644 index 0000000..cb1d107 --- /dev/null +++ b/docs/figures/explore-step.html @@ -0,0 +1,86 @@ + + +explore-step + + +
+ + + One mission. Only the executor talks; the device, both models and the collector never talk to each other. + + + + + + + + + executor + explore + + + device + actuator + + model + pilot + + judge + vision + + collector + the brain + + + reset · install, clear, sign in + + each step, until answer, budget, time or stuck + + observe · screenshot, tree, focus + + screen map, then the checks + + a new screen? judge it, once per screen + + the screenshot and the harness notes + + tool calls + + snap and leash each action + + act, then let the screen settle + + crashes since the last step + + beacon · renews the lease + + goal met? cards with a success line + + each candidate, worst first · twice + + reset, replay, ask the check again + + POST /findings · reproduced, or a crash + + the result row, with its metrics + + + + + the executor asks + + the model answers + gateway defaults: pilot drives, vision judges + +
+ diff --git a/docs/figures/workloads.html b/docs/figures/workloads.html index c8d5318..7e52e10 100644 --- a/docs/figures/workloads.html +++ b/docs/figures/workloads.html @@ -6,18 +6,20 @@ Everything the fleet knows how to run, grouped by who claims it. The columns are the three executors; the routing is on declared capabilities, so this is a picture of what the agents in this repository say they can do rather than - a list the collector hardcodes. + a list the collector hardcodes. The source of truth is the shipped entries in + collector/src/workloads/catalog.ts (runs_on); the three reserved names are + left out because nothing here runs them. Rendered by `npm run assets` in collector/ to docs/img/workloads.png. --> -
- +
+ - 28 workloads. Which agent claims one is decided by the capabilities it declared, not by anything hardcoded. + 34 workloads. Which agent claims one is decided by the capabilities it declared, not by anything hardcoded. - - + + on the device @@ -48,34 +50,44 @@ an executor on a Mac with a cable - install + enrol - ui-test + install - cold-start + upgrade-test - app-soak + ui-test - a11y-audit + cold-start - locale-shots + app-soak - drain + a11y-audit + + locale-shots + + explore + + drain - web-test + size-report - web-shots + tvloop - web-audit + web-test - web-unfurl + web-shots - soak + web-audit - archive + web-unfurl - digest + soak + + archive + + digest @@ -93,13 +105,15 @@ shell - self-check - + llm-eval + + self-check + - - also claimable elsewhere — benchmark and vantage run on a machine too, and self-check on a host + + also claimable elsewhere — benchmark and vantage run on a machine too, and self-check on a host
diff --git a/docs/img/devices.png b/docs/img/devices.png index 301228d7cb0633aa3c87bebe940d18a504677cf6..e701e2b46172a3ec109029a99a112a9e41fdf480 100644 GIT binary patch literal 110112 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 KmM^0F<-Y+Kf7?y~ diff --git a/docs/img/explore-code.png b/docs/img/explore-code.png new file mode 100644 index 0000000000000000000000000000000000000000..327117a1e36bdd0176f86c4b80c555ddf0e5b5f1 GIT binary patch literal 183937 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 z zm*L9fGG{(~NXbacVxDL3)f%a@C_9{ZQaDrwG;u4?(er{jGi|hTe2Q(fw(5ve_1by( zs13G8O~R#i9PoMmOBNQhz+7H#Zix{lcahZ4QNOC{su~Hr|7tVP2;<_}kZ^U_5EoCO z$?r>#Mr7BgZ^jmOU=lfvuZZo^{_*Dc_Cln?7>F{mwP#_G$*)OwvsN9L|2KmWDu3HQ zP77U^bAiT=%X~=3eEIl<>xQd9vfe+n6yeV}>oQ^**3M_nJd@~1v9?}>Te=@p3@9Px ziyniPHK4{f1o~=7*0_&8T{rdA&LHTUQ<)jdR+GC H+3WuSu~0nA literal 0 HcmV?d00001 diff --git a/docs/img/explore-night.png b/docs/img/explore-night.png new file mode 100644 index 0000000000000000000000000000000000000000..6732cad320ffcbf1c24bb3807d373634fb6b3434 GIT binary patch literal 197419 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

$qiQzjA%b~q}8NWsafg1 zp;-Ubgn5bsq1gHgYnw^DnhnrnAA8;m#6r;@eFOE2GcW(c7tfc%tyN}#IYZ_ zXoPJ5Elj~Z9>^K;0_}CpCgY@P$Z?4Vn94Wxt^8NWu*_~dcb`H`vPsOs;RyiXfYWPL51LyjJM&x-| z3DRQBn5g_WBh3n0^IhVhQpBvvoKdZV2b&}-R@)c4krf0BLO?9nU2%T>__);}87c+F z)oSph=gOA>%+l9)4s!<%A72v*RyQ@d?QGb_rc>f6okgFryrVJ~@4q-c)vWe32C2ju zkOQ^q11|2B>kWg3eb9O6&&HS2$Ry3dY0#;siwL#O~cJYoKkP~VJBQ~WH z*3(Dks?FDsMQr(_$!r#jm#exl3J!SUWk>z9?$@upDed=nNX8H`x~3+nbj-{#jRi1q7taPUMb>eaDm5LK znC=my1*vv=c80G8t#K-GmTi~0F-&^E3`F&`nzomh^v%y^Utzj>>)$N2)5t)=w>V`w&!&Je3lhNENBJ&ka7cVM?t(A_ zr40bDQ2m^5xa*r-oE%S||LQ-YipVEk^hS;e`z2T*PG!v`5{+J}={U#v15qa_Kr774 zkMz`X_qqe3qG3Wka1aR}xU;ZobM(8yX#0y-STp+xtDT(@OWsXV8F{Sl@f(y7%F^7T2PCV7D0(gF2k(#(mFJ3fHp%6eF5Sxl51p z6X{_jBsEu94&7BPB83Q^X5jQStKJ6jEpP@CPJ~IqNu2>txn+<^1EN6&P-OI zQr_c>)bEF!i)D>UGxOU_e`zMD)GFEi?i_+54@+>05^z`%!ys81axabAN`;xX2A#vmeNv)-H z+c~_gZukd%u~^7CG@kGYbvQ8*hw~z`-c2Ba7-jdAoF2&50W@J2;L%U^efs1XMO%j|poj%fY|lxD3G!WY8MGpCTU%3y>}OAYZHt)IA#yS`+`4 zO8jol8JQ3li%cDfCwfav{0F&ud`?iI?c7rbe)P!Y?vQ$Fild_CQvR+)wG_f2>e!iN zx!?w~_rtCW%%eC4LcDS)VaP;}^Fg$)6KY_pIv-vi3yK=1)XFI;LZx8p#U-4bDw9er zpkC0c>JVdNJNF4ZxLiBQiD@KNw0S!@?T#EY5X%YBK+UI{#n?7S9)J{7AYUQr5LsNm z8jxsn>e+6*6y{oT2)zARQbJEoZrJSQByKo=WVr0zpmF25Gr%jo)0nQ|Lht0#&=9i6 z%Qomn4{lc7yys2R5%O6U83R#cAH*N1|r!$3+vDfvzo8%&$ia(AT=%=><(E$RXMd(h}aWq zZ9emny4aNiAd+3tywMvRTphomy62ethspb0flR{tNotaog4wT1N^6@L zl*L~Cph?7!`#(i*#J)(u63o@?uNJ z30-0CFE_XV(R9ZR#@#I?22B@JT&^_{>936Q0Yo}GCT~NgTTEYCOG>vr>_36P8dfKfX$UM!wSv$^B>fqC9z8S0gKn8M?YP^A0 zsl$n0{cnFc;vy=9SJ~F~&@3h`q;>MsfRWaGonAJPUu>TL=TG7LM~}9TfuxF|xT4F! z?GjRZ9B|+nqL@>Yz!sfIbHJxOE?`RVLG2SQgw^-}At5+g%$l&GdzQYwBKCHmdMwTP zk`7<^>?ckOF&+Kz!Sm&%b)y+Pe z)#9WK!tcsKyIW*1EeZ3n*;zZl^r0TDt<^Er;jyK?;*scfTk6bn*ph10yT?yScD7lr z_t*@tdY4aAZ(?$1gOaP=|6Y~2e#c#AW8MDYR`o2jc@dD} z0DYT>vS*aJJ!?=_c+S$c_5K*ZiBx%o z5bb8!<&kF9GITbA4}2=|)u1}0#8MVCTvYoG*nfe$kBpZ|;b(y7-7O`9ihAVonSKTz zU`r9c$6f`dZ&0vm`0B<+EBobaEnbay7!h+C3Ctf4==XZFy2PbCRc+c%Hg@WzTGTE2 z$Ns>{;|NGvFWRhXDqgbomAbtW4<+>4?f+AkkrhWcu)DFIwvn@eTU?`l8%b1D!j{)6!g{Ir-Mu%!lu>8= z1RV-J<BfS-ETUsIWPp1wy;ZySYK< z%Tz9!MSbPPJFKre5LwRK#GX!Dzmqy@;W#{1h1_J}+=os^*=`*#uZ4X3x?;Rn2 zJ~z!Vt%)uexweA~cmU!Rp1~Aiu}d9)6SF`*5-60>tE+M&3KKhZK#~h^uNZV(b_U#} z-Q3)t{qmPc&ulELT>563k(t2O7A`GA-0V6>saV=_TCq7viF?~}5d=<6fr^`%B_i>S z8FN)^7xW>qmCt(yd~3lvARvy4k(S%s}%$=nC2%=i2`E!+Nd*W#X}Nr zkAci(GO>8QA3h}^DgKYGSZi*2C{^NWd69_>OfDpPVaiRj{81^^$j5~`3W?{A6YDh=0}0y zU*F@#pBO;7&c}QOd}O=eM`|DD-{90M?C9sr8emwK-_1ZZ7E1b`=02B%3}Q zkVJe_N^F$r9|Iebp!tYR#ygw2x{Ax&*-ryexMFrgPash6uPNWpRt(I{4Rv)Y*B)%9 zqbGp6@5;_i;RFj-0ZJ!)Bd|{4V;B3Af`$KN9hK|pV+}`E| z=A4qOW8MM{6)+!*hW0syH%duDVs;iICN*`wCzgQVNB`jBJb)XS1oVNE-EU5K#Enk#FPC}pecam0X#95mOB8m2d1&K0Cs}*qrP^n z4~W5#aC#yqQ8j=aq@bizCO5smx=qJuO-)VRl$I3LdR`;{{_nZtM#NNjM*=6Npx-f0 z9yrg+6m4W~4_M*O_T>OeqGyD`hAwRe8&WuJ3QI~%$TY}LKE`Zq$M?S|LX)WGMHfkC>oIQ z=XL5e^uN2k{P$u2xBY*2wE2H>yB|B%f8S#tU1k~zr|nRU-a#Rt5=>94=E+ClL{0G| zC%fOy>aQCl*8Heyh!|}}@YS%wgngdwu?cJK1^t_JDrKLjv0RA!a-+f&&u@3Dn zeuog4H7|B_WQ|h#0PvDy`24RN#}r*yxaHHHS!*aBCuj`hrd#j9=G5Vvo9QeMDgb)| zoY8m!z%T{|helxoK&TUK7a!xtzfbb?(UqI&{ms1eHMFCH3^>$&z8Co66VXsnQ{!lFub`0SDObL@ zbqf^}6)VVneR6hDQC`kO*Dv(%fqjDjs25 z|L+0hl%4)Re(T1@X>9{Sq(8n`c}kci{%aUm1+2UOXYvU!em}nn%-_6x@mkpy{aGL| zB)9XSw-?9_S!7Jl&qKUNnf9Uq;wx{<>?h9c3^#8H< zo&im5-4uDg~57L5XD9!%vKf%?c2dI3R1&moPU(Paq2)4SVr7T>P zJ)k-Rws+@gIXaEYJ0~Y$bq+wHvC7piO~t1#aWanfH#Ma#<_qlZ(t+mAi_EC0$Hhoo zEL=qRQGEAmSn>laP}v3TC5B!nAGSi7t}gJwj4oMP#+^})jHC3@`O8g!-J%QsEbK808a~CY@~>sz2h<(CJCKdENfI{;t3pjzt)ns0GQ8q%R)Yp3yMc)R zj?ldMRJ;&yP5DpzkD{pu=$gARM6CO#>Lv5J3A*X^Hj2*6=mu&xGBGh>@KfYr z6#F8jq3%r=>{gq?{08cCNQmcAmo8t=;$LMCg@EZzQT394+RO~-t30on9b2UEWub7q z6g^#Fd@R)=@65MeP#)5mGA{WK0s_`9YedE?=(fwo1*ts6wG%E1H0s8GhHsVQmD zhZubWl#Jgf+8_bl!%q5+Y7Z-_`Z%;dP&}XCA*7mVkt9wXi=Mp;#6l5{Yg^6aWMm1@ zAKBoD2M2B`kXZO5`yb{t+n|5oPuSx+{xgSMYOGo)Op1t^TT8B1%aKOpkd3s5D3I-W z?E{I^c6tE3`tX990Ln2c>sl&5nA^Rl{pr^22zHGgv?x66QWT5#nqldEgNJQjVmvJVm#rbNs z>P?g_^3z+RO+ZM#BJOXr2Zh`eGNQ!n_rF1EgF+nskeD|lRxHgYqV+Ep;6B_z^)gCr z9h7idNh7V}peq~Z9^^J)3zZBrRLx9&;GwPTyvv;Gg9jkvN*P*8F|uN(kln5T{5E#9 zrlGo;`_=<)in!1+IWen>pzi_OW&d0?ccsdvLkt-sBCj$eg0m$=+YCSt4->BeCV>*>70iXqy8MkVLDs;M`$hK4v*{ z^Kwk(C(zFTOZ66)w}1Mz)_-K-R?nI$exCt2+d%kf{NMdgu<-?ZKqNAmm5os))T3a@ zroq?8&=3~Nn1A6y81Q>aF)}JDvR}Jw$<@ERv}A4>8y81BJYxtj+xTqNrR8OC^U<+a z;$mYHSPyHQD=KQYGhs=FF-3)+!^2S|17Oy)qop6C^E)dkIf-LQQ*;xrPbQb=0g*!T`E)$siPyK$rf8fS6(V@C7N za9ck>!>M4bwe=;rt1fO!?|r?& zBcWB5M_Dlc ztMQSMw>xLM?9!1(j?a!eBJcj24>Ui7Xv1KGF8n-?Ut@&T1bV`zUUwbAj}C~>pZ`7`@bUEN(~9jwz)A-g*O2VSORc~@ z6n)b$Vu`bjBqAo}>b(LdW$;90cfYl>11-U>OD|OI?Cg{c+D8YweA~-eT6zG|q3#8B z-Q}(AXjGB;rrjsit8R<}4-S9ke;*tGJlO9V7-%KCk#gb%;-%p4&5_}(;s>BLghf)= zy0aQI_2;z*1(`7ggt3Wv4|h$Pf&TpT*05AzS0b?70aj^DHm^$VM4sQrw>$}E{0jMhhmP$ZNybGcpxClX$mE3c21XNFhJ z#-xEZszwBYQ-*_6#D1roh0TILnbn2ytf+{K72X8wgh?;@>90z$TU3j)6vw6_K`s}L z0nPYME-s+8>Y)esy?fu&b=jnIl#3YH#KuNPf6siI`O*uNO=jw*P64SS6R(YGf-kUP zeDh!5eJ(C`LzT3#z6=%R{+5}!SiIT~@&bq#+y6!q(7G$(?js<2^&aff4N-Npp=S88 zW16t*a{yA1R^yZ-D+*q^bF6$l8^xO3&2_RtvLW`K@hh0N1?iH})ReMr!F3tOb_-ot zzL8YH^1{Mn#~}N$nXIfV0Q_Xq>ORf5Iby79Fu$}}Ns8@$7|4faGY;ph2js}CLFY%F! zaVt2bslK0b?shh=u66YrHUeaWooZqo(CN`#y$|rNJ5@lL5=0j)DJgaL&fVmsBqms_ z%QWa79cYvkLCgec$4NYXEG#0DB%Q3Kp|b?yJR4ix?olBV(;}!I;MUgmc6O9wB8P$P zrSYA3<+e+CX4i*b>M~zh(AIgWa8>BB@C2|?)66hNR4)B0adX};YMe`0`Fdj7ZnWIy z$eku%3?!al>b%LyMjg)BVV%IFU}srf8ZDizJ(2f%vo|-n(+arxYwiMJv zj*+~u%dq-9SCF$>@9FAD{zHrja_i|x*>)XKm9Iav1?t&Q6_x++VlRz!vXC+6pFyKH zc7C1DJ1^}Py0-S=!-p;7^6nZ=fMEjS-`Da`W;Vt;Vo?72`dVVbxJ8^nf`JiY))N~E z6jpR+>4v9W!OPJxMxbBaINR961ecPWfQ8;;Sy9$GA`&}}I#dga^6;7ktC_IGx3UL^|-6Gc|U~ZV%6GC{(`zE1r^Q*Ca6^RtN(#byrj6~xda5@ z^NTce^qfEK?5!zt{g2{TvpHX+T)lSf9&*j8?c3&53HeVAdr^wy?rykDlDKmi8jUm@ zuc(YPQI#szefUXLH4HQ?fYc2Xffo|i{etP}DEmY{MlQ9`kg$jaOG8rHE-p5r(R+Cx zI5H^3y{f$fC?vT-ZS7;={iTh9!dFsE>=l&pQEq+ULz^N~y75Z;ynNIR(bqxQak{`+ zjOZ&;WE=-}da${bS6)z3+H=@{@b!E3Eg2jzEl81amnAjH5@ib$uixOvZaf^PPxdiX zbz2(hnm*4af*J1V>Dwmt`bW-+cx2TDWN-J)&24PV`5?a890h&}K1Vm@gwL-$gKx|dSueFYV!)pGrl#`oYETq=)-4hETj0Qkd*%E~#3X(SqG^va@wNz)+q_eGGz-!+2Jo|&6lQlm&29>Gi$G`Zz4L-5ZA z=q9=TwDNTJ)L?slk0*PbfYd5$!;}%8W(dzH5|gfGT(ii^^a+TG!7pen!`Yc4Ydbrz zoSmKbUG}$JcDEdyTr?qR0yg&cMWDva&yPUfSX&1`@fE!fUMJoqe=}OSL!0?X@Q2-t z`qr-=JsR6Lr8fuYAie#()`|NT1DlGd(I}(1ScBm_^|)q3JPvG?g1?})9sjUC6_Sz- zihI>VN31ToRgVXn1(8#2zo{3+zKovy%uXeF!kq@KpO=Bwd5 zR1py#;2=6TS8(9@*sD&0=qY|7(8bZ&N;eLxg7Vx8{+@1`(_wO*47?+~{@M<(mpeIf z9YJ}IIMGb3yWiF2YR8=6eC1>@1ITrY>_NGFQ&n|2po*7|Cy!e|!{i*{B;@FMgGuiA z(&;I2E(K&&0gzA3j@encN~k^J2H^2)(vxAHz?)^76J)8LVGAlLZ)Fg!%#D8b%FSy@HJRYlt(|A!(HvJvVxH?ulF57OfqhrM6D94}WtSVsuGkHZyEaItv_&qWv^hCV6$7lu{#8(r$-@^?pT zZOP5;@>4xFCJHp=-;ltQ7XF0P%&7n|XzJ?|WS1Q4>Vh>G7#r(q81dT4o`Gz{0qHpk z{x0!o^gDo?Dj!gVpQQ$Qop>Viw4pZ;BG8&`|M@zrtK0m>W9|K4mKL9wYyk@c``d>N zS<;ELC5_Gz9aOPu#xhzuDvp!Wedtq=G~L^j-e;~GFP8e*^XC59`)hQ!5Hb>q$)K4$pKY0@DFJ#0Z{`DZeHbKVZn8Lo^f zXQ#}}t?6jNa+^TG(sjq6t##PA;l4^!f_3d_2r;>(g(fhvx^`{u?hZU316mXE@w#CB zJ!wdDJxXednI{j7qwMp1?C8K$!=E@R1D-?r^1s*CO5eY>zicp(sF9sU{m*D}Zqxp5 zmJOAuuC5gk9(eRfgtz*l{2AuCxw$o{gNTZeu7Orp+ZhNkKOs-a*I`=bmR^v2rZJdE z5GKM0Ua=p9STXQm;o$>~rSagY5<_%FwC$u2mHc(S_FHMi2>m#MMZ{{<6E0)J$td~oH^bL^V_K(HIh_s)0sxMw{VxHOD zT;1IKw(=&?zL1+w1Cln~?;a>6*)TDt^at??eARjUuGed)@5`U{CiSbz%cV)OR&r%0 zAu9&g6Qbp1#K((MqgNi;o1pVMh(gB;56@J1|Ndg;?;X^{9v-hL|M58>G2EYDM-tcF zd9rQ)#R9IaS=$Um(LvHuLHNuA?Rjuod|7YtJ>D4+RyqP{UD_V}3OX6z2hf;rt!-bzy}i8n zR<50$>GntpHUjl64+IiQbWXQhIqD>z0MpYY135&;$k@}(Sc7Fhp01wL*~#}ixj4T- zHktpqO6I|Vm${;nl2&D|{-+%RSXtQ&dqRzMjpgMoLdL9eWDFiCY4DuM!Z3gb@Pv!_ zx?u*p`G9@RwxO7y*8s+IzB2i-K^%Rsf62{=Z7EK;A{fE^!k4)3wk! zDqu>aIg<;Gwssvf;a6TBk6$u(4!G7s&&z^k&i^c%bg=6t7<8x9FD`5pq@5DBlvr5t zaGTGGdkBG?U*Xf2&qiqUX@VPHCK@!%tb6jGFzmLF13B0^zMiYA2&2=CSk~jvLM&R! zdQR|h+O)t%Ga-O>fPDG`Ul23TyjAVzOp)QZds1 z=bVje*RRjJ?SGh&jwWjVi_;!|;N31e!FzoptxeHL3HtQEFUE!FvZnj&zy9S3(vmjU znCZVSk*urvaXoq04||J{f9Jnw-!z%X0o?tvQ+0V%tY!_sam)Xf%Evdqaq_>fYmc*`c)JR>V7y<|=}OBBtcha~ey1PQJ~J^f zd8<%-Qetss1|F|;d58ryOMrS{?)P{VymNjcoB!y$;H%t3{qDJ=Y^ zm?p9+tJdqN8>S?hC}opHag%*L`%Nw&#{Nxl0uUV6xnVWf9S%PIH-X3;A+MUcl1q`Z9QYda(TDwI08%*BJ zESDmZqPelP6BG3tN&TLlo?TsC=OAf`iq{X~;7c6Os;3@GIJ8`Z2lDgo1)qLk+t$~& z{hoFc2=_H{Ev>B-QnpO2iLB?dPo`RaG%ZxhYyjT9zh9_w+9e;;g&=gKdU|=}RiX9j zDrqk_(d2tBtn>w^KpI^J+Yfh_@~SLsUZhGBUKmYHQz-S6v(A=1jfXAk1b6BoifZ0? z7;74%tXqh2gHVW7%TvDLryulUH*40zO3Yews{H&upsIZcDZWRQwyXDFPv6XcYa(aX z8gjTumKmI$EVt@t9+>8Z6g+y+2xD|S3QKN~JR#}4J-*AKM`NUmOu zg=P>MPj8*Mv9?5a{`|mAvzQp|U{Tad@E}(En|e@u;?Xcv+9?bdCKh8l8Z=0+lf2!p ztguBEMN?uZ_App78`nEvN{if!f~qDy9BgehsH@MYUMQ@ZCYyA%5?qr`oq$Ykdf3Y$ z6;27A7Pf5z1`p6^T`)_|oT24$`<7R#kE|>GuD=@hu^(CPpXkm06!3}V-dQ?& z4KMnmqPHMQU8i@2?8#!9s5NFyTB1)cggRDm>K9^gZ; z(pbj?d7`G#-y|xPYB4VR&6}YJvf0oQ&L&~e&R(-k-eVhg-*`#-{O;Z1YRem3%5H(%(u;AL0$KX5{5*uEy3CAgOT7>2na_XNe-lqr>L zD1@V#pzf)k(m?Mdv%evvDdDoi8YO2?s9$5+^zK^C_7p8NS=v|sgzegg+m20}quYZ` z?C-o$ugcyO7?!-S>X6urIbD3PN=7HixNjafnq@4FG&&Fa(@z5+ji}Jp z*-!CJ6oHF*u0>-K@qIxwplEw0*HFch5b1PikK=tf323KmN@3QrwcsJ zt_#$Yb_P$Gx}2R+Nv!+=@wba-yi7|x>wEp6`>+{9QU~F0W=dJAD!&Ibag%Tc)F_!u zH9<=oU8~DY+A$6G7}U)&&t08EEyzeNv9?xCn*4$iJ(U-(10tS_==HURpz8&+y{<&z zEg3X#*YmhHysUCBgx?MH)(fr|avDlCFNdRDLEoAZ;BlkeWWb0y6i z-*@_SuWv@?cGPh9`B29?SGO+?5eAJxn^BbL~~ zrsJRuc}ovP%t~`Yb`>wWX?|bMx~nZalUr23` zG9wO5O!)Ze(z7Jp6Eiupa&zh9ulI-*b+-mrtC=Z(V!G(g&Q9$t(Z<)Oo+%&n@IQU_ z)c+%mx0lD&m}p?*`R0uUH~@eLHiKJ^i+uRB5mPb`JR{3$&HlF4WoA}Gbt9As1VTkc z1t-+n-hOC`u!Cn6v3;wcpx~-K7-81ByR#Fm`n$Ci=C*3R_;(&}KB0@ zm1bNS7Y^4@bbRxCXjRDad}GR>e!{q&n;HYd;k{Q~d3kyL**zm$eqJHz>1M$4-sNRR zYAW1Ov8_#O)gp6Q&DGZ4N&{l}IkE0&>ow2p>)Auk!y|^9wr^J+TzPnl^Ud4#FZHAk zcjd#~N;G?cT0&Jx>D&cS5bQ_ocmDa)+1Z_2wa`^pF*2|omeAMLrBXYmp%Iad=~qj6 zfiv$gP_i}{<$QnQeW_zcZN%L6N}n0q;5$xF508(Z0{lOH3_3s!@Mz-s$ zb2yx_j)sw*Iy)NkFkShD*M_gxZJxnQg*dm|vS4M6*AaNHjQwxOfgnw89>Lp^lJ{=i z0BH^-6^Od;TR9^Xw( ziP2V9&lw40(te?@U)L5>X-n>&Ihz>bzx_pZ2wOE(p!d5{yX>W1n_?TLG9vYLg3G&p zp)2_#8Se+4MO?a6QgZ6#sZ$9F2@4YD78V`!zx9_~V!hwF()!eU-gb;4`S?a%W<2G0 z67-d0gn+bOsfyeB^}Wa33Z^=dY=6Ku+1Va@_vs0K5ebD;QIO4NEn#frd1_tHXdBPN zhnfjCM9>iFde|P*fp^cmQ)5nuX%UEvZN+c|U+qkdduU$VELZWU0)(1F{I0DD9#tx#7y;`n7li^7^CXD)t8W+f*4wmBM_EvkliUWLtro6*~0e< z@St)$cDt%VY3a!GIOxrbH}2Y9$So=F81^{`+uKZpH|*|7;CN~?P;V~G@cul#l_XZi zZ_uE`%L}xV*d0LQ_lsqtC+imnhmCM^_hJSgJzAq5HQt|aZQWT^F2A9&Mi8CyS?}*@ zd=US!nml9>d*2`feT1%>My?~_iKJ))c#YNX9S&k03cWq#jYH<3`87Hc0_Yum zzDRDTxA$MwZxPpvLjPju7kDX;_T1R!%FlPL*|X*^qZtdiCcUvAE}1dK&&%6L*sB{D z*NBKflYaO3Ur>pFX4PhZt#=ho=`#5t!y~xaa8y*|Y)Ny5CRcf(%IyK67k85)=crh+ z-5SawM4X+L&Ov)W#4dy*ywKbIGz_YZvtu?bp-?k*FJ%r6SoJAd25D*!vyzfhbXZqO z<%lr)`>IkGHwC|Pmq)IrajRl@+K1{FJ}^$V)YCvJ9Sl5smdIFQ5w$s9McqewbS`i{ zO5Io=x397K^?8;i+e5h-Y*m}fDO6n@x4kpdv!xw6JxS7CCi&;u{uIIX2{)*|%9X`! z%xernC2N>`{ju&JEO}o|mH)*8q`U^gH|s2W)7}#UuHMtv>2EX^MQn_KXX-do?8XHY zO)dulYLbPjw_q?k9Z%`(BOA>$Xo8f@()UlhTp>__*AiH#!%*B+E~Ik!l7#H-i8i_xq7X=gTKKgrt&$UjuALN2Ey=Sd4=-NPES!q z_Gz!(P`ay~^cT(z@y9Vm{57ACYAkWy-=u2{d}^C%m@ES~0_l9SoaR>~e%q4MU}s5m zz>M~nf&hFoX>`nJIbNuSdazG-Lllw!6=t9Rx18K&!+LjH6sL8a$@iSgv|xfTC$2E&Q;_4=v@g^7&*F?_M-bWl@u8 z7DI4XywG~1_vX2?(o}oROFng09mXj>#1G4>V;PcFgV*DQt>!+`BDS5ek)X-3XNErW zPHgwsk2AaT^QQDhMldZP6DEUHq~OT90dq!2SFp|v$8-Na-CtX}IPu3W2bYFn-WBC_ z85VaWp4E~1jR!Mwfz)cZE&0yV5LO!Z~CrEj4T>b)-yol=AyQquO=b3cy zRgnGALahE6U-0&p)Zs5PK@AOJ9oS3`enP33z9Ueb?C7E;k+$WPm86+&Z;o5GTjfk0 zV6m^Rfm99qH|QW@VKFWuuO+)riykiNxWpc(o+_!*&(Ma%9nSFD!1-3Gt)@c{WqFBm z#v!(?SpQ%2A*_O=N&|Ro*LU(+g?rq~_|;?ycg1@-=}$^TT6VyaM;{K2LUHuN#$`^2 zPHnH(Q+W&y65$}nZAs+9V6M!V_GiDx8C{g*oYGp=Qh@B=X`GS<0lB3kvvHW_?u!(~ z=*Wi$RSeP>Gjo|MG8&Dm9U4i#JFAvGBoMXiqN~`eI-2m9E4{n>)nr2NDY^K4AI=oIA$01w5+5L_xc?bfnJ7yZ zd1L$%u|?e|Bq8_{-4cr=Z&zI^X(fPex#y^@2WiF11M-J~qBzSVPLn!IFE6Xq)!Ekv zFR&DCbhzp5HnPn2vW$X6n@J73qw=n=ce`!K zeeg^1T-*Nq*#RpAwh$z_NubnOH9J`{mp@|Z0FEGccseh?P31&a^rb(SrtVuJNc~5l z5(s`()v?r?s@z#_1PQsX$k4mcV|?}b^XGr27uupyyojTO8zR?bvV(tT#WSf4+dMax zF(${li^W;Qom(8sM?Lh&vc)*gw={0ymXU|~wBY0!i@HefAeBSUdEIB$dz09l z6Y&%3iC1eGZ%y*AeR os^>q^ttU?C0agN??dq%8Xd7)@Eqosg-<>a_J(rE&%&nVwz0t{@-A z8bivV6q)luk#q53&!-Z^T}#W&@$UOr8Ivz$!rmU`H(4fG%GrP0CNn`*=|wbJFkQaw z0>+4%Ui!W4o|GY0d1B&){C%LVs!$WEk&}2$I03g(FhoT)eUiMw$aWuT))GSLf+*j^bgRji1-LODvV;ZPGamaju zprsaM+{Q;G_QesF4c?vJ}qIP@197r^*@iwx`=UxOrr z(|brqms_MDVbExHrnzkxW-~IM4@asxEEm|{Vo6fjoSl`fotK`^P-HB3r#DJWipK9C zDHacp@*ml)U9sv?qOFWt{yP0?(;g-^bDusipF}2^LtzgbZs#sCQw}FWR<$I2h1$~B z{VzoFzjNH%C+*wTWym5p&-L1DD59c-x1LB2Bv|$zw;x%6%zpgKD z;D5}T`CdD&pnhjZxk4G#CTNlq3`kNE>kNDhH`eeqQO*|QGn-Mfp^ zn8*tOl%B2*V6I}oZn3xs^ca{lL65O^aQ0fdyttVDSBSKW9_9R1e*Nkv34K62E~^Rj zU|#r~@~XKx)7Frih0w`oZokwJ_@9$?`&XF^gr2Xg_FHCL;)%B<*jrh}e}UP4vHgO( z8@M$*?V+_Avv71nG!9Jqo`t1$BP~Y#$d(i#n>RXP76Dg#p~9l834ii+ih5HEd2Z|b z-As2ml`&oFHmN(`5*jaLsUxqZHD-O$v%3i9eWgsX1UZ_C)nES2@jE~>JmaSH#2DuK z4GEKjt#2i#XjY&N=8HSHN?!pakwZ$|)=jxKLnox%&0V8>Is|wF|o@sc5lSe58F@G5?1=$vV*8ZUG#%%?`yt) z-x=8ktam&Rn)1l`|7uN@Y0zySiRp;*tzMcBYYZ3vypG8X4vo4~k)WKpXi^QpjZkAF zb-kA`Z7Gu{<-)e+x<>BUL8RBlc5SWr{)M8!&9;OqD_p=u0<3*GA~bBOEh;;VRqE=M zE029f9@uG(0`xEi*pgDn7m=zRY468)cR)I# zU$<$Kzf32bs>1s;-~D5hkmbmD4A>9aQa>~Ts{eKKU(;uP`s%Yq+fWlmk5Dv~cJEQ$ z-@V4|s&WR^?d)JGb`{%?k$2_Kt6dXTkkN}yQEA`ZEc)@L>#M!Pr97XX4ALZpx&;sw z)z|H{$MHp00TJKbpWtN1m>83~fsDesF`Pq@@=DK~Qc zy5>*vUNddE-4(?`JA>+(;EHu|FST5ujNiAIGJZ*?c<$jO+%_XQW@l&JryY*~5`b5W za`VeLk>a%k4;p1}be^Zj>f5Fw_I@*}Nu?*N9$?*N4#tJl8p%sGk=J5Rw@Ba`r~3|W zdWnfyE_KJ>hc^=H?0P6sFsHE`h3 zS?r5)8KPC)*=OBJn;W$pe(PTlD8b_;}cqAO>kQRuz3MEh#hqt10yoxX^zl~pdLFy@1dY01CUn{@k-L2@(lI;=Ni1|4n zWA|sqoJR)LxO3d)8h^M^)`OM#%Ii6rseF|s$*{(BRWtZ<)9zAtpBr_`7w3njV8yVE z8JpE0i9yxv@%qLQFv_}Cj7`T;ORMX#-J1F8cV&07j6mZZ9;3F42Sj3lUgbs@bRrL{ zV2oI`2H%EZG~PXnjQkf1C^vcU7IRX=|#J zps(ll#^Hj0ZL`Wa{w+e-W~^28$`GjX==y-`hayIlOQjF%H; z&qIle0tn8Sw*9*2%A#UC+t|1E4yLG$SY82e`+%0#fw`%y>SULxQ(kiwC72a zcaiFyW|Ptt+MnJM!npbQHN5eW*n?K*p0!kmJJOuD2U5sjqCS=6WAe|I?WQtZT z^sz8ggsYw!uWafO^X2517P0ta0(>5d-vWN6^ufJ*_>?+abXN6VJSN;@V>`QC*;YHn z-G)izvDhJC+|{m64eYbf@~v%B;DvxlbV0S-ZT*)v-`8fv5IJKml zhB`}}G}fUNL+LY;;D_@kKKsG51`C8MTsR01mo7*Z@Eqz~#r)Ozr&IHVU|HG3WUWV& z!KKU4#}B~CJCSREPS{P2GagjS<_N8lhkEK!9lw3M4HAF--R*28T0j}U=}Ef%EfE}T zW|`t^-x>z9W;UDqxD7%=c==iHHlvOb;)Dz(6H?5|m9uvT^Y%+tIEiHe%TCAF=ZQ_F z+~#Qq+r@X^9T_V5`!5th&^{B3kDn&(&0_ZYbqZ_EEx4vLa&sNW26zDFAVXOtU-r>h zpRBL1pO)UqX^z)%mbmt+{H|hPV6*IU;v|u}; z9w}<~w1|X+!Q8{kjQ>w?Zcxa8!h8@!VJ?9D#UW+nks7ajWNjD54@2bT-*Ll5 zcJ4v%fU2fkH+sr)<7*#{9J0ec(myVN%!GOBy|!wZDaBP%nU;1dKRe>o2Jl#0$ZC1R zqp;}Co>}5DnBgm6L1=-Cl8K_|ej^@^vnH!~p)69hz~_fcrUBVnG`SXpi0XOo%ZqG?5Ogp^>)EunAEU!Gw9+zYXS?PZgZtX zOuVbD07phld+Zic>+z*~@qjr@W`JAFfOMm`I26X|Rn*yy&@tt=VsnuJY;09v!2 zICcZoKw0ue9?bKhYG#L^N!TRit8OjjZkH}9hITmSya7X?ydq6{+a)DKDv1g%%g|HJ z%y!2+{!>uB|K%5ZPd@{82kWVrYn@HbFUs}YSw$by@<-*K&XzXHGzJZ7%f^J+Y04Yf zqk9{)(836(7lPv)e6eWCnsVf`M%+{#6(Gb;q1)=*v-nrZp)b>k@M$SV+DF>_*~>rEZ4ZyNsn>*{?VKO>I{Aaai%;g@0DO@zz-rW@Chl7{V; z{&B&k|EVpJN?2{>=*%>}(@>mBog1bRst1IQjZm*arTwFu#amDH$56;!1MJb;;Ra_B zoU?0AAyuGRu;TBCn+{Ue8VPBBPl&>I?h6SR{J zJ2uzX%WOw4pY52~N6L`rIx2|#{h^q# z6;A0Qpe7EYnpq%92Fm(tM_f><&}~H1yX?5uHEq6ys@-99CEvLWfaUef6Lm=6K}j4(xO-cdTrr4{bYQ3&W)-19{4*Xns?9 zTrb=2H==_ffUQh=>^KpYT!$ulH8jgXeer?KF^b>5Ewx+%jLS_4w-8EEbbvquDQ~+! zV>+{EA}%HlK5`HmzJI9xBSB3%CgbRvoVa+6N4yA?+8~ZAlexB%rJUWtb4qf^q>4pDV(1)#>eAqZ&Q|eW~d4?F+ z7R6;vYZq(Mem9)bc3`zr=5-JuUy=Qzy0*3(#GNHv|E0iI@+w1kXS}cUJ?{4@%am;# zVAOOn00DL!L;ZL>g=0po(Zk}Gs= zaFpF?s-l$3p93o-d3?IU`MZE|?bD-`N5kcbCb*7@_0pc??c7Z0rezfy;Zm^>mOypnHdm1pw{aN|*C%2WxU1%7{n;M|e zSVcMR-pfvh{EDLiP9{@#++UDMh2d&=!zMf)?aPH0HKy3?I=xZ<`-8bWWp{@!a-feN zZe`_(Cf{m1?xeiAtkzSZ?K$Pkv0R?3m2%LLx?r;&$13Hv0muPC1oA8-&ullZCFG`^ z(>Wu>$U@kDMTQXWXjU!O*lE>&@9?+kNPUlm!KB8cj=h(bE)-L&e%rJS*Fmq5@pxd7 z=ofQ&8=;|~P1EUZ8o-4vuV^fDy^P#js9ILFXN)u*5P8e-;`Kx6TViHn5Ag2GU5WjD zr=J5-_P&WV&0A-e{S)vf-!~b#lBRb&JrBbv+dVC6QDj2Za(620MHUvpBJ!6${b86h z;m@U?RLX=5y;}+9>T{3nMcr~>5_h+aiw|-S9H--(DEqh~>KleVIo6q2zW1vL%mY^! z&Z7qR>G=2R)1mYFwLFlaA6!+m^e5KGcyo@!X*}G<$2b!aKZ?CbDvJKAb!Y*ifPu*~?ET=7osB zy*o@b3qMjlcH+U&ok}mYwS6hStQb-8cqm)7_eZ%7{w2(>V@)#4_rkl#5Y zOc1KR>PI%8MD0d--I{UfX8?I=7>xqkS6nT`$X46u2D zs=H$2y|)>o_ti_Z*w;dkyAc+;MUjWb`!MEa5BZQ*Bhuy3J>E}x7+)op~ z0KFa6@{~kXfUUQ%#_EUI*r6$zjk1)kj(9-&D-8E69I$|b-bhzBTgBoGE$#YIWF>D; zUHU>aKUT_}Y(mJ}WxS?H&-Z8;P2K(8_Uc(?j1zvvk*uckiCh-#9Dy1#iv ztZo$=Q$x+61a~f#B$JDa*QBg7TucbZibCyIuPk;Xxb3h~nWsR#KcJ?{KB)=NYDukS z?yvo?L{d{x;ifU0(lhkut*31%UO#ED&xgiJ(kH(xH zf78hw6@i2#-#sx=^{E`HQk8yqwp%(OC70eg;A0Z{s*d;BXlszNw+vhG+Hr};M8`h$ zOhJotv5$N>?cn8=wO90!DT7<|FLOS-eww!eWLtY{9e(rSoBhsuON&)El7cx^UaUd3q9_RQg!v5mi=;FnPZPWfnR zcv$|9juPDT%ayjywXM&SRn#Z4uOpg0`XDbko%1!%DDZrWkB0 zRGD8JQK6=$W1-cqq>;d|6rPeBhg#y=I{H~y95BLH4u?HtZEI89UG8~wO{=+TKBQpa zR^-7Uh?!BAoB8KebJ{ys92{OM=GcywcA0$EElep;d{4QR;d@Kq?%lE|F6H{_NwyDF zs{djEHjjR%6;8E|%zdKUBsJR+&#gB#54f&38iAv;bx!wXeB`;$L;u(LUj9xo-`TQ+ z4U3lLth6e>?Ujm++p@8ZF*2 zmOmU;teV=Xro>YyY&ue2IykNS`Fy`_j$DG+Dl3(#$mdZA+K#CTWL^g@BK~D zQ9{&!zN2HH+ewey6NE+dG497LmN`M`K~pb5-Q6B)xSr4GLFb7H7+)}=Mto>@Fclr?GW z`zFz?5#9I7SAW`mte_$6m9m?oy?sjM2C%0%(d5Ja?&yJ)nUxw&lbCnqO%L?JX;uaWu_ebkkXJSeMN+S|dC0I%2IxMpIV*L-ws z*qEzdl{YIoCdLM*M9(f}f*r7cmAg|ZTmYnNrMja;R`29SoSkoNPsI$4Nh3%HRf$y! zS``JI1%jI5n(FE!{|{Af9oBT){*PlKf}kkUaHE8Pgdm`#iZl#qX%&&~&WWf4Nv}zo=7`_3fz0?dl3uQ3>4z&}%_KRv8`1hIGW(5el=tJoNrB_CrKLf43W2 z*}B8G3>0+1-w)TUOujSN%iRvIVyGCyGlWM+>o}dkK2R`H$i>oJS_tYOTw|L#0Bm*z}|Afrcy-D{HnuQx?<7lqNLmYfEdZDSJyq zXxK1!79}MmIQ_U+joqW%R5#r%*tCve(^JPY-W(Nw|K>6jMalD?&h9Ap+!o(|f?Pp^ z&{R>n>|Jz_s64Qh85*<)Y zYNcTsOv+)76$=gWAyMn1>3f6gT6Yg_a`K{i$dU{k<{I?yj+c#B$0;>Leob^;*YEx$ z+2er9nmxC=W#Rj|9&8S}lNRI+Kamj^D!k|gzrqnlb#6prx(0f}hgL?EU(ML_n;RR4 zvx`lL=(p2(ifk{yL40^D@&`S09a22(K6sO)$`Hz>Qy03`m$)@Qm8XkMUrPot8wu z`bV%xFia!hcqj#kOyYMMrKD%t2H(=wGDtpDAUf6`0G)P3z~%9v60>pn_1>dp-f0l%R+t|3nV)?u!h!GEH&t|%H1L}qpS(;oShWrlR~ zBO?cve|G5u90O)NPDi8#;kW)YbVKF*BYriB)D0x2$;!3)S+;=jDVTmrxp8B<`Gv*~ z!w<6f(xh#Eo)Z2x`OO6!5e&@y;yf>IPY2UmSsnVOp17W_(2FEJ07BPDv!3)^59JDxqeCX`e-)LSz%JnUFpTkr9; zO2WDx8T0UWR%}+^IdU&a{}3pAi*n!i@nhDgI@HW)QB6<3c!0R266-sx3gn2~Yc4+F zYt0+nu+0cJxtFlhAizWsiQ6M`^(2E1c@Gbr(y2xR5o2R$+HXHv^fO3) zJsJ`-uGq+FF6~R(DCl1R46@-F0nXR=6EQMgvqLJvzrQ;szk9M~p{!fUp0j;^r55$6 z2b+-#iianvzdh+s+$Fh#S{^@{ewkP}2fuk@XPccU<o;a`S{5^Tk$J6 zHtDZdFkM zKOkf&<=ohP^nLz1qH8@5Cr`@PRcSsEZCWG%ucE+dl76ZF5$j*0YmsQ`lA}3NNluQw z-+Qs@imx*faOA+^Yv=d4V|VdOWi1stVx}1`jO#FfoO`XUVxXsI*I7qJNr~p{W%Y90 zqtbKHvRZQvx3<})#B>cvEQF5m-U2AXGmJ4vlBhlmj+EyJB55CGR{fv=R zPyep9sHCDok*TDzXmR{yp*6sNI(<12fEb#KcMv3cntMs{1pe1$QHtm<(UGDrf3gzm zDhg&Fe`Q^X19X*Eq^9p{`La;HZvKkkJ|>p<%LTGQH%go$udU`dr3yY&)TdXW-wB0h z#3H_~uMcGcgwca%-7>-aj|ha*44=JS;MmJ-m0q7Yx$P!q0pP5E7vvATEG!Cnfe6W_ zssrbg#B>`5QUSJblv@Z>10cs^Nk03%-|YC^#lPsHQ9LA!4uooPO}c| z)bvvQI_0Gp(jEcK0STNJY2QysjCc4OdKruKNPk)@@IVPL2!fk`WwcOTx-5dE!6W=I zW}z4O8lO!3ry4D&LVF(ocEx6WuDPB>qG)8~_{Vm8?F_F@CYAZEWQ6bFRJ+1(S8E7O zs+3idY#|*uZaYPhP5@%l9y1rf+GsKya#quvsvO9?nH4}63sY->^|-oU>b@8 zey~tny7cMfsR;`!OCgckh<^Kic-mp;KtcjX#~PC$IQ1k=)l(i<6=4^a46H%-QF?*e zjb*h$BUMDye(P)P)-NO!QxfcnzG{q2)L(rVaZPkG>Vju)@4c=-cEj8|J!KX>*Nuq* z`I>y@rY&QQb!%yBwQDSfdtK890V-tt7u=eq{&dO8dG<0OVeJ0Lr6ZwTf?a_%-Zz+$ zrk#r)kExd+1_q`-{TRpqp_s-A@w6>N(H_nUR{$H2sTX52-bGPNzL#S6zU<|za3QSI4gzqb98rn8JIJk9L> zxOq1}-}cRBfV?v;gn))91_p&pH(5z;n=v+F=k-4u!~c^pbb&cSvU?A zEFRiHjjaCVV;q2Ct_y}nZwW^FVl^ZpR8^(FWw`9U?U-^~vrpccb3qDJd2BLoV*KVQ zAxg>+)lFyKI(;OZ5yh&Qzq9Huhut4;IL_*N0&!2$D(X5Z0|7>*Ilw0we z^55qxgK<0p;-=xe;o)lA@WNOfa}#^}ahtW3$&DjaVG(eZn#hruNo!`<#el)6@S_5 z#+(AI#(E30M{+TWE%7Ap8S&(xhW5L1#Dzv0{~tTrccTE2yld;FxoYu9pSdt5Lkgn| zVY4)Ty&AD0(;H%%ByKQpt>tH}IiIq4s<=ZX*ZX#W8*oMSVucxUAhk8lpz}{JmW~;% z5jeNKw#Kid6%f!U@;8bVGw5SPJq_x-ElmJlb?Bwi zP^e2H^DKG0`*V#%_%IT}d6{kGfs9E@8_RpO%Qk|(`(g6znU1O-8u607kD()x67H2b zx56^F`;Qj~f86a}iAj+>JeVNj6GIS>0{u7ZF#&(W%?XOCInlCa_{}X+{FCUJsZwnD z(|)43xW_McchTReI%OQFla2}EZZ*O^@K<3WdcAZ>?s!PkGSi+i+eq4Ro1vY{3*`|q zvZ7riWL7a4*cBST@vgofYRQU!t|J8`OEsRUjPJ&{j>&inP$E(Cr289;*f|8w6iI?!X_R~Vj285I9ZF5*^?zZ z^0#=uO_(&EY>pWa=KWOQ5aR!40Vv!6mgI{)Fesq3^qQpEEU`M0g~xu$)ye5aGxTAW zR%AnHypDlxm%#k^Ru?5Q8X&cw8jY{ovpQlI`^HOqg6uN7C7(H|o%;Jn@ zLfa?E@rMQyw_uw7_*8TAO4m=V))GEA)*SEk)!}c3qE>%+kAmN>rV%P`p;T6b4L{yYngZFC*p_Rct>#1RdS@l4K|I{$zbmPd}f4$`r8vEKbV1+N+ z&K%#}iohKRVd|DVRb2i2d_2nEy?J(;CiweG9P>C*Bbas-A>NbiDb1|Q)-$nfxx4kE>C~5cg612ZA6HD2WE1b_OPtnTHasCjke25E-s}6 z*ofbZmI@!2Q^Vojh$fK$5GpVcpWy<=k$NM*=V&~Hp5Tw_+>_(*P2^3F9JeRycN!Y8 znKaOiaL}J00zAZ=1qm+C4#YGEEY;|x8orDwaLOQDMppOE)&H_J=xlijP>F1~u4qXf zU(i=pznLmym)o;ee3x_n)t?yit$5P$)>d)T{wH#F1~I;kIxz#U%GI4H_&-ntB~Rni zM-J4*al7+D@`;}CnV9()b`bE83D9%AdGqE2df={-kcnpe@Pm-qW&4!(^WWz&P>eD4 z#Ke|lRgSM6igcm9CXIHhOR)N)@X=*F9)jK)OIC1yWg zCdcZn@;9KZ(Vq(8<$@e-)Ey9rlF6LAGfIKPp5e0aM7_`z8Rr3+ZZc$Ly?mql>G3Fj zr?wtzYfc=df7bd8%wq+!?a0xJKN8CJ)XaT<<%>Dh?Ox7xLV34($l*7l&2Sj#yWX0~ zoyn5d@q`p}?{(r3Z&$kcQ>M=b=H=6YU9nLHFFh4hgZB5S@LXl`T*7N5DRB5&bl~6F zf)O}$KOW|Bpe-g=2>?{31l~^*eG+CEcMV)c^_=TcFXIUELOQ}1ok(9_+n*bKlK*5o znNrD{G&-sC0f=p<27q^TY7rk=muM zyu7k*;#dwOgOhRRvFA;)iScptRQ<%1)w*y~k16O)#tv0QJUSva3`|S4&tDplB`gD^ zYIqZ%mjIDilkyV`6pzIY$Z}12IXOAudYL7hDmBSc{iL5_h65$%{TOKFTtsFA!xV8v zS*zRbeS6L%(q#4u2pBE78zn0*Tl37|=t2&qXG?KhJla5wo~UD58D{zx48K zG#ke`s+tcM|Grpu-b-wo(*cowMu?fmgst=hlIl^DpF0wha9vS-$L6F{E4AB?&58pe zZ(TAds4(AK2!Y*84o)~aG$r3@AXFWpd@PWw2dUx(l?VsmDSdl3Nn+d znTLl;dpoPhj@${+i)-_NghT(fp(v()tth0v==&`?x+!yJKt>?h1Cm6#LA+{Lchtnh z+R6%VW0rm{1orqY#ZU<1crclr_>;6|5UVzZKCzpa@z)6nOP{izE3-@`#9`OmC@I6Y zlg~ER>T7V`Ahz6h0c*ynnD?_y0eG>^AW2aGjn68u;4}IOF(+*r*c)&&QGqmMg55GF zHUMBp`G9BsSX$KfRJIUqG*gZiLTG=b`z6Cvzafyeg zTeVQ6kYSzsu7Ct;y~Ie>b&rHcpeBV%O;_UMkw0i$rqc|m4JSXg9YaqE1Cr^)AaaB? zVx}iw6MYKg2SO;4&I39OZe7!1N%9YcN&jEXQ?$?z4i0wzQx}6^Nve0CT)G~ondlux zh?8fwXoBpYH=8L%Z?pq!Kr87m!>4M!>}+?B~xn z_@{6HN)f5&Y#Sm`XGyYaVB5d5BGjfsO`yLO8El^bep>aKwX z1tt$Xx^Gcj?hZi8pXIFNt8slD8pifVD-5Zr;>f_bCPOC9J4HOjEN!W`1a!~w>qL2?+#TD|JNq}DO%pAfw(P{zOJXW`t<6c>y#YKSJCM6p#hmPa<9_Bth={2&*>KoFcl62 zvaS!vCXb9=k_k49JAbzmOA6$0IJ}Qvc)bIF&p^z9Rn}j3v(cq=sQg_YOM2WJSa;%= zO?J}hFwEJkC{RaM@oU8V~mdXhd=QnYVJeW>!kktktB$toz5)25e?^-n%XG zEx=ze<50qWdM3WQDZ-&>#A=|6-Z9^DPu(*S z)W;biZRP=J=w7(m7sMdijJ6tj+KTbqKE5v_dRIzHDFqFBcItrGY|~e;Dz6wYCdD)d zxvja<-dt%V$uCZ7d+i+@qzb=IOSTFL%H*mfZDWP*k(oR@@BIb5Ez(&c2OJApHo}rQ z8)+jNYRzs0SZ|7JJYkEKXnA#xb`g>XOzqcTr=Kv_HEsx*x*rH z7H-a%G9W>p;d{)FV)(uz3o9~)g2W;<`rL0FrYVz}BH17KA&lZ?M^9n?!AdH0PsQMl z;W(lGb!!f&i%s*WwQYwMbNHz3< zQ{~~CY&dFd!L;6yK$oxIyZ*8<-nN1e*YUaINUlUT_#sojR`X!l;mCp8$nb4}G$&)) zk)l+11F+_{T%m_^uz&n_ac5sYCBTTMq(JP;@3V=BrH-gdgdox^Ab_CBhN~qUt0_gZ z7?-@tKx>97nbfa>+4<#l;Hofra%g7m>RGwc9?+0ZLp$a+%o(`bPEyTj3;a=$&jZ;m z0RkVZ#(TvbMQ>e%t+{xGT^~wF$er|x6 zu%d1$M?Vklhlt&B09KgYtJd4*)8W=hSQ?8Q5vq4}tRyuPp(IDOwLUHnupQ0BoUG0aTT1nFfI` zMDGjc_rW9#98DXIEEQJNgb;cAy(_kED*w1I<@CjMY;|@2cOfOdy~$<%XkzN3W}==R zAa!qUimgcbAL2;xEzJv$; z1tz^`Z81UUX>D!g{Wwtmzga+*;>ju0>=X<|Z?cJPq#zknVcloe`3+Aa<0u zHj{P!Q9BLvWE}`S)%)toE>t6qA|>zly42Or?~0x6d`32 zC-Uguk~Ks6o68Y_#(~suY4RE_E&6mjnc7176t|1WkOGNGN8Dk0FCAlEvs(9aZ;{M| zc#a?(vI8|cEuN|K)pbQeL8MFASEy5r_kE!bHUT;8xu<78fhJ(1Ep%V4h}Y#_u8btr z<{TJ~+@!t>A-{ZC9VV&AsGOLXXik`}rmXLO36t^LVMd)4J-q1~*MV<|4m<%HYGG3o zG0skP2#YnBU9C9SMUwE)IQMGy#bMsZErBN+CkVn4MRqbZ%OlQ~M~{;|D?eN;=29u} z55(C>WVO2t1kk8X65{&q;VQJ*V>;4BnomlfY~!P1Q2q57=y$U9Z^g37a;|0nzZQ>< zj*h)7^@{#|7+Y`SL1M*<~aT&0rrY$L^fL!yb$nBmSJcR}9MGJ6)XeRqmiQ--iDHi4?x?6w;> zfno)!QCx^y#)k&KXDt+?s|shZ7qmCv7n%$>cIB0#X53Knen+Nt59THZkMqq*htAdU z{%U%n($a6RNrh*G@p>E?IM~?{9gry|bEc!1=jeVb5&-x(ez>s-Df(BHl^!{e%sF;x z@AWzIrehG@?kP+OuBJdykT45G4AL>l2}!)knopiIgElVYtT6-tR#RQ~%_4IAY{d=3{v>C*`iKf`}rI+90i;Fh3vjYu%aE(XMr+Kxr zx9sC;0`TcxXBXxm^9AG8&h&}*-u=_f2?P)|dl1rZ3nZ|#yYR!w2yTA&gRAvN+l0kd zbD3mx&9^u$?`;V%;XNRkdf!DiAJzli@spuw=*bZeaYLBBB!(cURkg$ec}c2(MZV0w z!$?I%;kt+07ziXL76<6`r$MZyw5H45r98L&|5BP0*K`Kl1Kph=sjb;>EAsO4PIdu= z6-C0!8(g zJN% z8`FTFGd-FS(wgtT#*z=L8=yycxwxP3)LRA8ggHF>Oqqk9!PYha*{e>1sPHmP{5^}T z^c!e3$8{W{rC2)*5?-W#oD4jeBpDiipM_NyGBGi;laO+3fc|4ypB8B3lk2f1F&BUe zhHPCR6hSH5nlN7g#N7#jL!i8589)X!-#8>u}C6Ytq_BirmAI zpRAJp#~rCo$<8_wxlJEF{02zglYYM)Ih4yg)Q)L~xPhbD-0aaDW}itaBrINJKkQw8 zVD3K@6e7xu(>}PIKI25S*yCoIBPggsnoNvV8*oA{!E&b?Le(e_P3SebjTZrVPS)#b zP#}=Vye(84|EhSHnc&)d#K$T4U=8DsAqS#07}tK7SBiVF)30P9+$wU%{Ww>01%t`2 zIQrmbWFALzx`jGLnG;XEE&xucjMoa9s&bl|^lR0D^9UgAF1~pK z{6cN*>;}>vd#!F8!reF~BUnYbMfmRA=WIiED&?KmE>U?|m6fGiJCn7HM=n9j`nV5J zAUgoANIkUM3qk1HDmJ!g1bR-;_D!+wCvndtMDE-X6cp#R|IEzH-_M@Ow?4aY{`}?^^Ku1{ih%CD^;Lu0C8jZfo+n0tF+D6aRE1SS zu}Kq{k=xw4y-dFhTsrCKy`WmQN_UY3~dY{ zjyqH3YYAqX#S@Gl3gClZ*YD9Zc6RMY>_s+$JN}tdXH4V-;^AU!a)H{A^5py0bsP>d zkNtT5T<+}5*UNi0wfOVrX~T!j6ei2T1E-+LPSzh2TNZDAE?HP)m+6AR-^&;7cVuR5 zPMPG}0x114rq&cHa@Dz~QyM$wNs({m;QyN8pHkdzEv>$)Ci`IRtNF`{MyD-eobT(Oe@CFQIeAF<+VJ>8^r`&>V3jIMYysim zrUQflSN$u3&NH>68Bz?GKK}#MR7;eAeyQ+GEE(HlYt%W0e|nMxaVrA?PcbxdC(B*% zjGZ)g52gIlbjsl*RL-sAiAnoZSfz3^E>13TyXZ&lx7gP@hw(d z;}+R>{shW1@x9OILv4&P;C!ch%)nIZ#fun^)$J)!tJD-=hWa~4BR%EoB!{w@q2AaS zRVUdXJ?Hxe-dC?m_1gW?&Mm5YlRZ-aO;P7IyhHH{K9HzneuC+_N>-7Yv@V8zS{%H_ zbmiy**{$w>9bx64*sJ%B=IYo(RcoZ`W&waStw`u8Mv0xEr{__5o{XSTNEW;TN*?(T zYOjM|`uS*XJRVF)W7FNt&XGyc?m!n?CVAK**x0vzkdY}$|L0eewF2Z@i39K|bSQ#I z=mLrV9+@ziGMU8-nZ0!(38&fde0ZAr!11_O6KMy}evfQE;v*hL(4K)|LhsDbkiED^ zfA$nixWQ6Eo$SyMcb9cQ=ASM82Dr9p%;`LkKGGq3^-B2S!^?Ue8hrz71j}d7PRp{@ zI^a1So$a4Leah42!+Z3;bJNlq`X;&thN|@*$V1?G%SYzSYm?cyQnjT^a7*pcTo&gC zBFd4jXC@)dmb=qiKx}4QY6K23tZ{y7yIB+S{rmf7vd|y{ecju)Zm+J;Z%^W;Rt1a` zW1m+Yjpp7*!e~hbWK_bm%{5eIp zx}RT^_u}$UQKxo-EHI}+IyW53rSf0dz3>F_pXU!QwBg@7j;X4ua@g?DEEeKv`@g^= zdoOkNco}XKa1hrd4AS`Qfiucow*NjqXM;0UWyh%Na%9c__nFhbpN0RwpD|GU`wb znEc;gB14~D*k|_t_t(k9&u*Y~zyQ``Kt^`V^51)Xe~n`PNB>BV-B6q*kx2aZjWL8~ z+hArot->d$rG=VO(<;3ifYmp74a^#Iu)iDY<@km8buPCbhsG~0E>Z5e0VA(0Dn_sh z%w`@RZWUy5w_BzpHV zM7x(>L9ll9n~5Blh3qDk*L9Uj%o6GLy1+n4n0ES68{t*Fh_C(L`VciGKR=%*v`U`w z+~*#QX|}e2QQe(8B0v8TazZ9)bdwp^yv?ny9w@yVf^{9>ZyuCC@BK?nor!BftyVOk zqrd_{i2Ar!T*E^{Bcmb{sq(YlB?i(l-DYECMVFKmWL2cX+dA64%)Iyi&X08gp#HMx zLowwV6QniT_yU2of7rypvb#Xper^xc;QCSL<@3QBdPQ>^&3OMk5oq zlVEToGdR|@Qk8LmV*caxLVwY?HwJ>RUr+i{a?K9<9E8vXTY-J0LnmD>Y)Y=FK$dtQ z;-h%~pHTcY4d8&e)Di7u^MFmVM6-70^!%xm61|6Hqe$9;^qiDQAZ8&pHnTG#Rw^); z$P>lRx(;~*++~6JQfq1QdBrQ>)Z5h3=hFei!(;5lA7a?wU%$F^;2<2gkDkwu_c2#W zrlSXNl=Mo^6+KA_66Vk`;=q<;okIT5JqEH1)hP0(HY%}%AGEhv8r*TJml!@TTiqjp zuv2+#X#=t%2hRPu&|n6ECF+@zMpj`CqH7yWPMI2 zYelW>p;3%dj*H8@-NF(DON|gcJ^hrvcae$~51H(2ZEwALd-t65DBbN<#NHz1xpPF| z1|L?RpSvNv_;YB|wF|DB;8hc*Bv$6<_LE;Rvy1p*$hKCMjBF;!C^IUwG|QC>zx6_M zy`z)8iT=h7J#&Me;{h_?{8EL-IAr6${&oiHWVG4`_YP`}^n5_wTQ=8!e1ov|`Uwand%giv_pnwESreBo~wl z=8==9qD_Z*t<4^7?bEMXK5~=nndwdY5*&t-^1aiXsuB>SHg9#Ftog6y--q`Yl-vBs zr}hoY;R9bS8=>2OUeh-3y#0TZ(>#Y#wss`!VJ&v=LqkK+=Lb}j(Ny7Aii-=Sybdd( zqfsA2fw1d`-qrE2u(IBW{plj|`sBZk-Cs*NfNb?#)4OuZh?%gxy~UruPfmRCV_*el zzOg7gYHVzXi&yGNZ*Fd;NMC*YC^d0x@CByiv5U*@gI$WIrY63`x||%Vz5+DP&^6kw|GMpP7qAJo*Z+} zn6uMgO-;?iQqT8fw{F@f+x%ej#l~1wG@B^I>2Ha-ww_jOvY(j^#*Zf?t+*Iwl$l$U z*W2gP;3^<2d{0tbKM;|TVYULyn7O#7rmT$nOg)E~!G0oWGjmKa-W0)9se1U`V`0)| ziAi#&>128usImqK|EiA0e0^X+xN!ch zkc9ZCT4H8FgSzJt7otcl&ctSK{XvynWeVj1a>$}%d<@xlJek8H=R0|5@cgZ=^2@KS zYLzLyXST9wyGJx%G?blRdILS!OI|8V^ZwC_N)f%ciZz`GTbTo-ig=MQ{t z5|~EggPO?YxmDveZHZCY`I=r@|RhZrfO$(VC!3iK0l+dAeS8@#JsO{JW?E3EsKMsfuEtT|%{X?dq5MZYtyBjQj5IMVp zd-_PXLt*1~wCG2i-T8)xI6Bu}=79u;=(VZ}UQ_DFg68crZ{=NU1RtpL*JJ#@ZM3#t zYafe}k`-4Lm703cKn&g9z1X8Og%hQT<}VZttjYFLi$(eb)q#!>ligH+(@x>haPD~TU)9KQzjfWc_~Z-6e|#=`w3YDO2tIE6 z7!xCGGtmRnHXV>mG}PYyN)>bRW0aQl_9{%y$zfV~`6=JBHZmdp=~Ks|hkn}zTdytp z%xL64r5`jzioUHKWEuZ8<^ont0`Rf`R!ugpJtK8C9*21WRx8hD2E-a2kedgzv1&1` zn$u5#?b!uYewtEbR9KW(CXL^&{r#IdRjAXpd(wq|?pZ$b z*xcZVU1fS^?BS2#ribIt{hw(ozx;K|(8ry*-S+e6@1MWVw`&}5&Do9Qqw0Y}p-BS^ z-;c7?%GI~9eDp(tj{mct#Rw=6 z(`bEdllYL&u%Gr^P)j1+N)o$;Sw7{|QoqCCh-IhN`w&(@TMDiLxmaBpyj+D{eJ5%dWKGNNn zup#=cKjkim>lRGAZggUz@o3z*+mh}kJ;J}84+%+d{bMg)Y>d}3*xK?qQRqoBmKf*b zo8H4DY>ZSp&2hFz6T0Q0h#nr3D*wdj;$p%xpVU6)ad1{?v_aD-qw8Cb1_g7nWD+5+ zci$Z+0FQz_vV){J3}p06uEdaKh&XiYe=C2OLK)B4*tDQc2$a(e+U2%UTGxb8<8C;K;AVs3#*i5#!Y>C z;|{?O-4og=F$d4Uj(f2k+O5ms<^Po_y=3jV$wtv5B75R z*r1f+qQA*m#c$z`DQF9Va1W2K%zkkkVuqEL*?)mbT(rx1K!=O^291h0G$0%C6#An% zWhf9LPjITY2m8j28pkA-4Up=gyb7^7yZ46_v ziMjYU#m3CsWYZ2=7sKd)-rvD(uB1Tsj)h4|Laf z?_p7x(`Fp@Lu&2hbYm$G{jFaqxW+BxC^-DoUhhkOj(74{N)z!}?Qo@#5VqbWsai4M zflqA#0kz0Cf{`tdOk47G)Qp>PwSIg*0RzYWwvw25du!Aq@RQVV1EOSqvAc)o-UQ@` z*ltW`*bdpG33mSFy_sl^y7f?I_f6DzolaXUwh!Tl$on;|B4X}3DOWEjJX$Q@yH@oO zgK99S^R1`*cYWEfr$*Ij_Wq|C*Ks3t{`zrT>7>J^6KH`|-hC>Ixw$#D zY-&b2O9ZeeQ0a_fnX7cGCp>F3L)G4{tF>u-%a{$3^|j9{%%~0M;Wj>BV-P8pnh|mp zeUNvy`Cb=~y*^l`XYl#s$H^pM+zw%4#UJfRx~{)iJMcp`>G-lAxfwbkt6neM=+Q3% z;DmC&P~EAIv-O@Ck32_TTiT@dJh%@#o%vRfUtF&x(l@?R>f&;fTjO!y{ujanA(i5O z@&^A4>GV6ZjXeO_UR%n|t8PQBq|iB;^r!d#oXVJ(?C>dx=$|c`S9b4lyi$dDt7^?hdO36`?wCTV!yx>uF~o+gC}SZR?Y+n-JJA z(p$(`1#G}+RpaBcFm#Fe9iCgfk%GAA>5yvYuCo%l0lSvXNqOaJnzTn942JsMt_D1D zZKXO+fcbgSePa%*n_cmA%PVyB^xq-`WSatAwUhYzPd|lc(^~KcgolT1%f+Q_|Gs;t zM^%lJcjYhRrmc{8GiL&{&qG3)MQ2>v@5KG-)1Z*2u&-Zl!M@&NV5#t5NyIeZ5Nc-J zqSr^6!1w0vZ=9oWV4tjpXVugc7HaSbimqm<{E@o%=r~=%%xj%Z;`LsFVfjeHAsd8| zM^j%|7P zI64E>r^W{6P)X6ol9KPWxsPQzI9zmHpFEk5v*ZWxPcc0I!RO<^=%~=fHwR*_RB9dz zx{AJfdV0>vUv6bPwU z3Q60%yp(BvO)*wG&axnjj!03)Nc z3scb(5fKq)F70}*amnlIJGivC#h>55UsqXCz3^n(2z&efOqEak2+er@$$JRg)TdpK zci<$bZ@{|Ar8Yjp#cg%s?vQ#rdnlhH?!kUM)A*1O%|QnoS`^v~kW z*z)}7UoJX=VM?Lv`Z<#&PLAblg8(Ow=IP99egjpb5|tex)=p~JP^!VeBURGUS}LpL z^yb6vn@6A8Le^FDG)PlssTocQ>{_-JofpCb4Al2ksm5eZF~d#fp=^xbL$3@5uAs8_ zKA0P=GA|V4kc}K6t|?HQXZ!Zs)<#PIpXV!YTI?U%%=)c@lixoBGt-AV#FIv=6jeLp z%nM>YoqnpT8=791x*lZN8sBs?YzV1;9VeU`<)^Kg}n+jW8`TaasGc>{@YCyov-$=cXoz3=9 z1~N_S)u^p*X-i7>k_>(1!6`Pq1>v1vmM^%StUEP$GH{JPU$ARIa?0+YZGqqnJw*z_YqiA zjcm$DNw_kr7vIR;=_8H*6ayweZhy`VDE~c1AkTAcAxI`8aHadKTk&@*L~mXLog1`7 z@*jA?w#i1jsawvZHNL~2YO{XLyypAz7XK+1-gsiv=%rk%+e-KpfbBM$62m#Gj}fT zJi;Yupv!+LCqBaF<7<_l%if+yDChIeHZCwHaM?=;bL}~nsY;9# z5IFRh;ugKWbPf78}JIPa4&3`t6pjxbiG5hXVAUo`L=e?vnCfrJpIZ)l(&o=vrB? z`NtK|;vyZI`Q?P6bnH|>se3!$)|jvr#Hy>fxT>fF*~86s_W+ zc=edxe{TU_3mb4Yd-+v}X9u}cV;okREBa1S_pTyWbdu|dy8d{_ft>?oettd{>l)22 zCF0jV6O0$SosV8>G}-pw-dYpFjF~-T+g!z3SESU{)oteGMa%i3JX>@fAyKFw@)EPI zsUHoOZr3xe2*y%8KqM@LOmD~@tP_o~$8{O!qq4N(<%MjzIf~U16v~i0kw5f7{?0+1$$BdE{`S zj<-OHHOlJxBG8ACk~W`J&cDpNrfn))0Y$~$4M{Vzxo3Dg_Zpb?VE#Ye-ZQSLt$Pa?bj|kE|psbImp8oMVphJkMyn@KWyxN@I$~i<-OaVJd|_o=Ne<9V@*!Ud$yc zxWn%C`|`O>U~VoCH7yHbo9!aTJZq$doSba#bgmGF%S*TKBFLmVm4awY5w+=u^^rqR z4Gt*>nAjgxRDZb4`=E0X6q|@vXOA|={Cp@H{bN5{{p>qm{N2o+JJ2yH2&C_9r+M_$ zb6CN;o30~>K7ul>#$k7tM)EZ6y2t{QD|}k}YNKn?f=y49jhxPGJqcxhA0Hn)>Hdw| zdqgXqN8#grZgURuu6;#SbtawJPle0ons0npVTi`Wh`g6=gT}|1rS?dXikJg04M8!} z;2l5wI>t+#Dr)?jX;#(88vDtS5z~9s$#OZ3`vM>rV_4>~0X9?1DRYApMpv=3Y2?do2!REA%8 zH#aU+s)i5vQ8Np?aYwtz5(;PA3%hL6k7>$oGd8s*JSk|hf+^OvoGz>thMTX*NzY_y z&1{(t{9-R=xk0g**=$mh-S8*UfN9Qu`{&Q$j?Q9IdH1YpALIP1c<9NF=x|2YpVWOH z+OuSR>vN1hypW7lxNOH3K1CCL)hPCBBbO`%vQw-Wp(ng1yJtYuN>=^cYAfDtq^UW# zc~aXRK4O__>QA1m+p_n@%55WvCaZR;aZPUDgzrvv_LJtupI6EaX@g$j1w~_e1{Rm# z2W%x{mnRIS4bBb%Gwx;7lUsO-HN(VTDwTe-Ey*sf-}PwU5zXWD1=t?pQEncCt21O^ ziXFV?3v{I8AuSrfS4e!FnZHMvMTt|k+zn~ zTO@8K@4sHcubLAS#R8Q5ZYU^k{o*|COZ96NOLb|ugI{;+p$H~ z>)7Wch>&#Co%%)!bnC%`XJVa*-ZyK3{`F;OL+w?z$+<|v@vGfTM%3@oz3!Dj%6{HU zblSX4j+d`T-fO>p0(;t)xyJj$!^x}^9$k-?f**!o?TpQ9cL(2jd=iD#$xg>3Z3Tch zkNx%*8ek(y+)R7U1Eq~lhajLr*JVUrEww!{?%EZe4zy$K?Ww*zw$nQ52DuVJMgEmH zCh{9*d4mQ6NPh7c8{?R&I$YW_CMzIb&RSKrxfxqgfe2_k2Vg{YR@VTvB{*CL4DZ2a z6a)mxSgRmwS=!H?LNGgXHSXhU@SZGU&+V-Zo00~{pIHnW^a>*`GAVEvP~}6<`0m~} zvC1>3J58E6{*+j0jwEW0X0H^RkBN?9xi=rt640+_QzV}%s+!b&;^}E4<}=`iC5tP_ z#I+QhY>yxL8H`^I%(q1Yy|AOHgY%=3@ePaIz8E20UOWCcPwGo;LqoPX2UqoMVLHh6 z`M$uU@0NM0-=fD_(CfC0iv%o!`vm3Y{vguz{z^A0P=g>tnSnte-E0Pc+$vDV3R6whJOmtny=|AKTbi z^A_nMr?(bwkMkb7y6ylkeJXO!oj+1`v@$Pm5JQTSINNTr=K@y>jXrTmIDE_Nd6hOJ za~5O|qc(i2(qoyg#aC1112bt5uc-_;Z(Lk_v*Ppzlw^d8G`MeDT5l@7j%D;S@9geZ z{8phYGtFnI<;?5^eHdQB1USX^@viznHT?*8FbyBApq4c3S}Q}mP9^O&M`-OQ4Pp&?^($3gfs?iN= z>M88&j6x zVL0-(6D*`}UMyrXh9nx=Bu%BwS%2A@ZfMm+zYpI2aqg7K;%?UD%sg(HoD9oraxQ3D z>!2>(N!p5;C>nZTuq=^VFVLNW8gnNc^VRS$|M%x{VhS7WdUw$`T+?`r0nMDGUl~ z^Ime%=sUF!PnDXYd;KJy7Sev-kOGWEMP&|e0J<) z=~qcB&6(myu_*U_hxX^rz%nn~B#7Q)j>R6>pKrt0@$ukz}2kXiikP>fcyE>vrbYWEoyu z95g4j#qdM>9s={HCWW6n>BiP=*3lQa*hV@btg!(aq%JCwyMw6g0=3m53Ee1r(z!V! z_TyvylwUt}uvyty9P{k8)iw3g9=L#17+oW)cFK8UV}GQ~K}#XMU}|KWV8Evl_qa>; zyJsTLpQ~8yG>!_$GV+Xo*-s|D&LQvRML9ZLK3sv#pc0Wc3ZiMDEB70mQ>o%Ew8s7N z^`(AyeCoR%_uoN&@#9CRbq%+MkQk$6=5&_z)3HmT3a1nP4KxGY#V0e~@59Ylivd_(kOI+GNY~=PYw+!=yHwo7VN+9PX?|W--Nc3H~2U zjAs_NP;p-V`e$XG`l%|w@hXdm8>ypr3@h(2t=PgP49vZ7BIyr@K#D;Mqpc@eRf5TG zZQ@(|%%`-9mNO`R} zO_$by0T%wb%+}k{IAd~hS}q8!d>3US7zNo7&agEb4bqFJ?Tx)0^EF{%X4Z2WJv?+( zSC31js)j-63Z6;Jtn86~H)&?`y7Z2;P4_tWfq@)KcD9}+n(-l737%&gbzA7lO*{IQ z2a^~ti*`l3BR8_<#_r<4&ljxh~+*SPb~=jbU-Utt9=KN$vA#%Oj)2Pw-QkOsG*$4^V!1u4gm z!wr;Ibs<@84CISzYySHX_q2g-Rwjo0f|4TW^OAys9U3vDmToT3=!NsWcV}`{ACp*F zJvH)2fTVPq!R+Zk-76o&=&JS~62-iKNTiO0O&mS_92&99u647T;ETa{e|RD( zz4#jv`4nNg7cW@(c6`h{JzeG1%{<@Dg^<^6fhwdA+?|&oA;>(dsuXgO14^Pdv$<;jwn0o-KOE5i{HBlME|lOr!={q#-HUy+G5A&e7}l=H^^Jk41dK9;5suU1w4bwGL0QouWO8 zt!v=z-mZ`W4+{nAq>wx?BF$bP3F*|_o1kk9{C(HaedOuGmwB7RA3}4(8ocXqkx$8O zPt*j%dp1;`V>91T$xH8)&9!DXIAzbfJP*JoocU}0E8#)3>&qNgazhbS4V|%e9`9K# z)SQy>5rks=ZO1RI9bjiTIJe`Ex+WAtW&4b;Fy`NWS)}lW`CPEXx1Sy#ue;RulP*4m z?VLV2Len)0p@@>O#heUYhL zI4r$v`r*fl2*;}~pBCp+Z^FA(6gqonPN!Vu249~(;(qpE0~G9I_#yAOXA^5uTArbd z(RqV-8Issfg!IPfHn2|A{sjUcpKtxStFEK6*BwIDt6K#sOL=V7h6S>Vj`Xn(D_;q8pVg^#@syLZMdX>*X~!qaz39eI=l3hx3B2Xu>7|WiEH1u)D!VZ< z3%^Ii=I`G7!fNW{{gRDO^YU;P^E8h0^dMgj^`=@v#28_k-6a1WEoi$mRk!=AJQER} z$m?rvjkOndMy3`(HcOs_;#b&y9wDcyD{1(h#1m+< zl&?7^w_oR0uW9-!^8Ib&X6UGnTvM2MOJz$&wS1jLv;CVq1v}VEka|vd7x~<*p{BMN z9;*sPmH0}zJ5x*jPoECj((c`-PL-^-5Qvbz?fJ1(yJQF%1d2nqu8c@lZCuxka$f$7pUqL7VZU^j6~uj;T)(IK zExd7_5F7~e^&V!hH>5fn((@i|c4pZg2Rl7T@x7%IuQ46Tjuiw*a9tEe&d=ozs^v+Giba<}+xZY{NZ<&vCey zm747BcK|R!s$Bp&Sf+m$WMiI^LN=bH#!VVqT9Pa_y&?q6fV%s*`*S|%xcR8TKY#9i zkvct-RpR>%_Fr4IBg@ONuIWCp@$rQRA4jOi^xQL-+sVkuIT4B@Vb#_Rzptll-0X9NjzHbcoo_PDu z;=?b^NEk76@CuuNW6>uuh7k4~_=65=FS zWO!HcwGy!^z44Ij@e67kZBDlov-7oshxD<2Du#wv-FJ4nBRQUPGV=3Jh&@x9T2txm z=%oJ*nM>0TslU)Sj2_~CB378Up1@RUK$G#YprB`8Kp_0^P+~ZUxBY;$Ql#nBVxl)` zvj86@s@-UMf>>ed3MXgV$sXE#{+#Cg{CouuW_6KE5EEMGU{@9G2HMMcH z7)(v@W?&YJ2vCAi?(U}Y`?GDPX9$1HVZU(ONk?>^>QIhAkc{T(BO`aBq# zjpvj$S@GBb-;FDpm&`jAn>-1*9T5B&9-N?yr1hQXv(Dxr!EUyW+Y2KPG^Zm?3NJ=- zk^uy}4HO|zW%HmT1)d->tk^ysr&+1*-`X#&pI8V5^_mh&6Y483; z`LM7ml0FBkO$kKIPC{X!7mF_gj5SVJ7V?=?*;h!5?fwv`p8hprSs?p><|;L z>@;2Ei04xg5joWnwT^jGPCXi}`Y3hxZevD;77BzUS=BHd4oC_O}-@Hu)jT zYjeTa!Kx=tg}b}5#S`)q)JE{o)diP#b&>ALjEDqJEcuga|pt!9I zI=JTX?OSpHWwVAU4m~65Mn)Jj*7!27z<5WY2h`kpo+e=`1{MUEpaK4th^wb z$vQyyw%AI?Ur|%AE=eaYaFWGsn5#xUV*j{1>BIW78Hlsb<*C(GZza0}&WX~u)LNQK zZ6MunNM<&9YrtNgGz$7Y3OV*QESIiVnr=5m>X+`$bk1brnH`!F; z)8cps=B^z;(&9U+5Qa=^H`d0&br^UyA?toZcsR@41h%y9XdqW2iv5m>3S zjSbivrHC*xGCK7iI#=Zy9{4D%oSq5-MZ4L{C%Q?=VkdtBM{P>NLnBDz-jm+aCF&+# zS-C^F)hCKN4*J_iu#}Q}8j&F`vrCC&RtE6lc~K3CY~E*AX?;CTPJQv46@9}dePOq7 zZdumz!wc0S;3yF7o*JfqpyT2YaWP1?%EZ)79)K7P&Cx5dT9{ys`0 z!Lu+|;pP5QzsCraNKp*8MOM1Y-l>fL<4iC$v+C9RAXmfLT8?)>l(UoYOiM(*+OBzok2XhKrrK$Vk8}3t96{#fnNJKA_d&#R zaKnkEtTppS_baOK^tSHAVbvYeg{T?KEMqZ;u6MwT5TVi?*V(A@At;aHDmi6Ei_CbO zwvB(^vC^6*ROkZBuz&gASU_+?j-XTXN(UuWuzT5~iE~+hRy@0-$j2$mQMW$3ERAT+ z7?XH@A8tH1y48QNm#;U0*lBD*rr{UDp88Rdk%@!n6?ySEq^oEhJ;zKNqJ(XA;7pk_0 zM_v4akv03G73%NX@PuY&U~ZuPA)EJ2kK+P6MQgW1u8sKlVjD6PizdBRm!JE04WazW zks8DB2ZJ5AHg!_>b!;4@)~orZM-Yg;u`2`L!xlCmZznr&h03p)^C))4XgV^?;vW1J z(tnr7s;3HM`4p&BY?wQeCv9Q)?-suoTX1-xS|1TqV(A2Z`os_~Z6#ek&8>r8&L0*M zBcpuijZAg#>Y|@u>lL*i?WcRm&;NqA-`F?5=qO8f4FJ^bYfm)l^y^N^veN>7Ei_6C;ZZ5NB(W3?A_t=#h&TS5x6{OD%XH*mT*cYnLqQ>_!zP zK|&DMHi`L)F?P!BPnbNRwzuB_a@Nj0BO4f&@MfykCxTNt-Xp%bqti)oR*Ai?Adn3r zCNV9!@fP|Jh{3ie@{MLhjA)7qBU2ARavTU=)b7SaON2*{*q?U$kzZ;1r2$IZ#wOl( zD?_`j{o8SgXf&q$;S1~Ph@sK>sJ{fnXkXAV`5KW=cXuHjLrJWz&JN~;w~0JsW5A-` z#mR-p?pD^;9=Z^g23E^MhHeZB3uv%BwBjBUSxgHYJu*XjAA5J*wRl=a?ZkzvyPPv# zU@z;;IW%(c_5yB5kes}gfmg2>p|!|UnCpcSylwI0Cbw00@YoovT9OsRFYs+nMcLvc z$<7r7T|8UF{Mg%!HZ66eRQ3V|T!^#ck75pe&+o~oX{v9y)H~)c35f|hMz7e20m@VZOdT?Xv!!!>u++6Y z2iQ@9hQFSL^bi-8ej83T@F!&)9ovR+l$R60>5|CEHnVo^MBV{d+t~bu$L+6xX%Jbn zudrOX+KYex{?wlhdcX{*23!unMj%|A0a&o$?^Ti&wtQxQIV()mLI0vJQOJHHR2`Ru zt(w5XIP>UFLJY6rc5ECpN&W?>DSA_7s3Xu@e&ui}I;-;iS*``hz+eUE}nnZ$xSZTSFWisp%?H&5}2>@?N&^}@F2cei>?~;`S;800Wa@7ynYzfbW3S@`D@YkA9Qdu zN*WN2R6O@^?@EyhDVVuaI?fRq;Za5>7BZKvcP9Y|AZMZ+!Yf_SH~7MJrF?hSYX32; zw5-dv*(2J0fq!F(Va3#2)@Uq++sbq`P0YTjzHVokwrsJdFh?Q1ZuOMBNK*@GIkLII z#iGh2y`iCk7_Z#T@BIpPzxnI%$<|@i;=JbTHfp9)Eta*A`6#1oLcpdte6u92np=o| zUuBSH0N2zv#=mtCmWMeuvEKXyFu2cu`~X0vT~+~N3sp|Wft#x%ZB42J0}39q%E(i>$ZW_VXUrLRC5qo>)gE4SIM?|cO@dr z&Ck=s$m4@sTP=L>j^#{wFjohQ^2aI365J}P2?18E{dN40PX!O_m%=eknjm3Y+yu43 z*r%;H4>Q~A8mKzO)b#HrCe2p`^S-T_xy^>oE4F4=l;u93-^8Md47)*dQt#)ktK<@8 zH)_gu_SVSU*t@3RXl9Xsd;<3V$J(@VzfGm~yBuE&W=(=_-QKb@(F?o+s^WWt0)8{-2wz8(@mUb<-bt6}JY6#S}JX#6kFxrXOrD>ZNz2ekd zM2CzGzZ$30g{GpQwqNoDee^x!Ruv<-Wroi8QP`5m!`ir_tAP^SDBFvy+Gh8%?L%1n zcujL7TxITT!}Vk376E;rLY-sI(M8yKr^H6rJHo)Uxf1F_TyLPFc!t^jCd6ev0F|kQ z)Y1Mh?@gjX=l}WqS(JBF-?HeCLyf-(cv*Iqw)`$Y7*V^zNnLKbqf{-a2H-){IJ^}A ztww92!{Cy&YDe$$SzS&IM7P@{JDs1^5WYvOiE~@uM=ByFNEUhr=Z?Cjy7|Ez@hn1* z?EBEqWwWF0OS$r2bgOiTKoqV!jtogKLf36{DqsmI>QYUZWtKaclAaDGXkSOAgP zsqw2tDQ}`L`W3dG&Lr`7-@cWwcCD}S#09KO+i%eMsHlEz)56(K?~hO4696LCVqndj zbNU4l%8awpJXgN50mpRs)b;j>XQ-@Gf2#h~27TCLHp*l{13Mmdbx<)wB1YPp-bvw` zlY)Y^E+1rlb7Rf9LSDk;JtA-Y?5Tr?C0ddS>YKJCTrxCXRNRCQFI!QDgWUMWOtlUt9i7hb^zSb6*5)_RhZ&dX#hj{K zMWSelZi8eY|F&4G;T|{(_SvmFw>331wr8rr)V4x^N*9UYX?BQyB&L!LxXX;pz47yY zT3QJbx&CY6j&Lyy{wjD^E^!>w~SKw;Fcv>&h&(4)!B1nbUf=w3xZk4%2D z%%-Llm5FJ4E)~*HlX$jy6eb2)S)ru#w<&Eok5=n}_+$QtpqAEcOCX;$onkn|CFtn8 zI^AnmUC<#^v6Fqx!w5v9=Y^n^$yZW7Rt|>zqQ4|4T92XSi?K>Zape@WVftGS}3a$=bHUY9$JhP#I{ZMor?qgq=uZ_7x z{bB*2xXGmmsw+I(3jog4tJWd$5Q+#W0M?k9RSt1`P62~|ETbfSpFu!m^YFCnvlJ@3 zf{w1^4qC=-eA)#`NpdFbbGfADi+07tbJ@>TOim#xlQ?}lKYbzb*0&siGJXnaYj3uu zeq93C&qhsD=}}ciyYErHqif?z2L4MR_u5hO^7lY|Oc_EEIom!bBvA_?4F}i~|7r5~ z+fPV^oSIL@cMhyt>rLu9{UJquM&&!2(6c#Vh50AO>>QZj*v%G=YSqKPfyr!6)eoAMtyd=!r%xUIeO5%$?(N$jrkx|2!7+Y+6(s>X@?CcShRJ7RQ>N#Kkl{jyUAkw`DBlQv5m;a;j~R zThV_$ArvRkV7&xA=tNm~D1IJ=uL^4!3wkwcm#T+{jcgolhNQDypk}CtJ|-zPQ)wI6 zH>0}4;#EYN@?Qw(kt`Now5PV6taPT_udFek^X#g@jPh~w>2vj!YyKK0w@K2S+D<_2 zAI4o0vK_`yIu_);Yu1&%3_8^b*do2%$7Z*a&eYDFtUc$(Tx0gW=(5i~SV;Jw$HLWq z2Q|#2j(x%Pt@n`7fZ=K=skQ1+JJt4GD@!X8ebZi6u6MVs0pYAsgxPSs;S7aIb1a$= zZmH&F)e;hzUFtp)?}t7ah)*PHcZoiY3o)g-I7i<<;|ivYZgE}-dhum-Uu|3UC?o+L zG1e~77ulpc+6B3q+df@pzgScoxN_HZP)OX>%jX!>jUme(w_@2jUC21CmJB)l^o=!Y zWM`}DWZ8FNzIQ_v5ltrM7_Ih`Zj64HA~5&$)M2z5SE3wB^dxVVmFDH^;AFdonM=hJ z_wDnb%Hh?i$4T<5npbB5Xhjk-8(%zP0(aI=@)1u(9}!VR$EG-qj@mFXWv{5Q_UWP& z)TX#32>M=vOsRj=rZ+%MC{PH!Z`uLq9V>eRDj_Eiz<6dV)njQWt7v?aIr{tCGknv^ z?kbZrSW?82m|~isx>Gw$tQgx-R%76@visYg-8(xB?UIB`O(m1fuKS@(8nQkTWLrdy zal^_+4h~96WhpAOEzQ2D$2Jzzuc2{?-vs>vd

fTQP}K-LH9Ut|5gHgvFK%9kdJ; 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�tyx?6J??uj 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

%$5e{Xc?c>Y#NuSu5n6 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

@(AM7Ypqhgz_qaFk0?h}_g^fxr+f z$Mj`N8*aI#-!w6y;c{aTW7bIzKZU3V30<8J?gx+J(XQU4WqkwC#N( z?CxNrx76ThY*>>^3dJLC zIXOA)*}Sw^34Ja*Zww4F_Pg$G&ho*D91kuRE3H!nO30~Z2F$_oRrhfUL8c7(wSYC_ zK9SXYFV*jBXVyfI#Ci*C%iHca(nMVEhhNCVzoOI9(9qV=txoUS4Ody-kq&N>szL`8 zjBfeQZ8Glz9_}}^Kn!+^Eg2Z^fj2qUgc|!0h_EPM%J$BVS^MR6bHoxK!{E!*!x9_Z z(2A#lf%h#Z@_ZTLzqKT+%67QWZrNA^!0!rN+APHH`~wU(v~PSo~Esz@FG(2 zAiQlgc~b0&>KJN0J>A7VoAF`5sQhF=J=AKNCsXN5DCNumPZ9}$=8fxegVyTfl*Co= z9g}peiy3+A4S|sJI^!bB$k`LdV&8U%IEYRuX?iZBCj`DrfwsTX4>TLm=uM(FYa^Y7 zSOfE*CK7XmJ%=2b?no#s%&$z;nkmrKWZpdS_rFbJ)rf`!O?qFPj~Fv3WeWR{ zP}P44c@dpBIuRm++Ay-m#>60XQx?MAJt|OJXcE(eEAU$xK%L!pg_q~U_Xc~bZOpuQ z*JGmWAEnds_?-T2Q_^orP1dat(eC*B%eL2b`#D?6M>E^$+RyDBS+^~e=34cNd-quh z(xEk?XZtMs&3e>g2bw%jO0geD^1aLdcy?R~WFjp%Eicc1td)%X{C@%*pUkWhPX~w3DMvrPigf3GzPr$KxM%2X;a` z)>yJGIp>ubh-dtSuihL_4smcrIBbO?LNn6i6?+}|`Rf5F4*l;8c2fFo&aTc*AQJ3A zVd^nhU&``FbyrDK6_vLXfB%e*meDL{6)kH-8gWe7)xMhB;6UjJy@)jUlHsG^*> zcol`{q(`*D<5^C5=)fotI`t|}?#kv%G@vq!+{SzaA)3Vd@@B9mOmX&4!# zNHs&d8GYNLr)aOys6gU#mjeFul2{VH+H?7}&ZR8dUgX7bCE5o?qXgRvqvm6gY((2x zMn8&E8EVUTT*Jfrax;hVv$E`qi+C2m;|@PQsi@PU@Sb1aL}|ci3ZKbDe;y`r`z-Bo zm4QrMs2#8}nLhtBT1Yim#wH{bit#=yL72uz1hE}q4IKNfgPV>|R0(ZbzTsr!4dHk> z4+B)xFXnxi>7!w?<>sEGN>69%aO7QIZ}>8`kEAj-wp;quq-ii~W9)H>`P9?BHdi7q zD1T-mz-yr^vkjO-FB(eD>a!M6RGesRC$nnk9`-&&RjXVflQ(m4y^@pP*nY*LuhSI& zU?tke3l|@HRsC8uIuQUuin|g6uw-eCHv+%TP&pIH47Ul2j$MG6IyT1)&06xMn`3-aM>6c=c`;<6iam5zaOM66cjXV@ZMa|3=a$}H@mII zhLJ2REWj2QF`pK(J1>Iv{|u^a`2yUKzURsL`+X*6W)poaw!(f+Y^`FaDO{w=aFz6K{PO`jtTkgKiW?1h;dnrT-3dO;gr16EW}yz~|g zQhy>T;WH!lV`ytC{?F{FL7B>A;5Iw7s!9#2z!fo-W1g?{SUj7~CA$Rrk&`pKgR(cJ z_6enj;$fSX&Oc7)&N{-%#z^A(iuV~+!zgGAvpz+rh=ftox~8it$@+eMUmHGBp=Bx9NnT3)a#SH0lMiS^nJ2#QDzd z@AxaCcTi_X`)@-ir_+Oe^a_N6Y!@!)+Lm=&eQt|ptPsNYQ8iT)np z;mRreGRMkpHgB3}%tE;s+aC>&6^ry1;c9y}pMB0@*H?KF`?&i9TQvCsx#d{&CjZ*n zBmOddbUfoLqoX6ChZ|qNr4di0qkq*aJGqSm=z1dIm#fGK0s2;y+RbKau)0-kD(;mb zW;}Lf&MvTqlIc?fofFzP1?JmIdV72KMW{{>Ym4W04aLA>>8NBcLC?)yj`lLdRP)7T zzPx;>TxeJ*uf63n~NE0YLP!WZ>>#h~MJ$zaIf&>$~GLQ0B+qVs-p zj1|?J*V42_baL84163>`Jsvz%}3>!4ir-jl5=a_Y=Ni=N!~7PYXA zzT#)u7Hd0o+nXk8F5P{j@Av`gUZS-V`VkGoO6n@KZyA%UdVvDp0FTra4RrMN*&wZ| z!rR+tMk4&9dd;4uXow0Jaz=o7>9OUV?sitnz{C#f$of8=Vs2}zhzAI9Zvyj9_q=DI|VBeEz;K2lo7gV ziC-!iwr~GR4TEs^$`uj0-~M@w#8yBNVoUSt{CFqiX9?h?V}l8g=yGXCd|I}U**Yu< z45l~ z!^7peIpeS2DQTYu=A9%DRNdEylVP1qC#XYcLUojUdGzf4%k!2EhenKSD2}JcReF=A zhqUS4Bdo;YYc`jfYK|?$eu`+B%7xVL)yR{f+A>T-@3Wb8hRog7a`2&n2;BZSHq5~D zYKG-3XY(SW>*=W*Vm^Dv(1)SM*gW(O!j9#+-srTIj#o^z@rBAbM{XM_uY9(4*Ua=% z8X1VNfsdNz%Zv%_8QP}0Xz~qJ|Lzh3Rk}HNBh$B11c8fV&HAzS%u)7Lg3^C(GtKjH@_! zhYGzvcMN>xxf${#FN2&5YZ5KL4N;6cS&kOzQZd#@fzhi+&STTl=>vdgMTE9+IqmnL zBX-QEpe#SC=1q|)#Z|cG4uxQvmtks$ib>|cG5H=ugh8z81u~MZw-cUxNi4-1%Vy@0=#Wh|xEmx7?Eal19vNJ@5X>HP$ms>D2~R zZHSeL-Oh5Pe&5JQdZS^z5s)G+J^gNg0V;k{^kb;AGdrg$+nh3vh-7kWaI!A}`EFp% zL4QfOnp+(rVPx#JW8lJKotkqioUT>2o+H7W_<_DJk!0Cbkac*B;BY!(P}fG?FFLw1 zzSh=E#uhKx%S%7#3X_kI4~?!a+p)pJ$d_RtFk@g^X5v(-tbJWO`w;)zo~16XjdN#Z zrq7(tqg@S2N&6+NAPY~c&Ri!3FJ-xIG@7b7GK_?9?QGYrl{YEpPS^FWCQrB?MSP<&6+i*}?t41DQnL7v@HaYfM#5k>1fe4wLwAR# z9w<^Jbr#0Ob&W?kxMD8FVT+^^&{MKgBB9vG`lBlDYx^}8L$}^;`utr^-}mdqcJrJ0 z7gL^RG}GajiXPgs-aa>{aG&+fFQQSa#f4T+ z=|bN=$HZWeEkrK5u|I59<5Nj&kEOpRA>jky+DozG=b6Rk;)k(Ci~!1TfSHyWb887VRd zy_t;~Kkjs1HCJQEm`Ul_QrBRy&rQ6cub!sbB8=1HT5oV1e}4hu?7=5D^N5t6z?}4g zLsX|P($dKO@DCrEiD^M|lb0n)wX;i(Pif<#G|QC5v9OBnoq}X7L>nEUK}ZiHsg~5` zcf5%F7VA7j7Sm&04psmq>T^PmBk64gwTcC1_AQk-b6>=o?_at}ULnmx=@=MP;F0}X zgBk%ny`d3`X?n{`A|emk5B*32xFSEF?OD3r(R2C5%t2xYTZxihkjxBbj6X#XQ*%se z6$ZT!bIxkV_r1CMD4#}TW_#hNXN&xW0mhHF2rDT&%`n`LSP{YEGK*!X7qy)y(-_(c zn%rW4QIlKp+R57T39QLnrh^sVyB`d0E)v*uSxZ^ZMhc^rS|He*!Wa9fCs_EC^*UCH z*LQ9+3vDg~YS;XtoEdVl%gwIfyNJ0=ulp<2Tp6y5;)bHj&4F0-?cV1L<~IanM`&~! zxzgIKn`npU9jGG_^LnHCV%OTnNak_0lD?MIkWjOS=gqiuG{$QxAs?FMm_W@|+j43mJx37n33hq?qq4eDV zM8d0hO2hMkxvI`*!|c?R=Ak3&w*!=0J#cTJ&~Sgj+;22~Y9%}}loH@8=dGu3m*I|A z5*$i(_Y5~ei{Ncy(#yHBRt`FOGac+H@8My#-Lc-~>O;SG>eQ(|77upkaB4go4Rr3? z-Vh8;F=*DWo66D$-|1`?amE%UDJgDA{*0nVr(%FQvB?<{#4oIfNui2KLdJb*(&1Jg zuPU9X4Z9){<{$W&+1PxJ=vAz2sd!vW=BQiY^QiMHjB%RU8iL-_0@*53 zULL1OU+Qzpty7M%aH*9nhFTUo`+3xbHo`{n(g(C|+JwJ!? z+rQsOp|T|Xt8zV*S=SuSNIHP& zNPE59+h8RJ9p$-$RzqKu4@@b!g#O&@6rBNPQlTRZlZ{BvgUD~2nAcvM6(U5~lpm{z zW@?$ID+;kBW62=T;SdO>N8{vTnY6*d%UNx6Zg*e1veHtKX1r_Q7iPGL8<2p0YYVwY z`f_+Qs_oU*M47(3xkhY2YcA?GNS=z4GP#)>uYhh$w(@IUy5;kywURZn13c5t>=!gV zaa06hIiKUACXUBDQfMUFb`Wc(-z^nM0V8&yp$!UbWPBhuX+nzjtt*el711`EeF)uT z3$&_hc+%*!2V(Op;hyTFyOfn2m+o6tQq}iGzha1J`tg6~aV*zNX|BTiI&$R=Nd1LEj49dJpNG_MS~Few%Y@*h8zJkb)5E(MC-hc zvhM(%XB1qvvl}kRQ3Z73wG7lVzPmS9wEfZa=U89uLs+v%ch9`Z(b2^FN>vX_I3yPf z2j!GZk`SHJ;?WIjdlHOG%_qmM6_*%~PVLtz73)vWusjKl{Q6*SOB%jEd*>c z^JU7M3%ckqYPrg!-(UOZ7uv9u-Jrl{t5)AcLXJ7pn_QGt#MC2F>O#Y?iI%-TlTzS6f%h~fyZidK+OfFQdTY@@qPF0RKs!t59%N>x~H2FzbJcX&E zF%SN<*z5(cb*?w?A##$I@r2ES@6B{Nq9wgZM9x~Oivj7cgw&Z1G+n}@R%1vFj59yC zdM%3CXssb1?6SH{4}G7&O@W)lR;ZF{vzb4)43XhvBAjoFx(nJL1RC7>-DhIOsW%)2 zwP@M(o0o~NI!BV6wVs`!bx=)npy-)q1LyZaV=bT?Y>v97x$d6Z?t}+gm5@MUDCAb4 z)&9d(b0)`<+V$*YJla?}O{@r|pDs&_Y3fqIO_yc(>FRKD9ye^p zuVYyf%k#|5lrjXwAqGgD}yaUcat(oTA_U(Yq2ZRN=O>3Fn3*AV5aA zkvNuM?>(8Tn~$?|*qdt7q@*M@Kc}Ie?c~%0u8U%O^h&8{lQy>{C$HgPKKS~C-N$_ENshoxZ!^|p zWUFhs(jo|X7mB@if0Wnbj_u9ianEaon444dbAreA8yAuv zN^YEYk0y*66!Mv$``ki3KO71r%M7JQp<|RBv5_G*idnUfVH5F|Xhak?yySiE&kzw2 zQCyrKe12#pF!=EDr1dCLf8E&5N^HHUq$DtgzeQaO8T^vpcW5j_h|^;JSE2#<5EZpz zm(63?z738o81dXHC4k%(c*2y7y2SQ0tyj>1MPcOJXm)YSs7rC|KPe_Z`c5)RTde+- ziTEG0#+IgwpVHhv`4t)Z?V|Ke<0qRm#0R~@Qgf4~d7)`v^?>EMC2dzkD|S|`aiN}? znwlOSBi#ErR^cxwD13~=c6(GK@R@(lOpmxdl~7gOuoEbhVf&%NSjs<%b;rYOI!jX> zide)hUH9H-FM5MM!XhG4PI;bQKaY2$@!qZ4)=@?^wU?^lJ$*Y~xd%y*W{^my_zU^* z%L;!ch8|bLRryp}lMh4`UkqN$t1nU&-{F9Y$x-I|zAaMNT8m$FDIiRblIiP;>`|d=y(y*WPtelx5DWAAIxzbO$iU$4<|6j<2Q)ec za&yiNU>1G%!wAc_&DSaD7FJtyzOrIwW`=g%Z8*ZSIzEAt+kCFW$wW`(q&5$WAF^=z zZw^}lS>X03SOl#Pox$N&FYTi4eQxAF%#d;zC@9Do9pvYfyoi#osH@X(iW90f9Q?&Y z`*ig+=B)I4)w?Y?7IgI1bGaw*eWevB;HL76`BrzH4`@&FCc3PUQ2zxZA6EiUV`l7S zjn-o5PHtV_rYj7l)He5rZH^k=5;U1s#mYjlc&#Nf1`_>;Eo*hv>>BCd120JbM<*VA z6hMcvT+F0Ud$0x9pnocG1x?kqc!7r{po4>{=zDb~o2~g8L;6dG*M0Ae7bPou!z0@_ zLCl_~h`C0uF&5IXbRkgEW50)w86gnCC#8i2GIEOSdUjLKB(u-ojCAOunbf79i_DMU zvl=QY4%@?TlJ&mZn(7-EINoj!5Qtt2h>G6d&z>K7tv&vPHd9M}e}5PK8A`0l=*NBZ zpt##PaV>yrTtZHu*0XU;?u#3*28kQm;^m!*H_az&LsPk7{&fohxgObAXimMKc*on^ zQe_CUVEjK+@@Jp3Rd{M?a=xoBS=*r5dz51auDyQ zSnUNgbfslR=%$WO-+rs2&+c#Kf^w=_;`(<`m=a~!QJf~&L3-ILf2{JH-dx+EZy+Q5 zPX$2M8x?^^ul`}HTSzxZW1`Rh9RE*P{{LST5L}}9nxq#X-2Xn6tSx+6>X{C~KX&3@ z{`{klCjbAB>i?#!;s1*X{~ulVn`ezwaBg`npjg8jw`C}!{ks4A8a^$m>*unTswDuK zW1O}yx3HhVo<+9ivOFn`=r{FWzFawPnZ}UTj`tsZos98sy@p@iuQ3g%Zb9QgUCSk< zHV~?iZIU&EEnoCI7dY0awMvGot>< z*d!U-Y$-0fQeoS&e~4Wz>+rwrem`=s^_41HT4|}*CkFp1e9)v{ieX-Y{8!b!b%ZjL zIn&nY)^j}-&`C~yRoH-`O#DxQ47yC@8=VHWGwpP_?wh9Z8m@PlwDFw(9oDx7s5M#T zOA!H`H}4hDm;R$aWJ3Qh7U*dA^_t}$0#ZWCNB4jO+J3JO++Q|tA3Yi;`Rim-RHBd+ zq90+AQ=wORX2d(y=gmKM8?~X47;8oT@CrW{$Tjlt*FrS$>g+|BVH7aEg$}vjOK?V1 zfeK?L(o(k~bRy!hwH>@N&EDFl3H_irzjCuAfoBp&S;qtYCRNCx9)MJEZYsC}dKO$$6DkQQ%OC$IDhf1XxDfnVLebjL!v)VSW&1 z%C_XEIIuQWP>5(Kzte{e8U8U9Nagr^>f@k9le?tW+g1$CozokB^YQ~Oh;(VVNYFF4 zsVE2ZhFw;W6-c>0y7Muux^nV$J>q^JvMl|j@gyvS3z=M#%OnC1mMR>o*N^!_bn!Ly z{70t{6-#UUyK*t`!wjP2eWRIM#qLfyp!CMvbK&^eGo0F;Ti=?KbH}p%6@&TO)(&7# zhyrARLc3J(KH{l@8;v-Y+hZz1N9~hVExN5UO|k5-Kd`vwweUQD(Zc?`G9%brN@DZ? zZ(^(oEci7`Ik0lW$(DL@C3bC<2{lso8aEJL=H9Cod6J!B1&Zf zyvY?x)GKN1mb6YxoMp7!GGEVgk(u)db44>-lh=*lBGLk8k(+r4*EihV*X zhskTW2h!B&rid?(ryjMm(th^w-bIVME}~E7{`~r!2hOfC?-1_$UJk$HmbQq z-R2)KH(v!k2~wpOFS|A7hb}H08&X)y#5;g0&3`82!ruzhFtoZAYAA-%2@ykjt*Yh# z1aV4oe!M5nsc2-&Ili~h3K|-zmkA0pJLi-ej?Qdgq9Xg?i8%Ky#2#QVRzNpEn4S3Q ze%7tU_777HAIkMni{54gdCn!Yd^UYt$@g~qdAPi7*1INy+q0EPqG^z%fK%(Zn9_pk*NhW>o4 z#Nn}uVFSZMgku3wx$tWi*V;8zonvbbYfr7o8C{F-!xP^2$(u@P(afqY2^08updF4( zJEd26=WOY+k-$C+dofI+>&xWk!K ziaome;R_LRGb~Z167qKl1A5Yj@5)hSJF+)tTj_(Rc24GSe;>H zLSN2CED5oB!0qKZSqc+>wyuQD?8G)kb`D;Zjf4Hggj2_~*mmuQzo)dcKYEmi z8zdQ&OIKJCKDe%jg=1$_7CtdEDx>AYz(QU7zJTP5X>${21atVO?3LHS&*-VCFO}46CB*Q#daqvLJ>gjpaj;ds( z-tt+15f)`6B9W^}g+gE1u+xy?kmnjMZ`BIP7IjA)lFH&lR`YT&$!?nr3^6B6DK})$ z?@_#+Ug$0YXC0{-;Wc*x_i`n77iM}-qn#Zm%guFh@rc#Kc&I*z_yj568A!z2>afzw zpZ6+MOU@PZvIU-YcFz?9yl{k(4Jio&1Nsq~RAs`Yc0XF;zP34K2x2~ln|52vbHwfK z+o*v>bz4LoNDffDzIs7Jk?P$=YUO5EF4egcydL>bI@%cP-QUG1NyJp*J?i?+#9EDw^FpW~$$pGh zj7bXh`_skXpwQjLH+TI3qvaGYKj^s?Ail*}br)fu_NyllHMeB2TYsagQNM3h@!{3b z1lww!`o>B=~VusfE19Z<|U#FH|xfw(rvND&dO)_Osh2>#Gw_OB$ ztFNc}S@%bZon{8)vx}}}-}VOZrIi}-!;So1e8I;26x619c$8w-C$UqUlVj#7>Id(p zrtnKq-u0Yo^V&|;*oRGD$6xJQjSO+9Pumw4R(G%Xr)uYA=}G_D84o;ft_g}WFCZSI zL+}&~_e{jd3W{w#NXN^ae=H7g;(i?Uh2!_oA!4o|5AWM_Vd1%B5y#<7H6gK(B4ax< zqgDkehmW;G)n@2Zmlsox!yk1L$wr80yCYK*ILb34<_112jCx*|O}lb|CXe1-Y`)z{ ze?=I&YPqfQEe`vIy$z$fc@!^+%#w#sMEjEdchj8feS2BvfaOb@KPC5RO}b@mCSjO* zvhsE@LO%1|exS!*Y`O?3EENXc{R!eoYWnITJeaYhEFpe&S|F`_}?qU>E>h+4$$L$|A!)PT%$joXzbW2S-9^vDHitlp#PQnu?d2|{l)rZ3R*`5;|rJzqj7fxmgKTMR!X~Cm1sTrwkO5oKmt;WuG}ObB&$&`t9M@{M55_`UOFs@Uh-G6&T;`%r=_O#{&PHRb8%- z(|leO5#ygQC&mBVcIL!(OV0E)jE&+m7#pHu`jce*s&g&-J&e|d!NCW;?+L6f>F6~yDGWk_ID^RpA!;Aioh?Xr!=_aVwA3Iv8pe@n=aIr<<|}SDgA0i+B;oj^?M-bq zQbj6<*MgLTlH?8DzpNTT+i8-jGcHXNG+WdU03EME9*5iAA?0170y4QQoI@RGq+H4< z>MlfFCT?PjXlU8?3Q+!e{-)xm>r16QJE_%OyZ+X+uP9V@GuLAVmV+JcVK>>&LY~;R z!)S7ERDFD9{O}u*-tKOxh2FT6CCRz`>!7U{|HA^}7RkZ{;~rE-m9N0wk+;E5+?Ju= z>__$a2I7==1ZCs>Gm(tu0ZG6+U)OLZx?iby{Ot1g6SG_(j=f>8v(h{e>Bqss;N)MJ zY2_EdUEL=dZmY>AGJu*QJ#D>wm0h6-oI1gF`SJ@&%@j>1z>;^xWmk?NmELDR%EHx+{f~Aj{HmD5ptCLY-d_L zao?CfpQ`neXg7Pc0j@U_z9JK6JZ^C5Z7wZU6)vH}vaO?_ulkuY(kp@Tb0Nq-HQAM$ zQ|>_|+NESgu=>B2LS`&KO+*h4oy(^JuWG;(a0o@T9F!D(hO>kJ`8NTwr%wfN$MWoq z0Ng88KKVe`iTdGvQ5hiq*BWRbbGJBq%UoYF{Z>Misisvc*w{x~v(lg3MlAii=*Q3Q zn?DhV6%Lil+my+5Iji-*ZDI?o^u^(&6pJax31#frAq>w_(5~(BU_&vkoM|lu{N$_< z@-B*-OF^JEc%rwb+0G_oLEiPIBetDH{hin6Uq`i^1@b^^^>|sPs*1lmMs-JbQ=Nks zg-KQX(l_oZu~j3~6|>yRvzX}o6--xa zfKF-FAk%Vqq+WRf|5xICHeAOYdtr6ma*M+bFuYui@7wVj5w}&LK3G#DGih2wisE*k zCf`+5iLC=tFH3SXkvV;)9-sz?fA2FqU~P|n$4|mVqpZICH|uIRhSX@iX7WI4XaMk2r4IP?nEwjtO!IL( zYkpzD?vt+8*&^I$f*g<&N?@c49VGryhH>ue9{S7^a8ebzd4VQjxIpxZ7kb0#{n&o7f_D}SnnS#7#Z!Ha>@Go*&I96#CCh98H^dC!g1V9Qr z?k{xJl{*$tQ}x~^p59Y$RaF)Q@McSt-?@UK711!-F;T5Bx_Mp9=q=}EhD*IRL~|E! zbgJIUD#fT#S7~Xm;Y&Pn%T~{I37J}(o!~SciXb}^W1waDm|1k4xUH6QD@i75b<&oz zuFCDw=e^EUXj^rNO}C|$?<-!cdCl?p=LpkVB_falImnu;RH`&Ef^cf`aBWcy!e#&# z{Tlk%Oa&%Ud3&13L?r5rpzwpqrmgmthRsEd`_-J)BKXsG_z&y|#|Xd*g(H3Mhs2=2 zBjiS#&9nCD#hB3d6}pWlHQ|0n$n7YAiJm^-u@w1?S`6h^A*(olBdK?q-ED51kXjUkceINGA)^%j<*JG=k-jiHD-_tFX8XT~xV?X*d0 zD@i?~_ZW(}`FK$nj)f;cLaE~=RgGFOce5cF&A|?#f9<^UaAdw&EK{HO=4>5dfKh%m z;2XY=M`=qe6JEv7h_A*g#G%gpCRZ!jM-r2sl^SN(3muaGtYW6s`B5 z%M(oAsd;m|91)(8(r8Kgozg3*;?(l}9G||imIP?;cN&<>mvt<^{Dy`tau^ORW?Jx1 z;bb-HW~-s9G;XK8>?iOuKL~o%2nkF6_ZewF$d`*4{!X6nduIM<@r1Y+u{+w@M#=Ph z>3}6tgG9gSTxW{ar%I$M%VCcwPxo_TGYW{73H#s8wQ*|N7kJB5Ggx9+tX$rrAKq0{ zS_M7H*`tESBWPb+7xvxM;n#Qz#viY9K*05Z2!sY{UkEIiX-G#&pljxzpP2cYMnaAq z?o`>d_!|?bbeOy9hH(@%ZZs`pgTGsubYw?gaIlSUFxmp!Ee!7W4N zv`n0w1!XpAN($Jhh@T|RBwbs3c)Nm95s{vw)M+>S5YiN4TazWo(N8S|>xfP!h>Pax zt1XQL9mX_-FDu;Z!f${u)y(`BxIjv>-PJ^mimS0iA`M^L%jzZ6W5$#TBKKjlPj~@w zRuPTd$Y}7ec(1e7F#Yf;cF?!)QjmhDDbg3LH2G;Qi=HwjA~mmNTr4=WmgbW!3(Hje z)5aIS<1;!Pm6#~fk`xD}+WrN0$rDq|g-{$=7DMJl&HAW@$L+WAEuZ8YebqGIUm*W< zAxs>fjo0wSa%GN#W2~y2dtB(H#D%dX|DqqLW80A$H-FJ4Q_ufcCR7Dl6PLS3B6mUP zsxTjBR`?E$HOpUAG9b&(pQ>1Jcu8gac&=bnevEr)z{#N+Q>DPi)Ep+q5KXnTq@wlG zt$I}>amuz;h{!VMi9+4f_nhtZTrAlP1UJvjyMa^_=K^KxwV@MJ=XW_9g_>`?Zc+Vs zlzvhCMHGELl?CeV5u(SgyQtn%2Dz^OwJs12QiU?Q$oW~OS22Q%9k*l0HK_ArN+VeS z(@6o7-sd=Xi~@+pJ?yzU?S$%zC23)^r z?iYN#^(k4W2(<^ZEJ10@di(t6eG4_Op{QT6y>?3)ef|CeQ z>V574@<@jdUr64YQxILc?m5Wp@|a6|UcV^)097eeGySk(9?mKTeUrV=|83v=mvmq3 z#OF_MHvUq3&{~(>xz0=x2i$%>euw+JoGK*)gCZ}pNr7eRwMyXks@vbTQnjD^%^II@L z5r1fT-XaHjo$jiesJQjpQ_Gs;Fz(%UvyL^uDcz%Mia$$pZ7v~aSw?4nrgfLh9bYK8 z5idq~;veV#BX7mi21tu#%xuxCk z!uz{`z+}fEe|2?+RwA=98NG7W+|(ZaVmBhFbgLM9(vYR3vaU|3d^L1K`%Z_>lxP9b z``&0A8$?C$!d@Xu1M=f~Y?p0cUX6TfNs?`7{pC)4g}`!qRAH)iOsGnaVQYg@A&L}9 z4$6}WeP#gOKrX9@+ z7lZ4HEgL@a(LO(3xc2Y+fDSMuJTW~x0>w|zn|ox!b?`XtDI#MS_&W{geCCcMnF z$MmVf_6q&_L|?S^$r})?z~!Veb@K-@UZv3wg^M%l zDA$1B<9CfNkdQ+b0d9Q z)H5{m)dArIZHBkVd52I>KEzqmBXZj246xq2?Uc>>Dhk2k_8d-CNbZciJW^r#{m_+_ zKu>8Ke#&~F|6);~{`2{C@EUqHPl&+0FJ1v=P`2{J?Y~#+#|)-8cCy58p@vd==2itFMLkNzN)k} zz&*c=VSUS3dHdaOMvq!$djxANqoFDxi*B!4RWdfoO!t_x-;FXkVxM#==g<*EugHJ3 zt#e;&Ewfn_MYm0UP={0{Y*YyZJ!Up+=q$(829AfcKm5NHWL}6qy+Njd=tk@@KVxX8 zb6oE+nVHJ5W@MOh$hvtZ<*8!1&i#VReI5wLkDu&zwltQbjd^rv3b7!y;OHmY#qL?%P(M?FQKSGu6~YoT;QyZ%!60$(g_ zWX{coQ^S!uoNPj`rTNI1@HG|T(x>y`tqQ~Yk@f4Vrkqtpy50FOQEk}>2MC7}RgkYx zYIlLIF&G-6B>=uCX%+kgjk;owX9*L7>9aA5f|}76$@kJFGfN=&P=+l0mP0*{^*~Nd>*=T%l-NycX?1^` zM~}{K$0H?}i}~t7EJn?IP1RY2m#fRzFGob##&%GCD*gc;dPpVJA2}h;>U2(oL1|ui|B-6e z)p6>Q*lqJ$^WF0ZAGIss=>q7fqUV!$i=R$}XKa~7 zPJuN0j3BuO33Z+kBw~KPLQJTT6Xr1CF?vfmJ;2w@idK<+bdrRPmd%n&U99kc9_X8D zC;6hz7t?dYn8jcZKF+(64Cdz2<0!^h9hK~xWy0yBNTbyZ!hRwkvn6SdjF#BZ+SZnq z^G>iSDx9F)=;iLOX0BOLHyxSOA`g!7WY>--W5xf*0=OnhGihC(?GZX+v9NKhJv8kM z8}+3T4jyfh-ML$Nm}XkWyknnfF9@>Dtjr)M?)4>+qQ%auy%jMJoc8gn*iGx(JF8tk zKucMXQD!|=T57{iA!X=}4f7EMlB!koycAPyMchg^!veVn%iBDltG8zHeHIOShx{FcI29HHSsDy>S)#Pc*CKgHa7>F~_Fw=q`ghkaa*othXPkVTy{5+Ga%eDkHs6nO#%kY~sFXO_A0F3)7s!Mfy@1IoZ^MP6ROb)!_$a z<#Gsu;3f-H|8xkHW=-mPaIR<|1R+$S_Ry5i4m`qZX*E9BqXQg*o&9F)NnMfFqzCsa z7hR=JQx%BijG~kQWN>8PP9|1t$o>R>(tF$e_Wc)GslDVxwm6EE%=eJVjK%wd7e-KX z1hg!MaohCC3>sz0T+5_84h zdzky^6w6W(rqUo;!iL(E<(}12Aq4zfecxb#mEKmfRj~mF%T4JjnFZvn@z%`+w_L&| zppf2M0!5wgipXwMqxR(BOwFgFOySEhExi3IK84{?;aR=N3C{L7IasX4>ZJ_#E?JWV z*z~Gb2zA2CCkiAW=mPB836588GYzCe8Qt1J7r2;kRiQByZuiN=*r>ODmKYA7>V+nV zgxQ`13A(r=*BzT)G3D7m3E;x#cg(wbeN;y}CZcatxtZi6;s^L0;Y$T+H$FBCKMN1n zKKaFPVJNuSOx!Ty#O={{Xesp*PPWR;G6=4i4w%K;tz29DCE!r8_AZ9QwNE|Q@&z_} zfZWbHW@E_nJ>@Ts{v&1yirg%aOfxJtHn%jUg|Z(fC=oGFK9XnDQYA;r6|zY2Ix zom&|O-issUrnQktuAH1~i*0!7g3i_dvM|<|_c7VE6f0E;E9?q})E7q)3bF<;p zNvQd4F0$`O4HjxDWp2%db@)u%%cT!tO)-EonV%qG!1WumGVm!M=c~}m7sm%@FA6@% z-|u{Ggs5xLOUQID{B}~;sIi3w78OgtJBO__ctrG`4ms4Z#|8S%l8Xv50T2OsRX&!% zKJCRC`Lo&Nlp~9Kjb8)Vp^xtU6+-<7bt>2!svMr>H$t)XZ_c`9pg<}-rj@w3XdLv5 z2BLqdQ|xQhvrCoJGF2F9uRwj8U~NU!Ztsd>!xMcn8jN3?gS+ax zft4UM=fmb!;~YZ{5Q0FWZAs$UYHRMa(ow$IQ?`5op26#QQAo|y%*Xn?V0i*inb{?K z)+s9@TS;y|e)?n#J`je?@4x(b@w&!rU1g+OAAbYZ)*6@9s3eQ#03&i&1dx}AQUpkf zQl_WP$Nn;cmc0>&I7)$n3RQ-0EY-RJC0XDo$2O9@%SL+%fukyzkO7KgAhQvUo)Qvy ziT0W}H0r@M=k(@HUSWEb0u_iuv2;eOy+(IWi=gmFt$p>>1Tv7X;>3k2Fz#ntxLv9# z2HXYfNxRV3z}2BnWMO`K)*xz-J?9{Y7tKsMh1%#aO+JhePtHXJDhXemnk&ZuZ{2Mk zh9owJ=3QYaS}MG9=$xJN5-zAK^~ib2a~uTMTSWd)UFBEXx)#es0aXH>8HrS=oV`N# z@#RyhHvjAF(p{Ne9=k5|S4?wrxyn=*nW7$ipS31CffRvB!_6nCW&Kk=33?0zp5f^{ zW}H&}UL=!qV1*mauHH+to6A!*vE=aG4|#nbMZ@{wSHl*}`K3(vVz)bWY~_FPcZ-;=0vCI;(IsIy}QB&vHa4 zlo}OoXofdWQ1E$OT+desBtl86+xg7clE*Qddr(>MHq!B6Xd6NU!M27F|0vOAACpna zM$w0b{OmFrz;|lx410C+7_Q3CHrdsmAT4|4mkt>hajnsbQh1(e<@KON03^h*y=c<# zY~d3^P9Z+MW&=P|>)0s#Vxt+Y^h2wRBx)1;6f2uvi5(i2PbJg3FH3Jq=jy0kgp9>- z5IviH?v(iS`(7~1N}bX#gGP(dRsrGyZ`ZnCc0WFHYH#(qP~YBd)%cf)Ec)y(VT#`t z$f4};v?u38#-AdUtTmy+0CAb&pEazGt9_GNft)!#4 zZTo~V%F7nEMh+KK`MFc#`(OhMN%Fl z;uKya8uvF<$S(YRA&xAbg$-k=*MQe8s~J4Zrob8$zP%T>C#`-ZwRo^&&Hz@Ks>%&Y z8CSfA@t%=C(iZ<*y4|r^d2SaarrWXG!G5^jSc6-#ym6= z??gss2 z?1y9+K{E1=yH0+;X0)*&@74p~0V?nn1}F@zy~Wy6Y2s6^xd<1_Oze?m=e*-5w>$bu zi6sGv1PK1g!*D}CXkbd719Y4VZgwx2Qp;`h_5HojF-@Lp;wd4P&D9jpd}m6DX#4&T z{S=oSD+-ICOa0lXhjY6xJ&)dy9}<>HHBnOFrHGv|6mj&zhD(Wp(#-Yz@PKEbkNhCe zXxC3n9ct&agR9i;-9jVU3u_#o#wKcu5~t3jswiYV;Ry##cwJVu&Phi5XH&7>;_{#C zhMhl#8r*az{!t9mTu42x@0KN^b>!`&Pu@Q<@0{a0F3qn_(TxDhk*(|td)#^--$~gb1UC)6>OTdCqwikcNC64juZRpYvFVCAoH%OPf>tgBZRKvxCK)#W zw_;5oG5z;E{A&st#56Q>KY~?0Z1$t}Gu4=DwF8x%8JN$u|EZ8{^J&BVf5puHFVrsn zS&t|GDIE9zj-fk8bDhk1czE(Og1gqznmzG?!+s-w|9(9K3SX-gGukI-M7Fh<1B!C$ zHfGJzb;|TVxwu^Py&*$IK~1>5=-$>lc3=4Nr6VHVPliFQSQC3Lv$I&MHcvi%_|G^` zaDSJKE?<|gFS(zgrP`H`A#x2vzN;d&edg*#lx9D~CSHnLa4MYd< zS2lLWvc0YjplQmQx?+!cxw*c_?Z`4tjrJ#`_y1I;J_*DCKKOx)>!z*!*~RuqDi0+q zYbZs_-RS_((1?io?m05@#J~vuEh{6V`NsFiho`=~c!>m4#XP=i-?o&AgoKdL@h5Yg z;-jM0U;wD+a%<_ZCAGPsrKKi_++)9(LnlQCXqP8X0{R-tjkbq9oVHzH;{mvC^%V?*7ny4mZhrly9TjxN_i*@@+n zR-(1#p4;VcQ115T#^qqf0$yc-67WTrUe##%^y-R)(Y{Sy;J(YZ41heWCRUy}YJKGY z_)+GJ4$BNr!1oSE&%55B)AQeHnyfIDBOL_b=<>SntStLI7UOxG2UDhJ_|bi&Yq`E- zVQ+{`Non%!gny@1OY^zZkZsC-idAfH?|i);Auz00m!U#q5ndXBfyiv0B|efS&wulw zaV9vLQnge!H6fwSd3T(f#4MX2ncWs&z~HWOgf}`Za(Mj&7|Nnteej<{SoP|B#auW~ zCXv~D#vaCH*L32!0WE~b>7Df^*{OO9V_H4x4xlfsZtjYXeLF6*Cm_)B#3R7r@VY#( z4E~n4?Dg1uvfjgTrKGFN@AvSfsfiaBab0!A<-K#<_VA385WP9)xHklw)_g5L-4}j; zwLE)kqMn(VdC--{*BBigWt%In{ckJ)v56@FJLcu#aeCv;;>1EiLgM-$@MsNbAyQVaG?g_%AXJ<#tsFyhyd31Z zB#TpxJ1^Dq7vS-m$df$)fVF^G_yI^MwYH1Klr6Upw`AfGBHF>B-|M{3cNG8K9dbYq z1Zvm0pG^M3oO4o|n7~(W$;naQuFB8H;fYL1a5e)`gMrN_DqH8DlGN5t!Miv!sjRGI zV_{)tu8P08S}tB)B@z!Ov@kVgw>{v5XD61Im(#Z1Ujisv|L6$80RW{Rt={1tp6>V1 z&0E&gr0v=K{HoJ|5K-qmOUB*-CDGxZE$x z?CcN{=K1Ez$j*LpaiLRh*d2<;LN(t0@8&*v#SDKD@}n?}?0k1#oTbw5(Rc7`y~qAL z9wxtbZ`Y2Q8FzTq?%cpJR7qLM@8M>yob8=+a?^jgr;Mdu5quw0J=+MwmiqQ0xqwVz9>7%(;YSPlEFcaVF zlU`e$#_?JPord#;dM6MFBq}O;pylA;@PDlXM!2|wl+<4BvhRT0NCJ})w6wM5d|WzG zjg0!Rjn{u>W~O$@H`&M4T2QcUhbcQiXw@v;C$D*MPTYP*v-9hhG9`&#*-G`a-qp#8gQH^(S9dpg5C#eS^ale8W78ka z`(*UV-yIGS^vKA!-Wj-widtU%Xg5?N4QoCza*-9MD+e+m}S5sfj+5mpqpIM!-DCV4btCjf9!32Gn3M*EY`mbA_@gGX4Zxj?Cb^^)qo(H z<0O=}YIOWR+gg-0EF!DJh=Mu=_tz2=l2}GP2R|0&j9b=4}l zgb}Vvffa&%|0wwLIaRuAgUCT9Ze?d>x2g2|JOY7B6zBiPWNox0;V20%}1*x7+@_S_aX0o@i} zdV0CD3P9+PiHE;H+g;f>P|?tMLx9t2(Afk0i!p-R%j-5Ef&rJ=_U{6HCy>r}rtXVtmvVw_=4sAXW)e#z%(5zx{g(BefW05%Ko!Q9j~ zHn_Xj5fI>+Y#UGD6Q&Z%hJiThjZIC)N`d19+uijzowPu)nE_|N7s_O05YVfn2_YF{ zaB*_Voxw!>%P}-J@jhx-22ubZ zgb#cBr2-Gf!jxu|o*K%^P7fV79Lw5yL>wOQ-TdBgJR1v*#-aN9`p4V*E5Ii!XAqCT zKUt_88S6^-E0&d)_uAZyM?`qqoWlTEtWdzxBA9SCAnKe62Jrm>v$DeNsHNU%OJV2p z7gWGrbrBm%V2d6cZPKncM9khpI-Sbw3X^ zSJU+f$m4i88&T8q?Jihhu@o0MEB?3ZcP@ zZqGdK!#I2&PQ=;4LFfeSNX%4Hrw_MBfb%5!Q57vhYK%O@XVkNb!)tF6jJh>qBp^Zk z*h^w{=%I!7_hD_zMwVA((tlU$Wsmg^8vr%&nysi6xILdpWFa{_IT`!dxqc!O8a8VI z8^#Icc5RcZYpCDReq8I8=Wo$}s^w&g!_LA&#Nm1X946&$u8(o5@6vrMQo?Lshsd5E zLT>?aF#55~`BxNIrCIq{*g_Mp7~kdgerYqi`z#uI{ zIpJx1Ui1k9=@cKJP=@9^sn&;Q@AyuP4Gi87;jvrK#84|&;kY`uDpJMRH8)#NrPKpf zHzkkL%xGq_*M*@Po7*8_l7yTb9-ryK&X^H}Y+6)&x;XU0#IAKH+%@wJ7FL~aXAkv6 zUi0meS7Kt~!C+=*AhYZ?OoyPgZ}`_(S}9&>j?Zm_yyCqHv{X0{ZG@qqdBA9Rq5k|7 z;ER4UUWiM^M^Y`th5ZS#Riw$7jI-` zl32mQ5-()?j4Oce7@o#Z1H3VD#bI=}B|Vt(yklTx@gz?7oza!|oq=JvC#STfqvC)} zi1)i=Y8(Vmfy))6_NPk)9y?G`arhi|Mhz~N|2~ez62_KRyM#GsbdOKv-EdDRCKeVt zdXUjQ!|NFgvX@=Xi86j~MQs5tqcklD104lZCXMr?FOm#^ba{CCR0qnD1NiL&=s`I?q z2llru41qN5+I;C%k{8Mv;8lVHro!Rcl1&LzIc zxVW0Vc)exMeOclNoVVkjZjllT3ig+Mu83rFKIG5L&GDU`D*LOdSpXDDjhNfn{Q7t`EsYppvl5DI6XUa&6cz0*ENzL?QxKdO z8yh=3v~6i=`CFX|?w4ClFBYDiN4JhZ9;Ysv(;2mipN%fOUSZT1`dn62q@Ahq+j&t5 zFf|)axxwX0=-yGx28xdCdkBIT6}Js&eu>`R~MIVgDKOB&TK6-G)zna z%01N;PyyGoU4+h7z=wj8Bgmq`X?vLMxI~*Cpr!yqC_8Tm*S3%BY)ni{O}CDYdRqqg z!D^U3oNffwm@J4^ljM~ni$dR zOgfQ2%z~_9;e=y_Y77v5?K*pdvp71bTxKdN^PbRN;L;0TJVO@0tuz}R^L91BF^dn5 zrhvoYT?-A>4(oYMciu)uMwZFE_A5`YnZF`@l}qEUx0+4^+>d9==9}-fh}p*`d$K$G zYS-l+`myo3ZZT*8W}kgV3ivS!OXHa)%;v#yIxzkl$A<#si2}z8TvckRROqnAnVkOgy?piIU2QW`k|Ex^DcrrI^%otD55?c7YfkqoO8V2>FoI2;kjN z^|Tj|5hX3L&QUFzd$=~p!OhH;gH{J1< zmzTmw80ariTHd~S|Be6vfua>NJkj%e1dhzbJ;rieTnsUnr}NIw_syPHzIP`9-k<&7 zp`)VmIcYn2DfM$EPn>#^m2WcZv#&}{nXdA5Tw9@2rH9Y0&WA8YSR zhsY@;-fCsNn&NFz+3YrQSn11kacdpWlsEBBKAeXysB?Cfi;gZVbr-k};i-~NtQgPV+uFJ<3axFa5>!fn z{21T2xPl@WwACNq=Ru<^w^~v-9o7J2{^Iz2q0IN|Fyh;{Z)cta0Sp>*>!CGQV4_Tx z_e`HHY&!$dw5rVC%YL9Fw}Wq|C(I;NoStr{`;?fC5GR?e8Lr!S%`oqM5@fa5-`ObO zLlPGg%gcdCSsROFCQ_zpYCrzyml{B@UEa%*Jf3IJ`4ds8PGm77cxB7O-3{>wJgy$=>k zh(uX`TM4nT-NUb5z0ePWH32T#ybS;+nEvuyZSh0JR;j>9T5)qTDHWqV;GBd);=iew zVTA8Od83`dq8Eunw!_5U|Gc|-+TC<8$YAeM`)8W@B0WJLeDrw8rPK~B$EdX+zKN%Z& zY^pG3QgRDHDTKArSNtWt{Eonm2kkVv5Ses&y|C{od6I?YeypnvWuu^|0i>uQisB>T zvwH6_|8A|>8?m_Ici|7bp9?-RL}n2j40eQCnX;!1HjkPKdk(U=9bgnC$A_R~ zCZ@#(=S0BX^up){;OLx}_}v~BZUBTrLDT~)?t)l|Nkr|@{$J~Vk$K>#aULkWcK!4^eI1hANqLYHr<4JBf!k>mY4Df>_fIKbpk=t19k=-vqe#J7uUb`}uXp?fd=t1(!sYAflesWXL4 z<>YK#s+}hb6f5TW+QB*s+uz-XvIaI7XhN9jt-W=Xk|s?0rw;~!JB6aV(M6nZfk`0W z(w9I1p*j1=2m?NYBG?#lv~Z0j%F`ALcrH-mKmbY;IT&ypJ=++w`&Dr7lK{}5YuUiT)^a;NUJv;O2^VN zP`fzk9f+s%N@iaH?6^tYtHGo82ExV#u1)d{zPX=2DnlpFOtM?xxkxc8e|t^f#cE+d=m zT27|+psjcW$(&p~d}o6bp`HrkK+GLO$!+9!D$@Uvljf}+U?LsNl;hCr7C|6MCo@J& zOm02-ey72dH2t(hgfQ@V-@Ad4bb;TFBA3&)_3Wvgxj7Zvwa>#1j>?=_Qb|Ko+f0A# z04CLjr}z|R;%u(oGA;EGd%0uf*`Y>4Nkb{`>fKzLlW(@8jf+X9bRU&Q*k0V_c#1l3 zyEgR9fj3M}q=jV1N^$yxCZN;4lRaQJ<#oF3Dp{AXrXe+2;?g$RPYd83k;OJ#R zG8P^r;`hHrZq)cVxpW-=Okn;X1Ulrw*l-^V5N}|5yv68Aco*9f$4{OiwV;_^3AP{mb?B! zhSs~NRzH|Mc1*Xj^A=!@S*|DxJXZA2bQ#b5d~aQ($wPj$J6COW9>&mojle^X6u{2^ zxOPSzO*y^W<#2Nv3mi-rfF4v>-Q2?AC8B3kRP>D58Z+cp*|PL0)Ak3?_Y7%ZI= zC`tI92849P02hqwVcrNH7tDVy8~;lWj^W-=LDl@%=3AahD!S7_k~1A4F{NuV$6lUi z@z!cek=pMC&Zawtqg!7QRfi7Xkn3uz#TDX99xpWHrc(M6^R8X&RotBy@*s+Bq1l1L zaz0*O%RftB($G;%@Y%OFc|)9eDzQ4lW60YvwXwED&ybHNM}uRA!{JtYUB@ZQsY>bP zIh%;}*P{!RArxqHoFFOmLd*E(;^;U$I9OCrFnZ(C)6;{sG5)Ii z?~GJN7=CA+cA5x)okYl}-)5HX%M4^^cak~4Pl4nVWcU>D2Xk}Df&8ThBO$#W_$OQ0 zlWKC5?k%<`p4x9(^#O^R_4zvUnMtl_Ft)2Joq%24Tn;GoX63?GP2uRtOj`DH-{r(gG0AS$ofj@r$z2cnzeex6k zvvNW1Z>UrMjRmv||8cT`=l{=u{dtNjqIN3Xf1Dhg7W3sKTF@JrHIQmT~vv0Ux zMq1W%8#ySDfFOBP#6;9X$y)u{I5a6-dlEBh)<^Z8;9{{W# zpHQ-xo1Y$;oIKczmHv~ZXv+>TGqfBQ+-IsSgA`F29Zpvzo(T!@Y;A9DZ5dZO0rbY9 zcmf)vk(}IISGxjzgM+;Mm+yws0RZ6WO4Nv6fWcw1TKotge~6962I{~vC3v?_DCcXh zXzA!)zChWXtS3NZ%Tb~hkLD*3cDgN}wt_cR$g9TVux$xB; zz{K{LrBmdwySP*Q@xYGKdo~zNewB)e1fp_a>ColEg=$Nfeo4NJRHNsA*qG>{pa39Fy^JR%a)GYDf!t>8Vm2-6Xz20v%!SRD${$`r z+8;$Z%rz;Z@2gHxVQ$THHwj6JW8cbyHBvF)h|j69P?Gv2e9_u(&|xYqQ*|twz>Qv=@1Y=sp6JjU9pn`j(bbZ%~G$VRCp~9E_vc{mF`GzuF7W z+DrI6D^W@K>f#Xyv5@O|I&xKL4vT1-lySIU5vJt-V_CzbJ%mNq$;p$T%|-s<}(%7ZVo|MJz#bw>}BfE3-iIWFLS zb#;qW9xa80bGu%ztp7+qTy$##V~YQ&lk*oxM<5KOsS{QQC_;ff&9R`QjPKpzm2+9i z%0jqY6uxzv-bEFBi@6RpvKJ%}$_$d6Fb!}ya3tGAEI);sSp2r10cF{xo%{Xm!E7{uuP0Au>u{sW}DlagiEbveczd!aam38{~U`z z#HZ+A0sPauFG6xeJcCQIKVOpoVPX8q_Xm?Fov(0Xw8o|}V9RX!0KE1(<@DqvK-_og zsbXxzUw3{phfdUsPLgr2tF3ZA($gvymNp8u!Uzz0gX2{A@K;4VeTvP|zJNjhxt`yh zswSPmKPU11pR(^TUNd`kq^i_m~0rT#=G+`s>=H8FwG zVxV?olp+R;V+6BupkMmW+y0Nl^#96N{gwaUS#WomB7^l4cQFc6(#Y=vn@pqlSSTLV zB1#$>B|ireZv*aU_L58l{x%x~X@!7{rbE3qDs6Iq2(v}C2v~)A6dx$#iXW)1s-UL- zm?6bH;XD&z)Bg2H{O<=g*QpcjR!~fC&5d=@uqfB27cZ{ER$QB)r=q1Rud3NROdISl?V4X*v1bzWMtjnnb|ak)nDF zTtTF{R{=uwZ-WykI()6I4(=4yB#dw^@N&%&Jl{mj(DvhVZX1Nf@~ zn)vULp8P+Rl@gl(R3QLa5eM^I7MtXVh>_K=xBnL6+y?xyWPwp|d7pDWU>?8@5S~4| zzT?3da=5a`d10xCj~ASpn#yJuEVA}u~Bg37|Ig@$s20W#r&6GIQi4 zgzMWY{LDN1ZVEbYPI5sJC54lsO8J35Xxv9hpK*4E}jYpyP9Dyj@MJI^hY zfdpsu_UHguIgb$oHP_zU9NDUnXI|gT%*xh4&Vpd&h@t7;SQ!YM4u$^}qg_+O{%T=r z@89KnL5z93lg#cickN(Q2%!N8dv*QphrahoB;8!4TbYg|#-~IHO{^NMj__R#R_(Hw zdmhY;0dW@@PqDy&`tI;l9(QSE+-g>qmT*`|DG^cXDe5UI>JKc(o7@4lsbW3( z>U{?O$I!JmK*V==SnjCl>H(~rucM=*_V_SgvgifGl`f8^V17j!EQVdjK!WZ)8Oub+ zg7@^{ViJ^_o4Z8&giZGQx2&e7yKOypfUL)H=V$v@B(x~0+;>3G`|waag824$eREKl z)!?qqEKQf&_pUBiUO-tvLBa{h3;SI^@Pr(xNCM!}hsK&SR;5iq1l>P0^p&06(FFnf z!`%Q)(hZQ)RaH^__8f5l+fnKm)cR0kGSC`LDVx>S+j!*D=6l?UvBc+adYCAf!1u=>G_~n4Es? z9lfT*_{_#-g+EZwUK0s8Fw@fhfV8XN)uY9=(N62*@s!)HPfQPb70 zyP|>E7h^4>+4A1&x2Iie`BbVGKu&YS{eUT{((dtd8lPvGS7Hqd73cLzyYQ<5zKwe- z)*5DJC;h)~&`PGD|N2<1D~#LKaG+HSQOMxdRTm!jYX3Dp4#|k?NdY+0W~MAMb!64P z$J}B&S5vq*e3gLxK3jpx9NrOt%EaVw&;j6e!*{p!WMpNVdHDut`xh51?IbeEfx?Sn zxuECBxjA`hJZ@=uxom6%9JYqrT3Q;n@N4ZR=U{$mKO6?_y%{jst*Vf>khV6j?8e4M zPgj@g-a@3ucNA3A_>UkL>&*UR27!A)Kh{qS@%;C%n!BsY7MhxXT7e=+MF^<^0>2(< zr1=^TrFKrt9_J?88|Hauj%U9^pms~+^*M=&8Xg+;TP7MBcs%W!j*V`xtVBKapXmuP z#-^5-yA?+LJ!b2 z|5~GDvop!bM@2+{_QWjDmW6~k0(E7)+E^y;TeI7K*S6$5x-X$2=^k5Lm+V1tVz-+> z#OwtsOi(eiVw@SatgEQlE+_E;eu^@I}JSQ)XnEH;MF=VOV~;3 zjX_~7m1n=?TYkQiRHP&ys&x%%hfD-`pHaU=JJ}ouZ?nEldp!PmfoHjSOv1Zod2<+`VN`9PJvd9Uwpw zG`MSUcXtc!?!ny$hY&2dySqbhhv4q+E`z(v>G$1xSDl|<)%o{TQK?E*GBb2fcR$a% z*SZ$qaITit3;7-1^7VFY7#(nbI)EJRn($pG!AbhQuTNnUfT5g5Fz)S*;@ zhKqga#!Fi5wjVy=>~nWCNBN~nCWCozqeA=i;yYc3}&Xm=}STvxqDeO4tKrhj2+cpJ$>1rL`NlJGa|PQPHmLZ5goh zu(q2DYS*4igxcPuysNK*-}m;i?!oPYy~BL_4^gSE?vQzUPQDZJEzzj1)2+wwa1x!z z&-{76C9*EkRP=& z8Eu?p00w_RsG=*Kof<`_QNKH!x49q3_kDTm1k6v>($r|7uIrBmYc02E4NVSw9(#=& zicP{BmOvl&-EM3V;8+57`2so}yubj-CSLD$<()e)_yKO;Jy%{rXFLBStRwLMR@KL0b$+>v`t^l^D^c9B<2G`8$K zJ`~7qX=AiJzZ%8$oT$*Bu3WLEmse0tZ9fm|ki?vyl0X@MHQA`7Xtg)A6rJsmXU@B4 z`Oh_k_J1$)Mhkr-tDWrW>8Z_kyLIRn78jd*`WCyVfm#gF>*?8E=1voqN(#e5#TXi_vc2k?G;JzKUIYz&PoAUrqQda5*t%Bmk({ zGnq>r3y@Ac=fL;<3(i%IdXj}|LH#8fi|0A1KqSLh$St`3Z-+NSb&CJwVhtnR)k_N* zgn!n-W#7WR_rDgmpE)@--r|-dP!+I^#V-_;XkRkM-j=5jl=Kv*+O-!x?+oa+xlI8B z!EfIl^7gV0wTpDruD7nD7}7fxRCHD=v=^El9;A~Pj7xFim6AwrY(Uz)s-@{zIrn{4rKUQqkT!SI}enjD)I$3p~xR3 zMTJz}{7FExG!yc7hpbCoMGXJFL4Rm0{;R9!b6XD#RhSqA-WM-XqZqudW~tgmRP;Jf znC#wmFd6iR0Rn9G_6nw+*Jt7o_T0k4{q}nSUdIzGC?sjn$>km2{#9Qg>*GDZF)jNz0m+Y%rc6F%Pn9jGuhmdYJQ0-sUL_wxO2kNGm-4?iW>P`tOxe2XO7- z6NKp*=tntN8h0-r@DOdc?AYQT>flDl=zxU`T4>=$?yuKH_SK~*==)m2e?LU_+!h8p zl=$4A?Oebgp&T<9Ke7YtTquPV=_=@{N7X6OM!maytl`d1B=)?|{;{r|>pyeS|{iQ?2$j17Us%MS%p=Cp9; z1JMQPN6AKZ**oRWoDyyt6ac!pgqx&Ab$=B8A*>^)@QJQ@XG0d)?whu>G`pTo9bEXW z0qQhVaQL6Pnt57Z`;E$)X%q>d!pr+IhR@W0~Orzi5FMu;Ut^za>bu;z* z*Ve`v=273w{ZEEux?tu1`L#>xI<#%^-F;(d1ZJD4ns;c&i| zA;tYQgNyVwY>!PKR;QiRH(#ph>^^U+PCn39s z?kTs_gqejYbXn!xCbJkS0ghk{dKwy&**zv$i38w}%;^iX8dh`URY{0V0-MPZArXlT z9w%lNz63q))+U$px%FJ*S`O;>PF7-KT0KO{5uj!#4}(B+;GaJJ9RH0crm;ikp$vdwa+-$rmp z`W7J_t$?gARoJ>yNTdYbmu{PR=0|Fyj}WS3ATI?A3-Os+rU$?BIq$UQL($l$Pe%l_GxHoN!>3ZrvM!<4Xi9g6|U6Z7r04CNs-K~0s%#{G2Pwmqp#@h zB{emUPv!3MpH8%I!YK1*X~Ab(d;4cO?qzRLdyejLMPu;CvuynIcn8Az*lZi;qXErqa|?8!uLlHBC*^wk#Zw_Zb~r3{ZsTY`Tf%FK`d* zF{EtS+TCS#TF)hDf3m1b)Gxz5>XU)*sI+r{2%aq?P(% z*)+&At1WjYJ@)a(Z%>4{%IbrA@dIn29X=CC^Y7JYfjONUK2PjCH2!)@!hkXKXYP*m zNxI@d!hn2ghwp@(EX7xY3_kbt$Y>Z0O-;?-xr7Xl zaTV2Brj-+<0{3;t$VAeBb3P6yp}c2o0$lpP$lZ7=eGMkJR$i5EF;d1$LS;DYMCr7y z@a7nCDH#>QGquv9@Ye;*4=Ft*idIi(Q{Bxs&M1;P1m{=+g(Y*|RRt;y-d1i3YJs%Rqr=?{{J;TZEn(G18#*iW4NvEW0Fg`40X2xy`m8w!| z2Ii$I#IhKr*Ec+HiF$HvAcE-kI%pDP`x0;U3Pv3a<=9x4GKI}s=8 zFreF2TseJz+8yR>|L9DyqT|{EA z<@?#&8c$GEW^_7Q72nL#QUVAYcP$$fep5Fqd;F$Ci3Y5Ou*faBih>RS6h|B~w&94m{`JY#WE(%@pgxYrNdSnUEsyp+l8+;4}t!jRrvOUe2>Z3N6W2-bg2o(hmdruz&=UN4Z42MDO)M(<~* zC)!?qfBWVlG76=Pp!0^mR7vQb0>!m?aba1$3Wh>LYNkP^s)dE7Cs(CBhjo^h(pkR1 z4(CfixAH)gaXuS+scbRT+iXale^5B5hq=C{JJk%N=nn@WzxCv>>W~nBCmR9robTnY zYOjRSWwC1N$Jz;1`b5x0D~}I2*l8-N?03SqgiKyHoCU&?s5}j?ak0q?z7W*a_=~l1 z7}Cq9iDx&K=U~QqquTQ@#5LR(4_%fNRX) zCtz$L?0iLAE|K;m?2OcH0qXiHbla%~7=pbQmgf@()X_B`UwAm+4r$sC+w56YHHyZ& za<+tXvYU$C78=IxU#7nr^Tik;cT7{NVX zzZ}7E;?Tc9nFE&HVoLLj#Mt=!Bb0t@PGgOGy;n+46I_I0Dd{6v+mZ-A0geF%#z79E zi~ig1r;R8(MpRc??=){ZuVE!2U?V4jg&SM*w%#Uu34!0ii2$+!bco-szsT z@z3PPHq;;IFS+2_{f&CVTOZnrQtA85RL<&x1XWMM_kUJy4S5fXX)7FdIyX1hM*Z^B z?jf%X&!+=+H0S6yIaUpgQ5yk6QDE)AV>5A6M?;z$z?2G;-o5fY+c1?Y(7kyJzZEAW zqV$_;=SvfidpasH)2C;!ic!D;!mb}xdQ?iEiV5=sER*!=Zrn?AERG@$CelkcaP{@U zfm1G9=B0(%CmWqKxm^{YOm>2}xLT>PP1H=eXFffFNalw6 zemDTvj@4HnEJU0j(0Y5aHuyn8S^73SGwzpyMl=aqk9b60VRm`A_-iig6v{0e2hzk< zO-+r*UP}<%`v)8><5`7>EY{QNrKq&zR3&~ZV`Cjf#mb>BcixVS48CUy3|tF-6z^9p zw<22*2ytrRZ1`udxOnQ`k^y5`dHy$Ie)fG+R`jpS%TBeFJWkGzz#8;7;NCQ`M=ct2 zb_Usu!XCeCw4|%3sYGTlj!h3Q4-cE3^jhF|^H_QGD~)`Z%XPJ0+TFoiY_@WRNwuAb z^c8cx&m-Q)*uRUE1O8P6wg4LwaV3$y-FH3eiuDF}|A>|}nB)HXL7Wuln*b_jLl!0` zuz+z1AHf_i{6?msp#|Iqo#q%QGct5nJ#O(Q+sz2aY7Oev zT(=0{tS0??6!2FYt+wN_8QNN8N>mb)l593=6t5HOBgWz;+Ir>A*XmENPI9`=550aRPax`Sr-NaI~j2Hz+Wc?mJrxwfyM3&+08g>TdvS#9|FKOcafuiaLxam(^=Yjq803uI)#VA65&&lJ^=q? ziL@PaDX6w>40nDTf&)Og(Xf!7_Qv?{kjoYvr7M+Wr^=}8W(;VT(qs3iqB;+~?O!7; zr645f9qDkMA=NW(ghn0-*dLA^Qr2D^mE1zd`t=OTI7JJyo2H>PkGp+)PUr80e6x#b z`Db}5RoD5Gi}f}mxdpbPB2zlIa8hPcJtrrld9e3ceBNzunEyE|oOh9*yz9w<;zf6^ z`;99ZVwup8#Dqk~cU2%F8((`2*TV6c4V!B3ONPIR@CqQtkJ~3RuckwOxcHvEuOlr@ zLp{ejVuJscc9v)TvTZd2I$y+bx?V@xv4W>gl_HzFSIiVG>4-_KzSuzdzXr61i`4Je zJ$g0rE4COBgeN%5zcFySF+P0I3RKFWq^33aKp?0*(hp3l;giy061!RBp6OF_RW`nl zX*>i=pm+cXAlQ?xf5ibRx3Vx`dq4BPi|GdY~{luiW zp`Q@IL|0)e{y#$5hsnQm)c<|U|A#cco6JdG&+6}L_Px|Fi(jOhEI%NE-4DO9NtJ|C zl_@2vF$M00Dt-RXTSm2+R)uGqLfk_@L`sNy!d6CnE>g**rBo;1qZ-yae<>=DU}j@s zqWBw_q+cmBsQ6#4>(DZ1_>(2ZqzWME@Ipj^kH$vmR5Rt{S!_OtX-JpF!;AQaSCKX* zF`Rq-(wSdP>)&(i6DKFB{+jiE5owqrqefQ}ucAtgHmLpY(a>sOzOuK(xS#|QyMGje zrU$ZosT9R2d~wmzDhBBdpPnw|dk0gQC~^;jnhWZ6$jizp)hP+|5C`_I0)%s#16?d6 ziGTb%QobO(XQUyeQ>pza0YA|@n+_BL+Zw8BD)z5d5%9MSqPeex+x{svkuhwp$)jMX z5FBDfB{f2QQYR@Vu1cOgV){N4OoT^jE&P{Vwg;C4t>0z^_m?6EttBxZbl#rlmOq@tC`fjP@F9q zhu2%P*(0QorDbV{Nh*!avH8K?T%|6LrmQRg)iFwRb#XYIZO#j+cF@zyyz~0f34%v* z1vw6nkDGq@fD>WX&2i7VhkI=)WtE)x*O1n0w2wXaD3^RUw~&Bb{7#(BM2RfbMKCH@ z2iqbfRqUFXiH(Ma>PPl15rE4g`1W^d-A|j!q$YIb5L_X|6%+H*$YPYL)I3v`jjho- z=Md(frO8KL0{Id|vqK$#o)8)#^Gy|f)Hk^~Woa0lCI|sHHB0|ue8tYw%}uAx4VY|1 zp3`gZ6Jq_-d^;8^0KkD3r}6+Z;F9p|ba0hb68(lx>-55a*>fbm%lgw(Srw30_k0}Q zySZ`R_d~$rwBHN0YjHi71Gl-4bauYBlqwfR0)f8ai3z*WfsFL@7cXyUVIfJ$&oi8W zEw(#XEDZ3y+ODz@|dW;|@bq`e+M-Eh?oW))HBKa$m`BULBbh#PF~!cR|K&A)YQ`U0 z#_9K%+G2`>4AAbjdHqP|41Doz*L>cM2wTO zv+?Ast2!2i2?gk~@)^AD+r6Jt$y%MyWLTho?Q=yhe?*jcMJlqeV_W-^BXYO_G);Hh zT+sk3Cz?E$$Bo91A3sP1H= zkZb&h8o=cQdJT#|pzUEj23b~gxK{>gX)k`6sD^xy$7Z#k1imwXQy&!#ua_5+Q|rB< z_vp5K$tpM4NZvCh;d`vMi7^ET`|yOTE5mzabOuno6N}=*$^#(6UPs$T(NMVR-;x_y zfTBr3b7EsHnfpxd0r`xsooiB3`sq&AwFxio_t7lOHxl zMSL66!C${zp}YFZp2pH;AuE4ByDe!&4XwMBFGq9SYwHi$C(5PK~EE z@G@}lkn-8wJPi4~`JH%~nJr*nV<-*ouP()*aila}P+4ltJhuB0<8!+nPc=)so~BgV zp2g#wdY`v6DE&1V{5_SkrJEc)2s|g4_EaXzOY zp0(YOsH%x|DUur2>RMP>QK8Z%)q&s0%_cJPI`20;gZ*Ht*B;1JRZ%1po(hiiO>DxD zuDh=p0A!Pll-v)MOCso`5tEJVzmw6#{;eQzsRH$Q29Lb#hH#GkemM5cyxseAmQo2G zmt#O!?Fc{#0@4jYs^0l{o{pXV?%@*k#8Ql8D}Bj{6|T{4!$3d%C+w)fK5ZM?K=wq4*+OkXfCfF2jdxTI_txB zopWy%KMAtB>(k(qjWz`#@s*xDYnKHVO# zlo&}oHDzUO0>7`lE{l+1G5zk%G2xq5(``xS8?sL#{yi61B*>Osh-#4-(?LzQ-*>lv; ztSIH_C)$%4=*myUbDZF)bbhQ1^>g=1sZovaRh8WnCOI5h$iH{q_1%WnNe%ELuFtfW z^JtLS$mOJ%u9xbq7hIZvbWhxb^}6c2(>i-6MIW^BdmDa)eYkFOia1hSRLMMDzQ<*? zUQ5-VQHlfa-IjfAtkn0k9`8;sAKlIW2*UOgJls6gP*C^_vdRAQD=-i}cx!QSSyd5R ztgI8NkD=xM=y~Bt6}4!*_*#r~K#tpWKVM(azGp?*7XdKQLI`!~``*RmOR3^9voj+i z9DC6TtKKE^dSkF1l|P z9V3089X@rAsCZ+11T6e+?hIa^CglTL*!$CY+m$$}G9DK&0j85O%fJEyupgiMuD$<8 z&Zm+PQ>xawh%Gt>sRa!<0*6h4LU2!pBc$R6 zOc&_St%sZ~2BIbuMa>2ij`|@9lE5c@wTz~**Ry*c$dq-4+B#L0bV{DSXR{ z;I3tP!q9f{E3mn_PP_$(fb9%K5%PJ=Ch7aQnAHnU<%+>s{Gy&?V`BqYq)7)1I@uop z(uU7JVRTS+NgT!d^Z7jBwi#XR{xK8eGRxmHp2g+V@4E4Rv7qm(Skbg|I+jg0i)gRl zxe0sTIUsj`ymC;DJ(EQ5O-@5|47`g402Ugbtu#Wy=KTje_@k%fqS5gyo)-2)Ex(gZ^XnxsH>q?Ic^9RId4^+ zbp@x|9MpAofl8tE->I}H5s8t%Nd+`{(z_SzO|GFeG}DkpJnhH@G$hNJj;xAjw?-N(Wfv*@gi)hhTsG$s z{{G6%``lqv)ok131BC<))IWa*$m?!Rc9E^lnbuFQcuJlyynCGtz0_%b*M+qS{dJMF z-)_A&fo4YLJk){NE#&xumn&$vSc=T;Z_C>|Z&Plyzp!*A-2D8JBaH0Edve7j*~u!? z2ExhQ8OOM6;Ye`pr>rX9V-tJb(iDk4gqIYYalpDlO=me%*;llWlnvsA5PtrXDD9$x z2KFE|?gCqdcr?s?y7u7-?5r=49{O;&u6=5BuhPe}TvTgEgZoncYfH zYuH3eIlH*D{NZxNMa$-STU@m7;_;=Ig~E>7-g#80Le2LP3>)79ap=6@n!yc9?jq91 z2Gr~RetN!J67;MXkjd4}5_?0#txLU`9042E*Nenim)x$U#pN#Ox0bEvznhHjf3sIl z$_jM>aS6hYc(OZ&wLvcMH$EdJ-=3qr`9}xXuMQy|?q&#{f6%ZDgp3oxj%7ov^J)P} z`0eFF=jSq7cxH~yp$+1>(bC*k(NqXYa4wek5q(6mNQ`)^r-yftT0hp;>S&`oKFKM9 z%RV);hUJ1!Aj**lx4o->H(Gx)TO(PIoNIIGzeozJ$mJcZ@^s*}>S2CEHR8;o-}J8e zIbiY?FK8=`tgXJbX+q#{pmD&ZBJn;-^u+eZnu<;k#zBE39`$>pnZvss3AT>~^FiEW zTh#t#V$`;^R@X-LvgH^&z47xcO6E_aoWBZM$R@w__Kz7l>uT$jOJ>i@y{+!bQ&hfT z(bbyCO^i%HJ?{!swM&UbVllOKRK86YNXLBL%JP08_FE+x0(_d1k{0I0onBza%q7vu zcpw9FVy&;AWtQch$XF^J;4o<8?95t>>vHQNU#a!F8&_s&X$6abgGNA*ne2v$0syam zmcSpu1OPmYEf(fjFG-3F`4$Vw^z;nio0K@v6UEzNeu;vtYdW3|q3JgbasCE3G(@A$ z55X>w@8t$onlVlRFqw_>mEQ0E_hYqM4dJXm1ppQb=G*zZqod=h&YE}>4x8JBfdYr% zm&cbdhIOyw3N02)tm}v#`Asy2jvJKkNQL0fmmG1C3NZGYiYqo`EUww)gd=8EBvJu9R$&>VvuI(VpxAM6Us&*?civJ0qwq%bB?QA+W z(PX*(TD~2osd}w5g!))hQ@h!3u0|O6&xJlfLwv&56E|dc$}?+q+vh25fT`UJ=^|1z zg?UCjzT_rLr|AD<8|B;>pBl!+KYT+ozLlw}0K896$4lPi-$Fc;X#C1hv~7$YH*k{z z7BiZnO^oi!<3S*kFcXxbgwc^3fJe|00sGZl^%!qiz^4W)CYA6iN}i&_)smM3MqEou=0wnPW`4bEXb$1WZyq?-6FMAH=hUrs*k*&D z2XBHH$9+=q3&?HQishO^7cA_50^3Dv0*SQrfcAHQa&G7B5cz zi{3IfC{U>+K zJpX3{q(+o>gEeGAmrmyIFjAASmgN>7MMdP|sxl{M`=8&xv$$X7|Ni|6B1^vD1aoep zYkhrYrna=SC4YC{XXjgltW?3Tfm)BdC9|u_z4oi4V>8r=)bUSapDbzpMMPoSz3kz>94A9A7NsQk_SR32BYBS{{K(7hib z>o4bT{d<>g!wpM#z)q8y3+&VMr?_}0{nO^8zOUb%5Y~Z%2Cupa`jT)(SyiX8#TI&s z%-eYD`7f22gpBs{2?2lqUz;Z!bOiPH!0xs4oTyb~i{|eB9*C(yCIl=eWTxmT%Z5^I z_&npIUynLX)bqGt-h!kpWUOCIP|*OhxBJ;@b7W*Bfb<(Lj%j~?gS9^aRyrj{uP-n3 z`W@4i>8FbgCb%lJ{#_b1#!QRf1c6&3B@q#^_sylmA5AT#7LyTENTKM~ zkH0&K*nBRR%(NS=)hOf3)T-3VRQX0i(eQD!M1@FT(sC^3FYuZ!iqzwJaC?PvuX@l` zYJP2eNs~surHWwxI?wBwIVmC7w?Mv-fKM{xhBKfxTQsYVM@Be8OE7aUMCeeQY}jWV zAs|lQ(!0w<)Dd>|^Meo-;^WE})%v5L8*xj5&`EXk>VPq_vFxCqnUG}pUs+8esGsVK z$C-<2&AUb*#n!tEy)5>q9H&VpQeYvaoC1FhM|X3J;ywHk&)HNY5hnI}tFW>3DeP4AMUDA>_0Dp=PQj)+ccL331|`3odc@0B~y* zHm>xMQ-rS)X<5wDS&t*gkwX3whNXbtxS4Uqkf0J5?Z;c~#Dz=&Q(g89{EW?IElZRh zI>4aU1zkOCWHYFFFp(%KI+8 zLt^}Y-z}@q4?OI7uFOzfdYq#peB+PK^&3!d-BrLDnLNBv zA~^M_rpB-`SQmJTq~{i6s+)C_D_!0@+ituJlZSxJRm_L65j6d zc|_+>0Bq{=cx9q;?yWT4e3p)gQ+3{c-(^+Rj)DCZ!q>pXpZkyXlH*Z0X@rhIUIrby zxuW(V&GUq>UKXQ|SL=7iutXDhn#g;%=6f)Heqc zDJ)ikI(RR1T1}h4Cg|}9DByB`a(lL3YguBI%!f@L_MLIk%x`H4)!KnN@uK945J%Mx zYt`gcuCfSo2%vk#SaSj?+BL@a2TW@axUAUg#}vC*Fk0rQwd?8YYC{bygB&@bGvxSj z(;{{va!j*p5kDe!2-?q-i_V@-fz*>BKmA&zo3(WD5bp=XVbJ+oUUTz-bS5^d@%5*0 zuLt8x&HY-r#qMKWp(76$?QH0ek;kN*tQCBGGW`C_(l({xdMt~O7&D=UK24=>MBqj{j&L1c^`b}~Q zh^g6o7YHbD2&=&eVGBN4jGml5>F{Nj)~t5ryawP^G9r?$#eRBXWd;SHBPO=MLw+Yo8&ITEf{+&%h!y#ozlkqTC+&Op;`Db7ii=xR~b zCS&!(GOTk64A)FXuQP>}N1X8ctVYcRcRK_;>Tt3o!<;%R3aoNHk^SNYUHU7c2F7jH%7wDD3t;D1@^rFvbMOyc<5mRintW*e zg%oUg4sAxDlg-ux;V#C5s@KGahevi+@R&F`>sp#^<5|Hj+&O}j7O~N4>5DBbEilHn z6l#?k9aoZnwDIsx-WTg^~ zgz$Om((OWb(AY7$K=AhB?vC5#$$7h36qyqPivs6cMyEk$ZG+8}EI|_78rqLMpPU6S zkUp`rvPz=WoSvk_<^YWXDI8d42?Yfrmwte~Zg$?`jf}-;@FBTk;p!TwXPEpkR8e6g zxTa91ok*{ns;_VXFnSe7x&-$xu#q?A$$&_QWqWQR`7o}Sfq@_h6bYowgC&m9%o*&e z0GZQv^??QJ=o*uk)#hjx_F$9=6CYq4B3yM<>b43zzrgwZ^t}*7l2CAUsH|L21i83C zjOb9uJw84uarnmNmkji^`c&G!^tKi^YD>*vE0x5@TBm2EON|U~vO77s_&)#`J#A_V zp-3mN=JnL(|Fi&B8i|2{)DgD=`wJ{ zUrb*;wh6OUqs6OgLMuM?@E|uamiq)*r<+b9$?BoumTgh7QZV_~5A*HNPHm z8N4>$-{aZ(EAjfCIqF_vsm0}#Q4zS#R}Y3WpFXh%A7f&9ZQ*h8))tlyuWvn}5$Ak| zKZlFs2|wFB-LdM!|sO3FAcYt*O+It(?gV=D}{u( zxH#EjyGQ$awl}i22b+U?j>lHo3m-s^pbRe8tuy=;S~)r5aC%|p8D$22YkVRwCNdf} zx(&Vkha~!MeTaB6W{lJ{G=lO#B8v2kmN}1Uy4u~&`ZJ16z3^Mn!bWtErE^+~;?=hMqAwil;igl9ZMYJHmXF_gHw(Q1BLwzh>E7 zbA8v=R$plddpN$>0tP&iapVA+(q=fG%4(sb-shELYUUaC%*K&-MT-JBHr#fW%rbo*whB~u zZ?3brMA#enUp9LN2z^h=7#1#9OqarOxKKiGz(rXAYDsagq+<#WX6@k)1Q>;okaUf1 zkfx2ed6M#DW?h5evD+N`zBsI8!=S3Ey|^6D3$giJ4GsKpKhuewwyuaHK#O{s&-VF; zVd*kVe{`BS?Hr_5R?zW;BtR1NdNtw#_}%{eVI(EJP8^oRVymaG$pt7CAKQES=S|lz zvqVx|H@wpXk$2CSJZ2A5YE8?v+FJmB+^zBiJRv{4vHmt8(MS@_aXhbQ<+=ZQgCe^R z(qn)C{tUeVOjUG25@<}u&Q$PUExmkKWZ zg=iuE0vl3mD2!+Ki7V$U`!((YHI>Wc%`>K{HM2x@t8%|$S@Mn2uBeY5GLCSX7>8U# zx@bg4M2&- zM27uM>5|th+*Q4&U}4=|5wgDJ=oqV1kj~_pnK5Mq{T+(sU{rZ9O_@HX;#Yck_@CdD zgaTKNI%|At{I_it0C`Ljmkb_eW~}GB@R1^u|MCo%A?=NtX5@Xf-usw*nklX|m||Db z*`H~Lf`_~LWTh5$7oL9N%UkioXdTdD?Z}1Rt_N`5z*9TqS53Ug=KYabUQ}EmsUAi~ zR`-*+5|M;l8j5=2_#?*ajC^?PBHbkPnewziHvcVlJk!y^sjEmbj4q>P4Z2uf1vRU=grl8XP8lb%`@Ov}lB?8&9^6Udk3zr}Di^t8 z_uB=r68=!typ7zfVD8YX#+07SLmX?`P=(F*aSZFJ5h<75=q8nRc4r%#U*<`DL5i8r zE2T7a(13#E8XXd88(AuPD53A_#bZ$xt7L)XL9ExSSIL8Hr>)PyDG==&tFEv1K8JG5 z^b#@ZA@l_pSg6fd5=zsLpvYmlbYAqes*TJw9@My4fIS5T2_^_qi|KHoEL0))+=<}m ze0;Lnp$Fo4yRY{G8nycZRUKDf5;lST(`;($L2RtxPohCCs)MacDQ;gNXYK$7W6z>g z?0da{i!M}^YURH5L*NK%X)Qu~@tg=5qE?TGl3qxyH=q~w$Y zNq4ox?>Ip1RmB;Y+M*%~B7^w(*@_6e3Ers?gG5nmU5^Bgbw50_48w#}$xXba_p!#nd zk}uBVtvjk%YbZ2KC+AiGu` z=t`c=k!BPA%E~O}g5o(I3=frRvo#EYd*IT3_|H>tf1O;O_p>PE({2ZAR8?dY4d3jv zeF}NK6BE(!ADr%?;>-Xyp<65=4?Hu(qs!p#bQtFNnD)b`L(+kF{@GiqWdz6BxHRL@ zVuv_EwqnZGkaq@8*diejR3Za@_}xysjxV|5cXP+%oN@&3p8Y4mnO&Hxq6~&Tl#eN-0&OdFHnCqZ47_p-l2H2x&A)45GJT zZ2AU!a!L#f!7Z9tS6<&lSeWA>OvMBkrl)zcs`yeW@X@70IcZ_4LG0k)qNUSu?4N|5 zkL+$!v301GDw(~!6bd?1WQ835y~u@~oIw=Pt-)zUb~Y~1Q=~8HhwwNt+Abok>00FM ztx8q%div{gp|T%2r>ydWq;{C4E7=45e}TE>&3xWRB#%xn$qs= z8d9BhL)}=DPNF3aKMqk!bLL)~n#!p>gArKdB}fv_qe5$>eb-u9ynWDajRNGG%j?^i zp*;ZTUpN>YZ9tQ$s^!7G_Y7E@=-C@Oi-OGn8^`|K{5@0LP`N6?Fe&x|&Do12^4>vS+mp$q%*l zE*)JlIVS{oc(gAcAE5&$?@p6DgIk}Yb3_2HgE4bTSgn(b3xdg36h04zT#~+m{pEDQ z2LSIRRH* z>(sRs{rMv^GmEV3%NrBZ@q#bF%Xru=RgI&N|53Z>d$uAy2S1w-5rHsEya~oZzO$3qUODCXjiH9L%Gta>ev^#y}==srZ;nK31O_ZROk&?0`wwB7w^iI9ih=+=A zQ!4&2B=KR(5IQh0iJ>U@xvW-0PM?sl=`J=F#WDd;*`~3sPGfX28K2u4*#I`}-b7<*W9WPqhDiK0s}WVn*`wv->>OiH%p7d|FRy%V1CxpM-`yxCR9s**YrlmGftgU-*sE8Xv!) zw6$13GZRYH8hcDVoZrq6g<4{KVu)Bbl`?tf%`}ZzU!N$$Pe|Bl*PM@te@+S0IiduS zKMHw#A+y(Ud(0IFbvAR~r0nf+4;L7iDHb>cCi#Bmr9Zz^ov3_%==|tN<2-}K^cnA2 z`3-!&*PxBjh>6B|#(ij#ZRf>(x<>r$b4+=U496&2@oK zyBOd?CdZQR_uFbF)AcLaKqz_y5*)Vq>7U;luS*EaED8R`XjTd#F(`P=XkR}}W(vbj2QR=R(Fr+x)ruE*D)(vKd&kV zr2#S(A#2}6-i+ll{W1NhwxR_*otEQg?UGo^l9>_D!{!%LGe!2WavLrkfQ_;z7rB!? zgH6kxHe@WdrvxbkoUwm?NZSp=SFuMRn6~yo~Wf zIeub8MfL^|@*yU^nU&dwZB-fQuj=amw16}T1A8pL8!C7h5>D11XWhYTeC^z4fh$2{ zTPXvR=5<0M!2*mX^TpMu1M-<&JDQ4@_C_+P?4CCdl5s^74))HuBy{T(fEEV~2+@Jh zE|>nf_@0U1Ytt7x5uCX6*vkT(`@v4A>P3%-!%O#t8kZK| zmdS3wj{j-*?Z<2rtd^D*4lYhh%KFLzp>d73?+eV<8&pt$*j=j|e~erak{niw2U&A@ z{^HP*i^9uqC{NJa^)rG{v?t*|2MtUt5*&fY>8xSo{aW1v8yYr<-igWA=CzTDAAxX- zoXKn?=W&D{4Flv?@=I#HUm&SRq@A2<#7L&9Nnv^RO_{Jo`5E1V^acOaX!=||#Ejmk zV1&Ic4i}AQ@v!`uUCdbF=yA`9w#W$Smj+gS|VmOdM(V zej$1OKeW9CP#tf#=8L-}Xn^1n+})kv?(Xic0fKw51b26LcXxMpcb(36&i{Pp)}6X{ zYNjSdRjRTfo9^BH_Pf@4e$R8KS`@z(`v!M?BZJFBV%|DLq%+y|4F#r{YPe`DM-1t@ z(Wv56LW0urtZ(P$a`JHp@>$6@x-+#(KcUYC2GER$5x2Kg;|DjYJTKSlYaQ})Ap|fEzCC(X#^hV&ZJ#{z5F@8Dnfp^;KezlxaM!zENH!{whUzpRGNFBmuHu_zY;whwU zEv-!IcgrFX27lvNBNmxr*38D;=C!G^W!FfNMCT-hT(J{BGNja4UcbD;1_EYaiGwZh zqZw4cQC35VlFKtV+2Yy-mZopoi_SJlgbAz6=I78Zd2p+E~aC!hu>I1H2!kB_-GEQlF6d@bEq%(h#Pp zP_aGNk=DS4Po6k!cwJ4+-BQ);(}FnXXm=5S7UFbRzwIqVZoE80_9EhfL0^|bSjm*o zAtON_N06Jxzt+3wWUF6w*zy8f=OWS;g)i$tak0D~D&`)7hZWkV{k!|t+5D&dpti$lBBeGZZ+8?i^h!GOB$!o zUp3OH+O#SGLA%?zZ z9og#>f&5aWS|}bP2&{WWe8YUHeMXa{4tf`~2@3K`F@R@`-o++=%vb859kCCKU(6PD z%bPKkisVs(J5b3Z2g{;%{GNe*Mmp@SP+_jei=R|oWn)NSsu7huS%}ev!>BOnejHAg zr;blz?o6$ht(|W)>>HUN;IQof!PHH;nf&a>FWyH*aDeJ7^o~hK!otSZQ*{Q9fo=cH zu1^2muqQMpSidIjn4#88BQv~Oq>OR%x(8U{t#b>s6qwn1YIxYVX6AZIUZ6eP+;y8{ z0Kd_!jrKb6BeCiOOy4Tij7+2*bjHR88<=uo2-kHg@?hcfpV?)`?wX>FLX$HGiS3S!Hk(_|{l&A-9`J@Ji6 zIk7-#q4=|}xP7cHvL73kvt)-zO7NoVtI2$3xTi=mvw$FJ&#sB9-kLG`Cu$mpGr~JA zZd$)|DyQ>)fTqt=Y_pLf_VxAISxE`y82tX`rrZ0fxgr=KxBvUFK4P8DC!-{YV|9Oe zbiMf|H~K{?zxvFY$kL*^eac_t8F!Kx>;VMb1~f}BulD!o)DQZ5oA zF`%4ktR6R1_bIYy1f7PuyjwzXf+d8+VghoQoXvq@4&bEuyWujnegyN+uP%3E1@o5G zYwlij=ZqVxj2~zzO zK9;|0l8*lOssp^M7g!(tyE0uN97cD{YxIBWvxM=;0( zf|M_al1m;UJWr?}`_ulrJF@LXn1jQxrJ+z-hA)b~)A`=^zGz;n6R&-Lsk{CsdBBwP z>h|i4S}1(Tjk~0{7*382=m?&ke&xgi~EfG&FzQG3d`&BD$~OZ zAYo}4;gTWV?VO#+=FDV8p5tRl0p_r1TII?EpGbkz_+bJjH2B9G0jg($ud==wu6t7d zeEV1iYtB^jMMm|xw5S}8krr{p#BnoLlE6E4`B*~MR@Z`Kt8>#1yR7XB%wxV%-Y{;0 zJozO#L7ZgLe*5f13`-S0h|N~W`%HQQ@)-6Tai)zOyB4M@GUc^~%YMwySRG!UEqR8h z@$s^};-c%@>nw>qOcZK!E31W{KyTQ_kNEHY1$NJv6x6Q^kQsw$z76`dNq??3-5DL) zam3SDr6VgZZ!fPN+voGXE>v2ED3daCB1_{DVUguBU|2dr^#u|xRM)91sHsZIiq73; zn`#R94cwjs7czrM_og8|#j5u}1^dRWJ7m&Xaj==GF4$Wj?+JE44p@*3a$AyI6gqre0sNbEAOdhD|s7RD$ z|4MeC;AX^@po(LeQ&Fx<7nw?pb$JRc&{=$Y!T7sHM){eoPMgN)NEvc6peRqzLlp^a(rS@ zICwitb(t8vjue_pNX4`^A9ZR2%0NoYWBl5C1SPnUZR58O2VBu@pkq@@Y5eDSHtFqk zbLbHMx6+-(C%4T}GMpS*QBBcRc!t)7ISNI}!}Frb{Bq(SphET5&r{obDMAHIW=T z67aZ{ppyjPZE-)mO?XX+n?HtilH4Fc`FFpVc6;20{`UiLuiH{8O=Z z`Grc6+!|2$nu~Fn2V`>{L;X1J_l9DI^2oG7>DT|&OEc}TGnS)3i7FZq`#sOguTq_s zsxi^B9diy5qG_S?6RztQ+%CUY96kC!^{n-9X2yeiAKXjY!9zdG1!RzyrGNtmgmoN; zPC;_tluDG(n(a_>iP`;k$^-s&D>yr8SX*0>@Ly31|;t>XXlD|aFQ4En!*)}O!|@9(<* z&#MqeH<_J4P4&+=h-W}UBK`YSfoJY-z}fxhRp71lKZ|bwjk$z>zk?0i-^*wkTEH)- z!k>@h-#^UYr>OLQ@J|0f2Wj_b@df%*bS3(vh!)JGnw0-Y_9s`|g#O8FQX`1~rSHsx zcM9nL9ND1vgf*M!WHrAB2psMM?7NH;7q4_N zuIfps&JURaM|UrzqyeLC9xKo?l@b*SC5b?t4XV57|2!dN9z$47Oo@;Ve184<8Nq!7 zfb`8GH|PeEa~lr?O{Hj>ALUXEf^#MqigEnlq_&~XEYl{W)Y@62EL**NVFOjwyF#FV zY0;`)+=|NDfLeg(b<&2{@c|cc=&?Q&M!>hiX6KrIz>(F zF}w*PDp7@$JLZW|muMD)W6=5~?+$94l@LWe;Le7AwI1O@6~O~MX+V`CC6voQCqT%~ zjy|aeSpFfV5f7a_q?~F?!X=fJ(e0zV_O7#uh`*kml~`Jg?x<7GGs*Jx8C3z{4I%5j z3j+fS3#uhkfLq{pd*|914?$;!OwNcAkMBM)j6+BFCX>iISU$QC@f=DUXe2OfYjnYN z&S`#uhHZW17E2eMH|Xrj6enNRH_T(-oT5?#otOiBma+!(y z=fpW08$%vGo<)6SHd1plV#eLZ#4<88Tv=T$Rf%1vKE=h|`V0trGUG1#9h&i_5)bVW}DBp?L_aO8@>lfxQr{a909Pj=2aX%_Sgkdj;` zMpdgZrGZi=P>8RB|5o)e-7o=i(G0em%2w)8+YlmMUUX&u^@*10vYn+rmVe5vV6vPa zohwnz;Pie5B%*ZM)wfpzc*M_~%rz71gY9vt-XEH|2@g)xkvKC2` zn*64ddwmX3h+IY@F_U72sz;fUBD+)wzMMa4Oi>)AqkR0xNYtI=$^DV+}s%wNr38EUPAC;H2 z>#ST!eD9C@G@9dN>BKf^j^DpuKFp_BhO~gPSn}s7DXhW3K|U3+MG5?{$Y6B8uH5Pg z4~Ij>)fiuq|-oX@p-%w3+URsxZrc>4VkX4_V@Q6iW7GhCHX9{a=V=;SylB` z^m@Q|D`%l`e6>R^Y;e`cU1au=|4>jnB!<#^!tihs}aH zap0Dh-84##dcDEd7r^bEoSdva-YF<3ViJIX55O)OJ3Q4}uMiOv^+$c(IX_STEV}9^@)K*;uodd^A*3{Uj)$G-ztE6P6b_mFSKVENSEmQ|kVIf}KZ}$JF z`h2%PK|m|4HCHT{pPhZJGL;n(fs7jhO!j^*A3mc22JL{p3lScf$CtOMI-7`{{ZV2# zAsmxV-m|Q<6k{~QwwaVn#;bE|4zakrv=yN}+z%XjUuPtb`}Fe3UnCqOFbE=p+x-}j zJj(}bmd4P+3F%*PrP1pPe!Mfp=wAoILnGnEjHD2v4#H8^WLJZo?=}Yo0cOi}&Be=3 zVF3664vhq2eZE*_2!Lm~jKLOunr8f~AZ-E}@lNlLS363i3UD&W z*&C1qY@nG;M;}jbCN^0FY$nZs0V)u)hhL}-Oc-~ySGZTbxygPl*WM=2>c@C1M%CU6 zrm>3~p_=qm?J#Rw7PqKXBv?uhVNYY@2D4WOmWJ&lRD*H!hJXuagUADtV#|Rlhkf)5 zx*2iJ(`+k3RI=zLCut4eBApTve0v1E9{Wo0TverS2`v2&fmg6wXcvPRRhHum#V2zJ zv^~!8;Q|G8FC}0u_GyhS@~oLGgWqk}zdhFYhk(pI9{l>-W9V0wwcM zWrT3IK5C;GlO@ps2*c;b%Zk_<&J|54cQP7xk7g{6qnCqzG2*#4sPw{t0Od`CWFegj z>C+t9+^4o54HX{%VAWvt+FqLr!^)&kVPu-iQ~OwTJRFwY?L~<=2q!Z>es^~#0m+e@ zG`1Di$2xgmQ{yTph$CX}ooXwt)|;8t!)pDwF$#U4$dE}PEG%rhaqVc0_+(X4R<3cq zIQ%AMGT?`WW;h^=5hje|`|7fHe83eBYQ7U{`hM}+#6%wTtAg@y_uJ?Mm*cToODR$I zi)pS_kP-^*;E4BD0^1r-YgjnkGU>tzC&xeVE@mUMMoRsin+g9gY|i15l}Y_`bHY$R)TX5wjrU}Qx_|L_(l z;O`0|yA~8A9Xph0%(Q5r+P9CkTD;9Uq;;9~FdYh)A`4lGpv_^gfIXxZ#8M{c|3}i+}Tyl6pnN9s0;8xVBqGYq?99EZTVnR6rWoC2?LwcXi$&dJ3K7>W3{D1WQ~*5 z`L(esi;(bu&dCyi<9E_0eSONh=gF)NxbQH7eqcM%{qySboZEieXn(E*rKh1fnbDYW zkz4PV_Q*)UJXUKk5fRa|hzKVKr+?AK$%&>s;9ReEqG@-3s$L+I?q4nN3T#m5wA;aA z_2dxonB~agF4h`4_C+&bTp{Tt=8iEE!kBmUpDmy) z?)s8+z(#PVg;c09IJ#jFR4Z9OF8VNOFj$Bf4FIi;-q1(8;egQ1epgydd_05-kJ?lW zELOJMkgj)A)X0v&Hh_QAYO#OREzCz?@e=i$AwWa>WqyLluk-!!0idqm?`jbw#obP; z#F8r1{v;-fYGXs9p;NDqTLf)?=(vH>_Bx5=yT!_xT^R^OJX)_{SmNMN`gHj}{Y5;1 z>~CPk-~RMWRSX5_-+&amFflyO+Q!1gctW)uU`LQxKleHQixH%pBX#=W4PCpL>Jv^R zliVis^;*M8(IcRCqt$8cU0=te{c=lz0>jA_SWOj8@d_1v)&y+F(c?zGOCx&>zfmuYm1O9x@NARLuD`gQgUF zT&EeEF(rz$gFVJ$48pW!8TqOkst|vJk+X`F0tbW6BJ~LU(YbkA>Ljt2`Hg~hbV%X> z86h7cYAa^|5f^tuPW52((CKOWsRQX1aEIlv>NVpGV6dKVtwjsrvgE8UuHGK7UHB7@ zX=m$o_XM3U9V?FDFK&7aWyir$l%GEwHgQ1&CH&Op`>G?qzWlfg|I?XeE~az2zdpZs zI{xWToYp&~Xd=J6~icDO(? zo*sMS%G4QTZEtIf`CrH@HG5k1lY=>i$jlPB8a{9Di@_(`CGqiQk=Cyz?k5pjbeNhV z?lHO#+ivqg#;@f4cD&l1FGirzBSh>7J#3P0mZtU@zCYlHV0Ll@M@b1X`e1X5D*rbz z(u(%#`YNay*QILX{K3ES_Exj4x>he}=->%HYnIf`$+C))4yPjpBjHC=d|z=9f8%R* zwa`9NWM1}x5g-)6vF(1CN)nSUsCRM;xk(^mQRDUOxnjvGQK9JdF$ek0%NusuFvJc3 zL8w%ygORoZfs|BlJ62&})}pMee4LorFA58Rja@!LtzB)lMOD#?`{j$eni>`w8Vo}K zG@{2_ooaDONm^>!`@@+B=Ue*Y5}9r*ptQ-$%6bQ+3GPn|qpoj{GqM$}*Fc&F-XJJ) zT_pS=%x#7%2`#Pd^95eA7dZ0dd}Ffsx|gI&@Onrb z{d?SDZ#dyE>*{j8yyQFv1Mv!YW(aIPY`FUCBZ&QRadxRf9#2Q?e+}FvMwCG>M8mN1&nwvVd*MZF0mSvp@G# zAbbw6a5>ldoH611{&XPqG&{G@R_8(^PD5bmR~sJ_gYxw&;xSY&Uz5dMoNT%Oi~D4z zz}D6llj-(3ff$|@;%_JNiWvy-Sx$4KdjBZXH+k_cf1_W;J0f(>=j%D2Z=pFLZI*Nov+mh70kTft|b9I)X7CT zTlrRyJN?a=pZ3U7U+78n2j+D{$3ba!@)q^rw%ZO8?KJQ(bQ@>g1$jI-aafAc2^ijWZ0ZusS2oUWw{5|X0 z41xt;);(k3p$5aIQt6V^+L%(n>qR5jP^rVmWYy#`2I#0tGZisDBi|ZZc~8R`tfvmW zxCbT_e3c%}5g4vWywu6)55)Cx`+0C+ly&533J8?x{v}YhN)#wRcDhI;8EeuyYwqKg zds4Ml>V0BNBB^|FXRTCWuSC)>{7jVvCSmU>tx-&}*yh#Zmp7ZO()Phyq_ViE z7K}xsZ&`Jh%2A_Q>XlvG{CvB_l;LwrSO^8+uDZTL_mVemtFN!Gx@>PmC@{MYK%0Bg z_Tzy^tw{{<1ZwoP#XJCJCaLW9-J?s6#U&Nd1tH;)($cb;4|@wg?UlMGvxGXSNe1b{ z>)u-~GF`Rvlp^tXEJo(f014hDo8j|q{A_%bqLM?!Ub*f^nmH4p&tW2sW`oTOVmFTO zI|Vf}GY@e<;|lk~D!h`ONQ%BxY;xi~fIS3&{PxZ8zW@GnN~ccT+xxA~vI*r!(p%n$ zk*=`uiUHBlpCgtzmH-`6z~$Lyk$+4Y1{wYDiR`pSuhf`x+qWy!#4(%8@v zTvr8PUAs$4DuS#1((qAHrLhWl`+9pPBX`(4^I4<=Ja)<&_!$qIO@35X+6}@~$9N;Ft4Nu6OcFJAX4MCoOI7mnnO5ht0S-)+;Dmtl3yRI)8~=b@qTzTTx^sl#}k zwth99*$|5+BPX9o<64-SitX7_gAkbs4?Rc5cvcD zOIXF_zMby_0SRvV3$y_UKs#ss{LIIv+gN^h=tG(F($KujIXO-sr>lB!xCz4Xa3W@7 z^XP79sT>?Epo|LWlT>s(@08sgZ|2K1i=^dv_~YKTYbNS#mP+Nmsg~&geQb|JCJIjG z+7N$X1XiJ$(k%|VE!hgP1PS|?!dJVJG4)GLeaE6~-n=QY?qt&m)MuE&$K~DTY9S+R z*`39(=lJKaoL%COKEr3;Lt-R!rqbVKR|A6!&~XDl9%+Zc!65S3cWtSZ=8AEqaf;l( z3F>C`eP&H!4!{QUfQv^-?;OTfzO|H3GnO%(@=t;cYYmisnjTi%?L|yyLWYRnhl5NY z40H}*zts1wM$m*uNM1kY2u=@j@nMF&_Rihah)uI=_whR_QcaFHsTrsI9D$P)8@ zMBo(qhPJY}JZ0vDqq!1xt+0LHrAL2aVd=BcJe0ZM>HadVd26Sx{@wb{S)GL7o0DDl zr8J+nsl8oBhA#+U99FgH<0oKHbyvaXYrC8P%;apg(a14X<-A_Oh2q2Zucz0wXG`JL zqy$Zl4p_)iVI82>AcW;P!Tq6}iI1}<5O`U1tBoqL@r{%vpyY&QgF zF{HdH1VjfOm@o0rJE;=hX%U0p7W_K9Of&}hdx;-RLPZDJ9xPy`38ek>HFSC`j&47DdGu$WKh>axB`q{Sz5$!RO@oSsUpM&vpktQfy6#1boEjg~DgzCZYP zPJJ4tF*eq0Q~nb9y-H2$7OhI$YP6tEK+aqV#md^M@VjXKoRDTj4$o2AV=fRYJ32D) z@Nk2}lbp(avvi=#{W3ZOR5aj@ZMnG+)KBI!`EB>dRKiJ@kYE;@qhK`xpjND!Bxv=C z0&6r2drHq?!}H?|ikacz=wGPpaz7~=aB-~w9a%p-Ogy}Ey$cjRW}l^<=nlZ=4~WaN zaTU$0N}RO@H`t=&(8e`+!7nk5P9Sx@DulY5K`xENWmpIsb(mYLB+%%Ao^MLQe-Mjno z3d2=dRaG9Gb`!}D8-!HSYR!XORjJm;GCmj5l|4lWNdunMp$*6eAo9C9v3U{sjUr&;=7X}!o8IL6Xah(b%g|!_DgvUHxe-m?boLJCeG8^3gg!Obev|Tf5npPRO(BeOP zcU;d84}-fPW@o11>G9hOsxE0+=}VhQB_wq|de5t!@|*NJF#>IXiPK(A{;SPl=rnk4 zsqMjNAEK`Aix9AU&L$ZJ&0UlTv}NIw62F32Z|?+ zapj_=VO_g6Ra)(kNSxY_3GKHXC~c{B%N{lmvqhns_8qV)dA!}W209UNmtj9N8Z``^ z`&}*c5N;P`O>(v$_dtVLVBCqEVQnaRJ$I6iCDAMH_!f#@>YE{1o09I7IIh&3f2Y3T zP{8rmO6nM1I5=EybPKJ-(g4%6`FpRFhIf^QHwgWEeEIpziL&W{<3IA{6Xlagw=F}~ znQU5o7^Qf_*3fIUWIxpRwHrY$tgu$BbBl{jI)BWcd#A7lNYlnKeTh)jc|kVA$dA{H z;RZg`>jYWV%fYu}RA0KyRXTid5NIxz1V>nO;qc zWv=X^j5a8LhI&pVU>C|Zc5ZIYg|+M+2P^xi=qO)Xqby3m6y*VG)^m-I;KwooJrp2l zsi;|N1GLgR?e)5LZ|AB*j+}75Xnx-KJ1`YA+i{JxSinC?<$^>~D zw4dQscA&x^tCf0dszg3s-*+LD45uwHFNHWWz*gs_vnv2_G4**!YgobTXV>{r?NBiB z`}1h7=SiP>g{zT00-<`2Y;U+ zJ`EdP1C~N^5SjFVldBAO5)2r09zJPW$E3)9n)2W(2l8jOo>#8A`g%}jp)wowW+!tW zfvyp{HfG0tgc%)GRZO{@%^*<12oHAV?;0yfetv%Ox;;NYs&N#F%(FePAO0U)b*7KU z%cI+i8#L6jqK({GhYcWDitxo^!ZVsb-uL)P zb(|a^g`Xj;`jK%GV$%(htH7jL%IcNfUH=OqZvLI>z(Rbc0O(-KwOT7*hfIOOpvlAS zbaj1hH+fyugjtl6_2RBSq+XTwDMQCs2z%I{{!Ty~O<04%eJ6o+vY5of<6%E-6%>&D z=VW$HsWQOf3O~`5S4$NY5G0*9W?nhxR$z^-ryC8H&ql+NCq^6Caule4mTmvB!b3wM z5zvC@Ee`S(k5mhz%(VPEBAPH;waM*iI{f3I6^NJ2Ei#|XoQDnTBPE@b!AGs}oJhxW3%wxamw4Qbi@v^rGZ`b|F-zxl*2t1$W@TPpT>gt2 zySqOjOQq^bP@9uPDvLo602#VI8|&Uc^$bj;Gk^SjW(G&&E;ZQtN=c1|p^vn+wgH0R z9RovUi@R82U(H*HDagNOfz$`P@R*w;5)z!U&hHs~Vw@hCIJz}>cz8lk$UfVl=x4*M zK!^H}aJAZa1eoBEOD8|hYudg)?#Kd<7AGZOBVBJcj)W{1qX@&r^m}r7K>nmj%yS` zrsV$G`w6-#Dl)h6fak7xZ^%}S=>!}sEL71Hu;dvqKDNmT;f<4%8k;uw+*P`7bwANE zLVxWt2t--yeC6WN)9MZyGJ1S^2@DF9_R{lrm!P70Z+1Qb+9r}uT|BO|-QAopdzUI~i!=jJj_4 zDC+36AM~>%*ubi{YpECPF5P(H-zFNdagehw{Zv~Zne$JRC56#C)=f|&zD9TGwTcuZ z9*cu(voYhF)hTtwIk8xo7`OEU-33qD%C*;VY?qNQx=lVd$I-{BT$G(DWpD*6E|rJl ze!@dteX{Y2^*xajFiV{yTi`^thw~w+SC4=ffq+-;Cgc{a?d-`MMMEuOI4 zLt7by1aHBT;^F`;fXQgO>+NONbF&5)^gz`PIpyvcMbcn{kc>*dP&hs)Y$p9ja!JcT zcV6@dV5%495Lhb@03mDK+_s#?LbP%HhcB>=$ulg!$v!wfH4S4(&pQJ^bpZZ6?h zzowNA4zvnM2A}5azT3$By8h`;iWc7ugf+dGg7B7?cAni_4IIsuU<@9I*TJr^Yew4W z_|#hL$nP(QWQ^vD`ugty$TUOZO{G&#mLTSIpopG?3;rn+5sYt*Fb0rn7@^5PhtoJ# zC*KsyIb7Yo^cqSif-S8l+gR12B;|JQb6fcDM9rdt8ALjnZM20cStD0Vz5f5&CM0nF zS!dtK4KR~fYO#WsZF{-5U284+PB}I{ zyzekHWpinve$$^~3k;}l@RI=>`9~F%l5~%Jp!AI9`&g|F)tUt#)t)g5Uh{l^z1@ix zi^4+UxgpKd9_t5unci#m#{kPu>#Od-OAAhq+eIK!IzAySEhFRO<=#5e8w~?Jt!3%C z;^iJ+?QR#f!+OKvX?pL0@3pbUD3^GM0sr-Vg|$ljb|9U{*?D2jBaPjivRSu-r^S_w zjI`}x9lDnXgc&{v>5D{JT5L+n%Z@A#!6k5SwBOuoSZMeOJGAjY@EibhY$#9X^HdJ^ zg=_xJM_}d+v>dAdJ9MG4a`hWgC8b>ekHnx=f*(4-yK>+VQgSVB2=r--ApSSlNV$Os|FSc`Fa?3B6cn`|%DKpU!S< z&`~meu7&L`glv7gU&-%1YbN6amwCSDy70O`DwqYzGI7&u_!e*^IAuCwPh9 zc7C;QbUb4ZKP?qxlzr@{z={&I7gio7=~6rG$U!nyWRJ^0=-&)~81K;SKm9fui>h0@ zLUVt50t^AC0ZY~Zf3OL%^pT+PdL7#r{E(M7Aw1_z=J0}a^PSZkw)n7ozVWOxSkf; z1C}6M=wIiNv(hvKv2w5y$cdWJ;Q~89_#$7M?=)*m)Hb^?-C(%MfBEptes;b}|1~ZF zbLF0L12{5-zlmHHocD%O40# za#OY0c)i&*ufbEV4-2E99R08!nV9{(H2o_Z-1po^?;0UX9LBc9Fc?|koXN=Hs1N>N zpT-N~Hg?As|Cq?v&E9JHvcsGS50}Nne?1f0-0EiHLyT@_Q)~yg_)?~I4GaHPRhz9Pp7P{ zy|n~A1;#FWK^!rm-#Agr8U`BltKgr#Sz%EBAp-v)W8F}HjkXH#HW{13MC@*@qtAg^ zjqlHdd!O6l4ugyhDpau8rLNW3b6cl235c}%oCb5#98tter#?ZlG?>Qw1;mx)Rw-_* z31-O^%uu48iD+wTYI3HTlp|fbX<ySP5)1qARgr+=$J$p@qVGAjCA zc0EcPB+mlS$~2yuEvWs)wxL>-alhhnb8~0vYReuDM1Co;F<+{)EHK}#tO>ul)bEj$ z2y=9-aQAfggGoqA62odE`2h)|pbp6Hw0WM+ARr+Hklnov!LiPM+Ka<{BLINtBwAe? zW|!hd;7@bo?Cg9Zw#YY1?{HBj<7<*|NG|VvD{t+u(E}snLw=lSFpmO$0+e-}OiXbS z1ZZ%b#T8{mBZJ}(4-d8~%%-Ms?MnRe{?af;Mkd`2qk8m2#KgozL`IB9Swg<@+Rty1 z<+O@3)6Hu7Gb9q^C(s{k*q(x_f@C zqNxl0;UA!3Sy7`XmBQ-$x@b=>leS!MjgvI;vf+9X5D>7T(UN#QX6`>^B>F|WO@Wqg z3(4NmK2R|pEiTQrotKxDm6eo~w9a`q`V%dn#>_J{l8e&gQW0NRu*_a_J>EL!H9DLG z0x#wGv{TbcN-R@TaTh8+@-s6phm=dmWYc?1syHeudqd^S@&U~aeu@YqO8l=qnWX5lfhQNjIlNQAjc4ZrNC>; z@e~NaBY%WtIUb_GZu@5|$Y(5zt7{8&kPU>9b$BcR9Y`7j$!gMSFo$)bfvB;%ydtS2S#&RS!T^-=#3iY3CsJ8fmaa-EoL|YqI6Bm zz?8X%OEB5g%6t+wwnA>RFA0++4!*H|$rljRz_dcLX3Y~Q&yvh32uTj^DIuKE)qj;+ z-V_5rDW5%fwHtF1Ih+1rkX?L~1-@V-m@{L2c8YU+f{++g)cul|L#JS&pwBjdU9*G> zl~!&w(%aQ#ztuCs_i|~y&Dynd-Ke4xiP%=RI@z+U@bI_jzuoz3Ufxy-ro#@|wnzmkZxVKm!G{D+5Y22^jf|=xJTd z6_u5Eo2`2l{lQQ5#E>iH-vqHg>q4T!1$>zSn?0Z1iw;;|1AHe3HURMd7Df*#B|;hM zI^{W9a4s0icqK&dED*s#JsbF3^`8dICZ!E~N$gH#p9(sXR%`&?T5hxPWD_l+eeB6= zt&*U>uiH~~2j#}>&HJ#R`uP~8`eFU!N0-G1(^Ifdee5~`9oSg$ z^bEe|>D3n|)5exxalF-z4nFITk{NP<%s-~)FI2vlfML|7wNu=Ghlu!>#1>%Qlh{(M zXv2Jo`Jh0+*3wpVp`%T3K%QQljB&b01I&xpm_=#Pk91axsVyIYU$Wgsoxl|Yw+lGC z!Nlw!WNBE36NL%KjwRJIa>59o^G<^P&{)JRSDA5e<*_3E4{iPfLz_heP!(_AcVogB zOE)Z`;yXwJXZGditA%&n&q~y3t4C%!PtKI@cIs=IBG2{N(^wj{yPxY7NaeL$*E}b! zdBdyKjjTtuu9<0Q*rR%goHzseOql*i6=_NQr`%oKb{eODFs+I@<^=)3{PA}!9+{k) zGN-@hH>3;vH^#hj3pN*AqfDht!M{0cVI$fx;M2dDfEdpR9ad2Qv}lIJ4i?XVICTls zg7W?6ECFv4Q(_Jr&MFZ%?L^N^O5=cD)sjxT&);vD9_GGsR?00SEn?TNAuu zQ-Q9lXKg4+@bC#B`4EC2Ujn=I?3z}iuFlTk!XIG$2_8`Y!V3-~?Cc!Tcx<7K11O=r zarxs!HdGUBtz`O-W;a-7-#Z?kmwz`3^zxZ(#<jX0xV86ke`;n`7h7|d{K@MbC^5-1WVwM}R6y5ndUFkaIWr+} z^$g>@zO(Y$;^J0q<-eW<-l$OF&ilJlLC?*Xg}=vFKQ+($Xtn;+3utZ`=tW{g2|6t~ z0zfMQ6CkDzb3846Nc=&Q00nbj7u=lKr}uYh#O!nP^2r~jKLJ4qjxLUXOMO{UF-c6j z=y!X4ADjC^dsOL%pn@diRZ3hWw!Q1XsH42;{QnnI9-n|FgmoT=kuW^Io|T{6ivJU^ zMjAz+qVidPFz7a_He*gM zO9MK`J<%ILc9xKvl9QU+?tUcS>EgTPYG;;`N{q?;sz@ND`^kd0g0?n?^}bd&J1!>) zcXny*uCJ~yk~NkY8|vE5@ZPS^RFx7|vKTIFL2GNoG6HNki1SWES;uShm8WjU4**f; zY}?sUI93XN&k z)as(TTtx}gJ2CCBSYeqqF@)e{HG!YJ-U8m=E%94F5fQy`adHSDL{AjdjcIP#xg+c_ zTBvaI2H5u)CBEASm^&@MuXX53%Ob)dlE<_|72=c;?z9o2gl-3sXf?ULZ?eK)v-uNmi6!ea|JLH{L+&9%-?$RSrA-nj=rN5GzTSCuW;Bn>&x7<99ziopr!y zvPen7EfE8AA5|QGU~aAr&}UX>1H`M2jEqHr>7N};lwM4jYX@=fp94EZ$`&)_7JqL=F09(b&-)>{EaQ1Ize0#MF0^?J=`Ih z=j7r@MMV|ZJ{pG|4Is`H7lC9x+oOCB$h#ZuPnKF zml+}$2h6|3Urag()YDxhzmignSd4;y`j|x;r@%i*dZO?DI+Bi7n<)Iv>Z>;#4Z@+x z(q%`*sG^|e&%<8ZtkzNjtlc^J{|r=j*{1)Dpy!5O zwPPX*Mq=fsC*LH;Z4bZIxP^_J! zofY*UjJPW|6@cc`n{H|LTwK!p9WVdCfT@SKSO~Z<9EwH!i7{a1gZxH0S}=~ZwFnvz z&WR8I71#{fiMPrWjEs$26xwF~59Z!FDC@Re+m;YeQjktX>6Gs7Zlt@VyAkOW>F$*7 z7U@R18>GAQJ-P4uSx>Czeb@TlnE7U$@edtj@Vb82c^=2U?OW~uSyIxc@1JIAvgs!4 z&Zu6W`}B_ChoTJ))|)DUgWtRiw14Ec2P_2tG%uY`4(MMp+UGkb@Ik%MkI9y?7;f{z zqR*ic?Vlz0_U9Hd2z$6BJ~`y%)zVfcTkBY}7PmhWcFsYUX{vL=H@GP_h3%bgc3gzEvtnqL-R@j{O>W;TR-nOPkR7}zK4$oN^m~d zQ^m%`$QR|SW;aziFGoJV*Ms4$`(BmZQ%53k;%E0QcUYR+=>nMf+?*b{%@=>hL-@u^ zPEMSS&+eGj$U)a@@vs!V1fPnxK}PlVeFODJqEvuW$JptUl)z@T{jSX$sYtQ^Qt z*>yVKCi1&b7Q}vhCx6_4M^eLVBJhX>DH!{Hmeq(XRjeW;dxeAXe1QTK5oI$gQA{jq z&aE`NgSyfy-7J3M8+xn(JLB-(^P8m9T{Xu^0GZ5lHI17od1xY{C#1RxWtf0!;TTbz ziVxsA-NOxoqVQoM&?xq2?*SYB1me$W7rhqpxPD`vs8=8||AukjyxH}J`Z9VR)!e^s@JP8vu2z!x`oe4zOB!1nMJs;>PTr``nN zmTvj1w$KtqxD|IZi6ZBNZUmB$Z>Hw@ zMc&H(8V|$Y-u!WcoTvXU>2&`;?t!-5BfAb#T}t3nu>P{`>9_xFl>EN{y#EV|oy6x% z3jA!r_~EZ_Vck(dU6YT<1LX<$x%wvX_wNji^{JcTZ-4RsF)uF(S+9+93t% zo$u5HE6&(X0&awr6JdU3m*`X1RiH!L3TCP>(ZlBuRPV|hMXisNnW1+>_b}{pH`|? z@TL(8B?m_Vd6-%;i7NzXnbg+SE*8#`C2RP$xG>o4Wr48NS6EXMTURM0gpysWdzA3j z3Sulcloq#mQ{hN*;ilEEk*nw(z-c?<(I2_%n*V16G)hd+En`EEUYSC*WLq%F+(h)(>-^ z4jg^?g2-d_&N78%^1F-4!Td>ZFw4|;YzCu&jMj&pw_x1{dNj79B;shVZ*CkMjRs)R>sZxxWVvBOvL)luuq;s?QDtlmaQ85BbCtUM+>FQJs8AA} zuEuMh`8aEG%X$m;L94uSBkd1b3{AisH7h(#MiE0DwWzf2aSy2ngFui-H`>;lAdCVU zNf%i26(W#9m0!C^xDqoipTTHM4jWduI44WTEn9Adr<-qWC&pB4oCk$vMCVVhi{$Vxc)%-hRK_O4_fC@4BMw94FG6U!K~KDHB^x^Uhq$>xi9FU>7@7y33CyeJfdkFPZ?syR9v4){ zv^w`UR?EY)vkhziz?gIW99}{`5N1z-Ny~WC#v&$_h0SB4nNmfKcsy+4)N3@e)S|x2 zjE>HC^YV0a(CuL6cSS`7u!s#NGo4PTXp#JHap#vJ|Hz#m{kOSu$uuTfBG&c39C*Ly z*9t}hL7@jr4x7jAB1pl6u_-YHfIZ}Hl6;5Z6w8p*{#@+mohph*?r<_L7T(Ur?i|fr zWLe-egn%9_l2JKF@xVx+s3;09OAqG@|FwRFwCHa6CkGgqyTZZB2?5GAgzvLbRN6K+666=hxL z{Szt9`v4N?Is<7S#jiuhJIoyUEop6ena=vh4?D5n7kk%sqa8u*{)qieiS_#3NLwUt zLZc=D!3@)ZID&g7CiXkyHgRWb>+SGfG9HS?Y5>yU;NZQ>nsAu#m=O1-vx{387B^U$ zz1`iJfC@lTR#M)cb6o)Wr97z=H3fxJu$f0kH@Jjj)H51Rd}VVg7Wh6s_zz~*+Cx)+}Co$m?jJkBW1||{>QJOpN_$QJ)FZNhu@86Q-{a1@NtFuBg-jhVMQB&`xsu`=0vdUEXBPI53 z=VpYbP0(i(PaQC5Vx(CSZN5B?arc?fD6x{VUJss@hgFf!%OQN_=dq2hWt7=O`TawO zVP_1dqNU%5_ssmOhFb}%pkk6D=z?8rd1x1jSgJU_9gTWBJs{c~mGbpsWVO4Hk}~+^ zX#r^An(LjZZ)r)znR-_7S=B;-*u?PyN!%nW9?|jHE8US1-6ZBat4-h20xU{yo_ADt zW5|ng zs<>XNR>9b)JWcft)j%P9 z5#(#CR(~%S8StfH^bNkj^A$Rl24Q3G??mb_h!#+Zt;F||B^c{-84#exgqmDiWx*gr zM^?=lu1~3X?g1D*61hL&VA<+GxH>!E-Lsfl^WPecW{W{Qcp4gR=p@P;X{nlQ0sDEU zo{gN%ahls@^>W9#It0#FosL4q><);eandBA@Jk>IQdZ`iw%Z(-iJ?qOAN4&d{}anF zEuFy0MozvBz~XIo8Cgcvt`lBvkg0vVTn#~~iI2E;Xj?38xr=JkiG)RxP_46GQIO#& zW-Mg0E^@#8WbXFd6&{mT3lgV$N2zFYAVEk-8jI&)wKDayI8#OCJI z9rCryXlS`T;PB$%p|I_Z>O4w_N__eDxd}EDEW$InteV_SWH=HWbbX)%=!ltokHCF@D3bM!W7z2+dfXE`?dRZ?=fBKup{$#uW*gzAQ`SSBi zt-LD*xb80ItkQ`)<d}UT`5vh?Z4UK|5`T zREYhsy05s%c&4L}0LPFb-KPp;OFb>$o!OUwR5y1}%w+YC9^=BJ{4voA3H4*;B%Wvzp6|q+DHZ!c#bc)Z6T$ z8p#Jx%h_u1O34Yvb3J&}FOMx%CUbY9*(nmb1zF6FqCG-2+YW_dNDFxv=!P>W%1Ly5 zBBV@qPe2P7)1tD9OX3IYYVylQB zMfksV0gFlV)36N-bq=X zWF0P)-qBq|d-m&w81i#|tzEbh%vuTsiSv-PkMRCgv(gD04Juv=*k}F@A;nGjCCF!= z-8(f_+XI}9ZJDede^oeQh!nmfxc1pocXq?5)hhA2Bb|`=#zv!u;}E-%#hQyo9n3;? zFa73_2=j+spTCUxe$p0G%fm^3e_ScZ1U6S*6yNy6h%Z08)m`?kOKEfx_-!ZXJngmU z{EcpQGzLA!#l=O3I1G<_uXjQQt*1EB{TMPn3lZ@=j#hK1zZHgFrsAPl$1RxJ)3>A)<6eB#)E(WfByG%+iO4)ZyX#v9JNdE zEjRG^ZF2)Z34U=g-zI>umpw&Z*o#^(#;7ZBk4c0?$3r0V|ebU35_ zYTj=6bJxnj=E3ro4t-i^D8iT!*G*4Wx}}Dw^kTWbh=s2HM>A=|G{Uz5=R@T+w zW{|z+YP6X7KsKEnga*jq=R05%;CvmUk}*xo`RHz8@ff*0neZxI)?%sU{v;-PqA2Z4 zWdtrqO-TvC>z7-~Hy4eEV9|%(AIs6ms{Va06(1KL|I;z#<^IxRPdjoqGX6_QSk<4A z;Q67@*4BoBrtr}R@}xb22Ll~lvoW^T2a)ivEia5)6^DCW%M$L@eR z7eOL?0FiJ3etsBag1y7v$U89O>;7rX(=&6;rx$a`w3-d(QzbDnoaGNmRz&xJcvn`_ zf^6_MWoV_-erIurR#;eQ2JR7AnQwm&rNE27%+@aRwooQXmAYFS=JJI>0tRz`avNnw zjDSJQKXk)N%GGJVIlZ`N+J!yp1p<&#m>tZz6Az^mhh7>TlPop4R9?UTU3<=zNNgJA zUVlKTt-S>N6$6P(@X_fdUbMApiqQ4iui&nTmf1Pje1q?Aywn1;2)GexK9*t|>5`&v~OZdZ+1?I>+c!831m(D!m9 zQgWTv7Jqw{tG$xB-a*z^tB96MHTS!Gg%Fi2i#?7<@8T%N$B;`#8Cgk<)s)1d*I*5J z>=kRWu2yPFfM+f}C3F(MjI`tbPF>!mPz~>$BmTi2!x*Lhg3{%23BH7?Lqne_85?`n zszD56ZLeW=$aL#H!(=*BG=a(a8n6BcXJ~`uMvyp#Fy09JXMxg5v5Lfe(K%7uyTArH z%{VogGo+ys%gtC$AwXYy5nW>;AR!(SavU|5a({{vg@#;Nli~d4L{0jrHnhmafx*?Z zmv`7=;iRK4aBI6$rIt{2ZtJX}HJ^S(9B_e}qHlFb^i{*DfaohD+!ubDxH)>`^zUad zUK40}1Dtj{&fl_|MPO*Hw3ocSty=Fwx1xHs9%Rw~ZWuNrr|G*qIX*u{9vJTT8!YR| z53Y#vzhP%_l3A60vl^wv!_hTn>hJX1TE9tsa9|yBf38u9evzsSpSLFqy3LRnarh2| zV(5S*>dqJjbR81oCZ5xNQXn7CM$DYRj_>Lb@yAY`$=s=9-+PLPw7@-`nBK%G%g$}* z_fv}{+SSiGgt(-il+NY{o*L4K>0F)~jrX0UTV`YIJ~XN@G5IU9=bjr=jKj#XT;!Q} zaxYX^ymPZ~cDlFpZa6-1%*n&Q528;71v{O?gEA3o2uJ!btYf9G)twPsW-bp5>eJJC z!<0`C+_Krs{;&+26~F(VS%&w*ejnFeUthOc-Utz)cqd2^Eo|2R)=Gz@Of|vJh0we# zN^`{ttpe8yo%wKVsAe9{NWs6&0!*@6Zcd7%l30*&B!}?tZQ5bXpgo;c$y8^dU=g#C zI60e&UlwWE7)SCF|y#MMk59~HaY4G-_M_QDobjRD*SjoG*dvaqK1aWlnX!4 z^&v+O4F{d~{rx>xGbh<@vpzSdigEp=ub27esO^@J*Xv<>%s3I}eeUk_H*0`QhNm^^ zL4-yU5rLI;>I%groZ`U{@6oF;_`sGn4CYF5IHV#V`RI8 z&9}(1ryN8@wTtd!nPXp4@!_ZRz+>s59vM1Zw>`k)>X*pzv4HMWn?L}&grwnfr3T&h zVa2QIU;1dI+|OVxg3w6$w)0C$GP=Gbku2@XwzgTVx^(fJNkwh(fC zo3oM{anI%&>+3hx*HMH$E^^|uAO4Y)MwEG%DYE`l(O~lGc@UO`f9}V2yXBvR@i$*= zxC6zO$*zja>J{bEMorLk2P=QS@PJn2B*Qlh=wVFlDhEE}b952074Lt>q(%8+d-ZwU zF*hI}KFi~s)S?%fO(1TEjdQ-vC>_yzktC7GhbSj8F3XR@r!bkHsU5OIWycePR5$0V1~3UxB(GI2b#>ki`zDs=G|wus9XKUNb01tPKzj zJXp8x^wL`-j2^8z=2XVlIFewFdO1dZ*QLWtT`G)6X-nh?E z$7T|H@G6qWMoE2E$3*$7mRE_AFJ$3!AK&(Lzxr?bhxme3Q@OTmU9?McsnUbe3vNPC zLCD!A%k<;;-MEa28GI$MZ?ei0I1Qz9TBL;yqIY?hbr`4(o+VVeT{{B$>f6Gm2p0=W z94aeFz@}(woSgK8EBt$JvC<#j;^Sd4=ATBDS(%wel4(fbE|aHxI8!S_^>)EVsoJ4X zML7yW9T&G?+~UQXwXJ!_3vR5EXv$I@;#_ASH7+@2EN+|`<#%05AKOaV(0{3Zd~Kh_ zBUgB;oj2z3*p7?>2M0%IG~Hm0yfFkN4ik6XKa8uPsrf>JY`qxGdqNRn%bq46*}cfp z9GN^OrD1(%raVPc$3@7+$jB)ED~Ljq6fn{s&wKkoQIlAjz15Vf$}eRhzBpV$h7`FQ zaW*?GZQqY0x!xNaZn@c!AS6Bt~y1n7PNZF)PIsMn%Kt1hR39t22UxJ!Jt&Vkw}oR zJ6ZYGX`C?3t_xr4^t@nq;*$>s3Tyn`WKFo%nAsKmHG&y!b-@SMK^*|+Q~F=86y79J ziT_;wVA7>qY1Vh>pPCM%J^kOc9N#k`?g;nv5s^WO@`NQw36{z!eLPqm@r=&=Rw+?! zV}oL@K6ht6g*mugKIQVK$k;gu@5)YPiX70i8uKMn#XVgxYLKJ3Lz9vjv-B{`0USnm z**s34jB!Zcd{_<|)~T3Dj>S0t(RO^439I{j9MMdeqUSx4U9GxlfBzh2LkKEp^+x6S zOr-un(8Qos0&^$rSi+fl)uEUTYUF3a#tSZbZ~V2v>8K9LbxH~%{&Dc=j#uB=QHTD zKAtS~h&_I}bK!<`Z~%O69@K4hc>sT#hsb{{;pehPL8&j@-Wa*QGA*nTuBaggnNp#gAezxi)xJ+kf1hi zgb-3Yv$ge+dSm7zcP{jZvU0(M1`_GJcdT4oP?Cc=60yAIYi9`z7z~nuG9YudGx6Ox z)kFHN>D{MWM>6DJY|o!RKVowpNk89h^|KH`Amp>3qcm^|-(Q6UMWWC!3Z&XipeYv%e*syL_axE-cHq*M)xz9-H%`m*J?HLHT=?;Os=Pq$g`*}|L-`Dr6h{Tp!9sSb&mY(vW>$M3n|=SNfq>f^mtg{ zn?TqBgUc)x$+zRVNo~s;n1a$`2YY+H^67C_Bo?P(|AyJ2)a^=9(yYBtNuKuB_OIdm zK*-mqg@uuG^}f2)?e+#pIaCydO@vOMi*(~HvrnEJ~LNRNuN;E}~FFPiR zMavYbSUfY&$;!`{LkD!Uy?)wL%jfWQWc6D9sziDcA2+Oh?wb1AqQ~gw7WJl4o`)n^ zl{>h3BiTrd^BU4Ju0YV#x;6v(MS44SJ(b!pLAtfY@9;oN`>meJBuQ87B%72Chjmn~1%nkStwN|RP~Rt406jhB1dKD*~$ z3=R$spyu!n^3G|0{(0C?V4!vWqHD#^qKo}GP{vcK*J(>@MeF8vTQ{v5i5iY~?FM!j zEQ1%N?E!IATAZe%9phDsDblS5$8Tk1WXh7Qn1+W=$j#M-2`u+oA8yQN#|sWyP7eTx z(9X{vfPioNaCbcfjnoGb2Fh_{WpzMLu4WPLv-lf$j3Hz=xT{aM%zpfQQq9{W3v4wZ z@SN`JhsLQciHY-kE+bo1Hl)T&jn2obk&%(}^YcG5apyDmzHL+v^FS$Wg*a%BPqFYD zlf&ULRaX7B zh?Xp?*4qQH75mtDQ9M&=bPWq5OQ37@GN0dgC>azUbp#N)!^J^GKys%o`7&yb%z!Q9 zIozqlfsOL<@o{YqSf5V$koM;P%3@R-jNo~Iw%P&v4|=SsGke?Ewk^3VzGeBx!Va9T zrIEx&=C5%~Qx&(~gE`%WUh|x)%ABX8Cp-cXVI2Z#*eRIg2aD%SDay>j&3SivCK`p+ zqsbbE$uIX_#xD;!t%cnA6_>+gGS^SK1S%X6`%H*2@yqx~)k*2cX5Sr(hrAz{lOGu! z|A|p4pyJ24!OYgl@v-SgWDFm3+xpu{sp}6@UuhH#u7AD!H{ z*BGyu^e>vS0+4}qYnF{Q9G^$-jg@r0J;BAMfgxwr)z>0yQ@`sekTJ!e@wl5pTvCaq z%nn0^@!j5B`RJL2i4YQs%`@|>ccYdXmoHQY`&Ni7=p7krRYQaPsIzZ>=xXNAhKAW! zS>1dtATAAd!yr?;^l=C%H`0@Mp9TM6TTZb-4QO9@BxQ4P+|5PIwPXr(UzuQOy*s;i z^kk2hR0j36HQFrk$;FeCipV%oI_8Hu(JE^7&MWhoIT2&n1LwQkZx2}il$oc=2d?&Mvqbc63M;w}=P@=aHOHKq1~F~wUyXsL^)asO3rDN(q;2r; z1s!YcL;n7j7xwWbvpTE_G-2wU%T^E%p%cqTM_rxji1ibgCgc{pU;z37W>PbvU+bRV zO=wB(#1aSBCz+4WMH4T|zb3O79Ys^SY9>J!k$yrsT}^R%fRAYcFl~N*59r>ZW^@f?Y=~5qD6SHp&)-dA zd@nBII~=tdb-DDYGnn}3{ZV2c63qrcs3ZCN(y1^4=HcLE>-j?4{aDBvbBq%0+1|7xhXqoHMOnUMRlI zR*MxnZSFfPlLxPB?Y{@n(8#_u<&3kZdBdI2l*u`00%acyZm|S!*w3o=IIN#RBf;G{ z+B*QbYlY6;dFa{PK7N(}#m%E}*?1e64PwUN&xwyoW4*4$} z*}O`PwcvUaptXxMUWM;+7bI9*{x%D6efDsrk8H0bg~c;8ymScO>{x7i&}_~bxP`lU zXE;ruaM` z$9XzXd9?1c1jngmW^R_|tcT9zM0>2EXQWKR+5BQH%W9%?|^*(iTYN)XDe+}pASBN9WxJg>u;faQ`DX~<03-Z4w<5IQ6r-BKCdSJ8- z+t&C8jWU~w1hpLIA^G*7k)ZbXU2L!P{^p9NBw~CcsIxL$mufsT_mzf9{vvJB2NG~ zS2_Bdc7PQzy^q0vQ04r1&Zhxa%dC)Ub*RXL}Qw^iu34d#p5yW*03L@1=5uZssNt#>n*W)`L z_*)?PRXvWfDIQ0L(0M+EOdhwDBFI98=2rdlhi+8&&o>)kFtD#yC~^fz@P7{>oERHK z@2uDA(<{T0s)(&gxjO;705rGP;`Gj9gmfMUJNx*=L{jNy=bDWvVV5(UT4_$` zK`k5LXaxj(K~YHhJ6TVfI7|#2$XL$zh^%ZJ^^FY^lT$vz&yoPN4u5pXRMNe#uFz;pCOtdOPZ4NFhn6gANZ2VfQ*h_y<+ZnGbgu**D$EgiEw2@HC6jb=ynjHO$$_i2j!wEPQ4cK{ zG}?0-Hj>1%N7wi7H$c^NTld`UEup8k)%?Ps$L=IG9+KP6*|t)QQpccmSuN}YZ_(Jn zT;uR!TdGy(FzD-6A9{)&cqd;WFG*UrZq zLWAp&C7%veL*7F}FG42CnnzNYMVS?3yq9v3w=4SEFzv`|>Pv|Dy-_~xw4G@Ty;=e) zIH)i;07;|qMVNFgfa>x~8B}rP;H`d#w}=*CcXQ#I?=3Ia9j$Dnd0YWnT2PNZA7Ove z@1BKt9W}#JCsftmR}aoU^K`n(sQOK*{~fzhI+W@{!y+_Nv3c%x{PE9Ip_PWV{;~eM*Sg8PD@S%%)Br0oDvA&@x0T} z$i>!`&wWf^r~8}O3-S%_lbc~ec7K!kPDM_Q7V9g5U#m`nNXhx~F2nBw_U7x`+f&@7z_utwZEoYB!n*A)FV(e=b8~N|a+v$_ z$!cqBoBqayj~np^OY=^QU3pVw{$%%zHMt z*gaR&Qu1)>u$wRaYtg&Ea_6|#|IXaU@;a+K+>8k)MOo$J#{`%2oh0+67Bf7ik)rMg zfuHT|@1k;-obDdR{L>DfmokEUqL7df0!&s$OUCz1_o?udG|vaNhJHSj^&w&;6fmo) z?yZK|zu$!WLGn|0DYKMa$>GtIMe~OaUB5)ghONc&0^|aVFp;5c%Yj+Fbitd4H-Fe& zyip77S>Ok2QHD=3nk{Xyq`67ua1o(}GMqxl-m$!0V-P=qzmXs**f0FA@95F!Pn{FMwe#{pkPv9AzTDw>ghc~$ z)!(69#?|nwzazQwd57~0jFgg84b)3jDR;vVn26nr?dDZ+(n@FdUO;E;1-o{1w4>p%eV}Y|V zVf5FGpDXtq8>=nryrUaXO`GGYL)J%FJKE^eQBBhV4O9PyW2lvrit68q*GToQwqBRB zIc=M+n)ma-`%9xyr?fB~8&E9<`mpl!YA&E}z~sj0&d z5f>y6_ji#$%(U=$`dR~r-p{wUnw)6>IDjP$m28gEP?q0Y-(x59?C{~@c)Y&%2O_^e zv~OpT8STPIcpI=@fDY_|B^f?~hf`+mmm%PZN=WU~D<@RH9>2CT77oQ}w7WH8rL{j3 z66!9D?(1M6m8}0bHyxVBIyl%~Syi|7V^MR^w!St(+o1J+MR_#f&Y zn^PhAhQHVvP^k5Uwm|(W*8A^K-YxZ>OM+!)?z2@&elQ&i9+c2QeP*LCC$9)D- zUX2(=#Jk{4H&04U5tGs^AjRau11FT3ACIl9>>fEiTB5-?+^0j7Ua*XbB091ynaZ=WL zRy&ubb8UC`ZT{6zwo~$cZ8Fp`>|)>GYxg%*FNmJK^pghdP5lwWsqEbEbXkY{Dp-K@ z_U&zFO}=`|!(BVn?ZdOqFTDo8Oc>QU+}zv(2wQIpo4&u}q+q9_vOVo0bhLP6vRsy> zpcG{=Kgj&~xe45Z3rb3oneAwF6)E|D68DKqJY1gt9`W~aJe4Yy8yk&sqBeeLj|dPE z6p#?jo9GMk{M0!)`OSEM&2w)=X1BGfx)PV&;!C#N$=qfbKzAQouA8#6;aos9K1k<%{16M&7Ym7P}m`D&PhTONy`&nN5gv@4CPal_r z5dLrTaSgyxhyA0-=oHTu=ooGDrGHz|n)QvLcE;j)p)J{Y(ZyFx}2ePp>RP<{dGBVX5T^^l* zz$@AN2-LuJTfiPDPC_>bo8wruDs&^Kv3tIwBdc1lN9TZrCB=*boB9V2lhT0Nh!9G) z3C4esMvph*o)F^k02Xuffs3OGXK*>A9T3U~h)Nz2Pab-ND?{$V($10kh@E+#>|L|;T(z0=KSR6^iS3~jf2^+iI_ znh>cIF}6%CxmVn~PV_277JRl!%B3_5FTcUhC7wOS81M`aZ$zaxad z%>oovC1I!|%8?}<9c_RrRhg5LJ~Y^<(HWTR)BcZbl1W5qg&W4 zG~XAqww@&QQ`j)yg|;A9fX?I5ICa-ZZGN@RWXKC|OY_Yds|!-d8*;bqr{$TQ->35-<`c5gM}=?aVHi}Szr6`w)xqXl!^5FdQkhTHQ#-F;CrU>lGG2$cNBNg^x z%cs>y%<F1i|gueYGqU_<-(dg`uP**s%09?^GcR9WCRNk-CJ6N9dd>ns$4@ry zB#q<_=g(NKMr_fc+rrPwNBM*%ES<)hNq270ll}H9T#z|0CTr z0%T{W-y7Xmij6bfv^wkYFHmHke9|$dI&f!%v(wX{U~|8pS&UDwp9XEV7`;b*aYpETd-JMm;;E;~wD&_5 zG3*7iSWjvg18Kyti-}EZd|ks$Ltjm&i1hzH#Y?34FBGrnRMrZzc#JJ50YIkqR4lMC zs+@kAqc>GEh@vg0?E0`*05nzplL%+)do%SZbQCz)rg3S`JAMnTR^&7kqB4z;?`tca zZaj9oN{020f4&J28#5|W6sL)U-ypqx2P$tytRO^mtkAo zI&{M+Y$a1m?%dned*6XEsou@GV50D*0f*uP*Lg7iFN9`%R51Z%qlRMqnFUBaaqw`z z3K~QF(jv3~IfxF)7wHD|Ps1=c=!S~ z1h6x^(Zt6OIAL9%EAy37;y!z0lu4H|*qbz3*WuX_>T`9?b_wUm7e(*mD(#m31$ue>=X?i!y^G}IoX+kbv8nAgsh-Q)1D=q`o`Mpb3+hVAuU00#5q zM93$L_hEc20mm0W8n zvY@PML5Wz;8(Krdo>+Oe8O+X3Q>4fIs`2mP5p#SzE^W4cLR;%EGsdt%D_^m)Za0*z zf;DuvChQ+(?A@)Z+1c5|xtP6&HEp+*r^~MGA$Z9D|3NM-3AvpFMBb=><6((<_H%0* zKJ(rXky)Q99gzn7b%_RlPGTMW@;`2;|Hm5Ze`Swp(A*x0R$tXXHUz>$;DmshtiRpJ zzet)!QULx_tMKjL5aRm7`u#3AH4IT?UY|AYwxuA;?mRIif7kkqGG*FEw^lFbsx|?s zo*chA`ki(EJ2S4QyXw=go_h&eY+{p-M72-l@&p*ZSj*kOD>H<-73lU%Ry9W)ith*E zt1U@FoF3M+(y_&ZOwjp76EVDU58yf4G7#Vl$)iUG60wX}*dvQSlxOPC>s@vFG!yzGU z+SZ{4eYt{#hJ|%;aV1Yo;yZTV+|G-qQWg^vGd3MJWBLVub#rxfa|5PQe*C{u&JHXO z?)CMrl$AlUaPyc5uUk;0v7t^;=?SWyx50AH?NR?xrDu}ed^(W#3iK6Eg=bkd`5Axx z5i)GIZfZacvp31dzJi2H+^h>`epiqg-wVEi$r%`;89oI4SUD6_sX~c~ay$F|2{KiX z6Ju~Tcyij^Etmr3<7HF>U)HZ_Dh%H?I;;(Z5Yzv#WP8zrhC_gU5%PF~RMvgsl=kJx ziMX`1|5aI8S?yFywb{hC{#Y(<-Jj05xJi^MB`BA#K={;f^7}_vWPFP#MgVz6@VN81 zoUGr&BG3ES-Ot4X$*b4nZOOEn``+}iW8hHC5N1nlK27QUSE&bBfqqCYTI(F%Jq69PPtf3NliI1 zCT1bUorIHaC5-8D<>PTUVe87Q3+H0^l2;O^%P1|dUmd&#!y$%GvsDEOxv{U~L=ELL zY4!2nA*tj4bgC_s{{G$-f<55ZW0+^SFJ2#VTv8D_BgWw28|}22RIRaQ9op{jg=ot6 z`4}iETdmBq+(RvAvh}R8ug}U_rx0jC!WtM%gT)O)vYp&q-Ty5D92fg{1bFt~TR1&N zIWX}dVMWpDRZY*T$uEtJW*)p94(DA72*YaMI59ITG4F26cm?_>LJxSJx$aT0dok5D zxF8TPSL727kH5|NwT(t1J%)Q0hIqb7K7)4<|Kc0CM3|28$nU%T(4-f(Yy=oMpU+x} zZ-2*ylAwk!by}UWLlU~ff98GvK`yPX^C6*`k->1}htE>Uqw6qXBZybbf5c%uPqDwV zvC16V)xYWf^2PrpG$fp}bDcnTaq&K;wmShDTDy@Q1qFqNyE}o`9{tuN$pLZtCs1IJ zM$;m~4Q761F!uJHG0-%T18EAZgUfl`JxF z7HINYL8S1-VfM2z??s~X@e^ifj2AU>{>G9Z zmA2GnZnY$TYdRo~YlfC&XmTi{GJYujd>N9KaA}+}E?INoHFwVf{1{0esazvgoKq$2WDSjM22mulBvH+B9k;RQ?L>R3nqOiuk~Wza5*k7f7K_c zlE8k2j?ZEpm{kdHWBlq5Z*&bV@xsc58b*%?%+2yv(e%qL`HB5FY8Q*Qqu=BvMY#)k z@ixk>=8`bP;gR|3cTx$gY-z|}JS@7}A^OkJ&GkGHLH zM4r=SUm|#JO!}e=(mWoX^C2mtM&L5QtRn{rM!6rag6MO)2qb%sPcrB=h7It6f=QKN zuQeV{`$i&-$84dxIWd6G;n=gWE{ZK14fM_oM3&Fa)ZV>M2}m_AR-SW6ond1ms_Q_; zPXwjdr(I#=R1rfb8Am{H!)9v$_`R0`L!Y@9TdLgDlC8wTuihE6AB==9e9TAe*VFDgG`sJG<-F$Qv!K#j?weYipXI9{Gyv_Cv6+md2Ob^Go7a=dq<)aW zz{F&+??F*fnF@)c!RL1GNT1@mTJ}Y01;DRbC_^Czl`}{o@|;a+TZiHAwsm$Io@9%K zfh8S04k2Ny-ESJY*@9%?8R!bbR#(z&b~@CWmJ}6*LweZ|nT+rvea>q<|Euiq^XGmd z;SZXMss`nBs4r$>AkM+J!JGfyK>}Xmp)(|Ic4C-%17^PmL~uaOZyUqLdXR!h1pfQb zc0BL9&yXsZfUrt?yg$74_lIF6?yzG`R>+gV=kbJ$l3OB_(T)E5 z%uN1vewh^Z``>9^j*i4H{2;+~x%ml3W}=R1c==L%f8+Fd2nIEz5X`~LiHrG`zs&;1 z^1mf5ev^e->k9LuRh)gd;I+)Fe%8!Qfx<_Ih0p~;fF~O&+FbYJh~n&=W|E#21MLgl z`fm$nB}&EcVP;r1M9pc(gM0;L;VWzbS6B2_#nUDP+|mr;HQ` zW#xVM5`{^Htj-aS(pc;G;X_zeCruy52i=o+sj2MqxSeY8leqq6dOTPTURNPM`H%YU z%UE7s(#PQzuNpVqiyO2Cmp^ET)MMG-RJ2m)U`_>@V;VxK`8J7aebbm49bpgssrQ19 zru@*#7*{t-$;5nU>SLWE`wC;ns|T4|vaEW=mE`4hmf>#Z(Ohd0dcl|XJ#veqoCyNS zP`-otGUh!uG_a7rN`-9q>sL|aKFQ<%f(JJ`WI`^_{;op_iC`TD;&X9F;aT7ZC@T5> zR3bH6rfNZI{2R1gYph1g-_tS+d~Wb_*~Uhe5=zF>QY|;%03HkDS23 z;PUd?+s)I6W$FY6CXdd--#6WeEzS?$JMoN$)qC{HnIFm)Uo*V(bhfK(DkDP9My3E4 z2*>p;8(hz;+}uJ`<`u|*FuZ;Puur-;jbhc1=9N7HW#1VHGb#)NPBSxejSVh}(Q%1- zdaE!A$kg@vkzIi&CCwjhz8Lz}?&Y{MI1--?9i znomj9D(o*dlR7k$0{X$z!gG~=2N->02w&-r8@dix{9FIS5fD1tt7z8jB0 z+9sle3#k9a#13WfeCC76$oIT!j?v+DGxKc!e+L-=vd5U0TdkUHmmC)w9U{pTWb+KF#9lOvIBvy+T&=| zVSYk?2|y-f_Po2wksy>SQqnF_pKA3&aM+9P{q`*?D%JHSq2v@=$k&hxc^wT4>&go( z>vcn}<7o(#5s?m%xS}N3bCYv%tp%Y|YHDao3f%BqEqhR$f@8=J?3E^+ zk&?$v^BoF*WC_&@gX8Wr_nSGZ)&!N=%;)gRJk^OW1rpJ%3;JV?wVGd&`o)8@k*o{< zd(MmLHI>Q=N!Xj~>(8l>DmM?Xgg-WeH~Iwx1Qwl7rA`ObnM)%1&2n2b&CW{;zRyR;aA*P0hNPqHNJWAV$%nMT*8S zFwj5UTpQFNgq`Oj*sO5&03$?yBhT4Qo{A|zg|Icqz7!IEAZO+G z-44Vo>wY{qpIQh)B?dZfC;@03e(QydNM4lcS5D0RhD;2h0xe|LP-9?nky{BTf~gm4 zXlTe*NB-x^yCZ-Uli2dcUkU4eB^9ol`or@@x@KrF#|?mwtEKiPDjb@ z2f_sMDM3Dl1q9aBOu(Fc5=!X>(fT4?b4o235NjjQj=`lr$z8Akvji>z!H6F;`n(7 z$wjXC=VwPM^4v+1N>^8R!A&d&4ySzvf4jw!vdVH|j@J*tHqD<2IX2vb4t0!-$kVJj zxVV@Tka|qOI1_CO*K3-xhM#9bW8ajAn+D3)s0UvsRZz#@b|W*v6A+~=fwa`j+^CxM zziiP#y#KaE8{%2~-)zyZDgRqrG=cTv|FA9EFwE_MX6RiEhth-1@Y=(&2-Dq|;SlAi z8}Z;eEpg{;gZ^0l0LM?foWYYGZTv(g}h}jtGBPtoF`#= zGn~T7OV5w0asB9apiG59lXX*f0|GZh#R9x9j)S4>!(RUvUo%M%!Ajb+xR?k5m+Q*! zbpNAdMQ;WC#F#FSl;mPH0<%Do869z6MJ5f&hA0r1=lBi zG`UVF%FV3FtgGvqo5Q?Hq z^<;!$(fb~`fKgEW=vC*N*jnY{khT^wO9^zVKOR)e52Hk&prPt7 zY=Jq?R91_=zJ38u91dHOIHb(s;-&}VgSl$Kd_;KoPoF;r^!(hXsmV&h49#?qe5X@iS@2uU zj4)D5#z1+&@#FLQJORgtMPTm*@!b37%na@7{xW%jSCT|xxplPl1JFGYd(1qXd!EfO z)(kIu7$D!Z=z8slZePsQ+wlK^j@6fqreCYnM!EzJeosAR;%lC>Rc=EsO@8rRy4Nu9 zWdF#4Dk6sP1k_I7?o?i=7EfXy(fVpzq9aZqCyVLU6mXcVvsQ{Ahkkn35aX1K148?} zOx_=MHGIuZs;~I{H*Wmpy!m@*jIuP*xJfp4xF}e(U?LA$VhNI;zfH%nyx3^^qIae1HTx;NXCet3MqCO4j7IRB+n$4S-`Pc1i2soqAi_BxaUs zXTMKoPqBwns;_3TbzPjCs$F+`yzZID6%v1)jIFi(4taB`4g8EgQVcS|pKuwrPdZ=U zFWN#PB7Y3)f=f1bJrbnDA)yv?XwuR@AF@Q5!DC#KE}>!L{~)SP(EPK+PgY%mXC%J# zT#`D(&4J=*3sWVHGo+?z4ccAgt1 z`fIZwEDordk#Nx7b#`=iVPePZ>1%PMT1s79o22Rv_W8+rMJW*w5^@kYYtejrxWD9o zLrcr+w0l-^1%E1F56N0VNT~cJ{h1X z1-dEgHhJKpI6688Wpr6HLyl_?XP%2MJL-CFx=JeVFKWPd@p@#fT z<7d1ZySuAWTFt62*qXY;i}Z69RLDJ&QK*7LMTsw8ynsA^whGLZ5p%Z#4#So8I#)m1 z+l1il;f8~Mi>C6ph2H$IVGaKj-fVeuyFI$Gu>tmvZI{$95onhryu7^P>8tZm|3aS$ z%jc?$@U>X|Tc7d5{p6+;?;bjo94GzoVKvRCrSN>Tn;6~d^0hCCX8;h%-GB(V*q7D1 z)o@-bBr~4JvnHC=K;9J#LUB|Iltm&*M1zB{-baPB8k;7v^1#yF?M!a`hWX=ghK~EW zQr)(xAnGZVArrtloI-hqE`MCv>-68i$(J$GM38IsZ&1NV`C3$Sp}cZ|wS-OPW;&c_ zAlADXtuZ8Xxb3(9CpcLpB|iw~|H0urP0sp!iXcm&xAGPDD(Lu)D;BfhPPcsNH`4XE z(-kg0UoEfII#oVpNyK7{A5VsCC(8g0$v_8_xlTkVp&2LBM`Cc)(zZGBfozM`{i+;w z*^GT^c&=-zb8@|UkYAXCjF;TGB?=rKW;ZgaD++p98#?X>I^?7mK|l&e5G?E+?uahf z{r~niPjPNz58Eh9hv*Fwb`TNv4HR1!KU@0aqx=^;ng7|~=RduGz;1-Ws{o$AL1o;P zZtudm7DH1(kOpV^;SgzNkK{)qTUL&_qU0E>nVnRE-(1oiU!)C`2fWDONnKIz8pX zXl7wN6&h|*oL^*3TgXVR6e~Y6_fiGt)bc(4yZKgV3OIpCz7q){508@3gI`baCzqk0 zm7nJ@q$WR)2O{c}Z{Ki@p*mv!;+mhWUj+{Bri*$a>KrR7DyE-$4}DjMTw7bQ8Eu13 z!`5Og`ZZe0pl8qk>~zJA7aE2lP}S`(=C zp}(4Fe6H2t`pNzd9S!YS>Yx=nJh@wos-z=)>hg_ITzrgn*a%T!QJyuWjw59_d{*hR z-LERGq7!T>Sz-8jWR5rI9~EF1<27jE2=1zG^TU3M2%R()=2{-)vqGb7ECrucy&$~r zrA+k$_}KDGG@ot=R%qoyl^hd88m$_=%R~M*%UrzeX{4#LdK>MOVZ%(RPHk8^M+gej z1@jQJB(_?_t?6c-HUC@una2xP3+6mQLD7r-Ol0TzSaggPzh)S@A%Z;$o{ zDxjQ0N%r(C)Iaf9c%qPF!-bzJ8bVL&j;C1%{6z9&@;Mt%m<{XysI2^zo1-FCetlzK zL0b|*>@Tx3J>KLyovpWcyL-7^kbx4GbW(X)VkZSlAVJVWMJPxj=k?3HEd!zW7fN;3~Uqxz9 zPW2+Ec?!gvM=>u-O1qS0v%fu)3nz~wOI~^w1aCBu8NW-7_sKs`1C7J-3Twyj7NZputj-JvK~h=PoA?R2`yY%)xN&nq7R^2Mm8G-%9C zb1yG0?48XC$MMl5662lD&n>40JxdfDS#B?hT`dkY-~xgI1cb4gM7+HpHT%lTJqE_L z8WNDOcEF(xDe$1UafP#i-fpeKX3J(EVsG--l05hbKkC4?*spPdRn|q;0d@^OZ)N=L zMA<33tH$tp^Jv$i_7)k)-WI~zVMSX2u z--h83EGiL%(>fp?p5I(V0v3A8#^n5&f}V-Vv{|nheDR<-9y#rfqdUD#u|ao)^}-di z+W9Fq57ha^%6HCTzQ=~nwwc-4$*Czi^|H+L_e|FN382@CVi*C!T*lY3t7A2VJRky! zbq3uxXSaZzaJkARI4Rwrx1gYBQ%_=E{|zK8N7@Zb%aU+UO_#l?#>wD z?ir^uK@p*NL4&pG@#3{itpc8ZmjlHlR=8Gwqn#*r_~!v%i|HHdwfg9GG>uH!38sPx z3Xvl!Bf&r+<~h1TzDH}%?k*GC~u(7+Qil%_i$tNSrs)gvtN znFT+a^~jUfIfGJw={F)$lWhdSrK+Mb^i z2(#A7G;(4>liVG&>GC zz4vGg!UFYgy04(Gj^=6+k#_!*j7B{e#iah~k8WXOLyV1IpimI`zXzik@&P2hv9oi1 zF@LmRo|61aQN_y>-u;_&N_4bj_`M`oyhzUY+i9oS+1c>$)>j8@ciPp zC{C@w`lMULVSaDY>$acYnA4GB1MIGPmWO#x9ZlbGGWz0Oj;iyvyyfElD2cn%izM>R zB*jZ3PXPs&DIt`Y)qbN7liJ?Fq50+pzp@lpLtAlN{R0>`=>`Xn0?0tO`pA?ZEiwGd zc6YDHLIB*V`mZ?Ern~0wUVoW+xTnp>ZvkrowAM2 zm3#>L%OuR6SFOPxFAoB@;8TZ>1QUn0Z^R&WL};-1Z~thkceV{HJXN@~P1FMe0u;=c zn3-3%;8k9!1!2=`Co&pvJ?)i&wQjXL)r-mM;e0whUdQ~LjM;r+`&+p&jc!v}cDC`k z;;_f%0sF6Czdp{Xyxo0X=22TF+grYM&9_b4Yi%!UTLxcRB$*G*ohpS^Gto>{Dz-tr z5i*MxD3(Zx=?*{OklUzs1g3qeQj?b6NBts~a3b zDXC|?bUopvs5xD{di6LZ=r_VqAXDT-wD$5&LeEJdd_+<2h4pv>`P;|(F@5;cs+Sck zl_j0~Bg&*QwKB5DvRL#ChDK2`47CrAicJGfhI?EYzr?8n9>h>H#C(MbNPbL&Zz4c< ze-)-BCZmsLHJbM~J#0Q7rpX|RrbNmAHWHa{N#yB@6^?G_|q}HGW z^+5CH?qR9z&U&-;RnreGQma@79BFpc;ghj1MBiEdVyf-e>xrZ=xJ@N&O+_vy9d#cC z9$V6go7AV(QNUoCG{r1047BTIc)ZN9L6_W`ZO!fDf*H--B;c=6@i{loK4pw_;qZF> z$Sh57x_}w&XdlPdAppiK#@g!@`@$}{MEm_7-OXM)iqupVt179iH`KHghZrLz*!HwF z*8^|HBg05ke2k)V)xQg9VC@*W2feRO_;}UjBNL*W%sKyv5c~ z5@cQ1N8+gRL3}*?hpW?JnWUac;dJH&mSo?xj$Xyl`5xT$Zlsl}^AJFbL&q&DX8bd;Wo-`f)1BLI&&nvD}5|_xqOz#LIgw zwO^M$9+9SBVsHu8k%<0$34LBk9U6M`Z~%>IS&WGmN7d*8M@|}dwsiaJ(7y35wNWM_ zN=wKG3d5smfpTCF919!{9Sof&eKXP6yD{!h9vfY;v3q|EOYBkOe2`S!e1TU9|Fhon z_R>FkIgTfs*1DRjFK1A_qr2O`s+-T(X)3s%LqN4?b_}kLPXRW5g>EkFmufaMV?F#0pL4N1c4QRe0V;a5@-+9PX&Ma_~tqRjLnnr^V4^Vgh+BLP5m}-}d|Ir(KkAYBIsoJU9XM zA@c0_dF2|gT&BUG%P%NchlgWuB=>}b6i<1>w_zFOR@Wv#apo7CJ@Q?x6aojWY_fix zdKWm-Z;L3**+QG9#J=!LJ&ziP`EP0FL}aXx!Ri&v#zk)$rgYBd zz3SmE#>Ha`Hx6n01bNSElNVlhXR;eVM7?;h{2TICdU;seBt*#)$dgl(G=}fsHOQQc zT<8L;q@2Gn2<`js{(CShYAiLsviirsSeJJwU)`jg9SEeKC~tFtSLqnB1aHbwu>8B8 z6BpjOUwW-Zyz+(BT_OGb9k`?v-%W_thjCMpc5GP>A*$ojTwu3~FZ#Yvlv;eIC9bQg zW{zPY$mlElUlq)D*=4~%!OV4EdmUec>p-OWq+q7$xwYu0k8Rae(5iV%O;%hph8Gob zB_iVY@X?SHp@`S1b^Oq})-4dnVRyDdONefG31Z3a&K9Sk?EG6ur^wD%A3f)$6Z`Yjt@kThw<5kA3 ziHVNIK?e&xWz1m8*7}yNmXcnCv`iC|bz5e6PUMTr2(DVviNUt0Ei$vY(sU#S>KnJ{ zubZ7bi+R$EHS+dtC}Dy>lis1g#pNSqA`6W)@#X7qhrJW+Q|^*O$wgu>fBWXp&&c=e zy=lbIA(Z`*?de%z9u=iEB0nXUznG!w((j0zub&2gGUPf<$GcQ=J|s*3(+kjl@m%)I zJg>B^V&F>w@+wK1@S8>?C`5aD`S1QuV&*$Me;{U7vHtl5ul-5PT$+1$LuZ8H|Cg9K z4xdxnUUw$zXY2OgV&?ECG4te$>&ZoClD5`f*XOFc)IA#!5h#_F z?5>TQ$2BZ?GU+u&*VA)dhgC;&p2NBC$^0SwTexIoBzt=XEbk*OFHgfheab5?mXnaq zgb@LuVL+hl6Q`-5(6(yZ*4~!3^-ZIhjNy$$&(_xFmZBn6iw7Y?8b92d5vNqI0}brc z*Amm^f)ITCl=O07PF#}D_-CQjorkADV(;J}xpX_0h|mYY52OSTO=4nVWeEcnXBOs_ z2wZA@{(dcWK`FLvO5Lw~ely66VZ4Z$=}eGzr?~yX|_$jU%1j7ECh{@=MN7#vZ+;7rRa%= zOu#{MzG&lFHsb3HPE7K@aBy+By1IfunwJSvll~Scs!Ja6+}*89M24)UJBN$q(|;)N z;CzVlDkr0o1Q@C~&X|@KfpmeWc-?0(I6Q&+KQc&9%oQ+{KFLyHD1Vz@kOJxxFh;nx zwuU!8U>ilX&7xthktmi?nh=)}lTjV-0tDBURPt(SGbQQ5t7ZF()%*i2W0c3clk@o5 z!6cW+g9X7G{r`!G%TJKA%d1TPwvo`Cj@Ol|_zMx2{zQ}NxY=21;9ylt^+`k9L0j_! z!nY~kR}`tU3AD;8IySFoFROoXs-#e~BEP zoXb2>(HcLFenD1%VGh6+d&mNFUNRhk9Dik5O{NkJhHNU)Wgm4hCf0dR3GYjesQOPC z8S6{DgX;yl9y?hedf-V$+S3?>!9myPE=pa$tVMV;aBNSw^`*J7WX+ZQ7}zpc2>9x& ztjMD@bHchp)K_NW9f6(Lx|*gA8<==GIYhH;92n*JsS>_L72E6=>Nv09PAmtzajnxe z-qP#Ty+kL{(N?|(M~cf`BS=s?fj~{$5g-yLRrzt42+Ws53A)3F&u)~^_#b*XPIsoY z&axU`tSG!~3;6n@U%QNFboFSLfN!cv z;EhE?rxRVY^%ICqxuJ}opA}H(W89wOHak8m?bp9MM>Vz>DrGUT-9v7fCH13bilkX) z_!m2OXqn_6H8NoK774lqbC}gE*c77T`}(_&pV2ef|4m}I1_KN6 zU;hC?G<#O7fBhZst$Zj?8qfu%zbwhyAdbb7UYGv|>sS{{&$(7UGr7(1!(-!L}bro8)c%QN$4 z%zWgeb_+t`jL{$@VqP#iW%nXmHZ-YoUH$#BJY)7?0zS8y#=?LbN`$OZW~ckpBt6s( zz$T$~qHrCs@5l6Xwt5Ijurwnhl4Fx%@}`$}q`u@t5WbGO z4YPZZ13aAImra*_d2tT=&GM+InPkCxqy!j~Rq0Z4#&?9pBV?M~Yb$DcdS{(_LKtsd zY?@DRf=DEeV4=aNymicKMi&YZUw(Sg;nnKBXy7$k`Nrt4k1jSAxyAm!&(u#9Vv7A( zT2}3|c^Rg=>C=Ave9cX*_!@(d-#*RL8lamSu{G*m&s+N_uJc}qk158e(_FluP6e@3 z`w4b0svc``BM=Ea-;Y8nN&UJmryP7@uB8*X+5vN&nQQx)LMZdUGS^-@hrI@{m z068*r$Fvbz)#Wnbx$x%z##0S*S!0-v4%yH3j;pcKVmH{qM7Mqo-}C!U&<(mwGRdbW zr?iH@_YyE!#+E02^t6(3GJ^I!V+{>MI4NW9mica8grB0rC$G#wV6Cv0bpb@lU6~#I zN;SaEIM4nJLf--(Ptd3C`G;Ieyg#1gy3n7fLeX!ijK9WV62GpBEl|}kF=D|OQ35pk z>+Q3)h5Z8fcrzBiPJLuQykEO8toc7PXZrd=xxR-Ld=ydg_LWe3uj9=50K{aZ;D-dg z@)8qVTfp&}&_z}s_se0>C8x65kQ!Yhit2M^xXCl7(g(0ThiciM#y?y3I`6F=rvwts z!Sb@Qg!Cs%GK}d&qD|A4>En`iS^~p28oY303lkfgqu@&sfHKbs1Fs#)SBG&;3ug@L**tIur@Lh()@Tu3q*|I27B%w zWPQ6{Ez^9ry?(SzZ~V+DHtKh7bM+m984L>E=I*X6Siu&KeA3}|VQ`to;1YkaG(8B4 zqaFmZ3yBzdi&L6}tR7!ie08HHpo{#VLAey#ZNgxkFfiu5B9E6`WwW(Btq|ic)DE9n z{Cro;p+|`w>eXn=2eM+FT35Xz6iO3Sww%IuKkE{AyMi`XiBfc$Fn^J6=s-kk(Xr-4 z_u&ano64>qxZHGn*mi;gj%4P4Ig(p>#ZeEBe_z-!4w4cw7zVVaEm!XyoyBI3guJQh z4TRm`ckD=**a!f3`%cANdb>Ed=g&}{Sn3VukzL1b6he8bM1?OH7Uua2To;^pXgKzU zk0}(j4Y>^bwAWOa@CqURG0f-bckSxZFxszfFZY2*FYvk+2n#MyP@ra8^?B^}?~bgg`{-9E7-f}~Xkpe%qM+4i-#bm8Cc~MW zPT!SLs9B%v{TLmW!e+j3wWXuOe3YIA;fwa_9>UL_sTlLuR`14`Vt1tciw0UOOb+h{ zB^jqUu?%4Lm#G-o6GM5=1o<%MSq}mZfbWe-B5L%ujd}ua>tDdn* zcD=i+lczW;{ZYWXTNXRj7$@d>b-SPld)X3v?ptm#iEm8a|Cl}yl+)oVk;2(yX>|YGE%!I0$0VFGn z!S4}t!Sun1<%`259c3MBM%)S>3h7S{|H(~npTiVpyOHDqKeDGMEhZc4KYrxfF}z)B zxK~PuVoMX>`ArG-onb{AsRMG&c0Hkj~q>Vi{TtM622j39;cKB?*c@|pew9Om=;zW(YDhJ!21$h)b z?=cR=VrcBoM)>z83m$x~*vXL4dt~ zc-ecAi@ZWKM3%F}h0<*cO16{vS|UTBu~S#gL6%>)ZcIN(b-RUV6SnfG#%r4ec*z!!H_W`i;SU za|1oFmQt7k^OJ}enILoHOgeH@T(noYFnT)r`;kdI(<8cE3CQ56Qyo@~zd-5Ozd>m< z!_s zg9WJ+T0Hy~Lw+S8x$h0SKi*t9$AYz*Cq>!Fh*JWl=#U5~s17cv==zTMP2UW5__PY= z_3Z9SMXN~VIK7^mVuVTdTJj?Y+V_cRpO&c569u@Jn3w?pqVfmE z#LYgX>y$28xzKL4kg%vZSbX0(FVn%2`~)^iz(NIypk)g7|F$;ztoTna;1u;|UjA!o zgJmu0h)@B~s>&nVtl{1KK9cbPLAIpzgZasHVu|9c?EJR>Afzpx2x;?$fPU=Z>I+ut zXo;c;#=+?L}m^Onm9*q`P2xZBYXOmv9N zTvAn3^~2~m8VrO<{#2fV0bZ_FihKcRy~xA{H;)+43zRphUO>Afj{8gxnF;|`Fy6N$z6sD*%4bYktwNYf(P#} zR_M$2%opq(eKxm0%ibQ5TcWhrnl;QBrzXIy-&|t z3gmnJbj1oQ1V=HQAO)P(`5>1{s?)8}G7FA071`lpmcyrXm8E|5Fs>UZywxSK{L+8o zP^M`k3gBsXd{8J7`IB)(c|#&mj8Ao`JTFA5y&L++Va)oE!`O<84K0)Rsj37o275cZ zGcIiz87CL=zofvm7C1;ZV&ha)V8`HPiwU-U|Ejibc%IhXf66+zv913K3O^NJ|9Zih z+kYb|eyXMZ^^fnIrnUS-0za(_slk#Yo-aU3BdDMLe$|e(d43;!ChF5%0<^dNzu!t9 z=IO!uuXp|*{#+|erI)C$h(1uKh1H;?l_o&Ni;^93Q5C+=ATyN8P?DVJM^?c6=cD&{ z%2nh4fta5o5M07P$U1WK$>cLl^@c;U!pt__-nVBU6PXLq(RPHtr)J+&#{H)j7d+H; z@4*r5hp1Hs)XZrKPREmNbHbHTSMCf#;6of$IMj3ES0mr}c%tkW<%;+IgMOC&*^V`` z<7gfyl%<4&bcOeKdF&oa#42_e0XQ7FG`pE=Fq_c5BePa4bXs3=} zi~hl%&$*I+NLn+jycmLTvEs?`yxf9tXShcH6(y56sbu-gya$>dPZ#Y zHJNpM`t#43uRM>G*xyWW{m`-gd~6&$f&0nY&!jWBnJR9~biaz{hYZj*NX!CySVWbpLumtc-}ulh*idEle_oVrput&~qIb zXpQ^h>E)8x4w@f5buDT6yzWG>Ptg&e(N|Zis;Zu5LZw0Xmf>n|clYe({CR{$`plEB%&CG=paSP5)ypE9^ypAMb=6lT}lrug(J&BPll*9b$ z_MDj4x*@4PSc}f)OFvg{Ei0gELF3`mA%D+OYiWMILXL$>F*sa;gh9sVq)@T6qRlG^ zRuvWxMu`l$I7g+SeaqB6!^zQxZedZ7&bYvpRUS4UGFpm>ndMSw5>_MLB~h&jELM;t+Ge(BV^CT@o@i$F+FXm^Bh;E351(B%@XB*PFPsmLE*fe4 z(`@7e3IUK=p)`44Mjk06;?5+6-y@D0lELF#-Ds9x@f$6+;PA_Y6qzo9i<+y3TvBp> zs)zmQSK6&1T@veL#N*@NZd(VH9gRMTtZ52Vc}tLies>lO;etN>e7tnl6WgPp-~{sA zf&Sqw+Zj}PHypNmpgjgV5^(-fYS0xM`*m|`t6PR_5;s}`%4(b%9v%|rEayb`YDBpA zZ7&%04q)p5AhLnJ{%efhU(~9yDLn9;XOX161AP!~rX9am!MscJ-A#dtg`4z||LNwZ z&b7wd3uPrG5pi+U?PdPAZ{f@AOR7^j9kQkAmg}4>KtOl^{QBbJ;`n&6;J5z1ez8a* zXmQ^~pw>#W^u9k=%~0B1KVbIqu#~rz@2dQ4KpBCJ^->5TUpYA;fdix&P{XV0U0$eW zv)X!6$bM(A-;glNa9johE2A4nZEL+k4V9IHv2SAxeq?}*<6&?PPlU0yy$$#4Q|RY9 z`(J&d2Hkjg*4uO;No<3io#dp9rMgN=rfS>3&-HM;=) z@?+3-#TQHvY1g~N$H)5{eoaY1QO!6NcCD$GOJE?S;W=CD?8p4|3upjU!LP6Oi-1*S zS(!$KZF;SgbTU^bh&razHdBAQ5Z3AsYqDji2##Oq0s1IuD)AezJg7umA_vyTevS$_ z2w|6wCmX#$$tn;OPp>`at;g@!FGvxEsWosCYMed(1|cxHVF?0=NZ2$*WwvZ>nA6;F~Wfq*1c1D zzTj!7>p(HhT90c~{s#%GALBd5TZ)D4+T8|Jc{1-DGEs#0@yjz=qSAy&G_8fQFNRY%`=Jj+6H46G<$2117Pj&I* z_Kc*a*L`|s4O&w+x$dC!JGbps%6zImM8uO^P~kl3j*E(9^GJg8{C)zCSzvy6Xh{&> z>SgD7X#oh>5)O*Ix!*c6;jbAXz-2cW+F2Jb*5VOQ(3w@t9v)wtm;8qls!|QBhk{X*739mb>xcT64M>#eX z8y(ZYz@~aNEOJ#Q+K$!OR{-X&aW=-$-1HEy1K!uMjMx51x^czDGOSSCV|W zL6=_SC;_W3$T1LJG>K12-SbtDnduvgxA@JhrFP{62ak^#eP-v@P5~b6OQaMZHV=){ zg8FWt^iJe7fSIY&yRL{JW;S+oR8sO6DKprT&5I>a!@SAsi?3q|0;^a^2}7KQ=kJwtzc!(egF}Se9;vdjEalLYCrlzG?M2AXQtW@ z)q&@qUVt2*Wd5^Qq~{Q@9*wR$W2?f!IWkEI$NFd-DIP)@qlxt^SacpeQ$uX4Qf;Z; zmZjz88Lw9RT9iG3khFy<_$&&uf)p-h6=7=g9euN9X)by+I>@AediQW-HBY2b^2{8J z(etRC>xl|e=!LY2g5a2QEuz_FCNSFC8HQb?UhX`w&B#b$z`+3r6;8rX2s|mx54+Sg z<=M>m;Q1O!uUpDQP9Dg`itvU?t$|P*H#AT+yIiro>TfJHQi|*6TyN} zJWUPk7)lwx?#_bZMwnuatGp**5{Rs-4(6Yv%yZ|hE`Ouahk~A!M<#oGy$8E>hK&kx z3(vk!|#gi5l{`Q!qS|S!drQnb0U>oCTx7Y(kT-(2yx~6d}IzC z?HtWMz~+Rz)8Vq!e_}*pJ5r0(GpL8bA>!LsqD<-tvse*UI1e>_X2bLg+WxZF8tdIQ z@XYkT+1ljMgeXiOHH#_~%z<@+Y|7v5ars)>DTZ~8uu{yTD~9vA^HvI<2~R-KN8iE- zjL*Xng6v`_7!%`6gB4CJ<-Ba%75fzr*K2CR5a2Q@b8!DIJgyTe3+ z8kaw#!H{2UX2+DippoeHW0STG76hC7kwl|smWhJ;Mn*;(H#cg^;N!Qxx?}Wy zB_!l9^=qP*qBg7jSX-sgCcw4UmoMlp=byB?gnAwT#JI9 z4|KFn{%{e~`IH*Ej`P`=yMHsYncernF=`FtF}T`HGSqKl32JGoduB8+X6`<#E7s!G z*ds$*OYiz2cEVO(#x;dTy(@o{I7HZSvrW1b|IW3)%YKS})k1tAfI*p*5kZWtv~`99RfQSkvw+{uY*v$dyw@zrq*oOz1oe-W2Jsk5_@lK?IA`BMcaam25J?W zV3gHPMC>7NTRIW8-d~`qH4o2D7liP=x!Gd|aJKs0oJBDh^Z~>qh;I=Z7$Fs2Qaja9 zR*s7)AHQ6-&K&>PIec*v_f9qD%kJJD#tRIGQ+o}Yn`Jrv#*4W`05nBG5}D&-j}UEt ze7p;zCzaP$EVuuqC>}web3LIrK`}$Pzv_0n=}V}i{=U}vKvSBI($X}WZI2A7NdiyYL-z4PhmyK73$48!9efrNxTtxHXVojGl`>ELk&8;ZaL z^@eObTlS!j6qG@b@f9T{a0pLhlLZr4*;uLU$XXEB@EvdE*-3cxTAuC7wk}_V9V; zf^^GkzNurcQ3q{`p!_~6^A)1IJ7O=_;|oIWJlAbnpM>gV4aDX(Rb4mSI^Hw`pBh>` zhb*wWQb{d#Ox-}xE%)k`xn0w^XN4E_NEE`K-c|nlzZ}wAQbxUqHSN-fi;}{GHHczmT&@DGW+%V?avd% zxF_hk>fg{caC`oNuDK4FS$02@-@fZd`3t(H(9T{ngsxO37~$~~{xS;Jy8*pX0{55Q zSx`GkOZ*H8*q!5k8Ckt5pz71s>Rp2l4!R^}xT-JazdfEm*Y&&*G^>2GtVu=EmLUj#qL}2I!m zv%H3amQunpm+{KV2LpY|LG_ZWmL9c9UL13 zf7ID?Ha)hGD&c5wj6%Zb);e;N`5i%-&SeoM2REh08o=2eGjt%Va_r&$)v4Uo_8Q#1vYwH`2px7KG`8EB{&1PUl2!)@o>(rra zJdz(` zl7yQ2HVN6VnI*D&5Lh+OZfziZ1?b`q$*4J2|h zzvaxke;K#`eLoz(nc16=Q~&BKEy!*;r-ysI>6ZhEJ9%bi9gUmUTe_JL)EY@^9j#w-gjX z)_C2|*$Un8CNz&4AioH1slvb^A_o6#sd%`GiCndiwCnv!JGjU#9Hhag-iMC#Mt@=( z@{@?ZmCV$^2~!z0ywv&B9J_*o!unda>a^On`^|avawHMA^YzKE>(ebD9|F)-7;NYc z@#(v;arxaf#gp#}d9IK5j|wlsNV-Nx)2V|)K2a1;cG)!Z+W9%MBl3U6MdcBww`;?e zzyUkD6+SqPP0Y)%U0ANLoE#G)BV{`~c+6U-ew8?e&!_EHupf@}iX~#ZN{|*B_6XQNM_Y8E-CmKft3PtQ{wADcQ`H1!73u z-Fd7w{K&W!RHiI1%!58af^e#=j6gw&a%lG2mz-;MOb(aIl~<)$mZ)khcTW zUujK#yU!E%<5RsKy1x!01lmvTPMTNlUf5HJ2D^v9k?7E4u8`44fyCy6Va-zt^%pS; z1~G7_k5r~q?(%@GXj)CZZDS?#%>@IZ^0{s%dF}Os7m*kWUH(c>rZenFeMf zMSjM>4vog|GJ)vo5=J=c~bJD|a zrTsjJ-`1)aQho;>Y4ejwv2k}R``Z0}xd$*q$LGNoJl=(zqf+?6p(Z(N+FXM&`&C}> zqYOHn$SVuR;6e1TpJtAAqk4J{wS|blsa%V710&oNoI6;F4cY?cHAXw1g?(V?@1PBl;xVu|$hhV{-;O_3OXE5hnYwcaQwQMuHvP;-|jJ5;Q0tN(c+H|Bw@!!O_h_27yK@2*($}YHQYK7R3ziJo zPxmie?F3stub_0T!%g15-Jg~>)>hVlK4t)=5k$~?Vme|)S+DA`2x(czMIP7Lv?QC$ zC5^rkdCSH`_Kx`cYSSBOpO@?y5E9imdl6^Q@DG}uTBQEINk9@IJfrj(%`Vrre)0Ah z%~saSk3lmta{CvW{WZ5+oJ9d~nJpX!nUYMm z(Q8@!%0ZupXHKBT8k&!Rmv_ExQLpnDtv}V{G)7g2$6-@CiIhf0RkFm)SsubM7x`AHu1o|tD>%;uyKt(8$oMjbn~xJ&E#v7K_$aCy^`YovCJ7$iXG$r& z90IaD?dU1CIP~uKTbd)y<+nFeg+;VN@n0amsaJ=I>L=Z*BS?gQ-(|!Iish|ICRR;B zFQ49D3%p9oV{Qx5k*Q(VZ-$5V=TLg71D(0e!v7ImRIzA_std_del>hv)r zfWv2x#m`%W2Aiv_^k1W@8NZEsXI&@FtcPnq@7Xxd$)T1!l1l9%&BVaS^Nsf*CTujc zd2tlLz^q+(w(VxjJC6)nKveZLp<^!-AQ|k5)6f>dBAFj9)|xR*uQPK+wSBf4OiEXa zSM(J+o#?~tSLH`CPWAJ9C?%LHh$<*3Ew3r3W_YWCIGLipX`e7K)JCYST7n1mEy^|Y ze7|(>7-gZR<|`x7&?=1wO&M*g^0FYS>#tpewY6Kq!%=z|wuW_HyfHmq zew(Xl(*u+{CdS6TBrp8AJU0h!5VnMt)6cW6L*lr5o3ap?y%+sD2TeWYN=mE*7vziB z!g){MYkNI{>Pu$#OS&@^RaI>Htn~ITsN#J1xa5N+HvoC)E7KEvF%wE1$*RB?dUtu? zZL+}qOt^!nn!G@>r$>`#6C~sVHAjAl4TmqW%g{WR!*4m9R*xC``g<5mgWlCHuz%D3 zX}jXSH_2CRzY!3M7sMl&M+~iKR6=udK=%2&-9D!#PnhgXUxpt~D>&gZ82LPuT~idZ zSLe*Jo*om)WqXjgr0Kz7kK-#|m=UX%(*gm3LVLzA!CdNyJdvawRoPiI@R#<1s<4UfC8N{ z+S(3tz5imhx9(F_9SS4>t6f0F2-)~B5!A7%hir*F#rW=e4BGxs(#a^Nx#NObSU3_V z5sM}#bMFSkoA8jtRXJSDdjRc88rNS^v}5a}J-xoY-Kk$*V25vgn0k?2i`>uH&y^kZ z@p5wM2{z7IdcPAyhS(Ak;YTzFhKElsPau7=N^4-4nT}RB4?n8TO*SV^&;DK*-#ZfU znleu!{|S;$H@DF18^%fFAkk=cGyYU>&$alc!{9D0>04vifZ_Kln?*cnH2N~lQvtt~ z0M=+|y+gkUs&CP+D^_DB#%ai5+@>~D=KsEpQNZ+Aa+%l~Q;H9|o;Bx_4kO3Vo1Rk_ zeZ$12Kn9}ju=8vI{s0X5IbM1)sjSL)cDgV8TtC{3My-bxQ+Jp|>jqxmyK3uyv|~Dtl1pTbtWZc!#)tlbNu+JeT!2AB6wkkq+_6C$ClQ7t6yZk!BU~sO z784oy>S&=rky3HStuAWpxn350RWiN~snc8>$q=Ewt49YDUq~5kc5c}H=8sttzVQ%w zSXj8uC#M&diVBLEw_=yC%kVLX$vtj&x<_&Ww-L9zmoRRE0WT)PM?F)lc6J*j$IImX z$m^gl329c$&CS_zyowNgGi7?(dhz^)%HuqsJ>IzkU~z%7fnBG)#W$R~U!+R-?boU7 zLNqPw(ZGof1Ud(Qi|dzxE`;nXSZ*g+KHdN%g4+p2+SzC;!19cU^wd^lPWFG^N~z5- zZ$3Tkf3Cl^X}*{&;obty?Xsex%JOQprwwd5{+rIbBORTQ(yXW)W07LF+Z{kIF>2i& zgQ>_*y$%kNmpju&Yrl~gThCup*-iX}j@W8Y2#_r`-wTnOe<|>Aj$XCCIh1mCCiir= zH(Wxj_et8hT&$-KhbS!}L5zT)&T&VdGQq`B=o`bxZECRCI)gMt$MBNP?fH&kp0st! zSYL3f*MnPrDWKF}359V4sn&cKaW&i-!%lq~#T*?(O>;zmqA5iw~|X57k#)q=|_hIk0DqAtZk-2dPBAJEmoJ0U-GkF_k|>~hT_&l zU^dV|jluF0>YhM}sKCrXMHTsRZ1!q)H~d0dft(EZJ*D| zzQR|X?!LP5IY)}i;t+x-$^;&j7}VINM{tmnN7w`cZQ9RoR73)&jzF8O!hhylLQhRC ziARPAGd|dHmV1MTcndOXowCV&Yo~(T3Gb*GR_uAnm0_U+)oby_J}G^Y*U*48hfW!K zv7pzvZMQX)yiauo(sEUXeOWc5qcg7U>zr6g6E&Jz3lH~@XZ8;H=#F+*aLD9a$G5kz zx3Dl;VKzLEBqTJsb@{{`JX!g~X}6jmbMI%p`+KC`aen(w}9z z@}y%@y_2KCcKcM}#{DGK6M`4vzB^3QapfL#NgbI+D%(Z4NXoDMLgHh!^m`gJGz5OZ%R4n!6Emdzt&shQg8GGae`li6Ym2`m?I`=%suT6mr` zZ1MJ^rhrNnHah>0TorqZkZU(Gv8&EcLmHKzrI5}WYY{_9-9^kwSXx`+av(Yk^6P3$ zJohE>a=?+zox#~rsDhcXIK>oe1{z{XwN3NGWReYohpCS=1>^^(KP+4HP58S(g*Uui{34lko`Fa1`Kv`I-b*G}FwEq1K3l<~ELX3#N`__Te z=F6we#TQv86f}_d5Zt?5`0V6XojOf$U0;Ij$bBq*J+2;5j+)LUv%>iyRwlK1f7yDj zo^%uJ6X=cu*Dg3xVe$5E&F^_XLID?rb$r-3wGqUwg--Ai*7FL`?oa!brs!-X_%$7G z=~C%N7#o((>*|IDC?D2#FK)|PA7T1#K;fLt{7=1#SKk=vsO}Fq5SlrZ+SGM2!;qm? zCb6Gtb-XQ7!d>@8?ur&3QR`h@L7iJ4NRasXLJX(0M#RJ*<-WgT6J_Y^_7fJ0a8O|Q z(LUZ40#3lBWn{9r4d(EBrcdeSDqYID5XL_0sgG}_T7y9@L%VzK-6s|8&EJjITKUmZ zjEuu0^7e^%N;@e0O^<8l5v&7g0%`D1mv_0W;~wQG{MWVzvm83!2i38VDf6}70#xB^ z2Hh8XQ{fF0=~fBYWgt0@?0V9LU0hP){jh=UFi@=Kup9_lcy7+WJDS%s1!e02vfKQF zS6HL)nWBWv!2MfTGRU}(LleSe!BS!?seANLrtq$^b{shzoA-$(@_6b;$oYjz^+^a2 zakpGaScc@%+5#435oMfDapG+|=+9^7X5j^mV}mr=OpedjrEkuL#iWv-a>y^PrW5NB)`CE;(w3(43O%%AodeZw0dDRZM6Ue<-R@Y7~fl*gJ3`#rPW zg5nvm)+>$bANyNgV4Be2jgg6>yg2F;;COlsj;Ia#RX#HLL%Vug-T33OX#6+2TZ2Hr zBfaT+69IGmd0!3!NRh*wwgqLu@(6SS$jM~Tb9-k?$Nx@AUBP2wea^Sda7gXvdfrh> z0OdnyZ>YQTBcH>e?^9D#fOr-qxpqrz?EJ@}gsD=L%7w~@vO2Z1RPPNLDoWOLIYJ&p zUuZphf(o0dnpaWa9F|`(Z;D{LvM3{?qd?Rq4o zQ2N_LXrR*0Px80x1ceU3x8#PLEG^a;)qLmlj8 z?N(RTDP?OK-LHS?vt>#0UHxl<;J>-OFALIv9CAyEh4!m8#}1h+rlQUpNHVVG3DX1c ze(ElsuBx=`Xv?ByvADF-{dD!SsK^l9U&s3MgCL-ygrK7OTVCI=!RWxcmCS!4XA7tw zBZoKmxNxD>M+QSViqzk!P0L{)zuxlmgPPx{kZ4`-PJ|@h7IDO$1l0PpA!x0GhtrUd6H#dXSt7@PQH|Mm-TF@!H9>a^M zHp>WB)CKtH!h(W=hl;Ee11kfUIm~?(pkp~cKF%+*d50Phv__fFmPo);lO%!6)5sZ4 z$ktF-N5#X_J=c#Qnh%a<+Skcn(g{ZNfyx>4y`DyN3=Fd6vpwA1Hd9Jz5n;iXe?#P! zro?51At50}As?J%WP&8WW{z1@&F2YJ-8*?I)b$N)L3AQ>wvFpEz+1EJW@kYrFnSq@VMZfi{EAkp zDA`=!Uq9ScQB*~E^7TtB)0PN~XIk@-M5jpQ^>hQ~7KIjKQar$P%VfhWr zRc9?M9NnyR1&Q-%V39R#L^=*|-lezZ1#W@)YXN!YtEjA4wMyfluk9d2$J(1jeAd@j zSm9g*NenkuWU9?arUQff5>sSrhF z=Nn?9DPGnjas6bE%T^Sv=X#<#?!VmO{xZNFPJfx!^%?@g#z!Wf?LFq76Ed_rrN|Ng7S>-acgyZC`AZ`NW>27Dtk#2gINM!H6e;o;4mg}@nXcm zEf3>gUN_WZj4Psva{+H4xqx(4iV=K z1EF^Od2^zZL(pM|8xJm1{(*tjLHEa5azi?GutUk#evQ<&^BOQnxaSwDd-T?~D}hAb z*C!GX^%`H`&KF#km~p1uL6?;UNO;K8M4>ek$`=bRzpy)KbEd^tgy>FWv%%+b>p#l| zn9Nf;RM>|y?a{tN4%I+@hbGPL`gI$|Voq(zdkZ*VRUR(2(s;G50w8aFEY3^vg`K0E zx##N#fnj9Xk2`ak1LNWF#uV#&ce=H0?+0Tt6+h$mA?I8e6b-Hor%*&_WQY8IFP!nX zArPH&;d1M~vj<|3*uT*5ui|;|+l1nc;}9Vruju+e*ahQJ{z{q;`e(LH4v5szVWSh*AQqv^E{&Zcw*xOPL{ae zMI}>4XM?e}rLi?eIdgMn{#?mUVw}Liq75#@9&U+76?}{S!O)=71P#*PAzclBxFVi} zfdpK(sGc&c8hHA^p8>oApZRyN8P0THLHJtn+xoIIaQ-!?*arXGvRQe0a!Y7dJpRG{ z)FI>7nkrK&k%uZu>RI9v40^Q6ue+*YZmirGT4z2+%aB-TAjjqXF}1}H6x()$2^lnI zPEe?i{wEC|k(y2UJ+jf@Ilm5cRsvu0sTJSwXvy#Jx9PrnPky0E+k&a{f}Pi=N+fT* zKv_zj12N#v&idWoRKZyP^%V~3dmETgk!(2#=SE=$#h$x>IpKfv3)y)Y&**+FTzLQ4 z@i~Rt8#?y6{;BZiKYq(uYMrVjy|caFZtOs;yS3c2VmoJ9y^2t5W%+8IzkQ}FwC$&E z>pL7ohPXNY7MYTtpX9*XGEI;&3%qbH%)!JiM5-L&(?R1uUNfRMzrw?t0|N-{FaZfi zqT$vC=k@q$J<{KZL|j<>H}zch_#9sW8`u4X4B*Q>0Q505(HgHk!zJXfSgf8f%sSbG zT!2L+93_iugC(3e_K5AbKIYxnSlc?>(Na;DCiaA_I{^8+@~B)kDO^yc9aot0Zo|j- zo;O9sA}nLn6a@3af(f?|*0%6)G_@6q$0IeYEDzF4R@bmmF*Sf5`@Vmsf%c_h0Un zDNuKi-fe7cr1Cn;kJ%>OHf#)J!3y?M(~<0ET`l7Bn}2W9JwLf{u(g+!ljOGBk04ZK z6Gw$I^J&vh;d3f(DP`xS$t899T6%cM1Q~$y%3!m4B6$GuTTlv)%T7CW!gqXeSiVbW zS1urlBK`e+`2B~{qLTVlt|%_UX(|(rtJ_%+!iI;~vB1E_TsJZaOXB>a$-&#~kzQ!a zIiKD6;b8njPUz;_oN6}Z#g><-s2ac|12KUFC&D+HuLQWiKgx!lsKKHinJPibp13?m zvw4i0HY@T=uCI5WRdbV?~{M*hQd|J_evgN1_ zs+`_4zVQ5u*!Hn~Fl3B1AlEW_D(7j_3ZUv8-Pzq$4Y{qn!lw z9Ie#|a3JCHCilUQ4J5Q?6AQSk-O3de(ijh<%EbqW1b&r>j>YhP8pM9~bFR|YG$)zVOFSq=rPe*pS>9Z1kn7g1mhCz|Qg zA+FtQe*)49fS0sH&Xc))CctBTV*d*O?&V1stTYMNAnpKc+T)bSY5aD;rj4PFQBqj} zB1`smT=urZqkitZO`hNhC$|3;fd=E}wN%=g(GASH!B+MwFKXFvAVo2 z?fEaCHqdedpSGTtwTMXbKR#_ae4Ys^Gk_koz17Q;BlLR~YBN@S|3|3pxI%|r9*GdQx3|1mp`QI=f_NyM=|In!u2L z+>NCyM_D;qBu{^`y6Uo97<`m+Q?gMDjZQ!fU+xb$s-l#Y9&N8|q}Wnx=O_rbdVUll z^f|W!)0q#!@U(p&l%tMSCCWn= zDj7>MT6~Fxt993925k=$rZoRR2>;Sf5Q%dc0drb)&yG<1?f{pb5MNH@`RWO+TL|L(e; zwtBa{LR&?p={n`aWEvWe_lj6j{$-AWP^+B~7L4B;7Ta%?MR*e=Sbhny_AwpC<2a6- zG%@LtZ}VnR^vkR3KR_mu6MG-~3#;+OUJQCaUQFlych|L+ z44Y8c4_l5z!$@$GwdFYlU`2HeCMTsOHLnd1a;I2#?PAYji_pZtLl2Up!6!+i2_rx@ zsChj;?oCo>&&om$f64Wf z1$JDwGCMV({M=r0#={Fm%n6ZIAioMBlm5`>{@Fb)E>ck&Z`b1C-VZLyff1X7gT|=6 z>#TB<4ld*yE}L^xUbv0K8+Ga5Yii0Wv3?CJyN7xvMLCob2yrLxrt4q^drA=HgF-vGyF|stOW`iihPP@w;17co(#3CguFJuoKbDn13f3hUGWI*? zGiM3XDt3B=)$*!tQe&VF23%vdf*IxS-L5ke@z5l=URHH0yN@r6j5OblNdO9YsPBE+ z?JrGv)Zo*z=-?Vi^1m(7*ZJiWs-QQ@q&p2tuj%v3z_*WU!lbuMI0FbKayWJepp`a`Hp7@(lN$g$(I#y_##Vg+)Lk=Nm}SU{8wxF9#wMA~Hv%z+7Jtg}O2! zQR@q{tgpC)%=!b@v%7r*7G|3z>8aZn)5AWR-EF6! z9n-(zK%_n|uR&Q;9>Y38NlEc(09+U-WOD#QXbEK?gr3cUfGWfTuLhqKo|#`J?Jmrh z-QS)ttT5Ih3oopd7l@_3IMltBsbfgHzsE`Dc=-I3WauA0K19>~*DRpdx*78i64Z{> zGF+HDV%W0aBN7npYT#)=S23@j^2i1JMF-nYrT-&=uHI=Einx4!Ffw>BYIgVNo+BIE zpM@C2zcxMVrF!qS@nnhsR6KUqrmXbOUg&wT|G#0%f0Z8n`vL!N3F&vQvTeY3vebWA z=LH!VWiFp{p=Z(FvK;bXSO3?ZWZWJ`mZ&yLhD%m+QRijix>RJkHgER z0pHF*`h4{&1EK{o3A#|UT0CkY+jL^*+gw+oq!iillnhz1f(1)r;3OdPAETi64(DGW_01K~6xXheXVVy@%zu(Mh;WL+d71gDhx|X#wVpd({VU+m zcAaLOrQ%6~kGWN9{<@7!#+{NaM)V5%xO;9Uwa{h+H&nFjb%}PKB5N;FfIIK+ zud*gTXDlP9Rc1eh%*j zxW-;>`(@cc?*0~qZKQo|*3cyJTP?dcsgzZUl54u$)P?(ZG2Y5)F^B^cL|}?15nLfEd@mM}&_425q$K+>-syA6o~9%bsj> z0S@ZE+@Kqgh&_4R=sP|W1iZ14ky9XfG9mWWI=UR{6}7xSs0&xlkQW3m>p3)#Ndvgr zrIy4E4)^6vM_^qHA*~NKk#k0++eb$1u{oUe?z$gkQ8Yn~koZ&?f&$Yhn8?{8w!uuOXuze-^=@O~*~m_8cu-3_q3ZEF*FJa45{ea$^<2hJ|K^iP^@&eWu1 z>%X3D4HNOWvBn6RjHoIpC4>0;daojZ5lKyr*V!NkvF+vj%=hmDVLyDPp}ZBx$E+n4 zz9uhdYHD;VsVFx;4DpD{L8y!C3Z_ey$jZqDmX)6I>M(2BxG6?6*fB}J>+GskWo#rBKFzP{cjs^=q zqaP-oSs+)!IIFBbk@R{b=o@zXcNmh#n-8nRkyDN+rRd?}q!^fez6WBb!d#pqA4M#mnT(-yzK46db3qX{Uk)mT{WZNPld?RBrGOqB$p^}ArFg7_H zA9#f^UelQ6%e5qaQdV1(95SA^9IAVzsNSvF^0~CMCie_+4wVp%9uKb&4%u7EYxB095S+eQ zW%`4<)0LkNOmcbGSI->`<2l0Txb3TJyL;b4-rIaJ6De@zfYVPn7fv+Jqv zr5>=9^Z_0gttYhUa<-^QwG5ZnG(tUR%&b~ZFQcsK{?reJ|NZ=%|25aWuuxK38hiU5x3L>(rupmt1;bWx@RQ%Be{rXyO|~`tQ$z*omFHKOm_<`E z(U$gO6On0s_E7`GH|*w{eh6=*jmQ4Is$-C{bH%t)yj{8>lP1#NXYGczs?>c#Po*qbNsV!`fuL)fMGz| zOwKu{P3S$k?JFoVl;86KOLPa5lfoczX=$3V<(jT=(7mR=o+4+jd4?ntHj_T+O!E z130@qJw4OXN(OHJy57l;CvMeA*@(E0YGu~A2WKa0#XuE5(;UYqr=10RIh_yK7K|U zMyQf9C!8*a^MH^B?SN0WcSqUTWHg>iN)vVE2FWQ}$oRZ3eEm~O79JmfDw*m#eX}&N zh;$miCm=*n*>QSRAXtgG@Gm<)5C$BFKi#E`nx0=>5%CyHOPcL~h&m7T`eccQz}-E9 z4bjn7n!9yR#M|dS_uq#`UZH)O{Iq&>l!AB`Xc73tLA%q99FYR%4*QN;`6Nb>7nn*e3R^N2i_!TraH0(bs2tSGXb0> zP?n&=K?el|NrdCa042#1KiD{N)i^s#gcB}Qy4c*w=sqTRdetJk5QG;T9;+sjI^pOq z#gmuRE72mqp7}asyU!WQ6u8_CrRFKsy!K9_<{6O@j+H|;M}_?+`Z6=u9(pRw zU}J!GR<$t3d_U9jEjmT`Ogw4Hhx~Es-Z%okZd?4_7dx06QbyGUo{Xs# z*s*tCx0wt%{8pr_7lMZ+sTF(;rcm~XoTzr7W?F!;3HmzM@?Xq@exON)vWX?jZeBQQJl@jl;8 z&+t%T{L8rJ$5-=+U>yC&|7Ur3!_R>I?c`x%?X(%Y0s$2(L? zSz8^S@QvqA`^;q0{{Dg10&icx)BqC`WS}Xl`6`1xZFJIYyxbvw z4y~3Omlysa;P0B}+<%`@saYnVxFlcp=RxhGQ)X#~l31?En5jrfS9*AIe#zCAhO!0g z#jJ4#+2qjgsD2qXE-b6GJkg?R6F>E(Iq0ySo^K$$Wyh6#ri-c7Bq}zP!m|ac(K`Z= zE-o&BkWWc?_0P`{`D+@ikblVMaeF4fx`K018Vq>gUJg&=l@uG>se&c^=3wVM)9B)D zfp?+PpB)sn%=isruEr)$pWW+@PgCP3<$<>A8BSO_B&6qLM9o8{v_ zr%w?t*gekJsvzN_B3t#lg1b{cCrd$IZ8X|&D6IU0?2d4H-P};x*rZ|7swz03QYEJ( zuY4jWC-=6Q!vcw|1s)s4lPrl)57QOjyfke-gWr(ES=l;`&X4!5u8O2O$%qH@;e+)?u%nw?fYN`gkP-n^CjU_@Mr5D}UT$Ju+uP4TM>4gD6v*Vk4RK z?ys+wyu)Xwc)ycSbJb_{K~BM9d|l1dcR&mr%wW!2e}T%myw~+1jvJek3LXL8`|iO7 zl~Yrz*OlZ07CnfNnV%V{m3z#90Qib8?@8wxG0Fbp7SXO(+sFJ$96mRUZRj-b6aN{J z?sk6^A7My{Zq>ahKQB=+-xgFNqNjn%;p+N@M(2Z?PlcK7zP(SLOC1YZISLOz_W&}f zT#cN-&+HztGNt1QjSHpR1j6M4XZw|AW@cF78@sCz-4G7`i_Bw`*1Hp1k7rGJf!$SR ziYrApP+^p5`K1LfR}i5vB0x~lLEvd$u?|=1HVB=9x8gkV1_6sIrZ3Ez2<)TFV3pQp z8`ODzE%F1WQ?b5uDl0WR`{kc0?eV>f5rLD*+3JE4ZDp-ahr~v%f!F0+HTY#agcGWF zUNwhN^QEO9CTTB}n8ORKl_b7-e%E?j^2em466K?V7amwYcR-IEARcGvo*%KldD&Gm3U_ zNTv6g9NA{=nM@z|Yj~-n?6lsV`WuTyXZ=G1(~nJHkY!v{osAfM@oa0R9rp#c=4r$o zU~3-uJ~4Sl2O4B6m=zu%{iuDw=%KSsL}FrUlADv89CVPHJ_#HWre^)_9DDQqjRRIT z8M#6qwAkMWa+w8NMiL|Hm(GYp5C7Z5SbH|>O-(!v4fE6Y?wa%S7DYvamG41=C}@%F z(I5J?vljT~yYX4@Fm~TYXnGeXCl|-WB$aaC5R0W8;906B*1>!xGON29jZ>kN;*yB7 zlg<{%pGEpJ>VAHy3jwm`lqOQoHk|c#xaShS-O8dK)=8DGaRkj(i_1p?s2XS{mFK~+ zy=B4-OsrqtD&nFeoSXB7b`k4JM99u><6DXSYZh>@eF-spqv@%f<)0-8f#($%^&`TY z1+;*dkr*?R&mu3;KOrH1{w_}C>vC{x`vBeWsa~Q1S+drn7 zqWw^Z{Qaw&$on2F1VuEESdke58&3=J@@2}JYc})Jyuktwrt2kLaGq)jc-EAONxqn) z5)#VhFfASK?wXt1!c(a%Sx*ak3L1VaVzX&Ep{QCW@;n~}o@n0&I}mBv_VfgRve3ep zcbY}5HCE_w*TZ~QmRsGvOUo^ucPoiHb*RHzXF8u(ZqBe7fRZKd=PQMFK0cRAH`<>% ztzJJF@jV}IFF**AoeXqtFi)|zj~$4hW?vatSnxRYMS}}}%tCoQI$jZZuKQUHClElE ztA9p&QG%b*UaupNsU)=y`K@X8+a=-87VQFMq`uuGW4)OUxE_j?Z_`7hDFeNR(5C}L z&mAy=)1aj(YH419c^gs8Jy;K2qZ7hOq>K$?pQ`VcO@jWTpZ+RydoQ;VA}A?tZGLw* zr75#Es6_zuCa_K-Kd5`J`HSwA$fLT?6Ar`-M(JWB+Ol|%C?!k;rKn(%W$zF}xeaogXj1~OU(8q3tXSG~p8zLaTh z*0Ye6sjfSrW-OcX4iVgaKV?)b*(o_W>G;^F87aqSCx=E)V1jnd+sW%NHh11J`2~<^ z2j%_tS!5ICP3%I$cT7BaB3v)kY1csOzcDZP1I@Nc^7177ADrKak?` zq$*W3XYO8A1ly1b`+kMsVCcqg?O7oIVsl|3c@s`Qw*)^)rU3e+)$ zvSawXj@!T3MfyGfYY)045p!STPe^JOsD0)s7Pb2AI&YAae zJ1a{({C0aST;e;iQ5YzDP38Bbu#i=`BM}Pe)*t$L1hz3kXF$c4o!c;7rLMXSQnS?b zwEn+YamEM<2_qCusi^5nJ+}zV4Ay{{1O|z4`*3q{R5K4WrdV%BwAtnk^WGuanS96N zV0cG7GPtnN8)P{_$mKysL-Tqa2bDnZ$|wHE>JNGib`*ThpPqWM$(%P=>=jWCfCiQa zVok~jlzf?jzxZMFIGHcDRx(zt`BZQdec4a{|B?Z!a()+?}HjO zblO#>y{lsOuHy|ZlRg9xm@n9$&1~d3IVMBNR+hvjcpqnK1XQH#;XPt{*N>W?_^FuR zBqX>$-B5CVYg*vq$}VFI6;FwXpKibrkul(qP39GH#lwXE%Gh$;3(iK+S(V$F(kS3Xb_x-+V<8 z*+u5EH@Iw94CJF^7=h<_-`3&E{ZR*6hCH|-8zu?PB9%{Wd%Wqh;^4;Yn4cl8-1s#3 zMZ>84hJs^4R6i;Z8xGMB6qkX{ zkISv`#ErFS^metVtWQdP^E4fEJQE`KZ;B}Gv5<|ttK=@uKi5c`dECh5RL0j>vty5W zdwpplPS`yYMw7<~=FG^m`NvEt@}{4^qE&MI`TL()HN zjdk^7)&AD0o4(!44nj8`Ozcf(DM0h{Xu*WT&l^sCL&W1ee5i#Dy3B63bY^A-4+~gW zlHwBb3k#i{oyC2!T2d!kHMOj54KdNskdN%o;JiZ{Zj{&84$iuXlIFraZVdKRNprwt_7y|K5yx{!)27v&x zfYf*(zI^jyihH(Do<@4>0~Y4#diCcs<=QHx=-?p=XEWAWRUL27@uSvZn-e38rUmh= ztXDDWNSN1P^Xb^e$;nXAvPc7-?}&i|R15S?cbr=Qt;NlNrsaa}xFDLXA3%T-*eSPRAaw{h6Y zn)%r{{J$}-%)WkYM)JW;iKmTv#8Q`0v*mvqhvQFG{}dFM*i-%=u-2A=WWy9TRCQEoQQ<+@vph$QwxXt> z>}Vtn&eGnl(aTDVoqdEeQay3d%6C_Qn2}`1Gpp-mpfrPwY}5YQ77By}Hp}<_g0sT^ zgR|DA_Bn3Y-%r%35!;G(Ar1@;$a=&o3Xi)W8*T1&kVYv1BI!Z1!HrDIxPh7-z zsj~4EW+e_mE{+6Nv&>IqnfefZzK>UH;dmU@sK;|H{($I0a3;l>Bb5j>YrZZ@OIzYt zvc$p0yPIB<%g)YaP8a~mU`KoTI+;snX9BD0nwpnRA|;c&=OgVxet}h~IQGjgc4}91 zuywxThXLE~0yP0<(7S{ad=T*2L`j&pDg{_-L`KJC(+R~W_3NPQmKM--@sm96-MOtx zUhW_H&>xpKBD`=MIwd+w+zM07{2?Z|l~QUuFrI-I5yoV+$6)%mGA|K|3rap&=4y|= zB=5=a3CM;GW))D^lG?^lF(#!rG-DdwrtLD!)!GQ)L+}Hzbh|G`&T8Qn+m05@#Xl(N z_C@ysh;{6@cuenu%zHR$!=ImuDbqf$mP-&F+c~@hj?MtL3IZA zIHs+$bqj<~F0H)klp<*n8dN=kE$4n-np^PFu2V-g%LIK(RV+`td@q{s<0hD$7h@c1$f>eHAk^Y^l~+ zBI!SH>F9gb&9X1QI{KOr*oMChz17&Ei_(W+;`W!dc`b9DsxpDbm)p=NXMd3YRq63B z|F6}l4N|Bi0($|TOpeUX9?N;(W^H)<>AS?K`--2hNdF*l`=vHgw{9wgUt_T;e$>Xo z!5Glj(aG^2T)BmYiA#ckR8du#<7T`+f1#uWJ5+p@ z_KuGF<%#`kn}=$0ZhJrH^;0W#PkhP4Kdv12c!AjBrVJvth()5-Vhm!}B>Q2i_TAHr z>uo36_5Pg+PpJ6S1%hcxE|mZZEAF@NZ#bz|R-so*N%wSrz!}L@HAVJ5A#&j2MEmF; zD*i=_@_8WV?YK~y?r0^sjEzFQffDk`DkB*+FR}3)o%}q0eDs8X{JF3HA%*x!V|FT_ zYqxVx!sdlGo@yx>@4K~^VP?s1abgK_Fg~5E7*Rw?wQ;-Y-a0xoMMaUu&&0$igXvZv z7{U>1LX^lk0N@a?qNbXU#}8Kkk%T(0eL7!5K}`eoCzow{0oHDcTs%C1fq|u-XARsx zJ#Ls$MYX+l$Sul0nc?!wD=z4rL7acn@p?1^txzMn)$w24)R+?x1-x5##sP+6?|DGPk?iQKL}r4$l`>cR^f0A!k7tD2K<$Ep60Ro_$bT^bpQ-q3?D3Mvo_V6d z>Byr|uVc9NUfOlUGD@Jth)K|V;@8q#O?P*9(y&;DJZpSFFCa|0r|-|UmNtdEdLcGP zN&Ynp=%og$H2HFYyM6RJ#iM2khKyQoZ&j0Q4)!0Oj!&+KGvL4zpWEY8)~Iw6JLu1S zW9z@NzkDesab?k}>Q01j(<+8cn#Siox!mSgSy{Q{c4u{cJE>tYV|ke&vi`N=YRR1_ z`06B(s9mS0^2|U@?PRJ<2PJM}Tu#8J44a{oHbyFFXJvDH`MMnp3!$MC5JZgFocB5F zet=5reS>g5_{eAzED#ZQFb~>14o5uM6U^p`;?;ETPUG0rZ zewYkjfDsXU-|wThY2cJdt6P)k7tZy!R*7Wy?eR8zCXJ#Isk!=w{Cb7Fsa>nPnH&1k zi`0V+rYoF`AFDnokR>Y!{-wC%XRpr3)Qurkx^Q6QPMoZj*ZwIt-3z zMCI!v1xgmhvzixPTec7n^p}Rw2TB>Bds)zab4ls!Kaq;DpPYwwrf9_>792>e6?|(W zB}E*#YHXD4FD7~uFYT%75*{<$q-*iP+3WrP0CBQWQ&4eE%;uI5HGt9L>}(=aIr@$x z%r-KqcsP&CrlCYaULIKvIi{^nB!*I#2AqrJ60AR=+hv)wR?WMCYBdrG$H`)5Wu6en`zf1DhzfYX&{CDH96v zoITMFFcmO&%(3A{4xg$9;KA@ILrUKkZM=dOv0nMM{OxzWms%;>pl}cl9FYNNph&5J zZInb$LL-#p(jc*wu*~9`s?0VwssoX-J6c?=*e|86xNK3H0h8s8s|v;ZQZo_ zJ5zMb_U&VP4;ty)AL__8StK(v)A0TfRDPJ@Q`~1qEl(>cE{ksGqY}jP+@5Ju)hNe zT+IGB@0*RdHX$-4vBJ{QN8^qFFf+g?JC?-QfBJ#L?3k8lRg>--^ zG(o^d+gi5Nb(zWVV)5?DbL*gXKzvANu7-f$BYQBYw#D;Vub}O{77C7=kFU$KxSO?S zr>`f*r|Upt9vFPm?(t*FXG-htjca**p=>5N$Hjb>28#6 zq`SKtqy?l!y1S)A8foc9TDnsj&S1UoyS}y8j&JR6f9D)8{*_DTGv_m(F~;w{Z-bnr z#A^}Mx3CO3sYO9=U&e=Z^3BX_25!b}y>wObFdVLMhpo-JIQ&p78UL-3*sdt!?CT~* z{zd@};39wZN&c0*O+MKbM|n%G>>mqdJl$d7M@7W1aedKI9mEp`P3Ywp((XvJGb2K; zfPKJlSQv<&@r{eo2$b}6p^2Q~WTjs_L)j5{d#k>cF`yqwhYQI!8U64{n0~R-wKn^U zHw4YFGJEdg`l6F(d&=I(P}}#R#IxBd6=i9Cp(R~SpDbRFFE6nVA5FJF5vfrsM->3KHqiV&WBTON)ugUd9W7?+(QL=2XJT#+n&3l7c zvRe}Go8L;E8KfU7=i6vebNQrp6HgCOXnH8d>z}z7{;a8pDxMi$Q;czlKZ%1X-h?3j ze$j>n;g{3!`wJB{$s_DPm2kt+`7?yb#@9K1G@PwFq;jTOp5{}wEaBIgR^!j@vnF|c zcz=}`a+|)JEW+kI;_gXj=XlLoq35V>{OLXUn1$m@Ny-S=CIn2IH0wb5OlF)akC67& zm312PZL7e>x8&;%4O0YB?77c)UU>Mt!q)R(jB6cq~ zMaAbIm4G=`MP=$U;p+aMrCBr<$t^KFUbnB(G%a6ZI)0syl9FbUt5w7fVW3mC4_6eG z%ScIGTwdBLvKpJ1bToG5uYZ1N<{TUamL+55i^?z^G{D9I_CzBPi6F;=t*VIo&` zRrYwQz)NBpmgg?E2QOa?9BpqW>dHU!KvA)xHnO)@aB+#OPXHS9- zWjV7onUR2;@b3WOgv>qo>#k;R;g7_FKv`;PdZwdHxoB#VrVaJ?@AUL^@rgpBKLAZU zywvpcnAB7&Rd7^}Gz|GY`R>jiY-optr}UUqKF)nBD6X38f=`n@nyDZf$}RXH3+eM(BL!Q|Qm4H-8 zOJ13JH}(~EiRBeXF50ib3aWY0_tj!n@A5^zFoxj#=a^!Xq4@1X9WPZ$zJr)yr1FYI zp3-hIFl3Xl>}Okl(g;}BAX`q8D?g91+;z%&L8_b89?r;UMT%`_UHM4&1s&ZD$x66P zsJJk)0>dLFfTeFk`Cl&BdbM|yl(jG_S}bK(TDF!F!*K>Gjx9vH*x6~_ZJ&+^c+}^d zlUBYTo6Mb9oVPP^TNHUwSzexhufCuY+=2*F(>P>v@dvii%%h>hh7-w?Jqs46F5iP$ zbRvJ13zRYxvVZsyqgiIF$l+R!*cey=Rg{VOpTml*eL>|<8R?cvN63GNEZUlS<|)wZ zoW?19*R$Fq+8D1Ym;56A;ASEIYsjVEm|5t8bJ|8b-m_Z<(1M+9N-GWZbnm~eTtD){ z`RV#xJ9qVf8AE*_G#%k}?24rZkIuIvXN>55X+jA2#I?L;r(s~k&;c#$KPD7?2JiX2 z6IMp;uJ-5a;stGjR{cIrKEIbS4NruL^nM2rKnzU`eVb2bTrEyluurjz)a>zkE|q1b z{-wiI(eY8XBOJvR9~a?qWeGTl0Q)SV*s&lC+)Nwf>Pr6i0sPm|IugLYXdrB0?mk!1 zb}xQT$!@)*sG`EB-w7QfU&w*CHllm=YeWEHJu;?$!>)IbM*f{B`ufsDqD<3IriBEX zK3rDLZ#_QFo8~(b6gtuG##F#z(T+g%{q5oOlZKPRz7mc(iEBNhm!O>6?>Azzc-KzqL-24>H z2MvOdV5aG?W@<{tO8VzSFLrd%is8PKvl{3}0j}eQJd=`oo#pDU7XrK%!sYo9;Jq7u+`x+_ zXPceSVNl)Tb^q~OP|3FfUqL45KT^D+at5FS3XlfM@s6?nrH;^TRFK5=7w$}wc9^D1 zMUCq>s^%&$-}c87iuMdBNioG%;^zL=eufD7KW_GJT&vBrp5O2=w*LN&R8gJ=$cb-x zDlc&tAN`UXgGk5Uoz2en1CK3;yI>Jw&Q$15bz2WD5MgVV@ zjxj8?-rpx6fI}sCDu$jT6TbuOmC5Qj71x(f<6~ega?a5B90?&DG87B)J{!&-Yr&+X zBt=5c4#)5O^(S#sPF915HHk&OmU-JCi>}RMjb1Q-2S#_~lK4#*0*m6-OitWXm3fsv zf%C5(*<>sZN5bY`g@2n#F5!wxdgeZE}i0pt-FuTI3@uD*l|q|Chq;hmRC@XO^XLRWRXN%qx>A<{lpHE3v{5#XB>Ao8A`TO)DHrAq46VH z&2}z78W4UyE+F>?MYa}hL(t@%-p$2rE&#BWQYLM6bCur1cjm9X0Ch#>2H%lL%EpDC zy^K}5zVVW{gma7njF;<`0kOfF@4rh?#_90-nk;pOknkGclzxSGI2RR^?;~n^G?Fzu zT4BBLQ$EmY(jv=Y-GfiG3}ysUe6D3nriOLTw}B;DtQ!ES-9#MaXb4d_0_J#e{aP0p zYQ76s8((8`N=k~y70ZSF6a50p-0rFiqC{{8h{hPj%M{bN+-n{)v)Ufd2}EyhU_RmT zC|DV$#e8wNYS-Cz{?--#iMX!~8a5mz+rnGh+D%zn;t*bYanTSKnfZCo56dF1BwX|t zJj{pVK}syRJ3e4y66w^Tm}XGo6K+P#7cDhSM?ObNM^FkHwmH10Wt)n}gdU%v4!+cK z*#ungkaO3>AY3tGNSBOc&1eO2JUbx`vT3AlH z7a&g_7M5ge+zl5>zp)!Xtq$<3=I%R4NCfT{CXQQ+PGdZjrM6Nb`5djqO!4^mmzwJ8 z3L%d6&QTwC8PO2{GQ`lEF=5X3#5_KG`hfHutgNs7*f?SLxqjD~2M8&1duqkpd#xBG0WtE>M2)zCg4C{~Lh4qdMr-y;Tj=|pL)2=VIL>iT-ut7TW+ zgm|nF39*nMF`I{rUTa?)JkADpNtoQEH@@$Ld=7gqGE`MmekAf`FrkFN8n)KtUftTZ zeqcwgNeR{bK0Pc;k|46u=f^jfG$TtSP-VTBKaC*%iO`dtZKp&|;MtJD0918hY;>Np z-JSlggi%2v4t+$?>B&j2wpFC7JKJ9glJTTG;T8>Y`c?12=b!Xpp=b_`Va>taI+E}? zq4UE&LNryTF}vNd{71jNkvAv@neSR_mzDK`^;Ax;l3FqrmxCi=kLhvY1 zj-zBvKYpLyL?%J*h7wv|uk7MdPl|pXh>#xtVQ5tzffK)>#E3cj7VQ)baqfH&4ctP& z(x71wdd{ULGKKBv`$>R+^&MjQk7EVHrVUau_*2_w$YSywebF)EPG2K)D||=CL_Aj` z&@twg$NF&%+`Rb9jF%8Y1`QLxC_oW>>1fbrk$UtKF?X78P4m^2l0ij8p^9#WEqpaZ zqO^$Ku4y~lSE9y1IQy-ue{Sk7mPJWTX>oRxcLBV?>a&{z7o><|2lF;r71hbuNvakUVCQ_2g1g?f-0%DF|W+`EPTxG5h~1Hw(36Hetq^ z&MA&}z@5gxNxpyHZ#dfEw|N@$1p|LnN1r(P@GN*SkmnYSkZIdH zHkK3yjRAoOOVQ}C!&@^ZGZ3VZquOD*@)bku+TG3~nvS)3c}(PXiG0 zaM(XGC-|o6eDbA)X#%_EpBOHY$#gC2?qsH$9XwVzsEF+!5@_;hRLh{X@8FzACvJm@ zv(aj*s1D5FoD2cS*syaj0@B|MyOGeJR}e|WJmPS42i^|;PBD|Y&|*q2c-;kATrQ4x zZz2hGmJsqKn0ci@>l}2Mf9>w-C@O>cc(EeQ3&!61v1$z{M#@&f=oGPCvQd~!)uN#k zRtq+YIjF`tT=`lHOTY`$yoO^i$!sOyYrtOWb||W;D*Z9v(_==yu*ml!OZ;{GlnQ2$ zJD0MgDM$TyEGc!oMxJD|*HZUTfUHCbqL2p+rx?r=nJGLhVqTY&MOF^F%z7gexX3}- zp*J+vR++&jVE&zyx@L}i>6@pgihEz$jQ$3@6#%*vVCRi;todDabqr%7BZ zSe-)L;^r2Re>NEPs<4C{9WmqmHC-)I&C;m@%TJ@FNpf4%zC39Y&1;dRDoi|M;g}FE zpPSNaa0R}wvp;wJ@RrWT>a)ClQLg(yXiJNsn~{^=+cOzfJQRA0o&CREAB?jADN5_} z)03k$oy^2HiPFY{z{4_Y=A8o*e$JIC0loVSbNYk4zDGzMToXEJ_6-sL*H`48SBUh8 zYD>=A$V=6m;{F;_blbG?h&K^PRZKWP68%I{wHGt7Dsg^*lnFk2N>65q=FPL@mkzsA zlvtXBMnfPv@n_(9aqcIUP_zvM%u`Jjj;XIA1cuZC2l9QR)kMup|8ra+*!D!Vk}2@? z=gc+*%_Z5nXcj9LNjMLeF%39b@ML5IngWpm90A;44K9!l!b##KgZwvR;e&>9xnXlINl3dONJwr8|`79kf zrb+F>zvPq2gzg~)FL%6T2Lmjmgj!r{ypnbTQ@7}PFmqCOS ziq?6CnlB8J@aUnXBAuiN6S1d+OG_KZ>z`+WZ!`oRi96R92D{7LHzotaw@ioB(XlYt zEcV^xh?XN+Y7#&7Ru`Aj!8vzLEp`nrW!>v^i(TKtq2wju=$%SKD66T3eK)XZML56v zkz60$(cG9=LN@li9*J!%zc?HJL0r7sDcwzSVV^c(cxGA|V@57luU&B55ay+`NRI_XI@gwgVCgtO%nI$(YFfnIg>2{%lJR10@R{?Z>{l-vs67>e?!} zM#-#jQO0hW7;lLR{)Mn~f|KON?k2=hEs!^)5F$;!kQWzRT(N6lC?Dz~ab%eYiNN36 z_=Qb~`D=UO&ZWGl{QUehOL7AnozC2>A?_(Hy$Jurp02x4)6%2DBNOuIv%K$=_a?PN>#TMaUVSwOdusVrd{muGA9 zI~@fL4JGXv}QZnU5#iWOy6bubuygCdA z)f99e7tWBuELx?=Cn9U6hU8dQ}raRf*$x6aUeG1-t9mh7Utg09z26N5xxbz$! zFH5xumFUW}XCDS#T}Q*=WMQW_p(2=)z{&JrDbjKPaO!ES{dp6nBOww7{~IQo-mG`C z!|W|lUR^#nEt&T&l;f(i(&vl<95JbtCUMx?CboiuG zQLu@2iN3z@k}~J4k;%F|C853oGefS3op|8t=K8*NgX3(Pz5W$&>3qwCO|Eq(PcF!C zLXGS0G3Gg<%48NSm{`Spw?N8E+d4-jg{@ybo2(k&+si08Pn{JU@(JfnYh4q|nMSfZ zZL`wF4dIcf&<#4OY`JmwHMGMK@I?WBjsIW@rE}7K{H8>UA>(#*EqI>0GNLRui=T_R z!$6gQ;tgIzTFEQu*VKUD_DGmQSwqc5L9`y>=Wg0tia z8(T*8OJTdP{^#s=(7k-H5_ZIousG8BWf5hN8n_PEX;dPIzz+3F^Qs~%EAmOU6z%)M ziCcvFW$_fvjfVB~nK@^{Ajl5f%GQznQ_!veb&)fLa!!4+%KzGLlDYO)2_91YOHJ(QY`-Rws=BE?r!dOK4!g_Yxv;baX7aInO@ z^eL8`Y)l4TbefnICt~r-D!o1{P9txt12DTvSz>>rdAmxS`aH8RTmmZItH z9iUS|cF0DDwby8x0oHjSJn_8^Hs(D(Ar|HHPyjp;{gb#m9q!A^|=UN&4qgaxm| zcX$DTWiSw5rYg12olW{y*RR7gtQkg{HdwWo!UGbI1Qp%>fO8ktdB*j*+lhN5Z<(~= zcl(mJa0|wUxm0xFhe3?!19-3C*O&a1ly8_GB5R7pMQl|$sBXdF%k&bpyoiy%8Vez^aGqcGSw6qYiOSE<^RCv1s@>_Q z%Gf3%h>J=U`NsMw6Zkk^sRTRBCkBj<)*$zhx|L8gN5rYhi?md%Z5BPTKaj{R(?+PAv(-RlW zY->sLR#8z=bU0PpYl|JQ(KSBAy19&UKRuxuFV~J^os7caH@J-?IL_IowpSMYUXbAv z`{m1TF!j}ZGhg!H=JhLe;?e|vyf-H&b~&M6x%vl@4GBuIFr(-9kGe(wuOgxHz)s02Q>Q8*V~Xg+^! ztC?D;f~}+=6{!w9lsVb|kmJrX=p@bdx`)C=HZix?@7%abaY?zphJ%F;da{t^DLTKL zNRB*3Lydq(2w!n%47zSS*&3vo0+6hj02J>d``3Xch?ig z`DQKQ)!~|LiGIMrVjX+APf*#%$1L8o2tJo@0MD;0*2g@5YR;vyNTXT&0d0#{Lx3f5YV89 zQsjmj(qaZm4%Gl9$&%NzUw$&8hcogD81v9=cYg!BlZUs4v{83(3t(5It)D ztPLu47qx2f0$g0zU>+4rG*pN0^nSv<@7~IYBH-y6>!{4n?-?Al?14h_x|u6D_w-g& zRrR`>a`SNGY-|v0pPz54o@7nlLA!R{icCwW(Bhg{sJdqDam`I34D82wUs&Ri1y3f-$XIhtV#v~DmBB4^Y&SkgQ)95jBn#+#R0^l4!l1Ab$$pSOnlQ8mzwqL1!eD0;y1nal`PQIH9#hQ`ElDx zeCxUw8K1@8LQ6;1L~(7SZyO?7EXA#fcx)>uqGf?h=~yjKxma0pLX84bz+%#jHZI^f zYyh+Scy3$0wQY6Ix0Ktv>vhWq&;`BQt7yyoMasZ%7{OK{&}`HXI-s<)G)bdoiA+BK zSY8%{*&z~%O~^RfUE4qSb#{L#@IhNL@eup10&IXih0|= z&*_a6@;Hn9CxBTj@ABj~P_A?c;m)vttD^H>{%vCL$w=B8T54)|n){--0)YI8M=Pb; zY+EOCxT3zSXvn=9&FTVdGd{mnVoAwfd|+T#NYq>M88n*scM_j)D!p$}nRbc@TAEuZ zBQxaHRccK~2(P$7QE(+QQ!0T`1k#KU1((GQ096(do9m%3zhz$JD zD|G2zYX}X-uzXx@16@M|Hhyo(Z%i)*01%(Hz6=(jTk3C2Zf>rH5+=uTdJ73wp;uY6 z)F^V?ezFXlFq2=-&(Fn+CR62v4Gh`}3rD|>P85vXos9@sBOd>F zQ?h!LB@*&*6o8h6Dj_cVp$P*Mm&^T>d^c0O5k?vo%ED09y>CnaM(`(Oi>8uCABo=a%3Fp`&Ho%Z)x(B7H3WY@sArq+Iu!t1k$A ztXCVZ-QDFi`@)QN&*S{EfwA9|$sfY}C#G8EobdrCVuIuU_5X2=ZJD#-SK){CP|EiDa66Gy)1FgH+!}yCFzH#-K>6qxRQ( zuCuV;@fLY_->5bF0{acwH{b3(-*u8amH58Gj32@+=pojqsBV3;n&N{fONKv3>T=PI z=bV<@VcZbu$h?b^7t)u3GZSiwZ49Lm&@8Xx-KeUx%*!`qfFQ(Bd1Pz)N zZMWbH3R2RW5&E`C<+!8I$;AVCa-|EsM#7$52JV#7VK2f&+a8X7#+T@BQ^V#)6r_9Z z0DUG^6u~aJZ!{I^!7UYS0Ddl6LO&LR_gec>+Cfx`+lHbwO5+jOhRpEXx%k@WgOI?` zuJ*U?HW8}+k{B`i4Gi?|#bwV1B@WqWGu0u6cPIGnc{2E@i1KQbEp*DwFMcuUEqKk= z11~48QAASGiM}q3=2}qjWm{-Jcf3L41(bIZXroygd*l>Ve-NUAy<+;VDykn*M4(4b zj<}YVMic74KrtDQxp^A&Gsj{kP8qj(^j09HtmF$`2prR@(2I*jKuHlK%Y;TX+Y3l5n%E=mD9G^Q^}4d7 znG0~-I-IRM3qTXtFO0@|krKsea-N727mBot;Dt)aE!ypSwF)xCX1pKzahYV+ofrwi>e|}tKf2;uunDdwYeAONrF^arS`tCZ z$-x};k3tIV@z)?eb$5RUuOwqr2J=Cd*=>}#0TR%D1bNINY2n=iZAN3+QcTtP0lvwG`?&(&(4d=kA$yw8D#nk<}9ldO+UN4A*MO8tWP%7+kZ zE35sd)HWrNaviYW$jHdRK%_Nb@)k6vbp4m1?biP|v|XFk%KguwZOPWgeNx-#Yb|l^ zlf~;QFI;$hCk7~oH;K@w3Ykn+D)4DS90vw_>>X_PDbntK3*J>J-Oq3Mw+~nb8o5Tk z2wIvs;Tc(u?f^EoqL}-1)zFIhi&*RWTWRywPfR%Bm+|aItRMWJbx#k}5Zj^iZGL=B z%*6SIEMAd=`oD#_3oTsOTgPK=Jl?u^TVg=$_RQ#N`A&dRC%P!NBF6_XoIEuZuj=JP z#SEOPBjs&_gOWTWk0V0@gSkU-q!-)-Y2pF0c-e-;KYZmRhr|5y!8Q_MZO{&p3k zG$Y|818?No3gc)(jF%yNh3V6)FQ?N(tF25yNd52=Il@0Eh%-VYV#|)59XTtcEeWB2 zAL1WMDfJ)I+Na84pYrRpYw|~)-6B5JO{rR%+LQdW{c;NZ1@@DWxzJ}4k3`$nn}OkJ z**wLz`opwFM-!!((av-pPZJv*2G;y#tut;+1e15#*4o0t!bYN3TNz%W#PxlkI#o_d zF*P$oK}o)uY|;}J*qJ2~>>u;{LQR*0on2fs@LOY3?c8AR4BSJyfSilyhgHP;u468r zI~<%QF%Vny_fON(RJ%Pdo&pu@;--8P;J;a2U7c*zD0BH$zwE!GxwtlizP~#)!i%Ka z5&L6kNVoB{Xfglc*qpNM+2EHLmmM(Id%h;cXq+dOMe)~OfU&WV{!`%D1sdvTMBveD zV`@fnP!hznsALmIo1&k<`uqO{)+2eOYz^C#OUau=%j$SsZy;f>U3)zsG4jeq2cP`X zo3#b;6vX47wrxT<(#Buigcjv#Fh}?=@!=W3Cl2u7Xb7nJ$zO?kKhUG>imRwxRBg~^ zj`;43hmiOjXxfTUMmM&k-IuCY4~hAo`Fm;n{7taBz7LJX#+pm$y?;W1#t0Mc4p>%$ zm_7p%9!aa=gM?+DptGQMz~$>noW;X=#*ecR^FDT56KDrc!@L5e%EDJO<;H@L(d@(~ z{jqy5h*t8uRBraq7&9L}6h1|(Wf|P4z^c3T;Rdgv5nZR*On*-8?o^5VqmaYy_F)P{=oSDm^b(ryysob0Qn+h#N^L3%;l~l= z{a)u)q4Y))g=k#<*0fyRIoYLU6shk`Z@K;WGn-j0`9#~~;#%_ZUHLKFUcy2RBiM?J zvlF!fBA!j7DoFQDH1!QC8sdGv!MJ|gLmt+DowCo_%ojUN+(+FFCRd6*@m9SqlBA5< zdGj;8CtID4BtXIyPd0M+!)JM9&a~gSc+Nes_j$%4{hbpytY~ozO7>O$^E9YtgdHUP zW`RbhkPhzyt;xB3L>Dv5We#8Wwu8x|_W-}aTG)`$IG+Zo@B zIk>D<1s@2Z>&7`x7u$(FX94d^6-#F*fGt&1>wMs421mo8O8IDb><&MPQa(mP(ErM3 zZm+HRJiWwBw}~d_S&iKoW7rEU-V2RNTy9A>S2w^gn_^h56?r6J2agGBOz+XYLYv<~ zaQS~dkgZp_L;wnw;ZMs-#1!MtuKQ!A|K9|%g@pVx(th7R-U`5rB+%i^D&O^CbS>*# z+Ni4j?pG?Pf4ray@1C@9UbZ6UA#~?uIQO!-x##c`ByPhVPP$S6olCE zJKSJzi6$d9XjMNf!q3BLp~wgEE-bE!XcJNMzW-(9J}|iK``9Kr6V1xndB~eS<@<1^ zWg~lNS~gKx&=Q;A|rnB!(Gp(jgIvks3fJI>uN9qOw2Tt5(1s>RN4EGuB(;FMOC3S=LzXEL;#VFF-L z1KWU3VHsquLPC01B^R38O>#2m8m_Ibs1^T4mN59R&?gtef z9!9_9{l+eSrK+9&_vIy=F`R|4gnF$@<=90wX`l5oMb3|w0F%2W(qyN7IiOMk4zufb z9;06p?6PGOV+0J1vYWf3YF*(>=5o=XK947`spIHU~C%x}1lllz>y{I-IAp8~aPwTJ>EhaCDP$qd_W>t(DAf$w) z2%ONT59U33OmuJZ4vR97YmZlUtbbo zT}I$C6&4{Rqxi3k!iS1F(6jY7zXr#6Ym+;&4CR@?TNzA^DPv4=X+^+{758;p$Laq( zczwMDeZLkY@G_3<{aMIYLy;tR6>H4)Z+hy)-Y-kBy)nxoDc3dJN=K#9uH$B$C@y*^ z<1u{hxKzX`Mc^ReLWGbUsZh}1Fsz55v?6ylJ%3IV%@ui;TacVQkkj)9H<5<;ZzwWy ze25+!6(wXT>6E7>8y`3)w)>id#e#kUFN4NNi$G~+VnT^IJUpBajYaHA-Sdh|X+0u+9!C;SJSj^CcXK zs|qSPOIeP8A3iu+wgfY@8+xvm(5j9Xf=Babk9gJcyPU&J*FhuUdY24wbtT)@Ygl;j za?AInm~Iubty_3mdr3b4>DEV#F7OAG>co+WD);-Tvc74Ki5`OK?sr2@W#z@N-%wH4 z_jiR4S_`M#AhyXv3?8q3p_P}Hi}ng`IN7_v{!%9=mD8fbs!vDJH%-16oeR~3Og??; z@Rh4qQ?igk@>iRVNWPQt-q}#2!;0-Psg-NCnmd)vFI8F-i|c=wNiHWW#PsrOH+UE= zu}z;``NK@WY`J$WX*?2jsL528vA{ zDKX>M=|B9WdI`@x5LgVW$EOIXdNxpD=h_slG7}y~To2cmTx4zzbZYaBj%rF12NgRu zld*EbOsA`i;UgA&dx7-LOPIO;$o~68v;0Tw|7oGA9qwoD()>FcoR6{h>w)n9khh+Y zj*H>x2lv@%OrhzH=_&*Fo*p_$2K403g1*xVMi$^o>>D7ahI%W2vJ)X1rJ$~`xiab^ z91&NIlz48$Y-N4sz%q1F-%^?`P08nB#wc_X;^2MWUx0M#i0LY?2_JX4F>O=F-R}$H z4?-lXZ4V7XIhDKu^I;<)3&L2wU;+URhdjw!^0jhZ=;DvSJPi2GXJaU7vCP=auPW+58L}zfSX{WXF%L?ZepN+_ zlIf8jkIORX9B^-=h|;&?M}I3^{l(#@kgdJvGWVIR)(2PCPi3!wHRjdWnoN5~)|`S% zKrY4-y0D-8I5kNbStXlON;Ow1kOI7KJ>3}?kc5M~)#jDX-d{}o;qbmd!MM3?-i`F(yKb`qslhuf^3~S3sc6wskH#K5gUR z;B3Khr1SNUWH!SyN(Wq75O`*q&tt(oS5tD%uWI&ZX*L~BmYK8qWoQTNKIH9DFJY#ultwVsW3c1J`Q$tkP5&!uvm32J>HSk%%s zcEDXO7Ae^FAefV1v2UDItL*2W*+T(F5H>b8sRV{H+i2-jriUQx^pI1q-g-|*{uck> z1sn{FiIJ8qk4v|haGaJ6v#&bsnBCz*qn^|e*lq#a^Dp7A;C?SNnej3)9e)pvLx+ba zzJ+~qraImtEm1cPsX7~w?s!bk%$S02QEWz?h1zg@$CEO1WCisj?aA!nwqNG@6qKq^w5CC$5JwV(SoV&+uK20qM4t@%?_ygQX^idU<=D!cjJ*!s>!oI8C)gZ8#l&l|>O7v_ikpf^-JBLXxg zf{#L7K9AQwWmTQ|Ja?ftj3!CdDzr2n&V9iXyz9mB?1QOkoTUd|Qa_IQa&y65SWUBF z-{X7(UKZY>iMwt#v7%&On3|$o$!DBxU>A5g1<#H0hm_FmCbvU3MyapE&P(^#YC4FW zo{4EC{c>;G%v{~c#Gm?}KeA=R-(?5>6lP)5oJ0X{(R#ZJa{HKiwaTo1>&5Un4yniI zKw1RbQg=R1&cfzwgY`ZPH1}{%a6S5Rk{JOsPl_`MAy36!pLE*DGQ4b_*>i*!p(VDzU&l`3)c? zSJ$^e!9g-Dn4w13>1yqhf9(Z;-eHL^cn5>i8TqsWwkftrN?O{7n~S}XG#CJ9Q1+ia5E!#E>)XinVB+45v{>NW({3r-0 zD5!`xpnb@9x!?=77KF$>PJ*x*v|CwCe_Jti3T*@FsI5d09Rmg2H-Cuhh3XL+l>z;( zu`zPE@Rwt!^?zuTGUf%On3bgwE)tEdf7%%>j0gKdrxdEWH=A@KJJYaOA z>f+#r^SJ^K$WV=|gN*#kK$2iAwy{DIAT$c0a+u-!8w~R;@6vBWHx)g&ySX91;yy1b zP(^p`NvbwgD}B%J@V&2o*#jvMCpyfAQAVQuMOALiWY^+-^$0(NwPo;5`2ojkdFw-; zS5!ImpH=E#VhY(v?l;T=B`Upc>vNyUk_`7lAW8ikAAev|pRYI*v(X=4E1AwWaw%l{ z&LrpTEmaEo-tHCN*RvvMzo;v<^a`wN#6J?%o035~9G`rO8x^#`P-sLk-X>CcBIbf039(Tk%mv+>HeT|f27$G{efw!eE+Ytq$ z+O3Af2gAO~j)EIom4k^TmH3T9ccM@~d@id*7_a(OnmDIAZwJuvuy^FQF~AbT&TJ<@!cLlP8_edcTaoqr6UjH2Yf|{Sm~s|sy><7N7rLZtM5cQ4XC8&ns%_|eHtl8 zwnwE~ri7?j%ngNvmIBb|Wuzo0Eo}8anbt$0c#_Qcr;OAnc72C8fO(I#Rf`ryzPwqK z2OC_3%VbJiQo4lmOJ?hzCxOBtcJ7g^lNZ}Q>^wpE=e0N(f;rEjyzQp zrXdb&({TpfEwSW^n71{_-$Tt+OIfB}U$oF+;t+~-*YbS}Q;8EkX?wiC>o(00rsaJQ zZm!5+#C*KX9|Cn}n+JdQOv}6F5TY0BqM?5(5!(EBiHLkFBXX+Z{#_^fEp{Srk}^7I zP}@XuIh^Cbyes)lsTbgj&!zte6_;$>S2fo1pC5as3cBEZ(hVQYt=r+Tb zj`w2`Q5*?xdMm@b)xImZpK^uvBV*frUH@E?6<+Zlf#p$j|C)QeLKum^SEKtbbbTOn zU%h&@?0u;n-7h!?aeG~Iq3e&Jt)^yb>MBw|_z}`_y1CMQ;s~s9z1;d^)pWhRyMk?j z%;?R`dPG%brry)mXx3~~P1$Q2x_Kbl+=fTO<`=~hC(ZiO^Y-1lxjJheqtlMZ7=E&q z0pG`av?(^WFGzDjYtwL$WvijRM6O?5-GH>=_u%b=jRxy;>#d{#g01J@*I?RoKDg9J6+g$arTw}Y!9hzyo24op6`o@N zx|}+m)+lVd>tAeyZkr@(ihY*7AG>&tnqkyFF*OP|=Ly$QQBiFr==yjAi!r$6XAL0N z=UjiJ?>!`!`I%E+awm_e>wb+H-2~Py5JZ4&dA!En3w3c_rn9S2KbS4`aE(=YIs`dP zJ;NR@FwIrsx2K2=Rw+>}v2~5F*~I$%WKxj5s?H)7l*bFqR#a%%Y7&6?mjcs@4*eZ0 zQT;ZN0sR>t{xL9(!-{%kwxMxWiRk(gf%gg$&2LM2ydp#+n_*siK>>k;-_=p4Z$PiI z4W54&H8oLj7j}jFrm0gg?mbc%0)BF`5E&x6f>iync3GjZ?uW29@qFZV?Q!e>fkVM7 z=pP*l@+A|XF8#s5mLyK9LaXVk-iaY_XLEXdjl0WgIk_EK9!b1dX*h{P5r=YewSL&} z%*#dyeBeU*a(BKsbF4^eljc|;=aepBmCWs3hpBr!d#bY8!v1(;==Tn*kpj#J!@IBd z2M(Tm=gX6|fp@NETEBjq45W8ZKf-);a`W7oi$I2b;s&UPE1?`_5g$mP*MnFpZ% zTQdSp*N_!r*dI&osbP5;~lTF&EFl%35S>@P-!IV)0@_yKGkU z!;2OTi&7@~>U9edPWWwfNk*s+{{;X9`u7{_hTh=?R6w<;+LXrPb!qK952`FYykRhY z9uT)3Y-~^w|B6f6L3cK`HIYnZ&aq$8^KDL4+x3{JZT)v< zSmxc33|W%mC}o_SN$!=_x3IxuN%O^5VsuDYu!;8Z4rBs%EyTk^fow)yT_wipHJ7_PUM(dZD|9ZjgN!rP|Lr6@Al9M zbN2E)649L5-ts$XOj}#q&O?5RS3b+cctz0^4Sxo(^+BJ?czAeFUDvlB0mJ#G-CS=} z2J#zoEVZ~;cCUNqr$I1WClC5mx`mHmRA%YiU#W&cP){#Yp15z2@mUFJqP zp2^S4>zuOun@qyFCHf$VN#7rsAar~lz%b4;0ReZV7n9O`xQDVr`ug79-V)|NxN5i( z*yA$>DMl9mCWAn+scC#$cGNm2ANakjq%y8L?pukbj5fX5X98mwW<6eVssedJA|6H> z{{_utHMIT&KXJkCQ7)&C(Dp(KS%p$InWg2c%hBQLT0VSZl%2`+22v~(RbHp=ot1`; z){Qiw8rqK9n)--I(|)9s8FPvBDyllRF7ybDTO_tpK^iqMV<|2K=!ve1zr2%@f~ zNP~q?AQ$Di5kG?%9`=#&8BC-v$>$dB_wrYn{VkB=+CUrz1&B~IM3~(*sdB7ZwM{dBCTw}^|1@rH{)3Xr8rSJE=Nkho%5XVzHC%$^P7v$l zOm7B{3~~Ki?1-2^;rl^fYN@@W^Gk;WdZb*&r&)GpS5E%`rXdF0{ocYDJbDzgZ@tis zqX*D6Qtmg0-nTzzxoDEt>sy#+34{yY0CjS3lf_g2@#*Jbae>V+Hv|m!!bsRHIO2Hu zeFU{O(#nYJcj5~Wuw)8~rZsihFx(T}s;rUb<}Md4acp9|okF6H^?A2kV@5QjdATi? zeLO+31=a6Mr!^O>>Fh zJ{4^7TAwy^?$})Cw-bBZN>x)`m{WcBla9avL9-~9x}2?VN>naWkv+83noBEPHK#G< z7w5mvIHP|TmBaaCCj8Blx8RwAQa+1IQ|7q0e}`VQMt>Yd=w=QoCIpfPm>Z% zT|H|D%`Vekp=1vE7@p%Bh{$#Zgl_Cp-et@+$xgzgHf zOY8>r{IK{=zgHDJzA+s3G826c{!y;5Z^uO>KB+gHzl)^EaRS*v?iQ)2(|$P*sFo=C+j3Y|YILrYFbxu5y6T*!n^Fd*ne^s7g%|3~xhwun8B^2gcX zCFW@SH~=*`+Y*)tbg+lUGPk7d zd$3%cQ`ba8S4E`13-vLLvled;*8lFd-PquW*|k-g4kSmvPqXv;K#W!j*sdymt$ej> z@rq*I|2>F8>nLg!D$b*OTeCiPTBXRz;B-Ee_(p)ne6Kg|oS^VEk5ZYZH)6o2wuwY%{_sQvzJw81N`Yy|06OU<36Th2piibzY zX4?^qkz;tUPk?ypu+o4GYq)!^4!j62aGtBGX_CdW2aAcyB=Qc8jd3+St~4+F=#HX$ z0S^t5)LBFH3GXsI4k@Ugt60@a*6N+)_>pAETkVE%H8u>V*W0aq-hr%~6<|v2Hxf>d zo(c&6@>GSMVSI*Ip{i+zw{(+ki84i4^d> zX&BQp^A(~?KdQlX+-Al54ADt!giOHC&9jFWAwDwvcE+MsJZEfbXz}eRu_?Imth=lt z1$75qcL%}f$Be1(m>(EN0@q&f%{-u%SKnE(;_X^mlCZcKXjwZ4^_*WpQeYEG$~eq@ zWd5~Up_p}iffVQp&FhRSz4;Zx5EkXt&i-1l>gzcxS#@(}zjJ~WR7xtHU~CU{q1x1IO8xF z{vlG2&vV~%e&^?NUGOQHfdxtfzQUp+m-s*Qs~30lMaf>xmp@g+82EK%HxO8VaN~>+ z1%T8nvR(xzc&e{K`7TD#jR|4Jci`vAzD2F6tMyN8Zv0LRG?Cz0_jl81v7^5`X>i@@ z{xtT>M^Ky8=v)7~{vqHEW2@04L#0jYX29M$?iXe!rmu zF4}bG+YLrj8_)LDu%?BkcDAP?Qw4zrT%{Ly!wU=XROo7!u)V}=UP-Y@jMkl)om1o~ z&AN6fTeUWPPZe!>R8=}im|sbh1LreCJWf{K1EAd?gOKV!)y=?yN{-xHUy0IR02yHG zNZAFT+`}QX+Gt_G#SIlT$jGJEp!;QmhC++J>w zhc5>;#$h7k7yf(zkXr6By zDTq{a7kFE{2QIfiR{=K#3MQZ~sZ4+SH-JdkZ~RUNnrK(oyM~4)!3`f$GJ%%4dT^iq zmNOPiS=S!`+hP?Ii5r`oT48g=Hl`McLi_>nSyKMG;x7t<-5R&!3w6}@5+SUt%GQK; z1jukmoK@bkv6|XSi5c-8aiLJ}e|GdI-O4?#(vU-Pdq1TUQssVU;IGfh`t_^Bm!w%O zoFbCY{2R-TW7F?whKjQ+JILWp;Fwi#7c36wHuMWX?dJBp4=!$|ct;?hGgez;*r@4z zG4M{O-G^=S%j0X8DEy^`%1=_J>_B^rS8Kk#qVZ#dqK}dA;kih?IW*D&^T2PNo<4T# z`*r66MjR%0(v(&7x>)74jiwB)5)36N=I%i5+1Mvoqo3pB68Y0wO}3(i3fhgBIvR@7 zxf`|(FC5i{1|R3L9RmcC_aQ^CwgEvYslVqCnT z*_~WSOM$AmmRb>0M0St+Y6^Hr;%qQ zK(Cf=4?qGGJrPH% zZSe?-7}PJ^|EJ5_;9r-w=g}i02P0?hq6?YhriFrxBvJ*+ z=Fzw!`W7G#8A=kzqJV$rY(va`leL=NyKSh+?RF1{eWZs-VbBU%YU6z5iBNHyMu(yr z-$Mzyvsn%xg5o||wwm2tfnuQe6`7SMPbc%(U~hYvn6LhbE>m2o4MviPzGpUJ*g4k^ zGX2k}Z0yC;#`NS4KOE3rO&=ZmYNa9J%GaYvD^p>e<0t6rF(i&N`ajbH9xMKv9?%LW zjlel=@1vR}MVek<)F5bS#jHQo5M<2Pa+AP4jY)$oE|!!3 z4i+j%;3PjkFA>6DsPp@+$kXXMJI4g>GyEzJOO~9B;{Ce%2^Iq9Yr`?-BwA!u@-BNs zY$RP*EMGq<-dr~o7l$6BjkZiVO4rh`7)IRlOJSwp89g%46PK^~%w!!0u28o21Pjd= zMQE%XHEP0-kg8CdUcgxX;_8K-qgUeS#_%&7V3{e71DLsCoeTd953t_(A3Q+xKX?ER z#KN!?d@SbGwVT(~TY%e(9EHEWyS^yzhn)?GRdI2fnbu&c4TN+x{6!6v?JGVVQ_-Q1 zkg$rrAYuEaG7--PB0b}^!xnQQJB~x`Tf8&0h8hV)lZl=4)6aj1w2E{4b#bqt9M; z_>YhBSL79;*L7GOuIxw9$erz#cQ0lWA?sp^2l4O2t6I>?v-Unh>Sqs#KF*?eNj7 zh?=+6qu~A;8j78brN)d0tbe^bh@Q*WC`P&6FMT`g3@Cj55~6<c)<7~OC@Hw{d z4jH_92(Sp(iP65LCtD)DK+SDysoAL9lHB+AC@&I^17J_=$|yvX|p}- zY*bY0qs0=hR-Yb|L-mU>bB=;n%=1sL-S4lRnk})|ZFaer24FQu3ZQGBN^)40(9ld& zRZ2u9-F+|7wcZ2jAriS0w@oP0^FVx#M9hlvoz;ScM50>#4(mvsM#DRDX{DUtkq{@I>b5PvvNaPnSVza8qe@Q3mD<`f(Rs9( z9GyaU{G!GP0~3VsVU4ZVSmz@^?xdx{q33f=CL2(pWeH%;alwYdM=MonxLbjTami(; zhgETb$4t6QmMf@V--6XekA`$Y*e3xmO(uw)emt#0ZQr=se0?3~`367;dWr;!8d_$2 zS8VR2P1eXSFyx>J~EB$mntMR+x8*1atioV@T@`izvts5{`p|KriO;r=Kfl8a;m8U zJ6yH?#u>D}orbS}hrYAd_scyPJrxpL*E^OAu2dbcdnWqQE#ck70gYaSkBWP&FzNL4 zvFN79JX?XvKrAxmUr~IcUYw&6J6ev3A1}ut^PE5A4f_vWCMzpTEXfbCnqJ%EL<}67 zk>ZwQW~LPd*ngGn?c4t~#oPTN5f{@%jl4s-d^W`|j++4j+_Vez0%V|iZkfFD^Hv)m z4H(Wpr{y@kasgx)=!Q^)=fC^Udn*wp$KMl}zy934_-nWP&qu|}|7V5&GcP50MF06H z+{7P2Femu;)1$Rf5x@oF-+yra8L$`s{U}<_Y}ec9Um^an)c=4W!GE@udC>rT4h}fl zw}JMy|KFdi4-o|X_WypZ|G(b}%uxRQT)v5Y)4SDMoT ziC>N+wHv-m7g&JLghz+6JmcqGSMncqqvRi@zAFv zzCC*7y)puSw!6eB$EN$;zZAenRpTYSk=WK89?5t|>I3*^+n(vS0VP29S88X=`>z~6& z`X2oLfdhyZkv2j87aRcfZ#Y0i$-GY+dJg1aF5`rBeE0G*9N;Z7ls%YZt@AlhK)}Yz zAR!xeLI&*2W6r(~gk?r7x^VdzffigMzYJEEme^q(y13!?f!!Q1tzev0{7w4jvglh( zug7_l_1>uB(o*;Ji`mwe7CN0asU*2VJYxA`h zVn2Hx?+438Tuuk5>C3fSn{sO2lC7658{yz2Wd0DqPI(t29_&5>JPyy{4;J=f`sEpV zM8QYoa6)F|T@2YD1}Y?IhK7b{tptBa?BK0E zrS-n{-NYbEgZZ zT9N#*-S9rX2hngm;4mRg7);ryl2KsmFm?cApFLt+%Uc$fsrMQI*T2Vtv%1!AFY#Y^ zHJ?sQM9LiOZ85sKYU+8F6;_I6Pf|!F=dthL@7dV8R&XvcVvvJ%yn+OoU3mk2PoGvj z%^@A&fVkLV#c4~`R5Ih*soG&r@+J4C&1aa=zhx_5D<$fBa|jbX>cxk&M%Q7;WW&W| z1geDi?T=p@AlsfUQxX#&MO@Iau;A->?KF_^IF3^ybPg68*Ru*0xk4dxr=%Ue?VR84 zc#V^0WsQ}5K}JP&S*wFXLRxA#`2)f^DYs1qcaejtWvQGlkvk7Q5Jn68l#y{*#FC?v zU0wa%&}=28r6DqkEsXPbNJ|{oa&Cb=@!cH#{r%g2F^$`Utpi1y?~a%%l7B zQtx;8-4tPek-jQ%fc_bA2dSw=e56t@s00c97Vd(I@YDPo9ldL2QcK2^9X1%`*L)AF zH%R2nyL(30h>MUxKb^gTK?H=_rp3ZeRcYlhiq^YG)-k*^4H9c@^AD`qjFM`6T)b2g zA2%gO&DqZ&@So0N>1r&>RX~bJtU(71?~>1k_XII3#O}4RVDUyN^V=Oq+A{?tTmo+M zrJn<#RRGB5nQf3Kl`=hExY`MeM1YQlsgD4L=O70fiO-xRJrrEf29(YmT+L`#(T5D8 zO`XfNG|{j~ss7pZYx>eGh377w1^7|YBA=Ng@x`q&dcU8{xok^oP&0FctqLpsqE@Ah zU_m=%II96u7F@MT%lR!@jgho=fh8`Swe{7rOAQ;eD@bz^AIU|wTQqa(8H=E2W8laM6&yymbejOtYWu<7E zKd^C{Q!GJ4{=S$IH#~++)UO91^3X9bqKG)DSTCpZ)hhvFJB7o}FD>n1MWdel-8(17 z#Syv@<~-@Ei?d=%dhXBXxYM#ZIxG@EnjS3O6^H`%$d8+|I;?nAK@~yGcXO2nU7f=8 z+AW&$+C&5d9;~~2an$gHxv0tjRZQ|rXv+|OC;a`UNt*AyVccK0npGUBk9r-5?P(J z>2Po;D0o=x1Kr&>=SkH-$*NFnbKKH_?6>$0NChdVs90#u&v%)dHSR)c_+M?9|7vlY z`gIe<^ELHr3A?kr?_dUx+r;tQ+{U+Wz_G#3%Iez&3~qEWlHB|sfSkUdA!cNR4i<&T zr&-s;qTc(-x9XJ1yu3Yw*f8_^cm1O_&*KY_0|}~ImgRpcncVG(BHjjP+k59`k|$t+ z7KTlWfDF&)w0GVi9K`iLT82rOQU9lH0dB=BAi-5W1nNc=b_?Ute=M))A>`}D0YU3&s{IW8+*7{{|^&<4BO&|d7(E_M2cVkGQm@UGnHo({QirRzfABa zSi1M)+{h09!vsIjojI96L=~j`Or5)E;1LU}0hl1=lCcet}=_;NW*VRl2RUKMmX=0{1xp8ounPRl&Q5k}b(Zg0 z7OhUr{5UBKgN!EvFw@R796MVh zDX{1-etwA-Bi4dIhU;`SNubkmE=5d>C4HnI_QXU(6Yzw_c(^I7oCs-Vl!a@~n&JDoSk9^ij?c9o$4fZYY~AnoHv5WbZlW z-`cWRutvj)8SJSL3l(X!ZlQ8( zI^Tm>+X*meJATV$yFjME6^b5lI}E_t`=j1NW15`BJ9QfCn?b?zQrqo9*>$?J{Aif{ zm$ ztE83yu0Kz}z}fUmL=Q_L4X+E7hXdZ8=67ugB{nl+JUBfrwSEH4efXj&O+Wv;)2}dz z5B*oC-|4y2PXs#sGprBAe|7r(Qo0Fl`SuT(mKxs;&mcR1PXF8D**$^3JN>MNrmSZl z+90l}hZA0X7Cvd42n>gjLnB$lOM-zy`M!v~j|hh}G9;cmg&Yc$TqWU3Pd{`ee}l=) z(vOZVa9T)6kcM8a$y4K9-yF1k9Fx6^)KjB&rtlU0{ifgds_*x`Hf*M~v(|Hc*n7zQC}Lv<^&x6L9m<4{0%3Nx z_SOZZ@e zdNKM-K?DWmvj+{or=uY`Bz;39J-!;w_)quWNcA-@@83py?V}?pbpn%W$Iuz$;OLJ? zD7t;$0)IlJsf!sficbm`u{11>A3)cfHC|0t34A8w5Xr57Q}yO|!U~_q<%^l1sAE2z zpBhBH^A*AMR>(H~c6VXjD)K}d2iiR07iad5u?8F&biX~Te0q&u5d^OOdDr4%Y?qPI z7hw8j+?!+zJ$hvAQ`N=O2+hb~ET_`#(a2gGN63s{&}_Xg=ptx7sRX|;JYzCZ3)rpBRHPmE0gXJg0n`5AJ) zy128`Gw};#LvhwD}{`oRH{_Z)^3D8b#PE6v>}xg# zyYbH~pr+D%I(B;`o%P+Xd|6^S_8$-{6?$DMHm%UF1e%h09rE5oEOCfa@$nH^9=V-u zIlt>73q*xIyI!b8;=mEdN2@X&zZi!d!+d;}U*8{-^|6@}99kb%8xKQRR995&Ts+-x zhtanw722#}y@I<2@mvq=@bkzBd0ZI^@a5n#JRff~Y}&OH-IwL-fU&XR80?39yhNn?Uy?@aicusRDQRTZ zP)H}I#>Bkbd=XOL4pk6Z-dcB9-ro1>U1o@*WwC*msk62h) zFOF8|-*U`3u3GKYy-!P;Z#|{?Tghpnd6C$@VFgVzsF^Z$(%wmJ+M}i6B zk4mcC*EclUEyo!%`LM2tBpapdD?Y?qKph2jgkpuhE0a=}Ag07R9Tcf|~@j zQkJxswYi&{lQ(7St1X`yr|{k=OfV-z_Y|bJs~# zbx_!o?C$)dtc0JafrPxEtH`&TGEgkcq?GE?11M+77WDG=`q&P?AEecW;bUfjPwt6` zFnt5#sr2!mTG>+|>qKkVF=)buW!2@edu^yof4oPGfxTsVbR9qt`jy;&XOtV4PbfW< zEjUDL}1L{lcV8HvCT8K_7Z_J4$Q2%4gmQbB@mp)O!eX+Ol z&ugZHpH+9R%;tu-(86>5ADW&HNG7 zTTc@vCL>XrL~ExiP80G>dhB4X86i`5Rl^qe^aLY)w@Jp+eAZjlNx>MI50_iJH`}dkgh;2<{|J;L@mLMmhDE}=zS|mB z`hv=T-%wM6xlo?z@9OG`ruF-|;a~mS@V~n}_{eoXXj? zva&KcNY-SdbKP{3VpD(uVcVO}dyZDRF8@(aZ#5Gdl#sm7PsE_+*J}(1b52bgf|66I9yHR)Jx61;oE_I)^PoFbI@UX#L3YS6CnUw zc4K=xA#v`_N={zBimGz&Ia#*vuX6x;dDSydO#&H-g0hK)m6jnyQ-^~5&O6_x<)KdL z4Itx9`S>zs($&7!aelmSe9deO7WqiHV@$L%An!bet+zhW{U@#Tap{y|iWkPe(y(8@ z!q&2+l$#1IENK;h4OCtudX-}Jq<7UiIVo)tFkACz8q3L{h4uRlAPEIVL?E*k6?iVQ zO&8N@)X52jWMt4!Wwd$T{WzM{kH0-9wYdW7+=bIKcvSxkR3PIS{&ckfgoAm{OtD*p zB3SXEjB=f)-uPjJ0Q-w%R%~JyEnh$)NckZ61|}uTY~q-p;ds0l$QKFTQgJV>jgCGw zXBLXcCrs&L=nYqI!+Sz0xejkGO!ylT$QrDKHsv&(8f+*AbQ^#bAQ{Rtihy>tSHdX; zpa@(kZvI9QJkrQb7yMDgFR-H&(#h&3V8def#e?{auz{wnJz%c9;v`S_PR3;1F99~R zCEzQMS+|*eD&c4nEQF+Dqn~7SCzlApbs~RK5dSH1^5LGTu~D~b;X>s6mu=eFP{&SS z$;czuiNnP?_&R8m;eF4q_>@N1xn;XR!;mk}Ud_2QvSyJyOs42dH7#9)oze{hy|Hc6 zE?4wT$k%jyB90LfR;SHXn*=RT?2@;^#>D>3e3;?Raf4eJk;c=iyVdQX+TvVO!{__f z8=N_rkJ5Ymx*%h`KpiV_dR9etciHZ^iuCQ1u5Mopr27(YYp{E8v{?0y6(Pn56elE2 zScWWnIqnB_Y>e-pm<-G|Rd!bv%7`{bKQTu#do$d1c^2jOR0zIv+ojK~PP`nEqWh`i z?L(s{esjZ*iSg!>18k*O5Yt)F0+rA6VZ-P5l(sykW8tGov9mSrE&|Ep1dHC<7a>Un zVnd;z_+xL$jP$OPd@pqm9%TIGVdKul%H=ewj4bjiBgeN_PBk5yB{@sG43;#zqXFFs zL_Jl2+jdvrw=VP1=z5-adz;$){FJk?F}6{U93kTj&$Pa1C*s8NG9*;w$$HO7B4e7M zi2^UojR!Rv$B+B#J!%DT%`gP!*|gNb*KI=FU)2g?)oPcQ z7Zt)Rcg)P>Wn+{+IX-|A(yD>sP~x~O@5M%EcUW=pLZs98JZDw*`g3-y5D{<{8TNIA zxzRN(`{9v0bVOG-2q_4shNjkSUA z(v8t`bI^~3YXPmqY%2G4nPsPDnkD-9hgs=JOc~JjK`vf$^HfwFcCX- zVr#oV7yg+l#UCcI)jaCRGCMhE0KfwJ3uU8JR)1Pu#!}p^pyEC234i|%Be_v!R@S4y zbjo?z$e!8*0}I9=B!k-`F4lL$E?@Zy@JXrtOZ-cXx=+I+)V^twutdtnZ0hLHK>?D1 zvS2i9v=`n)v)z{eKqwPzP+i133X_B)gj0AkD~pr_2hWa@lo76#^xGzNUpay7N#xSA z>fjQqy+7QkvQW;A4O;XXF%ifuTRG@vu;Ya;#A?AC`}n08wtX8D8$Sp6ydFsu`re`g zgG{dV3&1Z%!e{K6@2*|z@uH6LynO}pkb3hGZatN(%=+*WMFtqA^59hIdS#QDz|*#1 zCvkrt>BHo*4(rin@F~fkU%%cW2jktv*66Ca&c_-klN?{OT9q!nSb%L%@=x8B(Qk@n z)%rfh&l|u0SUQRSgCQ$CX$sxb4bqN84G|&;IYS`2%pV-Ae#o0ZEH&M8rXH$e8P}lr zZIcv|K{E76Ci&-LKJGIc#yOm)aieqQigeM-Mg+w_mAZX$lg?w(llLj_e)VJiCaIFd zTIMclsjB+?!^d~3PP&+pCZRtGsi*kQBU!8#J^c z3oteb{n&@?U;AmPzj1>pDb1hPb$=LN87zOv7g1^A_ln{ZeQ>b3KQ&>;P7}NC1sS; zD=&N%4M`c-x8z?GNVD5yHrbBPfr!8`nVMdfx0#!-Ht~mU_PmR{$nc~?J4W4am&o62 zY4M1L3`8abcRlC|8(5UL+;NU;{j(;{+C7hsMsJ5HoY?^+)TE4p6Uq-}-gh6_N z!IST#`$0_Z<2DS`wW5wRyyRQ-fzZJ3bnj_FCkd3FzEpb9q!$$A{2c6B-&EBGllhmG z`?ab%mDSbw?8Zpb+<6!|3T9#yO@~HJ)hjh36Q6W+Y%DDBxh?0$4SE5<$TI@6dBL@^ zOtTS*bdu;ZTphi3lX(6(n02wZj1XLZE}Y!8=c2l4bRZ(P4s;{Z59;=7vO7@kSun}4 zu(Z6s1B~LLluPxJ#i_C%KLpItMfUjE*d)0I6r8Lg>Z4qAGx=G!3)~(A(SE+EHW|ia zb{-1dq~18i-*5VWh!cs+sQ>H!=BV{-B(_+^v-O!^U>f0oL}{TMV)L#8Bg&w6b-}Ji zvKpRn=?0ttMhLER##S|mmTfL9NBfD2=KZL(P;>ZlB#O{HJYj5}q`dbRz<^LFf;rQn zkDPF@AWp<#5I1R{A0%SxcQS1{Em(fyY)6{wohy@Wkm1#MomW)5+<*QfcDB@C7p@7g+P z&u#APK%qlUM|BM^SEr|zcAehYU~~3Uf@-4omxJRzzTZ65L!-IQg8tIkq!u#L(pX_m ztp~`fj$EZ`lg?~m#|3SGJWfqbo7aZ&nvJPSc4b`*CHW2J=C-e>a9KV+v+iu2wN6C| zFOvarD4yEl_sn=3E6=d6PrEjn<8f6aQq}>Y&@l=^DlK0>s~csf|6=9e<*lHJ)DTrnH)!U;kM953CU1C4e`P{Mh ze^iWBpz`0&)lk1U6r%lZwSFXsd1AdP06Wtii|o2^9~9rufAa8QhIiS_j31x%NpE=6qr zYR;=yt5Eap?}@%pnGZ}24Gjebj>IP)6>Nmi2`G<{3d8t^HME2~;xByC0ML}nquEi- zWfHCea6u4Dpm}wC!$VyxpDp@oL%aY3oZ(?tJKmlry<}vhRw=2eu6C)YKU!%g_9YST z{n;I%+2%3NY%$AbQLEHTnIs=e$ZLK+q{ggL@<~}st95I)cE#(=Nlk6O3_n4l>7AjQ zy;12`lhHHJxn@SiHG)5e82Va-I*`tMSft1DPhf=mMu${vXoiwyLbGt}PvE8Sa2!{C zWm%o){yjFX0H5t^LA>p091AQg$?_l`D>6$+>^rk$maSMHs^T~Z*|uINmo|Kzjg<)t zR6G*^7fTJ|faWLqgr!4!jyd;bk;RZDp0Kncv1^I;X85adT_RxUjB=B;$R#7R= z(AH2>Yjn6eT=Aw*g^Y-5H^ob@Fql1*<$vU`-hfNe)Yep(=x@awi4{W0P%PCZimA3v98`^Yb$@zS`$K?%CejNahN|#=&X_BY@V2 znUrsnMAz<%bzMQ__!Hl#e+VoIMce|3wP-j2$|V(`8AvYfv)*7Mm0~zY8*>H6j}C9zC3h4Dt$ViY!fvfA~%55@dUf>Jei~_FJ8{xQknd_)4}qE z?JQ(YPR{oG(?8i!bV)2`Z#)8^2-Wii?lvZ6AMQPbg@g)1EVFoYK5t_6rF3IpVPm!3 zfiK(gFvBd%FHGpQcb)_`O||?69}APE*+M=9KrFD+|#6j4KDMC4-9kCN}fA0s;$>EmYn#L<0T52*? zKl)-S3T!q!jfY+`>VvG3KobAuTz1q@M#k4$1PmC`yGnrF_q-)H_^? zm$3B)c!%UyVQK&*ahEureS5wu{NS;W3RH4zEytZ_0D9g2cpCQJuqRy2Xwzt$K2>&9 zJU<>EES^5KevVN0OhGiM;}LfZ96EC7%z%e}={G@w85i2gJF5XVhIyL0V;yeOcf%@M zK9fR>Qc$GSn1TqAaLtL2WB4w-+G|FeRA=)Y>>v+$11HMcj01BCX7RU5U%o;b&2;FG zas1AX(Q(u9?Hnd zsA*V3YBLjm6c)Z>`TpWnts~;fbg23zbODFryfg%Ci|o_F{opsVY9gJsWCY*@ymKF< z|5m7@pxNMk6&a#v4EI6E_2n~sL0v+GJVCqBQSVo0uOKm}-MQ{|K8MrVPWXHj&&3k8 zZHDB>&?ure(1>GX#={!tll3~CU3Wb@fxO&xG8w!_^9eKKrsrT?J3H}}Taxo^;ljGE zKLq{~C6ao!B~yvAf#)!QIe$W-?{$fQ-p%%?^yD@VlkOM;E;NV~-LMXUNZk~fe zse=MJdtIC`!4~F})I*V?iC8u`!MoFf+lbeiRB~lZ9v%X@?Mc#tcBo*+njqxh=u8oP z7nG83BdyG7rvc`w2cyiU#C2n1pIF}GO-(WSm3dY|**cNM& z^woUC8677as1Bb~L%W!0y?~{d?FmE?qlOC*N|PxzW&gS|GlT7My|wq^FLZ;IzEE&$ ztCqC1YO@X($DHtbi2CQ5Z!gLH=f~y*mXt|Uf4kdMf8CL;tgCE3KyY@yzPs_&mDkb9 zh)xuDo4xxWX0vn+5`!Iz#j3JNOi9D~N57i$i>i$7QLgEJ6!^~?fJ;zq1adG(CbInC zz}(#2`O(UXI*p{bc+QYI73=jg;lai;c>m~VCC4W2oncKr^WI0#CsZ=FPC(& z{RE62P(fffdvBOHPSBeCZ3DdRttn_JD(Zi$@$>Whv6&v5!2Vfj>AG@VCY|pAoJRRY zJpf1&3@mK>!w7d>oiov)HMZi0`hO{(r8!I(_c(JM{#}pDGv2|9d#`6kuDtNUkSD}Bm z+GH_$A|X?|4VZ}Wl93`ms624B5}%E!n_aSss3f;;*yi*bmB+Wgq?_q-SNdzWoPs!N}U0 z&MD$e)|isAho{GHx~_w~nPlI={7F+VpdRiy96mtIiT%UM|6aL6myDK|und~Y+^7Ai za56vZJ3>Sp)S98ZK#F0TOXskS5x{C#sy^2cy;>PHB7&c@n?C zL;FchO?k%p{Yxmprj+<;;Zvi`S8}9|D1;D#nsQ2%dtdP>i!F9k4Ryu`%ik@Ce5(Gi z-!mkt)ntlo{M_B3YF?Fz~0`{?4n8hoU&oKH#kwm2K?= zRjqU`!uspi&Yo6Cc%JL5@GEJuW#=&#mS$t{G39cR!@rp`p1VS_+j4 z78OL6XEnt~4;JDsXj|fw)OW~2&1jbn-jen@ez02e(f?l5HVm)X3>P6&Ut3*XUd;Mw zFAt%7>(U`cVI8V@ZWdR;M=^0m+XZ>EJETLI61K% zly~;@l&NJ~e;o|b4*Ov6GnjNNWW-=Hc`9(p-2P}suIHm-13pSINbQn1Y^eN6o}yg? zC(}L`FYyCvVL~PZXfYNu89=gkPD(f!FS&6XBWgl8vveH=Bk6dJRDUVN;jK;kLyyN#5oxPova>Dk`~KdkTk?a~47O;# zOK%WyhP;#UY$pZ){5;+B(Cs_>n8b1(RHV}%ZGQW6N-*yBhkIwM`FS%`bOupfzy8Z8 z4gIV<-OUr`e*qu1>-gbw1|64i8R4IS51mJwhw9iaIN+Dz2IuZL*^?Nmr%siE;mm5h z^6e~)Jc)LUva`$?g6x}5zn*+L% zV|Ch{Fk&_yv1K1ANlJ>l7%Xp>FscHXxQ>N|WPwBU6gC?$l_3JJPjSkr*XJkO^!F#T zo{8@dE_ZUQP4E*0%8J_`@PbLiQN_MWmt|+o@&%`Dyk=?Ok}zhci<^KnD=3fRcS#no z4k*JXgAZs*c$ABuSqWJASYAgH?f&BOcf;tC1S$%G#!K3sgc!NZ=4p7bqn9W`>ioo~ zucyWw+0Tp(whK(ZuJm;3KC$gM24d-q$*DejE&;Y81z_Kn=l0xIRf9!kK*>~YF?f~VBiVMc!97=5HaX;JjYu~nN z(_58ntDlr!LsYE7=Mbuwf^v;tQ`YP{g!(@}%h?g5XmmOfUXXY>)V_0oCJgaEv88)ob(gv&bt2zIwM6T~`&37k8j?hhI_m6bMbgkCSTXf@mTAV}ggZxq* zhVQS};ibobt4UWM3rRZzzBLigbH`&N9>h|Jc&(YnyU;>@g2UJkOQ@NxSOj=7Rsa=Y z+s9zO7&=N!#2yb&5z9U|5?Y$eFeuiX?^6j+1*}H3D!%-Kim;rIMI_Q{x-T@zA5KP$ z5PxpzgIL_>ZL}K|ayYd+5*hU5xu=t+0J#!25_49xBwqD^9h?2A- z`1``4L?kvJGrGu@U%F>4RB*DlD0d_w%5j@er!N@Imqb9jGw}A7 zuIK9V0yfF=Xr%q>XkJ@G3k!Qbh~f5yXjF<)gcGFTqbI{P#4Fz=ei42A4;UlgLe81~ z=0*IT%V73~2T4e$+OIt@a60F6p``V>JJR5s{3Y zE%U<{KV9!_V9=TnwX%8b z5S?5bF${7{J+fYX%U#6<4B+_=^k(cl)+Gs1^dipocEu%>iiJw-trKI%1)OKt$oPy4 zK)Osq4?8lb%Rnxj#(0yZ=1ZyvHq#1)Z)x6`?|X~2*1^}Hz+RTg|=oy?6+;X(;Id^UTedu1xjHZR}fNS}N<|9%1{OVGxz9HA>S zkNY~j^(_t?L;UFFp|1U!k!#lMbTqvh+{yXrYc739SHl|hQi#nr>=cT{1tJfs+Q1l6_4; z)V*m-Juqm-;@7Q@92t?lhpzM%RrY8A;gk|b^@_A>?fY%_r^N-qV9*>w%fV_Bpp0cf z`=>R>&C$r=;MNk6;hk!`dmqku=B8QIULf~2uRc=e_gTOglMk}(*|cBeir8_|!qA~1)9Ai( zce|YL2~M5O>tzSjd}n%}VP)IOwc357A~Uh}kIhr2iAk9Z9+(3F!+I3xy^Zcq8F7p2UgL_@^x6sb}rNF???y#_aj@7s_1l(`UEXT}iJ4p3(w}sbX zk_T}{(sLsHR1m}Zp%96yTyC#lsk+EYa=iFIFcCLUPvOnI$dmtKB8JVUBTN6nMDP)M zK4T(oo-q-R#O$)NrVj!#j$FJV{!6SD$;ij5rA#|EpAd+YVERZ6|CNDw9AXL8OBg-Oy#*rM`z8${8`-!e_j{Y>1Qjhl*tRA*7ok56S9Fj3n+yMDsL+IS^S-#b0snp05my+tWk ziCjDK$dHJ#-G`)2AUY*(UjEC{K2m`aI31i;j+>gICC|(wW0IP%0+na9%@&R;aM)Pkzd({67FV> zPhdwVy##H{lh%=W|Ky`IA>cHO%i;P-&UEmnjl0W(qO!I%c=_`8$fU0Aufbf_VU32$ zkS(I=PN#@|np;?yot;%!oce+A<5!2grNPxu*q?%Ol3=+5TsOs!x0!Yoi_*D7%(j$p zh>MT+%a{?k{dh8zV0DD(9=Hxxvce!8$oVi^utOYPbbO6mh)7yPs)#l>+~Zwzmw+vg`MC zr4ebR8zcnj?vidvX+gTXK}tFV>F)0C?k?%>l$3@weBSxI?_6{4HP(?2JUVF6c+Qj9AFqJ&Z2 zIyqUZim6P{S;A&L0*^hg!~(E&*W<$h?9aA&i9S7$`+=9$TVK~ush%#U-ze(Ji>oQ6 z?df49L!P{DuS8fb^*?McBNz*DsLg|a>N>P=wKKMn=vcm@gv5ZtcvLKIT?7(ug zK6D8Sxai9q7@1&wS3Cm|Cb-PEh6l)kRpfe0&~edVWW$BsoP;nkVFTFA`n}eI)0a?c zYmwIoi9<(GE)tp>cuFe^G;-0w)$_ZZPWg{!fb_eAxZ2y#nrbUui%rd;_~#4qI)}SN zAFz!`9Bk~e^e8lW`1OA_mj~vr+vxLnxN}R6>#-1y6;@W_Pa~;1p>Vqe{1(H&+P=nP zh{ydn;kBkqUEbLE@hzs}rcC?A9~Bww#g1NS><4{9$T&8W18Lk8ZEbCJrARRewjL3f zNB#a=ZsHNpQpAld_RY60GSRH7zGTg|WZ@dsL{3Wv$=z@`0rVbyR`hk&pupHx2}0cE04I1chCkpS_9* zcC>f29FTL!$%{jYA!_@&*8A-nTNoU);0ZmT&IKbEGm5J@Kx3Wd5%g&u!F-$8r1%{> z_+&Bee(&+f)Hgje1#5}?cyQJkElEB;=qGCQ&@iQRQO%2)mBQ&_e>dE4PT?YAVj|<9 ze4j;^%zb>c@q75yVf$Fr59@)I@8(`#<3B_gw1FXtlO3!Vp;7|yjz)h!B^BH0f+2mc2 z9N%Lnxa&(=F*&q-23Jp3rv3wz4{&RQL9As=$Hm3+)IPjRP=YMEcxw;tZGUc`;GmN( zh0BhP$0X#{MKHnz$y;7>6Xzv0aKA24QrDTyc;|NZkg%TBD_Ct92K&}T#jH&zJMN=~ zVoJ<+zWt2(bh1BZ!B`nGe&gj-)Qe5l&KQIRf~sr$ULcNaV#$Os-McFKw^_ph8^|J(1Dpn2_A6#=qzGJPLK^=^)7cm zmDWQ&#I0c7TUYX*hFLdgUSOz^-G7+YCPP5A(kz9Nr+kx4=vmS)Pw7 z9f$n6?_fc3^)^&$tWeo>WAw!{Ny_NBu_bmiB$Kyno*A?&u`9p` z5hdwpR)z$AjrYjQ^@fs3lqDuN61xna%u9CYLdie4!k>NwPWaOu^2XO}A&L*zD zp7YUWW<^EGTAGT{uVwy7975e&1>RfISTm>%kIGGJFB1EV`O*Bb->g?1ierzf26kweTMd2(VF_ zQGd?@{x3F!|C#b39(s}+3eoxV1FcIh$E~#()6P+msL=g|RT?>N$)>CYG?}7=H z@h9Rs2n2i-_$OI=Za$eprs)AB7*^N$$NR^wEF?lxAv)UbFa;X+E#-Z1WBA7_B-Csi zz!n5GgxvC9_%pJS+zpdpAz#}oKiBEe`buVwKQ__S*hrgd#I zCR~>yo7Je-NM?MbzI1i3CH=R#&oz)W^a5GKTksz)w?mP$#k-K}yyAZ%6nD&N{V0Tp zqL(^4xza<4mXAkjrjepjWE^#Pb$#+uERT84yjI+tCT2RT_umv74?_)cz2fYjF#Dlk zed$rr`X7bg)+(?J1TGp_zaT3RpJkpwLa2$&kHgDs!6A2m1+aV7Mwd>EqzS`P4NDVb zvTV`JBn~1)bb*N_MWmbfQTb<2&sIS7;f8(NV+8KOe<>U^`W6-py90p>;xl?dcW|HE z$?dLWFrYv1WUvmm_NL3cSXKuMb92A#6?{El2Ph1Qa6sYA!QGu}CZ4suHK2%hZ0qGY zx=YB=L%O;;KaeVDX=yogn15qqXCL}f_q@gmp=V~l+FD9S7ZVc`DKSNGM1?%T`$1H+ zv8iEZmVM8Dp|tx~KI(~}3Q+07!=}AE$7CqM#x=Qa-ZA#$5a_Pi%*UJ7;ul}*+2uTE zsWgOYbcjT*@9PzJQUfE^f9`%^!taMu;PJsnK!jOgVoum=g489D<0^HJ5=X5Y-upDky1hhRwoB9IiJ zu#=rIuVQI6?m*WL9q6%C(!`G*=jC zavqC8uRG9awv+%3@BV_mZAJ8s|M_96IDt6;CBi=hm&18{7>8L?GX+#unm5jM_`H;nRB{9NB54zmGh_IMmZ~qyHio&#d48Mt=5rjqnA1<@e9*C40KF1R^z?X z@lz^q0X5*JT0-Q1Zuj=pmy$y0n4MARzj7bn_l504#$%+WdMjPVK0Tw7Fg`Pu?A#-hymwwV*WB6oWI#AEe1Ng)A&stG!1yxtr?2 z^s6y5^Ro43dC#5=W@wp!qC0X3YgaP$XkWf$=q#!rAc;!#>KG5krE6Dt(vE93jWs+6!R;4(IJK zC)$(XgT-ec@wy5Muc)z07ZMF6WC!}X$&Jj1X7h1e!bH}(=pQ6d`jpZMY;M}m-oBsS z*Y=?T6zM(=dt;jzjI0nxY zt#xo>1Ma?~9TOTA7~?sGP4pV)b04xPv#Pz_mAp9y^;c`yX}2&5eQcE@PONN6_z3x| zKu4LkeXvl**EZc`MN4RZpNGT!ea7RA0Nu?l6#j)){Q&JUFAx}u;5qMClq+4TwZL-^ z3k}5Pb_{K5a&x__0gC!q90H1=SUUeUP&u@g(-viI0B!+%D}4IBp~wixgY~gCN8M+g zKAmhvaNaK`aZs5Btj7ELba-qwptpH!?Ct%avPiQ)7S;B0uHqZ)M?SbbP$mS*L6Aqr z=s9eU@?A{V(9_th2y1wszl%jFMx`Vt`$KjFMN@)aAQJ2Gbip;|vC#oc1V1`Dx;Q!= zLJsQ}a|r-}&TFI=kOg@=@<~i5d28$O{CWjCy3xF`WL}TEH%TLw(NDmnP*6rf(!p#r z`gTY@=ltrbptzU;8}VgO&`2WkGQGVu91<=z7FM36C7;ViHxOJLZ+3TgBN8xm&&*s& z3U#h`i6OcYVB%ejxUcDp1Voews`peJ zcE8OfB@sR!^+IlK?>04ZxZU5lgT%0svUeI@V9?s~LbE}LY+lm+DLx)v5&^f9R*UP* zL*r%d3bd}LTndxHO(2?xKa9K=F)RF*tqX|c!XqH~P!1JD=S2|k8#Xq8G@*a=&h9ow zTqIQB!sUREhW?p$8lOilKx*JB87-H<*}huAheoUCr=PmMx8Qjg?!u)s!tZpl)E)Ht z=;-KqrIGdByP$=cR>X{-G6~X!rKI2Ck$F6Jq*YW@lFrYp?E*gf!#6n{%Sy-`Qx(u@ zBYP9`CarhrtCqQ(ZvzT8`-;&FGBq~WrE<8gDZKCP$N3*S;smhsQkB`Pai%?jq)7~T z;RIq)WCblB^J2_oCJq!22m&}N{fp0EV^q3tRxt{^ML-4p0QHXeG)CGJtsldx=jjG9 z(LbNZN8y`j38kn=JelM0eB0E83oN5jr7jAS!`qA)Gl?hD=q_zl%PLi5u15r?qOd8g zm-3uP8(cQWndSm!kywL8^s{WUb!xB(b&}eYeB1$zf{g^Sz-M3=N}Q1 ziIQ&sE$MmTZcb)_P>Ug$J|1zjO*<09+0DT)7uxvaF4U?@H|tlUcqy+cK51c48F?dw zmCiF-R-e`F)jc>>xk-$5XJw|{{@x>1L_PTG)pTCftn2Y1^ zi773<=nGWAhs)-|ousfx1WzD6JmT)mhta9aKuUV|RI?qIctCxluBhDbWxvov+VDOc z`wa*Mq6L3wd%77ZWF2#Q13B3nZKl)gynZyGA5eVr5LtdI$L}nc^A=A^g{LT=?@_Td z%IcWU;~t1H_JAa~90|AYRawjS$vzCVR1)*f_Rd?)#us>b;RLA{{ZYWWwD`P&sKYuk zqTq4g@lN^^2E3mqg!gsP7=cMB)vv|-OjR|^eh-L0F}^^tq8N=EiKfNLqZ<~3Dw59V z?<$33h2wAy<6X=91>}uKgRwWIKR<-hGuKIal}H;gaJ|B|&ul{xHWzvG6MGQ?Hd8^c zxkY#;pBUw(LyjEor8X;VlM)hHQx?>?Z!Oz>VZ10ly{B1I&==BIu}^VDr34DJ!E78K|tPF{o72 z@vH!5FTtDf3}Gy~jau`9cb~Yqn+gjH>Dz7~afwbHoXw9WbL5KE8VbXd zfA;_a@=io?QTMF3uaEz6cp*POzpU*ps)zI*zXyb58*H~XrP7RzjUNDsqp7JyY<+1A zIeK;H^#m2m?@%mHl^H6n`}81Yer!Ht${HUS8FtNo^8!+}R1FOm_Z);7z2{Lz-TM)@ zH@=02Ve@SOZomd89$2I#r34|>>UDwYf?p3S{Yqyt*#K%B9iW1!;RTWqAjsfxI%zhU zB7|I~d|arx*d61ZTjamEWClLXshttbq4AlXo(D%I6(zb)mDqH*Oi5KmbkDGrsE~zV1vuZgNgin6D^lvEnv(b=dwGh1*#$l-F^h~ zm~22peO@~&)^+Rjdui2nF$$7-i$B`u81>hLv8~#DU|xaZcpHZE*6w)>F@Ze6nViw}Cn2e?4{Q37$EOR2;*S)>gT<$pqe7k&f zPy$7+l;aQ5hx?TP=aP?Jj3cR@rIbsBCecIXh@~wlEnvjrpyIn(^PnyOsdiBN8Yh>^ zW5D=Mvb1r38zdMg`O9=Wd_;8nYtcB?I2l|o_f)k#Fr@jM-CJ&Z@d^yBa_BaIyJD91 zzj9Z!;2!-yx+^U5%l?zQf;`R5@jH89IbDUUyHo3X9au=Xl%cQFm!jUnZ>SJ82!xEr z!vf|S!yIIusTH+}ozm6}83S5T+?o)bEG4QOy6|yRURe(Cd-TlN!{0|s>e?y@i{r638&fD$4qeWThwq** zW(}umV`4CTJAO!5GF3Csv)iq$#jenVMZx+@6XFuSoE7)K3<@6@ZN|jLms~>mpqVMV zqR>V79tKtobw8)^h?*(924meojJ{;{o;w<|Z~lD>5GavtMZI?U_o50YL^vnz#+I*+ zeAk}pnBrE@0r{6Iewv9Q6ZZc@O~si4$-ikT8Xo?enhIe{!5<`z31zJ}oufZxb3V3R zk1m1-KPb;BRpWEpxm;@2G~ReNS~gQ6j(_b?;iZmj(d1_>s4Wd|q8pg9>(S$rmwTcM$$ zFVLUa_LE4{_#Ezldcp^(pI>ty`~ZQnHnxtC4p50Y5xh^`nLSeNH>sRV)6nUh8Jqm(J3gR zc;AVJV?%i9hxG_ypoxgMkSB+jzUhSV1WUJ}IC?0%yYmPRAiDLGe}=+D*^8< zfL&N>i4%q>$}x?4gWy2M&QA0(D?E|Mq_W5M<}5F5?L$LDgFItoIz=4y5(2dv-#b$wyWQZ@{bFYGXpJ_I(0Je&=31lc^$n!OP<^PtM^SNuQ({y z&@MNm=)K#ax7n;#Gz+^I;?{G9RMSn-N-%bo=BtjQA#p+`S#{k`x(Fx?8VTwWm7(_) zzRpQrk(+l_Z1!bDwO#Gttt~olZ^yMCR~Y@`+o+A)l4NcjDdyAJ=S#&Wj=YkxTriqF zC}Xw#V7{wHsmSulo9E*G&!VmTn71o>!0L?Ppyn=p}#5z<&>FRq|*|#SujWRka2h# zr{pW0V7vXy+qbLb#?x7U9MRKqOB<&4rn_J}Bm_reOl#W+NTG!HBEI|(jTN~}YECxr zM0Nn{U|~xz!OQVSCz13ft1xq^CuUgN+Ss}6399Y!e2S=b{u z1}WPwt@W`}bNL1C!QuO0EMhre4CJ=ln1&G6t9z^n+5>F6C9V**+ZPsGN(3OwWikmd z@7O%ogGFkx-EVdojt6xc;e`BVE1lqMeRg&^8!I%;i@}&Bw+vvK*C99`EPN|});+fa zbsFI{jPaZXi|8Ip*E8=h4Ahrx<54WB;+3Qk2o17@q?fThJCr39E4#Nf2D)J@fHrKXrSIiMcmAx1BYL@eC=Bx9hPl8Q9s z<dc5d_&r>Z~qLN@Mn`0G> zNa3X77|w`t;Me_O!;pndyghXHtT@%f(ZW*pq^PXL^W*^usXj1}0W<@D7YEGddKL>; zc)Hrka~lew7f^GMeG|S#!4n$$*cQR+-c!bYCv_;pv{}$B!S$d>)23`Uv__|CRChrhj=fteA(I)stB<4Es1Ml8}#S+11{MjncM@qEsXx2yZHk{89lAS$dCg~18fq!St_sG9$9*)8Qp9w;oD7T+fq!u;5nr7^6; z!exFrEf15h+z#{oz|hE`xEw1A7W@ZNz^IR)g%q3EH)bqTQS(2)a0WeP=56i76?3jr z^s7mZg6f+TG7h#jFg<3PS>?1ribin|)y^jQU)@qe{3sneMF^2>4FopmKfJzbGWcg?I^uEdF!UCPU1!aNNRmcefi&bi%Yf{$7mJ@sP0}PHk~ZbAC9R``qOt z+v`LN% z-mQME(67CPcDA5^&Y_qnrlPl!Y4d4R%f|zc#Hykqv!u&>6Tv}^O;sf&H7+xw>qfHt zLba7d-G-bWP3V1oom3*MMFXEMGtQkpeoNs=r+QaD5dR}LK{{A8Z~4-3$y5a`yY5A& zjj8%Vr~fO*qq+HM`+KQW9F{F8%ux56p^d6xv6OQESuMc>E{8)=W_bKrH)~_{)G=v3 z-vucTWgMds-B)VTG~aI53mcOz*L1CMPNyhPGIo~7Uz6VtK%munnA7e=ewNlz&dbGt zBl|Ce4f`nnPT274JlJqYN#zG8M>T;w=qmXLPFr>VVQhfOUrcq-21TO0)p5kCBsL!A z^NKLH4Z*qG>cnMXN)S3m!=C`9bp2~(g<>a2f9nu-D}r^bMO{nlWuizDJVh39_G{8HTf}dC#S0kE>-Zl zdCp{WU;N4kEO&Nw@$f{)_XS65;{>Xv428_ueZSsXzAbFO)51biwt$PR!WgTT$CFA7 zniY>USxq`af-Vo1L@tfduDxCG)aAIwp-6@I9W(PWRo)2L%@@E&@ZDj5xVac>dwh5R z!n;F-EHVD4?vD&l8Osd%y)5)rWx$~>lfdL~vLu#IcZV{TpzqmxsGq9wyjm4tegary z=pxWT#K-rP`Oa2Xm$(KERp71+cO-TT+NzU(x z)+t(v%Ax{JEkC{Uuxtv?ORmmWWBg)E9DF&v=s|vs+D4R>7ocL-&d!0XKSRK2AuPd^ z2}Dxlb)Z7=P#^s@YvjMx6kUt;muVqd+GNWjNf{R>0dls~paiKEZyqV*(}FZ@m81s@G@(ka zaK3@&K7OS{9}_hNYNoQWgXo0cFB6fJ3H_+1d*|73Tk)JRyRC^ZPnwI%kqkzY4pE1! zg6emPd#{oHo&|Uaf0Lch#0o6H5xr1{Mowb*xSYM&~fJlu1E7I0WhI^XcfY zsJfg}v#nj%^jpZmprl*Cp|GDHDPx?G1I@r|J+q`av@97N8k)hRH!`W(eBA^BdCaLU zPc0K{!7CjaL6WH&2&a=U$Q6`1!3aAcYA#$u%`Dj$$2ZY6GyHBXUSHXodoK>0) z4G!^bm*aoz9+;P~z{gTl)>;PE8vUvD`I@n>8B*BGPbMZNxLHRJm6Vw*X;xQ}grl@K5X)+FG##KYcR2R2$l zOG@k5K?;M~#pKgFwQ_o%=ZF69WZE9v+hwhHQHg=;K!Yk@o{_QD4qX^6BxYcIHhqs0 z>Gbyfdqi|j+ep;01=8RIZvTJ2T_vuyrV7EQR4tz$9ta0&0 z83zTs9ND~y`QH^68f%BVQ$zZs?^soIic93kyryf>Y9T@%n~hu=<*bfJX zV%jHKIX2_u8BGcunvMuKS82yrp9uFj=e6DtA5aCHXXYA8Fl+Q9Xc0i3L8ZZ$J9`sr z%mJA}!e252I&0CJueGF??4t~(Z#cRkGS@J&8z+=X*XC^VIoQ_gs+wI@#hdZVl-?N) zry3c_aTOim;~R}8DAjZ2=g;tAQ(-dS4*QGKW|KSH z1Qx^7@pwVuuu)p|FKNbv5jsk0FPeOOgi9>U12x3TX0=+KOUoS=av3-CIJg>)makAk zdSD-OlzkXExVR%y82l$KHMN!>AD}L5?JTb}nF_MgiGQt&#b%R}o3gN{HRjxZ{nip` zCKx78L%y0vBUX{cqy9c*`Xlc)5zLf+I=#LKeo|Mafy!Rt+q**1mXP>Zt&Fjf$sT`( zZ_xG*&K>^{r64QpmrM^{_MTB#^n8n@a4oWz3__!LS=0P|&c4-U9rbrWMC5_Ec8ukP z3(|+g$$**Jke6w_6wD1Z%I>^TnOeAgE_SeT^To3@lI5*Uh3xSu$Qh@QbZ5yIOZi6KAL#qikeS1aB!{X(@Xyf~p%>m!@F z`~C7Y017D#Ok;6V7MEGdW&(33D`UHZw&xXu+-0C- zWL2lF865D2g3HHYMaFR0 z=4nKN`V4o0i&M|l9Ge97SBMUa`^asPvp?}tMxt=U7jlaRL5nzrmXD=VME^R z^VfGxV0Z>!nJ3ZZfAdQBI4&kmp(wyn>6`rVK=KmRXYFR^g4R~>vHQKz6B4O(-<+`f z5G}`lb#a08^5xkDxtB*65)ysOdGLVCOt1G8g`Z?@O`4B?9(*>NeZPD?Y9|NmabKF} zH{Z2jQZmxkxzh&85?GDp(Qxw}p_2RUI2|Gn`vKsod1>1ljSJ@n*NINBd>H=K*7LgM z`lr{Oi4IvL(?lsgSI`t;Av9w5$PfcPKT&n(-rin=-Od&;Gn8fOt-MRb4Uvt}*{$1D zsR|};@wvbn%`?hYWX9XjbHyIeZ~9s(yxk=HjUf9nHYrPVu(rdZmz z&2e)e;Yzj^rn;=NPOUt*T;VoM4)S}+B{1$b#63fC22fmq(@wi8=0FX~^-2Fou{d(g zaLN-J2V0N)B!9ZG|I!B_6&cceAc5zX?%|^J*o#PqL8Xer$Cp02I-Hwc4+nJpQW^iQ z{H!p!p7tSm4-xmfmW!{}2in(3pE6X<%IJTY_E113@6CJ^_P0qOSHqz|e3+^Ia$F+97>*5J~x?a6CWp=^6}|)oQ_vc>*T(@m{`EV0-oXI&RIS2 z3eB6k_s{B!bIZTA?%7eX-%QhUHMX{%9L!{!RuR5l6M*Gz%WY(%rJY$_ZIhVzk&pnx z_;T~%d#*+oI9?{}Fb<0x$kuhFj@d%;F&;k`mzB-P4T0jW^?LS9B~0BNOOtDJ4C6wD zr1WkS%+hLfpa1gYZRfe+_YxTyS@$L7+qY_(G=vZ9kbG^W8H8WZI_qtBfddTaMMl!v zz6PI;%Ui=edhi94AMdC{%!hZvu%i2$Kia}@EeY*a!VC!YOW>T3f5k%4&XD^Thd;ekajN0#hJ{8L zt0Ny7AOAt-&F;p=#=!<;u(X6kh_bHdYKuqnvAH=oP0gqc^y~ck^@ab(@84}a0&B8- zeFFl-fY~W^JOYndWqGODhtve)SBb#^IJ|A7o~ue3jID;Hy3X@ zYjP5j_A$AYY3LeAbTCo#X391-ymwp1=1X|(G!gzh6Do{>s6zzf`UTHy!h*zmh$-F>PxfJLu19V_Y^a^sFq-se_JHW4eh5nS`%ZHLaZEeK2Y;E)M_ec zscYG3X?#XV_~}hbk@jvNmYSxFJ?iLw{ye!jaS$U4zo30avS^wuhC0;f%iL8Bqw!_f z>|1vyzK6Ft4ZRbj_Ci}UZ=BDz{bjZwOH106LO7wJS0Iz*%_6A_H_iOCzvLm>a$*QC zhFCytvE2lGoGBWB4(>Y%TYz)WF6Gf;*>}BTe9h z2$Vb-oqSk(@eP*gqm(^wvv2HNFua|9@>qizsTn0?AIMHo)4jt8@l(u`b-CSEeH9WM zX!!yr91cTFtgpq*QE`#J`DSB($|&DLa!sx7nZ%)#vvQ)xZ6bh$((k{)?Jb!*y%%LsuUG7BO8(l>OSN=nU?$O_+%Kp)YG=+*L%Fc;<#oLVYL0iLJk5=TcNKkU^Dmv)`p!{ekm;}paAc0LsIzW-P zIBw>aiE=CZd3^2QZNhTBk|auYMl0Xbk_lvkNTYG++cyW=cfz04z4F@P+|0pr5Dnzd z(;B)6@%?P<2L$*RO1rvd;}EF~;AVJUY0i zGz)h2^93_QscXB;0i_R;68Awczus`AjOtYk8%@>6fn8@w?(LJT2KaUVWdPvywqz9r z8$BDR^;dpO1INRPAxpH@frC&&+BL1}l5+^gZ0?D1yeT7Z>x)ZENIg^)Ob|!ZZC`2> zL{XK_3|ZOjoF}D-%)hOy-L`f~+}UxPkMNZ>DxWi_h<+C%_0NoVDCqsO1rF~m2q^H` zfJ0?9pcc-1Ma@gRcjaoL&pR7z)r0kQNnnWvaJ%X`&<NK>|?fRcF`O2wo+hJgLJ|dh>{y2H~>q8$Rsb$C_6&Kx@>00DxrB9CVf6oH` z{7g{L;*-7sVaaV@aQdPYxb!YLxKbu!>_PLdx%shfmfR|~2KPOi8z7M(eY@bZRX;PJ zc4VO0Ve##p?9X`8E8(#P7!e9(0f8j}qs>9Ff<9$f8k28dRc0rQ&_un&6oqVxgh!2< zFepsB?2`M7G+5Z}mhL0%G^3M!W7QYcq%#lr5OoH06&eOTewB z{7IG=1vRTzrrORL)U*83a|fl}kpsU^9^9T&k85U>KY#at*B6VJ*rZU_Ulxe;BH{ql zDRJGv___^L0J2qn5x1wamjX${#&u?&%F%L7Nk%JjZQf{nbfS9=1AkoCwzQ{lZG?`1 z$R`O$m0a<+T%KD3_tWo1eFco6?_r>6lD6_>@g?MB3@hfORCztlI_JM<^*(`g!yke^ z^X|9myO`avRF)h=3w>tKNfvgLv8YTT<1?0l?G-*xfM^#e4Fb93txE%C1cABv-Xy6u zLc`L~Y#9}Q#2qfia$9kAJVRqBF{RhjQlor(EI+n5Ba5kr+)<9=EZGMnuozy zcv}d+e<`T?BY zRMrsI59DgMC;b(fa5x_^`&)qlkJthckCTFowxP6k$8|$`C!M4#WqIk)%nWdv@Y!_= zno5yzDV%`PS6l{YvUg$Ux^*-S`)1kM9I|N|9p`zRca|8Hz*lgQe2$> zS}+k!;Srkjvxo~$b6`!PA<%viLj9>l-Ey?Hwb?m$#^ZnHSf9KFh0YiCU%V7D#HEd@ z?WuSE0kg|f*}E>Y>$tn0Tn3R;kU6WUV1mkR+Df@+Lx&61G>>|(U$XMj@zR+62;dR- z`!_Pb=RG+*(z=32S0^d^^IcbM8(R+|z9cz}jp2xvQe;}w|B+@FXiC__Reeo=y}y{Y zP+R4+R?cZ)kOMuB&7`EP0t+1=-vlCqK8gCC#1TfUUv8+3!z>;)^lKzpZ!>Uqz~#o< z?D6Oc$`n?;?$|iqL;fH*hpx8p}NdwXtu#2$(UdYrk4v>xI6pDPIukwQQ6G zXDt2Fb-6V~qhlKt7p;d)cAW$@5cZ!~dWk5r^PV+$pHrd#6wfXp?9eT7{rIn-f)p2}W-s;zy z0CtQ&xLPD|@v7A=ti|W{qx;frphmV|mGE+;&vfcB(Q9$Mn&z1sbrg}}nln(hw?KkKJ+1>|Ep3MtG`d~@(P=m^jM6&LQ^<;=6k|Kvp$^_@3B-Oftp9w5!z)z3yb5!Lya#midY72 zaAFl<%gpqpS*#iwuWW22JGskB9hBDR_ z_}!~MgXZ(;(ud|`(CJ;FcJy^E^78UcCc#z7CrB4a^+mmk8WSvhR>#gaL|$GL(LIJ0 zW2sy}qv|MJ%qVh%zKbP6GneMLIJ=f$F+9pgm9YjCE$*?? z^?;0UmOdb3$5&*5WZj2 zPfhPJR?Hn69UEDBnl&s@X|f%;IIbdzk@WY8O@{X;HHBKhSu?-AZK5C1PYij52~cym z2|?BUt!^nrL!S51z&#l&e(FJ)Kp`p38TrCTb`<^QR!W zufEvn%>z-}EjoHKhXd>cE28To2oh%Owac*@EEI!k7Lcrl1fLM^uEAh2nYxae4VpKi z+q3CLOd7bQ(%-f*-($C*QtMUB|3DtC+ITHaFP0&H>P$P73#L!Mg_Qz-ekL=LB~++( zWwMMJ52UiT#b0Q8T_`_HY};*C_3eQYT|PQ=7rZwb8zXaJRDvH4{cH>y#a3; zFYM7rf57PzqkjtU6G89w-{x&@0Z|i@G9Y#Fd=e}tsjap7@ABn_+0X4AO1cgXIpXhg zdy~HI8ucdMBJPazXwnAtZj|CiY9Zcz*Qa=!5GI$=FD|ve=!F_)Xl!22u?bc^ zivOqwtD^cHOK$-t4z>s8;9Cqv8g+HJJoOvmaQW~o(0A)C{B7U9@n|^ouF=(W59!ac zNK988S`fGT56+ZWC^-jP$I1HntqyT{%`fYgv4g@v;?2o&bGE+4x*{$9NJ1$YW&gZ7 z`kG{GU2Bf8pFf?wRo71y^yzhYtoUY+N+26wa*zltuUXgAmC`O#+A&Q9boaX4-uR1& zaC33jZRIsiP7MVNf)$Z9Xc83riyVLT|DGJ*xkyOTXIw~#76a%9ja8KDk66$bTf=|Q z*)TOqXF1kfj{NXm;$_?s!N700J^1H`29v?+c^0me9=$XUSNXh_sTlY&3T;9*cY8r? z%cN5upXU9l-4t%S$qfa-?CjFH{}`(J$X-L+z(hehYDQZF>|fp%yTO;SWr zU2-E@uB}}EFt#!((_0wxGKlcSdJcJy|1C!|KBx(Zrf9G~7;ccJD5__OP|v6NFQD(- z`uwjm3uPdkI{j10$RJzJ)tGG$UIdIZ?&^Y2aWP>mV?bMRei?O)>DceKK#jMQ%=+DX zHYbGIrZt77wTTGQGOY-|j46#~dwcIfFO@X7Cnq48B-KqPZzQIW{8~RPBO+n^^_Ux( zm`?%wTFcZ{R^@t8_DKzhXY6^R8_{~r(n5!L8o^RObS(`627ky#Wh*k7dM%}SeG6f-07@8eU1goQZqi3{j| zmCZY}U%ubaubLY%oaybO7oaxD=K2Pfh`F_mOc&~jCiK1?)B7jW9zHzI92^a?7`w0k z77pE4tFpsqU35PbY0{-V_IG|;;Hn6-&=>Zw)${4e<_b1sz~%zqQ91N&dnIGJ#PS9X zIs%uQMifzaJOB3LdyA%UWE4LlA1j}vd>R$Z!7p>&9K znLYv4R)`z;l?hsXf)e_J{$}qA=P~;UWh81M$cPY&W3>|k#_y;D=(FpxrcBLD3xBCp zrwZ>1NjqH={k7Z6)|fbSK;NXMhWEL|w8r@V5q*Bc@eelnudn-8f4n6B*e`>x;${Dl z@0Nz#PXX@*`ai#=e>pd|Fj>Hrgv$C-<&-kuU;miGIuPNnjrTvkx8?s^lAP}K{hIE` z7mjkypYJK$IaqMxI*2U^Vr27}u;1cZWQl4_65z0~8ySix?`NvCm()t%L{(R!}7)!klWe9H)1kE)S0Lw(TvtJ&MkXI%BXJDJZVLV z(#Hr~u<8BtZk_*vm=2rM-HCChr9xYl`FALJX0NwB^#2ZrlaJnf<;4Db7O=wBDmV$$ z2>y~~WhRz{Uo5oJkDhi_X4gKQt(QsWuw1?vfjLi~G2KUmjUJe0VSnA9(y@J>NlHd= zbX-(e)Pznnol^s1f=ux}Jw4r8BE)L|SDqf3Dap?E+q1a2yScf$GiAl~7ZN0PLJa9q zzaO5G#yl)lt!fhb@}c{+9M7NHuq9t2LB%|297cC%Jv~xy;y`k2_uPJs_G&%jY}`!l zbTr^{pAFBlly`b0_Qp!v?VsvTMB3{RjADsUGiOi8YO72WIV?-I8@$U$Z!(X^&Zc;2fk zmx1mz`gne?_I3y`xIV3^&bI&6+VcERl~T{Vw5-W)`OsKeYPpd;pcO>K{oe5;nNyKc z4i|?#vA&3dyUG3Z>AuFHCYnNqq!9vDp6}_DEJv~dByHlq1RAA!a=qoa2}tv7wk7wj zhXS&FLM*K7CpaSW)mGnn+NX=O*=0@55#dU^N`9?poQX$xf1mcR0x{|-sj0|1Sy@?e z^jZrPqbXPuGW%ErNM4FllLD;RZ02*#E*H6SNo?+4@NMGaxt%PR0?{lWRrzk;+8j2Y zAJ9B`dJ?yqFEsntyT!+~|F72WIwvPxFUZpkO56|Q3F{KTkhZ~>AN^uRD*}e?#@2QFKZzFIRl6XzR zi;E*F>@;DWv`>f$g!{o z1O39cLsphBFRzi$&e5G69EuBQ==(=T$A_AH*xw5X$_3xJD$M$;LV+yqG z-L^3}$7ql18TC9+V`mNO>sa4>t*B7Ad;ew_>|m!hK$~A_X*K_`oSXrPaqXc7u`7-w z8CPfiNq-pfV~|tJf)Zp56j(~DFO*8koH%htJOgWJe!Vqt1`?tZyL@I%fZ%* z*+>eiUTJA*VIa%yXvAKg|2UjqzKjoorMsgei%K<612<1LHufi;n{1ymdV0CL7qY#&oA;0_)5b}U?-s7Llq#z)WaKpUS5gH#0u`>?(dilyk&7HRSO*TQ^@_ zjqcvoyI!%34Zl=h>(vpaC-NRjQ;xu3r9oH;ieUxbfhT*~5XL=HcLt)QH+`eVq)uxu z94a24v52;&l+xtPP}xcP6iK?@$@F=|?wGUV=hU#>pM44KFQbRYZUI8fo{tn5ABUu* zXqbQcNQe)6x(A3AOSYw8U=rhDVLo5p>fwFeido9<*sEE6dL)N$K&do zST-Ip=j>{y#h6?bo<+~@J8x@IPfI0D%Ztp;%BU#0F!ZBZcU>T3%>!Jgh;9TH%?*7l zK-dr@TOF%dWCF(R@p&AO(!|A5mhVN6 zMp!3emGwHCI(lhMlcHr}erIAI3NC22b0|_Uzw@osiY&2wq-Gj4f!v}pT+uQsH(k9S zYkE3y9OC>UhVr7#dj!H@0CiSK%Q&}OOb`gjVy2F}^YaB1v7Pqtz3JHi+R@RlZ zPMi)JR(BYIl=ROl*`)VbdhO;`R;fdYOvn5c8G>fKpzs&t`OvOiQFjl-5Gyy&(TTZX zjewCE z*CDmEw0N|dpB~T^#1-FYw#qm-kmt*#HJObO&(9L@Kn59wb{o9Yt$9=DcXuvsKYjP` z&=*OFIJ*Vdj>1^o&(VJ72UxAE6&^!4X>y#m8y`40ICxx7nmn)R3{;la-({Fx&l^RD zhJ@tiNlDL8S)|O&=X){PO3A}2SQsn-1EEJ$FQO|Z?JPNBuvbDQe19hN7^2hcDxc0~ zad)<{KR226z5ll?jx_esHf`(x6D!D%PlEh7N_;FhfEm&Yl?6^~P2+78Ojaq0!-rW+ z<#o>Szx;_E)sG_jh+hP$lHM&ImBNj6=l&pI0_@>`s{=v^KUh4fA|i%zhY|sb4v`P6 zd9GzD3GdYwk7>nA5)X{{N-~m^6jV1~!jVvs z0U0n1o{GXdvdT}TN`*6=&dB+A{fB?GsW06|>{C2V*VKSIJHei3?`}9{?_}+CXLiKJ z1q{faou>#zgWChK#!C0)?Jt@-sy0aP%4ssVO{8pmp7LZ<*NHnTfj{tGRZanZ-7|~Z zW~HuH7V!s{!=y7ecN(AhxIlkaQ{(;im)GiL6gBNuVDDTuvWTXAy``ZzVLJQ+(vSb)@sd&N+28VPH$w{w3Mx~Ej*d=7a$#|y zQ;#OBe$}^mL?cej33gO8O>V+S%<6e4`GZmKpRw8cX&HQ*nQ&~X0O+Cu3n_-nN zD;KJhal|~R_L+9EgiGAu9_-1SN+c%J3(=-7(}{~57pHj_r><9KQ)U^h?CWQM#bBegRtr`fK z88g{~nYbetp{&#GSL*{TEyxwFr`;#PA{PG^GWF~60J?r3n7^+LB2-IH?6GnQ!iZ>{ z6Aqot4hRm|7u)HIhnloV>cmt!yC$-j zI{9kF>`JrhtV;1KYcg{3P&B-*-}a+H*RJQ7*j!#WB~$rw=y)vib91-Th02Iu)Vqa* zH;O+oFfq_Awwl>FSs8?ehN9r{exkvmqNXI__xO&KGi8DPk*%j^!Q^!HX@}#WJpt5l zcI#ol);(RKV}mT^X{L4OFObQHJv3RUIy6GMIa#^gL>>zg74(7a-hVjt^G~3WfY9^1 zrmTTO$c|}u{5{y0$S2qn@NjX=NlTbnr6sf9MXEbK>uG5}Hnb@z zDYfct2tZR6k6pWHNc0=xhyF(o`H!`xi#1^aVv_By$B*}yXg4=wyiX`eN`6mIxbCS- zW`)^@uv&XV?>Ou|c;|_^o%gyzF6T|q|zb+ESl6D&9C`+9%sx0W3h zBAw0g{d+7=5w8NDzHrK|*KWlJmCd+gcqn-9R`-2OTKhNMf{mHnsInf z$8M_&pu;^L;dd=uXkRZMuh~t>f>THDvtf6rZ)v(^h0E5~R)(*sO{!L%(=O9bXmCbt zAX6}?;Ml>akFRNaqVaNvHeTwo`}pW+a&nRs2H#1A3Urh)=%K+edRU2}knsCHg7B=Z zmDN<6%3BNuCxll)g)P<=F0zr@rdhZ(GE}!`_F;!1Bo~Xj=~}ISXy-$b^C$59Ue3cJ zOHr{=ML5UTGZVTf{qB2kGe;G2E1maW)2o$1Z9okB+K+atOZ5fokcUP?9P4WwW+vTV zl0do?m6fHJnC9mCy*zPFFZ~4q=-{eUQ%d82I)r=-Im+t-F=16WiNV1^q$^}`>OOuB zI}1z8pGe^icxn0aJ&MJt;39;kG5{J*;Ks73_-#h!@5%u)b_0gv`48x0E-nrM_U|wE zNK2q2=ht=CuuAs6 z?u{n-=y^q7-iD+^w7dt_R^&5BsxzXz)Xk}N8e|-O30v$lL4PdQ`euDvmS)_(yGRjX zj~IO?xQ3{Vt{Ym@{NzxDIgNUWMK`7n&u~_WXyd{3;i~@j&1u4&ZdIEG$+`BMwfK?( z*O=h@Oz6Z<)NMR^3Gbi-f<{dQEIqS3-XdXzmZCvs1e{}Nff}}bJ(EG??UUEb3_Ihu z26l-Xql^}Hwn@U-Q=}TLY8#=PBL6W9fIooqR-K8NSsFh$!@U3QlbLhRqOcZm8_!|P z)*+8lRT^UE@McKg}J*{rs&BTBH;iQItw-2M+0c^J55#|4a=aaAD-U{uec%u1;BLkMmi-`_x_m^TKXN zu9=zq7MVGAp&*RZi2y8tJFoi-6XnlRx!QmPq0jKH%B$_tycvW5Mm<;1neCE`UM+W;5UDMBOlAHugi32sv~d5H0JU&LAR!g&In= znb741H!6IVzNWr6x_6w+{IlMTuIGN<0~UXr>h%-ZV#h1>=ulyJ$ING-YJDnS9{n?( zKC?6tBnSGujy_kZ?&TF&0)S;WDK6k+7@;mv;-LC(T0EQ(t1|kb?!2Ct?-O->@AInl zAKNTg6NjGGpKi0*_Ik4@b@o}EFScoE&JGSN`#%9OO1q!Q$S+{P)G1LSXY%Fw^aZ@b zlYfI2_>ISDtG(9d(>YyUTI^#9_=I##)KHoN?2U~L74Ip=AY)o9$mM2o6v`-0$k?6HKG_4}&VjKmx)d z7@99Q($|k6$cOw7gqy;f_KLfs>A8+jj=h|E09E~@wd8%aA%1;*EgXvGv3cGnxZ-~d zm|K`58wE}}db%}$9e_jOaCyLmDGw;R{r3og6o6p>t9YKh|gW2;{m5R8}j9i3C-FzQ0NIqeMN6&709oZw?Gw20My zfPIspz$)k)n6uusva$?j1hCgx6%~8eFORzs@7h$7Y3~%Y*6lt!G?6&5u&`pj#!STu zze7GJH4x}u^?7(XeL|l;AYl7U#N!(1E$Q;CS?dTJ*A3(_8F@M+tLzR)rMndN;tao& zh4z=n*V9T;rgV&qA=N6Xs`>f3-Jy+UZyKY)X$wUnzxBCF_wz14&5WA9D3Y*m^{d{{ zwpaA;+F|%xKYHE1st=)1PdT?Sy}p;aJ>L!%(P-b!^KmVG)+87I!m@{<4l zVQ#q$<@PLT9qmBO$keFUP2+byT{3Upn9Mu;2w=US5U*I!Ebu@Z3URDEE>fG1<4fHn zCJ<4v${UUIer=NJ8AuqF-Skf&CXB?x{7m(Zl)l}DV!=;jC9_PnjJyfnOuc^4_1V8D z+!0ru#j7)GW*n{-DQD>1oFi*8N_@i3OEGdRRGhEwL z*Uz8AVQ4`K4x8Jw%G*DdmruW%o`KLXG&D2|>*s;I9NxdqK(fkw{=L!;m;Ko~ zILcaOYEnCePuqxi%}KTQr^a|?os*;a?_p&AfV0k>Ivz)Nl>kkEi~RtYLJ_ho z+R+=oy3<9`n;v^t2b~&wL1W|K2;}?N^3uZN*VwQGF15Am7GXl!o2hFoNU=63Dk>@+ zGo8J_4=fm92!Yx_e#gtNKi;v%X_vRza(}Z#%G3e33>El@O1xI>_KxtcQ3wY+yJGSH z$gvm(duuYxG&ME-_+i~OkIdO=-Gh48n<^jEVOpITc{kd8>Radg6plUgc00{&Ep{js z4&`&eF^S(F#4=cp^_)>TIkL((MR*3zr{dz`Q;|q`AhXs7rb_c4&Qhh6ig7g_uzEh!E?r;9!MUzE8)uU@jGK!|8USje*NW zI0|?|Qqh5&$?rmg-&!!6+u7M}`?Gks zI~rRT+#00w&^+5Fmdpiy`(|x&FyQ_msQAjii{5MVDMW_3hUDOF<=xO#fR593-{^To zE>6tnT_8)g<~?;Gq4%I2@kuz+mzw*HCIa0g*f9WfFTX~6+Xxen(e2O8O+$=P0clu8 zL={#H+dA7N*JXqwc2ogjPpm^-FWJ@Ut3DDx1wFxQ2-)My>%*7%Dvd0KGTrLD$n_Z) ziHWQ>4J-;U8%?1?9ScAvX-%>A{1PN$5~lUz;NB0HEgrPo;aiiHc--)2Mf)R_H)?BH zI=6WJC-p&6?f{R@^b@mIS9EN&?EfA5a7Rn~U!xBj`u`33;90+4Zw;k8u1#N6A5pHS zZ+W5m#lgHto9W?k>jkfABy4QQaRj%2$~n=*24gLaV7nDhrYtRsYo26~o`N&VJn*CK-OV&p0S#woaZro79ss zV?Itx*8bf7451;CsmJ>gW+((>bwYZxr(mk9ss*c1L@{sPPnOW(IiaOUz~dmnt&r)a zK7&;}y?a2g+jw3wva@x@!C_XfrWT-CSz5KIy)N;6&=G5}DVz?2>sNxOr2sdbPjq_8 zCkmW^#JkC!A)MP@y$17Vm&b-mR#O?X@#N_{OTINEn5ZeUF)*F2H=7%cNMw4tpIcj4 zSWwv>9!{`$>HM;Lbo3QUywzd6`7hN$Uqpl}wWlp%;sVXq)+gk_{o(PvZ|CNt-t*n1 zyaHiIlT(G;8xH6B3zMOaT@*C?z$2Q~DmeQgo+a~Q@ImC(=HBV|e98Uk!3Jt*a0qy! z-CuzL3NGouZiRDPZd4M7&0^D>?y-5fP~m&scgd;}uT@y-v`Z~Lj_I+}P-V<*XIm~7 zt-u?%57?no>1Sl{v;JynJE-VN#6Cd7?uIDn+DEB1V;J)Zkn*qu%tTOmX}`GWN;OvM zt|8!z!PZ4B>LQ6rxH2Z3fR|Ghp@VqxD+EonEIK-x zEWkdH3e49b=}Ki+<=GM;%ck9eoE#A)Lc-;2=~BV*;-99}JiEqVJCV0``-TE0-6~_n zMRYD=8iX*&mPw)Wnlj5|`t;9hFFqBvD^2~M5$^nXW4@;}dEX;N#PAH1TKvv5rHf^2 zipP$Y%0N<2E{s%4{@N7p)-@PUFK`%4-EqJ!pDN9P)qHytKnDXQ4#LWN%0dAU!PNpr zZu~ja)t0}d8e{>Q#p#w`JaYhsts%&`z#e<8BDd+vY~Ig-{^tHHvBxYqn%e+bV@_T@ z-*&|uE?~&WV-Bt;nHDrWE&wGAtRkv6@&Y+=8EDv_})6jI91>gez z?_fmw&$Jx$1F`-=(nEbKjY?i4BOFRxgvc#rOU>v9Y;yEPK~GU0OW~vPj{>s|aM3vOYG{Q&9@1jfdrDox)-8A;I7%?;Pnf<~F$^ zW#WLy>}F^vw{oCKuBeTYLFGbcmI0<@c4{;AHG7qOO=E|mvW}{j77-?Xx(6d;k=@nU zn%{`&TFQ}Qz4`3-%dd5MLX`jVB1kR&@*+C^4=-Y9YhG~FnVNZJAcaYBFN0WGH&D** ztS}Y&X(Fj z3InP){$mzkI+l(~HG6Z+V;C0AruR5AHg*bDp&&_pwI$C0OYmjDcr=N*G&Z)&#&T+4 zjnK-9K!LO4^0A-%5*~%nnD6~|2c)C!Iq)1ImAD-55Nd*W1~CnOpnvbSSWkM6a%A*&JKU0sfboiZj$1($S$Y=rG>v zLg<45j^t`5>9r$)Eea}|gry^HqIf!01sz2XKuiGYEIu~`c|cHXnm6w4TgHnK5EARK z7~4HBV9Os%lGM4gDlZK}P8`rOy+uH=rY-P?m}Fg;r)lJS^W1AKLBZJkBduR({oLKQ z%=Xs^Qm0|=Pb$39vNDc%dqsnZh-Fp#2=?Hij*^xTxhr;OVcEOb<1pV}`-wq;E8 zPfG(`!6V-(rF$bY{>mW>uzmXw7zowuJI77-F8XK@Rg>BvE&~pYP$X%j=WzQ-WEoN) zE~x2kBIn0i&q&Ees$ts^u+x!QbXODQU(LeT=loHB=6%j<)3FqG)1##PIbO!ZwM;_> z%?A5lpI=?>jKMEF4X74><`FI?)#4k}oN1gn-%Ss1zv!K*87u$&m~Ix{;YMwR{I^R% zmL|43yFJ<8j|Ef=)~&OZep`f*$(@~E(O>7 zqgkQ2Voqlxwe~GbxlYB4nZ4UwH=@JfwOA2>Gu%fvW#5rp+hnb25m65feTDbME=+H` zxWWqb^zA+HX!lgq)fRcQ{YVi+4VlKm_lOTHt!Ux{x<*z2DAui-3$m$Pb`#f~(TWpK z52$ad?h{W_wjCo7g;Ia@%#@bp*#vgJ1-#JZeNf^sVe4i=c|XLV}~D!G%dv#B#D%*(YU-OU$; zJ?=x+;b6Ka4KwTo^n1e8LuBYe)SiWv^HaLgeh_wsLW6e*zvqC2*I^^JC+<{peyr4T zKl%p-5D^gWo|{jj2zii*FZO#yRRQf~wfKQ^ua`5vy4uOzeb11UnwLug9_blfwlA-5#-L1a)KWf5`GBDACOfK9Oe+Pf2{2JfR`G|A}+dx5TD#2b7 zOY&noNZJPtsBm&RefR<9d!}zKq`=h4;qdWlN}gOiD(Rya&Ym*ZH7+YF%hMVA*z5{+ zQ^BBVnGIzl;ZuwIxl!~-sc)~JbU~X0GD+9GTb^X$`<0Z%l*K*Y3Efp)J-^mhz5x+9 z->3F|n5UWH?*{;zN4w2?0SvD=tZL(;iB|W|?ufwl%CH72IGY4}u#u8K=ld`+XJTT~ zteMExglg>JXj1y!Z0yo!zL{Bhlkm{^wV@7?p3x*16v=ftuO8zCw&O4BNFnl(c%)XC z9olK_LMMVl%cZ_iy8y^-=)_mXhsD6~{wcJ7{Vm@n*rvmfUpBVa8&kogR%w0UHfep- zZ7bqY3!WJNbIK6=sPKnpK~?iMWh1qr?^)zUkmitD5p zIiQ*6O08&m#AgI04HgHV~4lSf`O9zECx^DzlT{u=s zv{+nHCCiABCP1(rC7aE*-JUe-VFgUeS;-%gV~i2g178Y-KtF!F3>X&)0Zdf(jN=^h$G>h)ZmLq^>WWwt>nMPFjKi-nRRA{LhCg^nk#n z#QZ}2l?2{$2)t;w#G)w7%E4)=DLdO^1slz-vq;W0;Jz~gn0s2(?{Po>wDm#m$Ezvs z1{=A>CZE=lVZR5LYnN&*YT=NZkL(JY|6)A+pM^q#Hh|*qYuPJ%$;OCg!Nf%83re`X z9!fb2MFRuc>usQY1`W#?Oec9Wh~h1EefeliCMG7Fc83Q>26BBvZFbh}=c^AJchiG3 z&yU^KD5uk#Q2uWxT7!oMz`eQ2bj zPdYipKSUH2HtJq(bSgYv^IeNe5L2rFUPzPm!X&`ytZEiZwdzyI{4VzMK>-keDW|=e z$MJpl-xP`@969 zBW!X10*}7b6ZK@?vYHMDhCSXR?@qB! z7JArhY_xk`<6j?h(-lY=kK?hlk0JU|VF6n*NI``T={8OqoFU|;ZX(zsaP%FSD!$$c zgD#>|J=qEDp!6LT*7QtD$S5jl6>=S-`w!FO!$^+iBnl=XcGk8)vP;DqHncnQ?Kz$? zod1dGLC?Vcr8YCEqpUQo_ z4VqULC}s~R(j>Ft?@>+Hc~rd;60FwEm|=xM0|j)wp>jOI5y9GMxcJK=`2x)eV%fB| zElOx%Rz^lT3*4dYhoCHd<)-wg6$TFWIwGp9yu8_yeV|4mFd`zNI08A&Pf}9)H3rJW zt8Q`ohNG=M`B1#$;$lfj{j>Q6@RM{25^Hw8cT~gK|F!PufdN@UCH2ML(bdt-rMR#d zc4~2IsQQT_dp!b9lAfI0XdpZKmDp?Z{_!kHa1YqcTs-Qks>%th?i1jc@FD(ztTexC z9OYSZ5W$(I7+iE;#OKfcKeSt=M(YqlF+O>+&(vC26h1#c%ZBF-4>L5l&d2}w4pj=M z4PzufP#@&o(%SyA5eCM(Zk)IL&+|}|!@^VG{G$pmlu$(Q^2^vV;$B^x?(HS%DU9no zlL^+njqT|XU0C?As;i4x$i~Sz_n5QFx2n&d7?&Wl5%F(*J){uSdD zMF$5Ty>60Z_-JmxyH&u1`}5=dmDL=>YSs8R44Q!DM{h|U8(1Z{SDl&+QW6ruB}xH1 zjh3;bVcm%6$WsT-)6T>SX2ITk@l`!alwVsl|A6hepH_;BF>3j@mo_}-x+bdF?4QZm z8A}@*@qFtx46@GHS?Q5QU}(YsVW_5}qTS@Yz?Kgk)cF}0xn6X!l0Zcgk);8bHhMv} z7yqVDrg1C=g z0IF}Wg1-ZVP*u*UR;PphZFF-E)PuQzdT;b zyQ6vE9*d1@7nnq6*(%3=Eoy!biwL`HffErQpGKL;sVF)}1$9ktFKFkRj|Pm^3p7hiAqJbvo3GCe}ISY3yCiM^s>=RBwA5fYgN#0RovV0AVG>HiBA$7 z_BG=*(bt%x!5hwgj6IRvN()&_VOw?&9qsM0@w@VK2U?50zHBZi~2FVVXF6O%3e z1s?ZXhQK;R%%;Is3-!m>-zdQ1jbO^1DKoEbC&uG4cRm(vzfb|HFIT&90ND z`7J6IP(Zjua^0MY+6-D+S3aEWx!Aa(6v}b3zP0$C9pvBHFg~6%5kicYX^T=>$@gh$ z3kDVj^3=^x$k4)Lp}hS`?23ZJW);fz5}eHq+|@7}@5^XE>(ldlB{4?6)IedQoNn6a91iwQ%bB9(e~skw?kS6*w0&v~xq#rwJ1L*l9uhl8 z_^(>e9W*a{2nKwchEmyh%@xydRwj=%?AWLWc}GjKW^o8pL*6TNeBT)-B6sG7 z^f+N;!;*ajUsk;@jQpR-RzI}=szBT{9%wTR7ddO2?$xyMBZu^t#klFx@nZ`aB1wp)S`y_i<%?``t$d3 z&sN>VPh+*4TIaBt3>dfArE0}$w1O++ha|rg8~%Bi2$QhJba!vKbylzin~1QuzUd+s zAR;xQ@PPpEzrG{zTd@UrQkKbhnZ~-OQuho1`|?hYe^YQ9vW*R(IX4YW9q9g# zXY!uGXOYbT^bs;*kwraxJyQ4Qcuutvk5R0PUq$(P-p9wFT_8Whuk^AX{NG#LaT|Da zf)9QJEK!u%&LAJ^?3tK{iHsOgRaqMp$>(EaeSEZZ+oQjCDj`PZ+)YO%;PHs3)M;<0cfTm(^Ii>GqAP+iX$qJrFYCv;c= zcp9$wsAQ63Qc{kLW=n(YDDSqP+!*AVm-tvfw%A96p^li@)7w@qPtGkLnehj=>o);n z2C>N0c_5G~=&kkKt+qXr#vZTSb6SIjZ3>2}vG|DHG@WHQv@eWw{Z0;-q!=*woB>cE zfA;?ay3+AQ+4S!Jqq@@d_hh;tiepcPmYA64ay;Iqqgk5JsV|en%ScM2 zQmFLfgTs+#N(ck$8^R^O4$@XRT)zz&r7n}Md6xw4qPBE~GT-yw5m?a&Bf;TmHuYA)9eS zb*h(-jjW3aY`_&qxL`v6C?UJ;_d;8D&wByY4f_VkFNuqNiBgo{w(xi{h0bmbB2arf z%Jr^;I6z>1^T0No7VFE;pJtyl&IQ474bL9lS3v>(Vu5-Bq=XttsXpu*ERkZM-xX3J zQF|p5G_GQG55;l6%E5azBTtH{7MG|K#h*XJ1{9I2H-Cph>w{t=SQGn}?(X{#6Gz9A zSTp)4A0m)M4LuM4{PJ$Y(1fdiL<*5Bf7pqL9!uk6rf`KB8yqwY#K{)D*~14p~I9U1%GHb;extG+vPJ!Rn?xF zWG6%;x4my?pC`X>p0@o#(PSC7ZQEzB`mijiZ1z~Wzgy1t@_A&(e-tXfh)QNdp_C}p5bUJgz)E3*maoM!i^P)xreA1j`52ZW1-0o5Q z^>TWG9TrvK>}Q0I+|wtL)O*Ry4!h|hcuQ85ksZq#e0JxpdDwtGo`%o;qD=Su`Y6>Tj!X1q6&*y-ja1z8Hr73PfM;SUr{-Ewe_;mwjwXv6K{+ zc0-qcw-$bZIZyMBUX?DTpTd03Dk;ByZU1$cd~gshVZl?@RJ$>!|f>I<*kk5 zt<3|tfG2oV=&?@VtV}6?7b5>zFjpf$iqC6pZ0Xq5rn6LoKeC?H4KyrI%)j5>c+6`S zjl$3b4&PGJR_5gmmTr9zhlUc4I$E2eNW{h70ns;b`V0xQKq|2l@-GOS7_xBcbqC?bUo(0!9bG-Cj#-<^c!o+Oc9Y*y|GD- zpuYL1ZJT-4B`#N8V%=UtJTA#`@^;`vpc_d<-Jif}Dm5P(8z26)!+jS2sE``gpW;`~7t} zFYk*YTH=(VG5DxRm$y_3{8@-d?7xt_Uq-B}!$00V#IvE)B9$8)W}_%b9B}0b7+mRa zB>F*VRVkCr-*+6I2_JkR1-%1EIq9pj5gHfp6bdb^ii(Qq3JbMl1Y~(U?ccTJ{Z_It z(MYb1jO-L>X!fEK(ov!-E~Z1ebSy|3wYANq6#Yh0D;4j4-x84upB8n46?jGZ&x=u* z`~zBUt~vzQCU;6h#L({vJQUb{(YG;D_yuKnpr{ua$tL;E=CsVOXmE&8Ea;|h{)_St zon>>j6zs8ZIr1e8?zHsp*brJ;4}bn>S}skCF06JcS{vOCM;sQEXYwf=zwuC({*&oY zu_T*I%xX^)HneiHdzyz~zDLMcVRq93>zVeJo$?$s8CokyaS;NdMic@O`dR3kM}k1e z`FSdz>!!+lC<-plw%}WY;I7=_^ei%gErxg0)$G(4hZ=@!>+x0Y7NlDK)q9DjZI-bf z_PRce&p}j1mY}9JMEu&t>6VV3vFZ)pUpaj8_!?e|jhKHBmUY2FeU|uAyVuDghCbOu z5m($DiRoncgakcE*=S%@xv=5(P_9E){cdXOEA- zVji!9B)R-82aiEC{7=D^jJ}V1oh?Tt1Z8r$fBsxX%aBQ^SGZf~uKKEZcmB+!H%J{Y zJ}ZSOo@;v?Nz6DaxvO(^l`VBdWb6OL;3^)I^&Y&ozokclV*n|(K~_ELG+)s>L89?S92@sHxDrYFZ!H#H7$%#^>0~zU)|QqUfFgaj78t}cC$vXK z-J{O%C>$xkF$#Y4eS%lg9O!u4-9`Qf|59U|KlH~nv?GhdpfmiI`^9LbyG6*o2fxqd z{p?74$8LXs4`$(Z`3Qe(V94rws}rGyPhDI>ecj!~B{>D%e_h&rOz-%H&^7;iWQ@Ne zuL!fQ(?(AA%>XWf^)Zk3X?0T(OMe3!L+Z%+&9UVidQP8`vg*eEu{0w!;TuA^>{@o+ zbr)Xm>G>htvD7hkuVQ~&vP4P2e?cvmpMD$Xp?`_Iyf{aW4tI67^>CO|0jJmR74FZG z5p2PFeaamOXwSf4#DHle8kCBFh6>v1m4onGjCt~+h|KZZIx2kaM69t)&7D_QR`;{z zYq-bGG;^T}RH=-)b8iNZ4PQp%2b}D*4<62ch8r)aJVY&M*@<&daYxf!T^+o3LR{9( zB&BR54uc>dU@9a<1XUW0PbKR3J3?P}$7F%`4`&njkJ;j;rRL*fgBshT*?N7P z=y!Lo)}*tXWR};$ln`&NszLrPyBi6kF1(kpoln0t|5ZL}4B^ zdIID4V*l6Rvg`ik+bYuhjj`W4!G>dF(X2rkOe3b0vyCk3Ob>KUz~p8ihz!@s7iF6R z(*@Q{v6y=l7LrjvO&2~;DAgVTm@~Jq(-xV1W~zX6#6hX$D=rvwzc`?? z7`xkhaW~aO$a_0Qd^V=ldkDx#NbWSWQ-z;A z2LFxbBIt>R0Mi)rVs>ilxkLj6ffDUD7ZtR{##|aW_)6sqe+TSahjnUu!AwW6*UyY)*S7kD9j@#J!?l?!EZ!y@uBz_?8!% zUdb_~|5*JYL&g8}ICS>AGiasrrMr90@8Nnm+H=m9nXIMVHh3m3^3p6!_piTU8qO@d znz{Jt;6xacfr>X&99>t=cFyj*WnX(o-{E6#i`KSnD0a~M@ija&NwaNmtP7`{-KbeL zhFq;A z&tqu>=NXf!{W3Qzmw$8_-MiX9-IQ+75TAmY%A({>enRDR>8LX@=g=ftz7x=6FlrHZJ=Qq*-a#deP z@by_}d%@q|^7^lT{lB^Aa)f1E4_#*tj_{vEBreKs+ysdpbLWOJCK?({L%%QX+!a+# zz+E+jACJ7BAFOLWmn_x^wr$2PGi$Ss8hW43o~^<4V>;Wz9~qJG_Lo^}DX-m}3pRO= zGk4)2y>oaAjhaTz%8ARLN@p28*{(F)Y#F!e`iYgVVZ^h!3`0HM+!?ZmP2hodd?~-J z8uKchX!(%D=GR)#$B9L5$o8c%XU)dv(&X83lGn=?V-yx9YP(jmG;Jj;qQ{#TKNKC) zN}`tAB_l+YX8#n0m>3m3B@fX}wS-`aC&+!cvgcRc>siX73%UI2C;j)_+|%G$$xI8g zYae_eV3)tO^Zmq^(j(4GuaTC-dk^-PB%iM|RLkt{+y*YVEULp|^}-fTWUva+>}LeEswN$q3Cvk8X@OcYqi;nUWw&cvqAs@=qS8m${7(kZ6e7+(kMshj}&{VQ1lMMeGoej&Ku+0JCyqld<7`!fq} zWEs>n4bF=i`o?9164Iqv2b&ui2-nDkY2+3Tk&BqUzVl?5i1W*rL6E0JBg%8JG`VsvpT0Tcj+ojIavCGdd@GYDrnm5 zG^ZJ)X!|EKmGU~#a8&-n>;i>&WWI&8l$GtncWV+8A8(GZ ztMyM$^RU@lI~tdTRh}JT6Q(n{p>A$eH3a5;j-^Yps7`6Bxf+k-;NalLYPpG>^>Jyc znLbHQ2PpAIGxWaRN!tU%4(DsD`L)>WCv;>SBt5EMoqF%P>eO`!$R(R1%YRUdTJ=19 zh@UO)SJ+yvL!}eqj*JKkv)hbK!GHh$B}*(rn}3Nyhj}JnKw(^*%g2ufJzIOgv*eH- ziD%!$H8-!UtVn<89461wdl+5m^2rI_6aEmkWVyO3E!{biE0IsAs0CB%o*Nyl4jO?Y z%@o4~znN6#<_US(Y01M_VpLM_lZw>D-ObJPp=sNWgL(!LBnD5*>UY-Y622zKe`O*P zvTtB}?olWi8@n>>l}Bl?hz{gWPGKiB_ES1 zV&6N()f-2LTsEVWa>I1>jZgH-FA$5k-JLO7*H<$0#wvD>A0B>|Rd&%dXNgo~)Ycl` z+1mCgJ`?BA=uF0;MpfcQuoa=%LUyQQW6qE8$G;b$e?+5LDk>dPZUr74{#A2S>C zE_F%~9S*0%GFgWrB>`hBSuKOA}>EZEXRU z-Z71F`;Fk|OLgGLHU!jEBxrbO2;E=A$d3P*sQ-eS;qs*Y_BkDyv8EgBRNGa(uj+7W zx3a6JM_5phu=4MNhmSKKS0NGyy4A072QOc~3|Q#X0l%H7on+J%`LhNo6pO8alW+|U zVXVC87RCzjD05hMf$#E%lIar{Y3`d3HSMRT^_8vXSud-!yqB{!v0PBpnX9YoA@Bq* z)$m5r8-I180yY~+81pTe?(BWXBmN%SjYgwUy^gJ|p6y_8z1>{{9jxfqNl|E7nIq+gj z@~0L-mVb%-Lh_hI-;+W}H#H@d6}ZZC&lh)`fN+JKn9`Zn(We3FEsZW}x?;}P?D-kL ze`g-@INi~$bx~IyQBhHXmzIlo{`s+DL+DHx;Q$_G`4r%f^NxwTX+&ey@TAL|uHj9g zPj^<&76YxSNPjpyq{jQLE{T+U^yZDfe@S`8yZMKm)SEbs)vi;-{qoo9*>Fio_d~pY zRP`ry5@6N0xDH<>x5W?W zOy^S~JxoZ@1XemZ`MM1=GmN>rt!<{eo0-kWdga%|k00+Sy6fS{4JG^S^l=s&{8Q|6 zb)FH;?etO2(ZD-*Fugn!6sW2Jrd&QgL9W2A&v>`*pwP3O9d^ZAeG|4M{HV_Qh7##_ zW=oNMY$fkIUSj@i<%R6 z2TSLcg1lKB<4Fn%&2M6|ct=AFqcJlH|2T_q1_{r1)%Y$v2L%&4qGYg-iDaz}g|BbVpVo)gQCzI% z^T`d2a`bux1O%w+PDWla(xErvlIl)W%z~uy!yq*bJX!n!ZaOL|Do(9gMfH=DRED$F z)kkUEsXbe z4RATVi6`pYSu*q(7%aeHHa?T){Idl>9$05A&`BuLDptDq-CItib;rhfBQz`mhr19K z6jrSF-dQ`kY!R#F(WCL}mJQP)S#)J_Fw`A(lvRA0^X3&dH?kQ9yHeVo4Zb_x5bmvyn-ydeamM4lA?wLlVke4Ml+M;{s}f z=#Apyk8G46qz~JFS-`3B`O2SI3wk;-mH=aWM2?j4i|dSqR=2$6WfTfEnUcbyPU})! zxx3nyDlq0GxrFN+8WIFjSl~~_?*)4)A8z*2wdEw1))Ls>zsw7lM6%s}dS?$ZY4b(T zScqpC>ZKg()!V}=SjpcrxIGm0?2V@5xy_M))HK6p6HXCCXtB)s;~Fr(oSjm{#QePc zqrE81Sn`DCSeQQIdqAjCxsC3859S)UZET#cJ|GHe+pa?cb6Z+kl)wzMw0q0zlasUQ zL3^LEHVyTg;H^$0@=sb$?7M4&s%nZ!jiIt~4MM`oZN?@B2IGFmeGL$NJiOe8OrLNZ zoUgP-ADB3_AO`UbiiWcoxlXV0BPx?;YahJ6h*Z=rI&gL4y+2x@F9f;d^m!q1f19QF zF@LRljYlsMhuxjKUu7LevDEtZ&71Sf+yVOW$;o<;`PBRf66%28=Ze}NPG>nofN%%% z_{wj)SC{V5+S)b|_Mk|8@y#91zuPaqq$;Rr%pqLbkaF9?vsGVGQLpHXIukW7V?A$< z@)-h}Mm^*1M}%@CAh6IqB4yH)wFO|$y;cpl%@!UCXJkI{IF6bpa!H6!zd{5Zz^x*P zvDgZ04^#~X`|aD4PEz~*GLl$2iB_xKh%t2y+N~t!v~e3cuMjG{QS1z zP-nrk!qYPngXT-qZJQExvZSQr9@XT*qlSviXj3X`YB9&*x8v=!M5{18$aX9jB3hhF6!YMVix9Q2-$GX( z#YnE-Evj)aXK!pfv9X|FN9)h@NkLJ?jgnB>?B~2zoBiN!(oR86MOD?bAobk0)i%ez z<3EO{CUC{}8lW4Pp)$C^3y2*ay(;q=2DH60Fy=}ZUm|8RZad|da+cspCQI1JHn^*af z!}eg=c-;W+3liczRQ=^5{=zA~oz|EFfv@w`9|<%Kod?p`c&fziJCou%UJ|(`#p`H= z48dPza}1hNu}PGr^?&XD}Xiotl}R$KP7!q2YixDkW@&?CRRA)^{a#pl z9^t3+(9m@beMC@AcR@D4eSb93?&4$)Myq`-mX2l9+(lEzg&`MsIBrm=-*P(3vrL8H zr8=)9F7p=GX>8o!!_O6^Rpk}bPOF;-JUCu8E=8#Xaj&a{5PX$gD6h}XNu+k6@*iD< z>s3J?{@DSl)&sGt7u*?c zOT%s~RMBX4ccwH+_%-+N35TqbfoQ*ox+|4gRpK z^Brw_%3tkN6t$Ax2Vn5Z(0s2x(!ff4b^P`cG5dI`H#YZ;*HwXs-Q&x2yoS82#!^*| zSwwp6X8(KU5}sO+ADgS~l7LwQnm6Eg=YN9R{M<3=Q)+RG8Uep&Ad8vokF0fZw0ufw z*rfGcXLMj%Ven`Q>**;Z5ij+oFxfV|DRfUBO+7o6)7U`b2rg2oE-6o{noKlyj`{qV zk29fyLw7zWd!BfI$?np3ehQHI{z~z9`)O5&pZ9p1G3HDA*|ug+$jLIZlQ{lP$)1B8Rs{wSNe8jYS+JHE!Kij37}|uW74b z7GZKy**Dl$%e>VyU2KFKae+Q_*ucip6B-2s1kW_`+@a(b+!s%NKPj7$O9{ zVXWVVS>d;>WQ>hYTres3{CmPLWlbjYja$@xRtoOs^=`Y|z0Hl3PfcA)YdT^<`%aq6 zJ_H@1@-nfsg6zC(vc%@1s*(#;!zUo&A!E+vywcMCicF#8v@}zMFPDy5lBkD`2bV$X z-l-rDCDGG^jeW08i8E#Y*6KWq130?o)$|F4ok}_{05O34cD25l!;5(J9FE&gV&Q&XC4xkK)%k_T#l=KiC$j(WZ?lHhc}GDUfP4ALU~UQaN~9 zJvFw@A;u$;HXdZ6btJoqQ?CZgUZyW?vs z0S2}9czQy|$H$L_rO0|?O=;%i+~6!}mw<0|DEZnu-IGSm=UI|$vYxK4zqZPG(`Q8o z^cS1=QH>+nq7^4`I${oP1&O{gl641-3Zhl6M|{G<(2J9m@84@UV4!TeJ9pmqv9Xa# zr1QI2xVje4TBoc#v2J!>$qrZ#ctX7P7u$}tM!Qo}H>wVQMJ5&XQy_8tB*^o@q{5Ik zApFl(H9zMuhTHazJkLS`C8s}rQ2VEo(e%U{Pd5lZ?z!U`B3ZJrya^N~Z$CpT+07#*-(hhd5(uL#n z2Vdw%=d)X z3^ycAH`rFKmxITZv^4zQDJe^5%gAB9r@pqr;oSC7p4;t-Sgat;l!VJwmp#8H1^2*c z;L6PC+#I_)kBhzfqW^sVrKC$81dl|0#OF(@QivXu$kESO!C=N4lt=d#x|~>(I3Rb5 z(2Wtu9D&X&NI5V5Waj2}-dzeRs;++dL+S;us4Vs~Q^eYq?`ldKVP*2~j%ZPj^#@}} zK02%l_Fzi|r9k7J%zkaR&Ds}+l#ZcBP)mY!T-ec zvMCVrW{J*hBIRQ14eATU$N&|Z;fYA#*gqQ0y@%Yi_4mZb+>Z2eBdFsUuDSL>_#Z79 z9Z%oz{eDvW>VYroD#_nuw6&Am(MFjYq#i(un8I3sw~}WyrozI*Dv+CZ*gh*MN0HFY z=o@M-uc9ShiQ0@M+mG7~ostk`rbH?GN*e-!xU^j+f(qYf3;47MAiwaCR|Ht8LeF{w2)8w}#C)#y zar9BKF$2E_B?I`D4t;@|FH&h@a-#LLha5}8DcR2GNZGWfCQCc_*Com7X{d7deG7xe$jkIq%Z)`0;`L!IzK_Hb${H8_c7Z9*^Ym*}hBL~DEst~Oa; zC<5wlE#Q!JLe4z!ieybc{LZ&h_Wnkvxx@4b`h-7fN=7ZqHH5m0O_8K*NmYooaH8oy z$^zJ*7as2K*@-}j=2D5lcnYcJx0mP))y=Xg#R8&e~jKI=- z;2P_eNDnG+E-`c`AY)O-{b_4V33T=F00S_?+1b}>=u5ckr%)O!deLnsJ*blRNGVT??by%3W|zp6T!*V;Rc_qhM|rF zV)y#?%YByZJB>XV+b5@0b4BHU$^o=s>fxui5)wrtt%~$cfSA?JO}?lZTGw`PEL-Q& za#Q#)`txqPFf8qhvS5C%GIlFGfhV$E0ed#Mtvx5LprzNH_9%{4OeA1qug%X3*qzd% zJg48*l*Pow)>O(%Zq6-VmzYIy=cIiu4XtB}Vz0JKJ)L_!gsFQeFd!zwlwH4n?H4C^Yt!CT3R$6wl(wsppPikbpS+!2Z}?f|QUk~2 z3V;cj>0Uury4bY+%DlLiA{$bU*-Na=0{0cchAgt*oh%q!aQxrF zQNT!)_`Xq<_bgD90)%cv;K6~OSRRaC}Fu)zZsxdCk)4rg? zNY{}5>4n=}1B`#m57mHd3#AX+lQJ@LimY}^IdpPC8gt`gGbtK4q9m{UF}_ES)b{6V z2YyTNM+{K1?iq%4vfq*<2dNPX1zr{XeHei5qHgJ9U*5IfvujVA{e60+ zTa~YGCxHf3%R4z~slKO({p`l6x3``y7L@>+qXbd&pnfH;DEG4ETJ||XbtshPD^X-LXv}w+_Fa};;f`3e@f7mHNUF9y%K5ye%zeN0a3UyLjyisQM}n-- zuS+OR@NceDv9ANNvOC(MyOXXVakc^w{Hy~YEb3CT-csi3PvGZmRtjmXlnAZ(mp0!A)sf( z(%7@4MibmtXAH(=r`R+9QTIm8a1=RJQ6{U}qkH2P)j;B&pR}>HwRAl510bAO|24KE zlZfhRN-|#CP@`RK@Hk6!e+w1>HkX<7a!kyQb{_FO`NZRCVE5#nI0Zstf)rm3_u&2) z)vdqx)hEqGrGjqDd0P_5*Ifl$nl)la8kfA+yNhnE1mKm{&N-KxODg#GI&oQl{%Amj zkM)y{kYqUR;en^lI#YekKIWD1ibP?r;JXqu{TDB13L%6v{bKWKruaHULUs14eI1PC z`?JC0wzcg-<+$Q#6~#cHVdY>NKAfC2Zi;fJye} zZR!qBBK;w)P{lKcw1JM-IH-)J`#baaQR9i0`rCZ`vwt_WvG=mSbU<5Nqq@UL!ZJB( z53d<>33Led+(YVDiq+EBcj1|))5_E8qCVey!}4nEn59d$dWAIhx-gJNWvSs2o*&ao zL7ljRuR}NNLiL*!=*~G;gS0=;-LixCzg#>CH~z zOZ`!pD2%&{iwk7U4j`Gr!oukD5#H(}jEkXSiDss*u2#7+q^qm@^rBBm+0o-hQ`zqm zsk9;F%&wr3^Xb(;a)i5gviWD10qS zbI!}a6Ux2^^abZV(n`Q~DOJH*RcUWR#JT0rK9|NYwKH^`HUea&=fR>**&kV zd&&IUG|H&@QVVwCUcF8JlC)#bkMBd-*X#|Ywr^dYaWjRxJExRT{RnvZ7ScBWCMNE= z`njbU)V|+wXA=Ro$?iYVNO*yyE+-(~J_=i1k^j|BF@)w6El^g5T*AIjhj?fl}DqYb8nOy`q}h2mr}KfmBvvL(6nexi9V& z6&Ga|yhR6w9K5lS7L~d`Ul(g3ZD=>&xBIE|eKk_macAYCHb5m2+}RQlv5S#NA-9pc zfatnpb4Kv`Ro57O#K%8lt;3Bgczl|gdXA<%f4K9KVv!$Oy!eM>-N#D}?&b5*z`(>m zxJy7Sr)tE;6v+RnjrQv^dM<~8Ew2Z=y9N2}qAlb8F2|kg_2YT=1Nn_4E>4^cJTxTd zVsEdx8H&++xM$230QZx^xs5r`)>;|6wAXVvTY(v-!jDnmHQZ`a5;e(LKy}YE8Wh!# zW-;G#59ke&hkt4qUJk*n$p>&AZSk)5sAo&=PNhJd4bI@BFQjTWx#Op17D4kaBBJo2 zf^DkYc-Hid!k!+5Yfw8mx&A~I$XZ87Iso*$mkiI$CGX*G=IZI`M!OcM4NgG+O_>If zG4!O2ox_*t4kZBrk+B;Ngdti#I%13%6!Hg?Ju5e^4>#RVO`w#~w<|(K$h*3J%x@l! z1k&dH`^>u~rZM}Qn|7BOpFYJQUO{Zn%z0|RfVjC6hiINXb3X{lLjQmDc8&v5<9ir5yu#_A=-LK_P(*iB{Ne001_MzNMkwdDWVK<+u1~y_pgLO#Y04}`%#>_AFip{X5z|RZ)hW2V!wB;$|a5h(!mAq-S zw%?*trrxNkM3z`|fWZ0d87unQvWU4qE7aF8^=p2-{ND5!TnQW!_sp+W))&@i&%@U;Q2eT_UWQ>*$_PF7!?Y?*z~Y zuPyKU;CB3&MGTDG4aLlBoioggj4ZLfiZsR3W>7Dz*h7eZ8vL4T$nzSq$?*6uLR#^_ zm90Tu(?!$%m|`?UHfX8JlDDr4d4u_K{G96_%S=Wpx6}@17!FTd`EDgoJbx6fFrXL* z%EiMX3lTIu2MeMojdXGwn9{z1;GJ^fC#X5wk=Sb@#b^DU($i9Vs}3O@uLz3V$X>G) z6|@*Wrz->gQmwj}6%Z5vo^h`eleJJiCgJFE(BzHm^*4I?GB1kT`Z>~iwj$ta_S26* z)W$mHPS|S{>Yg7oJ0e0}ZNDk2wfepEwj>jvy&6&=dPi7H>bvN-Uj-n(3_SeLB4c#| zVS8v{({u?J3vcgGZ0a+%a_%f~zqLPs(k3H9LdnN3U$!(wchyjw24Eb7((d((2}6Y; zEJlH^=c<;jPva1k#B&vO?5A=><2cz^I`OyA8%t3&LV`bo#ZsAgOhEt zaASphOUo5f&yaV|vfkzqhTj~VVH=Q2FXvZ;{y{<_OJLUB4<8`R4nS|`>g0&84_C@R zI`iMP>Kc?SmcT<`4it%7P2PgUuZR|AJt%&KaAgV+eoQk}EqwU!L7EA7EMP3C98M)x zx6;lRBdYQZ`zDk!4`=wP(>%K8mW_T6^TuuLb89}VBw6&sT{YK27a(Rjo`XQo!T9(m z|5Oj{(9Z9mPD#Dhj6k}2eoe)!b?oGsB8Q2PCeW#jIXw+`l`{giWpRwu&js_*)Q=7h z{?%=>CL0)XTsa>aZ3yDEIta*w*&TdW4(E`p-0>UVHhQ%T94iihO-o)JpTf!`WF zUhBMDG;PWBHsVCwn=us=6Hk80Ci(JcN*B5lpixbgNB?@VfQ{e(+J6YCJf_oF zZjd7QT0JTl!vWK;G<}?Q{6L`D=SvL+rkdKmmE|2=Rja(%b5h`5al2unxadTz+yy!4Cl80Q z@YSl@7nTZ2&)5=bC)PR^we;6u5J5)TGc$IsHqMwwr#}u)FgZe2sg@jQHQFY3q+_v= z5N+Rvd*ELU_H;i0-Wr}X%{yd1KUb$$ZG#fu`#nzki1xPvjmC~A%R|8OGl>!x2N$j> zP2P8PaA=VcEiGjqP~zse-uQ*RI%13;a`gKz3y1*F;OuU;c!L5>pVSLi8Os`h6tx}s z2ro;ZJFPkFXgG^w2&^k;YN}}Cdc&$f7pGKnE;k+{9)1st0K3sRW=aeFTY2pmKT^wm z8`MylZS(cg}snV*+=aC|i2x=ZhvU2a8+VzAejil*Hxw`ruSD z_`pCHQM+*DZQx#20RCvp%j*}KEqT)+t zZ#;5*g5YswGwT?UUU>7RFQ|m?o4A|K+{Z}jUoS8Fzl>0$j?!}yM4JfACx2xBQ|nIc z>?7xX|9(PC3s_)$mKO|d6iUlkr-${aX-WC)7C#WU41MKSAM1>&0Ft-kX|0qJJ*;WV z5@AE3ELvEeq@bap@j0$BF08WAqFq>MM<{Kbf%jc&00f*Omz019`^6=aBK6wEL{AOQ z^l5d4ELd9FW`Kt1$D3r)LWknB?Z<3TU}&bR1Rv5Aw~ECwyG5q{Obyb7W+X>Oc3#V%Ctmw!XecF+M=y&Sm{Q}_3` z*u|x>1xvA2znkiOve)WK*c7q8iC*Z?+&0!szF||Dn?m_JFX!90f`S!)PD;x6XziP` z#kI}TSbH_578kMD-AZ_q6~zC8Wkw+3^8P;e>>SSPfHrxrawY!S*?6I6PO_Y669EMO z%0u=@f@}>FMbKozXB^nSR~{G0G!xNVpRO^G2JSJ4EB1kB?6YOR(lw99f&`X=V=ZB^I$S zo)C1BetWe#%W`|V)_!w&CUqN#-mUy<88ku zwIS7<^7!bS+SCho6~-akefo`E8_3FJj~u^tZmGViB04@rLavlR@s*dCSC*vB>g0|b z?LyATw0dx+pxiViWyJ{Joa2k#Je5Zm;`_+TwzgHE3G9CGxe5mKgNumA%eml zT9;d#ryVIAu$>S<{cYx4LS3Z7F6To54^5t=MBpGcP(fNcKwn>9!`0O~nVS&YBwkwc zAPVVIei!ZW%)!-~?9#MMUSl~eAx-Z*t6NaL?{>@`3B$(Wyf z!^Xvydes;aVb_4vwqtTxkhwTpNWTk)>w~FqnVCI&O1bZa-O+RPUnqtLLI5$DexsKy z->dV%a%_UC*7xyjQ}Y&a-tc1Y-9-9dU2Nm-y)kFUXZm|Z6|!jyr>Cc1K1abTD;;mG z;Y*LMU!*JcF_NR+jE1;&Z}qLVeA3a|HyGand&{id%f0sRFZS%Nh6nQT=zQwqju!zC z+XZ*7|E=Ni^ZxAyzh0r)pO|lbChkAKT`8qs0i+}@SET!-k$^GL8kHnp$cpu-_xrYi z7)xVEk=_*|;_&nJSp@6~K=dCSd9fjQ-RFoc_$&a$h^a`8K$T~J75pydb4(wd9ra#n zsl`Q<_;c=N!1 zfxd&>C>4G(#Nnfhr)_Lp-wTE@%D>*E^XgXzwksd1edxrPU&-)ia!7Uz`@D!0&*UD= ze4_}sj*N}_Z1~C8m7FxysMOVY>_-X;V9ITk`<%EIU&yy8?Oq)spnbypd3%39HA#5* zr15duLd{7k`P?r1gv03MWVgPQTC|>yj>=N5&4t>Yx+sIx&%q*v?U%RD&Di&7_3{~s z7tC>h+9obuy|n){2MBLSLw4&ukl@TzVSOsmE}R%lP5+el72E9Ask=Z=56T;U)HiOs z2w4ij)cUW}_5aznV+4O=nLfl~guqz?_VD32*Sxf4-U%NvCaa8!_Upz!Cv1L17U)0N ztCFN%adEK%YHEJ3U|Mud5#e;SAZ~mSes(6#qP%iU#{i+nlCC3m!Fv`w2RXuE za@s!{0yK&VZVgKQyV`30Il&X}CInC0g^;~22cQU0+2WFk_~W+2ii)cIoM~TiGe=1^ z?(Q(bb`P8$+L-+ms$ger>*(>rd4C@;*BxVoa%V)U)P<`JRh+V%Xi0|FlOh%SR)^}V z)-?1h;hmtk##y~4pv%B*j;%!4c=ak?DnQA}*t+Ah_ZkB+TJUDs{% zBT0$UV$9suFQ1w02>jTQB@A)LKP*YQn4Hv2OgCt`5&~O`a=yX#%oaU#7FbAQ1kW=@8uQlE?Ju5-EUIRVYIi}p2~drR#qs1$=o`2SO=S*&s72aEFIe+?Az`R zf1AU!t?gF8&Rtc5)n_ z`!NSen@ILmJh_rpCL>KE9AM^ZGw&Np9kk==4u19?laHPjF_ogRzXwH@75F3VZ(f1Z z%zQfroI%ViF7ooY>duHkq;gFG>AU#0*JUr%kK<^y_PRRIK7F0!fZ2w`c4)Mo@;Giu zq>K04DZ;9&r?=V9Tfv{v-nukTnmtm2!Av~*%$cTl4@&bN55vC&D=-muwwuZQIE_nP zh1%W#&`B@d!r8{{WP7_xJ-kotQ1u(!CV&q8*{5x{0JNUz>AmQO0b4HNgTXugR%w81 z0I+ff%MLIhJPz*VrleYGYljpS=>wuPLxhv7`D!#Zrr*4{tb|y7KtWYG?ZDiixV^hJ zV9)>+L$^c8XN2=Y$8R|Ke^>#XNwDS}x3q|D-F8ZuaJ{sDKZfl-HRj57W4065s2|H*%PHlPnnmcfttC7momNMxu zPrkh%09UJiqfEmwfzt9ne7AT`0Nhcw(WISzC14EU^DkD&-Hi$cX94RjUB9!vWTJKS zD(=rFQo{|Vf~*QPT3I1uhbOmJZ@_R;IG^p%Uyp~MKXWp=J>oQ6x3TGsqaW_0%S_Ks z;$v@XDgEA7!NtThF*I(4niD=~-3-hpPgdwJ<7s~Z`pZ6O>Gm)m7?c5sEHw=^lRp_f z72uD5{c<9Pp>=+~E+O#d?{LwJJ-<7)WjDlsTmx>~Td#bJ)!ObEfEI7r7FJf|IguB> zi*xHq3F~W5T1uNw&bM!`K(8EktWXaP&-QE9Ig%2!>Ala7YqT>mX{@ZsuI_mXmjS}M z%5K`LdzmS^-oKmf=~K5Xgr#dZR@+_q`N3!~cXrw%*Od`)6)6CGw%Zc{e!jlnr_B>M`6LUeOZi|` ztzp*7zwfMDkDB^9cU}Zy2TORFS1nIn%F9ZcO|&>!{5(CQGb4I4Hgl2J!+s$jJ|NF0 zZ-G$`A8ce0UHc(<=Ldp7^b$h3S`iQg1BQSdY@<_kHx1SD zVQPI5pB@N0XSveJe#6c5={Y0mio-Hva;iRu1w}1O!J#ad?|fxZIp%? z4{tf(W;>fgN&+Ts9v=SuXd}cDvpq{0Cj&38@B%QCCp5BNiqklhmO;U{A3IiTqOSMm z+q8wIJL3XjS~tEVqW@(9X`ggHF#epxePw1~>$Z0}5Q8?D+j@Kvt6s1En`%!p%9HH} zjCFkf@#IaLUo4&Ex04X7(r~~%X|=lAyB3o~tx8%~!_XGsZ|Uh{b_S42V4g`jlgh!t zAvsv9rd=yCnmWbp!d=r&zKE7d>rvbF<$!&DZLNpKW;miE^vA&alO0b zx9RSda5?jl2eFG^Z|Z+sF=u=x6nL1krbnb+A>mX1h{q&8D<)Ys_d3`u^(b4|jDHaO zeMYC(5P}phkKG;Fpl)i2`41Va*X=xyOv3b-#ch-&To!MAL^mYL{WPwuu%eA>>j_|yqpHx|3M zP_1-OuuVx_=xDtY?js_pLBVZYEEOX#065y}>KoB>$n{}AhWMIlz|r>N#Tx-m6J(B) z@T?gc4Q^}GoRh5?w-GlRg{G5>Z>x*CWC9e}Cay1uJR!jC)$KWvnbfyazo34xfozdL zPM3wyh3eJy-Yxx_r;pUKXWH%brKQ_e-U;nN*v_X+Q>Xsr>wo)*jF$`0%xn6 zvcBWZQ(xahV7~nbdDO3*RH#CeB>YlLNGchC%nU!#5dP zzxMvj*p?*S;W0)6W0;K4h0y%V-CdLk>S_>WY+Lu+GxjUkSXl9edrx_@g~jsD3D;O& zo0i_?at}$ViV>W&&-Z#VZF2$eZAZ7P(9xlpySr(o+gTjjd^*MK1(d(_R&2H?h^XAP z1}-Mey8Xm>?LgVZ|5zMw|9@q8V`wzUBXw363V1QdnB-pHq3f)Sdc;G&(7uU*y@H*^ zX#1DEv5-mh?^i?+ccJFIuIC*plhX+QcDk<~VA@`>B>hfV;P+mjK+DR^x=|b*+x&6& zW=@O!;!j|pCOjc_?NhSI1U7Cj{Z75fX!qlT$^ehcz2=UN4#msIE}5B`m^ivr*3zz6 zm~cu?I@PmhE8j(R3Ot%@jxQ(A-v0irQA8K7LCj(paFPBNY-_DEDDKi$c>N-BAk_rv zIo>KecJPQYy_7rocgV>u7LBq`ez(ICX>+iE6yy*W2B@C+ffW?mzMrGhM|ILu#-o}e zCLPSVLqruNS#IdP+$uvq@B8p8;5%AZZv%#60G-=6*iS%Al)^xuJCINtfI^TaF4kF~ zW(blJ6O-2enz(u3!eBN|f&qAnYdi9HZ4epb>85{Ul&(!SxZuiXJZKJ&xJxG zO*ya5ZaS84NKj5FsRG<0zxHv0+v#NIX;Na8qSr}5$@tm{0TB_u4iYf8J}AQ2JT4n| zJ58!zZ*9`iIbY#dUla%${oKXW>H3ZIQqG0Ef}hqn->37o)0=I=+SeWEb0eTTPxN8t#;eeI-#KP@5O} z8oC60YG~;ml@>VhMD&O!OS~2^JO>c&%%cKMRXQSD-N;}9+%4XwRFq?;84}Py9i8&g zzh32Fn>>E<>UK^I(G-}*ciFir6ffTl_xHO;>SQdAH~Vc0vGuX2WW0ts82J`{ca+ir zk6wqZTweOJP+ipm-GDT<%Q=nZcz~j_lpA_!6GPa$T!HUoIyWH~AfOF39A6@TX z0*m*r&X*@vw&#c5yn?B}Y~d{2e{9y|+Hk<8Pusa6m$ANy7%E6!JY1Y(IN93)c?!%o_*b2 z3@}zYP}H^q2I>alT1+xb@z2nLG=9MPBvRX8$OMei`@wNzq&4k$cp}Vc=LMRNI5z-d zO!;h&;R!3y*UQLgSgg#Vdwz9w-Py@VO+(}0=l}=N^mr@+^W9~lqxmSO9)X>5NXmuno6&scZhW9y@e*70HG%kLXvl}_p_hz zz2Cui@Q(NB8~+?QhJ_nk_kFK5=QZd2T?j;?=EWlFt&>+SUY*6xaK$@js;#~mCpz%w zv_FVfx_;+8BlqX4D=UMZfB7F52cwveeqZjjpY}UV7tcemG>{ZLw)?2`Pj*h>+oYQJ z0;}fyPZ}FR2Vx!up^I~GyY~CX-34x7%!`;^yzNqsDUgKiQ{qFePMjTour8&qtlT5vwEPRSr$^4%sZLc$?py{Wi@N=_3+)-dYMH!2FnZXA zB$t*;%~^F;S%U$*QyJ>{NMs)1K)utT)jLJg%cQB(CM9}r@xDpeEQ1it!}8;T6qEH*4q!43P1X1WSAo_ z8TH&xFCX#n!nTy==cLI3;KC+%!?j;Dy@GoAkw(>SU6Ydtg4#~GPeozrlA+Yh`LKv| zbtXneTN@ibL0%mi8n;WVtf{A^jSLMHtQLR!Hq!2a;Z&f&0RTg z^I=&I4(p#jvG`&255mAC_<@SkiQ~S2=8$UQwqjnl&D}fJr)i|a)%632RLWnd@5lm})PWoaef%&Q3Y!Vn#HK7Lm_EOLy=ttU%WD?5 zx;m53YYBQLro3Idp2agU&?G!^QeFX4D1!#*Nq+k&$DZbwk~9&8<|!x#SL=(@QCCjL^>Eiyw<#ynM>#EMAPq0st7Y=Zug$A1EtS*EudJx@ zfRj8uv8Pj3R@Mynrp6ca+JS&Y<85<~_8!gX<5$l%Gk1gb_n$&cAP|U&p7_Xcv@X^I zBw9(*2G0z&U2qtkQ#7w&j$54lBJw5!t+}8Q!eYXseQy-d0A`k!+z$rZ`om36(cCNP zN)Q=ooJ`571_gdfC-#DUUS9iVr1Wh;Vc~2NW@s^eamR|@#@25E(J8jGy{&#FDmpTJ zc4Kt|x4ML#8Jo&q{VFCZW>oWby@6Pqoa7<_eopQG9obdE1ODva&;PK#{`bZCA7az1 ze;*B+{~fA^Ll`{0P~(8$mcc?2kErw=k{X!Jiw{om&3>18K- z{i_9l@AH5Dv;SYhRQ>;m8+badyjsSo+nYBjVye%n-9iKjwcW_9`$WXA*Sx8rdP}cXT;3;^; zm66;2H!+a)^4buu#%*v_A4M8jV#5;TN_>o!$3Y^MxW33#ez$QVHQ)j}iL%F_QEoTs zwL2~=aO@C|LV&rHfR(w=o1d#UULyYdsSlOGq=V}+{%_a411=i^LL1-P4|p)Y_OSz`i{ z+}u1o!Wf&ALPL|03m8^p zjs_rdwka_Ev3FSPm76!~A0KVH^GD25!Jy9kB_t#uWP5WrH!m+MH(Lg=;!++} zI2#+g9H!L9EQ2TPW@qK`qjC#YLPyK>93&;D=8O9W|4jr+@aTzj{m zNMpc%TgmM)CO@d31Jewqdyg*#L&Bb-{*@?J1u>q`++%HK?oTI)Ev#mV-9T zEXk0@PVFpZ7f)opGRKD(xCP6zo#sV(f@g^BezjYr721$#BzRz^+US`CxoK!@C zIhMbc97YIn!#`GT|DAle5!x@GcEyJ)Y65%_gfufJu6o4_?kRn+%&8L1_vK7zuK>)( zM#h=Yc|qf0sr$4{8sxUdw_TzF^ltyvlo9B`Z_bWr0kMbnwzlY{x}M$Pl3vG?5eT%W>}!4tk=Y`Vyn8{C=^fa=b)f{j2?A52s=PNJS^$3fVHa=dm=Od+*KAk z@Mz;A4eLeON@KC8n0WYzQ4Z{zh=GA%W~xRtcy%(8J#~3*q#@UyN9|cPUggujhr}nk z&zoDZ<)L!T938i!^B~e&^AU-O(!+c8wCg5ib^)l+Q=TGQX{Sqdp|g^P=j8_m)~(n#GdC`TB=B{O9i>sQ^`)r-YaoPGHJTZXrC~I@+MM9P_wFsckYljkmL@Qy4|#$ zCBea$WzENrA40$$zSLFQwyRfUBHW)=7$)O*_z^^};xDyf+Z0&&=9(G&)t%)!6uQpIrESS-w)J_*l!wI<%83OtH_ZtHy0AZz=vO@LQ zi>E%^inQyWa$En;<5Xijyp6|`aVVsub${xV@z=i~)Md`lPLQ1Nj1?8}g3&%S&j!^m zN~{frB-svhWrhdyT~{H-iNK?^i!$iXGN8c@ac?|UDEp-Ear-NaCy$<<(`U$9QM;22 zyrzo$Dug{1lfw^vyjES`h~y1&50lS+#p|}%gajygi%I^~p_bGL2Ln8?`J?DX!67z!1NI(YP?6}>;!Gyg`&%kjBsKa@f#Po^HSY}BIFv7hW` z9BCRq}A=DpEoGZb6CRB_boIdm{aVQjdSYdj_ z-JL0IIy*c27J(;DJEgtt#{K*Af=G%lwp2SiO(psvsZ-1HLh$M5SCH$)Ok^?&DV7)Q zpeT$2(^))OH>i{mwDQ7B5G_pnUJeRkNrDgC;nTV7!&s7#>hVp|9-Gh9T!RUs1L(Z9rzS&{@xRHCXV1$k)UCYwBoH7plt=StKN?bQ*n#4MptcGxiVk`%ngw3B$If&!B%F44}FRr4mCCcJe2(;*)$<0=QK2Lvv=< zTNVP2?wjA0gA7YoSFF6MVd1RUz#7V?ZC1{GqD~o+5EV71pnwMtU$wev<9i*x3C}Ee*wn(v28=v7W|h;j6S>jOu^~=nXosb)$Y?Of~Xgy?&>9YcYb62R!<{-i{c#PkAbYj#|SNTDRtaD6+N4i>h_o z?7fLYfq;iXLf1JQD5M%36em+qeZMA)UI6k@C4zJ=1)jU0Lit0Q25N)0S6`2D<-#Cc z6gaT`83W8E6@x5aJfE!fD#bQXKDHiXp#M0^$9#?XaCDENP@Vd-XtuDG9qP3f`+9Mt z(9;u584@g&z3)w4H5splAt3{EuC8vAh!GoZ8x>_`pPg#zc(GOJAgxfLkO_G^hJ`N{ z<^iZrg$>bXAW{X_C+dLl`8Yp7izj zRog7sV+0Am$jP3oxN`pF+}Wc&4c=3+iT&^)`EcIKMpl_p_cQ@b!J`CX#rMk5Byw{@ zL*JDvwdAZQUWWm((0QqcloYBFdS*_E+niH1;oeL+nv&LYM|`k59$TlND#Dl0vg@)N%_r+(UP79?c8&`5YloSxp-b#*O0 z(01#B`H)rGFjtM=lCm%Lpf^91DG41tT-RU~gB{r)KYo-fwz7>;%y_wy6&-!K5#l}X zoQ&8F>$zfF@M`A6$drd{p%OCN32v{SvRZ^Dz(eenwt2e%fN}f>5RmiipF0P z5>l`Gym)}#o0#Op3uH}0WGE@K9Wjh5>FRNZNHjI^X6i%dMTUTivb`F||wrHV; zQP=l6z&p_;J}t}_2SrY4_#AS|eioIG@R<2FdXjetgCy&z{tW zZ&G@YNx9ki;hnpY+*&?|`*WD_K&~QkE7Xro?fpd0ro_7+p;GVoi_Et;aA(+`nya^#z!5Qc^iTIxQ4BJ~kv|I~-I-AP6ECa-`hWo@qH)q*+YE z*J!Kv)`sew`WilcIhC4SXZV~0Dk>^{`mO*s|5!N;O~@!mKhyTGUKz}qc|8LqVSA>H zNg-a%&t%O~n#_YOUwmD;Db24|ee2F011V*{+-`UD9zyn~W}g~zoJXf(P~MMANT?6Q zo|=4|QNsyIjkYBv_mL#2X;DM@J4kBjhzW9c$K1HPXqS?6&!ZtiYf2{J~} zinPz3puoA(FMBvXP2KY9336Io4w5W((VUJMso8FYk}GR!epXg4OuA2#wlsWfc3WBa z4O0<3ZFaa?aS-Fkkbb9N)=*!&@WbOEJE^U$y`z@!9r5_lJL(d=RPP4T#rwg;Sd` zXiAq0JA7+=nrtlfc*DMYDqG*O;p3LPnIVbMK*1$(tYLd-(T};trTpMB&)U&0VbY<^1UirNY>2 zl6#YIlv_XvGpKe(`~8vHsIm2^FQ48|eXACGWVpsXp0SQWpOGZAa(s&*r zL!G6!G;y10IMryDwPETNB5hGg(Ow{63UqWvP&(mi-~NKY4iwC7GdY70q;aYUteyiq z&wF&v-J9qI`;M;L;zzo#x?odc`kaV@?puZjF)v`@u4<*>5Yli^dUa@9a% z0S%CiH1t)_OY9CV#QsOD@i8NlleLFppqY4Zc#!>p%bWhx)fYpbKcB(T119%Xb`^v9 zp^>go#{RLfO6srriV6w5wZ2EJY24Oai*2%)xHuX-yOt)z{%?BhKFja_{P{CQi6rEF z8G%Du%tw->{T%tyDlaf!HPppqgV4n~!p$pG>B61L>T27Zw-mEW(jFv%+@>F@a(Q)q6|qJOyNo0EGJtU?@PZB<2u>W1fZNZ(3odeEQ@qSVUAXtkMTq@v>P zc=^UMoOPaZax_oazWpL`Zwo>meN$&VwAcl)$xw*&eM&N@J_=$SZ@q)5N}Wdiggo8r zPn(@G<|_@kSb=#h#F4_mc&QR=z5#dJ5Rn?o)@Ifb6{Y+3#gNDMm@*9;B1fe;1_Y*^ zbw#;W@iz>$=Da*Tox=RxlJF>V=`X6h$}2~++Hx897IkS?wSm$?diY`|J>;9vslmKhoti|gkt|A=+uptCMU@u8NtPH}K}eH_LygIuC1jHXT~rDkpc5XJUTtYJ;_ zu|kr58RuWmAZqrX%rsB=a19l>Jv{3_8RPV1ebWVapWvh%24>0(|goGICe5S@@=Oyi~jxZ1{8qV7h19 zXQ?L3sF7wF*~EEyH^s%ic=L5lfsgOg_{QkQp)v| z#Z?NU>~$)yi?7wo`Xh-s(?@z%udXZ@J=aQC4Ts1Q96A=ez$@y zV^;Z7KdcPjZvRZj$bvvHk#qmL`@5R$`YpoQ&=aifpyyuyZ4Yl!J4~C_u);&rAk6-#8U!yj53rZ2U^Iujv4R>C_)Zb(PZw+XU4f1_P+aJ3ijvZ$X$atgXg;udF13c-9Pl&c^;b{RP_7g#D(gIc5dvcB@h2 z-+O#h6--AvRu9sP&A`U~OdbsLtgL!X#4@|3PqK9@no=0%U*fZRoZDF^m?#DuxKa zIY)=Z>0Q4rU1tLtqvBz;7P~rl6OFyixs6PdyVQ%jc7cimAOZY+PhHW*Mp;`s^+8>0 zre+EUCkol9W*`#@{h=@W@(w0rJLVFvuZ>I&Oe zY;Xh1%gc2pP+{)M)^XmP0}n@o@vkbyu5K=Ohk0v8=S=ha`-{*N9OR495Fv>EPN?eo zT(gq&9awL;myuJ6pLcd(jxDlo<$y6hb3J(NbVd4JP zP_{d@>k~DGAaPQ#GCy4QhwdLB5wb^>n|Cw56fC1FUh;O?WA}1?>pmbhQV8N`F>|DW z!Ar_^IU2o3A*rcJujhcCbu*lyVLmD(^+`v2JFw_rP`Pz_oO-eVEDhVJ+t*R?hv#1X zE<)^6G(x|$vzxi^lSp#%yIvbvIXSDJlLD%;v+H=AGBjW64(Df$&d!=%g6FJDp5Fc) z#tDa~RacWhjVNmBl8r#a*|Q95X6m2WFcn#?opl50>Y5PMkz4P0d3cy0l0WscHv747 z1F7?=GR6;m4l7I!53N8n7kYBIwg$@H+j#8nta5ay0|>LmjdP2Oi`5&ou-1_4^0l^M z;o(0KE9>j&62tEtM#0>`g*)mpq=_9WJ{Z;=kKS|+^)?p!KsXi77QJHd-v#2txD{72WC5s&W=9^HjK(akA9om3R?fA)Y6;J+{aX$L+5TOgn)AbAEv;uqOpy zjS5Se8V@uBk+kP_01UCirV_)aRI=YPEbD*HI$62vKH|Wo7-d-Gp*elxHVfg}Co>{{ z`R>*%n!KP93Z?i;IhaJnNn%_~g92ITL5KtMc;MOp)Kd*41hEOLJDzqE=6D=>_IZ!g zyAy|G5rxooT=UN2RLLt!4GM|N0V*K0%ziA_L5FtjBF)>H86Cma*5*%s#>r8yM)D^u z?^Iuh`b-2RMSZKT%!)l7i4eC_S0|L$ZB0`FDoSk{4yN=t6+(T;Xmq9hxLe~B2qZbT zQx(_o5=@P2TP%qbhOWXl{-Glu~7?NeC+ic-H#u?#hDIw zjFYw?lxNlEK+I$68(=sVUI(Fn5>Bo;B@`4fb3oJl8XEFB1f?w8f8rLP>J|pe^poQ$> z@uH-5P$p6Pb{`vU(NVX9gGrNiwUS9|jp?Ydf~^C!Uv+gpm6eqdcQl5lT2c}37p}6! z114;q(e{yKm7E;6!L2Z-Cf+6VFfTt#i~%D3kMMRcJ7%E2zeHpFL8rHuhyMN^Wl73a zdMV^;q)e2NSgv-H?X=fi)*VW*7d~;WB_vVUGrT`AvD(c#`Shth#VzB?ezV@ZfQYQv zzvCOpT@6~5XV1P8F5gJ0C{*Ss36&-w=z`qcO(27q#zrmDH$0p8n~aV`A+r`7uO820 z?n}pbu@;}-2j?OF=SY4ax>N%ODMdcymgwkJGX=%)jW+6`6jxg7Uro;skQ-9d>R3r3 zoWVw}&S}{fJ+am{Hti7_hX&Un9$P;@A@|8JGt-}!;G_{W)hOjkn&(Pn8+cex416Fc``xC$YQ!cQmLUSGy+p1>{ag#X z`2N&=`0!es2%`p2?!W<%H9F6P+)r_1hz3Fwc(6iUW2me4P~JR%s$=ggRys!)TzZdo{DtV9yE& zCH-6~s!){%$aB)0BhJFGjOaI4>!B}~jFL_o@OHt)IT>dF)@Hk zYhGu&AmTWC5=Z~R*B6NoOzue%-6>9nrxt7;RI%l$Q?@QZa;Lu=ZJSWZ__YMSlu!eo zj;^Ed4;P*&<<8R>jcA;s@w>hFvRD!53xYm)HeBYp=T~LOO-Q#j3<4-Qel0C+5lv0s ze?7ugCn0C#vY?UmH}J`B9PVL>QCv{J4D zAHOOW?r&QRK)L8Ok{(#FCVS#nq)O4H_J>wO&4Hg_HN?e4_lei~!pNzKgtayN>WE2| zx8yJAD?4Kc2jhIgFI#(S&#i?RMvdzQS~S15{4{I5DTk-BB7Hx|sDD;Yw&_w4bQmkL z7!OITuYbHP4J4Kuh3{H@HXFZvdx>KslTW`s&R%Ud8WPeSDs%8=tSD_o%M%p#_P56M z@*>f13kx#W+M{TY=+xACkZ`v&8zqYX@lk{Y9`c9_AE_w|O5ZE8vf4I<2Zq3= zMfDm;81ut^+M^kI_t}d19QQ5VV%ZYnaIhmQ-ej-x;zPP0h zleBZ&+q$_GT?I|8BkuKwp4(;wynpDmqid!!B;85!T7gq{t~VD>!I6n}U$2N*vPL(x zG_i6$EiJPjr|gRK@LY~KyV#bIbl9*2MH$^K)pl5C#f7t&7;{pqs`gxc;h>ZY9u(A3 zjf^$=_c~@ll8<>iqnCQ1|b9d|@>d@*Wbj zc~a+>&|k%Z-P->9zD0*7iNMQdvUUsgK!XMp!;%@pR$f-J@9o4@ghr!nR&Dc{`yOv>QZp+fwz7<4S}%z4L*=i z`7Lf6fLJJ7C?qdNW3VaOdezxsTx^8#$j)p;fAEEf+~Vj6w4 zdH&uHA2S@Y|8!J(N0Z4LUFvsUnRk5y3O%(h`+CjD)^I*zX)Uh!OCtiDgkX)y=~-Ds zKhy*oN!_cXj)JPpCELTLfQ<#{xgG^d#X%j5ARvMmE>)UT&seXCc`3DUwXhVJNO#Sb9 zwdCq)GGz)uQbpo>kmL+a=Qy#y&kr?lel**nY6~3)7N>mR>uZ&??1y$h-#0CJP;aTb z1Y~Wm%^y8UP~_vvu*1U((+AyD2@lHRG1FEcQs4Z1vcT2YhZseIcyHpxr|jO?-6!Wo zlAbSkQvyvWT^l~rQ&T?}c&z0gf|97r&csf7fGly_=<PMYz8k6kT|}VlvHqpA`w{3MXw?vZuuMJLsd zR$3O6r(0Lo)()rkAn=9Kks#(3e*UhFy1gmiWJGFe$y1}}I<5%U<0noS8Fi(~o$XEt zlfFB%3+7OZA$r={ySNSSy?TGBf$qvfXXY_p5Q&~~3edQk_RGuIIB9HbOfyXLeAs#R zb%#sOAL(je>*;|xIB5FCzN4X@4*(`~^82(W@87?lAmvU;@OduXe6yjUAsl=n!k;|( za7zW~R=Uq$dMzkdnli=3rChjhVb0WSUV|M3SIHuO?GuT&x$bo61qTP@XXkVC^7C`^ z^MY~hnY{9li`SSR3Wy8xJ>4D@<&&>0sOhqX>g9gNx#;S^V_v#LVd?L+{MdFSJzU-b`?|; zSp*E1duaTDfFJiFjx!?sgRd-@`v9{P5u2+E9Wh*pe2LQ6=h6-qWEU}>}NLNvEIN% zId)9p+&Ws@L(>s}x;!}*(xRdar_fe0$7u>!>0aezWd-_@_LLv~42?NO>wk+Y*hR)V|ut!1p6&AQ!@K@yRxXV>Vedy)jsHT8{iFE?7Z{f!2`vm6XzZsAGMjgqaKC?{5f1T zhks*J6W4EbNyJK1Mga%)K1wP(hX*je7ar^AEHIiRL<>C-c>UDg9`{`V2kg@7HrFEj zGQbp6VD!{a{l=joSM!%%aCob&ZPJLq#@g~T8ir$oYK@Uk<(-^b+kNLFwNp+OT&yXE zz5KJfbSKpRiOwvIu1?Xl9odg%?{Df(@4Tz7jt3ote;zdj`(MSZ$f^Nk@LE_)x;*o* zcPBuL{JYoKyb+Ut;9$^F$0|Pu4eajjw&_v~5_@WCW;*9xgTP=g*;o3`)0}?v=8Xp! z^T#fjHiiQ%#NgUSM(e#ibLfKV)zi@-e1EqozT3HZEXXI|KQ4{OV%m%PnNPh-F~qIc z85*W~A9#3q@zA_`ADIY{(=;7g3tEd>25m=Q`BvB1cnY`>tglx^_GTRdUaa0F8uegs zNP=0SOWvm2C2?T;(t|)GJzfE4#^lAshGTT}#C^w1nzw%eP$&+}ziV1!v#hb>G83c2 zQ|ZeYZ=bu+?*SFXukD zG`E^U^Y$Y1FY)Na_$5G5V45&A0!(ym7R!YoYisMiy4=DaGlyfxi;*{P+`B6dGkoLW z0bo9^77M`ngKcFsatas=27&+l|HD}@CNS_4$|I5HM@ z+iXV;uHNClD{;%r#q#Z&SkRelAtxv2X|24H2_}Muhp_T3y!=8tjExNqa~Cdfa;6{- z53?7pFIcd2Cs$)8?GM@kuABOfM(Jh;rlqOb%F>edG%Y}B>ghy6pk5Wl#l@}3jG}D-4-cFmowJXUXBq_|J>}H`>y4L9QB8(s=65;u@ zwMnkEC7af_lr+ig_F`{0sIw`I+sB83FBRqDilJ9eeCD;Zx&+!{ITXwk-@dUoQUj)i zEP_ceoag4aor`WrOgXTwcoJO zw%OEazzqxQ>yxLimZ}bcNZB3CHqA$V?d=Uk>v%kUlew-=ZfY`58Mhi5x{rWstFC2g zVx1UNigWAA%8H79W*7CZSv%Z&yD9+Z*Nt%c$`p0XC3q!e2ZV*wS{TkS z05$WgS?T6%<&;h5dx7L&ef_A6W%ZI@>-hrQ^%q5^CB?w3boamog-{n)_bcRKzwNQ{ z4k>O?QDI>o;P9DJTlJuZ5E)VO@ z4&VNcX5b(-_{qjdkntu_)ippTDtB(&Y&iT<=kHEBdZxX-9hi+nxa`7U+gy5vGxe1J zM@14phcM4w36Qa69V(Bt9hxOxUv#gvNBlLjxOf$Sj-fN>HJv_~aPvyT7qy{GmpD&M zQo)wc-Ai<0(`kbEJ>w2ZanWl z2d!Ph7iRb?V3zqNPq=FgNI%yFXxWQrX-GGLz!{Oz{k1o!uK`S@UF8pZ&|)XY&H^Jb9U223)(f5%MqVCDBuUL4j4SScJYVf*7lF*^NpL2!Ft2v8ktmpQ9^Q7w4%69L%dR-9 zU6xeSXh_N@X6+T^aS2{{XKv+=^g|i-_~2etbqS4F9eTLrJ(q#}@XHTx(~_gK!cO- zzhI7t7x(!yH&^SuV6&$o7IXjp9ksZ^*OS$tH6Kf^)pGF2WL0Fg*y`#yal#iR*v`%w z3@q5nu1S0ME;j?m?4qy*2`DoC)xrwg*B9!eXX@kx%v%(gu1}P?Mwo`^wAL`DzL0#~ ze=+3~;1pY$4Wtwo^{aB=Q~E{bK_^>vb;sRfYcn%9iTfXUlw*r?xOn+1h1_ zlPiuHxpQB(>`byP>78tBTsEv2RJqAu#U(fPp;;Whr%D?VFF~9oI&Yv!(bgK4-#e^M z`w=K@o;Muq?<-H#-!}uU&kDoKoAn4kbtB};?VNTiZerSWzLAqKwPI}m1UVU933Cg$ zGyy&dL{T!`E9-s!mu`VScC}m^;}D-lLaay|Zn$CA`zPVs~*+6C%Emh81;aNbP8rgQ4rvL)~A1_upZX zpBEOhAOE`TjBF-xdFHwSbZw<*nd2p~XXWI(+F)x>k4vZ`b<$-9gx+B^r`G~cZU*B3$VHfA#jNeP^1eR%wTbeK z($ZErRmR0|4)&xZK#rDno!tl09cFy|Nkc=6MgsH2i~pKw!NT-M6Za+riTAhz_tr52 zHw$bJzF4&fy?8F~FZU6BI3Y5UkGFl}16(9^ayG);0-DhO@$gHt2WC3I2TKYzH@U>8 z3GMVfvGQ?T$0Z!w@6##T8&lVt1DDcPwwcaE-VOg~m);et=cAftXg69#OHf&+r9|Kr7GDXwR(9hr+7#I+`2zi4M|c(qnPn|LZP zrp*^XCYA3Q9e1v;znN0p@;k|>ZoAtRbi1v0S~s(&{>m?QYD7Hq__a+jbSTY$B%>?3z|Je(&pCofFv#!Vq^_qB>6d^0U>qHJiF6Sx&y z_82@fFecQkatbcM$Q zhlYzsShy`i?o}ael1@a<`Irgs9CKva#Rmu;sm`0iVd{1QZi*sx@y6rJBcqF|UYe1mJS4!0G>+WPJ18omuWhU%s&_9la zPCQOF$copAW8&uwiMd5(Jc5F}22 zgtZ&s*w5msFc>lNpKIir^`|nk>pc%|(RqyV_!Bnr^7EbCodbiugspv#{0Mp=Q8l{> zW8yD$#9wqQg77RnKYAPbKukbP;PJU9W8AGF*H&;cmRY&3rSe*4^=;nV`Qzi5d6MEU zP|vcP36D4NqF5KRbWE2yxf(W{Y2#hBp%#VP>Y;*x???wLKik{&!)7+9hel!4Hw6ZU zI`*QzNwy#8Kip3)Y-yT2GeD55U+ACjhdJ94Yo*k$X9vx+n56R+ZSsB;|xWQP=KOS@Iyy9b2PnolZ* zh7-eRs=Aq(>^tNmKp(l7q148`%?+#B4)2GaTSkK1cWF`8(X7y8Y#Zc6^Yy^lg+(wS zV&l&S%U78P&h@hfhK7@!bOC)NOY= z7nja&EJ?L9RVPoMo^&G_)!)1c^3>X$VOzh$^2URV?Dq~ROz%wpB*wAh%b(s}=cTi5 z_9Vpzzrm1x|Md#%`X_Dn8u3E#)-ry17#$f^gPG3&8 z08ipo2#JcWG4sqMByy3)t7J6)Ym}#=Z<& zf z$)XBV7Ett$Z{@6w) zD-E!xKu{yDhBmgd`%u&TjAYEi!zaKK*%Exx@7C=%XY_RRbbp7=7`?B*S(NCii8(>K zSiQZ+^h|KffYibpBU2fgn*H+-BzJg%7Tp+&am6bPN1+YcAT4=SfOZqynDuqaKK-iv zW**93gc`U_#bL(Z|kJt%aA?!lgab+z`x_mS=TvL;C%&~s-Pn( zgbv0B<#RqJV7_6D#!=z{sh6q&1hoHM1OgUGQ$~y}SH>>PKJU80!`zAE6f^qUpN>)v z{OQ7J1pe`-OLJ#V)dV(A+!e|Xw>?Hp&ZuNvdguJeN@=Azk?C(lit zwgD~8#B1Feue<~>S7{|-I$vc{`wBG6qIyIur*Cl`1q$V$crFljZWDz5U7)X5JYK>R zL%UI%H`=~f)rQ$7&fi((O|9l#2)#z2bGCyMz!d>UUL3 zYy&V&H|jQSDg|1aTXxi29?0jc+_oL_?i^p-FXSvrA2V}8c#|WOf?xB499WX@Ek1rq zf9L0q*L+4~L^a^-Pd66Ldd}T(5N&(25*|j!`EvZ_$U|z-YnSTqju`c8QeGog>{p|r z9p`(G#c#w#Z*b~7fA;F@YbA5@$dfGK%;l0&=W)l|?EShiNpB-s$PD5i|I${w8`k*l z?hwWe6NtRrxhPKBJr!2XkO)94#{i~#@cfad;fbtSMu@htuGjo#{rE*WvNA$J zVII@ZWmqc!&5e~%4n&Xjvsb%dXB(QuRo*CxRX=3_27-^M^ni~eZuN!DU+!u4*fj7A zy(Z=KyTI_nE9Udz>cLn8yXEATU`4>zE@3P+qbe?Am0z^=HPSA28hGsXzGt&UHa2iN z086?1%3LoSyx7$heC5=%2O=(x!>bq0x$&4?lki5%LOr z8n-ZATkXzT^w7h=FoMN0eo`vw0mB|IE}c=MtX)^jce%CYfv-akH` zG;b|($vK1_11p*DrAUAAsgiQ_VL1^WO8jyAp<#I`my3hjEqUvc$@eAM6D%i%Y77Mg zd?;DeSmRQj+64i`DVDwtP4Vvw#a%i?Kc=ZL_QXMMP-NEI%~HeO>A)6)oJmbBSYEJf zm_|kIUoGH=x4K%#*SGJyo4Rq3E43D_1b*9T?>y+3NjyHoyN;spU*|jHF%v**0Y-Pj z5nuf^gSn-xO0A^QVql`*yIA8xJ;xKI5z5RZ)>q;Wt*+HIjepwK4;{mhgV25bV)Oyla`+9NZc*(ACD1 z$O;<#U6+4N2{>OU9qoncNGSllBV7dT;^wAI{W&W?`98M7qwTjcVb88U%YE95?6-5l zpka}MeOIPuzxq~g#SH)H)6(D?>iv%$)+>`{_t!q22lMirT&4x~tClHHt{23CjP0~! zVb2wY=4%~h88oL)(fxUE;pWZcy1x78&tJHP&zW}x1vR*B7$YLAjfNGN08MO=bm>4g zo2%G&UsP;)UF>Vsz?;g~tPy34mMJEs%dq=f1gsECVtl-0QOJ=l9bM{;mWst*j&6y*ns@FT z-LODtAmk?1xaO7R9Z*j#Ezx!l40@`437(lJbipU;vOL_Nx?iPtVq2C=9(|!hSvi;^ zFFSmeLk=qS8H)m8jib z@!wpm@~vIdul8<_EoRr0rda_0xc0G_sEGKau*##uRCq@lrY)ebTmLSqUM>Vuva$VNAHXH~KSY36GkNL`Lap#<_x?(mi1Y-;M zq1gH4fXMvhflms*og3yQ-cW?BJ7qkzl4cas*)_n&?L5#v@^S@HyKe-*^1#$$)q9;1eqM=6Bs;{7;o8e7jJxQU}2c> zSUWF|ABV%GcMOG|+c2q{cuf`r+HtYp%L#qPdL!YHmI#7PL?z5tmReF|IHDW$C77P! zf3f$LVNtJN+wh>V9YBqV0(1ekowlYO8Zb8>g@4rZ{p*$0HRl2Q!cT4H3MjJ7nP z!FHug*$6MYz>EMciYoeRExpBe`d3i&dv(A0x+fTB<5iIk1|LEZ0UuCcw z^$W30WucR71{Q>pn;kk82!%6gRBENh#c3fM3^l1>2FhpTSFpWRQkg| zj^s5Wy+&D5ri=PyKJ;T_2Xk?$amc`DlUQANmznG@R~LZ1Xk}%2GQVS2)HvWVJ3qrb zJw30jU1ff~RT!!F`PK;cMD|3a-+MKTVGXxXpICULKAfb6u+Rxi26UJe3F$ok zXJU?V;P$QCG|Ak2j$h-e;sb4Kl$=jB3i|#(U!-a_c6_)z%RZ*p9ZSbg;^4S6=O@%R)MpAlBcPQ|LAG~edC=u) zR>P_|FtOKM)owqrHAT;AAdgbSg0+fr+l#Bb@QP&gF%Z z4;xzTx`cWvlrhB$I7(2R2nT8ayfmZMdZoHttES2b)0J@f3^pK+k{MhHvW>ki-qwt; z(LtNc-~v1vmzS{7lINReg@>aarlxSi&*0kh!=@-YE^eWYCWl>CmZXML1^u(weFV$5 z{oUP;PKx+wZmy2fjT3-}vf*)dy+4AXo&nVx={|jaL`LURg=Yrr*RlTxtTpjThjOXM26=bv06l^Qy+JuPI1KoNDBj^hb#(87|VPJ_r1bzwRpf z_7s!NwvC19@P2BB_0@2Ac=))kk3BLy6F6Lj;UScmHga-QSwYKbvtt2?l^b=u)e$4V ze_UIexV!rqBz!8DTTM4PNxsc42D_NU8OB_zAIr*+GrhgVbGBC{K!gAjy0&`r#&2-b77`@%ut`|NGno0~%e`E0PuG*Z(ykCd zCLmtFd?P(|nOTuZgFYQ>JNIa@`=~(kyR9|JdmLmO4}qD9{O*NriHLhdTvbtpiG>+< zqu;lK&zg9iFARGY_h=9#qPG^4I5_e9zI(=Pte)~@%}gJXj6a%X;hWkb_n^e#tK%~w zkSH@b3AgtCBnIbu5kH`L3;Aw6A#=v;VN9RTrdT%bvT~_rm5oND=fxPH6Wr|(H^;=1 z6k>QKz{a5A^DtTzf$k#<@`Fbg@&`TO6}pj6{`t$oG7pzUM{cKE$(Pf-3oo}U=GQ=f zp4WSWbPvUp&``3D8qiNI}w|mys^YX?jxkP-o-WfSLnT$Odu5xn1Kh4T7ygtRBNB1MW zo5Yk+zEn^}HuklKhwscjnBDs5=O<2xo7SxH2D3FNBxgftdrGyn_IiA~)<7N8Dn||S z3+M5s-j5Tfr(uU|3H!-Q%}<82Wocnm?!6mJeJKh2`t@^;eLH;(>3dF&`vjTEqOyHX zha2&N zbrTz8U%c^WEADA?23(y{nIAGrGSudGFZGR$Td{W#H2lFI1U=e*w~301a`y;{h-Myd zGx{!-T^+W7%hYr{JU6$&TU?P*84V2oyhGn6a%k$5KQU55ArAcl^KBA<2X?ldh(goQ_!Wzwc=wQn{V{$mL$EFn;f-~pt=w4RSJuy*TNvpebrx!F*aN`mewPdKVSo72< zIITKow|$3;GyggyXrqX;C#!R_zmrdGJT^3=berB()p+hXef1GzCMLH`WgMj-!)5rZ zo!IzzvG?yE5ff7a9vrtX&vF)G{D@F8DP;f+Wd?+cCcrjw@dEm(IK>G7waHvz@b8e46)i5`0B z%?Xvx>B@B7jL|2DL2aV~S15V7*Rr+eMdhI^*;6`dqd;fWMz>La@tXD;$!*P)2zo}r zF?)yoH>WN!T*>@>q+_RB!QfWm!%1O5^q&s}$dr5Xj8!@b4 z8nJbflb;k_B!&6;dD13;U}hmbKsqBZo+hTxalT^+W%FY%<0Si@g^Wt#U5pkCm8R2>gfd5$yX5+mkKiI9SaFb|4xQZ9)iuc!)#aZp%4H9?x3!|UbZ8JH@%0b->6u}|H5~a|T8AfH96uJ|slGr=7EuO&yLmNk3==$C+vi96h@jQg6>=aJn zvEAcMO71_pyEIF@5*P1C2`I)Y<$N_FIU$L*s@uxv+t+2Y$U?pW0KvG-baqSY; z#i^`MunD6`vjRo!4O5xuKw(r~CM7fEV$)Peh*cg*$rm$c#g_h-jG}wLG^4BP&Js2o z%Q(|7eYVkVH=KyiF_=Ky{ri@tuVNe{@l}|#xExLs4GrjPT(rtQwFO&(>-NOhW|0bf za{0A-M|_GAC{i(1T#7ka;XQvzY-IkSW?5Y%&@uQP(A5Drn0bNzLrsQmGMuJJYb`C6 z{NW0%)#kI7+Nnf1w-1sQoUK?}8l!eUPE4Fus(cg1Bi6AY z@uSPd+|)0rwlsBJ+I@DGF=`=}%#np^5L8rPX)w^=5%Lanj0trOD(8ZcQNaerGTOpn zPY4O?Y>qrd0x?m>nGS8)SG&k#&zASo9}G2WE``O#SL-oV!=7-8W;#q7WnRdyMge=#%h1GssYwu)NyIP=)5T}%YI zvx5X2S!z_VFf6+SpYu5|{uSBcAJoL21!KbQ=~Z#jL(f#xaddOoOAY@g7w`-qE4V#B z%fOTPZGWwnEG9L`nJ=DPcxGjBY3g3@kjD?01iu~ZwA$~vp42&W=gp*{!N92fMTckU zzEeyn8&!32ym`F)GR^y#-PU?j4J){OKX9#@i!aWhR-y)PwDy$_^eS@Wmr1-Q6mr1mBEN{Q)KSR}Mh?(2p2Yw2m8<>ZX!rM2zQa}ZI% z=(SAS$Aa*8(|)v6Of3`Y0KHHL-SH~la~N0857y6S^~GA<6!9~y_ep1VeOLXjWKwe4 z{(7$gZ>J-7LzIBsZ7lqIR(m27yPw6?y`_-8(t8SX|k6Sz5Jk5&K#? zDrqE~b*j#8+Bw;PFkfrt4HP3~#*AdOvl~7m4pZ^$`u);FIH|S%=Mp8GG>R|R`@EIz z1q0NT;Dl2i_qGnQ27KY?lG*(I$+^GND(SZ>Vl*7qDTuL)1ux<6| zG0e(mKMs+yS%{bB#wR9nJz#_XAJGF@v^1jFhyN2wn zrbasc;@UG99a)E&>EQS$ht;B&3VZbqHYSYoAUUr~VnGo9z56=@0(IY5R1Sz9^0gi* z;>$s=&78d(SaZepzuPY+749@$*Bq`6rcC?9Cp~M)U!!Mz@!}9P>i6$9+9NZe9)3GL zSiQ9LmSb}NoFXUFj1wOXkBx;(dj$< zRye3j;XDh@jnltB+3)o$GAPPINvZsDgi||JNKcM`SQe~?uuh{mU!;AuRCxmhFUE`b zWIlHbB`GVr&_9_C;gn2~Xrrrh&dVJYr=^L&0SikDhOX|#hkshApBuGUIb14P^;W~7 zCM=WovHXO*A~dF6iOlin#qO)GTeX9I(=~>g_V$sWf(4+Bp(phz(d2r zENc;lhW~u9Iry2I%{?p9Vfx*tPxs@;fUj+}bH0<$lNbGOJo2hg?RouP<(zMRVQ$=P zS;9&x-9=9&${|Q>%zi_IA7>1?ms?;g1N9vHkkOvXz49k(BeX3)qLVp)b2&kZR(+C) zBJ%c%v!zf@VSd=>kSO@*n8h|FthSY?h_r+A-Lh+nZ_suJsDJ!_>*BLM?ox~ z9DPoG6dTK(g!KlDRdp2YPUYVIdcbQuOkHF8Yk@i+>0x+Hglqh|g9yYAOxZuIBc>2X zC;D{Z;3mVTOY`GTY*DT|GuOi>b8*}?a+cs)ZabB?+xcM`Ha_L^m31>yf~I^{FAt>`$GE)$&cA?dPRQFd0xQ|gt8SYO(k|d zer!>Wy>I&HYnbGK1!wU70hf1$yj!g1+yybrTi_~L{mTbIX2jusdh-=KU&Z^zs*Sbt%KgQ5RGfuYSN>F zsER!5P=+Tvlk83tpA~7PgxqIdO2=#V#GxB@sWO?ezs~u(qRQE`PPV6aW)7A+d@S_e zzWrb?@8s=HZ^x^`pS;|Immk#M^5MiWlQVGy8Iv+Ibj+~`oE|cAo))l_IL*KoB z%|I!K)R?{n=49Dwd2Efw&p7dZIDN`{DCjwMR#LKuOFa8MK3-EtgY@x($mE%g>>ci{ ziOQqHG836(kG5PznT!1cS#1Z-w7xR#E)?C_R}dLLJs4+#nwlC<#dT9`#*+!b__lf? zGi3UDJNwKX;_b}Pms?rzCA5SCx!W(1gHRmY@VJ$oS?|*kPG24rKcLQrv1`Uvhv4E?Xjofm)z1`m+Vr=v2r(VBjZ%3Xus6E) z_Yv;PNLkF3#Dj+P2VH6cRY!|kw~!ipUGBtMvD#1JwMAmjD<%jV6@sAul=$h4g|oP zJukIP-4`w z+shOS4P{{H5*BVrPd8j@m)a&@>Qmu0Ys*q^e>3eC8Od&vJbY+L1uN2JT%osa^w7Hr z3u|MU1#PX^M!CNV%R(hpE|_aJyP~50?3b2)`!=xpy}E)5!LR@4Q3E0t?mxvTRG3%b zbxf_exKbkFCP`GEg-QQ~6FTd0~9W+N`r}AqcX&uXjghrKS!sa@On>QxB>!A?rL>T$2zs?jpjb9mq~GOCcWj%a@Un zgHuplX_Z1CULWX?z8hwYPU1lw0?&IS#XBaSlbd^Od;p)bJ#X7k#dO^8jBm(^g*WgW z$9w^il1lg^#kdtCQy=seH(Op{s9M2T#J|UM&!g@9aqi?Y5tn}mHm46J+o?wD{^T>1 zGFDok$THf#3hGaYqYPO{2?nOCOyf6y*5(`fvshxE z*mlrEzdCWwNBS5Zb}nMWUQ3PH$L?Ts|8QRRzbY+No1RKL1d=U@cI!)T>F}a`Kb%pM zhVa!1U7cnO_a!q=jhOSdQL_N*Q=5k%S1 z8qH2om5qai5`{JmBj;4Po{NeTlH<_Ysy1s`fh{dB#l*&T`j&xM)IaFWim>7}E&_4s z3&fQ+X0zdiRZr3A*%EJXKa>mR1x|hG-!!i~rwH1=!t^c_5Cx9D*PZ7D0T)SylNQ+2 zyZxrrR%e;mt`R`9a@A3R6MF>V#4i=+OrSlTQ3?e28?i_&~N0P zxxN0cq;6dj@BQkZOR1&XmSp(i>IvA~=tFNCm$+4q=~lmX+3!wEays2`{5o4Ni{Z2D zyasYIyI4vlz!DN+*p_NgXH@$94e>uup1csN-k($Ds=T}m*kV3gP_J6PeFhg;U)qzG zXWbW5XAXXt=uHC8lg>ug|$!%I$Uc()vHW?KC6QxY}hmg=Tg4eK_+GuzqSY-s-NXknG)CwqHQQG#OtA-L z%_7X|cA1+BUe{~qTVZta^0_1S_wMDjA8Z63Ilf77QA41BR#|L_N`k+u^Na63tW^FQ2saY@%Gr4y5T=vD`>opS7J|0z>_=d~N zvaW|GN2>hL`6084l^!8on@j9`q>VcM_?lC;R5F`chn)I^&-PlohPUN@1pqV$N_6-> zgePC)_~FV!M6p3E*0uT_gd;-JW92)i_o8J4%n!GLPV99@E_*^6nS}}jYrgD>-ruWf zUKoptryt`$7IJ`vX|W(-#b)k&dIeTs>5SR%Y&Rq@v|MAWG#u7;d&h#cb zdQ=y1e9Kx{QluajwC;CRjDg(h-;ZDL&DnCg`qQUMmAeC6uM?z*h-SC(;@@z;$9S@p z%S{>@8e(L4IH4G0InPP-kd)74<|S|ooJrCNGPzP>SDc$J0{0si~nk018tbeZS$*c=uC3Ey_i7rKZfIc;TQHcl;e zo;TU-Pi}FNhFO^!Q(n4lSzx4*4SW)LkDF!<0LIh4=)yy@FCuEMXroo=){Fgx~X ze6IVUKIpUTjgU|rOufdYrnI4`KQo(FeSEi0d3a@B-@)n>)wXulwhsII`X;g`ux4Vj z3Jv`VN+B;EI)25|C~#NI*n~2No0REs**^>oztSEu@V4kGDAoJ!Y=^;o_ksJ+V0sMN zB1e;b3{FK5Yut#>I1yIW|NOf_n9uQVp1q6T1{nICu*M;O2?zha4g!6P@#NpX-TZlZ z2UG8V{j^K?=zmH&$jbfSFaF=b`R@_<->)1E47wan(i9oEyyb{Sn1%=^1w@Z3bku+~ zq4%+4!=M>g(w$^s=G&0u!BNKq@;eZofW2JH$Zp8|ll=~5dI0!O8M2#E!5n8~*XRMb{*@dM z=goinR(v-_hK012bL!L2nDpkB(OA^2!e{XqknP2bzg?RN-pg&c=^FNa$A`q?&u0GN zcLG1PlFQmhPbz7-<&^&{Myj=&w_`wx^eeia85oNs460eazLPs@QS*wP=O+SDgh0~Q z_v+nMV%Aks)zntiq^=Ls!h%%C+phfWJxg2m@lEfwr+TO}Se7Dp6mgy2XAg^sw7;}I z%jHXsS60-f0rwJblduL87*F%D%Cp|%Yj~S>4|H;#Rp@*7(o;y2;S-q4XYf=4vyP0* zEcZvUl+IX~^Z2<2e>~~M9s>)D3hpsjo}qw1xY?4V#P-XKS34^4(!Ni;_lMrhWW;`n z7A-aggtGOtTpJ9h+viCs%E_=>cG%6&)61uV7-=*M;+m=5RYFC84>fr#DZJXT8fk6) z#t)C$U-V}D54`B&JKsY5R#=6sacl4(sZOsVUbP?43n-*%Kk}Q-7&Nnn{TNDr*T;Yl z*?mI7mq`;S!T(A?LNsdi7>uu9)#Hymtnb+PJMs0O z_srREMnY2kL*&rYh$%6QYH896(QNLHpiv8;Xz>sDvKF{h`1RT3z{Y(B=PDWNoA*2G z^!$Cl^H*7G(68O}ygWmGo&6l|OY^Bmdavojrlv?kN1p>-+^qZx2hBvdZ}yRw zf0e_{{yn|bmW>0NP@jK&x?PpDB7Z>-sruk8(82o^7mSBWcgd5|u-A2TH?732kNvxD zh+hjSgZZD=J~|T39PB;F@g8ZL{;855UO~!Y12&y2dBhLs$6U>u_6hxx{5vvUw-$$Q zrra%l)If!FRv==ko%{bNC-sA9_hAZink@`b8krEQt*FR!8K_YxBP$sl22St$AvgDA5Sv7kYHnN3N!+#%uAkG>%em`T z&DyVI!+dBjJ2D~!X22C66r+ykes1>7Yk#5QwYh-eLR|MsZ==;pkv6bQ@g7URF4`lg zSjh6n3mQ%kG~jm={dEUzDIXkNzj9#X_qbixpgY<&512dp`W^#Q_BSZl)f8!^!Dc6z z@)_MY1OP$strKxcNmbIdwJXfazWbqY80W?e%=h{%u5pe50`bXXH}4ZCgm_Wi#2cHh zbFzKfc8hgNYK83i&NlpS8JfsnO)(iyJFefE_l!gAe!MKX;(JOh%=?WT0&#Ua0BS6{ z#Z6XRg$OnSA~V&-Matw7G%DWFM9ba2S(G0JP20O6rD8eN0(M>7O6QcVyzc| z2m+rv4tjZYs6Rv+n0Cm3HIpXd4KdcgE z*dFPqKTPF*W+8=6yFdz-?i9;|8F5mjjs5`2!bM&n<_cgHKfn z!N2i?hD3zk#AJ}#TL_FzMg;|hwy%_&4ojcG2k5g?_BE_%2F%N#btB3uV=FS`2k%jyJMDDYgbpE_r*z} z`o$o^`(kRY-skGPvsY49awB#szr5fTBfI5j-pP{UmvE=$ilt~6n~#>d`x!Qsm)mlJ zsZ;_-ZeH#AaKF&Ses@q~Q?>mfkdT?kSM3@roKE%iG0(S^vzdsrTjeR68F@$9XmiCxWxr|fa+He*P z4NX^DBBv#8XviH1l*!;;QWM><~Hu~AE z>$*L~WIa(`QWQ==329P~l#gWVK0nzZrlNvB%mcE&TeEepfCG5C%G%cX%CVo9pRF|3 zW+?9j$->BJdGrj>H4!KKB33_>J9ND@=tjBFR2U{pS=3d&7IYsCYR5bN+t=)>g)g5Ji80=BXeS-SW3MtVDEoq z{nKt|WaJB>Y;4%Lj_<5lfvrdUZS!qFR!E0O#pTuH_jPD!2_n4023{3PWe z$M-TsQx2CFBQWpWp>Is(@j7iK?$vHE*$N;K)Bygz{^6NDP7e<5c_e^1yMeq{Kvz z=|Z$z93B}T$FpY(mD4+B=M%qw{`M8T9Ps;!Hy!o$FvxzV)o}&nD^uDjebZ4Youmi9 z6=kg}cL6~=BQtZ&*>aLeievZ|)t{<4pB*C%x4olrZ9ZSbsKwREVuT_v0{sbeLAgm< zCsh;<6_Xj%*GF&t-;6IMd~&A!;&HToG!P&;be=sK_m!Mi0l7U{w*p#Wu`y2vf$#~d z92M2?<21;aYO*=4-ji57VBr!t+@*GitDF>O7C>KKn_p=P#TLA+4}M759cM;8mO{`nGmccB+u;Y+HH(k zgX2yU1s~KlIp+J%O_-+ig3r~(%M-*^AAc`S6aLSdmL;;9t4dANzV9}gZ0=GTPaf)U)i%dF=FxF1?c!rQ@Cbjr>4;Eh*f>z4Pagshei*LI3L zWD#+LW}D+xJ7+5}V$z2Wi(#RF!@2|rKxhcP57+MJ%U_r%vHdAMN72}93!+CTfx zgt253-7Lh#?Tn3M_y2LdwaX40%&T3Ml^rAdK$R?c*UF86gpW6;Y< zj7bdxs=D4OFkf-=;K0DX?>+@Bd;N9WF^l?>IqakWMPr@VcN!-&uVPRo{*6T6Hy5c4?8@Bb6V-1UKsjoH? zOZClJaW|zDrdt<&x|rZ@rI6UAsm?cDXw=zgOF5NqkpRX!#{7|Be2O?4f0Joy=xgAB zERM4R49UeEgFADVhh>r&$V$aZe6Hw#bL`5Ue-?lZEjH=|8dJat771faTrlg}O~$IS z2)Ml-u3Q>5?grDVt(Yy9%IDmL%hKR9-}EbML$`62k2iIu%60A!nQf`}q|-&^*2b9k z&vpgvv-O#j?OI^jcAU7$ch@Rei8MK zQF%1qlQ=r@52p0lX*h`uOhR1Ptl_dCy~k5b`;$wSke()2sLS(lnkb-R1JEnVR3AFPRkqo)#> z%3V#G{B`_q?^sTjqNIJpLPMi5=L-rpE3YxZ@ypnjkEhL_!xa!}H)L}O9hky=?fV-f zEi5f#P*h&k=M~&YH~X~%us--KFl;sVrZ%J%wW1bI<^u>Q1U2#$a+mw-ey(W?2jK~M zPjQq@di8rtCZf((9126acE`^NY>3x z$84*&o&gg1>eDFqajm)>6vyv;_^aqDtOgx?OA)%B6vqW=?zzhuUs!w@UP>~{U3`3x z^G-UWqbhJ|%eLw=V4Y>Y{VT0$_Jf5Bf#hN)=kM@GNqE?yA`7$vPJcj%(t zxyNh0Euw`$iWLFTs6*CV7+Is0JDfbcGb9V|<$_F05PpMi=fet(2AivPS)n7RGS3t# zixubZBQiEWwApVnZxZpmevAci`>MS*f3bws-5W>7GWW6YJpY@mB0?PlVn>0~gsgHj zWz4pC1<#o%)(@~scKh>1I$kzGKpoljZmnpxPE&}1pWoAVktR^aqJCFa((`27wnpw{ zodriCrJx6gHsu47XJYfECAAg9q~oJwLdU0sOpNgGhB&h)St?Ug%F6Ac#Y99zy^pa1 z?{Ir7z17z@F<~6%?-B5+$%sjPnNH|)y4GIVXFQt+;ySd@3G4y2Xh&h~URI;e#a7iV zKlGGmPMn)(zUHX@L+L~wc@FZ+@`lmfSX|f534P7`5J(-kn;*liW5-?S+o+;i ztoEuo#p6Wg>ZFm1bMZY-?@HQ(~C5ukJcg zKiQm}9xI~|u(O-@!)TZ~oyu>W>Pov3f9pT=Ipk|k*LlYG#HblXb0ZVedl!>O8ol2& zwYGBge`Ml3|jD&UB~rmzR<jWJDiua(_VngpJ+&N}-i);!!u+EofY z-v@s+fa(74032;5ys|ympQ>*HRGdh#31dL2w>XsC;revAKU+G*p%oR6jfrVHQEU&8 z#Jz~bMIn3p5?Sb(k(=5?pLX4~&qiU^SX)Qmi=+8p0oU#)+J!>v;ru&&-Tj0q1NsX5 zlkvrtCQX42x9ZxOArOKxMhdTFjlwvxSK+o^lGY9C5I;kD$OSX%)Ur?oWR=0%%y}iX z70Y02+Vfq=ddj>|NCH00T{M<^K*^|4SQ)Y?ERmaDuTU+n2}gaM`2M}DKlSCDgOrpL zz|2&Z{9&wn7+Uz`p77SEr$AwJuDXG3NIHr|dd`eYhA(&-9IG8wd;Hpy>-ZK1a0attym-j{%3r28IP{+FMyLa^k>PWZYUTbZ`4vG)f@%YhG(wY1a z;EXPozc#l4JEm)EYfDRyaqv`BzxD{XybJ8F zTR0bSTRTGDQh(*SwL$~aDGhxIladsUR@k^bbtd)a5JbF0wt$T~y;pa?d0T#rs zK|)dzUTd*1lB?J!u=o|@Huk5$Ah0kysd$%aPSa}~9L{!t)}r->%YuSO!}c8d#B2`X zEg=!kjM&QpA8Ave2Wb~fIO?`Ai=U1v+$I<3710XtI>!hXxPYO%+KTmCOhCYcBEt1SUsdfO&~G8T zx^Qo8K4UvGkEkCh&d20=o)`Rx>uF`M@+qR@VblB-u5bK`3W;LsmMp+YIe27j6rA58 zFC(|W2`VNgM(1UN%o8@Zp`Tw$A6>$-VYNorA2+#VrdJ`c5*14bPg!!I`mEaXtR&mM z&Q5bvW7DYGtSmlmxJGqC()q)}KD+@&h@VZ-sMD@}rF4b00HmqVtGpQd<;#~Jka4O? z9D zvaxiBt|FE3bA9^)W!;FlQp!_dc6>_QRcDot0nvl2 z9Ee0lCtU!^)$TSwe-cm#1(6@-N(vp>33PY9YR-FZ;T!?`FPC?S14&CNW~8u+ceXw1 z7SI>6t9WW05F2KjTXI>jFs2!uVCr;#ySh-5B5MLX!B$D z<8m)03kx{0u3D|ZSw0vCob1t2k~xhU1uo_kD3pgMXR<+FUcO)Oq9+LsUmeb_+Koz2 zHyCuYD2;OsqvBR^`~52*AwuBXx75D*p73McMsdilE6B)zliM$67F5dKz}quwvIs9V zdSVqUlYOx4(gDkJdCB@A0ehz@#O_7P#dn2Ar9gWVniwN>|%g z;PZqmF01XEr(^ElL;>%*JvF_{z#anUYd|Rcn}4TTkoJ7ynG9)|D1H!?`{}buK;o%W z=3+e@o1d2l)2vnEDyld5HD`O4RLIOo2I7_d5yFVz;6M=((b(8nTva#cNdVX>1xgk1 zam><^l8TQlDyAOL;iFG7&=TUGPQTc(&k zg!RIpaG(%?-dRpUy=2)HRDvnRQdA( zwM;!Y!Wu7Loj^ezEw=Yh|MBqVE&u;sdf`Vn$yB&2C={nnQeLbt8{FrL6ml7>z4nx} zOc@zY!EOSM_LF_$4=5c+x3*? zkEjmN=eNfu`7^Nl>^9l_IGYA}o1vz~KN+CV?E+HEg4Tjm>7)bI*%bs^E+g=J#& z{{4IU4S}nkvc~IU%`$An{*dI=@OhP2^SH_@%j3)Zaq^^}l;0wM7;V(7q*D97CrfqP z&m{`ulp&jwwJ@z5Kqg>ddtmlO1dbP|^ZO!c=u(`9vfx}?b(SFAfm>9q05TU{NGG?2 z*7&Rx7Y#438KCUjpTJH>$1nES70~#GhJ@&z&!M-?1R(h|*h4cVky$f(HIoFhzPf-> zf7W%@eFJ(OnUcap=Ro-IA(!>J3Sx34)ms!i_meHe6V_@_15#Mfv%@k#N(ge33@;Ht z>Wi@m0r<-i<~1NeVvbF@@SIldi13njIZk<*K^cMt6pL&lr8~W1JC>yqaB@wb(1?W5O9jY2TygpnSWD3q$!*{G`SI7yg;8lPPggtu8CuQ930 zss?a|YgT#%?lS!M6u=L092^{p=T67BrYpOfL7}i3*03h0t?j*cc?R<>dCTGDt4c>T zRA$=0HSMb9Ih)?qRwnG3G6NpA&-A%XQL%$5##S2f_KXXaL26hI zQam8ir{kUMlVA+2iR(ZEfD{@>3$9sU30XNILg@c#3^zym(sdi}qCI=xr;?+vsbCo+%H5xF462CHlU53(z{i1lD2+yMNpU5n;>r8}uW}sY(>K{1weFM^5x4A; zdQ8fO?hdSh;*ZY5v@&P2o^P+LPZY5rSV1F#>=n>UUAgv=Cza$NGybZJq;!qF)^ zE`kPR+Oiekjd%jUW%%|%O?-M)3ledNJ@ zuCz*MtD5U(Mg{@iO}$e~Pw(?kPJVvH6f@fh6DapX;0FeOdkHu6vH*AhKVm?L{PI4i zSc0;xqM~9Z$GaA4Q2(bi#Z3dZ;0CvDzO%D$^Y=SD23}K-Km&C2D>SH|8^&<`tyOO2 z7SNZey(-mzeFqaO5G)M=`qw<~;RG@FNko;2GSjDTx~#Kw^l!QI_h~uFP1zD~FKJ|q z;_T-Tg1Tk90hekV)dfUEq@584GIauP@<#zn=F6>+(uc-+lf5^Mu-yy%`vhe3X*mse zf`Du`_a`w?M(h0?;YWV_aw;lTTuH{l8Kb{j>GC;Afz?Rrto|Y`K4wOW^$mcV>%X>4 zhTjzXQ&;%^j=n&|p1I~t(e_16QrH(srCgpANXZYDbpRH}DTP2H&8YdT9E`78S>>C;vy6^wCRQ?7@uz|Ys;->WrN&mJ!V9(t2=0!G42RYTN;)MhNOppPY zd3n^vr`W(s&!cpv?85djpaopaZRq?hj|EDHxg&`H1M$6@va4ENUdgSxwp8mB0wdMK zy(to#2&Mil5*I#!O$CC2H22<~z`l3h(#Z9#lnm}COJdRoE8V;uK0%!?Zfn!>tw1p# z6JnVvmK+*|TyJdeTGh^2aS>B=!VeNMf?BB4o2d0ZIJ+rXiHm=C_+bt#OSeUZib_nUeL?FV;YHy&^8acd zBB7gW37{YTM+5B>`u{u{IF5vs0n*j=b%x0?vvRg^u-%IE*b?#>x`!2|kHKTZ*VY%==6(>_eauDD`+^O$ zivc>F#!n4k7P}NT{jcLW1$*N^pa0W6+s z_8f_3OjYRfLQB3xVMU03cuzngag?07YnI;@^wFyB|7W#sLoJyNcKBK z=pn8uc6Me?TIpM=86`#O_2spBLl&&K5J+-{f+bKSc-QFS|LI@6ls%ji= z`OR{uj@bDZ-9rV?Jpeq>MA1P_XAZD5n0yZ(J$&pa&?;@BXut4dD5}}RkRqD`8&VxK z$`JfHmdF@b`(OV62nMP&ZT{Q&dF{DJ#x7UDGr1Zs`F}x*yIeP$QwNdqxAzTTa|VDn zx|*{`d_{Z{L&!1>JV=qDBBIDHM`f?u>8MCM$3h@Y_ljPG z{b&r6p1H(E0%!J+Dh#RMg;%?~YAq%pi7^@NuoQNfL zfRO}NSpC)gAJiFQl@%BmY+vt?-i&|$LCRlSp4xs|&UE9!hDroV$@?>Q#r<7?vyBkV zsPGPw2*u&e=K*LZqt%$WM+{rVyYwU<{`DrvKe&JAuRd_k9KgyTZmBbqluUf-cJGZbW-_J`kq8j5pu(KzG9MvLK|Uo@$*;&NeFwg54>&K`f{cXW+&Lq&d=;Hw zM#kM)|Gs~mRjA?yz7(357ry1znQ^?AZLa9|D~$uxGr%SU6T0~7aT!3rnKQO@+k}Fa zx}^~Rh4HyjEGm+LxvcNB;7pK`DEluUP^Zh8nd0IR6XkAfh+G%`M3RY(3=ZPlkwryZX=;<^cpOaL!D z4ln>||1Wru6J0pXE3g1o@%C>4Jj(OeujwmPL##HT#dBx&tlnVQU*I%pOUcR2?;FEA z+N@n?&OkQq%l6iOH*=Dpr%E^KU|F{kr2W7KA*6KQy#^A~-EHffmOv%(%c=~yq#Bsh z0g@#!s@knh{v`d-6ROGY-bhR!9MjBuhyiJe2D$W4WRG>B07d~tUmh^|HY%qLhlEH1 zxIy_<-uN1Tklf%nzs1EBaSRP#;8HDarv@0_lLQm!yW1NBfH>L|-hM@)=a>UTH(&{@ z03nVSFa96)-ZLtytb6w@r4=eqsGiI*i%=JqWtVeJ@&u-mOSnew(=ctOc381fJO^qSoou{3_D(; zD))|c3qV$j=c=H_^Q6z8-}5=XN3PwMRkP?xXy{~yYKN?i_}pm2?{6+Nh4Co}i|Olk zz#)Dt96*%|rf@2QL=!vc+H3FEL|^G_E(pQ-tbgf;XK!I)2ouOu4}`6=JZRAB_G9;7 zAiq~v6H@Sgk(B?yEvo+L(YK9wTPvMX*L_)Xk+js}y;sD-f~)l$i4VgSl{ELK4P#uk z$5mDaEk~$;o@Hw*N-W@N1U+Ak(}?2}F|PEsnN94QL4-Gz*=s*@T6)t}8lk&i57BFQy4O z=bHBoB4s9>iLNmtVp)6>-cxBdM%cfVKp%`$(}0}SGsCet+qD_AJla57w=&L@s+?kR zqC|^lx&19U`7|DT>v+0={d@>Fvj2&Sp-o48MP&uZ_}3|CJJUr_TlXu6^wz!v(1AE{ zZ?3;!HdNcKCx4jAq)ZVL#g+k8*!F)$Bs zlP4dC8B`+g92^p?uWx`>TaTuy$Xh*Ebl^!;f0lR1&uUY!G-ZYiQT*okH~ad6;g>ma z0|9^L0sy4qRPW~Cb8NBg;#R+zRgAtoRgsd8!C^P0zT_M;FISt~777ko-R5(YyZn58 zF^kb|zSKh4+_CQ?mE(Wob|(DibRG(>w;K?+?XTzk{P_Ww^62E7{0#sg0yjuWT)(7u z6`N;qYxSv(;^%(B@j(vRnB1js6FB&o7p>D^Kj?^g-MDtG-){G^Obp*`hGlJH5zZ@g zmATjGN@%s&q6G}c`xXU3s)RtrzHn)8bvJ3PG| zqlZ>f77IE5+HVQV+hml~PFuh8&EyV@KWuvO`UE1oDI+N0LO{Gk^tDwp;4kv__B)kh zwtqsBlFwylbLcQ1*<&?wro?I8X{!AC^ZhoYv;-ve%|SY}?whyIv3(j?;s;I}j|O)a z)$_3AP4qNw_1s&*ucqK96gf5Y;?p?gV=w?R4jVVtr=Ri4l&|Wa&l}*kuCnR-P#buo z_G8g6GREg7RX{P=6SZ|hEIIF#$k2`*Prn&<4Cb3Qy8#~#0x zGQm=5+&Fr}IHqdmvEJbC-I(37)E)n_()_8?>Rmxk__o)Ix{K#XrB^M&!M?*8&>Rj5 zpZ%Q;m?Nuq#qOFFTP}m3@fylI8fs&6;P;i$-zOjx+DAQbsBnAyp~C`RwFOTFKbi zF1M>DO)KJFXQ}tfK3q>P-Z55JpDIIUP1fewb*dU-t9V)y7m3Cv>s~DV3*404BNjQ$ zhtt3XyJ{7?f3Y_3wDP28L%A*kg?=#(b1k6h_gmEsv4+_{Z_9ds z%6IZXM}_xFpY|+&g)bMzKAsSInCG+}Uc9%b-1L*=;>A5TKcU3mK2cp0aX9=?{_3RA z{+yeZ+o()|UUlPTs2xt~FxF=_9kgQJ_~3j4|F_>Rl8|vl&5^3R;v|AVIbq?2vA}fg z?E5#;YV~j{b~SvG;RpPv?r)7`?(+@f1dRf6gK1ht8-vcF-K1t@KfQe@Lor*ec$)+C zUKVb@#a$4>KTnEiru9-VsH|c$M<<^?dp45O@>!j^Yb0u=)~YHiF>%71Q2UHZ{&W@P z7;+A@aKFqPKQ%-xH2 z8|1RZjwLH36)&|);}cQgzRDMPt0@(q+GpF6HruNL7XJebV`};dFROu?d+qgwpqWKH zVxhf3=S3z09+%C5Rx+*P-86xwXg=NAlFj;^y6uh*H%1J9n>9|;A8`#boY;;^*M^i+ zj%e4~$P96W=9l4`fR{koh;c^JUyGl9!15VTwisd4@E#;)5_3IQ@lkubqR3J+9W;H( zEV`w;qZ&tNJ*fe@IgiNZ(4;k>2-wAnxVwEikKidDQ4FD0eOhk{sj11!U!}kVUNm#A zfy^T-MsJX-i`AIF2ko#PtiRG3+f`=)L$h_Q$cpdg&HH?TtyMnghi~d)gW`F~b1Fz+ za=Gu;oNi0U9H?;zr4w>-pe;XX-0|i2XuI){cO3SM+4ohuG!9>;RidtKr)b<<`~X@{ zq+3wKyDlwrwf*3+>@C>vZPtvEr4qtL7SI1NcV?c<)ba*?x)CpPG7?9^(B6#y*3n=+ zg3Q`w)+)Zw>AKyayr1JZ)^Zq_u*Q_G)}6XDtJhQx^kenTW9sNh{N{wmh=s2k3j;$| zpITYquq))WW>kp6j@4pIitHB6w!h5H&6W6&o#ahkes*$xcO;2MJ(@f|42zXgFZw$3 zL|$1@kyHKB#q<4Zk571bgoU9sJg%;8>66GiB|>5W^+B@$bRGpQEmq3s`@1xA$&K{)xgaM9@bxe?QGGgph?7)gtq~KjTiaih;~(YQ-vebtPqd?dKDv&M6i{sdx%0#*<%Ars;TIQgft8{ zA5lCG2#{fuOh-XJez3$;sIMFkAD`$_bIJv6L~o{}_cyN|q?!Jo^vjbZPEIvkr4dj! zb;>F0)iJKZpbRpxmI~gy=}_tE?g-3xzs=YLGHYjwa%P;3d*X* z7n<=Oj;;tzBB)1fH8vNO`bX*|Ew*c#Qe~F+(#q<9!{g0AKo=gm8#nmDt-FtxhDG2i zoH1Cxpfy6Mx4Ys&?LDcdS6?*t3<|_CN$UQ=Vb__;Ma&0_pSR_u?VrDe8}bX}b}_CS zJsxC{IMFomLTH<;$t7oOQSSq>qML2`f1)oD^R^R@FUvQMed;iVM(1aa$|Ho!UbF|& z-5W3dE|qN?O<))?@Lf3`eKUP-FTTIU+9-)_OjP7+O8qL{(us@iMILY7oN`o$Mo7xa zosGtwvh`f*%nSU5+n%#z4N(I0SFVU|=j5g}J~QL}{;;Db{R|$WSs!9ZE!&O?Si>S6 ztH{A0;1mI&kGD^t2u>{nNIO`e)~$5D(^Nf=K;??gF@#yp!sxoyPpj{5zzDVF#}C4+ zIKa(ytD{rQDB4;9&o<6^s^YBfgemgO2MoZ6wLx6S{-Im(hnoh;6h4y4k zG{w;4sxveTR^~xyw9U!EYSPk{Qo?|ytgfz3`22ZIYTCBKzZ|-k z2PF(23huXGUnSGav!qCCq=P3}$Tgkah>VN`WY949)A0J@r znt)*zxFXusc?JtkC6hEAv_2Ev9T$-Fw!b0DW~uHAsr&cDp#ud)`e3$4MW_sHgL5r0 z1EEi+ueEkT@?fCW z-IbnRJdleHt_)vu0s*hA^oyctv@0Jy&*tWkTd2=5JdW3GxWyj-rgac~nq428zbtog`0b{)J0{!%57@lNkm}+-9XwCz(Ux5yw=|-SuB- z6#KSu*$pZxT@?|mx|^dtgmd|LC!WUmhlbKqq~*l6Ql4#a)37X)RZ?2F2130mScQ3O zm&GkhKN|V)qXkw$PLP_Kl$3;ANm+St?J=BdX(B$g(P)1$$@Q2=c_ps~rSnH|+hPGx z&egQOo6-?2WL*W3HR(le4d1KGoSZlKZ`@k)D+{sgwviso%_$79;yQ*9mDHQarC_qM zY#TSu$r?!7UY%T@>6kqnK&_V2?5jAbh1U!8X=biD@1hUyKX{O#h8Edd5>sz#-j04n ze<1|&P=~|aTWj&_v*MKx2!K!MRqRVgTQRe}^Y#uc-6%xvtyfX9h6_}aR%gA?zV{X88?FTK39zGaX3H!`0isM?w!(a(ug3Jy%d^GPl^xvN4CAZGiiGMFb{*wKS zx(iFSL4=T?0qS3H7VOByM-Jh91kyx319=3tJrG>O?jKp?R}n)^!z4mj<@d1IEZzSkB-iEithSVXhVo zVqYhk{oT&m!sSawPb_{YU63Vro980Hoq|^k0Z_-%j6crXo1f^(GR#5chH7c_u5~G; z3_353NJ3U=-U&kQ9o*S>FNdTq{J;qo6y|73gbd;xk-_4qTwm zIvxi*xTpl#M!Qb*XuIvA(S}o~rt-jF*(eLGNfL-)&LJM$yQ7Fi?bI5^?5`(M;_Gp0 zl$PnSyX;LTnF^MSI%dF$n2%6McV{gEny=>&qzn6pF;Fz7v;aB(gtJk*jzmout?MT* z_*eKP;=_lyNVCU{WNePZp9=ZoVKoWm^><=#)cYc2bLaw#x&4ssB>Hem(#|fI>K0@G zkiBc@_Z7fZBzAOJJeBO9AbXO=K{2klQg#eaZ-b#@s6joq zf2*q$O7G&LyzDWPq7}yxbK@{MjA~mJ{bGvla!dJzoKZ>n_b>+KpD>1skd#iw6SLCM zMmgbq=4+hU+NBt&b^F5?uT(T#nAJh-Vu0y!mW$k!efZv}in#t*?Qq~Sz1SlO9l&@; zvl`wtMC8?%I1G|eax1H-{J2*Q1zZo44_tTmH@k)$+Tf_HF8n<#`c>uJjHKf@+ppKB z@Q?V#+vp?wBIK0Fv*y{|jaf<>O8d`WZqYLp702D(Ive(#fk6mdR@Czjv>rcZK*aW~ zdI&zF?5DqV>x;c{`j@FGgwMqNJ9iF7#1=l@CWCxh{+qm&8o%l!-_rzyGEMhGeFlo` z>|O8o)k?yCp6Zk|^7REldWozoRh_3)f|Q)J_xtxyk)fih8isIRc$e{M5h>l-lVD)D84rTP%uA5_-%q1Gz zlS%FizQ(gNx#mL|nsev=##a=2g@?~v7O+3FiHjQ!?lqe8FU^xyQ(vbjHO?~GgmPWc zt`X50KHbo;*B216AO~i)I@jK1$;VEK>kIcxyj4> z@VWny&=MUU&Y18!1vM?)FRwbHLs8|enIBHo3AO*F>X41LCF0)9nUoIbAsC+xk`S(x z9sCARY^ExWZ01(%z4<=o(D=^ zjzjdn06(~_9%f1k^bJ;FRdfri-2D%$WRQ0=CE9Meb4JLF>r*w_oyDnRfInZTX0N;ylZ%r={aU8itaws7PQDp+yhdSPYUFi; z`Kns1rh!6950c2ZIOLTY`ZS@BKMj+vChpXjpvd?;HQ0)V-W-)sm6x~qoLDID5K(^4 z=+xN{K83wAg=%c{S8#WKcIa1aKlyt(fg{b;Buw&$xTLYm6+bAW9+pk!=?t6kxl{fL zo1Pi?I~A2dj@qou4PSO>nRr$R8Wi(NNztxUV2aOQHv$}jFewzK* zYG(!UGXJgLB=|t!mbfXZlJYAe#^EB`jdwOU9^N3IVsGI)JdG$5X3SB8l8>BYPGV2n z#tpIxrtZ5&HBoUjAjYpcQX6qTN_qKZ(a*;UMFk;J!wa*_ycOD(o z3<8EuBTf1}{G1_#-8*hkNX1c}*Nj(AIc58gq`~?+jN6iuu=8tMoF79Ox#soIzPs=+ zk>y+MIk<;;s6rFEO@wy8@NivXn+{ebV%$RykOL6qzKHwf;E!@i+;a8n`s>2>U-7d4 zwj%z2^cU|k4gZ!S5#KfqI<;ELjJf~}jU>M)&cymR4-Y>QJ6d>1py5EuS4MzcJUSSk660owmFCSORk;p8 z8yq{qdXJj#6%Mmuw7u`3XY}N?L_Cf-@};7}#=NQd_->{3-OBkC4>OtSqhYgo`|I

HZ817k2>Xq*_ID_ORDDUyE~A=lYQiS@+9<^-2CjlT+|V4<1fj2_gH=w;1uzr=S@o~d~8X^6F?aUc^DQn zs$jJXR8;5BlYVNO78lEti0}`R{{P-#`6GG1`kiH2$al)&;s|z%2k390T zFR00a^t?Od9j-MQXW&-h`e)BiT_zXGL=&F!*SXe=bBJ+>Ui`I| z3sxnW;s}F4-|>KP2Wk(=Bg)O0lL9@@p{S-vOhn9iekyy`{#e{CZyUm zM@u-%dpVpfNZIOGYN*JZh022y>(^Q<2jC@_RXZR+(aaTv7?nuYU4e?=z%>?VdjR_U}mza|R{` zd5W=Lt|#%Gz_|24K+P3Qg8R!UX_}P;QkJZ&-62gE|8)kg;vCWZEC)cu5$9;0M#lK8on!<>x;Z?zN;|n9;WsV{^sm_AU#SV2p?y0X00C@BvL8O5m*p|=pE2em z70dnI;NQcfDVV`8zXGFPhlqCLjtu3|A2_DNcl7p}aYMeC zsa7u)kK;hLPJ$Ny=e2eE|A)oxFSPDI|BKnjwc^@Ntj)KnaI>Kl-}(!RN@Vjzpp_cqV62a?<>$*UZ=!t&9%4*F~dtK6dqda zYu-JM&=v)av{~3q=IVJ;(arA+u|=0(-Jzj4f8OX6=nM$Wn8i)gDVJmJY*!$R#` z@%w3lSZBZm|9rE!;Q8oPyAz)#Bn%VYPYsF|(sza;N+@)D@yDNXmj%9N{(JQg0{G)8 z)GlKqptdv4vvDH<{iXf4w*mx&%4Z-S$c2o@YJP`Hz_y_k??Rc$jp$w$Ie9&vwaSo;j(hrMGLr(Ofl5HAT6^ z{uYOVjou$L1;*?TnqqaaFHa6`SQipmjr^+*d!DQh?&|C7H!RFYh4WkfOwNSD>U2t< z_1tlw%OQLJ!3RW58e!D;LC&sOTMol|s#{mYgx&OQJACH_>=%1&p|VM2%fc2aOEpHy zUf|^hL+Smsn9?2&RJPdw)L3JaH+}v7%mr)^|AoqE=$u0}eMi4NgWvw57`yiRYXec=;<}qp2z3No$yu`0xXWAbq zgbVi%?tkT&eohAP7S7GCI=4LI_b~cNpUafb&j@6-R;6idSXA(L=2<$tXG7(0o`C=0 z3L_}X215g)U3(Hj(=>Mj`U|?+J2zzKU8>02Ae~$1&NH>1`M%d?eCgXaC}jh~0u~0o z!s$NqJY>&@n3$N4K{f|-J+Dp@7aA=@?ul)iV+t~-#X8f}$u3+r-L>7z&#>}yn`#~* zq~zi5JHOo>5<#CemYPL@`F-6dd%8$$dwazLtc+Y>3Yis-c<%2K?`@6B#c@@75k~+r zQj{_nxL9YzxiQ8ONzSAANcBNn-)y9^2kYUBqQ zn2;RLKK6Y2c^6yZ4YXS?lx0wUHxhRaU%3gQn)`X^&UncWnO1Gp z{8^KEJVNv0u-F%};!Eg7NAlP?e12}O%sAJeZ+<;h6BdW6t%^KnZ3GI!?8PGZhE%jl zmWIn8_I*$ZWhtGEv6qR0zMJg~Y{hG>FYxe9?XPb>Bsz8KCL`;P!a1|QxNyXQjfy^d z7?M~u7wOm*>J9c4FG7QZ2O2G(aEr2{nl^=bye8KzT<0`wmR)DK2N{JzCJe&3EbBu$>il{h1*t`Tmk+9gAC$-e3YtUK?xUnkiLZ#eZcc`eh7nM)urAEET8L zGpiyN0)mXxKLiA@+6M=BC{4>?I@{tUiS@@5{cH`I%*~y8y^CSddhF{{Bgkhy*L`21 zJ0|#yvvrU9X%m&9s*Ky1rTIZJL`)p%QZ7k)$)HUPQ|%)+sMLj|oKmtPB-dNlz^mV0 z165mWlBU_teoEU#KdczM9@uZa_CAvFseScQ4tfPwrVdLEsv=aha=vxUq#M z)}O!wm3VZ^-0N1jmFIQ|1vV9@UyaX)YP)nG1vQ+qZB|1(1N9G@B+F0f_|x;{2} zu!}O&(n^UJsCFW`xZP|ThGr;BsU$FX+GpS zlKrOUjgFWXwrb{v7hO+#M`x~EefwYu8d>Rknb2H0zNMztBQ=#7B4h1uObz4rdAV;W zbH9^TE4cr_(z5bgno7E2%W09lHC^?tXWuMiCu5P{`W?1O)r7xw@G!}MlL)85K8OkG zgAq|tCH6y@7kDQlIjzP3l8qQ(N+F<+=1uKL8ps^)D&7+uIpb@pBO@c@=vct)^?7}9 z6KtAtP_aLr{f=l3);Hja>`>*a%rX+>i7g(;F|n5!Eys}KwFd8hvl?*H*Z1IXcGWq2 z^2DDE61uppU}^Y|H^kpFWZ_=9Pl&(6-C)C8wTW6J5bY8N8=)EX$TMP}G}IVaxs?;- zZ6_YSmC%iXyd_r!iTnp=MxT15Bx4S#3DXOg&#|JlmO88 zOgBzl_*!BHcjQ39(g0u%7K-XZ_;5nyd6J!vjh9h3SLVY&7+DfWh)+xvgx8{lzHBAz zuoUYy=%SM1S2)^Oq{;PZ5jID+d>Xf%?d)WQwEVr5*w|r0N^WrUO7GFxLNq7nb9LGT z`nk37=!#Z8kFl>iZXr{NF%y;8nT&Cx^(Ax93cu(c)w4?ARaF6DP1z!!;8hc^I@k-H zS*kNzYY#l}s20q5MVf|2E)A`gupuSSAnej|~Qpvd(K!4tF~oAkIVx>Qp2*vAJYGX-zKl zQv_|_Q_Re5dwsJ}&<$i*L*=ZL$tzut)7oQ^sL2FwR};so_h4-o)j4yyT^x#fP8Qtj(yrP_L_o6qZBI9`9Q11rsvq&l3G^=2rzEPNPBpC zKoWiUOhYTGL6WB7|KM=Vxx)tpqSkq?Cj`(9Dhz$cur2iB0x$ zTwH{cZo(fOZ_&}oaIZNvsSP$IwlQcLB5!C_z|9G>vXNhNqB4D4RJpLIwB^I@ z4kgR(KhFvK=bY7zA9MsvGygZ#M82%+!6#kyINQ40&tMBHQEt=Vw-_Ey2-QB=iudz1 zZeL4_DzY1}UUb1`7p+2k(aqhFyBrl17(r)p@=x=Sxobn_X3-{tRsyhp@I_@9%uB9F z=8lezg5jf6!WzF0AfACYu+#7U&S1RbMl89gs`g|e`e9eesttW6Yozq~K*%n*HW=~S zQBU|cpBv#vClVz_Dv!l}!_j5CZ zp_!(!i0jqlR%3yoD78~Z9&5soo z=S^7>){bqAkFNU7l=a0_lyzeyL9bJ9bZu?ii0B;E$Qm4C^Ypl)jWXaYMUF>trp(!n zX7}V$bcr+6f=Wmfu9Wzvio_Ik*WwPd)7N0NYgXd@hp>QOq;>5{g;T6~TaJ_V5$O#C z-St7o>iOF()xMY(BTlfcTdt`juC=qYTn^7MiAYPOI%(V6&M+z~++%0#idJT#v1;ir zIN?D!IYmrB7~Dh(h3hkQ&?|xq^G?eA7U$t}ON-`|x)6wn#l^)j**4GB)WYY-B_etE zz*mlmmKFnkJI#-(_&5H{1$+YQ2KTf@aMAG31G@oL)V^)5?(_KgcpS1&;%sk`9SCm~ z8XsW$D9trsRqd(|w_RAvYE*Phd>GB?P;;ekmGe5!v|mjp&K!hGdexv>L7>yxpOTqJ zoqJ5(-=vrNrb-|#BI`Uj2|ms{1qssnqgW==z5S5V9$)G}pVJp)9cSKF14$ltH6Dw_ zdPv)1aEH^zzq^9yPtpsq$Q-OA?Q5ss_L=WXN=dy-_1#;lBtAN#NE;X=8VN?hJi%Kb zzRbuZl1rbOnu@Kfqw$Y!fsfmii;{kGZzC}&5V!ECjQsjW!4yqbb$ai9o9-WBu4~tf z%dsU^Tw9SBov$VDc}Q~4ovFil5`>&m33SYziSk_Rf@!r=K&HiO*53^$#IE*s>^Syw zRw{bXZgK!vTbVY=+LG1Tbe2#O)s}BX={u&g%H+f@PMbt$Ihpf+em$M^9#RAz*l=lW zhsOumD9x}$rXeS~E3v`W_mE%_RZgP9tmYPjj#$^-%yHiN1)mc-%{YQh2 zvjcWotbYSjoMk4{rZA4HAq8YjfeHw4{$TI*BBo4KbSvFI*afT3WYu+u2hvgs3wM5Q zuZkQ#dxe~};tOMr5X4-;BX}8Sg zx(#C-8E@ad!&^NP{R;I47xCX4eNnq2Q=4~VC>9m5(vZ7u1yt{};eqvh+z;nXP7MzB zUu?|SO+}))F2HnJ>saj_*HyZE@+^@AL;qwAvXXuqtU1UNRhUgkJaC8VMIeCWeWEyxDZK#Cgbi;=1SyqNtcT4~B<>CT858L(Y33A59 zs*a9kW@dMEK7rCkBl*PHl@dy>#zb!d1wcJSZ4HNPNjbG^P+zvc+afu(H4m7m$d20~Y1*(w6D>fF!|w0nC8g~bpXZ;|o1`)N zX9}ioKt;gL9Z&tzzx4_^E^7a?8Wh;*N@rK_>5G=sLbwx-Dm0n@{evSiOd$5-nAq65?yTY-1)yvO{Ot`s<8Lyw{wbZRkbHAMTh7?^>> z`4J3$_ohl|OmcRZOnbAR5A67XgKu=mL?+%k)dFA5r(s}FpB|3h`@6Y_3g0&mF0KwJ z(z}Ro@8m6>%rjx0!=+ivys0h)I9d&Mk91k_GP$^YW)SSoTke8We&~@PJNy_Nxjy7g zI4KCs)|7uMX1RG2(jrIKQ{uE^XCVN8j89DMpSQ{u)zx|3HR)j(YNI|ZbJ=<{IqZ)= z7`yr_eJ@$EwQ_ipkRmAP%b%;BTt}@x9!d9xF zs3;+;_DedYkjov&U6(B>_YeAbj{J9WYSKjcWZ#ewY8D~2M~|LpYJ$1}mwS`7gFzV_ z)(MW`;7s_P#V;vnA%|P5u{BTza&!$}HHLc1Kd&W%e=ec5I5Wkq%G{~TLZWYlaNnfz zqxJrAweU7hYrIe#bfh)X-x4+jXA^h(AbuW#c~_Rfntw2){eK691`n)vC9c|KMW zPyYAvW%?<`KbyM3k;YdJ>RD|HnIq3Zn6ifmM^&Ut-ST5HZANkZ6u$w)*@PRAb z^VsJeBqQ6XMXoMR-=Ex;J>m+QbWy#eFz|v877W04M2Rujs6IY3GyeEIKt9J(eyAxr z)EJxQ``Wn6hWZDckL?2Gs$U|BgY&zLyDXB`VOe8wz6?< z7Y^@blR}GB!5M_AiLNDoS6qNo=l7Q5^Xw5b4F=YaMsujzjb)6CUhh32pEZV&Voi{L zy96D>^Y4-KKnuq>IGHFF^c4zqG$8J}5kpoGs94AL`EF zj7QXfg}~L(r`Vt^!`R{xNSYkA%hV*4=g%i<7*T))My47XtRbwZOft5bx0-qI|F}Q% ziA+LV2c5s)AWCB*i}ysf%h+UUZsFI$LaAJkpX+Vm17`a8F!3vP<>$|rGgzw>zbJZa zmu!YU&Z(yVd#H7fCv*_WKRv2|k5ja*G@rrG**f`6A^R9VTDi}EiULyYU;dFxNry_& z8ISap9=cRqpA|&o6k|a@DehtZ<^xi=lV5KSHX={I@?dFT2|^*@p{E+bBn5%OhhHwS z5(&fX`1ATdUikl)&RhS}Kk0w^C;ddB)jEU@m?Cjo$bvml0|QM{^c1HyXr$2AaQg&8bl0ZP9pkct zl`v4Y!+C%T8Rzgr0)%^IWd+N`coZPpa6zuTSdzNfZEtHiGXo$8a6G9n>kw1)7jx0o`jCoJkgoggj-{g^^h80A@ z^YkJj+PvR!M+8LFNZ4NCKX5;&;6+f15g5-k+^r2WqVV$Tod2o0(Foo@c0aP|)%xS6 zn#MxQV~N2rfb+N0+T*+G0Gp=M3gIH{{4*zpSol z(N7sc_9mK(#nI}wNT{RM59Z!73Qe!>BA zbv^-MTbaoVXf8v^aEW-G?*(+3Sy@(@Sz`mHefIakBgNdv2$}JDcY3-Jh_Nk^E@+H` z9dC)3z@9a3*&dncfR-er4Rqtj_VKULU!Q)p2Ioet^%3Lo?WBhV5=kAdoBNyUd1fZo zlsg;q)*DMB2HyJ1Kd&pNbVRX0Am(}en{ixR{A53;I=AaUHnjK_Ib7b1jlDAdNdccQ z9JT(Lgh@pRJaIwcWKk|&S*hFA-!R#KZ6(-acC5Rj>%-5VKdFlkF&vGTo-GEX)by3K zB@NkbzVxjwkv$rRljANV3qvAybKPNG+9qyBQ_Zw08m`+}O$Ua{Ch0i^X-zO&Vx{j( zJ(OopXy~8rOHW^!Qa3Lhc!urs*t04J&y1F&rqe9^&Pktds*fABB{rbx-)Kq;@$I7a z*Sp9GPdYa-Bt@oj3ab|_1W3{_v9WEolO9L3U$r*f$xhbM(ZTBENKMuR(3yq1#3R9F zrkkK_*>ZVBy#)LaK=`plowTn~7W0f;Xy0n*lD)1*kY$!%o*ZDHrq)YG%vL`a`h1aZ zKD%vfzEM+Pa>!OrODlS`!YnaKV37bZe5kP-ZOzBH%clP}_U#dL`H;SN;pVz$J zh^<8V*|T(&gWaL-{O)&H>~(3azG8i8Q%y}}gNY!M8!`R?2iUs9C=SDgrqaEug5^=0 zTt>~J1=7onEB52N#$YJYm(&EpHRV_qBJ7+ z7nZU-6A}}tc`Y7=gsC&D+Qfbl_cKZ6vHba){>C;GIv)V)v7N1)a{tYuW$*N>CNPMC zk2Tr~`+&o6@X4bmQwO-g2@Z`J5}~JO;Oo&sG&VLWQ((=Xkkr;bz*hLq7INfT*`a1A z3@jh>`)ra_l24)I*xbz*aTDzJW0Tx ze1FfI4eH>UEVqA1hwu(w=CpV^Ngp2Nf{vK%zqabInKoc;UV_g5d~dox)3I)*gGOk3 zll~+zHLCiu8^!>e-8s2z@j_tHr2b2bLQ=!GCS??}u%qGj3XnGENyr`RSa{@OEH%By zUAAFWf6)-NH&aZCFS9wKwHM`^&-_@}O<}oRworYg{Y&5dmP1P)Q zZ6RP2UK@U86}!OOHQe~?ok!3Ul+`|XyAeG%$4pMuk;A20%~)QcjF43(wbST|$_UOH zRp{c4F!GJO{Cv=EmL+qiNTczqZDifI$6xOAkg#J3kIF+0TAp_r=B0)~JDWYfaJxd>s~7|%dZW?k{hxJg`lH3G zRoSjKNb4jGQA}EB?m2{o2CM>krhU1cQNc<|vz_Qb9|bufB?n)HbS|g%n~p`cv$^vE zcG+4?A|h@otJle8%`ve7(1)zItx$n4D?~OaOHS`*Ar3G8?G|5*Ys;3U=|N9Y@4%$m zOb2Aum6ai4D#e%zqj7|ayJ$d!p+HKOm8W3~%D}*}Nb`o|YKL2vwQuwZeg=kG%(se$ zj9>y?9mBS^hI`h=pZTo5pK>fph#DHeHbUyKm(2RY148&XVf2X`9bGpop+f#pthx^R zAkjHGSNYRI-vQtKs^MX4PvShb;RM)osK}Dsm9+zF+YL&so+m^LIT>+M$VIJJBzH;4 z$pz+tSD5i)5A^)&f&~KYc-vMr)pTx+iXZjlIaIuljqlq9Igx=l=#H@a`4(@XXfv9d zrqH>(WY>FxK+b|?eXOx;Q)JI!@M8;bn5ITX-G#QZ&|pwgTN@h8y||fPkQiZ=>K-1Y zD=@zbWboKrmJ#Ocl3@&*r20&mBlu+SR4cQ-_lS~_u$NiLC$fm~O~rQ^@(Sr?TnHX~JOm z7+!b%F|hlgR*|7v>5DCN2TLQ*Mr2Ge%1&y9#g|1~`@1tHa|%LQo+7pC<>-2l+<84i z9T2l2q9(0oguwO-27|AsMo!stGAE2f)KZ`M|OGD}zg*1b?%fu``YP>)Cc(aHWRXT1kca=vTL;oPTW|}79;=hCj}ohx-oHi)ynAV3f9j_P3KtzuioW6G)O5q z5#$y0qhC@UPxPtvi1Xm90%V5G3^FK1M2(K1>=iz-ueUc7OU~uVi{R^p><+_&0|w^br!Fy-NB$UBO)W)2ajXLu+ONE24c2;vzXC3I;9JB%{OWToRfv~vRZp6 zvN93F(y;n<(FtQ34vy{b*7a4~l_MgGazaN5nCc!J!`q=ed&e{_I3U1`GuPQBYv>H_ z6SMHzKQH;}^=@k0G%LnvPuEZQYF|P^0+R~bIHS15=+;U6zQePg@si@TX4ODx%ubke zw6_Zv83iCU+y>qYEN)ppdGe)|jdC*5dP70(fR2%!o%=>^TwJRq3;C+4Su~P&qwa^` z7AEp1KyZlPiZ=(HwFikP`E3>&czXOKVH!t>EV7Z4lh32av-YgA-40!K>MVUmrK$FJ z_eWaO5(WXR0c7o9Xg=?7{%v&@JIA_H$v!P#i$zy)>F2~mtW%l&kjo@4Jl(rvW|n3o zd|mf2GBOSipOMjT;;yZ2!@<5dpK1?yT5kN9>!*T~8>!uk-M5{NRuN=Jh91+M>S@t7 z!9qLwVuQg^nJi@f-Z`6RqvYhYaf7;u+b`5u>&h3+Ep=~E&vItpk0Wvo*c%Dws<2y` zygeDiQ{|c`Q;$9F&h}isb@z1kbw++}#wzY}XkK~w$67Z8WhT~E@hvLOZkr>LG}fyw9$sE( z?cFeBeW`OfeGIDiS?$_dc3vn;uum9IKQwR?A=rel>dTKl$M4+T9-f|Gu#!1fa(?z&k0WDYnGsb*ka2NHpq| z3wt#uV**)?CZ%*TG(T5+7wr9LrfjC=&3g@v8Gbf1M&2M_Go4Xj>YONiK?9G%<)j29 zVR{n&RejskinjAkMCXZ#>kPJD?Cp-lr0vz0WXlM&-CkAT3X3jxgfBP%k6Y@&+|4vP zV&(j6D%#k|*e&|E!FVX@VUmj3B`os`-Ntf#aHGB3L?xwt{rdLpWO`4&f~@TE=EYh= zJaTWRtu^t2qo;g6uI+LFzFe;l4)u?4i|g&>J0qleuguTy zo7YNiS7G7rQFGshK8xTJS@K2Wzo@uSfk9cvG-%P!d%vdK!rA6I~KSH zs8`X(B5QO9uiu6Cv(tb66O@d>5%%Zn@Zah|$A7aw6b#Y3F&x@S3nw(nA!_{BD{q0| z$*(`7P{)7!Yk~crTR_rAbRcacpAAVHnSxeN44zB@k{hz~$Nl|=)Sbg4tt|Q#&P(NkP5n$8nc7N6^_DFsX+heEnzuLM{m*)*I?OqUP%p^9 ztM}<*S}r*`*+HpYHt`@Vq#gX^pzIfVL>5PMa=-VLM^qrM;VB0$Wb9HLEOf>YoH(IC z=1sWTG3V@obgRd*5bw7@Cqa7^B~<_DP7-*^LceYe)M(#-NO`P(_pS&OlpUL>gxK5V z4y^7|k2&{C+{K{yhhAeLV);~do@?recLH{b|5VCJfECC;eTusjHw4?HK6!$GlT27! z*wx?b%0W;Gaq@nKg^&nzD}xF^h!`f&JZ0(!?h6|EX%pOwrz2;B&_JARyim{d^`1`7 zO--%WxpJW2NUEaV7n3A`R^AW}%0~33ixkA?5<$N)@($%lK|H2&O(xK2a-}%>1g&zE z1S}!zuspY4x!>}`=*T^gFOK=MyhM&>#rn?m{hu-qVtFF?`Q`81r-mJ_8L*LIA)6OE z-VcLH!;wPXvnY2X_WNm;i}qI&j*)u9ugbi2(Z%6vB646$u2$hQ{BmjB!W=ZxYk`dd zX{2wyc&b{xF4^A6&%9vN)W7{H@uVLU3y(ys@H2R-Yr9Bx;Ziu!Er8KNaA{=ZQ?TAm zmC*7g>22W#mAmq63r+5Q52B9F_Tzbw|8msrRlTUNld*7F{fT>Uayot%+&_35$3|M4 zU_Vy$_>4pu@t|8W@nPovxa`i*fU zrY`b{tQWm_(j`(m_1R@xfhfpQWV`?=OSd@LIl>#S9a=}Q5*y2d)Sy3qxGUe%`I8kH z-}G|hhR$eep82#t`bZ{0`bTmy9E0=nsV@-a$%`7RxC0=iW}{69cA4#OcB3F0Y-%yc z9g@Cv#=nJU|MKNFH@$&-r!|~P*8qQ|U9dLv+4t~>haPATu6jwTAy-?Czt~(XYUXJC ztt$eTl0{x|wsk_pHh2IP8R42u)XTMxKu*l>mt??W$8?z`WkX6@OSnvE8~HA7R)4}V zZAcW3?J2v_OJKgCXJELTq5E$4xt5l&oQ|FGqrCQ~aHA;{i*JW!Z8tGd@>8OkJ?Sm$ z_wO^(3Mi_m(SAdKok9M+n0+3}0j?m#3SsiQZ|{3gFQ0Q<(cczoH?$B5#(htspipAi zm!{ojK+Pzoo4-+1lWXZx1WY{zEXW#qincN`!ZI@PQYxmVZ_GE}xo&m4Zt=wJ$Bn4% z9mI_Q@x+6uZ%p7CCELB^yAvZnXnX3ImXWGt0wYe2vNuLSK?P2X7=1k`mT$b|n*yOoO@h1RJ$WC7o9yg$XzdHE z6LX+o^2ciP$ObVBi{Z!Q16qOHfqe}|>DQ-OuYJ6zupRh#bvMuIi6R49Gy1?dMK#j8h9EBw#FlH#8GPS8 zJ<4J@}lK!6T10N1dyDJfWx81wBwh_yC$r>s?<@gCtl<>Kkdzm?u!4CA;?T-=6@4 z7&xW&Ck;{Zx;KwCxV9Ulr)Ge;U_%v7D6dP{n`AER-Or=CVRJ%Obo;?!QV<%#3qMO% zR>oq*Gn8-YBK4z^KmKqD7IkupsxkmM%tmC@)8|G>3f=V!**$PCMy1FcB$Z5o1p{_K z?6uT(Z5G-_ApQ2Yy*(EHsIjvECM?8+-eUM&5PoH;1zW73PCBqPQQs7hgB>56@j*)i zf*E~zAX-JOTkCd{CP-9?l^DgeY6X7AjR;E7@83HGpE#x8EZ8y+1(M-C4$m*T+*_w~u~DT_PQ*xJU1%+yrkKH-VLa5GLQVF9~N&nm;QHb0=D zBzLv6E>D`#B6@#Wr=+xoYHxaB=(CO%JdwhKsno#+ORTq6z^aft7sFz;1-;qeH}G7B zc1PSEwwZt11pC$&OT4+c340ygo~kfBte_F%t(0TZ{ZTW1l8Ps$&8q~824KICK5M<# zMvE{u^YbByCw_rIRg*q%^ zvk{HanQJ_EO?7L;SFqn~f^R5v2PsAL1?G%AKT8Og++RPhtjO|59_zEWjURMO%4kZz zhGs$~)qc-zQx_8v7?n;@j*mKis&B|afUE1`87iu?6m&bmI4J$cI+$DcK6-ZuMufla z6a_Ft?s{`FHogkoTmp|Gye6Mtv^fHQH-&3b2-3t}Wp4cQznt4gaBUUuG#?!r*#EMV zr{J5yMPLXEXmKriAO2qa4TGGENPfpc>{F#uTlaQ@ymbxxx~f~ZZly!#+nfWW-M;&naYXx&Z9Gt9(J;&nDDpJ)XWg?)oH)f5K4eX|!2#i40kqi;bVh_tx4xO9s&=-F$TZ$J|iv7MbA zv__(#h)s_vfW@2E@2!A&ESWFELWM%L41OwCu>EtgTf>pJkKm7uYKMk~;xydpUEs`^m~9Tr21|0vmd=It zt6+oFp}7<{@nY{tKw!Yi?JekJ$=ou{6N9Dv!vRhVYhWJ%LVz|3A`oaqBk9RC(94)8 zUYl+b`EpjuP+3c7qxSGw-c7GdiBTL}JUsS2`Llw%JFQ!*8pkCq=ybGwcJ`428jWqY z)-4Muu86iKpAvC4)TBUURD;#%%uWigKG+L|;dovmcm>sCCn%loZcp@@O_XwkhVgAq zc~*OGul3ApI9X+B;etao`k8YyrpLw@ENVoQxXDWQwx+#~xs*)=$wnGOrK-XgvW;(j#vyscEn-d?f+0un*TvwKst~xq> z_tGYk7C0|ZCpQDk)l-gEYGVSYO65W>S$}rw{3fJ{P72Nr0%?B+9<})Vf1le zwk5vCPD_+}ee9Ya7tXE4tEA5Bo9%j9T$qly&>RA|gxE_LHQ#kXa#K&}ZHNhHeaQ z&+S5LVW2&eQNP`Uw?AQ6r(uU(LwEDqk~WmOK`2=&n=9r>j#^ljv$V zZ76+yEF(ii!FA($rV3wPdG2nsL2Xb2TH*3htY26SW1INgt-`d%7Z6rI$aQ0No409VvIR9ZNQc3}of za`r3>^q+Usj7Edrge7=-YN{h+yR=H!GnB!slowK@n$GKF7S6EPl{{@v!KYHxoA15+ zrF(Unq-0=NlU5=B#rH?<=uxE?dnX z4mg{D4F0JK=#|ld7(W%;19E|_hLyWy4M(3~b6-kIN?gBg-ny1!FV}o51--XSts7-G z-e@siYk-hvC{$jQ`BL5e)pe-RL)yoBP*Wyu9V60=F`efpKq>{5_;WD}H4TP_Xq$_E zyvY+m=Ok(`wnkRQIOnhJ;a}+J?4;eDM}Hj7gTN2X7K_UG$UX}_v%_9+V$|17mX_{} zL{C@drR_Yay6?ct&;N)P6=OT>9xvwWyog~=SIja;OG|swvlN!TM*X$`_Y3VqT->xR z{ee+YSKS^U48&={$VUU|{54viR*h(o7NTSIXODuNQOp<1g70f(+@Nw`LN@sT=K8pFQa zWJx{*1VQ7OFq!4l=O4IH6(%rSW_JRDAS_e&6zOIBE}zh~TgUKYSRD(qUo5-=S_G0w zHtE84x19GjNzzF^Dl$|Gi~3x=Wb}C^-}iQ46aa5Ppg zhx=;F)_o6if#Eh8e2;vi-i_tGce{){5Kxl9H?c;^tDFhCBn-@a_PDtdW30P9f>SA| z&1Z3)L&Hy{dy7>@sT^pM%VcckpO2`);~Fi`HTyx@#M}{O|o2g{T4or-; zPbpO^c&?@c42M{O@$@7^Ytyp?=5>l!6WL28)a52lKF?7VW@F>nrm3{ZAtj2EyK|5^ zGZjwcP~TMdINSp_=7tukyKWLt)|1 z&=rQU=$yOYcE#cTpO6E)tYV>t#A|xbyk}YYS=;853z`XM$j`MFBRtOmZ4om&hqs;| zeOSt8zQ4#YRIjGIYhfq=~2KP-8{3BvIH}iTQmNh{k zlHXzFxAcrsz0S6wBKoMt`xDGJ;m2qGPxQu1;g_vrS#mW&9|J#i z#*6I?eXgoB7P#oYDX@R}jL>ASjWd=7jiXTQ@XN7Nz8$rH3`0cB$nfy}2gVj(G&SQs zyGAARUExav0Ac*A5)`P*7yckH-ZJJ^V>{>4j_BjXh}P5Y3yFra)sI(#`I}PuSpSYFh(uY+kBj@X$kvpu)YI*0K7{LJ3xzR%(-;4`zV)h1xx~0k7KLhj2Y8FJRw% z?SVE>)?M#}OU3GuV{x<~OyyH$kj?lE2CyDRbV{9NYj z&Jx~hJaf^Jvh{v6bX@zLaSi>o7Vs)Cau>H+<9_agMAT(+m@O*j&!m?X6%nqk)(Z~} zX-;=KUjt$;E@|?`_isOWJR_E{*XJ1^&(o`RQT7DyMe$nK z^~^-h1dR)ao1-;Q))q$X>bA6+iAQ51R3DITi;VT~F)(CD(erL_?O(*YG%TF06sW<1 z8>rOG*w`m9_hM;lCb#GZsLbV$KStHI=l%FD)9~-k>X<-`5%DbJH{PovU8gseDm=@J zR?>^RyMuy8Pn=^i-c9<6A>O$<&!C|$uiQaXUgPzHRar1RI(n^g*)xQ}`6>-fSz|jK zRJq4bOC(I;O6VXW6f}Gb2h`iuwK}08q^>$QS>|))9Th$@a`NpNOtjtd>ecI!P~)3# zXmfx*dG>$B}}8kVLleUz23n~XACZc{HG|t`3Iu!wXH6 zV(3Gq7M&8Q?cq^T2|FLz=hr8~EMc!av#om@sCnH757{wcP)bfoN!8KX0d_InRzAWI zrU;b&dZ^!Q9l1lNpCJ>i3y^2Eu#Zl#4E;nW_(kKPW@dzAz34;r@@fg?c3$_u-h@OH z&s9doSsXkI!c>?K7N;_Cv)#?+HbWV9Xz@png5$U5%eR|$JLwo1)pok4vlkOpOp5Hk z%dNR-|A}#&2!=7@udqsvQ-}sf6ZgbSV)TxfthTn%Ln9Fp5U+mQ#A(zI*-m(qI(3BU zc4y*U6~uWmlc87Ni@SLmhq`-sy?Nv7NpxZ}z3X?+dSmCA?4d4Zl5-GCjiAM_43m|0 ziL*1zge?WK(muamTapz;;Y&U~bWV4jG|hLN7|m|OF=Cwv|HdW*`G6zl^BM~0JA zfh}e)3m$V?ULGM1784V0Z)e|LCxP=JA6-E#4c>%!`rU6?eq#al%BJMFrO?J9VQh6em2)mE&{+zuNvIXY#=kilQ>Sgv$yQ`cg3~F0&o%-*dV=lRjTNi9L_cnAmZEY_96#JdCo1(y^ zJJ+t-s3jKWTZ2{@RgAp*+q~(HhC}{k8X>GO zJEjfSnwvQjubehk*>%53i5cBv-QkV3cphyz7OWe^J_GX%E34IPjXKKBJIf@!+wBS( zCkl!}SRU)?O{zQ?kagziJ)nU+lil6jK~uq8zVf|q**K>8jdZ-u%ihH?)dvQh)qU1i z$o3(P9Ai_>yW>kcDFpg+-AN(blBnomBBepx2Hr;vuE*A+Jz8Q$b)xv~8ljA8#WUU0 z891Q*$GYU^cvhP0NI5K%vTHtSj#R7QRwho5n?_wtESg6@87f=nmy(se;#LlWcPQGN zN)<4zrML^rgXOw;$}!I413434`|?_?MN(ICR}Ni2?YGTlZey?-?)%{pCf{W$({vmc z%0Trs(khqFx)^krL}!`|0$8PV`<;q$_wJa32A-5f4nPb)WC< zCgaxO(;E~@*xGI^7=T1;)tQIQ(sI)Rh+3!ykD`b*KVax8 z&BJ41UaX`B^%MnO+@#i2$$KX`AAiWtw_a*Xh9$u3Mwl<`wT;s-D+*y$(H&q*EZ&^? zX1t{HxCa?t{gB~x{2?u>LU55_&>C;*%+X7i;^5-RGBdl)(+2`K&(l;3qGebnh*YBQ zu|AVb*<&LsFLwfW&WLU8N6+;*v1Z|`Rd{xr>fQI0MD9JBrKC8Ut>2m{C)a)$#p6wr zCWk%dEgBdeZhyz#UPMPnQ*&r&c(^HTET_#A9A+_rPNVlWeWLOou%0wo!bTraIuZNe z_@D-=q!}KBy!!q|4>6l^>%6;6qeIEb#*hZHO-|0t9K+3<$%iUJ0o-yXcjOD5jtF}U zfrJ>;92EU#hpB&qqR`EXwHRY4TSNa_EU%W)q+kyUs@DUbqdxtwd7b}tq1yhXwIV}D zJR>1u#IX0N@&hFQAUuYE?jXXRz)La$sd+JZ%O@f>b}O&LrX^pWK}^jLOQ?thPg;q6 z?xuR!w~rp+8yvg|-%FAhsqoR?sEz&0n{vJ%XSoPkbGj2OT{e3E9oEAQEt6KToj}=K zc$Dim$ct+H2c*M5&Jv(~)BU*@RA-YUs`d+BDO!#OVo)9pXS+jv{z`59$fcNWojgS{ za-Y4{TduD_EaAv><%+648(W*oED7mU2vVe-lHE@^iRA(70rGusFfcs+SyA*aE+$Jj zbB34^3cTD7U<2xSv!7Cv^q_Blds6^%A;x(*@L^28wFMsrvS-9nQt1#M#!-AX*H^9x z<8$K*L$BT`e?n4GcDblZ8lS zSVSZlYZO8lrQXSUNhGxuIz~$&rN&pCmM6*>rOy#TN6!^GdjraYgARLv`{nd?_%3en zb2I`pau)f|v6Ff0HN|^)(ELJm^4@QNUc1D{((ltZdRq2cJy5RLdVl)O$TQ-17rpW{ zk-8xld3v`TN^pdr9KU8BRGcqD1O!rXWq3fl`KGB(IQqE$0g9dEvY;uTA67p+=5PUI`g#6}4Cf>L@1&|lm>d5SxFj*~G* zjF6O#(yxLRSRds5#3M3^$osE43otFKL>}(uUK&txGJa%i>}@n{X&*KX`%@BpeIOM{ zNN_VurB8RZj=q8BtqMWVw1u-fQKh7Rxdc0apCV-)AforLj5?r=V*j&F{ zzmg<#v*XuVK;D}LKwAQn>i|(p6@l+^-do<}oc5{H(mW7aQ}adSt|&1zoq^9-*W;4xHb4Q`+Muq7Ii(M9MH!cqSSOaB(L!!_r~s7TQaRga#@ z=r6up${zkueN2KE3XZ2zC@6o8f{V< zJyIIi+Yr8`v;lLl1rpc-awRa%j!VZ2j{4(TPg3}Pdg6tEj$@b#14B6J)FHNJ z@TKFn#6u%TW|v!v6^D@DO)7Yhc*W`^>5H7g)E~#B{k5pB0zY~C&_*HK;)%L?e>~vR zHhsT79q*-tW55#e(9L5>XRuxrrTIMaW6!_(P9M z$!APj)=S6@#(f&7RtK7(C zN8T^#jHROGexFODHEgLIC4{JguJEzk=XMv9(bAH$dJVx~ZYgy1K=0gLc7IfP`Q5?i z$i6=aVIl^O6FC#)z!4Sp^&0k@L9V7h_>2%P)z9x{g0zy|U4(<8^)~iW%g7bJ^ZDPu zKTj5N)(Dr9v>>xCp>^t1^%Eqv#;RQoPNNuL*g_z-MpWygXivIK1Z?h~cXkg010Uzb z05Qsuczp#a(~sYiGBb1b5ww^b#jk+h{ux{IPt>PPJ1_jN2(J~!j5Zex15`maIW@KCQHFXuj&4!uTiC*OALI#^hc zPfg=NN8{M5b1bk7t*`V0R)i0uew#ey8VluKfA8MXo#JBUGn2z35TP={M&@0XXo}X9 zlgnG+77YjQYT=r9<9g}##;HR`&z`JUAc%{*th1uoI#RrO%FQbhp%StE+;2KJJ`3?so*59y=MoI|7BCic$pt^qxyQUS+4~> z5w+Zrp~39v<9`ihNu1%Nwah;+ARvr-`Ree^L7V&c8`j3=at7GRya4xr^AM!9B6@k< zZhOTyY52=xV=J^l!62)qLeo}p?;NW5WM_HSX0#1;%%vAXcMe@#;Ps3~tM6gw$F+6o z@oN!e237nDnp4iPd>2_JirO6|!}nr46q{-~OCB+Ax4uYv`1qAylXbpig*$&B??46r zLh~1Hc*`UI;>G=oe#qYsUP3Php`pXm-MeV?o#)o-bcCN@?3r*i;8{SRyWJE8eHZ#= zrn1_j@Jz3*wHnS2&cFMQ9#Ps?`?X4tQ&3Wt8TYKkIPdB2ZZY%NGJ1to{{BcyyAvYTPG zHVSHLIS$Qp!Jr5zb0}EIZNe}YjRw(nPUd#cm*bqLJB*D5RN!HId1%|W~Idx+NIWMi}b7@{jP56#zs0cUlz#_Hv&u3iP8L;4r|)2WUw1CZ>;*L#xG zw}w@*8^3H93*b*zW=J-*`+CEU9sk^cZbL_Fvt(XQRyNnRZI45xlxABu+j)1w9Mw~| z_~R;x#(8pbLrg?SND5m<@vukAltIna&I}b3Uy;syQ{Z&W9h4b%4)hoD(H26uLv`Zf zTfgrPeRflDDpZCO=>oT%!`ea)9UVP%B)bqWmp)mk^#^)7#&PS%L`+ZiMjA9wv75ho znENP#LvX$KUDFr)>qxt#fY2dD9rK<4&Msl2DnQ3$-}ER)XQcB{#Hj5&pdk)YQhrO{ zl3k8HD!2a*HA5=r(H1Dic4We;*!tk^dX!o9Zw|hyBK>nw0=pR{B)JNjR>q9_-MPs* zx_z;oxHS`_u5WP)YIaovF^)^#oFN`-jgYf~7&9=umXm(;Oqd<4E-q&yuk+Oe*J}A_ z#%DOWLRG$F&`p#!O@_-Su1l70y)zpD7wxu!hT2RQM85o$!LgVOysnlvlMYQTzSlu* zDOkARJ*&)A5;&e=W{np14+&YT{Y=2Rt<&uw!8^-lS7OoGv}x1VI{pGXlFYe29`WH( z6rIb432p<{Tu=+gl;k4?j13eO-#(s^*GzzcGu-s_seWg3|rJ7oNp?Y(H0JpQuoRFYXFyP$t>H$+0`aNc6i5^%uAqP;VXn&h& z=p!K^r%BWfZX#%+=AEv_{`m1@d16=O2dQm6ZJGUQIJ&d1@*L8gG!TnQ`vBbG4Xq+j z+i!htH}p7tUMcNhQqi$g^1I*UsXXP z#y{HZ6P^}mNmSXKRX?_H;edY%k$gC_T93w&lar`OD-~(i8AcQsC8wtb#<$XTJ`}h_ zvl|?WvokW$I&aU80S4+Hm_fz>&uBX0YX zDe@f24p-2a4+Ab#-fpP1mxLACH~-&0}=* zijHQDl^PZ6NsX~s-bk{T45i%`S3>ex8yI4OZx1`nmoW>TtGP!%zH|K7GnQ#ZY5uG11RZ zW0QS1JR($Zx!6#W=f@X+nkGUbqSTCxGjp0hO&{SI|ADii`Pev>X*uilqjTV<;Xt{n zLorA)y|OGujOMQ5sA%(68ne#uWpT}U^r6Y8w%5nrqw+(wGS2b zW(ocmuXC+~^Iv!!C9A-?D=1Wo`7(JAR@GXUQMV``V}^i5Q}b|0_8e=X)^6_szsR7L zKVu@v$CUFJk$_-*Qf+Upj$Yi$Bp~r2<9?T%tpBNO-DwT03`ae@w3iQh-Jc5#lwaoM zeQ-K7#n3RD!kH~FGBOQesSLG5Uz?bJqm=NLRN1+v*d#;0+~TQjJA~K~qlKo34bb$978t=L|rt zPIHH`il9=Ca%N`(%dD&S+#Z*kk`g>0)h}E0%osWo7jIE+RnS4?6>WOY$}*J{g~+J(3~>F89{N7~ zn+Y^#*Sn1#hU?vpFW4Ri0ZH7lxYBNVW+rZ#5*@cifa(wVpIM!yx6(r{6qbQR)rnM4 z%imX*kWK^aBeRQ#vQ#${&)Qv)a9E#{BhzqN4gT);xfdDVDYuT<(NwJ#lcm%!1Z8DNpGe9v0l?LAikGD^U z;n>8)e0Nz1TB7MkVpRUqF*?pp4%$$16>yq#&j=jc{mDI(hnN&bkDR%W7 z6%*41W6IemhZ*npYZ85BCEhlKsD)cL?St zc+JM1YB(+?j0n#qs#{vFv`X^R>b8S^<~eQ|XMsam{0-~r9DZ;0Yb~IJ4{Ff};?o1# zfyYZ%|3rK$@wq3jkyIzrZOysO_mp%1HAe}h=lp^(p@;gia&p|()m2rmUET5&{gG2x z_xuYvt^bDR0cDOvMt@t=585CCmerXS;rNy=-%UB6XWd1H3J%TrCi4QM8TuH($-2C} z$1?Wx-o1_rqLmjQH0PV!X=-`0EI`8XyCC3bu-su@e;GTcZfY{EM%dXOx-wfZ5E4x3 z?(I#=Zt#A@H=>!!S^l10lH)z5-+9viq<$8(qBg6o=|cOI8nA5^#^`vP`SW%qXtcBg z!TAewp?FVpvYIBfr|JrJzOqV!mx`&!hOsboiW#*bs&4U!bF7QmDaXPn(W(CuK}DlN zMq^#mV~Oh6^DmYuPF6t6?RkOP+nhzv(a|F6M*kZiKV&&rPy<(WB|4%cEase91XrUdKs^J6`w*PR=Fy%+B@6GbWfOsekpb z%&g-*3GK*k##4}!Cm_fO34IMlbX5DED))v2jITj%S~qpFpdr&|hY`v(fPn z@CSB86+#%Pd4F=juc@jE4(T2*2T;I`kXObosd1ucY@9prni??#hxMkL=zV-^TvKG& z&1G~N+IKRYwRrbu77_N93A^44$5p~@q#WfC1I=iYZc?PpR@u5>7x)193Fbl~Y(9St zYi3l287J-`k+K7b(xFIlt$-&dUpIf0185G<0CGVcD8&WZK;FOxH;AGbfw6 zQds!{T>9LqDy3y$fdkQb?T{i^(4bP$lx8BND!`N5x)?`VzOvMS z+ge8>fj2Knys2$=tyrCRS3_}5+t9LYtE8@8&VT~Rf5f8?0D|}m>?!^j$kI}HhWYyC zi@IpMbbJdJL<|*j=1;w-v4AS2?Ga?SZszKHNzH9Jxj-biv$4iI-|K)oq97UlSWb*$NLnmbaOIZx##I;~`oLV^u66xl7JGQJ z;ycTHYXlXNZ&DRp7_2nzDd<^e1?Z{z!9bVscy?&V)cd9xlk=lJbR~6lv!X>ye%WuM zB4UOBsite!_|Z}m(*EUy1b>=glK6o=R{6L0=>vOF?Z&M9*{d6EFVyQ+Y# z{SnhQei*2|o*C+I7)&W6!%p9;nWm`xmhBgZb_rc$IXdfW?{Si;?A6!g<#`|(OHI$uAMbY6ynn$&T&EiKPQg+aW@wx< zU#4hgT)D|y6Rp+U&%cy!5>sxRLC-rTjOavmPBr-KSbN;$=8EA&m-oiMad&rK8FE{- zmry=}>JRQw#R8*TUsoUCJ>B0V$@VA1@`5d)=x3?Xsvh8R_}+SLVCX>%Dix-Df?{!_}uE$hMQF315-3cW3{Oq1r&3 zF>6x#H;$>y<0r@Dvm5=W44`akhhf~^V2cBpJ!cPS!1#v4wlZq&EGFx(;gc|3V5SY#WLLTVD9?-DM7r@hTBd7FO0^iA_M9 zdG3{C)yvL~1}(lk;`Zvks9^!N`UX0>u{QL$y#?05Ne!);1*T{W#&2PbU{5M!Yn~kj3;p{Z`Fx)0z zYX6(KM&7~FSDIr~4NKc&eyHf}i1Kr1*YtGNA_I|Sx0}%SLetEz0JY3(``}Q(e+Gxf zTquJ29p;_vc#S5%6>$z|#7qh@t1OB6MR)mkI$@wW;`%pwU?Zjfxx zauZf-MPbNq)?+T{E-8-%Lr$$FwJZP?h6rqwJ zqjbqbWui&$n60<>BXG?!WhPC=L{U;wrZX(GwKkU)+q#d?nTJ?!_T&$AHbq-3zo*aS zn@-b&WxBM~)X?4f<=XD49lUkt)pi9&^#`YSo=3Af)U$WiCadINRizZAWaI*aqY@q- zRghB{*bKE3+*ybh>j*eTB(NHX5lHeHeQ^K5$&)8pw^s=W2m);y?l*i;bC`vYR?1K! zA|e&c8Y}iKdi@Vcfz8~i97Ok2W|VC7wRET&)&!Lb8^_iY-ne@!m6^ZJ{#d77{G@kd ziDt~0iB|9>XdoF3hbr?uWtJO0JTfQO7L>YH9Ls7jEq@@U0nK0=ef$HvbbL+}@I;JbDZ+XKDlKUE+Rm{_Uz4G?kyJ zomPfUGvR|cO{PDK^~PLR*5@pZBGs6Y!#=&FDx25v4Gj&iOGa&ByREW~*)EO}tj_g0 zG=!w*n1svpInL>{|K-Ngya1fg=F;&${?*Bo8>+shl>qJ^@e4{K%bGGuVPUs!wZK|8 zgcVJGZTL6hpY@J_i0cKLu!0W?+sewy&s9~G&4p{_kyld(latF_gzs<|Z{?+U+~PxB zH+_}oTkt8_#HiC8OQS#cN7KAXF2vXP2OF1M83nB)&$*!YR4-6}DuD(@pU7&zPfK@o zeGQY+(ed#UxDjM>;3c`MOMVyy_W;%EbyM9*yd5DmwOQy%ef0nwO=|bso3^@Op=&aUwl#(dU^JN13;-Mtgg&1C`WC9hSj?O?s66mzL&h?4qs-{E9@Xdea@ z5p4HBA9O-+e19^6k1R3&|B(Z|WV$LSh|9es48@;?BN<~X0KD(NDjYWOKne2e^`Fc5 zgJc!6*@|gmDrEJeDAX#2=YOT~kjNhBUPvy+a3JO#HL`SxgPI!NpmkW|wS>6VA5h1o zYnk?O&EtPtd>yI86SW<@iRfYs9aK@J6r}ua|K&~363%Gf1PVy@toFzGZ*N67k<#(M z*n!NUG&&8nI|$=Z(9$YvH{gwMYq^*QsaO0kzSdB3Ffef$55r>?-DOZm);2{6%47!4O z1`-``2DLc)*ubv^lurv}E|<$rnGZK{C*%bK1B( z#6>>U^WRv5qTN}Z2SsNG2wUZ~-!cC5=@O_{vRe=aA=CVD036JLh30)AtNhbOE}~#r z$nUU|RW?uRCt9k-Nu%b1fNhYG(b7|VWv(!%{pz)da(c(LK=*j4_Rh8HSq%;OFY*Tl zo5jC-zwyM_Dq-P>Gke7aWWO}*@a?l=3bzETPQoEqAD#fRiH-Kh?opnaixdpFbs`aKiz@B81KsZKkr8MzRk}jbtfklW#De+e2#lw(<&f zI(QJQv%pZDIEU;bnc|MZuQAdnYajVkZ;x3J2qf@5r z^msNU@_xGNL)TjQd_62lnL7{Q7;djGZBixlrHYlGZ<+&$lT(Fw@5bxARQ z6F|O;rW)P;cX5O7g2YBq2~*h}#~W+{f7+YrFg;99SC^EWlDdkFao$@vo#tBftPp_L zzXeFGE^EV;vVg}A!0aWja55LMYuWnZ_EW7EsHzj2z>ZQuUQ5II<8u7SQJ?E=kCrc?FEn=sNE`d&!oQzmVKPfD^4$ zNc8KcBb#ecZ@V_sk7<2;aRm9@tj_!Qf(qS>F;pb*y9J&!#9yxAyAQVmm%|HY`ore} zf@ugIK635Dl8{S zi3pFh9LkqSBsl=C|H)3L{^;s7;cSlIw;Qf0`dM5gK?#Y-H?&;L_Pts1@25Oqv^wC3 z3`S14r^1LRpligy1J(*R-?!49qd4{>iD7UkNueUF6!!cr8Z zO*)j6Mi5X?P?0WOba%&~sHjK?2qG;d(%lS#fPgS`m%z~71I+LpgUc1qeLwf}#`bOR z{Ij;T$y{??=XqXd9LIkAc6AQJeWydc-Gl#u2>H)x>Hl~>```GY>l4e$e=>e%jvqgM zS5f|*9{?o)%lb;9J5^Qkj{Tik{Lj)x7}EBiR^3Q}^$sXxLsQefEE_$io;vVwpZcdn z3E}+I$cSs~Uu8+@DiQC(S!i}P7cP9JK!<%r)UP`_ zxAZZnEe8&sb54FldXQ;AAP#?At@AHmZQe`nq%W_itqIfW3$KpU)+A2<#UF}N$A=aR zD89Fz4iLvX*F^!J2tM}m^x@?pQvXKsgg}^r*4DZ8<77-2a-$UB?+tNAuzsyVVJY5r zlFqiJzoX*}MAh8#sMEu`BqN5jO4j{ z1^^0CyNwnf2JCEPgkfVrr|EjFhA}$TH>?a_8xd*iCIZ)#BY4f0^g3SJ${EPZH`oFQ&#iVh3OyCZ?xo zDB=UuxRHU;^TS6Md$R3j3oK^4GE%LKU0l~7j2kVwn+C^GkYS8e5p$grwbj3CG0z14 z!q`dOZ?b5i*|htYWD^n-E&KAY#gi2II)j{id=67o0PL}_hV)>8ML%*In+!CLrEe5M z{{c``c#l)ipn*>)eWP>{HC*DL8G-I9w2H~~ArsJK_od`A@nBWJw))ZYv9hqRunNso zJ~@Ov@|?jv>mnBy_(2|&oJ38wx3_VYjkw#aeYnl#xPsNzlsDXjkPIlTz~&`dBBJq} zw|8d6j9l-Q`Mi*#L55OFSYXR48KsVK|2L=M)K8y`myIDz{PNUfL#SG0sn8C(*)Vp6+i!V${O$*BXG6~JaaxMTkP z3Z-^Orta{wXNUb-=K9Lrx-+!n zo3nNtVcHRm4h_FlVQfYT?`pvq=)SV{e9<^ipGB|RuqM}G@KP#!iGt6^Wvfkv7|-rOVvX@YT6uJ_$p)mJY_hL` zW6+K1vXR~FT+7I)=x8xWKZis=NseqwRm}t$)!+mhDV6Q^AI?fUjek>#@uS73J1AJk zgNOeHJYtF2?Ghif zw>3gZ=RF`H44pJ|CsfBtw#`X`*Jgc0m(_BQ98Rur$-KhM{H zl&-V7%)q4Z{`zv;#)(Q~gI51(Q&d9pGx-^9a=s1Rh|GEQ~1s zL1aP+L$)V}1UXW9L;b2{c7nUpK}1OmL4jBI)qQ=vn;}Ez5{e{UHE*C}9b&Q3C>ku!o>zDi!l#iZ-5 zokpZveJ)FUr|IGc@x?ZI&H^=dq{q|`GLyr$J&(4gv>ps*iW|>`2U?M@3lA4$ui@CBBxLk+hjEjRLE~k z+hH+b($9Q`U1tY4fI_o7olMbKx=U43_M9Wj$~)s?ZdmpzadO?!<6E>x9`Owl#9~)| ziNy}N6qpa?xUS18;&HDauRd&37n2#zonE8<5^yc}#YLp*i`8@G8l$#5K zlM@ut){?dFC#Jg<#Wf+-OFTOpAcNmwNOPX|6VOpxi(F!+EU^B&ob2QJq8nH>-6=kL zPgS+had6Tf$5O5YNOn0ndCx+#{N?0#Y^u1`n7!+>-+8Q}d1RZN-rr#acI4CDJvaQk zQ)uHsYgdhJu;CN(&pR6)9&T&SLSw7OHZaksSd9_&`O`nE?#KuQ)5cV9ZZbOpEUxTG z$q@InY^I!kVzaSUBGB9d0J2;fDfPxc+mfc72|_53jOV z{~zI1{nyXA{^8>l^9-xETn|1UD12WKh%PlPi(R(g%xbVN_8CnzQwaS&Or(9wl#I!= zBt?|upjh(Rd-b>B1;+Pe8|Gs1M=1-g`$<6zS}H(<5rr{0<+NKQo~M>wl+fdeSO*Hl zyISygNaSq@2nl=l?s)(G&im=Q_5|UY3i66z)Amwz0IlGI3?M)%6xZT7LKH8?$ce?d zYwXZwNLJ(xAbtpDSj3U^aaHU-;16M-$-i1qti*Xf=1VpbLj1v*;kILQg6U4_Ixbjc z7tk&wB_|(8NOX_y4X;9l^Y(i8-JEMSRf*{g%0iekl|W2-*6)rr0W8!3L`yWd|6oM0 zv)#y{?fZh?L+oPF_+-otL4u_RXruXf`SH+@8j)Udgu3es#a>$9moF$L-ceJVYTt8z z&>RS?uRW|k>Z;TU#IbYmo;Kz-;jKVcx3b~ORgu@NGEWc5UmfIF)2vamX=cIpm)B$( zT2D7y;;OC6mS1FPTV3m4wr{HPL$^e6Y2oRK z&loJ-nH-Pw>@xvAi>>>ol9Ilmj1)nk+KkViZRg(j`VyZcGsETe7g(4Ls;evKTMm}M zR2Atuld@nHw{m&qI2#>*%Gk*)c?CJK^^PYNVtF=WXt1CvoU+IA?1JWuyAgek`!XwQ z!!q}ipY~U(6vnt`KEA%vnzC6K`ci*s)5Q)b#6I>%^ID;DcgKSjsRe)62cwIz&S*(V zNiNvT^{NduqmfZ})qYefR!4~*1wBK@Pam)4`(We+^Q83b5q1js+2*&GWR7XxDD=}k z|7wDK$7-;|0dh^Y*8~}6wgPupF2yfRCr5{@7TE5(?ZoWq&bI49pE(qVHgcjvw%_ND zwNJgDf;|fmYx;z!Y^6Lr>Wm!v@>BgpPhcjMg`zltL$iFkCd1=}rR9%SrpM5{O&Nzy z+TesVABPYV6Xvr{W?5cvoB`7%u zTb>FFQ^+JoczKP9L+r$JV>-sNl#h{d8*+nmieB!Z&#tbj(m${suPA0=Cv8Mta3~tb zJ1}4eq43wVM4o%q0R&XXV1Df25dWp8>^;}T;+&iZ zLo@5!^rEBl-6qzLiJ^QaWYv&aamoU=D>>Hq`u}RmC9)F7&o=uYU<>4=6}RAZPtML> zY3eh)GCmGS*~5p$_oA)L&9@(68ce`J%zC=U|Hz0uSFzfVXOXFclt=jzErUC?*bp>} z{YZ9Q%&ptEo9mmwEJhy-#DI3u$gl_|qe$dH)(_asnc(y;8I!e&q71tdYvQrh-r8b*kI^SrFCY>>YcxG~|Wy+blMAh}`D zBJGhCH`?&{8d3Q~k$e~bd-1Jo$;wG!-!T3uLwj1pXQs)twiKP!a@A(;p%$n4tRqlCPV)rH#W;u1(_rc>&_e1JV=C-@ns>B*?rh*WJa< zOfVv=N;T$1gc~H<$XL0!Vg&8F-d~G{m-A^PUhwUyQ-C!KK_qG{?SI!r&=f;rv&Ih;>~VHPZuXKsbZgp_wKbo-O{yqSq|-u&^aobg<=2# z&Y5SgCTxv;J+73j@YWCPUO6;3x`qa{b~4kds;j#)ad1{I$;ns|)deK1z_6zqkZp8a z>#xWi*lLrv5Z`+@?@?R~u1n@s+jH&KcCZqRsOS7v3e4XX#R91HfkK$1#H1*9*!9Z# z2P!r1d2XkeB{hF@x^A+E|5){A?M>`?DL2JWB9|%c=Iq4{bX>6*ByLAM=bH6MCAglJ zf{+G<-)`Kiz$w6%St7E@0QJFQ!3$=rj~@@oNhNP?_ZDlxm>S+6Q{@{5*eUW$IYCc_ z)eI+}yeP!ip^=?mQp}Wt!;E|W2rK9 zR^MKC>@(7g$9|`mGcp5>9ha5Cg4j7#_|KO-b7sm3fP}wm!xF1KV3d1DVj>k?l zefwVcg?IEGyRRVHX2Sd7D1)XhL;oKxYMg-t7d7fc>C4*`&%DC*dN!Pa>J))R){$-1*WgL z{Wt{HdeuNQ>OSsvQNostzL zX(z3u6uduz{w7!Z1AztP&A0Vme>;ru1e5ANE#N4oqJl1(i~C{+t*4t3tsu>jlyI5N zrQ_*evbm;#KV@@q<#txlP%J#Pt<|{Sbg^-9Hq$unx6&7z$xjGW}7T!?JON{-oyh%2^Hi{>v?`7K4AIm0tZIJBs8Rlzv!#8>-%!+k? zTDj$l(&&!?=-YFq9tj3cwY6VW9zHyQzAY!GWxc7rY$J=j6aOzZakfZeOz^klpp)3V zmHPRxwO}q*T@6dGCE88#YO?OMQw71|0fKvF*EUKm9+0L9TYaC(Z5C?am$7jl-zH{x4v}alLxD{{!QD|x)!YYU18r?6GppLG_@ECTSji_#7d_c=M>c=O0-QL6utzGO&d*>>v2e(CJt1{Yw>am*VuM0& zC^7T!sv~Fe9XFK>t^AKJSB3x7or7M!kdB+k=*ye;ke(Leg9fPZ_h7< z9WQlLlbxYr@dUM?2!BKqa1Vi{px&!4_vvqvI1emgs$Lv&gNokL-PgC}0wO8#)|eB$ zTh&{>qzs%YLc%?h>TM!d&T&M>H;}CV5H8p{X09m=7z%`P$NT`726F>91lqt z#CG4J#Lk^ICH_`ho3y*T8yGn9Z-7^l8^kfl7aU)I+Ow(m=yPjdwRFe6UEvQ4$tBA~ z6{sZ@WzC=H*v&Bsj?{&HoK!_VRdEz*aup#c`)-$kPZLA0WEWtid6&vLrRhwGv)=$exlA6 z>x33g2?nh)HilNTPPl&svbm9#Q#stgr+2T!oCn!}WZG41_wLlkUH+kRBPR%S?#<1C z^Qys<={&Kh}*w6hQ=ig23TvMI0=|7L@Mh5Yf(-~$a~vlU9#Vj~Ll%~q0qkt9iLLkY7r`;%J7IhY z&c2{A)IrYMbO*T|+!W8c=UfHHda7jK2EG)8lNW@ z@0$E+(N{oxn&u=?F&SYM0u#CB3KIo~)!w-N@kRjiLAjC?;5tjs%*qPomvpcx-3{*4-LLWj?cj4K?rzU7 zWsv5PW$<`!CkPugAqbIf<~E7t{=|=^X%|)$6v$AhA3aI?sY3;Y-RO@1Q*sB3P6Ieg zL=VE22~iZFizsZYll|@RznbwaF#@maT{smvdAURX1}F=g(?+W(WTd6n(e+}s3GQ{x zQQX4M!>|)PA=s!7eZto->qD=ke*Sy};Y=l~w&P4w(y+OEk|(qD@x*tCsMP7YzuNqq zz=@>3|MqQ;KMgg73e-+VM0EG&yO&NP5S#?uS3ekp8zv;z)YcrCwuiDLP9f)5Zy?lwsAbUsa0mqD2qz}e?nUEFX0N&DVmaA<_72ii*Y|-qEk{5j6NR6O?q^`a-yh1* zE{wLj{WJH3Fn$88F@yxAH5@aW%kUaIgMED;CMh_e%4`3#)gCDT- zwYB@19fW`1rHArn`0?#D9eHWE=ojzZ%!P#JD?v#zkkJ z%TZ(h>FM_`b~Rw1_Lrw$ulWP&eXFY2)8z}sYW?0RZUm2;|7--3=6C0F(~vPY#Ok z169>{-iseUf|^Clh%C0GkNT&XpF>K-zB*9*jUpZVe(Z_VPHH;xOfcgEJ;1^(2j%BA zzrXbx8EFY@fgP|H+4E=5Y5XqaT&Vt(^jXW^4U`)a(x3OGDfdo|wNrpF;hywE`$&aM z%JKV5_dv)|W1f*AvQ5U!&v^r@dIYX8wZ7d`6fIZ!`QsfbHAg$b6*%yL`!~S>j)EZe zsoW%~9r^VBIy2PR>1fzR6I@;K(l^ z*uPj%t(fsw7=4t9Kh@;&@V?E>SgA8!0oA72p=TJfG%UK`{ufigrxrHk`oA@W_S8-dZRHDf*%ZDEeq=a1 zFAl=@!>~p_E&MX!`)A<$Wna;C2A;l362h{0;Z&eNrKi8Oh*IFP(}rg~&KR7MRFado zW(^v~PINOl#wxidXI~~ZiY_*n1<_sEFJ4s<=QY5U?H=sm*go&AlUaDB1emYGB zEsesr-n`&_#D@>xlNf(w?rt2LB@AFM;SxE{LLXqB6?reG?6agkWB~Jw!S#T^`w!HZ z7?_Pb3CclxBhV2d@Pv-~00@a_7Cf|Dde( z81qLQ9w6wt23mhwr@@1>0C4Bo|E{nP9IaCK{U2p$=+Ba$qDtS_Pe)&3viJvE?CQ?e zey7{N+Sh>TRBfF>cxCt>%p!kN8@Tl>fkJBb{}d$#SRe_|R;z##Q44)@XRx;R1tma3S^+w8{rdcLEQB`~4wXy4 z32JM?Al{RdtOl!7dsj_~y3Hx&-}ArKYdsm>ABUL9eFb&dYeGXFkYKYGA@aV)pOM^V zX=*A`Bp%Sp2MSdEue2h8Tw^lDG&IAFk4Px236MMYTC)9jb&F(733fT0f0+1nnOZP} zq@+wgx?fTAT@YfO|D!UG@NMQlBzab1=vV*i_I-qJUOZ7r*E+rS_Wm`w(lW@%RFQ+I z@a}&!?Sq&qFg1lw(^DlzYNe)RXMZk{gtt{n`Q2HNJ$}UA)O>vE{=c9p4(=|WPiZ0_3C4IKwfwc5s(lxLWZX|^&cBf?fBv~;m_jNKten-R`Ca=k4EKzJB#qiY zb68rbEeaJZU5zoQBE8hbTVU<+DKGTXKSc_+_|68|WLI)gEIB@c>Ddqnq zqswa#J>*eYcz-B>L0mHjQ|?3?K+>O`E6^M9_C_#w)v?q>36@06=3>$zW8x6qx=deg zIpX7&4jk0yAwPKhIFv7U>5O zOO6?zu?`0gjMe#d78We@mKG)^D(`Pdt!@&Oh7!fI{=%W`>I0tJIsFUQUFY7n8M(~b zLj5u)avJqutCx%36Zq~h0~OjSH|>otB83ea&al970{>Q)0eS-D#58XaGKKDYPZl|J zcKx6tc5kXqTp4at$N+QJ$PTT6@5Igq1qFpvpf$r%3$1S+MtEq;$Rufe`%arixPVvK z#RG3Fj~{D!{^HqTqQfi*YnR69OwFsT?0j8FiAdD0TT;T6!ZZim&`dS9>BM%9QH+~{ zWhl}|-ykKKYTaR|M63MyrHhEESsl&dl?>rU-g9fII!LAc$K;ZR$MmvX?q+pDzpgNm zOQ`Lx&W++BkYyt(^~&?yYuGX?49#KV`p12Vo#*A%$M2dw z095qKtKj4z&mFoWhyk;EPxq|C7!zuzgxnuKsA^1-zDrBHHWg8m%$dgw-(7m>TCTHy z1DP@h&kdetpv+v0PL6i}eXb|l6dT{9c?)sK8s${ZZaRz*0c42fRc zSJA;3_daaBxU{^iUNEQPm$}%C78kc2H}+X2q2{%o31K0Mx52KQWel#LXnjRqi;m`F z13j3?#ob-(stfjrSy!5<(}I={7iMu0&H3lh4!8kQ;<>x zy^9W2>Ar^?Uuqqz^FPTTHX6le*4Wr22S=8%zlR9s+&ZfRYWMqXb@(iDkvt z+N;Jb=U=@Kr=m(RNm1_XoU}!!>)=8U&vHhOsy%afBYeqR|6u}c3<F-f zEI6v2i{9=p`XuqX<&dx)VZL~*OrMHX0`-f`ee86-dg*f27aZn zOHtjm`Xqqgvs|L^_4PBeYGAAwc-JZUP|Q6($Qt?}@jTOJS$D#DZ9Zx^gM=j!JNP5_ zV|+XVt|^o0&N-`aZr2XxVsX1VI`O@lYVFOvgAz_!qC(%hXG&1ofxV%3UT#$jUpc|a z1jpt8U~s+pLKVs~Q+bw2A$qG9jqH^+-2h9W(#7aS<9uDZfZHRQu45;W+l{(99u5XO zSUUeKe;cD`@7!k!Q8J;lo)r9WnbYYX}n>%GBm)T2Tc?Z;T>!i}vtGH|B>k5nklnr|k!0 z1UYIIzhG{<`ov%-#SeNvm1~q6cGg>;=1Ddftvqljv()m{*UYnA_{r$Sq2V7`sWxHv zCO%d9A4=KtxvSFBr9?C)7fE zOV)!weq1#bWM{YkvWqpvcB9#Z6unw)9{->D}Z zB_hIM6czobcqX7IyO6WA9QR2J(c-ZvDsrAzqP;1+adwS3`g&@Sf@0kzF)5!H`UV_? z6<5u%pAP1~+25OuVnBKP>Au^>95#jlSCo-4#I5}_^O^0dn{DK{C^vI71>H6GEmRCr zCoyDuo`vaPEtOk};)Q=7eR(2Bcsu`ZO@YjQUIeNX%1tb539d3g`Lci6na zy`9owJ6UXh)c=;3EgVuVMmUZ#=*Sj=SjbjcL zk+i^E8JoGJ+#;XAQo0_jm;jD*ksATcW)aLhJ$X!I3}Uv8>5U8Ji}(#D-?FXYuyHYo z|}5?Y78C8N?ngh!2%?CMm{!&M`&ntOgYM zkTqtzG-N%NN_4Qedd_ooO0O&3?80#WB0VxEKcA21lHQkHvoi>5N#AG%A$xNmE(YB- zw=}`dFVYt_GoHYzGB!wYdw(}v{d$zXNY_NzrXi_YQv}?QJy3r533NHD}LIIEGH! zpC{EQic_9dGmF}Q?KVULZX7Iv8iuWm0mXCT5ELJ9E#W->s4s*il*&9LB-C+B7&E}d zr5@HME)C`z-7FFMOHy8!r4STNo z&6_fBXs=10Fze1R+e@2BN)pFmx#%ildFl|3HjGsp@-v0jUv^2YR_^U!LEi|FtAxO7 z&i8y6YK?hWqjF~nLkDw?DU28~fL6Y5IGKSKrYTp)Skpc%PF9|k`17H^@Oinl`_l=7 zJ7E0Bi$+Z!OmNkcDN2k-iH_7uaZ7FLrYB;4Z@3XZZy)&}KE*qu7Mv&Ze>+R%0^+a4 zI{W405g#HHqlLn+UBAT7Sb`(h>$9zPaVdzoi#xLYDwye=LZql2zuULKhm=vIM@Dk4 z2oApT_AV9AeM-m**W2oLKP_C-hK;ku^7I$v>W&(A88VFE+)uMrvs?Vg!r|9D;3!28wOD$m&Vx#IEr(8n%9X zZUTh-YpwV1xAqk{7G-97Pue+ca5h_ykS}bRCtvnTz8iu6o{KIlD9}ifm60a6ES=Du z6MnQBl2>5&l#>0uxYf`Asjkvwrdfm^5kDe1tyjroEa4V19erie+?YSDS37+qC(iM) z>cbExe(&wT#AHo_dakan4i-n-`D+qJ1GJB0cB_@@>v4ps2$Yn?EEBmca?P0N;5X9? zqHa*YV7XYI6Ghj5y`X{?avlf0q9=lwl^#CqSSM-z`lY$3?C)I-4;^OV?i9?+Qul_6 zoQ_Ug$8y1rgp~9H@AQfFIMSFE+~Odz{jNN2ceeux-ReiQDsATxB5%YvP@Sz< z2r&i8EyW!a$mM${@gDpF-HNke;qS1OPK(53#Ep%OniZo45y>}i-u&iaXJ_Z&pgK)K zUY?4GRJxae#K-3>Hv5*3N1{E|bneBeTK671ep0!wd40~DX#Ii%zi&&{y_yS_Fz+!| zS>ndqt=RE~KC5A>4;`AQVJi(5OZY7# zaZ&rFtWn;&uCVHX0@%x(&Uno&6Q43mMeFZvX=wH5kSDam?Mz+R&+OrGu&U(ScFuAe zz>epDP}H5dEUBdkd5U4jes02%%CqxxH+p=6Uw|(KLdl1%uv1crg@U`s0p8`dqwR#l zrX<%EW_wOeW$U3_##?J^i6WB6DaXm`8(eqho$%X*C^ke(uns=Kbfcx^dx96|grH3Y zb{%~kx4H5_?O|Ya=)&aWa4*S>6nDh>SHePlBR+pDlGTa+&~@_1S9B=P@b~Pn-{wiv zMBT7_;2#hm4>;z#x9P;pr@n{tTsGK7qj12TSoq%9s1!*U`7hi;i4l>L&CFwJwD#g| znzMO|gfovbX@I4rHY2~Kt18y^Jd0hNMIN)m?{37D?14LI$2s@$*1F3arY6B|q()+o z9hBE)HTebjdEK)C<`kT~G1t3V8)+~$0=&pMVpIkb5s4w{!IH;l4Zelh?c=E}8obN3)`0 zff{z`!MUKQ#OqBkb6+j|?;p7Wvh3A9r1F$Mpbucio}Qd!+SBkPw}?;s?v9Du+A7*0 zyBjWYd-|HIhf_N>DY7cUN`spEG%%dEKlEuNx(#WSmwYU{$j`XZEWBX82hi}DRkUd7 z?^xgIX_FI(qHjNTC&bH?RtAxjI_q2N#kYUd^CfcM|6(wm{|=nhc`q|N7*?x4hVI;1$NVmn7{a-GiT1LWXw{3m5ocDd zAJ}C?3fHYz`E&$JPc(;%VqZfcx1Z4c)J{%~qLGOROI8++x5#QqDZP(+2M>9l>1JVP z4{`IWm8Jack=xF;;(I#$v*WK`+3vx?!F{vBE%B%$o=-Kk5Ef}ty3k9jg?kUz*H0>n z@1&inz@-Z#cjNc6*XV9NhRq2Q*BDb>UG?!|{O45IwjfF_YnODjHVyCnZXf(~-9Ef& zTOES|*Je-Y6XNbmI|9Rb9o?IwZ{M96*9~Vj2)|*N>rzUotD&QD#w^ zOmaoEK%`@c*_M)&EK9h6j^Qfse64q?D;r~L^sIcozyOYady8>C`d@f>xb#PGhhXb)(hGC(i%$>Pv^;(w z?sV>iLC(6p{JpGJT$j)vr?kIs>OTbgcfKo>0liY(Lncs_N{W`01$e$M$^ zEtpu2YiMjtj7obS5w^ZVMjxUw>$SF4S?MK=a@YhfLID2IJHQUvO~=wy5Zu)oWf|mt z7@?fEK#!H>(v+9iA)t~TQU!0`rmx42kh|`5idO!La>UT%&M)3R3%gx~QM=D1g{Y(5 zSC+lJ6nrTA3p{p!hG;jpWi$J#?cGxO&Z4H{YgHI? zu6=jL;0eT<`obI8uvMeLX9Gc3e7OYsXF9EL_*YEn$+w0Ulf`k%PqC|s?B$(CwsvP% zdt*{=-1zc9t? zOAWmUQ4Z(g0jkFYX*)swM|U+hF>$?PS_z^dz3S?xPMw+|LE`#{bu}ugwpmCS`mdK& zJRF2*hj}r=xnk(`D^Xm9zjXMX$4os{d$R6Ijj*{%AI(v^46Lqpw!3w0;*Kc2%UU+r zycNa_;krsBcg|EAcoBA~9?w;t9Q~B`X&~EfGNe8@k^MPmUvS&iik)aTfh=DA#G1nINl?KV(=XnS-Sgb? zK5*!0LSj-%dt$^oc;&e+V3AN40ynvK?luK};%%MSo;!%>2BJbjLV}~x6}VVgx4U`J z7ClATxl9YaxtmFvp}09F@$l=9BkhrzwIw|jdUeBlc*O`EtD5;b1RRjqR5SWeR(nnh z_>E_;$nEj?Ua5+b%j41IZn_YJf$h&3N*ia7loI64gd!)1B;8)HA~d9%{HErwNCdq% zkC!m!2Z}Lx!bVPR&#ST$SkIseVTrEGP-NErh}s#{lkxs>lnjR=&HTjcvNA3%ww|Dp zs$D#@o{ZlNpsTp$r66G4Qn}SrG@8@4Yv(eE3cZSO=JtF%FBtP9s7g|bCzm_XdbekJ z!RG=4Lkv9a0TYu>K0er)UP(;UMla&^5QWk`m6fq;c^#jojK%$uiV_m0s<0V5y;0+^ zWP3$~5laNDbn$p`3@{kX`FVRBf%jAARlx=5@FPZuO=Sa&fvu9rd+nH|q=?WBMFr29 z0OZWo9X4oz0-N?yV#@F6Dfgv}q=|`Yp8#4Fe+YN35l#0yJkpX4uD8#)D=_J_cg?H+ zqPd=4HN^eSI@y?e2v#=19=X{X8ImnPx^edBHev1J>B^;J~Qa*A*#P}owj zh+iBmv!4!uu#Vyf{nbx8nZqzMBsmTD7uf{=5txOq#FAh3`oTgB7d)nNW@5xY}OMsMx-CGbh7Df9GfX*@pCdejmyYcIGdw$NtqP7qos!1R&kiEI`qdBK(~~L(win_0s*69b z@AUKf7Y+=(152{_R_5nkUa^(2zdoj#a&{>!I|0=eS3Q;;7k|I|IkZSxzV z#TOzHh?c@Y#KP;=N1sxQoh8W6(q*=q0vc*S68yfT>rya%Gbi$^H@Rh@&DJOsUlQ6( z!YYo?W-(F+w@!afZ9GZjeTG-#u9kaFrVQi>TBy)TNmaP z@Xl&#K7A_HiNu`0bp85weeV33b-Dh4%mWDP7Xg`!moKw3X2kTxq_VP=x7<^WcSb0h zJtBwJ6>X^g*}CzB)*U(G9@I|6Hbt*3;YGV`T;UmhMX{y)Uh~B9fR`r%-n^A`Fi;0s%_!ANz@Pwd*G65MAT^*M>>V0mLZmK6ord(y$O+IrWE5!hWy@T`6@*C;I*?b72 z;|U!&EPb#?%(h5LT}4Y%=`1xh{kbzAJ6DbzL}*E6b_?)>5LRVY^TSztGI$4Cq_%Hr zF@jXW^%&u&w}twA`~#(88dgpho8Wd6{nA^FJ@_gr#46xT+qnASjZFEMN4$9j1=MTl zCuk+%w~KBv`0c-N@`MOjWkevt@pVPMv?cug65^`?q7w7w`Z2rH=bbr86d#wLSo5fb&Eq6tsK2S8hiSu$?{pCNuLXn zs`S^sE?5z!7oW9Pgr+NzAhgEXZ6WPPcie;ShB?_O#p?`z?w&mxeE$HVl2fcggGXFj zB39_eM*t|<8>=~+*xZ-53m(1w66Q?GStYmuguUNk5ams|J@uA~A3M#lSCGfs-Sv>K zqdWW!5lknOTU(~^Pm)y^cX1A{i+4050z)3CxW>h0$Sji(rUvx#F5zA{U+rH;@2O;)5bDJ92}J7sPTp`w=5`KixgUIa>OMW8 z)g+v@SfQ;wd{8J(Rv`rri1cVNi^ygQzysfUS!^w)Smn2E_3+M96sN?rGGQw3cYXx# z24ZkOk-K(5?AkKU-J|K~)$Oh>VrdtdLwedUd;@P}a&a~U$6hixE^#gUm7LW@Xz+oC zYG_Er6z6_Np^y2#Y%A~+H{_*~_a(k71Cxma84q>S4Oz*65Xi)weiNc2Nq7rmCgEox zhD{iv62q~r#?@7qI&GEJQw+{?!y@wGaMb755Ata#=&xM3Z6i$RszPVN7ZHvZ2##9Y zF9Nfy9aEr zw#|${6uk>5UM!X4fM_9`r7T=`?W0ZrbY&&y{tYq2E_V`EB%qs7&+gCZ832f?3Or+9 zf?&`sEJ)g4X1aX|-QMGS599;e2$UBhAD~jkyi|lWpxKx=k5?eYfRApLpU}CPvo(ay zog<`>5o-sib^SD23bmb1z-rYxV4FRr8Q;okc@u7gu(}d%MCX|)w9nBk&)(%G6Giwl zeQq5Rsn9oRZod(h)7U~nt7lOX-dp&q?QJdgd~JKU+|aVYxoy^~#YYJ5#3@%6=puyM zwZptH9{%_^A18Db0zvem9V(B0#sYr+)5w*7ZWzx0-MmcaDPdgx`uw`c|MeI1PQWEZ zbR;F+^>6C$Ov3>uBI3gt7y@@5J-Vl1`udDQjNo8fTVG9NiI*3|NoF)PH|GZX*CPqP z>=i9VXwO)(qW>yAfN>W9S!36UX{6ladIy1V494NwWH4%PK7>UnAq%!`fQ-1aKRvDy z?YD=Agt|*j??7%S(g9zRkZ>6Wl_IdIQz*E3jXZfC+Q#N=XuX((MNYk$;|>598s!*=-al%$m8!9!2s(co;m-?WZACDgs#V_Y~>zJ9CScq4zcYE+$zMN1{u;3?vDmn8}L^_)JxnBgocG11a zpdfCWsx5F}*ei$&3d-~B11-lo5EH(ebUOiYkeSEu4h^4eN8kl@Wo2a$ zy!U3Wt^(GBb7HSH-}mCBOZ|$vxUT-r&Q7_o%lsT#S@(w6L^;wk;_%;o#McGT(TKT! z6*lV%4GU`|F=~!9*<-K!ct`)?cs?;D?63b#QvY#;ASD-G=B9Iz27lcY8>3vDu5DYC z(|{$95wN#Q)@k+|dr4$}A?1AS@9()LfQr8QxXhqo>VEt<{yUx1?k*)+jF3Zvq31Lf zhgC#geExoFijec*50DGpWD>`}J>$6+AETy77VxrYuXOYFkIFCJZMnNhBtAGMCI&Na zS&U7B6Z0N^nMp%a^DO1IqzMaA%Lj{KyxnpZg7G#{D5|2xly=iY3X1 z_75HIHoZQ}#USKf6qkJs@@Kv2g%FN+TSjpWAomXKY%CUfHZXyST0?5)pnH2;MCeeF zUY-AZ%zT!}6W)-gD3`KyPAI}Ld5Y_HRh(hGI;bc95QdUh(WCitog z4Ii>EiNTFNt~r~N>m#y?Mjj?Q@-Flp@LFctjT9QcJ~>3B<1~2s_VG;TW${h-O*~YO zYKR-mb}2#;LMjHT)sC!kF&^^7HTql;V1GUl8v0_Jh^3>eQ$xJ<$s)|B7cOTDIW5q# zj8mR5?^_#!*#cgu>KCNALA?OnW(}pVTi1)bi?s{AdRPH|e#eE#-Z1yfuL)n7Vw^>I zFYDL&qhs9g*a5rA-8@gKaH`?bJ)Ku~#qq6s>=2%Q@q(z|NbrmSNT|{#EX4;4EUIho zN>BRUVZ0*7=r~t&O;yJQGpEiY`{tbE=HO<-gVfc`;i7AdLVYW1aK^lSM;wWNnviFq zqpkz)SnvthU(GA$+%}P_+aZckBI}jj;>;XuN=)=(_ReFqPJ1iK$+d5&R^vfNkltu1 zaJw-39RYO(&GL<&d%PR9jcL=gOi%k1@(L`tvSpFv=gv8gPqm_U*R7(;$FzY(KfgF& zw_%=P(BR9(vDcJ|6g1jM6SOlF-&{mOO|yzk9~u2_g+6iEuR9rQU4;}ZqBK{} zdnjm*Zg@it73A&t`1n4z53A>HV1QqN?==!~8(lfembOR7XRGgYx{^$6$x9!p7$dgo z?L*%-yFT+ZXWl^8pWa0eV+P^LLMTekG%_FV$Y!>ycId9h^{vk`xQt(G{965br8SfT zEw;BfEV}*aau7$a?sA)aV>+-LDVdIs*iEkVk*)7HF?}Q9^j$Ou*q5~imsJv?YAbq= z?`_Fxrsn2bgJX&X1qFtN`t0wKeof>C+gzT@joaJXQ&UsAdn==YrB28lO_-PS9UR1W zdaJeHjF*jKRMT=%l0xua?9{Qbr9uqAQqwVY6s${<{OS2V7bjv0QEmf4IOTd2_kH>x zD*XcaijKSTRw0(#$$RT}ZajYML#5?|A~Y6k)Z%0h20ptWzoB|1PVQjn=!0q>vUfWH zg_imHNM+@B%5EE;kE0)}`8O%i`f}g6abw20S+l_YDz#5p)OgU9JUCFoS!jRvgkT1t zQ_v0!40>VDGF-fiiwjdfC)@Rm`L<&I72*^0$kE$1B68#7G*)FdTt6)q;rOwepy1Jd zeE%_}l`A-HZIGLpnh979u|IE(mt|9k5Y&4yz<}Q_zS|YE`|a(e(B6^)yKeAwsz~*v zio}w_QCt3`&}pyBB>Bj^YA;L{B8rorQRM{Y?Adt+4lV&ECoozuPZFjup#C$79N2a$ zzV#E~roFoNcZrYar_>e{BSm_9NsRhs^b{;2(#s)bl1v)0i#uAe`E?PQ*=np(zFZ6H zB9)Sk?e+F(_GS#G-b2egEg&FZG!l;s##Cfwwfml-ICDnBaJFwq)U7o7OFhg5Et>8g z9#^KAb%|m(goxGrO-wDtTpDQEf7koiFHYSaO4HmZY{WB|&8){AE;gL6d1AO^HsdI2 zuX5>e^}&M&_m}7;N3BBy;pA;I;dbLM5aOL^nzts3LSpg`BZ|NHqa6)Nn%@KKoChst<&pmE+ox~W^uAACL}o8~LGSx>E8>5ojE{SQuq<@Y z)ptN&?zTyN@qiudIr_?t&=9W^JPvn?@Y>vO*x0`^r4E$2;X;d-EG#U}x^Z&8;o^efe-?}J>%8Ll7h)B0kM4Eu~rlLp@ zkQ%8$dhazU~s{OfT&E=4^3tJ;OPNPg=N|8N#D>c1PEM+46?aZgwyQn!HNR8^V-muH?k>#;|Kt z!*;X+BmpC%`GAvEDM96bA~>fXFPyEY{0}s8cuQu$wLpTFnB}UaM&@#kO=a9krlsEt&T|0juZ^%3FJK5Ovf|<_)xqPa5t54%Hs2qBYvx z{Y{WXqALNtGQ^d2{^}EEXMqd#hvSAdBW_aO*~`q!J~3^ZZ}juy0xiOvHv5yr+$UTe zcIr?^16E~|ZU@`3yIWNcTW?avERU2N1`A9c4cO3EV55zIJp%kfUxorMV8^QsJOd71 zDi8&>Ssm^QKu|lgDyLenUq3i)eeNc` zsBQV`m46>-nl)GRt@e@(8n+7{e|zT(%-V>=L-M)1ZI%l5^T21>=H&a6iJyt=ybxX2 z+t)jY(BicmUdIw6kcT3BoXELBchIchGs|iI;`p9$mF2rSrS!VLGF!PGfU)u@n7WJB zz=aWbt^j-m|Fp)#A&^K&ePjKETT|i+gFMh3om7}W*uA;M#Bz^QPS^Y;ZVTSQvGYAm zUKz!SFLwf=$FhhaG9VIY2|0mM+6bF;F7J}F1Tjdweed?D-DN@}MR4Wcvxuw;4*xuY zG+x~L4t}f}-DP%@G2qE`hlYaQ#c&gP7k>jKDV`3S9GKN&FO9G}8fY&Au-nr|oyMU) zdAM7D0zC_5o@60xTo2GDY3nOC>*UNMdr$2pAkRCqy@w7jiq2cTK~BwXH$h(YcP;tZ3g>HE06D7 zgf})$eQgebSr48yc2J0_o4gCqS($DngLfb95=lh|;>(4Gzh=UR7qKikp3wQR#9E4t z-|$f-`aDnRvHlaR=1JrYsRgJ*2`nC{|GM7_MK_yvfUS4bs!dr%<#bY#?06$f!qC{z zv_!K_GW-DNOoQ-1pC{INbqtNZ0J1M1&fi`!Aivll;8%hhvfo)}03rA-kr)U0J$7kO zheWGE)E*#zk|aOvjRpQyjZxXe!^Hl}zIRb~P&K9Eylg5f?0LEH!wp5RN{b_2 zfvlcR>khrPC~yj#3Uu`d>IA#TZP3_1G&BhtrNd&OiJFX_9q`FFOdk(dPbcIBCIsC! zQ;8`#LDAY4N2fP!V38$@9l;erv#*0oX%R3GQ?;h$=pGNQCA;>*0=5-Tw=*PkA9;h^ z^D_pIN(sl{0Ug@uIe~{hU_CwTkKj#LM9sR714SNcxJ(gypgej=cj3uouNHR?$r=#L zM>csMn(BoL6#xqx7ZXEy`*vt(Xg=r#4T0o&958stEXw6oJx$k=zzk5d5t?XMLZ*PS zUaM*q&cH8UGaUeYY|(F9#7vf>HOGq?$wJOY6*wbG?}BU@A6^{l*#3&SZ}Q}%>u}Zk z_w470O&d*f&CYJxMV08z>EQSYRBP_@q03~joJp&ok)S0{T$>I*XT9Xw+%!in(GOM!o2N0B3YG$T% zH~b=Wlli^mRIL#SDT{6An;_ z<4N_aNGfKb%G*v<2$)FHsc2}4swC)kloO`5zGpzMJUj()^pwe zwC}|(#H>nToq+6Qef@h~FbT<-A=ghLu8hmx+qdDRw*nIwQ=z3gUhpbW1Cy6n_3k#Qk z5;WXFOL2siUk|Hmz23l)>OO89*+zfwc*a_UaHs<;_FA=U zI9y`1KxL6zV7$24+kR8U`$)wf4J`m<9(biX<$7LH3%+t9*KjV`7h17w@SS*o|NR>_ zvW*~`X=+1$SDS1Q4bO=>3=hA7yDFZZ#Mu@IejA%zM)TTxkFK;?a&A~~|HIC?jD9@N zYu=r{s)suR?>BQ72o6AtuGIQ^0jRg<(5en4=S=|tfi_2P@6*i8=H$oTMjlwl{!Vk_W0C&&lJ-D!0X6RuwQ_k6Y%Ikh&S{cL3Zc`qZZ3DR^Ek-0goOdvyD%`OhwB z2EYmBj*gB8-ZMR_AjE-#fSNl82VHLhw1_}cGwv1h)}I(*9Ura~DDcmGLl7YVAii=V zobeIs88*3HsT*{LO%~Gt)RsYyhgvI+%bEMn1z+$DW1Np3J?D5VAP~z=Ip;(S;K^@8 zJNh`tb{Ei~tsB@V)#nBKPNATzE4QqY!a6W2>UjusGL#lftW{TiMpF=kV+*6Fd zJcDkjm{YQHwyRqV!wZv9-p`Z+k`-`6YjAW-&_31J1#P|I(<;mP^%c^2gd8`@#`F|8 zM1Jp_mXL8UkbL3xS#!|*_(p_s-Mt^49$@IS<=)G=8ah5h-6RrNiVP^6o=?A=2DuK- zTb+udr#N)j+ap07NuO7tH~H8EwMNG_8H_5wM{)I-{nj4PkRr{`j3vjf5 z8uAPbs6!ypRKfHyicH{*!Qxn&z})OUr*#nF)}LAnr$^$lySvu`>59Q`1tf=`F2cq# z6P}wpSoWALDF6rL-}S^%4L+RR;^0Mi#yiTWM#nVEV-~nPC#i!6Au|}v3>?gOvXmCn zewwRNk`@;5r<2*+*Kw~;Zo3Ef-i6P=5LY5ki@-53nF)b=czQ_wx-VIG4}?Bo zd@&a+M_eX@IOwxtq0BKrj+b_FK~@?!j_X*So`Lgi^MbFP(EdEv1Ob1# zapTt18bYPrOwa0>vh4ZfJ+s1iA?NFk`{~`cJq1MO8aCaKXbM2FvH{%XQ;R8>DA8Ja zuR$xEYAFkA!KQlV$k-szqvQ(i&he5uaQMt05kR>q_1KwLl$6Xpn-VHS;rY=ht7IH5gYoq3y*k+&b~qMEbQ6F2Lw2!oE0S$jD(8^m0!)3S7(2Az3u1o|1E9(uSEF= z+*3V?0UFI-WtCLhgZ9PfX!Qo(KNl`EhS0!mtj3F65DOk)sLl>#Aa0%2G8vkfh;404 zq~*_6(rj*S-t1ccciFGtlrv}P2}9IBywl&`)9q&gRv;j#5xLqL5C{~&s7pHn;QgE( zrgbBI7Ym{=Uc0)+;D!b!ZKLQ1MMx#l3Z3=W5jcm$wOlN>oL_#Kq&|ML-!m3rfz&E^P?J zducn%2_ujIN}Qd|9x#btoSDn7SS|7J$KYV>{J$8 zZZmnZxf$S3fADkK0ueQ&%Cb7?T`P>A@HKMZpM@U4Kt{3QpdZNIe@dHNTwk&N&-s80 zM0%%(DEH)>psDXdN4(2k*;=9KW4q~nnmp9WV#aC7(Ok?wBR_G*iTa>ZP}rTZ3WwBC z=<9s5K6j9*eEIT4T*Y{o5V74!O6c-BE2spktm>%C;s5a?=T~oTw<8QxoW0^L>*KQG z$Nd7*-%IlbH*?nW^SvbwEw!~RU%Z$rT^R+XwY5}LBfmyE9)~jtNjg~9n3?rpe+=nr z4V^Xgw7yW@z|!iKoc=EDr$!fpcp*;LM>Ey zNc3B%$avEEFww-pVZeJ*Wdhvy5=2+`F8a@!_o=(f7?$JjIqL&iR|B`q>0ZWBHPFhEa)XdeYmQ`)+^{=CJdG{F_b?t9B>v;)1pIkz5b22U$XMHC#@|DC3kb$%~+>sPMs z5rSuT0SP@zx0?au5zq%pW>xZPS-xuj@q)NdS!HfK<;N_+SKgZN0QIqEy+{A?f{Agv zhiwHh=@oVDCJ+J@%OdPqZZqa`$A;@U;!0H zK_7B@%3XiYk$O6`OpjV?F@FSPB|>xO?@9qX-$C6x4hB!K+npUgDQCVyn+|BwDsN>4 zB3aPOrg!TW=bJlw$t%Oy=9G|gw*ahcWou+7EwFhe4<9@L`3uX-qzu8qpOv&ty1%`% z_x{s8wM(|>i2si*6FeJ7pUqAYi&?K05~5Gxy7%;A5e5BzO7@L0}q z%fVbIRM)z*O&nW46L^a=U;C;cv+(>B^hlJIwV=)fdw95b;R5HxkrPy5`_x>2w4-t-XT*NEg)I$SozX@7QUu z&l5;f|8^xgq2euOzQ9WObbiDop2jsj$;)Gh=ViZ!`O=8j0SN;A=}OAGr}GIGa&i{B zy1IILPo6#d1z>ilPQ~V;_mNIISHhZ+MO81d|*1d7}5aETQE-@~FHuArf*&$Vcqp(k;+@5I=~Cg2|pxPSCFA#2Ib$r1LN{?KBm40{EdK>ds883eyg8ZW^P z$f?f_La{R`nO<6D=?KlNS{dz}aapaC?6 zTtnPqfA_bGRCgx;7s;ENneoK7r#!(p;@1RSAi?`XB3>g7JXcm}>G0arvvK_$_D2HT zi>FVEsij%X@IW5%nOv@_w)R>{_t=_gjd7)Ju?Pc4LfG!YJIaQ8X0?_25@QD+wlId`*}I)X_k z=9tVi;5%}!WJv-)?QY=YfE+}eK;KGqtjsu;sq(NjAU^(YeYGeJWfxe)|3{HFaQI8q zhvK=;Rjg-M{k?HM78x})>fSYcK<1jh!c(g$fy(^qS^)y(^RVfyhXS5YqKAhkA9V}% z0GOZL44SKch0{Og=cUf3u}{sJBlssGE3u}MXbg^)V^&NQbJRnV5 zGKa(2+JdCKARsFKk1(x9wsMB8Ex^Je`e9-~_VjO~oXS60{j;aa7uvHSMERPb%F(!5gRHvcuy7xN*~aKE|7jDV10HgUAd z!o+1h=q6GwH%@Z3b-e6IR4PHLu`1Rr4ba%EOx{ReXE{0WooWYfGWs-Jb5wb8|^*c;9Fe5DQ|n zcod#(>q-WFm#;o(ZyPVdI5ZShq;de@OvG~bPkkz*w~mjIzS+jdF7ff~@~|fQA^Bu6 z0nvM#-8EdD3F29`1J(1cxSb=(?_$1yoE%NJ*ED677?Nb|2C{IOoJEo3>Q!7NS85)| zrd`EI-5V6-Y=M(w!~Gpt0)h)7N0or_J6$A>)-Y<1nd;o%V}KlBxnMZa&` zUB4byn6>{3?Pr|jNM}v*5t2F_q*IM1D=o9VYfPA>b@0o<>`K_K?tsN zl)=ojL)Z4oq&$qhOCo8Z95i6~7IF`NxkJ}$@e;<{rW)&LlywaG>tX2^ce z$x&St3E;Y^;jP2XT>#N7dc7FWxnM<)C;C!qFx2Z<js5R}vmIfgZYd%5k^YhUH>UsG|6C=Gp@P40NwF_MJTf#}@rIcUF2FHZ;v0ZAy zD!t)agOy%3J5xu-4F-{;r0%0lo%4=T2=>EKn>-+J$b-Wdwdyb>z>s_EcnTZ9glx9J zYgyUpAyEAmpJ3C*$h<>*^)E|v^M|Obd6Bq{;rHg#3&YkYnscifJp%Hd`}e*0o_A$B zu4FnI^?c2Ti069j`r0EwmTa@>qnoqID!}6#1;I)>+3lORX&L9Li%gLF`n^6nf=@10 z&aVx`B;%~3E&3k5W%5&^6O>L|D0K>ET}g(BEB+Rroo#oD&8_6hS|6~@{23f zg!gGs&T@Ud*Y~#|;e%r!DyqUnkz#g%jgx7Ohtb{im9~ee^w*!?xY#&=`(N=|RTTmm zZ78~Ym6nz!`5Gl9VyG-S@@6s@JNrY&4MLDVK=;V@wWUXOb>NYfj*jQipDAKaBx!K< z=I@-lQ`f`r@$okgD2$B!$yO}PRs|E2`w`yS&)#=DmxQ1Ee#bS^1rSQ%2fXmCtc}@? z6b%g_u!36x8AM>^g+D}r)Mer^69+Oq-FR(5WMof6q${~fED+3{fpaFwIA%U_2k zV>WY{gqYOCzvkR*c*%-&ZJst-PcbQ`bEPh9z93@3M(utDoKSpRix=MT6BvOl{|Dp8{9qr1?7mT@u^i@siSb zb8bd4zW{@{;}bKHm%QApLig^0qU@d)nC}FKk=D{O@__-L)n28i_#0U`?kW>I4{R;f zxYcC79(2@4%`Pv0e|!D<&d!bzQv>0i_ggeV1g3ASuZ+sf9NygQeScK_-k}2Kt7`}9 zCjE&l#xI1ol8#PY-4vQ3zhNXN;yz#8At_e2oV7@BKjlZiz2hrORn;Ijee=o=Gd1Q2 zv(t%jew*1hL7@24TZbplRf{9%zNJ*>sEW^?c)DMOIXFSo27bOS6NA_Z<#)){%d95f zE6DM*x_0gM*C;X7E1(urNgk5?#vv0U)4*VVg1B3?$YE7PrMLEit&Ry7`c6@y|BI&j z4;TIW2ZmbG?YEnME*QjBOP+04z@X{4cg!T@Ta`I@!%jloETeCK|#@3>U+TvUqjMA%g9>-6?9i<{{0|y zd^jhOi~T{3ZOt*8AZU#vsnw_(hq44~^gKtv*=mav@%*#8a&oI|WGs{3T%rhOq|Q>! zL%;X;&)7l|IbrCnR8`VaIk~D6zbdy^7@u-bVs!Ro(1vkOGq};1Kn0`KU?x_H(h|Hj za}RVcy#0psuMMJSO!oZlg0*cG|_MpV?Xx6atSQTUU zwI{i4iWd|Z1Wi}fh*SFpVbg!?$UBq7OWux;UPfBLqSGu~2bbZF_|Ulu!mHFdUlDoz zg;tnbi-DG>Hy7ut>`#8po@7Ch((~6UBphu|n;4L5*<`n9Z`cnUSsZGV3^aUFGT2=~ zBc0j^1Nu_Ac^8(jzL$+O(=%=OoPX7aOpH1n^ncz}3_C&(Z;)Ft^Y;rl4x?^S(~Da* zE^ij{m?Z_%TCHk_cGkBqFGF-a-nIk_yexHk8`xi59CLD<;6y$&wZrK)hq2KB0vNlE zzH~BL?}k|&ky7tcEBN%46X8=02Sm6L(2Apw1}{l%PS$nY4@re1`1QKS*bqv*VfS9h zK-!`9$A|HQiEU!=^7jOz9(yrjY$jhVi(g#A_PTvn2;-1dzN9SZHvN_Tlki4Bi;5AA z;7Bw_{;eA~DrXzD7#+Ty#K$FZ(sZ35-GxWzo4%m*f2FcgcQgbhr=`VK8KerB^d0aG zKo$L^_d+d0`4wXnICGOH2MSX>-EJi|i#d!4<1Z)etn#-UA988hr>MJgQ@1Jzc}+*| z@#kS|W6E6612%7j)n+vc@59LtGg3+ExF5RzSr4|DFgK6UfY9b*7^zDC#0%_uR@_lW z22t~_rjSjPwA8$c6_@K(>b=kJzN)qqx%~Ei^yxyy202R>5zCeXFAs$CG{k8Si5y7r z2(FU~Doj$=(P3(Nv=|>T(q1SgmzOC*^!shyOW^82t}xV;^|UM_2zHLv!%~>!%8vVT z?Iqlnf)Mn#!+9-dGf6BaI5}8L-2&7x0&8)X!nu`CqsE=Lhd06>!xlQC0@#|D;)Ok< zw_n_vPlT^#D%!Rd$M(jfu)Z$2EW6u3nI>~Gbp&y`! zDK~{wEhOv?Sr|qcedtWTmS=DnaJiScHK|Vz6GhBEP}L7Ou<6Xd9!>~59-s)o>|?Pl z*7rV3wcTukaA4>61ac88rnP>n41K~+YVM)ute9K5^E)mx@8oU~{Z5*gqUmqEK6JeDzP;4& zSv|u9tCIFh>fkL(jxbIiAaqP>6Z8C@`2duesr~&k%ZwlmVRevG!GJ7NvWs)1>Z&rY zkxCJBntpRq;jqAUb5TnRgw}n8q>-yWR7DG*ejB=2mEZz_ji$57YukKB|CRBQqU!2b z@Sgex7TKo0?zi{#e;BAEE4A(7s@po+R>Rr#Kx+KNxJX*vV@APZZ%vr7`j^Kwt+Ih3 zwBnh93vn+3(+qx;=I!o>Nq)S91rn0Y23fM2)VX;b)1gcFzm)!O-I;;=;`8 z)bTnfIagO#wKw~%5Z!Paj}MGk%~2Xq2<;XS6qSTuiw5OwanU%X9VKtNdfe&f3Lg6QSo-B z(#23xEn%jX-)5)~qORU7dzCmOpV7x)=0<83``Uw#4klbl$&}Q$I9v4MXQLe(WhUT- z)s{^eT4}tTj~_oa+5gLIwvC_51~$EaJswmPo%6sNZ|CMFdzNynjiLSg4*q;CwdmV*o?hY+BDkkJaXLKdpM?)8L5Lwwg)E#o)%a+7#yI?Ny zz~kYbVO~X-Nba&@hc}&MSmdNlGy5;wAWs51%*aW(4%fpBBekUyN4V9Q6lUpZ=vd4SadoZFaf1Nw(^Mk!i9%<- zlMTwO^M2=7Cbd>RVoCu%zUqQaqs5d29;b8<%|-f=ier_wqh0lo3ES z1|5^Ov(<3Qn$2Efe#~(;Hn4x9IHD;eQOrTM##`ev$j(~OE$ME8qzKBF*8X_!fmTe5 zx7k}rMvFd-`nD`0bLjw4(}*@!n(UV0j0^x`8te9~DhWK+izlx<2Q)_qpJ zZ1)k1wcqA5eckBul&XiD8^X2Um>mPP^j<>IEV&VqzE*P{0Mveuz=TJYNB)mrN60D( zE)G_rtA9z$Fg(~PO|^aY>zBmIx@Ut@@Xk(j%FXNKG+gc$4k}xDiKQ>|KYqM4cq*Ka zUxhPi{$*}e>eJ0&O325ie{E7Kx81KjX>H~4)_HQ;Uwmoujq*z6(@S}}wz)!h1O2oj zus_d~-nwaMJbCiumB)JzWO!M`_*B#!*YK>*ig3Do~c zpMz5L=K%ZW^I*`>e&@F~!X`N2OPKFg>5kV>8<#kg>t``tRjHf1kb0L$W8Ti{lLjM5 z(NMv;M??)gqGsuCC-3><+Y$|F9v+dPRQt?JQtwKqBH^^0;@ROa$yiDIylUg`v~%9O zi%p#&gG|VlUPeLSm#6QnycI{MJkyWZR-Qf9m(>pP`? zC`&!?GK98zaZrRj{J_YFEUGI@(BxNrORqiWLv~lNJ(@cdzY+2Vp3u=)(H267$9Z~| zyeUM6T*)p{YKCp4<=~)lfDKx(Jta%Cxz#1E1H;6B^sYy=Ugh)lVrm*$Bq^!fd<*cJj@dC28j0@n zkq3yJu=|92U2zUZoj~9CG9*g9GQwBCg(c?8<;8~3JmZXe0n8 zLI4%qanJ*D!WI=1*{NfBOo$g+=pI}qI<2tKW3!)1C8H~RHXtIyNHD)+v}9S0Vm?9k zjcfStAV6!dNT6IQ)17ef7(LQ}6e!&ZQv^6icY*Y<Ik?R;#g!$3%56C{>jz*cr@>d7XBhRwr5pWexbU9HX3`s2h5 z9N4zf<+W(C$s+NvXU=aHJ7QufAcD@zpBR03d5T6@z|Rhrt0I^O2=LYpqm#al5ehGX??+EI9=a9HFphn@O` z<54(7xTn2C97W1AWayMS!LEas+>|*@+clZ-t4rz1EMd?<6rMVkc zP*Xa{d}y)8ol7wLWa!|HfM@L!x0mQZu8Mc)Hj=|C0&Y%5M#uJYBIQs-PvJWmIm1ax z_dG2aJXOUgKBnGwC@?yf&rm^&U#YOO^R)Dh89a;eaP;-$`qC!l?5DZuj7nQw{t;|o zbTcej&~3zj&D!+zdDTPC|H9lrFO5gvuz0B;z%&T8V{Q2>Z@+6RnqHaMj3RSkp`o#n zRY3(>Z=e06ByK4?7&BpZa?rvSEI5F7Y5{VS;e%U7w*-6aYKJmJh?lING~Z z+9%hC)Tc8`ub<5Q+)Zg(8%L@jTz*E`4Kn~4**O+K+`#JKU2vC~bHW~r7x>d^W`|DX zpoCLmkG+b3_LH3*(P!CFy;9{cO~sf_Ypga<4Jj5UO=wZXAVKhnu0oAA#LiT%4mpvA zE;o25VNDJTS_kfb`1I*PZX+McyaW!*f#-V8lu%eqz{cmxObb&eC}I`mtWZ*8V2evX zJaj*eEG{m_w|`XR)aK96Wk2QdUG-_<1dBHJ3p*}Ce!ab7Bii5V{FBE~f`V*XH{RVa zk(fBD>8K^Tgk9*T9&qF4o=;&#M+wuix&YXCMe&_e3wJJyZQaT0n;;sIsVhLQXLw-6 z|Hv%DTKjOfmEsg>xa(4%$-R}Q!HBNUjhC>M*@b9x4|wn#d|A=rKu-oHx0;S^hAk)g z-9<~LUFtviEC%~F{X}dne-+`<1Qts?5(Fdb7ZUI-{cm}4h1m3s^-%Puk^s#U<@M`# zNn9Jun3x)l4>GQ{HjAz|B&`M+-AoQ;B#~GgTh5n3BsEfl-eaFDcZZf2Yd(Bn%vHaS zMAGRtER1PTGG11t(@jyJvua_2B6li_=i|bc&j(Yub_Hhx+X<5A_W{jA(hI8p)-D zX9r#T zJFBH;;zNfOx%Ye=*PUAUwY9Y9Zr!@hko;PGWT1N+x{MxZuwjM4kczSVeR)_5jCo@9 zA626lgjJunwFLzDFc%zqO;mMt(-jCe|UJkGafE{ z)JZo#{J!7u=C4_r=#l$J7|$?sh=J})DhrJ@C%%E}N=gBJjGVLcNz{)Y@ZNX$ zZGDSog*6`YkWsCEM`U3Bv{%pdOcsiz2jYP_}1WksW+->>Wq7eN(t)f$`21e zC4;Qer&M&hHWPmEFJ|u2=9&lH2G(Y)xK1$@)On7+vq^&K`-qb- zZ#j15J*rbeQ1J1i2hBrG9swSzj>Wx_BRV`8fyuXrkrN_r96O9Nq4|#*h?J}r5@Zm^ zzrXnL?r>wJCy@XfZJ&STU3tLSo4LBKb9CH3>APjoG+{L{VHD%uGUMloHVp}u%goLO zn}4(dym%WR4DWgu)6@OgL@Mwyf*bt;6CJ%q5ZNi~pQIPBM3#a2wINm_EyGe4@QN@7 zGbdRKf7z;KS&c%{{&%2l=++liKowkGZg{rm;^8+YGMMYD23cT3^CQlkltD%geu*p|S?6P$rtZbbA>c>+}vH2vQ0o}bax1nksf!)1TTdbXqzf&S_F?H@N^8NewC00+n zVcj=}3d>-TiZ_4|``We4Br}##2mhi9RFaFX|6!Hzkx%1LS)G`iSUwRENfcdC-Bmj> zyK}FFiW5Cg_t%?%K+YA`s43uIUN$n+DKfQFdRl{(<)oMcY34>oX>_`c4QfrrVvLVP zwRzAh8ErM)UO#AdU7GY0;%+%DzvNX(?@$dHo?C1Rp;yv=E>;2&w~}WO(NuFvWAv#y zb*GGB$b2xKx1a;B+gW|nU}RH739PBE&&7N?#tacVTbGbc_j~y4gqV~j1!)FB>6ywP z1c^*$brEb}8@;8kukTMv^EP&3xZicYzXdR(Q87`PU5L`3{m!ob+c1Yw$+!nrC<*7+ zuH{&rgzA0_6HuFy&~U?so0X=ZNjZymwW}rurqUCSvg{30u~$noGrz(YprZ|z-_^0a z?w9^tV3fG~aRc&db&2CyVyhwBuFcjiXH|<~WNMYAYOl(jL~6T@jgM9mt(>g<$ycsX zCWpqjtB=nLA6;@0cp(+%?mf$qw|tDobb7Vs9}O`xW_b*J0TdmHJ_Z<&uIvY@9q%Lxt@CfZJBifIcNw_x=Yb?wW(7JjhR zXREOh^78V%X*A@NHWjVLQltA_;WX9~sG<7u&CSBf5lytTR0!4H)L}e(pMUUerYzlDtl8}^c*u)c-hBI8BQk4`vj(N7SdwWScH=Mv`{3Hm77k9UKGhSHvk*Pa zimHDLs%Sqq?B7N^NH`w++RFZ9yT$UDnk3OG^q`cxxK2ml_tQPJR#(+K1K@9T=;CMr zd=Lb`Datr#lnFZ-k%KbjeMjdTmjx;wO0OovRs?K9SCv|B%q5AXoaCu^njY1&KK=PL z0A&5oqBf^d229*hp*JaL$f@40>PAQFc6Lw2#!3z%w~QxZATL$gC9lM9jp=yYPcKbw z8qp4G*5wfMUh>)I(Jr!;F^9oG|DdJ%g3ZE0sl`ew8eJaFyLUxQ%6sKtrbvudVx^(I zL!cW{u61fFG1-Y*%k1+^#%jruRw{4v(9m9yVwtm@d5)ZL?()by-5XGq_=?+$#Y`U7 zbf7=n36gSRFE1B#xFEBPf5Ff`vYt+5V^-vief1Fwnhak8oi>*6eNdcwy^&_JTw$WE zP687TE8c-rT1mpaA$5qB-{Y?4R)wXQu@lxLjV_UIX;xjr0G3*e&>>mEY+C5Kbi5qebpq{GE7*4nUk~EgFfTnFzsSRS~|&azHR}dJ*X07yN*|UBY=kbh>!{7Th?>(GnURWqu&toYhi+Mnx3k2zrF ztcsj0EJr(4)#4|a?sPY_nOfO4UR$J!@mf$rR2y#f4YlVi>n_u}U||r#FK{PoZP}gH zEM|rmH;81rLao2W#l?O4^a*gAycr4)#SrnM)dX$U6<6~WGE{1o-)H4zM|uhDgx7+u z#sdRtD+m*`XH?Yu_Sf0At*%6?)qZ*RL7UFaLxI*mV_Feb007iHA2OCVN&o z09Ft55Vux%wFFF<>&}k`Hc0hw!$4M5ix}}e^q2MZ=31X5>gd6d4Fi8BB4I&Zi$fNz zn_Ct7^HU6p&X4I+Vj2WBJ_zV~x-I6qJb&5rye#;_$VhK^yu0z}AjjNFW5M2fK-*AR zMx&!$5STQ}6tuKFcD<^s#i$8GX=zg~W*?SUarZRd@u2TOwXFNP=xJz%-s;!#V%!Lu zlcE4;4=Q}VT+tx4tc}^?hmJ-|lGw`CD!13&6i60#`eje07u+bo%VyG;0PiIvm8E&K zzuhvk6KFmdDRU`%z7$)u5T#rG z8n~r`8QCj)HTKfqi2qu)eg5NjX`<@*+wqonunCfcobpQaxtFxArWX<;ktM9__?i1y zA;HG$n3pp7gv~AGQ|U&cWhGvX<6=a3qNj^%^<3h36t`Y~I&C2pw5MCaF7I zFd46ApL3q=S&6r*CoxL{3v=r+cIyS*Rgc-e8K{j(g2tLA>I>Ijlmmm1)!8VoerA}V zVe$63qo8j{2=P*M_7w-nGfQocF60Zy+QcHi&0Zm-WXJHMzdszp!-g$H>ZohpQ+ceJ zyKO4y_TE6pDi=om(o#F27pXXhx0mDMQdsk)@S}PPi3QEgg2AQP8v<5aV$d@SGLuD4 zS>+RaxvtS^?J=K#jGxV5HT-5qg~`(;^Y(aoLl(-xfrF||O~*@Eta7YerW&O@5^ufW zi&Xn=;q91MzS+vOGJ5gi(}so9onGRun)PLgq?6I)!Rm_a>J<1_cgqGfC=^jl5;}VF zofN^eNWUtSR|N5R_M;l1Yan|@m9 z5(OfWw^N)|w&Q;a$Wx&ub^iV8X+QPy>2H-}K0;;xct-6d=^tWw8X1<-#A=1aDv-vj ztA=uQ+{jf2l;j`K`lbpt1^5IJv^sYQpP;X#@IFN@?29qN))>jc%xqR%xoG4bkfI$mr2!o3eCi1gZ>* zEuVLE+B~3`x+6N#C4@?%rzMFQH<@HtlSjO!n+s-)2tePLhwS@H*&3@F&I0{Tq<RdX8qT8s$c^&Je8-!LhuI-Ga-$mE;2jXi*aQ=S1kcXO>*f5yi^5iWlWYW5J zok~MjU42mLM*lHek7@aKSf~NF0(>W)-#y9E4Pe=WOG^(~9mTF?HmPfyBakSRf_#^j zoGHe7l>#@LVk)yh<;07Z2uDRz8@nfdq_aH}uDoUD!QvimGPp%5=r#M=LM{*+p4W0b zDgm_VsTdp0TWA?r3x4A&UmoqSPvYb}ut$~KgCet~rY$=Gf#oLg5dXC=pM&KAYU3tN z`XT(FVt%CV``f9adEEiDdafDGrJu%+%mx0oI8FLvVZQT|I&(p{neGnEfB!lx=+;{M zGqyGDjaMei=UFsFH&^hb?#l4>Ew17I#7@7*gYVz_np>D}+IKx%odfv7P=ZF8??SYg25d8}FrvJ;Yo*9+{^P1MBON5u8MeCrRs&E6v<*U@9 zMhER|3s4dFiGiier?-T4Y9kkmQeSI&{QP!mPL%edc%?5S?UC71&^uoq_P#WEar5^5 zgtzxoDGG9}Ol3`)tCoj%Ki|yzD$3^|{l%yf1gOuqB9}j;G6pwhJ-sOx(7|FPyXEv+ zDtgD!txETmsZh~`e86HWHZX_xnoP?vq8j#H-GlYCImhj~ONvYs z_KjLQBBKT)te1Xcw0klg7E;` zpi6jl+Xpsgtz_Q28jW`3EHYESYmm86lzlu+^f-xAA_1%nrrLBn@>emHgD?%*xA?K5 zJH1xp{lnjgyE%>;oeGDv(%X^**Oo4I>Ag)57aFS;2wFb#OAjS5Bbnn2CQi`bLRXTNU9 za@lp+B_dm81LT<_3{x2~24Z5I;%|W_<3Qb{$=~HG?cHWi_1)JPzRVtTK&x{^J@HrE zXopSU?~v?NiBI1B=(a@(T%-I~F&^Q|@j$*QC;iHPN|9=|R!zRn5%^WZSSwv~r5(*u zCQ5B*R=YjREu%E1iVBm|M+>bM2N~%a>7Y{if-bU_X{gAi>cX)A<4dP4E0?r4$dBf= zwLgJ4j&=UI*}I*yt@WKdZfhOux$h4eF@P$V2#swL3XJEs z7*#B~PDIvzbgsyXp==4XNkGpqzbX_r5$5x(?Wb}$BOzdtWR4|{XB#bTW;w0JuBPKZ zGv5MF)N zt3^enF;QynRahU zm@+tm z=2DK5IjEfbVdt915Ueyt*L6^s!MP^?cVBKi;;X3DQjo^|rY~$Qb2T$~;b>6JKe91Ipv6=d^5Y zKNgg$84aIC2otuA+^DS^<-hCn;Dre&7=fyK8*F%7^WF)_ z2?jeD+7leodgaC(v`u0vD@Tx3&a%v}__Kfd7G1g0SyEcu`qRfF+hxLo!=SnQd!5vn zeN!1l#70z%E~o^iJZ7};#mbk5hv0(m>i#a0iL$dzHd0jVFP|F(!KFt)Knn!_&iKXT8@AkXkw)_IFpjBHzqsabCO6@2=w97WeKfN$xdrX6|lqUoWP`}TL=L(uYKlpke@B~lJV zXlbfx-1ScZElZVIS4OK2EgiPHuczExkk*48cBp|SjLG7*-2!=9pw^MLrn0h*S$gX&l6CEynRA%X5^c9R3>t?SHg)rB6*|SvSK@#?WEMfvk z-!S9+34WP5-`-~r_0n|j7&eW{KmIrIa7 z-Fq4M4R)vJwcnw*uN=jNN5BLBXi-uho`0>wSOe%o!SBEbq1=DoEtKE%-&uQHD}dCX zN}>Z7m*s{kKu@=-w6xSLVwB=(RvUPdot}<+I4~d-rd#$;bVo#l`;PK$d;8)yxPn5g zT8977XI;&f7A^FdGq$JE%-$6;=VM;-r`f@G!bnn0h}0U?-VTpc)YbP1qSUpgcBJng zwVe;04%4&e21ys1uCM=`QP7!oxj%P}WC$578E zoPonp37Ms187VXQ*}}wCRH~|(4-U z_R8dxv(u!j-8lR+Ft;neqDYKIs>gex_6;dlX<9hn{7W=AqYmzaK~25WOmXDN{Eqph zoS~96KQ&ip&+2Ir)URo88=RT@fq~`mIt1k#&QtSF_3NF?-1lPe+iP#Pk6f7Rp_X<* zj_K>)f9tRzd`ZqK%UJ9Zu@}eoP*DKtTj}BGSP#L%tz-i==l-SJg#T&1YVIX)8!uJ7 z2zxT)?P3a!?OFqx1FXNvVzpfgaJ!MFOVtwJl*cBKV~HfA2xAB>CQI<5zDrTNuYAqle4!`0fg?ROTH zM?AGw>P}p)86$F2;SYa+>Lcwg#d`(tNu;3)_cy4G^)^wohtVjoIN6O;!a{q`{9}@FKxp6Zod~s(38l_^# z(+$Sc9cTD1bru{V#{x{Or9nge1>%D84_bD-7<7R&megh(g5qaMfhckXesAZS%&>Ve z?vmfRgrya}f9K=g(gb^(AFb-_;){=4ZEleGn4U?_DoP1vU@z+*q6_)GD~&KEr<=3J zKbmxSnSZ&Xjl&s)I~R5^2bQGR>_VcYY*a8+DQ@O!4LpvV7zyFY$JN&!-MgEL3+yrs zz(!f9H8l-azRk|gDv1@f6pIPEFlIf{{zzlO2y{_W>9K5>DK0=4rTG!kTtYlz8-2U< zI7yiPX^MbOVimn7IRqxS7sROuP>JUn3RzF=uX3*DY&XEBZu7!_p@V{(p?u&c{2?Gj ze<)dbaNYGYwIu%eY6?GVv$n3z?rNsmsr&m050LZ3=<4NPq0s#Ldg5B42HiZ$WlB+r zzZBvf+9JA8>DKr5KN(6NuX?pxrlg@kFcD|P_Wx|-Wq9Y6oBkK$qumG^EM)n=E;vKSveh*ifnlEe!W0zI0?o_D~j+3+5Nq}?H zGv*VZI_{a4NsI^zvi5$m9DDwJ7Hn@eJdd{x@$^zpMevp2q9P`>OPjF^z(yJZ2Ih_k z&QpyQD7Sz@3-C6cd`dx*#T91gsB+eg9rT(nEJ^{q9Ed95(Uzs1k%^P9=m zB=VASqWM(7Nl^RDSmNV^I2_^?0wCkTt?&-_uSyEHZ{4EmGskVp+kClb(Up}(PJYPk z+Z4ChznffVO6Ca1FBq3?8(Pamm~g}(BX);2eZ2Uk&ZDJoxaRHJ%sL<$h*;&%l3@=( zy@PvaKvl`IXT6a0X#f1R!NT?N@O6n`$rRmOtE#Rw8q2Gv^K z^(o=$)*GXjwkU=`Og>Bq^qqQ$)x7~-3VU}~M4!||NdP7@@7c4NX(ELO)dtEggFCx| zjm6V@;9IQ3QS&XC66=xUhXdZvM!T)aXbG?X5uKg2f2n#7sTynz_#dviA{vcZ>qVF{ zaYJm;Jb`G|J-IjlM0U4q;nu5%__nqpK#l=Jd$#IGE6~eoO`{V m+1$+4cK~)Ike%|qy&aO+LDe;Tsrp*}we8MePrtD7zWygl_BqS| literal 129369 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 z z>Q&SA{dg!szt*nalUXGGZCGIabW?+to5={?fu)un-rHYwQWb6J0-f(o5{RjGr) zoFQw_-cXvt++=5YR4_%3)Pq=TcSq4JlI8YI3CH`7H4AF<1#&VwI*4`t)0vjFe*cZ08+Q4GnF} zSO5@RItRJU^|>Ha{X^%nfa%1cQwfpO^Dn;B)1UgsbXNqfo`^gjnLAV)sI3jzyh{6J z(q+3WyK>SQlLAHzD-=<>SggpzDB{>w^g<4#$+|$Zpdo!9aJQTa_ry2qqD7S$yz*+z z$62>s@eN0U8%IG$)}oRX8_z1&BdC)+fbFOOkY|+-BA`~T^puwq-1M9M$r51$LKvHt z%%7!{ngyON?MC8MUOmz-s)^1I>vyFOz+#_&w^fCK_{0g=HVpsxF7(K)E3OPk4hZyC zgU2_rQBvXft`NI*izbQEs5HB(bqTj>2_D<^aksrUlCOUhSq?ObPI_+rYBg=whYsI9 z?5sxvA}5+h7w3#8208tXCa_rR)Yy#5CV45CrR&X9AUE=A10yzG=))SO1Kqa$$rzvN z>r10PC?fWaz*A;b*UV0H3DJ1Uo-5|v;2>j(9w!Iani}d81%rg+Ki#k01}bjU*Qn}^ zH_*BdiHR(FIqRrY(9I*V{jjuK!g{ec1&Tu4>L*g3} zGz=K8UKMlg{UmH@y)xkr8nguXzmANFf&SP}-|jgN`4p=81$l+ft3nmgdyGnN9$U0?(ofE0uMS$B}odKNxqg*0ye_%S{G zIFIK{*FgV)hcVr$d))ryP#!VuYq{%M_#>TqLf!Auf!Es zPF3qn#3y)CuD$Z}Gw}X(YV;^SD{CKlcV`4ksuJeo`fK$1UPImnp0<`K1-epk?6M#}2U%&1*@Fer^ktHQ1 zz;L2N;ZMmlyg7WK{M`K6Er*F6u&(P7itc_zJ<`uPh+=xs0(I$jma4V z?is9)S6hR&m*kZlZEZiaJe2&;S*wyR>SOj8EUF%h^QNn0ma3ZE)ae7>Vb>?lKr80X zf+|;*^@?uzsuHMdo6Fm!VZ&-ZqZmdzx)|p5s-a+OYYX`D#1|*?b1i~_AhgPU^V6Nw zj1*)Wdk1T^J*qo#Z)h2|ApP{-y?a>9kk2kK{gsvNOd_zmwHpl}{wDfRRuBHveExLL z&z&WtOQ(DG-YOznT9x6H1T%AELrGKnSO>BA;tj$z!Qfg!j(0|p2x4(GIOM>aux;}o zBTpY4SXY;2hyd5MrZa?Xz?7JDOv`>i@FXPRLV)jH!!jGi>#PJF4qg$>w7#n4fm#ab z=q-jsAlDamf`YzK%R{B+PtG-T%-U({vPep^my|}`d1^8@(~MA6s7xIJqOVgL8c`j$ zGe?BWLu-Vziifn#cfCPNSh|Vj6!9?nE(slI$~ZQF$%j_PW|2p9ivH52I)~W|@CI5> zBZJJGmIu`g7^UNe2G4>fvTN{3w+<_wzHs#8!G<|41Gj3pQVG4R80rI$t`9&{(2{z{ zfi>5fmvLjI3q?I1&Kn$s(s0|JLB@{8tC1v|GZN&_*{!)K=RQTy=Lpr`nd<}R)!)7V zJL^Qj^TZGxVX(EGLrLj|a{xT2yGNGh@?~+8wrL=gXluaszl=Faa;iOk?rf7Sm}mA1 zAUPYeCC*oGz(hwkyCq0cK35zb5k5bkrN*Kde06eBQ^Bv;S(qurB&el-acdX{rp`JQ z9Tj|cD9!Zb*RS^!<>gnbYom1X4_Pv@9>Pb~iMd@DMnf4ScOEGxN?E32F9=T!bjc)m zKkL4R1&mX+Pj9IVU5PQW6 zalLJ(;E(l)@0}SG_f_}Ud9Q_DoiG>CdYCQk&e0&iUC(a;JhpbyA67PdVeiSaiaUe;y)r)QG|OfGJu@U9S8&VR)+++g@kxTRB#|c z_=bu-IEHG4@_SOb7c#Ua{`G7BcVnuFL2NfgIdX^Qzk6f>^G{lsmMutp&4^RBXSyJF zmI`_FZi2Wg8(xn|(pxIU3-h+^?W>4WumW)w7CCXtDewpb`b^G$u@Gu=&eKyau$k(e zD35vwD_SekIT*YIfW*sSOu(z(#Fnf_?1B{@^m+wtQ|s#DRL_u-l9FGwFNUc%@5V-* zf~ckvt=2l$sJGrPV|w1v92VtvLtPUGgj2sB@*%Ec-y#}-KvNJW<@_B$!Sl~|7CJ?tbV+RaTB4AH@k5IlkWbI z-so)E&&=b>;*C$#92~S`kt;|Aria;UR8*2@@IMO+&q1bx`_dHJAC6ilVD{_uYh93% zF)B}D7VIWS30n@ZEb9DfBn^`iacTP64w`V>xziY9=x#aTBp_%dQOh84L&)iWvGdgfg5 z?Du{4yN~^4-yfD9({*3>Rp)t*bBy2k|HUGRTOI#tU^j}P8Ittc=dg&d`^Ik3C z)bT73JvA}tw5a#ri{kepVg@Rw*d{&Gwq=NWl>xRy@A?=|YwoZ3(PxVfA$u$Io=ELxO)nW3EbbZGQZx^P)95Cg?LsOtlnZ8Y_?`e z>AeWqZ!6S9)$|qS#!W5_76z98`D0p|lCn-n)pz*(s_gORvw6BN$GvEvq}Usm^7_X( zM*TFpChjcUoBatQgML=ywFadJWLVrbv0aMxBO_>5y*W?1g>sQ~akFzC7R5EOL;Gpb zUakmc8*}I~QB(WAA0N>+$F6lAl_z7Zr5aW^3LzFp*o5v&(*+ z{J`t?ly`91<;=qMo#&D-oJ{a7BaW|ACLv+0h+!&m-MWQ+YTkU|XJuvOo}y)xRsmXL z3JuEg;`x_L*I9J6DxL8*<}6wT55`Bvykw4J2%Z=D47~KbEM(?=9opw}AH#Y#w&CoK zR~+u+LnC*^!4CHCn&XpQVd)e+JZYmM==Au8)lHqT`B6p zMo&8R1e@WNl$wH#tSr2V)gJlZM#+q$iXNrilu0fesN4D)!SC9J$F=7WZBF%Sau61% zvT&SkqWhWrt~iO@uL;U*w!(HXmxt_Z^jPF|bZ{r+^IaJa4gb(Op6^HM_I=?kGQO+R zQR|Y6Q#5{YRIlU+*8GV0G|#pAFij1ONzVmNwLZ@wye$ zI(5QrQ`*`xW$@_yoRD!>cHjUU&a;4qav^z;a$kri>X_SLpdj}kjtrMH!KwKALp(U@%^SY+tQJg7 z;l1^@K5al z8e)94&t|h-|E7ovuRcS8FHPElntZs@r7Pu;yy70&)3Cet%M*d;P>%iJQRm*r&#(#m zkhz|WifGABamZV=#>jHpe2M#Vr(Y(^B=g(qeVoTI&t()5{wO_aEL_TT7^dLhu-;55 zjsNoHk8W>onOsxmh%_s8zJ6QUl%M$Zo%W?-PAlsbyd52@@k6;a&t)Jtgexgilh~kc z7W}NcZ(~ldsXWqE@t$qaflf>iGP|~!K3ydH5w!e1VYxQsLH4qm{wux`L+0RiY8e_| zCr-@)?!)Tq^!aLKD`Pbc4biGDheC`FUQBUAE=#mZ9jSZ44zEp!BXg}qLVUeQ zV-6PaEkq-j9*J(t(F8P-1jkmzazC@7D7*ph3+}#M7x)7`x44vlj=_9Bh>@E!!+63~ ztVwxfeD2qD%^q~{BdmpIuV^R)+8(F_X#JgLatBw|=u7{Yf{mu7d*Ryqsn4IXT9)W! zFJHMrspHnxrktzi8*4D-=T~;WJzG9b*?gvqb16?z)?{?fpq5xYh3=KqR3-=OkY!~t zqbAjsf|OJ-05NYXDwGlvAssv$m=C?uFBpCxDYM^>-xM6Cn{`MHn+VwigK z-qEYQSsJ@uHl&#&M{KLr93N>%bdjJh=QSQ_H^Ry^=vm|?{ggU*!4kSKA#-Rp0oY{pqb!dWQFZIdc5l_ZXsh&@W;_18rBBaaf>15 zm@k_>4N6mc5QUCd&Car=H(EtB^5*ZXTX;`=4qi-uiOgH?4N$Cgs>7%f&{X=S+e@Xx zi|UNA*{ZF54;sgKSFfJ!HmXw%_Nb;)Ec{+m9bVg1#}y{=T!Ci)EfS~LJBhup*=GMP zP;-aOoB;z!{MrARqP!Iu);V{#Z@LGv+joZ@AQ{ynsaUgf z7)G9zi5ijqn;6Xg-#n(4FCDAbpJa$ph_)c+ufM||yis_|J|O#jZg&HZXtb{86zcPW zc;Hv4{hoZbMz5Fs`YZe~LjJq$6!~wCk)P3^G5Pn${;df-Bb}UZ0&PSerfA9(`+(@F z-Z8&%M(M;z=u(2%Yef7&kswtRKYN8shv@tWnJle_Ius+I{;U+;9e(z;d*|)GyGX(M zT+xZz0NyV{sWeBF6NA>6RR!%d-=v^IHxwzA(=SUOvj)n) ztg8y`4N$oY@Jm>UTF<1UVj1odh{zqQ!(e`tR=peIXC$Q_t5u17wcG06aeI6>SWqBm zDMAp1`-ixT9+y{$Fb{K`PR4%3#2Y@~V!X~_V@qI4`Cs|=&HgD!G+C)*&QeM?Nw)~)5I)Pf~X4?x8G~jG#)71<3 zG2s0)3B?J~M@CVdI{xUsloWR<1mL@TZ^~~8seUG`z3bzBr;iKyRY9c_lNP~__zlD} z)`|+Y!l|MFQW`Sivt}%C%$hP|e912; zm{u#fe|-5?B`5ADYYAeZh|dzac1}T1-X;*TA0UfsXBB ze&z$3Pz=;z^st2_3vnKypMG+aHa?{rA)IrsNhwF0U@Jw*ls!_}?N>)JaPp;`xNDgOz0NP%ry0+wo~Pjzil zH#^9)jZHjd`~uG!Fb1CzdBbNcE-N7|J34Xt4nQOkqoK!~50}$!HYq#_!(2(L%j9d* z9dE9xZRJK6Jso+fh01+sX6Db`K$`D+fsjxmt2e1hrm;f1QtU1Pz@~)f!AcnqVYYEveK4UQ5@GU%(?a`{{bJSt#z!mN^ z&~i6a{d0rB)HXt_f;ddLXnHr+HIX-Ff$}r~1D9m|dDap~j{}Bl>=azV@-IfH$!!r; zgS1XLV_81f)F^<;5dJtDzTDXFTmZ<0Jf2Hxu*E&C*x5H+@ZliTe!BfloFi+KJ=5O zcpTwF_Bb&1!_-(ppF9B)H?!ffn=X%e7=<$D_kbG!s2E;SZdT_+?4-y#;;E1W8K;6L zm8>m#59Kb(349_RnSwLbtz%EBz7*-KDwP~iosnAf9%96ks*eHjq#8zun<97Izj#vp%M|sipZ<8x+CBr$ zegF9U-^^|QhrS4Bp3MZ`lg1e^3fmMA_@(QjVK^tt_}8r~q(*2=;0$u08R%~HVpH}Hnb z*oThhw%o|mw+|{*MC0>%Rhk>vr9VYVDoWM8s)3R5Dy!~d#+SUWNl6uIXWMjgjAg|Q zVIZr+SYBrFr4(nklTa6wRTs=(W^<5&glM0!elXJ+9ZK-%}-goi- z4-<2EJ;~e**IBR2T364HOir6x@0CWq9U%0i!hwPaJ_p7Qdp#Qs*JB|ctu^F*$lZQ$ z{5Bax@#wvWGidR3&=s4E5U&R5A&ykh&)~ZrdgJrFyLUH{k2%$PCp(G%eQCSt>MI$11k0v)bA59L-8EStl{NaKIoxM(n`;0 z06)mfY`cihZ~T%egsG1uybrmPb44fSl5+`S3&_`_+u9@@EMcWx>0+WRQ+tMa<;sL~ zD6EqsM$*Z#NtqAusVCG!1(6A*+5JSd2jrI!%SMCDUZ}(~=>85vB6<20Z0yg0c3X7j z?DIFNpmcN{dHHSMrIJQsa1OQO$0eh zJWJ~1=S}~aM+%uT6+1hn>OX&+l31Jm$oeR`GmM}!VgQ!5CAJ&!9gqon{*^Fk(i~1)$zaJux$8hTEB=t4=dB{#UL*>k|vf-MbX*loB}5^7UiC1j~jJHL}HFA$pI% z1EiaKd)eV8?0bW;VQXAzwL{g(U?+FfU87ClzuQ^~APuQ=^Vxj9C z_Z9BW@rPnN-~;d7&?chLx%F{X=(gNj%(roAt5Ng~*en~?gqE&C18OF(Vz7!sKKGZ; zzl1-`mj{$V1ETBHQwKPnxAaZ#1KLawld2zGDfzd~T2QE1HKA%4Q zNp!(}z9++@ktA6a;&?OJhf#hy&Af8+Nke$0mQdVdh} zyTV-H*{T+DcTtEPK`cBxut(2=fuybNKxA6MW2TJAPd;H>T0bU?zm5-DBqtH7Z%@0ShLX@*-4@wNh;aBf_R6Ddv{3Snnw zHy-AP_kUcgDZwydH_JrN-?Zxeg)?UsCSF4QIcz`yM#o${UEmeZ=Jap2ahFj)r~p^N z>Ag8`QSJ;N$y{gh)B$dzj%oM@sAUkb8?Q|g4_RqS3{J2rIoRbc4ico%C(liWW*XbC z{S6%X#8@TPqI`2oeoilXH^axrC&FGwX-j`_;R#*d$SJFQi{YVOT%LiiUs$hU*XQGU z5pr{=e18v#7v0iFB~Mrt91fs;)uz>lw8AVpCWhEyzSW&>R#Vy7K9Xm3b)+K^mxn2S z=MbpMNfo%*)0If6S)GXRtIhGutS3C~i^7cu&Sw5Xi9Ta=pNGM#11!yyp#n zO{s1W%+N-mYlS}V@Tgds70Ziy90JPwtRlg;&*eIB9dQjRgFl&gV1rw~L19zWj+Cp$ zV>DFisq-(>WpnMrJ%-TGF@c={My9i{^W`7cOm`;gbvE?n{?46PSG!*4H1}XA-D%1l zPE*X~nR^k?MD|lvg+A}=(iItnd#1G`CN11HyX%|`UW7)68ES#+ISvPmkQF0m)vR*! z$HF1{bgs~J(Rk2Ib>d6e&)g%MJw?WlT_U|mFwJ0@#iHgN_-1D#B_-8OrbY~&=kWsa| z5e!mt7RhGql}BH_GN4nqhKCm#>9E?rRMKBy_F7t6dhgx4xf;&}JL#n}V>NZk-+^U; zsgLnrbPL27V*P%M7Bde!PuVT9$R<$d`jQw2Ko`^DG z6Z1U98Mm+9-H0T5%zIgjA>6J@R;)R6s|&n-bNpc{)}HIC5)kfB$0<^C)U71uG*@8p zm`kNp4o5kD6IN_Wh~72PtB0)=mS#)AW=Jv^!Gk0VKy3tn87)aclo+UO9)dEZETi_o ztojCYba0O+=vbB~1FR$C=>(L^&tET1v1pI3a-UN|YQePH^+Se(W~;_#a(x5&YxCzU z{>XUM9tTjx&iI&DgO)*F&F968L*pgx%)?;-WQG?VK7aZ0TsBX;T?XFVy_&3+^@VBA=L zEMiQi{9fhQ;DKe@C?rsUw)3ALPM0el2QuTuww&a3j)K5vOMl)lGBV0Uv)wkt6o##= zb3urN;Ko#i-@R+6BA_w9c7(69v(tpgYTccl1zO(s-xerHvvHIrslX&PvX^~I34F~q zJG+$|-mLluS_^g1`BD1?a_*55K|=W<`{Zbxh%!r2&WPHZr(1w>gcv$E&=s!l^Vm@( zCq-DUYTF#7L&@ZUl`oVMx~3-JUTwY;(O{t$!A^VuYvP_Aq89)2OP$34d(0?K?=QSW)!5hvZdoYY zvLVRL8kFk!I%TM)=~*Ucii@IwZ{CO-AJE%*v#=Dp%Nz=imP{ScQ1+E|`3kO+GM!C$%&%>K=K}mr0j>(> z4RJYhJl;Fj5~cQ|qoZbG(wa=cbl2I$W%=?RKt&GZ({2402Mg?XCS=abfYEk^ASN!s z9i7L!)x1t*ctDP1wOCEnb(ZYT&bd&}_gj1(eK7I<6-Rg)l&{XW-0Zv+Rk<@2NluVu zHb*a<<=G|AW?K8_1kd&G+bsZ_qyEfJX3cY8#*W9v z9ys@7KWR4j87NGHmafQu4@q3nW$DM|J!G=&`2mik>=YE1W7Q%cIG?^ndR=CwBQd6k z%R0Nxcj^Ya@pDl$iezTB9OleDIji1m%7LWF)(l{ zSxrndQ`Q;pkAw+NAA$h9hp$OKPE&eP1Ts^x0STv;@q*{Cc!V2?3vOWGDp~$pLvM^0 zuKo;FR|qtH$wmBlqbC`=dtKXc8;V^cK|E-)e@S73bmY5d__(^gy^3(*exiygslSh0%BPX z8OcdWGO4mA?ciikN>b17E zT3IpY7{M5FM8l(IJ<|;nL=exx=Br8{(3KM#CKnY@T7;^e3v4or(!?T}xm^Y}%OnBk5Md`itIrnpj? zZnGG1&wfA8(GfMFBd8wR`D{&{?BhNzm>tViDbM4|*t4m(0j~YMWNJ&IWVxf*W(z>< zx^kGkSzv9FrR3VsKaGU}g-io+3C5(f!>~vA6M5~#c11eSEsNV?^^m8yKTga+Z}b5o zvAEKskjBUu3(}QB=sgW;qEHz&hpJ1@k6W-{1U|u3w9l{8@;j$^an!6X8n#JtJ0vwL zD@MkPY?SwA!m?TjxGX;n*ll+=(2ImH(8hc~zx!>VHH8FtdNeebIB9WxpX4)ml=SqR z#@Q(obDBhT^T8pzt-{2m>#Niie4d9T{|blXI?hDmED075hF@`A0Xlj@P#+8q>&2L!QDUWgU6nL=u& zn*Ak5VXwtIQIfAft_k5E4@lu`Q5IL4G_w~f7H$LSW{;;tG4KNwKx!n(s!qhd3PemD zUyD*=g*Fno1u7Pr>aAZumNGl$^qxYC^rHD+SjX8DtRwQ3#q?GuR2{AI?QBStaaagM zfTm$Yt_JGNo7*dwm{W(7(+Gjn)q42Q{;=-+b=I@p5?lIe>gtqE?>0Z0o~j68+pF{@ zVOB(&py)bZRsH=Bl%sG$!mq13tQ!_nx*1xNrO`r1Pw(a75p>icS#LD~myS*p+F)jk zEZI;Tuu=ZSEhOL)v)I;tDhI%7HA#U&ft-}xsw#7<=3`-0;uWB*DRg+2C*ES&Im|%T zITQA#9{47DmGZxqYqFwoCx7a-wN+JBm3WbGz#_-TzpyGP=UKM)!xaNW`(ufkHFuJ$ z9NzTv1_YLMC^!@R)M@%}ojM20F<#>@q1A*!yU@C6c6L^0lw)@2qwfy6`;*7xFFO*v zKk8XNijfC<4Js=uKuG9jyVFNgD_zcCSp;J`4Acmd8FNg*Y)ekC&9wOLTg@Y}4*Q1| z$A||iHIjVFI6MrQZfOY0cwQ~+ZbVPMtf)-8#?xq@Ln#zfuEo&nfbAj~S?1$DN7t?6 za5Nzr%)m}bIdcRyzJTt=32!Z$@m{61z#|IV*aGA(v}yBTYnb!s1uWa{0Y%hU4#is$ z5FYm$_@G-!(fO(7zf};ie59@2n|uzhz8r>#&B$RX1{M}&!^B8t1D)NB^HgPJMfB~M zv*+AH3S0w@O8mUW&J(k&19<1q^Vf)>ssI-;mH~TGV4hXh7PXpK{wQz1J1dmY5 z*wfgK3?^8q5O;F zNCQ3O6S9qyri`V;StXNxCsRaf#`RBqJmdBLtXE3#M_Qzg@`-+cl7Y&2Fr@QwKxoq> zwXi1@o9vH{`hR9D4rV{H4jC>r2G>8=m6FLP#3|hw?rd1?^ENm z7MG>LeOE`VDc7OCp&lnL-aSMtjTCm~?tNB6J8O}N2`MQyxPY~Wve@3j$|4R~>(z|x zEb16{kYARwHBg&Cf>Ke73;DQ=JPUr0ws$0Y5M zT^+l-MIeovo7-jPLdn=t{eCjdSkCw_r!hm~1{n@ApI{Av)M|YQv?lQ%QmE!%XNCNW z5g9y=?T&qnQ;wx;YD75`Q=b>=rIxZZb+Jvk!tiy3N2P^zT}v^{ov|0PYK%mCDF;q0o&b6 z^2R@4Cy*2SByiBSAr+B24g2U{h*NC62?$VWX3baixh|Wd-CP&{BAv`42i?UYVWRL* ze}7VP69k-dP&=ScuXkRJv)(A3>ec-Q0=wPej2esmgGP=8~PuM4J!NS)y zd#D2XK-4m6m(${Q2PuBz6gr|0b(yXem@l*?O2*&dG#|3+_J9T+e%8l4KWK9YjYdXp zNvyRlq4K33YE1)UayY_ok|LdK=+#IftTD9LeWTx^*4!C|N=U_*dhW1TtFTw+$j|>^ zvcC(y!t^vMd{MyMylX{uahkQ?+1X|D z;leE}1XQM?yINAC#$-OzN6N#pD4;JoIf~87T^BSR^!>YNTv-`Ng;LYeT|oU%v90K< zY>CR*uPV{orOg$Ij0g{B1QXVQZc?cOeduGWl+$C+>?|` zaFKL-Tl4#W0T_#Zp@Gy65Q|LZxRv(ErNV|j{Q@&N`eCizpz`SVLWvj8v(@KXD)@i{ zKI)%;oAm+>6&6*XVVb=g^B5LN4=%32xnN`qfpv^kXsOc`>b|tK4XaYwnU0bAl_*8c z9)l7;&Q5PwhaYxC^heel$|?bsM9E2x)G(3H{Ts)WhTI$2U0Cg=vi7HgfKACa!>E&g zK2C~4!SzQ-7?CIv;$3?=!zPwD%=ewU3T_2i$A|92bX zzbki+5CT#mrx!0o&^HbR2KF2L(#cZUuaK$)xh3UsRYL4DPbySI94)l7In;ktuO(PP z@kcEq$p4LKJmg|5KPXvHr7VMr96^)T<|IRr50j=ar&Ac-|zBAm5Kx=8YWWz ze{u?Y^9F(Y34rl0?8YpUW4|dBd7PdzB|-^LBbhzKwNw(nZle&FsCTZQo-3S$?D zE~K{4VOVvXg1f7l^Ww3a=m9#QNiv60kYY!(F6Kdska&2L)XwVH|CcC^3NH7m+gKdM z@&`@=zjFa}bR{v;$WzM;_6Y4UzhPDoa;i<`9^REzqi>Q(;cse3^tkZX62qf+7A`H~ z&QW9a_ndAmrf3$gv**OlGPz?e2Ap4ro;02wg+ zE(RxX4fbq%00@PY4H8UBC@p?COI%Ab3{Z|>QZiLjrxag#RK3(+hz`)VL>Wd1C7(NU z#{I+GXE6I22pdx;6|BJ8etu&16S`x0d|z^Znf>Vh9J3nV`#%74e4@8Shx=@p+U3)5 z7C|25I^vs=GnbN+QJic5s~Dl=P8Z=SaKfV`55Yv0<><1=10$58nkr44glm^ob`=?{ zO}31I3t*n(C=Zq=@8C|buB;R^Y8w5aRa5Jrc||=|T|L$qsNZ9^ABA#V7GMV^Ce#D{ zFZbGl+fNC&{cs{rimW88!F>ECs!Sw7ObR)T2{}Q<$t>tEmRv^zhi_%yX^vEB{seRs zp=yq7s)l=&PGVZxx1eO_^wnOm7v20&nha}|GtQ?(4uanipN32w9I3^0Yd5UX$b*uT z$Gu=$;z1mrven`LgDP=Co*N!9&+l0i{+aiGTy6Y+=ZkRWT4o$h*JhMef*DTPkhE{On+L?>_zV5nvj=smPl(|Ymlc&^R!q`{dG6Ht3< zB*AASQPNbe-xQ3@x~$q)j*Ha;?{=SKz++VKHA%g^Vh3~$f44+dU5t?Ul zZ13dcTz5Mp;9bo_w;I2r_(CANEcmqZyQ(lzqpYg1K$Dc4yzvD|K9!yTkW^~;lBzs1 zdLHD2mH7AnyyefS<^Z#a-gP_zB= zc!+yN@o94E!+bkxZ}JP|4oR})*vzp|WglrY);^?Q z<8v6(pi_{2D=u3?4kWzu;^aWlJbG8*SrVyad=kcqL9@ktbwR?~t|{0jmF0EwhZvS* z1U%4?el0RxJMFD%ci$14o`kjYS9-6Xhw_x2m;3+XkyaN*5f#K{P|}xQ!q9*{&3kxxM?g^`eI3U1O+@A)0R@Y-ePZ|+0p(Na*oGx3yse7pN` zEU|sc-~>R#=!i#jpNf)q*CU5nB7~d3obb-V%*`oP1#m~olohM`RQ#XN)1>6&Uop>h z10U&RcIG5*#PVmzh{MGmH;(1lRPZ$Y$?u%$h|htSW|=OuGa9?k5`rFszu5fze-E-f zphppd!Wp#L(_smF5z#`BuP0wzSMBP+6)y?6O9+;|1_DbgFo-jSepkYV;dHHhQ zba?Lg%T0b0p1paK)^CGcX0tsRsswbATSo%14=J6S*IFO6aOj+^7;z%Sk}2oa#B)SxuWr^K&7jw5gmxeBYi^y z9ViYy9VE5BeERSqT%E-#T%DTR>p{k~#e1r02jJhj=<3+MwG&Te{!1AcIrtplBjGWv|^ihCQ|5A~A3_iM^_>yR~gk6P? z%K7jy?A6)w`K0xM+3ZwjP6ld>BG+HcqSmD$+3fAXt)bj5u%|4$(pOb;4yEVAM<0j# zfr$6+v-pF9@nO4X>vqq+ciL4B9ZZf_w5&DGTiBdA1~%Y{Ne4B7I~q#iA&8FjMWiiY zi+Q{bysWCbF5P=E!dCYAkv^Z7gQ3dN3Kg2ym>450+&^xw7}s&n~;^?WQ^^ED=~Cs zu_!FsZcNp!pN38>v(9%|KGPw|!qBkWn@&a=-bZ}RqVhcClgzpYz8d+SYmoA4VzII3 zDT?|hb(ON3u)#VeqnBz=y8M#ucIEFWpW1|NjuM$Bu0ip})tK^^%EpWNQxs10EV{PV zhman6TQKJ;EYO%YC(6F9*Uu9Cf}ZC{;r@L`<96tqN7}NWYcxJ0LK$@Emoxr~a@=P1 z4#bKVwOfv27g3KWNc|G3A7VVUkUO(cdUX9dv}NU8H?UlE#v8IRNYv_E$Q@)k=n7qs z+1pyOsNCo--JLDPqm@N^8M{fJ?AqfgP((gTSK?lBcqtuY!DjUHT`P&O{?L9U=Mqg) zVUgW~JGsUi9kQU^>xWLXe8BFHZI4&t8IXe z?q>VtQ4JkM;jFgG;Am^&`xwGo?`MroTgsz`1H($E+hR?MZKgXiVlsK95z^y2i(|Nz zBJ6*to=qk}Ivr?@jjM;N4e8)@3~g?K_qr8S>17-aHga9gzijF7_zlp|4d-b~#+-kt znZ!HV`}^@}`b@iAPYdL3c4>%z8mwUOXgA7KhS`yurGI{BXW2z#$gW#NGOl*e=L93! zj!SOFZSP`VGGH9nQKfgYoE+0dYXQVc1QdBBG;m9yfR{7ZrFo+vvsb|O={yGBX7Nuq zYIwVC7xOj6BJG7Iy-CjJ`p0f}gz7(jB44Ptx4G)(<~Qy~olbZw9%Km!v>6CAd4ajv zg|2>^J>Da5j-;ZYk}I;T+q}V9U*DiEDi*<%Ve%Nt69<~r9>JyiyU9K4TI=^M&`tPL!=8kS0*n$Uoej zd%*u-vDjkLGn_N`a6iis<4XE#(EBi+0=W;g@^Ze|SoMv?A20t9C*y$@;y~z7EY3H4 z1!fRX#4sq`)1T`~m6erUxO6d%m{Yps)}?AM-_rH1VP(i?rv`-Gu>a43Cn^fR1W#gy ziH(`4xx*-vw$Pp%YIxPQa$^ZQDF1~Zxv!$~GefmTz5nwNcSHO_1*ixR#nGuFweyq| zRUmC?Ogn15>$h87r)r135<&}_f2Xuq6=~JRw~ZG~dFBV?8S>wH(yObhafn%-Gd)q< zAm<8=K%tJ}(n6MBTufEossovi1sO<>Q;%*#?X5vLrBGv1qPv5WsNZCH-`0{Fl3L}x zS!uCXeL;-pFb_Kj5yBXpFm5)Qa0^K){Q7mdt6!hjlw#1{x9;+G zPYf>Zb&l^ES%Yl$73EH@v-;cPm%NnkseC`Q+tVD{3oIZefX*xH(R@vy^a?eXhCnwZ z$zq+#Og`MEncbiyAyA3^F29omb$3Ex4AfhiRhU@^ZrQ9O%k*KI#M#^L| zE%*b}hg%GkXs!J0OztLZs@GwnEPBC+DA9D|9m?aR6^>S~uUD6T`jWPLDMAE5)Uzku zhn?@%9(~a#GKP^rU%VVfxUbzYJwH!4suM9_vfN{vw_d&)`{>c5U)ghiQcV7`OKX$o z@wpNT3apz+yzE!1FwwS?#HLJfm}lhjjFmoEb?oz3nAzSs2V1GKCu)xp2_+2M3%wCoI20a4*Gh<6G^-=uNBExd<XLsqW#>k@rL3#PB@AJSm)CLMcHJa=epK?@aMcXW(KY|BdbL;K3jNj~`O)_q?AFw81rQ1mVrM(rUz?*N=1_ZIG>{Jp8r(Jn z`u^VD8R?rH7W%}9(;4H8w?AaxbjYDg9i-}ad?a>%+6Y=PeHRhPJ zR7t#=ZI@7v1szhCQb|7$rs8wwPmTEREK6Ekys)w)bJPjEQ(Ie`&CzN%AR3~m620M! z$E>N?GNXiLN~&4C_S-A*qm?d0#%oQWlmJ{$U!j46prF+`)^z=!Kjd8*8OGHWbW?<4 zG8}+d__8@7U$iokk|Z5gO?Lx`$RP#$n!{|Cg5Ha$ zNk_+-MA#EXBbPceC$wSS3e^1f_h@)jt6n$NM5s*2szl>CAE0bctxuuE0}FJbbMAP@ zFvpN@5f(8J)9H|}DgTAjL3%w=JYt)sdlu*Pcj`|O!8;Usm1|8GR0XW#;-J%8;_!V) zi-IPxC@;;WgLqnbsHbsWQ9duhb0e;M4wT2{H5DF;J`Ma5M*Xr_m0Pgye^m#jV&7&dqgHS*n5$11z;o z=_7m0G2&7OR&3nhJS8H?JevM!yp9_yz0tKnd42BOk=_yA>X$QPB_R5u(cF%`{a#A` ztO4Pl+CN@5=V{2ss&|SxpWFnn&WIB$wd?sBC8KDi-lD_}z{Qx#*m#RG7*ZHjSoW6K zz1&P$=r{jE>aEjTXSPn1=RfpZnhp#!_Qvd;3Q`|bK5*8w+t^_3_S`XvVV#(W)Xftg zoO_nCr&b(xYPvtyz|_=KNvVnOAAAtAHSfR5zx4ML7)_RX0K0^DQO?)8>9WSLnnzMr zn`-dSr_vlD4HZo`0%m{$CQfER06;gI9OrWwBmJJ^!NWbDY`Wj~Fs9`%yBCq{XrLhkn|fw~(!bYN!Jj#@-iduA z8K>Ss)S2%LsxHD4nZ&gZI>OrNvNUyOL1b+o%xB+UmCTir?#hsC5m<^c$O{MzyumKl zwYt$+Oy@k1Ufol^)V!O+o+ov;>Jkv3eiKj_j5; z4WBE^rQIobIV~H-eer2iO4inkiPfW(4dtbgo7p_$-#^R~JM3#$VG(n!_6(f4M2;8e z2cWmI{Y)&*;3H_$C<2I(j(U$<7?(J$_sYYkrt_9Av)_EGmJ>DGc=)#On58%9AG1X0 z4xPXfVMWvEYON@Cuw8As$>4Wa>G?xzGHOO&@ty z+atPO5*@#S;lSj)rC--tqRiOG{`|m-6&V$&q@C|d$-GY{gouD|(ldvT*CMSp%gXr) zK2EOWo2Z8>qe_}|F6GiTDy&PD#AZ05>YUw6>mv{4T>MEwkUhJBk3)TE0p(h)_ptq* z2#)pUV?9&no}eJ1z%6LtR{~1N^+N-&WnBXuf0cMSFsMxE2lpia;1zJJVK$wX4(Bjq z2tMV!m0+W2{y4`00`uJ0c*I0RLrWFs1luK1V5i_6*q_U~x?&iUk>64U1!HG`muef* z6bo2FW?+4-D+viNKo(cFV1G|z2$63=^pj*Y|4-NcuQS3_d`LK(q=a!?|#Pe6u-K2ti}!r7V&}jO}xXk_980JgL!V?{K)=J z4yCZ$?2lFke;ne_?fKzyj()a#DcXIvuDpggJ*ja2Z`6=s^53YTW&s_U14KmBT`Ne{|d_&E&71d?;HD)<3=D)Y z3RczBFc)c$kfMW3sK3p>r!xM>x?px)O8vm5lTrUCJTm3$@z9M$5*8EKuYQ+g=*0m(tGqEx1MJq$g^f zPbmpPECS;-3^uk$psz*T!qW~3k^?+b?`DW&9OWPQ5dmP!rwUmQU<$Q0N5%ctv! zOK5YZ1))4Iv~bSOR;nt;Ioq=T(eN?ouz?jD^0chQvJHWufzVeJaSNIU=vfUzlLr0tokKa@elDOdbP@> zyH=SReh!h>KR(FMTQs(z=xAS^ZSkEsgIYG2O*&)t=u4W0pV$npk;ASue%fMC@p?~$ zlUJiFu=C#v%&i@MzFTpkFI7M}QiXWd4W1^rM0DW_k!-utZysr+8g$AmCZA3?UX+sR zg!B|W18@ZSXd$oYZh_zb4OC*;v)avZE zJUF4_;!cB{dzFvXoviGLAm=N_vy#^q+1%97)X3FV zET20v^3sZ#m;NX&)PTo)-g0n*|G`^Uz3m6T+u+hI4E|XyCO*+#(XBS27CJWoRQU%{ zH65~g!_uPecJM*823GWXw_g7^4gY_Xj-jy_tM(yTU7j~f|MdLJ~NiE2qAoD6>& zq|fg)ok+z9>Yat$Gahqfx9HikNso$|wYAr#cqJuzYc+|0569JX^Oc?X^NNi?(iRfb zUpD@x-rKfC5MI^uO>Zw-Uf&FY{AD|ki?QHMEAZPX)x^WrDgUAtV-{AUQ@wSSezxnN zagFFiV@IxXf;Ro|oo4$bRMFer4%HSuMdqm69{@Ga9X9V@mp9-Ulg_NL)?MTpJ&WwV ze{Hlf+e@`peDIX5^M^z-?GArYN<2Tu>sW6j9?&qLIF)Np4MVeLvGz=xI_t3UoQ$%a zqO26@SdmOi1p4ll%ro1DuGFo=4TGk}Gjge2SOAR8Xhyoea{+}%!QSg^hRX=+)B1If z`rpGx!ScpfDzI$nhgh4$F_L4bQ` zt=N29dtzS)ZujI}%4ZLDWps0MAI$Z)wO(bn5EZ4Pq2e$ee`qf1xqNR{DKJKDmi)hj zWQ;zb9IuXD>MB_yY^I=LLdF$)PnL~X1A0|!%DQcwB^k9diH!hV6hy>tU12)OUF|kN z^;_|%+m>oPuTh0bBSJuLdS~i$LCEsSbY9x*if-=+!X>BSa&{(pKSNp&Hk&bJo8eO+ zyfTb*_G)3~L@jY)p|l#dIR`HOKM;V?l44+BpquViKF-#kr0mgcK^*xXpZ~r;*boOa zTvESDlAPBwMmcVUdEQFyq&iV>xm4tL+)qy~9@z!*4P}K)a^e4_;PRpo)HD$_f+B%* z&MRG;FLnOCg3GB>*e6}kP_3*}$)IpTIY~gBkQ5Db59g!c38eHdtiMm0R~3stH*qlq>@q+ z_Jc|is6Y{E;(lJue0EZqU0T&Yt_?3m^Q0oJ{pnwObuW0|s}DM^iB9@m#*<5xX1^Q! z_LS2D7!5ZqLBsgyrNPAwn5%1xCZq2_U^CQxgKlJn5Nm27(+l4yYb&GQo?sUV4g6KTkk2pFG=0NmojkOl)r$SJ4s&zaFFnH3FZ9s;St zRmplnj$v+SKS4V0_0O+S&~FJi&EgE10h zlGwyzI-TFWtNLyxJ}V@6B3ChrZkzNQ$Kg6==l(+DaIM-MulaJ-S`2j#It9GoPqe5R z)Wq;ZJ=$a+QYWfRa;c*6-E-(3ab*P!z(Fm3NO>H&(_v^S@Z3_(gYa@hBP~rWUdbDT z(U5*!r;dT>wb0H=Y9eP&m6}Yqrq1Me19Z46V^sJbRQO#I0fh-UsIPy?6Yt89PR8wY zEs=eB4j%Z3MoI7q=93DF7l?9C=(Z(bK5VD6RmV%S+%nrTGoP_{&8#!P#ub(J^8Z(R z`QMU>`5&mgP@+(W?=Zg-5PW2zxWmN8)^Qn`bPS!{Rx{h$ezy7CewB5G?O3Ttf%;@{ z7#8#s3_>_b7d*BS`bPy?@@BC`Y&Og zUtfI5gjxNayn{NGn!3JeQYWjIMpqgr4t^#%yN{?CN^#knl4Q3TIGAX-rUXDG&-s2k zg15NmB%Pp2LU!Q1K>WW<1~JGF)7`qqI%O&Q$osx3a-_X&`{SAH|6=d0qpDilet%3h zBCrK%1SJKeOIk%iT3TWOO6Q^%jf#qNmvnb`gGiUs-Cc`Xz#`ARV7uda-sil(-x=eK zamF}j{^52H=UlVydB=5qug~`&K?o%CaR4GFFg_rEdDyNUh)m)-Q7S)_TIUWgL|tCv zq1#pW4@rr0wntyz`FWa!n-sOTX}lLkb;RZibC(JuuOk2*5RS)xjOX4!gzEHwe*#eb zNZDcmFwuqPr?p%zSG1{^gGl6|(Ctw-(%vj~L#+T8HXL$rp4kP7G|w?xMX@_5#w#k1w9DnD|@2 zEm5_WAp;6IAot=aQZsobChAYNcI~Pz5k^1il4F~a8PXcTwdEJvop7L z6;Nz}z8@Bxpb!w3qNtfD_+aJ6`dvBKc3qw4DRRyr|7;~Ak&b4 z2)g_D*~D+FnG$kN@j25!EdFi8xB<*6z#EIMuh-UlrD!8h1rB*AE$s`5_qpc&;onq0 zsB8Q5{~NUeCMhqztkT|ykZO-lOdK~xF@prUjY|}jlppHojh1!&%jgN7JmWJUGY4cD z;s}!-C}@K!ipntz`L=vD|E3TIJDWUJOjW6yA>diAY{N3vD{|IUdP}aU< zj;U&WdNkv+v%@|k200JM-xRlHN(@+OI^ILzD$Q+`b zcceP$PYUXHmI$Bj^#P0okfs3Hhy;+)j~o6CY@$+d1z&$?B%*Iv#&>_s_@zCebzXQby*mp@fs@AHFBirOhe8*Ar zP?|wcKaf?#xsDbhk14>k{i9Ry32{3YoosA!pK;y!j7JPVjLQ)U&R=0O{lt5q((vb7 zz(s;9BL@NapZdXr2LhBQKs-epDW;sG=5o0829&>HVlNB<%MZQGLG^OGiAqo$xo{tV zj{n8pW;JKUFjd2;YalQXD8BMewvxVm`zFc*YVv7iBJQI{al1G?6s&e!ynO()`fx!PC%N{4JbW{Nt6KX%B?pOs^U|A>c<}( z91N<_stV_;t$WOdawpc&DUA2-93!f>F5P+Zg~vfHuu7h|)9MNmpa^7yL_SsT0wM&7 zpmDNGTR?;RLd?|h(D5SzZwoGu*aXw%{i^A207iqjG?(FW^uVK&AriEjU+fYF1+0mc z9b8fsj8t{O%^w*5mysX?xs~-#DL+XbeEOm#SaeDo`T1}76!61~8Ci3R zy1~zsQ?1FPV*D6Bynzw{B%)?$x$bJN=bDmRz&MjT)BltiIWUHJY#ST28<00m5# zA4|`fmnQ(H48$f1ge?&}SYkG2cUg1dj0eKf|G@!g62u<=%>pN4|EY^PyS09Bmb;LePLfx%2qpHr3-tr6?^@6J5B^o-ul zm%cpA4xbC}QwTXnkm-{17P_9M73wg>t&SMPAm*zbpf#tZ7WDW%7AO@-yVJj@NK$te zfQqC8cG&d^bD=8cKeI{n?sYhxpX#9kAmF6|xGo>#S_C^bCgwe^o&IEG5>8KG%^TkI z>`aENuCKE}Z;zETIrKJ;WZ#yV7HIkU`rZ>VO*f1basgG%R`UR_5^{|8pENI^qc;P< zT-%X;VBhosDceCbT8;Do#_Uw5TQg`bPY%c@;IWosfUH9SVza@}uYjXc_gX5^&6nP#-3}Z5{J2l~}+`h+tIBwk&D|CvD%nU{J4d!@z`jtY3wt}tz z#U@BShBIwA9z23epgO~MD3<_fSWmg+VD29%5i2X}&`=4#0acpyf*A#4V&B!yv&NNGF zbu+Nw+`dgFVEC%B$3)9{yUB_qvAWv1v6*F!89tn$^W+JzfHR-SxKe;v;xg$4X5dIv zP5LG=hjR97BUEv3JidIm7GQxC_=D~NIB=*M#BkXx|KK^_o%%zaVb6VKAhHmsH7Zq( zqhXpIr1gy#?mxvMD=X~-vP}jQ*&4{rpr%67Km32Z!5e%7Si!abR*`RhDbz4sePVaag6!=dP&j*vyYB(*y^@5289D~YYKQvxPCg2=rOpvZaTJ7}7+ z2=30du7bGgL05@nQ2H%Od^h@0Yfld$*A(+D=wbXH@{YD|XBla+LJoybl731>3bY{& z9>SkbhE|I>lX_MHvX_c{ejD@Q-WHmLVt$FC_D<-XM2edA^Eo3(EK_$*+;}S5<2GeH!?j1t~jrpA5)2F0(^)uC&@7^ zR8c@AN0|}+-PME1?W$K%_v+~~6%LPMpNKU%?^oO6$!7!bnZ>TC-CbFb&%q{UM~U1j>PV$t)~gPe$hRe2>dwdPt};2NT!fDPaRpKWmXczP=PJ;)eOsLF7~(VIK@o7$o5iojd@uG7{i zl8tQ10yZ`kEkU)(1m_evxt*rL&hCyCT(FSo(umRmDh4LiE<*N{jOuG>#q{L4bID!j z$C}*lSgO`{h6rlqAP_Sxa$@|EGH4ep5KQ079HY{6&;CubF=wHR(roZI2%C-UY?MuH z(`cjK*qH}#Zv+NOtsU*{?O<}HuUzC%N`M7SX=W9#y>8;jp3tZPhEI#5Y;NXzsnsXJ zScH7LtAQf4mCZ}pt((nAc zX5ZmZ4nT>04n`{Z4;b^$@#)?|tA~|yqpQE|8Z7}@k=5v+liA(#*M~<@fR1);?+S1c z=&WAr-pbDhsPGrw;r(OJZ4oN3Ua`6yZ2PM1+7`mN#NY!VL9NhB!5q~ z?iMoHntob{fAY(j2G64ol-Q!y=psXoT{Deb3wm$g(#>4M#l@Z1Ls`R&!1YSK3?A}? z!`{}3z^r!!HOkKLERXVgxZFpnJn1n>!R#=k`ebSmz9b|hDZPWtzygpLN0@yf6(BvxOv`Jt7?%HM_!88!-l78O zZ+-Y=%}yZVBkmm^u%D60 zI{^KuIlyrW2vmc`qgN_vJy=Ry=J*%1lYW9wR8BPAuD8?`v_lfv#rTk*=;%`Y0kE#& zu-fD5gI4K`e-|&C;?+6(U@+*mlhHMJ7I8Ov~w7pY{TE)z`{ z)f4~IeFZB05BC)f12EQO5o-45O}!u-AhTIRdA6j*C0NnzV6z;}y|4c2a5a+`Ne)WH zfn%tM4EpWA(?f=r+bb%#mN5MM{Y~uq>LqWY^xR8rC#Yso+Z@dMP#PE`a#B+>F-apA zEhW>l&UDlMgpE{f0R474($P|1f$_5b0o*(m;P25hF*(`JJmW1#gc;$CpMwPHeZ2}Y zR2c#gTRPjneyymh_~uQZMGSB-v?h0Cr9J9zDYNC97)TOhia0MOTUuDi5tp<+BW~vp zgwdeym@mYP$x_l#C<+xjU;Snq?S?aSkp({!_%jR63fPgCS@0Jt2uCEzALc2&*}yyn z$$ssc`?`8tYT+-}mH=jSFjXA@W$ju03*il~mf+P5_Kq_YXRRG^j#Gm2;q-}%#|@uF zbzU&%R%vAEp#uUD(SU7qrK#~y?IJcDsH!2bNj9)Hr#iO@-QfU`z@qL=v%J@9@+zm& z|HdR?H{0N88-%+ToyA5(7#5Axo}V43YEJ)55_=)Nk)1)f$t9dCq4+CKRo?`;PFuj``*-)3n@~=KI1gD0Tn}q7RbT_`5*-pnFsMz0Sltqm#a}Ag}oVV zd2mPyt)36M(&A6S!jc!z5!z@F8XnqpnINB==TN*&_IPWBjvVK9CVea5PjRrbU%e&` zJcW+|-D*<3a&N$`mNMMGX7gr+hW&|PHr*vJq`h6g2-zN(bW4VSvobZ>9b~r?)6-wd zaUfnDt(BTti6&V~csU#OnMb;gq+Ekn&)Mm9f#RPBZXpHHuZRGd@o{h{qp-8_+0`p( zzS~d8x5@4@?5v%~LO}UQM~{6E_@d@OtxJKHQaF9DlQ*I5n(LxqS>-X>zrsV*Ie2-E znhH~};(%QQJ;-NIbv{jCh)M=?So?+#Y0{~*vd&u@u&J7(RgMYjQ z9M2ETC(lnBAi_$r9!U)Sf?ZT7wiuV7mfW(!#{$%x#enuJf#p0souF=Bl?3K^2#ydK z4gA$)PWq{Fi1U4<#m>_Okq)~18trWdTbFs~H70avTep<)>hYDbILC0{tBAe_pIWN6 z_P-~*zpP^o2EQ_Aq?fdoD?Qydm`e`qymk!)VLyubHonbcAo<$K%41+)z&@87EYPt^ z(3lCja_tP+E(s3H0>F_~=sy$hS}Fihr?2Gb=jQf^XDQyaK?pf7kkzyketZUaNmO)GHSgmP9YCr$32)iC==<-(mZlH4=KzlBa9udor1+T8 z1<<$F2Hn`f9C%ZjLPPBZLPb-v)Ov{dB06V=_D3n%^aJ3&MaRN4u&6&6*rnzW856^V zdX{K@b7b`wf2kJ%0_KM-fL>WKN$`lR$mw@gbw0}k8A%3(Fx4^o}ZM# z;FA~|V{ZA*NPpo|d*FB7-Y!uwuFd-V#S38blm)4>cd!LzM*c!am#_>nu|G1~_N~AV z$!5u?iq40W$6}f${5H`mxN_0R3HVGv+wHSm8@veky#w6+i<@}2grd>xm-31R(l6A&(BGHXul99@O+!`6geC40s?kjuRRArRWM{7dY_0VaLJJ4-@5-^7>Kx z{d#SX5wRD4*ARbu{ofHCsPO&=cQLL%ARFyrD9A<#(|-fmKn2!+v(*VURW?yt$bb;* zXa|5`>)h3AA|X%p^geaD?$lk>xc;pM_u>#xEDTnk4DLU+egi?;mXT}e)!B;04yZhG zRdv*bV4x~p7L`0eu{V;-e;Ajvzi+#Hm*_4fDzQ;N{d*GID{Nh&Py)g)m+6qeq098` zor_>UCOE-srm&zy1%6JspWDC@1w5rYe7=PKBXqXke{$Siw zkUX&ZOoU3e1oFR3zCfjhxJc@m@W)0_E+8-LNP%hTSR@p(W$R$*dY-$ z7YE!Rl71S4M2#keHs_5&hbdA0)Dye`E*K>K)?R0YI*f4uB>>vyV#j5s z&-Y?10$eYfLD%P({|{r5tC^^`7H*hwab}GV;LK=lUGF}yXgspIiN4{9?lL6ntg`EBf3k5e=o0Z z=sNHZs?vxm$u55W>);>kYVSGNhe-eiyH0zdkCcGu~;OgK>{o&?+0}w}3ZbF?P8bqVzt11@UGku)X{~PmAjlFf5Eq zf0lXb>IWjv{=hHl*RGH8ex-`fH2ytRe193FihsTL`baR$$Y^Wlvp;0u%eVtZkC4<< zbd8JrF!(qwH-pP`ZMQaO+k4b- z3NB6~t#>{p1P)l-YZ*j^ZtTBa?YmUe*m#LrK!VZY618wKUAs8A{{O7(?tk;)|D;42 zL(F~diF47f{o^@;|4e7?T{XNC+(tx#i)(lb7Z4Q?o4RBJbdTr)^7HBM zXLElt&(K&BuJ{mm0#}F0-SrPhLJf=e?34MHAQ6NX%QGAOBek;5ZekSFf*kuV{d#+7 z)j;|J1Mco^!E`Idqj0ywH%r|R-`u_ulW<9N?Bdrs-ULjgBc=%R4L7;E1d-3w)YKov zJ_1PlBdXojOr&xu9`i3&4qDJ)fN=2r4M(Nf zs_WmZ5q8K)gwjQNeq5$2D?!>dWPU!Vus4R^Zeyh87(_`z%%0ZoUM6p%3l+<=ucbbYSMZ{XPrIL^0rMY)w9$2zStL*ss&MIvPnq@;7oYDY{p zFKrEeY~_MFmS6hpG;4_^;G3XvFqoOSs-kszkVqrB%B*oTSp})IAz;ck8{0Q38(#(M z-@P^1OfWGjziAjxrIL-!-kiUnBOslwG6~y1JZ?YP*=bVF11&*VcWmWLsRAiR|k4q5b2)BK- zc6t!bg@|`Kil&Qdr^r6B7~9|YPYE%Xu43D@w~0v`D(IT*_u1IChYRKkbs%t|1**z< z;`Y+*a|5_g{8;&}$P|uv{=ro{ujE_efvYtK#`t+1l?M>0C#>jTadMt^Y0_G=y`!yT zEPQ@}c0{+v4>rLBYYQ6i)>G2FtoKsUzCq2l#}KFt3}5PwQvt9O-nNErmgvym z(=VPj_=EM?OEmuocaPeW-Q3(CKYlE9gkh~eb2vLe2Ho0NUFEabk{m;>5U;#{{~m#b zV5vJP0@cm@);-Y^wJt5f=exp8(Zc71dDS~V#o~x=-}IoUG;V5NighbUE>=9X_Afk` zlNE9}h$*8nIc{+~@g~$f3AAkkl?5I9z91(UgvQLsNHL3q@YK!ZxgsT17eLkKS-3C~ zZ!HVavg*xD=u*6J3aVq4VqNxyU60kPV5hU8!a?hB#Ozw#$$(o%R-TFhfhGeedObKl z_pgiPwO))n1J7r1WC?vg0Sm30Gzs<~jbD@^`L8=Z!S@O1?(S~Xa-qS?QpqDZTqWs{ zQjO1A%Qeu%#Pp7JT^xx!Jqd+dWlcHG;XvEr0n^jj*_{nSHe*X;*&|v?($X6sMM#H- zx4UD*hco_rJdzafcEw%Y91im#=H(R`$UWlSq&5Xw!r>Y{U`1mxl+8xs>xLY1)9E_P z)U7(*m^yXQ($X@Q>2Aitd5AXsS@RlC;I9kZ#G!sC)=S6_>ws5SFFqHW;wsj)c-b2C z!aEytI3p(uV82Ko*A=gKcd`-dggm`VI7RfhD1Eu`1o$<-l$2Buc-qJllASN~lm!pV z7yI+3p&=_BjDw?SeKAj?;8}t5IipG*wzCRI{1oV+O^+1m1Bax~vtxpd#jL+BA@;>p zd+M0SmWc%g;%R+3uM5WQ&Sqa=0?OAsjcPsed~nQ(ZsGTMOd``rSB3NXNUoBS)#sqJ zmOc9O;pYiK!KNW^y=QU13vc;igv|+Z7ygO`j9UO$w7jZI(4m@T0sEJrD4HF9>n*Xw zEA_<|zk~Gt+9RZ*o15>-NrO<+J(AiP&pA44+WAMSg?nXrwSz-L1~C+*g#6Zvw<8}r zZGMH;+?(pqgv#(B3(HS!CY-V8U)Bwk1l=A~%sH|EqH`lf46toqpnMdEX(tvnA3ac#tjS48B@)3TOMG;^MR_br*U{%99`OPupMi zonS#HA32<*grBVp)y3+(IqqFxR5{zpJFCpf>f2<(55)(KUFg_!?ffhpn1TY|)Lo_B zcJaW9j0Yl*tT*g>JX#!1{%~PJV+{hGN;Ob5ozDY{4%HepX|${w;tnYfOz3F2oGXQ} zCHUbZXoy@}40O16+-mwqLve9G<52F4&tk>Jr6D0BdL8!dzj&YN}%6H+Churm3wZhkQ>Q-u~r0e*9{DA&BV zDk=xjBSoPNc=dBF{=rk>%)IuGA3wHFU+S$E-R0@*Zg)II49)wJatjWR4yHby0ba^$ zgSqq%TXAmPTHn~P-V!b<0{o|ezCIAc9CO5KhwgJagO=Rrvz-00zQFS-`>wtjR22f> zFUt9ZFZky~h|2f+R%=#z`on6)*Q^=Zh|GbFdmEr9-AU`TDYtNO5pi@>lb4^Z4<}&K zh`$XM`y&sSxZE1kVx1}3Dc=IYgp9shQ%julPN#zG3f>+|?ba+*%Vl750Q5#ft_Q|C zI*oCs{&f%O>6Osx@u+{Qzn07T^$D{w1fr4S*AAC}25T~yy=n+mIVUr1!z5&W>1d0{ z3hsQgDC%yU|8qcd4E#zT05W`wbgaW5w38hY12c4nr8EBf`r8y>gq zy@vXs$6s<5p%KwRlyz>1EG-}h*|)Q`h4#c4tW;K2nXDRTK?nMI`o~ZGbO5D7jS@Clv3-FCE+k`nI*XQZS6K!YH%lP2$m zrw!mE6A=;7Jo(unNx*W1>~YOxMy|p&gDGtJF55f%HsSfM+r~sy&!(Hco}TMo13{!c zl1`Z4X*0U9r|YHcxps#Wcu&`~D($y>y@ihoqNZLw0s|fV{0#o=+06~wqvZk}@b|hJ zD@5jol(2A}R`t%VL7YSL)Rb0G7x-H4ncb^!s90?_HG!TNoo_DzB2f}ry-P>bQqs?p zOSn}$h~2#70E5w0XM-iDss1tCy8R_!}VJ z6x~2ne~@+b`RKjQtRDljOCw#JGbNSa>CpL>KXy^w?DEefaCwu(mLf9U@nw%}4)*Q> z!!w2#e|~LfTQ$$G5+!{b=e3?ME9hbU&JKYrPNtcdm;id(ug#D3CadVDprELolyU)6aXfZ0hLiw8QR<1YdwjN zk1sDDKJi3?0>+)Cr7@WE{)qCgE*S)LsHoquF+}qrx_Y#bO$xFC1%^MreZnLdt}$jM z@+0RjH93d{eH{I-v!S8gd~#a&hD;>vAMaid1g+| z+WNZUUx(cGyv`~b9=o{-1e3Taihq4V)0A$1T?*PX-pjw^0R7`Jm!BdIqBfGFUHNkH0pPCx8rt2psBLV5`Y1@Q^JFCxSWy{+59t-~ZQTO{-1VVCiv28&yfhf>~ zu4U83=XPWNy3Kb^55T|gmxi64xkmm51npSfuRxd}@yFJe>FHOI0l{)&>P3H^v?c(J zT%zvh@T4Q%G&y11-S|H6BJ4lOqub3C6UOp^*_Qi7)$|c+8hl z5(mK98x4&}->UK_T^joJ2&e$C2Fzg+IQtc7u($;dVMRo(u9-(k(MAF%QVE%Rctm8` zV7hJk;ls1ew5a;~kzshRT+B+^zR%VDI#pT#T5VZuZg=x%HCwebOeyg$A1}{?UGQye zJ>so+-qK8$<{Q}O%a>MAo0?Xo@auio^WHXI3-K!@NU0MRVtaAQLCY;fNts!aQjnB1 z(GLX;#=<|&?TJ080g|fj)~`k$RjzjL|J7L20@3W0#l)g!?6jV}RePsLqz%#5)_4|l zvS$M$zU^|;{b_=m3njExHh9UHK&A^9aSgt ztuzT0f&xCim3(7kqiVNn{u)oe2GsRGd$uc$RkD+Wc{_;A;>o*i;rgkm9xz3!$3IOy zb9MhY3|(Ja;~+srSTDD6k*mW@pKCRdfBU$#?@lKGaO$sZ>&{=ZPmqQX3qbo7Y6N>w zfDiN6jzDa29Yg!C|NDOj{_lA>t}Ci|f4)HQMo#_d{#+jXzZdj>Wh3OfQEReG<&PEZ zu)dXWRH@c9Z7`0mgBJxH!?St7i|qO;wWtP&3nYcZ@rq#(b2MoN64(o zZE>~~=WNIx8FK8^6N2RDPpNYoOQWDCy2+@V=l#Wt&+RCxus5px^bzdsQ*+m+E@oW? zd9{k027Hj|YdAvGcpm$k=4NJc&i!6oYgCj}JuyN`nrew?@9@U+mc-g_Fl@3Yr1rFv z@Rw#*@9kyeh5qcKG9z|#J8$dLPfkv~dBfwi!Qg-*g|OA@?L;{zNSV#T>T<-e!a}+1raOzKeD=Ak#e7;Td(_Jxb8$g3(+AVvuEhN;$CNjHQT*>Tjkxo{cht;s9&Aw0!Xc;N73 zTCtp;Zh}3wV4_>^;&nZr#c8Q)$n4yC&r(zLS1jNpW68D>ZQ=OM^TC>gT4q5i1=`iM zwUA>mX#~?)S7<=I)^R=U!r7h+^DY{z_R&HeGw5Bgd7A=*O zlm((SKiMqPJ2^dVS)AYB+jA{mFdIX<)YRNU%UuJHbyJ=C9T!9EZb zmYO@37CPwnSBZVqoEXwxR@oBlhjJ<_hk!{({TjIHq82|KES%t#ogiEaaw!rE48rvK zA0M0@4=;k-Q{d_$974Ry=dP5z91n(PvVw43?Zn5cG2XbHT6Q6f`Fy~{W=hPMV6cPS zanG~Zhi!GwFDDKRV$Pz5uhXxh5j~)?f}rB72VkV{`br<@uIH9RoBXl$?NAnJ$eZ7Z z?uG=1#{t7?AU_=&8|&>?RI{onOnkQe5EQL66C}7Jz2tV zz)R8rWyR0t&v^!i2sQbJ#^xT!#C;75jEFYn=^HjEx1U+B|3pPe*|M}~3xnZn)kKG@ z1aO&GpX@S*V@8pXerx=;Akw0%S5{gYi#+;XA5pS+N=}B$N6W}aMa4nMURYXLS(w;A zmqOzrmFmnkLhltPuL7|?R{qo?O!-JafYB-1`MIf-hJv*Y#MV~4%{RAOrpdZE)WKk| zM!PqpetP;F=F-v8Q9m!SPT?%VQNisTS(KLJ?c389>|&F$EDuu|s)uvytrjPT6hDEy z($SgdT5D1Y6)~GRJp8!V+4=qZ{Ew}zo4j{T%%`d?Yo-i~)gRGvGn=eGu8Mp?*mIyJ z%HKyv+tft&@pELpN=8H<;}#kcUOsdcAyW>q}T_Ggy{qRDC}D&CC{}tGL&1#4(GD>m#Zo0)fcQG!2I7 zALnuEgq<9KE+*ALU%Is|^n>Msm7J2E!#f!s*JqpM+q^g36P9~#c=UMjY6)h38n=_t zl9ioF!Sq@n?h5JOi-;iNWxnm=63!g05Y0-b+}O-(DLB&!UJ?Tj4~SfcK;7?#`HI)%;c z2@L4jjW_051bvVOf$a8{Bi_gc*+i{o(3#MO5*exc(n5p#9=nI*)L->Oos-r zYCgqOrw-g_qvz!kY}|LBFJr!6pZhKYkuzKRMsPBRGkWgrTb%`x*UZP@LmM3%TX+?u z);$pDKQ}wuqU#^(>D3$b`Lkn_nK-b9TOqb$y?Nut&_I9xpkjwBPbAr1L25;3m4v!r zo^RIi#DG^vn|>bukS*vqhy-7vRcTv^w)T0yjZu{+7_(03n!~wb;7?lTI3bELI@%r0 z=49UHyQXD&-f6fcrK|d^kx@Ap6C26gBWQPWy-A=_9{#h@gPMSMiwSp8z3PpEqv#^+ zoEnyRQfsq)5{|y_xa$2$?0NRsmiAX^b%<1q(C+vO6q{l+tz4RfBWn;!BrG(>>cTb!G#=%Bl|k?^}BM$!AFl8KUZ85e!W3t&V0g}t~^bAsbFLhU|ijpz0JG#!IAmn{VnCbhRFJD?cDBRT8(O2UlM@HoB zyW@BTUq{Aq8JvyZ@V|anMRAOs~SZn2W(Z!@~&2aQnbo zKQA&ktrl@S)fHLxMEY^$R8(-)LeA9KXE-E>T#rL0mT$sNMpCkfx{;cjt|YQVKr**A z^7__1eP4L41{2=#!MY8{aaKZX9J|?P-4(xkypQS#nKkz(F!3;HWuwlTN_$p~P1Yw9 z`)=eqXea6V^b0TK$FQ0BQTvvQm&vHU9V))PIa;8!vu)R5!nm8;tK4HU*Xug; z%93|#eZUzte|RVN>3TlqV9%GGGU5Z+Z-v8+);ecXIVE08FOw`A7d>dMTg*9Hs;>C1 zs+ZyJdFs$fwRV!w6_lnhDpL#>DOg5*^cl(?`~CO$D%TB(7pfy0tLmR?CtF*W*DdF$ z$?{DXzD7hmt_m{-esjS+wL}Eu%rp5MX)@fL{cBgR;s(o8Z*dy!^nX13h%@OVX&L3* zuFz9Uty;gBn#wU19rDiTxxKEavYol+d(PU`HDj+^EDW0t+PfmS5r!tvDm9yo%)&&F z^x)2Z4y;ql^iP`)CeIq{BMQG?udJ%AdMX4GX1-ks!Zdt*mAnj&9aYfwFx7J1NL>R8 zmswR$7v};O6XpHkie17NVlAmDX{zv{!Ro0LNZCw+Scjx!hlIHu4A%6$X^BuO?3CYW z^23?yT-%%&{=xO-tK?3r73JmEjlALn_LUGD>a>!-X-_87I3RCqAALNSa%`N58D$RK zsBoOP8Tqi<{%kdr(nz}nSl&H~2og5hS@fV7t8mG>tJow+(q1jOHre0*ke`i#ulXz5 zARVowf~t@lZM(##KpY`4K2w`^)qL3XIcoSo|0}oI);Acni@D1_BCm3v1ketMF#%MPwWX%a7=_QDi%OVn zt$4sk1-TO(Ceoy$@QLwlE#RBY%}3J#0qg6QL5czWtsj~samHg36+m|cfVqrALKYQU zZynmC+Xh>jTRI%UbIyKUbY`ctP%m@i)-77-`MQoZx#h^M40-b5y;m^Ul9>8rAkji% zQ^&%Xg#Ge-0oC9F=$!HhwMsr?BgES(9FSpH>A{~C)WzSJL!sf{V-%&^YhK>Bn*2s% z)w({qU2**MH5Q_pfsI~#za*Knf5|pTUfv+G%wqj3B5KlQ*S6}k*1S=l>#MReLZYo} zt?*QjZc(OFtHwMy&h6bSH~srE2FCfvp{!FpS`=kYN(^|s^LpO+QxHMygGw!WhRmGY z(pr<|Y=<{9Z-(+9IkgbIQEGkP=2gxMYQy1JhRKWcZu24;8sf3Sjh2U~^?jGLe-NwLJ<2jplhfNY4F4qyR zI$#l|GlZ{JmLDFr#5ro#4(DWgaZEWwRMbgHaM@{{qWi~!zIlG}Ix-Ti=kWsYk$h z$)_{hSJ=M1$vWm%_S9iK@_PTMo!O=pmA~D-9Yj)Z=VV-poM~Ce{y8y`qZv(l+r@Gl!^+Zp1kO^k z+iY^riv3=F3Ok&^3{lO^yaB_)50~uHG`pPon1QL!eLCJ@j_<#-t58|Vmq&n4 z&g=XtMnOx(2`mdXzkevfF%8N(nG>tEsViglq?HVw9u4iNvNJ8|4%s(;;jmJ{kp_l8 z$DNNZ!+PE0pL(}|f!El68$r^x%&`Q?K)5%v5VF&|EyD;*N9UawHY53=3B}P+B_;Dy zd+$-Q969r;a@U;1V%B>U*Cv+AnB8|xSwNR<2vdy5*R24rx+iCZq8;X zzvWXMnWL_M(-pb>2-LkD82v!sm)aRYlViif-xLI8et*;R z?aTCuQI~XTL+E7r*`77a3PLOkbY-iUr{FP;~rwwFpr=SQNFEp<&=tJ5^wBz}*ds|6II8qn1GXjwTy8 z&l%sexlSh@nA)7Gqjj&iJMhurqKDhVPr8%en!sR+;T$2NQd6To>5^11)19-7ixK1> z@YpX|o`6YxyQx$*r=x?gbh3b%UY6@hw4j}{u1#kcY|>&lDseXSbW<9)c4TKWYA`~_ zLDlGI$}Z07R@?XFc~xryMdfisb?TyRc%?}PzgxbtKTjSZPZ_7=m9YNSAv*uEvIzvI zdugT2RX%lL;^`Fqh0HABK5?@J-NcVEm9|K}Lny zH0DxV5sZ*L!g*hJ1& zZ4xJ^NAtT#e4CY*(eH_ZXI#&h97u|;S`c8QJL(Za);n@hW`saxVnP61wToQ1_Av7_ z##l3biAy6sGdgeWd!imA4Mfg<`{WEN44HhbuCAb}xxb7jD;vvRvo-t4F~@((_Q0m2 zDHG9yQQ;8OzRI;X+HLbv*5M}zFe@|TO%#%*($L)VTqJA`km%3wJ_dE@#V;J-_aT`VQ)XXQpD}|XR>c&je zmAx+LR}4DcSYLLA=L{`)Ep(S<)-rvv0}~{@IuOj$J>O)xS^G1^t3zpY)xk_-6i&jx z9R9Ut^deTpI(o=xF-lZ}$veSzbiXNyn(A;Lu2m%ZGACInUMMbYh>pQr;oK7;_d-2~ zsf)i1x>0dFgWpCf9m_3U@Vqhy3n%nr>;PEb-0;Rfc}1(468KAgkb zB;i!FhS0sCHz|Heqb0ww+BYLprk|;%)|th^rp#6ICI*j$L?1FtHK1c}ulxG>_gEGo z7&{&+CZ!YD*<0# zgH%JsN$&~$U}j6@U^%{a^%_kdRHZ&yx^j27r?mRi!%5#QO(w2l@qJg2w1BfkoLFJq z+q1X3jmva?_e%BM;LcfRXCmnHTbweTanwxl@1bOanD}5Grr!;Rnc;_Lb%ClIv_rI5 zG`pvHZ$2KEtypq?_*(oP#3ps#zD>T8SDsT^O3S3vc^Ey8X&}qr7cM7nmC1QRUA~ep zo+s2yf`5<6v+}*p{$mziUZph50K>dSIp=l>fdHacykto-8)j`(Q7Q$`$8!2yY8G$S zC7f3|ziVJ`VUABStK;EqrZ-22!R}=^2?&B{}utj+nS6?Y*j-Sk%!cQstUuyXYGCq@Z+|$d}t1Bxj{rL*OBG*y2H8_=55kL``Oh5?d>u>o;%slE%$hR6Fp;R;J#g1&jXRP4aCBO&XE7{#e)EH`J6e z{HyWgH*9!r@YO-PJiokw8D8Bo^5LSQt==0=cppTb&CTLInyQep+{#fKQ|nZD1*U3U z())9GI0v7+vi_~@;?^@itewCUZWv*r#bj)3?CB8}5D)+%=!eTP;r*3pI6n00m3AqH zphIk<&tL%&?kJwTp`n2iPOg_(I{5)&Ha@(TT(7@Nk0ySu6#@x)DXD1wr+A*EUxiZ! zf&)h$T)%<-$wTb(=TFGvNQyvzZ-14~ZSNjfe=cvTUpN(NJ(s6o_xs`{KmNOc!=hB; zJ|3B^!K%Sd@Ni9BT->8Y83D-YT_Z*QlaTl)yLJ|C@QY>(Lozvxr$b3Mj=s+?E-uE# zl4Gdp>G@+~V1>p*u1ZVXC^I2yvDfEE(Y8WSD0{!$5z%jcy@Hm z$c=2%&0AlMTEGv8!@8HFRTNytx~^|&i$(Wy9|a_TNjF?0^Utf&vuU=kYAF{~AF@^V z@|qAEX5;0Bs{?bn-SpmWtYpHwcZ-pM6sZQf42#2to(4sAQ!ZX~t4QXK-=p4Nf!QA3 zAvVf|M4{8)q;1lH1woh?g0AN~JeH5TzV%VV8d+_5+Wxy`&5Sw>_Snr&f#QdcuXi}b zSb3T*VY5%0e5c%D)hZi2I{&6sZKu=XT=e6~n3?T0J`dX%ew!0?_%nv zn&t=@y!sH;2E60&Q3hs}s2b35Ze0Nhqx-xQ4tUWu?G%33^EI-2BDi>*#t+eY^qeK|7LfOl{WjA(}kg{aS zzEsG*GnN@!$TG+>V;RQSWd>s#**#Z%@8`Im`?u#0xaSAQf%%vj$N9O=>pb7D_jzTA z$?T1XK^4#cScO+3?Zln+q9UQN7DlGTvcT40IetdFIGDShlFQpU9?R!_2O)9+kFt%D z9os1)WMX})+F`6m;zO>OljrRr++2E3Uv!rg3&Z~UkQ8qWG*w24Fu04<9kF57!3kBMU6`v!&CM(leB3OB&~kp^uy{V3P-5IbSb4RmCp@s= zJW6n8EqcJhA7HEKSJFzoSZDad?-k-58f*RAE#^-Ja2-b}{Kn4f(VO@N#c_SkMk4T9=qA6$=(wC&T5*F zVA_&>r>^cwjq_pc!T7+yRrkbi3(~(X8MRr~$qc`E#9=_8JcYc%kJCTQ>c1_p!CRjx3az{XWetwP8H7m!jZ%}wR&>$;UdMX%5 zrP1sX(rsDgU|ssHniTozT4Wt4o`0NtRoB)wY41@Mj>-7>7l{+Vf#)R3VrWzaUPYM0 z$Px6?<@mXuUTLRkZ6HL`X~OeU#-fH7e#cJ^h#xdIi`5sLSGY&)KjK0gsHX}$v=>x+ zLa~vNY@O`h&*US{bRDpqJc)93<#HXr4yrq~@py3ygQQ72eKivjrS5chPuwdYRUHHx}o#<8pj7Oatu=_nK=W`g~1; zP0=x)6qSLxgo8WO+Tzm@!_U72?za+_>Lw?h-cu#=g*6FB{V2UIbiSH z!?F*i5I%{EnXLPYE&5Va_3f*Pkf zpkPL2nycMOrhzyXv}Q5j2HB=~=l2`hIXF>P; z0C0O0+O0rGAR_&-Ea4wa1yHr{5n5y-+Rd+X_Nok z3jifxPOo`7VZxCun1^5b+cfNa|LHfU!k#d?7dVf%h}I;*xFDETlC8tTzDMB^suR1Q z-&2L8K*a@vP6f}h5y2I)%>V5`wd-4%%_WV=c%g^i0^G}qM{f)%CzVrj0cSh z^{k<#W@Tk9^1uGt&hABQZK@>1#Y0U^Rdus@oj-j9W2q6X+=%*8lx;K0!D%{5&U&Pj zR9AU+ytPe=v>H;cK`m$y%>x3`r)MH}J*M@nuFgsi6=PlpGXvQl>rWY$+1o;TAs1U`*#Zv?HWY*tj?$MOQW5HZ$#ntT)n2mJIa&<@ z`RNpv5xe_NB4ECD_EGh?Q9BSi(lv#n&q3GpD4Y}V@c>14CN$1}n&oVIMnDC-+BA_) z-k>|jWE1`oDKQw0dlVfRnK&BRdivl%TB}A>JVoyOUR(C`{@c&80sSK6je2n-j;8|y z14Je3Y67B$M6$Qic&Wj2nMR!5#nIV8mwmRMhnu%AfR6@MNoeTuVzuHkc`496cn6F} zZRIlM-E1`*v74GFuJ2V#-I@x_a$Vdm#>?Pir;W<3(`UrUMM{2!b)#*xB4s54opBZe zdisx*tORlmJ+YV*FH7$eg~vPkTe+bSfJgf;iP7Im=I0{Xa zf-rkEgMp%A*z={E@F`W=j@T_)kcR4b??}kYj+hIX3RDF3^#sq_JA8M z!#8wOarkG^B2;Tg!#7~i`~sj`Y;QLc7DWh?)-Pz=Xhf1qY&4%xGe;iEhcJ~gr4A)5 z5wAxGa_vLt>7=2JaW+#2~k@T`+_^6vKZ_rxHh zN%E5UrE3+j>HB&fkm0j-&i(MN@>0fZ68NROd6GIDS&Rn!XC zT%(pMY*hYe6Td9BqHh%K}x<7s3K-tq&C_$%b&SO@}+9P96gNsguKayouf}KJV$|Q@9|; zlO@8OGKw2S1=aXC)}g{r$9>h%otRB$(9U#9NrFASad9-^%}Y-F^`L-Hg$6x8_7@iB zRS`G2#Sotx8z;5tG5b>G1aC6mEvLo%=>jfY-B9`s*}yp$AkeB^#9#iIS6qw93((Rk zOUbDD=y+Z{`rPm6QMtlJJwpiM2`2V-d{b{5U8e) zz^l65iceWcE)V0(`eIOID*hy&wruOQ`3Q40Q;A(e>xB*^!rgd4elx(}v~Di?4t6!? zRKORM)x;a)dD9|sqB4iiJdX0tZ?4JYjtHUUE1QQ`b~z&>+wd^X5bPAa6GMF`FI4Fn zmx%c}Nx1)`P`*7?hW^K(bFc+x$jq>pFd7^ieD;Aod1skqoxJPp$Koq9@vAcV(G$#r z=?IC<1L{UJF(fPmR<_gvwwCQzzDH%2*)DBVUuQF}vu?mSe9&`o>HLzzXZfY%E6#T3 z1x=2;$5v;eNV)lXh3l+)(PoaiY`{X=>n`0K23O1=G)HPqSA+FXg?mBJI8Ca&SrR66 z+cv{TBM{&x4_+Fj-yR-LV(*S$Anl|{kMC}{awhe=*)*kI9m3J1I^DaJzr^e?;;hqi z_q&RnDDSF-zirb&1{D5z+1BBl0ym`pX8FbQ6Vd28_>{RVm$0F+qW81N51Q^d~}Nux7j@;le&X6+#w)A3Yqm;fA2^`%RuquJvA3Bj7n}e4gPO zv_|ZNDzI6&j!$a*PZ9QIM^tHZ=?pPto^S&j7jSeRyELz2gJ&aaxWlmX^126ZxnO=; z=xJ6O%D??!r*zhJ2i0_?u%Me<7XbnQWy;P%&uf>Pf6uymfG63R!XqFXSZ4HE!KR%H z8(2Bd+zm1eP9b65NIg|Tk@*(bKDp}!I7N0@#zw?j1~@MAaC3nu?Cf8BalDq&#qj!| z51na=JWK6S-;UN-;hI{zn^l=H@+qrw7Bd10lHSnXdeEa`XTH4Kyudy> zX?dwsb7E(TbAz!#b|5(#F`1VbmkMjwjveRfhz=aH5t>_=|B-=g-cDZXSuTH{So}vg z5V;n13nKynZ89d?yxJVBBuPHzG#W(1 z&q1w;a>^B?Qh6cC)PH3ozJNL3Zizno!%Igiy$}?agap@3As6&`koQ)3ZkB~b&{0Rw z;K0D{LeNnd1=f>-G$(G6arO3}AP~{E?IEtNnw2;@hGNlWIN;oT0s>av!;XBMoIq5< z9gWlGw5)i%JmCS9`4i(@y8I4KheNo@z;&J=OXO&3X_I{_9nwV4XKt-!_d+7SDdIV< zXpE*B`aMwBP$3kTQPikM!M0Gp8>d|!Z2y|=pjbF{%CwR%Xbo!-N!(YIJ~<=0B@gJ>A#weqe&v*A;10kY1-lV94a zq*=wvijIb@I5SK#XR%6}?B4+obiI0$hjN!0xBKdmh9f?&LW!=^GgdyQ<1kB9=x5iM znXTa7f$keSfND(NJxQQBgIfB0*ZJ6V^X*F@Mi>CQhZ)<1V2ek-LWa+DM`R@MwcG_s zZ2f$=6e0li=vzn&n;%4@)6U?X!^7vX@yuO}#z>tx7h!S{vKZ7w>gi(c>#+><6hu0~ zdHMK|9B6T<3q&Oyew`Q_2dcy1onui~(QD17nEACHmMx*Pcf6bt) ztDz<)CT%vg!If?gF^A1hm@6hIlBxhi@jr>0~#aSY%!OxYu7M)+$Y_PmgbJsnS{1SO zS29u{KT8D-#3~Pc9T~xFG5gNW5sjT?+XPIc$t}F?J|H>-U8-jWhnEjmXVZ{>79Lx< zlRJ&t`fi)=oiYWC>p8f&xzTP}0YHq-0d4toX~s)a?ANa+re?C=xIwbnzZjVn#wkZ$ zRX2eD>cs;bBF1_=ZTA8IduC>4ES_6ncLCHuoL2=PiOc=fzG=CAh)}t0*E>MgdZX{_ z(4UH7oO;!OWZjm}@BMt}2e48`enakXHPYrM`pX|W<<%)p$Pg0~xZN30!LGknyiC{z87M3RpTSqBayXW$WL>r%Dbb*Cq6@$;e|tH znIF8&kLL38?ckC(K05pdHO8x&@jVLk_l9x>iwB6Dzk8pUL|Cq6YL1=CkUvTyP` zS^N33#=B(S*`~etvea(03L#+DQ~7#CS5HOMSMFOcX9^Re*$-82EcNo<)Dm}b4+$Y) z?VOa#f=!oDWrT*W1k1hW`!HISW#p5>zbmXr9>fwxmAd|`^cS=1CeQ+G+>wzd# zY?;ttLUgwpQ)vgIFa-?blORxKJ^5YpS)`v6zBv0L`yo-QB|9ISlZW`RevKUHrPwOb zXGw(B27#FmG6WpXas1Y2#}mr3T|WTYm?L|9P#NtAv#q5wb+T$Ks+t>$o;0goIB|zJ zHp77bX{L!30_rEzYTxntvMrbhb~Z)%(cg~&eJUUkxa9)Z{8c1z0kV-1=MXq)A`*4B zx7tcxRrUSV_pTCkZuP(1O3U1`gAS(m(Fvt0=xcFlDcrDFLP0^^DAF$s61hztlkg#W zgcsBKe{-%S`3M?+`b)wk+bto>yYE0A*d#Wx`Vvjt_egPUnpoD+8o#A?ddkZAUYhvR zH1{h&L$}vTR!sKqVhP}pXRDX;HSo#p5yxO(`233Wyv`Q?x*$Oz{|$hV`7#^7$<=%Y zCOG8~{*Kq#Zdc-BA@0^IV#XEvHch*@XWFhSDZ>;*PctvB;w9l_jrS*&^>3c(09`bu zM(q!i6HATbWW3TmqXC))_%$4!&tFqaoOn2OSaZ}rG*oQMWuOJxQhdWjiN^^tt9|dP zszlkPHmue^qPvy)jX{5}kRcIaUE1A6k_5GOgxDV=)dcL|;9x$*XePV3xOnv!vs4vT zx<;wyMOxZ~mlZC zXUUCRr2A_tS(P&)rT&io1~y^4-#-m_T#tm8kkWXNf|3FP9MWGJ5nr<^<(Q%0I60m_ zpRts~>W?I;30y500JI~wrz*&4Gr64%kI_nm7W16XRLH#qP>C6oj^DhJ8MqZF|1^Kb z&XjNS@0P#A!|%A^NALI0^Z*-5?aryLzf`#{>)_&uBQ<^F>w-aD!=A9;?CavpkzqeDM< zcygBs$ilVP9rYHcslpQYji62oMPI*%)&w3){qeuP9B2auNGd9YhU{!hU^;sH_FUH~ zI)s|mhdL<$)X;4e(ox9)+d((^!r~8J@I(+9B9PyPIv4i5l13+yWDiOF;C$i3)^E$E z>is;jWxJniYj?J{5h>#}SAo+tAV`R2c-d;a;Q z?CVoP|9*fA`-D|NGDR4@>-iBj^8pcg!4v`{?-i(#_`Imz?>XrKzb}iXz%T T3S9(0p;DIDcvSMx{Pq6;O(Sq@ diff --git a/docs/workloads/index.md b/docs/workloads/index.md index 0f9084c..dbdb9b0 100644 --- a/docs/workloads/index.md +++ b/docs/workloads/index.md @@ -4,7 +4,7 @@ What the fleet can be asked to do. A workload is the `workload` field of a job spec, and which agent claims it is decided by [capabilities](../concepts.md#capabilities) rather than by anything hardcoded. -![The workloads in three columns by who claims them: on the device, on a host, and on a machine](../img/workloads.png) +![Thirty-four workloads in three columns by who claims them: on the device, on a host, and on a machine](../img/workloads.png) The collector ships 34 workloads. `GET /api/v1/workloads` (or `fleetr workloads`) lists the same set with each one's params and an example diff --git a/mkdocs.yml b/mkdocs.yml index 3c8a399..4da58a6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -75,11 +75,7 @@ markdown_extensions: - pymdownx.highlight: anchor_linenums: true - pymdownx.inlinehilite - - pymdownx.superfences: - custom_fences: - - name: mermaid - class: mermaid - format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.superfences - pymdownx.tabbed: alternate_style: true # The cookbook includes the example job specs verbatim from collector/, which From ba14ceff07bfc51f4c99de52d41c93f24ccf6e42 Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 20:51:24 -0400 Subject: [PATCH 04/19] CI smokes for launchd, the Windows task, arm64 and the desktop app; release checks Four GitHub-hosted jobs for the never-run list: fleet / launchd smoke, fleet / windows task smoke, fleet / container smoke (arm64) and desktop / launch smoke. A changelog coverage check for release PRs and a check that marked workload counts in the docs match the catalog. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 38 ++++- .github/workflows/desktop.yml | 63 ++++++++ .github/workflows/fleet.yml | 162 ++++++++++++++++++++- CHANGELOG.md | 2 + CONTRIBUTING.md | 25 +++- README.md | 4 +- collector/README.md | 2 +- collector/scripts/check-counts.ts | 25 ++++ collector/scripts/test.ts | 6 + desktop/ci/launch-smoke.sh | 215 ++++++++++++++++++++++++++++ docs/getting-started.md | 2 +- docs/index.md | 2 +- docs/install/macos.md | 2 +- docs/workloads/index.md | 2 +- scripts/changelog-coverage.mjs | 213 +++++++++++++++++++++++++++ scripts/changelog-coverage.test.mjs | 89 ++++++++++++ scripts/check-counts.mjs | 214 +++++++++++++++++++++++++++ scripts/check-counts.test.mjs | 69 +++++++++ 18 files changed, 1122 insertions(+), 13 deletions(-) create mode 100644 collector/scripts/check-counts.ts create mode 100755 desktop/ci/launch-smoke.sh create mode 100644 scripts/changelog-coverage.mjs create mode 100644 scripts/changelog-coverage.test.mjs create mode 100644 scripts/check-counts.mjs create mode 100644 scripts/check-counts.test.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 826759c..98a62f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -105,6 +105,42 @@ jobs: - uses: actions/checkout@v4 - run: node scripts/version.mjs check + # Also unconditional, and for the same reason as `version`: the numbers it + # checks are written in README.md and docs/, so a docs-only pull request is + # exactly where a stale one arrives, and no component suite runs for that. + repo-scripts: + name: repo scripts + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Unit tests for scripts/ + run: node --test scripts/*.test.mjs + - name: Documented counts match the code + run: node scripts/check-counts.mjs + + # A release pull request -- a `release/*` branch, or `develop` into `main` -- + # must mention every pull request merged into develop since the last tag. + # Every other pull request skips this, and skipped counts as green below. + changelog: + name: changelog coverage + if: >- + github.event_name == 'pull_request' && ( + startsWith(github.head_ref, 'release/') || + (github.head_ref == 'develop' && github.base_ref == 'main')) + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + steps: + - uses: actions/checkout@v4 + with: + # The tags and the whole of develop's history since the last one. + fetch-depth: 0 + - name: Every merged pull request is in the changelog + env: + GH_TOKEN: ${{ github.token }} + run: node scripts/changelog-coverage.mjs --head "${{ github.event.pull_request.head.sha }}" + collector: needs: changes if: needs.changes.outputs.collector == 'true' @@ -142,7 +178,7 @@ jobs: ci-ok: name: ci-ok - needs: [changes, version, collector, runner-android, runner-ios, runner-machine, fleet, runner-roku, desktop] + needs: [changes, version, repo-scripts, changelog, collector, runner-android, runner-ios, runner-machine, fleet, runner-roku, desktop] # Without this the gate inherits the default "only if every dependency # succeeded", which makes a skipped suite skip the gate -- and a skipped # required check never reports, which is the exact bug being fixed. diff --git a/.github/workflows/desktop.yml b/.github/workflows/desktop.yml index ed6870c..2945167 100644 --- a/.github/workflows/desktop.yml +++ b/.github/workflows/desktop.yml @@ -27,3 +27,66 @@ jobs: ./desktop/stage-sidecar.sh - working-directory: desktop/src-tauri run: cargo check --all-targets + + launch: + # The first time the app ever ran was this job. `cargo check` proves the + # Tauri calls exist; this proves the binary starts, spawns `fleet up` as its + # sidecar, stays up, and that its settings window loads and answers over + # IPC. Linux rather than macOS because that is where Tauri's WebDriver + # support exists (tauri-driver wraps WebKitWebDriver; there is no macOS + # driver), and because Xvfb gives it a display without a logged-in desktop. + # What it cannot prove is anything macOS-specific: the tray in the menu bar, + # the Local Network grant, signing. See desktop/README.md. + name: launch smoke + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "22.13" + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + workspaces: desktop/src-tauri + key: linux-launch + # Tauri 2's Linux prerequisites (webkit2gtk 4.1, appindicator for the + # tray), plus what the smoke itself uses: Xvfb for a display, dbus for a + # session bus, WebKitWebDriver for tauri-driver, ImageMagick to capture + # the screen. + - name: Linux dependencies + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev \ + libssl-dev libayatana-appindicator3-dev librsvg2-dev \ + xvfb x11-utils dbus-x11 webkit2gtk-driver imagemagick jq + - name: Stage the fleet sidecar + run: | + npm --prefix collector ci + npm --prefix fleet ci + ./desktop/stage-sidecar.sh + - name: Build the app + working-directory: desktop/src-tauri + # custom-protocol is what `cargo tauri build` turns on: the frontend is + # embedded and served from the binary, as it is in a release, rather + # than expected from a dev server. + run: cargo build --features custom-protocol + - name: tauri-driver + run: cargo install tauri-driver --locked + - name: Launch it + run: ./desktop/ci/launch-smoke.sh + env: + OUT: ${{ runner.temp }}/desktop-smoke + - if: always() + name: What it printed + run: | + for f in "$RUNNER_TEMP"/desktop-smoke/*.log "$RUNNER_TEMP"/desktop-smoke/fleet-home/logs/*.log; do + [ -f "$f" ] || continue + echo "== $f"; tail -80 "$f" + done + - if: always() + uses: actions/upload-artifact@v4 + with: + name: desktop-launch-smoke + path: ${{ runner.temp }}/desktop-smoke + if-no-files-found: warn diff --git a/.github/workflows/fleet.yml b/.github/workflows/fleet.yml index 063754c..ef55942 100644 --- a/.github/workflows/fleet.yml +++ b/.github/workflows/fleet.yml @@ -89,8 +89,21 @@ jobs: # run it the way the docs say, and drive it through the CLI from outside: # a container whose port is published but whose collector never answers is # the failure a `docker build` alone would call green. - name: container smoke - runs-on: ubuntu-latest + # + # The arm64 row builds natively on GitHub's arm64 runner rather than under + # QEMU on the amd64 one. The release publishes linux/arm64 from a QEMU + # build, and an image that only ever ran emulated is the one a Raspberry Pi + # owner would be first to start for real. + name: container smoke${{ matrix.suffix }} + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - runner: ubuntu-latest + suffix: "" + - runner: ubuntu-24.04-arm + suffix: " (arm64)" steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -99,13 +112,21 @@ jobs: cache: npm cache-dependency-path: fleet/package-lock.json - working-directory: . - run: docker build -f fleet/Dockerfile -t fleet:ci . + run: | + docker build -f fleet/Dockerfile -t fleet:ci . + docker image inspect fleet:ci --format 'built for {{.Os}}/{{.Architecture}}' + - working-directory: . run: docker run -d --name fleet -p 8788:8788 fleet:ci up --role brain,agent - name: The collector answers, and the machine agent registers shell: bash + env: + EXPECT_ARCH: ${{ matrix.runner == 'ubuntu-24.04-arm' && 'aarch64' || 'x86_64' }} run: | set -euo pipefail + arch=$(docker exec fleet uname -m) + echo "container is running on $arch" + [ "$arch" = "$EXPECT_ARCH" ] || { echo "::error::expected $EXPECT_ARCH, the container says $arch"; exit 1; } for i in $(seq 1 60); do curl -fsS http://127.0.0.1:8788/api/v1/health && break sleep 2 @@ -165,3 +186,138 @@ jobs: run: | export XDG_RUNTIME_DIR="/run/user/$(id -u)" journalctl --user -u fleet.service --no-pager | tail -100 || true + + launchd: + # The twin of the systemd smoke for macOS. `fleet service install` writes a + # user LaunchAgent and bootstraps it into the gui/ domain; GitHub's + # macOS runners run their jobs inside a logged-in GUI session, so that + # domain exists here the way it does on a desk. The first step says so + # rather than assuming it, because a runner without one would make every + # later failure look like a fleet bug. + name: launchd smoke + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "22.13" + cache: npm + cache-dependency-path: fleet/package-lock.json + - run: npm ci && npm --prefix ../collector ci && npm run build + - name: The runner has a GUI launchd domain + shell: bash + run: | + set -euo pipefail + echo "uid $(id -u), user $(id -un)" + launchctl print "gui/$(id -u)" | head -15 + - name: Install as a LaunchAgent, it serves, and its agent registers + shell: bash + run: | + set -euo pipefail + mkdir -p "$HOME/.fleet" + cp -R dist/. "$HOME/.fleet/" + fleet() { node "$HOME/.fleet/bin/fleet.mjs" "$@"; } + plist="$HOME/Library/LaunchAgents/com.addisdev.fleet.plist" + fleet service install + plutil -lint "$plist" + launchctl print "gui/$(id -u)/com.addisdev.fleet" | head -20 + for i in $(seq 1 60); do + curl -fsS http://127.0.0.1:8788/api/v1/health && break + sleep 2 + done + curl -fsS http://127.0.0.1:8788/api/v1/health >/dev/null + n=0 + for i in $(seq 1 30); do + n=$(fleet devices --url http://127.0.0.1:8788 --json | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>console.log(JSON.parse(s).items.length))') + [ "$n" -gt 0 ] && break + sleep 2 + done + [ "$n" -gt 0 ] || { echo "::error::the agent under launchd never registered"; exit 1; } + fleet devices --url http://127.0.0.1:8788 + fleet service status + # Reinstalling is bootout-then-bootstrap, the race service.ts retries. + # Run it once here so the retry is exercised rather than trusted. + fleet service install + for i in $(seq 1 60); do + curl -fsS http://127.0.0.1:8788/api/v1/health >/dev/null 2>&1 && break + sleep 2 + done + curl -fsS http://127.0.0.1:8788/api/v1/health >/dev/null + fleet service uninstall + sleep 5 + if curl -fsS http://127.0.0.1:8788/api/v1/health 2>/dev/null; then + echo "::error::the collector is still answering after uninstall" + exit 1 + fi + [ ! -e "$plist" ] || { echo "::error::$plist is still there after uninstall"; exit 1; } + if launchctl print "gui/$(id -u)/com.addisdev.fleet" >/dev/null 2>&1; then + echo "::error::launchd still has com.addisdev.fleet loaded after uninstall" + exit 1 + fi + if fleet service status; then + echo "::error::fleet service status exited 0 after uninstall" + exit 1 + fi + - if: failure() + shell: bash + run: | + tail -100 "$HOME/.fleet/logs/fleet.log" || true + for f in "$HOME"/.fleet/logs/*.log; do echo "== $f"; tail -40 "$f"; done || true + + windows-task: + # `fleet service install` on Windows creates a scheduled task that runs + # `fleet up` at logon and starts it at once. Same lifecycle as the systemd + # and launchd smokes: install, it serves, its agent registers, status says + # so, uninstall, and nothing is left answering. + name: windows task smoke + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "22.13" + cache: npm + cache-dependency-path: fleet/package-lock.json + - shell: bash + run: npm ci && npm --prefix ../collector ci && npm run build + - name: Install as a scheduled task, it serves, and its agent registers + shell: bash + run: | + set -euo pipefail + home="$(cygpath -u "$USERPROFILE")/.fleet" + mkdir -p "$home" + cp -R dist/. "$home/" + fleet() { node "$home/bin/fleet.mjs" "$@"; } + fleet service install + schtasks //Query //TN FleetRunner //FO LIST //V + for i in $(seq 1 60); do + curl -fsS http://127.0.0.1:8788/api/v1/health && break + sleep 2 + done + curl -fsS http://127.0.0.1:8788/api/v1/health >/dev/null + n=0 + for i in $(seq 1 30); do + n=$(fleet devices --url http://127.0.0.1:8788 --json | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>console.log(JSON.parse(s).items.length))') + [ "$n" -gt 0 ] && break + sleep 2 + done + [ "$n" -gt 0 ] || { echo "::error::the agent under the scheduled task never registered"; exit 1; } + fleet devices --url http://127.0.0.1:8788 + fleet service status + fleet service uninstall + sleep 5 + if curl -fsS http://127.0.0.1:8788/api/v1/health 2>/dev/null; then + echo "::error::the collector is still answering after uninstall" + exit 1 + fi + if schtasks //Query //TN FleetRunner >/dev/null 2>&1; then + echo "::error::the FleetRunner task is still there after uninstall" + exit 1 + fi + - if: failure() + shell: bash + run: | + home="$(cygpath -u "$USERPROFILE")/.fleet" + schtasks //Query //TN FleetRunner //FO LIST //V || true + for f in "$home"/logs/*.log; do echo "== $f"; tail -60 "$f"; done || true + tasklist //FI "IMAGENAME eq node.exe" || true diff --git a/CHANGELOG.md b/CHANGELOG.md index b1b6bbf..36829f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,11 +25,13 @@ a CI job fails when they disagree. the bundle gains a directory the installers do not copy. The installers are fetched from `main`, so re-running the install command fixes an existing 0.8.0 install; no new release is needed. + ([#86](https://github.com/addisdev/fleet-runner/pull/86)) - **`bug-garden/tools/check-bench.mjs` passed `bench-delete-plant` without checking the plant was gone.** The card's `check` gained `absent_text`, which the harness enforces and the standalone checker ignored; it also matched case-sensitively where the harness does not. It now reads `absent_text` and matches case-insensitively, as the bug garden's README says. + ([#88](https://github.com/addisdev/fleet-runner/pull/88)) ## [0.8.0] — 2026-10-15 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 835d0a2..c86eb27 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -151,7 +151,16 @@ this is the first rule rather than a nice sentiment. - Run the suite for what you touched, and say in the description what you ran. - Update the docs in the same change. The site builds with `--strict`, so a broken link fails CI. -- Add a `CHANGELOG.md` entry under `## [Unreleased]` for anything user-visible. +- Add a `CHANGELOG.md` entry under `## [Unreleased]` for anything user-visible, + ending with a link to the pull request + (`([#86](https://github.com/addisdev/fleet-runner/pull/86))`) once it has a + number. A pull request nobody using Fleet Runner would notice — CI plumbing, + a typo — gets the `no-changelog` label instead. The release check below holds + both to it. +- A number the docs state by hand (how many workloads there are) is marked + `34`. `repo scripts` in `ci.yml` fails when a marked + number disagrees with `collector/src/workloads/catalog.ts`; fix the number, + keep the marker. `ci-ok` is the only required check. It always reports, and it passes when every component suite is green **or skipped** — a change to one runner does not build @@ -161,7 +170,8 @@ the others. One version covers every component, so a release is one number everywhere. -1. On a branch from `develop`, run `node scripts/version.mjs set X.Y.Z`. It +1. On a branch named `release/X.Y.Z` from `develop`, run + `node scripts/version.mjs set X.Y.Z`. It writes `VERSION` and every component's own version except the desktop app's (`desktop/src-tauri/Cargo.toml` and `tauri.conf.json` are not among the places it writes, and still say 0.5.0). Then run @@ -173,6 +183,17 @@ One version covers every component, so a release is one number everywhere. at the bottom. 3. Merge that into `develop`, then open a `develop` → `main` pull request named `Release X.Y.Z` and merge it once `ci-ok` passes. + + On both pull requests `ci.yml` runs `changelog coverage` + (`scripts/changelog-coverage.mjs`). It lists every pull request merged + into `develop` since the last `v*` tag and fails, naming each, if one is + not mentioned as `#N` or a `/pull/N` link between `## [Unreleased]` and the + last release's heading. Label a pull request `no-changelog` to exempt it; + Dependabot's are exempt already. The check only runs when the branch is + `release/*`, or `develop` into `main` — so name the branch that way, or it + will not look. Run it yourself first with + `node scripts/changelog-coverage.mjs --head origin/develop` (it needs `gh` + for the labels). 4. Tag the merge commit on `main` and push the tag: `git tag -a vX.Y.Z -m "vX.Y.Z" && git push origin vX.Y.Z`. diff --git a/README.md b/README.md index c46f42b..b19a08c 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ hardware?** It turned out to be yes, and the fleet is how I know. | **Problem** | Mobile tests and ML benchmarks are only useful when they run on the hardware, under conditions, and with the exact artifacts a product will ship. | | **System** | One collector owns the registry, queue, leases, artifacts, results and dashboard; independently implemented agents claim work through one tested JSON protocol. | | **Reach** | Five runner implementations across TypeScript, Swift, Kotlin, JavaScript and BrightScript, plus host-driven iOS and Android workloads. | -| **Workloads** | 34 workload types spanning UI tests, visual regression, exploratory QA by a vision model, llama.cpp, Core ML, LiteRT, battery experiments, builds and deployment. | +| **Workloads** | 34 workload types spanning UI tests, visual regression, exploratory QA by a vision model, llama.cpp, Core ML, LiteRT, battery experiments, builds and deployment. | | **Proof** | The first production question found an int8 CPU model faster to load and run than its fp32 GPU alternative while preserving useful accuracy. | **What this demonstrates:** distributed systems, mobile platforms, protocol @@ -140,7 +140,7 @@ something a runner can do without the collector shipping a release. ![Twenty-eight workloads in three columns by who claims them: on the device, on a host, and on a machine](docs/img/workloads.png) -Thirty-four workloads (the figure predates six of them, `explore` and `tvloop` +Thirty-four workloads (the figure predates six of them, `explore` and `tvloop` among them), and the column a workload sits in is the answer to "who can physically do this". A benchmark runs inside the app on the phone. An install needs a cable and a Mac. A build needs a checkout and a toolchain. diff --git a/collector/README.md b/collector/README.md index f44d9fd..dc85912 100644 --- a/collector/README.md +++ b/collector/README.md @@ -99,7 +99,7 @@ so it never touches a real fleet's history. | `model-convert` / `dataset-prep` | machine | A checkpoint into GGUF, Core ML or TFLite; an eval set that carries its licence and source | | `serve` / `shell` | machine | Host a model for the length of a lease; run a script whose hash the machine's owner pinned by hand | -That is all 34 shipped workloads. `GET /api/v1/workloads` (or `fleetr +That is all 34 shipped workloads. `GET /api/v1/workloads` (or `fleetr workloads`) lists them with their params and an example spec, plus anything a registered agent declares that the collector does not know. diff --git a/collector/scripts/check-counts.ts b/collector/scripts/check-counts.ts new file mode 100644 index 0000000..76a0c37 --- /dev/null +++ b/collector/scripts/check-counts.ts @@ -0,0 +1,25 @@ +/** + * scripts/check-counts.mjs reads the catalog right. + * + * That script counts shipped workloads by reading catalog.ts as text, so it can + * run on every pull request without `npm ci` and check the numbers the README + * and the docs state by hand. Reading TypeScript as text is a guess about its + * shape; this imports the real CATALOG and fails if the guess and the truth + * disagree, so a refactor of catalog.ts cannot quietly turn the docs check into + * a check of the wrong number. + */ +import { execFileSync } from "node:child_process"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { CATALOG } from "../src/workloads/catalog.js"; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); +const truth = CATALOG.filter((w) => w.status !== "reserved").length; +const out = execFileSync(process.execPath, [path.join(ROOT, "scripts/check-counts.mjs"), "--json"], { encoding: "utf8" }); +const parsed = (JSON.parse(out) as { workloads: number }).workloads; + +if (parsed !== truth) { + console.error(` FAIL scripts/check-counts.mjs counts ${parsed} shipped workloads; CATALOG has ${truth}`); + process.exit(1); +} +console.log(` ok scripts/check-counts.mjs and CATALOG agree: ${truth} shipped workloads`); diff --git a/collector/scripts/test.ts b/collector/scripts/test.ts index dd1a2b6..8d98c6a 100644 --- a/collector/scripts/test.ts +++ b/collector/scripts/test.ts @@ -183,6 +183,12 @@ if (!(await run(process.execPath, [TSX, "scripts/check-metrics.ts"]))) failed = step("workload table matches the directories"); if (!(await run(process.execPath, [TSX, "scripts/check-workloads.ts"]))) failed = true; +// The README and the docs state the workload count by hand, marked with +// . ci.yml checks the marks on every pull request by +// reading catalog.ts as text; this is what keeps that reading honest. +step("documented counts read the catalog right"); +if (!(await run(process.execPath, [TSX, "scripts/check-counts.ts"]))) failed = true; + // The shelf picks each device's drawing from its model string; the real // fleet's strings are the fixtures, so a regex change cannot quietly redraw // a device that is actually on the shelf. diff --git a/desktop/ci/launch-smoke.sh b/desktop/ci/launch-smoke.sh new file mode 100755 index 0000000..18ca7ba --- /dev/null +++ b/desktop/ci/launch-smoke.sh @@ -0,0 +1,215 @@ +#!/usr/bin/env bash +# Launch the desktop app on Linux under a virtual display and prove it ran. +# +# Run by `desktop / launch smoke` in .github/workflows/desktop.yml, after +# `./stage-sidecar.sh` and `cargo build --features custom-protocol` in +# src-tauri/. It needs Xvfb, dbus-launch, ImageMagick's `import`, curl, jq, +# and -- for the second half -- `tauri-driver` and `WebKitWebDriver` on PATH. +# +# Two halves, because they prove different things: +# +# 1. The process. Start the binary as a person would, with no config file, and +# watch for what it is supposed to do at launch: spawn `fleet up` as its +# sidecar, which starts a collector on :8788 whose agent registers. Then +# check the app is still up after a while, because a Tauri app that panics +# in its event loop does so after setup has already returned. +# 2. The window. Start it again under tauri-driver, the WebDriver server Tauri +# publishes, and drive the settings window from outside: that the page +# loaded, that `window.__TAURI__` exists, that a #[tauri::command] answers +# over IPC, and a screenshot of what it drew. +# +# Everything lands in $OUT (default $RUNNER_TEMP/desktop-smoke) for the +# workflow to upload, pass or fail. +set -euo pipefail + +here=$(cd "$(dirname "$0")" && pwd) +tauri="$here/../src-tauri" +bin="$tauri/target/debug" +app="$bin/fleet-desktop" +out="${OUT:-${RUNNER_TEMP:-/tmp}/desktop-smoke}" +mkdir -p "$out" + +port=8788 +base="http://127.0.0.1:$port" + +# A fleet home of its own, so the run cannot read or write anybody's +# ~/.fleet. config.rs and the CLI both honour FLEET_HOME, and the sidecar +# inherits this environment. +export FLEET_HOME="$out/fleet-home" +rm -rf "$FLEET_HOME" + +# The sidecar shim checks /usr/local/bin/node before PATH, on purpose (a +# Finder-launched app has no Homebrew on PATH). GitHub's Ubuntu image keeps an +# older Node there, below the 22.13 node:sqlite needs, so the one setup-node +# installed is named explicitly -- the same escape hatch a person would use. +export FLEET_NODE="${FLEET_NODE:-$(command -v node)}" +echo "node: $FLEET_NODE ($("$FLEET_NODE" --version))" + +fleet() { "$FLEET_NODE" "$tauri/resources/fleet/bin/fleet.mjs" "$@"; } + +fail() { echo "::error::$*"; exit 1; } + +echo "== what cargo build put beside the binary" +ls -la "$bin" | grep -E 'fleet' || true +[ -x "$app" ] || fail "$app was not built" +[ -x "$bin/fleet" ] || fail "the sidecar shim was not copied to $bin/fleet" +[ -f "$bin/fleet-tree/bin/fleet.mjs" ] || fail "the fleet tree was not copied to $bin/fleet-tree" + +echo "== virtual display and session bus" +export DISPLAY=:99 +Xvfb "$DISPLAY" -screen 0 1280x800x24 >"$out/xvfb.log" 2>&1 & +xvfb=$! +for _ in $(seq 1 50); do xdpyinfo >/dev/null 2>&1 && break; sleep 0.2; done +xdpyinfo >/dev/null 2>&1 || fail "Xvfb did not come up" +eval "$(dbus-launch --sh-syntax)" + +health() { curl -fsS --max-time 2 "$base/api/v1/health" >/dev/null 2>&1; } + +device_count() { + local n + n=$(fleet devices --url "$base" --json 2>/dev/null | jq '.items | length' 2>/dev/null || true) + echo "${n:-0}" +} + +wait_for_fleet() { + local pid=$1 + for _ in $(seq 1 90); do + kill -0 "$pid" 2>/dev/null || fail "the app exited before its sidecar answered (see app.log)" + health && break + sleep 1 + done + health || fail "nothing answered $base/api/v1/health within 90s of launch" + local n=0 + for _ in $(seq 1 45); do + n=$(device_count) + [ "$n" -gt 0 ] && break + sleep 1 + done + [ "$n" -gt 0 ] || fail "the sidecar's collector answered but its agent never registered" + echo "sidecar up: collector answers, $n device(s) registered" +} + +# `fleet up` writes its own pid to logs/supervisor.json. Used to clean up +# between the halves -- by pid, never by name -- and to see whether quitting the +# app took the sidecar with it. +sidecar_pid() { jq -r '.pid // empty' "$FLEET_HOME/logs/supervisor.json" 2>/dev/null || true; } + +stop_sidecar() { + local spid + spid=$(sidecar_pid) + if [ -n "$spid" ] && kill -0 "$spid" 2>/dev/null; then + kill -TERM "$spid" || true + for _ in $(seq 1 30); do kill -0 "$spid" 2>/dev/null || break; sleep 0.5; done + fi + for _ in $(seq 1 20); do health || break; sleep 0.5; done + if health; then fail "something still answers $base after stopping the sidecar"; fi +} + +# --- 1. the process --------------------------------------------------------- +echo "== half 1: launch the binary" +health && fail "something is already on $base before launch; the app would refuse to start its sidecar" +"$app" >"$out/app.log" 2>&1 & +apppid=$! +echo "app pid $apppid" +wait_for_fleet "$apppid" +fleet devices --url "$base" | tee "$out/devices.txt" + +settle=${SETTLE_S:-20} +echo "waiting ${settle}s to see that the app stays up" +sleep "$settle" +kill -0 "$apppid" 2>/dev/null || fail "the app died within ${settle}s of launch (see app.log)" +health || fail "the sidecar stopped answering within ${settle}s of launch" +echo "app still running after ${settle}s, sidecar still answering" +import -window root "$out/screen-after-launch.png" || echo "warning: import could not capture the screen" + +# What happens to the sidecar when the app is SIGTERMed (a logout, a `kill`). +# Recorded, not asserted: see the README's Status section for what was seen. +spid=$(sidecar_pid) +kill -TERM "$apppid" || true +for _ in $(seq 1 30); do kill -0 "$apppid" 2>/dev/null || break; sleep 0.5; done +sleep 3 +if [ -n "$spid" ] && kill -0 "$spid" 2>/dev/null; then + echo "after SIGTERM to the app: its sidecar (pid $spid) is STILL RUNNING" | tee "$out/sigterm.txt" +else + echo "after SIGTERM to the app: its sidecar is gone" | tee "$out/sigterm.txt" +fi +stop_sidecar + +# --- 2. the window, under tauri-driver --------------------------------------- +if [ "${SKIP_DRIVER:-}" = "1" ]; then + echo "SKIP_DRIVER=1; not driving the window" + kill "$xvfb" 2>/dev/null || true + exit 0 +fi + +echo "== half 2: drive the settings window through tauri-driver" +command -v tauri-driver >/dev/null || fail "tauri-driver is not on PATH" +command -v WebKitWebDriver >/dev/null || fail "WebKitWebDriver is not on PATH (apt: webkit2gtk-driver)" +tauri-driver --port 4444 >"$out/tauri-driver.log" 2>&1 & +driver=$! +for _ in $(seq 1 50); do curl -fsS http://127.0.0.1:4444/status >/dev/null 2>&1 && break; sleep 0.2; done + +wd() { # method path [json] + local method=$1 path=$2 body=${3:-} + if [ -n "$body" ]; then + curl -sS --max-time 60 -X "$method" -H 'content-type: application/json' -d "$body" "http://127.0.0.1:4444$path" + else + curl -sS --max-time 60 -X "$method" "http://127.0.0.1:4444$path" + fi +} + +caps=$(jq -n --arg app "$(cd "$bin" && pwd)/fleet-desktop" \ + '{capabilities:{alwaysMatch:{"tauri:options":{application:$app}}}}') +session=$(wd POST /session "$caps") +echo "$session" > "$out/webdriver-session.json" +sid=$(echo "$session" | jq -r '.value.sessionId // empty') +[ -n "$sid" ] || fail "tauri-driver did not open a session: $(echo "$session" | head -c 600)" +echo "webdriver session $sid" + +cleanup_driver() { + wd DELETE "/session/$sid" >/dev/null 2>&1 || true + kill "$driver" 2>/dev/null || true +} +trap cleanup_driver EXIT + +# The app under the driver autostarts its sidecar too. +for _ in $(seq 1 90); do health && break; sleep 1; done +health || fail "under tauri-driver, the sidecar never answered" + +title=$(wd GET "/session/$sid/title" | jq -r '.value') +echo "window title: $title" +[ "$title" = "Fleet" ] || fail "expected the settings window titled Fleet, got '$title'" + +has_tauri=$(wd POST "/session/$sid/execute/sync" \ + '{"script":"return typeof window.__TAURI__ === \"object\" && typeof window.__TAURI__.core.invoke === \"function\"","args":[]}' \ + | jq -r '.value') +[ "$has_tauri" = "true" ] || fail "window.__TAURI__ is missing from the settings page (got $has_tauri)" + +status=$(wd POST "/session/$sid/execute/async" \ + '{"script":"const done = arguments[arguments.length - 1]; window.__TAURI__.core.invoke(\"get_status\").then((s) => done(s), (e) => done({ error: String(e) }));","args":[]}') +echo "$status" | jq '.value' > "$out/get_status.json" +cat "$out/get_status.json" +[ "$(echo "$status" | jq -r '.value.running')" = "true" ] \ + || fail "get_status over IPC did not say the sidecar is running" + +# The settings window starts hidden -- the app lives in the tray -- so it is +# shown the way the tray's Settings item would, from inside the page, before +# the screenshot. +wd POST "/session/$sid/execute/async" \ + '{"script":"const done = arguments[arguments.length - 1]; window.__TAURI__.window.getCurrentWindow().show().then(() => done(true), (e) => done(String(e)));","args":[]}' \ + | jq -c '.value' +sleep 2 +headline=$(wd POST "/session/$sid/execute/sync" \ + '{"script":"const h = document.getElementById(\"headline\"); return h ? h.textContent : null","args":[]}' | jq -r '.value') +echo "settings window headline: $headline" +wd GET "/session/$sid/screenshot" | jq -r '.value' | base64 -d > "$out/settings-window.png" \ + || echo "warning: the webdriver screenshot failed" +import -window root "$out/screen-settings.png" || true +file "$out"/*.png || true + +cleanup_driver +trap - EXIT +sleep 3 +stop_sidecar +kill "$xvfb" 2>/dev/null || true +echo "desktop launch smoke: ok" diff --git a/docs/getting-started.md b/docs/getting-started.md index 13bf3aa..6f5cd5c 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -382,7 +382,7 @@ it needs on `PATH`. - **[Concepts](concepts.md)** -- leases, capabilities and targeting, which is what you need before writing a job spec that does something interesting. -- **[Workloads](workloads/index.md)** -- the other thirty-odd things it can run. +- **[Workloads](workloads/index.md)** -- all 34 things it can run. - **[Exploratory QA](explore/index.md)** -- a vision model using tonight's build overnight, and the bugs it reproduces. - **[AI agents and automation](agents.md)** -- `fleetr`, the skill and the MCP diff --git a/docs/index.md b/docs/index.md index 109ac8e..cec7b1d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -49,7 +49,7 @@ fleet on. The answer is macOS; the suites run on all three. --- - All 34 of them, what each measures, and what each refuses to guess. + All 34 of them, what each measures, and what each refuses to guess. - __[Exploratory QA](explore/index.md)__ diff --git a/docs/install/macos.md b/docs/install/macos.md index 59d29a1..988891f 100644 --- a/docs/install/macos.md +++ b/docs/install/macos.md @@ -75,7 +75,7 @@ and the host executor inside it, beside the browser runner and the dashboard in the same relative layout a checkout has. It runs with no `node_modules` anywhere near it, which is the property a release is for and the one that would have broken silently. Only Playwright stays outside -- 400 MB of browser needed -by four of thirty workloads, made a dynamic import so an executor without it +by four of the 34 workloads, made a dynamic import so an executor without it starts fine and says so. ## `fleet up` diff --git a/docs/workloads/index.md b/docs/workloads/index.md index 0f9084c..39516db 100644 --- a/docs/workloads/index.md +++ b/docs/workloads/index.md @@ -6,7 +6,7 @@ spec, and which agent claims it is decided by ![The workloads in three columns by who claims them: on the device, on a host, and on a machine](../img/workloads.png) -The collector ships 34 workloads. `GET /api/v1/workloads` (or +The collector ships 34 workloads. `GET /api/v1/workloads` (or `fleetr workloads`) lists the same set with each one's params and an example spec, and marks three more names as reserved: `push-latency`, `camera-eval` and `desktop-ui-test` are accepted, but no runner in this repository implements diff --git a/scripts/changelog-coverage.mjs b/scripts/changelog-coverage.mjs new file mode 100644 index 0000000..8e74370 --- /dev/null +++ b/scripts/changelog-coverage.mjs @@ -0,0 +1,213 @@ +#!/usr/bin/env node +/** + * Every pull request in a release is in its changelog. + * + * node scripts/changelog-coverage.mjs [--head ] [--tag ] + * + * Lists the pull requests merged into `develop` since the last `v*` tag and + * fails, naming each one, if the changelog section being released does not + * mention it as `#N` or `/pull/N`. A pull request labelled `no-changelog`, and + * any opened by Dependabot, is exempt. + * + * ## Why + * + * 0.8.0 shipped with notes that left out work merged before it was cut -- + * exploratory QA among it -- and nobody noticed until an audit read the + * history against the notes a day later. The changelog had to be amended after + * the release. A list of merged pull requests is cheap to compute and a human + * reading a long `[Unreleased]` section is not a reliable diff. + * + * ## What "since the last tag" means + * + * The commits on ``'s first-parent chain that the newest `v*` tag does + * not contain. On a `release/*` branch cut from `develop`, and on the + * `develop` -> `main` pull request, that chain is `develop`'s own history, so + * its merge commits are exactly the pull requests merged into `develop` since + * the tag. Both a merge commit (`Merge pull request #N from ...`) and a squash + * merge (`Title (#N)`) are recognised. + * + * ## What "the section being released" means + * + * Everything from `## [Unreleased]` down to the heading of the last tag's + * version. CONTRIBUTING.md has a release rename `[Unreleased]` to the new + * version and add an empty `[Unreleased]` above it, and before that rename the + * notes are all under `[Unreleased]`; this range is right either way. + * + * Labels and authors are read from the GitHub API with `gh` (GH_TOKEN in CI), + * and only for the pull requests the changelog does not mention, so a + * complete changelog needs no network at all. + * + * Plain Node, no dependencies, like scripts/version.mjs. + */ +import { execFileSync } from "node:child_process"; +import { readFileSync } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); + +export const EXEMPT_LABEL = "no-changelog"; +/** `dependabot[bot]` from the REST API, `app/dependabot` from `gh pr view`. */ +export const isDependabot = (author) => /(^|\/)dependabot(-preview)?(\[bot\])?$/.test(author ?? ""); + +/** + * Pull request numbers from commit subjects, oldest first, without repeats. + * + * Only subjects that look like GitHub's own merge commits count. A commit that + * merely mentions `#12` in passing ("revert the fix from #12") is not a pull + * request being merged, and listing it would make the check cry wolf. + */ +export function prNumbersFromSubjects(subjects) { + const seen = new Set(); + const out = []; + for (const s of subjects) { + const m = /^Merge pull request #(\d+) from /.exec(s) ?? /\(#(\d+)\)\s*$/.exec(s); + if (!m) continue; + const n = Number(m[1]); + if (!seen.has(n)) { + seen.add(n); + out.push(n); + } + } + return out.reverse(); +} + +/** + * The text from `## [Unreleased]` to the heading for `sinceVersion`. + * + * Throws when either heading is missing: a changelog this cannot read is a + * changelog this cannot check, and passing would be a lie. + */ +export function releasedSection(changelog, sinceVersion) { + const lines = changelog.split(/\r?\n/); + const start = lines.findIndex((l) => /^## \[Unreleased\]/i.test(l)); + if (start < 0) throw new Error("CHANGELOG.md has no `## [Unreleased]` heading"); + const escaped = sinceVersion.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + const endRe = new RegExp(`^## \\[${escaped}\\]`); + const end = lines.findIndex((l, i) => i > start && endRe.test(l)); + if (end < 0) { + throw new Error(`CHANGELOG.md has no \`## [${sinceVersion}]\` heading below [Unreleased]`); + } + return lines.slice(start, end).join("\n"); +} + +/** Pull request numbers a section mentions, as `#N` or as a `/pull/N` link. */ +export function mentionedNumbers(section) { + const found = new Set(); + for (const m of section.matchAll(/(?:^|[^\w&])#(\d+)\b/g)) found.add(Number(m[1])); + for (const m of section.matchAll(/\/pull\/(\d+)\b/g)) found.add(Number(m[1])); + return found; +} + +/** + * The verdict, given everything already fetched. + * + * `meta` maps a pull request number to `{ labels: string[], author: string }` + * for the ones that needed looking up; a number with no entry is treated as + * unlabelled, so a lookup that failed fails the check rather than excusing it. + */ +export function coverage({ merged, mentioned, meta = new Map() }) { + const missing = []; + const exempt = []; + for (const n of merged) { + if (mentioned.has(n)) continue; + const m = meta.get(n); + if (m && (m.labels.includes(EXEMPT_LABEL) || isDependabot(m.author))) { + exempt.push({ number: n, why: m.labels.includes(EXEMPT_LABEL) ? EXEMPT_LABEL : m.author }); + continue; + } + missing.push({ number: n, title: m?.title ?? "" }); + } + return { missing, exempt }; +} + +/** The newest `v*` tag by version order, or null. */ +export function newestTag(tags) { + const parsed = tags + .map((t) => ({ t, m: /^v(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/.exec(t.trim()) })) + .filter((x) => x.m); + parsed.sort((a, b) => { + for (let i = 1; i <= 3; i++) { + const d = Number(b.m[i]) - Number(a.m[i]); + if (d) return d; + } + // 1.0.0 is newer than 1.0.0-rc.1. + if (!a.m[4] !== !b.m[4]) return a.m[4] ? 1 : -1; + return (b.m[4] ?? "").localeCompare(a.m[4] ?? "", undefined, { numeric: true }); + }); + return parsed[0]?.t.trim() ?? null; +} + +// --- the command ------------------------------------------------------------ + +function git(...args) { + return execFileSync("git", args, { cwd: ROOT, encoding: "utf8" }); +} + +function prMeta(numbers) { + const meta = new Map(); + for (const n of numbers) { + try { + const json = execFileSync( + "gh", + ["pr", "view", String(n), "--json", "labels,author,title"], + { cwd: ROOT, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }, + ); + const pr = JSON.parse(json); + meta.set(n, { + labels: (pr.labels ?? []).map((l) => l.name), + author: pr.author?.login ?? "", + title: pr.title ?? "", + }); + } catch (e) { + console.error(` could not read #${n} from GitHub (${(e.stderr || e.message || "").toString().trim()}); treating it as unlabelled`); + } + } + return meta; +} + +function main(argv) { + const flag = (name) => { + const i = argv.indexOf(name); + return i >= 0 ? argv[i + 1] : undefined; + }; + const head = flag("--head") ?? "HEAD"; + const tag = flag("--tag") ?? newestTag(git("tag", "--list", "v*").split("\n").filter(Boolean)); + if (!tag) { + console.error("no v* tag in this checkout. In CI, check out with fetch-depth: 0 so the tags come too."); + return 1; + } + const version = tag.replace(/^v/, ""); + + const subjects = git("log", "--first-parent", "--format=%s", `${tag}..${head}`).split("\n").filter(Boolean); + const merged = prNumbersFromSubjects(subjects); + + let section; + try { + section = releasedSection(readFileSync(path.join(ROOT, "CHANGELOG.md"), "utf8"), version); + } catch (e) { + console.error(e.message); + return 1; + } + const mentioned = mentionedNumbers(section); + const unmentioned = merged.filter((n) => !mentioned.has(n)); + const { missing, exempt } = coverage({ merged, mentioned, meta: prMeta(unmentioned) }); + + console.log(`${merged.length} pull request(s) merged since ${tag}: ${merged.map((n) => `#${n}`).join(" ") || "none"}`); + for (const e of exempt) console.log(` exempt #${e.number} (${e.why})`); + if (missing.length === 0) { + console.log(`every one is in the changelog between [Unreleased] and [${version}]`); + return 0; + } + console.error(`\nnot mentioned in CHANGELOG.md between [Unreleased] and [${version}]:`); + for (const m of missing) console.error(` #${m.number}${m.title ? ` ${m.title}` : ""}`); + console.error( + `\nAdd each to the section being released (as #N or a /pull/N link), or label it ` + + `\`${EXEMPT_LABEL}\` if nobody using Fleet Runner would notice it.`, + ); + return 1; +} + +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + process.exit(main(process.argv.slice(2))); +} diff --git a/scripts/changelog-coverage.test.mjs b/scripts/changelog-coverage.test.mjs new file mode 100644 index 0000000..39ecaee --- /dev/null +++ b/scripts/changelog-coverage.test.mjs @@ -0,0 +1,89 @@ +// node --test scripts/ +import assert from "node:assert/strict"; +import { test } from "node:test"; +import { + coverage, + isDependabot, + mentionedNumbers, + newestTag, + prNumbersFromSubjects, + releasedSection, +} from "./changelog-coverage.mjs"; + +test("merge commits and squash merges both count; passing mentions do not", () => { + const subjects = [ + "Merge pull request #91 from addisdev/ci/never-run-list", + "Release notes for 0.9.0", + "Fix the thing (#90)", + "Revert the fix from #12", + "Merge branch 'develop' into feature", + "Merge pull request #88 from addisdev/docs/0.8-catchup", + "Merge pull request #91 from addisdev/ci/never-run-list", + ]; + // git log is newest first; the list comes back oldest first, once each. + assert.deepEqual(prNumbersFromSubjects(subjects), [88, 90, 91]); +}); + +const CHANGELOG = `# Changelog + +## [Unreleased] + +## [0.9.0] — 2026-11-01 + +### Added + +- **A thing.** ([#90](https://github.com/addisdev/fleet-runner/pull/90)) +- **Another**, see #91. +- Not a PR: ] or issue#94. + +## [0.8.0] — 2026-10-15 + +- **Old.** #88 +`; + +test("the section runs from [Unreleased] down to the last tag's heading", () => { + const s = releasedSection(CHANGELOG, "0.8.0"); + assert.match(s, /^## \[Unreleased\]/); + assert.match(s, /## \[0\.9\.0\]/); + assert.doesNotMatch(s, /Old\./); +}); + +test("a changelog without the headings is an error, not a pass", () => { + assert.throws(() => releasedSection("# Changelog\n", "0.8.0"), /Unreleased/); + assert.throws(() => releasedSection("## [Unreleased]\n- x\n", "0.8.0"), /0\.8\.0/); + // 0.8.0 must not match 0.8.01 or 0x8y0. + assert.throws(() => releasedSection("## [Unreleased]\n## [0x8y0]\n", "0.8.0"), /0\.8\.0/); +}); + +test("#N and /pull/N are mentions; HTML entities and word#N are not", () => { + const m = mentionedNumbers(releasedSection(CHANGELOG, "0.8.0")); + assert.deepEqual([...m].sort(), [90, 91]); +}); + +test("missing PRs are listed; no-changelog and Dependabot are exempt", () => { + const meta = new Map([ + [92, { labels: ["no-changelog"], author: "addisdev", title: "CI tweak" }], + [93, { labels: [], author: "app/dependabot", title: "Bump x" }], + [94, { labels: ["docs"], author: "addisdev", title: "Forgotten" }], + ]); + const { missing, exempt } = coverage({ + merged: [88, 90, 91, 92, 93, 94, 95], + mentioned: new Set([90, 91, 88]), + meta, + }); + assert.deepEqual(missing.map((m) => m.number), [94, 95]); + assert.equal(missing[0].title, "Forgotten"); + assert.deepEqual(exempt.map((e) => e.number), [92, 93]); +}); + +test("Dependabot is recognised however the API spells it", () => { + for (const a of ["dependabot[bot]", "app/dependabot", "dependabot"]) assert.ok(isDependabot(a), a); + for (const a of ["addisdev", "not-dependabot-really", ""]) assert.ok(!isDependabot(a), a); +}); + +test("the newest tag is chosen by version, not by string order", () => { + assert.equal(newestTag(["v0.7.2", "v0.10.0", "v0.9.1"]), "v0.10.0"); + assert.equal(newestTag(["v1.0.0-rc.1", "v1.0.0", "v0.9.0"]), "v1.0.0"); + assert.equal(newestTag(["v1.0.0-rc.2", "v1.0.0-rc.10", "v0.9.0"]), "v1.0.0-rc.10"); + assert.equal(newestTag(["latest", "nightly"]), null); +}); diff --git a/scripts/check-counts.mjs b/scripts/check-counts.mjs new file mode 100644 index 0000000..e515a0a --- /dev/null +++ b/scripts/check-counts.mjs @@ -0,0 +1,214 @@ +#!/usr/bin/env node +/** + * The numbers the docs state by hand agree with the code. + * + * node scripts/check-counts.mjs # exit 1 on any disagreement + * node scripts/check-counts.mjs --json # print the counts and exit + * + * The README and the docs said "28 workloads" while the catalog grew to 34, + * and nothing noticed. A number written in prose cannot be generated without + * turning the prose into a template, so instead each one is marked where it + * stands and this checks the marks: + * + * The collector ships 34 workloads. + * Thirty-four workloads ... + * + * The comment is invisible on GitHub and in the mkdocs site. The number right + * after it -- digits, or words up to ninety-nine -- is compared with the count, + * and a mismatch fails with the file, the line and what it should say. + * + * ## Where the count comes from + * + * `workloads` is the number of entries in `CATALOG` in + * collector/src/workloads/catalog.ts that are not `reserved(...)`. It is read as + * text rather than imported, so this runs with no `npm ci` and can sit in a job + * that runs on every pull request, docs-only ones included -- a docs change is + * exactly where a stale number gets written. The collector's own suite imports + * the real `CATALOG` and checks this parse against it + * (collector/scripts/check-counts.ts), so the text reading cannot drift away + * from what the catalog actually holds without that suite failing. + * + * Plain Node, no dependencies, like scripts/version.mjs. + */ +import { readdirSync, readFileSync, statSync } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const CATALOG = "collector/src/workloads/catalog.ts"; + +/** + * Shipped and reserved entries in the CATALOG array literal. + * + * Each entry is one call at the array's top level: `e(...)` or + * `fromManifest(...)` for shipped, `reserved(...)` for reserved. Anything else + * at that level -- a spread, an inline object -- throws, because a parse that + * silently skips an entry is a check that silently passes. + */ +export function countCatalog(src) { + const start = src.indexOf("export const CATALOG"); + if (start < 0) throw new Error(`no \`export const CATALOG\` in ${CATALOG}`); + const open = src.indexOf("[", src.indexOf("=", start)); + let depth = 0; + let i = open; + let entryStart = -1; + const entries = []; + let inString = null; + for (; i < src.length; i++) { + const c = src[i]; + if (inString) { + if (c === "\\") i++; + else if (c === inString) inString = null; + continue; + } + if (c === '"' || c === "'" || c === "`") { + inString = c; + continue; + } + if (c === "/" && src[i + 1] === "/") { + i = src.indexOf("\n", i); + continue; + } + if (c === "/" && src[i + 1] === "*") { + i = src.indexOf("*/", i) + 1; + continue; + } + if (c === "[" || c === "(" || c === "{") { + depth++; + if (depth === 2 && entryStart < 0) entryStart = i; + continue; + } + if (c === "]" || c === ")" || c === "}") { + depth--; + if (depth === 0) break; + continue; + } + if (depth === 1 && /\S/.test(c) && c !== ",") { + if (entryStart < 0) entryStart = i; + } + if (depth === 1 && c === "," && entryStart >= 0) { + entries.push(src.slice(entryStart, i).trim()); + entryStart = -1; + } + } + if (depth !== 0) throw new Error(`the CATALOG array in ${CATALOG} never closes`); + if (entryStart >= 0) { + const last = src.slice(entryStart, i).trim(); + if (last) entries.push(last); + } + let shipped = 0; + let reserved = 0; + for (const entry of entries) { + const callee = /^([A-Za-z_$][\w$]*)\s*\(/.exec(entry)?.[1]; + if (callee === "reserved") reserved++; + else if (callee === "e" || callee === "fromManifest") shipped++; + else throw new Error(`cannot tell whether this CATALOG entry is shipped: ${entry.slice(0, 80)}`); + } + if (shipped === 0) throw new Error(`counted no shipped workloads in ${CATALOG}; this check needs updating`); + return { shipped, reserved }; +} + +const ONES = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", + "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]; +const TENS = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]; + +/** `34`, `thirty-four`, `Thirty four` -> 34. Null for anything else. */ +export function parseCount(text) { + const t = text.trim().toLowerCase(); + if (/^\d+$/.test(t)) return Number(t); + const words = t.split(/[-\s]+/); + if (words.length === 1) { + const one = ONES.indexOf(words[0]); + if (one >= 0) return one; + const ten = TENS.indexOf(words[0]); + return ten >= 2 ? ten * 10 : null; + } + if (words.length === 2) { + const ten = TENS.indexOf(words[0]); + const one = ONES.indexOf(words[1]); + if (ten >= 2 && one >= 1 && one <= 9) return ten * 10 + one; + } + return null; +} + +const MARKER = /\s*([0-9]+|[A-Za-z]+(?:[-\s][A-Za-z]+)?)/g; + +/** Every marked number in a file: `{ key, text, value, line }`. */ +export function findMarkers(text) { + const out = []; + for (const m of text.matchAll(MARKER)) { + let token = m[2]; + // "thirty-four workloads": keep the second word only if it is a units word. + let value = parseCount(token); + if (value === null && /[-\s]/.test(token)) { + token = token.split(/[-\s]/)[0]; + value = parseCount(token); + } + const line = text.slice(0, m.index).split("\n").length; + out.push({ key: m[1], text: token, value, line }); + } + return out; +} + +/** + * Problems, as strings. `files` is `[{ path, text }]`; `counts` maps a marker + * key to the true number. + */ +export function check(files, counts) { + const problems = []; + let seen = 0; + for (const f of files) { + for (const mark of findMarkers(f.text)) { + seen++; + const where = `${f.path}:${mark.line}`; + if (!(mark.key in counts)) { + problems.push(`${where}: unknown count "${mark.key}" (known: ${Object.keys(counts).join(", ")})`); + } else if (mark.value === null) { + problems.push(`${where}: "${mark.text}" after is not a number`); + } else if (mark.value !== counts[mark.key]) { + problems.push(`${where}: says ${mark.text}, but there are ${counts[mark.key]} ${mark.key}`); + } + } + } + if (seen === 0) problems.push("found no markers at all, so nothing was checked"); + return { problems, seen }; +} + +/** Markdown files worth checking: the READMEs and docs/, never dependencies. */ +function markdownFiles(dir = ROOT, rel = "") { + const out = []; + for (const name of readdirSync(dir)) { + if (name === "node_modules" || name.startsWith(".") || name === "site" || name === "dist" || name === "build") continue; + const abs = path.join(dir, name); + const r = rel ? `${rel}/${name}` : name; + if (statSync(abs).isDirectory()) out.push(...markdownFiles(abs, r)); + else if (name.endsWith(".md")) out.push(r); + } + return out; +} + +export function counts() { + const { shipped } = countCatalog(readFileSync(path.join(ROOT, CATALOG), "utf8")); + return { workloads: shipped }; +} + +function main(argv) { + const c = counts(); + if (argv.includes("--json")) { + console.log(JSON.stringify(c)); + return 0; + } + const files = markdownFiles().map((p) => ({ path: p, text: readFileSync(path.join(ROOT, p), "utf8") })); + const { problems, seen } = check(files, c); + if (problems.length) { + for (const p of problems) console.error(` ${p}`); + console.error(`\n${problems.length} documented count(s) disagree with the code. Fix the number after the marker.`); + return 1; + } + console.log(`ok -- ${seen} marked count(s) agree: ${Object.entries(c).map(([k, v]) => `${v} ${k}`).join(", ")}`); + return 0; +} + +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + process.exit(main(process.argv.slice(2))); +} diff --git a/scripts/check-counts.test.mjs b/scripts/check-counts.test.mjs new file mode 100644 index 0000000..3537c0d --- /dev/null +++ b/scripts/check-counts.test.mjs @@ -0,0 +1,69 @@ +// node --test scripts/ +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { test } from "node:test"; +import { check, countCatalog, findMarkers, parseCount } from "./check-counts.mjs"; + +const CATALOG = ` +const e = () => ({}); +export const CATALOG: CatalogEntry[] = [ + e("benchmark", "device", ["device", "machine"], "Prefill (and) decode, [sic] {x}.", "device.md", benchmark), + // e("commented-out", ...) is not an entry + fromManifest(enrolManifest as Manifest, "host.md"), + /* reserved("also-not", ...) */ + e("web-test", "host", ["host"], "Playwright \\"suites\\", one, two.", "host.md", webTest, { dangerous: true }), + reserved("serve", "host", ["host"], "Serve a model."), +]; +export const OTHER = [e("not-in-catalog")]; +`; + +test("counts shipped and reserved entries, ignoring comments and strings", () => { + assert.deepEqual(countCatalog(CATALOG), { shipped: 3, reserved: 1 }); +}); + +test("an entry it cannot classify is an error, not a skip", () => { + assert.throws(() => countCatalog("export const CATALOG = [\n e('a'),\n ...others,\n];"), /cannot tell/); + assert.throws(() => countCatalog("export const NOPE = [];"), /no `export const CATALOG`/); +}); + +test("the real catalog parses", () => { + const src = readFileSync(new URL("../collector/src/workloads/catalog.ts", import.meta.url), "utf8"); + const { shipped, reserved } = countCatalog(src); + assert.ok(shipped > 0 && reserved >= 0); +}); + +test("numbers in digits and in words", () => { + assert.equal(parseCount("34"), 34); + assert.equal(parseCount("Thirty-four"), 34); + assert.equal(parseCount("thirty four"), 34); + assert.equal(parseCount("twelve"), 12); + assert.equal(parseCount("Forty"), 40); + assert.equal(parseCount("thirty-odd"), null); + assert.equal(parseCount("many"), null); +}); + +test("markers find the number after them, with its line", () => { + const text = "# Title\n\nThe collector ships 34 workloads.\n" + + "Thirty-four workloads, and\n" + + "thirty workloads\n"; + const marks = findMarkers(text); + assert.deepEqual(marks.map((m) => [m.value, m.line]), [[34, 3], [34, 4], [30, 5]]); +}); + +test("a disagreeing, unreadable or unknown marker is a problem", () => { + const files = [ + { path: "README.md", text: "34 here\n28 there\n" }, + { path: "docs/x.md", text: "many\n5\n" }, + ]; + const { problems, seen } = check(files, { workloads: 34 }); + assert.equal(seen, 4); + assert.equal(problems.length, 3); + assert.match(problems[0], /README\.md:2: says 28, but there are 34 workloads/); + assert.match(problems[1], /docs\/x\.md:1: "many" .* is not a number/); + assert.match(problems[2], /unknown count "runners"/); +}); + +test("no markers at all fails, so a deleted marker cannot pass silently", () => { + const { problems } = check([{ path: "README.md", text: "34 workloads" }], { workloads: 34 }); + assert.match(problems[0], /no 34`, and `repo scripts` in `ci.yml` fails on any + pull request, docs-only ones included, when a marked number disagrees with + the shipped entries in `collector/src/workloads/catalog.ts`. The collector's + suite checks that reading against the real `CATALOG`. ([#89](https://github.com/addisdev/fleet-runner/pull/89)) + ### Fixed +- **`fleet service install` on Windows had never started anything.** The + scheduled task's command kept the backslashes of a `\"` escaping meant for a + `cmd` prompt -- execFile quotes the argument itself -- so the task ran + `\"C:\...\node.exe\"` and failed with "file not found" every time. Found by + the new Windows smoke on its first run. `fleet service uninstall` and `stop` + also now kill `fleet up`'s process tree before ending the task: deleting a + task does not stop it, and Windows does not take a parent's children down + with it. ([#89](https://github.com/addisdev/fleet-runner/pull/89)) +- **The desktop app left `fleet up` running when it was killed, and its Quit + item could not quit.** SIGTERM (a `kill`, a `killall`, the end of a session) + killed the app outright and orphaned its sidecar on the collector's port. And + `RunEvent::ExitRequested` refused every exit, including the `app.exit(0)` the + Quit item calls, so Quit stopped the fleet and left the app running. SIGTERM, + SIGINT and SIGHUP now take the Quit path -- stop `fleet up`, then exit -- and + only the implicit last-window exit is refused. Found by the first launch of + the app, in CI. ([#89](https://github.com/addisdev/fleet-runner/pull/89)) + - **`fleet skill` failed on an installed 0.8.0.** The 0.8.0 archives carry `skills/`, but `install.sh` and `install.ps1` copy a release's directories by name and did not name it, so `fleet skill show` and `fleet skill install` @@ -33,6 +68,38 @@ a CI job fails when they disagree. matches case-insensitively, as the bug garden's README says. ([#88](https://github.com/addisdev/fleet-runner/pull/88)) +### Now verified + +Four items from earlier "Not verified" lists, each now checked by +GitHub-hosted CI on every pull request that touches them. ([#89](https://github.com/addisdev/fleet-runner/pull/89)) + +- **`fleet service install` on launchd.** `fleet / launchd smoke` installs the + LaunchAgent on `macos-latest` (the runner has a `gui/` domain), waits + for its collector to answer and its agent to register, checks + `fleet service status`, reinstalls once so the bootstrap race is hit and + retried (it was), then uninstalls and checks nothing answers, the plist is + gone and launchd no longer has the job. +- **The Windows scheduled task.** `fleet / windows task smoke` runs the same + lifecycle on `windows-latest`. It found the bug above; with it fixed, a + Windows machine agent registered against a real collector for the first + time. +- **The arm64 container image.** `fleet / container smoke (arm64)` builds + `fleet/Dockerfile` natively on `ubuntu-24.04-arm`, checks the container + reports `aarch64`, and waits for its agent to register and answer + `fleet devices`, `fleet workloads` and `fleet whoami`. +- **The desktop app launches.** `desktop / launch smoke` builds it on Ubuntu + and runs it under Xvfb: its `fleet` sidecar starts a collector whose agent + registers, the app is still up 20 seconds later, and SIGTERM stops both. + Then, under `tauri-driver`, the settings window is driven over WebDriver: + it is titled `Fleet`, `get_status` answers over IPC with the sidecar + running, and a screenshot is uploaded. This was the first time the app ever + ran. It has still never run on a Mac, and the tray menu has never been + clicked. + +Still not verified: any of the three services coming back after a reboot, a +graceful stop on Windows, and the MCP gateway against a real identity provider +(it needs a tenant). + ## [0.8.0] — 2026-10-15 The fleet as something a program or an AI agent can drive: a versioned control diff --git a/README.md b/README.md index b19a08c..9298f91 100644 --- a/README.md +++ b/README.md @@ -177,7 +177,7 @@ languages, sharing not one line | | What it is | |---|---| | **[fleet/](fleet)** | The CLI. `fleet up` runs this machine's components under a supervisor that backs off and gives up loudly rather than restarting a broken component forever; `fleet doctor` says what the machine can run and why not; `fleet service install` keeps it up. It wraps the three programs above and reimplements none of them. | -| **[desktop/](desktop)** | A Tauri menu-bar app around that CLI: a tray menu, role switches, the dashboard in a window, and a notification when a component gives up. It exists to test one hypothesis about macOS local-network permissions, and **it has never been launched**: CI compiles its Rust and that is all -- read its README before believing anything in it. | +| **[desktop/](desktop)** | A Tauri menu-bar app around that CLI: a tray menu, role switches, the dashboard in a window, and a notification when a component gives up. It exists to test one hypothesis about macOS local-network permissions, and **it has never run on a Mac**: CI compiles it on macOS, and launches it on Linux under a virtual display, where it starts its `fleet` sidecar and its settings window answers over WebDriver. The tray, the Mac and the hypothesis are untested -- read its README before believing anything in it. | **Alongside them** diff --git a/desktop/README.md b/desktop/README.md index 5dc157d..ddf0970 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -217,14 +217,41 @@ the first `codesign` invocation. ## Status -Be suspicious of this whole directory. **The Rust compiles, and that is all -that is known about it.** There is no Rust toolchain on the machine it was -written on, so CI does the compiling: `desktop / cargo check` stages the -sidecar and runs `cargo check --all-targets` on macOS for every pull request -that touches `desktop/`. +Be suspicious of this directory, a little less than before. There is no Rust +toolchain on the machine it was written on, so CI does the compiling and, since +the launch smoke, the running. Two jobs in `.github/workflows/desktop.yml` run +for every pull request that touches `desktop/`: + +- **`desktop / cargo check`** stages the sidecar and runs + `cargo check --all-targets` on macOS. +- **`desktop / launch smoke`** builds the app on Ubuntu + (`cargo build --features custom-protocol`, the frontend embedded as in a + release) and runs [`ci/launch-smoke.sh`](ci/launch-smoke.sh) under Xvfb. That + was the first time the app ever ran. What **has** actually been checked: +- **It launches, on Linux.** Started with no config file, the binary spawns + `fleet up` as its sidecar through the staged shim; the collector it starts + answers `/api/v1/health` and the machine agent registers with it, inside a + few seconds. The app is still running, and the sidecar still answering, 20 + seconds later. +- **The settings window loads and talks to the app.** The smoke starts the app + again under `tauri-driver` (Tauri's WebDriver server, wrapping + `WebKitWebDriver`) and drives it over plain W3C WebDriver: the window title + is `Fleet`, `window.__TAURI__` is on the page, `get_status` answers over IPC + with `running: true` and the sidecar's own output, the page renders + `Running: brain, agent · :8788`, and a screenshot of the window is uploaded + as the `desktop-launch-smoke` artifact. So the gold-standard check, not just + a process-level one. +- **SIGTERM stops the sidecar and exits.** The smoke sends the app SIGTERM and + checks that the app exits, `fleet up` is gone and nothing answers on the + port. Its first run found the opposite, and two bugs behind it, both fixed: + the app had no signal handler, so SIGTERM killed it outright and orphaned + `fleet up` on the port; and `RunEvent::ExitRequested` refused *every* exit, + including the `app.exit(0)` the Quit item calls, so Quit would have stopped + the fleet and then not quit. SIGTERM, SIGINT and SIGHUP now take the Quit + path (stop, then exit), and only the implicit last-window exit is refused. - **`cargo check` passes.** Its first run failed in the build script, before any Rust was compiled, because the bundled resource and the sidecar were both named `fleet` in `target/debug`. With the resource renamed `fleet-tree` @@ -237,19 +264,35 @@ What **has** actually been checked: arranged into a fake `Contents/MacOS` + `Contents/Resources` layout, and `fleet version` and `fleet config` were run through the shim under `env -i PATH=/usr/bin:/bin:/usr/sbin:/sbin` — the Finder environment, with no - Homebrew on `PATH`. Both worked. That is the piece most likely to be wrong and - it is the piece that is tested. + Homebrew on `PATH`. Both worked. On Linux it also finds the tree beside a + dev build's binary (`target/debug/fleet-tree`), which is what the launch + smoke runs. - The Rust config struct's serialisation order was compared against real `fleet config` output. It matches. +One thing the launch smoke had to work around, and that a Linux user would hit: +the shim checks `/usr/local/bin/node` before `PATH`, and GitHub's Ubuntu image +keeps an older Node there, below the 22.13 `node:sqlite` needs. The smoke sets +`FLEET_NODE`. The order is right for the Mac it was written for (Finder gives an +app no Homebrew on `PATH`); on Linux it can pick a stale system Node over the +one you meant. + What has **not**: -- **It has never run.** Not the tray, not the settings window, not the sidecar - under Tauri, not a notification, not the dashboard window. Compiling says - the Tauri 2 calls exist with those signatures, not that they do what the - code assumes. The Cargo package is `fleet-desktop` - and `productName` is `Fleet`; if the bundler cannot find its binary, that - mismatch is why, and `mainBinaryName` in `tauri.conf.json` is the knob. +- **It has never run on macOS**, which is the platform it is for. Linux is + where Tauri's WebDriver exists, so that is where it was launched. Nothing + macOS-specific has been seen: not the menu-bar tray, not the + `Accessory` activation policy, not a notification. +- **The tray and the dashboard window, anywhere.** Under Xvfb there is no + status-notifier host for the tray to appear in, so the tray menu -- Open + Dashboard, Start, Stop, Quit -- has never been clicked, and the dashboard + window it opens has never been opened. The Quit item's code + path (stop, then `app.exit(0)`) is the one SIGTERM now takes, and that is + checked; the menu item itself is not. +- **A bundle.** The smoke runs a `cargo build`, not `cargo tauri build`. The + Cargo package is `fleet-desktop` and `productName` is `Fleet`; if the bundler + cannot find its binary, that mismatch is why, and `mainBinaryName` in + `tauri.conf.json` is the knob. - **The Local Network hypothesis.** See The bet, above. Everything this app is *for* rests on it and none of it is tested. - **Info.plist merging.** That Tauri's bundler merges `src-tauri/Info.plist` into @@ -266,11 +309,11 @@ What has **not**: otherwise, `disable-library-validation` because `fleet up` re-execs itself as its own children — but nothing has been signed, and the switch-to-Electron threshold above is measured from here. -- **Windows and Linux.** Untouched. `terminate()` on Windows is a no-op with a - comment saying so, because `TerminateProcess` does not run `fleet up`'s +- **Windows.** Untouched. `terminate()` on Windows is a no-op with a comment + saying so, because `TerminateProcess` does not run `fleet up`'s `process.on("SIGTERM")` handler and faking a graceful stop would be worse than - admitting there is not one. The CLI has never been run on either platform - either. + admitting there is not one. Linux has been launched in CI (above) and used by + nobody. - **Notification permission.** On macOS this needs a signed, bundled app; an unsigned `cargo tauri dev` build may get nothing. The tray headline says the same thing without needing permission from anybody, which is the deliberate diff --git a/docs/deploy/headless.md b/docs/deploy/headless.md index d149b17..eac4f06 100644 --- a/docs/deploy/headless.md +++ b/docs/deploy/headless.md @@ -133,7 +133,8 @@ in [networking](networking.md#macos-gates-local-network-access-and-launchd-canno Either way it is irrelevant to this page. A headless host has nobody to click the dialog, so **the tunnel stays** for exactly the machines this page is - about. None of the Rust has ever been compiled, either. + about. CI compiles it on macOS and launches it on Linux; it has never run + on a Mac. ## Rebuilding one over SSH diff --git a/docs/index.md b/docs/index.md index cec7b1d..93d89c8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -137,8 +137,8 @@ And two front doors: [`fleet/`](https://github.com/addisdev/fleet-runner/tree/main/fleet), the CLI behind `fleet up`, and [`desktop/`](https://github.com/addisdev/fleet-runner/tree/main/desktop), a -menu-bar app around it whose Rust compiles in CI and which has never been -launched. +menu-bar app around it that CI compiles on macOS and launches on Linux, and +that has never run on a Mac. [The history section](history/index.md) keeps the original architecture plan and the design journals as they were written. They are not maintained, and they are diff --git a/docs/install/docker.md b/docs/install/docker.md index 7f07282..2e11a35 100644 --- a/docs/install/docker.md +++ b/docs/install/docker.md @@ -17,8 +17,11 @@ docker run -d --restart unless-stopped -p 8788:8788 \ machine agent to register and checks `fleet devices`, `fleet workloads` and `fleet whoami` against it. Its first run found that the image could not start on a fresh volume (the directory was created root-owned), fixed in - 0.8.0. The arm64 image is built and has not been started. If you run it on - a NAS or a board, an issue saying how it went is welcome either way. + 0.8.0. `container smoke (arm64)` does the same on linux/arm64, built + natively on GitHub's arm64 runner rather than under QEMU, and checks the + container reports `aarch64`. That is a cloud VM, not a board: if you run it + on a NAS or a Raspberry Pi, an issue saying how it went is welcome either + way. `runner-machine/Dockerfile`, the agent-only image, is still **not built at all**: nothing publishes it and nobody has run `docker build` on it. diff --git a/docs/install/index.md b/docs/install/index.md index de6d590..2b292d8 100644 --- a/docs/install/index.md +++ b/docs/install/index.md @@ -28,7 +28,7 @@ can type it. | **[macOS](macos.md)** | `curl -fsSL …/install.sh \| sh` | Installed from a real release on **arm64 and Intel**, checksum verified, and upgraded in place from 0.5.0 to 0.6.0. **A real fleet's brain runs here under `fleet service`** — one launchd unit, three components, on macOS 12 | | **[Windows](windows.md)** | `irm …/install.ps1 \| iex` | `install.ps1` has never been parsed by PowerShell. The CLI's own suite -- supervisor, config, `fleet up` end to end -- passes on `windows-latest` in CI, but **nobody has stood a fleet up on a Windows machine**, and the service backend is untested | | **[Linux](linux.md)** | `curl -fsSL …/install.sh \| sh` | The installer is the same script macOS runs against the real release; it has not been run on Linux. The collector's and the CLI's suites pass on x64 and arm64 Linux in CI. **Nobody has stood a fleet up on one.** The systemd service backend is installed, started and uninstalled by a CI smoke test on Ubuntu, and has not been watched survive a reboot | -| **[Docker](docker.md)** | `docker run ghcr.io/addisdev/fleet` | Published for linux/amd64 and linux/arm64 with every release. CI starts the amd64 image on every pull request and waits for its agent to register; the arm64 image has not been started | +| **[Docker](docker.md)** | `docker run ghcr.io/addisdev/fleet` | Published for linux/amd64 and linux/arm64 with every release. CI starts both on every pull request that touches them and waits for each one's agent to register | | **[Devices](devices.md)** | -- | How a phone, a television, a Roku or a browser joins a fleet that is already up | ## What the installers do, and what they refuse to do diff --git a/docs/install/linux.md b/docs/install/linux.md index 39e4885..ee0408e 100644 --- a/docs/install/linux.md +++ b/docs/install/linux.md @@ -133,7 +133,7 @@ reboots unattended and is never logged into will otherwise sit there running nothing. **`fleet service install` on systemd is checked by CI, not by a deployment.** -On macOS it runs a real fleet's brain. On Linux, `systemd smoke` installs the +On macOS it runs a real fleet's brain, and CI runs it there and on Windows too. On Linux, `systemd smoke` installs the user unit on GitHub's Ubuntu runner, checks it with `systemd-analyze verify`, waits for the collector it starts to answer, and uninstalls it. What that does not cover is a reboot: the job enables lingering and starts the unit, and diff --git a/docs/install/macos.md b/docs/install/macos.md index 988891f..ab5f3e5 100644 --- a/docs/install/macos.md +++ b/docs/install/macos.md @@ -181,10 +181,14 @@ writes **one** launchd unit running `fleet up`, into rather than the five plists the old deployment had, so switching the brain off is a config edit rather than a `launchctl` invocation somebody has to look up. -**This is the one platform `fleet service install` has been run on.** Since -2026-09-19 it runs the brain of the fleet this project was built for: one +**This is the one platform `fleet service install` runs a real fleet on.** +Since 2026-09-19 it runs the brain of the fleet this project was built for: one launchd unit, three components, on an Intel Mac under macOS 12, surviving a -reboot of the supervisor and a `kill -9` of the collector under it. +reboot of the supervisor and a `kill -9` of the collector under it. CI also +runs it on every pull request that touches it: `launchd smoke` installs the +LaunchAgent on GitHub's `macos-latest` runner, waits for the collector to +answer and the agent to register, reinstalls once to hit the bootstrap race +below, and uninstalls. Two things that cost an outage each, both fixed and both worth knowing: `launchctl bootstrap` loses a race with the `bootout` immediately before it and diff --git a/docs/install/windows.md b/docs/install/windows.md index 9f60cc0..2418b6c 100644 --- a/docs/install/windows.md +++ b/docs/install/windows.md @@ -12,9 +12,11 @@ irm https://raw.githubusercontent.com/addisdev/fleet-runner/main/install.ps1 | i **And nobody has run a fleet on Windows.** CI runs the `fleet` CLI's suite on `windows-latest` on every pull request that touches it, including the - supervised `fleet up` end to end, and it passes. That is the whole of it: - the bundle from an archive, `fleet service install`'s scheduled-task - backend, and a fleet left running on a Windows machine are all unwatched. + supervised `fleet up` end to end, and `windows task smoke` installs + `fleet service`'s scheduled task, waits for its collector to answer and + its agent to register, and uninstalls it. That is the whole of it: the + bundle from an archive and a fleet left running on a Windows machine are + unwatched. What *has* been exercised on Windows is [the machine agent](../platforms.md#what-a-cloud-runner-actually-reports): its own suite @@ -130,10 +132,16 @@ On Windows the service backend is **`schtasks`**, registering a task that runs `fleet up` at logon. It is not a Windows Service: a service would need elevation, and nothing else in this project does. -**`fleet service install` has never been run on Windows**, and the scheduled-task -backend is the least exercised of the three. It has now been run on macOS, where -it runs a real fleet's brain; that says the command works and nothing about this -backend. See [headless +**`fleet service install` on Windows is checked by CI, not by a deployment.** +`windows task smoke` runs it on GitHub's `windows-latest` runner: the task is +created and started, its collector answers, its agent registers, `fleet service +status` reports it, and `fleet service uninstall` leaves nothing answering. Its +first run found that the task had never worked -- the command it stored kept +backslashes meant for a `cmd` prompt and failed with "file not found" -- and +that is fixed. Two things it does not cover: a logon after a reboot, and a +graceful stop. `fleet service stop` and `uninstall` kill `fleet up`'s process +tree, because Windows has no signal one process can send another that Node +turns into SIGTERM, so the collector does not drain. See [headless hosts](../deploy/headless.md). ## What is deliberately absent diff --git a/docs/platforms.md b/docs/platforms.md index 094a2a9..3874659 100644 --- a/docs/platforms.md +++ b/docs/platforms.md @@ -14,7 +14,7 @@ that says which ones somebody has watched register is worth something. | Android phone, tablet | `runner-android` | `adb install`, or sideload | **yes** — the original shelf | | iPhone, iPad | `runner-ios` | Xcode, TestFlight internal | **yes** | | iOS simulator | `runner-ios` | `simctl install` | **yes** | -| macOS, Linux, Windows | `runner-machine` | `fleet up`, or `npm start`, or a LaunchAgent / systemd unit | **macOS yes, on both architectures** — an Apple M1 Pro and a 2016 Intel i7 both registered, passed `npm run conformance`, and produce comparable synthetic numbers with matching digests; both run under `fleet service`. Linux and Windows run their suite in CI on x64 and arm64, and CI installs `fleet service` as a systemd user unit on Linux, waits for the collector it starts, and uninstalls it; the launchd unit is only proven by this lab's own Macs and the Windows scheduled task has never been installed. On Linux x64 the agent also registers, inside the Docker image in CI, against the collector beside it; Windows has never registered against a real collector — see [what each one reports](#what-a-cloud-runner-actually-reports) | +| macOS, Linux, Windows | `runner-machine` | `fleet up`, or `npm start`, or a LaunchAgent / systemd unit | **macOS yes, on both architectures** — an Apple M1 Pro and a 2016 Intel i7 both registered, passed `npm run conformance`, and produce comparable synthetic numbers with matching digests; both run under `fleet service`. Linux and Windows run their suite in CI on x64 and arm64. CI also installs `fleet service` on all three on every pull request that touches it -- a systemd user unit on Ubuntu, a LaunchAgent on `macos-latest`, a scheduled task on `windows-latest` -- waits for the collector it starts and, on macOS and Windows, for the agent to register, then uninstalls it. The Windows task's first run is the first time a Windows agent registered against a real collector; it found the task had never started anything, now fixed. On Linux the agent also registers inside the Docker image in CI, on x64 and arm64. No service has been watched to come back after a reboot, and nobody runs a Linux or Windows machine in a fleet — see [what each one reports](#what-a-cloud-runner-actually-reports) | | Android emulator | `runner-android` | `adb install` to the emulator | **yes** | ## What Wave 5 added @@ -28,7 +28,7 @@ that says which ones somebody has watched register is worth something. | **Apple TV (tvOS)** | `runner-ios`, `FleetRunnerTV` target | `devicectl` or `simctl` | **builds** — `xcodebuild -scheme FleetRunnerTV` succeeds. No Apple TV has run it. (Exploratory QA drives tvOS 26.5 simulators through FleetDriver, a separate UI-test bundle) | | **Vision Pro (visionOS)** | `runner-ios`, `FleetRunnerVision` target | `devicectl` or `simctl` | **no** — the target is written and has never been compiled; the visionOS platform is not installed on the machine it was written on | | **Raspberry Pi, Jetson, Steam Deck** | `runner-machine` | `install-agent.sh`, or the Docker image | **no** — but arm64 Linux in CI reports a nearly complete descriptor, so a board should register cleanly. No board has | -| **Anything with Docker** | `fleet/Dockerfile` | `docker run ghcr.io/addisdev/fleet` | **in CI** — every release publishes linux/amd64 and linux/arm64. CI starts the amd64 image on every pull request that touches it and waits for its own machine agent to register; the arm64 image has not been started | +| **Anything with Docker** | `fleet/Dockerfile` | `docker run ghcr.io/addisdev/fleet` | **in CI** — every release publishes linux/amd64 and linux/arm64. CI builds and starts both on every pull request that touches them -- arm64 natively on GitHub's arm64 runner -- and waits for each one's own machine agent to register. No board or NAS has run it | ## What Wave 6 added @@ -37,9 +37,13 @@ that says which ones somebody has watched register is worth something. | **Roku player, Roku TV** | `runner-roku` | `build.sh --install `, then an ECP launch | **no** -- and less verified than anything above it. No Roku was available and no Roku emulator exists, so the channel has never run. CI compiles it with brighterscript's `bsc` on every pull request that touches it; the firmware's own compiler has never seen it. See [Roku: the one that has never run](#roku-the-one-that-has-never-run) | | **Roku, from the executor** | `collector/src/drivers/roku.ts` | SSDP discovery on the LAN | **partly** -- the SSDP and device-info parsers are checked against recorded response shapes in `drivers.test.ts`; the UDP socket path is exercised by nothing, and no Roku has answered it | -The desktop app is not a runner, but it is the other thing here that has never -been run: `desktop / cargo check` compiles its Rust on macOS on every pull -request that touches it, and nobody has launched it. +The desktop app is not a runner, and it has never run on the platform it is +for. On every pull request that touches it, `desktop / cargo check` compiles +its Rust on macOS, and `desktop / launch smoke` builds and launches it on +Ubuntu under a virtual display: its `fleet` sidecar comes up and registers an +agent, its settings window answers over WebDriver, and SIGTERM stops both. The +tray, macOS, and the local-network bet it exists for are untested; see +[its README](https://github.com/addisdev/fleet-runner/tree/main/desktop#status). ## Android: one APK, every shape diff --git a/fleet/README.md b/fleet/README.md index 4f55b71..8051e13 100644 --- a/fleet/README.md +++ b/fleet/README.md @@ -232,21 +232,40 @@ the collector under it. Two things cost an outage each on the way and are fixed `PATH` from the shell that ran the install, which is how an executor ends up unable to find `adb`. -Since 0.8.0, two CI smoke jobs in `fleet.yml` run what had only been built: +Since 0.8.0, CI smoke jobs in `fleet.yml` run what had only been built. Each +runs on every pull request that touches `fleet/`, `collector/` or +`runner-machine/`: - **systemd.** `systemd smoke` installs the built bundle as a systemd user unit on Ubuntu, checks it with `systemd-analyze verify`, waits for its collector to answer, and uninstalls it. -- **A container.** `container smoke` builds `fleet/Dockerfile`, starts `fleet up` in it, and - waits for its machine agent to register. Its first run found the image could not start on - a fresh volume. +- **launchd.** `launchd smoke` does the same on `macos-latest`: `fleet service install` + writes the LaunchAgent and bootstraps it into the runner's `gui/` domain (GitHub's + macOS runners have a logged-in GUI session, and the job prints it first). It waits for the + collector to answer and the agent to register, runs `fleet service status`, reinstalls once + so the bootout/bootstrap race is hit and retried rather than trusted -- the first run printed + "launchd is still letting go of the old job; waiting" and recovered -- then uninstalls and + checks nothing answers, the plist is gone and launchd no longer has the label. +- **The Windows scheduled task.** `windows task smoke` runs the same lifecycle on + `windows-latest`. Its first run found that the task had never worked: the command it + stored kept the backslashes from a `\"` escaping meant for a `cmd` prompt, so the task + ran `\"C:\...\node.exe\"` and failed with "file not found". Fixed, and `fleet service + uninstall` (and `stop`) now kill `fleet up`'s process tree by the supervisor's pid before + ending the task, because deleting a task does not stop it and Windows does not take a + parent's children down with it. With that, a Windows machine agent registered against a + real collector for the first time. +- **A container, on both architectures.** `container smoke` builds `fleet/Dockerfile`, + starts `fleet up` in it, and waits for its machine agent to register. Its first run found + the image could not start on a fresh volume. `container smoke (arm64)` builds it natively + on GitHub's arm64 runner and checks the container reports `aarch64` before doing the same. What has still not been run: -- **`fleet service install` on Windows**, and the systemd unit surviving a reboot on a real - machine. -- **The arm64 container image.** The release workflow builds and publishes it; nothing has - started it. +- **A service surviving a reboot**, on any of the three. CI installs and starts each unit; + nobody has watched one come back at boot or at logon on a real machine. +- **Windows stopping gracefully.** The task is stopped by killing the process tree, so the + collector does not drain; there is no signal Windows lets one process send another that + Node turns into SIGTERM. - **`install.ps1`.** No PowerShell was available to parse it, let alone run it. `install.sh` *has* been run against the real v0.5.0 release on macOS/arm64: checksum verified, binary installed and reporting its version. diff --git a/scripts/check-counts.mjs b/scripts/check-counts.mjs index e515a0a..6024d1b 100644 --- a/scripts/check-counts.mjs +++ b/scripts/check-counts.mjs @@ -133,9 +133,24 @@ export function parseCount(text) { const MARKER = /\s*([0-9]+|[A-Za-z]+(?:[-\s][A-Za-z]+)?)/g; -/** Every marked number in a file: `{ key, text, value, line }`. */ +/** + * The text with code blanked out, same length, newlines kept. + * + * A marker written inside backticks is an example of the syntax -- in + * CONTRIBUTING.md, in a changelog entry -- not a number standing in prose, and + * it must not start failing the day the count moves. + */ +export function maskCode(text) { + const blank = (s) => s.replace(/[^\n]/g, " "); + return text + .replace(/^(```|~~~)[^\n]*\n[\s\S]*?^\1[^\n]*$/gm, blank) + .replace(/(`+)(?!`)[\s\S]*?[^`]\1(?!`)/g, blank); +} + +/** Every marked number in a file, outside code: `{ key, text, value, line }`. */ export function findMarkers(text) { const out = []; + text = maskCode(text); for (const m of text.matchAll(MARKER)) { let token = m[2]; // "thirty-four workloads": keep the second word only if it is a units word. diff --git a/scripts/check-counts.test.mjs b/scripts/check-counts.test.mjs index 3537c0d..0a7f032 100644 --- a/scripts/check-counts.test.mjs +++ b/scripts/check-counts.test.mjs @@ -2,7 +2,7 @@ import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { test } from "node:test"; -import { check, countCatalog, findMarkers, parseCount } from "./check-counts.mjs"; +import { check, countCatalog, findMarkers, maskCode, parseCount } from "./check-counts.mjs"; const CATALOG = ` const e = () => ({}); @@ -67,3 +67,16 @@ test("no markers at all fails, so a deleted marker cannot pass silently", () => const { problems } = check([{ path: "README.md", text: "34 workloads" }], { workloads: 34 }); assert.match(problems[0], /no 34` next to the number.", + "```markdown", + "12 workloads", + "```", + "Real: 34 workloads.", + ].join("\n"); + const marks = findMarkers(text); + assert.deepEqual(marks.map((m) => [m.value, m.line]), [[34, 5]]); + assert.equal(maskCode(text).length, text.length); +}); From a5b8b2faa092e67e0f3fca6307e772a19d2d8e7a Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 21:04:37 -0400 Subject: [PATCH 08/19] Explore nights adapt: short nights, skips for missing builds, warm after checks explore-night.ts now checks the cheap things before it warms the model or boots a device. With --fresh-build, a spec on "latest" needs a build the brain shows as published tonight; without one the job is posted as a skip (ok: true, "skipped: no build for tonight (...)") and the command exits 0, since ultra's night queue has no skip code. It knows when the night ends (--until, default 07:30, or the job's max_minutes read from the night queue's manifest) and cuts each spec's minutes to fit, the workload saying "short night: ran N of M cards: X minutes left of the Y asked". The shelf warm-up moved from the manifests into --warm, run after the checks, with a refusal for memory retried and then posted as a skip: that refusal (64% free, needs 65%) was fleet-explore-apple's exit 1 on 10-14. nightly-builds.sh republishes an unchanged build so a quiet day is not a missed build. --dry-run runs the checks against the live brain and posts nothing. Also fixes tvOS simulators describing themselves as os "ios", which made every fleet-explore-tv job skip with "no device matches". Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 55 ++++ .../explore/night/fleet-explore-apple.json | 2 +- .../explore/night/fleet-explore-tv.json | 2 +- .../deploy/explore/night/fleet-explore.json | 4 +- collector/deploy/explore/nightly-builds.sh | 27 +- collector/schemas/metrics.json | 2 + collector/schemas/result.schema.json | 2 + collector/scripts/check-explore.ts | 2 + collector/scripts/explore-night.ts | 241 ++++++++++++++++-- collector/src/describe.test.ts | 19 ++ collector/src/executor.ts | 13 +- collector/src/workloads/explore/index.ts | 25 +- collector/src/workloads/explore/manifest.json | 4 + collector/src/workloads/explore/night.test.ts | 210 +++++++++++++++ collector/src/workloads/explore/night.ts | 185 ++++++++++++++ docs/deploy/explore-on-ultra.md | 47 +++- docs/explore/job.md | 59 +++++ docs/explore/troubleshooting.md | 39 +++ 18 files changed, 889 insertions(+), 49 deletions(-) create mode 100644 collector/src/workloads/explore/night.test.ts create mode 100644 collector/src/workloads/explore/night.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index b1b6bbf..7e75723 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,8 +16,63 @@ a CI job fails when they disagree. ## [Unreleased] +### Added + +- **An explore night admitted late runs short instead of not at all.** + `scripts/explore-night.ts` now knows when the night ends: `--until` + (default 07:30, ultra's night-queue stop) or the job's own `max_minutes`, + read from the night queue's manifest for `$NIGHT_JOB`, whichever is first. + When the specs ask for more than is left, each gets a proportional share, + the workload runs its highest-priority cards in it, and the result says so + on an `ok` row: `short night: ran 3 of 7 cards: 40 minutes left of the 60 + asked`. Under 15 minutes (`--min-minutes`) the night is posted as a skip + rather than started. New metrics `explore_cards_planned` and + `explore_minutes` record what the device was given. The night queue's own + admission wait (120 minutes behind a CI job on 10-14) is outside this + repository and unchanged. Not yet seen on a real night. +- **`explore-night.ts --dry-run`** opens the tunnel, runs the build and time + checks against the live brain and prints the plan, without enqueueing, + posting, warming or booting anything. + +### Changed + +- **Explore nights that need tonight's build skip, not fail, when there is + none.** With `--fresh-build` (now on `fleet-explore-apple` and + `fleet-explore-tv`), the night checks through the tunnel that the brain has + a build of each app published tonight before it warms the model or boots a + simulator. If not, the job is posted to the brain as `ok: true`, `skipped: + no greenfolio-ios build for tonight (fleet-explore-builds did not run, ...)`, + and the command exits 0: ultra's night queue has no skip exit code, and a + missing upstream build is not this job's failure. `nightly-builds.sh` now + uploads an unchanged build again (the brain ignores the duplicate bytes and + stamps it published), so a quiet day on `develop` does not look like a + missed build. +- **The model warm-up moved inside the night command.** The four night-queue + manifests ran `shelf.sh warm pilot &&` before `explore-night.ts`, so a + warm-up the shelf refused ended the job with `exit 1` before any check ran. + `explore-night.ts --warm ""` runs it after the build and time checks, + retries a refusal for memory every minute for up to `--warm-wait` minutes + (default 10), and then posts the night as `skipped: the model would not + load, no room on this host: ...`. Any other warm-up failure is posted as a + failure with its last line. The manifests in + `collector/deploy/explore/night/` need copying to `~/night/recurring/` on + ultra. + ### Fixed +- **`fleet-explore-apple` exited 1 in 0.0 minutes on 10-14.** Not a missing + build: the shelf refused to load Holo4 at 64% free memory against its 65% + threshold, after the night queue had admitted the job on its own measure. + See the warm-up change above; with `--fresh-build` that night would also + have skipped earlier, at "no greenfolio-ios build for tonight". +- **tvOS simulators registered as `os: ios`, so the TV explore night tested + nothing.** The executor read simctl's runtime key for `iOS-` only, so an + Apple TV simulator was described as plain `ios`, every `os ~ 'tvos'` job + skipped with "no device matches this job on ultra", and each + `fleet-explore-tv` night "passed" in about a minute. A tvOS simulator is + now `tvos-26.5` (watchOS and visionOS likewise). No TV night has run with + the fix yet. + - **`fleet skill` failed on an installed 0.8.0.** The 0.8.0 archives carry `skills/`, but `install.sh` and `install.ps1` copy a release's directories by name and did not name it, so `fleet skill show` and `fleet skill install` diff --git a/collector/deploy/explore/night/fleet-explore-apple.json b/collector/deploy/explore/night/fleet-explore-apple.json index ef7fd58..3665787 100644 --- a/collector/deploy/explore/night/fleet-explore-apple.json +++ b/collector/deploy/explore/night/fleet-explore-apple.json @@ -4,7 +4,7 @@ "command": [ "bash", "-lc", - "source ~/explore/env.sh && bash ~/harness/shelf.sh warm pilot && cd ~/fleet-runner/collector && npx tsx scripts/explore-night.ts --sim fleet-explore-ios:com.apple.CoreSimulator.SimRuntime.iOS-26-5:com.apple.CoreSimulator.SimDeviceType.iPhone-16 --spec examples/jobs/explore-greenfolio-ios-ultra.json --tunnel runner-ts:192.168.50.27:8788" + "source ~/explore/env.sh && cd ~/fleet-runner/collector && npx tsx scripts/explore-night.ts --sim fleet-explore-ios:com.apple.CoreSimulator.SimRuntime.iOS-26-5:com.apple.CoreSimulator.SimDeviceType.iPhone-16 --spec examples/jobs/explore-greenfolio-ios-ultra.json --tunnel runner-ts:192.168.50.27:8788 --fresh-build --warm \"bash ~/harness/shelf.sh warm pilot\"" ], "priority": 86, "needs_gb": 35, diff --git a/collector/deploy/explore/night/fleet-explore-tv.json b/collector/deploy/explore/night/fleet-explore-tv.json index d40afa4..31fb525 100644 --- a/collector/deploy/explore/night/fleet-explore-tv.json +++ b/collector/deploy/explore/night/fleet-explore-tv.json @@ -4,7 +4,7 @@ "command": [ "bash", "-lc", - "source ~/explore/env.sh && bash ~/harness/shelf.sh warm pilot && cd ~/fleet-runner/collector && npx tsx scripts/explore-night.ts --sim fleet-explore-tvos:com.apple.CoreSimulator.SimRuntime.tvOS-26-5:com.apple.CoreSimulator.SimDeviceType.Apple-TV-4K-3rd-generation-1080p --spec examples/jobs/explore-tvos-bench-pilot-ultra.json --spec examples/jobs/explore-tvos-bench-vision-ultra.json --spec examples/jobs/explore-dozehound-tvos-ultra.json --tunnel runner-ts:192.168.50.27:8788" + "source ~/explore/env.sh && cd ~/fleet-runner/collector && npx tsx scripts/explore-night.ts --sim fleet-explore-tvos:com.apple.CoreSimulator.SimRuntime.tvOS-26-5:com.apple.CoreSimulator.SimDeviceType.Apple-TV-4K-3rd-generation-1080p --spec examples/jobs/explore-tvos-bench-pilot-ultra.json --spec examples/jobs/explore-tvos-bench-vision-ultra.json --spec examples/jobs/explore-dozehound-tvos-ultra.json --tunnel runner-ts:192.168.50.27:8788 --fresh-build --warm \"bash ~/harness/shelf.sh warm pilot\"" ], "priority": 85, "needs_gb": 35, diff --git a/collector/deploy/explore/night/fleet-explore.json b/collector/deploy/explore/night/fleet-explore.json index 27062e1..efcce5c 100644 --- a/collector/deploy/explore/night/fleet-explore.json +++ b/collector/deploy/explore/night/fleet-explore.json @@ -4,7 +4,7 @@ "command": [ "bash", "-lc", - "source ~/explore/env.sh && bash ~/harness/shelf.sh warm pilot && cd ~/fleet-runner/collector && npx tsx scripts/explore-night.ts --spec examples/jobs/explore-garden-ultra.json --avd fleet-explore-1 --tunnel runner-ts:192.168.50.27:8788" + "source ~/explore/env.sh && cd ~/fleet-runner/collector && npx tsx scripts/explore-night.ts --spec examples/jobs/explore-garden-ultra.json --avd fleet-explore-1 --tunnel runner-ts:192.168.50.27:8788 --warm \"bash ~/harness/shelf.sh warm pilot\"" ], "priority": 20, "needs_gb": 35, @@ -13,4 +13,4 @@ "nights": "daily", "wait_minutes": 120, "gateway_key": "fleet" -} \ No newline at end of file +} diff --git a/collector/deploy/explore/nightly-builds.sh b/collector/deploy/explore/nightly-builds.sh index c9932e6..4751f45 100755 --- a/collector/deploy/explore/nightly-builds.sh +++ b/collector/deploy/explore/nightly-builds.sh @@ -7,8 +7,10 @@ # ~/explore/builds, reset to origin/develop, built for the emulator or the # simulator, uploaded with the app name and `develop-` as the build. # -# A build that fails is reported and skipped; the night then tests the last -# build that did upload. An unchanged sha is not rebuilt. +# A build that fails is reported and skipped, and the night that needs it +# skips too (explore-night.ts --fresh-build) rather than testing an old build +# again. An unchanged sha is not rebuilt; its last build is uploaded again so +# the brain shows it as tonight's. # # nightly-builds.sh [--tunnel jump:host:port] [app ...] # @@ -107,20 +109,29 @@ for name in "${apps[@]}"; do [ $fetched = 1 ] && git -C "$dir" reset -q --hard origin/develop || { log "$name: fetch failed: $(tail -1 "$dir.fetch.log")"; failed=1; continue; } sha=$(git -C "$dir" rev-parse --short=10 HEAD) build="develop-$sha" - if [ "$(cat "$STATE/$name" 2>/dev/null)" = "$build" ]; then log "$name: $build already uploaded"; continue; fi + case "$name" in + dozehound-firetv) file="$dir/app/build/outputs/apk/debug/app-debug.apk"; platform=android ;; + greenfolio-ios) file="$BUILDS/$name-$sha.zip"; platform=ios ;; + dozehound-tvos) file="$BUILDS/$name-$sha.zip"; platform=tvos ;; + *) log "$name: no recipe"; failed=1; continue ;; + esac + # Unchanged: upload the same bytes again rather than nothing. The brain + # ignores the duplicate but stamps it as published now, and that stamp is + # how the explore nights (`explore-night.ts --fresh-build`) tell "develop did + # not move" from "this job did not run tonight". + if [ "$(cat "$STATE/$name" 2>/dev/null)" = "$build" ] && [ -f "$file" ]; then + upload "$name" "$platform" "$file" "$build" && log "$name: $build unchanged; republished for tonight" || failed=1 + continue + fi log "$name: building $build" started=$(date +%s) case "$name" in dozehound-firetv) - ( cd "$dir" && ./gradlew -q --no-daemon :app:assembleDebug >"$dir.build.log" 2>&1 ) || { tail -30 "$dir.build.log"; log "$name: build failed"; failed=1; continue; } - file="$dir/app/build/outputs/apk/debug/app-debug.apk"; platform=android ;; + ( cd "$dir" && ./gradlew -q --no-daemon :app:assembleDebug >"$dir.build.log" 2>&1 ) || { tail -30 "$dir.build.log"; log "$name: build failed"; failed=1; continue; } ;; greenfolio-ios) - file="$BUILDS/$name-$sha.zip"; platform=ios xcode_build "$dir" GreenFolio iphonesimulator "generic/platform=iOS Simulator" "$file" || { log "$name: build failed"; failed=1; continue; } ;; dozehound-tvos) - file="$BUILDS/$name-$sha.zip"; platform=tvos xcode_build "$dir" Dozehound appletvsimulator "generic/platform=tvOS Simulator" "$file" || { log "$name: build failed"; failed=1; continue; } ;; - *) log "$name: no recipe"; failed=1; continue ;; esac log "$name: built in $(( $(date +%s) - started )) s" upload "$name" "$platform" "$file" "$build" && echo "$build" >"$STATE/$name" || failed=1 diff --git a/collector/schemas/metrics.json b/collector/schemas/metrics.json index 3a1c5f8..24d6dbf 100644 --- a/collector/schemas/metrics.json +++ b/collector/schemas/metrics.json @@ -34,8 +34,10 @@ "explore_bench_total", "explore_cached_tokens_mean", "explore_candidates", + "explore_cards_planned", "explore_findings", "explore_findings_new", + "explore_minutes", "explore_misses", "explore_missions", "explore_model_ms_p50", diff --git a/collector/schemas/result.schema.json b/collector/schemas/result.schema.json index c394673..9af30a9 100644 --- a/collector/schemas/result.schema.json +++ b/collector/schemas/result.schema.json @@ -174,6 +174,8 @@ "avg_rating": { "type": "number", "description": "archive(asc/play) and digest: mean star rating over those reviews" }, "clusters": { "type": "integer", "description": "digest: topic clusters in the assembled digest" }, "explore_missions": { "type": "integer", "description": "explore: missions run on this device tonight" }, + "explore_cards_planned": { "type": "integer", "description": "explore: mission cards lined up for this device tonight, in priority order; explore_missions of them ran before the budget ran out" }, + "explore_minutes": { "type": "number", "description": "explore: the minutes this device was given (params.minutes, cut to fit on a short night)" }, "explore_steps": { "type": "integer", "description": "explore: model steps taken (one model call each, however many actions it chained)" }, "explore_actions": { "type": "integer", "description": "explore: actions performed on the device after the leash" }, "explore_screens": { "type": "integer", "description": "explore: distinct screens reached tonight" }, diff --git a/collector/scripts/check-explore.ts b/collector/scripts/check-explore.ts index 9d0dbc2..d4bb61c 100644 --- a/collector/scripts/check-explore.ts +++ b/collector/scripts/check-explore.ts @@ -5,6 +5,7 @@ import { runExploreChecks } from "../src/workloads/explore/explore.test.js"; import { runRokuActuatorChecks } from "../src/workloads/explore/actuators/roku.test.js"; import { runAppleActuatorChecks } from "../src/workloads/explore/actuators/apple.test.js"; +import { runNightChecks } from "../src/workloads/explore/night.test.js"; let failed = 0; let passed = 0; @@ -16,5 +17,6 @@ const check = (name: string, cond: boolean, detail = "") => { await runExploreChecks(check); await runRokuActuatorChecks(check); await runAppleActuatorChecks(check); +await runNightChecks(check); console.log(failed ? ` ${failed} of ${passed + failed} explore checks failed` : ` ok — ${passed} explore checks`); process.exit(failed ? 1 : 0); diff --git a/collector/scripts/explore-night.ts b/collector/scripts/explore-night.ts index c48ccb3..8a05e5b 100644 --- a/collector/scripts/explore-night.ts +++ b/collector/scripts/explore-night.ts @@ -6,16 +6,37 @@ // has finished so the memory is free again. So instead of a long-lived // executor claiming whatever the brain hands it, this command: // -// 1. boots the night's emulator if it is not already up (and remembers it did); -// 2. enqueues the job spec on the brain with tonight's date in its id, pinned -// to this executor's name; -// 3. runs an executor in this process until that job is done, failed or +// 1. opens the tunnel to the brain and checks, before anything expensive, +// that each spec has a build to test (`--fresh-build`: one published +// tonight) and that the night has time left for it; +// 2. warms the model (`--warm ""`), retrying a warm-up the host refused +// for memory for up to `--warm-wait` minutes; +// 3. boots the night's emulator or simulator if it is not already up (and +// remembers it did); +// 4. enqueues each spec on the brain with tonight's date in its id, pinned to +// this executor's name, with `minutes` cut to what is left of the night; +// 5. runs an executor in this process until that job is done, failed or // cancelled; -// 4. shuts down only what it booted, and exits 0 for a job that finished and -// 1 for one that did not. +// 6. shuts down only what it booted. +// +// A spec that cannot run tonight -- no build for tonight, no time left, a +// model the host has no room to load -- is posted to the brain as a skip +// (ok: true, error "skipped: ...") and does not count against the night. The +// exit code is 0 when every job finished or skipped and 1 otherwise: ultra's +// night queue has no skip code, and a missing upstream build is not this +// job's failure. // // npx tsx scripts/explore-night.ts --spec examples/jobs/explore-garden-ultra.json \ -// [--avd fleet-explore-1] [--tunnel runner-ts:192.168.50.27:8788] +// [--avd fleet-explore-1 | --sim name:runtime:devicetype] [--tunnel runner-ts:192.168.50.27:8788] +// [--fresh-build] [--warm "bash ~/harness/shelf.sh warm pilot"] [--warm-wait 10] +// [--until 07:30] [--max-minutes N] [--min-minutes 15] [--dry-run] +// +// --until is the night queue's hard stop (default 07:30). --max-minutes is the +// job's own kill timer; by default it is read from the night queue's manifest +// for $NIGHT_JOB (read-only), which is the only place the job can learn it. +// The night ends at whichever comes first. --dry-run opens the tunnel, runs +// the checks and prints the plan; it enqueues nothing, posts nothing, warms +// nothing and boots nothing. // // --tunnel opens `ssh -N -L :: ` for the length of // the night and closes it after. ultra sits on the Mini's side of the home @@ -24,14 +45,21 @@ // fewer service to keep alive on a machine whose services are LaunchDaemons. // // Env: FLEET_URL (the brain, through the tunnel), FLEET_EXECUTOR_NAME (default -// "ultra"), and HARNESS_GATEWAY / HARNESS_KEY, which the night queue sets and -// the workload reads. +// "ultra"), NIGHT_JOB / NIGHT_ROOT (the night queue's job name and directory), +// and HARNESS_GATEWAY / HARNESS_KEY, which the night queue sets and the +// workload reads. import { execFile, spawn } from "node:child_process"; import { readFileSync } from "node:fs"; +import { + NIGHT, buildMissing, fetchedSince, lastLine, nightEnd, nightManifestMinutes, nightStart, planSpecs, + warmRefusedForMemory, type BrainBuild, +} from "../src/workloads/explore/night.js"; import path from "node:path"; import { promisify } from "node:util"; const run = promisify(execFile); +// When the night queue started this job, near enough: its max_minutes runs from here. +const STARTED = new Date(Date.now() - process.uptime() * 1000); const a = process.argv.slice(2); const arg = (k: string) => { const i = a.indexOf(k); return i >= 0 ? a[i + 1] : undefined; }; const BASE = (process.env.FLEET_URL ?? "http://127.0.0.1:18788").replace(/\/+$/, ""); @@ -130,10 +158,91 @@ async function bootSimulator(spec: string): Promise<{ udid: string; booted: bool return { udid: found.udid, booted }; } +type Spec = Record & { + job_id?: string; + targets?: Record; + app?: { name?: string; build?: string; sha256?: string; platform?: string }; + params?: Record & { minutes?: number; changed?: { repo?: string } }; +}; +type Item = { path: string; spec: Spec; asked: number; jobId: string }; +/** A spec that will not run tonight, and what to post for it. */ +type Verdict = { ok: boolean; error: string }; + +const minutesLeft = (end: Date) => Math.floor((end.getTime() - Date.now()) / 60_000); +const hhmm = (d: Date) => d.toTimeString().slice(0, 5); + +/** Why this spec has nothing to test tonight, or null. Asked of the brain, through the tunnel. */ +async function buildProblem(item: Item, fresh: boolean): Promise { + const app = item.spec.app; + if (!app?.sha256) return null; // explores whatever is installed + if (app.sha256 !== "latest") { + const res = await fetch(`${BASE}/artifacts/${app.sha256}`, { headers: { range: "bytes=0-0" }, signal: AbortSignal.timeout(15_000) }) + .catch((e: Error) => e); + if (res instanceof Error) return { ok: false, error: `could not ask the brain for build ${app.sha256.slice(0, 12)}: ${res.message}` }; + await res.body?.cancel().catch(() => {}); + // A pinned build that is gone is this spec's own problem, not an upstream one. + if (res.status === 404) return { ok: false, error: `build ${app.build ?? app.sha256.slice(0, 12)} of ${app.name ?? "the app"} is not on the brain` }; + return null; + } + if (!app.name) return null; // the brain refuses it at enqueue, and says why + const res = await fetch(`${BASE}/api/artifacts?app=${encodeURIComponent(app.name)}&per_page=1`, { signal: AbortSignal.timeout(15_000) }) + .catch((e: Error) => e); + if (res instanceof Error || !res.ok) { + return { ok: false, error: `could not ask the brain for ${app.name}'s builds: ${res instanceof Error ? res.message : `GET /api/artifacts -> ${res.status}`}` }; + } + const newest = ((await res.json()) as { artifacts?: BrainBuild[] }).artifacts?.[0]; + if (!newest) return { ok: true, error: buildMissing(app.name, undefined, new Date())! }; + if (!fresh) return null; + const since = nightStart(new Date()); + const why = buildMissing(app.name, newest, since, fetchedSince(item.spec.params?.changed?.repo, since)); + return why ? { ok: true, error: why } : null; +} + +/** + * Post a spec that will not run as a finished job: enqueued, then closed at + * once with a final row on host:, the way the executor itself + * closes a job it skips. No executor is polling yet, so nothing claims it in + * between. The build is left out: nothing was tested, and a skip pinned to + * yesterday's build would read as yesterday's build having been tested. + */ +async function postUnrun(item: Item, v: Verdict): Promise { + const { sha256: _sha, build: _build, ...app } = item.spec.app ?? {}; + const body = { + ...item.spec, job_id: item.jobId, ...(item.spec.app ? { app } : {}), + targets: { ...(item.spec.targets ?? {}), executor: NAME }, + }; + const tag = path.basename(item.path); + try { + const q = await fetch(`${BASE}/jobs`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body), signal: AbortSignal.timeout(15_000) }); + if (!q.ok) return `${tag}: POST /jobs -> ${q.status} ${(await q.text()).slice(0, 200)}`; + const r = await fetch(`${BASE}/results`, { + method: "POST", headers: { "content-type": "application/json" }, signal: AbortSignal.timeout(15_000), + body: JSON.stringify({ schema: 1, kind: "result", job_id: item.jobId, device_id: `host:${NAME}`, iter: 0, final: true, ok: v.ok, error: v.error.slice(0, 500) }), + }); + if (!r.ok) return `${tag}: POST /results -> ${r.status}`; + } catch (e) { + return `${tag}: ${(e as Error).message}`; + } + log(`${item.jobId}: ${v.ok ? "" : "failed: "}${v.error}`); + return `${item.jobId}: ${v.ok ? "skipped" : "failed"}`; +} + +/** Run the warm-up command, retrying a refusal for memory until `untilMs`. */ +async function warmUp(cmd: string, untilMs: number): Promise<{ ok: true } | { ok: false; refused: boolean; line: string }> { + for (let attempt = 1; ; attempt++) { + const out = await run("/bin/bash", ["-c", cmd], { timeout: 15 * 60_000, maxBuffer: 4 << 20 }) + .then((r) => ({ code: 0, text: `${r.stdout}${r.stderr}` }), + (e: { code?: number; stdout?: string; stderr?: string; message: string }) => ({ code: e.code ?? 1, text: `${e.stdout ?? ""}${e.stderr ?? ""}` || e.message })); + for (const l of out.text.split("\n").filter((x) => x.trim())) log(`warm: ${l}`); + if (out.code === 0) return { ok: true }; + const refused = warmRefusedForMemory(out.text); + if (!refused || Date.now() + 60_000 > untilMs) return { ok: false, refused, line: lastLine(out.text) || `exit ${out.code}` }; + if (attempt === 1) log(`the warm-up was refused for memory; retrying every minute until ${hhmm(new Date(untilMs))}`); + await sleep(60_000); + } +} + async function main() { - const tunnel = arg("--tunnel"); - const closeTunnel = tunnel ? await openTunnel(tunnel) : () => {}; - process.once("exit", () => closeTunnel()); // Several --spec flags run one after another on the same device, sharing // the tunnel and the executor: a night can drive Holo4 and then the // resident model through the same bench, or a TV bench and its explorers. @@ -141,8 +250,86 @@ async function main() { if (!specPaths.length) throw new Error("--spec is required (repeatable)"); const avd = arg("--avd"); const sim = arg("--sim"); + const warm = arg("--warm"); + const dry = a.includes("--dry-run"); + const fresh = a.includes("--fresh-build"); + const num = (k: string) => { const v = arg(k); if (v === undefined) return undefined; const n = Number(v); if (!(n > 0)) throw new Error(`${k} wants a positive number, got "${v}"`); return n; }; + const minUseful = num("--min-minutes") ?? NIGHT.minUsefulMin; + const warmWait = num("--warm-wait") ?? NIGHT.warmWaitMin; + const maxMinutes = num("--max-minutes") ?? nightManifestMinutes(); const night = new Date().toISOString().slice(0, 10); + const items: Item[] = specPaths.map((p) => { + const spec = JSON.parse(readFileSync(p, "utf8")) as Spec; + const asked = typeof spec.params?.minutes === "number" ? spec.params.minutes : 150; + return { path: p, spec, asked, jobId: `${spec.job_id ?? "explore"}-${night}-${Math.random().toString(36).slice(2, 6)}` }; + }); + + const { end, by } = nightEnd({ now: new Date(), startedAt: STARTED, until: arg("--until"), maxMinutes }); + log(`the night ends at ${hhmm(end)} (${by}): ${minutesLeft(end)} minutes left; the specs ask for ${items.map((i) => i.asked).join(" + ")}`); + + const tunnel = arg("--tunnel"); + const closeTunnel = tunnel ? await openTunnel(tunnel) : () => {}; + process.once("exit", () => closeTunnel()); + + // --- preflight: cheap checks before the model or a device ---------------- + const verdicts = new Map(); + for (const item of items) { + const v = await buildProblem(item, fresh); + if (v) verdicts.set(item, v); + } + const runnable = () => items.filter((i) => !verdicts.has(i)); + const tooShort = (left: number) => + `skipped: ${Math.max(0, left)} minutes left before ${by}, under the ${minUseful}-minute minimum for this spec`; + { + const left = minutesLeft(end); + const list = runnable(); + const plan = planSpecs(list.map((i) => i.asked), left, { minUsefulMin: minUseful }); + list.forEach((i, k) => { if (plan.minutes[k] === 0) verdicts.set(i, { ok: true, error: tooShort(left) }); }); + if (plan.short && plan.minutes.some((m) => m > 0)) { + log(`short night: ${list.map((i, k) => `${path.basename(i.path)} ${plan.minutes[k]} of ${i.asked} min`).join(", ")}`); + } + } + for (const [i, v] of verdicts) log(`${path.basename(i.path)}: ${v.ok ? "" : "cannot run: "}${v.error}`); + + if (dry) { + for (const i of runnable()) log(`would run ${path.basename(i.path)}`); + if (warm && runnable().length) log(`would warm: ${warm}`); + if ((avd || sim) && runnable().length) log(`would boot ${avd ?? sim?.split(":")[0]} if it is not up`); + log(`dry run: nothing enqueued, posted, warmed or booted`); + process.exit(0); + } + + const outcomes: string[] = []; + const finish = (): never => { + const bad = outcomes.filter((o) => !/: (done|skipped)$/.test(o)); + log(bad.length ? `not every job finished: ${bad.join("; ")}` : `all ${outcomes.length} job(s) done or skipped: ${outcomes.join("; ")}`); + process.exit(bad.length ? 1 : 0); + }; + const postAll = async (v?: Verdict) => { + for (const i of items) { + const verdict = verdicts.get(i) ?? v; + if (verdict) outcomes.push(await postUnrun(i, verdict)); + } + }; + + if (runnable().length === 0) { await postAll(); finish(); } + + // --- the model --------------------------------------------------------- + if (warm) { + // The wait for room may use the night, but must leave the minimum. + const w = await warmUp(warm, Math.min(Date.now() + warmWait * 60_000, end.getTime() - (minUseful + NIGHT.safetyMin) * 60_000)); + if (!w.ok) { + const v: Verdict = w.refused + ? { ok: true, error: `skipped: the model would not load, no room on this host: ${w.line}` } + : { ok: false, error: `the model did not load: ${w.line}` }; + for (const i of runnable()) verdicts.set(i, v); + await postAll(); + finish(); + } + } + + // --- devices and the executor ------------------------------------------- let emulator: { serial: string; booted: boolean } | null = null; let simulator: { udid: string; booted: boolean } | null = null; if (avd) emulator = await bootEmulator(avd); @@ -156,20 +343,32 @@ async function main() { const { startExecutor } = await import("../src/executor.js"); const executor = await startExecutor(); - const outcomes: string[] = []; try { - for (const specPath of specPaths) { - const spec = JSON.parse(readFileSync(specPath, "utf8")) as Record & { targets?: Record; job_id?: string }; - const jobId = `${spec.job_id ?? "explore"}-${night}-${Date.now().toString(36).slice(-4)}`; - const body = { ...spec, job_id: jobId, targets: { ...(spec.targets ?? {}), executor: NAME, ...(deviceId ? { device_id: deviceId } : {}) } }; + for (const item of items) { + const v = verdicts.get(item); + if (v) { outcomes.push(await postUnrun(item, v)); continue; } + // Plan again with the time actually left: warming and booting took some, + // and so did the specs before this one. + const left = minutesLeft(end); + const rest = items.filter((i) => !verdicts.has(i) && items.indexOf(i) >= items.indexOf(item)); + const minutes = planSpecs(rest.map((i) => i.asked), left, { minUsefulMin: minUseful }).minutes[0]; + if (!minutes) { outcomes.push(await postUnrun(item, { ok: true, error: tooShort(left) })); continue; } + const short = minutes < item.asked; + if (short) log(`${path.basename(item.path)}: ${minutes} of its ${item.asked} minutes (${left} left before ${by})`); + const { spec, jobId } = item; + const body = { + ...spec, job_id: jobId, + params: { ...(spec.params ?? {}), minutes, ...(short ? { short_night: { asked: item.asked } } : {}) }, + targets: { ...(spec.targets ?? {}), executor: NAME, ...(deviceId ? { device_id: deviceId } : {}) }, + }; const res = await fetch(`${BASE}/jobs`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) }); - if (!res.ok) { outcomes.push(`${path.basename(specPath)}: POST /jobs -> ${res.status} ${(await res.text()).slice(0, 200)}`); continue; } + if (!res.ok) { outcomes.push(`${path.basename(item.path)}: POST /jobs -> ${res.status} ${(await res.text()).slice(0, 200)}`); continue; } log(`queued ${jobId} for executor ${NAME}`); let final = { status: "unknown" } as { status: string; last_error?: string | null }; for (;;) { await sleep(20_000); final = await jobStatus(jobId).catch((e) => { log(`status: ${(e as Error).message}`); return final; }); - if (["done", "failed", "cancelled"].includes(final.status)) break; + if (["done", "failed", "cancelled", "skipped"].includes(final.status)) break; } log(`${jobId}: ${final.status}${final.last_error ? ` (${final.last_error})` : ""}`); outcomes.push(`${jobId}: ${final.status}`); @@ -185,9 +384,7 @@ async function main() { await run("xcrun", ["simctl", "shutdown", simulator.udid]).catch(() => {}); } } - const failed = outcomes.filter((o) => !o.endsWith(": done")); - log(failed.length ? `not every job finished: ${failed.join("; ")}` : `all ${outcomes.length} job(s) done`); - process.exit(failed.length ? 1 : 0); + finish(); } main().catch((e) => { diff --git a/collector/src/describe.test.ts b/collector/src/describe.test.ts index e37658d..a1cbc38 100644 --- a/collector/src/describe.test.ts +++ b/collector/src/describe.test.ts @@ -34,6 +34,25 @@ export async function runDescribeChecks(check: Check) { check("a wired devicectl entry is still hardware", d2.kind === "device", JSON.stringify(d2)); check("and keeps its product type as the soc", d2.soc === "iPhone17,1", JSON.stringify(d2)); + // --- an Apple TV simulator is tvOS ---------------------------------------- + // simctl's runtime key was read for `iOS-` only, so a tvOS simulator + // registered as plain "ios" and every `os ~ 'tvos'` job skipped with "no + // device matches" -- three fleet-explore-tv nights in a row. + const sims = { + "com.apple.CoreSimulator.SimRuntime.tvOS-26-5": [{ udid: "TV-SIM", name: "fleet-explore-tvos" }], + "com.apple.CoreSimulator.SimRuntime.iOS-26-5": [{ udid: "IOS-SIM", name: "fleet-explore-ios" }], + }; + const tv = await describeTarget({ id: "TV-SIM", platform: "tvos", kind: "simulator" } as never, sims, null); + check("a tvOS simulator's os is tvos-", tv.os === "tvos-26.5", JSON.stringify(tv)); + check("and it is a simulator", tv.kind === "simulator" && tv.soc === "simulator", JSON.stringify(tv)); + const ph = await describeTarget({ id: "IOS-SIM", platform: "ios", kind: "simulator" } as never, sims, null); + check("an iOS simulator is still ios-", ph.os === "ios-26.5", JSON.stringify(ph)); + const { evalMatch } = await import("./match.js"); + check("os ~ 'tvos' selects the TV and not the phone", + evalMatch("os ~ 'tvos'", tv) && !evalMatch("os ~ 'tvos'", ph)); + check("os ~ 'ios' selects the phone and not the TV", + evalMatch("os ~ 'ios'", ph) && !evalMatch("os ~ 'ios'", tv)); + // --- a Roku is a Roku ------------------------------------------------------ // It used to fall through to the iOS fallback and register as an iPhone. const express = { diff --git a/collector/src/executor.ts b/collector/src/executor.ts index d825343..4bc477d 100644 --- a/collector/src/executor.ts +++ b/collector/src/executor.ts @@ -19,7 +19,7 @@ import { runArchive } from "./web/archive/index.js"; import { runDigest } from "./web/digest.js"; import { countXcodebuildTests, xcodebuildDiagnostics } from "./xcparse.js"; import { - fleetOwned, physicalApple, simulatorName, isAndroidEmulatorSerial, appleNotReadyReason, + fleetOwned, physicalApple, simulatorName, simulatorPlatform, isAndroidEmulatorSerial, appleNotReadyReason, SIM_PREFIX, type IosDeviceInfo, } from "./targets.js"; @@ -2413,11 +2413,16 @@ export async function describeTarget( for (const [runtime, list] of Object.entries(sims ?? {})) { const hit = list.find((d) => d.udid === t.id); if (!hit) continue; - // "com.apple.CoreSimulator.SimRuntime.iOS-18-4" -> "ios-18.4" - const v = /iOS-([\d-]+)$/.exec(runtime)?.[1]?.replace(/-/g, "."); + // "com.apple.CoreSimulator.SimRuntime.iOS-18-4" -> "ios-18.4", and + // "…SimRuntime.tvOS-26-5" -> "tvos-26.5". This read `iOS-` only, so an + // Apple TV simulator registered as plain "ios" and every `os ~ 'tvos'` + // job skipped with "no device matches" (the fleet-explore-tv nights of + // 10-12 to 10-14, each "done" in twenty seconds). + const family = simulatorPlatform(runtime) ?? "ios"; + const v = /SimRuntime\.[A-Za-z]+-([\d-]+)$/.exec(runtime)?.[1]?.replace(/-/g, "."); return { model: hit.name, - os: v ? `ios-${v}` : "ios", + os: v ? `${family}-${v}` : family, serial: t.id, attached_to: NAME, attached_host: HOST, diff --git a/collector/src/workloads/explore/index.ts b/collector/src/workloads/explore/index.ts index 9f2b72e..a0c8876 100644 --- a/collector/src/workloads/explore/index.ts +++ b/collector/src/workloads/explore/index.ts @@ -39,6 +39,7 @@ import { changedFiles, changedWords, loadMissions, orderMissions } from "./missi import type { ModelConfig } from "./model.js"; import { replayThrough, toMaestro } from "./replay.js"; import { tvloopFlow, tvloopFlowFile } from "./replay-tvloop.js"; +import { shortNightNote } from "./night.js"; import { stepsInWords, trajectorySheet } from "./report.js"; import { ScreenMap } from "./screenmap.js"; import type { Actuator, CheckName, ExploreFinding, Mission } from "./types.js"; @@ -71,6 +72,12 @@ type Params = { surface?: "touch" | "dpad"; credentials?: { account: string; email_var?: string; password_var?: string }; mirror?: boolean; + /** + * Set by `scripts/explore-night.ts` when the night had less time left than + * the spec asked for and `minutes` was cut to fit: `asked` is the spec's own + * `minutes`. The result then says how many cards ran in the time there was. + */ + short_night?: { asked: number }; }; type ModelWire = { @@ -285,20 +292,23 @@ export async function run_(job: Job, ctx: WorkloadCtx): Promise { } let allOk = targets.length > 0; + const notes: string[] = []; try { for (const t of targets) { if (Date.now() > deadline) break; const r = await exploreDevice(t); if (!r.ok) allOk = false; + else if (typeof r.error === "string") notes.push(r.error); await ctx.postResult({ job_id: job.job_id, device_id: t.id, iter: 0, ...r }); } } finally { if (job.targets?.exclusive) await ctx.locks.release(job.job_id); } // The night failed if any device explored nothing. A device that found bugs - // is a device that worked: findings are the output, not the failure. + // is a device that worked: findings are the output, not the failure. A short + // night that ran is ok, and its note rides on the final row too. await ctx.postResult({ job_id: job.job_id, device_id: `host:${ctx.host}`, iter: 0, final: true, ok: allOk, - ...(allOk ? {} : { error: "one or more devices completed no mission; see their rows" }) }); + ...(allOk ? (notes.length ? { error: [...new Set(notes)].join("; ") } : {}) : { error: "one or more devices completed no mission; see their rows" }) }); async function exploreDevice(t: Target): Promise> { let actuator: Actuator; @@ -440,11 +450,18 @@ export async function run_(job: Job, ctx: WorkloadCtx): Promise { const logFile = path.join(work, `${t.id.replace(/[^\w.-]/g, "_")}-missions.json`); writeFileSync(logFile, JSON.stringify(missionLog, null, 1)); const missionsSha = await ctx.uploadArtifact(logFile, `explore-run-${job.job_id}-${t.id}-missions.json`).catch(() => undefined); + // A short night says what it managed in the time it had: "ran 3 of 7 + // cards: 40 minutes left of the 60 asked". On an ok row; it is not an error, + // but `error` is the field a summary, the digest and `fleetr` show. + const note = p.short_night ? shortNightNote(totals.missions, missions.length, p.minutes ?? 150, p.short_night.asked) : null; return { ok: totals.missions > 0, - ...(totals.missions === 0 ? { error: `no mission completed: ${missionLog.map((x) => `${x.id}: ${x.error ?? x.skipped ?? "?"}`).join("; ").slice(0, 400)}` } : {}), + ...(totals.missions === 0 + ? { error: `${note ? `${note}; ` : ""}no mission completed: ${missionLog.map((x) => `${x.id}: ${x.error ?? x.skipped ?? "?"}`).join("; ").slice(0, 400)}` } + : note ? { error: note } : {}), metrics: { - explore_missions: totals.missions, explore_steps: totals.steps, explore_actions: totals.actions, + explore_missions: totals.missions, explore_cards_planned: missions.length, explore_minutes: p.minutes ?? 150, + explore_steps: totals.steps, explore_actions: totals.actions, explore_screens: map.seenThisRun.length, explore_new_screens: missionLog.reduce((a, x) => a + (Number(x.new_screens) || 0), 0), explore_candidates: totals.candidates, explore_findings: totals.findings, explore_findings_new: totals.findingsNew, explore_not_reproduced: totals.notReproduced, explore_misses: totals.misses, explore_refused: totals.refused, diff --git a/collector/src/workloads/explore/manifest.json b/collector/src/workloads/explore/manifest.json index ea2a6a1..d6f55ad 100644 --- a/collector/src/workloads/explore/manifest.json +++ b/collector/src/workloads/explore/manifest.json @@ -100,6 +100,10 @@ "mirror": { "type": "boolean", "description": "Stream each step's screenshot to the job's live view. Default true." + }, + "short_night": { + "type": "object", + "description": "Set by scripts/explore-night.ts when minutes was cut to fit the night: {asked}, the spec's own minutes. The result then says how many cards ran (\"short night: ran 3 of 7 cards: 40 minutes left of the 60 asked\")." } } }, diff --git a/collector/src/workloads/explore/night.test.ts b/collector/src/workloads/explore/night.test.ts new file mode 100644 index 0000000..f6f4098 --- /dev/null +++ b/collector/src/workloads/explore/night.test.ts @@ -0,0 +1,210 @@ +/** + * The night command's preflight, without a brain, a simulator or a model. + * + * The first half pins the pure pieces: when the night ends, how the minutes + * left are shared among the specs, what counts as tonight's build, and which + * warm-up failures are a host with no room. The second half runs + * `scripts/explore-night.ts` itself against a fake brain, with a simulator + * spec and a warm-up command that would both fail loudly if they were ever + * reached, to show that a night with nothing to test or no time left posts a + * skip and exits 0 before it touches either. + */ +import { spawn } from "node:child_process"; +import { mkdirSync, mkdtempSync, utimesSync, writeFileSync } from "node:fs"; +import { createServer, type IncomingMessage } from "node:http"; +import os from "node:os"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { + buildMissing, fetchedSince, lastLine, nextClock, nightEnd, nightManifestMinutes, nightStart, planSpecs, + shortNightNote, warmRefusedForMemory, +} from "./night.js"; + +type Check = (name: string, cond: boolean, detail?: string) => void; + +const at = (y: number, mo: number, d: number, h: number, mi = 0) => new Date(y, mo - 1, d, h, mi, 0, 0); +const same = (a: Date, b: Date) => a.getTime() === b.getTime(); + +export async function runNightChecks(check: Check) { + // --- when the night ends --------------------------------------------------- + check("at 22:00 the 07:30 stop is tomorrow morning", same(nextClock(at(2026, 10, 14, 22), "07:30"), at(2026, 10, 15, 7, 30))); + check("at 03:00 it is this morning", same(nextClock(at(2026, 10, 15, 3), "07:30"), at(2026, 10, 15, 7, 30))); + check("at 07:30 exactly it is tomorrow", same(nextClock(at(2026, 10, 15, 7, 30), "07:30"), at(2026, 10, 16, 7, 30))); + let threw = false; + try { nextClock(new Date(), "7.30"); } catch { threw = true; } + check("a malformed --until is refused, not guessed", threw); + + check("02:00 on Thursday belongs to Wednesday night", same(nightStart(at(2026, 10, 15, 2)), at(2026, 10, 14, 12))); + check("22:00 on Wednesday is Wednesday night", same(nightStart(at(2026, 10, 14, 22)), at(2026, 10, 14, 12))); + + const e1 = nightEnd({ now: at(2026, 10, 15, 6, 30), startedAt: at(2026, 10, 15, 6, 30), maxMinutes: 90 }); + check("06:30 with 90 minutes: the 07:30 stop comes first", same(e1.end, at(2026, 10, 15, 7, 30)) && e1.by === "the 07:30 stop", JSON.stringify(e1)); + const e2 = nightEnd({ now: at(2026, 10, 14, 23), startedAt: at(2026, 10, 14, 23), maxMinutes: 150 }); + check("23:00 with 150 minutes: max_minutes comes first", same(e2.end, at(2026, 10, 15, 1, 30)) && /150-minute max_minutes/.test(e2.by), JSON.stringify(e2)); + const e3 = nightEnd({ now: at(2026, 10, 15, 6), startedAt: at(2026, 10, 15, 6), until: "06:45" }); + check("--until moves the stop", same(e3.end, at(2026, 10, 15, 6, 45)) && e3.by === "the 06:45 stop"); + + // --- max_minutes from the night queue's manifest ---------------------------- + const files: Record = { + "/n/recurring/fleet-explore-tv.json": JSON.stringify({ name: "fleet-explore-tv", max_minutes: 150 }), + "/n/queue/one-off.json": JSON.stringify({ name: "one-off" }), + }; + const read = (p: string) => { if (!(p in files)) throw new Error("ENOENT"); return files[p]; }; + check("NIGHT_JOB's manifest gives max_minutes", nightManifestMinutes({ NIGHT_JOB: "fleet-explore-tv", NIGHT_ROOT: "/n" }, read) === 150); + check("a manifest without it gets the queue's default of 60", nightManifestMinutes({ NIGHT_JOB: "one-off", NIGHT_ROOT: "/n" }, read) === 60); + check("no NIGHT_JOB: no budget beyond --until", nightManifestMinutes({ NIGHT_ROOT: "/n" }, read) === undefined); + check("a NIGHT_JOB that is not a manifest name is not a path", nightManifestMinutes({ NIGHT_JOB: "../etc/x", NIGHT_ROOT: "/n" }, read) === undefined); + + // --- sharing the minutes left ------------------------------------------------ + const full = planSpecs([60], 300); + check("a night with room runs the spec as asked", full.minutes[0] === 60 && !full.short, JSON.stringify(full)); + const apple = planSpecs([60], 50); + check("50 minutes left for a 60-minute spec: 37 (10 held back, 3 to start it)", apple.minutes[0] === 37 && apple.short, JSON.stringify(apple)); + const none = planSpecs([60], 25); + check("25 minutes left: under the 15-minute minimum, so nothing runs", none.minutes[0] === 0 && none.short, JSON.stringify(none)); + const tv = planSpecs([45, 45, 30], 150); + check("the TV night fits in 150 minutes", tv.minutes.join() === "45,45,30" && !tv.short, JSON.stringify(tv)); + const tv80 = planSpecs([45, 45, 30], 80); + check("80 minutes: all three, in proportion", tv80.minutes.join() === "22,22,15" && tv80.short, JSON.stringify(tv80)); + const tv50 = planSpecs([45, 45, 30], 50); + check("50 minutes: the last spec is dropped before anything goes under 15", tv50.minutes.join() === "17,17,0", JSON.stringify(tv50)); + check("20 minutes: none of the TV night", planSpecs([45, 45, 30], 20).minutes.every((m) => m === 0)); + check("a spec asking for less than the minimum needs only what it asks", planSpecs([10], 30).minutes[0] === 10); + check("a custom minimum is honoured", planSpecs([60], 30, { minUsefulMin: 20 }).minutes[0] === 0 && planSpecs([60], 40, { minUsefulMin: 20 }).minutes[0] === 27); + check("no specs, nothing to plan", planSpecs([], 100).minutes.length === 0); + + check("the short-night note says what ran in what time", + shortNightNote(3, 7, 40, 60) === "short night: ran 3 of 7 cards: 40 minutes left of the 60 asked", shortNightNote(3, 7, 40, 60)); + check("and counts one card as a card", shortNightNote(1, 1, 20, 45).includes("ran 1 of 1 card:")); + + // --- tonight's build ------------------------------------------------------------- + const since = new Date("2026-10-14T16:00:00Z"); // noon EDT + const tonight = { sha256: "a".repeat(64), build: "develop-3c16689273", published_at: "2026-10-15T02:52:59Z" }; + const lastNight = { sha256: "b".repeat(64), build: "develop-3c16689273", published_at: "2026-10-14T02:52:59Z" }; + check("a build published tonight is tonight's", buildMissing("greenfolio-ios", tonight, since) === null); + const stale = buildMissing("greenfolio-ios", lastNight, since, false); + check("last night's build is not, and the skip says why", + !!stale && stale.startsWith("skipped: no greenfolio-ios build for tonight (fleet-explore-builds did not run") && + stale.includes("develop-3c16689273 from 2026-10-14 02:52 UTC"), String(stale)); + check("a checkout fetched tonight with no upload says the build job ran", + /fetched develop but uploaded no build/.test(buildMissing("greenfolio-ios", lastNight, since, true) ?? "")); + check("unknown checkout state says either", + /did not run or did not upload it/.test(buildMissing("greenfolio-ios", lastNight, since, null) ?? "")); + check("no build ever is a skip too", + buildMissing("dozehound-tvos", undefined, since)?.startsWith("skipped: no dozehound-tvos build on the brain") === true); + check("created_at stands in for an artifact never published by app", + buildMissing("x", { sha256: "c".repeat(64), build: null, published_at: null, created_at: "2026-10-15T01:00:00Z" }, since) === null); + + const repo = mkdtempSync(path.join(os.tmpdir(), "fleet-night-repo-")); + check("no checkout: unknown", fetchedSince(repo, since) === null); + mkdirSync(path.join(repo, ".git")); + writeFileSync(path.join(repo, ".git", "FETCH_HEAD"), ""); + utimesSync(path.join(repo, ".git", "FETCH_HEAD"), new Date("2026-10-13T03:00:00Z"), new Date("2026-10-13T03:00:00Z")); + check("a checkout last fetched yesterday was not fetched tonight", fetchedSince(repo, since) === false); + utimesSync(path.join(repo, ".git", "FETCH_HEAD"), new Date("2026-10-15T03:00:00Z"), new Date("2026-10-15T03:00:00Z")); + check("one fetched at 23:00 was", fetchedSince(repo, since) === true); + check("no repo named: unknown", fetchedSince(undefined, since) === null); + + // --- warm-ups ----------------------------------------------------------------- + const oct14 = "2026-10-15 05:09:50 not loading holo4-35b-a3b@holo4-35b-a3b-gguf: 64% free, needs 65%"; + check("10-14's warm-up was refused for memory", warmRefusedForMemory(oct14)); + check("so is one refused under pressure", warmRefusedForMemory("2026-10-15 05:09:50 not loading pilot: memory pressure")); + check("a load that broke is not a refusal", !warmRefusedForMemory("2026-10-15 05:09:50 load FAILED holo4-35b-a3b")); + check("the reason is the last line", lastLine(`a\n${oct14}\n\n`) === oct14); + + await runNightCommandChecks(check); +} + +/** explore-night.ts against a fake brain: what it posts, and that it never reaches the device. */ +async function runNightCommandChecks(check: Check) { + const posts: { url: string; body: Record }[] = []; + let published = "2026-01-01T00:00:00Z"; + const body = (req: IncomingMessage) => new Promise((r) => { let s = ""; req.on("data", (c) => (s += c)); req.on("end", () => r(s)); }); + const server = createServer(async (req, res) => { + const url = req.url ?? ""; + const send = (code: number, o: unknown) => { res.writeHead(code, { "content-type": "application/json" }); res.end(JSON.stringify(o)); }; + if (url === "/api/health") return send(200, { ok: true }); + if (url.startsWith("/api/artifacts?")) { + return send(200, { artifacts: [{ sha256: "d".repeat(64), build: "develop-0123456789", published_at: published }] }); + } + if (req.method === "POST" && (url === "/jobs" || url === "/results")) { + posts.push({ url, body: JSON.parse(await body(req)) }); + return send(url === "/jobs" ? 201 : 200, { ok: true }); + } + send(404, { error: "not here" }); + }); + await new Promise((r) => server.listen(0, "127.0.0.1", () => r())); + const port = (server.address() as { port: number }).port; + + const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../.."); + const dir = mkdtempSync(path.join(os.tmpdir(), "fleet-night-cmd-")); + const specFile = path.join(dir, "spec.json"); + writeFileSync(specFile, JSON.stringify({ + schema: 1, job_id: "explore-greenfolio-ios", workload: "explore", executor: "host", + app: { name: "greenfolio-ios", build: "latest", sha256: "latest", platform: "ios" }, + targets: { executor: "ultra", match: "os ~ 'ios'" }, params: { app_id: "com.taylab.greenfolio", minutes: 60 }, + })); + // If either of these were reached the run would fail: there is no such + // simulator runtime, and the warm-up exits 3 and is not a memory refusal. + const deviceAndModel = ["--sim", "fleet-night-test:no.such.runtime:no.such.type", "--warm", "echo warmed-up >&2; exit 3"]; + const runNight = (extra: string[], env: NodeJS.ProcessEnv = {}) => new Promise<{ code: number; out: string }>((resolve) => { + const p = spawn(process.execPath, [path.join(root, "node_modules/tsx/dist/cli.mjs"), "scripts/explore-night.ts", "--spec", specFile, ...deviceAndModel, ...extra], { + cwd: root, env: { ...process.env, FLEET_URL: `http://127.0.0.1:${port}`, FLEET_EXECUTOR_NAME: "night-test", NIGHT_JOB: "", ...env }, + }); + let out = ""; + p.stdout.on("data", (c) => (out += c)); + p.stderr.on("data", (c) => (out += c)); + const kill = setTimeout(() => p.kill("SIGKILL"), 60_000); + p.on("exit", (code) => { clearTimeout(kill); resolve({ code: code ?? -1, out }); }); + }); + + const hm = (d: Date) => `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`; + // A stop a minute ago is almost a whole day away: room for anything. + const roomy = ["--until", hm(new Date(Date.now() - 60_000))]; + try { + // 1. No build for tonight: skipped, before the model or the simulator. + const r1 = await runNight(["--fresh-build"]); + const job = posts.find((x) => x.url === "/jobs")?.body; + const result = posts.find((x) => x.url === "/results")?.body; + check("no build for tonight: exit 0, because it is not this job's failure", r1.code === 0, r1.out); + check("it posted the job to the brain, pinned to this executor", job?.targets?.executor === "night-test" && /^explore-greenfolio-ios-\d{4}-\d\d-\d\d-/.test(job?.job_id ?? ""), JSON.stringify(job)); + check("without a build: nothing was tested", job?.app?.sha256 === undefined && job?.app?.name === "greenfolio-ios", JSON.stringify(job?.app)); + check("and closed it as a skip that says why", + result?.final === true && result?.ok === true && result?.device_id === "host:night-test" && + String(result?.error).startsWith("skipped: no greenfolio-ios build for tonight (fleet-explore-builds did not run"), + JSON.stringify(result)); + check("the night queue's log says so too", /skipped: no greenfolio-ios build for tonight/.test(r1.out), r1.out); + check("the warm-up never ran and no simulator was booted", !/warmed-up|booting|creating simulator/.test(r1.out), r1.out); + + // 2. A dry run with a build from tonight: says what it would do, posts nothing. + posts.length = 0; + published = new Date().toISOString(); + const r2 = await runNight(["--fresh-build", "--dry-run", ...roomy]); + check("a dry run exits 0", r2.code === 0, r2.out); + check("and posts nothing to the brain", posts.length === 0, JSON.stringify(posts)); + check("it would run the spec, warm the model and boot the simulator", + /would run spec\.json/.test(r2.out) && /would warm: echo warmed-up/.test(r2.out) && /would boot fleet-night-test/.test(r2.out), r2.out); + check("and did none of it", !/warm: warmed-up|booting|creating simulator/.test(r2.out), r2.out); + + // 3. Too little night left: skipped, before the model or the simulator. + posts.length = 0; + const soon = new Date(Date.now() + 12 * 60_000); + const r3 = await runNight(["--until", hm(soon)]); + const r3result = posts.find((x) => x.url === "/results")?.body; + check("eleven or so minutes left: exit 0", r3.code === 0, r3.out); + check("posted as a skip under the minimum", + r3result?.ok === true && /^skipped: 1\d minutes left before the \d\d:\d\d stop, under the 15-minute minimum/.test(String(r3result?.error)), + JSON.stringify(r3result)); + check("again without warming or booting", !/warmed-up|booting|creating simulator/.test(r3.out), r3.out); + + // 4. The warm-up fails for a reason that is not memory: a failure, posted as one. + posts.length = 0; + const r4 = await runNight(roomy); + const r4result = posts.find((x) => x.url === "/results")?.body; + check("a broken warm-up fails the night (exit 1)", r4.code === 1, r4.out); + check("and the brain is told why", r4result?.ok === false && /^the model did not load: warmed-up/.test(String(r4result?.error)), JSON.stringify(r4result)); + check("the simulator was still not booted", !/booting|creating simulator/.test(r4.out), r4.out); + } finally { + server.close(); + } +} diff --git a/collector/src/workloads/explore/night.ts b/collector/src/workloads/explore/night.ts new file mode 100644 index 0000000..2ab4ae7 --- /dev/null +++ b/collector/src/workloads/explore/night.ts @@ -0,0 +1,185 @@ +/** + * The decisions `scripts/explore-night.ts` makes before it spends a night, + * kept pure so they can be tested without a brain, a simulator or a model. + * + * Two questions, both asked before the model is warmed or a device booted: + * + * 1. **Is there anything to test?** A night that explores tonight's build + * needs tonight's build. When `fleet-explore-builds` did not run (10-14: + * it waited two hours behind a CI job and was skipped), the dependent + * nights used to warm a 35B model, boot a simulator and then fail. Now + * they post a skip and exit 0: a missing upstream build is not their + * failure, and ultra's night queue has no skip exit code to say so. + * 2. **How much time is left?** ultra's night queue stops at 07:30 and kills + * a job at its manifest's `max_minutes`. A night given less than its specs + * ask for runs every spec shorter, highest-priority cards first (the + * workload already orders them), and says so in its result, instead of + * being killed halfway with nothing posted. + */ +import { readFileSync, statSync } from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +export const NIGHT = { + /** The night queue's hard stop. */ + until: "07:30", + /** Held back at the end: the last replay, uploads, shutting devices down. */ + safetyMin: 10, + /** Per spec: enqueue, claim, install, the first model call. */ + perSpecMin: 3, + /** Less exploring than this is not worth booting a simulator for. */ + minUsefulMin: 15, + /** How long a warm-up refused for memory is retried before the night skips. */ + warmWaitMin: 10, +} as const; + +const MIN = 60_000; + +/** The next local HH:MM strictly after `now`. */ +export function nextClock(now: Date, hhmm: string): Date { + const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim()); + if (!m || Number(m[1]) > 23 || Number(m[2]) > 59) throw new Error(`--until wants HH:MM, got "${hhmm}"`); + const at = new Date(now); + at.setHours(Number(m[1]), Number(m[2]), 0, 0); + if (at.getTime() <= now.getTime()) at.setDate(at.getDate() + 1); + return at; +} + +/** + * When tonight began, for "is this build from tonight": noon on the night's + * date, the same rule as the night queue's `night_of` (02:00 on Tuesday is + * Monday night). A build uploaded during the day counts as tonight's. + */ +export function nightStart(now: Date): Date { + const at = new Date(now); + if (at.getHours() < 12) at.setDate(at.getDate() - 1); + at.setHours(12, 0, 0, 0); + return at; +} + +/** + * `max_minutes` from the night queue's manifest for this job, if it can be + * read. The queue hands a job `NIGHT_JOB` (its name) but not its budget, and + * kills it when the budget runs out, so the manifest is the only place the + * job can learn it. Read-only; nothing here writes to the queue. + */ +export function nightManifestMinutes( + env: NodeJS.ProcessEnv = process.env, + read: (p: string) => string = (p) => readFileSync(p, "utf8"), +): number | undefined { + const name = env.NIGHT_JOB; + if (!name || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(name)) return undefined; + const root = env.NIGHT_ROOT ?? path.join(env.HOME ?? os.homedir(), "night"); + for (const kind of ["recurring", "queue"]) { + try { + const m = JSON.parse(read(path.join(root, kind, `${name}.json`))) as { max_minutes?: unknown }; + if (typeof m.max_minutes === "number" && m.max_minutes > 0) return m.max_minutes; + return 60; // the queue's own default when a manifest leaves it out + } catch { /* not this one */ } + } + return undefined; +} + +export type NightEnd = { end: Date; by: string }; + +/** Whichever comes first: `--until`, or the job's own `max_minutes` from when it started. */ +export function nightEnd(o: { now: Date; startedAt: Date; until?: string; maxMinutes?: number }): NightEnd { + const until = o.until ?? NIGHT.until; + const stop = nextClock(o.now, until); + if (o.maxMinutes !== undefined) { + const killed = new Date(o.startedAt.getTime() + o.maxMinutes * MIN); + if (killed < stop) return { end: killed, by: `the job's ${o.maxMinutes}-minute max_minutes` }; + } + return { end: stop, by: `the ${until} stop` }; +} + +export type Plan = { + /** Minutes per spec, in the order given; 0 means the spec does not fit tonight. */ + minutes: number[]; + /** Anything given less than it asked for. */ + short: boolean; +}; + +/** + * Share the minutes left among the specs still to run. + * + * Every spec keeps what it asks for when that fits. Otherwise each gets a + * share in proportion to what it asked, and if a share would be under the + * useful minimum, the last spec is dropped and the rest share again: a TV night + * would rather run its bench and the explorer properly than all three at five + * minutes each. Called again before each spec, with the time actually left. + */ +export function planSpecs(asked: number[], leftMin: number, o: { safetyMin?: number; perSpecMin?: number; minUsefulMin?: number } = {}): Plan { + const safety = o.safetyMin ?? NIGHT.safetyMin; + const perSpec = o.perSpecMin ?? NIGHT.perSpecMin; + const minUseful = o.minUsefulMin ?? NIGHT.minUsefulMin; + for (let k = asked.length; k >= 1; k--) { + const avail = leftMin - safety - k * perSpec; + const want = asked.slice(0, k); + const sum = want.reduce((a, b) => a + b, 0); + const minutes = want.map((m) => (sum <= avail ? m : Math.floor((avail * m) / sum))); + // A spec that asks for less than the minimum only needs what it asks for. + if (minutes.every((m, i) => m >= Math.min(minUseful, want[i]))) { + const all = [...minutes, ...asked.slice(k).map(() => 0)]; + return { minutes: all, short: all.some((m, i) => m < asked[i]) }; + } + } + return { minutes: asked.map(() => 0), short: asked.length > 0 }; +} + +/** What a short night's result says, on its device row and its final row. */ +export function shortNightNote(ran: number, planned: number, minutes: number, asked: number): string { + return `short night: ran ${ran} of ${planned} card${planned === 1 ? "" : "s"}: ${Math.round(minutes)} minutes left of the ${asked} asked`; +} + +/** The newest build the brain holds for an app, as `GET /api/artifacts?app=` lists it. */ +export type BrainBuild = { sha256: string; build: string | null; published_at: string | null; created_at?: string | null }; + +/** + * Why tonight's build is missing, or null when it is there. + * + * "Tonight's" means published since `since` (noon of the night's date). + * `nightly-builds.sh` republishes an unchanged build each night for exactly + * this check, so an old `published_at` means the build job did not run or did + * not upload this app. `fetchedTonight` -- whether the app's checkout under + * ~/explore/builds was fetched tonight -- tells those two apart when known. + */ +export function buildMissing(app: string, newest: BrainBuild | undefined, since: Date, fetchedTonight?: boolean | null): string | null { + if (!newest) return `skipped: no ${app} build on the brain (fleet-explore-builds has never uploaded one)`; + const at = newest.published_at ?? newest.created_at ?? null; + const t = at ? Date.parse(at) : NaN; + if (Number.isFinite(t) && t >= since.getTime()) return null; + const why = fetchedTonight === false ? "fleet-explore-builds did not run, or could not fetch develop" + : fetchedTonight === true ? "fleet-explore-builds fetched develop but uploaded no build; see its log" + : "fleet-explore-builds did not run or did not upload it"; + const which = `${newest.build ?? newest.sha256.slice(0, 12)}${at ? ` from ${at.slice(0, 16).replace("T", " ")} UTC` : ""}`; + return `skipped: no ${app} build for tonight (${why}; the newest is ${which})`; +} + +/** Whether a checkout was fetched since `since`: its FETCH_HEAD's mtime. Null when there is no checkout. */ +export function fetchedSince(repo: string | undefined, since: Date): boolean | null { + if (!repo) return null; + const dir = repo.replace(/^~(?=\/|$)/, os.homedir()); + try { + return statSync(path.join(dir, ".git", "FETCH_HEAD")).mtimeMs >= since.getTime(); + } catch { + return null; + } +} + +/** + * A warm-up the shelf refused for memory, not one that broke. ultra's + * `shelf.sh warm` says "not loading : memory pressure" or "…: 64% free, + * needs 65%". On 10-14 exactly that, one point short, was `fleet-explore-apple`'s + * `exit 1 in 0.0 min`. A refusal is retried, then is a skip: a host without + * room is the brain's `skipped:` case, as it is for the executor's own + * pressure check. Anything else is a failure. + */ +export function warmRefusedForMemory(output: string): boolean { + return /memory pressure|\d+% free, needs \d+%/i.test(output); +} + +/** The last non-empty line of some output, for a one-line reason. */ +export function lastLine(output: string): string { + return output.split("\n").map((l) => l.trim()).filter(Boolean).pop() ?? ""; +} diff --git a/docs/deploy/explore-on-ultra.md b/docs/deploy/explore-on-ultra.md index fdd7323..bf367b0 100644 --- a/docs/deploy/explore-on-ultra.md +++ b/docs/deploy/explore-on-ultra.md @@ -23,16 +23,19 @@ LaunchDaemons. Explore plugs into that rather than running its own. | The emulator | AVD `fleet-explore-1`, android-35 `google_apis`, 1080×2400 at 420 dpi | | Holo4 | `~/.lmstudio/models/Hcompany/Holo4-35B-A3B-GGUF/`: the vendor's Q4_K_M and its vision projector, renamed to LM Studio's convention (`Holo4-35B-A3B-Q4_K_M.gguf`, `mmproj-Holo4-35B-A3B-F16.gguf`) or LM Studio lists the projector as a separate model and cannot pair them. Model key `holo4-35b-a3b`, identifier `holo4-35b-a3b-gguf` | | The gateway name | `pilot` in the harness's `litellm.yaml`: Holo4, 300 s timeout, no fallback. The judge is the harness's `judge` role | -| The shelf | `ondemand holo4-35b-a3b@holo4-35b-a3b-gguf 65536 1 3600` in `~/harness/shelf.conf`; `bash ~/harness/shelf.sh warm pilot` loads it when at least 65% of memory is free | +| The shelf | `ondemand holo4-35b-a3b@holo4-35b-a3b-gguf 65536 1 3600` in `~/harness/shelf.conf`; `bash ~/harness/shelf.sh warm pilot` loads it when at least 65% of memory is free. The night command runs it (`--warm`) after its own checks, and retries a refusal for memory for ten minutes | | The key | `~/.config/harness/keys/fleet.key` (roles `pilot`, `judge`, `vision`). Not the Keychain: neither SSH nor a LaunchDaemon can write the login Keychain on ultra. The workload reads `HARNESS_KEY`, then this file | | The night | `~/night/recurring/fleet-explore.json`, run by the harness's night queue from 22:00 when memory pressure is normal, 35 GB is free and no CI job is running | | The brain | On fleet-host, which ultra cannot route to. The night command opens `ssh -L 18788:192.168.50.27:8788 runner-ts` for the length of the run | -The night command (`collector/scripts/explore-night.ts`) boots the AVD if -needed, opens the tunnel, enqueues the spec on the brain pinned to the executor -name `ultra`, runs an executor in-process until the job ends, then shuts down -what it started and exits with the job's result, so the night queue knows when -the memory is free again. +The night command (`collector/scripts/explore-night.ts`) opens the tunnel, +checks that each spec has a build and the night has time for it, warms the +model, boots the AVD or simulator if needed, enqueues the spec on the brain +pinned to the executor name `ultra` with `minutes` cut to what is left, runs an +executor in-process until the job ends, then shuts down what it started and +exits, so the night queue knows when the memory is free again. A spec that +cannot run tonight is posted to the brain as a skip and exits 0; see +[short nights and skips](../explore/job.md#short-nights-and-skips). ### Builds, TVs and Apple simulators (from 12 October 2026) @@ -43,7 +46,7 @@ explore night can never push those past 07:30. | Job | Priority | What it does | |---|---|---| -| `fleet-explore-builds` | 19 | `deploy/explore/nightly-builds.sh`: resets `~/explore/builds/{greenfolio-ios,dozehound-tvos}` to `origin/develop`, builds a simulator `.app` (zipped) and uploads it to the brain as app ``, build `develop-`. An unchanged sha is skipped; a failed build leaves the previous one as `latest` | +| `fleet-explore-builds` | 19 | `deploy/explore/nightly-builds.sh`: resets `~/explore/builds/{greenfolio-ios,dozehound-tvos}` to `origin/develop`, builds a simulator `.app` (zipped) and uploads it to the brain as app ``, build `develop-`. An unchanged sha is not rebuilt but is uploaded again, so the brain shows it as tonight's; a failed build leaves the previous one as `latest`, and the TV and Apple nights skip rather than test it again | | `fleet-explore` | 20 | The bug garden on `fleet-explore-1` (unchanged) | | `fleet-explore-tv` | 85 | Dozehound tvOS on simulator `fleet-explore-tvos` (tvOS 26.5) with its stub catalog: the 10 bench cards with Holo4, the same cards with the resident `vision` model (phase 3's 20 navigation missions), then the every-button explorer | | `fleet-explore-apple` | 86 | GreenFolio iOS offline on simulator `fleet-explore-ios` (iOS 26.5): the first real-build night, phase 2's precision bar, and phase 4 | @@ -60,6 +63,36 @@ reading the production catalog. That is the owner's call (WB-297); until then the script builds it only when named (`nightly-builds.sh dozehound-firetv`) and the TV question is answered on tvOS. +### When a night cannot run (from 16 October 2026) + +On 10-14 a CI job held the machine from 22:00 to 04:00. The night queue skipped +`fleet-explore-builds` and `fleet-explore` after their 120-minute waits; that +admission is the queue's and nothing in this repository can shorten it. +`fleet-explore-tv` then "passed" in 1.4 minutes and `fleet-explore-apple` +exited 1 in 0.0 minutes, which turned ultra's `model-ladder#night` check red. + +- **The Apple night's exit 1 was the warm-up, not the build.** Its log has one + line: `not loading holo4-35b-a3b@holo4-35b-a3b-gguf: 64% free, needs 65%`. + The queue had admitted it on its own measure (35 GB free); the shelf + refused on another (`memory_pressure`'s free percentage, 65% for an + on-demand model) and the manifest's `&&` ended the job before + `explore-night.ts` started. Yesterday's GreenFolio build was on the brain. + The warm-up now runs inside the night command after its checks, a refusal + for memory is retried for ten minutes and then posted as a skip, and with + `--fresh-build` that night would have skipped earlier still, at "no + greenfolio-ios build for tonight". +- **The TV night has tested nothing since it started.** Every job in it ended + in twenty seconds with `skipped: no device matches this job on ultra`: the + executor described a tvOS simulator as `os: ios`, so `os ~ 'tvos'` never + matched. It now says `tvos-26.5`. No TV night has run since the fix, so the + phase 3 bench result is still to come. +- **A night admitted late runs short instead of being killed.** The night + queue already refuses to start a job whose `max_minutes` would run past + 07:30, so on ultra the binding limit is usually `max_minutes` itself (the + TV night's three specs plus booting and warming come close to its 150). The + `--until` check matters for a run started by hand and for any future + queue that admits a job with less than its full budget. + `explore-night.ts` takes `--spec` more than once (run in turn on one device) and `--sim name:runtime:devicetype`, which creates the simulator if missing, boots it, and shuts it down afterwards if it booted it. Simulator names start diff --git a/docs/explore/job.md b/docs/explore/job.md index 916b819..57bebd6 100644 --- a/docs/explore/job.md +++ b/docs/explore/job.md @@ -36,6 +36,7 @@ And the weekly mission bench: | `surface` | from the device | `touch` or `dpad`. Android TV, Fire TV, Roku and tvOS default to `dpad` | | `credentials` | | `{account, email_var, password_var}` for setup flows; the password comes from the host's Keychain | | `mirror` | `true` | Stream each step's screenshot to the job's live view on the dashboard | +| `short_night` | | Set by `explore-night.ts`, not by hand: `{asked}`, the spec's own `minutes`, when `minutes` was cut to fit the night. See [short nights](#short-nights-and-skips) | ## Models @@ -120,6 +121,8 @@ Metrics on each device row: | Metric | | |---|---| | `explore_missions` | Missions run | +| `explore_cards_planned` | Cards lined up for the device, in priority order. Fewer missions than cards means the budget ran out first | +| `explore_minutes` | The minutes the device was given: `params.minutes`, cut to fit on a short night | | `explore_steps` · `explore_actions` | Model steps; actions actually performed | | `explore_screens` · `explore_new_screens` | Screens reached tonight; screens no night had reached | | `explore_candidates` | Raised by the checks, before replay | @@ -135,6 +138,11 @@ The row also carries `missions`: per mission, its condition, steps, how it ended, screens, candidates, misses, refusals by class, the goal verdict, the bench result and the model's answer. +On a short night the device row and the final row are still `ok: true`, and +`error` says what ran: `short night: ran 3 of 7 cards: 40 minutes left of the +60 asked`. `error` is the field the job summary, the digest and `fleetr` show, +which is why the note is there and not in a field nothing reads. + ## Artifacts | Name | What | @@ -183,3 +191,54 @@ the harness's night queue runs `scripts/explore-night.ts` from the manifests in A lower number runs earlier; the products' own night jobs sit between 20 and 85. [Running it on ultra](../deploy/explore-on-ultra.md) has the setup. + +### Short nights and skips + +The night queue decides **whether** a job starts: from 22:00, when memory +pressure is normal, enough memory is free and no CI job is running, and only +while the job's `max_minutes` still fits before 07:30. A job that is not +admitted within its `wait_minutes` is skipped by the queue. That wait is the +queue's, outside this repository: on 10-14 `fleet-explore-builds` and +`fleet-explore` each spent their whole 120 minutes behind a CI job. What +`explore-night.ts` controls is what happens **once admitted**, and it checks +the cheap things first: + +1. **Is there a build to test?** With `--fresh-build` (the Apple and TV + nights), each spec asking for `"sha256": "latest"` needs a build the brain + shows as published tonight (since noon of the night's date). + `nightly-builds.sh` uploads an unchanged build again for exactly this. If + there is none, the job is posted to the brain as a skip, `skipped: no + greenfolio-ios build for tonight (fleet-explore-builds did not run, ...)`, + and the command exits 0. A pinned build (`sha256` a hash) only has to be + on the brain; if it is not, that is the spec's own failure. +2. **Is there time?** The night ends at `--until` (default 07:30) or at the + job's `max_minutes`, read from the queue's manifest for `$NIGHT_JOB`, + whichever is first. Ten minutes are held back for the last replay, uploads + and shutting devices down, and three per spec for enqueueing and + installing. When the specs ask for more than is left, each gets a share in + proportion to what it asked for, and the workload runs its highest-priority + cards in that time (cards are ordered by today's changes and how long since + each last ran). If a share would be under 15 minutes (`--min-minutes`), the + last spec is dropped and posted as a skip; if even one spec cannot have 15 + minutes, the whole night is skipped. The plan is made again before each + spec, with the time actually left. +3. **Will the model load?** `--warm ""` runs the shelf's warm-up only + after both checks pass. A warm-up refused for memory ("64% free, needs + 65%", or "memory pressure") is retried every minute for up to + `--warm-wait` minutes (default 10), then the night is posted as `skipped: + the model would not load, no room on this host: ...`. Any other warm-up + failure fails the night, with the reason posted. + +Only then does it boot the simulator or emulator. A skip is `ok: true` with +an error starting `skipped:`, the brain's convention for "nothing ran, and that +is not a failure of the code". The command's exit code is 0 when every spec +finished or skipped and 1 otherwise, because the night queue has no skip code +of its own and a missing upstream build is not this job's failure. + +`--dry-run` opens the tunnel, runs the build and time checks against the live +brain and prints the plan. It enqueues nothing, posts nothing, warms nothing +and boots nothing. + +Not yet seen on a real night: a short night (every night since this was built +has been either admitted in full or not at all) and the warm-up retry. Both +are covered by `scripts/check-explore.ts` against a fake brain. diff --git a/docs/explore/troubleshooting.md b/docs/explore/troubleshooting.md index 8f9008f..2e4e070 100644 --- a/docs/explore/troubleshooting.md +++ b/docs/explore/troubleshooting.md @@ -85,6 +85,45 @@ would then report as the app's bug. Write cards whose typed values are ASCII, or test non-ASCII input through a language condition and the app's own keyboard. +## A night is "skipped: no … build for tonight" + +The night ran with `--fresh-build` and the brain's newest build of the app was +published before noon of the night's date. The reason says which: `did not +run, or could not fetch develop` (the app's checkout under `~/explore/builds` +was not fetched tonight), `fetched develop but uploaded no build` (look at +`fleet-explore-builds` in `~/night/log//`: usually a compile error), or +`did not run or did not upload it` when there is no checkout to look at. Most +often the night queue skipped `fleet-explore-builds` because a CI job held the +machine; its line in `~/night/night.log` says so. Nothing is wrong with the +explore job itself, which is why it exits 0. + +## A night is "skipped: the model would not load, no room on this host" + +The shelf refused to load the model for memory, and kept refusing for +`--warm-wait` minutes (default 10). The night queue admits a job on free +memory as `vm_stat` counts it (`needs_gb` in the manifest); the shelf decides +on `memory_pressure`'s free percentage (65% for an on-demand model). They can +disagree by a point, which is how 10-14's Apple night died. Check what else +was loaded with `~/.lmstudio/bin/lms ps`. Any other warm-up failure is a +failure, not a skip, and its last line is the job's error. + +## A night says "short night: ran 3 of 7 cards" + +The night had less time left than the spec asked for, so `minutes` was cut to +fit and the highest-priority cards ran in that time. It is `ok: true`. The +explore-night log in `~/night/log//` has a line saying what ended the +night (`the 07:30 stop` or `the job's 150-minute max_minutes`) and how the +minutes were shared. A night that would get under 15 minutes is skipped +instead (`--min-minutes`). + +## A tvOS job skips with "no device matches this job" + +Before the fix in this release, the executor described a tvOS simulator as +`os: ios`, so a spec matching `os ~ 'tvos'` found nothing and the job was a +skip that read as `done`. If it happens on an executor that has the fix, check +the simulator's runtime with `xcrun simctl list devices` and that its name +starts with `fleet-`. + ## FleetDriver never answers `/health` - The first start of a runner on a simulator can take a minute; the actuator From d95515068b11ecf5c915ed3b51478b623366e777 Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 21:13:40 -0400 Subject: [PATCH 09/19] Honest green: skipped is a job status, every failure says why, registry hygiene LOOP-PLAN Phase 1, all four items. - The queue closes a job that ran nothing as `skipped` (one rule, skip.ts, shared with a one-time backfill that re-labels historical `done` skips in the migration that widens the status constraint). Status filters, facets, /metrics, the Overview, the dashboard chip and the morning digest know it. Waiters on a skipped dependency skip with "dependency X skipped". - A `schedule-skipping` alert after FLEET_ALERT_SKIP_STREAK (3) skipped runs. - ui-test reads the failing flow and step out of Maestro's JUnit report; every host row with ok:false gets a reason (fleet-client wrapper); a failed job's last_error carries it. GET /api/artifacts/:sha now 308s to the v1 content route instead of "no such endpoint". - Rokus register as platform roku; a serial-named Roku retires its IP-named duplicate; the sweep forgets declared simulators offline past FLEET_SIMULATOR_TTL_DAYS (7). Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 68 ++++++++++++ collector/dash/src/api.ts | 5 +- collector/dash/src/deviceKind.ts | 3 +- collector/dash/src/pages/JobDetail.tsx | 2 +- collector/dash/src/pages/Jobs.tsx | 2 +- collector/dash/src/pages/Overview.tsx | 3 + collector/dash/src/style.css | 4 + collector/openapi.json | 10 +- collector/schemas/result.schema.json | 4 +- collector/scripts/smoke.ts | 137 +++++++++++++++++++++++++ collector/src/alerts.test.ts | 62 +++++++++++ collector/src/alerts.ts | 71 +++++++++++++ collector/src/api/jobs.ts | 2 +- collector/src/api/mutations.ts | 41 +++++++- collector/src/api/overview.ts | 3 + collector/src/api/peers.ts | 2 +- collector/src/api/system.ts | 15 +++ collector/src/api/v1/prometheus.ts | 4 +- collector/src/api/v1/routes.ts | 18 ++-- collector/src/api/v1/schemas.ts | 6 +- collector/src/client/api.gen.ts | 6 +- collector/src/db.test.ts | 71 ++++++++++++- collector/src/db.ts | 86 +++++++++++++++- collector/src/describe.test.ts | 8 ++ collector/src/drivers/roku.ts | 5 + collector/src/executor.ts | 48 ++++++--- collector/src/findings.test.ts | 19 ++++ collector/src/findings.ts | 52 +++++++++- collector/src/fleet-client.ts | 10 +- collector/src/junit.ts | 73 +++++++++++++ collector/src/queue.ts | 16 +-- collector/src/registry-hygiene.test.ts | 74 +++++++++++++ collector/src/registry-hygiene.ts | 92 +++++++++++++++++ collector/src/result-reason.test.ts | 95 +++++++++++++++++ collector/src/result-reason.ts | 119 +++++++++++++++++++++ collector/src/server.ts | 54 ++++++++-- collector/src/skip.test.ts | 69 +++++++++++++ collector/src/skip.ts | 82 +++++++++++++++ collector/src/web/digest.ts | 4 +- docs/api.md | 19 +++- docs/brand.md | 2 +- docs/concepts.md | 50 ++++++++- docs/dashboard.md | 9 +- docs/deploy/alerts.md | 28 +++++ docs/deploy/index.md | 1 + docs/explore/findings.md | 13 +++ docs/figures/lifecycle.html | 8 +- docs/img/lifecycle.png | Bin 151636 -> 178307 bytes docs/lab.md | 9 +- docs/protocol.md | 20 +++- docs/workloads/host.md | 9 ++ 51 files changed, 1526 insertions(+), 87 deletions(-) create mode 100644 collector/src/junit.ts create mode 100644 collector/src/registry-hygiene.test.ts create mode 100644 collector/src/registry-hygiene.ts create mode 100644 collector/src/result-reason.test.ts create mode 100644 collector/src/result-reason.ts create mode 100644 collector/src/skip.test.ts create mode 100644 collector/src/skip.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index b1b6bbf..a3efcd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,8 +16,76 @@ a CI job fails when they disagree. ## [Unreleased] +### Added + +- **A job that ran nothing now has a status of its own: `skipped`.** A runner + that could not run a job says `ok: true` with an error beginning `skipped:`, + and the queue closed that as `done`, so the job list, the status counts and + the digest counted it as a pass: `nightly-tvloop-hardware` and three explore + jobs a night "passed" in two seconds for two weeks while testing nothing. + The queue now closes it as `skipped`, with the reason in `last_error`; a host + row of plain `ok: true` over device rows that all skipped counts the same, + and a fan-out family where no child ran is `skipped`. `skipped` is accepted + by the `status` filter of `GET /api/jobs` and `GET /api/v1/jobs`, counted in + the status facets, `GET /metrics` and the Overview (`skipped 24h`, beside + done rather than in it), drawn as a grey chip on the dashboard, and given its + own line in the morning digest. The v1 summary's verdict, `fleetr`'s exit 4 + and the MCP verdict were already `skipped` and are unchanged. A database + opened by this release is migrated once: every `done` job with a `skipped:` + result is re-labelled by the same rule. Result rows are not touched. +- **A job waiting on a skipped job skips too.** A skipped build produced no + artifact, so the install behind it had nothing to install; it used to be + promoted and run against whatever was already on the phone. It now skips + with `last_error` `dependency skipped`, the whole way down the chain, + and a job enqueued behind an already-skipped one is skipped on arrival. A + failed dependency still fails its waiters, and wins over a skipped one. +- **A `schedule-skipping` alert.** A schedule whose last three runs + (`FLEET_ALERT_SKIP_STREAK`) all skipped raises one alert naming the reason it + keeps giving, for example "nightly-tvloop-hardware has skipped 3 runs in a + row: no Roku developer password on this host", and resolves on the first run + that is not a skip. The tvloop nightly needed it for two weeks. +- **Simulator rows are forgotten after a week offline.** The lease sweep deletes + a row whose descriptor says `kind` or `soc` is `simulator` once it has been + offline for `FLEET_SIMULATOR_TTL_DAYS` (default 7), because simulators are + recreated under new UUIDs and never come back; the live brain listed thirteen + of them. Real devices and Android emulators are never forgotten, a row that + holds a lock is left alone, and results and beacons are kept. `POST + /jobs/sweep` reports what it forgot. + ### Fixed +- **A failing `ui-test` now says which step failed.** `nightly-fleet-ui-smoke` + failed on the Galaxy S8+ every night from 10-10 with `failed: 1` and no + error, while `Assertion is false: "Fleet Runner" is visible` sat in the JUnit + report it had uploaded. The executor now reads the failing flow and its + assertion out of the report into the device row's `error` and + `test.failing_flow`; when Maestro produces no report, the error is its exit + code and last stderr line, never its command line, which carries the test + account's password. +- **No host result says `ok: false` with nothing beside it.** Every host + workload's rows go through one wrapper in the executor: a device row with + only counts says so ("1 of 1 tests failed; the runner reported no failing + step"), and a final host row with no error of its own gets the failing + devices' reasons. A subprocess failure nobody caught is reported as its exit + code and last stderr line instead of Node's message. The collector also + copies a failure's reason into the job's `last_error`, so the job list and + the `job-failed` alert show it. +- **`GET /api/artifacts/` answered "no such endpoint".** It is where + `DELETE` and `/pin` already live, so it is the URL a person reaches for, and + the 404 read as a missing artifact: the ui-smoke JUnit report was in the + store all along. It now redirects (308) to + `/api/v1/artifacts//content`, and says plainly when no artifact by + that hash was ever uploaded. +- **The executor registered Rokus as `platform: android`.** Its Roku + descriptor said `os: roku-15.3.4` but no platform, and the collector's + fallback for anything that is not iOS is Android. It now sends + `platform: "roku"`; `os ~ 'roku'` targeting and the tvloop workload are + unaffected. +- **A Roku seen first by address and later by serial was listed twice.** A + sweep where the box answered SSDP but not device-info left a + `roku-ip-192-168-50-218` row offline beside `roku-X01600EMFRJ9`. A + serial-named registration now retires the IP-named row at the same address. + - **`fleet skill` failed on an installed 0.8.0.** The 0.8.0 archives carry `skills/`, but `install.sh` and `install.ps1` copy a release's directories by name and did not name it, so `fleet skill show` and `fleet skill install` diff --git a/collector/dash/src/api.ts b/collector/dash/src/api.ts index 7346c9f..2e13d0a 100644 --- a/collector/dash/src/api.ts +++ b/collector/dash/src/api.ts @@ -166,7 +166,9 @@ export type Job = { job_id: string; workload: string; executor: "device" | "host"; - status: "waiting" | "queued" | "claimed" | "done" | "failed" | "cancelled"; + /** `skipped`: claimed and closed without running anything (no device matched, + * the app was not installed, a dependency skipped). Not a pass. */ + status: "waiting" | "queued" | "claimed" | "done" | "failed" | "cancelled" | "skipped"; /** Job ids this one waits for; it stays `waiting` until they are all done. */ depends_on?: string[] | null; /** Whether a higher-priority job may ask this one to checkpoint and step aside. */ @@ -214,6 +216,7 @@ export type Overview = { claimed: number; done_24h: number; failed_24h: number; + skipped_24h: number; last_attempt: number; oldest_queued_age_s: number | null; }; diff --git a/collector/dash/src/deviceKind.ts b/collector/dash/src/deviceKind.ts index a9aefce..1433201 100644 --- a/collector/dash/src/deviceKind.ts +++ b/collector/dash/src/deviceKind.ts @@ -7,7 +7,8 @@ * The model string comes first, because it is the one field that is right * about every device on the shelf today. `platform` is not: agents that * predate the field are reported as ios/android by the collector's fallback, - * so a Roku arrives as `android` and an Apple TV or Apple Watch as `ios`. + * so an Apple TV or Apple Watch arrives as `ios`, and a Roku registered by an + * executor older than 0.9 as `android` (newer ones say `roku`). * `kind` is the agent naming its own shape and is believed — but only to pick * the family; the model still chooses which member of it (a `tv` that says * "Roku Streaming Stick" is drawn as the stick, not a bare panel). diff --git a/collector/dash/src/pages/JobDetail.tsx b/collector/dash/src/pages/JobDetail.tsx index f690f78..8d98a71 100644 --- a/collector/dash/src/pages/JobDetail.tsx +++ b/collector/dash/src/pages/JobDetail.tsx @@ -87,7 +87,7 @@ function DependsOn({ job }: { job: Detail }) { .{" "} {statusOf(job) === "waiting" - ? "It is queued the moment the last of them is done, with any ${jobs.…} references in its spec filled in from their final rows. If one fails or is cancelled, this job fails with it rather than waiting forever." + ? "It is queued the moment the last of them is done, with any ${jobs.…} references in its spec filled in from their final rows. If one fails or is cancelled, this job fails with it rather than waiting forever; if one skips, this job skips too, since there is nothing for it to run on." : "The chain has already resolved; this is what it hung off."}

diff --git a/collector/dash/src/pages/Jobs.tsx b/collector/dash/src/pages/Jobs.tsx index 7e1ddd8..c1c363e 100644 --- a/collector/dash/src/pages/Jobs.tsx +++ b/collector/dash/src/pages/Jobs.tsx @@ -132,7 +132,7 @@ export function Jobs() { // 'waiting' leads because it is the one status a person goes // looking for: a chain that has not started is invisible in // every other view, including the overview's queue depth. - options={["waiting", "queued", "claimed", "done", "failed", "cancelled"].map((s) => ({ + options={["waiting", "queued", "claimed", "done", "failed", "skipped", "cancelled"].map((s) => ({ value: s, label: `${s} (${d.status_counts[s] ?? 0})`, }))} diff --git a/collector/dash/src/pages/Overview.tsx b/collector/dash/src/pages/Overview.tsx index 64c564b..93cdf40 100644 --- a/collector/dash/src/pages/Overview.tsx +++ b/collector/dash/src/pages/Overview.tsx @@ -83,6 +83,9 @@ export function Overview() { 0 ? "warn" : undefined} /> 0 ? "bad" : undefined} /> + {/* Its own number, never added to done: a skip ran nothing. No tone, + like the chip -- it is not good news and not a failure. */} + = {}) => ({ + schema: 1, job_id, workload: WL, executor: "device", targets: { device_id: DEV }, ...extra, + }); + const hostJob = (job_id: string) => ({ + schema: 1, job_id, workload: "install", executor: "host", + app: { name: "x", build: "1", sha256: "0".repeat(64) }, + targets: { executor: EXEC }, lease: { ttl_s: 60, max_attempts: 1 }, + }); + await json("POST", "/devices/register", { + device_id: DEV, descriptor: { model: "Skipper", os: "android-14" }, pools: [], capabilities: [WL], + }); + + // The plain case: the runner's final row says why nothing ran. + const SKIP = `smoke-skip-plain-${run}`; + await json("POST", "/jobs", devJob(SKIP)); + const closed = await json("POST", "/results", { + schema: 1, kind: "result", job_id: SKIP, device_id: DEV, iter: 0, final: true, ok: true, + error: "skipped: no Roku developer password on this host", + }); + check("skip: a skipped result closes the job as skipped, not done", closed.body?.status === "skipped", JSON.stringify(closed.body)); + const row = await json("GET", `/api/jobs/${SKIP}`); + check("skip: the job row says skipped", row.body?.status === "skipped", row.body?.status); + check("skip: and its last_error carries the reason", + row.body?.last_error === "skipped: no Roku developer password on this host", JSON.stringify(row.body?.last_error)); + const listed = await json("GET", `/api/jobs?status=skipped&q=${encodeURIComponent(SKIP)}`); + check("skip: /api/jobs filters on it", + (listed.body?.jobs ?? []).some((j: { job_id: string }) => j.job_id === SKIP), JSON.stringify(listed.body?.jobs?.length)); + check("skip: and the status facet counts it", (listed.body?.status_counts?.skipped ?? 0) >= 1, JSON.stringify(listed.body?.status_counts)); + const v1 = await json("GET", `/api/v1/jobs?status=skipped&q=${encodeURIComponent(SKIP)}`); + check("skip: /api/v1/jobs filters on it", + (v1.body?.items ?? []).some((j: { job_id: string; status: string }) => j.job_id === SKIP && j.status === "skipped"), + JSON.stringify(v1.body).slice(0, 300)); + const sum = await json("GET", `/api/v1/jobs/${SKIP}/summary`); + check("skip: the summary agrees (status skipped, verdict skipped, finished)", + sum.body?.status === "skipped" && sum.body?.verdict === "skipped" && sum.body?.finished === true, JSON.stringify(sum.body).slice(0, 300)); + const ov = await json("GET", "/api/overview"); + check("skip: the overview counts skips on their own", (ov.body?.queue?.skipped_24h ?? 0) >= 1, JSON.stringify(ov.body?.queue)); + + // A host job whose every device skipped, under a plain ok:true host row -- + // the shape a ui-test takes when no phone has the app installed. + const ALL = `smoke-skip-allhost-${run}`; + await json("POST", "/jobs", hostJob(ALL)); + await json("POST", "/results", { schema: 1, kind: "result", job_id: ALL, device_id: DEV, iter: 0, ok: true, error: "skipped: com.example not installed" }); + const allClosed = await json("POST", "/results", { schema: 1, kind: "result", job_id: ALL, device_id: `host:${EXEC}`, iter: 0, final: true, ok: true }); + check("skip: every device skipping under an ok host row is a skip", allClosed.body?.status === "skipped", JSON.stringify(allClosed.body)); + + // One device ran: the job ran. + const MIXED = `smoke-skip-mixed-${run}`; + await json("POST", "/jobs", hostJob(MIXED)); + await json("POST", "/results", { schema: 1, kind: "result", job_id: MIXED, device_id: DEV, iter: 0, ok: true, error: "skipped: device locked by another job" }); + await json("POST", "/results", { schema: 1, kind: "result", job_id: MIXED, device_id: `${DEV}-b`, iter: 0, ok: true, test: { passed: 1, failed: 0 } }); + const mixedClosed = await json("POST", "/results", { schema: 1, kind: "result", job_id: MIXED, device_id: `host:${EXEC}`, iter: 0, final: true, ok: true }); + check("skip: one device that ran makes the job done", mixedClosed.body?.status === "done", JSON.stringify(mixedClosed.body)); + + // A failure says why on the job row, from the failing device when the host + // row has nothing of its own. + const FAIL = `smoke-skip-fail-${run}`; + await json("POST", "/jobs", hostJob(FAIL)); + await json("POST", "/results", { schema: 1, kind: "result", job_id: FAIL, device_id: DEV, iter: 0, ok: false, error: 'smoke: Assertion is false: "Fleet Runner" is visible' }); + await json("POST", "/results", { schema: 1, kind: "result", job_id: FAIL, device_id: `host:${EXEC}`, iter: 0, final: true, ok: false }); + const failRow = await json("GET", `/api/jobs/${FAIL}`); + check("fail: a failed job's last_error names the failing device and step", + failRow.body?.status === "failed" && failRow.body?.last_error === `${DEV}: smoke: Assertion is false: "Fleet Runner" is visible`, + JSON.stringify(failRow.body?.last_error)); + + // Dependencies: a skipped dependency produced nothing, so its waiters skip + // -- the whole way down -- rather than run against nothing or fail. + const DA = `smoke-skip-da-${run}`, DB = `smoke-skip-db-${run}`, DC = `smoke-skip-dc-${run}`; + await json("POST", "/jobs", devJob(DA)); + await json("POST", "/jobs", devJob(DB, { depends_on: [DA] })); + await json("POST", "/jobs", devJob(DC, { depends_on: [DB] })); + const depClosed = await json("POST", "/results", { + schema: 1, kind: "result", job_id: DA, device_id: DEV, iter: 0, final: true, ok: true, error: "skipped: no build for this device", + }); + check("chain: a skipped dependency skips its waiter and the link beyond", + ((depClosed.body?.skipped ?? []) as string[]).includes(DB) && ((depClosed.body?.skipped ?? []) as string[]).includes(DC), + JSON.stringify(depClosed.body)); + const dbRow = await json("GET", `/api/jobs/${DB}`); + check("chain: the waiter says which dependency skipped", + dbRow.body?.status === "skipped" && dbRow.body?.last_error === `dependency ${DA} skipped`, JSON.stringify(dbRow.body?.last_error)); + const dbSum = await json("GET", `/api/v1/jobs/${DB}/summary`); + check("chain: and its summary is a skip, not a pass or a failure", dbSum.body?.verdict === "skipped", JSON.stringify(dbSum.body?.verdict)); + const lateDep = await json("POST", "/jobs", devJob(`smoke-skip-late-${run}`, { depends_on: [DA] })); + check("chain: a job enqueued behind an already-skipped job is skipped on arrival", + lateDep.status === 201 && lateDep.body?.status === "skipped", JSON.stringify(lateDep.body)); + check("chain: and a dry run says so first", + ((await json("POST", "/api/v1/jobs/validate", devJob(`smoke-skip-dry-${run}`, { depends_on: [DA] }))).body?.warnings ?? []) + .some((w: string) => w.includes("already skipped"))); + + // The artifact a person reaches for at /api/artifacts/ -- where DELETE + // and /pin already live -- used to answer "no such endpoint". + const blob = Buffer.from(`junit-${run}`.repeat(20)); + const blobSha = createHash("sha256").update(blob).digest("hex"); + await fetch(`${BASE}/artifacts`, { method: "POST", headers: { "content-type": "application/octet-stream", "x-artifact-name": "junit.xml" }, body: blob }); + const redir = await fetch(`${BASE}/api/artifacts/${blobSha}`, { redirect: "manual" }); + check("artifact: GET /api/artifacts/ points at the bytes", + redir.status === 308 && redir.headers.get("location") === `/api/v1/artifacts/${blobSha}/content`, `${redir.status} ${redir.headers.get("location")}`); + const followed = await fetch(`${BASE}/api/artifacts/${blobSha}`); + check("artifact: and following it gets them", followed.ok && Buffer.from(await followed.arrayBuffer()).equals(blob), String(followed.status)); + const unknown = await json("GET", `/api/artifacts/${"e".repeat(64)}`); + check("artifact: an unknown one is a plain 404 that says so", unknown.status === 404 && /no artifact/.test(String(unknown.body?.error)), JSON.stringify(unknown)); + + // Registry hygiene: a Roku first seen by address, then by serial, is one row. + const ip = `10.${run % 200}.${Math.floor(run / 200) % 200}.7`; + const ipId = `roku-ip-${ip.replace(/\./g, "-")}`; + await json("POST", "/devices/register", { device_id: ipId, descriptor: { model: "roku", os: "roku", ip, kind: "device" }, pools: [] }); + check("roku: the IP-named row exists first", (await json("GET", `/api/devices/${ipId}`)).status === 200); + await json("POST", "/devices/register", { + device_id: `roku-SMOKE${run}`, pools: [], + descriptor: { platform: "roku", model: "Roku Express 4K+", os: "roku-15.3.4", serial: `SMOKE${run}`, ip, kind: "device" }, + }); + check("roku: the serial-named registration retires the IP-named duplicate", (await json("GET", `/api/devices/${ipId}`)).status === 404); + const roku = await json("GET", `/api/devices/roku-SMOKE${run}`); + check("roku: and the Roku reads as platform roku", roku.body?.platform === "roku", JSON.stringify(roku.body?.platform)); + const swept = await json("POST", "/jobs/sweep"); + check("sweep: reports the simulators it forgot", Array.isArray(swept.body?.forgotten), JSON.stringify(swept.body)); +} + // --- preemption: a long job stands aside for higher-priority work --- // The collector never kills anything. It answers a beacon with preempt:true and @@ -2647,6 +2778,12 @@ runDbChecks(check); // the live brain's alert list with noise nobody could act on. runAlertChecks(check); +// Honest green: how a job closes (done, failed, skipped), every failure saying +// why, and the registry keeping to real things. +runSkipChecks(check); +await runReasonChecks(check); +runRegistryHygieneChecks(check); + // Where a host's Playwright lives and which Chromium it drives: the two // things a released executor on macOS 12 needed to run web work at all. await runBrowserChecks(check); diff --git a/collector/src/alerts.test.ts b/collector/src/alerts.test.ts index ccd7920..d2e8c6c 100644 --- a/collector/src/alerts.test.ts +++ b/collector/src/alerts.test.ts @@ -148,4 +148,66 @@ export function runAlertChecks(check: Check) { check("but a personal laptop that is thermally critical still alerts", thermal.includes("hot-daily-laptop"), JSON.stringify(thermal)); }); + + // A schedule that keeps skipping. The tvloop nightly skipped every night for + // two weeks on a missing Roku password and nothing said so; its job ids are + // the scheduler's `-`, which is how a run is found + // even on a brain whose old jobs carry no requested_by. + inTempDir((dir) => { + const db = openDb(dir); + const schedule = (id: string) => + db.prepare("INSERT INTO schedules (id, cron, template, enabled, last_run) VALUES (?, '30 6 * * *', '{}', 1, NULL)").run(id); + const job = (id: string, status: string, lastError: string | null = null) => + db.prepare( + `INSERT INTO jobs (job_id, executor, workload, spec, status, last_error, finished_at) + VALUES (?, 'host', 'tvloop', '{}', ?, ?, ${status === "queued" || status === "claimed" ? "NULL" : "datetime('now')"})`, + ).run(id, status, lastError); + const NO_PW = "skipped: no Roku developer password on this host"; + + schedule("nightly-tvloop-hardware"); + job("nightly-tvloop-hardware-202610120630", "done"); + job("nightly-tvloop-hardware-202610130630", "skipped", NO_PW); + job("nightly-tvloop-hardware-202610140630", "skipped", NO_PW); + job("nightly-tvloop-hardware-202610150630", "skipped", NO_PW); + // A schedule whose id is a prefix of this one must not borrow its runs. + schedule("nightly-tvloop"); + job("nightly-tvloop-202610150630", "done"); + // Two skips are not a streak yet. + schedule("nightly-two"); + job("nightly-two-202610140630", "skipped", "skipped: locked"); + job("nightly-two-202610150630", "skipped", "skipped: locked"); + // A fan-out where every child skipped, for different reasons, three nights. + schedule("nightly-fan"); + for (const day of ["13", "14", "15"]) { + job(`nightly-fan-202610${day}0230--phone-a`, "skipped", "skipped: com.example not installed"); + job(`nightly-fan-202610${day}0230--phone-b`, "skipped", day === "15" ? "skipped: device locked by another job" : "skipped: com.example not installed"); + } + // Three skips and then a run in flight: the in-flight one has not said + // anything yet, so the streak stands. + schedule("nightly-inflight"); + for (const day of ["12", "13", "14"]) job(`nightly-inflight-202610${day}0230`, "skipped", "skipped: no device matches this job on ultra"); + job("nightly-inflight-202610150230", "claimed"); + + const skipping = () => evaluate(new Date(), NO_SIZES).filter((f) => f.rule === "schedule-skipping"); + const found = skipping(); + const bySubject = new Map(found.map((f) => [f.subject, f])); + check("stale skip: three skips in a row raise one alert", bySubject.has("nightly-tvloop-hardware"), JSON.stringify(found)); + check("stale skip: naming the schedule and the reason it keeps giving", + bySubject.get("nightly-tvloop-hardware")?.message === + "nightly-tvloop-hardware has skipped 3 runs in a row: no Roku developer password on this host", + bySubject.get("nightly-tvloop-hardware")?.message); + check("stale skip: a schedule's runs are its own, not a longer id's", !bySubject.has("nightly-tvloop")); + check("stale skip: two skips are not a streak", !bySubject.has("nightly-two")); + check("stale skip: a fan-out whose every child skipped counts as a skipped run", bySubject.has("nightly-fan")); + check("stale skip: a run still in flight neither breaks nor extends the streak", bySubject.has("nightly-inflight")); + check("stale skip: one alert per schedule", found.length === 3, JSON.stringify(found.map((f) => f.subject))); + + // A run that is not a skip resolves it. + job("nightly-tvloop-hardware-202610160630", "failed", "smoke: Assertion is false"); + check("stale skip: the first run that is not a skip clears it", + !skipping().some((f) => f.subject === "nightly-tvloop-hardware")); + // Disabled schedules are not watched. + db.prepare("UPDATE schedules SET enabled = 0 WHERE id = 'nightly-fan'").run(); + check("stale skip: a disabled schedule is not watched", !skipping().some((f) => f.subject === "nightly-fan")); + }); } diff --git a/collector/src/alerts.ts b/collector/src/alerts.ts index a52ebfa..4980b48 100644 --- a/collector/src/alerts.ts +++ b/collector/src/alerts.ts @@ -13,6 +13,7 @@ import { db } from "./db.js"; import { beaconFields, deviceStatus, effectivePools, hasBattery, isExpired, parse } from "./api/shared.js"; import { minuteKey, prevRun } from "./cron.js"; +import { skipReasonText } from "./skip.js"; export type Severity = "warning" | "critical"; export type Finding = { rule: string; subject: string; severity: Severity; message: string }; @@ -38,8 +39,58 @@ export const THRESHOLDS = { // Below this many prior runs there is no median worth trusting, and a new // device would alarm on its second result forever. regressionMinSamples: env("FLEET_ALERT_REGRESSION_MIN_SAMPLES", 4), + // A schedule whose last this-many runs all skipped is not running, whatever + // its jobs' statuses say about the code. One skip is a phone on a charger + // somewhere else; three in a row is a missing password nobody has noticed. + skipStreak: Math.round(env("FLEET_ALERT_SKIP_STREAK", 3)), }; +/** + * The runs a schedule fired, newest first, each judged as a whole. + * + * A run is the job the scheduler enqueued (`-`) or, for + * a fan-out, that id's children; jobs from before provenance existed carry no + * `requested_by`, so the id is what identifies them. Read as a primary-key + * range rather than a LIKE, so it costs an index walk however long the history. + * A run still in flight is left out: it has not said whether it skipped. + */ +export function scheduleRuns(scheduleId: string): { run: string; skipped: boolean; reasons: string[] }[] { + const prefix = `${scheduleId}-`; + // '-' is 0x2D and '.' is 0x2E, so [prefix, prefix-with-'.') is every id that + // starts with it. + const upper = `${scheduleId}.`; + const escaped = scheduleId.replace(/[.*+?^$()|[\]{}\\]/g, "\\$&"); + const own = new RegExp("^" + escaped + "-\\d{12}(--.*)?$"); + const rows = (db + .prepare( + `SELECT job_id, status, last_error, created_at FROM jobs + WHERE job_id >= ? AND job_id < ?`, + ) + .all(prefix, upper) as { job_id: string; status: string; last_error: string | null; created_at: string }[]) + .filter((r) => own.test(r.job_id)); + const runs = new Map(); + for (const r of rows) { + const key = r.job_id.split("--")[0]; + const run = runs.get(key) ?? { created: r.created_at, statuses: [], reasons: [] }; + run.statuses.push(r.status); + if (r.status === "skipped" && r.last_error) run.reasons.push(r.last_error); + if (r.created_at < run.created) run.created = r.created_at; + runs.set(key, run); + } + const FINISHED = new Set(["done", "failed", "cancelled", "skipped"]); + return [...runs] + .filter(([, r]) => r.statuses.every((s) => FINISHED.has(s))) + // The id ends in the minute it fired, so it orders runs exactly; created_at + // has one-second resolution and a backfilled run would tie. + .sort(([a], [b]) => (a < b ? 1 : a > b ? -1 : 0)) + .map(([run, r]) => ({ + run, + // The family rule from the v1 summary: nothing in it ran. + skipped: !r.statuses.includes("done") && !r.statuses.includes("failed") && r.statuses.includes("skipped"), + reasons: r.reasons, + })); +} + /** * A metric watched for regression: where it lives, which direction is bad, and * what makes two runs comparable. The comparison key matters more than the @@ -258,6 +309,26 @@ export function evaluate(now = new Date(), sizes: { dbBytes: number; logBytes: n }); } + // A schedule that keeps skipping. Its jobs are no longer counted as passes, + // but a grey chip every morning is still easy to stop seeing: the tvloop + // nightly skipped for two weeks on a missing Roku password and nothing said + // so. One alert per schedule, naming the reason it keeps giving, resolved by + // the first run that is not a skip. + const streak = Math.max(1, THRESHOLDS.skipStreak); + for (const s of db.prepare("SELECT id FROM schedules WHERE enabled = 1").all() as { id: string }[]) { + const recent = scheduleRuns(s.id).slice(0, streak); + if (recent.length < streak || !recent.every((r) => r.skipped)) continue; + const reasons = recent.map((r) => skipReasonText(r.reasons[0])); + const distinct = [...new Set(reasons)]; + const why = distinct.length === 1 ? distinct[0] : `${reasons[0]} (the latest of ${distinct.length} different reasons)`; + out.push({ + rule: "schedule-skipping", + subject: s.id, + severity: "warning", + message: `${s.id} has skipped ${streak} runs in a row: ${why}`, + }); + } + // --- collector --- if (sizes.dbBytes > THRESHOLDS.dbBytes) out.push({ diff --git a/collector/src/api/jobs.ts b/collector/src/api/jobs.ts index 03f830e..35af083 100644 --- a/collector/src/api/jobs.ts +++ b/collector/src/api/jobs.ts @@ -3,7 +3,7 @@ import type { FastifyInstance } from "fastify"; import { db, type SqlParam } from "../db.js"; import { AGE, beaconFields, inClause, iso, paging, parse, sha256Refs } from "./shared.js"; -const STATUSES = new Set(["waiting", "queued", "claimed", "done", "failed", "cancelled"]); +const STATUSES = new Set(["waiting", "queued", "claimed", "done", "failed", "cancelled", "skipped"]); const EXECUTORS = new Set(["device", "host"]); const SORTS: Record = { created: "created_at", diff --git a/collector/src/api/mutations.ts b/collector/src/api/mutations.ts index ee5a30c..287765e 100644 --- a/collector/src/api/mutations.ts +++ b/collector/src/api/mutations.ts @@ -33,11 +33,21 @@ type MatchingDevices = ( // inserted as 'waiting', which the claim loop does not look at, and becomes // 'queued' when the last of its dependencies is 'done'. // +// A dependency that skipped produced nothing -- no build, no artifact, no +// metric -- so a job waiting on it skips too, with `last_error` saying +// "dependency X skipped". Not a failure: nothing went wrong with the code, and +// a red install behind a build that never ran would be a lie in the other +// direction. +// // The machinery lives in this file because both of the places a job can close // have to settle whatever was waiting on it: a final result (server.ts) and a // cancellation (below), and only one of those can import the other. -export type DepSettlement = { promoted: string[]; failed: { job_id: string; reason: string }[] }; +export type DepSettlement = { + promoted: string[]; + failed: { job_id: string; reason: string }[]; + skipped: { job_id: string; reason: string }[]; +}; // `${jobs..artifact}` and `${jobs..metrics.}`. The id is matched // lazily and the suffix is what anchors the match, so a job id that itself @@ -179,17 +189,21 @@ export function validateDepRefs(specJson: string, deps: string[]): string | null /** What status a job with these dependencies should be inserted as. A chain * whose build already failed is failed on arrival rather than parked in * 'waiting' forever: nothing will ever close that dependency again, so no - * promotion event is coming. */ + * promotion event is coming. One whose build skipped is skipped on arrival, + * for the same reason. A failure outranks a skip. */ export function dependencyState( deps: string[], -): { status: "queued" | "waiting" } | { status: "failed"; reason: string } { +): { status: "queued" | "waiting" } | { status: "failed" | "skipped"; reason: string } { let allDone = true; + let skipped: string | null = null; for (const d of deps) { const row = db.prepare("SELECT status FROM jobs WHERE job_id = ?").get(d) as { status: string } | undefined; if (row?.status === "failed" || row?.status === "cancelled") return { status: "failed", reason: `dependency ${d} ${row.status}` }; + if (row?.status === "skipped") skipped ??= d; if (row?.status !== "done") allDone = false; } + if (skipped) return { status: "skipped", reason: `dependency ${skipped} skipped` }; return { status: allDone ? "queued" : "waiting" }; } @@ -216,13 +230,25 @@ function failWaiter(jobId: string, reason: string, out: DepSettlement) { settleWaiters(jobId, out); } +function skipWaiter(jobId: string, reason: string, out: DepSettlement) { + db.prepare( + `UPDATE jobs SET status = 'skipped', finished_at = datetime('now'), + lease_deadline = NULL, last_error = ? + WHERE job_id = ?`, + ).run(reason, jobId); + out.skipped.push({ job_id: jobId, reason }); + // An install that skipped has nothing for the ui-test behind it either. + settleWaiters(jobId, out); +} + /** * Resolve everything that was waiting on a job that just closed. * * A waiter whose last dependency is now 'done' is promoted to 'queued' with its * `${jobs.…}` references filled in from the dependency's final row. A waiter * whose dependency failed or was cancelled is failed with `last_error` naming - * it, and that failure cascades. + * it, and that failure cascades. One whose dependency skipped is skipped the + * same way -- unless another dependency failed, which wins. * * Callers run this inside the transaction that closed the job, and announce * what it returns after that transaction commits — a broken dashboard pipe must @@ -230,7 +256,7 @@ function failWaiter(jobId: string, reason: string, out: DepSettlement) { */ export function settleWaiters( closedJobId: string, - out: DepSettlement = { promoted: [], failed: [] }, + out: DepSettlement = { promoted: [], failed: [], skipped: [] }, ): DepSettlement { for (const w of waitersOn(closedJobId)) { const deps = parse(w.depends_on, []); @@ -250,6 +276,11 @@ export function settleWaiters( ); continue; } + const skippedDep = states.find((s) => s.status === "skipped"); + if (skippedDep) { + skipWaiter(w.job_id, `dependency ${skippedDep.id} skipped`, out); + continue; + } if (!states.every((s) => s.status === "done")) continue; const filled = substituteDepRefs(parse>(w.spec, {})); diff --git a/collector/src/api/overview.ts b/collector/src/api/overview.ts index 37f0b9c..ecf9f2e 100644 --- a/collector/src/api/overview.ts +++ b/collector/src/api/overview.ts @@ -77,6 +77,8 @@ function build() { COUNT(*) FILTER (WHERE status = 'claimed') AS claimed, COUNT(*) FILTER (WHERE status = 'done' AND finished_at >= datetime('now','-24 hours')) AS done_24h, COUNT(*) FILTER (WHERE status = 'failed' AND finished_at >= datetime('now','-24 hours')) AS failed_24h, + -- Its own count, never folded into done: a skip is a job that ran nothing. + COUNT(*) FILTER (WHERE status = 'skipped' AND finished_at >= datetime('now','-24 hours')) AS skipped_24h, COUNT(*) FILTER (WHERE status = 'claimed' AND attempts >= max_attempts) AS last_attempt, (SELECT ${AGE("MIN(created_at)")} FROM jobs WHERE status = 'queued') AS oldest_queued_age_s FROM jobs`, @@ -153,6 +155,7 @@ function build() { claimed: queue.claimed ?? 0, done_24h: queue.done_24h ?? 0, failed_24h: queue.failed_24h ?? 0, + skipped_24h: queue.skipped_24h ?? 0, last_attempt: queue.last_attempt ?? 0, oldest_queued_age_s: queue.oldest_queued_age_s ?? null, }, diff --git a/collector/src/api/peers.ts b/collector/src/api/peers.ts index 06e482e..956dcea 100644 --- a/collector/src/api/peers.ts +++ b/collector/src/api/peers.ts @@ -44,7 +44,7 @@ const PEER_TIMEOUT_MS = 4_000; * What may be proxied. * * An allow-list of prefixes rather than a rule about methods alone, because - * `GET /api/artifacts/:sha` streams bytes and `GET /api/stream` is an endless + * `GET /api/artifacts/:sha` leads to bytes and `GET /api/stream` is an endless * SSE response -- neither belongs on a path whose whole purpose is to fill in a * summary table. Everything here answers with a bounded JSON document. */ diff --git a/collector/src/api/system.ts b/collector/src/api/system.ts index 862b5ea..4bf4e36 100644 --- a/collector/src/api/system.ts +++ b/collector/src/api/system.ts @@ -242,6 +242,21 @@ export function registerSystem(app: FastifyInstance) { ).map((l) => ({ ...l, acquired_at: iso(l.acquired_at) })), })); + // One artifact, by the URL a person reaches for. DELETE and /pin live under + // /api/artifacts/:sha256, so a GET there is the obvious guess -- and it used + // to answer "no such endpoint", which read as "this artifact is gone" when + // the bytes were in the store all along (nightly-fleet-ui-smoke's JUnit + // report, October 2026). The bytes have two homes, /artifacts/:sha256 for + // runners and /api/v1/artifacts/:sha256/content for everyone else; this + // points at the second rather than becoming a third. + app.get("/api/artifacts/:sha256", async (req, reply) => { + const { sha256 } = req.params as { sha256: string }; + if (!/^[a-f0-9]{64}$/.test(sha256)) return reply.code(400).send({ error: "sha256 must be 64 lowercase hex characters" }); + const known = db.prepare("SELECT 1 FROM artifacts WHERE sha256 = ?").get(sha256); + if (!known) return reply.code(404).send({ error: `no artifact ${sha256} has been uploaded to this collector` }); + return reply.redirect(`/api/v1/artifacts/${sha256}/content`, 308); + }); + app.get("/api/artifacts", async (req) => { const q = req.query as Record; const { page, per_page, offset } = paging(q); diff --git a/collector/src/api/v1/prometheus.ts b/collector/src/api/v1/prometheus.ts index 3142fbb..310ecb1 100644 --- a/collector/src/api/v1/prometheus.ts +++ b/collector/src/api/v1/prometheus.ts @@ -32,7 +32,7 @@ export function metricsText(): string { for (const d of devices) if (!isExpired(d, d.age_s)) byStatus[deviceStatus(d.age_s)]++; const jobs = db.prepare("SELECT status, COUNT(*) AS n FROM jobs GROUP BY status").all() as { status: string; n: number }[]; - const jobCounts: Record = { waiting: 0, queued: 0, claimed: 0, done: 0, failed: 0, cancelled: 0 }; + const jobCounts: Record = { waiting: 0, queued: 0, claimed: 0, done: 0, failed: 0, cancelled: 0, skipped: 0 }; for (const j of jobs) jobCounts[j.status] = j.n; const oldest = db.prepare(`SELECT MAX(${AGE("created_at")}) AS s FROM jobs WHERE status = 'queued'`).get() as { s: number | null }; @@ -57,7 +57,7 @@ export function metricsText(): string { family("fleet_queue_oldest_seconds", "gauge", "Age of the oldest queued job; 0 when nothing is queued.", [[{}, oldest.s ?? 0]]), family("fleet_jobs_finished_24h", "gauge", "Jobs that finished in the last 24 hours, by workload and status.", finished.map((f) => [{ workload: f.workload, status: f.status }, f.n])), family("fleet_executors_live", "gauge", "Host executors that polled in the last two minutes.", [[{}, executors.n]]), - family("fleet_device_success_ratio_24h", "gauge", "done / (done + failed) per device over the last 24 hours.", success.map((s) => [{ device_id: s.device }, s.n ? s.ok / s.n : 0])), + family("fleet_device_success_ratio_24h", "gauge", "done / (done + failed) per device over the last 24 hours. Skipped jobs count as neither: nothing ran.", success.map((s) => [{ device_id: s.device }, s.n ? s.ok / s.n : 0])), family("fleet_alerts_open", "gauge", "Open alerts by severity.", alerts.map((a) => [{ severity: a.severity }, a.n])), family("fleet_artifacts", "gauge", "Artifacts recorded.", [[{}, artifacts.n]]), family("fleet_artifact_bytes", "gauge", "Total size of recorded artifacts.", [[{}, artifacts.bytes]]), diff --git a/collector/src/api/v1/routes.ts b/collector/src/api/v1/routes.ts index 4916686..7d74ea8 100644 --- a/collector/src/api/v1/routes.ts +++ b/collector/src/api/v1/routes.ts @@ -35,6 +35,7 @@ import { isTextual } from "../../media-type.js"; import { AGE, capabilityMatches, deviceCapabilities, inClause, iso, isExpired, ONLINE_S, paging, parse, sha256Refs } from "../shared.js"; import { schedulesView } from "../system.js"; import { SCHEMAS } from "./schemas.js"; +import { isSkipError } from "../../skip.js"; // --- the table's types ------------------------------------------------------------ @@ -252,7 +253,7 @@ type SummaryJob = { const SUMMARY_COLUMNS = `job_id, workload, status, claimed_by, last_error, requested_by, source, spec, CASE WHEN claimed_at IS NOT NULL THEN CAST(strftime('%s', COALESCE(finished_at, datetime('now'))) - strftime('%s', claimed_at) AS INTEGER) END AS duration_s`; -const FINISHED = new Set(["done", "failed", "cancelled"]); +const FINISHED = new Set(["done", "failed", "cancelled", "skipped"]); const likePrefix = (p: string) => `${p.replace(/[\\%_]/g, "\\$&")}--%`; function familyOf(id: string): { jobs: SummaryJob[]; fanout: boolean } | null { @@ -290,16 +291,18 @@ function outcomesOf(job: SummaryJob): DeviceOutcome[] { const spec = parse>(job.spec, {}); if (entries.length === 0) { const device = String(job.claimed_by ?? spec.targets?.device_id ?? "(unassigned)"); - const skipped = typeof job.last_error === "string" && job.last_error.startsWith("skipped:"); + // A job skipped because its dependency skipped never reached a runner, so + // it has no rows; its status is the whole story. + const skipped = job.status === "skipped" || isSkipError(job.last_error); return [{ device_id: device, job_id: job.job_id, status: job.status, - ok: job.status === "done" ? !skipped : job.status === "failed" ? false : null, + ok: job.status === "skipped" ? true : job.status === "done" ? !skipped : job.status === "failed" ? false : null, skipped, error: job.last_error, metrics: null, test: null, failing_step: null, }]; } return entries.map(([device, p]) => { const error = typeof p.error === "string" ? p.error : null; - const skipped = !!error && error.startsWith("skipped:"); + const skipped = isSkipError(error); const test = p.test && typeof p.test === "object" ? { passed: p.test.passed ?? null, failed: p.test.failed ?? null, skipped: p.test.skipped ?? null } : null; @@ -363,7 +366,10 @@ export function summarize(id: string) { const has = (s: string) => jobs.some((j) => j.status === s); const familyStatus = !finished ? has("claimed") ? "claimed" : has("queued") ? "queued" : "waiting" - : jobs.every((j) => j.status === "cancelled") ? "cancelled" : has("failed") ? "failed" : "done"; + : jobs.every((j) => j.status === "cancelled") ? "cancelled" : has("failed") ? "failed" + // Nothing in the family ran: every child skipped (or skipped and was + // cancelled). One that ran is enough for the family to be done. + : !has("done") && has("skipped") ? "skipped" : "done"; const status = fanout ? familyStatus : head.status; return { job_id: id, @@ -620,7 +626,7 @@ export const ROUTES: Route[] = [ operationId: "listJobs", method: "GET", path: "/api/v1/jobs", tag: "jobs", scope: "read", readOnly: true, idempotent: true, summary: "Jobs, newest first, filterable.", params: [ - { name: "status", in: "query", type: "string", description: "Comma-separated: waiting, queued, claimed, done, failed, cancelled." }, + { name: "status", in: "query", type: "string", description: "Comma-separated: waiting, queued, claimed, done, failed, cancelled, skipped." }, { name: "workload", in: "query", type: "string", description: "Comma-separated workload names." }, { name: "executor", in: "query", type: "string", enum: ["device", "host"], description: "device or host." }, { name: "device", in: "query", type: "string", description: "Claimed by, or pinned to, this device." }, diff --git a/collector/src/api/v1/schemas.ts b/collector/src/api/v1/schemas.ts index 6091d8e..90c2500 100644 --- a/collector/src/api/v1/schemas.ts +++ b/collector/src/api/v1/schemas.ts @@ -133,7 +133,7 @@ export const SCHEMAS: Record = { Job: object( { job_id: str, workload: str, executor: { enum: ["device", "host"] }, - status: { enum: ["waiting", "queued", "claimed", "done", "failed", "cancelled"] }, + status: { enum: ["waiting", "queued", "claimed", "done", "failed", "cancelled", "skipped"] }, claimed_by: nstr, attempts: int, max_attempts: int, priority: int, template_id: nstr, depends_on: strs, lease_ttl_s: int, lease_deadline: nstr, lease_remaining_s: nint, duration_s: nint, last_error: nstr, created_at: nstr, claimed_at: nstr, finished_at: nstr, @@ -171,7 +171,7 @@ export const SCHEMAS: Record = { DeviceOutcome: object( { device_id: str, job_id: str, - status: { enum: ["waiting", "queued", "claimed", "done", "failed", "cancelled"] }, + status: { enum: ["waiting", "queued", "claimed", "done", "failed", "cancelled", "skipped"] }, ok: { type: ["boolean", "null"] }, skipped: { ...bool, description: "Nothing ran (no matching device, or a host refusing work). Not a pass." }, error: nstr, metrics: nobj, @@ -221,7 +221,7 @@ export const SCHEMAS: Record = { { valid: bool, job_id: str, - status: { type: "string", description: "What the job would be on enqueue: queued, waiting or failed." }, + status: { type: "string", description: "What the job would be on enqueue: queued, waiting, failed (a dependency failed) or skipped (a dependency skipped)." }, fanout: strs, spec: { ...obj, description: "The spec as it would be stored: `latest` resolved, lease filled in." }, candidates: arr(ref("CandidateDevice")), diff --git a/collector/src/client/api.gen.ts b/collector/src/client/api.gen.ts index 26a3314..4493d39 100644 --- a/collector/src/client/api.gen.ts +++ b/collector/src/client/api.gen.ts @@ -142,7 +142,7 @@ export type DeviceList = { export type DeviceOutcome = { device_id: string; job_id: string; - status: "waiting" | "queued" | "claimed" | "done" | "failed" | "cancelled"; + status: "waiting" | "queued" | "claimed" | "done" | "failed" | "cancelled" | "skipped"; ok: boolean | null; /** Nothing ran (no matching device, or a host refusing work). Not a pass. */ skipped: boolean; @@ -211,7 +211,7 @@ export type Job = { job_id: string; workload: string; executor: "device" | "host"; - status: "waiting" | "queued" | "claimed" | "done" | "failed" | "cancelled"; + status: "waiting" | "queued" | "claimed" | "done" | "failed" | "cancelled" | "skipped"; claimed_by?: string | null; attempts: number; max_attempts: number; @@ -486,7 +486,7 @@ export type TemplateList = { export type Validation = { valid: boolean; job_id?: string; - /** What the job would be on enqueue: queued, waiting or failed. */ + /** What the job would be on enqueue: queued, waiting, failed (a dependency failed) or skipped (a dependency skipped). */ status?: string; fanout?: string[]; /** The spec as it would be stored: `latest` resolved, lease filled in. */ diff --git a/collector/src/db.test.ts b/collector/src/db.test.ts index cf03e8a..d38b250 100644 --- a/collector/src/db.test.ts +++ b/collector/src/db.test.ts @@ -19,7 +19,7 @@ import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; import { DatabaseSync } from "node:sqlite"; -import { closeDb, db, dbFile, isUniqueViolation, openDb, withTransaction } from "./db.js"; +import { backfillSkipped, closeDb, db, dbFile, dbHandle, isUniqueViolation, openDb, withTransaction } from "./db.js"; type Check = (name: string, cond: boolean, detail?: string) => void; @@ -265,6 +265,75 @@ export function runDbChecks(check: Check) { closeDb(); }); + // --- 'skipped', on a database that holds two weeks of skips as 'done' ----- + // + // The 0.8 shape: every status but 'skipped', and the columns added since by + // ALTER. The live brain's tvloop nightly closed as done every night with a + // skipped: host row; explore's tvOS jobs closed as done over device rows that + // all skipped. Both must come out skipped, a real pass must not, and the + // result rows must be exactly what they were. + inTempDir((dir) => { + const file = path.join(dir, "fleet.db"); + const seed = new DatabaseSync(file); + seed.exec(PRE_DEPENDS_ON_JOBS.replace("('queued','claimed','done','failed','cancelled')", "('waiting','queued','claimed','done','failed','cancelled')")); + seed.exec("ALTER TABLE jobs ADD COLUMN depends_on TEXT"); + seed.exec("ALTER TABLE jobs ADD COLUMN requested_by TEXT"); + seed.exec("ALTER TABLE jobs ADD COLUMN source TEXT"); + seed.exec(`CREATE TABLE results (job_id TEXT NOT NULL, device_id TEXT NOT NULL, iter INTEGER NOT NULL DEFAULT 0, + payload TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (datetime('now')), PRIMARY KEY (job_id, device_id, iter))`); + const job = seed.prepare("INSERT INTO jobs (job_id, executor, workload, spec, status, requested_by, last_error) VALUES (?,?,?,?,?,?,?)"); + const result = seed.prepare("INSERT INTO results (job_id, device_id, iter, payload) VALUES (?,?,?,?)"); + job.run("nightly-tvloop-hardware-202610150630", "host", "tvloop", "{}", "done", "schedule:nightly-tvloop-hardware", null); + result.run("nightly-tvloop-hardware-202610150630", "host:fleet-host", 0, + JSON.stringify({ final: true, ok: true, error: "skipped: no Roku developer password on this host" })); + job.run("explore-tvos-1", "host", "explore", "{}", "done", null, "lease expired on ultra; requeued after attempt 1/3"); + result.run("explore-tvos-1", "sim-a", 0, JSON.stringify({ ok: true, error: "skipped: no device matches this job on ultra" })); + result.run("explore-tvos-1", "host:ultra", 0, JSON.stringify({ final: true, ok: true })); + job.run("real-pass", "host", "ui-test", "{}", "done", null, null); + result.run("real-pass", "phone-a", 0, JSON.stringify({ ok: true, error: "skipped: locked" })); + result.run("real-pass", "phone-b", 0, JSON.stringify({ ok: true, test: { passed: 2, failed: 0 } })); + result.run("real-pass", "host:mac", 0, JSON.stringify({ final: true, ok: true })); + job.run("real-fail", "host", "ui-test", "{}", "failed", null, null); + result.run("real-fail", "host:mac", 0, JSON.stringify({ final: true, ok: false, error: "skipped: odd but failed" })); + const before = (seed.prepare("SELECT job_id, device_id, iter, payload FROM results ORDER BY job_id, device_id").all() as unknown[]); + seed.close(); + + openDb(dir); + const ddl = (db.prepare("SELECT sql FROM sqlite_master WHERE type='table' AND name='jobs'").get() as { sql: string }).sql; + check("skipped: the rebuild widens the constraint to accept 'skipped'", ddl.includes("'skipped'"), ddl); + const status = (id: string) => db.prepare("SELECT status, last_error, requested_by FROM jobs WHERE job_id = ?").get(id) as + { status: string; last_error: string | null; requested_by: string | null }; + check("skipped: a done job whose final row said skipped is re-labelled", + status("nightly-tvloop-hardware-202610150630").status === "skipped" && + status("nightly-tvloop-hardware-202610150630").last_error === "skipped: no Roku developer password on this host", + JSON.stringify(status("nightly-tvloop-hardware-202610150630"))); + check("skipped: and keeps the columns added since 0.6 (requested_by survives the rebuild)", + status("nightly-tvloop-hardware-202610150630").requested_by === "schedule:nightly-tvloop-hardware"); + check("skipped: one whose every device skipped under an ok host row is re-labelled, its reason replacing a stale note", + status("explore-tvos-1").status === "skipped" && status("explore-tvos-1").last_error === "skipped: no device matches this job on ultra", + JSON.stringify(status("explore-tvos-1"))); + check("skipped: a job where one device ran stays done", status("real-pass").status === "done"); + check("skipped: a failed job stays failed", status("real-fail").status === "failed"); + const after = db.prepare("SELECT job_id, device_id, iter, payload FROM results ORDER BY job_id, device_id").all(); + check("skipped: result rows are untouched", JSON.stringify(after) === JSON.stringify(before)); + const indexes = (db.prepare("SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='jobs'").all() as { name: string }[]).map((i) => i.name); + check("skipped: the rebuild leaves the jobs indexes in place", + ["idx_jobs_lease", "idx_jobs_claim", "idx_jobs_parent", "idx_jobs_requested_by"].every((n) => indexes.includes(n)), JSON.stringify(indexes)); + let accepted = true; + try { + db.prepare("INSERT INTO jobs (job_id, executor, workload, spec, status) VALUES ('s', 'host', 'x', '{}', 'skipped')").run(); + } catch { + accepted = false; + } + check("skipped: a migrated database accepts a skipped job", accepted); + check("skipped: the backfill is idempotent", backfillSkipped(dbHandle()) === 0); + closeDb(); + openDb(dir); + check("skipped: re-opening changes nothing", + (db.prepare("SELECT COUNT(*) AS n FROM jobs WHERE status = 'skipped'").get() as { n: number }).n === 3); + closeDb(); + }); + // --- withTransaction against a handle the module does not own ------------ inTempDir((dir) => { const file = path.join(dir, "standalone.db"); diff --git a/collector/src/db.ts b/collector/src/db.ts index 89a3b24..aab8a11 100644 --- a/collector/src/db.ts +++ b/collector/src/db.ts @@ -32,6 +32,7 @@ import { DatabaseSync, type SQLInputValue, type StatementSync } from "node:sqlit import { mkdirSync } from "node:fs"; import path from "node:path"; import { DATA_DIR } from "./config.js"; +import { closingStatus } from "./skip.js"; /** * What may be bound to a `?` placeholder. @@ -199,6 +200,49 @@ export const db = { * because the collector is one SQLite file that a person owns and the * alternative is a version number somebody has to remember to bump. */ +/** + * Re-label the jobs that skipped before 'skipped' was a status. + * + * Candidates are the `done` jobs with any result row carrying a `"skipped:` + * string -- one pass over results with `instr`, no JSON parsing -- and each is + * then judged by the same `closingStatus` the queue uses when a job closes, so + * history and new jobs follow one rule. Result rows are not touched; the job's + * `last_error` gets the skip reason, which is where the job list, the alert and + * the digest read it from. + * + * Idempotent: a job it re-labels is no longer `done`, so a second pass finds + * nothing to do. Exported for the test, which runs it twice. + */ +export function backfillSkipped(h: DatabaseSync): number { + const candidates = h + .prepare( + `SELECT j.job_id FROM jobs j + WHERE j.status = 'done' + AND EXISTS (SELECT 1 FROM results r WHERE r.job_id = j.job_id AND instr(r.payload, '"skipped:') > 0)`, + ) + .all() as { job_id: string }[]; + const rowsOf = h.prepare("SELECT device_id, payload FROM results WHERE job_id = ? ORDER BY iter, rowid"); + const relabel = h.prepare("UPDATE jobs SET status = 'skipped', last_error = ? WHERE job_id = ? AND status = 'done'"); + let n = 0; + for (const { job_id } of candidates) { + const rows = (rowsOf.all(job_id) as { device_id: string; payload: string }[]).map((r) => { + let payload: Record = {}; + try { + payload = JSON.parse(r.payload) as Record; + } catch { + /* a row that is not JSON says nothing about a skip */ + } + return { device_id: r.device_id, payload }; + }); + const final = [...rows].reverse().find((r) => r.payload.final)?.payload; + if (!final) continue; + const closing = closingStatus(rows, final); + if (closing.status !== "skipped") continue; + n += Number(relabel.run(closing.reason, job_id).changes); + } + return n; +} + function migrate(db: DatabaseSync): void { db.exec(` CREATE TABLE IF NOT EXISTS devices ( @@ -234,8 +278,11 @@ CREATE TABLE IF NOT EXISTS jobs ( -- 'waiting' is a job whose dependencies have not finished. It is distinct -- from 'queued' because a queued job is one the claim loop should be looking -- at, and a waiting one is not eligible for anything yet. + -- 'skipped' is not 'done': the runner claimed it and could not run it (no + -- device matched, the app was not installed, no Roku password). Counting it + -- as done is how two nightlies "passed" for two weeks while testing nothing. status TEXT NOT NULL DEFAULT 'queued' - CHECK (status IN ('waiting','queued','claimed','done','failed','cancelled')), + CHECK (status IN ('waiting','queued','claimed','done','failed','cancelled','skipped')), created_at TEXT NOT NULL DEFAULT (datetime('now')), claimed_by TEXT, claimed_at TEXT, @@ -256,7 +303,8 @@ CREATE TABLE IF NOT EXISTS jobs ( parent_job_id TEXT, template_id TEXT, -- JSON array of job_ids this one waits for. Resolved to 'queued' when the - -- last of them closes; failed when any of them fails or is cancelled. + -- last of them closes; failed when any of them fails or is cancelled, + -- skipped when one of them skipped. depends_on TEXT ); @@ -668,6 +716,36 @@ CREATE TABLE IF NOT EXISTS findings_digests ( if (!artifactCols.has("media_type")) db.exec("ALTER TABLE artifacts ADD COLUMN media_type TEXT"); } +// 'skipped' as a job status, and the two weeks of skips that closed as 'done' +// before it existed. After every ALTER above, so the rebuild can copy whatever +// columns this database has by name instead of a fixed list that the next +// added column would silently drop. +{ + const ddl = (db.prepare("SELECT sql FROM sqlite_master WHERE type='table' AND name='jobs'").get() as + | { sql: string } + | undefined)?.sql; + if (ddl && !ddl.includes("'skipped'")) { + const widened = ddl + .replace(/^CREATE TABLE\s+("?)jobs\1/i, "CREATE TABLE jobs_migrating") + .replace(/CHECK\s*\(\s*status\s+IN\s*\(([^)]*)\)\s*\)/i, (_m, list: string) => `CHECK (status IN (${list.trim()},'skipped'))`); + if (!widened.includes("'skipped'") || !widened.startsWith("CREATE TABLE jobs_migrating")) + throw new Error("cannot widen the jobs status constraint: the table's DDL is not the shape this migration knows"); + const columns = (db.prepare("PRAGMA table_info(jobs)").all() as { name: string }[]).map((c) => `"${c.name}"`).join(", "); + db.exec("PRAGMA foreign_keys = off"); + withTransaction(db, () => { + db.exec(widened); + db.exec(`INSERT INTO jobs_migrating (${columns}) SELECT ${columns} FROM jobs`); + db.exec("DROP TABLE jobs"); + db.exec("ALTER TABLE jobs_migrating RENAME TO jobs"); + // Inside the same transaction as the rebuild, and only with it: the + // rebuild runs once per database, and a backfill that runs only then + // costs one scan of the results table, once, instead of one per start. + backfillSkipped(db); + })(); + db.exec("PRAGMA foreign_keys = on"); + } +} + // Every mutation that went through the control API, with who made it. Kept // apart from the jobs table because a cancel, a device edit or a refused // request is not a job, and "who did that" is asked of all of them. @@ -687,6 +765,10 @@ CREATE TABLE IF NOT EXISTS audit_log ( ); CREATE INDEX IF NOT EXISTS idx_audit_at ON audit_log (at DESC); CREATE INDEX IF NOT EXISTS idx_jobs_requested_by ON jobs (requested_by); +-- Again, because the 'skipped' rebuild above drops every index on jobs. +CREATE INDEX IF NOT EXISTS idx_jobs_lease ON jobs (status, lease_deadline); +CREATE INDEX IF NOT EXISTS idx_jobs_claim ON jobs (status, executor, priority DESC, created_at); +CREATE INDEX IF NOT EXISTS idx_jobs_parent ON jobs (parent_job_id); `); // Jobs claimed before leases existed have no deadline and would never be swept. diff --git a/collector/src/describe.test.ts b/collector/src/describe.test.ts index e37658d..6cb7f59 100644 --- a/collector/src/describe.test.ts +++ b/collector/src/describe.test.ts @@ -49,6 +49,14 @@ export async function runDescribeChecks(check: Check) { check("and is attached to this host, which host routing follows", typeof r1.attached_to === "string"); const r2 = await describeTarget({ id: "roku-gone", platform: "roku", kind: "device" } as never, null, null, []); check("a Roku discovery lost track of is still a Roku, not an iPhone", r2.os === "roku", JSON.stringify(r2)); + // It used to say nothing, and the collector's fallback guess for anything + // that is not iOS is Android: the shelf's Roku Express listed as android. + check("a Roku says its platform is roku", r1.platform === "roku" && r2.platform === "roku", + JSON.stringify([r1.platform, r2.platform])); + const { devicePlatform } = await import("./api/shared.js"); + check("and the collector believes it", devicePlatform(r1) === "roku", devicePlatform(r1)); + const { evalMatch } = await import("./match.js"); + check("os ~ 'roku' still selects it", evalMatch("os ~ 'roku'", r1) && evalMatch("os ~ 'roku-15'", r1)); const { rokuPresenceHere } = await import("./drivers/roku.js"); check("Roku presence is off unless this host is told it owns them", diff --git a/collector/src/drivers/roku.ts b/collector/src/drivers/roku.ts index 724dca8..cfd35ef 100644 --- a/collector/src/drivers/roku.ts +++ b/collector/src/drivers/roku.ts @@ -403,9 +403,14 @@ export function rokuPresenceHere(env: NodeJS.ProcessEnv = process.env): boolean * `ios-18.4` have. `ip` is carried because tvloop and the dev installer both * address a Roku by it, and a workload should not have to re-run discovery to * learn what the registry already knew. + * + * `platform: "roku"` is said outright. Without it the collector fell back to + * its old guess -- iOS if `os` looks like iOS, Android otherwise -- and the + * Roku Express on the shelf registered as an Android device. */ export function describeRoku(d: RokuDevice): Record { return { + platform: "roku", model: d.modelName ?? d.modelNumber ?? "roku", os: d.softwareVersion ? `roku-${d.softwareVersion}` : "roku", ...(d.serial ? { serial: d.serial } : {}), diff --git a/collector/src/executor.ts b/collector/src/executor.ts index d825343..77709d3 100644 --- a/collector/src/executor.ts +++ b/collector/src/executor.ts @@ -18,6 +18,8 @@ import { pressureReason, readPressure } from "./pressure.js"; import { runArchive } from "./web/archive/index.js"; import { runDigest } from "./web/digest.js"; import { countXcodebuildTests, xcodebuildDiagnostics } from "./xcparse.js"; +import { junitFailureReason, parseJunit } from "./junit.js"; +import { execFailureReason } from "./result-reason.js"; import { fleetOwned, physicalApple, simulatorName, isAndroidEmulatorSerial, appleNotReadyReason, SIM_PREFIX, @@ -167,13 +169,6 @@ async function listTargets(ios?: IosDeviceInfo[], rokus: RokuDevice[] = []): Pro return dedupe([await adbDriver.list(), await simctlDriver.list(), targetsFrom(ios), rokus.map(rokuTarget)]); } -function parseJunit(xml: string): { passed: number; failed: number } { - const m = /tests="(\d+)"[^>]*failures="(\d+)"/.exec(xml); - if (!m) return { passed: 0, failed: 1 }; - const tests = Number(m[1]); - const failed = Number(m[2]); - return { passed: tests - failed, failed }; -} /** Is this target one the fleet may run work on? Presence and jobs must agree. */ @@ -598,6 +593,10 @@ async function runUiTest(job: Job) { const outDir = mkdtempSync(path.join(os.tmpdir(), "fleet-junit-")); const report = path.join(outDir, "report.xml"); let failedToRun = false; + // Why Maestro produced no report, when it did not: its exit code and the + // last thing it said. Never the error's message, which is the command + // line -- and the command line carries the test account's password. + let runError: string | undefined; // params.network, when the job carries one, is applied around the flow run // and restored afterwards whatever happens inside it. A profile that cannot // be applied fails the device's row by name rather than running the flow @@ -617,9 +616,10 @@ async function runUiTest(job: Job) { flows], { timeout: 600_000 }, ); - } catch { + } catch (e) { // Non-zero exit also just means failing flows; the report tells the truth. failedToRun = !existsSync(report); + if (failedToRun) runError = execFailureReason(e, creds ? [creds.password] : []); } }); } catch (e) { @@ -629,20 +629,34 @@ async function runUiTest(job: Job) { let passed = 0; let failed = 1; + let failure: string | null = null; + let failingFlow: string | undefined; const artifacts: string[] = []; if (!failedToRun && existsSync(report)) { const xml = readFileSync(report, "utf8"); - ({ passed, failed } = parseJunit(xml)); + const junit = parseJunit(xml); + ({ passed, failed } = junit); + // The failing flow and the step that broke, from the report itself: + // `smoke: Assertion is false: "Fleet Runner" is visible`. This used to + // be read by nobody, so a failure posted `failed: 1` and no reason. + failure = junitFailureReason(junit); + if (failure && creds) failure = redact(failure, [creds.password]); + failingFlow = junit.failures[0]?.name; // Scrub before upload: a failing step echoes the command it ran, and the // report is downloadable from the dashboard. if (creds) writeFileSync(report, redact(xml, [creds.password])); artifacts.push(await uploadArtifact(report, `${job.job_id}-${serial}-junit.xml`)); } if (failed > 0) allOk = false; + const error = shapeError + ? `params.network: ${shapeError}` + : failedToRun + ? `maestro produced no report: ${runError ?? "it never ran"}` + : failure ?? undefined; await postResult({ job_id: job.job_id, device_id: serial, iter: 0, - ok: failed === 0, test: { passed, failed, artifacts }, - ...(shapeError ? { error: `params.network: ${shapeError}` } : {}), + ok: failed === 0, test: { passed, failed, artifacts, ...(failingFlow ? { failing_flow: failingFlow } : {}) }, + ...(error ? { error } : {}), }); log(`ui-test on ${serial}: ${passed} passed / ${failed} failed${shapeError ? ` (network shaping: ${shapeError})` : ""}`); } @@ -2370,7 +2384,7 @@ export async function describeTarget( // registered as {model: "iphone", os: "ios"}. const d = rokus.find((r) => rokuTarget(r).id === t.id); return { - ...(d ? describeRoku(d) : { model: "roku", os: "roku", kind: "device" }), + ...(d ? describeRoku(d) : { platform: "roku", model: "roku", os: "roku", kind: "device" }), attached_to: NAME, attached_host: HOST, }; @@ -2823,11 +2837,17 @@ export async function startExecutor(): Promise { log(`job ${job.job_id} skipped: ${e.message}`); continue; } + // A subprocess that failed and was not caught by its workload: its + // exit code and last stderr line, not Node's message, which is the + // whole command line (arguments, and sometimes a password, included). + const reason = typeof (e as { cmd?: unknown }).cmd === "string" + ? execFailureReason(e) + : (e as Error).message.slice(0, 500); await postResult({ job_id: job.job_id, device_id: `host:${NAME}`, iter: 0, final: true, ok: false, - error: (e as Error).message.slice(0, 500), + error: reason, }); - log(`job ${job.job_id} failed: ${(e as Error).message}`); + log(`job ${job.job_id} failed: ${reason}`); } } } diff --git a/collector/src/findings.test.ts b/collector/src/findings.test.ts index f42c30c..aaedf50 100644 --- a/collector/src/findings.test.ts +++ b/collector/src/findings.test.ts @@ -264,6 +264,25 @@ export async function runFindingsChecks(check: Check) { check("digest: high severity first", d.apps[1].top[0].id === a.finding.id); check("digest: judged-not-a-bug is left out", !d.text.includes("Not actually a bug")); + // A skip is a job that ran nothing: its own count and its own line, with + // the schedule and the reason, never folded into done. + const job = (id: string, status: string, err: string | null) => + db.prepare( + "INSERT INTO jobs (job_id, executor, workload, spec, status, last_error, finished_at) VALUES (?, 'host', 'tvloop', '{}', ?, ?, datetime('now'))", + ).run(id, status, err); + job("nightly-ok-202610150230", "done", null); + job("nightly-ui-smoke-202610150230", "failed", 'smoke: Assertion is false: "Fleet Runner" is visible'); + job("nightly-tvloop-hardware-202610150630", "skipped", "skipped: no Roku developer password on this host"); + job("explore-tv-202610150300--sim-a", "skipped", "skipped: no device matches this job on ultra"); + job("explore-tv-202610150300--sim-b", "skipped", "skipped: no device matches this job on ultra"); + const withJobs = buildDigest(12, "http://fleet.test:8788"); + check("digest: jobs are counted done, failed and skipped", + withJobs.jobs.done === 1 && withJobs.jobs.failed === 1 && withJobs.jobs.skipped === 3, JSON.stringify(withJobs.jobs)); + check("digest: the skip line says nothing ran", withJobs.text.includes("Jobs, last 12h: 1 done, 1 failed, 3 skipped (nothing ran)."), withJobs.text); + check("digest: and names what skipped and why, by schedule", + withJobs.text.includes("- skipped: explore-tv x2 (no device matches this job on ultra)") && + withJobs.text.includes("- skipped: nightly-tvloop-hardware (no Roku developer password on this host)"), withJobs.text); + // The timer. const at7 = new Date(2026, 9, 3, 7, 0); check("digest timer: not before HH:MM", !digestDue(new Date(2026, 9, 3, 6, 59), "07:00", null)); diff --git a/collector/src/findings.ts b/collector/src/findings.ts index f1d45f7..0d92d49 100644 --- a/collector/src/findings.ts +++ b/collector/src/findings.ts @@ -39,6 +39,7 @@ import { db } from "./db.js"; import { iso, parse } from "./api/shared.js"; import { sendWebhook } from "./alerts.js"; +import { skipReasonText } from "./skip.js"; import { DASH_URL, FINDINGS_DIGEST_AT, @@ -825,11 +826,55 @@ export type Digest = { again: number; top: { id: number; severity: string; check: string; title: string; screen_name: string; replay: string; new: boolean; seen_count: number }[]; }[]; + /** Jobs that finished in the same window, by how they finished. A skip is + * its own count: it is a job that ran nothing, and folding it into done is + * how two nightlies read as passes for two weeks. */ + jobs: { done: number; failed: number; skipped: number; skipped_by: { name: string; count: number; reason: string }[] }; link: string; text: string; }; const TOP_PER_APP = 5; +const SKIPS_NAMED = 3; + +/** + * How the jobs in the window finished, and which schedules skipped and why. + * A scheduled job's id is `-`, so stripping the minute + * (and a fan-out child's `--device`) names the nightly a person recognises. + */ +export function jobsInWindow(sinceKey: string): Digest["jobs"] { + const counts = db + .prepare( + `SELECT COUNT(*) FILTER (WHERE status = 'done') AS done, + COUNT(*) FILTER (WHERE status = 'failed') AS failed, + COUNT(*) FILTER (WHERE status = 'skipped') AS skipped + FROM jobs WHERE finished_at >= ?`, + ) + .get(sinceKey) as { done: number; failed: number; skipped: number }; + const skips = db + .prepare("SELECT job_id, last_error FROM jobs WHERE status = 'skipped' AND finished_at >= ? ORDER BY finished_at DESC") + .all(sinceKey) as { job_id: string; last_error: string | null }[]; + const by = new Map(); + for (const j of skips) { + const name = j.job_id.split("--")[0].replace(/-\d{12}$/, ""); + const hit = by.get(name) ?? { name, count: 0, reason: skipReasonText(j.last_error) }; + hit.count += 1; + by.set(name, hit); + } + return { + done: counts.done ?? 0, failed: counts.failed ?? 0, skipped: counts.skipped ?? 0, + skipped_by: [...by.values()].sort((a, b) => b.count - a.count), + }; +} + +function jobsLines(j: Digest["jobs"], hours: number): string[] { + if (j.done + j.failed + j.skipped === 0) return []; + const lines = [`Jobs, last ${hours}h: ${j.done} done, ${j.failed} failed, ${j.skipped} skipped (nothing ran).`]; + for (const s of j.skipped_by.slice(0, SKIPS_NAMED)) + lines.push(`- skipped: ${s.name}${s.count > 1 ? ` x${s.count}` : ""} (${s.reason})`); + if (j.skipped_by.length > SKIPS_NAMED) lines.push(`- and ${j.skipped_by.length - SKIPS_NAMED} more skipping`); + return lines; +} /** ntfy turns a body past 4 KB into an attachment; a digest should read as a notification. */ const DIGEST_MAX_CHARS = 3_500; @@ -874,11 +919,14 @@ export function buildDigest(hours: number, dashUrl: string = DASH_URL, now = new const total = rows.length; const fresh = apps.reduce((n, a) => n + a.new, 0); const link = `${dashUrl}/dash/findings?status=open`; + const jobs = jobsInWindow(sinceKey); const plural = (n: number, one: string, many = `${one}s`) => `${n} ${n === 1 ? one : many}`; const lines: string[] = []; if (total === 0) { lines.push(`Night QA, last ${hours}h: nothing new.`); + const jl = jobsLines(jobs, hours); + if (jl.length) lines.push("", ...jl); } else { lines.push( `Night QA, last ${hours}h: ${plural(total, "finding")} (${fresh} new, ${total - fresh} seen again) in ${plural(apps.length, "app")}.`, @@ -892,11 +940,13 @@ export function buildDigest(hours: number, dashUrl: string = DASH_URL, now = new } if (a.count > a.top.length) lines.push(`- and ${a.count - a.top.length} more`); } + const jl = jobsLines(jobs, hours); + if (jl.length) lines.push("", ...jl); lines.push("", `Triage: ${link}`); } let text = lines.join("\n"); if (text.length > DIGEST_MAX_CHARS) text = `${text.slice(0, DIGEST_MAX_CHARS - 40).trimEnd()}\n...\nTriage: ${link}`; - return { hours, since: since.toISOString(), total, new: fresh, again: total - fresh, apps, link, text }; + return { hours, since: since.toISOString(), total, new: fresh, again: total - fresh, apps, jobs, link, text }; } /** Local calendar day, YYYY-MM-DD: "once a day" is the owner's day, not UTC's. */ diff --git a/collector/src/fleet-client.ts b/collector/src/fleet-client.ts index 80b6750..4a39792 100644 --- a/collector/src/fleet-client.ts +++ b/collector/src/fleet-client.ts @@ -8,6 +8,7 @@ import { promisify } from "node:util"; import { createHash } from "node:crypto"; import { readFileSync, writeFileSync } from "node:fs"; import os from "node:os"; +import { withFailureReasons } from "./result-reason.js"; export const exec = promisify(execFile); @@ -66,9 +67,14 @@ export async function post(url: string, body: unknown) { if (!res.ok) throw new Error(`POST ${url} -> ${res.status}`); } -export async function postResult(row: Record) { +/** + * Post one result row. Every host workload's rows go through here, so this is + * where a row that says `ok: false` and nothing else is given a reason -- see + * result-reason.ts. + */ +export const postResult = withFailureReasons(async (row: Record) => { await post("/results", { schema: 1, kind: "result", ...row }); -} +}); export async function postBeacon(jobId: string, deviceId: string, extra: Record) { await post("/results", { diff --git a/collector/src/junit.ts b/collector/src/junit.ts new file mode 100644 index 0000000..8b7490e --- /dev/null +++ b/collector/src/junit.ts @@ -0,0 +1,73 @@ +/** + * Reading a JUnit report: how many passed, how many failed, and what failed. + * + * Maestro writes one `` per flow with a `` inside naming the + * step that broke (`Assertion is false: "Fleet Runner" is visible`). The counts + * were always read; the failure was not, so a failing ui-test posted + * `failed: 1` and no reason while the reason sat in the report it uploaded. + * + * Regexes, not an XML parser: the reports come from a handful of known tools, + * the same pragmatism the counts have always had, and a dependency for one + * element would be a poor trade. + */ + +export type JunitFailure = { name: string; message: string }; +export type JunitSummary = { passed: number; failed: number; failures: JunitFailure[] }; + +const ENTITIES: Record = { quot: '"', apos: "'", lt: "<", gt: ">", amp: "&" }; + +function decode(s: string): string { + return s + .replace(//g, "$1") + .replace(/&(quot|apos|lt|gt|amp);/g, (_m, e: string) => ENTITIES[e]) + .replace(/&#(\d+);/g, (_m, n: string) => String.fromCodePoint(Number(n))) + .replace(/&#x([0-9a-f]+);/gi, (_m, n: string) => String.fromCodePoint(parseInt(n, 16))); +} + +const attr = (tag: string, name: string) => { + const m = new RegExp(`\\b${name}="([^"]*)"`).exec(tag); + return m ? decode(m[1]) : null; +}; + +/** + * Counts and failures. A report with no recognisable counts is one failure: + * a run that produced garbage did not pass. Counts come from the first + * `tests`/`failures` pair (Maestro's ``); `errors` count as + * failures, because an errored flow did not pass either. + */ +export function parseJunit(xml: string): JunitSummary { + const failures: JunitFailure[] = []; + for (const tc of xml.matchAll(/]*?)(?:\/>|>([\s\S]*?)<\/testcase>)/g)) { + const body = tc[2] ?? ""; + const f = /<(failure|error)\b([^>]*?)(?:\/>|>([\s\S]*?)<\/\1>)/.exec(body); + if (!f) continue; + const text = decode((f[3] ?? "").trim()); + const message = (text || attr(f[2], "message") || attr(f[2], "type") || f[1]).trim(); + failures.push({ name: attr(tc[1], "name") ?? attr(tc[1], "id") ?? "test", message }); + } + + const suite = /]*>/.exec(xml)?.[0] ?? /]*>/.exec(xml)?.[0] ?? ""; + const tests = Number(attr(suite, "tests")); + if (!suite || !Number.isFinite(tests)) { + return failures.length ? { passed: 0, failed: failures.length, failures } : { passed: 0, failed: 1, failures }; + } + const failed = Number(attr(suite, "failures") ?? 0) + Number(attr(suite, "errors") ?? 0); + return { passed: Math.max(0, tests - failed), failed: Math.max(failed, failures.length), failures }; +} + +/** + * One line for the result's `error`: the first failing test and its step, and + * how many more there were. Null when nothing failed. + */ +export function junitFailureReason(s: JunitSummary, max = 300): string | null { + if (s.failed === 0) return null; + const first = s.failures[0]; + let line: string; + if (!first) line = `${s.failed} of ${s.passed + s.failed} failed; the report names no failing step`; + else { + const msg = first.message.split("\n").map((l) => l.trim()).find(Boolean) ?? "failed"; + line = `${first.name}: ${msg}`; + if (s.failed > 1) line += ` (and ${s.failed - 1} more failing)`; + } + return line.length > max ? `${line.slice(0, max - 3)}...` : line; +} diff --git a/collector/src/queue.ts b/collector/src/queue.ts index 18c2f67..07350a0 100644 --- a/collector/src/queue.ts +++ b/collector/src/queue.ts @@ -81,7 +81,8 @@ export type JobSpec = { template_id?: string; // Job ids this one waits for. The job is inserted 'waiting' and promoted to // 'queued' when the last of them is 'done' — a build → install → ui-test - // chain is three POSTs and nothing watching the queue. + // chain is three POSTs and nothing watching the queue. If one of them fails + // the job fails; if one of them skipped, the job skips. depends_on?: string[]; // The runner will stand down and checkpoint if higher-priority work arrives // for the same claimant. Honoured by the collector's beacon reply; a runner @@ -264,7 +265,8 @@ export type CandidateDevice = { device_id: string; model: string | null; os: str export type EnqueueAccepted = { ok: true; http: 200 | 201; - /** queued, waiting (on depends_on), or failed (a dependency already failed). */ + /** queued, waiting (on depends_on), failed (a dependency already failed) or + * skipped (a dependency already skipped, so there is nothing to run on). */ status: string; job_id: string; /** Present when the spec fanned out: one child per device. */ @@ -473,6 +475,7 @@ export function enqueueJob( }; } + const closedOnArrival = depState.status === "failed" || depState.status === "skipped"; // Every child inherits the parent's dependencies, so a fan-out can hang off // a single build the same way one pinned job can. const insert = db.prepare( @@ -484,12 +487,12 @@ export function enqueueJob( const r = insert.run( child.job_id, child.executor, child.workload, JSON.stringify(child), ttlS, maxAttempts, priority, spec.job_id, templateId, dependsOn, depState.status, - depState.status === "failed" ? depState.reason : null, + closedOnArrival ? depState.reason : null, provenance.requested_by, provenance.source, ); if (r.changes > 0) created.push(child.job_id); } - if (depState.status === "failed") + if (closedOnArrival) for (const jobId of created) db.prepare("UPDATE jobs SET finished_at = datetime('now') WHERE job_id = ?").run(jobId); for (const jobId of created) @@ -510,10 +513,10 @@ export function enqueueJob( try { db.prepare( `INSERT INTO jobs (job_id, executor, workload, spec, lease_ttl_s, max_attempts, priority, template_id, depends_on, status, last_error, finished_at, requested_by, source) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ${depState.status === "failed" ? "datetime('now')" : "NULL"}, ?, ?)`, + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ${depState.status === "failed" || depState.status === "skipped" ? "datetime('now')" : "NULL"}, ?, ?)`, ).run( spec.job_id, spec.executor, spec.workload, JSON.stringify(spec), ttlS, maxAttempts, priority, templateId, - dependsOn, depState.status, depState.status === "failed" ? depState.reason : null, + dependsOn, depState.status, depState.status === "failed" || depState.status === "skipped" ? depState.reason : null, provenance.requested_by, provenance.source, ); } catch (e: unknown) { @@ -532,6 +535,7 @@ export function enqueueJob( function warningsFor(spec: JobSpec, candidates: number, deps: { status: string; reason?: string }): string[] { const out: string[] = []; if (deps.status === "failed") out.push(`a dependency already failed (${deps.reason ?? "unknown"}); the job would be failed at once`); + if (deps.status === "skipped") out.push(`a dependency already skipped (${deps.reason ?? "unknown"}); the job would be skipped at once, since there is nothing for it to run on`); if (deps.status === "waiting") out.push("waiting on depends_on; it starts when those jobs are done"); if (spec.executor === "device" && candidates === 0) { out.push("no registered device matches these targets and can run this workload; the job would queue until one does"); diff --git a/collector/src/registry-hygiene.test.ts b/collector/src/registry-hygiene.test.ts new file mode 100644 index 0000000..16df4ef --- /dev/null +++ b/collector/src/registry-hygiene.test.ts @@ -0,0 +1,74 @@ +/** + * Registry hygiene, against a real database. + * + * The rows are the live brain's, October 2026: an `iPhone 17 Pro` simulator + * UUID offline for three weeks, a `fleet-explore-tv` simulator that registered + * before `soc` was written, a real iPhone offline even longer (which must stay: + * a phone in a drawer is still a phone), an Android emulator, and the Roku that + * was listed twice. `last_seen` is written directly because a week of silence + * is the whole point and a suite cannot wait for it. + */ +import { mkdtempSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import path from "node:path"; +import { closeDb, openDb } from "./db.js"; +import { declaredSimulator, forgetStaleSimulators, retireRokuIpDuplicate, rokuIpId, simulatorTtlDays } from "./registry-hygiene.js"; + +type Check = (name: string, cond: boolean, detail?: string) => void; + +export function runRegistryHygieneChecks(check: Check) { + closeDb(); + const dir = mkdtempSync(path.join(tmpdir(), "fleet-hygiene-test-")); + try { + const db = openDb(dir); + const add = (id: string, descriptor: Record, daysAgo: number) => + db.prepare( + `INSERT INTO devices (device_id, descriptor, pools, last_seen) VALUES (?, ?, '[]', datetime('now', ?))`, + ).run(id, JSON.stringify(descriptor), `-${daysAgo * 86_400} seconds`); + const exists = (id: string) => !!db.prepare("SELECT 1 FROM devices WHERE device_id = ?").get(id); + + add("75619D0E-5B01-46FA-967B-0964985BCE93", { model: "iPhone 17 Pro", os: "ios-27.0", soc: "simulator", kind: "simulator" }, 21); + add("CECF9000-9FF1-4511-8D1E-CD3E2E34E1E0", { model: "fleet-explore-tv", os: "ios", kind: "simulator" }, 13); + add("73BF450F-DD86-4DBC-AE25-763DE93B7508", { model: "simulator", os: "ios", soc: "simulator" }, 19); + add("799804C0-17C7-430C-835D-AFCD50824381", { model: "iPhone 18 Pro", os: "ios-27.0", soc: "simulator", kind: "simulator" }, 1); + add("09A99EFE-56C4-5FCF-9170-305B974BF662", { model: "iPhone 12 Pro", os: "ios-18.7.8", soc: "iPhone13,3", kind: "device" }, 51); + add("emulator-5554", { model: "sdk_gphone64_arm64", os: "android-15", kind: "device" }, 30); + add("machine-intel", { model: "MacBook Pro", soc: "x86_64", os: "macos-12.7.6", kind: "laptop" }, 40); + add("LOCKED-SIM", { model: "fleet-sim-1", kind: "simulator", soc: "simulator" }, 30); + db.prepare("INSERT INTO device_locks (device_id, job_id) VALUES ('LOCKED-SIM', 'some-job')").run(); + + check("hygiene: the TTL defaults to 7 days and reads FLEET_SIMULATOR_TTL_DAYS", + simulatorTtlDays({}) === 7 && simulatorTtlDays({ FLEET_SIMULATOR_TTL_DAYS: "2" }) === 2 && simulatorTtlDays({ FLEET_SIMULATOR_TTL_DAYS: "nope" }) === 7); + check("hygiene: only a declared simulator counts", + declaredSimulator({ kind: "simulator" }) && declaredSimulator({ soc: "simulator" }) && + !declaredSimulator({ soc: "x86_64" }) && !declaredSimulator({ model: "sdk_gphone64_arm64" })); + + const gone = forgetStaleSimulators(7); + check("hygiene: simulators offline past the TTL are forgotten", + !exists("75619D0E-5B01-46FA-967B-0964985BCE93") && !exists("CECF9000-9FF1-4511-8D1E-CD3E2E34E1E0") && + !exists("73BF450F-DD86-4DBC-AE25-763DE93B7508"), JSON.stringify(gone)); + check("hygiene: and named in what the sweep returns", gone.length === 3, JSON.stringify(gone)); + check("hygiene: a simulator seen yesterday stays", exists("799804C0-17C7-430C-835D-AFCD50824381")); + check("hygiene: a real iPhone is never forgotten, however long it has been away", exists("09A99EFE-56C4-5FCF-9170-305B974BF662")); + check("hygiene: nor an Android emulator, which comes back under the same serial", exists("emulator-5554")); + check("hygiene: nor an Intel machine whose soc merely looks like a simulator's", exists("machine-intel")); + check("hygiene: nor a simulator that holds a lock", exists("LOCKED-SIM")); + check("hygiene: a second sweep has nothing left to do", forgetStaleSimulators(7).length === 0); + + // --- the Roku listed twice --- + check("roku: the IP-named id is the executor's", rokuIpId("192.168.50.218") === "roku-ip-192-168-50-218"); + add("roku-ip-192-168-50-218", { model: "roku", os: "roku", ip: "192.168.50.218", kind: "device" }, 3); + add("roku-ip-192-168-50-99", { model: "roku", os: "roku", ip: "192.168.50.99", kind: "device" }, 3); + const serial = { platform: "roku", model: "Roku Express 4K+", os: "roku-15.3.4", serial: "X01600EMFRJ9", ip: "192.168.50.218" }; + check("roku: an IP-named registration never displaces anything", retireRokuIpDuplicate("roku-ip-192-168-50-218", serial) === null); + check("roku: a serial-named registration retires the duplicate at its address", + retireRokuIpDuplicate("roku-X01600EMFRJ9", serial) === "roku-ip-192-168-50-218" && !exists("roku-ip-192-168-50-218")); + check("roku: and only that one", exists("roku-ip-192-168-50-99")); + check("roku: a device with no address retires nothing", retireRokuIpDuplicate("roku-X01600EMFRJ9", { model: "roku" }) === null); + check("roku: nor does a phone that happens to report an ip", + retireRokuIpDuplicate("988a1b3541354f565a", { ip: "192.168.50.99" }) === null && exists("roku-ip-192-168-50-99")); + } finally { + closeDb(); + rmSync(dir, { recursive: true, force: true }); + } +} diff --git a/collector/src/registry-hygiene.ts b/collector/src/registry-hygiene.ts new file mode 100644 index 0000000..2e7e9e5 --- /dev/null +++ b/collector/src/registry-hygiene.ts @@ -0,0 +1,92 @@ +/** + * Keeping the device registry down to real things. + * + * Two kinds of row outlive what they describe, and both were on the live brain + * in October 2026: thirteen offline iOS rows that were simulator UUIDs from + * runs long gone, and a Roku listed twice -- `roku-ip-192-168-50-218`, from a + * sweep where the box answered SSDP but not device-info, offline beside the + * `roku-X01600EMFRJ9` it really is. A fan-out with no pool reaches every row, + * and a shelf where a third of the entries are ghosts is a shelf nobody reads. + * + * Forgetting here is what `DELETE /api/devices/:id` does: the row goes, the + * results and beacons it posted stay, because they are measurements and a + * device leaving the shelf does not make them untrue. + */ +import { db } from "./db.js"; +import { parse } from "./api/shared.js"; + +/** How long a simulator may sit offline before it is forgotten. */ +export function simulatorTtlDays(env: NodeJS.ProcessEnv = process.env): number { + const v = Number(env.FLEET_SIMULATOR_TTL_DAYS); + return Number.isFinite(v) && v > 0 ? v : 7; +} + +/** + * Is this row a simulator by its own say-so? + * + * Only what the agent declared: `kind: "simulator"` or `soc: "simulator"`, + * which is what the host executor writes for every Apple simulator. Not the + * looser `isSimulator()` heuristic the dashboard uses to keep simulators out of + * hardware tables -- that one also fires on `x86_64`, which a real Intel + * machine can report, and a real device is never forgotten. Android emulators + * are not forgotten either: `emulator-5554` comes back under the same serial + * the next time an AVD boots, and they already carry a presence TTL that hides + * them while they are gone. + */ +export function declaredSimulator(descriptor: Record): boolean { + return descriptor.kind === "simulator" || descriptor.soc === "simulator"; +} + +/** + * Forget simulator rows that have been offline longer than the TTL. Run by the + * lease sweep. A simulator is recreated, never brought back: a UUID that has + * not checked in for a week belongs to a device that no longer exists. + * + * A row that holds a lock or a claim is left alone, however old -- the same + * rule the dashboard's Forget button follows. + */ +export function forgetStaleSimulators(days = simulatorTtlDays()): string[] { + const rows = db + .prepare( + `SELECT device_id, descriptor FROM devices + WHERE last_seen <= datetime('now', ?) + AND NOT EXISTS (SELECT 1 FROM device_locks l WHERE l.device_id = devices.device_id) + AND NOT EXISTS (SELECT 1 FROM jobs j WHERE j.status = 'claimed' AND j.claimed_by = devices.device_id)`, + ) + .all(`-${Math.round(days * 86_400)} seconds`) as { device_id: string; descriptor: string }[]; + const gone: string[] = []; + const del = db.prepare("DELETE FROM devices WHERE device_id = ?"); + for (const r of rows) { + if (!declaredSimulator(parse>(r.descriptor, {}))) continue; + if (del.run(r.device_id).changes > 0) gone.push(r.device_id); + } + return gone; +} + +/** `roku-ip-192-168-50-218` for 192.168.50.218: the id the executor gives a Roku it knows only by address. */ +export function rokuIpId(ip: string): string { + return `roku-ip-${ip.replace(/\./g, "-")}`; +} + +/** + * When a Roku registers under its serial, retire the row the same box left + * when it was known only by its IP. + * + * The executor names a Roku `roku-` when device-info answers and + * `roku-ip-
` when only SSDP did, so one flaky sweep is enough to leave + * a second row that never checks in again. The serial-named row re-registers + * every minute, so a duplicate that comes back from another flaky sweep is + * retired within the minute too. Not the other way round: an IP-named row + * never displaces a serial-named one, because the serial is the better name. + */ +export function retireRokuIpDuplicate(deviceId: string, descriptor: Record): string | null { + if (!/^roku-/.test(deviceId) || deviceId.startsWith("roku-ip-")) return null; + const ip = descriptor.ip; + if (typeof ip !== "string" || !/^\d{1,3}(\.\d{1,3}){3}$/.test(ip)) return null; + const dup = rokuIpId(ip); + const held = + db.prepare("SELECT 1 FROM device_locks WHERE device_id = ?").get(dup) ?? + db.prepare("SELECT 1 FROM jobs WHERE status = 'claimed' AND claimed_by = ?").get(dup); + if (held) return null; + return db.prepare("DELETE FROM devices WHERE device_id = ?").run(dup).changes > 0 ? dup : null; +} diff --git a/collector/src/result-reason.test.ts b/collector/src/result-reason.test.ts new file mode 100644 index 0000000..a9175e0 --- /dev/null +++ b/collector/src/result-reason.test.ts @@ -0,0 +1,95 @@ +/** + * Every failure says why: the JUnit report's failing step, a subprocess's exit + * code and last line, and a host row that would otherwise say only `ok: false`. + * + * The report below is the one `nightly-fleet-ui-smoke-202610150230` uploaded + * on 2026-10-15 for the Galaxy S8+ (988a1b3541354f565a), byte for byte apart + * from the path. The job posted `failed: 1` and no error while this sat in + * the store. + */ +import { junitFailureReason, parseJunit } from "./junit.js"; +import { execFailureReason, lastLine, withFailureReasons } from "./result-reason.js"; + +type Check = (name: string, cond: boolean, detail?: string) => void; + +const MAESTRO_REPORT = ` + + + + Assertion is false: "Fleet Runner" is visible + + + +`; + +export async function runReasonChecks(check: Check) { + // --- JUnit --------------------------------------------------------------- + const s = parseJunit(MAESTRO_REPORT); + check("junit: Maestro's counts are read", s.passed === 0 && s.failed === 1, JSON.stringify(s)); + check("junit: and so is the failing flow and step", + s.failures[0]?.name === "smoke" && s.failures[0]?.message === 'Assertion is false: "Fleet Runner" is visible', JSON.stringify(s.failures)); + check("junit: one line for the result's error", + junitFailureReason(s) === 'smoke: Assertion is false: "Fleet Runner" is visible', String(junitFailureReason(s))); + + const two = parseJunit(` + + + + `); + check("junit: a self-closing failure's message attribute is read", two.failures[0]?.message === "Element not found: Sign in", JSON.stringify(two.failures)); + check("junit: CDATA is unwrapped", two.failures[1]?.message.startsWith("Expected 3 rows"), JSON.stringify(two.failures[1])); + check("junit: more than one failure says how many more", + junitFailureReason(two) === "login: Element not found: Sign in (and 1 more failing)", String(junitFailureReason(two))); + check("junit: a passing report has no reason", junitFailureReason(parseJunit('')) === null); + const garbage = parseJunit("not xml at all"); + check("junit: a report with no counts is one failure, not a pass", garbage.failed === 1 && garbage.passed === 0); + check("junit: and says the report named no step", /names no failing step/.test(junitFailureReason(garbage) ?? "")); + check("junit: errors count as failures", + parseJunit('').failed === 1); + + // --- a subprocess that failed ------------------------------------------------ + const err = Object.assign(new Error("Command failed: maestro --device X test -e GREENFOLIO_TEST_PASSWORD=hunter2 flows\nboom"), { + cmd: "/opt/maestro/bin/maestro --device X test -e GREENFOLIO_TEST_PASSWORD=hunter2 flows", + code: 1, + stderr: "Running flow smoke\nError: device X is offline (hunter2)\n", + stdout: "", + }); + const r = execFailureReason(err, ["hunter2"]); + check("exec: the program, its exit code and its last stderr line", r === "maestro exited 1: Error: device X is offline ([redacted])", r); + check("exec: never the command line, which carries the password", !r.includes("PASSWORD") && !r.includes("hunter2"), r); + check("exec: a program that could not start says so", + execFailureReason(Object.assign(new Error("spawn maestro ENOENT"), { cmd: "maestro test", code: "ENOENT" })) === "maestro could not run (ENOENT): spawn maestro ENOENT"); + check("exec: a killed one says so", + /^xcodebuild was killed \(SIGTERM\)/.test(execFailureReason({ cmd: "xcodebuild test", killed: true, signal: "SIGTERM", stderr: "" }))); + check("exec: silence is said, not left blank", + execFailureReason({ cmd: "adb shell true", code: 255, stderr: "", stdout: "" }) === "adb exited 255 and printed nothing"); + check("lastLine skips trailing blank lines", lastLine("a\nb\n\n \n") === "b"); + + // --- no ok:false row goes out without a reason ------------------------------- + const posted: Record[] = []; + const post = withFailureReasons(async (row: Record) => { posted.push(row); }); + await post({ job_id: "j1", device_id: "988a1b35", iter: 0, ok: false, test: { passed: 0, failed: 1 }, error: 'smoke: Assertion is false: "Fleet Runner" is visible' }); + await post({ job_id: "j1", device_id: "host:fleet-host", iter: 0, final: true, ok: false }); + check("reasons: a failing host row with no error gets the failing device's", + posted[1]?.error === '988a1b35: smoke: Assertion is false: "Fleet Runner" is visible', JSON.stringify(posted[1])); + + await post({ job_id: "j2", device_id: "a", iter: 0, ok: true }); + await post({ job_id: "j2", device_id: "b", iter: 0, ok: false, test: { passed: 1, failed: 2 } }); + await post({ job_id: "j2", device_id: "c", iter: 0, ok: false, error: "install failed: INSTALL_FAILED_OLDER_SDK" }); + await post({ job_id: "j2", device_id: "host:mac", iter: 0, final: true, ok: false }); + check("reasons: a device row with only counts says what the counts say", + posted[3]?.error === "2 of 3 tests failed; the runner reported no failing step", JSON.stringify(posted[3])); + check("reasons: several failing devices are counted and named", + posted[5]?.error === "2 of 3 devices failed -- b: 2 of 3 tests failed; the runner reported no failing step; c: install failed: INSTALL_FAILED_OLDER_SDK", + String(posted[5]?.error)); + + await post({ job_id: "j3", device_id: "host:mac", iter: 0, final: true, ok: false, error: "executor mac has no browsers" }); + check("reasons: a row that already says why is left alone", posted[6]?.error === "executor mac has no browsers"); + await post({ job_id: "j4", device_id: "host:mac", iter: 0, final: true, ok: true }); + check("reasons: a pass is left alone", posted[7]?.error === undefined); + await post({ job_id: "j5", device_id: "host:mac", iter: 0, final: true, ok: false }); + check("reasons: a failure with nothing behind it still says so", posted[8]?.error === "failed; the workload reported no reason"); + await post({ job_id: "j1", device_id: "host:fleet-host", iter: 0, final: true, ok: false }); + check("reasons: a job's devices are forgotten once its final row is out", posted[9]?.error === "failed; the workload reported no reason"); +} diff --git a/collector/src/result-reason.ts b/collector/src/result-reason.ts new file mode 100644 index 0000000..17024f4 --- /dev/null +++ b/collector/src/result-reason.ts @@ -0,0 +1,119 @@ +/** + * Every failure says why. + * + * `nightly-fleet-ui-smoke` failed on the Galaxy S8+ every night from 10-10 with + * `test: {passed: 0, failed: 1}`, no `error`, and a host row that said only + * `ok: false`. The reason was sitting in the JUnit report it had uploaded -- + * `Assertion is false: "Fleet Runner" is visible` -- and nothing put it where a + * person or an agent reads. A failure with no reason costs whoever reads it a + * trip to a log on another machine, which is a trip nobody takes at 07:00. + * + * Two pieces. `execFailureReason` turns a failed subprocess into one line (the + * program, its exit code, the last line it printed to stderr). The tracker + * wraps the executor's `postResult` so that no host row can say `ok: false` + * with nothing beside it: a device row gets its test counts, and the final + * host row gets the failing devices' reasons, which is what the job list and + * the `job-failed` alert show. + * + * Pure apart from the closure's memory, so it is testable without a collector. + */ + +const ONE_LINE = 300; +const FINAL_MAX = 500; + +const clip = (s: string, n: number) => (s.length > n ? `${s.slice(0, n - 3)}...` : s); +const firstLine = (s: string) => s.split("\n").map((l) => l.trim()).find(Boolean) ?? ""; + +/** The last non-empty line of some output, trimmed. */ +export function lastLine(text: unknown): string { + if (typeof text !== "string" && !Buffer.isBuffer(text)) return ""; + const lines = String(text).split(/\r?\n/).map((l) => l.trim()).filter(Boolean); + return lines.at(-1) ?? ""; +} + +/** + * One line for a subprocess that failed, from what `execFile` rejects with. + * + * Built from the exit code and the output, never from `err.message`: Node puts + * the whole command line in the message, and a Maestro run carries the test + * account's password as `-e PASSWORD=...` on that line. `secrets` are scrubbed + * from what is used anyway, because a tool can echo its arguments. + */ +export function execFailureReason(err: unknown, secrets: string[] = []): string { + const e = (err ?? {}) as { + cmd?: unknown; code?: unknown; signal?: unknown; killed?: unknown; stderr?: unknown; stdout?: unknown; message?: unknown; + }; + const program = typeof e.cmd === "string" ? (e.cmd.trim().split(/\s+/)[0] ?? "").split("/").pop() || "the command" : "the command"; + let how: string; + if (e.killed === true || typeof e.signal === "string") how = `was killed${typeof e.signal === "string" ? ` (${e.signal})` : ""}`; + else if (typeof e.code === "number") how = `exited ${e.code}`; + else if (typeof e.code === "string") how = `could not run (${e.code})`; + else how = "failed"; + let said = lastLine(e.stderr) || lastLine(e.stdout); + // Not the message's first line, which is "Command failed: ". + if (!said && typeof e.message === "string" && !e.message.startsWith("Command failed")) said = firstLine(e.message); + for (const s of secrets) if (s) said = said.split(s).join("[redacted]"); + return clip(said ? `${program} ${how}: ${said}` : `${program} ${how} and printed nothing`, ONE_LINE); +} + +type Row = Record & { job_id?: unknown; device_id?: unknown; ok?: unknown; error?: unknown; final?: unknown }; + +const hasReason = (e: unknown) => typeof e === "string" && e.trim() !== ""; + +/** What a device row that failed with no error can still honestly say. */ +function deviceReason(row: Row): string { + const t = (row.test ?? null) as { passed?: unknown; failed?: unknown } | null; + const failed = typeof t?.failed === "number" ? t.failed : null; + const passed = typeof t?.passed === "number" ? t.passed : null; + if (failed !== null && failed > 0) { + const total = failed + (passed ?? 0); + return `${failed} of ${total} test${total === 1 ? "" : "s"} failed; the runner reported no failing step`; + } + return "failed; the workload reported no reason"; +} + +/** + * Wrap a `postResult` so that no row it posts says `ok: false` with an empty + * `error`. + * + * Device rows are remembered per job until the job's final row goes out. A + * final row that failed with no error of its own gets one built from them: + * `988a1b35...: smoke: Assertion is false: ...`, or `2 of 3 devices failed -- + * a: ...; b: ...`. A row that already says why is never rewritten. + */ +export function withFailureReasons(post: (row: Record) => Promise) { + const seen = new Map>(); + return async (row: Record): Promise => { + const r = row as Row; + const jobId = typeof r.job_id === "string" ? r.job_id : null; + const deviceId = typeof r.device_id === "string" ? r.device_id : ""; + let out: Record = row; + + if (r.final !== true) { + if (r.ok === false && !hasReason(r.error)) out = { ...row, error: deviceReason(r) }; + if (jobId && !deviceId.startsWith("host:")) { + const devices = seen.get(jobId) ?? new Map(); + devices.set(deviceId, { ok: out.ok !== false, error: hasReason(out.error) ? String(out.error) : null }); + seen.set(jobId, devices); + } + return post(out); + } + + const devices = jobId ? seen.get(jobId) : undefined; + if (jobId) seen.delete(jobId); + if (r.ok === false && !hasReason(r.error)) { + const failing = [...(devices ?? new Map()).entries()].filter(([, d]) => !d.ok); + const total = devices?.size ?? 0; + let error: string; + if (failing.length === 0) error = "failed; the workload reported no reason"; + else { + const parts = failing.map(([id, d]) => `${id}: ${firstLine(d.error ?? "no reason given")}`); + error = failing.length === 1 && total <= 1 + ? parts[0] + : `${failing.length} of ${total} devices failed -- ${parts.join("; ")}`; + } + out = { ...row, error: clip(error, FINAL_MAX) }; + } + return post(out); + }; +} diff --git a/collector/src/server.ts b/collector/src/server.ts index 8831165..435af46 100644 --- a/collector/src/server.ts +++ b/collector/src/server.ts @@ -40,6 +40,8 @@ import { admit, isTailnetAddress, normaliseIp, whois } from "./tailnet.js"; // from this file, so there is no cycle. import { firstArtifactSha, settleWaiters, type DepSettlement } from "./api/mutations.js"; import { announce } from "./announce.js"; +import { closingStatus, type Closing } from "./skip.js"; +import { forgetStaleSimulators, retireRokuIpDuplicate } from "./registry-hygiene.js"; import { enqueueJob, matchingDevices, resolveLatestBuild, type JobSpec } from "./queue.js"; import { authWarnings, provenanceOf, registerAuth } from "./auth.js"; import { registerDeprecations } from "./api/v1/deprecations.js"; @@ -460,6 +462,13 @@ const sweepLeasesTx = db.transaction((): { requeued: SweptJob[]; failed: SweptJo function sweepLeases() { const swept = sweepLeasesTx(); + // Registry hygiene rides on the same timer: simulators offline past + // FLEET_SIMULATOR_TTL_DAYS are forgotten. See registry-hygiene.ts. + const forgotten = forgetStaleSimulators(); + for (const id of forgotten) { + app.log.info({ device_id: id }, "simulator offline past its TTL; forgotten"); + announce({ type: "device", device_id: id, event: "forget", reason: "simulator offline past FLEET_SIMULATOR_TTL_DAYS" }); + } for (const j of swept.requeued) { app.log.warn({ job_id: j.job_id, claimed_by: j.claimed_by, attempt: j.attempts }, "lease expired; requeued"); announce({ type: "job", job_id: j.job_id, status: "queued", reason: "lease expired", attempts: j.attempts }); @@ -468,7 +477,7 @@ function sweepLeases() { app.log.error({ job_id: j.job_id, claimed_by: j.claimed_by, attempts: j.attempts }, "lease expired; job failed"); announce({ type: "job", job_id: j.job_id, status: "failed", reason: "lease expired", attempts: j.attempts }); } - return swept; + return { ...swept, forgotten }; } // --- devices --- @@ -537,6 +546,12 @@ app.post("/devices/register", async (req, reply) => { type: "device", device_id: b.device_id, event: "register", pools: b.pools ?? [], capabilities: b.capabilities ?? null, }); + // The same Roku, seen earlier by address only: one row is the truth. + const retired = retireRokuIpDuplicate(b.device_id, (b.descriptor ?? {}) as Record); + if (retired) { + app.log.info({ device_id: retired, now: b.device_id }, "retired a Roku's IP-named duplicate"); + announce({ type: "device", device_id: retired, event: "forget", reason: `same Roku as ${b.device_id}` }); + } return { ok: true }; }); @@ -673,6 +688,7 @@ app.post("/jobs/sweep", async () => { ok: true, requeued: swept.requeued.map((j) => j.job_id), failed: swept.failed.map((j) => j.job_id), + forgotten: swept.forgotten, }; }); @@ -689,11 +705,15 @@ app.get("/jobs/:id", async (req, reply) => { * A crash between the two would leave a chain permanently stalled on a * dependency that is already finished, which nothing on the collector would * ever come back and fix. */ -const closeJobTx = db.transaction((jobId: string, status: "done" | "failed"): DepSettlement => { +const closeJobTx = db.transaction((jobId: string, status: Closing["status"], reason: string | null): DepSettlement => { // Dropping the deadline takes the job out of the sweep's reach for good. + // The reason replaces last_error only when there is one: a skip always has + // one, a failure usually does, and a pass has nothing to say. db.prepare( - "UPDATE jobs SET status = ?, finished_at = datetime('now'), lease_deadline = NULL WHERE job_id = ?", - ).run(status, jobId); + `UPDATE jobs SET status = ?, finished_at = datetime('now'), lease_deadline = NULL, + last_error = COALESCE(?, last_error) + WHERE job_id = ?`, + ).run(status, reason, jobId); db.prepare("DELETE FROM device_locks WHERE job_id = ?").run(jobId); return settleWaiters(jobId); }); @@ -815,8 +835,16 @@ app.post("/results", async (req, reply) => { app.log.warn({ job_id: b.job_id }, "preempted result for a job that is no longer claimed"); } - const status = b.ok === false ? "failed" : "done"; - const settled = closeJobTx(b.job_id, status); + // Failed, done or skipped, judged over every row the job posted: a host + // job's final row is the executor's verdict, and its devices may all have + // said `skipped:` underneath a plain `ok: true`. + const rows = (db + .prepare("SELECT device_id, payload FROM results WHERE job_id = ? ORDER BY iter, rowid") + .all(b.job_id) as { device_id: string; payload: string }[]) + .map((r) => ({ device_id: r.device_id, payload: JSON.parse(r.payload) as Record })); + const closing = closingStatus(rows, b as Record); + const status = closing.status; + const settled = closeJobTx(b.job_id, status, closing.reason); // A finished job has nothing left to show. Outside the transaction, because // closing viewer sockets must not be able to roll back a device's result. endMirror(b.job_id); @@ -827,14 +855,18 @@ app.post("/results", async (req, reply) => { announce({ type: "job", job_id: jobId, status: "queued", reason: `dependency ${b.job_id} finished` }); for (const f of settled.failed) announce({ type: "job", job_id: f.job_id, status: "failed", reason: f.reason }); + for (const s of settled.skipped) + announce({ type: "job", job_id: s.job_id, status: "skipped", reason: s.reason }); - // A skip -- nothing attached, a host under pressure -- is ok for the queue - // and says nothing about the code, so it must not become a green check. - const skipped = b.ok === true && typeof b.error === "string" && b.error.startsWith("skipped:"); - reportStatus(b.job_id, status === "failed" ? "failure" : "success", skipped).catch((e) => + // A skip -- nothing attached, a host under pressure -- says nothing about + // the code, so it must not become a green check. + reportStatus(b.job_id, status === "failed" ? "failure" : "success", status === "skipped").catch((e) => app.log.error(e, "status report failed"), ); - return { ok: true, status, promoted: settled.promoted, failed: settled.failed.map((f) => f.job_id) }; + return { + ok: true, status, promoted: settled.promoted, failed: settled.failed.map((f) => f.job_id), + skipped: settled.skipped.map((s) => s.job_id), + }; } return { ok: true }; }); diff --git a/collector/src/skip.test.ts b/collector/src/skip.test.ts new file mode 100644 index 0000000..6ca5cb5 --- /dev/null +++ b/collector/src/skip.test.ts @@ -0,0 +1,69 @@ +/** + * How a job closes: done, failed or skipped. + * + * The shapes below are the ones the live brain held for two weeks as `done`: + * the tvloop nightly's single host row saying `skipped: no Roku developer + * password on this host`, and explore's `skipped: no device matches this job`. + * Plus the one the summary always knew was a skip and the queue did not -- a + * ui-test whose every device said `skipped:` under a plain `ok: true` host row. + */ +import { closingStatus, isSkipError, skipReasonText, type ResultRow } from "./skip.js"; + +type Check = (name: string, cond: boolean, detail?: string) => void; + +const row = (device_id: string, payload: Record): ResultRow => ({ device_id, payload }); + +export function runSkipChecks(check: Check) { + check("a skip error is recognised by its prefix", isSkipError("skipped: locked") && !isSkipError("failed: skipped:") && !isSkipError(null)); + + // The tvloop nightly: one host row, ok, skipped. + const tv = row("host:fleet-host", { final: true, ok: true, error: "skipped: no Roku developer password on this host" }); + const c1 = closingStatus([tv], tv.payload); + check("a final row that says skipped closes the job as skipped", + c1.status === "skipped" && c1.reason === "skipped: no Roku developer password on this host", JSON.stringify(c1)); + + // Every device skipped, the host row says nothing. + const devs = [ + row("phone-a", { ok: true, error: "skipped: com.example not installed" }), + row("phone-b", { ok: true, error: "skipped: com.example not installed" }), + ]; + const host = row("host:mac", { final: true, ok: true }); + const c2 = closingStatus([...devs, host], host.payload); + check("every device skipping under a plain ok host row is a skip", c2.status === "skipped", JSON.stringify(c2)); + check("and the shared reason is named once", c2.reason === "skipped: com.example not installed", String(c2.reason)); + + const mixedReasons = [row("a", { ok: true, error: "skipped: locked" }), row("b", { ok: true, error: "skipped: not installed" })]; + const c3 = closingStatus([...mixedReasons, host], host.payload); + check("different reasons are counted, not concatenated", c3.status === "skipped" && /and 1 other reason/.test(c3.reason ?? ""), String(c3.reason)); + + // One device ran. + const ran = [row("a", { ok: true, error: "skipped: locked" }), row("b", { ok: true, test: { passed: 3, failed: 0 } })]; + check("one device that ran makes it done", closingStatus([...ran, host], host.payload).status === "done"); + + // A plain pass. + const pass = row("phone", { final: true, ok: true, metrics: { decode_tok_s: 12 } }); + check("a plain pass is done", closingStatus([pass], pass.payload).status === "done"); + + // Failures: the final row wins, and says why from wherever it can. + const failDev = row("988a1b35", { ok: false, test: { passed: 0, failed: 1 }, error: 'smoke: Assertion is false: "Fleet Runner" is visible' }); + const failHost = row("host:fleet-host", { final: true, ok: false }); + const c4 = closingStatus([failDev, failHost], failHost.payload); + check("a failing final row is a failure", c4.status === "failed"); + check("whose reason comes from the failing device when the host row has none", + c4.reason === '988a1b35: smoke: Assertion is false: "Fleet Runner" is visible', String(c4.reason)); + const own = row("host:x", { final: true, ok: false, error: "workload 'x' not supported by this executor yet" }); + check("a failing row's own error is kept", closingStatus([own], own.payload).reason === "workload 'x' not supported by this executor yet"); + const bare = row("phone", { final: true, ok: false }); + check("a failure with nothing to say has a null reason, not an invented one", closingStatus([bare], bare.payload).reason === null); + // ok:false with a skipped: error is a failure: ok is the verdict. + const odd = row("phone", { final: true, ok: false, error: "skipped: but the runner said ok false" }); + check("ok:false is a failure even when the text says skipped", closingStatus([odd], odd.payload).status === "failed"); + + // A device's progress rows do not outvote its final row. + const progress = [row("p", { iter: 1, ok: true }), row("p", { iter: 0, final: true, ok: true, error: "skipped: charging" })]; + check("a device's final row beats its progress rows", closingStatus(progress, progress[1].payload).status === "skipped"); + + check("the prefix comes off for a sentence that already says skipped", + skipReasonText("skipped: no Roku developer password on this host") === "no Roku developer password on this host" && + skipReasonText(null) === "no reason given" && skipReasonText("dependency b skipped") === "dependency b skipped"); +} diff --git a/collector/src/skip.ts b/collector/src/skip.ts new file mode 100644 index 0000000..70820cb --- /dev/null +++ b/collector/src/skip.ts @@ -0,0 +1,82 @@ +/** + * What a skip is, decided in one place. + * + * A runner that could not run a job says so with a result row whose `ok` is + * true and whose `error` begins `skipped:` -- the app is not installed, the + * device was locked, nothing attached matched, the host was under pressure, no + * Roku password. `ok: true` because nothing went wrong with the code; the + * prefix because nothing was tested either. + * + * For a long time that row closed the job as `done`, and the job list, the + * status counts and the morning digest all counted it as a pass. Two nightlies + * "passed" in two seconds every night for two weeks while testing nothing. Only + * the v1 summary and `fleetr`'s exit 4 read the prefix. Now the queue reads it + * too, when the job closes, and the job's status says `skipped`. + * + * Pure: no database, so `db.ts` can run it in the startup backfill without an + * import cycle, and a test can feed it rows directly. + */ + +export const SKIP_PREFIX = "skipped:"; + +/** True for an error string that says nothing ran. */ +export function isSkipError(error: unknown): error is string { + return typeof error === "string" && error.startsWith(SKIP_PREFIX); +} + +export type ResultRow = { device_id: string; payload: Record }; + +export type Closing = + | { status: "failed"; reason: string | null } + | { status: "done"; reason: null } + | { status: "skipped"; reason: string }; + +const clip = (s: string, n = 500) => (s.length > n ? `${s.slice(0, n - 3)}...` : s); + +/** + * How a job closes, from every result row it posted (in `iter, rowid` order) + * and the final row that closes it. + * + * - The final row says `ok: false`: **failed**. Its error, or the first failing + * device's, is the reason. + * - The final row's own error begins `skipped:`: **skipped**. + * - Otherwise the per-device verdicts decide, read the way the v1 summary reads + * them: the newest row per device, with the host executor's `host:` + * row standing in only when no device reported. Every one of those skipped + * and none failed: **skipped** -- a ui-test whose every phone lacked the app + * posts a plain `ok: true` host row over device rows that all say why. + * - Anything else: **done**. + * + * The same rule as `summarize()` in `api/v1/routes.ts`, so a job's status and + * its summary verdict cannot disagree about whether anything ran. + */ +export function closingStatus(rows: ResultRow[], final: Record): Closing { + const byDevice = new Map>(); + for (const r of rows) { + const prev = byDevice.get(r.device_id); + if (!prev || !prev.final || r.payload.final) byDevice.set(r.device_id, r.payload); + } + let entries = [...byDevice]; + if (entries.some(([d]) => !d.startsWith("host:"))) entries = entries.filter(([d]) => !d.startsWith("host:")); + + if (final.ok === false) { + const own = typeof final.error === "string" && final.error.trim() ? final.error : null; + const failing = entries.find(([, p]) => p.ok === false && typeof p.error === "string" && p.error.trim()); + const reason = own ?? (failing ? `${failing[0]}: ${String(failing[1].error)}` : null); + return { status: "failed", reason: reason ? clip(reason) : null }; + } + if (isSkipError(final.error)) return { status: "skipped", reason: clip(final.error) }; + + if (entries.length > 0 && entries.every(([, p]) => p.ok !== false && isSkipError(p.error))) { + const reasons = [...new Set(entries.map(([, p]) => String(p.error)))]; + const reason = reasons.length === 1 ? reasons[0] : `${reasons[0]} (and ${reasons.length - 1} other reason${reasons.length === 2 ? "" : "s"})`; + return { status: "skipped", reason: clip(reason) }; + } + return { status: "done", reason: null }; +} + +/** The reason without its `skipped: ` prefix, for a sentence that already says "skipped". */ +export function skipReasonText(reason: string | null | undefined): string { + if (!reason) return "no reason given"; + return reason.startsWith(SKIP_PREFIX) ? reason.slice(SKIP_PREFIX.length).trim() || "no reason given" : reason; +} diff --git a/collector/src/web/digest.ts b/collector/src/web/digest.ts index 95c6934..83c8842 100644 --- a/collector/src/web/digest.ts +++ b/collector/src/web/digest.ts @@ -115,7 +115,9 @@ async function runShelfBatch( await postBeacon(digestJob.job_id, "web:digest", {}).catch(() => {}); const j = await apiJson<{ status: string; last_error?: string | null }>(`/jobs/${encodeURIComponent(jobId)}`); if (j.status === "done") break; - if (j.status === "failed" || j.status === "cancelled") { + // A skipped batch ran nothing and has no outputs to read; say that, rather + // than "finished without an outputs artifact" one step later. + if (j.status === "failed" || j.status === "cancelled" || j.status === "skipped") { throw new Error(`${label} batch ${jobId} ${j.status}: ${j.last_error ?? "no detail"}`); } } diff --git a/docs/api.md b/docs/api.md index 38bf3db..93f56a8 100644 --- a/docs/api.md +++ b/docs/api.md @@ -20,7 +20,7 @@ disagree: the test suite fails if they do. | `GET /api/v1/devices` · `/devices/{id}` | read | The shelf, with status (`online`, `stale`, `offline`) and current job | | `GET /api/v1/workloads` · `/workloads/{name}` | read | What the fleet can run: executor, params schema, a valid example spec, how many live agents can take it | | `GET /api/v1/templates` | read | Saved job templates | -| `GET /api/v1/jobs` | read | Jobs; filter by `status`, `workload`, `executor` (`device` or `host`), `device`, `pool`, `source`, `requested_by`, `mine=true`, `q` (substring of the job id), `from`/`to` | +| `GET /api/v1/jobs` | read | Jobs; filter by `status` (`waiting`, `queued`, `claimed`, `done`, `failed`, `cancelled`, `skipped`), `workload`, `executor` (`device` or `host`), `device`, `pool`, `source`, `requested_by`, `mine=true`, `q` (substring of the job id), `from`/`to` | | `POST /api/v1/jobs` | run | Enqueue. 201 with the job id, its status, and links to its summary and wait URLs. 422 `no_capable_agent` when no live agent declares the workload (or backend); 400 `no_matching_devices` for a fan-out that matches nothing, and 400 `no_build` when `latest` names no published build | | `POST /api/v1/jobs/validate` | run | Dry run: schema errors by path, the devices it would land on, warnings. Always 200 | | `GET /api/v1/jobs/{id}` | read | One job, with its spec | @@ -53,6 +53,13 @@ its manifest. This is `/api/v1/jobs` (and so `fleetr run`) only: the legacy ran, never folded into passed), `cancelled`, and while unfinished `queued`, `waiting` or `running`. +**Job statuses** are `waiting`, `queued`, `claimed`, `done`, `failed`, +`cancelled` and `skipped`. `skipped` means the job was claimed and nothing ran +(its runner said `skipped:`, or a dependency skipped); `last_error` says why. +A skipped job's summary verdict is `skipped`, as it always was; before 0.9 its +status said `done`. A fan-out family's `status` is `skipped` when no child ran. +See [Skipped is not done](concepts.md#skipped-is-not-done). + **Who asked.** Every job records `requested_by` and `source` (`cli`, `mcp`, `ci`, `dash`, `schedule`, `api`). With auth off both are what the caller said, labelled unverified; with tokens on, `requested_by` is the token's name, or the person a @@ -101,9 +108,9 @@ anything else `admin`. With auth off, all of it is open. | Method & path | Purpose | |---|---| -| `POST /jobs` | Enqueue. 409 on duplicate `job_id`; the reply's `status` says whether it queued or is `waiting` on `depends_on` | +| `POST /jobs` | Enqueue. 409 on duplicate `job_id`; the reply's `status` says whether it queued, is `waiting` on `depends_on`, or was closed on arrival as `failed` or `skipped` because a dependency already was | | `GET /jobs/:id` | Status, including `attempts`, `lease_deadline` and `last_error` | -| `POST /jobs/sweep` | Force a lease sweep now; returns what was requeued and failed | +| `POST /jobs/sweep` | Force a lease sweep now; returns what was requeued and failed, and the simulator rows it forgot (offline past `FLEET_SIMULATOR_TTL_DAYS`, default 7) | | `POST /jobs/:id/release` | The claimant hands a job back before starting it. Returns it to `queued` and **refunds the attempt**; 409 once any result exists. See [the protocol](protocol.md#handing-a-job-straight-back) | | `POST /locks/acquire` · `POST /locks/release` | Host-executor device locks for `targets.exclusive`; device claims lock implicitly | | `POST /events/:topic` | Publish a pipeline event; returns its id | @@ -127,7 +134,7 @@ Every endpoint is `GET` and side-effect free. | `GET /api/devices` | Registry with derived `online`/`stale`/`offline`, current job, lock, flattened beacon | | `GET /api/devices/:id` | Descriptor, job history, latest benchmarks, counts | | `GET /api/devices/:id/beacons?hours=24` | Beacon history for the battery and thermal charts | -| `GET /api/jobs` | Filters, paging, sorting; returns status facets | +| `GET /api/jobs` | Filters (`status` takes `skipped` too), paging, sorting; returns status facets, `skipped` among them | | `GET /api/jobs/:id` | Spec, results, beacons, artifacts, locks, fan-out family, status report | | `GET /api/results` | Filters: `job`, `device`, `workload`, `final`, `ok`, `from`, `to` | | `GET /api/results/bench` | Latest passing run per device per configuration, with history for trends | @@ -138,6 +145,7 @@ Every endpoint is `GET` and side-effect free. | `GET /api/evals` · `GET /api/evals/:input_sha` | Eval sets pivoted by model and device | | `GET /api/schedules` | Schedules with computed `next_run` and missed-fire detection | | `GET /api/artifacts` | Store listing with on-disk state and reference counts | +| `GET /api/artifacts/:sha256` | A 308 to `/api/v1/artifacts/:sha256/content`, the bytes; 404 when nothing by that hash was ever uploaded. Before 0.9 this answered "no such endpoint", which read as a missing artifact | | `GET /api/visual/baselines` · `/suites` · `/matrix?suite=` | Accepted baselines and the review grid | | `GET /api/locks` | Held locks and how long they have been held | | `GET /api/executors` | Host-executor liveness, derived from their long-poll traffic | @@ -234,7 +242,8 @@ already handle. Work in flight finishes; nothing new starts. A cancelled job is deliberately **not** `failed`. The overview's failure counts and every alert built on them would otherwise count deliberate stops as -breakage. +breakage. A skipped one is not `done` either, for the mirror-image reason: the +overview counts it on its own (`queue.skipped_24h`). ### Pool edits go to a different column diff --git a/docs/brand.md b/docs/brand.md index 9b8e7dd..f36116f 100644 --- a/docs/brand.md +++ b/docs/brand.md @@ -70,7 +70,7 @@ dependency, so nothing new is installed. | `img/banner.png` | 2560×1280 | `figures/banner.html` | | `img/social-preview.png` | 2560×1280 (2× of GitHub's 1280×640) | `figures/social-preview.html` | | `img/architecture.png` | 2560×1280 | `figures/architecture.html` | -| `img/lifecycle.png` | 2560×1360 | `figures/lifecycle.html` | +| `img/lifecycle.png` | 2560×1464 | `figures/lifecycle.html` | | `img/protocol.png` | 2560×1120 | `figures/protocol.html` | | `img/workloads.png` | 2560×1200 | `figures/workloads.html` | | `img/platforms.png` | 2560×1400 | `figures/platforms.html` | diff --git a/docs/concepts.md b/docs/concepts.md index d2718ea..57164d6 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -4,7 +4,7 @@ How the queue thinks. Everything here is the collector's behaviour rather than any one runner's, and it is what you need before writing a job spec that does something more interesting than the one in [Get started](getting-started.md). -![The life of a job: waiting until its dependencies close, queued, claimed and running under a lease that beacons renew, then done — with a lapsed lease swept back to the queue, a preemption handing its attempt back, and ok: false or a last lapsed attempt ending in failed](img/lifecycle.png) +![The life of a job: waiting until its dependencies close, queued, claimed and running under a lease that beacons renew, then done — with a lapsed lease swept back to the queue, a preemption handing its attempt back, ok: false or a last lapsed attempt ending in failed, and a job that ran nothing closing as skipped](img/lifecycle.png) ## Two kinds of job @@ -220,6 +220,46 @@ Host jobs fan out too, and the executor's own target selection honours `targets.device_id`, so an `install` plus `ui-test` pair can cover the OS matrix with two job specs. +## Skipped is not done + +A runner that claims a job and cannot run it says so with a final row whose +`ok` is `true` and whose `error` begins `skipped:` — the app is not installed, +the device was locked by another job, nothing attached matched, the host was +under memory pressure, no Roku password. `ok: true` because nothing went wrong +with the code; the prefix because nothing was tested either. + +The job closes as **`skipped`**, a status of its own beside `done`, `failed` +and `cancelled`. Until 0.9 it closed as `done`, and the job list, the status +counts and the digest counted it as a pass: two nightlies passed in two seconds +a night for two weeks while testing nothing. + +How the queue decides, when the final row arrives: + +| The rows say | The job is | +|---|---| +| the final row has `ok: false` | `failed`, with `last_error` from that row or, if it has none, from the first failing device (`988a1b35…: smoke: Assertion is false: …`) | +| the final row's own `error` begins `skipped:` | `skipped` | +| every device row skipped and none failed, under a plain `ok: true` host row (a ui-test where no phone had the app) | `skipped` | +| anything else, including one device that ran while others skipped | `done` | + +A skipped job's `last_error` is the reason, so the job list, the +[`schedule-skipping` alert](deploy/alerts.md#a-schedule-that-keeps-skipping) +and the [morning digest](explore/findings.md#the-morning-digest) all read it +from one place. The result rows are stored exactly as the runner posted them. + +- **A fan-out family** is `skipped` when no child ran: every child skipped, or + skipped and cancelled. One child that ran makes the family `done`, and one + that failed makes it `failed`, as before. +- **The v1 summary's verdict** was already `skipped` for these jobs and still + is, so `fleetr`'s exit 4 and the MCP tools' verdict are unchanged. What + changed is that the job's status now agrees with it. +- **A skip posts no commit status**, as before. A green check where no device + ran would be a lie. +- **Jobs that closed as `done` before 0.9** are re-labelled once, when a 0.9 + collector first opens the database: every `done` job with a `skipped:` result + is judged by the same rule as above. It runs inside the migration that adds + the status, so it costs one pass over the results table, once. + ## Job chains Build, then install what it built, then run the UI suite against it. That shape @@ -251,6 +291,14 @@ not work the fleet is failing to pick up. `last_error` naming it, and that cascades the whole way down. A broken build must not leave an install and a ui-test sitting in `waiting` until somebody notices next week. +- When a dependency **[skipped](#skipped-is-not-done)**, the waiter skips too, + with `last_error` `dependency skipped`, and that cascades the same way. + A skipped build produced no artifact and no metric, so there is nothing for + the install to install; failing it would blame the code for a phone that was + on a charger somewhere else, and running it would test whatever was already + installed. If one dependency failed and another skipped, the failure wins. A + job enqueued behind a dependency that has already skipped is skipped on + arrival, and a dry run warns first. - A dependency that does not exist, and a cycle, are refused at enqueue with a 400. A chain naming a job nobody ever posted would otherwise sit in `waiting` forever, looking exactly like a chain whose build is merely slow. diff --git a/docs/dashboard.md b/docs/dashboard.md index eeb6c64..9a7ab3b 100644 --- a/docs/dashboard.md +++ b/docs/dashboard.md @@ -43,8 +43,13 @@ artifacts. drawings, from phones and tablets through Roku boxes and sticks, an Apple TV, laptops, watches and a headset to a board and a browser. The drawing is chosen from the model string first, because agents that predate the `platform` field -are reported as `ios` or `android`, so a Roku arrives as `android` and an -Apple TV or Apple Watch as `ios`. +are reported as `ios` or `android`: an Apple TV or Apple Watch arrives as +`ios`, and a Roku registered by an executor older than 0.9 as `android`. + +**A skipped job has a grey chip**, neither green nor red: it was claimed and +nothing ran. The Jobs status filter has a `skipped` option with its count, and +the Overview's queue panel shows **skipped 24h** beside done and failed rather +than inside done. See [Skipped is not done](concepts.md#skipped-is-not-done). **Filters live in the URL**, so a filtered view is a link you can send. Jobs can be composed, enqueued, cancelled, retried and reprioritised; devices can be diff --git a/docs/deploy/alerts.md b/docs/deploy/alerts.md index 0119178..c73857a 100644 --- a/docs/deploy/alerts.md +++ b/docs/deploy/alerts.md @@ -21,6 +21,7 @@ notifications — and nothing is notified twice, ever. | `cold-start-regressed` | Launch time rose past the same threshold against its own median | | `batch-regressed` | Top-1 accuracy fell past the same threshold | | `schedule-missed` | An enabled schedule that has run before missed its firing by `FLEET_ALERT_SCHEDULE_LATE_S` (default 5 min) | +| `schedule-skipping` | An enabled schedule's last `FLEET_ALERT_SKIP_STREAK` (default 3) runs all [skipped](../concepts.md#skipped-is-not-done) | | `db-size` / `log-size` | Past `FLEET_ALERT_DB_BYTES` (default 2 GiB) / `FLEET_ALERT_LOG_BYTES` (200 MiB) | Every threshold is read once, at collector start; a value that is not a @@ -35,6 +36,33 @@ Battery and thermal are only judged on devices **still checking in** — a readi from a silent device describes whenever it went silent, not now. And a device reporting `-1` has no battery telemetry rather than a flat battery. +## A schedule that keeps skipping + +A skipped job is no longer counted as a pass, but a grey chip every morning is +still easy to stop seeing. `nightly-tvloop-hardware` skipped every night for two +weeks on a missing Roku password and nothing said so. `schedule-skipping` is +one alert per schedule, worded from the reason the runs keep giving: + +```text +nightly-tvloop-hardware has skipped 3 runs in a row: no Roku developer password on this host +``` + +What counts as a run, and as a skip: + +- **A run is what the scheduler enqueued**: the job `-`, + or for a fan-out every child of it. The id is what identifies it, so jobs + from before provenance was recorded still count. +- **A run skipped when nothing in it ran**: every job in it is `skipped` (or + skipped and cancelled). One device that ran makes the run count as run. +- **A run still in flight is left out**: it neither breaks the streak nor + extends it. +- If the runs gave different reasons, the alert names the latest and says how + many different reasons there were. + +It resolves on the first run that is not a skip, pass or fail. Disabled +schedules are not watched. The streak length is `FLEET_ALERT_SKIP_STREAK`, +read at start like the others. + ## The regression rules compare against history, not a threshold The comparison key matters more than the threshold. Two runs are only comparable diff --git a/docs/deploy/index.md b/docs/deploy/index.md index 8760078..69c391f 100644 --- a/docs/deploy/index.md +++ b/docs/deploy/index.md @@ -135,6 +135,7 @@ port, bind list, tailnet allowlist, data and artifact directories and | `FLEET_PEERS` | none | Comma-separated base URLs of other collectors, for [more than one brain](#more-than-one-brain) | | `FLEET_POWER_CONFIG` | `power.json` | The pool-to-smart-plug map, see [Energy](#energy) | | `FLEET_SWEEP_MS` | 15000 | How often expired leases are swept | +| `FLEET_SIMULATOR_TTL_DAYS` | 7 | The same sweep forgets a simulator row (descriptor `kind` or `soc` is `simulator`) offline longer than this. Simulators are recreated under new UUIDs and never come back. Real devices and Android emulators are never forgotten; results and beacons stay either way | | `FLEET_SCHEDULER_TICK_MS` | 20000 | How often schedules are evaluated | | `FLEET_DASH_DIST` | `dash/dist` | The built dashboard. Missing, the collector serves a placeholder rather than failing | | `FLEET_LOG` | `info` | Log level | diff --git a/docs/explore/findings.md b/docs/explore/findings.md index 52dc2d7..9c826bd 100644 --- a/docs/explore/findings.md +++ b/docs/explore/findings.md @@ -63,6 +63,19 @@ through the same sender as alerts. Nothing is sent on a day with nothing new, and a restart does not send twice. Findings judged not a bug, agent's mistake or duplicate are left out. `FLEET_DASH_URL` sets the address used in its links. +Below the findings, one line says how the jobs that finished in the same window +ended — done, failed, and skipped on a count of its own — and names up to three +schedules that skipped, with the reason each gave: + +```text +Jobs, last 24h: 14 done, 1 failed, 4 skipped (nothing ran). +- skipped: explore-tv x3 (no device matches this job on ultra) +- skipped: nightly-tvloop-hardware (no Roku developer password on this host) +``` + +The send rule is unchanged: a day with no findings sends nothing, whatever the +jobs did. A schedule that keeps skipping has [its own alert](../deploy/alerts.md#a-schedule-that-keeps-skipping). + ## GitHub issues (off by default) Fleet Runner stays disconnected from the app repositories until that is decided diff --git a/docs/figures/lifecycle.html b/docs/figures/lifecycle.html index 5558bcb..307cf2c 100644 --- a/docs/figures/lifecycle.html +++ b/docs/figures/lifecycle.html @@ -10,9 +10,9 @@ Rendered by `npm run assets` in collector/ to docs/img/lifecycle.png. --> -
- +
+ beacon · renews the lease · answers preempt @@ -69,6 +69,8 @@ A dependency that fails, fails everything waiting on it, the whole way down the chain. Nothing is ever killed. Cancelling sets the row to cancelled, and the next beacon answers lease_renewed: false — work in flight finishes, nothing new starts. + A runner that ran nothing posts ok: true with an error beginning skipped:, and the job closes + skipped, not done. A job waiting on a skipped one skips too.
diff --git a/docs/img/lifecycle.png b/docs/img/lifecycle.png index 9d72156a7edb9630f19c54b822b5150a40b9b090..e520ece148e530f3fcfb137cab662b9e2f236c06 100644 GIT binary patch delta 29954 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

-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 e%V&ql#dGRK&PK~WY-i5?oZM68C;5+GzWX; zg)+uY1$UKpsiF^8X%I4Ca<)}NKr_@tSV3SM!dhvNa#36L3@}CKab` zDu3ku6Vs#hqZ0-}`bI{)+ClapikHQ!olsU*j?ZN((Tj%AQ+<#87&$&k_cp8M$x)KS zZUIPao3w7^2i?b+F86|-pnDg088Cei>%qP4>>zmV=P7?iZI#JOQg89faMRtiB_0b^ zGZ*4}N5jLV`c`)tjg_qrpDIsOT{H9xye+_EGK-B1yB_iRL2@HV?@x@BHS=)WoJ-41 zoR*f(Mcl>lRR?l6q_IHTDL-eiEe7QXl((iZ;w$GJ4$g!?Ela)GP%mxwWB#3SB=@b` zbDutadeS=X(4oQ}PDmhZhJdp-`PoM_9g}F^(XQW%kFA96EYNmTHz;l#<=A_Kja;E? z=6dGhs!tf~3|?-it{U1F>i(NVuBS!7Kqk8L{q)-qFM&~tIo*7LT2Jw~&B43`lrVeM zDzE2dE(zD_r;7yRBoAiAwQz5fM1Aa7Iro`S;2yKE>B(cG4LY0yhcCaMqQAPdtKq@e zRbOM|Ue}LaG(v{kIxm{eLu5y8VA){k{K;79McP@Lqn}uDo52du-WI=&j z^lPC~J|;aH(5S2YJi}ro8VzXQcL99AMp%q88k9fNm2i1v)~{`fW|%duUlEB=xu6*4 z#=sC~*wz$Q=xX+8i_;sQ^|+*@yaxQt0uW1XP7db<_@KBCwq;kO%Q0JLtG@@aO6K_1K z-|4d&YxEL7ucVT?R=SCui_u587@0Qx%&jJE!}$jU2N>99s(p$ald%z-{BlVgAfe9;l+!t>}t%8)R>D_ z)ryASX2#4BF#O5X_UR85sFu#3Iyw?D7rdi<4@UvyDL~Gt!SZD{`f^3Z5-(IC;kRKTYpS1j9(X~oUZ3TYoLvn8D-*5M78uUP22RmxpL@)_`yofn zM4b0j&BNy#(iUL=7APXMa#08GPv3fBx!Fj-#a%&;v)I z`#ro;LQr*G6pbeU!n+=$P@;aeX^7hzynJ0`^8CwSEZZ5$eqMzh!lxUzsu1-R16iYncj<3;1srSlas0j+6)7I(C8okTXU5WAs)eR8tc|%XDnLNuy z$7WhdGkGCb2NTkf>C026wIkTjl33n4%yX*)q+3kWx``8zI|-e`xbUB5g-GEel4$OPQss zcI_QoR29r4X3GTAEt4fDkHhPNloixXZ}iU&3{X9?H8!oUD#F&#-EK9Jgnx2HdR0wo1f2I*=71z5%3ppPqQA{w^bDsub$q+i$uXP;)c^#Jla;m>Vn2fxn4=mn0(=wzi#b;pH?uZ?>F(N<# zY5DD%gVf~W|Fnc3}$25ohoNsTTja=O<^$<-A|e&aty z3+GP{mIe6mv9hwVElyd-!@G*S!dm&dGGhf1lhpHhyG3ukBJEKqOA(T|NnDev3;P9S z?v{~4j2cf87Zo3--Dk7TfF>{CT?IKSO0LQIvb~Ouj$gi@i*$8ILa=suJ)8!KO`FRr zD~n-e{xoQi_B*4jQ8f?%0!1Taq9rsBWw6;vy9`1tzl=TX=?NKmp87*J!v99TMK_gN z3b2NYE}IvW6xv50Fdmi=cQ9!ucJ^y*z1y+<8v?!11a1BX@5F<4enXnuC9ix#(PyNi zH=c@PFZi!S;Q!A2K8a%e8}TX%| zAom9KrT^H7ztcUpVVOvzuw#ZQ2Age9opjv` by fleet-host | +| The device | Roku Express 4K+ at `192.168.50.218`, Roku OS 15.3.4, developer mode on. Registered as `roku-` by fleet-host. An executor older than 0.9 registers it as `platform: android` and leaves an offline `roku-ip-192-168-50-218` beside it; from 0.9 it says `roku`, and the serial-named row retires the IP-named one | | The checkout | `~/tvloop` on fleet-host, **synced from the dev MacBook**, not cloned: the repo is private and fleet-host has no GitHub credential. Re-sync with `rsync -a --delete --exclude node_modules --exclude 'packages/*/dist' --exclude tvloop.toml / fleet-host:tvloop/`, then `corepack pnpm install --frozen-lockfile && corepack pnpm build` there | | `~/tvloop/tvloop.toml` | Not in the repo. Points `[project] source` at `examples/sample-channel`, the channel the flows expect. Keep it out of the rsync | -| The password | Keychain item `fleet-roku-dev` / account `rokudev` on fleet-host, the same one the dev installer reads. Missing means every run is `skipped:` and says how to add it | +| The password | Keychain item `fleet-roku-dev` / account `rokudev` on fleet-host, the same one the dev installer reads. Missing means every run is `skipped:` and says how to add it. On a 0.7 or 0.8 brain those runs show as `done`; from 0.9 they are `skipped`, and three in a row raise a `schedule-skipping` alert | | The steps | `doctor`, `install` (sideloads the sample channel, **replacing whatever is in the dev slot**), `hardware`, `replay`. A failed doctor or install stops the run | ## Real phones from CI @@ -148,7 +148,8 @@ Three things have to be true for a status to appear: `fleet mcp` serves the lab as MCP tools; register it once with `claude mcp add --scope user fleet -- ~/.fleet/bin/fleet mcp`. From the dev MacBook it reaches the brain through the tunnel, the same as the agent does. -A result whose error starts with `skipped:` means nothing ran. +A result whose error starts with `skipped:` means nothing ran. The 0.7.2 brain +closes those jobs as `done`; from 0.9 their status is `skipped`. From 0.8.0 there is also `fleetr`, whose exit code is the verdict, and a skill (`fleet skill install`) that tells an agent which commands to run in what @@ -194,7 +195,7 @@ Five enabled. All times local to fleet-host. | `nightly-self-check` | 02:15 | fanout, pool `machines` | Disk, clock drift, a tool that vanished, or the agent is not supervised | | `nightly-fleet-ui-smoke` | 02:30 | `fleet-host`, an Android device | **Red since 2026-08-21.** From 09-16 to early October it was `no targets attached`. The Galaxy S8+ is plugged in again and the suite now runs on it, and fails, every night; why is not diagnosed yet | | `nightly-aliquant-shots` | 04:15 | `fleet-host`, `chromium` and `mobile-chrome` | Green. The baseline was re-accepted on 2026-09-22 from fleet-host's own captures, after Aliquant's sign-in page gained a "Forgot password?" link; the old one had diverged 2.7% on desktop and 6.1% on mobile since 09-10. The `webkit` and `mobile-safari` baselines are still the August ones, because nothing runs those projects now | -| `nightly-tvloop-hardware` | 05:00 | `fleet-host`, the Roku, exclusive | tvloop's doctor, install, contract tests and flow replay. `skipped:` until the Roku password is in fleet-host's Keychain. Red from doctor means the Roku is asleep, off the network, or out of developer mode | +| `nightly-tvloop-hardware` | 05:00 | `fleet-host`, the Roku, exclusive | tvloop's doctor, install, contract tests and flow replay. `skipped:` until the Roku password is in fleet-host's Keychain (status `done` on the 0.7.2 brain, `skipped` from 0.9). Red from doctor means the Roku is asleep, off the network, or out of developer mode | **`nightly-aliquant-web` and `nightly-aliquant-audit` are retired** (disabled 2026-09-29). Aliquant's own CI already runs the same Playwright suite and diff --git a/docs/protocol.md b/docs/protocol.md index f96a45c..1b1046d 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -49,13 +49,13 @@ means "nothing", and they are different on purpose. ### `platform` and `kind` **`platform`** is which OS family you run. An open string: `android`, `ios`, -`tvos`, `watchos`, `visionos`, `macos`, `linux`, `windows`, `web` are the ones -in use. Send it. An agent that omits it gets the old rule — iOS if `os` looks +`tvos`, `watchos`, `visionos`, `macos`, `linux`, `windows`, `roku`, `web` are +the ones in use. Send it. An agent that omits it gets the old rule — iOS if `os` looks like iOS, Android otherwise — which is kept so that a collector upgrade does not relabel agents written before the field existed. That rule is also why the field had to exist: it does not report a platform, it reports a guess, and every desktop agent registered as an Android phone until it could say -otherwise. +otherwise, and so did the host executor's Rokus until 0.9. **`kind`** is the form factor: `phone`, `tablet`, `laptop`, `desktop`, `tv`, `watch`, `headset`, `sbc`, `browser`, `ci`, `container`. Null when you do not @@ -89,6 +89,12 @@ results you posted stay attributable and `GET /api/devices/:id` still resolves you. What changes is that the queue stops offering you work and you leave the shelf. +One exception, decided by the collector rather than the agent: a row whose +descriptor says `kind: "simulator"` or `soc: "simulator"` is **deleted** once +it has been offline for `FLEET_SIMULATOR_TTL_DAYS` (default 7), because a +simulator is recreated under a new UUID and never comes back. Its results and +beacons are kept, as with the dashboard's Forget. + ## 2. Claim work ``` @@ -243,6 +249,14 @@ The last row for a device carries `final`: the verdict. `error` carries the reason on a failure, and it is what the dashboard shows against the job — so make it a sentence a person can act on. +**If you could not run the job at all**, say `"ok": true` with an `error` that +begins `skipped:` and names why (`skipped: com.example not installed`). The job +closes as `skipped` rather than `done`, nothing waiting on it runs, and no +commit status is posted. A host row of plain `ok: true` over device rows that +all said `skipped:` counts the same. See +[Skipped is not done](concepts.md#skipped-is-not-done). Nothing about the row's +shape changed; a runner that already said `skipped:` needs no update. + ### Metric names are not free-form `metrics` keys come from diff --git a/docs/workloads/host.md b/docs/workloads/host.md index b61db8b..499df54 100644 --- a/docs/workloads/host.md +++ b/docs/workloads/host.md @@ -270,6 +270,15 @@ directory (`FLEET_FLOWS_DIR` to change). `exclusive` takes a device lock for the run, because two suites tapping the same phone is not a test. +**A failing Maestro run says which step broke.** The device row's `error` is +the first failing flow and its assertion, read from the JUnit report +(`smoke: Assertion is false: "Fleet Runner" is visible`), `test.failing_flow` +names the flow, and the report itself is the row's artifact +(`GET /api/v1/artifacts//content`). When Maestro produced no report at +all, the error is its exit code and the last line it printed to stderr, never +its command line, which carries the test account's password. Until 0.9 the +reason was in the uploaded report and nowhere else. + **iOS UI tests need a Mac with full Xcode.** `simctl` and `devicectl` ship with Xcode, not the Command Line Tools, so they run on a different executor from the Android work. [The iOS executor](../deploy/ios-executor.md) covers standing one From 04bca7d2a8ae9e0ca87d5f4a81b22c2c114124a7 Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 21:20:01 -0400 Subject: [PATCH 10/19] explore-night tests: build fake manifest paths with path.join; skip the bash warm-up case on Windows Co-Authored-By: Claude Opus 5.5 --- collector/src/workloads/explore/night.test.ts | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/collector/src/workloads/explore/night.test.ts b/collector/src/workloads/explore/night.test.ts index f6f4098..6b1b292 100644 --- a/collector/src/workloads/explore/night.test.ts +++ b/collector/src/workloads/explore/night.test.ts @@ -46,8 +46,9 @@ export async function runNightChecks(check: Check) { // --- max_minutes from the night queue's manifest ---------------------------- const files: Record = { - "/n/recurring/fleet-explore-tv.json": JSON.stringify({ name: "fleet-explore-tv", max_minutes: 150 }), - "/n/queue/one-off.json": JSON.stringify({ name: "one-off" }), + // path.join, so the keys match what the reader builds on Windows too. + [path.join("/n", "recurring", "fleet-explore-tv.json")]: JSON.stringify({ name: "fleet-explore-tv", max_minutes: 150 }), + [path.join("/n", "queue", "one-off.json")]: JSON.stringify({ name: "one-off" }), }; const read = (p: string) => { if (!(p in files)) throw new Error("ENOENT"); return files[p]; }; check("NIGHT_JOB's manifest gives max_minutes", nightManifestMinutes({ NIGHT_JOB: "fleet-explore-tv", NIGHT_ROOT: "/n" }, read) === 150); @@ -198,12 +199,16 @@ async function runNightCommandChecks(check: Check) { check("again without warming or booting", !/warmed-up|booting|creating simulator/.test(r3.out), r3.out); // 4. The warm-up fails for a reason that is not memory: a failure, posted as one. - posts.length = 0; - const r4 = await runNight(roomy); - const r4result = posts.find((x) => x.url === "/results")?.body; - check("a broken warm-up fails the night (exit 1)", r4.code === 1, r4.out); - check("and the brain is told why", r4result?.ok === false && /^the model did not load: warmed-up/.test(String(r4result?.error)), JSON.stringify(r4result)); - check("the simulator was still not booted", !/booting|creating simulator/.test(r4.out), r4.out); + // The warm command runs under /bin/bash, as it does on ultra; the night + // command is macOS-only, so Windows has nothing to run it with. + if (process.platform !== "win32") { + posts.length = 0; + const r4 = await runNight(roomy); + const r4result = posts.find((x) => x.url === "/results")?.body; + check("a broken warm-up fails the night (exit 1)", r4.code === 1, r4.out); + check("and the brain is told why", r4result?.ok === false && /^the model did not load: warmed-up/.test(String(r4result?.error)), JSON.stringify(r4result)); + check("the simulator was still not booted", !/booting|creating simulator/.test(r4.out), r4.out); + } } finally { server.close(); } From 3ab79c9d20e32c0a3ef0a4d5f35e5215b28c012a Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 21:34:54 -0400 Subject: [PATCH 11/19] describe.test: one evalMatch import after merging the tvOS and Roku checks Co-Authored-By: Claude Opus 5.5 --- collector/src/describe.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/collector/src/describe.test.ts b/collector/src/describe.test.ts index 5d50442..9fcd36f 100644 --- a/collector/src/describe.test.ts +++ b/collector/src/describe.test.ts @@ -74,7 +74,6 @@ export async function runDescribeChecks(check: Check) { JSON.stringify([r1.platform, r2.platform])); const { devicePlatform } = await import("./api/shared.js"); check("and the collector believes it", devicePlatform(r1) === "roku", devicePlatform(r1)); - const { evalMatch } = await import("./match.js"); check("os ~ 'roku' still selects it", evalMatch("os ~ 'roku'", r1) && evalMatch("os ~ 'roku-15'", r1)); const { rokuPresenceHere } = await import("./drivers/roku.js"); From de4859aa306c4fa2ee952b723fab48e65b5ccf2e Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 22:31:16 -0400 Subject: [PATCH 12/19] WIP findings: fixed verdict, history, regressions store Co-Authored-By: Claude Opus 5.5 --- collector/src/api/findings.ts | 58 ++- collector/src/auth.ts | 8 +- collector/src/db.ts | 78 +++- collector/src/findings.ts | 452 +++++++++++++++++++++-- collector/src/workloads/explore/types.ts | 8 +- 5 files changed, 566 insertions(+), 38 deletions(-) diff --git a/collector/src/api/findings.ts b/collector/src/api/findings.ts index 55fa2b4..750fb0c 100644 --- a/collector/src/api/findings.ts +++ b/collector/src/api/findings.ts @@ -9,6 +9,11 @@ * GET /api/findings/issues every issue composed, dry run or filed * GET /api/findings/:id one finding * POST /api/findings/:id/verdict a person's judgement (token-guarded) + * GET /findings/regressions what a nightly ui-test runs (?app= &state= &platform=) + * POST /findings/:id/regression an executor reporting one regression run + * + * /api/v1/findings (src/api/v1/routes.ts) calls the same functions in + * src/findings.ts; neither route set has logic of its own. * * ## Guard posture * @@ -17,11 +22,18 @@ * network (see README and FLEET_BIND), not the dashboard token. The verdict is * different -- it is a person's decision, and it decides which checks run * tomorrow night -- so it carries the same speed bump as cancel and ack. + * The two regression routes are the executor again: it pulls the flows its + * job should run and reports what each did, so they sit with `POST /findings` + * on the runner protocol's side of auth. */ import type { FastifyInstance } from "fastify"; import { LIMITS, buildDigest, + listRegressions, + parseRegressionRun, + parseVerdictBody, + recordRegressionRun, fileIssue, findingDetail, issueOptions, @@ -33,7 +45,7 @@ import { validateFinding, } from "../findings.js"; import { FINDINGS_REPOS, FINDINGS_REPOS_ERROR, GITHUB_ISSUES_ARMED, GITHUB_TOKEN } from "../config.js"; -import type { Verdict } from "../workloads/explore/types.js"; +import { authOf } from "../auth.js"; import { requireToken } from "./guard.js"; type Announce = (event: { type: string; [k: string]: unknown }) => void; @@ -75,7 +87,10 @@ export function registerFindings(app: FastifyInstance, announce: Announce) { app.get("/api/findings", async (req, reply) => { const q = req.query as Record; - const out = listFindings({ app: q.app, check: q.check, status: q.status, since: q.since, limit: Number(q.limit) || undefined }); + const out = listFindings({ + app: q.app, check: q.check, status: q.status, verdict: q.verdict, since: q.since, + limit: Number(q.limit) || undefined, offset: Number(q.offset) || undefined, + }); if (!out.ok) return reply.code(400).send({ error: out.error }); return out.body; }); @@ -116,18 +131,35 @@ export function registerFindings(app: FastifyInstance, announce: Announce) { if (!requireToken(req, reply)) return; const id = idOf((req.params as { id: string }).id); if (id === null) return reply.code(404).send({ error: "no such finding" }); - const b = (req.body ?? {}) as { verdict?: unknown; note?: unknown; duplicate_of?: unknown }; - if (!("verdict" in b)) return reply.code(400).send({ error: "verdict is required (or null to reopen)" }); - if (b.note !== undefined && b.note !== null && typeof b.note !== "string") - return reply.code(400).send({ error: "note must be a string" }); - const dup = b.duplicate_of === undefined || b.duplicate_of === null ? null : Number(b.duplicate_of); - if (dup !== null && !(Number.isInteger(dup) && dup > 0)) - return reply.code(400).send({ error: "duplicate_of must be a finding id" }); - - const note = typeof b.note === "string" && b.note.trim() ? b.note.trim() : null; - const out = setVerdict(id, (b.verdict ?? null) as Verdict | null, note, dup); + const body = parseVerdictBody(req.body); + if (!body.ok) return reply.code(400).send({ error: body.error }); + const ctx = authOf(req); + const out = setVerdict(id, body.verdict, body.note, body.duplicateOf, { who: { actor: ctx.actor, source: ctx.source ?? "dash" } }); if (!out.ok) return reply.code(out.status).send({ error: out.error }); announce({ type: "finding", id, verdict: out.finding.verdict }); - return { ok: true, finding: out.finding }; + return { ok: true, finding: out.finding, regression: out.regression, change: out.change }; + }); + + // The executor's side of regression tests. Literal before parameterised, + // as above. + app.get("/findings/regressions", async (req, reply) => { + const q = req.query as Record; + const out = listRegressions({ app: q.app || undefined, state: q.state || undefined, platform: q.platform || undefined }); + if (!out.ok) return reply.code(400).send({ error: out.error }); + return { regressions: out.items }; + }); + + app.post("/findings/:id/regression", async (req, reply) => { + const id = idOf((req.params as { id: string }).id); + if (id === null) return reply.code(404).send({ error: "no such finding" }); + const body = parseRegressionRun(req.body); + if (!body.ok) return reply.code(400).send({ error: body.error }); + const out = recordRegressionRun(id, body.run); + if (!out.ok) return reply.code(out.status).send({ error: out.error }); + if (out.reopened) { + app.log.warn({ finding: id, job: body.run.job_id, build: body.run.build }, "regression reproduced; finding reopened"); + announce({ type: "finding", id, verdict: null, regressed: true }); + } + return { ok: true, reopened: out.reopened, regression: { state: out.regression.state, runs: out.regression.runs, last_outcome: out.regression.last_outcome } }; }); } diff --git a/collector/src/auth.ts b/collector/src/auth.ts index 07716f7..eacf1f7 100644 --- a/collector/src/auth.ts +++ b/collector/src/auth.ts @@ -239,6 +239,9 @@ const PROTOCOL_ROUTES: [string, RegExp][] = [ ["GET", /^\/events\/[^/]+\/poll$/], ["POST", /^\/api\/jobs\/[^/]+\/mirror$/], ["POST", /^\/findings$/], + // A nightly ui-test pulling the app's regression flows, and reporting each run. + ["GET", /^\/findings\/regressions$/], + ["POST", /^\/findings\/\d+\/regression$/], ]; const RUN_ROUTES: [string, RegExp][] = [ @@ -249,6 +252,9 @@ const RUN_ROUTES: [string, RegExp][] = [ ["POST", /^\/api\/v1\/jobs$/], ["POST", /^\/api\/v1\/jobs\/validate$/], ["POST", /^\/api\/v1\/jobs\/[^/]+\/(cancel|retry)$/], + // A verdict decides what tomorrow's nightly runs, which is the run scope's + // business; the dashboard's older route stays where it was. + ["POST", /^\/api\/v1\/findings\/[^/]+\/verdict$/], ]; /** What a request needs. Exported so the rule table can be tested and documented. */ @@ -356,7 +362,7 @@ function deny(req: FastifyRequest, reply: FastifyReply, status: 401 | 403, code: } /** Routes whose traffic is the fleet breathing, not a person deciding. Never audited. */ -const QUIET = /^\/(results|devices\/register|devices\/[^/]+\/next-job|executor\/next-job|locks\/|events\/|artifacts$|findings$|api\/jobs\/[^/]+\/mirror$|api\/session$)/; +const QUIET = /^\/(results|devices\/register|devices\/[^/]+\/next-job|executor\/next-job|locks\/|events\/|artifacts$|findings$|findings\/\d+\/regression$|api\/jobs\/[^/]+\/mirror$|api\/session$)/; export function registerAuth(app: FastifyInstance): void { app.addHook("onRequest", async (req, reply) => { diff --git a/collector/src/db.ts b/collector/src/db.ts index b1fc04d..d7cecc5 100644 --- a/collector/src/db.ts +++ b/collector/src/db.ts @@ -676,7 +676,7 @@ CREATE TABLE IF NOT EXISTS findings ( last_seen TEXT NOT NULL DEFAULT (datetime('now')), seen_count INTEGER NOT NULL DEFAULT 1, builds_seen TEXT NOT NULL DEFAULT '[]', -- JSON array of distinct builds - verdict TEXT CHECK (verdict IS NULL OR verdict IN ('real','duplicate','not_a_bug','agent_mistake')), + verdict TEXT CHECK (verdict IS NULL OR verdict IN ('real','duplicate','not_a_bug','agent_mistake','fixed')), verdict_note TEXT, verdict_at TEXT, duplicate_of INTEGER, @@ -701,8 +701,84 @@ CREATE TABLE IF NOT EXISTS findings_digests ( posted INTEGER NOT NULL DEFAULT 0, detail TEXT ); + +-- Every verdict a finding has had, and every night a regression test brought +-- it back. The findings row holds only the current verdict; this is how a +-- reader learns that "open" means "regressed on build 1.4 (12)" rather than +-- "nobody has looked". +CREATE TABLE IF NOT EXISTS finding_verdicts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + finding_id INTEGER NOT NULL, + at TEXT NOT NULL DEFAULT (datetime('now')), + event TEXT NOT NULL CHECK (event IN ('verdict','regressed')), + verdict TEXT, -- NULL: reopened + note TEXT, + actor TEXT, + source TEXT +); +CREATE INDEX IF NOT EXISTS idx_finding_verdicts ON finding_verdicts (finding_id, id); + +-- A finding's replay flow, kept as a regression test (src/findings.ts). +-- In the database rather than as files because the lab's flows directory is +-- outside git and outside any backup this repository controls: the flow text +-- is copied here when the finding is marked real, so it survives the artifact +-- store's GC as well. +CREATE TABLE IF NOT EXISTS regressions ( + finding_id INTEGER PRIMARY KEY, + app TEXT NOT NULL, + platform TEXT NOT NULL, + check_name TEXT NOT NULL, + kind TEXT NOT NULL CHECK (kind IN ('maestro','tvloop')), + flow TEXT NOT NULL, + flow_sha256 TEXT, + state TEXT NOT NULL CHECK (state IN ('candidate','active','retired')), + created_at TEXT NOT NULL DEFAULT (datetime('now')), + activated_at TEXT, + retired_at TEXT, + runs INTEGER NOT NULL DEFAULT 0, + last_run_at TEXT, + last_job_id TEXT, + last_outcome TEXT, + last_detail TEXT +); +CREATE INDEX IF NOT EXISTS idx_regressions_app ON regressions (app, state); `); +// 'fixed' as a verdict. The findings table's CHECK predates it, and SQLite +// cannot alter a constraint, so the table is rebuilt once, the same way the +// jobs table was for 'skipped'. Every existing verdict also gets one history +// row, so a finding judged before history existed does not read as never +// judged. +{ + const ddl = (db.prepare("SELECT sql FROM sqlite_master WHERE type='table' AND name='findings'").get() as + | { sql: string } + | undefined)?.sql; + if (ddl && !ddl.includes("'fixed'")) { + const widened = ddl + .replace(/^CREATE TABLE\s+("?)findings\1/i, "CREATE TABLE findings_migrating") + .replace(/verdict IN \(([^)]*)\)/i, (_m, list: string) => `verdict IN (${list.trim()},'fixed')`); + if (!widened.includes("'fixed'") || !widened.startsWith("CREATE TABLE findings_migrating")) + throw new Error("cannot widen the findings verdict constraint: the table's DDL is not the shape this migration knows"); + const columns = (db.prepare("PRAGMA table_info(findings)").all() as { name: string }[]).map((c) => `"${c.name}"`).join(", "); + withTransaction(db, () => { + db.exec(widened); + db.exec(`INSERT INTO findings_migrating (${columns}) SELECT ${columns} FROM findings`); + db.exec("DROP TABLE findings"); + db.exec("ALTER TABLE findings_migrating RENAME TO findings"); + db.exec(` + CREATE INDEX IF NOT EXISTS idx_findings_last_seen ON findings (last_seen DESC); + CREATE INDEX IF NOT EXISTS idx_findings_app_check ON findings (app, check_name); + CREATE INDEX IF NOT EXISTS idx_findings_issue ON findings (app, issue_state, issue_at); + `); + })(); + } + db.exec(` + INSERT INTO finding_verdicts (finding_id, at, event, verdict, note) + SELECT f.id, COALESCE(f.verdict_at, f.last_seen), 'verdict', f.verdict, f.verdict_note FROM findings f + WHERE f.verdict IS NOT NULL AND NOT EXISTS (SELECT 1 FROM finding_verdicts v WHERE v.finding_id = f.id) + `); +} + // Who asked for a job, and through which front door. After the rebuild for the // same reason depends_on is. `requested_by` is a verified identity only when // FLEET_AUTH=tokens; with auth off it is whatever the caller said, and the API diff --git a/collector/src/findings.ts b/collector/src/findings.ts index 0d92d49..955e6ad 100644 --- a/collector/src/findings.ts +++ b/collector/src/findings.ts @@ -9,7 +9,11 @@ * * store upsert on the fingerprint, so the fifth night that finds the * same crash raises a count instead of a fifth report (T2) - * verdict a person's real / duplicate / not a bug / agent's mistake (T4) + * verdict a person's real / duplicate / not a bug / agent's mistake (T4), + * and fixed, which only follows real; every one kept in a history + * regressions a real finding's replay flow kept as a candidate test, made + * active when it is marked fixed, and run by the app's nightly + * ui-test; one that reproduces reopens the finding (LOOP Phase 4) * precision per app and check, how often a person called it real -- and * which check classes are wasting the morning (O4) * digest the morning summary, sent once a day to the phone (T5) @@ -36,11 +40,14 @@ * other. Even armed, this code only ever creates issues. It never edits, * comments on or closes one; that is a person's job. */ +import { existsSync, readFileSync, statSync } from "node:fs"; +import path from "node:path"; import { db } from "./db.js"; import { iso, parse } from "./api/shared.js"; import { sendWebhook } from "./alerts.js"; import { skipReasonText } from "./skip.js"; import { + ARTIFACT_DIR, DASH_URL, FINDINGS_DIGEST_AT, FINDINGS_DIGEST_HOURS, @@ -55,7 +62,7 @@ import { CHECK_NAMES, type CheckName, type ExploreFinding, type Verdict } from " // The rules, as numbers // --------------------------------------------------------------------------- -export const VERDICTS: readonly Verdict[] = ["real", "duplicate", "not_a_bug", "agent_mistake"]; +export const VERDICTS: readonly Verdict[] = ["real", "duplicate", "not_a_bug", "agent_mistake", "fixed"]; const SEVERITIES = ["high", "medium", "low"] as const; const REPLAY_KINDS = ["maestro", "tvloop", "none"] as const; const ARTIFACT_KEYS = ["shot", "sheet", "trajectory", "log", "replay"] as const; @@ -314,6 +321,8 @@ export type FindingView = { duplicate_of: number | null; issue: IssueRecord | null; status: "open" | "triaged"; + /** The regression test this finding became, if it did: just enough for a list. */ + regression: { state: RegressionState; kind: RegressionKind; last_outcome: RegressionOutcome | null } | null; }; export function replayLabel(replay: Replay, check: CheckName): string { @@ -354,6 +363,7 @@ function view(r: Row): FindingView { duplicate_of: r.duplicate_of, issue: parse(r.issue, null), status: r.verdict === null ? "open" : "triaged", + regression: regressionBrief(r.id), }; } @@ -636,6 +646,40 @@ export function listIssues(limit = 100) { // Verdicts (T4) // --------------------------------------------------------------------------- +/** Who gave a verdict, for the history. Null fields when the collector cannot say. */ +export type Who = { actor: string | null; source: string | null }; + +export type VerdictOptions = { + who?: Who; + /** Reads a replay flow out of the artifact store. Tests pass their own. */ + readArtifact?: ReadArtifact; +}; + +export type VerdictOutcome = + | { ok: true; finding: FindingView; regression: RegressionView | null; change: string | null } + | ({ ok: false } & { status: 400 | 404 | 409; error: string; hint?: string }); + +/** + * A verdict body as either route receives it: `{verdict, note?, duplicate_of?}`. + * Parsed here so the legacy route and /api/v1 refuse the same things in the + * same words. + */ +export function parseVerdictBody( + body: unknown, +): { ok: true; verdict: Verdict | null; note: string | null; duplicateOf: number | null } | { ok: false; error: string } { + const b = (body && typeof body === "object" && !Array.isArray(body) ? body : {}) as { + verdict?: unknown; note?: unknown; duplicate_of?: unknown; + }; + if (!("verdict" in b)) return { ok: false, error: "verdict is required (or null to reopen)" }; + if (b.verdict !== null && !VERDICTS.includes(b.verdict as Verdict)) + return { ok: false, error: `verdict must be one of ${VERDICTS.join(", ")}, or null to reopen` }; + if (b.note !== undefined && b.note !== null && typeof b.note !== "string") return { ok: false, error: "note must be a string" }; + const dup = b.duplicate_of === undefined || b.duplicate_of === null ? null : Number(b.duplicate_of); + if (dup !== null && !(Number.isInteger(dup) && dup > 0)) return { ok: false, error: "duplicate_of must be a finding id" }; + const note = typeof b.note === "string" && b.note.trim() ? b.note.trim() : null; + return { ok: true, verdict: (b.verdict ?? null) as Verdict | null, note, duplicateOf: dup }; +} + /** * Record a person's verdict, or clear it with `verdict: null` (a mis-click * should not need SQL to undo). @@ -644,13 +688,20 @@ export function listIssues(limit = 100) { * is a duplicate of A and C is marked a duplicate of B, C points at A, so the * "this is the same as" graph never grows chains a person has to walk. Marking * something a duplicate of itself, or of one of its own duplicates, is refused. + * + * `fixed` is refused unless the finding is already `real` (or was, and a + * regression test brought it back): "fixed" on something nobody confirmed is a + * claim about a bug that may not exist, and it would put a test in the nightly + * for it. Every verdict lands in the history and moves the regression test, + * see `moveRegression`. */ -export function setVerdict( +export const setVerdict = db.transaction(( id: number, verdict: Verdict | null, note: string | null, duplicateOf: number | null, -): { ok: true; finding: FindingView } | ({ ok: false } & { status: 400 | 404; error: string }) { + opts: VerdictOptions = {}, +): VerdictOutcome => { const row = getRow(id); if (!row) return { ok: false, status: 404, error: `no finding ${id}` }; if (verdict !== null && !VERDICTS.includes(verdict)) @@ -658,6 +709,14 @@ export function setVerdict( if (note !== null && note.length > LIMITS.note) return { ok: false, status: 400, error: `note is longer than ${LIMITS.note} characters` }; + const reg = getRegressionRow(id); + if (verdict === "fixed" && row.verdict !== "real" && row.verdict !== "fixed" && reg?.state !== "active") + return { + ok: false, status: 409, + error: `finding ${id} is ${row.verdict === null ? "open" : row.verdict}; fixed comes only after real`, + hint: "mark it real first, and fixed once the fix has merged", + }; + let target: number | null = null; if (verdict === "duplicate") { if (duplicateOf === null) return { ok: false, status: 400, error: "a duplicate needs duplicate_of: the id it duplicates" }; @@ -677,17 +736,302 @@ export function setVerdict( duplicate_of = ? WHERE id = ?`, ).run(verdict, verdict === null ? null : note, verdict, target, id); - return { ok: true, finding: view(getRow(id)!) }; + db.prepare("INSERT INTO finding_verdicts (finding_id, event, verdict, note, actor, source) VALUES (?, 'verdict', ?, ?, ?, ?)") + .run(id, verdict, note, opts.who?.actor ?? null, opts.who?.source ?? null); + const change = moveRegression(view(getRow(id)!), verdict, opts.readArtifact ?? readStoredArtifact); + return { ok: true, finding: view(getRow(id)!), regression: regressionView(getRegressionRow(id)), change }; +}); + +export type HistoryEntry = { + at: string | null; + /** `verdict`: a person's call (verdict null = reopened). `regressed`: a regression test reproduced it. */ + event: "verdict" | "regressed"; + verdict: Verdict | null; + note: string | null; + actor: string | null; + source: string | null; +}; + +export function verdictHistory(id: number): HistoryEntry[] { + const rows = db + .prepare("SELECT at, event, verdict, note, actor, source FROM finding_verdicts WHERE finding_id = ? ORDER BY id") + .all(id) as (Omit & { at: string })[]; + return rows.map((r) => ({ ...r, at: iso(r.at) })); +} + +// --------------------------------------------------------------------------- +// Regressions: a fixed finding becomes a test (LOOP Phase 4) +// --------------------------------------------------------------------------- + +export type RegressionState = "candidate" | "active" | "retired"; +export type RegressionKind = "maestro" | "tvloop"; +/** + * One night's run of a regression flow on one device: + * passed the flow replayed without error (and, for a crash or ANR, the + * package did not crash while it ran) + * reproduced the original failure came back: a crash or ANR of the package + * during the flow. Reopens the finding. + * failed the flow itself failed. For any check but crash and anr this + * is all a replay can say: the steps no longer replay, which may + * be the bug or may be a changed screen. Does not reopen. + * skipped not run on this device (wrong platform, no Maestro there) + */ +export type RegressionOutcome = "passed" | "reproduced" | "failed" | "skipped"; +export const REGRESSION_OUTCOMES: readonly RegressionOutcome[] = ["passed", "reproduced", "failed", "skipped"]; + +/** Checks a replay can assert the absence of. Everything else is "replays without error". */ +export const ABSENCE_CHECKS: readonly CheckName[] = ["crash", "anr"]; + +/** A flow bigger than this is not a flow a person recorded; it is not kept. */ +export const FLOW_MAX_BYTES = 64 * 1024; + +type RegressionRow = { + finding_id: number; + app: string; + platform: string; + check_name: CheckName; + kind: RegressionKind; + flow: string; + flow_sha256: string | null; + state: RegressionState; + created_at: string; + activated_at: string | null; + retired_at: string | null; + runs: number; + last_run_at: string | null; + last_job_id: string | null; + last_outcome: RegressionOutcome | null; + last_detail: string | null; +}; + +export type RegressionView = { + finding_id: number; + app: string; + platform: string; + check: CheckName; + kind: RegressionKind; + state: RegressionState; + /** What a run proves: `no_crash` for crash and anr findings, `replays` (without error) for the rest. */ + asserts: "no_crash" | "replays"; + flow: string; + flow_sha256: string | null; + created_at: string | null; + activated_at: string | null; + retired_at: string | null; + runs: number; + last_run_at: string | null; + last_job_id: string | null; + last_outcome: RegressionOutcome | null; + last_detail: string | null; +}; + +/** The flow text for a sha, or null when the store does not have it (or it is too big to be a flow). */ +export type ReadArtifact = (sha256: string) => string | null; + +export const readStoredArtifact: ReadArtifact = (sha) => { + if (!SHA.test(sha)) return null; + const file = path.join(ARTIFACT_DIR, sha); + try { + if (statSync(file).size > FLOW_MAX_BYTES) return null; + return readFileSync(file, "utf8"); + } catch { + return null; + } +}; + +const getRegressionRow = (id: number) => + db.prepare("SELECT * FROM regressions WHERE finding_id = ?").get(id) as RegressionRow | undefined; + +function regressionView(r: RegressionRow | undefined): RegressionView | null { + if (!r) return null; + return { + finding_id: r.finding_id, app: r.app, platform: r.platform, check: r.check_name, kind: r.kind, state: r.state, + asserts: ABSENCE_CHECKS.includes(r.check_name) ? "no_crash" : "replays", + flow: r.flow, flow_sha256: r.flow_sha256, + created_at: iso(r.created_at), activated_at: iso(r.activated_at), retired_at: iso(r.retired_at), + runs: r.runs, last_run_at: iso(r.last_run_at), last_job_id: r.last_job_id, last_outcome: r.last_outcome, last_detail: r.last_detail, + }; +} + +function regressionBrief(id: number): FindingView["regression"] { + const r = db.prepare("SELECT state, kind, last_outcome FROM regressions WHERE finding_id = ?").get(id) as + | { state: RegressionState; kind: RegressionKind; last_outcome: RegressionOutcome | null } + | undefined; + return r ? { state: r.state, kind: r.kind, last_outcome: r.last_outcome } : null; +} + +export function getRegression(id: number): RegressionView | null { + return regressionView(getRegressionRow(id)); +} + +/** The replay flow's artifact: the replay's own hash, or the replay artifact a crash posts without counts. */ +const flowShaOf = (f: Pick) => f.replay?.sha256 ?? f.artifacts.replay ?? null; + +/** + * Copy the finding's replay flow into the regressions table. Returns why not, + * when it cannot: no replay file was posted, or the store no longer has it. + */ +function keepFlow(f: FindingView, state: RegressionState, read: ReadArtifact): string { + const sha = flowShaOf(f); + if (!sha) return "no replay flow was posted with this finding, so there is nothing to keep as a test"; + if (f.replay?.kind === "none") return "the replay was not a file (kind none), so there is nothing to keep as a test"; + const text = read(sha); + if (text === null) return `the replay flow ${sha.slice(0, 12)} is not in the artifact store (collected, or over ${FLOW_MAX_BYTES} bytes)`; + const kind: RegressionKind = + f.replay?.kind === "tvloop" || f.replay?.kind === "maestro" ? f.replay.kind : text.trimStart().startsWith("{") ? "tvloop" : "maestro"; + db.prepare( + `INSERT INTO regressions (finding_id, app, platform, check_name, kind, flow, flow_sha256, state, activated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, CASE WHEN ? = 'active' THEN datetime('now') END)`, + ).run(f.id, f.app, f.platform, f.check, kind, text, sha, state, state); + return state === "active" + ? `its replay flow is now an active regression test in ${f.app}'s nightly ui-test` + : `its replay flow is kept as a candidate regression test; it joins the nightly when the finding is marked fixed`; } +/** + * What a verdict does to the finding's regression test. + * + * real keep the replay flow as a candidate (a retired one + * comes back as a candidate; an active one stays + * active -- it is watching for this very bug) + * fixed candidate -> active: the app's nightly runs it + * duplicate, not_a_bug, + * agent_mistake retire it: it is not a test of anything real + * null (reopen) leave it as it is + * + * Returns one sentence saying what changed, or null when nothing did. + */ +function moveRegression(f: FindingView, verdict: Verdict | null, read: ReadArtifact): string | null { + const reg = getRegressionRow(f.id); + if (verdict === "real") { + if (!reg) return keepFlow(f, "candidate", read); + if (reg.state === "retired") { + db.prepare("UPDATE regressions SET state = 'candidate', retired_at = NULL WHERE finding_id = ?").run(f.id); + return "its retired regression test is a candidate again"; + } + return null; + } + if (verdict === "fixed") { + if (!reg) return keepFlow(f, "active", read); + if (reg.state === "active") return null; + db.prepare("UPDATE regressions SET state = 'active', activated_at = datetime('now'), retired_at = NULL WHERE finding_id = ?").run(f.id); + return `its replay flow is now an active regression test in ${f.app}'s nightly ui-test`; + } + if (verdict !== null && reg && reg.state !== "retired") { + db.prepare("UPDATE regressions SET state = 'retired', retired_at = datetime('now') WHERE finding_id = ?").run(f.id); + return `its ${reg.state} regression test is retired`; + } + return null; +} + +/** What a nightly ui-test pulls at run time: the app's regressions in one state (active by default). */ +export function listRegressions(q: { app?: string; state?: string; platform?: string } = {}): { ok: true; items: RegressionView[] } | { ok: false; error: string } { + const state = q.state ?? "active"; + if (state !== "all" && !["candidate", "active", "retired"].includes(state)) + return { ok: false, error: "state must be candidate, active, retired or all" }; + const where: string[] = []; + const params: string[] = []; + if (q.app) { where.push("app = ?"); params.push(q.app); } + if (q.platform) { where.push("platform = ?"); params.push(q.platform); } + if (state !== "all") { where.push("state = ?"); params.push(state); } + const rows = db + .prepare(`SELECT * FROM regressions ${where.length ? `WHERE ${where.join(" AND ")}` : ""} ORDER BY finding_id`) + .all(...params) as RegressionRow[]; + return { ok: true, items: rows.map((r) => regressionView(r)!) }; +} + +export type RegressionRun = { job_id: string; device_id: string; build: string; outcome: RegressionOutcome; detail: string }; + +/** A run report as the executor posts it, checked. */ +export function parseRegressionRun(body: unknown): { ok: true; run: RegressionRun } | { ok: false; error: string } { + if (!body || typeof body !== "object" || Array.isArray(body)) return { ok: false, error: "body must be a JSON object" }; + const b = body as Record; + for (const k of ["job_id", "device_id"]) { + if (typeof b[k] !== "string" || !(b[k] as string).trim() || (b[k] as string).length > LIMITS.id) + return { ok: false, error: `${k} is required (a non-empty string of at most ${LIMITS.id} characters)` }; + } + if (b.build !== undefined && b.build !== null && (typeof b.build !== "string" || b.build.length > LIMITS.id)) + return { ok: false, error: `build must be a string of at most ${LIMITS.id} characters` }; + if (!REGRESSION_OUTCOMES.includes(b.outcome as RegressionOutcome)) + return { ok: false, error: `outcome must be one of ${REGRESSION_OUTCOMES.join(", ")}` }; + if (b.detail !== undefined && b.detail !== null && typeof b.detail !== "string") return { ok: false, error: "detail must be a string" }; + return { + ok: true, + run: { + job_id: b.job_id as string, device_id: b.device_id as string, + build: (typeof b.build === "string" && b.build.trim()) || "installed", + outcome: b.outcome as RegressionOutcome, + detail: typeof b.detail === "string" ? b.detail.slice(0, LIMITS.note) : "", + }, + }; +} + +/** + * Record one device's run of a regression flow. + * + * `reproduced` on an ACTIVE regression reopens the finding -- verdict cleared, + * seen once more, the build added, and a history line saying which build it + * came back on -- so the morning digest lists it again instead of the nightly + * passing over it. A fan-out reporting the same reproduction from three + * devices of one job reopens it once. The regression stays active: the bug is + * back, and the nightly should keep saying so until someone marks it fixed + * again (real, then fixed). A candidate or retired regression's run is + * recorded and changes nothing else, since nothing schedules those. + */ +export const recordRegressionRun = db.transaction((id: number, run: RegressionRun): + | { ok: true; reopened: boolean; regression: RegressionView; finding: FindingView } + | { ok: false; status: 404; error: string } => { + const reg = getRegressionRow(id); + const row = getRow(id); + if (!reg || !row) return { ok: false, status: 404, error: `finding ${id} has no regression test` }; + const alreadyThisJob = reg.last_job_id === run.job_id && reg.last_outcome === "reproduced"; + db.prepare( + `UPDATE regressions SET runs = runs + 1, last_run_at = datetime('now'), last_job_id = ?, last_outcome = ?, last_detail = ? + WHERE finding_id = ?`, + ).run(run.job_id, alreadyThisJob ? "reproduced" : run.outcome, run.detail || null, id); + + let reopened = false; + if (run.outcome === "reproduced" && reg.state === "active" && !alreadyThisJob) { + const builds = parse(row.builds_seen, []); + if (!builds.includes(run.build)) builds.push(run.build); + db.prepare( + `UPDATE findings SET verdict = NULL, verdict_note = NULL, verdict_at = NULL, duplicate_of = NULL, + seen_count = seen_count + 1, last_seen = datetime('now'), last_job_id = ?, builds_seen = ? + WHERE id = ?`, + ).run(run.job_id, JSON.stringify(builds), id); + const note = `regressed on build ${run.build} (job ${run.job_id}, ${run.device_id})${run.detail ? `: ${run.detail}` : ""}`.slice(0, LIMITS.note); + db.prepare("INSERT INTO finding_verdicts (finding_id, event, verdict, note, source) VALUES (?, 'regressed', NULL, ?, 'regression')") + .run(id, note); + reopened = true; + } + return { ok: true, reopened, regression: regressionView(getRegressionRow(id))!, finding: view(getRow(id)!) }; +}); + // --------------------------------------------------------------------------- // Reading // --------------------------------------------------------------------------- -export type ListQuery = { app?: string; check?: string; status?: string; since?: string; limit?: number }; +export type ListQuery = { + app?: string; check?: string; status?: string; verdict?: string; since?: string; limit?: number; offset?: number; +}; + +/** + * A `since` filter: an ISO-8601 time, or a span back from now -- `90m`, `24h`, + * `7d`, `2w` -- which is what an agent's morning brief asks for. Null when it + * is neither. + */ +export function parseSince(raw: string, now = new Date()): Date | null { + const span = /^(\d+)\s*(m|h|d|w)$/i.exec(raw.trim()); + if (span) { + const unit = { m: 60_000, h: 3_600_000, d: 86_400_000, w: 604_800_000 }[span[2].toLowerCase() as "m" | "h" | "d" | "w"]; + return new Date(now.getTime() - Number(span[1]) * unit); + } + const t = Date.parse(raw); + return Number.isFinite(t) ? new Date(t) : null; +} /** The filtered list, newest sighting first, with facets over every row so a filter never empties its own menu. */ -export function listFindings(q: ListQuery): { ok: true; body: unknown } | { ok: false; error: string } { +export function listFindings(q: ListQuery): { ok: true; body: FindingList } | { ok: false; error: string } { const where: string[] = []; const params: string[] = []; if (q.app) { where.push("app = ?"); params.push(q.app); } @@ -695,13 +1039,13 @@ export function listFindings(q: ListQuery): { ok: true; body: unknown } | { ok: const status = q.status ?? "all"; if (!["open", "triaged", "all"].includes(status)) return { ok: false, error: "status must be open, triaged or all" }; if (q.since) { - const t = Date.parse(q.since); - if (!Number.isFinite(t)) return { ok: false, error: "since must be an ISO-8601 date or time" }; + const t = parseSince(q.since); + if (!t) return { ok: false, error: "since must be an ISO-8601 date or time, or a span like 24h or 7d" }; where.push("last_seen >= ?"); - params.push(sqliteTime(new Date(t))); + params.push(sqliteTime(t)); } - // Counted before the status filter, so the page can say "3 open, 12 triaged" - // for whatever app and check are selected. + // Counted before the status and verdict filters, so the page can say + // "3 open, 12 triaged" for whatever app and check are selected. const scoped = where.length ? `WHERE ${where.join(" AND ")}` : ""; const counts = db .prepare( @@ -711,13 +1055,20 @@ export function listFindings(q: ListQuery): { ok: true; body: unknown } | { ok: .get(...params) as { open: number | null; triaged: number | null; total: number }; if (status === "open") where.push("verdict IS NULL"); if (status === "triaged") where.push("verdict IS NOT NULL"); + if (q.verdict) { + const wanted = q.verdict.split(",").map((v) => v.trim()).filter(Boolean); + const bad = wanted.find((v) => !VERDICTS.includes(v as Verdict)); + if (bad) return { ok: false, error: `verdict must be one of ${VERDICTS.join(", ")} (comma-separated), not ${JSON.stringify(bad)}` }; + where.push(`verdict IN (${wanted.map(() => "?").join(",")})`); + params.push(...wanted); + } + const filtered = where.length ? `WHERE ${where.join(" AND ")}` : ""; + const total = (db.prepare(`SELECT COUNT(*) AS n FROM findings ${filtered}`).get(...params) as { n: number }).n; const limit = Math.min(500, Math.max(1, Number(q.limit ?? 100) || 100)); + const offset = Math.max(0, Math.floor(Number(q.offset ?? 0) || 0)); const rows = db - .prepare( - `SELECT * FROM findings ${where.length ? `WHERE ${where.join(" AND ")}` : ""} - ORDER BY last_seen DESC, id DESC LIMIT ?`, - ) - .all(...params, limit) as Row[]; + .prepare(`SELECT * FROM findings ${filtered} ORDER BY last_seen DESC, id DESC LIMIT ? OFFSET ?`) + .all(...params, limit, offset) as Row[]; return { ok: true, body: { @@ -727,22 +1078,80 @@ export function listFindings(q: ListQuery): { ok: true; body: unknown } | { ok: checks: (db.prepare("SELECT DISTINCT check_name FROM findings ORDER BY check_name").all() as { check_name: string }[]) .map((r) => r.check_name), limit, + offset, + total, }, }; } -/** One finding, with the findings a person has marked as duplicates of it. */ -export function findingDetail(id: number) { +export type FindingList = { + findings: FindingView[]; + counts: { open: number; triaged: number; total: number }; + apps: string[]; + checks: string[]; + limit: number; + offset: number; + /** Rows matching every filter, status and verdict included. */ + total: number; +}; + +const EVIDENCE_LABEL = ARTIFACT_LABEL; + +/** A replay flow small enough to inline is inlined; past this, follow `url`. */ +export const FLOW_INLINE_BYTES = 16 * 1024; + +/** + * One finding, with the findings a person has marked as duplicates of it, its + * verdict history, its regression test, its evidence as links, and its replay + * flow -- inline when it is small, which a Maestro flow nearly always is. + */ +export function findingDetail(id: number, read: ReadArtifact = readStoredArtifact) { const f = getFinding(id); if (!f) return null; const duplicates = db .prepare("SELECT id, title, seen_count FROM findings WHERE duplicate_of = ? ORDER BY id") .all(id) as { id: number; title: string; seen_count: number }[]; const original = f.duplicate_of ? getFinding(f.duplicate_of) : null; + const inStore = (sha: string) => existsSync(path.join(ARTIFACT_DIR, sha)); + const evidence = ARTIFACT_KEYS.filter((k) => f.artifacts[k]).map((k) => { + const sha = f.artifacts[k]!; + return { role: k, label: EVIDENCE_LABEL[k], sha256: sha, url: `/api/v1/artifacts/${sha}/content`, in_store: inStore(sha) }; + }); + const regression = getRegression(id); + const flowSha = flowShaOf(f); + let replayFlow: { + kind: string; sha256: string; url: string; in_store: boolean; text: string | null; truncated: boolean; + } | null = null; + if (flowSha) { + const stored = inStore(flowSha); + const text = (stored ? read(flowSha) : null) ?? (regression?.flow_sha256 === flowSha ? regression.flow : null); + const kind = f.replay?.kind && f.replay.kind !== "none" ? f.replay.kind : regression?.kind ?? "maestro"; + replayFlow = { + kind, sha256: flowSha, url: `/api/v1/artifacts/${flowSha}/content`, in_store: stored, + text: text !== null && Buffer.byteLength(text) <= FLOW_INLINE_BYTES ? text : null, + truncated: text !== null && Buffer.byteLength(text) > FLOW_INLINE_BYTES, + }; + } return { ...f, duplicates, duplicate_of_title: original?.title ?? null, + counts: { + seen: f.seen_count, + builds: f.builds_seen.length, + replay_attempts: f.replay?.attempts ?? null, + replay_reproduced: f.replay?.reproduced ?? null, + regression_runs: regression?.runs ?? 0, + }, + evidence, + replay_flow: replayFlow, + regression, + history: verdictHistory(id), + links: { + self: `/api/v1/findings/${id}`, + verdict: `/api/v1/findings/${id}/verdict`, + dashboard: `/dash/findings/${id}`, + }, }; } @@ -760,7 +1169,7 @@ export type PrecisionClass = { duplicate: number; not_a_bug: number; agent_mistake: number; - /** real + not_a_bug + agent_mistake. Duplicates say nothing about whether the check was right. */ + /** real (fixed included) + not_a_bug + agent_mistake. Duplicates say nothing about whether the check was right. */ judged: number; /** real / judged, or null before anything has been judged. */ precision: number | null; @@ -793,7 +1202,8 @@ export function precision(opts: { app?: string; min?: number } = {}) { c = { app: r.app, check: r.check_name, subclass: r.subclass || null, open: 0, real: 0, duplicate: 0, not_a_bug: 0, agent_mistake: 0, judged: 0, precision: null, disabled: false }; byKey.set(key, c); } - c[r.verdict ?? "open"] += r.n; + // A fixed finding was a real one: the check was right about it. + c[r.verdict === "fixed" ? "real" : r.verdict ?? "open"] += r.n; } const classes = [...byKey.values()].map((c) => { const judged = c.real + c.not_a_bug + c.agent_mistake; diff --git a/collector/src/workloads/explore/types.ts b/collector/src/workloads/explore/types.ts index 5997a39..7e0e8cc 100644 --- a/collector/src/workloads/explore/types.ts +++ b/collector/src/workloads/explore/types.ts @@ -305,5 +305,9 @@ export type ExploreFinding = { artifacts: { shot?: string; sheet?: string; trajectory?: string; log?: string; replay?: string }; }; -/** A person's verdict on a finding (T4). Also the training label if E8 ever happens. */ -export type Verdict = "real" | "duplicate" | "not_a_bug" | "agent_mistake"; +/** + * A person's verdict on a finding (T4). Also the training label if E8 ever happens. + * `fixed` comes only after `real`: the bug was real and a fix has merged, which + * is what makes its replay flow a regression test in the nightly. + */ +export type Verdict = "real" | "duplicate" | "not_a_bug" | "agent_mistake" | "fixed"; From 91dd4770d2f88a7d527e95f356eb79cec882263b Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 22:39:34 -0400 Subject: [PATCH 13/19] explore: load Holo4 at 45% free memory, not the shelf's 65% The 10-15 garden night skipped after ten minutes of "not loading holo4-35b-a3b: 56% free, needs 65%": ultra's resident models alone hold it near 56% free, so an explore night could never load its driver. Holo4 is about 25 GB; at 45% (~43 GB free) it leaves room. The owner chose this over unloading the shelf (which would take explore's own judge with it). Only explore's warm-up changes: the manifests pass WARM_MIN_FREE_PCT=45 to shelf.sh, whose default for everything else stays 65%, and it still refuses under memory pressure. ultra's ~/explore/env.sh exports the same, which is what covers the night already queued with the old commands. Co-Authored-By: Claude Opus 5.5 --- collector/deploy/explore/night/fleet-explore-apple.json | 2 +- collector/deploy/explore/night/fleet-explore-tv.json | 2 +- collector/deploy/explore/night/fleet-explore.json | 2 +- docs/deploy/explore-on-ultra.md | 2 +- docs/explore/troubleshooting.md | 6 ++++-- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/collector/deploy/explore/night/fleet-explore-apple.json b/collector/deploy/explore/night/fleet-explore-apple.json index 3665787..da2039a 100644 --- a/collector/deploy/explore/night/fleet-explore-apple.json +++ b/collector/deploy/explore/night/fleet-explore-apple.json @@ -4,7 +4,7 @@ "command": [ "bash", "-lc", - "source ~/explore/env.sh && cd ~/fleet-runner/collector && npx tsx scripts/explore-night.ts --sim fleet-explore-ios:com.apple.CoreSimulator.SimRuntime.iOS-26-5:com.apple.CoreSimulator.SimDeviceType.iPhone-16 --spec examples/jobs/explore-greenfolio-ios-ultra.json --tunnel runner-ts:192.168.50.27:8788 --fresh-build --warm \"bash ~/harness/shelf.sh warm pilot\"" + "source ~/explore/env.sh && cd ~/fleet-runner/collector && npx tsx scripts/explore-night.ts --sim fleet-explore-ios:com.apple.CoreSimulator.SimRuntime.iOS-26-5:com.apple.CoreSimulator.SimDeviceType.iPhone-16 --spec examples/jobs/explore-greenfolio-ios-ultra.json --tunnel runner-ts:192.168.50.27:8788 --fresh-build --warm \"WARM_MIN_FREE_PCT=45 bash ~/harness/shelf.sh warm pilot\"" ], "priority": 86, "needs_gb": 35, diff --git a/collector/deploy/explore/night/fleet-explore-tv.json b/collector/deploy/explore/night/fleet-explore-tv.json index 31fb525..c3d188a 100644 --- a/collector/deploy/explore/night/fleet-explore-tv.json +++ b/collector/deploy/explore/night/fleet-explore-tv.json @@ -4,7 +4,7 @@ "command": [ "bash", "-lc", - "source ~/explore/env.sh && cd ~/fleet-runner/collector && npx tsx scripts/explore-night.ts --sim fleet-explore-tvos:com.apple.CoreSimulator.SimRuntime.tvOS-26-5:com.apple.CoreSimulator.SimDeviceType.Apple-TV-4K-3rd-generation-1080p --spec examples/jobs/explore-tvos-bench-pilot-ultra.json --spec examples/jobs/explore-tvos-bench-vision-ultra.json --spec examples/jobs/explore-dozehound-tvos-ultra.json --tunnel runner-ts:192.168.50.27:8788 --fresh-build --warm \"bash ~/harness/shelf.sh warm pilot\"" + "source ~/explore/env.sh && cd ~/fleet-runner/collector && npx tsx scripts/explore-night.ts --sim fleet-explore-tvos:com.apple.CoreSimulator.SimRuntime.tvOS-26-5:com.apple.CoreSimulator.SimDeviceType.Apple-TV-4K-3rd-generation-1080p --spec examples/jobs/explore-tvos-bench-pilot-ultra.json --spec examples/jobs/explore-tvos-bench-vision-ultra.json --spec examples/jobs/explore-dozehound-tvos-ultra.json --tunnel runner-ts:192.168.50.27:8788 --fresh-build --warm \"WARM_MIN_FREE_PCT=45 bash ~/harness/shelf.sh warm pilot\"" ], "priority": 85, "needs_gb": 35, diff --git a/collector/deploy/explore/night/fleet-explore.json b/collector/deploy/explore/night/fleet-explore.json index efcce5c..2ea313e 100644 --- a/collector/deploy/explore/night/fleet-explore.json +++ b/collector/deploy/explore/night/fleet-explore.json @@ -4,7 +4,7 @@ "command": [ "bash", "-lc", - "source ~/explore/env.sh && cd ~/fleet-runner/collector && npx tsx scripts/explore-night.ts --spec examples/jobs/explore-garden-ultra.json --avd fleet-explore-1 --tunnel runner-ts:192.168.50.27:8788 --warm \"bash ~/harness/shelf.sh warm pilot\"" + "source ~/explore/env.sh && cd ~/fleet-runner/collector && npx tsx scripts/explore-night.ts --spec examples/jobs/explore-garden-ultra.json --avd fleet-explore-1 --tunnel runner-ts:192.168.50.27:8788 --warm \"WARM_MIN_FREE_PCT=45 bash ~/harness/shelf.sh warm pilot\"" ], "priority": 20, "needs_gb": 35, diff --git a/docs/deploy/explore-on-ultra.md b/docs/deploy/explore-on-ultra.md index bf367b0..9ef583d 100644 --- a/docs/deploy/explore-on-ultra.md +++ b/docs/deploy/explore-on-ultra.md @@ -23,7 +23,7 @@ LaunchDaemons. Explore plugs into that rather than running its own. | The emulator | AVD `fleet-explore-1`, android-35 `google_apis`, 1080×2400 at 420 dpi | | Holo4 | `~/.lmstudio/models/Hcompany/Holo4-35B-A3B-GGUF/`: the vendor's Q4_K_M and its vision projector, renamed to LM Studio's convention (`Holo4-35B-A3B-Q4_K_M.gguf`, `mmproj-Holo4-35B-A3B-F16.gguf`) or LM Studio lists the projector as a separate model and cannot pair them. Model key `holo4-35b-a3b`, identifier `holo4-35b-a3b-gguf` | | The gateway name | `pilot` in the harness's `litellm.yaml`: Holo4, 300 s timeout, no fallback. The judge is the harness's `judge` role | -| The shelf | `ondemand holo4-35b-a3b@holo4-35b-a3b-gguf 65536 1 3600` in `~/harness/shelf.conf`; `bash ~/harness/shelf.sh warm pilot` loads it when at least 65% of memory is free. The night command runs it (`--warm`) after its own checks, and retries a refusal for memory for ten minutes | +| The shelf | `ondemand holo4-35b-a3b@holo4-35b-a3b-gguf 65536 1 3600` in `~/harness/shelf.conf`; `bash ~/harness/shelf.sh warm pilot` loads it when enough memory is free: 65% by default, 45% for explore, which sets `WARM_MIN_FREE_PCT=45` in its manifests and in `~/explore/env.sh` (the resident models keep ultra near 56% free, so at 65% Holo4 never loaded; at 45% its ~25 GB leaves about 29 GB). The shelf still refuses under memory pressure. The night command runs it (`--warm`) after its own checks, and retries a refusal for memory for ten minutes | | The key | `~/.config/harness/keys/fleet.key` (roles `pilot`, `judge`, `vision`). Not the Keychain: neither SSH nor a LaunchDaemon can write the login Keychain on ultra. The workload reads `HARNESS_KEY`, then this file | | The night | `~/night/recurring/fleet-explore.json`, run by the harness's night queue from 22:00 when memory pressure is normal, 35 GB is free and no CI job is running | | The brain | On fleet-host, which ultra cannot route to. The night command opens `ssh -L 18788:192.168.50.27:8788 runner-ts` for the length of the run | diff --git a/docs/explore/troubleshooting.md b/docs/explore/troubleshooting.md index 2e4e070..237eec0 100644 --- a/docs/explore/troubleshooting.md +++ b/docs/explore/troubleshooting.md @@ -102,8 +102,10 @@ explore job itself, which is why it exits 0. The shelf refused to load the model for memory, and kept refusing for `--warm-wait` minutes (default 10). The night queue admits a job on free memory as `vm_stat` counts it (`needs_gb` in the manifest); the shelf decides -on `memory_pressure`'s free percentage (65% for an on-demand model). They can -disagree by a point, which is how 10-14's Apple night died. Check what else +on `memory_pressure`'s free percentage (65% for an on-demand model by +default; explore's warm-up asks for 45% with `WARM_MIN_FREE_PCT`). They can +disagree by a point, which is how 10-14's Apple night died, and on 10-15 the +resident models alone held ultra at 56% free, under the old 65%. Check what else was loaded with `~/.lmstudio/bin/lms ps`. Any other warm-up failure is a failure, not a skip, and its last line is the job's error. From 60ce97c644d0055bc1d1cfb0add1f957e95207b0 Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 22:39:45 -0400 Subject: [PATCH 14/19] changelog: explore warm threshold (#95) Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5aba0f7..0743d71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,12 @@ a CI job fails when they disagree. ### Changed +- **Explore loads its model at 45% free memory, not 65%.** ultra's resident + models alone hold it near 56% free, so the shelf's default bar meant no + explore night could load Holo4 (~25 GB); 10-15's garden night skipped for + it. The night manifests pass `WARM_MIN_FREE_PCT=45` to the warm-up; the + shelf's default for everything else is unchanged, and it still refuses + under memory pressure. ([#95](https://github.com/addisdev/fleet-runner/pull/95)) - **`ci-enqueue` speaks `/api/v1` and exits like `fleetr run`.** It polled the deprecated `GET /jobs/:id` and exited 0 on `done`, which includes a job that skipped and tested nothing, and it sent no token, so it failed against a From 822f812cd59d00f3084be560d1366cdffa948519 Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 22:43:57 -0400 Subject: [PATCH 15/19] Findings reach the code: /api/v1 findings, fleetr and MCP, fixed findings become nightly regression tests Co-Authored-By: Claude Opus 5.5 --- collector/dash/src/api.ts | 18 +- collector/dash/src/keys.ts | 2 +- collector/dash/src/pages/Findings.tsx | 55 +- collector/openapi.json | 1027 ++++++++++++++++++- collector/schemas/job.schema.json | 2 +- collector/schemas/result.schema.json | 14 +- collector/scripts/check-api-v1.ts | 37 + collector/scripts/check-auth.ts | 8 + collector/scripts/smoke.ts | 39 + collector/src/api/v1/openapi.ts | 1 + collector/src/api/v1/routes.ts | 111 +- collector/src/api/v1/schemas.ts | 124 ++- collector/src/client/api.gen.ts | 184 +++- collector/src/executor.ts | 66 +- collector/src/findings.test.ts | 139 ++- collector/src/workloads/regressions.test.ts | 91 ++ collector/src/workloads/regressions.ts | 220 ++++ docs/agents.md | 61 +- docs/api.md | 20 +- docs/dashboard.md | 6 +- docs/explore/findings.md | 81 +- docs/workloads/host.md | 44 + fleet/src/mcp/protocol.ts | 4 +- fleet/src/mcp/tools.ts | 168 +++ fleet/src/work.ts | 115 ++- fleet/test/cli.test.ts | 36 +- fleet/test/helpers.ts | 19 + fleet/test/mcp.test.ts | 32 +- skills/fleet-runner/SKILL.md | 26 + 29 files changed, 2684 insertions(+), 66 deletions(-) create mode 100644 collector/src/workloads/regressions.test.ts create mode 100644 collector/src/workloads/regressions.ts diff --git a/collector/dash/src/api.ts b/collector/dash/src/api.ts index 2e13d0a..6c895cf 100644 --- a/collector/dash/src/api.ts +++ b/collector/dash/src/api.ts @@ -367,7 +367,9 @@ export type Health = { // --- night-QA findings (mirrors src/findings.ts) --- -export type FindingVerdict = "real" | "duplicate" | "not_a_bug" | "agent_mistake"; +export type FindingVerdict = "real" | "duplicate" | "not_a_bug" | "agent_mistake" | "fixed"; + +export type RegressionState = "candidate" | "active" | "retired"; export type FindingIssue = { state: "dry_run" | "pending" | "filed" | "failed" | "capped" | "no_repo"; @@ -415,11 +417,25 @@ export type Finding = { duplicate_of: number | null; issue: FindingIssue | null; status: "open" | "triaged"; + /** The regression test it became: a candidate once real, active (in the nightly) once fixed. */ + regression: { state: RegressionState; kind: string; last_outcome: string | null } | null; }; export type FindingDetail = Finding & { duplicates: { id: number; title: string; seen_count: number }[]; duplicate_of_title: string | null; + regression: { + state: RegressionState; + kind: string; + asserts: "no_crash" | "replays"; + runs: number; + activated_at: string | null; + last_run_at: string | null; + last_job_id: string | null; + last_outcome: string | null; + last_detail: string | null; + } | null; + history: { at: string | null; event: "verdict" | "regressed"; verdict: FindingVerdict | null; note: string | null; actor: string | null }[]; }; export type FindingList = { diff --git a/collector/dash/src/keys.ts b/collector/dash/src/keys.ts index 8d4a966..34f2809 100644 --- a/collector/dash/src/keys.ts +++ b/collector/dash/src/keys.ts @@ -21,7 +21,7 @@ const GOTO: Record = { export const SHORTCUTS = [ ...Object.entries(GOTO).map(([k, [, label]]) => ({ keys: `g ${k}`, does: label })), { keys: "/", does: "Focus the search box on this screen" }, - { keys: "r d n a", does: "On a finding: Real, Duplicate, Not a bug, Agent's mistake" }, + { keys: "r d n a f", does: "On a finding: Real, Duplicate, Not a bug, Agent's mistake, Fixed (after Real)" }, { keys: "?", does: "Show this help" }, { keys: "Esc", does: "Close help, or leave the search box" }, ]; diff --git a/collector/dash/src/pages/Findings.tsx b/collector/dash/src/pages/Findings.tsx index edddbaa..1bfc842 100644 --- a/collector/dash/src/pages/Findings.tsx +++ b/collector/dash/src/pages/Findings.tsx @@ -28,6 +28,7 @@ export const VERDICT_LABEL: Record = { duplicate: "Duplicate", not_a_bug: "Not a bug", agent_mistake: "Agent's mistake", + fixed: "Fixed", }; const VERDICT_PILL: Record = { @@ -35,6 +36,7 @@ const VERDICT_PILL: Record = { duplicate: "queued", not_a_bug: "cancelled", agent_mistake: "cancelled", + fixed: "done", }; /** reproduced N/N is solid, flaky is a warning, a crash log is its own evidence. */ @@ -231,7 +233,9 @@ const typing = (t: EventTarget | null) => { /** * The four buttons, the note, and the duplicate picker. * - * r / d / n / a do the same as the buttons. They are ignored straight after a + * r / d / n / a / f do the same as the buttons. Fixed is offered only once a + * finding is real (the collector refuses it otherwise): it makes the finding's + * replay flow a regression test in the app's nightly. They are ignored straight after a * `g`, because "g r" is already "go to Results" and a shortcut that filed a * verdict on the way out of the page would be a nasty surprise. */ @@ -243,6 +247,8 @@ function VerdictBox({ f, onDone }: { f: Detail; onDone: () => void }) { const others = useApi(picking ? `/api/findings?app=${encodeURIComponent(f.app)}&status=all&limit=200` : null); const [pending, setPending] = useState(null); + // Fixed follows real, or a regression test that brought the finding back. + const canFix = f.verdict === "real" || f.verdict === "fixed" || f.regression?.state === "active"; const send = useMutation(async () => { const body: Record = { verdict: pending, note: note.trim() || null }; if (pending === "duplicate") body.duplicate_of = Number(dupOf); @@ -288,7 +294,8 @@ function VerdictBox({ f, onDone }: { f: Detail; onDone: () => void }) { afterG = false; return; } - const v = ({ r: "real", d: "duplicate", n: "not_a_bug", a: "agent_mistake" } as Record)[e.key]; + const v = ({ r: "real", d: "duplicate", n: "not_a_bug", a: "agent_mistake", f: "fixed" } as Record)[e.key]; + if (v === "fixed" && !canFix) return; if (v) { e.preventDefault(); judge(v); @@ -299,7 +306,7 @@ function VerdictBox({ f, onDone }: { f: Detail; onDone: () => void }) { removeEventListener("keydown", onKey); clearTimeout(timer); }; - }, [f.id, note]); + }, [f.id, note, canFix]); const candidates = (others.data?.findings ?? []).filter((o) => o.id !== f.id); return ( @@ -310,7 +317,7 @@ function VerdictBox({ f, onDone }: { f: Detail; onDone: () => void }) { {VERDICT_LABEL[f.verdict]} · {clock(f.verdict_at)}{" "} - ) : keys: r d n a} + ) : keys: r d n a f} >

{(Object.keys(VERDICT_LABEL) as FindingVerdict[]).map((v) => ( @@ -318,12 +325,14 @@ function VerdictBox({ f, onDone }: { f: Detail; onDone: () => void }) { key={v} tone={f.verdict === v ? "primary" : undefined} busy={send.busy && pending === v} + disabled={v === "fixed" && !canFix} onClick={() => judge(v)} title={{ real: "A bug in the app. Counts towards this check's precision.", duplicate: "The same problem as another finding. Left out of precision.", not_a_bug: "The app is fine; the check was wrong. Counts against this check.", agent_mistake: "The model did something silly and the app reacted correctly. Counts against this check.", + fixed: "Real, and a fix has merged. Its replay flow joins the app's nightly ui-test as a regression test. Only after Real.", }[v]} > {v === "not_a_bug" ? "n" : v[0]} {VERDICT_LABEL[v]} @@ -398,6 +407,42 @@ function IssuePanel({ issue }: { issue: NonNullable }) { ); } +const REGRESSION_LABEL: Record["state"], string> = { + candidate: "candidate — joins the nightly when marked fixed", + active: "active — in the nightly", + retired: "retired", +}; + +/** The regression test a real finding became, and the verdict history that moved it. */ +function RegressionPanel({ r, history }: { r: NonNullable; history: Detail["history"] }) { + return ( + {REGRESSION_LABEL[r.state]}} + > +

+ {r.kind} flow · {r.asserts === "no_crash" ? "asserts the app does not crash during it" : "asserts only that it replays without error"} + {" "}· run {r.runs}× + {r.last_outcome && <> · last {r.last_outcome}{r.last_run_at ? ` ${agoFrom(r.last_run_at)}` : ""}} + {r.last_job_id && <> in {r.last_job_id}} +

+ {r.last_detail &&

{r.last_detail}

} + {history.length > 0 && ( +
    + {history.map((h, i) => ( +
  • + {clock(h.at)}{" "} + {h.event === "regressed" ? "regressed" : h.verdict ? VERDICT_LABEL[h.verdict] : "reopened"} + {h.actor && · {h.actor}} + {h.note && <> — {h.note}} +
  • + ))} +
+ )} +
+ ); +} + export function FindingPage({ id }: { id: string }) { const state = useApi(`/api/findings/${encodeURIComponent(id)}`, ["finding"]); const names = useDeviceNames(); @@ -494,6 +539,8 @@ export function FindingPage({ id }: { id: string }) { )} + {f.regression && } + {f.issue && } diff --git a/collector/openapi.json b/collector/openapi.json index 348612f..56b2d27 100644 --- a/collector/openapi.json +++ b/collector/openapi.json @@ -45,6 +45,10 @@ "name": "artifacts", "description": "Screenshots, logs, reports, builds." }, + { + "name": "findings", + "description": "What night QA found, its verdicts, and the regression tests fixed findings became." + }, { "name": "fleet", "description": "Schedules, alerts, audit." @@ -607,7 +611,7 @@ } }, "400": { - "description": "The request was malformed or the spec is invalid.", + "description": "Malformed or refused before queueing: invalid_spec, no_matching_devices (no registered device matches the targets), no_build (no artifact for app `latest`), invalid_match, invalid_dependency, secret_in_spec, bad_request.", "content": { "application/json": { "schema": { @@ -647,7 +651,7 @@ } }, "422": { - "description": "Valid, but nothing can run it (no capable agent, no matching device, no build).", + "description": "Valid, but cannot be queued: no_capable_agent (nothing declares the workload), unresolved_reference (a template reference that does not resolve).", "content": { "application/json": { "schema": { @@ -1286,6 +1290,256 @@ } } }, + "/api/v1/findings": { + "get": { + "operationId": "listFindings", + "summary": "What night QA (the explore workload) found, newest sighting first.", + "description": "Each finding was replayed on a clean install before it was filed; `replay_label` says how often it reproduced. verdict agent_mistake means the model misread the app, not a bug in it. since=24h is the morning brief.", + "tags": [ + "findings" + ], + "x-fleet-scope": "read", + "x-fleet-read-only": true, + "x-fleet-idempotent": true, + "parameters": [ + { + "name": "app", + "in": "query", + "required": false, + "description": "Only this app (the explore app key).", + "schema": { + "type": "string" + } + }, + { + "name": "state", + "in": "query", + "required": false, + "description": "open: no verdict yet (or reopened by a regression). Default all.", + "schema": { + "type": "string", + "enum": [ + "open", + "triaged", + "all" + ] + } + }, + { + "name": "verdict", + "in": "query", + "required": false, + "description": "Comma-separated: real, duplicate, not_a_bug, agent_mistake, fixed.", + "schema": { + "type": "string" + } + }, + { + "name": "check", + "in": "query", + "required": false, + "description": "crash, anr, frozen, blank, left_app, a11y, visual, goal, dead_control.", + "schema": { + "type": "string" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "description": "Last seen at or after: ISO 8601, or a span back from now such as 90m, 24h, 7d.", + "schema": { + "type": "string" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "description": "1-based page.", + "schema": { + "type": "integer", + "default": 1, + "minimum": 1 + } + }, + { + "name": "per_page", + "in": "query", + "required": false, + "description": "Items per page.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 500 + } + } + ], + "responses": { + "200": { + "description": "Findings.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FindingList" + } + } + } + }, + "400": { + "description": "The request was malformed or the spec is invalid.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/v1/findings/{id}": { + "get": { + "operationId": "getFinding", + "summary": "One finding: the steps in words, its evidence as links, the replay flow (inline when small), its regression test and verdict history.", + "tags": [ + "findings" + ], + "x-fleet-scope": "read", + "x-fleet-read-only": true, + "x-fleet-idempotent": true, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The finding's id.", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "The finding.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FindingDetail" + } + } + } + }, + "404": { + "description": "No such thing.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/v1/findings/{id}/verdict": { + "post": { + "operationId": "setFindingVerdict", + "summary": "Judge a finding: real, duplicate, not_a_bug, agent_mistake, or fixed (only after real). null reopens.", + "description": "real keeps the finding's replay flow as a candidate regression test; fixed makes it active, so the app's nightly ui-test (with params.regressions) runs it. duplicate, not_a_bug and agent_mistake retire it. Mark fixed only once a fix has merged. Each verdict counts towards the check's precision, which decides what night QA runs tomorrow.", + "tags": [ + "findings" + ], + "x-fleet-scope": "run", + "x-fleet-idempotent": true, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The finding's id.", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "description": "The verdict and an optional note.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FindingVerdictInput" + } + } + } + }, + "responses": { + "200": { + "description": "Recorded.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FindingVerdictResult" + } + } + } + }, + "400": { + "description": "The request was malformed or the spec is invalid.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "A token is required (FLEET_AUTH=tokens).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "The token lacks the scope, or the job is someone else's.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "No such thing.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "409": { + "description": "fixed on a finding that is not real (conflict).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, "/api/v1/schedules": { "get": { "operationId": "listSchedules", @@ -1512,7 +1766,7 @@ "post": { "operationId": "uploadArtifact", "summary": "Upload bytes (application/octet-stream). Answers with the sha256 and the detected media type.", - "description": "Headers: x-artifact-name, x-artifact-media-type (optional), x-artifact-app, x-artifact-build.", + "description": "Headers: x-artifact-name, x-artifact-media-type (optional), x-artifact-app, x-artifact-build, x-artifact-channel (optional: `pr` for a pull request's build, which `\"sha256\": \"latest\"` never resolves to; absent means a merged build).", "tags": [ "protocol" ], @@ -1524,39 +1778,98 @@ } } }, - "/artifacts/{sha256}": { + "/findings": { + "post": { + "operationId": "postFinding", + "summary": "The explore workload filing a finding (an ExploreFinding). Upserts on the fingerprint.", + "tags": [ + "protocol" + ], + "x-fleet-scope": "protocol", + "responses": { + "200": { + "description": "Seen again." + }, + "201": { + "description": "New." + } + } + } + }, + "/findings/regressions": { "get": { - "operationId": "downloadArtifact", - "summary": "The bytes as application/octet-stream, with Range support. Runners fetch models and builds here.", + "operationId": "listRegressionFlows", + "summary": "A nightly ui-test pulling an app's regression flows (?app= &state=active &platform=).", + "tags": [ + "protocol" + ], + "x-fleet-scope": "protocol", + "responses": { + "200": { + "description": "{regressions: [...]}, each with its flow text." + } + } + } + }, + "/findings/{id}/regression": { + "post": { + "operationId": "postRegressionRun", + "summary": "An executor reporting one regression run: {job_id, device_id, build, outcome: passed|reproduced|failed|skipped, detail}. reproduced reopens the finding.", "tags": [ "protocol" ], "x-fleet-scope": "protocol", "parameters": [ { - "name": "sha256", + "name": "id", "in": "path", "required": true, - "description": "The artifact's sha256 (64 hex).", + "description": "The finding's id.", "schema": { - "type": "string" + "type": "integer" } } ], "responses": { "200": { - "description": "The bytes.", - "content": { - "application/octet-stream": {} - } + "description": "Recorded." } } } - } - }, - "components": { - "schemas": { - "Alert": { + }, + "/artifacts/{sha256}": { + "get": { + "operationId": "downloadArtifact", + "summary": "The bytes as application/octet-stream, with Range support. Runners fetch models and builds here.", + "tags": [ + "protocol" + ], + "x-fleet-scope": "protocol", + "parameters": [ + { + "name": "sha256", + "in": "path", + "required": true, + "description": "The artifact's sha256 (64 hex).", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The bytes.", + "content": { + "application/octet-stream": {} + } + } + } + } + } + }, + "components": { + "schemas": { + "Alert": { "type": "object", "properties": { "id": { @@ -1680,6 +1993,13 @@ "pinned": { "type": "boolean" }, + "channel": { + "enum": [ + "main", + "pr" + ], + "description": "pr: uploaded from a pull request (x-artifact-channel: pr); `\"sha256\": \"latest\"` never resolves to it. main: everything else." + }, "in_store": { "type": "boolean" }, @@ -1692,6 +2012,7 @@ "name", "size", "media_type", + "channel", "in_store", "url" ] @@ -2292,6 +2613,674 @@ "error" ] }, + "Finding": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "fingerprint": { + "type": "string" + }, + "app": { + "type": "string", + "description": "The explore app key the finding was filed under." + }, + "build": { + "type": "string", + "description": "The build it was first seen on." + }, + "platform": { + "type": "string" + }, + "device_id": { + "type": "string" + }, + "job_id": { + "type": "string", + "description": "The job that first found it." + }, + "last_job_id": { + "type": [ + "string", + "null" + ] + }, + "mission_id": { + "type": "string" + }, + "check": { + "type": "string", + "description": "crash, anr, frozen, blank, left_app, a11y, visual, goal, dead_control." + }, + "severity": { + "enum": [ + "high", + "medium", + "low" + ] + }, + "title": { + "type": "string" + }, + "detail": { + "type": "string" + }, + "screen": { + "type": "string" + }, + "screen_name": { + "type": "string" + }, + "steps": { + "type": "array", + "items": { + "type": "string" + }, + "description": "What to do to see it, in words, one step per entry." + }, + "replay": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "object", + "properties": { + "kind": { + "enum": [ + "maestro", + "tvloop", + "none" + ] + }, + "sha256": { + "type": [ + "string", + "null" + ] + }, + "attempts": { + "type": "integer" + }, + "reproduced": { + "type": "integer" + } + }, + "required": [ + "kind", + "sha256", + "attempts", + "reproduced" + ] + } + ], + "description": "The replay on a clean install: how many of `attempts` reproduced it. null only for a crash, whose crash log is the evidence." + }, + "replay_label": { + "type": "string", + "description": "reproduced 2/2, flaky 1/2, crash log." + }, + "artifacts": { + "type": "object", + "description": "Artifact sha256s by role: shot, sheet, trajectory, log, replay." + }, + "first_seen": { + "type": [ + "string", + "null" + ] + }, + "last_seen": { + "type": [ + "string", + "null" + ] + }, + "seen_count": { + "type": "integer" + }, + "builds_seen": { + "type": "array", + "items": { + "type": "string" + } + }, + "verdict": { + "enum": [ + "real", + "duplicate", + "not_a_bug", + "agent_mistake", + "fixed", + null + ], + "description": "null: nobody has judged it, or a regression test reopened it. agent_mistake is NOT a bug in the app." + }, + "verdict_note": { + "type": [ + "string", + "null" + ] + }, + "verdict_at": { + "type": [ + "string", + "null" + ] + }, + "duplicate_of": { + "type": [ + "integer", + "null" + ] + }, + "issue": { + "type": [ + "object", + "null" + ], + "description": "The GitHub issue it would file, or did; dry_run true means nothing was sent." + }, + "status": { + "enum": [ + "open", + "triaged" + ] + }, + "regression": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "object", + "properties": { + "state": { + "enum": [ + "candidate", + "active", + "retired" + ] + }, + "kind": { + "enum": [ + "maestro", + "tvloop" + ] + }, + "last_outcome": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "state", + "kind", + "last_outcome" + ] + } + ], + "description": "The regression test it became: candidate once real, active (in the nightly) once fixed." + } + }, + "required": [ + "id", + "fingerprint", + "app", + "build", + "platform", + "device_id", + "job_id", + "mission_id", + "check", + "severity", + "title", + "detail", + "screen_name", + "steps", + "replay", + "replay_label", + "artifacts", + "seen_count", + "builds_seen", + "verdict", + "status", + "first_seen", + "last_seen", + "regression" + ] + }, + "FindingDetail": { + "allOf": [ + { + "$ref": "#/components/schemas/Finding" + }, + { + "type": "object", + "properties": { + "duplicates": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "seen_count": { + "type": "integer" + } + }, + "required": [ + "id", + "title", + "seen_count" + ] + } + }, + "duplicate_of_title": { + "type": [ + "string", + "null" + ] + }, + "counts": { + "type": "object", + "properties": { + "seen": { + "type": "integer" + }, + "builds": { + "type": "integer" + }, + "replay_attempts": { + "type": [ + "integer", + "null" + ] + }, + "replay_reproduced": { + "type": [ + "integer", + "null" + ] + }, + "regression_runs": { + "type": "integer" + } + }, + "required": [ + "seen", + "builds", + "replay_attempts", + "replay_reproduced", + "regression_runs" + ] + }, + "evidence": { + "type": "array", + "items": { + "type": "object", + "properties": { + "role": { + "enum": [ + "shot", + "sheet", + "trajectory", + "log", + "replay" + ] + }, + "label": { + "type": "string" + }, + "sha256": { + "type": "string" + }, + "url": { + "type": "string", + "description": "The bytes, relative to the collector." + }, + "in_store": { + "type": "boolean" + } + }, + "required": [ + "role", + "label", + "sha256", + "url", + "in_store" + ] + } + }, + "replay_flow": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string" + }, + "sha256": { + "type": "string" + }, + "url": { + "type": "string" + }, + "in_store": { + "type": "boolean" + }, + "text": { + "type": [ + "string", + "null" + ], + "description": "The flow itself when it is at most 16 KiB; otherwise fetch url." + }, + "truncated": { + "type": "boolean", + "description": "True when the flow was too big to inline." + } + }, + "required": [ + "kind", + "sha256", + "url", + "in_store", + "text", + "truncated" + ] + } + ], + "description": "The Maestro (or tvloop) flow that replays the finding's steps." + }, + "regression": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "object", + "properties": { + "finding_id": { + "type": "integer" + }, + "app": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "check": { + "type": "string" + }, + "kind": { + "enum": [ + "maestro", + "tvloop" + ] + }, + "state": { + "enum": [ + "candidate", + "active", + "retired" + ] + }, + "asserts": { + "enum": [ + "no_crash", + "replays" + ], + "description": "no_crash for crash and anr findings; replays (without error) for every other check." + }, + "flow": { + "type": "string", + "description": "The flow text the nightly runs, copied when the finding was marked real." + }, + "flow_sha256": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": [ + "string", + "null" + ] + }, + "activated_at": { + "type": [ + "string", + "null" + ] + }, + "retired_at": { + "type": [ + "string", + "null" + ] + }, + "runs": { + "type": "integer" + }, + "last_run_at": { + "type": [ + "string", + "null" + ] + }, + "last_job_id": { + "type": [ + "string", + "null" + ] + }, + "last_outcome": { + "enum": [ + "passed", + "reproduced", + "failed", + "skipped", + null + ] + }, + "last_detail": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "finding_id", + "state", + "kind", + "asserts", + "flow", + "runs" + ] + } + ] + }, + "history": { + "type": "array", + "items": { + "type": "object", + "properties": { + "at": { + "type": [ + "string", + "null" + ] + }, + "event": { + "enum": [ + "verdict", + "regressed" + ] + }, + "verdict": { + "enum": [ + "real", + "duplicate", + "not_a_bug", + "agent_mistake", + "fixed", + null + ] + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "actor": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "at", + "event", + "verdict", + "note" + ] + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "verdict": { + "type": "string" + }, + "dashboard": { + "type": "string" + } + }, + "required": [ + "self", + "verdict", + "dashboard" + ] + } + }, + "required": [ + "counts", + "evidence", + "replay_flow", + "regression", + "history", + "links" + ] + } + ] + }, + "FindingList": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Finding" + } + }, + "page": { + "type": "integer" + }, + "per_page": { + "type": "integer" + }, + "total": { + "type": "integer" + }, + "pages": { + "type": "integer" + } + }, + "required": [ + "items", + "page", + "per_page", + "total", + "pages" + ] + }, + "FindingVerdictInput": { + "type": "object", + "properties": { + "verdict": { + "enum": [ + "real", + "duplicate", + "not_a_bug", + "agent_mistake", + "fixed", + null + ], + "description": "fixed only after real, once the fix has merged. null reopens." + }, + "note": { + "type": [ + "string", + "null" + ], + "maxLength": 2000 + }, + "duplicate_of": { + "type": [ + "integer", + "null" + ], + "description": "Required with duplicate: the finding this one duplicates." + } + }, + "required": [ + "verdict" + ], + "additionalProperties": false + }, + "FindingVerdictResult": { + "type": "object", + "properties": { + "finding": { + "$ref": "#/components/schemas/FindingDetail" + }, + "change": { + "type": [ + "string", + "null" + ], + "description": "What the verdict did to the finding's regression test, in one sentence, or null." + } + }, + "required": [ + "finding", + "change" + ] + }, "FlakyCell": { "type": "object", "properties": { @@ -3015,7 +4004,7 @@ }, "params": { "type": "object", - "description": "Workload-specific. Deliberately open, but the fields the shipped workloads read are listed here so they are discoverable: benchmark/thermal prompt_tokens, gen_tokens, warmup_iters, measure_iters, duration_s; batch/vision/speech/embed input_sha256, max_items, max_tokens; cold-start app_id, launches, states; locale-shots locales; app-soak flow, duration_s, interval_s; a11y-audit steps, variants, min_target_pt, font_scale, tree_source; build repo, ref, kind, task, scheme; vantage urls, repeats; any host job network and network_to; a preempted job resume_from." + "description": "Workload-specific. Deliberately open, but the fields the shipped workloads read are listed here so they are discoverable: benchmark/thermal prompt_tokens, gen_tokens, warmup_iters, measure_iters, duration_s; batch/vision/speech/embed input_sha256, max_items, max_tokens; cold-start app_id, launches, states; locale-shots locales; app-soak flow, duration_s, interval_s; a11y-audit steps, variants, min_target_pt, font_scale, tree_source; build repo, ref, kind, task, scheme; vantage urls, repeats; ui-test regressions (true, or the app its findings are filed under: run its fixed findings' replay flows too); any host job network and network_to; a preempted job resume_from." }, "depends_on": { "type": "array", diff --git a/collector/schemas/job.schema.json b/collector/schemas/job.schema.json index 626c33d..09d68d6 100644 --- a/collector/schemas/job.schema.json +++ b/collector/schemas/job.schema.json @@ -89,7 +89,7 @@ }, "params": { "type": "object", - "description": "Workload-specific. Deliberately open, but the fields the shipped workloads read are listed here so they are discoverable: benchmark/thermal prompt_tokens, gen_tokens, warmup_iters, measure_iters, duration_s; batch/vision/speech/embed input_sha256, max_items, max_tokens; cold-start app_id, launches, states; locale-shots locales; app-soak flow, duration_s, interval_s; a11y-audit steps, variants, min_target_pt, font_scale, tree_source; build repo, ref, kind, task, scheme; vantage urls, repeats; any host job network and network_to; a preempted job resume_from." + "description": "Workload-specific. Deliberately open, but the fields the shipped workloads read are listed here so they are discoverable: benchmark/thermal prompt_tokens, gen_tokens, warmup_iters, measure_iters, duration_s; batch/vision/speech/embed input_sha256, max_items, max_tokens; cold-start app_id, launches, states; locale-shots locales; app-soak flow, duration_s, interval_s; a11y-audit steps, variants, min_target_pt, font_scale, tree_source; build repo, ref, kind, task, scheme; vantage urls, repeats; ui-test regressions (true, or the app its findings are filed under: run its fixed findings' replay flows too); any host job network and network_to; a preempted job resume_from." }, "depends_on": { "type": "array", diff --git a/collector/schemas/result.schema.json b/collector/schemas/result.schema.json index f1ab890..27e214e 100644 --- a/collector/schemas/result.schema.json +++ b/collector/schemas/result.schema.json @@ -220,7 +220,19 @@ "failed": { "type": "integer" }, "artifacts": { "type": "array", "items": { "type": "string" }, "description": "sha256 refs of screenshots/videos/junit uploaded to the artifact store" }, "skipped": { "type": "integer" }, - "failing_flow": { "type": "string", "description": "The first failing flow or test case, by name; the step that broke is in the row's error" } + "failing_flow": { "type": "string", "description": "The first failing flow or test case, by name; the step that broke is in the row's error" }, + "regressions": { + "type": "array", + "description": "ui-test with params.regressions: each fixed finding's replay flow run on this device. reproduced reopens the finding", + "items": { + "type": "object", + "properties": { + "finding_id": { "type": "integer" }, + "outcome": { "enum": ["passed", "reproduced", "failed", "skipped"] }, + "detail": { "type": "string" } + } + } + } } }, "shot": { diff --git a/collector/scripts/check-api-v1.ts b/collector/scripts/check-api-v1.ts index 25f8b31..02d118b 100644 --- a/collector/scripts/check-api-v1.ts +++ b/collector/scripts/check-api-v1.ts @@ -193,6 +193,43 @@ console.log("results, artifacts, fleet"); check("an HTML artifact is never served inline", (page.headers.get("content-disposition") ?? "").startsWith("attachment")); await refusal("a malformed sha is 400", fleet.getArtifact("nothex"), 400, "bad_request"); } +console.log("findings"); +{ + check("an artifact says its channel", (await fleet.getArtifact(art.sha256)).channel === "main"); + const flow = `appId: com.example.contract\n---\n- launchApp\n# ${DEVICE}\n`; + const up = await fetch(`${BASE}/artifacts`, { method: "POST", headers: { "content-type": "application/octet-stream", "x-artifact-name": "replay.yaml" }, body: flow }); + const flowSha = ((await up.json()) as { sha256: string }).sha256; + const app = `contract-${DEVICE}`; + const posted = await raw("POST", "/findings", { + fingerprint: `${app}-1`, app, build: "1.0 (1)", platform: "android", device_id: DEVICE, job_id: "contract-explore", mission_id: "m", + check: "crash", severity: "high", title: "Crashes on save", detail: "FATAL EXCEPTION", screen: "s1", screen_name: "Save", + steps: ["Open the app", "Tap Save"], replay: { kind: "maestro", sha256: flowSha, attempts: 2, reproduced: 2 }, + artifacts: { shot: art.sha256, replay: flowSha }, + }); + const id = String(((await posted.json()) as { id: number }).id); + const page = await fleet.listFindings({ app, since: "24h" }); + conforms("listFindings", "FindingList", page); + check("listFindings finds it, in the list envelope", page.items.length === 1 && page.total === 1 && page.items[0].verdict === null); + const one = await fleet.getFinding(id); + conforms("getFinding", "FindingDetail", one); + check("getFinding inlines the replay flow and links the evidence", + one.replay_flow?.text === flow && one.evidence.some((e) => e.role === "shot" && e.url.endsWith(`${art.sha256}/content`))); + await refusal("fixed before real is 409 conflict", fleet.setFindingVerdict(id, { verdict: "fixed" }), 409, "conflict"); + await refusal("an unknown verdict is 400", fleet.setFindingVerdict(id, { verdict: "meh" } as never), 400, "bad_request"); + const real = await fleet.setFindingVerdict(id, { verdict: "real", note: "contract" }); + conforms("setFindingVerdict (real)", "FindingVerdictResult", real); + check("real makes a candidate regression", real.finding.regression?.state === "candidate" && real.finding.history.length === 1); + const fixed = await fleet.setFindingVerdict(id, { verdict: "fixed" }); + check("fixed makes it active and says so", fixed.finding.regression?.state === "active" && /active/.test(fixed.change ?? "")); + conforms("listFindings (verdict=fixed)", "FindingList", await fleet.listFindings({ verdict: "fixed", app })); + await refusal("an unknown finding is 404", fleet.getFinding("999999999"), 404, "not_found"); + await refusal("a non-numeric finding id is 404", fleet.getFinding("abc"), 404, "not_found"); + await refusal("a bad since is 400", fleet.listFindings({ since: "whenever" }), 400, "bad_request"); + const audit = await fleet.listAudit({ per_page: 20 }); + check("a verdict is audited with its finding as the subject", + audit.items.some((a) => a.route === `/api/v1/findings/${id}/verdict` && a.subject === id && a.actor === "contract-check")); +} + conforms("listDevices", "DeviceList", await fleet.listDevices({ pool: "v1check" })); conforms("getDevice", "DeviceDetail", await fleet.getDevice(DEVICE)); conforms("listTemplates", "TemplateList", await fleet.listTemplates()); diff --git a/collector/scripts/check-auth.ts b/collector/scripts/check-auth.ts index 9d8ccf1..2ebd165 100644 --- a/collector/scripts/check-auth.ts +++ b/collector/scripts/check-auth.ts @@ -142,6 +142,14 @@ try { const denied = await call("POST", "/api/v1/jobs", { token: READ, body: spec }); check("read token cannot create a job: 403 insufficient_scope run", denied.status === 403 && denied.body.error.code === "insufficient_scope" && denied.body.error.required_scope === "run", JSON.stringify(denied.body)); check("read token cannot use the legacy enqueue either", (await call("POST", "/jobs", { token: READ, body: { ...spec, schema: 1, job_id: "legacy-denied" } })).status === 403); + const verdictDenied = await call("POST", "/api/v1/findings/1/verdict", { token: READ, body: { verdict: "real" } }); + check("read token cannot judge a finding: 403 insufficient_scope run", verdictDenied.status === 403 && verdictDenied.body.error.required_scope === "run", JSON.stringify(verdictDenied.body)); + const verdictRun = await call("POST", "/api/v1/findings/999999/verdict", { token: ALICE, body: { verdict: "real" } }); + check("a run token may judge one (this one does not exist: 404)", verdictRun.status === 404, JSON.stringify(verdictRun.body)); + check("read token can list findings", (await call("GET", "/api/v1/findings", { token: READ })).status === 200); + check("an agent token can pull regression flows", (await call("GET", "/findings/regressions?app=x", { token: AGENT })).status === 200); + check("an agent token can report a regression run (none here: 404)", + (await call("POST", "/findings/999999/regression", { token: AGENT, body: { job_id: "j", device_id: "d", outcome: "passed" } })).status === 404); check("audit needs admin", (await call("GET", "/api/v1/audit", { token: ALICE })).status === 403); check("admin can read the audit log", (await call("GET", "/api/v1/audit", { token: ADMIN })).status === 200); const w = await call("GET", "/api/v1/whoami", { token: ADMIN }); diff --git a/collector/scripts/smoke.ts b/collector/scripts/smoke.ts index 0183f5e..b652a20 100644 --- a/collector/scripts/smoke.ts +++ b/collector/scripts/smoke.ts @@ -30,6 +30,7 @@ import { runEnrolChecks } from "../src/workloads/enrol/enrol.test.js"; import { runTvloopChecks } from "../src/workloads/tvloop/tvloop.test.js"; import { runColdStartChecks } from "../src/workloads/cold-start/cold-start.test.js"; import { runFindingsChecks } from "../src/findings.test.js"; +import { runRegressionChecks } from "../src/workloads/regressions.test.js"; import { referenceDigest } from "./conformance.js"; import { redact, keychainPassword } from "../src/secrets.js"; @@ -2888,6 +2889,10 @@ await runColdStartChecks(check); // armed GitHub path and the digest timer, against a temp database of its own. await runFindingsChecks(check); +// The ui-test side of regression tests: which app, a stored flow made +// runnable, the crash-buffer judgement, and what each run reports. +await runRegressionChecks(check); + // --- night-QA findings, over HTTP --- // // What the explore workload's executor will actually do: post findings, post @@ -2983,6 +2988,40 @@ await runFindingsChecks(check); JSON.stringify(mine.map((r) => r.issue.state))); check("findings: the issue body is composed for audit", mine.some((r) => r.issue.body.includes("Tap Save") && r.issue.labels.includes("night-qa"))); + + // A finding becomes a regression test, over HTTP: the flow is uploaded the + // way the workload uploads it, real keeps it, fixed activates it, the + // nightly's pull sees it, and a reproduced run reopens the finding. + const flowText = `appId: com.example.smoke\nname: "smoke ${run}"\n---\n- launchApp:\n clearState: true\n`; + const upFlow = await fetch(`${BASE}/artifacts`, { + method: "POST", headers: { "content-type": "application/octet-stream", "x-artifact-name": `explore-finding-${run}.yaml` }, body: flowText, + }); + const flowSha = ((await upFlow.json()) as { sha256: string }).sha256; + const rf = await json("POST", "/findings", finding({ + fingerprint: `${APP}-fp-reg`, check: "crash", replay: { kind: "maestro", sha256: flowSha, attempts: 2, reproduced: 2 }, + artifacts: { replay: flowSha }, + })); + const rid = rf.body?.id; + const tooSoon = await json("POST", `/api/findings/${rid}/verdict`, { verdict: "fixed" }); + check("regressions: fixed before real is 409 on the dashboard's route too", tooSoon.status === 409, JSON.stringify(tooSoon.body)); + const real = await json("POST", `/api/findings/${rid}/verdict`, { verdict: "real" }); + check("regressions: real keeps the uploaded flow as a candidate", real.body?.regression?.state === "candidate" && + real.body.regression.flow === flowText, JSON.stringify(real.body?.regression)); + const fixed = await json("POST", `/api/findings/${rid}/verdict`, { verdict: "fixed", note: "PR #1" }); + check("regressions: fixed activates it", fixed.status === 200 && fixed.body?.regression?.state === "active"); + const pulled = await json("GET", `/findings/regressions?app=${APP}`); + check("regressions: GET /findings/regressions is what the nightly pulls", + pulled.status === 200 && pulled.body?.regressions?.length === 1 && pulled.body.regressions[0].flow === flowText, JSON.stringify(pulled.body)); + check("regressions: a bad state filter is 400", (await json("GET", "/findings/regressions?state=maybe")).status === 400); + const runBody = { job_id: `smoke-ui-${run}`, device_id: DEVICE, build: "9.9 (1)", outcome: "reproduced", detail: "crashed again" }; + const rep = await json("POST", `/findings/${rid}/regression`, runBody); + check("regressions: a reproduced run reopens the finding", rep.status === 200 && rep.body?.reopened === true, JSON.stringify(rep.body)); + const after = await json("GET", `/api/findings/${rid}`); + check("regressions: reopened, counted, with the build and a history line", + after.body?.verdict === null && after.body?.builds_seen?.includes("9.9 (1)") && + after.body?.history?.at(-1)?.event === "regressed" && /regressed on build 9\.9 \(1\)/.test(after.body.history.at(-1).note), JSON.stringify(after.body?.history)); + check("regressions: a bad run body is 400", (await json("POST", `/findings/${rid}/regression`, { ...runBody, outcome: "meh" })).status === 400); + check("regressions: a run for a finding with no test is 404", (await json("POST", "/findings/999999999/regression", runBody)).status === 404); } // --- the synthetic backend's reference digest --- diff --git a/collector/src/api/v1/openapi.ts b/collector/src/api/v1/openapi.ts index 3798863..cede04d 100644 --- a/collector/src/api/v1/openapi.ts +++ b/collector/src/api/v1/openapi.ts @@ -104,6 +104,7 @@ export function openapiDocument() { { name: "jobs", description: "Queue, validate, wait for, cancel and retry work." }, { name: "results", description: "What ran and how it went." }, { name: "artifacts", description: "Screenshots, logs, reports, builds." }, + { name: "findings", description: "What night QA found, its verdicts, and the regression tests fixed findings became." }, { name: "fleet", description: "Schedules, alerts, audit." }, { name: "protocol", description: "What runners speak. Not for composing work." }, ], diff --git a/collector/src/api/v1/routes.ts b/collector/src/api/v1/routes.ts index 8207281..8db4272 100644 --- a/collector/src/api/v1/routes.ts +++ b/collector/src/api/v1/routes.ts @@ -23,7 +23,7 @@ import { createReadStream, existsSync, statSync } from "node:fs"; import { randomBytes } from "node:crypto"; import path from "node:path"; import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; -import { onAnnounce } from "../../announce.js"; +import { announce, onAnnounce } from "../../announce.js"; import { authOf, forward, type Scope } from "../../auth.js"; import { ARTIFACT_DIR, AUTH, AUTH_PROTOCOL } from "../../config.js"; import { APP_VERSION } from "../../version.js"; @@ -37,6 +37,7 @@ import { schedulesView } from "../system.js"; import { SCHEMAS } from "./schemas.js"; import { isSkipError } from "../../skip.js"; import { errorsOf, paramsValidator, validateSpec, type SchemaError } from "./spec-check.js"; +import { findingDetail, listFindings, parseVerdictBody, setVerdict } from "../../findings.js"; // --- the table's types ------------------------------------------------------------ @@ -71,7 +72,7 @@ export type Route = { method: "GET" | "POST"; /** OpenAPI-style path: `/api/v1/jobs/{id}`. */ path: string; - tag: "meta" | "devices" | "workloads" | "jobs" | "results" | "artifacts" | "fleet" | "protocol"; + tag: "meta" | "devices" | "workloads" | "jobs" | "results" | "artifacts" | "findings" | "fleet" | "protocol"; summary: string; description?: string; scope: "public" | "protocol" | Scope; @@ -145,6 +146,12 @@ const PAGE: Param[] = [ { name: "per_page", in: "query", type: "integer", description: "Items per page.", minimum: 1, maximum: 500 }, ]; const JOB_ID: Param = { name: "id", in: "path", type: "string", required: true, description: "A job id, or a fan-out parent's id." }; +const FINDING_ID: Param = { name: "id", in: "path", type: "integer", required: true, description: "The finding's id." }; +/** A finding id from the path, or a 404 for anything that cannot be one. */ +const findingId = (raw: string) => { + if (!/^\d+$/.test(raw) || Number(raw) < 1) throw new ApiError(404, "not_found", `finding ${raw} not found`, "finding ids are positive integers"); + return Number(raw); +}; const SHA: Param = { name: "sha256", in: "path", type: "string", required: true, description: "The artifact's sha256 (64 hex)." }; const E400: Response = { status: 400, description: "The request was malformed or the spec is invalid.", schema: "Error" }; @@ -469,18 +476,19 @@ function listResults(q: Query) { type ArtifactRow = { sha256: string; name: string | null; size: number; media_type: string | null; app: string | null; build: string | null; - platform: string | null; created_at: string; published_at: string | null; pinned: number | null; + platform: string | null; created_at: string; published_at: string | null; pinned: number | null; channel: string | null; }; function artifactMeta(sha: string) { if (!/^[a-f0-9]{64}$/.test(sha)) throw new ApiError(400, "bad_request", "sha256 must be 64 lowercase hex characters"); const a = db - .prepare("SELECT sha256, name, size, media_type, app, build, platform, created_at, published_at, pinned FROM artifacts WHERE sha256 = ?") + .prepare("SELECT sha256, name, size, media_type, app, build, platform, created_at, published_at, pinned, channel FROM artifacts WHERE sha256 = ?") .get(sha) as ArtifactRow | undefined; if (!a) throw notFound("artifact"); return { sha256: a.sha256, name: a.name, size: a.size, media_type: a.media_type, app: a.app, build: a.build, platform: a.platform, created_at: iso(a.created_at), published_at: iso(a.published_at), pinned: !!a.pinned, + channel: a.channel === "pr" ? ("pr" as const) : ("main" as const), in_store: existsSync(path.join(ARTIFACT_DIR, a.sha256)), url: `/api/v1/artifacts/${a.sha256}/content`, }; } @@ -632,8 +640,19 @@ export const ROUTES: Route[] = [ body: { schema: "JobSpecInput", description: "The job spec.", required: true }, responses: [ { status: 201, description: "Queued (or waiting on dependencies).", schema: "JobCreated" }, - E400, E401, E403, E409, - { status: 422, description: "Valid, but nothing can run it (no capable agent, no matching device, no build).", schema: "Error" }, + { + status: 400, + description: + "Malformed or refused before queueing: invalid_spec, no_matching_devices (no registered device matches the targets), " + + "no_build (no artifact for app `latest`), invalid_match, invalid_dependency, secret_in_spec, bad_request.", + schema: "Error", + }, + E401, E403, E409, + { + status: 422, + description: "Valid, but cannot be queued: no_capable_agent (nothing declares the workload), unresolved_reference (a template reference that does not resolve).", + schema: "Error", + }, ], handler: async ({ req, reply }) => { const { spec } = prepareSpec(req); @@ -834,6 +853,66 @@ export const ROUTES: Route[] = [ }, }, + // findings + { + operationId: "listFindings", method: "GET", path: "/api/v1/findings", tag: "findings", scope: "read", readOnly: true, idempotent: true, + summary: "What night QA (the explore workload) found, newest sighting first.", + description: + "Each finding was replayed on a clean install before it was filed; `replay_label` says how often it reproduced. " + + "verdict agent_mistake means the model misread the app, not a bug in it. since=24h is the morning brief.", + params: [ + { name: "app", in: "query", type: "string", description: "Only this app (the explore app key)." }, + { name: "state", in: "query", type: "string", enum: ["open", "triaged", "all"], description: "open: no verdict yet (or reopened by a regression). Default all." }, + { name: "verdict", in: "query", type: "string", description: "Comma-separated: real, duplicate, not_a_bug, agent_mistake, fixed." }, + { name: "check", in: "query", type: "string", description: "crash, anr, frozen, blank, left_app, a11y, visual, goal, dead_control." }, + { name: "since", in: "query", type: "string", description: "Last seen at or after: ISO 8601, or a span back from now such as 90m, 24h, 7d." }, + ...PAGE, + ], + responses: [{ status: 200, description: "Findings.", schema: "list:Finding" }, E400], + handler: async ({ q }) => { + const { page, per_page, offset } = paging(q as Record, 50, 500); + const out = listFindings({ + app: q.app as string | undefined, status: q.state as string | undefined, + verdict: q.verdict as string | undefined, check: q.check as string | undefined, since: q.since as string | undefined, + limit: per_page, offset, + }); + if (!out.ok) throw new ApiError(400, "bad_request", out.error); + return list(out.body.findings, page, per_page, out.body.total); + }, + }, + { + operationId: "getFinding", method: "GET", path: "/api/v1/findings/{id}", tag: "findings", scope: "read", readOnly: true, idempotent: true, + summary: "One finding: the steps in words, its evidence as links, the replay flow (inline when small), its regression test and verdict history.", + params: [FINDING_ID], + responses: [{ status: 200, description: "The finding.", schema: "FindingDetail" }, E404], + handler: async ({ p }) => findingDetail(findingId(p.id)) ?? (() => { throw notFound(`finding ${p.id}`, "GET /api/v1/findings lists them"); })(), + }, + { + operationId: "setFindingVerdict", method: "POST", path: "/api/v1/findings/{id}/verdict", tag: "findings", scope: "run", idempotent: true, + summary: "Judge a finding: real, duplicate, not_a_bug, agent_mistake, or fixed (only after real). null reopens.", + description: + "real keeps the finding's replay flow as a candidate regression test; fixed makes it active, so the app's nightly " + + "ui-test (with params.regressions) runs it. duplicate, not_a_bug and agent_mistake retire it. Mark fixed only once a fix " + + "has merged. Each verdict counts towards the check's precision, which decides what night QA runs tomorrow.", + params: [FINDING_ID], + body: { schema: "FindingVerdictInput", description: "The verdict and an optional note.", required: true }, + responses: [ + { status: 200, description: "Recorded.", schema: "FindingVerdictResult" }, + E400, E401, E403, E404, + { status: 409, description: "fixed on a finding that is not real (conflict).", schema: "Error" }, + ], + handler: async ({ req, p }) => { + const id = findingId(p.id); + const body = parseVerdictBody(req.body); + if (!body.ok) throw new ApiError(400, "bad_request", body.error); + const ctx = authOf(req); + const out = setVerdict(id, body.verdict, body.note, body.duplicateOf, { who: { actor: ctx.actor, source: ctx.source ?? "api" } }); + if (!out.ok) throw new ApiError(out.status, out.status === 404 ? "not_found" : out.status === 409 ? "conflict" : "bad_request", out.error, out.hint); + announce({ type: "finding", id, verdict: out.finding.verdict }); + return { finding: findingDetail(id), change: out.change }; + }, + }, + // fleet { operationId: "listSchedules", method: "GET", path: "/api/v1/schedules", tag: "fleet", scope: "read", readOnly: true, idempotent: true, @@ -902,9 +981,27 @@ export const ROUTES: Route[] = [ { operationId: "uploadArtifact", method: "POST", path: "/artifacts", tag: "protocol", scope: "protocol", documentOnly: true, summary: "Upload bytes (application/octet-stream). Answers with the sha256 and the detected media type.", - description: "Headers: x-artifact-name, x-artifact-media-type (optional), x-artifact-app, x-artifact-build.", + description: + "Headers: x-artifact-name, x-artifact-media-type (optional), x-artifact-app, x-artifact-build, " + + "x-artifact-channel (optional: `pr` for a pull request's build, which `\"sha256\": \"latest\"` never resolves to; absent means a merged build).", responses: [{ status: 201, description: "Stored.", schema: null }], }, + { + operationId: "postFinding", method: "POST", path: "/findings", tag: "protocol", scope: "protocol", documentOnly: true, + summary: "The explore workload filing a finding (an ExploreFinding). Upserts on the fingerprint.", + responses: [{ status: 201, description: "New.", schema: null }, { status: 200, description: "Seen again.", schema: null }], + }, + { + operationId: "listRegressionFlows", method: "GET", path: "/findings/regressions", tag: "protocol", scope: "protocol", documentOnly: true, + summary: "A nightly ui-test pulling an app's regression flows (?app= &state=active &platform=).", + responses: [{ status: 200, description: "{regressions: [...]}, each with its flow text.", schema: null }], + }, + { + operationId: "postRegressionRun", method: "POST", path: "/findings/{id}/regression", tag: "protocol", scope: "protocol", documentOnly: true, + summary: "An executor reporting one regression run: {job_id, device_id, build, outcome: passed|reproduced|failed|skipped, detail}. reproduced reopens the finding.", + params: [{ name: "id", in: "path", type: "integer", required: true, description: "The finding's id." }], + responses: [{ status: 200, description: "Recorded.", schema: null }], + }, { operationId: "downloadArtifact", method: "GET", path: "/artifacts/{sha256}", tag: "protocol", scope: "protocol", documentOnly: true, summary: "The bytes as application/octet-stream, with Range support. Runners fetch models and builds here.", diff --git a/collector/src/api/v1/schemas.ts b/collector/src/api/v1/schemas.ts index 90c2500..07b8edd 100644 --- a/collector/src/api/v1/schemas.ts +++ b/collector/src/api/v1/schemas.ts @@ -268,9 +268,14 @@ export const SCHEMAS: Record = { Artifact: object( { sha256: str, name: nstr, size: nint, media_type: nstr, app: nstr, build: nstr, platform: nstr, - created_at: nstr, published_at: nstr, pinned: bool, in_store: bool, url: str, + created_at: nstr, published_at: nstr, pinned: bool, + channel: { + enum: ["main", "pr"], + description: "pr: uploaded from a pull request (x-artifact-channel: pr); `\"sha256\": \"latest\"` never resolves to it. main: everything else.", + }, + in_store: bool, url: str, }, - ["sha256", "name", "size", "media_type", "in_store", "url"], + ["sha256", "name", "size", "media_type", "channel", "in_store", "url"], ), CancelResult: object( @@ -284,6 +289,121 @@ export const SCHEMAS: Record = { RetryResult: object({ job_id: str, retry_of: str }), + Finding: object( + { + id: int, fingerprint: str, app: { ...str, description: "The explore app key the finding was filed under." }, + build: { ...str, description: "The build it was first seen on." }, platform: str, device_id: str, + job_id: { ...str, description: "The job that first found it." }, last_job_id: nstr, mission_id: str, + check: { type: "string", description: "crash, anr, frozen, blank, left_app, a11y, visual, goal, dead_control." }, + severity: { enum: ["high", "medium", "low"] }, title: str, detail: str, screen: str, screen_name: str, + steps: { ...strs, description: "What to do to see it, in words, one step per entry." }, + replay: { + oneOf: [ + { type: "null" }, + object({ kind: { enum: ["maestro", "tvloop", "none"] }, sha256: nstr, attempts: int, reproduced: int }), + ], + description: "The replay on a clean install: how many of `attempts` reproduced it. null only for a crash, whose crash log is the evidence.", + }, + replay_label: { ...str, description: "reproduced 2/2, flaky 1/2, crash log." }, + artifacts: { ...obj, description: "Artifact sha256s by role: shot, sheet, trajectory, log, replay." }, + first_seen: nstr, last_seen: nstr, seen_count: int, builds_seen: strs, + verdict: { + enum: ["real", "duplicate", "not_a_bug", "agent_mistake", "fixed", null], + description: "null: nobody has judged it, or a regression test reopened it. agent_mistake is NOT a bug in the app.", + }, + verdict_note: nstr, verdict_at: nstr, duplicate_of: nint, + issue: { ...nobj, description: "The GitHub issue it would file, or did; dry_run true means nothing was sent." }, + status: { enum: ["open", "triaged"] }, + regression: { + oneOf: [ + { type: "null" }, + object({ state: { enum: ["candidate", "active", "retired"] }, kind: { enum: ["maestro", "tvloop"] }, last_outcome: nstr }), + ], + description: "The regression test it became: candidate once real, active (in the nightly) once fixed.", + }, + }, + [ + "id", "fingerprint", "app", "build", "platform", "device_id", "job_id", "mission_id", "check", "severity", "title", "detail", + "screen_name", "steps", "replay", "replay_label", "artifacts", "seen_count", "builds_seen", "verdict", "status", + "first_seen", "last_seen", "regression", + ], + ), + + FindingDetail: { + allOf: [ + ref("Finding"), + object( + { + duplicates: arr(object({ id: int, title: str, seen_count: int })), + duplicate_of_title: nstr, + counts: object({ seen: int, builds: int, replay_attempts: nint, replay_reproduced: nint, regression_runs: int }), + evidence: arr(object({ + role: { enum: ["shot", "sheet", "trajectory", "log", "replay"] }, label: str, sha256: str, + url: { ...str, description: "The bytes, relative to the collector." }, in_store: bool, + })), + replay_flow: { + oneOf: [ + { type: "null" }, + object({ + kind: str, sha256: str, url: str, in_store: bool, + text: { ...nstr, description: "The flow itself when it is at most 16 KiB; otherwise fetch url." }, + truncated: { ...bool, description: "True when the flow was too big to inline." }, + }), + ], + description: "The Maestro (or tvloop) flow that replays the finding's steps.", + }, + regression: { + oneOf: [ + { type: "null" }, + object( + { + finding_id: int, app: str, platform: str, check: str, + kind: { enum: ["maestro", "tvloop"] }, state: { enum: ["candidate", "active", "retired"] }, + asserts: { enum: ["no_crash", "replays"], description: "no_crash for crash and anr findings; replays (without error) for every other check." }, + flow: { ...str, description: "The flow text the nightly runs, copied when the finding was marked real." }, + flow_sha256: nstr, created_at: nstr, activated_at: nstr, retired_at: nstr, + runs: int, last_run_at: nstr, last_job_id: nstr, + last_outcome: { enum: ["passed", "reproduced", "failed", "skipped", null] }, last_detail: nstr, + }, + ["finding_id", "state", "kind", "asserts", "flow", "runs"], + ), + ], + }, + history: arr(object( + { + at: nstr, event: { enum: ["verdict", "regressed"] }, + verdict: { enum: ["real", "duplicate", "not_a_bug", "agent_mistake", "fixed", null] }, + note: nstr, actor: nstr, source: nstr, + }, + ["at", "event", "verdict", "note"], + )), + links: object({ self: str, verdict: str, dashboard: str }), + }, + ["counts", "evidence", "replay_flow", "regression", "history", "links"], + ), + ], + }, + + FindingVerdictInput: object( + { + verdict: { + enum: ["real", "duplicate", "not_a_bug", "agent_mistake", "fixed", null], + description: "fixed only after real, once the fix has merged. null reopens.", + }, + note: { type: ["string", "null"], maxLength: 2000 }, + duplicate_of: { ...nint, description: "Required with duplicate: the finding this one duplicates." }, + }, + ["verdict"], + { additionalProperties: false }, + ), + + FindingVerdictResult: object( + { + finding: ref("FindingDetail"), + change: { ...nstr, description: "What the verdict did to the finding's regression test, in one sentence, or null." }, + }, + ), + AuditEntry: object( { id: int, at: nstr, actor: nstr, verified: bool, token_id: nstr, source: nstr, diff --git a/collector/src/client/api.gen.ts b/collector/src/client/api.gen.ts index 4493d39..82c9e00 100644 --- a/collector/src/client/api.gen.ts +++ b/collector/src/client/api.gen.ts @@ -33,6 +33,8 @@ export type Artifact = { created_at?: string | null; published_at?: string | null; pinned?: boolean; + /** pr: uploaded from a pull request (x-artifact-channel: pr); `"sha256": "latest"` never resolves to it. main: everything else. */ + channel: "main" | "pr"; in_store: boolean; url: string; }; @@ -167,6 +169,150 @@ export type Error = { }; }; +export type Finding = { + id: number; + fingerprint: string; + /** The explore app key the finding was filed under. */ + app: string; + /** The build it was first seen on. */ + build: string; + platform: string; + device_id: string; + /** The job that first found it. */ + job_id: string; + last_job_id?: string | null; + mission_id: string; + /** crash, anr, frozen, blank, left_app, a11y, visual, goal, dead_control. */ + check: string; + severity: "high" | "medium" | "low"; + title: string; + detail: string; + screen?: string; + screen_name: string; + /** What to do to see it, in words, one step per entry. */ + steps: string[]; + /** The replay on a clean install: how many of `attempts` reproduced it. null only for a crash, whose crash log is the evidence. */ + replay: (null | { + kind: "maestro" | "tvloop" | "none"; + sha256: string | null; + attempts: number; + reproduced: number; + }); + /** reproduced 2/2, flaky 1/2, crash log. */ + replay_label: string; + /** Artifact sha256s by role: shot, sheet, trajectory, log, replay. */ + artifacts: Record; + first_seen: string | null; + last_seen: string | null; + seen_count: number; + builds_seen: string[]; + /** null: nobody has judged it, or a regression test reopened it. agent_mistake is NOT a bug in the app. */ + verdict: "real" | "duplicate" | "not_a_bug" | "agent_mistake" | "fixed" | null; + verdict_note?: string | null; + verdict_at?: string | null; + duplicate_of?: number | null; + /** The GitHub issue it would file, or did; dry_run true means nothing was sent. */ + issue?: Record | null; + status: "open" | "triaged"; + /** The regression test it became: candidate once real, active (in the nightly) once fixed. */ + regression: (null | { + state: "candidate" | "active" | "retired"; + kind: "maestro" | "tvloop"; + last_outcome: string | null; + }); +}; + +export type FindingDetail = Finding & { + duplicates?: { + id: number; + title: string; + seen_count: number; + }[]; + duplicate_of_title?: string | null; + counts: { + seen: number; + builds: number; + replay_attempts: number | null; + replay_reproduced: number | null; + regression_runs: number; + }; + evidence: { + role: "shot" | "sheet" | "trajectory" | "log" | "replay"; + label: string; + sha256: string; + /** The bytes, relative to the collector. */ + url: string; + in_store: boolean; + }[]; + /** The Maestro (or tvloop) flow that replays the finding's steps. */ + replay_flow: (null | { + kind: string; + sha256: string; + url: string; + in_store: boolean; + /** The flow itself when it is at most 16 KiB; otherwise fetch url. */ + text: string | null; + /** True when the flow was too big to inline. */ + truncated: boolean; + }); + regression: (null | { + finding_id: number; + app?: string; + platform?: string; + check?: string; + kind: "maestro" | "tvloop"; + state: "candidate" | "active" | "retired"; + /** no_crash for crash and anr findings; replays (without error) for every other check. */ + asserts: "no_crash" | "replays"; + /** The flow text the nightly runs, copied when the finding was marked real. */ + flow: string; + flow_sha256?: string | null; + created_at?: string | null; + activated_at?: string | null; + retired_at?: string | null; + runs: number; + last_run_at?: string | null; + last_job_id?: string | null; + last_outcome?: "passed" | "reproduced" | "failed" | "skipped" | null; + last_detail?: string | null; + }); + history: { + at: string | null; + event: "verdict" | "regressed"; + verdict: "real" | "duplicate" | "not_a_bug" | "agent_mistake" | "fixed" | null; + note: string | null; + actor?: string | null; + source?: string | null; + }[]; + links: { + self: string; + verdict: string; + dashboard: string; + }; +}; + +export type FindingList = { + items: Finding[]; + page: number; + per_page: number; + total: number; + pages: number; +}; + +export type FindingVerdictInput = { + /** fixed only after real, once the fix has merged. null reopens. */ + verdict: "real" | "duplicate" | "not_a_bug" | "agent_mistake" | "fixed" | null; + note?: string | null; + /** Required with duplicate: the finding this one duplicates. */ + duplicate_of?: number | null; +}; + +export type FindingVerdictResult = { + finding: FindingDetail; + /** What the verdict did to the finding's regression test, in one sentence, or null. */ + change: string | null; +}; + export type FlakyCell = { /** ` ` */ build: string; @@ -323,7 +469,7 @@ export type JobSpecInput = { kind?: "maestro" | "xcuitest" | "playwright"; flows?: string; }; - /** Workload-specific. Deliberately open, but the fields the shipped workloads read are listed here so they are discoverable: benchmark/thermal prompt_tokens, gen_tokens, warmup_iters, measure_iters, duration_s; batch/vision/speech/embed input_sha256, max_items, max_tokens; cold-start app_id, launches, states; locale-shots locales; app-soak flow, duration_s, interval_s; a11y-audit steps, variants, min_target_pt, font_scale, tree_source; build repo, ref, kind, task, scheme; vantage urls, repeats; any host job network and network_to; a preempted job resume_from. */ + /** Workload-specific. Deliberately open, but the fields the shipped workloads read are listed here so they are discoverable: benchmark/thermal prompt_tokens, gen_tokens, warmup_iters, measure_iters, duration_s; batch/vision/speech/embed input_sha256, max_items, max_tokens; cold-start app_id, launches, states; locale-shots locales; app-soak flow, duration_s, interval_s; a11y-audit steps, variants, min_target_pt, font_scale, tree_source; build repo, ref, kind, task, scheme; vantage urls, repeats; ui-test regressions (true, or the app its findings are filed under: run its fixed findings' replay flows too); any host job network and network_to; a preempted job resume_from. */ params?: Record; /** Job ids this one waits for. The job is enqueued as 'waiting' and becomes 'queued' when the last of them finishes; if any of them fails or is cancelled, this one fails with last_error naming it. While waiting, a spec may reference a dependency's output: "${jobs..artifact}" resolves to the first sha256 in that job's final row, and "${jobs..metrics.}" to one of its metrics. A whole-string reference keeps the value's type, so a metric stays a number. Referencing a job not listed here is refused at enqueue. */ depends_on?: string[]; @@ -747,6 +893,42 @@ export class FleetClient extends Transport { return this.request("GET", `/api/v1/artifacts/${enc(sha256)}/content`, { ...opts, query, raw: true }); } + /** + * What night QA (the explore workload) found, newest sighting first. + * + * Each finding was replayed on a clean install before it was filed; `replay_label` says how often it + * reproduced. verdict agent_mistake means the model misread the app, not a bug in it. since=24h is the + * morning brief. + * + * `GET /api/v1/findings` · scope: read + */ + listFindings(query?: { app?: string; state?: "open" | "triaged" | "all"; verdict?: string; check?: string; since?: string; page?: number; per_page?: number }, opts?: CallOptions): Promise { + return this.request("GET", `/api/v1/findings`, { ...opts, query }); + } + + /** + * One finding: the steps in words, its evidence as links, the replay flow (inline when small), its regression test and verdict history. + * + * `GET /api/v1/findings/{id}` · scope: read + */ + getFinding(id: string, opts?: CallOptions): Promise { + return this.request("GET", `/api/v1/findings/${enc(id)}`, { ...opts }); + } + + /** + * Judge a finding: real, duplicate, not_a_bug, agent_mistake, or fixed (only after real). null reopens. + * + * real keeps the finding's replay flow as a candidate regression test; fixed makes it active, so the + * app's nightly ui-test (with params.regressions) runs it. duplicate, not_a_bug and agent_mistake + * retire it. Mark fixed only once a fix has merged. Each verdict counts towards the check's precision, + * which decides what night QA runs tomorrow. + * + * `POST /api/v1/findings/{id}/verdict` · scope: run + */ + setFindingVerdict(id: string, body: FindingVerdictInput, opts?: CallOptions): Promise { + return this.request("POST", `/api/v1/findings/${enc(id)}/verdict`, { ...opts, body }); + } + /** * Cron schedules, with next run and whether one was missed. * diff --git a/collector/src/executor.ts b/collector/src/executor.ts index 10303e3..31c0537 100644 --- a/collector/src/executor.ts +++ b/collector/src/executor.ts @@ -55,6 +55,7 @@ import { FLOWS_DIR, MAESTRO, resolveFlow, runFlow } from "./workloads/flows.js"; import { discoverWorkloads, resolveRun, type LoadedWorkload } from "./workloads/registry.js"; import { bundledNames } from "./workloads/static.js"; import { prepareInstallable } from "./workloads/install/index.js"; +import { fetchRegressions, regressionApp, runRegressions, type RegressionFlow, type RegressionResult } from "./workloads/regressions.js"; import type { Target, WorkloadCtx } from "./workloads/types.js"; @@ -500,9 +501,13 @@ async function runUiTest(job: Job) { if (!suite) throw new Error("ui-test job needs a suite"); if (suite.kind === "xcuitest") return runXcuitest(job); if (suite.kind !== "maestro") throw new Error(`suite kind ${suite.kind} not supported yet`); - if (!suite.flows) throw new Error("maestro suite needs flows"); - const flows = path.resolve(FLOWS_DIR, suite.flows); - if (!existsSync(flows)) throw new Error(`flows not found: ${flows}`); + // params.regressions: the app's fixed findings, replayed after the suite's + // own flow on every device (src/workloads/regressions.ts). With it, a job + // may have no flow of its own and run only those. + const regressionsFor = regressionApp(job); + if (!suite.flows && !regressionsFor) throw new Error("maestro suite needs flows (or params.regressions to run only an app's regression flows)"); + const flows = suite.flows ? path.resolve(FLOWS_DIR, suite.flows) : null; + if (flows && !existsSync(flows)) throw new Error(`flows not found: ${flows}`); // Maestro takes `-e KEY=value` and a flow reads it as ${KEY}, which is how a // flow types into a login form. Same Keychain, same rule: the job names the @@ -524,14 +529,22 @@ async function runUiTest(job: Job) { // one flow that existed could never pass against the installed package. // A flow written as `appId: ${APP_ID}` takes the id from the job instead, and // the same flow then covers debug, smoke and release. - const appIdMatch = /^appId:\s*(\S+)/m.exec(readFileSync(flows, "utf8")); + const appIdMatch = flows ? /^appId:\s*(\S+)/m.exec(readFileSync(flows, "utf8")) : null; const declared = appIdMatch?.[1]; const parameterised = !declared || /\$\{|^\$/.test(declared); - if (parameterised && !job.suite?.app_id) { + if (flows && parameterised && !job.suite?.app_id) { throw new Error(`${flows} takes its appId from the job, so suite.app_id is required`); } const appId = job.suite?.app_id ?? declared; + // Pulled once, at run time: a finding marked fixed yesterday is in + // tonight's run without anyone editing this job's schedule. + let regressionFlows: RegressionFlow[] = []; + if (regressionsFor) { + regressionFlows = await fetchRegressions(regressionsFor); + log(`ui-test: ${regressionFlows.length} active regression flow(s) for ${regressionsFor}`); + } + // A job that names a build tests that build. Without this a ui-test ran its // flow against whatever was already on the phone -- so a CI run "pinned to // the exact APK just built" passed or failed on last week's install, and a @@ -590,6 +603,14 @@ async function runUiTest(job: Job) { log(`ui-test on ${serial}: skipped (${appId} not installed)`); continue; } + const mineRegs = regressionFlows.filter((f) => f.platform === target.platform); + if (!flows && mineRegs.length === 0) { + await postResult({ + job_id: job.job_id, device_id: serial, iter: 0, ok: true, + error: `skipped: no active regression flows for ${regressionsFor} on ${target.platform}`, + }); + continue; + } const outDir = mkdtempSync(path.join(os.tmpdir(), "fleet-junit-")); const report = path.join(outDir, "report.xml"); let failedToRun = false; @@ -603,7 +624,7 @@ async function runUiTest(job: Job) { // unshaped — an offline suite that quietly ran online is a pass that proves // nothing. let shapeError: string | undefined; - try { + if (flows) try { await withNetwork(job, target, async () => { try { await exec( @@ -628,7 +649,7 @@ async function runUiTest(job: Job) { } let passed = 0; - let failed = 1; + let failed = flows ? 1 : 0; let failure: string | null = null; let failingFlow: string | undefined; const artifacts: string[] = []; @@ -647,15 +668,40 @@ async function runUiTest(job: Job) { if (creds) writeFileSync(report, redact(xml, [creds.password])); artifacts.push(await uploadArtifact(report, `${job.job_id}-${serial}-junit.xml`)); } - if (failed > 0) allOk = false; - const error = shapeError + const suiteError = shapeError ? `params.network: ${shapeError}` : failedToRun ? `maestro produced no report: ${runError ?? "it never ran"}` : failure ?? undefined; + + // The app's regression flows, after its own. A reproduced crash reopens + // its finding on the collector and fails this row by name. + let regs: RegressionResult[] = []; + if (mineRegs.length) { + regs = await runRegressions({ + job, target, flows: mineRegs, appId, + env: creds ? { [creds.emailVar]: creds.account, [creds.passwordVar]: creds.password } : {}, + secrets: creds ? [creds.password] : [], + }); + passed += regs.filter((r) => r.outcome === "passed").length; + failed += regs.filter((r) => r.outcome === "reproduced" || r.outcome === "failed").length; + for (const r of regs) log(`ui-test on ${serial}: regression #${r.finding_id} ${r.outcome}: ${r.detail}`); + } + const badRegs = [...regs.filter((r) => r.outcome === "reproduced"), ...regs.filter((r) => r.outcome === "failed")]; + if (!failingFlow && badRegs.length) failingFlow = `regression finding #${badRegs[0].finding_id}`; + const regressionError = badRegs.length + ? badRegs.map((r) => `regression #${r.finding_id} ${r.outcome === "reproduced" ? "reproduced (finding reopened)" : "failed"}: ${r.detail}`).join("; ") + : undefined; + const error = [suiteError, regressionError].filter(Boolean).join("; ").slice(0, 1000) || undefined; + + if (failed > 0) allOk = false; await postResult({ job_id: job.job_id, device_id: serial, iter: 0, - ok: failed === 0, test: { passed, failed, artifacts, ...(failingFlow ? { failing_flow: failingFlow } : {}) }, + ok: failed === 0, + test: { + passed, failed, artifacts, ...(failingFlow ? { failing_flow: failingFlow } : {}), + ...(regs.length ? { regressions: regs } : {}), + }, ...(error ? { error } : {}), }); log(`ui-test on ${serial}: ${passed} passed / ${failed} failed${shapeError ? ` (network shaping: ${shapeError})` : ""}`); diff --git a/collector/src/findings.test.ts b/collector/src/findings.test.ts index 9955d8f..922787e 100644 --- a/collector/src/findings.test.ts +++ b/collector/src/findings.test.ts @@ -8,7 +8,8 @@ * loopback port -- nothing here ever reaches the real one), and the digest * timer's once-a-day rule, which depends on the wall clock. */ -import { mkdtempSync, rmSync } from "node:fs"; +import { mkdirSync, mkdtempSync, rmSync } from "node:fs"; +import { DatabaseSync } from "node:sqlite"; import { createServer, type IncomingMessage, type Server } from "node:http"; import { tmpdir } from "node:os"; import path from "node:path"; @@ -16,6 +17,14 @@ import { closeDb, db, openDb } from "./db.js"; import { ISSUE_CAP_PER_DAY, buildDigest, + findingDetail, + getRegression, + listFindings, + listRegressions, + parseRegressionRun, + parseSince, + parseVerdictBody, + recordRegressionRun, digestDue, digestTick, fileIssue, @@ -355,4 +364,132 @@ export async function runFindingsChecks(check: Check) { await down.close(); } }); + + // --- fixed, the verdict history, and a finding becoming a regression test --- + await inTempDb(() => { + const FLOW = "appId: com.example.plants\nname: \"Save does nothing\"\n---\n- launchApp:\n clearState: true\n- tapOn:\n point: \"50%,90%\"\n"; + const store = new Map([[SHA("a"), FLOW]]); + const read = (sha: string) => store.get(sha) ?? null; + const who = { actor: "taylor", source: "test" }; + + const crash = storeFinding(sample({ fingerprint: "r-crash", check: "crash" }), DRY).finding; + const early = setVerdict(crash.id, "fixed", "too soon", null, { who, readArtifact: read }); + check("regressions: fixed before real is refused with 409", !early.ok && early.status === 409 && /after real/.test(early.error), JSON.stringify(early)); + + const real = setVerdict(crash.id, "real", "seen it", null, { who, readArtifact: read }); + check("regressions: real keeps the replay flow as a candidate", + real.ok && real.regression?.state === "candidate" && real.regression.flow === FLOW && real.regression.kind === "maestro" + && real.regression.asserts === "no_crash" && /candidate/.test(real.change ?? ""), JSON.stringify(real)); + check("regressions: a candidate is not in the active list", listRegressions({ app: "plants" }).ok && + (listRegressions({ app: "plants" }) as { items: unknown[] }).items.length === 0); + const fixed = setVerdict(crash.id, "fixed", "PR #12", null, { who, readArtifact: read }); + check("regressions: fixed after real makes it active", + fixed.ok && fixed.finding.verdict === "fixed" && fixed.regression?.state === "active" && fixed.regression.activated_at !== null); + const active = listRegressions({ app: "plants", platform: "android" }); + check("regressions: the nightly's pull lists it with its flow", + active.ok && active.items.length === 1 && active.items[0].finding_id === crash.id && active.items[0].flow === FLOW); + check("regressions: listing refuses a state it does not know", !listRegressions({ state: "sideways" }).ok); + check("regressions: fixed counts as real in precision", precision({ app: "plants" }).classes.find((c) => c.check === "crash")?.real === 1); + + const job = { job_id: "nightly-ui-1", device_id: "pixel", build: "1.1 (5)", detail: "" }; + const passed = recordRegressionRun(crash.id, { ...job, outcome: "passed", detail: "no crash" }); + check("regressions: a pass is recorded and changes nothing else", + passed.ok && !passed.reopened && passed.finding.verdict === "fixed" && passed.regression.runs === 1 && passed.regression.last_outcome === "passed"); + const back = recordRegressionRun(crash.id, { ...job, job_id: "nightly-ui-2", outcome: "reproduced", detail: "the app crashed again during the flow: NPE" }); + check("regressions: reproduced reopens the finding, counts it and adds the build", + back.ok && back.reopened && back.finding.verdict === null && back.finding.status === "open" && back.finding.seen_count === crash.seen_count + 1 + && back.finding.builds_seen.includes("1.1 (5)") && back.regression.state === "active", JSON.stringify(back)); + const twice = recordRegressionRun(crash.id, { ...job, job_id: "nightly-ui-2", device_id: "galaxy", outcome: "reproduced", detail: "again" }); + check("regressions: a second device in the same job does not reopen it twice", twice.ok && !twice.reopened && twice.finding.seen_count === crash.seen_count + 1); + check("regressions: a run for a finding with no test is 404", (() => { + const r = recordRegressionRun(99999, { ...job, outcome: "passed" }); return !r.ok && r.status === 404; + })()); + + const detail = findingDetail(crash.id, read)!; + const events = detail.history.map((h) => `${h.event}:${h.verdict ?? "-"}`).join(","); + check("history: every verdict and the regression, in order", events === "verdict:real,verdict:fixed,regressed:-", events); + check("history: says which build it regressed on and who judged it", + /regressed on build 1\.1 \(5\)/.test(detail.history[2].note ?? "") && detail.history[0].actor === "taylor", JSON.stringify(detail.history)); + check("detail: the replay flow is inline, and the evidence links to /api/v1", + detail.replay_flow?.text === FLOW && detail.evidence.some((e) => e.role === "shot" && e.url === `/api/v1/artifacts/${SHA("b")}/content`), + JSON.stringify(detail.replay_flow)); + check("detail: counts", detail.counts.seen === crash.seen_count + 1 && detail.counts.regression_runs === 3, JSON.stringify(detail.counts)); + + const refixed = setVerdict(crash.id, "fixed", "PR #13", null, { readArtifact: read }); + check("regressions: a regressed finding may be marked fixed again directly", refixed.ok && refixed.regression?.state === "active"); + const retired = setVerdict(crash.id, "not_a_bug", null, null, { readArtifact: read }); + check("regressions: not_a_bug retires an active test", retired.ok && retired.regression?.state === "retired" && /retired/.test(retired.change ?? "")); + const again = setVerdict(crash.id, "real", null, null, { readArtifact: read }); + check("regressions: real brings a retired test back as a candidate", again.ok && again.regression?.state === "candidate"); + + const gone = storeFinding(sample({ fingerprint: "r-gone", replay: { kind: "maestro", sha256: SHA("9"), attempts: 2, reproduced: 2 }, artifacts: {} }), DRY).finding; + const noFlow = setVerdict(gone.id, "real", null, null, { readArtifact: read }); + check("regressions: real with no stored flow says why and keeps no test", + noFlow.ok && noFlow.regression === null && /not in the artifact store/.test(noFlow.change ?? ""), JSON.stringify(noFlow)); + const fixedNoFlow = setVerdict(gone.id, "fixed", null, null, { readArtifact: read }); + check("regressions: fixed with no flow is still recorded", fixedNoFlow.ok && fixedNoFlow.finding.verdict === "fixed" && getRegression(gone.id) === null); + + // A finding marked real before regressions existed goes straight to active on fixed. + const legacy = storeFinding(sample({ fingerprint: "r-legacy", check: "frozen" }), DRY).finding; + db.prepare("UPDATE findings SET verdict = 'real' WHERE id = ?").run(legacy.id); + const lf = setVerdict(legacy.id, "fixed", null, null, { readArtifact: read }); + check("regressions: fixed on a pre-regression real finding makes an active test", lf.ok && lf.regression?.state === "active" && lf.regression.asserts === "replays"); + + // Filters. + const fixedOnly = listFindings({ verdict: "fixed" }); + check("list: the verdict filter", fixedOnly.ok && fixedOnly.body.findings.every((f) => f.verdict === "fixed") && fixedOnly.body.total === 2, + JSON.stringify(fixedOnly.ok && fixedOnly.body.total)); + check("list: a bad verdict filter is refused", !listFindings({ verdict: "meh" }).ok); + const page2 = listFindings({ limit: 1, offset: 1 }); + check("list: offset pages, total counts every match", page2.ok && page2.body.findings.length === 1 && page2.body.total === 3); + check("list: rows carry their regression state", fixedOnly.ok && fixedOnly.body.findings.some((f) => f.regression?.state === "active")); + check("list: since accepts a span", listFindings({ since: "24h" }).ok && !listFindings({ since: "yesterday-ish" }).ok); + }); + + // --- small parsers --- + { + const now = new Date("2026-10-15T12:00:00Z"); + check("since: 24h is a day back", parseSince("24h", now)?.toISOString() === "2026-10-14T12:00:00.000Z"); + check("since: 7d and 90m", parseSince("7d", now)?.toISOString() === "2026-10-08T12:00:00.000Z" && parseSince("90m", now)?.toISOString() === "2026-10-15T10:30:00.000Z"); + check("since: ISO passes through, nonsense is null", parseSince("2026-10-01", now) !== null && parseSince("soon", now) === null); + const vb = parseVerdictBody({ verdict: "fixed", note: " PR #9 " }); + check("verdict body: fixed and a trimmed note", vb.ok && vb.verdict === "fixed" && vb.note === "PR #9"); + check("verdict body: missing verdict, bad verdict, bad duplicate_of are refused", + !parseVerdictBody({}).ok && !parseVerdictBody({ verdict: "meh" }).ok && !parseVerdictBody({ verdict: "duplicate", duplicate_of: "x" }).ok); + const run = parseRegressionRun({ job_id: "j", device_id: "d", outcome: "reproduced" }); + check("regression run: build defaults to installed", run.ok && run.run.build === "installed"); + check("regression run: an unknown outcome is refused", !parseRegressionRun({ job_id: "j", device_id: "d", outcome: "meh" }).ok); + } + + // --- the migration: a database whose findings table predates `fixed` --- + { + closeDb(); + const dir = mkdtempSync(path.join(tmpdir(), "fleet-findings-migrate-")); + try { + mkdirSync(dir, { recursive: true }); + const seed = new DatabaseSync(path.join(dir, "fleet.db")); + seed.exec(`CREATE TABLE findings ( + id INTEGER PRIMARY KEY AUTOINCREMENT, fingerprint TEXT NOT NULL UNIQUE, app TEXT NOT NULL, build TEXT NOT NULL, + platform TEXT NOT NULL, device_id TEXT NOT NULL, job_id TEXT NOT NULL, last_job_id TEXT, mission_id TEXT NOT NULL, + check_name TEXT NOT NULL, subclass TEXT, severity TEXT NOT NULL CHECK (severity IN ('high','medium','low')), + title TEXT NOT NULL, detail TEXT NOT NULL DEFAULT '', screen TEXT NOT NULL DEFAULT '', screen_name TEXT NOT NULL DEFAULT '', + steps TEXT NOT NULL DEFAULT '[]', replay TEXT, artifacts TEXT NOT NULL DEFAULT '{}', + first_seen TEXT NOT NULL DEFAULT (datetime('now')), last_seen TEXT NOT NULL DEFAULT (datetime('now')), + seen_count INTEGER NOT NULL DEFAULT 1, builds_seen TEXT NOT NULL DEFAULT '[]', + verdict TEXT CHECK (verdict IS NULL OR verdict IN ('real','duplicate','not_a_bug','agent_mistake')), + verdict_note TEXT, verdict_at TEXT, duplicate_of INTEGER, issue TEXT, issue_state TEXT, issue_at TEXT)`); + seed.exec(`INSERT INTO findings (fingerprint, app, build, platform, device_id, job_id, mission_id, check_name, severity, title, verdict, verdict_note, verdict_at) + VALUES ('old-1', 'plants', '1', 'android', 'd', 'j', 'm', 'crash', 'high', 'Old crash', 'real', 'from before', '2026-10-01 08:00:00')`); + seed.close(); + openDb(dir); + const r = setVerdict(1, "fixed", null, null, { readArtifact: () => null }); + check("migration: an old database accepts fixed", r.ok && r.finding.verdict === "fixed", JSON.stringify(r)); + const h = findingDetail(1, () => null)!.history; + check("migration: the verdict given before history existed is in the history", + h.length === 2 && h[0].verdict === "real" && h[0].note === "from before" && h[0].at === "2026-10-01T08:00:00Z", JSON.stringify(h)); + } finally { + closeDb(); + rmSync(dir, { recursive: true, force: true }); + } + } } diff --git a/collector/src/workloads/regressions.test.ts b/collector/src/workloads/regressions.test.ts new file mode 100644 index 0000000..5d419df --- /dev/null +++ b/collector/src/workloads/regressions.test.ts @@ -0,0 +1,91 @@ +/** + * The ui-test side of regression tests, with no device: which app a job asks + * for, how a stored flow is made runnable, what a run is judged, and what is + * reported -- against fake crash readings and a fake Maestro. + * + * Run from scripts/smoke.ts like the other decision checks. What it cannot + * show is Maestro and adb themselves, which only a device can. + */ +import path from "node:path"; +import { flowAppId, judgeRegression, prepareFlow, regressionApp, runRegressions, type CrashReading, type RegressionDeps } from "./regressions.js"; +import type { Target } from "./types.js"; + +type Check = (name: string, cond: boolean, detail?: string) => void; + +const throws = (fn: () => unknown) => { + try { + fn(); + return false; + } catch { + return true; + } +}; + +export async function runRegressionChecks(check: Check) { + // Which app. + check("regressions: no param, no regressions", regressionApp({ params: {} }) === null); + check("regressions: a name is the app", regressionApp({ params: { regressions: "greenfolio" } }) === "greenfolio"); + check("regressions: true is job.app.name", + regressionApp({ params: { regressions: true }, app: { name: "greenfolio-android", build: "1", sha256: "latest" } }) === "greenfolio-android"); + check("regressions: true with no app, or a nonsense value, fails the job", + throws(() => regressionApp({ params: { regressions: true } })) && throws(() => regressionApp({ params: { regressions: 7 } }))); + + // Making a stored flow runnable. + const root = path.resolve("/lab/flows"); + const flow = 'appId: com.example.app.debug\nname: "x"\n---\n- launchApp:\n clearState: true\n- runFlow: "greenfolio/login.yaml"\n- tapOn:\n point: "50%,50%"\n'; + const ready = prepareFlow(flow, { appId: "com.example.app.smoke", flowsDir: root }); + check("prepare: the job's appId replaces the recorded one", /^appId: com\.example\.app\.smoke$/m.test(ready) && !ready.includes(".debug"), ready); + check("prepare: a relative runFlow is resolved under the flows dir", + ready.includes(`- runFlow: ${JSON.stringify(path.join(root, "greenfolio/login.yaml"))}`), ready); + check("prepare: without an appId the flow keeps its own", flowAppId(prepareFlow(flow, { flowsDir: root })) === "com.example.app.debug"); + check("prepare: a runFlow escaping the flows dir is refused", + throws(() => prepareFlow('appId: a\n---\n- runFlow: "../../etc/x.yaml"\n', { flowsDir: root }))); + check("prepare: a parameterised appId is not a package", flowAppId("appId: ${APP_ID}\n---\n") === null); + + // Judging. + const none = { count: 0, signatures: [], problem: null }; + const one = { count: 1, signatures: ["java.lang.NullPointerException: boom"], problem: null }; + const r1 = judgeRegression({ check: "crash", platform: "android", flowError: "Element not found", before: none, after: one }); + check("judge: a new crash during a crash finding's flow is reproduced", r1.outcome === "reproduced" && r1.detail.includes("NullPointerException"), r1.detail); + const r2 = judgeRegression({ check: "anr", platform: "android", flowError: null, before: one, after: one }); + check("judge: no new crash and a clean flow passes", r2.outcome === "passed"); + const r3 = judgeRegression({ check: "crash", platform: "android", flowError: "Assertion failed", before: none, after: none }); + check("judge: a failing flow with no crash is failed, not reproduced", r3.outcome === "failed" && /no crash/.test(r3.detail)); + const r4 = judgeRegression({ check: "crash", platform: "ios", flowError: null, before: null, after: null }); + check("judge: on iOS a crash finding's clean replay passes and says the crash was not checked", r4.outcome === "passed" && /not checked/.test(r4.detail), r4.detail); + const r5 = judgeRegression({ check: "dead_control", platform: "android", flowError: "Element not found", before: none, after: none }); + check("judge: other checks never reproduce; a failing flow is failed with the honest caveat", r5.outcome === "failed" && /cannot tell/.test(r5.detail)); + const r6 = judgeRegression({ check: "visual", platform: "android", flowError: null, before: none, after: one }); + check("judge: a crash during a visual finding's flow does not count as that finding", r6.outcome === "passed" && /replayed without error/.test(r6.detail)); + const r7 = judgeRegression({ check: "crash", platform: "android", flowError: null, before: { count: 0, signatures: [], problem: "logcat could not be read" }, after: none }); + check("judge: an unreadable crash log is said, not guessed", r7.outcome === "passed" && /logcat could not be read/.test(r7.detail)); + + // Running: the right flows, the readings around each, and a report for each. + const android: Target = { id: "pixel", platform: "android", kind: "device" } as Target; + const crashes: CrashReading[] = [none, one, one, one]; + const ran: { file: string; env: Record }[] = []; + const reports: { id: number; body: Record }[] = []; + const deps: RegressionDeps = { + runFlow: async (_t, file, _cwd, env) => { ran.push({ file, env }); return ran.length === 2 ? "maestro failed: password=hunter2 Element not found" : null; }, + readCrashes: async () => crashes.shift() ?? one, + report: async (id, body) => { reports.push({ id, body }); }, + }; + const out = await runRegressions({ + job: { job_id: "nightly-1", app: { name: "app", build: "2.0 (7)", sha256: "x" } }, target: android, appId: "com.example.app", + env: { TEST_PASSWORD: "hunter2" }, secrets: ["hunter2"], flowsDir: root, + flows: [ + { finding_id: 1, app: "app", platform: "android", check: "crash", kind: "maestro", flow: "appId: com.example.app\n---\n- launchApp\n" }, + { finding_id: 2, app: "app", platform: "android", check: "goal", kind: "maestro", flow: "appId: com.example.app\n---\n- launchApp\n" }, + { finding_id: 3, app: "app", platform: "ios", check: "crash", kind: "maestro", flow: "appId: com.example.app\n---\n" }, + { finding_id: 4, app: "app", platform: "android", check: "crash", kind: "tvloop", flow: "{}" }, + ], + }, deps); + check("run: only this platform's flows, in order", out.map((r) => r.finding_id).join(",") === "1,2,4", JSON.stringify(out)); + check("run: the crash during flow 1 is reproduced", out[0].outcome === "reproduced"); + check("run: the goal flow that failed is failed, and the password is redacted", out[1].outcome === "failed" && !out[1].detail.includes("hunter2"), out[1].detail); + check("run: a tvloop flow is skipped, not run", out[2].outcome === "skipped" && ran.length === 2); + check("run: the flow gets APP_ID and the sign-in env", ran[0].env.APP_ID === "com.example.app" && ran[0].env.TEST_PASSWORD === "hunter2"); + check("run: each is reported with the job, device and build", + reports.length === 3 && reports[0].id === 1 && reports[0].body.outcome === "reproduced" && reports[0].body.build === "2.0 (7)" + && reports[0].body.device_id === "pixel" && reports[0].body.job_id === "nightly-1", JSON.stringify(reports[0])); +} diff --git a/collector/src/workloads/regressions.ts b/collector/src/workloads/regressions.ts new file mode 100644 index 0000000..5331089 --- /dev/null +++ b/collector/src/workloads/regressions.ts @@ -0,0 +1,220 @@ +/** + * Regression tests from fixed findings, as the ui-test workload runs them. + * + * Night QA files a finding with a Maestro flow that replays its steps. A + * person marks it real (the collector keeps the flow as a candidate), then + * fixed once a fix has merged (the flow becomes active). A ui-test job with + * `params.regressions` asks the collector for the app's active flows at run + * time and runs each on every device it tests, after the suite's own flow: + * + * params.regressions: "greenfolio" the explore app key the findings are filed under + * params.regressions: true the same as job.app.name + * + * Pulled at run time rather than copied into the lab's flows directory + * because that directory is outside git: a flow written there by the + * collector would be a file nobody reviews and nothing backs up, on one + * machine. The flow text lives in the collector's database instead, and a + * nightly that already exists picks up every newly fixed finding without + * anyone editing its schedule. + * + * ## What a run can assert + * + * A replay flow repeats the steps that led to the bug. For a crash or an ANR + * that is enough: on Android the crash buffer (`logcat -b crash`, and + * `am_anr` in the events buffer) is read before and after the flow, and a new + * crash of the package during it is the bug coming back -- `reproduced`, + * which reopens the finding. For every other check (frozen, dead_control, + * goal, visual...) the oracle that found it is a model or a heuristic the + * flow does not carry, so the honest claim is weaker: the flow replays + * without error. A flow that fails is reported `failed` and fails the device's + * row, but does not reopen anything, because a step that no longer replays + * may be the bug or may be a redesigned screen. On iOS there is no crash + * buffer read here, so a crash finding's flow is also "replays without + * error" there, and the result says so. + * + * tvloop flows (a Roku's) are kept by the collector but not run by ui-test, + * which drives Maestro; they are reported `skipped`. + */ +import { mkdtempSync, writeFileSync } from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { BASE, exec, post } from "../fleet-client.js"; +import { parseCrashLogcat } from "../soak-samples.js"; +import { redact } from "../secrets.js"; +import { parseAnrEvents } from "./explore/actuators/android.js"; +import { ADB } from "./device.js"; +import { FLOWS_DIR, runFlow } from "./flows.js"; +import type { Job, Target } from "./types.js"; + +/** One regression as `GET /findings/regressions` returns it (the fields this needs). */ +export type RegressionFlow = { + finding_id: number; + app: string; + platform: string; + check: string; + kind: "maestro" | "tvloop"; + flow: string; +}; + +export type RegressionResult = { + finding_id: number; + outcome: "passed" | "reproduced" | "failed" | "skipped"; + detail: string; +}; + +/** Checks whose absence a replay can show: the crash buffer says whether it happened again. */ +const ABSENCE = new Set(["crash", "anr"]); + +/** + * Which app's regressions the job asks for, or null when it asks for none. + * Throws on a value that cannot name one, so a typo fails the job instead of + * quietly running nothing. + */ +export function regressionApp(job: Pick): string | null { + const v = job.params?.regressions; + if (v === undefined || v === false || v === null) return null; + if (v === true) { + if (!job.app?.name) throw new Error("params.regressions: true needs job.app.name; or name the app: params.regressions: \"\""); + return job.app.name; + } + if (typeof v === "string" && /^[\w.@:+-]{1,200}$/.test(v)) return v; + throw new Error("params.regressions must be true or the app name its findings are filed under"); +} + +/** The appId a flow declares, if it declares a literal one. */ +export function flowAppId(flow: string): string | null { + const m = /^appId:\s*(\S+)/m.exec(flow); + return m && !/\$\{/.test(m[1]) ? m[1] : null; +} + +/** + * Make a stored flow runnable here. + * + * - `appId` is replaced by the job's suite.app_id when it sets one: the flow + * was recorded against whatever variant night QA explored (often `.debug`), + * and the nightly may be testing another. + * - `runFlow: "relative/path.yaml"` (the mission's sign-in flow) is resolved + * against the flows directory, because the stored flow is written to a temp + * file and Maestro resolves a relative runFlow against the file it is in. A + * path that escapes the flows directory is refused, as resolveFlow does for + * job specs. + */ +export function prepareFlow(flow: string, opts: { appId?: string | null; flowsDir?: string } = {}): string { + const root = path.resolve(opts.flowsDir ?? FLOWS_DIR); + let out = flow; + if (opts.appId) out = out.replace(/^appId:\s*\S+/m, `appId: ${opts.appId}`); + return out.replace(/^(\s*-\s*runFlow:\s*)(["']?)([^"'\n]+?)\2\s*$/gm, (_m, lead: string, _q: string, rel: string) => { + if (path.isAbsolute(rel)) return `${lead}${JSON.stringify(rel)}`; + const abs = path.resolve(root, rel); + if (abs !== root && !abs.startsWith(root + path.sep)) throw new Error(`the flow's runFlow ${rel} escapes the flows dir`); + return `${lead}${JSON.stringify(abs)}`; + }); +} + +/** Crashes and ANRs of `pkg` in the device's buffers so far; null where nothing here can read them. */ +export type CrashReading = { count: number; signatures: string[]; problem: string | null } | null; + +/** + * Decide one run. Pure: everything it needs is passed in. + * + * `before`/`after` are crash readings around the flow; null means the + * platform has no crash log this reads (anything but Android). + */ +export function judgeRegression(o: { + check: string; platform: string; flowError: string | null; before: CrashReading; after: CrashReading; +}): Omit { + const flowFailed = o.flowError ? `the flow failed: ${o.flowError.split("\n").filter(Boolean).slice(-2).join(" ").slice(0, 300)}` : null; + if (ABSENCE.has(o.check)) { + if (o.before && o.after && !o.before.problem && !o.after.problem) { + const fresh = Math.max(0, o.after.count - o.before.count); + if (fresh > 0) { + const sig = o.after.signatures.slice(-fresh)[0] ?? "crash"; + return { outcome: "reproduced", detail: `the app crashed again during the flow: ${sig}` }; + } + return flowFailed ? { outcome: "failed", detail: `${flowFailed} (no crash of the app during it)` } : { outcome: "passed", detail: "no crash of the app during the flow" }; + } + const why = o.before?.problem ?? o.after?.problem ?? `no crash log is read on ${o.platform}`; + return flowFailed + ? { outcome: "failed", detail: `${flowFailed}; crash not checked (${why})` } + : { outcome: "passed", detail: `replayed without error; crash not checked (${why})` }; + } + return flowFailed + ? { outcome: "failed", detail: `${flowFailed}. A ${o.check} finding's flow cannot tell the bug from a changed screen; look before reopening it` } + : { outcome: "passed", detail: `replayed without error (a ${o.check} finding's flow cannot assert the bug's absence, only that the steps still run)` }; +} + +/** The Android crash and ANR count for `pkg`, the way the explore actuator reads it. */ +export async function readCrashes(target: Target, pkg: string): Promise { + if (target.platform !== "android") return null; + try { + const crash = await exec(ADB, ["-s", target.id, "logcat", "-b", "crash", "-d", "-t", "4000"], { timeout: 30_000, maxBuffer: 16 * 1024 * 1024 }); + const c = parseCrashLogcat(crash.stdout, pkg); + if (c.problem) return { count: 0, signatures: [], problem: c.problem }; + const events = await exec(ADB, ["-s", target.id, "logcat", "-b", "events", "-d", "-t", "4000"], { timeout: 30_000, maxBuffer: 16 * 1024 * 1024 }) + .then((r) => parseAnrEvents(r.stdout, pkg)) + .catch(() => [] as string[]); + return { count: c.count + events.length, signatures: [...c.signatures, ...events], problem: null }; + } catch (e) { + return { count: 0, signatures: [], problem: `logcat could not be read: ${(e as Error).message.slice(0, 120)}` }; + } +} + +/** The app's active regression flows, from the collector. */ +export async function fetchRegressions(app: string): Promise { + const res = await fetch(`${BASE}/findings/regressions?app=${encodeURIComponent(app)}&state=active`); + if (!res.ok) throw new Error(`GET /findings/regressions -> ${res.status}`); + return ((await res.json()) as { regressions: RegressionFlow[] }).regressions; +} + +export type RegressionDeps = { + runFlow: (t: Target, file: string, cwd: string, env: Record, timeoutMs: number) => Promise; + readCrashes: (t: Target, pkg: string) => Promise; + report: (findingId: number, body: Record) => Promise; +}; + +const LIVE: RegressionDeps = { + runFlow, + readCrashes, + report: (id, body) => post(`/findings/${id}/regression`, body), +}; + +/** + * Run the regressions that apply to this target, report each to the + * collector, and return them for the device's result row. + */ +export async function runRegressions(o: { + job: Pick; target: Target; flows: RegressionFlow[]; + appId?: string | null; env?: Record; secrets?: string[]; flowsDir?: string; timeoutMs?: number; +}, deps: RegressionDeps = LIVE): Promise { + const out: RegressionResult[] = []; + const build = o.job.app?.build ?? "installed"; + const mine = o.flows.filter((f) => f.platform === o.target.platform); + if (!mine.length) return out; + const dir = mkdtempSync(path.join(os.tmpdir(), "fleet-regressions-")); + for (const f of mine) { + let result: Omit; + if (f.kind !== "maestro") { + result = { outcome: "skipped", detail: `a ${f.kind} flow; ui-test runs Maestro flows only` }; + } else { + try { + const text = prepareFlow(f.flow, { appId: o.appId, flowsDir: o.flowsDir }); + const pkg = flowAppId(text) ?? o.appId ?? ""; + const file = path.join(dir, `finding-${f.finding_id}.yaml`); + writeFileSync(file, text); + const before = pkg ? await deps.readCrashes(o.target, pkg) : null; + let flowError = await deps.runFlow(o.target, file, path.join(dir, `run-${f.finding_id}`), + { ...(o.appId ? { APP_ID: o.appId } : {}), ...(o.env ?? {}) }, o.timeoutMs ?? 300_000); + if (flowError && o.secrets?.length) flowError = redact(flowError, o.secrets); + const after = pkg ? await deps.readCrashes(o.target, pkg) : null; + result = judgeRegression({ check: f.check, platform: o.target.platform, flowError, before, after }); + } catch (e) { + result = { outcome: "failed", detail: `could not run the flow: ${(e as Error).message.slice(0, 300)}` }; + } + } + out.push({ finding_id: f.finding_id, ...result }); + await deps.report(f.finding_id, { + job_id: o.job.job_id, device_id: o.target.id, build, outcome: result.outcome, detail: result.detail, + }).catch(() => { /* the device row still carries it; a missed report is not a failed test */ }); + } + return out; +} diff --git a/docs/agents.md b/docs/agents.md index 5c703e8..92da17e 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -62,6 +62,9 @@ the file name to write. `--out -` writes to stdout. | `fleetr retry ID [--device ID] [--pool P] [--wait]` | Run again under a new id; `--wait` waits and exits with the verdict | | `fleetr results [JOB] [--device] [--workload] [--job] [--failures] [--limit N]` | Result rows, final rows only unless a job is named; default 20 | | `fleetr flaky [--device ID] [--app NAME]` | Builds that both passed and failed on one device | +| `fleetr findings [--app A] [--state open\|triaged\|all] [--verdict V] [--check C] [--since 24h] [--limit N] [--page N]` | What night QA found, newest sighting first; default 50 per page | +| `fleetr finding ID [--flow FILE\|-]` | One finding: steps, evidence, regression test, verdict history. `--flow` writes its Maestro (or tvloop) replay flow; `-` or no file is stdout | +| `fleetr verdict ID real\|duplicate\|not-a-bug\|agent-mistake\|fixed\|reopen [--note T] [--duplicate-of ID]` | Judge a finding. `fixed` only after `real`, once a fix has merged; exit 5 (`conflict`) otherwise | | `fleetr whoami` | Which collector, its auth mode, who you are to it and your scopes | | `fleetr login [--url U] [--token T]` · `fleetr logout [--url U]` | Save a token for a collector (from `--token` or stdin), or forget it | @@ -71,6 +74,56 @@ Which collector: `--url`, then `FLEET_RUNNER_URL`, then `FLEET_URL`, then overrides the `source` recorded on jobs (`cli` by default), for example `FLEET_SOURCE=ci` in a workflow. +## A morning brief + +`fleetr findings --since 24h --json` is the input for a scheduled agent +session that starts from last night's findings. This repository does not build +that session; it makes the input exist, in a shape that will not change +without a version note in the changelog: + +```json +{ + "items": [ + { + "id": 42, "app": "greenfolio", "build": "1.4 (12)", "platform": "android", + "device_id": "R58M...", "job_id": "explore-...", "mission_id": "add-a-plant", + "check": "crash", "severity": "high", + "title": "Crash: java.lang.NullPointerException", "detail": "...", + "screen": "02c1db49ee", "screen_name": "Add plant", + "steps": ["On \"My plants\":", " Tap \"Add plant\"", "..."], + "replay": { "kind": "maestro", "sha256": "...", "attempts": 2, "reproduced": 2 }, + "replay_label": "reproduced 2/2", + "artifacts": { "shot": "...", "sheet": "...", "trajectory": "...", "replay": "..." }, + "first_seen": "2026-10-15T02:14:09Z", "last_seen": "2026-10-15T02:14:09Z", + "seen_count": 1, "builds_seen": ["1.4 (12)"], + "verdict": null, "verdict_note": null, "verdict_at": null, "duplicate_of": null, + "status": "open", "issue": null, "regression": null + } + ], + "page": 1, "per_page": 50, "total": 1, "pages": 1 +} +``` + +The rules for reading it: + +- `since` filters on **last seen**, so a finding first seen a week ago that + came back last night is in the list; `first_seen` tells them apart. +- `verdict: null` is open: nobody has judged it, or a regression test + reopened it (`fleetr finding ID` shows a `regressed on build ...` line). +- `agent_mistake` and `not_a_bug` are not bugs in the app. +- `replay_label` is the evidence: `reproduced 2/2` is solid, `flaky 1/2` is + weaker, `crash log` means the platform's crash log is the evidence. +- `regression` is `null`, or the state of the test it became: `candidate` + (real), `active` (fixed, in the nightly) or `retired`. +- The list envelope is the control API's; `--page N` and `--limit N` page it, + and `total` says how many match. The Finding schema in `openapi.json` is the + full contract. + +Then `fleetr finding ID --flow repro.yaml` gives the flow to reproduce it with +(`maestro test repro.yaml`, or `fleetr run ui-test` with it in a flows +directory), and once a fix has merged, `fleetr verdict ID fixed --note "PR +#123"` makes it a regression test in the app's nightly. + ## The skill ```bash @@ -81,7 +134,8 @@ fleet skill show A short file telling an agent the order to call things in (devices, workloads, validate, run, wait, artifacts), what each verdict and exit code -means, and what not to do: report a skip as a pass, pin someone else's device, +means, how to read a finding (`agent_mistake` is not a bug; never mark one +`fixed` without a fix merged), and what not to do: report a skip as a pass, pin someone else's device, retry a failure without reading it, poll in a loop, or run `shell`. Its tool and exit-code tables are generated from the code and checked by the test suite, so they cannot fall behind the binary. @@ -101,7 +155,10 @@ and `"--token", "fr_..."` if it has tokens on (or set `FLEET_RUNNER_TOKEN` in the server's `env`; a saved `fleetr login` for that URL also works). Tools: `fleet_devices`, `fleet_workloads`, `fleet_validate`, `fleet_run`, `fleet_job`, `fleet_cancel`, `fleet_retry`, `fleet_results`, `fleet_flaky`, -`fleet_artifact`, `fleet_whoami`. Each carries read-only and destructive +`fleet_artifact`, `fleet_findings`, `fleet_finding`, `fleet_verdict`, +`fleet_whoami`. `fleet_finding` returns the replay flow's text inline when it +is 16 KiB or less (nearly always); `fleet_verdict` is the one findings tool +that changes anything, and needs the `run` scope. Each carries read-only and destructive annotations and, where it returns a summary, an output schema. Screenshots come back as images. Jobs, workloads, devices and artifacts are also readable as resources (`fleet://job/{id}` and so on). diff --git a/docs/api.md b/docs/api.md index 6d66b68..19d679d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -21,14 +21,17 @@ disagree: the test suite fails if they do. | `GET /api/v1/workloads` · `/workloads/{name}` | read | What the fleet can run: executor, params schema, a valid example spec, how many live agents can take it | | `GET /api/v1/templates` | read | Saved job templates | | `GET /api/v1/jobs` | read | Jobs; filter by `status` (`waiting`, `queued`, `claimed`, `done`, `failed`, `cancelled`, `skipped`), `workload`, `executor` (`device` or `host`), `device`, `pool`, `source`, `requested_by`, `mine=true`, `q` (substring of the job id), `from`/`to` | -| `POST /api/v1/jobs` | run | Enqueue. 201 with the job id, its status, and links to its summary and wait URLs. 422 `no_capable_agent` when no live agent declares the workload (or backend); 400 `no_matching_devices` for a fan-out that matches nothing, and 400 `no_build` when `latest` names no published build | +| `POST /api/v1/jobs` | run | Enqueue. 201 with the job id, its status, and links to its summary and wait URLs. 422 `no_capable_agent` when no live agent declares the workload (or backend), or `unresolved_reference`; 400 `no_matching_devices` when the targets match no registered device, `no_build` when `latest` names no published build, and `invalid_spec`, `invalid_match`, `invalid_dependency`, `secret_in_spec`. The OpenAPI document lists the same | | `POST /api/v1/jobs/validate` | run | Dry run: schema errors by path, the devices it would land on, warnings. Always 200 | | `GET /api/v1/jobs/{id}` | read | One job, with its spec | | `GET /api/v1/jobs/{id}/summary` | read | The verdict across every device, per-device outcomes and artifact refs. Works for a fan-out parent | | `GET /api/v1/jobs/{id}/wait?timeout_s=` | read | Long-poll (≤ 120 s) until the job finishes; returns the summary | | `POST /api/v1/jobs/{id}/cancel` · `/retry` | run | Cancel (cascades over a fan-out) or run again under a new id | | `GET /api/v1/results` · `/results/flaky` | read | Result rows (`include=payload` for the raw row), and tests whose verdict flips on one build | -| `GET /api/v1/artifacts/{sha256}` · `/content` | read | What an artifact is, and its bytes. Active types (HTML, SVG) are served as attachments with a sandbox CSP | +| `GET /api/v1/artifacts/{sha256}` · `/content` | read | What an artifact is, and its bytes. `channel` is `pr` for a pull request's build (`latest` never resolves to it) and `main` otherwise. Active types (HTML, SVG) are served as attachments with a sandbox CSP | +| `GET /api/v1/findings` | read | What night QA found; filter by `app`, `state` (`open`, `triaged`, `all`), `verdict` (comma-separated), `check`, `since` (ISO 8601 or `24h`, `7d`). See [Findings](#findings) | +| `GET /api/v1/findings/{id}` | read | One finding: steps in words, evidence as links, the replay flow (inline up to 16 KiB), its regression test, verdict history, counts | +| `POST /api/v1/findings/{id}/verdict` | run | `{verdict, note?, duplicate_of?}`: `real`, `duplicate`, `not_a_bug`, `agent_mistake`, `fixed` (only after `real`; 409 `conflict` otherwise) or `null` to reopen. Audited | | `GET /api/v1/schedules` · `/alerts` | read | Recurring jobs and open alerts | | `GET /api/v1/audit` | admin | Who did what, when tokens are on | | `GET /metrics` | read | The fleet in Prometheus text format: devices by status, jobs by status, oldest queued job, per-device success ratio over 24 h, open alerts, artifact counts. Computed from the database on each scrape. Not under `/api/v1` and not in the OpenAPI document | @@ -100,6 +103,8 @@ artifacts). See [the protocol](protocol.md#authentication-optional) and | `POST /artifacts` | Upload bytes; returns `sha256`. Headers: `x-artifact-name`, and for a build `x-artifact-app`, `x-artifact-build`, `x-artifact-platform`. `x-artifact-channel: pr` marks a pull request's build, which `"sha256": "latest"` never resolves to; any other channel value is a 400. See [Publish builds on merge](integration/publish-on-merge.md#pull-request-builds-never-move-latest) | | `GET /artifacts/:sha256` | Download, supports Range | | `POST /findings` | An `explore` finding from an executor; merged on its fingerprint. See [Findings and verdicts](explore/findings.md#the-api) | +| `GET /findings/regressions?app=&state=active&platform=` | A nightly `ui-test` pulling an app's regression flows. See [Regression tests](explore/findings.md#regression-tests) | +| `POST /findings/:id/regression` | An executor reporting one regression run: `{job_id, device_id, build, outcome, detail}`; `reproduced` reopens the finding | | `POST /api/jobs/:id/mirror` | One raw JPEG frame from an executor driving a device, for the live view. Kept in memory only (the last three frames), never stored; 2 MB cap per frame. The one row here that `FLEET_DASH_TOKEN` does guard; the `explore` workload sends it | ## Queue @@ -179,12 +184,17 @@ From the [`explore`](explore/index.md) workload. Full shapes and replies are in | Method & path | Purpose | |---|---| -| `GET /api/findings` | The list: `?app= &check= &status=open\|triaged\|all &since= &limit=` | -| `GET /api/findings/:id` | One finding, with its duplicates | +| `GET /api/findings` | The list: `?app= &check= &status=open\|triaged\|all &verdict= &since= &limit= &offset=` | +| `GET /api/findings/:id` | One finding, with its duplicates, evidence links, replay flow, regression test and history | | `GET /api/findings/precision` | How often each check and visual class was judged real; which are switched off | | `GET /api/findings/digest?hours=` | The morning digest, as text and as data | | `GET /api/findings/issues` | Every GitHub issue composed, dry run or filed | -| `POST /api/findings/:id/verdict` | Real, duplicate, not a bug, agent's mistake, or reopen. Guarded | +| `POST /api/findings/:id/verdict` | Real, duplicate, not a bug, agent's mistake, fixed (only after real), or reopen. Guarded | + +The control API has the list, the detail and the verdict too +(`/api/v1/findings`, above). Both call the same functions in +`collector/src/findings.ts`; the v1 verdict needs the `run` scope with tokens +on, and the dashboard's route here keeps the `admin` it always needed. ## Mutations diff --git a/docs/dashboard.md b/docs/dashboard.md index 4004b1c..ae22a18 100644 --- a/docs/dashboard.md +++ b/docs/dashboard.md @@ -60,8 +60,10 @@ artifacts uploaded and garbage-collected. Alerts appear as a banner on every screen. The layout works on a phone, and `?` lists the keyboard shortcuts — `g j` jobs, `g d` devices, `g f` findings, `g n` new job, -`/` search, and on a finding `r`, `d`, `n` or `a` for its verdict (real, -duplicate, not a bug, the agent's mistake). +`/` search, and on a finding `r`, `d`, `n`, `a` or `f` for its verdict (real, +duplicate, not a bug, the agent's mistake, fixed). Fixed is offered only once a +finding is real, and a finding with a regression test shows its state, last +run and verdict history in a panel of its own. ## When the collector wants a token diff --git a/docs/explore/findings.md b/docs/explore/findings.md index 6e9b3a5..697e9bb 100644 --- a/docs/explore/findings.md +++ b/docs/explore/findings.md @@ -15,7 +15,7 @@ builds it has been seen, how it replayed ("reproduced 2/2", "flaky 1/2", The **detail** view shows the screenshot, the steps in words, the detail text with every replay's outcome, links to the contact sheet, trajectory, log and -replay file, and four buttons: +replay file, and five buttons: | Button | Key | Means | Counts towards precision | |---|---|---|---| @@ -23,12 +23,19 @@ replay file, and four buttons: | **Duplicate** | d | The same problem as another finding (pick which) | No | | **Not a bug** | n | The app is fine; the check was wrong | Yes, as a miss | | **Agent's mistake** | a | The explorer did something odd and reported its own doing | Yes, as a miss | +| **Fixed** | f | Real, and a fix has merged. Only after Real | Yes, as a hit | A note is optional and is kept with the verdict. Setting the verdict to none reopens a finding. A duplicate follows its chain to the original, and a loop is refused. The keys are ignored straight after g, so g r still goes to Results. +**Fixed** is greyed out until a finding is Real (the collector refuses it +otherwise, with a 409). It turns the finding's replay flow into a regression +test; see [Regression tests](#regression-tests). Once a finding has one, a +**Regression test** panel shows its state, its last run and the verdict +history. + A **precision table** at the top shows, for every check that has verdicts, how often it was right and whether it has been switched off. @@ -49,6 +56,58 @@ on its own; the judge is told not to report it and the rest keep running. Any other check is switched off whole. **Crashes and ANRs are never switched off**: their evidence is the platform's own log, not a judgement. +## Regression tests + +A finding that was real and is fixed becomes a test, with no hand-copying: + +| Verdict | What happens to the finding's replay flow | +|---|---| +| **Real** | Copied into the collector's `regressions` table as a **candidate**. Not run yet | +| **Fixed** (only after Real) | The candidate becomes **active**. A finding marked Real before this release goes straight to active | +| **Duplicate**, **Not a bug**, **Agent's mistake** | A candidate or active test is **retired** | +| Real again, on a retired one | Back to **candidate** | +| Reopen (none) | Left as it is | + +The flow is copied into the database, not written to the lab's flows +directory: that directory is outside git and outside any backup this +repository controls, and a copy in the database also outlives the artifact +store's garbage collection. A finding with no replay file (some crashes) or +whose file the store has already collected gets no test, and the verdict's +answer says so. + +**How a test runs.** Nothing is scheduled automatically. An app's nightly +`ui-test` opts in once with `params.regressions` (the app key the findings are +filed under, or `true` for `app.name`), and from then on every finding marked +Fixed is in the next night's run. The executor pulls the app's active flows +from the collector at run time and runs each, after the suite's own flow, on +every device of the same platform. See [ui-test](../workloads/host.md#ui-test). + +**What it asserts.** For a **crash** or **ANR** finding on Android, the +executor reads the crash buffer (`logcat -b crash`, and `am_anr` in the events +buffer) before and after the flow; a new crash of the package during it is the +bug coming back. For **every other check** (frozen, blank, left_app, a11y, +visual, goal, dead_control) the oracle that found the bug was a model or a +heuristic the flow does not carry, so the honest claim is weaker: **the flow +replays without error**. Such a flow failing fails the device's row but does +not reopen anything, because a step that no longer replays may be the bug or +may be a redesigned screen. On iOS no crash buffer is read, so a crash +finding's flow is also "replays without error" there, and its detail says so. +tvloop flows (a Roku's) are kept but not run: ui-test drives Maestro. + +**When it comes back.** A run that reproduces the crash reopens the finding: +the verdict is cleared, it is counted as seen once more, the build is added to +its builds, and its history gets a line such as `regressed on build 1.4 (12) +(job nightly-ui-…, R58M…): the app crashed again during the flow: …`. The +device's row fails with `regression #N reproduced (finding reopened)`. Three +devices reproducing it in one job reopen it once. The test stays active, so +the nightly keeps failing until the finding is marked Fixed again. + +**Not verified:** no nightly on the lab has run a regression flow yet; the +logic is covered by the collector's suite against fake crash readings and a +fake Maestro, not by a phone. GitHub issues are only ever created, never read +back, so an issue being closed does not mark a finding fixed; the verdict is +the only trigger. + ## The morning digest Set on the collector: @@ -152,8 +211,8 @@ finding. | Method & path | | |---|---| -| `GET /api/findings?app=&check=&status=open\|triaged\|all&since=&limit=` | Newest last-seen first; up to 500 | -| `GET /api/findings/:id` | One finding, with its duplicates | +| `GET /api/findings?app=&check=&status=open\|triaged\|all&verdict=&since=&limit=&offset=` | Newest last-seen first; up to 500. `since` takes ISO 8601 or a span such as `24h` | +| `GET /api/findings/:id` | One finding, with its duplicates, evidence links, replay flow, regression test and verdict history | | `GET /api/findings/precision?app=&min=10` | `{floor, min, classes[], disabled[]}`; the workload reads `disabled` at the start of a night | | `GET /api/findings/digest?hours=12` | The digest, as text and as data | | `GET /api/findings/issues` | Every issue composed, dry run or filed | @@ -162,7 +221,21 @@ finding. | Method & path | | |---|---| -| `POST /api/findings/:id/verdict` | `{verdict: "real"\|"duplicate"\|"not_a_bug"\|"agent_mistake"\|null, note?, duplicate_of?}`. Needs `X-Fleet-Token` when `FLEET_DASH_TOKEN` is set | +| `POST /api/findings/:id/verdict` | `{verdict: "real"\|"duplicate"\|"not_a_bug"\|"agent_mistake"\|"fixed"\|null, note?, duplicate_of?}`. Needs `X-Fleet-Token` when `FLEET_DASH_TOKEN` is set. `fixed` before `real` is a 409. Answers with the finding, its regression test and `change`, one sentence on what the verdict did to the test | + +The same reads and the verdict are in the control API as `GET +/api/v1/findings`, `GET /api/v1/findings/{id}` and `POST +/api/v1/findings/{id}/verdict` (scope `run`, audited); both call the same +functions. See [Control API](../api.md#findings). + +### Regression runs (executors) + +Protocol routes, like `POST /findings`: + +| Method & path | | +|---|---| +| `GET /findings/regressions?app=&state=active&platform=` | `{regressions: [...]}`, each with its flow text. `state` is `candidate`, `active` (default), `retired` or `all` | +| `POST /findings/:id/regression` | `{job_id, device_id, build, outcome: "passed"\|"reproduced"\|"failed"\|"skipped", detail}`. `reproduced` on an active test reopens the finding | ## Retention diff --git a/docs/workloads/host.md b/docs/workloads/host.md index 499df54..17a67e9 100644 --- a/docs/workloads/host.md +++ b/docs/workloads/host.md @@ -279,6 +279,50 @@ all, the error is its exit code and the last line it printed to stderr, never its command line, which carries the test account's password. Until 0.9 the reason was in the uploaded report and nowhere else. +### Regression tests from fixed findings + +`params.regressions` adds the app's fixed night-QA findings to the run. Set it +to the app key the findings are filed under (what `fleetr findings` shows in +the APP column), or `true` to use `app.name`: + +```json +{ "workload": "ui-test", "executor": "host", + "app": { "name": "greenfolio-android", "build": "nightly", "sha256": "latest" }, + "suite": { "kind": "maestro", "flows": "greenfolio/smoke.yaml", "app_id": "com.taylab.greenfolio.smoke" }, + "params": { "regressions": "greenfolio" }, + "targets": { "match": "os ~ 'android'", "exclusive": true } } +``` + +At run time the executor asks the collector for the app's **active** +regression flows (`GET /findings/regressions`), and after the suite's own flow +runs each one whose finding was on the same platform as the device. A finding +joins by being marked Real and then Fixed; nobody edits the schedule. `flows` +may be left out to run only the regression flows; a device with none to run is +then skipped, not passed. + +Each stored flow is adapted before it runs: its `appId` becomes the job's +`suite.app_id` when the job sets one (night QA often explores `.debug`; the +nightly may test `.smoke`), and a relative `runFlow` (the mission's sign-in +flow) is resolved under the flows directory. The suite's sign-in variables +reach the flow as they reach the suite's. + +What a run asserts depends on the finding's check: + +| Finding | On Android | Elsewhere | +|---|---|---| +| `crash`, `anr` | No new crash or ANR of the package in `logcat -b crash` / `am_anr` during the flow. A new one is `reproduced` and **reopens the finding** | Replays without error; the crash is not checked, and the detail says so | +| Any other check | Replays without error | Replays without error | + +"Replays without error" is all a replay can claim for a check whose oracle was +a model or a heuristic: the flow repeats the steps, not the judgement. A flow +that fails is `failed` and fails the row, without reopening the finding, +because a step that no longer replays may be a redesigned screen. tvloop flows +are skipped (ui-test drives Maestro). Each regression counts as one test in +the row's `passed`/`failed`, is listed in `test.regressions` with its outcome, +and a failing one is named in the row's `error`. The regressions run outside +`params.network` shaping. Not yet run on the lab; see [Regression +tests](../explore/findings.md#regression-tests). + **iOS UI tests need a Mac with full Xcode.** `simctl` and `devicectl` ship with Xcode, not the Command Line Tools, so they run on a different executor from the Android work. [The iOS executor](../deploy/ios-executor.md) covers standing one diff --git a/fleet/src/mcp/protocol.ts b/fleet/src/mcp/protocol.ts index 456a670..81c9051 100644 --- a/fleet/src/mcp/protocol.ts +++ b/fleet/src/mcp/protocol.ts @@ -32,7 +32,9 @@ const INSTRUCTIONS = (where: string | null) => "The usual order: fleet_devices (what is online) -> fleet_workloads name= (a valid example spec) -> " + "fleet_validate (fix what it says) -> fleet_run (waits for the verdict) -> fleet_artifact (screenshots, logs).\n" + "A verdict of skipped means nothing ran; never report it as a pass. Do not retry a failed job more than once " + - "without reading its error. Prefer targets.pool or targets.match over pinning a device_id another person may be using." + + "without reading its error. Prefer targets.pool or targets.match over pinning a device_id another person may be using.\n" + + "Night QA's findings: fleet_findings since=24h (last night) -> fleet_finding id= (steps and the replay flow). " + + "agent_mistake is not a bug; mark a finding fixed with fleet_verdict only after a fix has merged." + (where ? `\n\nCollector: ${where}` : ""); /** One message in, zero or one out. */ diff --git a/fleet/src/mcp/tools.ts b/fleet/src/mcp/tools.ts index 59d95c3..b8388bb 100644 --- a/fleet/src/mcp/tools.ts +++ b/fleet/src/mcp/tools.ts @@ -71,6 +71,7 @@ const NEXT: Record = { unauthorized: "The gateway or CLI has no valid token for the collector.", unreachable: "The collector did not answer. It may be down or the URL may be wrong.", rate_limited: "Too many calls; wait a minute.", + conflict: "The state does not allow it. For fleet_verdict fixed: mark the finding real first, and fixed once the fix has merged.", }; export function refusal(name: string, e: unknown, remote: boolean): ToolResult { @@ -197,6 +198,60 @@ const SUMMARY_OUT: Record = { const READ = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }; +const FINDING_ITEM: Record = { + type: "object", + required: ["id", "app", "check", "severity", "title", "verdict", "replay", "seen_count"], + properties: { + id: { type: "integer" }, app: { type: "string" }, check: { type: "string" }, severity: { type: "string" }, + title: { type: "string" }, screen: { type: "string" }, platform: { type: "string" }, + verdict: { type: ["string", "null"], description: "null: open. agent_mistake: not a bug in the app." }, + replay: { type: "string", description: "reproduced 2/2, flaky 1/2, crash log." }, + seen_count: { type: "integer" }, builds: { type: "integer" }, last_seen: { type: ["string", "null"] }, + regression: { type: ["string", "null"], description: "candidate, active (in the nightly) or retired." }, + }, +}; + +const FINDINGS_OUT: Record = { + type: "object", + required: ["findings", "total"], + properties: { findings: { type: "array", items: FINDING_ITEM }, total: { type: "integer" } }, +}; + +const FINDING_OUT: Record = { + type: "object", + required: ["id", "app", "check", "title", "verdict", "steps", "evidence", "history"], + properties: { + ...(FINDING_ITEM.properties as Record), + detail: { type: "string" }, + steps: { type: "array", items: { type: "string" } }, + evidence: { type: "array", items: { type: "object" } }, + replay_flow: { type: ["object", "null"], description: "kind, sha256, and text when the flow is small enough to inline." }, + regression_test: { type: ["object", "null"] }, + history: { type: "array", items: { type: "object" } }, + note: { type: "string" }, + }, +}; + +const VERDICT_OUT: Record = { + type: "object", + required: ["id", "verdict"], + properties: { id: { type: "integer" }, verdict: { type: ["string", "null"] }, change: { type: ["string", "null"] }, regression: { type: ["string", "null"] } }, +}; + +type FindingRow = { + id: number; app: string; check: string; severity: string; title: string; screen_name: string; platform: string; + verdict: string | null; replay_label: string; seen_count: number; builds_seen: string[]; last_seen: string | null; + regression: { state: string } | null; +}; + +const findingItem = (f: FindingRow) => ({ + id: f.id, app: f.app, check: f.check, severity: f.severity, title: f.title, screen: f.screen_name, platform: f.platform, + verdict: f.verdict, replay: f.replay_label, seen_count: f.seen_count, builds: f.builds_seen.length, last_seen: f.last_seen, + regression: f.regression?.state ?? null, +}); + +const VERDICT_WORDS = ["real", "duplicate", "not_a_bug", "agent_mistake", "fixed"] as const; + // --- the tools --------------------------------------------------------------------------- export const TOOLS: Tool[] = [ @@ -466,6 +521,119 @@ export const TOOLS: Tool[] = [ return readArtifact(client, sha, Math.max(500, Math.min(Number(args.max_chars ?? 20_000) || 20_000, 200_000))); }, }, + { + name: "fleet_findings", + title: "What night QA found", + cli: "fleetr findings [--app A] [--since 24h]", + description: + "Bugs night QA (the explore workload) found on real devices, newest sighting first. Each was replayed on a clean " + + "install before it was filed: `replay` says how often it reproduced (\"flaky 1/2\" is weaker evidence). verdict " + + "null is open; agent_mistake means the model misread the app and is NOT a bug. since=\"24h\" is last night. " + + "fleet_finding with an id gives the steps, evidence and the replay flow.", + inputSchema: { + type: "object", + properties: { + app: { type: "string", description: "The explore app key, e.g. greenfolio." }, + state: { type: "string", enum: ["open", "triaged", "all"], description: "Default all." }, + verdict: { type: "string", description: "Comma-separated: real, duplicate, not_a_bug, agent_mistake, fixed." }, + check: { type: "string", description: "crash, anr, frozen, blank, left_app, a11y, visual, goal, dead_control." }, + since: { type: "string", description: "ISO 8601, or a span back from now: 24h, 7d." }, + limit: { type: "number", description: "Default 30, at most 200." }, + }, + }, + outputSchema: FINDINGS_OUT, + annotations: READ, + needs: "read", + async run({ client }, args) { + const s = (k: string) => (typeof args[k] === "string" && args[k] ? (args[k] as string) : undefined); + const page = await client.listFindings({ + app: s("app"), state: s("state") as "open" | "triaged" | "all" | undefined, verdict: s("verdict"), check: s("check"), since: s("since"), + per_page: Math.max(1, Math.min(Number(args.limit ?? 30) || 30, 200)), + }); + const out = { findings: page.items.map((f) => findingItem(f as FindingRow)), total: page.total }; + return ok(out.findings.length ? out : "No findings match.", out); + }, + }, + { + name: "fleet_finding", + title: "One finding, with its replay flow", + cli: "fleetr finding ID [--flow FILE]", + description: + "One finding by id: what went wrong, the steps in words, links to the screenshot, contact sheet, trajectory and " + + "log (open them with fleet_artifact), its verdict history, its regression test, and the Maestro (or tvloop) flow " + + "that replays it -- inline when small, so you can reproduce the bug with fleet_run or locally.", + inputSchema: { + type: "object", + required: ["id"], + properties: { + id: { type: "integer", description: "The finding id." }, + include_flow: { type: "boolean", description: "Include the replay flow text when it is small. Default true." }, + }, + }, + outputSchema: FINDING_OUT, + annotations: READ, + needs: "read", + async run({ client }, args) { + const id = Number(args.id); + if (!Number.isInteger(id) || id < 1) return failure("id must be a finding id (a positive integer)"); + const f = await client.getFinding(String(id)); + const flow = f.replay_flow + ? { kind: f.replay_flow.kind, sha256: f.replay_flow.sha256, ...(args.include_flow !== false && f.replay_flow.text !== null ? { text: f.replay_flow.text } : {}), + ...(f.replay_flow.truncated ? { note: "too big to inline; fleet_artifact with this sha256 returns it" } : {}) } + : null; + const out = { + ...findingItem(f as FindingRow), + detail: clip(f.detail, 4000) ?? "", + steps: f.steps, + evidence: f.evidence.map((e) => ({ role: e.role, sha256: e.sha256, in_store: e.in_store })), + replay_flow: flow, + regression_test: f.regression + ? { state: f.regression.state, asserts: f.regression.asserts, runs: f.regression.runs, last_outcome: f.regression.last_outcome ?? null, last_detail: f.regression.last_detail ?? null } + : null, + history: f.history, + ...(f.verdict === "agent_mistake" ? { note: "agent_mistake: the model misread the app. Not a bug; do not fix the app for it." } : {}), + }; + const result = ok(out, out); + if (f.artifacts.shot) result.content.push({ type: "resource_link", uri: `fleet://artifact/${f.artifacts.shot}`, name: "screenshot", mimeType: "image/png" }); + return result; + }, + }, + { + name: "fleet_verdict", + title: "Judge a finding", + cli: "fleetr verdict ID VERDICT [--note TEXT]", + description: + "Record a verdict on a finding. real: a bug in the app (its replay flow is kept as a candidate regression test). " + + "fixed: only after real, and only once a fix has MERGED -- the flow then runs in the app's nightly and reopens the " + + "finding if the crash comes back. not_a_bug / agent_mistake: the check or the model was wrong (retires any test). " + + "duplicate needs duplicate_of. Verdicts decide which checks night QA keeps running, so do not guess.", + inputSchema: { + type: "object", + required: ["id", "verdict"], + properties: { + id: { type: "integer" }, + verdict: { type: "string", enum: [...VERDICT_WORDS] }, + note: { type: "string", description: "Why, for whoever reads it next. Name the fix's PR when marking fixed." }, + duplicate_of: { type: "integer", description: "With duplicate: the finding this one duplicates." }, + }, + }, + outputSchema: VERDICT_OUT, + annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false }, + needs: "run", + async run({ client }, args) { + const id = Number(args.id); + if (!Number.isInteger(id) || id < 1) return failure("id must be a finding id (a positive integer)"); + const verdict = String(args.verdict ?? "").replace(/-/g, "_"); + if (!(VERDICT_WORDS as readonly string[]).includes(verdict)) return failure(`verdict must be one of ${VERDICT_WORDS.join(", ")}`); + const r = await client.setFindingVerdict(String(id), { + verdict: verdict as (typeof VERDICT_WORDS)[number], + ...(typeof args.note === "string" && args.note ? { note: args.note } : {}), + ...(args.duplicate_of !== undefined ? { duplicate_of: Number(args.duplicate_of) } : {}), + }); + const out = { id, verdict: r.finding.verdict ?? null, change: r.change ?? null, regression: r.finding.regression?.state ?? null }; + return ok(out, out); + }, + }, { name: "fleet_whoami", title: "Who am I to the fleet", diff --git a/fleet/src/work.ts b/fleet/src/work.ts index 128cc5c..39a1572 100644 --- a/fleet/src/work.ts +++ b/fleet/src/work.ts @@ -17,7 +17,7 @@ import { homedir } from "node:os"; import path from "node:path"; import { Readable } from "node:stream"; import { pipeline } from "node:stream/promises"; -import type { FleetClient, JobSpecInput, JobSummary } from "../../collector/src/client/index.js"; +import type { FindingVerdictInput, FleetClient, JobSpecInput, JobSummary } from "../../collector/src/client/index.js"; import { FleetApiError } from "../../collector/src/client/index.js"; import { childEnv, load } from "./config.js"; import { connect, readCredentials, resolveBrain, writeCredentials } from "./connect.js"; @@ -326,6 +326,109 @@ async function artifact(client: FleetClient, a: Args) { return EXIT.passed; } +/** `not-a-bug` and `agent-mistake` as typed, the API's names, or `reopen` for null. */ +export function verdictWord(raw: string | undefined): FindingVerdictInput["verdict"] | undefined { + if (!raw) return undefined; + const w = raw.trim().toLowerCase().replace(/-/g, "_"); + if (w === "reopen" || w === "open") return null; + return (["real", "duplicate", "not_a_bug", "agent_mistake", "fixed"] as const).find((v) => v === w); +} + +async function findings(client: FleetClient, a: Args) { + const page = await client.listFindings({ + app: str(a, "app"), state: str(a, "state") as "open" | "triaged" | "all" | undefined, verdict: str(a, "verdict"), + check: str(a, "check"), since: str(a, "since"), per_page: num(a, "limit", 50), page: num(a, "page", 1), + }); + if (a.flags.json) return printJson(page), EXIT.passed; + if (!page.items.length) { + err("no findings match"); + return EXIT.passed; + } + table( + page.items.map((f) => [ + `#${f.id}`, f.app, f.check, f.severity, f.verdict ?? "open", f.replay_label, `${f.seen_count}x`, ago(f.last_seen), + f.regression ? f.regression.state : "", f.title.slice(0, 60), + ]), + ["ID", "APP", "CHECK", "SEV", "VERDICT", "REPLAY", "SEEN", "LAST", "REGRESSION", "TITLE"], + ); + if (page.total > page.items.length) err(`${page.items.length} of ${page.total}; --limit N or --page N for more`); + return EXIT.passed; +} + +function findingIdOf(a: Args, usage: string): number { + const raw = (a.positional[0] ?? "").replace(/^#/, ""); + if (!/^\d+$/.test(raw)) throw new UsageError(usage); + return Number(raw); +} + +async function finding(client: FleetClient, a: Args) { + const id = findingIdOf(a, "usage: fleet finding [--flow FILE|-] [--json]"); + const f = await client.getFinding(String(id)); + // --flow with no file is stdout, so `fleet finding 12 --flow > repro.yaml` works. + const dest = a.flags.flow === true ? "-" : str(a, "flow"); + if (dest) { + const rf = f.replay_flow; + if (!rf) { + err(`finding ${id} has no replay flow (${f.replay_label})`); + return EXIT.error; + } + let text = rf.text; + if (text === null) { + if (!rf.in_store) { + err(`finding ${id}'s replay flow ${rf.sha256} is no longer in the artifact store`); + return EXIT.error; + } + text = await (await client.getArtifactContent(rf.sha256, undefined, { timeoutMs: 60_000 })).text(); + } + if (dest === "-") process.stdout.write(text); + else { + writeFileSync(dest, text); + err(`wrote ${dest} (${rf.kind} flow, ${Buffer.byteLength(text)} bytes)`); + } + if (dest === "-" || a.flags.json !== true) return EXIT.passed; + } + if (a.flags.json) return printJson(f), EXIT.passed; + out(`#${f.id} ${f.title}`); + out(` ${f.app} · ${f.check} (${f.severity}) · ${f.verdict ?? "open"} · ${f.replay_label} · seen ${f.seen_count}x on ${f.builds_seen.length} build${f.builds_seen.length === 1 ? "" : "s"}`); + out(` ${f.screen_name || "unnamed screen"} on ${f.device_id} (${f.platform}), mission ${f.mission_id}, first found by ${f.job_id}`); + if (f.verdict === "agent_mistake") out(" agent_mistake: the model misread the app; this is not a bug in it."); + if (f.detail) out(`\n${f.detail}`); + if (f.steps.length) { + out("\nsteps"); + f.steps.forEach((s, i) => out(` ${i + 1}. ${s}`)); + } + if (f.evidence.length) { + out("\nevidence"); + for (const e of f.evidence) out(` ${e.label.padEnd(14)} ${e.sha256}${e.in_store ? "" : " (collected)"}`); + } + if (f.replay_flow) out(`\nreplay flow: ${f.replay_flow.kind}, ${f.replay_flow.sha256} (fleet finding ${f.id} --flow FILE writes it)`); + if (f.regression) { + const r = f.regression; + out(`regression test: ${r.state}, ${r.asserts === "no_crash" ? "asserts no crash" : "replays without error"}, run ${r.runs}x${r.last_outcome ? `, last ${r.last_outcome}` : ""}`); + } + if (f.history.length) { + out("\nhistory"); + for (const h of f.history) out(` ${h.at ?? ""} ${h.event === "regressed" ? "regressed" : h.verdict ?? "reopened"}${h.actor ? ` (${h.actor})` : ""}${h.note ? `: ${h.note}` : ""}`); + } + return EXIT.passed; +} + +async function verdict(client: FleetClient, a: Args) { + const usage = "usage: fleet verdict real|duplicate|not-a-bug|agent-mistake|fixed|reopen [--note TEXT] [--duplicate-of ID]"; + const id = findingIdOf(a, usage); + const v = verdictWord(a.positional[1]); + if (v === undefined) throw new UsageError(usage); + const dup = str(a, "duplicate-of"); + const r = await client.setFindingVerdict(String(id), { + verdict: v, + ...(str(a, "note") ? { note: str(a, "note") } : {}), + ...(dup ? { duplicate_of: Number(dup.replace(/^#/, "")) } : {}), + }); + if (a.flags.json) return printJson(r), EXIT.passed; + out(`#${id} ${r.finding.verdict ?? "reopened"}${r.change ? `; ${r.change}` : ""}`); + return EXIT.passed; +} + async function whoami(client: FleetClient, a: Args) { const [me, health] = await Promise.all([client.whoami(), client.getHealth()]); if (a.flags.json) return printJson({ ...me, url: client.baseUrl, version: health.version }), EXIT.passed; @@ -468,6 +571,11 @@ export const WORK_USAGE = ` fleet results [--device ID] [--workload W] [--job ID] [--failures] [--limit N] fleet flaky [--device ID] [--app NAME] UI tests that pass and fail on the same build. fleet artifact SHA [--out FILE|-] Describe or download an artifact. + fleet findings [--app A] [--state open|triaged|all] [--verdict V] [--check C] [--since 24h] [--limit N] + What night QA found. --since 24h --json is the morning brief. + fleet finding ID [--flow FILE|-] One finding: steps, evidence, history; --flow writes its replay flow. + fleet verdict ID real|duplicate|not-a-bug|agent-mistake|fixed|reopen [--note TEXT] [--duplicate-of ID] + fixed only after real, once the fix has merged: its flow joins the nightly. fleet login [--url U] [--token T] | fleet logout | fleet whoami fleet token create NAME --scope read,run,admin,agent,delegate | list | revoke ID|NAME fleet skill show | fleet skill install [--target cursor,claude,codex|DIR] @@ -476,7 +584,7 @@ export const WORK_USAGE = ` Exit codes: 0 passed, 1 failed, 2 usage/invalid spec, 3 still running, 4 skipped (nothing ran), 5 refused/unreachable. `; -export const WORK_COMMANDS = new Set(["devices", "workloads", "run", "job", "wait", "cancel", "retry", "results", "flaky", "artifact", "login", "logout", "whoami", "token", "skill"]); +export const WORK_COMMANDS = new Set(["devices", "workloads", "run", "job", "wait", "cancel", "retry", "results", "flaky", "artifact", "findings", "finding", "verdict", "login", "logout", "whoami", "token", "skill"]); export async function workCommand(command: string, argv: string[]): Promise { const a = parseArgs(argv); @@ -495,6 +603,9 @@ export async function workCommand(command: string, argv: string[]): Promise [--reason R]"); diff --git a/fleet/test/cli.test.ts b/fleet/test/cli.test.ts index 8d637b1..435b25d 100644 --- a/fleet/test/cli.test.ts +++ b/fleet/test/cli.test.ts @@ -7,7 +7,7 @@ import assert from "node:assert/strict"; import { spawn } from "node:child_process"; import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs"; import path from "node:path"; -import { fakeDevice, FLEET, startCollector, tempDir, TSX, type Collector } from "./helpers.js"; +import { fakeDevice, FLEET, postFinding, startCollector, tempDir, TSX, type Collector } from "./helpers.js"; let c: Collector; let device: Awaited>; @@ -160,3 +160,37 @@ test("skill show prints the skill; install writes it and will not clobber a stra assert.match(refused.stderr, /not overwriting/); assert.equal(readFileSync(file, "utf8"), "my own notes\n"); }); + +test("findings, finding --flow and verdict: the morning brief and a finding becoming a test", async () => { + const { id, flow } = await postFinding(c.base, "cliapp"); + const brief = await fleet(["findings", "--since", "24h", "--app", "cliapp", "--json"]); + assert.equal(brief.code, 0, brief.stderr); + const page = json(brief); + assert.deepEqual(Object.keys(page).sort(), ["items", "page", "pages", "per_page", "total"]); + assert.equal(page.items[0].id, id); + assert.equal(page.items[0].verdict, null); + + const human = await fleet(["findings", "--app", "cliapp"]); + assert.equal(human.code, 0, human.stderr); + assert.match(human.stdout, /Crashes on Save/); + + const file = path.join(tempDir("fleet-flow-"), "repro.yaml"); + const wrote = await fleet(["finding", String(id), "--flow", file]); + assert.equal(wrote.code, 0, wrote.stderr); + assert.equal(readFileSync(file, "utf8"), flow); + const shown = await fleet(["finding", `#${id}`]); + assert.match(shown.stdout, /1\. Open the app/); + + const early = await fleet(["verdict", String(id), "fixed"]); + assert.equal(early.code, 5, "fixed before real is refused"); + assert.match(early.stderr, /conflict/); + assert.equal((await fleet(["verdict", String(id), "maybe"])).code, 2); + const real = await fleet(["verdict", String(id), "real", "--note", "seen it"]); + assert.equal(real.code, 0, real.stderr); + assert.match(real.stdout, /candidate/); + const fixed = await fleet(["verdict", String(id), "fixed", "--json"]); + assert.equal(fixed.code, 0, fixed.stderr); + assert.equal(json(fixed).finding.regression.state, "active"); + const notABug = await fleet(["verdict", String(id), "not-a-bug"]); + assert.match(notABug.stdout, /retired/); +}); diff --git a/fleet/test/helpers.ts b/fleet/test/helpers.ts index 7387466..5531cc3 100644 --- a/fleet/test/helpers.ts +++ b/fleet/test/helpers.ts @@ -160,3 +160,22 @@ export async function upload(base: string, bytes: Buffer | string, name: string, } export const tempDir = (prefix: string) => mkdtempSync(path.join(tmpdir(), prefix)); + +/** A night-QA finding posted the way the explore workload posts one, with its replay flow uploaded. Returns the id and the flow. */ +export async function postFinding(base: string, app: string, over: Record = {}): Promise<{ id: number; flow: string }> { + const flow = `appId: com.example.${app}\nname: "repro"\n---\n- launchApp:\n clearState: true\n- tapOn:\n point: "50%,90%"\n`; + const sha = await upload(base, flow, "replay.yaml"); + const res = await fetch(`${base}/findings`, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ + fingerprint: `${app}-${Math.random().toString(36).slice(2)}`, app, build: "1.0 (1)", platform: "android", device_id: "test-phone", + job_id: "explore-test", mission_id: "save", check: "crash", severity: "high", title: "Crashes on Save", detail: "FATAL EXCEPTION", + screen: "s1", screen_name: "Add plant", steps: ["Open the app", "Tap Save"], + replay: { kind: "maestro", sha256: sha, attempts: 2, reproduced: 2 }, artifacts: { replay: sha }, + ...over, + }), + }); + if (!res.ok) throw new Error(`POST /findings ${res.status}: ${await res.text()}`); + return { id: ((await res.json()) as { id: number }).id, flow }; +} diff --git a/fleet/test/mcp.test.ts b/fleet/test/mcp.test.ts index 027ed34..b503c44 100644 --- a/fleet/test/mcp.test.ts +++ b/fleet/test/mcp.test.ts @@ -14,7 +14,7 @@ import { resolveBrain, resolveToken } from "../src/connect.js"; import { handle, type Session } from "../src/mcp/protocol.js"; import { localSession } from "../src/mcp/stdio.js"; import { TOOLS } from "../src/mcp/tools.js"; -import { fakeDevice, FLEET, PNG, startCollector, TSX, upload, type Collector } from "./helpers.js"; +import { fakeDevice, FLEET, PNG, postFinding, startCollector, TSX, upload, type Collector } from "./helpers.js"; let c: Collector; let session: Session; @@ -169,3 +169,33 @@ test("interop: the MCP SDK client drives `fleet mcp` over stdio", async () => { await client.close(); } }); + +test("fleet_findings, fleet_finding with its flow, and fleet_verdict", async () => { + const { id, flow } = await postFinding(c.base, "mcpapp"); + const list = await call("fleet_findings", { app: "mcpapp", since: "24h" }); + assert.ok(!list.isError, list.content[0].text); + assert.equal(list.structuredContent.total, 1); + assert.equal(list.structuredContent.findings[0].id, id); + assert.equal(list.structuredContent.findings[0].replay, "reproduced 2/2"); + + const one = await call("fleet_finding", { id }); + assert.ok(!one.isError, one.content[0].text); + assert.equal(one.structuredContent.replay_flow.text, flow, "a small flow comes back inline"); + assert.deepEqual(one.structuredContent.steps, ["Open the app", "Tap Save"]); + + const early = await call("fleet_verdict", { id, verdict: "fixed" }); + assert.equal(early.isError, true); + assert.match(early.content[0].text ?? "", /conflict/); + assert.match(early.content[0].text ?? "", /real first/); + const real = await call("fleet_verdict", { id, verdict: "real", note: "reproduced locally" }); + assert.equal(real.structuredContent.regression, "candidate"); + const fixed = await call("fleet_verdict", { id, verdict: "fixed", note: "PR #1" }); + assert.equal(fixed.structuredContent.verdict, "fixed"); + assert.equal(fixed.structuredContent.regression, "active"); + + const { result } = await rpc("tools/list"); + const by = Object.fromEntries(result.tools.map((t: { name: string }) => [t.name, t])); + assert.equal(by.fleet_verdict.annotations.readOnlyHint, false); + assert.equal(by.fleet_findings.annotations.readOnlyHint, true); + assert.ok(by.fleet_finding.outputSchema && by.fleet_findings.outputSchema && by.fleet_verdict.outputSchema); +}); diff --git a/skills/fleet-runner/SKILL.md b/skills/fleet-runner/SKILL.md index a43684c..691c863 100644 --- a/skills/fleet-runner/SKILL.md +++ b/skills/fleet-runner/SKILL.md @@ -32,6 +32,9 @@ the shared names. | `fleet_results` | `fleetr results` | read | no | | `fleet_flaky` | `fleetr flaky` | read | no | | `fleet_artifact` | `fleetr artifact SHA [--out FILE]` | read | no | +| `fleet_findings` | `fleetr findings [--app A] [--since 24h]` | read | no | +| `fleet_finding` | `fleetr finding ID [--flow FILE]` | read | no | +| `fleet_verdict` | `fleetr verdict ID VERDICT [--note TEXT]` | run | yes | | `fleet_whoami` | `fleetr whoami` | read | no | @@ -70,6 +73,29 @@ job) or `running`. `fleetr run`, `job`, `wait` and `retry --wait` exit with: - **5** refused or unreachable: no permission, unknown workload or job, or no collector. Report it; do not work around it. +## Reading a finding + +Night QA (the `explore` workload) drives each app overnight and files what +looks wrong as a finding. `fleetr findings --since 24h` (`fleet_findings +since=24h`) is last night; `fleetr finding ID` (`fleet_finding id=ID`) is one +of them with its steps, evidence and replay flow; `--flow FILE` writes the +flow so you can reproduce it. + +- **Read the replay count first.** Every finding was replayed on a clean + install before it was filed: `reproduced 2/2` is solid, `flaky 1/2` is + weaker, `crash log` means the platform's crash log is the evidence. Look at + the screenshot (`fleetr artifact SHA --out DIR`) before you change code. +- **`agent_mistake` is not a bug.** It means the model misread the app and the + app behaved correctly. Do not fix the app for it. `not_a_bug` likewise. +- **Never mark a finding `fixed` without a fix merged.** `fixed` comes only + after `real`, and it puts the finding's flow into the app's nightly as a + regression test that reopens the finding if a crash comes back. Put the + fix's PR in `--note`. If you are unsure whether it is real, leave the + verdict to a person. +- **`seen_count` and `builds_seen`** say how often and on which builds it came + back; a finding open again with a `regressed on build ...` line in its + history is a fix that did not hold. + ## Rules - **Skipped is not passed.** Report it as "did not run" with the reason. From 063745f2790e21b9a579687fa2f2c3487a7d5264 Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 22:45:01 -0400 Subject: [PATCH 16/19] Changelog, docs and the dashboard shortcut list for findings and regressions Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5aba0f7..745e5a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,8 +26,8 @@ a CI job fails when they disagree. `GITHUB_EVENT_NAME` is `pull_request` (or with `--channel pr`). The pull request's own job still names its build by hash. Builds uploaded before this count as merged builds, and the same bytes republished from main come off the - channel. The `/api/v1` artifact document does not show the channel yet; - `GET /api/artifacts` does. + channel. The `/api/v1` artifact document shows it as `channel: pr|main` + since #96. - **`FLEET_PEER_TOKENS`: the brain switcher can read a peer with tokens on.** The peers proxy sent no token, so a peer running `FLEET_AUTH=tokens` answered 401 through it. Each peer's URL now maps to a `read` token that @@ -95,6 +95,43 @@ a CI job fails when they disagree. pull request, docs-only ones included, when a marked number disagrees with the shipped entries in `collector/src/workloads/catalog.ts`. The collector's suite checks that reading against the real `CATALOG`. ([#89](https://github.com/addisdev/fleet-runner/pull/89)) +- **Findings are in the control API.** `/api/v1` had 22 routes and none was + findings, so a coding agent could run a job but not read the bug list night + QA wrote for it. `GET /api/v1/findings` (filter by `app`, `state`, + `verdict`, `check`, `since`, which takes `24h` as well as ISO 8601), + `GET /api/v1/findings/{id}` (the steps in words, the evidence as links, the + replay flow inline up to 16 KiB, the regression test, the verdict history) + and `POST /api/v1/findings/{id}/verdict` (scope `run`, audited). The legacy + `/api/findings` routes call the same functions and gained the same filters + and fields. ([#96](https://github.com/addisdev/fleet-runner/pull/96)) +- **`fleetr findings`, `fleetr finding`, `fleetr verdict`, and three MCP + tools.** "What did last night find in GreenFolio, and give me the Maestro + flow" is now one call: `fleetr findings --app greenfolio --since 24h`, then + `fleetr finding ID --flow repro.yaml`; `fleet_findings`, `fleet_finding` + (flow text inline) and `fleet_verdict` (not read-only, scope `run`) do the + same over MCP. `fleetr findings --since 24h --json` is the input a scheduled + agent session can start from; its shape is documented in docs/agents.md. + The skill has a section on reading a finding: the replay count first, + `agent_mistake` is not a bug, and never `fixed` without a fix merged. ([#96](https://github.com/addisdev/fleet-runner/pull/96)) +- **A fixed finding becomes a regression test.** A new verdict, `fixed`, comes + only after `real` (a 409 otherwise). Marking a finding real copies its replay + flow into a new `regressions` table as a candidate; fixed makes it active; + duplicate, not a bug or agent's mistake retire it. A nightly `ui-test` with + `params.regressions: ""` pulls the app's active flows from the + collector at run time and runs each after its own flow, so a finding marked + fixed today is in tonight's run without anyone editing a schedule. For a + crash or ANR finding on Android the executor reads `logcat -b crash` and + `am_anr` around the flow; a new crash of the package is `reproduced`, fails + the row and reopens the finding (verdict cleared, seen once more, the build + added, a `regressed on build ...` line in its new verdict history). Every + other check can only be asserted as "replays without error", and the docs + and each run's detail say so; a failing flow fails the row but reopens + nothing. GitHub issues are only ever created, never read back, so closing + one does not mark a finding fixed. The dashboard has a **Fixed** button + (f) and a regression panel. A database opened by this release + rebuilds the findings table once to allow `fixed` and backfills one history + row per existing verdict. Not yet run on a real nightly: covered by the + suite against fake crash readings and a fake Maestro. ([#96](https://github.com/addisdev/fleet-runner/pull/96)) ### Changed @@ -171,6 +208,10 @@ a CI job fails when they disagree. ### Fixed +- **The OpenAPI document named the wrong status for two enqueue refusals.** + `POST /api/v1/jobs` listed `no_matching_devices` and `no_build` under 422, + but `queue.ts` refuses both with 400. The 400 and 422 entries now name the + codes each really carries. ([#96](https://github.com/addisdev/fleet-runner/pull/96)) - **The older job routes skipped two auth checks.** With `FLEET_AUTH=tokens`, `POST /api/jobs/:id/cancel` and `/retry` let any `run` token stop or re-run anyone's job, and `POST /jobs` and `POST /api/jobs` accepted the `shell` From e0ddbcf42e8ce2704e878f92766af86fb814f09f Mon Sep 17 00:00:00 2001 From: Taylor Addison Date: Thu, 15 Oct 2026 22:47:13 -0400 Subject: [PATCH 17/19] Dashboard: read devices, jobs, templates and schedules through the v1 client The dashboard called the deprecated GET /api/devices, /api/devices/:id, /api/jobs, /api/jobs/:id and POST /api/jobs with hand-written response types. It now uses the generated client (dash/src/client.ts) for every read and change /api/v1 offers, so its types are the client's and a field the server drops fails check-api-v1 instead of blanking a column. - /api/v1 schemas state every field the dashboard reads (Beacon, Device, DeviceDetail, Job, JobDetail, Schedule), required where the handler always sends it. - listDevices and listJobs return the facets their filter menus are built from; listJobs takes has_error. - forward() carries X-Fleet-Token, so /api/v1 cancel and retry work on a collector with FLEET_DASH_TOKEN set (they were always 401 there). - scripts/check-dash-requests.ts fails the suite if dash/src calls a route deprecations.ts marks. Findings and every route /api/v1 does not offer stay on /api/*. Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 2 +- collector/dash/src/TokenBanner.tsx | 7 +- collector/dash/src/api.ts | 193 ++-------- collector/dash/src/client.ts | 64 ++++ collector/dash/src/names.ts | 6 +- collector/dash/src/pages/Alerts.tsx | 10 +- collector/dash/src/pages/Compose.tsx | 23 +- collector/dash/src/pages/DeviceDetail.tsx | 57 +-- collector/dash/src/pages/Devices.tsx | 48 +-- collector/dash/src/pages/Enroll.tsx | 7 +- collector/dash/src/pages/JobDetail.tsx | 18 +- collector/dash/src/pages/Jobs.tsx | 40 +-- collector/dash/src/pages/Schedules.tsx | 27 +- collector/dash/vite.config.ts | 7 + collector/openapi.json | 420 +++++++++++++++++++++- collector/scripts/check-api-v1.ts | 16 +- collector/scripts/check-auth.ts | 52 ++- collector/scripts/check-dash-requests.ts | 72 ++++ collector/scripts/test.ts | 11 +- collector/src/api/v1/deprecations.ts | 2 +- collector/src/api/v1/routes.ts | 27 +- collector/src/api/v1/schemas.ts | 66 +++- collector/src/auth.ts | 5 + collector/src/client/api.gen.ts | 167 ++++++--- docs/api.md | 19 +- docs/dashboard.md | 6 + 26 files changed, 999 insertions(+), 373 deletions(-) create mode 100644 collector/dash/src/client.ts create mode 100644 collector/scripts/check-dash-requests.ts diff --git a/AGENTS.md b/AGENTS.md index 17f1eb8..4cc206a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,7 +11,7 @@ from an agent, see [`skills/fleet-runner/SKILL.md`](skills/fleet-runner/SKILL.md | `collector/` | The brain: Fastify + `node:sqlite`, the queue, the dashboard (`dash/`), the host executor | | `collector/src/workloads/explore/` | Exploratory QA: a vision model drives an app from mission cards (`collector/examples/missions/`); see `docs/explore/internals.md` | | `collector/src/api/v1/` | The control API. `routes.ts` is the single route table: it registers the routes, generates `openapi.json` and the typed client | -| `collector/src/client/` | The generated client (`api.gen.ts`) and its transport. The CLI and the MCP server use nothing else | +| `collector/src/client/` | The generated client (`api.gen.ts`) and its transport. The CLI and the MCP server use nothing else; the dashboard (`dash/src/client.ts`) uses it for everything `/api/v1` offers, and `scripts/check-dash-requests.ts` fails the suite if it calls a deprecated route | | `fleet/` | The `fleet` / `fleetr` command: runs a brain or a runner, plus the work commands, `fleet mcp` and the remote gateway | | `desktop/` | A Tauri menu-bar app around `fleet`. A front door, not a runner; compiled in CI on macOS and launched in CI on Linux (`desktop/ci/launch-smoke.sh`), never run on a Mac | | `runner-machine/`, `runner-android/`, `runner-ios/`, `runner-roku/`, `collector/runner-web/` | Runners. They speak the runner protocol (`/devices/register`, `/devices/:id/next-job`, `/results`), not `/api/v1` | diff --git a/collector/dash/src/TokenBanner.tsx b/collector/dash/src/TokenBanner.tsx index 6697f8d..792f520 100644 --- a/collector/dash/src/TokenBanner.tsx +++ b/collector/dash/src/TokenBanner.tsx @@ -3,15 +3,16 @@ // // The alternative is what happened before it existed: you click something // ordinary, like renaming a device, and get a 401 naming an HTTP header. The -// requirement is knowable up front — /api/health reports it — so say so up +// requirement is knowable up front — /api/v1/health reports it — so say so up // front, and take the token right here rather than sending someone to another // screen to find the field. import { useState } from "preact/hooks"; -import { useApi, type Health } from "./api.js"; +import { useLoad } from "./api.js"; +import { fleet, read } from "./client.js"; import { useToken } from "./mutate.js"; export function TokenBanner() { - const health = useApi("/api/health", [], 0); + const health = useLoad("health", () => read(fleet.getHealth()), [], 0); const [token, setToken] = useToken(); const [draft, setDraft] = useState(""); diff --git a/collector/dash/src/api.ts b/collector/dash/src/api.ts index 2e13d0a..35cd59b 100644 --- a/collector/dash/src/api.ts +++ b/collector/dash/src/api.ts @@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from "preact/hooks"; import { onLive } from "./live.js"; import { tokenHeader } from "./token.js"; +import type { JobDetail } from "./client.js"; export class ApiError extends Error { constructor( @@ -38,18 +39,31 @@ export type Loadable = { data: T | null; error: Error | null; loading: boolea * of "3m ago" and lease countdowns goes stale on its own, with no event to say so. */ export function useApi(path: string | null, topics: string[] = [], refreshMs = 0): Loadable { + return useLoad(path, () => api(path!), topics, refreshMs); +} + +/** + * useApi for anything that returns a promise -- the generated /api/v1 client, + * mostly. `key` stands in for the path: it changes exactly when the request + * would, and null means "not yet". + */ +export function useLoad(key: string | null, load: () => Promise, topics: string[] = [], refreshMs = 0): Loadable { const [data, setData] = useState(null); const [error, setError] = useState(null); - const [loading, setLoading] = useState(path !== null); + const [loading, setLoading] = useState(key !== null); const [nonce, setNonce] = useState(0); // Guards against a slow first response overwriting a fast second one. const seq = useRef(0); + // The loader closes over the render that made it; the effect below runs on + // key changes only, so it reads the newest one from here. + const loader = useRef(load); + loader.current = load; useEffect(() => { - if (path === null) return; + if (key === null) return; const mine = ++seq.current; setLoading(true); - api(path) + loader.current() .then((d) => { if (seq.current === mine) { setData(d); @@ -62,7 +76,7 @@ export function useApi(path: string | null, topics: string[] = [], refreshMs .finally(() => { if (seq.current === mine) setLoading(false); }); - }, [path, nonce]); + }, [key, nonce]); const reload = () => setNonce((n) => n + 1); @@ -88,28 +102,16 @@ export function useApi(path: string | null, topics: string[] = [], refreshMs return { data, error, loading, reload }; } -// --- response shapes (mirrors src/api/*.ts) --- - -export type DeviceStatus = "online" | "stale" | "offline"; +// --- response shapes --- +// +// Devices, jobs and their details come from /api/v1, so their types are the +// generated client's (collector/src/client/api.gen.ts), re-exported here for +// the pages that import them from this file. Do not redeclare them: a copy is +// how the dashboard drifted from the server before. +export type { Device, DeviceDetail, DeviceList, Job, JobDetail, JobList } from "./client.js"; +export type ResultRow = JobDetail["results"][number]; -export type Beacon = { - battery_pct: number | null; - charging: boolean | null; - thermal: string | null; - mem_mb: number | null; - mem_method: string | null; - process_alive: boolean | null; - job_id: string | null; - /** - * Set when this device is running a job for a DIFFERENT collector. - * - * Rendered rather than ignored because "busy for another brain" and "idle, - * and nothing here is offering it work" look identical on this screen and are - * opposite problems -- one is working, the other is a queue that is not - * matching. - */ - busy: { job_id: string | null; collector: string | null } | null; -} | null; +// The rest mirror unversioned /api/* routes that /api/v1 does not offer yet. export type Peer = { url: string; @@ -126,76 +128,6 @@ export type Peers = { configured: number; }; -export type Device = { - device_id: string; - name: string | null; - notes: string | null; - descriptor: Record; - /** Effective pools: the override when set, otherwise what the runner reports. */ - pools: string[]; - /** null = an agent that predates capability routing; it is offered everything. */ - capabilities: string[] | null; - /** /24 the agent last registered from. Distinguishes "offline" from "elsewhere". */ - last_net: string | null; - pools_reported: string[]; - pools_override: string[] | null; - /** - * What the agent says it runs. An open string, not a union: the fleet gained - * a laptop, a TV, a watch and a browser tab after this type was written, and - * a union here would have had to be edited before any of them could show up - * correctly. Agents that predate the field are still reported as ios/android - * by the collector's fallback. - */ - platform: string; - /** Form factor, when the agent declared one: phone, tablet, laptop, tv, watch, sbc, browser… */ - kind: string | null; - /** Seconds of silence an ephemeral agent survives; null for a shelf device. */ - ttl_s: number | null; - /** True once an ephemeral agent's window closed. Such devices are hidden unless asked for. */ - expired: boolean; - simulator: boolean; - status: DeviceStatus; - age_s: number | null; - last_seen: string | null; - beacon: Beacon; - current_job: string | null; - lock: { job_id: string; acquired_at: string | null } | null; -}; - -export type Job = { - job_id: string; - workload: string; - executor: "device" | "host"; - /** `skipped`: claimed and closed without running anything (no device matched, - * the app was not installed, a dependency skipped). Not a pass. */ - status: "waiting" | "queued" | "claimed" | "done" | "failed" | "cancelled" | "skipped"; - /** Job ids this one waits for; it stays `waiting` until they are all done. */ - depends_on?: string[] | null; - /** Whether a higher-priority job may ask this one to checkpoint and step aside. */ - preemptible?: boolean; - claimed_by: string | null; - attempts: number; - max_attempts: number; - priority: number; - template_id: string | null; - lease_ttl_s: number; - lease_deadline: string | null; - lease_remaining_s: number | null; - duration_s: number | null; - last_error: string | null; - created_at: string | null; - claimed_at: string | null; - finished_at: string | null; - pool: string | null; - match: string | null; - device_id: string | null; - exclusive: boolean; - backend: string | null; - model: string | null; - app: string | null; - report_to: Record | null; -}; - export type Overview = { generated_at: string; devices: { @@ -252,38 +184,6 @@ export type Overview = { health: Health; }; -export type DeviceList = { - total: number; - /** Facets over every device, not the filtered set, so a filter never empties its own menu. */ - pools: string[]; - platforms: string[]; - kinds: string[]; - devices: Device[]; -}; - -export type DeviceDetail = Device & { - counts: { results: number; beacons: number }; - jobs: { - job_id: string; - workload: string; - executor: string; - status: Job["status"]; - created_at: string | null; - finished_at: string | null; - attempts: number; - max_attempts: number; - last_error: string | null; - }[]; - benchmarks: { - job_id: string; - at: string | null; - model: string; - quant: string | null; - backend: string; - metrics: Record | null; - }[]; -}; - export type BeaconSample = { ts: string | null; battery_pct: number | null; @@ -297,44 +197,6 @@ export type BeaconSample = { export type BeaconHistory = { device_id: string; hours: number; count: number; samples: BeaconSample[] }; -export type JobList = { - page: number; - per_page: number; - total: number; - pages: number; - status_counts: Record; - workloads: string[]; - pools: string[]; - jobs: Job[]; -}; - -export type ResultRow = { - device_id: string; - iter: number; - created_at: string | null; - payload: Record; -}; - -export type JobDetail = Job & { - spec: Record; - parent: string | null; - children: Job[]; - siblings: Job[]; - results: ResultRow[]; - beacons: (BeaconSample & { device_id: string })[]; - artifacts: { - sha256: string; - name: string | null; - size: number | null; - created_at: string | null; - in_store: boolean; - role: "input" | "output"; - }[]; - locks: { device_id: string; acquired_at: string | null }[]; - status_report: { target: string; state: string; posted: boolean; detail: string | null; created_at: string | null } | null; - derived_timeline: { at: string | null; what: string }[]; -}; - export type RecentResults = { results: { job_id: string; @@ -351,6 +213,7 @@ export type RecentResults = { export type Locks = { locks: { device_id: string; job_id: string; acquired_at: string | null; held_s: number }[] }; +/** The health block inside /api/overview. The token banner reads /api/v1/health instead. */ export type Health = { ok: boolean; instance: string; diff --git a/collector/dash/src/client.ts b/collector/dash/src/client.ts new file mode 100644 index 0000000..0be0e04 --- /dev/null +++ b/collector/dash/src/client.ts @@ -0,0 +1,64 @@ +// The dashboard's door into /api/v1: the generated client, with the dashboard's +// own way of carrying a token. +// +// The client and its types are generated from the route table, so a field the +// server renames is a compile error here rather than a blank column. Where the +// dashboard needs something /api/v1 does not offer, the page still calls the +// unversioned /api/* route through api.ts or mutate.ts. +import { FleetApiError, FleetClient } from "../../src/client/index.js"; +import type { DeviceList, JobSpecInput } from "../../src/client/index.js"; +import { getToken, tokenHeader } from "./token.js"; + +export type * from "../../src/client/index.js"; + +/** + * Same origin, and the token as `X-Fleet-Token` read at call time: that is the + * header FLEET_DASH_TOKEN's guard checks, and FLEET_AUTH=tokens accepts it as + * readily as `Authorization: Bearer`. The banner can change the token at any + * moment, so it is not baked into the client. + */ +export const fleet = new FleetClient({ + baseUrl: location.origin, + source: "dash", + fetch: (input, init) => + fetch(input, { + ...init, + headers: { accept: "application/json", ...(init?.headers as Record | undefined), ...tokenHeader() }, + }), +}); + +/** Turn a v1 refusal into the sentence a person should read. */ +function explain(e: unknown, mutation: boolean): Error { + if (!(e instanceof FleetApiError)) return e as Error; + // Naming the missing header is true and useless. Say what to do -- the same + // words mutate.ts uses for the routes not yet in /api/v1. + if (mutation && e.status === 401) + return new FleetApiError(401, e.code, getToken() + ? "That dashboard token was rejected. Check it on the System screen." + : "This collector needs a dashboard token — paste it in the banner above, or on the System screen."); + // A spec the strict schema refuses: say where, not only that. + const errors = (e.details as { schema_errors?: { path: string; message: string }[] } | undefined)?.schema_errors; + if (errors?.length) + return new FleetApiError(e.status, e.code, `${e.message}: ${errors.map((x) => `${x.path || "/"} ${x.message}`).join("; ")}`, e.hint, e.details); + return e; +} + +/** A read through the client, with errors in the dashboard's words. */ +export const read = (p: Promise): Promise => p.catch((e) => Promise.reject(explain(e, false))); + +/** A change through the client: a 401 says to paste a token, as every other button does. */ +export const change = (p: Promise): Promise => p.catch((e) => Promise.reject(explain(e, true))); + +/** + * Every device, however many pages that takes. The shelf is one screen, and + * the unversioned route it replaced answered with all of them at once. + */ +export async function allDevices(query: Parameters[0] = {}): Promise { + const first = await fleet.listDevices({ ...query, per_page: 500 }); + const items = [...first.items]; + for (let page = 2; page <= first.pages; page++) items.push(...(await fleet.listDevices({ ...query, per_page: 500, page })).items); + return { ...first, items, page: 1, per_page: items.length || first.per_page, pages: 1 }; +} + +/** The composer's spec is free-form JSON a person typed; the server is what checks it. */ +export const asSpec = (spec: Record) => spec as JobSpecInput; diff --git a/collector/dash/src/names.ts b/collector/dash/src/names.ts index 77523ac..61a42fd 100644 --- a/collector/dash/src/names.ts +++ b/collector/dash/src/names.ts @@ -9,6 +9,7 @@ // Every screen that prints a device id goes through here instead. One fetch, // shared, refreshed when a device changes — not one request per table row. import { useEffect, useState } from "preact/hooks"; +import { allDevices } from "./client.js"; import { onLive } from "./live.js"; type Names = Record; @@ -18,10 +19,9 @@ let inflight: Promise | null = null; const watchers = new Set<(n: Names) => void>(); async function load(): Promise { - const res = await fetch("/api/devices"); - const body = (await res.json()) as { devices: { device_id: string; name: string | null }[] }; + const body = await allDevices(); cache = Object.fromEntries( - body.devices.filter((d) => d.name).map((d) => [d.device_id, d.name as string]), + body.items.filter((d) => d.name).map((d) => [d.device_id, d.name as string]), ); for (const w of watchers) w(cache); return cache; diff --git a/collector/dash/src/pages/Alerts.tsx b/collector/dash/src/pages/Alerts.tsx index 20c73dc..b1884f0 100644 --- a/collector/dash/src/pages/Alerts.tsx +++ b/collector/dash/src/pages/Alerts.tsx @@ -1,10 +1,14 @@ // Alerts: what the collector thinks is wrong right now, and what it thought // was wrong earlier. -import { useApi } from "../api.js"; +import { useApi, useLoad } from "../api.js"; +import { fleet, read } from "../client.js"; import { mutate, useMutation } from "../mutate.js"; import { useQuery } from "../router.js"; import { Actions, Button, ErrorBox, Link, Loaded, Panel, Pill, Stat, agoFrom, clock, duration } from "../ui.js"; +// This screen reads /api/alerts, not /api/v1/alerts: it shows the counts per +// state, whether a webhook is set and the thresholds, which v1 does not return. +// The banner below needs only the list, and reads it from v1. export type Alert = { id: number; rule: string; @@ -147,8 +151,8 @@ export function Alerts() { /** The banner every screen carries. Silent unless something is actually open. */ export function AlertBanner() { - const state = useApi("/api/alerts?state=open", ["alert", "job", "device"], 60_000); - const open = state.data?.alerts ?? []; + const state = useLoad("alerts open", () => read(fleet.listAlerts({ state: "open" })), ["alert", "job", "device"], 60_000); + const open = state.data?.items ?? []; if (open.length === 0) return null; const worst = open.some((a) => a.severity === "critical") ? "critical" : "warning"; return ( diff --git a/collector/dash/src/pages/Compose.tsx b/collector/dash/src/pages/Compose.tsx index c053258..54755ff 100644 --- a/collector/dash/src/pages/Compose.tsx +++ b/collector/dash/src/pages/Compose.tsx @@ -5,11 +5,14 @@ // before anything is enqueued, and the equivalent curl is shown throughout — so // the form teaches the API rather than hiding it. import { useEffect, useState } from "preact/hooks"; -import { api, useApi, type DeviceList } from "../api.js"; +import { useLoad } from "../api.js"; +import { allDevices, asSpec, change, fleet, read } from "../client.js"; import { mutate, useMutation } from "../mutate.js"; import { navigate, useQuery } from "../router.js"; import { Actions, Button, ErrorBox, Field, Json, Loaded, Panel, Pill, Select } from "../ui.js"; +// The generated Template says only that spec is an object; the composer reads +// a saved spec the way it reads its own free-form half, as loosely typed JSON. type Template = { id: string; name: string | null; spec: Record }; // Defaults per workload, matching schemas/job.schema.json. These are starting @@ -94,8 +97,12 @@ function stamp(workload: string) { export function Compose() { const [q] = useQuery(); - const devices = useApi("/api/devices", ["device"]); - const templates = useApi<{ templates: Template[] }>("/api/templates", ["template"]); + const devices = useLoad("devices", () => read(allDevices()), ["device"]); + const templates = useLoad( + "templates", + () => read(fleet.listTemplates({ per_page: 500 })).then((t) => ({ templates: t.items as Template[] })), + ["template"], + ); const [workload, setWorkload] = useState(q.get("workload") ?? "benchmark"); const [jobId, setJobId] = useState(stamp(q.get("workload") ?? "benchmark")); @@ -190,7 +197,9 @@ export function Compose() { }, [pool, matchExpr, deviceId, executor, workload]); const enqueue = useMutation(async () => { - const out = await mutate<{ ok: boolean; job_id?: string; fanout?: string[] }>("POST", "/api/jobs", spec); + // /api/v1 checks the spec strictly: an unknown top-level field or params + // the workload's manifest does not allow is refused, with the paths named. + const out = await change(fleet.createJob(asSpec(spec ?? {}))); // Fan-out returns children; a single job returns its id. Land on whichever // page can actually show what just happened. if (out.fanout?.length) navigate(`/jobs?q=${encodeURIComponent(jobId)}`); @@ -208,7 +217,7 @@ export function Compose() { }); const curl = spec - ? `curl -X POST ${location.origin}/jobs \\\n -H 'content-type: application/json' \\\n -d '${JSON.stringify(spec)}'` + ? `curl -X POST ${location.origin}/api/v1/jobs \\\n -H 'content-type: application/json' \\\n -d '${JSON.stringify(spec)}'` : ""; return ( @@ -235,11 +244,11 @@ export function Compose() { {(d) => ( <>
- setQuery({ status: v })} /> - setQuery({ pool: v })} /> {/* Faceted from the response, never hard-coded: the platform set is open, so a literal list here would hide every device the fleet learned to run on after this file was written. */} - setQuery({ kind: v })} /> + setQuery({ kind: v })} /> )} setQuery({ q: v })} />

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 z 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�sJ17X)hjE5xQ;gz;f10le)=-x^ z^zp$Qt8I6ti5WPH<^<2%l=@N9a_lxXzgj+2{hPcTU0xu?c^A(6@rqIWi3YyxPm8n1 z;yJ=;sn6ModGI9Q!zCisq3+MXwbz}|W9URdvFq$nm~g4r z%L=evy^$2h$-l4wi_U8bukVC9ho+UVdbiS2ezTLmcjuXY2ehO{SwQ5okyk}Qif<2} zsd(1x7`pCE6#GbHj!f07R4&b&V$Q}9-uh)JTlp{;r?GdbqL5goxV z4&Ts8l70r9glfBegc`>Nyvf?2WhK|F=W<7p-QRTL4L@CDXs&}3$AR~Q@3Zv``#mAU zfx_eSqvlJ2KMGL|cDEg@JMy^_RCb+iSO$_k#nEP3dlx)x#Et@|^*NZogR*#-M(+sx zP8iL+btclC$I1d1mYbk*8x_h|A%gg3&K*2snxB6nHvV~fR`T_CtAk={nW{}PhrTp%V!~hzTK#Z1935E++3ugOWO5C!-`;E5?X}Zw z8PGKWBROf5Z%tX&6jE$Oc2^J|$ft=*>(Wps8eUb-@)RNzr&e&sqqE?1a9Z~a|K#~c z^zaeed5u%VnES|xc6f09aM1KGW3)lf5VNGjfOonGPie()hot$7&-2RQ#m?{owa`V& zj8_-`oJAZ?XYf~N{M21|Dr9asCjgRP5ZS&$NUDcH$%(E#CW6-m!eBK$R#M<&fW4pm z>Rm=!IltOY0c*iUVm&Nw2>X=`@f#r8wfh$RN5Vld3cGq%U4<@2vAjCZ+unrVe~-EEn{BjqzxUIB;f zIg6^aU&0d3#s{sus+VBvRj1oKJ?gyfpL6WF&%-$(oKXxV^p5kMIaO+b=&@u+)_R1n zjGvs(gNO?v0pn5=T% zV{5e|R)u1vwJqK_ofob!S9>`##I@_kTB7Ds%bGVnQDTs`ygGv(%6CVbIwZ1hi|M|# z#%PGyyX`ne1Y(`tZOP?pc*x_#>Y5kzYml10ODbX${O*e_U+1{qkq)rT*1kv6awXQx zS2JX^dGN>;`c8z2wBnW>mM&$Ei#C;`3WrGv>u!qi>K02aDt60lkDQb`ERnKi*cxRp z;;3W$l4nQEx@Oit)c@~3{lmU8@9$-y_^cOpS~!GHZ=2!_TR$}2!c+Kc+G^Uunedzn zcE+jP(XadUIj<`swIo6dvOkqb9x5A#8?)ce)6`&I8E=HHIqTed`8UjHdOsxa2J^ep zSoG9hNcRCQE-qje!Qnag5Z9>Sl%@S!qFx_r6?u{b{n_6B;g8Cm(9T%?{&b{tSq;qu z=|8Ju`!8T`=|6<^?GHwW+B;vj{r&no^U%PoIlWBHg*==s{QuCWQ;Nji8lhaNJDto2 z)c?S;Qq_N~=lpvfxs^Y${a^RQ-#5>H-4p+HPyCPH1n}tmFZn~<3HliSet!R)wDwW? z`=);%IpClFhukFpOW();#eSLp{)YcPnEzXzr>6P(f}{Lp&0$2SAH?r+*$}rEq476gICb)+rLakKmWaA3i!Y6?_~bJ@A>cf z`u8{Zzg5Ei`<4Fx`$~UhuUC-#R8u@s|M&ZG+Mk?#i*~*v`*Q>wsn5&mtr2?IwX?Ch zL;fF!T;T49;8-vh&tB>5J2gQ(t`}go5=ZU-_>8wn(GssZ9#rirpfX_Wg#rI`VfMd^ z%M=y!pWHegkIk5G)%uX#-P!4eDNbAONQ~IEx3?$7A%C%1rubGlUBJ<*6Uk0J?O%E# z2)$eq_iZuxGXVU0)UA>pE8%yJ`EiMhMYE}rJ){z}8?29xe$Z9s_O*RK zO;}q;=LPPU-Bc-qN*h~q*JFS!jM$xq|B>DBSTDiMVq&ZwyH%@NWr&p5N8eFOyz>_x zom6E7kF=Ug=K1HJbEt9;FR$emH^ZeAqdUVwo|iw5;tGt4OBSnbWj(YL#z`(OuP8Y6 z$saxOJpOrf1@UB)HF9?Dy_8e>^zmaPjggt(_ssU@L{Z@HuLM$n`*{;^?{Fm0&9>41R;Z{>aTKGiTMN!!y zT_Rb)QtXy9G?^DtUQq$k)AN3_L8&m85D+cIAnD_sDv>PZHobBMF*FE9e^1>`$&HQG zT<;jvcf*R~cOqu8qN|f7Q zyn-)Lj65WFiQ!pu3;*%>XGDHc!*gQ;{(y}{Z0=q|P>n0tHE5|7Z2 zaBp|B&~yuRYAt>H6GA&Yko6y{E_DU{rx&*QtxKXv=w}b(agy2Zp3v`9;89B*w(BMq zCe2)t_|Mnmj$kJA^?_Yo_sWHCnV`G|;W@+{=6W zGUx#5Pkvrxcw{6&RA{3H2xQ<}1yG^Y<9;GU8N-eXpF_li>kvCTHP)(zt*VIL@DJ_n z>`C0#Sz>0Gncu&^eg+n|f2RaNZ$ih%V`EoqtX<~~3?X`z(W9eg3al~eV;#?)C2<+E zHR$;rpO0-kXBYR{I}bUaqw}#=ozY4I55@xq&*;(W*s#qJ7`QGkesZ+35}hCVmGD0Q z!hTwO{Axbc^VeIa7mWC2gxvHrGz>~)WVD=3)zz=iW+A0-Ek0p>eXEwJ*0OqhA2nP| zE%f4r2%p#+p(L6{xjPttdSga5Hs9B83QCIrc_08TTl!!^)`HWXKrWvC^%q{m6UpaH z0)x^|e*?=ReSBlmnl_@l!uH%=t_TGmEdO0qyo|wNIuH=U+no$4 z?!O0>hO+VoF&9owPtz?lHBBRivV{^o5Evwij`s2HMuE7l)(dri4{ghe`=U6@F6h{a zvlyz}_eFp}J1sTUuDJLZ<=SLeoIHD;TrYBJT4~=l(DXj?$>WD)oLv_7_F?f68h1g> z&MV{jV*3u&Q9ph#-a8)F@$h2}4*J59Pf4tVDHc41kUyrTcuc{a*3!Itg%Ap83mY7> zXz}-})nsGuzmGzZu1S_vM^-}@7Zxpf-<#Fes1M`fe8_%Pp2W{5|K;-+?D=^=fs$?C zm&w|P)^2LL)M@0#m0KnnT(kUdB8Z~C-u+EduLV_5y|0!bVWq$M6m}0NzdIIC=uOOa z%JEYU4!Y&p4$oSS%o5SxsZegaz+eVOKL2DYLW~bvHE2349I`dB<5ycGfB9%i8QD}AG3=3Y%ToOA-8shUnBh!OV7Iz- zq%u8{;ulz`${=#3rXjROuBZDs6O*E4MpBZOzJh{npIpOV)4NRq+q>A!MU&%@I5kB* zy*#7%fu40EnE)@`CNXCfmYz2|Ut;pUh3aU;ecx`!?C)|Vt*^1DRQY|$`SH;N(p-m3)-3{YX)v-h zaSBNRMlD{MXU{a;mB@ZpF$ODxl>Jxs_cKJTjJ%+L>$JN%RKZT`(W78}6$U>)f8Z|| zgD+1)U#m<{^Sv#0pJO@in6xM^#w*^avvaX5U(OS0<`Fba&Q3r0%zuzX9oTxQN{uVs zRK-v+NRS_uvdzDFj>S(_N#}Dcn2Y~-DN)k#((gwlwNvZRMDEo)Wff{sm*YupDG*qY z_w*QTP1lL@FsMmy0lB0nddmRrngHbOwbXGg%L$F0=)0|N?^N`4E6d$p9Ff9& zZ*rnx`jjFLjj=Th2_GDrup0Emp6YUB@mZjaKp^QNyE=)@VH$oN_IN5Rw|{0Ui++|xgd}v zyB%tlHaR`%aJd(U+Pp_LA5JTLl=>wM*-=2WJ2(y!#cd5Z550e5OYvr#5=-I27>#ujdJB` z$`io7Tria0VqC~S71S%0E(*ysr)=Mgon-y~SU!SI-0Jf6+%E*qEc(!k*9Q?^87ce9 zIFu7M6hrmg8rNhA?By+_Rbm@2Z=+ze0RN>30rIGS(&PD6kUkuJ^ zS`SW}@UaJJ7Hk8jW3I&_&C}e$uNeu0YPpAB@~3$p{kT)}vKOtn8a`&R_V^KZI(zIr zUyo3uV@cEbs%OU<6B)J&ThOj%S#R%uu|y6rrw&2R|kxoRe#%dtS; z9V{J=T8flXqR!6IBna@;K({p(#lg*pPR%{BwhY0|CnM#oMdlJpNl*l<27SdMEBw$a z!8k#k*t!0?e`3O|t9UB5GPU6Cd6`snt!%Ns@76OkLQZLlCGrWs(-1$@*1_E%O=vDQ z)(ng|PpPOFAu0i%ZPok6+Nay{Z#d}HO;_Ku|FO=>TjgT)Sj{@i)d^?s;6MnHnVmQ& zz%1IuV^jOnILrUo%-FHa))ypoh(7-P+o;;l67dzi)0!6_ub^3=VA&gd*lOt!fM34- z+WHIo_;Mq{`2FaBy*?c5CQL82LHp}fj4H;sruaJ*KN$bCu2Kwq zigZdG3{B51CT+TA`QC5BIr+MdS-G75QEfm3{}}`1?nKz^HA5^Kra`YXRIi2Y|AY(i z0yT^yx#UX9iqqNqsxeIqAUDm$@hL>az0_t5)%?HF3t&+ z6cW<4Tk&px{Mfcot1jL)7{{Z`6|a$0UVj~tlm*^-QP%A5M`2v|3VzutDb5KdHLi8< z`p#=%n3@KJ3#;ozdtqGtyFlh+G3%SiZVW)xDqV7dG)9JHGEa9>486ZPTo>J=%rZ zR8kCGTwFkE*uC$5A-ZqkKcA5ma4F-ZLd_}s)yUQl-PdDvyC8$(+pBFW8XIRd)4g8kI1vkp6YUHnOj|NI2EiHXJ z1)cXUzl5Pi(yJP^aBB|Gv0^YX;nGAh(Ktxs)0=RkssYT^?}v=Q6qaw)V%4$AEmT@_ z@wy4!$G9vD^ z&2DZ=KTWy)tM`Q{r$bDQqR+eNnSg0pN>Yx^^@6mTeaW_ji2+d*#b0=T^%rf=8KEMV z-v{zX5EbX;yxC48h%4+*Ov0}gV~M0IDrP%7Mk^>Qn)s~kq&kU>Rh?aWZbowF=j5Vj zSyYJb62|YpTYz1a2yFt5DG6clZbf35k>z*R;<6zzkIU6BC?JPaN=oYC7_UWlWYWZG z#iIYsZiNJ}@1BNcJOEmlr+1l{zg zx$j2+cf%Ds9HGk;V&IZecM(#^eH_dzC?N1%DXFpY)xWTSsqt|da=K?qmZf#gH?X8@ zeQ1$nzsEW1;KQ!Y!ndUteq!S6hYsaNx_IaK1=f)Uev7AKLsgEe?Sg=EH{a7E@A+$~ z+malyT33SH29HQ-XdY98Js+?IweV|1QW4x9dV&;p#vGRVDzUgaETT}u0yf35@4eod zB2d(GO$Ux;j);sG&s9^b=88MQf%2%MRjYOLbAPEy+cU>}&%!h`dxz1zuX+~*#bBg> zm>i=9b2vkB(S)`AVdfztP!0*tCXAq(Z}s$?oY2E%pnjIOtv*P|3ZhFXFUWB^-5w5J zbU>5Nh-?JE0MOPwU)Rs8YzqtSO5Jxjsi?otuzE=v|0<=_gQV^P<0l?&PZVvHrGP7| zthC=D?SxOmdk@zD=MjGrEC#EV!aJ~6YdEZupA76v@Hs1+QKrS{XzQd)#zAHz&*a~{ ziOS$9I`lFcPHB5LoT)}5UR|`di2N%bNcJ!?>)`ZS5cFL5`M4)C^^~Q-Y!Okh=+-uA zKLV zOpV~~-E;|$Mv3U{f~FhAP;LN1`jsf&%C#&=mD_!S^kuwpD2F#is$2B*5x4^@H{yCC zPkwXgv%v^{$se{jKKY_06iM0|htx1VxD-W|1O4r^mfwI^p;26Nrj*qs6Tt_h5vRpT zvWLBNG|Ho;i=YvAVR3Pty`lAb90G1}61$6p$Z1rGw+2AHUw<~zam4tw%+*Y)^1vOJ z@>hUTauCPE!LJJMW(22-Yv81PdhAShLE$ms9p1 zBHP%^5DU;!^(o_;0s^>N+{NU~ulM3ulnW1$mihWDQH9o#CXJWAMeK91E2WaUy;<0@ ze4cgx)GO8LBA`be6;Lnl4!egUp_kx+90)=@4@Z@CaetXk!~?_q9K0ht8vz;2XM1-W z;%J%DvV6#*M#C>jOmsi#&}r@oih^UQ4$>2N1t~*Yz7_>SZ-PRBf<2%nDn4{j4^@4% zTn6&XOcm2GF9Z&_(}C~Q!Yp7rS*Tr^7)F0}HSj)fZw1iDKGBs)Dt?&Ew{$IgL;X8n zKKJ)!zsEt`yH&C$##~;$=W6hx5E{Fw(ADyntp;O7=GP1Szuw+fH!n@nor46-k0W9| zR%d_qO>~E+nNr~tM)XG85p{;x_gH?k$fJ`jZXoMSe$FBs0H2=pR9sRoKh#UiIqY`vtUR}cQW6{-gCxO zo69PL4o9h*TVWP?F#v8pZY~;f>gzI}TV!|A<2+5|w;GwRZEg9{u`<%s@`EvV^2BSP zfCwR#<65oOPe+pyV~ZgLnz#4dHc1OT^M#u@^$iUe2dDDSql^>$oU-p=vOwRwLH`(^ z>n1}3yloU&hW+9uMW1Sm!&^Z{k@R8;iy*1+qkRjD znv@>ko$Gm2T~*bwv-viXo&~R+coGD3>n7vNiHXzPLVg8Oayys#&;4#P7w?mUgl%_D zWU*({pmJeDD~dm5Ncav&Flg!he?%%Klqe3*sK7eeSZ`0N!4Sb8LS8?09cLr~ZaQnB zaC?i+1Y>bHThL#Y@S+l$9wuTSLx7I!&eb$$+TbX*XHVR(g6V*(q1tz@M#3-BqpV4+$Ej{+hd#kxi$0|tpt0aUjg>^R8Sg1s+~rpE#ZQEj;}LT$ z3%K!{x8&3hUYrtuoR(~+-8LF>KCa&1qwKTH034EsN zsA03++i^8=b+x^DjV{c@zV^`boF=F_Z>Xwr39EW;r{}8Z?fsdr(rQ>x;0-`vl;}qd zxjH*x%w++Ld*eIrv+V5t_Ea01E(IxK#EGtl^Gzmsm=aHkZ%cvO2fqcviu4#Wp~d+g zU8%zAvB4*@z*WC|<~tBze%L5(YC65RVsX8fLQ_L>C@1wzpSWj-aFf$V+)Y<1#S-Ng`-KS(aVPPt83 z6uDpPR8&ueg8QCa-S*u!uF*wjKGN0pq@sE)$;rXZ9>d@HJrX#8O?d3=O@y~C4>4tk zcHL>0!Pz6kwuUe#ONz#v|MBNjHrIK%*OVHY)#K(h{U?!kzSpL2#iI-jPtJhjhs?Kp zwC?TelS1U}&;*~>DLlJ$(9pKEq)>`po;BTS^!s4J6msz62Vo4Vfq{Ld2H>GQ1O=;i zEyBqXa1|Dbzf2du0pf+Y=ce1-D`wn@Ukr}48A0ckrJqWfC3`j+t@K-NH~hF=qdXQk za3eKsh^B|kEZ)McJn$FYu;=W?(-A9{`iOt|oB&_s9W+kJ9!=xnLeKX8p z?qVrr1&szSTHlY17Zw*vTb1NtuHVx63^L6Q7h#gX-Wn;FS>O)Krj+mD=&fjO{^;BDo|Am+qq-Fn@Bdie;ct~ZY~NQ&N;j_(0X@|b9XZFmIus3M;Z}yXnJ4QdT~E{q5*@& z0_`uv2PUj==Im8>CRcjk)#aVEHS6-&+EH_$!c5v zT^obQBqOuXtqsk#Pjsr7kX(>t0=B}V&VKVuzOWM?-e!cTg&?hgXXste(3co>-l?gn zh=_=4&py_oYSTvr#f3iF)3>#nhQU#^q5>SEmXotCO}N??S>#Cw@!cn**bh@yk;g72`x~yMjRkB>9D~QLOV`t=p4Sz#lVzrVPH;5eGZt)~ z)?%LZdqwSV+eQSwD_rieUJus|ZF$|EF1ozQ;sUam5ikhiC3fB0KFBBZ1-glloR7@_ zX`oPK+o(caE9t8!7ZDYeeS4zRcOfAXll>K^o`N6hX+R}#A@bDa-wDbzwPRqCSF)X? zvOW*19J-3>tnTm4>#N%&uNbd~zq>x=F*G&(hD@f{&~gMoR0y57-m!7f&0>Rp$!XnP zK~f)$@0|NSa^Z!7Yz++Rhoxh1gQlI!D_n_iFCt-KL+SKMx2<1Gt+d!RVnsEzk*YP8 zhzuUy*$p8*fPILT6!GXT{rweyAcjv`3JSzFC;K{s(T23^8XSf`xkj4CA|O(VtYlt0 zcbV(C13YgVJ3HUAp&1G;V<`?+QGj*5)GQRPt4-%-6Y)KNcRgoxM^|NsGV)4TuZ}BFR#Q-MtCK#0srPlQ zk}N~8sb7>B7#LvtY~=z*qG^ze-+}%+5n0c*6B1mFpD{N-!-6bAZgjOA36}J z=ZSxA>u{!wM;{9!m6w}sbD!j4Fj#8eyEab4FiQWGXdndn0gl3J8LfiJssU*5E+;k( zz%7%nP0l)e21y8kA)8c|KHukkxKr=}yhQKM&&K=A5(NvuzN!%%@0@vf*nD^Yh3M&6wzPNaC8(&)}L- zjlE_IG6{MWTo_R)M(PuH)UT+@E{$Dh%nz>nzUvoOV8yafw(Y(H*B~^5pHiKKu8^oi zT)Em!;WnTR1Fm-R;z^5~M~3=}UvRgLkA9<6lgTkRe-lABv-miQPU?mAr3*obx;n4f z%EM>J`=oTwlERKv_!%ToSI`zS7-y={EjqDE@O+{Q&^9nxOWY^tf6` zS@u`r+Gpa7{2ES3M3iI?j~=aDkJrM~*<+{u0Tssw*-$`W0P`Ps5D}n_t2sPB5Li7N zXt;;J*~s3F71jj?rz&w|=%qyG2Rlw$ne$pIHvowwWf6szZ=EJhzgCnpRyNXm|Jvql za(uf+dn6q{m!zcIe(<3kzNt>h?~fm4*Y#t@#_ZG{x$c0xid1Rw^c;`A?Xy=zEg!;j z(}COv*&j(Dhj_OJfI>c7xQSjbAc`Q8>FDSTVrK7tJ>fd2+rX6x&j6-h)Ya7*j+O;F)4_=J0V{XMhwXsU*4?4tz5G8<&s$k0dRntbO87rtchp)z+^pOd^WE&qkLX8e5QK{*KlzL!O#Z| z!ZWF`KTRUyhdI=1v4qyxFVap|>`IA5VFFiX zrHYHn4eHRJx|DQ*+2Sg>Y7L2P&6aDS9Te;c8@}QBbes4DMjI%wh?go zAS+$?vz-0OBc2m6IR?r6<=&>Z5&H=Pr^L-l<{HQAMf|C0X#ix*55%C=zfUoOOzIQL zs9Wwyf?Dr}-8+8bh~0?Rlx%o@bVgDsMyNKjuy9e*k!V|Vd07^9z6x%3E-o+Dz?=RW zlM;K~&%6LY(hk!$9Fi7V0104DxG_RT-YY#34`_#&2g;MUlL6jgfUFv+`R9&?FD|rt zxH%a4xhwBgQ#<+YP9+%_G)l@OaTo3(9?umbpg@{yhLFYdYf)dT5lPRJcgx~YKXfBr zx4F`gKN+bBt_746`^cC2y1LdPw-PR%c3FLLTkL{`CBEICEqdG|6o3wy%X+Syy807G zj~V7+nd)*YZ!e?GIb>4l4|26?HsKC?EUn<<-|W9WdE@SheN*y+GbA#C|C04*bCEo# zb(!|%AMgUNp}RW>ctkb}48ch}4tZ5dZwPeP@A)2<(#NKWq?FdRhbHW z%S0fg?EVG?>T zuLFrpg#T0PjM{O0R}gSHf3Ks#fmc94C(Df_2#X~%c+#IKzbKEcpeoyJYN#&lLaW{t zQ~ep%0>G~|J@7_*ueo{Fg8J#oBZ5mK4`F-^l3Lcw_ZUTgV=K&RSST80aOxB zXcp?8#o8~pg+Hgd#rFW_gE5z=&?ld^?h(*__LF*%kQBjYJV&RJQ1cfTN`P`kiFss; zckQF>D`pX}lT*K#hmlK=Qa9UqhIH7$Cv>vcOaB&w z+lJf1ON&GOF36Wx33liOOju(1Z0+^L=FQQJF39^}u1)G{Vfp5yt9zu>b71e!IeP`@ zrpnDv=BGDmHKF{>6k*7$;NTvhWO3Z2if~}4NhH$wB(%5F_TqW~D1fl8oQcWc+5-`; zU$^Ar^&Lj)c~lLwKQUQe8|N{dzW(zUYSM|j-;-zSQ)gS(X8=yZGb<%z4aD&6{csgnLfwNElRPa8t zU*>O+u(!1(ASMV262P0zt&M^>G4mQ}Ir$#+g^3Wc<1TQGVtbzkP5el1RPreBwHD4w#E@QM?HvaK~R*kRZt-U0t!+Dl-@$`CDKGXgc77g+^B4dbP}Zs(gRU?C%O@7 z(jlRDh!R5}5JH0BU3kwK_x=I*!#!UJFkmEE8Sh%}e4gKYCd!`WAE&?T^q@S;F;aZ6 z&D|}ip042QT(RR3&;cLZ*E1+K>TZ;++@GG*%O-Xe1$&Z~UDk(A7?G!;Np$k81Q)8J@sil% zMvvxCSitV&N{8p3^+$CUjoDwj#)X5gQi&v0i;}T1bHB;jxlJIOr`>?g)5&v}(4y57 z;8HT)7c=cC17__kH}{21g|G@cf|4^dN7)e!L35Yw^J_E-UlSDKuY-^GS8t^75#NAH zw%5q!rh@Km!}JEbh*>>M!;eQmYZ~ow!^bWII2Ir#`e=uDcVD7-Z2(SF5~GbTTei$x z+^remR_Femk1tnFMqLTq#swj^dcHIf67p^`@JbYZ`GB~|Hl1ooo|5zJhf>)!9*@Rl zOKP};XQa5+`eB6!s8qGEPEL8l92F8uX~UFqM-IS5m=g-Gla`skWV??o^anG*yDXz_S_jPB^e#wNszdDDZcA504x zT2gG_rn1kcY%egg(RuuD(Y}b*mV}@MGFcXkH=w?$SOHNq@gB{N@7`gtG7)smPC2<- z_@G-jN%^ZE!Ld-N^`@L;{XH=fH~svVymTqxy0IB{z%dUlA`aH z&gNZ)OI3fwpvfol%P)G-XH*Sp9$R#nX^WH;i@os7^Nk5~eD6B>P2cHsAa{)`c3FXMF5e&||$u#xU3fRPFXnh~BcqZbrdx=Tlu@wfz}E^=qaj0(Sy;_uzPqs&1}g z;I1+PK?l1PZ;@!F4|DI6MqT?JaGr(R=};G!=n?r1p$&bkUD;_XV;dVs6H7^gYE?kM z`bqlM+Zf!$-s=#g*lc0B)giM-o07%JSMAE6@xOj61+spZS8u~Tu?K0{0g?^@(V(Ol zvqxuS*tbWB$;n+BnyBkrWiml&Zl`pjK(D>fYUaJ|T8bc@9|r>W1!UnVENs%6$IxlP*I zwqy@A)YZ3b&dk@EtuXypUji`VzU$h^NIVU_URaTo5Vy7IkACHORAGf9lNVO7e##G+ z7MAn=vfxeE+rrvI9e)t#GgOkLlCu185J{DL(jh!y8xbi0WHm6TXel8AYb3PK2f-fm zqQ3SP0leSG{j!2a0a?;siS{Gi)Y|%bbIab37E9z+ULXh0-4ESz-U5y(RuFFm%@umQ zbDX+RhsM7Ghz7qH`ZxFkb1N$xZJnbyC0Dc(U7TX;~$kLa@sO+z( zkLsYJdO%v)WnpQzn=fffL4Aygz26w2dQk^c`ajJ}5-!{g84iZP18YQithM6H-sO}GUS7CE?Oro4bxR%sB|9Kg z(MOZfxNMKK0Go4Voi`7}JJDy$*QY&T+pEN%!)PXJ(^S)9v0afpNU&3Ua%k@p9Bizk zbN~KG`>YaBAW(p*4=He*XRa2%1lFfn-qHsofPt(0w`7`9trFVAGcp{#eLYZ>=Pq23 z^piNpptLeFZQejgl7ryCTl^1a!u@c*nTMN*!~W4ev--~iKCq4X7XAIR;kfx#%%?F* zLj$^DELl&~%7yUom@tkGEnC~q{BHsdRPeX%nT=xr(U2Os{t3JyuiICW0AvL-Jhm!A zoN4-Vt$58}q2*=V;pVKo_QOPe*^pNA90;=>e2neI%~RjmMN=cbPA7c}ZoV2X%Sf94 ziT1d|mC=S~qxL$^slb^H?!=HLd(&%Lnws+g^hh}N`sh6JAS1q$Xt=H9kHm;xG?dG6 zt`H5~uS1_DrpWeW`L;W>EyGOL%X{_ePHUI1ftZf2guLs7GZ*od<0_qV+jhFrbq$?I zsBj2sqN1p1J8W?*c3J5*;a(yc0mxfssDq2kL59XRa5bhlp9;&$ywIno4}tV@_J49& z8tY4b8^h&0S$pr>=SVK3U1c@TyS5(@nl@!iA}|~!%gO0XmMSbSJ5}6D&F#gI!^!vr zW5`>P=qL0X`Tk7&tpBJ)O6DQibvrC9tS4~@*`6q**yuM11=-sc@|~YU%=pleB>s8WwMcKsob)Ke!7Yc4hO*r{8CxxOR{fsI);hD1dD(Zo0df1n%tR4ZQeoI7Qu-<^E!7Md z;VsI^ZygfJ5G(An7teJA8iKcp1W8-*(LBbsnPKMA*i$A3Xhe3DAI-LwcIBnl(X3z7 zI}u;igtmvM#y593Q@>gTfBldPXa%5K1xE$(D0CPz4dS>?p2s>gny)Xh#gvrsj7xu} zZ%jHd#z`!XQviZ-qgzSIXH7uiWEu$JRCulOp3u6PdKvyL&VuS7I@&)1t6JTr!Pf)@ z1e#qtX%yUc@vhNxcE&s0PV3p0)Zen2&5|({qmv~eA88Z@x?Aa?WFVi1%GU;Oj**7Qk}OQ+Z)-64-APejhfns!J! zC1~79B|Urgya$KJTTX^e<0~^Ds6qLPtUGSDaJ{&gVu+Q^05H09A>sl`PR{1$1|Z?x zLqJfWIZ;Rfun)*-oXOb7C`#l09O&ITiBe%~-VJWHztqa;ji)-CLnmK9X8?!$h3VZx z&OME6sbiaBvyHySwBS6d7D6(DOBfs@X0iQTErQUA&WdkiP1u>y$R<2Kh;65U~ zC3#)8=A{^oUC4n#N06Fg}+{kCTLyR06E27vHr% z(#u^*ZOX55>aDebzqln6neMC{JJssZ(Ns{7nR%h96e{={h;m-RGd4|`he6~RS>hK? zPEPt)MSNLS7Q>?u>|>xi$`fCDSE8cydRiC@V!14H(!)u3(60t6kQdm`s=#p+3Zq^ce+z+AeF(mPbd6>UAo4S2m$Ed-`;^z^#cc@3G)GTBpPR?#AV zXQtOkG2uz`FYQjGsIa_6{q#ajlLEK9oLy}#U;;rvRBmcZSP*nGEh<*2}W{nG(cq^{Zvfu zQm%b;OgY`Uo<+!fn4(7Yr=Lhl*x91Bfja~Ti{YvD>;U#JI&%DHcq_l26&vs@-*+oS zDCna&65b>a_0iDf7>JL6>eX8}l&vH6EZofe3|m@T+kngi#t%Rs5Z6Gl11%KjtgJ{CCXiZJoPPJ2^8%()6cfAY zZJm>QacQKHZCH<^A+TT&QD9FVyR509MGEpQ678%%cQx8)){RjF=$G!oRvE8YQV{4~ z;?4;R55M@&uBj=cV!rSz3gVZea_41txBYw2T31q2?>+TE;emUQ_jfQi`jYf}H?%lB z^MU{$--58QqpdT3@bxH-Bv#cyZ14;>>(L-6Z=dsVe+U%`zGGriWx8nQG59Bq#He)H zkNg1oR6tYL5zScg6*z$}C#Yv9|DJ1CL2=IP>-ZdN^;mWXB)Qfr)D>Crt6Bw})zzt( zV0sNdf{XswU)Ocx!NGcbP}5LN?SZw1hNjJH8~v^PZlLJTh4pC?B!q8=*#`!WX1f0z zxpjisyAgk^v_>!+5Q~EnQHG~r@ccz9Ny0_nxaxf6s;WahaUaXd_S=^)Q#bJVd;AHIH>? z4fFa?oXuiD=>xVJ3Uw8c9~{o?5VXrEXfBmW=?*Hz?mKOD}D5s+L`2j zNS>{ml{w%Q?d9nZR$n z3yo7wL$H>=O{j2j7VW+ap=!g znxDRNJz7`Y#mqxDz!!>wTYyHfmj;6g331e|t!>)2kC#uH*$D>hv5hWJ@8L>a3EDW2 zd;V)(etkK&So}Xfu-LQy`{f?}^8YFc;y*oH)rSJ-mmKS&#k&u_tu?%rfbgZnRDj!>FIv@=?zg)lEuR&$A0wa5#E>2QfiMLVP-vg z^d#^(2Kvf8$K#+!k6u3dA|(!VPupL{^nPtlgLM>EcyJKsDX+V4Nm+zS~|F&^k zr?<@^8AbQA?&W36Y?Y$s=0eNOI|eNYi`YpCd5ZI!G8#~$9(&@>L55ex18T|H+e=pK z8TuLj938(M-~3lXKRWmk*1s~D@Kb?*#g4!4Iv)QkKO=aI|F8Jb{kg-xqF<+^-;;l3 zTxtx;f5mS{FaQ24J_`6hyB7WD=A#aGZ&Aayo6sXN$pV!>#MnV4GR%nsWay@kl>h0v z8jQ8~Ose~S`;O!3(Nj2`!~oho`5TPEtyWM;+=ruAJBEr`PK0pcIam?jARj zG*1ZhDaL*TNi0F|2)c(oa6G)JP34~a#O3GWGwXQy?e_#9Lr3zVO(~2+#5+jVPLun> z6lrK3An9MbQ?gpIR;?_Szx#~1bMChBr)AUqlV=UhjdrVTxp{d~UcQG0K5Y+c0FVv@ zNY7BH*X9D>D{qIEK#g!i(*x9Z4n!W7k4W`-v7*ST;fG?(EQ3k(IWNC_QEiiY|6PZG z*u43CcWY);mXR<&|HEpFC1saCCWC?7GZjf-GM>Ki^{m}k8IluS}Qq!3(nJ4 z!Pj*qC3(lz7I6K)G}GD25900jM-k`4?8{y^m(NOWP;=;ov#iDV@$F{&Z1{;6GCuL{ z_O@o{v$a)UIF*>$G-C=rKDLn8fgY_EF%i-J?l)!5SGu~3eviP{H*5VgEG&!TwLhzJ zRX6Ab1)IlR%sgRbwz^f-t%MD1v0o$-;-f zzsDonZ;xD`2nGb@=R+DzWvsXqog0=ct9PhGDt3kkj8C1;Z+jCGG^1aU#u6GO7q|-~ z{{&J0fwgJm~t%CE^2I2r8izH#H{4WTxJb>(KallZj1PCY+UbklaN-T zFp@S1C1EXC#e!}qCX1$~XsE}$=HUjoBB_Zzf-Iky=ZM-6zvtzx&C2pir;QyL92#2n zd3fRlxWOUi;8JwEzYU`Cy=7uxs8^Kcx3NL)h*i2gl-Z^l*{f9y&xu)dt`~yu?^C;4 zD7VEzC8N2nGc&;sr)QsiaIUa^2D&27hujP&Yt*u{927jX1#?Hgx3ny-8ulEmnUL26 z4ZJvxPUNuICL-G88rfXCeX6;`zU-lA&_Am0W{oLu(0!_ny1z5`*&o?M?<#;}N__mt zb!{;Y%Gnl4`3x`r*ZQfgB5tqfa7_^3=K)6j>*j`2Hhob=VOpn>+Zrj6*R&d!Bcl%rLWL^lj`SA5| zVdgVD>giVNdeqKXsR7D-xD+;f*&9ZBK{K8SJ7Cvuxa=knE66V{>q+Ia9UK{1Y&D;Y zRTlL)=@}?*yOyig0G8qJP4{*ex6c1bN|_kV6f)2+Md*IFwI-ddEN;zJcT`m!9x2Lm zZ&j4sCvSmWIbAJH=k*Mcj#dP@W~)p$dfAg|@h9tL#E^lv*0rNQ3p?EsVIQCF1G1`0 zPzT6|aU%nyxAzmkS8d&`EfZ-OJ?1|e#LfV>J?Yf%W_Iv}QLl##a&{|-)~MvUC!k#$nAqK@i|w@qF&cM6Z5I6`_1ZR!-{g@%`OMwxz&3eo!!eKt&>wz z%9Jaa(9x6tiLRpP5AQ_l#{9&0l+r))a>oyBP6NAq>&!Fn@gqldAGGJ(I=+R{QUY2s zRo!CBtEroChtrymf{8QL-GkT(ltnHOKUx6`lViU)Ut6F?Glcqhf&m(B7TY>K@r4;a zf^T<8bdQVMHMU7KQ5j!PZpK#CK4++2_#4~~52f9eLLoE_r8di%7OBp(eQ+0 zuh18m4TLy0*V&dqff{b`ujG7AY31NYwN&~|4%;U|u)ZDY)*CnY%G7)h4=?zM!-dM;$wAN4K+A)J z15;B|b0zADlG{#GbF;h^efAf)_HFTz(&4P&?LhEo=M)zJIV_H~*(H zj)sI}GgH9nNCx;}szd+*;N-V~)%e^fA+KnE;=K+DWKc@`i@M@yKb4R+)i5!6s!z&z z?zp*I$!$JX6?V2aS1)^ESH{ksST1#Bw>k~q+@G$Ny%>Z-yJaI;J**tR`H8h!+ZPi0 zptiTc4{U5q`Ms1>R6hwQX5W1XBz)K|)urn0USHqP^1TshhKaU%PPj5N30_@>yq+tQ z<|G*IF4osDoyo_k)%9K5AJCmpokYOMiMERLz0O@-TynZ?4i9V>l50f(PchbNv{9`s zKG-KHknL((yn$|a-YtVb4Q*&YSz}NpXlgo>vM;yV4vniCGd&ql zP)5RXqf|cR>`g}pc;&w5P|gs&*sPRviKgN-Yq_o$PER9i_d$6M*2_kvN(p+zOG$)L z304H_zuP)`@(d4Uv7-+Jx^MTWdKUW@OgMRbb9BrGbwp2OT8>Nqj{ITQdc6RHsa80x z9w1Hgp+i0Xy<_Qu9yRKTc4c-MmGyRM0=`Ldm;~Ibxq0U}xH&c^uzgG~H@m3?k{stD zI2TYu+tSpQV)~uSondjmQj$df{CtSId}#3PbvHj-+&0qZZa1c%Iv+wDVy*RHV`Wzc zON!nglEc(RepvQAcXUKux^2L&;hJK$Z$t_ykSWy+QL6hZGs_|eny2S%6hEUU~Z+k-;K{wtW+d;?91}vHgUG(GX#f#(o zd?@srk%W<)oZJ)Zf@?8Mabj#~Ma789N=LvU$R_d=D;pa;KRFq(qQks7aT-kHtD>sf zxAS6qIGNk_n&*s5ljmVZ%doNv9Xc?*5jE^J^Ya6KM)L8gF5BAK*bq*?OM^-VUmP;A zS&f$MYx3~{TR#74W-*Y|GJ_xjZ-CQKw6m8~Ad345ZB`lM)wSF$9+k zewNSRyl^}(u#5hxP->3!xplKyaG_;>PshYmVoW+>CD|oZ2$3fPKJfGLsw?k)RsJqc zJyS)g4-80Efsc%?bdHJn=?B<cIYf8|78Vp&H7785)tIO#_D_(on~IC7=e3x)zIwP}mJXmg0!rYiXSL|F8gnh0$JttGO~wZirg@WnA>1<9n;--e5e_??+5N$lqv@N*I(ZX2)5cWY{E3$WVn z5u&ll=80->iT1Zk`EDf9E!5lJTRFiql3awcm`)rus+`#GC++X=y=_C>>}k<5?tWQ# zj#3E>0zD@n;LpLG=n16vyg*!?PUibupHg!gU6N*kVa4VII@>dehC25X!NxLC1(+nF zZ5^X!=L|{Y#iE4dQ1YSN)_VS%gZWBh&(q!eOaH4?ZwTV^{=wS)T#6V8n|F(DeVK^Y zdDc};lJd>@>1?brYtGCh>4ff7q2k?Ivwc8-e-f6=gvp>opR(^TZ1hLEWcE`&9mEz= zKDvLm=#QAzLriMw*=6k5c>FK@f>polO8#8_+bb^(jVG zi4S(SH=7fZ;mq&FQmrb$cgK6tcg;=byCVis!^6XtsY63U_d2c2CzDq%)TvQ+hgxD& z?gAcfq(Q?BZG4?2a+imZ2sRH_!p&t!eos!i$CI`*t9cJ2mldh;S zIk+Yn)u;^B^mg}XzJee7=-OFXDJfDBe%Wdg1CI?VK8p5|Eb3kR*P# zsCg+7+|r`MY+5LGWg^IHXuX11YLqWjqS7iyPku|zQ(K=l{iAP7adB~KYV#;sn@|yj zg@w7f8~iL<9~cl8E7^Y1tD-)=M#tmdC2ehN*bUp%G(m?4r^UY7wbpa&vJCw`UKeM` zxeK&4{=_N42#&+al! zkwp<|11`_^6iQ757v7wnOow#S_A9h_uZ72#rU%4sY`cOhjBSCy1OT8}&7|<7Sk!v} z9UYx?&=pT6;$6L+UjA@o0X(e4b|12}rW1$&&9*G*DXQyoJ2^NMY{y;uV4+b4$~55P zNNcU~;f#k58h@Eq_BUugH9Cm<+Ksh6!NI{kKU`75QMsuNE7rAe-`SAG|A;u&w2F<7mSMBRkBsCmTXijTwCFDrnv+B>Qd1iwTQZ@&evS;la#<_06nAF$> z`*DZR%dd+t4|flr;|TyTTwXD|s#f}f+Q)(vJ@L)0Ew#tdBr7ck%Ie(e1-;|!S=KvR znJv2cb~IUm1XrN*!eR(g^VrY{1Tu?wTF_t`#YHsa`=^K(eNU#Z;+nDy zB3jK}`sx3(muR1rS?^dohCb2Dp_-K4jN;(4>i14%miD5OqO4!p;BOx(YEKDpv+3