Files
Oleksandr Bezdieniezhnykh 06d160daf0 [AZ-808] [AZ-809] [AZ-810] [AZ-811] [AZ-812] Cycle 8 Step 9 queued
Step 9 (New Task) closure for cycle 8. Queues 5 task specs under the
AZ-795 strict-validation umbrella + OSM-naming harmonization:

- AZ-808 region-request validator (POST /api/satellite/request)   3 pts
- AZ-809 route-creation validator (POST /api/satellite/route)     5 pts
- AZ-810 UAV upload metadata validator (POST /api/satellite/upload) 5 pts
- AZ-811 lat/lon GET validator (GET /api/satellite/tiles/latlon)  2 pts
- AZ-812 Region DTO rename latitude/longitude -> lat/lon          3 pts

Total 18 SP. Origin: cross-repo request from gps-denied-onboard
agent (2026-05-22) after AZ-777 Phase 2 black-box probe of the
Region API surfaced silent-coercion behavior + the lone OSM-deviating
coord naming convention left in the producer's public surface.

Ordering recorded (per /autodev Step 10 dirty-tree decision):
AZ-812 ships first so AZ-808 validator + contract doc + integration
tests are written against the final lat/lon names. AZ-809/AZ-810/AZ-811
are independent of AZ-812 (their DTOs already use OSM short form).

Deps table updated: cycle-8b (AZ-812) folded into cycle-8 ordering as
step 1; AZ-808 dependency upgraded SOFT -> HARD on AZ-812.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 13:00:34 +03:00

264 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Task Dependencies
## Dependency Graph
### Step 6 — Implement Tests (AZ-285..AZ-290)
| Task | Depends On | Points | Status |
|------|-----------|--------|--------|
| AZ-285 Test Infrastructure | — | 3 | Done |
| AZ-286 TileService Tests | AZ-285 | 3 | Done |
| AZ-287 RegionService Tests | AZ-285 | 3 | Done |
| AZ-288 RouteService Tests | AZ-285 | 3 | Done |
| AZ-289 Integration Route Maps | AZ-285 | 2 | Done |
| AZ-290 Non-Functional Tests | AZ-285 | 3 | Done |
### Step 8 — Refactor 02-coupling-refactoring (AZ-309 epic)
| Task | Depends On | Points | Status |
|------|-----------|--------|--------|
| AZ-310 ServeTile via ITileService | — | 3 | Done (In Testing) |
| AZ-311 GetTileByLatLon via ITileService | AZ-310 | 2 | Done (In Testing) |
| AZ-312 Split Services into 3 csprojs | AZ-311 | 5 | Done (In Testing) |
| AZ-313 Update consumers (Api/Tests) | AZ-312 | 3 | Done (In Testing) |
| AZ-314 DI registration split | AZ-313 | 2 | Done (In Testing) |
| AZ-315 Documentation sync | AZ-314 | 2 | In Progress |
### Step 8 — Refactor 03-code-quality-refactoring (AZ-350 epic)
Roadmap: `_docs/04_refactoring/03-code-quality-refactoring/analysis/refactoring_roadmap.md` (4 execution phases).
| Task | C-ID | Title | Phase | Depends On | Points | Status |
|------|------|-------|-------|-----------|--------|--------|
| AZ-351 | C01 | Fix null logger to DatabaseMigrator | 1 | — | 2 | Done (In Testing) |
| AZ-352 | C02 | Replace empty catch in ExtractTileCoordinatesFromFilename | 1 | — | 2 | Done (In Testing) |
| AZ-363 | C10 | Delete write-only counters in RegionRequestQueue | 1 | — | 1 | Done (In Testing) |
| AZ-356 | C05 | Stub endpoints return 501 | 1 | — | 2 | Done (In Testing) |
| AZ-354 | C04 | Strict CORS by default | 1 | — | 2 | Done (In Testing) |
| AZ-353 | C03 | Sanitize 5xx responses via IExceptionHandler | 1 | — | 3 | Done (In Testing) |
| AZ-359 | C07 | Consolidate RegionService catch ladder | 2 | — | 3 | Done (In Testing) |
| AZ-357 | C06 | Drop tile Version concept; new migration | 2 | — | 5 | Done (In Testing) |
| AZ-362 | C09 | Idempotent POST contract | 2 | AZ-353 | 3 | Done (In Testing) |
| AZ-366 | C13 | Consolidate Haversine + filename parser | 3 | — | 2 | Done (In Testing) |
| AZ-377 | C24 | Consolidate Earth constants + 111000 | 3 | AZ-371 | 2 | Done (In Testing) |
| AZ-368 | C15 | Shared TileCsvWriter | 3 | — | 2 | Done (In Testing) |
| AZ-367 | C14 | Shared TileGridStitcher | 3 | AZ-364 | 3 | Done (In Testing) |
| AZ-369 | C16 | Move inline DTOs out of Program.cs | 3 | — | 2 | Done (In Testing) |
| AZ-365 | C12 | Decompose RouteService.CreateRouteAsync | 3 | — | 5 | Done (In Testing) |
| AZ-364 | C11 | Decompose RouteProcessingService god-class | 3 | AZ-366, AZ-367 (folds in AZ-360) | 5 | Done (In Testing) |
| AZ-360 | C08 | Replace IServiceProvider in RouteProcessingService | 3 | AZ-364 (folded) | 2 | Done (In Testing) |
| AZ-371 | C18 | Magic numbers → ProcessingConfig/MapConfig | 4 | — | 3 | Done (In Testing) |
| AZ-370 | C17 | Status / point-type enums + AC RT2 update | 4 | — | 3 | Done (In Testing) |
| AZ-373 | C20 | Clarify / drop MapsVersion | 4 | AZ-357 | 2 | Done (In Testing) |
| AZ-374 | C21 | Typed HttpClient for Google Maps | 4 | — | 2 | Done (In Testing) |
| AZ-375 | C22 | O(N) existing-tile lookup (HashSet) | 4 | AZ-371 | 2 | Done (In Testing) |
| AZ-376 | C23 | Delete unused FindExistingTileAsync | 4 | — | 1 | Done (In Testing) |
| AZ-378 | C25 | Repo `_logger` fields: delete or use | 4 | — | 1 | Done (In Testing) |
| AZ-379 | C26 | Extract repo SELECT column-list constants | 4 | — | 2 | Done (In Testing) |
| AZ-380 | C27 | Delete CalculatePolygonDiagonalDistance | 4 | — | 1 | Done (In Testing) |
| AZ-372 | C19 | dotnet format + NetAnalyzers + Coverlet | 4 | — | 3 | Done (In Testing) |
### Step 9 cycle 1 — New Task: Multi-source tile storage + UAV upload (AZ-483 epic)
| Task | Title | Depends On | Points | Status |
|------|-------|-----------|--------|--------|
| AZ-484 | Multi-source tile storage schema (source + captured_at) | — | 5 | Done (deployed cycle 1) |
### Step 9 cycle 2 — New Task: JWT validation baseline + UAV upload completion
| Task | Title | Depends On | Points | Status |
|------|-------|-----------|--------|--------|
| AZ-487 | JWT validation baseline (HS256, JWT_SECRET, all endpoints) | — (consumes suite-level contract `suite/_docs/10_auth.md`) | 2 | Done (In Testing) |
| AZ-488 | UAV tile upload endpoint with batch + 5-rule quality gate | AZ-487 (hard prereq), AZ-484 contract `tile-storage.md` v1.0.0 | 8 (over-cap, user-accepted) | Done (In Testing) |
### Step 9 cycle 3 — New Task: Cycle-2 follow-ups (test infra + security hardening + process)
Source: cycle-2 retrospective top-3 improvement actions + carried-forward security and process items (`_docs/06_metrics/retro_2026-05-11_cycle2.md`).
| Task | Title | Depends On | Points | Status |
|------|-------|-----------|--------|--------|
| AZ-491 | Consolidate JWT test-mint helpers | — (logically follows AZ-487 which introduced both copies) | 3 | To Do |
| AZ-492 | Perf harness: PT-07 + PT-08 + JWT-attach in run-performance-tests.sh | AZ-487 (hard — Bearer token); AZ-491 (soft — token-mint reuse) | 3 | In Testing |
| AZ-493 | Integration test DB-reset hook | — | 2 | To Do |
| AZ-494 | JWT iss/aud validation (enable + configure) | AZ-487 (extends `AddSatelliteJwt`); external: admin team confirms iss/aud values | 2 | In Testing (Option B: plumbing implemented; prod iss/aud values gated by fail-fast startup) |
| AZ-495 | Resolve doc-folder convention for WebApi component | — | 1 | To Do |
| AZ-496 | Bump Microsoft.AspNetCore.OpenApi + JwtBearer to 8.0.25 | — | 2 | To Do |
### Step 9 cycle 4 — New Task: SDK migration
Source: cycle-3 perf-harness leftover replay surfaced the host SDK / project SDK mismatch; user directive at start of cycle 4 to migrate to .NET 10. Closes the cycle-3 leftover as a side effect (AC-5).
| Task | Title | Depends On | Points | Status |
|------|-------|-----------|--------|--------|
| AZ-500 | .NET 8 → .NET 10 migration (TFM + SDK pin + Docker images + CI images + Microsoft.AspNetCore.* + Microsoft.Extensions.* + Serilog.AspNetCore) | — | 5 | Done (In Testing) |
### Step 9 cycle 5 — New Task: Tile identity foundation + perf-harness fix (AZ-483 epic)
Source: cross-workspace handoff from `gps-denied-onboard` (tile-schema scenario analysis) for AZ-503; cycle-3 perf-harness leftover replay-obligation closure for AZ-504. Both attach to epic AZ-483 (Multi-source tile storage + UAV upload, Layer 2) — AZ-503 supersedes the AZ-484 UPSERT-conflict-key portion, AZ-504 unblocks PT-08 measurement.
**Cycle 5 split (during /autodev Step 10 batch 2)**: AZ-503 was specced as 3 SP but reconciled at ~5 SP once the codebase was inspected (`flight_id` / `voting_status` columns + `UavTileMetadata.FlightId` field didn't exist). User picked Option C: split AZ-503 into AZ-503-foundation (this cycle) + AZ-505 (next cycle). AZ-505 is `Blocks`-linked to AZ-503 and waits for the columns to land.
| Task | Title | Depends On | Points | Status |
|------|-------|-----------|--------|--------|
| AZ-503 | Tile identity → UUIDv5 + integer UPSERT (foundation half — split from original AZ-503) | AZ-484 (supersedes UPSERT-conflict-key portion of AZ-484 selection rule) | 3 | Done (In Testing, batch 2 cycle 5) |
| AZ-504 | Perf script: fix grep \| wc -l pipefail crash in PT-08 | — (independent; references AZ-488 PT-08 threshold) | 1 | Done (In Testing, batch 1 cycle 5) |
| AZ-505 | Tile inventory endpoint + HTTP/2 + leaflet covering index | AZ-503 (HARD, Blocks-linked — needs `location_hash` + `flight_id` columns) | 3 | To Do (consumed by cycle 6 — see below) |
### Step 9 cycle 6 — New Task: Tile inventory endpoint + HTTP/2 + Leaflet covering index (AZ-483 epic)
Source: cycle-5 retro Action 2 — AZ-505 is the deferred half of AZ-503 (inventory endpoint + HTTP/2 + Leaflet covering index). AZ-503-foundation (cycle 5) shipped the prerequisite columns (`location_hash`, `flight_id`, `content_sha256`, `legacy_id`); AZ-505 ships the user-facing payload that consumes them.
| Task | Title | Depends On | Points | Status |
|------|-------|-----------|--------|--------|
| AZ-505 | Tile inventory endpoint + HTTP/2 + leaflet covering index | AZ-503 (HARD, Blocks-linked, satisfied by cycle 5) | 3 | To Do (cycle 6) |
### Step 9 cycle 7 — New Task: API quality follow-up (cross-repo from gps-denied-onboard AZ-777)
Source: cycle-7 New Task adoption of three Jira tickets originally filed on 2026-05-22 by the `gps-denied-onboard` agent during AZ-777 Phase 1 Jetson probing of the parent-suite `satellite-provider` service. Two API-quality concerns about the inventory endpoint were surfaced:
1. **Field-name inconsistency** — URL path uses OSM-standard `z/x/y`; JSON body uses verbose `tileZoom/tileX/tileY` for the same concept (AZ-794).
2. **Permissive parsing** — missing required fields silently coerce to `0`; unknown fields silently drop. Real client typos masquerade as valid (0,0,0) requests with collision-prone `locationHash` (AZ-795 epic + AZ-796 first child).
Adopted into satellite-provider cycle 7 with the recommended ordering: shared validation infra (AZ-795) → wire-format rename (AZ-794) → first per-endpoint validator child (AZ-796). AZ-795 is structured as an Epic that ALSO ships shared infrastructure (FluentValidation + global ProblemDetails filter + `JsonSerializerOptions.UnmappedMemberHandling.Disallow`); future per-endpoint child tasks under AZ-795 to be added by parent-suite team as the public-endpoint surface is enumerated.
| Task | Title | Depends On | Points | Status |
|------|-------|-----------|--------|--------|
| AZ-794 | Inventory body fields: rename `tileZoom/tileX/tileY``z/x/y` (OSM convention) | — (coordinate release with AZ-795 / AZ-796) | 3 | Done (cycle 7) |
| AZ-795 | Strict input validation across all public endpoints (FluentValidation + ProblemDetails) — **Epic with shared-infra ship** | — (children gated on shared infra landing first) | — (epic; shared-infra estimate 58 pts; per-endpoint children ~3 pts each) | Done — shared infra shipped (cycle 7); future per-endpoint child tasks open |
| AZ-796 | Strict validation for inventory endpoint (POST /api/satellite/tiles/inventory) | AZ-795 (HARD — shared infra); coordinate with AZ-794 | 3 | Done (cycle 7) |
### Step 9 cycle 8 — Per-endpoint validation children of AZ-795 (cross-repo follow-up)
Source: cross-repo request from `gps-denied-onboard` agent (2026-05-22). After AZ-795 shipped the shared infra (FluentValidation + GlobalExceptionHandler + UnmappedMemberHandling.Disallow + ValidationEndpointFilter) and AZ-796 shipped the inventory endpoint as the first concrete child, four additional public endpoints remain silent-coercion-permissive: `POST /api/satellite/request` (region onboarding), `POST /api/satellite/route` (route creation), `POST /api/satellite/upload` (UAV metadata layer; the file-level quality gate from AZ-488 stays), `GET /api/satellite/tiles/latlon` (single-tile download). All four are queued here as cycle-8 candidates, each mirroring the AZ-796 reference implementation pattern with endpoint-specific adaptations.
**Cross-repo context**: AZ-808 + AZ-809 are blocking dependencies for gps-denied-onboard AZ-777 Phase 2 (Derkachi reference tile catalog seeding). AZ-810 is a defense-in-depth tightening for the existing AZ-488 UAV upload path. AZ-811 is the smallest item, included for completeness of the per-endpoint surface.
| Task | Title | Depends On | Points | Status |
|------|-------|-----------|--------|--------|
| AZ-808 | Strict validation for region-request endpoint (POST /api/satellite/request) | AZ-795 (HARD — shared infra); AZ-796 (reference); AZ-812 (HARD — ships first in cycle 8 per /autodev step 10 user decision 2026-05-22; AZ-808 spec field references rewrite from `latitude`/`longitude``lat`/`lon` before validator implementation starts) | 3 | To Do |
| AZ-809 | Strict validation for route-creation endpoint (POST /api/satellite/route) | AZ-795 (HARD); AZ-796 (single-DTO reference); AZ-808 (no-prior-contract reference) | 5 | To Do |
| AZ-810 | Strict validation for UAV upload metadata (POST /api/satellite/upload) | AZ-795 (HARD); AZ-796 (single-DTO reference); AZ-809 (nested per-item reference); AZ-488 (must remain green); AZ-503 (flightId semantics) | 5 | To Do |
| AZ-811 | Strict validation for lat/lon tile GET endpoint (GET /api/satellite/tiles/latlon) | AZ-795 (HARD); AZ-796 (single-DTO reference); AZ-808 (no-prior-contract reference) | 2 | To Do |
**Spec amendments (2026-05-22, post-probe)**: AZ-808 and AZ-809 specs were amended after a gps-denied-onboard black-box probe of the running producer surfaced two real silent-coercion gaps and one input/output naming asymmetry. Notable spec changes: (1) AZ-808 rule count 8 → 9 (added `Id` non-zero-Guid rule); (2) AZ-809 rule count 13 → 14 (added `Id` non-zero-Guid rule); (3) AZ-809 added AC-10 advisory documenting the input/output point-naming asymmetry on `RouteResponse.points[]`; (4) AZ-808 added field-naming coordination section pointing at AZ-812. Story-point estimates unchanged; the new rules were already implicit in the AZ-795 epic's mandate.
### Step 9 cycle 8b — Region API field-name harmonization (cross-repo follow-up)
Source: cross-repo request from `gps-denied-onboard` agent (2026-05-22). After the AZ-777 Phase 2 black-box probe of the Region API, the consumer attempted `{"lat":..,"lon":..}` against `POST /api/satellite/request` and received HTTP 400 with `UnmappedMemberHandling.Disallow` rejecting the unknown fields. The producer DTO uses verbose `latitude`/`longitude`, which is the **only** OSM-deviating coord convention left in the public API surface: the inventory endpoint already uses `z/x/y` (per AZ-794), the Route endpoint's `RoutePoint`/`GeoPoint` already use `lat`/`lon` (per existing `[JsonPropertyName]`), and the slippy-map URL uses `z/x/y`. AZ-812 closes the inconsistency by renaming Region to match.
This is a separate cycle (8b) because it's a **wire-format rename** (mirror of AZ-794) rather than a validator add (mirror of AZ-796). The two operations are surgically distinct even though they touch the same DTO.
| Task | Title | Depends On | Points | Status |
|------|-------|-----------|--------|--------|
| AZ-812 | satellite-provider: rename `RequestRegionRequest.{Latitude, Longitude}``{Lat, Lon}` (OSM convention) + harmonize cross-endpoint | — (coordinate release ordering with AZ-808) | 3 | To Do |
## Execution Order
### Step 6
1. AZ-285 (test infrastructure — all others depend on this)
2. AZ-286, AZ-287, AZ-288 (unit tests — can run in parallel)
3. AZ-289 (integration tests — depends on infra only)
4. AZ-290 (non-functional tests — depends on infra only)
### Step 8 (02-coupling-refactoring)
1. AZ-310 → AZ-311 (Phase A: route tile endpoints through ITileService)
2. AZ-312 → AZ-313 → AZ-314 (Phase B: physical split + consumer + DI rewire)
3. AZ-315 (Phase C: docs sync, must be last)
### Step 8 (03-code-quality-refactoring)
Phase 1 (Critical fixes): AZ-351 → AZ-352 → AZ-363 → AZ-356 → AZ-354 → AZ-353
Phase 2 (Correctness): AZ-359 → AZ-357 → AZ-362 (AZ-362 needs AZ-353)
Phase 3 (Structural cleanup): AZ-366 → AZ-377 → AZ-368 → AZ-367 → AZ-369 → AZ-365 → AZ-364 (folds AZ-360) — AZ-377 needs AZ-371
Phase 4 (Typing/config/tooling/polish): AZ-371 → AZ-370 → AZ-373 → AZ-374 → AZ-375 → AZ-376 → AZ-378 → AZ-379 → AZ-380 → AZ-372
### Step 9 cycle 1 (Multi-source tile storage epic AZ-483)
1. AZ-484 — Multi-source tile storage schema (foundational)
### Step 9 cycle 2
1. AZ-487 — JWT validation baseline (must merge first; AZ-488 hard-depends on it)
2. AZ-488 — UAV tile upload endpoint + 5-rule quality gate (consumer of both AZ-484 contract and AZ-487 auth)
### Step 9 cycle 3
Independent tracks — most tasks can run in parallel; the only ordering constraint is the AZ-491 → AZ-492 soft dependency for token-mint reuse.
1. AZ-495 (1 SP) — doc-folder convention. Cheapest unblocker; lands first to stop the F1 recurrence.
2. AZ-491 (3 SP) — consolidate JWT test-mint helpers. Pre-stages AZ-492 if implementer picks Option B.
3. AZ-493 (2 SP) — integration test DB-reset hook. Independent.
4. AZ-496 (2 SP) — bump AspNetCore 8.0.25. Independent.
5. AZ-492 (3 SP) — perf harness. After AZ-491 if Option B; else any time.
6. AZ-494 (2 SP) — JWT iss/aud validation. Gated on cross-team input; not blocked by other cycle-3 tasks.
### Step 9 cycle 4
Single task; coordinated cross-cutting bump.
1. AZ-500 (5 SP) — .NET 8 → .NET 10 migration. Self-contained but touches every csproj, both Dockerfiles, run-tests.sh, .woodpecker/01-test.yml, global.json, and two docs files.
### Step 9 cycle 5
Independent tracks — both can run in parallel; no ordering constraint between them. AZ-504 is a prerequisite for the cycle's Step 15 Performance Test to deliver a green PT-08 reading (and therefore for deleting the perf-cycle3 leftover); AZ-503 is the cycle's main feature (foundation half — see split note above).
1. AZ-504 (1 SP) — cheapest unblocker; lands first to clear PT-08 reporting for the cycle.
2. AZ-503 (3 SP, foundation half) — main feature; data-model + identity plumbing; cross-workspace alignment with `gps-denied-onboard` AZ-304.
3. AZ-505 (3 SP) — deferred to cycle 6; `Blocks`-linked to AZ-503.
### Step 9 cycle 6
Single task; consumes the AZ-503-foundation columns landed in cycle 5.
1. AZ-505 (3 SP) — Tile inventory endpoint + HTTP/2 + Leaflet covering index. Self-contained but produces TWO contract artifacts (new `contracts/api/tile-inventory.md` v1.0.0 + bump `contracts/data-access/tile-storage.md` v1.0.0 → v2.0.0 per architecture.md).
### Step 9 cycle 7 (AZ-794 / AZ-795 / AZ-796)
Adopted into cycle 7. Ordering:
1. AZ-795 shared infrastructure (FluentValidation + global ProblemDetails filter + `JsonSerializerOptions.UnmappedMemberHandling.Disallow`) — gates every per-endpoint child.
2. AZ-794 (rename) — lands the final wire-format names so AZ-796 validators can use them from day one.
3. AZ-796 (inventory validator) — first per-endpoint child; serves as reference implementation for sibling per-endpoint child tasks.
4. Sibling per-endpoint child tasks under AZ-795 — added by parent-suite team as they enumerate the surface from `/swagger/v1/swagger.json` (out of cycle 7 scope; future cycles).
### Step 9 cycle 8 (AZ-808 / AZ-809 / AZ-810 / AZ-811 / AZ-812)
Ordering decision recorded 2026-05-22 (`/autodev` Step 10 dirty-tree resolution): **Option 1 (AZ-812 first, then AZ-808 against final lat/lon names)** — chosen to avoid AZ-808 double-migration on contract doc + integration tests. AZ-809, AZ-810, AZ-811 are independent of AZ-812 (their DTOs already use OSM short form).
Execution order:
1. AZ-812 (3 SP) — Region DTO rename `Latitude/Longitude``Lat/Lon`. Ships first; AZ-808 depends on its outcome. Own batch (wire-format change is atomic; independent rollback target).
2. AZ-811 (2 SP) — smallest validator unblocker; closes the simplest endpoint and validates the query-param filter pattern for any future query-string endpoints. Independent of AZ-812.
3. AZ-808 (3 SP) — region-request validator written against post-rename `lat/lon`; unblocks gps-denied-onboard AZ-777 Phase 2 bbox-based seeding path. Hard-depends on AZ-812.
4. AZ-809 (5 SP) — route-creation validator; unblocks gps-denied-onboard AZ-777 Phase 2 route-based (preferred) seeding path. Independent of AZ-812.
5. AZ-810 (5 SP) — UAV upload metadata validator; defense-in-depth for AZ-488 multipart endpoint. Independent of AZ-812.
Parent-suite team may reorder steps 25 based on consumer priorities; step 1 (AZ-812) must remain first.
### Step 9 cycle 8b (AZ-812 — folded into cycle 8 ordering above)
Originally tracked as a separate cycle 8b because AZ-812 is a wire-format rename (mirror of AZ-794) rather than a validator add (mirror of AZ-796). After the /autodev Step 10 ordering decision above, cycle 8b folds into cycle 8 as step 1 of the execution order. Section retained for traceability — the cycle-8b table entry remains the authoritative spec marker for AZ-812.
## Total Effort
Step 6: 6 tasks, 17 story points
Step 8 (02-coupling-refactoring): 6 tasks, 17 story points
Step 8 (03-code-quality-refactoring): 27 tasks, ~66 story points
Step 9 cycle 1: 1 task created (AZ-484, 5 pts)
Step 9 cycle 2: 2 tasks created (AZ-487 = 2 pts, AZ-488 = 8 pts over-cap user-accepted) — total 10 pts
Step 9 cycle 3: 6 tasks created (AZ-491 = 3 pts, AZ-492 = 3 pts, AZ-493 = 2 pts, AZ-494 = 2 pts, AZ-495 = 1 pt, AZ-496 = 2 pts) — total 13 pts
Step 9 cycle 4: 1 task created (AZ-500 = 5 pts)
Step 9 cycle 5: 3 tasks tracked (AZ-503 = 3 pts foundation-half, AZ-504 = 1 pt, AZ-505 = 3 pts split-off-deferred) — 4 pts committed to cycle 5, 3 pts deferred to cycle 6
Step 9 cycle 6: 1 task scheduled (AZ-505 = 3 pts) — consumed from cycle-5 deferral
Step 9 cycle 7: 3 tasks adopted (AZ-794 = 3 pts rename, AZ-795 = epic with 58 pts shared-infra ship, AZ-796 = 3 pts first per-endpoint child) — total ~1114 pts (over the 25 pts/cycle preference; AZ-795's shared-infra ship is the heavy item). Origin: gps-denied-onboard AZ-777 Phase 1 Jetson probe (2026-05-22). Sibling per-endpoint child tasks under AZ-795 to be added in future cycles as the parent-suite team enumerates the endpoint surface.
Step 9 cycle 8: 5 tasks queued (AZ-812 = 3 pts Region DTO rename, AZ-808 = 3 pts region validator, AZ-809 = 5 pts route, AZ-810 = 5 pts UAV upload metadata, AZ-811 = 2 pts lat/lon GET) — total 18 pts across 4 per-endpoint AZ-795 children + 1 OSM-naming harmonization. Origin: cross-repo request from gps-denied-onboard agent (2026-05-22) for completeness of validation surface after AZ-795/796 landed, plus AZ-777 Phase 2 black-box probe surfacing the Region DTO as the lone OSM hold-out. Ordering: AZ-812 first (per /autodev Step 10 user decision), then AZ-808/809/810/811 (independent of each other modulo AZ-812). AZ-808 and AZ-809 specs amended 2026-05-22 post-probe to add `Id` non-zero-Guid rule + Route AC-10 input/output naming asymmetry advisory.
Step 9 cycle 8b: folded into cycle 8 as step 1 (AZ-812). Section retained in dependency table for traceability.
## Coverage Verification
| Test Spec Category | Covered By |
|-------------------|------------|
| blackbox-tests.md (BT-01..BT-12, BT-N01..BT-N05) | AZ-286, AZ-287, AZ-288, AZ-289 |
| performance-tests.md (PT-01..PT-06) | AZ-290 |
| resilience-tests.md (RS-01..RS-06) | AZ-290 |
| security-tests.md (SEC-01..SEC-04) | AZ-290 |
| resource-limit-tests.md (RL-01..RL-04) | AZ-290 |
| traceability-matrix.md (100% AC coverage) | All tasks combined |