---
phase: 03-agent-registry-sse-push
plan: 01
subsystem: agent-registry
tags: [concurrenthashmap, lifecycle, heartbeat, rest-api, spring-scheduled]

# Dependency graph
requires:
  - phase: 01-ingestion-pipeline
    provides: IngestionBeanConfig pattern, @Scheduled pattern, ProtocolVersionInterceptor
provides:
  - AgentRegistryService with register/heartbeat/lifecycle/command management
  - AgentInfo record with wither-style immutable state transitions
  - AgentCommand record with delivery status tracking
  - AgentEventListener interface for SSE bridge (Plan 02)
  - POST /api/v1/agents/register endpoint
  - POST /api/v1/agents/{id}/heartbeat endpoint
  - GET /api/v1/agents endpoint with ?status= filter
  - AgentLifecycleMonitor with LIVE->STALE->DEAD transitions
  - AgentRegistryConfig with all timing properties
affects: [03-02-sse-push, 04-security]

# Tech tracking
tech-stack:
  added: []
  patterns: [immutable-record-with-wither, compute-if-present-atomic-swap, agent-lifecycle-state-machine]

key-files:
  created:
    - cameleer-server-core/src/main/java/com/cameleer/server/core/agent/AgentInfo.java
    - cameleer-server-core/src/main/java/com/cameleer/server/core/agent/AgentState.java
    - cameleer-server-core/src/main/java/com/cameleer/server/core/agent/AgentCommand.java
    - cameleer-server-core/src/main/java/com/cameleer/server/core/agent/CommandStatus.java
    - cameleer-server-core/src/main/java/com/cameleer/server/core/agent/CommandType.java
    - cameleer-server-core/src/main/java/com/cameleer/server/core/agent/AgentRegistryService.java
    - cameleer-server-core/src/main/java/com/cameleer/server/core/agent/AgentEventListener.java
    - cameleer-server-core/src/test/java/com/cameleer/server/core/agent/AgentRegistryServiceTest.java
    - cameleer-server-app/src/main/java/com/cameleer/server/app/config/AgentRegistryConfig.java
    - cameleer-server-app/src/main/java/com/cameleer/server/app/config/AgentRegistryBeanConfig.java
    - cameleer-server-app/src/main/java/com/cameleer/server/app/agent/AgentLifecycleMonitor.java
    - cameleer-server-app/src/main/java/com/cameleer/server/app/controller/AgentRegistrationController.java
    - cameleer-server-app/src/test/java/com/cameleer/server/app/controller/AgentRegistrationControllerIT.java
  modified:
    - cameleer-server-app/src/main/java/com/cameleer/server/app/CameleerServerApplication.java
    - cameleer-server-app/src/main/resources/application.yml

key-decisions:
  - "AgentInfo as Java record with wither-style methods for immutable ConcurrentHashMap swapping"
  - "Dead threshold measured from staleTransitionTime, not lastHeartbeat (matches requirement precisely)"
  - "spring.mvc.async.request-timeout=-1 set now for SSE support in Plan 02"

patterns-established:
  - "Immutable record + ConcurrentHashMap.compute for thread-safe state transitions"
  - "AgentEventListener interface in core module as bridge to SSE layer in app module"

requirements-completed: [AGNT-01, AGNT-02, AGNT-03]

# Metrics
duration: 15min
completed: 2026-03-11
---

# Phase 3 Plan 1: Agent Registry Summary

**In-memory agent registry with ConcurrentHashMap, LIVE/STALE/DEAD lifecycle via @Scheduled, and REST endpoints for registration/heartbeat/listing**

## Performance

- **Duration:** 15 min
- **Started:** 2026-03-11T17:26:34Z
- **Completed:** 2026-03-11T17:41:24Z
- **Tasks:** 2
- **Files modified:** 15

## Accomplishments
- Agent registry domain model with 5 types (AgentInfo, AgentState, AgentCommand, CommandStatus, CommandType)
- Full lifecycle management: register, heartbeat, LIVE->STALE->DEAD transitions with configurable thresholds
- Command queue with PENDING/DELIVERED/ACKNOWLEDGED/EXPIRED status tracking and event listener bridge
- REST endpoints: POST /register, POST /{id}/heartbeat, GET /agents with ?status= filter
- 23 unit tests + 7 integration tests all passing

## Task Commits

Each task was committed atomically:

1. **Task 1 (RED): Failing tests for agent registry** - `4cd7ed9` (test)
2. **Task 1 (GREEN): Implement agent registry service** - `61f3902` (feat)
3. **Task 2: Controllers, config, lifecycle monitor, integration tests** - `0372be2` (feat)

_Note: Task 1 used TDD with separate RED/GREEN commits_

## Files Created/Modified
- `AgentInfo.java` - Immutable record with wither-style methods for atomic state transitions
- `AgentState.java` - LIVE, STALE, DEAD lifecycle enum
- `AgentCommand.java` - Command record with delivery status tracking
- `CommandStatus.java` - PENDING, DELIVERED, ACKNOWLEDGED, EXPIRED enum
- `CommandType.java` - CONFIG_UPDATE, DEEP_TRACE, REPLAY enum
- `AgentRegistryService.java` - Core registry: register, heartbeat, lifecycle, commands
- `AgentEventListener.java` - Interface for SSE bridge (Plan 02 integration point)
- `AgentRegistryConfig.java` - @ConfigurationProperties for all timing settings
- `AgentRegistryBeanConfig.java` - @Configuration wiring AgentRegistryService
- `AgentLifecycleMonitor.java` - @Scheduled lifecycle check and command expiry
- `AgentRegistrationController.java` - REST endpoints for agents
- `AgentRegistryServiceTest.java` - 23 unit tests
- `AgentRegistrationControllerIT.java` - 7 integration tests
- `CameleerServerApplication.java` - Added AgentRegistryConfig to @EnableConfigurationProperties
- `application.yml` - Added agent-registry config section and spring.mvc.async.request-timeout

## Decisions Made
- Used Java record with wither-style methods for AgentInfo instead of mutable class -- ConcurrentHashMap.compute provides atomic swapping without needing synchronized fields
- Dead threshold measured from staleTransitionTime field (not lastHeartbeat) to match the "5 minutes after going STALE" requirement precisely
- Set spring.mvc.async.request-timeout=-1 proactively for SSE support needed in Plan 02
- Command queue uses ConcurrentLinkedQueue per agent for lock-free command management

## Deviations from Plan

None - plan executed exactly as written.

## Issues Encountered
- DiagramRenderControllerIT has a pre-existing flaky failure (EmptyResultDataAccess in seedDiagram) unrelated to Phase 3 changes. Logged in deferred-items.md.

## User Setup Required

None - no external service configuration required.

## Next Phase Readiness
- AgentRegistryService ready for SSE integration via AgentEventListener interface
- Plan 02 (SSE Push) can wire SseConnectionManager as AgentEventListener implementation
- All agent endpoints under /api/v1/agents/ already covered by ProtocolVersionInterceptor

---
*Phase: 03-agent-registry-sse-push*
*Completed: 2026-03-11*
