# Release v1.0.3 - Changelog

Released: 2026-02-25

## Overview

Major milestone: date-bucketed agent archive with on-demand loading, plus a comprehensive scalability audit that fixed unbounded memory growth, disk waste, and I/O hot paths across the entire system.

## Features

### Date-bucketed agent archive
- Completed agents now stored in `data/cos/agents/2026-02-25/agent-{id}/` directories instead of a flat structure
- Lightweight `index.json` maps agentId to date string for O(1) lookups (~50KB vs 16MB full cache)
- Automatic one-time migration on first startup moves all existing flat agent dirs into date buckets
- Migration is idempotent — re-running on an already-migrated system is a no-op

### On-demand agent loading in UI
- `/api/cos/agents` now returns only running agents (fast, small payload)
- New `/api/cos/agents/history` endpoint returns available date buckets with counts
- New `/api/cos/agents/history/:date` endpoint returns completed agents for a specific date
- AgentsTab auto-loads the most recent date on mount, with "Load older agents" button for previous dates
- Search filters across all loaded agents client-side

## Improvements

### Scalability audit fixes

**Memory**
- In-memory state caching for `state.json` — reads from disk once, then serves from memory (eliminates ~1,440 daily disk reads)
- Capped `liveOutputs` per agent to 500 lines (was unbounded, caused browser memory leaks)
- Bounded `agentGateway` response cache to 1,000 entries with automatic eviction (was unbounded)
- Added periodic cache cleanup every 5 minutes in agentGateway (was only on-demand via getStats)
- Notifications capped at 500 entries (was unbounded)

**Disk**
- Corrupted state.json backups now auto-cleaned to keep only 3 most recent (was accumulating indefinitely — removed 756 old backups totaling ~1.5GB)
- Agent archives pruned to 90 days on startup (was unbounded growth at ~25-50MB/month)
- Run data directories pruned to 30 days on startup (was unbounded)
- Task learning data auto-prunes stale task types (< 2 completions, > 30 days old)

**Performance**
- Productivity tracking now uses incremental updates on task completion instead of rescanning all agents (was O(N) full scan on every completion)
- Weekly digest loads only relevant date buckets instead of all agents
- `getAgentsByDate()` batches file reads in chunks of 50 (was firing hundreds of concurrent reads)
- Event scheduler history uses push+splice instead of unshift+pop (faster for large arrays)

### Agent feedback on archived agents
- Feedback submission now works for agents that have been archived from state.json to disk
- Previously, feedback only worked for agents still in state — now uses index to locate disk metadata

### Zombie cleanup date bucketing
- Zombie agents detected during cleanup are now properly moved to date buckets (not left in flat dirs)

## Bug Fixes

- Fixed crash in `getStatus()` — was calling deleted `loadCompletedAgentCache()` function after refactor
- Fixed null pointer in `archiveStaleAgents()` and `cleanupZombieAgents()` when `agent.completedAt` is missing
- Fixed task learning pruning referencing non-existent `stats.lastSeen` (now uses `stats.lastCompleted`)
- Fixed stale closure in AgentsTab `handleDelete` — date bucket count now updates correctly after deletion
- Fixed `saveAgentIndex()` crash safety — now uses atomic temp-file + rename pattern (matching `saveState()`)
- Fixed memory leak in `liveOutputs` — completed agent output buffers are now cleaned up
- Fixed unreachable dead code in productivity streak calculation

## Migration Notes

- On first startup after upgrade, the server will automatically migrate all ~2,000+ agent directories into date-bucketed structure
- Migration logs progress: `Migrated N agents into date buckets (M unique dates)`
- No manual action required — migration is fully automatic and idempotent
- The `index.json` file is created during migration and kept in sync during normal operations
- Agent archives older than 90 days are automatically pruned on startup
