# Feature: Chunk Matching Coordination

## Name
Chunk Matching Coordination

## Description
Operations related to the chunk matching workflow including readiness checks, matching status tracking, anchoring, and merging. This feature implements transactional integrity with F10 Factor Graph Optimizer using "Check-Act" pattern: F10 is called first, and only on success is internal state updated. Critical for the Atlas multi-map architecture where chunks are matched and merged into the global trajectory.

## Component APIs Implemented

### `is_chunk_ready_for_matching(chunk_id: str) -> bool`
Checks if chunk meets criteria for satellite matching attempt.
- Min frames: >= 5 (configurable)
- Max frames: <= 20 (configurable)
- Not already matched (status != "anchored" or "merged")

### `get_chunks_for_matching(flight_id: str) -> List[ChunkHandle]`
Retrieves all unanchored chunks ready for matching.
- Filters by flight_id
- Returns chunks with matching_status="unanchored" and is_ready_for_matching=True

### `mark_chunk_matching(chunk_id: str) -> bool`
Marks chunk as currently being matched.
- Updates matching_status to "matching"
- Prevents duplicate matching attempts

### `mark_chunk_anchored(chunk_id: str, frame_id: int, gps: GPSPoint) -> bool`
Anchors chunk to GPS coordinate after successful satellite matching.
- **Transactional**: Calls F10.add_chunk_anchor() first
- On success: Updates has_anchor, anchor_frame_id, anchor_gps, matching_status="anchored"
- On failure: Returns False, no state change

### `merge_chunks(main_chunk_id: str, new_chunk_id: str, transform: Sim3Transform) -> bool`
Merges new_chunk INTO main_chunk using Sim(3) transformation.
- Resolves flight_id from internal ChunkHandle for main_chunk_id
- **Transactional**: Calls F10.merge_chunk_subgraphs() first
- On success: new_chunk marked "merged" and deactivated, main_chunk extended
- On failure: Returns False, no state change

## External Tools and Services
- **F10 Factor Graph Optimizer**: `add_chunk_anchor()`, `merge_chunk_subgraphs()`
- **F03 Flight Database**: `save_chunk_state()` (after merge)

## Internal Methods

### `_check_matching_criteria(chunk_id: str) -> bool`
Validates chunk meets all matching readiness criteria.

### `_get_matching_status(chunk_id: str) -> str`
Returns current matching_status from ChunkHandle.

### `_update_anchor_state(chunk_id: str, frame_id: int, gps: GPSPoint)`
Updates ChunkHandle with anchor information after successful F10 call.

### `_mark_chunk_merged(chunk_id: str)`
Updates new_chunk state after successful merge operation.

## Unit Tests

### Test: is_chunk_ready_min_frames
- Create chunk with 3 frames
- Assert is_chunk_ready_for_matching() returns False
- Add 2 more frames (total 5)
- Assert is_chunk_ready_for_matching() returns True

### Test: is_chunk_ready_max_frames
- Create chunk with 21 frames
- Assert is_chunk_ready_for_matching() returns False

### Test: is_chunk_ready_already_anchored
- Create chunk, mark as anchored
- Assert is_chunk_ready_for_matching() returns False

### Test: get_chunks_for_matching_filters_correctly
- Create 3 chunks: unanchored+ready, anchored, unanchored+not_ready
- Assert get_chunks_for_matching() returns only first chunk

### Test: get_chunks_for_matching_filters_by_flight
- Create chunks for flight_A and flight_B
- Assert get_chunks_for_matching(flight_A) returns only flight_A chunks

### Test: mark_chunk_matching_updates_status
- Create chunk
- Call mark_chunk_matching()
- Assert matching_status="matching"

### Test: mark_chunk_anchored_transactional_success
- Create chunk
- Mock F10.add_chunk_anchor() returns success
- Call mark_chunk_anchored()
- Assert returns True
- Assert has_anchor=True, anchor_gps set, matching_status="anchored"

### Test: mark_chunk_anchored_transactional_failure
- Create chunk
- Mock F10.add_chunk_anchor() returns failure
- Call mark_chunk_anchored()
- Assert returns False
- Assert has_anchor=False (no state change)

### Test: merge_chunks_transactional_success
- Create main_chunk and new_chunk
- Mock F10.merge_chunk_subgraphs() returns success
- Call merge_chunks()
- Assert returns True
- Assert new_chunk.is_active=False
- Assert new_chunk.matching_status="merged"

### Test: merge_chunks_transactional_failure
- Create main_chunk and new_chunk
- Mock F10.merge_chunk_subgraphs() returns failure
- Call merge_chunks()
- Assert returns False
- Assert new_chunk state unchanged

### Test: merge_chunks_resolves_flight_id
- Create main_chunk for flight_A
- Verify merge_chunks() calls F10 with correct flight_id from ChunkHandle

## Integration Tests

### Test: chunk_matching_workflow
1. create_chunk() with 10 frames
2. is_chunk_ready_for_matching() → True
3. mark_chunk_matching() → status="matching"
4. mark_chunk_anchored() → status="anchored"
5. is_chunk_ready_for_matching() → False

### Test: chunk_merge_workflow
1. Create main_chunk (frames 1-10), new_chunk (frames 20-30)
2. Anchor new_chunk via mark_chunk_anchored()
3. merge_chunks(main_chunk, new_chunk, transform)
4. Verify new_chunk deactivated and marked "merged"
5. Verify main_chunk still active

### Test: transactional_integrity_anchor
1. Create chunk
2. Configure F10.add_chunk_anchor() to fail
3. Call mark_chunk_anchored()
4. Verify chunk state unchanged
5. Configure F10.add_chunk_anchor() to succeed
6. Call mark_chunk_anchored()
7. Verify chunk state updated

### Test: transactional_integrity_merge
1. Create main_chunk and new_chunk
2. Configure F10.merge_chunk_subgraphs() to fail
3. Call merge_chunks()
4. Verify both chunks' state unchanged
5. Configure F10.merge_chunk_subgraphs() to succeed
6. Call merge_chunks()
7. Verify new_chunk state updated

