# Runner registration legacy iop boundary split

## Metadata

- Status: planned
- Task group: `control_plane_phase_exit_followups`
- Plan id: `cloud-G06`
- Review stub: `CODE_REVIEW-cloud-G06.md`
- Roadmap target: first phase exit follow-up for `agent-roadmap/phase/independent-control-plane/PHASE.md`

## Problem

The default runner path has migrated toward OTO Server HTTP registration, but production runner code still exposes and imports legacy iop Edge registration concepts.

Examples:

- `apps/runner/lib/oto/agent/edge_registration_client.dart` contains both OTO Server HTTP clients and legacy proto-socket Edge registration.
- `apps/runner/lib/oto/agent/agent_runner.dart` depends on types named around `EdgeAgentSession`.
- The legacy iop smoke now runs only when `OTO_ENABLE_LEGACY_IOP_SMOKE=1`, but the production import boundary still makes legacy iop appear first-class.

This makes the first phase hard to close because "independent control plane" evidence is mixed with legacy Edge compatibility code.

## Rules read

- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/project/domain/agent/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/agent-smoke.md`

## Current evidence

- `apps/runner/lib/oto/agent/edge_registration_client.dart`
  - Contains `OtoServerRegistrationClient`, `OtoServerJobClient`, `RegistrationClient`, `EdgeRegistrationClient`, and session/result types together.
  - Imports legacy iop generated proto/proto-socket packages.
- `apps/runner/lib/oto/agent/agent_runner.dart`
  - The default runner imports `edge_registration_client.dart`.
  - The default runner works against the OTO Server path but keeps legacy naming in its interface.
- `apps/runner/test/oto_agent_registration_test.dart`
  - Already has broad coverage for OTO Server registration/job client behavior and fake runner sessions.
- `apps/runner/test/oto_iop_connection_smoke_test.dart`
  - Is now opt-in via `OTO_ENABLE_LEGACY_IOP_SMOKE=1`.

## Scope

Separate the production OTO Server runner path from legacy iop Edge compatibility code without removing the legacy smoke itself.

Do not change protocol behavior, generated protobuf files, or enrollment semantics in this task.

## Proposed implementation

1. Introduce a neutral runner registration boundary.
   - Move shared OTO Server types to a neutral file, for example `registration_client.dart`.
   - Prefer names like `AgentSession`, `RegistrationClient`, `OtoServerRegistrationClient`, and `OtoServerJobClient`.
   - Keep public API changes localized to runner internals and tests.

2. Isolate legacy iop Edge code.
   - Keep `EdgeRegistrationClient` and proto-socket-only imports in a legacy-specific file or clearly marked compatibility section.
   - Ensure normal runner imports do not pull legacy iop generated proto/proto-socket code.
   - Keep `oto_iop_connection_smoke_test.dart` importing the legacy path explicitly.

3. Update default runner code and tests.
   - `DefaultAgentRunner` should depend on the neutral interface/session type.
   - Fake clients in `oto_agent_registration_test.dart` should use neutral naming.
   - Existing OTO Server registration/job tests should remain behaviorally equivalent.

4. Update documentation only where it names the default path.
   - Keep legacy smoke instructions opt-in.
   - Do not add broad migration docs unless needed to explain the new boundary.

## Expected files

- `apps/runner/lib/oto/agent/edge_registration_client.dart`
- `apps/runner/lib/oto/agent/agent_runner.dart`
- Possible new or renamed file under `apps/runner/lib/oto/agent/`
- `apps/runner/test/oto_agent_registration_test.dart`
- `apps/runner/test/oto_iop_connection_smoke_test.dart`
- Possibly `apps/runner/test/oto_agent_migration_plan_test.dart`

## Verification

- `cd apps/runner && dart analyze`
- `cd apps/runner && dart test test/oto_agent_registration_test.dart`
- `cd apps/runner && dart test test/oto_agent_migration_plan_test.dart`
- `cd apps/runner && dart test`

## Risks

- Renaming exported types may break hidden or downstream imports.
- A file split can accidentally remove legacy smoke coverage if imports are not explicit.
- Keeping compatibility aliases may be useful for one transition step, but they should not hide the default production boundary.

## Done when

- The default runner path no longer imports legacy iop proto/proto-socket code.
- Legacy iop smoke remains available only as explicit migration evidence.
- Runner analysis and tests pass locally.
