mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 16:41:11 +00:00
510df68bcf
Captures the full output of autodev existing-code Phase A through Step 4 (Code Testability Revision) for the Azaion UI workspace: - Step 1 Document: _docs/02_document/ (FINAL_report, architecture, glossary, components/, modules/, diagrams/, system-flows, module-layout) plus _docs/00_problem/ + _docs/01_solution/ + _docs/legacy/ + _docs/how_to_test + README. - Step 2 Architecture Baseline: architecture_compliance_baseline.md. - Step 3 Test Spec: _docs/02_document/tests/ (environment, test-data, blackbox/performance/resilience/security/ resource-limit tests, traceability-matrix), enum_spec_snapshot, expected_results/results_report.md (98 rows), plus the run-tests.sh + run-performance-tests.sh runners. - Step 4 Code Testability Revision: 01-testability-refactoring/ run dir (list-of-changes C01-C07, deferred_to_refactor, analysis/research_findings + refactoring_roadmap) and the 7 child task specs AZ-448..AZ-454 under _docs/02_tasks/todo/ plus _dependencies_table.md. - _docs/_autodev_state.md pins the cursor at Step 4 / refactor Phase 4 entry so /autodev resumes cleanly. Epic AZ-447 (UI testability gates) tracks the 7 child tasks that will land in subsequent commits. Co-authored-by: Cursor <cursoragent@cursor.com>
166 lines
18 KiB
Markdown
166 lines
18 KiB
Markdown
# Traceability Matrix
|
|
|
|
Maps every acceptance criterion and every restriction in `_docs/00_problem/` to the test scenarios that verify it (this directory) and the expected-result row in `_docs/00_problem/input_data/expected_results/results_report.md` that provides the quantifiable observable. Quarantined tests are marked `[Q]` — they assert against a Phase B target feature or a Step 4 fix that has not landed; they activate the day the implementation ships.
|
|
|
|
## Acceptance Criteria Coverage
|
|
|
|
| AC ID | Acceptance Criterion (short) | Tests | results_report rows | Coverage |
|
|
|-------|------------------------------|-------|---------------------|----------|
|
|
| AC-01 | `credentials:'include'` on every authenticated fetch | FT-P-01 [Q for bootstrap], FT-P-02, NFT-PERF-02, NFT-SEC-04, NFT-RES-01, NFT-RES-08 | 01, 02, 03 | Covered |
|
|
| AC-02 | Bearer never written to client storage | NFT-SEC-01 | 04 | Covered |
|
|
| AC-03 | Refresh cookie `Secure HttpOnly SameSite=Strict` | NFT-SEC-02, NFT-SEC-03 | 05, 06, 07 | Covered |
|
|
| AC-04 | Numeric enums match suite spec | FT-P-04, FT-P-05, FT-P-06 | 14, 15, 16, 17, 18, 19 | Covered (`enum_spec_snapshot.json` committed — Phase 3 gate resolved) |
|
|
| AC-05 | Annotation save endpoint + required body fields | FT-P-07, FT-P-08 | 22, 23 | Covered |
|
|
| AC-06 | Selected-flight persistence path | FT-P-16, FT-P-17 | 32, 33 | Covered |
|
|
| AC-07 | Bulk-validate works | FT-P-20, FT-P-21, NFT-PERF-07 | 36, 37 | Covered |
|
|
| AC-08 | Live-GPS SSE per flight | FT-P-18, FT-P-19, NFT-PERF-04, NFT-PERF-05, NFT-RES-10, NFT-RES-LIM-06, NFT-RES-LIM-07 | 34, 35, 97 | Covered |
|
|
| AC-09 | Annotation-status SSE during page lifetime | FT-P-09, FT-P-10, NFT-PERF-06, NFT-RES-LIM-05 | 24, 25, 97 | Covered |
|
|
| AC-10 | Upload size cap 500 MB + UI error path | FT-N-06, NFT-RES-07, NFT-RES-LIM-02 | 38, 39 | Covered |
|
|
| AC-11 | Initial JS bundle ≤ 2 MB | NFT-PERF-01, NFT-RES-LIM-01 | 40 | Covered (documentary — no CI gate today) |
|
|
| AC-12 | i18n key parity en ↔ ua | FT-P-22, FT-P-23 | 45, 46 | Covered |
|
|
| AC-13 | i18n detector + persistence | FT-P-24 [Q], FT-P-25 [Q] | 47, 48 | Covered (quarantined — Step 4 fix) |
|
|
| AC-14 | Destructive actions require ConfirmDialog + alert() forbidden | FT-P-26, FT-P-27, FT-N-07, NFT-SEC-07, NFT-SEC-08 | 49, 50, 51 | Covered |
|
|
| AC-15 | ConfirmDialog a11y | FT-P-28, FT-P-29, FT-N-08 | 52, 53, 54 | Covered |
|
|
| AC-16 | Header flight dropdown a11y | FT-P-30, FT-P-31, FT-N-09 | 55, 56, 57 | Covered |
|
|
| AC-17 | ProtectedRoute spinner a11y + timeout | FT-P-32, FT-P-33 [Q], NFT-RES-04 [Q] | 58, 59 | Covered (quarantined for timeout) |
|
|
| AC-18 | Browser support — Chromium + Firefox latest 2 | FT-P-34, NFT-PERF-10 | 60, 98 | Covered (manual smoke, no automated gate today) |
|
|
| AC-19 | Mobile / desktop breakpoint variants | FT-P-35, FT-P-36 | 61, 62 | Covered |
|
|
| AC-20 | OpenWeatherMap key not in source | NFT-SEC-09 [Q for source until Step 4] | 63 | Covered (quarantined for source check) |
|
|
| AC-21 | UserSettings panel-width persistence | FT-P-37 [Q], FT-P-38 [Q], NFT-PERF-08 [Q] | 64, 65 | Covered (quarantined) |
|
|
| AC-22 | RBAC client-side route gates | FT-N-03 [Q], FT-N-04, FT-N-05 [Q], NFT-SEC-05 [Q], NFT-SEC-06 [Q], NFT-RES-08 | 08, 09, 10 | Covered (quarantined for `/admin` + `/settings` gates) |
|
|
| AC-23 | Auth refresh transparency | FT-P-02, FT-P-03, NFT-PERF-02, NFT-RES-01 | 11, 12 | Covered |
|
|
| AC-24 | SSE bearer-rotation reconnect | NFT-PERF-03 [Q], NFT-RES-02 [Q], NFT-RES-10 | 13, 97 | Covered (quarantined — Step 8 hardening) |
|
|
| AC-25 | Detect endpoint correctness (sync + async) | FT-P-11, FT-P-12 [Q], FT-P-13 [Q] | 26, 27, 28 | Covered (async path quarantined — F7 target) |
|
|
| AC-26 | Numeric input hygiene | FT-N-11 [Q], FT-N-12 [Q] | 66, 67 | Covered (quarantined — Step 4 fix) |
|
|
| AC-27 | Save error surfacing in settings | FT-N-13 [Q], FT-N-14 [Q], NFT-PERF-09 [Q], NFT-RES-05 [Q], NFT-RES-06 [Q] | 68, 69 | Covered (quarantined — Step 4 fix) |
|
|
| AC-28 | Annotation overlay time window `[-50, +150] ms` | FT-P-14, FT-P-15, FT-N-01, FT-N-02 | 29, 30, 31 | Covered |
|
|
| AC-29 | `mediaType` is typed (no magic literals) | FT-N-15 | 20, 21 | Covered |
|
|
| AC-30 | Class delete confirmation | FT-P-26, FT-N-07, NFT-SEC-08 | 49 | Covered (overlaps AC-14 row 49) |
|
|
| AC-31 | `mission-planner/` not in production bundle | NFT-RES-LIM-04 | 41 | Covered |
|
|
| AC-32 | CI image tag + OCI labels | NFT-RES-LIM-11, NFT-RES-LIM-12, NFT-RES-LIM-13 | 70, 71, 72 | Covered |
|
|
| AC-33 | Production runtime `nginx:alpine` only | NFT-RES-LIM-03 | 42 | Covered |
|
|
| AC-34 | nginx routes 9 services with prefix stripping | NFT-RES-LIM-09, NFT-RES-LIM-10 | 43, 44 | Covered |
|
|
| AC-35 | Manual bbox draw on CanvasEditor | FT-P-39 | 73 | Covered |
|
|
| AC-36 | 8-handle resize + Ctrl-multi-select + Ctrl-wheel zoom + Ctrl-drag pan | FT-P-40, FT-P-41, FT-P-42, FT-P-43 | 74, 75, 76, 77 | Covered |
|
|
| AC-37 | Class picker — load + hotkey + click + fallback | FT-P-44, FT-P-45, FT-P-46, FT-P-47 | 78, 79, 80, 81 | Covered (pending backend ordering check — Phase 3 gate) |
|
|
| AC-38 | PhotoMode switcher | FT-P-48, FT-P-49, FT-P-50 | 82, 83, 84 | Covered |
|
|
| AC-39 | Tile-splitting endpoint + parser | FT-P-51 [Q], FT-P-52, FT-P-53, FT-N-10 | 85, 86, 87, 88 | Covered (split surface quarantined) |
|
|
| AC-40 | Tile-zoom auto-zoom + indicator | FT-P-54 [Q], FT-P-55 [Q] | 89, 90 | Covered (quarantined — UX missing today) |
|
|
| AC-N1 | No collaborative-edit semantics | NFT-SEC-14 | 91 | Covered |
|
|
| AC-N2 | No in-browser ML | NFT-SEC-10 | 92 | Covered |
|
|
| AC-N3 | No offline mode | NFT-RES-03, NFT-SEC-12 | 93 | Covered |
|
|
| AC-N4 | No response-signature library | NFT-SEC-11 | 94 | Covered |
|
|
| AC-N5 | Dropped legacy features (Sound Detections, Drone Maintenance) | NFT-SEC-13 | 95 | Covered |
|
|
|
|
## Restrictions Coverage
|
|
|
|
| RID | Restriction (short) | Tests / Mechanism | Coverage |
|
|
|-----|---------------------|-------------------|----------|
|
|
| H1 | ARM64-only production image | NFT-RES-LIM-03 (image base check); the build pipeline produces ARM64 only — meta-config | Covered |
|
|
| H2 | Edge-device deployment target | NFT-PERF-10, NFT-RES-LIM-08 | Covered (documentary) |
|
|
| H3 | No GPU expectation in UI image | environment.md (no GPU in test rig); NFT-SEC-10 (no ML libs) — together they verify the constraint | Covered (by composition) |
|
|
| H4 | HTML5 video + canvas + EventSource on Chromium / Firefox latest 2 | FT-P-34 | Covered |
|
|
| S1 | TypeScript strict mode | STC-S1: static read of `tsconfig.json` for `"strict": true` (planned static check — added by Phase 3 if accepted) | NOT COVERED — Phase 3 to add |
|
|
| S2 | React 19 | STC-S2: `package.json` dep version pin | NOT COVERED — Phase 3 to add |
|
|
| S3 | Vite 6 | STC-S3: `package.json` dep version pin | NOT COVERED — Phase 3 to add |
|
|
| S4 | Bun 1.3.11 | STC-S4: `package.json` `packageManager` field + Dockerfile base image pin | NOT COVERED — Phase 3 to add |
|
|
| S5 | Static-bundle output only (no Node in prod image) | NFT-RES-LIM-03 | Covered |
|
|
| S6 | REST + SSE only (no WebSocket / GraphQL / gRPC-Web) | STC-S6: dep scan for `ws`, `socket.io`, `graphql`, `apollo`, `grpc-web` (planned) | NOT COVERED — Phase 3 to add |
|
|
| S7 | Two React Contexts only (no Redux / Zustand / TanStack Query) | STC-S7: dep scan for `redux`, `zustand`, `@reduxjs/.*`, `@tanstack/.*` | NOT COVERED — Phase 3 to add |
|
|
| S8 | Tailwind 4 + `az-*` design tokens | STC-S8: dep version pin + presence of token CSS vars | NOT COVERED — Phase 3 to add |
|
|
| S9 | `leaflet@1.9.4` + `react-leaflet@5` + `leaflet-draw` + `leaflet-polylinedecorator` | STC-S9: `package.json` version pin set | NOT COVERED — Phase 3 to add |
|
|
| S10 | `chart.js@4` + `react-chartjs-2@4` | STC-S10 | NOT COVERED — Phase 3 to add |
|
|
| S11 | `@hello-pangea/dnd@18` | STC-S11 | NOT COVERED — Phase 3 to add |
|
|
| S12 | `i18next` + `react-i18next` with EN + UA bundles only | FT-P-22, FT-P-23 + STC-S12 (no other locale bundle files) | Partially Covered |
|
|
| S13 | No client-side persistence library | NFT-SEC-01 + STC-S13 (dep scan for `localforage`, `idb`, `dexie`) | Partially Covered |
|
|
| S14 | No test framework configured today | META — these tests' very existence supersedes this restriction; resolved at Step 5 (Decompose Tests) per `acceptance_criteria.md` AC-14 / S14 note | N/A — meta |
|
|
| E1 | Air-gap-friendly bundle | NFT-RES-03 (offline boot) + external-dep stubs in environment.md | Partially Covered |
|
|
| E2 | nginx strips `/api/<service>/` per service | NFT-RES-LIM-09, NFT-RES-LIM-10 | Covered |
|
|
| E3 | `Secure HttpOnly SameSite=Strict` refresh cookie | NFT-SEC-03 | Covered |
|
|
| E4 | Vite dev proxy at `/api → http://localhost:8080` | dev-only; not testable in production runtime | NOT COVERED — meta-config (Phase 3 to confirm) |
|
|
| E5 | `AZAION_REVISION` stamped at build | NFT-RES-LIM-13 | Covered |
|
|
| E6 | OCI image labels | NFT-RES-LIM-12 | Covered |
|
|
| E7 | Image registry + tag scheme | NFT-RES-LIM-11 | Covered |
|
|
| E8 | Branch triggers (`dev` / `stage` / `main`) | STC-E8: parse `.woodpecker/build-arm.yml` triggers (planned) | NOT COVERED — Phase 3 to add |
|
|
| E9 | `client_max_body_size 500M` | NFT-RES-LIM-02 | Covered |
|
|
| E10 | OpenWeatherMap direct-from-browser today | NFT-SEC-09 (key check) + environment.md `owm-stub` (E2E isolation) | Covered |
|
|
| O1 | Bilingual UI mandatory | FT-P-22, FT-P-23 | Covered |
|
|
| O2 | Bearer never in localStorage / sessionStorage | NFT-SEC-01 | Covered |
|
|
| O3 | `credentials:'include'` on every authenticated fetch | NFT-SEC-04 | Covered |
|
|
| O4 | RBAC is server-enforced (UI must NOT trust `AuthUser.role`) | meta-design + FT-N-04 (unauth → /login regardless of any client claim); STC-O4 (no `if (user.role === 'admin')` gating sensitive data, only UI hide/show) | Partially Covered — Phase 3 may add the static gate-pattern lint |
|
|
| O5 | Refresh cookie attributes | NFT-SEC-03 | Covered |
|
|
| O6 | No hardcoded credentials | NFT-SEC-09 | Covered |
|
|
| O7 | Spec is source of truth for numeric enums | FT-P-04, FT-P-05, FT-P-06 | Covered |
|
|
| O8 | Persist what you type (panel widths) | FT-P-37 [Q], FT-P-38 [Q] | Covered (quarantined) |
|
|
| O9 | Admin can edit existing detection classes (P12) | NOT COVERED — feature missing today (`acceptance_criteria.md` notes P12 violation; PATCH endpoint to re-introduce in Phase B) | NOT COVERED — Phase B target |
|
|
| O10 | Destructive actions require ConfirmDialog | NFT-SEC-08, FT-P-26, FT-P-27, FT-N-07 | Covered |
|
|
| O11 | No SSR / RSC | NFT-RES-LIM-03 (no Node in image) + STC-O11 (no `react-dom/server` import) | Partially Covered |
|
|
| O12 | `mission-planner/` not compiled by production Vite build | NFT-RES-LIM-04 | Covered |
|
|
| O13 | Bundle size budget ≤ ~2 MB gzipped initial JS | NFT-PERF-01, NFT-RES-LIM-01 | Covered (target — no CI gate today) |
|
|
| O14 | No CI test step today | META — resolved at Step 5 (Decompose Tests) | N/A — meta |
|
|
| O15 | No vuln scan / SBOM / image signing | NOT COVERED — Step 6 / security_approach surface; Phase B addition | NOT COVERED |
|
|
|
|
## Coverage Summary
|
|
|
|
| Category | Total Items | Covered | Partially Covered | Not Covered | N/A (meta) | Coverage % (Covered+Partial) |
|
|
|----------|-------------|---------|-------------------|-------------|-----------|--------------------|
|
|
| Acceptance Criteria | 40 | 40 | 0 | 0 | 0 | 100% (24 fully ungated, 16 with Phase 3 quarantine markers) |
|
|
| Anti-Criteria | 5 | 5 | 0 | 0 | 0 | 100% |
|
|
| Restrictions | 41 | 17 | 8 | 13 | 3 | 61% |
|
|
| **Total** | **86** | **62** | **8** | **13** | **3** | **81%** |
|
|
|
|
Acceptance criterion coverage exceeds the 75 % template threshold. Restriction coverage is short of 75 % because most of the un-covered restrictions are dependency-version pins (S1-S11) for which a single static check pass (planned `STC-S*` family) would lift them to Covered without changing the SPA's observable behavior.
|
|
|
|
## Uncovered Items Analysis
|
|
|
|
| Item | Reason Not Covered | Risk | Mitigation |
|
|
|------|-------------------|------|-----------|
|
|
| S1-S11 (TS strict, React/Vite/Bun version pins, Tailwind, Leaflet, Chart.js, DnD) | Dependency-version restrictions need a static `package.json` / `tsconfig.json` parser pass; not authored in this phase | Drift between pinned and installed versions (e.g., transitive resolution); accidental upgrade in a refactor breaking ADRs (ADR-001 …) | Phase 3 to confirm adding the `STC-S*` family; otherwise Step 4 / Step 8 may add them as part of the testability fix |
|
|
| S12, S13 partials | `STC-S12` (no other locale bundles) and `STC-S13` (no IndexedDB / localForage / Dexie deps) need explicit dep scans | Low — currently aligned per `package.json`; risk only on dep additions | Phase 3 promotion to a single static dep-scan job (run alongside the dep-license lint) |
|
|
| E4, E8 | Dev-only proxy and pipeline branch triggers are not consumer-observable from a production build | None today; future risk if the proxy diverges from the prod nginx | Document-only; Phase 3 confirms |
|
|
| O4 partial (RBAC trust pattern) | No lint rule today; the design intent is captured but not asserted in code | UI accidentally gates sensitive data on a client claim | Phase 3 to add an `STC-O4` lint that bans `if (user.role === 'admin') { /* reveal data */ }` patterns; FT-N-04 already locks the unauth path |
|
|
| O9 (admin can edit classes — P12) | The feature does not exist today (only add + delete); cannot test absence of a regression | Functionality missing relative to spec | Phase B feature cycle will add `PATCH /api/admin/classes/{id}` plus FT-P-XX in the cycle that ships it; AC-37 / AC-30 already enforce the surrounding contract |
|
|
| O11 partial | NFT-RES-LIM-03 confirms no Node binary in the image; an explicit "no `react-dom/server` import" lint is missing | Could regress to SSR by accident on a refactor; the image base check would still pass | Phase 3 confirms `STC-O11` |
|
|
| O15 (vuln scan / SBOM / signing) | Pipeline does not emit any of these today | Supply-chain risk | Addressed at Step 6 / `security_approach.md`; outside the test-spec scope |
|
|
| AC-11, AC-18, AC-24, AC-40, AC-25 async path | Phase B / target features with quarantined tests | Tests do not gate today — risk = the feature ships without the assertion being un-quarantined | Phase 3 chooses: keep quarantined (gates the day the feature ships) OR downgrade to documentary; recommendation: keep quarantined |
|
|
| AC-04 enum spec numeric values for `MediaStatus` / `Affiliation` / `CombatReadiness` | The exact spec values are not pinned in `enum_spec_snapshot.json` yet | Tests use symbolic comparison and may silently match a wrong UI state | Phase 3 to require population of the snapshot before AC-04 tests gate CI; recommendation: BLOCK Step 4 until the snapshot is committed |
|
|
| AC-37 backend ordering | The class-hotkey contract requires `[0..N-1, 20..20+N-1, 40..40+N-1]` ordering from the suite; not yet verified | Hotkey test fails at integration; ambiguous responsibility | Phase 3 to surface; fix can land server-side or via a client-side resort, depending on the verification result |
|
|
|
|
## Quarantine List (running)
|
|
|
|
The following 18 tests assert against a Phase B target or a Step 4 fix and are quarantined until the implementation lands. Phase 3 will decide their disposition.
|
|
|
|
| Test | Reason | Activates when |
|
|
|------|--------|---------------|
|
|
| FT-P-01 (bootstrap part) | Bootstrap refresh missing `credentials:'include'` per finding | Step 4 fix |
|
|
| FT-P-12, FT-P-13 | Async video detect (F7) not wired | Phase B feature cycle |
|
|
| FT-P-24, FT-P-25 | i18n detector + persistence missing | Step 4 fix |
|
|
| FT-P-33 (timeout) | ProtectedRoute timeout missing | Step 4 fix |
|
|
| FT-P-37, FT-P-38 | Panel-width writer missing (`useResizablePanel`) | Step 4 fix |
|
|
| FT-P-51 | Split surface not on dataset page today | Phase B |
|
|
| FT-P-54, FT-P-55 | Tile-zoom UX missing (finding #24) | Phase B |
|
|
| FT-N-03, FT-N-05 | `/admin` and `/settings` role-gates missing | Step 4 / Step 8 |
|
|
| FT-N-11, FT-N-12, FT-N-13, FT-N-14 | Settings form hygiene fixes missing | Step 4 |
|
|
| NFT-PERF-03 / NFT-RES-02 | SSE refresh-rotation reconnect missing | Step 8 hardening |
|
|
| NFT-PERF-08 / NFT-PERF-09 | Tied to FT-P-37 / FT-N-13 quarantines | per above |
|
|
| NFT-SEC-05, NFT-SEC-06 | Tied to FT-N-03, FT-N-05 | per above |
|
|
| NFT-SEC-09 (source check) | OpenWeatherMap key still in source today | Step 4 fix |
|
|
| NFT-RES-04 | Tied to FT-P-33 | per above |
|
|
|
|
## Phase 3 (Data Validation Gate) — Open Items to Resolve
|
|
|
|
### Resolved in Phase 3
|
|
|
|
1. ~~**`enum_spec_snapshot.json`** — populate from the suite spec before AC-04 tests gate CI.~~ → **Resolved:** snapshot committed at `_docs/00_problem/input_data/enum_spec_snapshot.json`. `verification_pending: true` markers remain for `CombatReadiness` and `MediaType` (numeric ordering inferred from schema member-listing); Step 4 .NET-service inspection lifts those.
|
|
2. ~~**NFT-RES-09** — no `results_report.md` row binding.~~ → **Resolved:** row 96 added (tainted-canvas fallback observable).
|
|
3. ~~**NFT-RES-10** — no `results_report.md` row binding.~~ → **Resolved:** row 97 added (SSE server-disconnect observable; ≤ 10 s indicator-or-reconnect; reconnect attempts ≤ 1 in window).
|
|
4. ~~**NFT-PERF-10** — FCP baseline has no `results_report.md` row.~~ → **Resolved:** row 98 added (`FCP ≤ 3 000 ms` on warm-cache navigation to `/flights`, headless Chromium, 2 vCPU / 4 GB edge profile).
|
|
|
|
### Still open (carry forward to Step 4 / runner)
|
|
|
|
5. **AC-37 backend ordering** — verify the `annotations/` service response shape and either confirm matches or schedule a fix on the appropriate side.
|
|
6. **STC family** — confirm adding the `STC-S*` / `STC-O4` / `STC-O11` static-check IDs to lift the restriction coverage above 75 %.
|
|
7. **Quarantine disposition** — accept the quarantine list above; decide whether quarantined tests gate CI today (recommended: no, but they are picked up automatically the day the feature lands).
|
|
8. **AC-04 UI enum drift in `src/types/index.ts`** — tests will FAIL until the Step 4 fix lands per `acceptance_criteria.md`; quarantine until Step 4 OR run them and use the failure as the gate to schedule Step 4. The drift list is pinned in `enum_spec_snapshot.json` → `ui_drift_summary` (5 enums).
|
|
9. **Parent-suite doc fixes (leftover)** — `../_docs/01_annotations.md` line 208 and `../_docs/09_dataset_explorer.md` line 165 show stale `affiliation: 2 // Hostile` examples; should be 20 per `00_database_schema.md`. Record as a leftover in `_docs/_process_leftovers/` when raised against the parent suite.
|