This repository was archived by the owner on Jul 14, 2026. It is now read-only.
Description Summary
Wire the TcpServer into TrackerManager, add auto-provisioning of tracker instances for unknown nodes, and handle disconnect/reconnect lifecycle.
Context
Depends on #5 (DetectionSource protocol) and #6 (TcpServer + TcpReceiver).
See design spec: docs/superpowers/specs/2026-03-11-tcp-push-detection-forwarding-design.md in the retina monorepo.
Changes
Updated: TrackerManager (tracker_host/manager.py)
Start TcpServer on init if tcp_server.enabled in config
For mode: "tcp" trackers in config: create TcpReceiver, register with TcpServer, create TrackerInstance with that receiver
For mode: "http" trackers: existing behavior (create DetectionFetcher-backed instance)
Auto-provisioning callback : register a callback with TcpServer for unknown node_ids. When a frame arrives from an unknown node with a valid token:
Auto-assign a local TCP port from auto_provision_port_start to auto_provision_port_end
Create a TcpReceiver and register with TcpServer
Create a TrackerInstance with default settings
Start the instance (spawns retina-tracker subprocess)
Log the auto-provisioning event
Reject auto-provisioning when port range is exhausted (log error)
Disconnect/reconnect lifecycle
On node disconnect: TcpReceiver.is_healthy becomes False. TrackerInstance keeps subprocess alive for extended_outage_sec (existing behavior via fetch loop).
On reconnect: TcpServer routes to existing TcpReceiver. Node's buffered frames drain through. Subprocess continues processing.
After extended_outage_sec: subprocess killed, instance stays registered in memory.
Late reconnect: subprocess respawned automatically when frames arrive again.
Graceful shutdown
Stop accepting new TCP connections
Close all node connections (nodes reconnect automatically)
Drain in-progress frames
Stop all tracker subprocesses (existing TrackerManager.stop() behavior)
Updated: config parsing
Parse tcp_server block into TcpServerConfig
Updated config.yaml with tcp_server section
Acceptance criteria
Reactions are currently unavailable
Summary
Wire the TcpServer into TrackerManager, add auto-provisioning of tracker instances for unknown nodes, and handle disconnect/reconnect lifecycle.
Context
Depends on #5 (DetectionSource protocol) and #6 (TcpServer + TcpReceiver).
See design spec:
docs/superpowers/specs/2026-03-11-tcp-push-detection-forwarding-design.mdin the retina monorepo.Changes
Updated:
TrackerManager(tracker_host/manager.py)TcpServeron init iftcp_server.enabledin configmode: "tcp"trackers in config: createTcpReceiver, register withTcpServer, createTrackerInstancewith that receivermode: "http"trackers: existing behavior (createDetectionFetcher-backed instance)TcpServerfor unknownnode_ids. When a frame arrives from an unknown node with a valid token:auto_provision_port_starttoauto_provision_port_endTcpReceiverand register withTcpServerTrackerInstancewith default settingsDisconnect/reconnect lifecycle
TcpReceiver.is_healthybecomes False. TrackerInstance keeps subprocess alive forextended_outage_sec(existing behavior via fetch loop).TcpServerroutes to existingTcpReceiver. Node's buffered frames drain through. Subprocess continues processing.extended_outage_sec: subprocess killed, instance stays registered in memory.Graceful shutdown
TrackerManager.stop()behavior)Updated: config parsing
tcp_serverblock intoTcpServerConfigconfig.yamlwith tcp_server sectionAcceptance criteria