# Batch 44 — Implementation Plan

**Date drafted**: 2026-05-13
**Drafted in conversation**: `/autodev` session, prior to batch 44 start
**Status**: PLAN ONLY — do NOT start implementation until next `/autodev` invocation.
**Cycle**: 1

## Why a plan instead of just doing it

Two architectural decisions converged this batch and need to be executed as ONE atomic refactor; splitting them would leave the codebase in a transiently inconsistent state.

1. **C11's internal flight-state gate violates SRP.** AZ-317 placed an ON_GROUND check inside `HttpTileUploader`. "Upload bytes" and "decide when uploading is safe" are different responsibilities; the latter is an orchestrator-level policy decision that belongs in C12.
2. **The C12 package name `c12_operator_tooling` understates its role.** It owns orchestrators (build-cache, post-landing upload, operator-reloc) — "tooling" reads as a grab-bag. Rename: `c12_operator_tooling` → `c12_operator_orchestrator`.

## Decision recap (from the prior conversation)

- The on-ground signal will be the **presence of the `flight_footer` FDR record** (kind already registered in `KNOWN_PAYLOAD_KEYS`; producer is C13's AZ-292, shipped) with `clean_shutdown == True`. No new FDR record kind needs to be defined. No 30-second threshold. No dependency on E-C8.
- C11's `HttpTileUploader` becomes a dumb pipe: read pending from C6 → POST to ingest → mark uploaded. The flight-state-gating Protocol/Gate/error are deleted from C11.
- C12's `PostLandingUploadOrchestrator` (AZ-329) performs the footer check; if the footer for `flight_id` exists and `clean_shutdown == True`, it calls `tile_uploader.upload_pending_tiles(UploadRequest(flight_id=...))`. Otherwise it refuses with `FlightStateNotConfirmedError`.

## Tasks delivered in batch 44

| Task | Type | Complexity | Notes |
|------|------|-----------|-------|
| **Rename** (no ticket, hygiene) | refactor | ~2pt | `c12_operator_tooling` → `c12_operator_orchestrator`. ~57 files touched. |
| **C11 gate removal** (supersedes AZ-317, partial revert of AZ-319) | refactor | ~3pt | Create new tracker ticket `AZ-XXX` (or reopen AZ-317 marked superseded). |
| **AZ-329** (rewritten) | feature | 3pt | `PostLandingUploadOrchestrator` against `flight_footer`. |
| **AZ-330** | feature | 3pt | `OperatorReLocService` — unchanged from existing spec. |
| **Total** | | **~11pt** | Within batch cap (4 tasks; 20-point budget). |

## Phase plan (execute in this order)

### Phase A — Component rename (`c12_operator_tooling` → `c12_operator_orchestrator`)

**Goal**: one atomic rename with no behavioural change. Done before any code edits so subsequent phases work in the new namespace.

**Source moves**:

- `src/gps_denied_onboard/components/c12_operator_tooling/` → `src/gps_denied_onboard/components/c12_operator_orchestrator/` (recursive `git mv`).
- `tests/unit/c12_operator_tooling/` → `tests/unit/c12_operator_orchestrator/` (recursive `git mv`).

**Symbol updates** (kept as-is — only the package path changes):

- Class names: `C12Config`, `C12CompanionConfig`, `C12BuildCacheConfig`, `OperatorToolServices` — KEEP. The `C12` prefix is the component number (12), not the word "tooling". `OperatorToolServices` stays because the CLI binary itself is unchanged.
- Logger names: `c12_operator_tooling` → `c12_operator_orchestrator` (all occurrences in `c12_factory.py` and module-level `logging.getLogger("c12_operator_tooling.*")` calls).
- Config-block slug: `register_component_block("c12_operator_tooling", C12Config)` → `register_component_block("c12_operator_orchestrator", C12Config)`. **Note**: this is a config-schema-key change; the deployment env will need to update YAML/JSON config files that key on this slug. List of changes goes into Phase F.
- CMake flag: `BUILD_C12_OPERATOR_TOOLING` → `BUILD_C12_OPERATOR_ORCHESTRATOR` in `cmake/build_options.cmake`.
- pyproject.toml console script: `operator-tool = "gps_denied_onboard.components.c12_operator_tooling.cli:cli"` → `... c12_operator_orchestrator.cli:cli`. **KEEP the binary name `operator-tool`** for operator UX continuity; this is the only ambiguity — see Open Questions.

**Import updates** (mechanical replace across the workspace):

```
from gps_denied_onboard.components.c12_operator_tooling     →
from gps_denied_onboard.components.c12_operator_orchestrator
```

Applies to: c12 source (~30 files), c12 tests (~12 files), `runtime_root/c12_factory.py`, `runtime_root/__init__.py`, `tests/unit/test_ac1_scaffold_layout.py`, `tests/unit/test_ac3_compose_files.py`.

**Docs / config updates** (deferred to Phase F so renaming stays code-only here):

- `_docs/02_document/module-layout.md` — section heading, `Owns`/`Imports from`/`Consumed by` paths.
- `_docs/02_document/components/13_c12_operator_tooling/` → `13_c12_operator_orchestrator/` (directory rename).
- `_docs/02_document/contracts/c12_operator_tooling/` → `c12_operator_orchestrator/` (directory rename).
- `_docs/02_document/epics.md`: "E-C12 Operator Pre-flight Tooling" → "E-C12 Operator Pre-flight Orchestrator".
- `_docs/02_document/architecture.md`, `FINAL_report.md`, `glossary.md`, `data_model.md`, `system-flows.md`, `deployment/*`: all references.
- Task specs: `AZ-326`, `AZ-327`, `AZ-328`, `AZ-329`, `AZ-330`, `AZ-489` `Component:` field; same for `AZ-401`, `AZ-403` references.
- Already-completed batch reports and cumulative reviews — leave as historical record (do NOT rewrite history).

**Verification after Phase A**:

- `git grep c12_operator_tooling -- ':!_docs/03_implementation/batch_*' ':!_docs/03_implementation/cumulative_review_*' ':!_docs/03_implementation/reviews/*'` returns zero hits.
- `pytest tests/unit/c12_operator_orchestrator -q` passes (no behavioural change, just the rename).
- Full unit suite still **1522 passed, 80 skipped** (same as batch 43 baseline).

### Phase B — Remove C11 internal flight-state gate

**Files to delete**:

- `src/gps_denied_onboard/components/c11_tile_manager/flight_state_gate.py`
- `tests/unit/c11_tile_manager/test_flight_state_gate.py` (or `test_az317_flight_state_gate.py` — locate the actual filename).

**Files to modify**:

- `src/gps_denied_onboard/components/c11_tile_manager/interface.py`:
  - Remove `FlightStateSource` Protocol class.
  - Update `__all__`.
  - Update module docstring.
- `src/gps_denied_onboard/components/c11_tile_manager/errors.py`:
  - Remove `FlightStateNotOnGroundError` class + `__all__` entry + docstring mention.
- `src/gps_denied_onboard/components/c11_tile_manager/_types.py`:
  - Audit `FlightStateSignal` usage. If only the gate referenced it → delete. If `HttpTileUploader` still emits it in FDR records or elsewhere → keep as a closed enum for `confirm_flight_state()` return shape, BUT note that `TileUploader.confirm_flight_state()` is itself going away (see next bullet).
  - The `confirm_flight_state` method on `TileUploader` Protocol exists per `interface.py` — this method only makes sense if there's a gate. Decision: **drop it**. Remove from Protocol, from `HttpTileUploader`, from any test fakes.
- `src/gps_denied_onboard/components/c11_tile_manager/tile_uploader.py`:
  - Remove `FlightStateGate` import.
  - Remove `flight_state_gate: FlightStateGate` constructor parameter.
  - Remove the `confirm_on_ground()` call at the top of `upload_pending_tiles`.
  - Remove the `_LOG_KIND_REFUSED` / pass-through `confirm_flight_state` method.
  - Re-test all upload paths now run without the gate.
- `src/gps_denied_onboard/components/c11_tile_manager/__init__.py`:
  - Remove `FlightStateGate`, `FlightStateNotOnGroundError`, `FlightStateSource` from imports + `__all__`.
  - Keep `FlightStateSignal` only if `confirm_flight_state` survives; otherwise remove.
- `src/gps_denied_onboard/components/c11_tile_manager/idempotent_retry.py`:
  - Audit for `FlightStateGate` / `FlightStateNotOnGroundError` references. The retry decorator wraps `TileUploader`; if it catches the gate error it must stop.
- `src/gps_denied_onboard/runtime_root/c11_factory.py`:
  - Remove `build_flight_state_gate(*, source: FlightStateSource) -> FlightStateGate`.
  - Remove `flight_state_gate=` from `build_tile_uploader(...)`.
  - Remove `FlightStateSource` from imports + module docstring.
- `tests/unit/c11_tile_manager/test_tile_uploader.py`:
  - Remove all test cases that mock the gate / assert `confirm_on_ground` was called / assert `FlightStateNotOnGroundError` semantics.
  - Replace any fixture that injects a fake gate with a no-gate construction.
- `tests/unit/c11_tile_manager/test_idempotent_retry.py`:
  - Adjust if any test cared about the gate's error class.
- `tests/unit/c11_tile_manager/test_protocol_conformance.py`:
  - Drop `FlightStateSource` conformance assertions.

**Files to LEAVE ALONE** (these reference the gate in completed task specs / batch reports — historical record):

- `_docs/02_tasks/done/AZ-317_c11_flight_state_gate.md` — leave the spec as-is; mark `Status: superseded by batch 44 SRP refactor` in a one-line annotation at the top.
- `_docs/02_tasks/done/AZ-319_c11_tile_uploader.md` — leave; the relevant gate text is now historical.
- `_docs/03_implementation/batch_*_report.md`, `cumulative_review_*` — historical, untouched.
- `_docs/03_implementation/reviews/batch_38_review.md`, `batch_39_review.md` — historical.

**Contract document update** (Phase F covers):

- `_docs/02_document/contracts/c11_tilemanager/tile_uploader.md` v1.0.0 → v2.0.0. Remove the gate clauses, the `confirm_flight_state` method row, `FlightStateNotOnGroundError`.

**Verification after Phase B**:

- `git grep -E 'FlightStateGate|FlightStateNotOnGroundError|FlightStateSource' src/ tests/` returns zero hits.
- `pytest tests/unit/c11_tile_manager -q` passes.
- Full unit suite passes (count will drop by ~10–15 tests; document the new baseline in the batch 44 report).

### Phase C — AZ-329 task spec rewrite

Rewrite `_docs/02_tasks/todo/AZ-329_c12_post_landing_upload.md` from scratch around the new design. Outline:

- **Description**: `PostLandingUploadOrchestrator` reads the C13 FDR for `flight_id`, locates the `flight_footer` record (the C13 writer emits exactly one per flight on clean shutdown), and if found with `clean_shutdown == True`, calls `tile_uploader.upload_pending_tiles(UploadRequest(flight_id=..., ...))`. Footer absent → flight didn't terminate cleanly → refuse. Footer present but `clean_shutdown == False` → operator inspects manually → refuse.
- **Dependencies**: `AZ-326`, `AZ-319` (post-gate-removal `TileUploader`), `AZ-272` (FdrRecord schema; `flight_footer` kind already there), `AZ-292` (C13 footer producer; already shipped), `AZ-263`, `AZ-269`, `AZ-266`.
- **DTOs** (in renamed `c12_operator_orchestrator/_types.py`):
  - `PostLandingUploadRequest(flight_id: UUID, satellite_provider_url: str, batch_size: int = 50)`.
  - Reuses C11's `UploadBatchReport` via the AZ-507 consumer-side cut pattern (mirror locally as `UploadBatchReportCut`).
- **Reader** (`fdr_footer_reader.py`): `FdrFooterReader` Protocol + `LocalFdrFooterReader` concrete. Iterates `<fdr_root>/<flight_id>/segment_*.fdr` newest-to-oldest, returns the first `flight_footer` record found (or `None`). Streaming — never loads full segments into memory.
- **Errors** (`c12_operator_orchestrator/errors.py`):
  - `FlightStateNotConfirmedError(Exception)` with `flight_id: str`, `not_confirmed_reason: Literal["flight_id_not_found", "footer_missing", "unclean_shutdown", "fdr_unreadable"]`, `remediation: str`.
- **Acceptance criteria** (~8 ACs, all unit-testable via fake `FdrFooterReader` + fake `TileUploader`):
  - AC-1: footer present + `clean_shutdown=True` → upload invoked, returns `UploadBatchReport`.
  - AC-2: footer absent → `FlightStateNotConfirmedError("footer_missing")`.
  - AC-3: footer present + `clean_shutdown=False` → `FlightStateNotConfirmedError("unclean_shutdown")`.
  - AC-4: `<fdr_root>/<flight_id>/` does not exist → `FlightStateNotConfirmedError("flight_id_not_found")`.
  - AC-5: FDR parse error mid-stream → `FlightStateNotConfirmedError("fdr_unreadable: ...")`.
  - AC-6: footer search starts from newest segment (don't scan all segments if the latest has the footer).
  - AC-7: Returns C11's `UploadBatchReport` unchanged on success (passthrough).
  - AC-8: api_key in `PostLandingUploadRequest` is `SecretStr`; REDACTED in logs.
  - AC-9: integration test with a real FDR fixture that contains a clean-shutdown footer.
  - AC-10: integration test with a real FDR fixture that contains a `clean_shutdown=False` footer.
- **Non-Functional Requirements**:
  - Footer read completes ≤ 1 s wall-clock even for 64 GB of FDR segments (newest-segment-first short-circuit).
  - Memory peak ≤ 50 MB (streaming reader).
- **Excluded explicitly**:
  - Any `flight_state.tick` / `state.tick` payload-field reading.
  - The 30-second contiguous-ON_GROUND threshold.
  - A "force-upload" override (intentionally not supported).

Update `_docs/02_document/components/13_c12_operator_orchestrator/tests.md` C12-IT-03 to match (footer-based test, drop the 30s assertion).

### Phase D — AZ-329 implementation

In renamed `c12_operator_orchestrator/`:

- **New files**:
  - `post_landing_upload.py` — `PostLandingUploadOrchestrator` class + the AZ-507 consumer-side cut (`TileUploaderCut` Protocol matching C11's `upload_pending_tiles(UploadRequest)`).
  - `fdr_footer_reader.py` — Protocol + concrete `LocalFdrFooterReader`.
- **Modified files**:
  - `_types.py` — `PostLandingUploadRequest`, `UploadBatchReportCut`.
  - `errors.py` — `FlightStateNotConfirmedError`.
  - `config.py` — extend `C12Config` with `post_landing: C12PostLandingConfig(fdr_root: Path)`.
  - `cli.py` — `upload-pending` subcommand (already a placeholder in `cli.py` per the AZ-326 ship); wire to `services.post_landing_upload_orchestrator`. Map `FlightStateNotConfirmedError` → `EXIT_FLIGHT_STATE_NOT_CONFIRMED` (already defined).
  - `__init__.py` — re-export new public symbols.
- **Composition root** (`runtime_root/c12_factory.py`):
  - Add `build_post_landing_upload_orchestrator(config, *, tile_uploader: TileUploaderCut) -> PostLandingUploadOrchestrator`.
  - Extend `OperatorToolServices` with `post_landing_upload_orchestrator: PostLandingUploadOrchestrator | None = None`.
  - Extend `build_operator_tool(...)` aggregator: when a `tile_uploader` is provided, build and wire.
- **Tests** (`tests/unit/c12_operator_orchestrator/`):
  - `test_post_landing_upload_orchestrator.py` — covers AC-1 through AC-8 with fakes.
  - `test_fdr_footer_reader.py` — covers AC-5 + the streaming NFR.
  - Integration test fixtures for AC-9 + AC-10: scripted FDR segments with / without `clean_shutdown=True` footer. Live under `tests/fixtures/c12_orchestrator/fdr/` or similar.

### Phase E — AZ-330 implementation

Implement per existing `_docs/02_tasks/todo/AZ-330_c12_operator_reloc_service.md`, adjusted only for the renamed package. Re-use `LatLonAlt` from `src/gps_denied_onboard/_types/geo.py` (the shared definition exists — AZ-330's risk-mitigation note flagged this; we confirmed it during the prior session).

- **New files** (in `c12_operator_orchestrator/`):
  - `operator_reloc_service.py` — `OperatorReLocService` class.
  - `operator_command_transport.py` — `OperatorCommandTransport` Protocol.
- **Modified files**:
  - `_types.py` — `ReLocHint` (consume shared `LatLonAlt`).
  - `errors.py` — `GcsLinkError`.
  - `cli.py` — wire `reloc-confirm` subcommand.
  - `__init__.py` — re-exports.
- **Composition root**:
  - `build_operator_reloc_service(...)` factory.
  - Extend `OperatorToolServices` with `operator_reloc_service: OperatorReLocService`.
- **Tests**: 10 ACs per the existing spec — all unit-testable via fake `OperatorCommandTransport`.
- **Contract document**: `_docs/02_document/contracts/c12_operator_orchestrator/operator_command_transport.md` (already exists at the old path — gets moved during Phase A).

### Phase F — Documentation updates

- `_docs/02_document/module-layout.md`:
  - Section heading and all paths: `c12_operator_tooling` → `c12_operator_orchestrator`.
  - C11 component section: drop `FlightStateSource`, `FlightStateGate` from the Public API + Internal lists.
- `_docs/02_document/components/13_c12_operator_orchestrator/description.md`:
  - Rewrite the C12 § 2 row for `trigger_post_landing_upload` around the footer-based design.
  - Remove any reference to a 30-second threshold.
  - Update the component name in the title.
- `_docs/02_document/components/13_c12_operator_orchestrator/tests.md`:
  - C12-IT-03 rewritten around `flight_footer` (no `FlightStateSignal`, no 30-second window).
- `_docs/02_document/components/12_c11_tilemanager/description.md`:
  - Remove the AZ-317 gate description; C11 is now a dumb pipe.
- `_docs/02_document/components/12_c11_tilemanager/tests.md`:
  - Remove gate-related tests.
- `_docs/02_document/contracts/c11_tilemanager/tile_uploader.md`:
  - v1.0.0 → v2.0.0. Drop gate clauses, `confirm_flight_state`, `FlightStateNotOnGroundError`.
  - Add migration note pointing to batch 44.
- `_docs/02_document/contracts/c12_operator_orchestrator/` — directory move (Phase A) + content tweaks.
- `_docs/02_document/architecture.md`:
  - Update C12 component name in the system overview.
  - Update C11 component description (no internal gate).
- `_docs/02_document/glossary.md`:
  - "operator tooling" → "operator orchestrator" (semantic).
- `_docs/02_document/epics.md`:
  - E-C12 epic name updated.
- `_docs/02_document/FINAL_report.md`:
  - Component table update.
- `_docs/02_document/deployment/*`:
  - `containerization.md`, `environment_strategy.md`, `ci_cd_pipeline.md`, `deployment_procedures.md`, `observability.md` — replace package name references.
- `README.md`: any references to `operator_tooling`.
- `pyproject.toml`: package path in entry-point + any tool config keys.
- `cmake/build_options.cmake`: `BUILD_C12_OPERATOR_TOOLING` → `BUILD_C12_OPERATOR_ORCHESTRATOR`.
- `.github/workflows/release.yml`: any references.
- `docker-compose.yml`, `docker-compose.test.yml`: service / image references.

### Phase G — Tracker (Jira) updates

- **AZ-317** (`C11 Flight-State Gate`): transition to a "Superseded" or "Won't Do" status with a comment linking to batch 44. Spec stays in `_docs/02_tasks/done/` annotated.
- **AZ-319** (`C11 TileUploader`): add a comment noting batch 44 removed the gate dependency; the AZ-319 ticket itself stays Done.
- **AZ-329**: keep ticket; comment with the design pivot; replace spec in `_docs/02_tasks/todo/` and resync description in Jira.
- **AZ-330**: comment with the package-rename note; nothing else changes.
- **New ticket** for the C11 gate revert (suggested name: "C11 SRP correction — remove internal flight-state gate; AC-NEW-7 enforcement moves to C12"). Component: `c11_tile_manager`. Epic: `AZ-251` (E-C11). Complexity: 3pt.
- **New ticket** for the C12 rename (suggested name: "Rename c12_operator_tooling → c12_operator_orchestrator"). Component: `c12_operator_orchestrator`. Epic: `AZ-253` (E-C12). Complexity: 2pt.
- **Epic AZ-253** rename: "E-C12 Operator Pre-flight Tooling" → "E-C12 Operator Pre-flight Orchestrator".
- Update `_docs/02_tasks/_dependencies_table.md`:
  - Add the two new tracker IDs to the table.
  - The C11 dependency on AZ-317 (if any task depends on the gate) goes away — none should, since AZ-317 was self-contained.
  - Increment task / point counts.

### Phase H — Tests, code review, commit

1. **Full repo unit suite**: must return to a clean green baseline. Document the new pass count in the batch 44 report (expected slightly lower than 1522 due to deleted gate tests + slightly higher due to new AZ-329 / AZ-330 tests; net ~+15).
2. **Targeted suites** at each phase boundary:
   - Phase A end: `pytest tests/unit/c12_operator_orchestrator -q`
   - Phase B end: `pytest tests/unit/c11_tile_manager -q`
   - Phase D end: `pytest tests/unit/c12_operator_orchestrator/test_post_landing_upload_orchestrator.py -v`
   - Phase E end: `pytest tests/unit/c12_operator_orchestrator/test_operator_reloc_service.py -v`
3. **AC coverage verification** for AZ-329 + AZ-330 per the implement skill's Step 8.
4. **Code review** (`/code-review`) on the full batch diff. Architecture findings expected (cross-task consistency: c11 and c12 cuts) — these escalate per the auto-fix matrix, never auto-fix.
5. **Single commit** with subject:
   ```
   [AZ-329] [AZ-330] [AZ-XXX-C11-revert] [AZ-YYY-c12-rename] C12 orchestrator rename + C11 gate removal + post-landing upload + reloc service (Batch 44)
   ```
   (Subject is over 72 chars — split into subject + body per `.cursor/rules/git-workflow.mdc`. Subject: `[Batch 44] C12 rename + C11 gate removal + post-landing upload + reloc service`. Body lists tracker IDs.)
6. **Batch 44 report**: `_docs/03_implementation/batch_44_cycle1_report.md` per the standard template, with sections for each phase.
7. **NO cumulative review this batch** — cumulative review fires at batch 45 (40-42, then 43-45). Batch 44 is mid-window. Per the implement skill Step 14.5 (K=3), the next cumulative review covers 43-45.

## File inventory snapshot (as of 2026-05-13)

### Files referencing `c12_operator_tooling` to be touched in Phase A (rename) + Phase F (docs)

- **Source / tests (renamed in Phase A)**: ~38 files under `src/gps_denied_onboard/components/c12_operator_tooling/`, `src/gps_denied_onboard/runtime_root/c12_factory.py`, `tests/unit/c12_operator_tooling/`, `tests/unit/test_ac1_scaffold_layout.py`, `tests/unit/test_ac3_compose_files.py`, `pyproject.toml`, `src/gps_denied_onboard/runtime_root/__init__.py`, `src/gps_denied_onboard/healthcheck.py`.
- **Docs (updated in Phase F)**: `_docs/02_document/module-layout.md`, `_docs/02_document/components/13_c12_operator_tooling/{description,tests}.md` (directory rename), `_docs/02_document/contracts/c12_operator_tooling/*` (directory rename), `_docs/02_document/architecture.md`, `_docs/02_document/FINAL_report.md`, `_docs/02_document/epics.md`, `_docs/02_document/glossary.md`, `_docs/02_document/data_model.md`, `_docs/02_document/system-flows.md`, `_docs/02_document/deployment/*`.
- **Task specs (updated in Phase F)**: `_docs/02_tasks/done/AZ-{326,327,328,489}_*.md`, `_docs/02_tasks/todo/AZ-{329,330,401,403}_*.md`, `_docs/02_tasks/done/AZ-263_initial_structure.md`.
- **Infra**: `docker-compose.yml`, `docker-compose.test.yml`, `cmake/build_options.cmake`, `.github/workflows/release.yml`, `README.md`.
- **Historical** (leave alone): `_docs/03_implementation/batch_21_*.md`, `batch_42_*.md`, `batch_43_*.md`, `cumulative_review_batches_40-42_*.md` and any earlier batch reports.

### Files referencing `FlightStateGate` / `FlightStateNotOnGroundError` / `FlightStateSource` (Phase B)

- `src/gps_denied_onboard/components/c11_tile_manager/{interface.py, errors.py, _types.py, tile_uploader.py, idempotent_retry.py, flight_state_gate.py, __init__.py}`
- `src/gps_denied_onboard/runtime_root/c11_factory.py`
- `tests/unit/c11_tile_manager/{test_flight_state_gate.py, test_tile_uploader.py, test_idempotent_retry.py, test_protocol_conformance.py}`
- Docs: `_docs/02_document/contracts/c11_tilemanager/tile_uploader.md` (v1.0.0 → v2.0.0), `_docs/02_document/components/12_c11_tilemanager/{description,tests}.md`, `_docs/02_document/components/13_c12_operator_tooling/{description,tests}.md`, `_docs/02_document/architecture.md`, `_docs/02_document/module-layout.md`, `_docs/02_tasks/done/AZ-317_*.md` (annotate as superseded).

## Open questions for the next session

These should be resolved BEFORE Phase A starts:

1. **CLI binary name**: keep `operator-tool` or rename to `operator-orchestrator`? Default proposal: **keep `operator-tool`** — operator-facing UX continuity matters more than internal package consistency. The user said "rename C12" — the C12 *package* — not "rename the CLI". If user wants both, change `pyproject.toml` script entry too.
2. **Internal class name `OperatorToolServices`**: keep or rename to `OperatorOrchestratorServices`? Default proposal: **rename** (it's internal; renaming costs nothing and stays consistent).
3. **AZ-317 spec file disposition**: leave annotated in `_docs/02_tasks/done/AZ-317_c11_flight_state_gate.md`, OR move to a new `_docs/02_tasks/superseded/` folder? Default proposal: annotate in place. Don't introduce a new lifecycle folder for one task.
4. **Whether AZ-318's `PerFlightKeyManager` lifetime hooks depend on flight-state**: low-likelihood but verify in Phase B before deleting `FlightStateSignal` from `_types.py`.
5. **C8 ↔ C11 relationship**: C8 was producing flight-state intended for C11's gate. Now that the gate is gone, does C8 still need to emit flight-state to anywhere? Check AZ-391 outputs; flight-state may still be used by C5 (state estimator) for sensor-fusion gating — independent of C11. Most likely C8's flight-state output stays and only C11 stops consuming it.

## Acceptance criteria for batch 44 completion

Batch 44 is complete when ALL of the following hold:

- [ ] `git grep c12_operator_tooling -- src/ tests/ cmake/ pyproject.toml docker-compose*.yml .github/` returns zero hits (excluding historical batch reports).
- [ ] `git grep -E 'FlightStateGate|FlightStateNotOnGroundError|FlightStateSource' src/ tests/` returns zero hits.
- [ ] `c12_operator_orchestrator` package exists with all prior `c12_operator_tooling` contents + AZ-329 + AZ-330 additions.
- [ ] `pytest tests/ -q` is green (count documented in batch report).
- [ ] AZ-329 + AZ-330 ACs all have direct test coverage (AC coverage verification step).
- [ ] `/code-review` on the batch diff returns PASS or PASS_WITH_WARNINGS (Architecture findings escalate per the auto-fix matrix).
- [ ] `_docs/02_tasks/todo/AZ-329_c12_post_landing_upload.md` rewritten and moved to `_docs/02_tasks/done/`.
- [ ] `_docs/02_tasks/todo/AZ-330_c12_operator_reloc_service.md` moved to `_docs/02_tasks/done/`.
- [ ] Jira tickets transitioned: AZ-317 superseded; AZ-329 + AZ-330 + new C11-revert + new C12-rename → In Testing.
- [ ] Single commit on `dev` branch; user asked whether to push.
- [ ] `_docs/03_implementation/batch_44_cycle1_report.md` written.
- [ ] `_docs/_autodev_state.md` updated: `last_completed_batch: 44`, `in_flight_batch: null`, `in_flight_tasks: null`, `sub_step.phase: 2`, `name: detect-progress`, `detail: ""`.

## Recovery / abort guidance

If Phase A breaks more than expected (e.g., test_ac1_scaffold_layout / test_ac3_compose_files hardcode the package path in surprising ways): pause and ask the user before patching test fixtures. Test scaffolds may encode invariants that the rename invalidates by design.

If Phase B reveals that something outside C11 (a c4/c5/c8 wiring, or a contract conformance test) depends on `FlightStateSource` for reasons unrelated to upload gating: pause and ask. C11's `FlightStateSource` was supposed to be a C11-internal Protocol — but the C11 `_types.py` declares `FlightStateSignal` as a closed enum that other components may have started consuming.

## Pointer for the next `/autodev` invocation

Re-read this plan first. Execute phases A → B → C → D → E → F → G → H in order, with the verification at each phase boundary. Do not skip Phase A's verification — every subsequent phase assumes `c12_operator_tooling` is a dead string. If any verification fails, stop and ask the user.
