|
| 1 | +# GoAgent v0.2.0 Release Notes |
| 2 | + |
| 3 | +**Release Date:** 2026-06-12 |
| 4 | +**Branch:** improve |
| 5 | +**Commits:** 119 files changed, 22,634 insertions, 1,302 deletions |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Overview |
| 10 | + |
| 11 | +v0.2.0 introduces a Runtime layer for agent lifecycle management, event sourcing for operational recovery, a dynamic workflow engine with human-in-the-loop support, and a pluggable vector store interface. The focus shifts from "agents manage themselves" to "Runtime manages agents" — agents become disposable executors. |
| 12 | + |
| 13 | +--- |
| 14 | + |
| 15 | +## Architecture Changes |
| 16 | + |
| 17 | +### Before (v0.1.x) |
| 18 | + |
| 19 | +``` |
| 20 | +Leader Agent |
| 21 | +├── manages sub-agents |
| 22 | +├── manages own lifecycle |
| 23 | +├── manages own memory |
| 24 | +└── single point of failure |
| 25 | +``` |
| 26 | + |
| 27 | +### After (v0.2.0) |
| 28 | + |
| 29 | +``` |
| 30 | +Runtime Layer |
| 31 | +├── manages ALL agent lifecycles |
| 32 | +├── resurrects failed agents |
| 33 | +├── replays events for state recovery |
| 34 | +│ |
| 35 | +├── EventStore (operational recovery) |
| 36 | +│ └── "What step was I on?" |
| 37 | +│ |
| 38 | +├── MemoryStore (cognitive recovery) |
| 39 | +│ └── "Who am I? Why did I do this?" |
| 40 | +│ |
| 41 | +└── Agents (disposable executors) |
| 42 | + ├── Leader Agent |
| 43 | + ├── Sub Agents |
| 44 | + └── Custom Agents |
| 45 | +``` |
| 46 | + |
| 47 | +Key principle: **Agents are disposable executors. Real state lives in EventStore and MemoryStore.** |
| 48 | + |
| 49 | +--- |
| 50 | + |
| 51 | +## New Features |
| 52 | + |
| 53 | +### 1. Runtime Layer (`internal/runtime/`) |
| 54 | + |
| 55 | +Agent lifecycle management with automatic resurrection. |
| 56 | + |
| 57 | +```go |
| 58 | +type Runtime interface { |
| 59 | + StartAgent(ctx, agent) error |
| 60 | + StopAgent(ctx, agentID) error |
| 61 | + RestartAgent(ctx, agentID) error |
| 62 | + RestoreAgent(ctx, agentID, factory) error |
| 63 | + NotifyAgentDead(agentID, reason) |
| 64 | + RegisterAgent(agent, factory) |
| 65 | + Start(ctx) error |
| 66 | + Stop() error |
| 67 | + Stats() RuntimeStats |
| 68 | +} |
| 69 | +``` |
| 70 | + |
| 71 | +- `NotifyAgentDead` — non-blocking, triggers async resurrection |
| 72 | +- `RestoreAgent` — factory → replayEvents → RestoreState → Start |
| 73 | +- Concurrent shutdown with configurable timeout |
| 74 | +- Panic recovery in all agent goroutines |
| 75 | + |
| 76 | +### 2. Event Sourcing (`internal/events/`) |
| 77 | + |
| 78 | +EventStore interface with two implementations. |
| 79 | + |
| 80 | +```go |
| 81 | +type EventStore interface { |
| 82 | + Append(ctx, streamID, events, expectedVersion) error |
| 83 | + Read(ctx, streamID, opts) ([]*Event, error) |
| 84 | + ReadAll(ctx, opts) ([]*Event, error) |
| 85 | + Subscribe(ctx, filter) (<-chan *Event, error) |
| 86 | + StreamVersion(ctx, streamID) (int64, error) |
| 87 | +} |
| 88 | +``` |
| 89 | + |
| 90 | +- **MemoryEventStore** — in-memory, for dev/test |
| 91 | +- **PostgresEventStore** — PostgreSQL with optimistic concurrency |
| 92 | +- 17 event types covering agent lifecycle, tasks, memory, workflow |
| 93 | +- DLQ auto-retry with MaxRetries |
| 94 | + |
| 95 | +### 3. Dynamic Workflow Engine (`internal/workflow/engine/`) |
| 96 | + |
| 97 | +Runtime-mutable DAG with HITL support. |
| 98 | + |
| 99 | +- **MutableDAG** — AddNode/RemoveNode/AddEdge/RemoveEdge with incremental BFS cycle detection |
| 100 | +- **DynamicExecutor** — ApplyAtCheckpoint / ApplyImmediate modes |
| 101 | +- **GraphEventHub** — pub/sub for mutation notifications |
| 102 | +- **HITL** — InterruptConfig on steps, InterruptHandler, InterruptStore |
| 103 | + |
| 104 | +### 4. Pluggable Vector Store (`internal/storage/`) |
| 105 | + |
| 106 | +```go |
| 107 | +type VectorStore interface { |
| 108 | + Search(ctx, table, embedding, limit) ([]*SearchResult, error) |
| 109 | + AddEmbedding(ctx, table, id, embedding, metadata) error |
| 110 | + CreateCollection(ctx, name, dimension) error |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | +- **PostgreSQL + pgvector** — production implementation |
| 115 | +- **In-memory** — dev/test implementation |
| 116 | +- Users can plug in Qdrant, Milvus, SQLite, Elasticsearch, or custom backends |
| 117 | + |
| 118 | +### 5. StatefulAgent Interface (`internal/agents/base/`) |
| 119 | + |
| 120 | +```go |
| 121 | +type StatefulAgent interface { |
| 122 | + RestoreState(state map[string]any) error |
| 123 | + ReplayEvents(events []*Event) error |
| 124 | + Snapshot() (map[string]any, error) |
| 125 | +} |
| 126 | +``` |
| 127 | + |
| 128 | +Both leader and sub agents implement this interface with compile-time checks. |
| 129 | + |
| 130 | +### 6. Resurrection Plugin (`internal/plugins/resurrection/`) |
| 131 | + |
| 132 | +Pluggable agent resurrection via HealthChecker interface. |
| 133 | + |
| 134 | +- `HeartbeatAdapter` bridges AHP heartbeat to HealthChecker |
| 135 | +- `Supervisor` with concurrent resurrection deduplication |
| 136 | +- Factory-based recovery — each agent type provides its own factory |
| 137 | + |
| 138 | +### 7. WorkflowService API (`api/core/workflow.go`, `api/service/workflow/`) |
| 139 | + |
| 140 | +High-level workflow orchestration abstraction. |
| 141 | + |
| 142 | +```go |
| 143 | +type WorkflowService interface { |
| 144 | + Execute(ctx, req) (*WorkflowResponse, error) |
| 145 | + ExecuteStream(ctx, req) (<-chan WorkflowEvent, error) |
| 146 | + ListWorkflows(ctx) ([]*WorkflowSummary, error) |
| 147 | + GetWorkflow(ctx, id) (*WorkflowDefinition, error) |
| 148 | +} |
| 149 | +``` |
| 150 | + |
| 151 | +--- |
| 152 | + |
| 153 | +## Bug Fixes (50 total) |
| 154 | + |
| 155 | +### Storage (12) |
| 156 | +- Embedding queue dedup key mismatch (SHA256 vs MD5) |
| 157 | +- Write buffer data loss on Stop() |
| 158 | +- Transactional EnqueueTx for atomic writes |
| 159 | +- FOR UPDATE SKIP LOCKED without transaction |
| 160 | +- Reconcile threshold time arithmetic (Go duration vs PG interval) |
| 161 | +- ManagedRow connection leak (missing finalizer) |
| 162 | +- Missing migration tables (4 tables) |
| 163 | +- Circuit breaker halfOpen cleanup |
| 164 | +- safeFormatTable returning empty string |
| 165 | +- Immediate retry on flush failure |
| 166 | +- VectorSearcher dimension validation |
| 167 | +- Enqueue silent on duplicate (now returns ErrDuplicateTask) |
| 168 | + |
| 169 | +### Workflow (8) |
| 170 | +- Panic recovery ordering (wg.Done after recover) |
| 171 | +- Graph executor in-degree tracking |
| 172 | +- Deadlock false positive (stepDone channel) |
| 173 | +- DynamicExecutor hang on node removal (synthetic skipped result) |
| 174 | +- stepEg.Wait() concurrent with Go() |
| 175 | +- Duplicate step ID detection |
| 176 | +- MaxAttempts=0 clamp |
| 177 | +- recomputeOrder version-check race |
| 178 | + |
| 179 | +### AHP Protocol (7) |
| 180 | +- Send on closed channel (recover guard) |
| 181 | +- HeartbeatSender Start/Stop race |
| 182 | +- getRandomSuffix nil dereference |
| 183 | +- SendMessage error preservation |
| 184 | +- Protocol.Close() method |
| 185 | +- Peek() atomicity |
| 186 | +- DLQ.Remove trailing pointer |
| 187 | + |
| 188 | +### Agent System (8) |
| 189 | +- WaitGroup panic in finalizeMemory |
| 190 | +- Start/Stop TOCTOU race |
| 191 | +- Process mutual exclusion |
| 192 | +- Start partial validation cleanup |
| 193 | +- subAgent ProcessStream goroutine leak |
| 194 | +- doFailover cancelled context |
| 195 | +- Dispatcher partial results |
| 196 | +- streamEg tied to stopCh |
| 197 | + |
| 198 | +### Runtime (5) |
| 199 | +- Nil errgroup panic before Start() |
| 200 | +- Stop() data race on ma.stopped |
| 201 | +- Unbounded event replay (MaxReplayEvents=10000) |
| 202 | +- buildCognitiveState DB call timeout |
| 203 | +- Stop() using cancelled context |
| 204 | + |
| 205 | +### Event Sourcing (5) |
| 206 | +- FromVersion inclusive/exclusive semantics |
| 207 | +- Since filter inclusive semantics |
| 208 | +- ReadAll ignoring FromVersion |
| 209 | +- PostgreSQL unique violation → ErrVersionConflict |
| 210 | +- ConcurrentAppend test verification |
| 211 | + |
| 212 | +### Other (5) |
| 213 | +- SA5011 nil-pointer in 17 test files |
| 214 | +- SA1012 nil context in test |
| 215 | +- errcheck in integration tests |
| 216 | +- Mermaid diagram errors in README |
| 217 | +- safeFormatTable return value |
| 218 | + |
| 219 | +--- |
| 220 | + |
| 221 | +## Infrastructure |
| 222 | + |
| 223 | +- **CI/CD**: GitHub Actions pipeline (lint, test, integration, benchmark) |
| 224 | +- **Integration Tests**: 60+ tests across 12 test files |
| 225 | +- **Benchmarks**: 36 benchmarks with count=3, updated report |
| 226 | +- **Documentation**: Bilingual (en/zh), 12 new docs |
| 227 | +- **Examples**: 6 runnable examples in `examples/advanced/` |
| 228 | + |
| 229 | +--- |
| 230 | + |
| 231 | +## Breaking Changes |
| 232 | + |
| 233 | +| Change | Before | After | |
| 234 | +|--------|--------|-------| |
| 235 | +| `NewLeaderSupervisor` signature | 4 params | 5 params (added `eventStore`) | |
| 236 | +| `NewColdRestartStrategy` signature | 2 params | 3 params (added `checkpoint`) | |
| 237 | +| `MemoryManager` interface | 11 methods | 12 methods (added `GetLatestSessionForLeader`) | |
| 238 | +| `Repository.Vector` field | `*VectorSearcher` | `storage.VectorStore` | |
| 239 | +| `StatefulAgent` interface | `RestoreState` only | + `ReplayEvents`, `Snapshot` | |
| 240 | + |
| 241 | +--- |
| 242 | + |
| 243 | +## Benchmark Results |
| 244 | + |
| 245 | +Platform: Apple M3 Max, Go 1.26.4, darwin/arm64 |
| 246 | + |
| 247 | +| Category | Benchmarks | Hot (< 1μs) | Normal (1-100μs) | Cold (> 100μs) | |
| 248 | +|----------|-----------|-------------|-------------------|-----------------| |
| 249 | +| Eval | 5 | 2 | 2 | 1 | |
| 250 | +| Handler | 3 | 1 | 2 | 0 | |
| 251 | +| Tools/Core | 9 | 6 | 3 | 0 | |
| 252 | +| Distillation | 9 | 4 | 4 | 1 | |
| 253 | +| Errors | 4 | 4 | 0 | 0 | |
| 254 | +| Event Sourcing | 6 | 4 | 1 | 1 | |
| 255 | +| **Total** | **36** | **21** | **12** | **3** | |
| 256 | + |
| 257 | +Selected hot-path results: |
| 258 | + |
| 259 | +| Operation | ns/op | allocs/op | |
| 260 | +|-----------|-------|-----------| |
| 261 | +| ResultCreation | 0.27 | 0 | |
| 262 | +| Wrap | 0.28 | 0 | |
| 263 | +| ExactMatchEvaluator | 3.11 | 0 | |
| 264 | +| ToolExecution | 14.66 | 0 | |
| 265 | +| ParameterValidation | 7.26 | 0 | |
| 266 | +| ConflictDetection | 1,067 | 0 | |
| 267 | +| MemoryStore_Append | 563 | 7 | |
| 268 | +| MemoryStore_ConcurrentAppend | 707 | 6 | |
| 269 | + |
| 270 | +--- |
| 271 | + |
| 272 | +## Migration Guide |
| 273 | + |
| 274 | +### From v0.1.x to v0.2.0 |
| 275 | + |
| 276 | +1. **Runtime is optional.** Existing code using `LeaderSupervisor` continues to work. Migrate to `Runtime` when ready. |
| 277 | + |
| 278 | +2. **EventStore is optional.** Existing checkpoint-based recovery continues to work. Add EventStore for richer recovery. |
| 279 | + |
| 280 | +3. **VectorStore is a drop-in replacement.** `Repository.Vector` is now an interface. Existing `*VectorSearcher` satisfies it automatically. |
| 281 | + |
| 282 | +4. **StatefulAgent is opt-in.** Only implement if you want your agents to support resurrection via event replay. |
| 283 | + |
| 284 | +--- |
| 285 | + |
| 286 | +## What's Next (v0.3.0) |
| 287 | + |
| 288 | +- SQLite + sqlite-vec compatibility (VectorStore interface ready) |
| 289 | +- Distributed Runtime (multi-node agent management) |
| 290 | +- Enhanced HITL (approval workflows, multi-step review) |
| 291 | +- Performance optimization (TopNFilter regression investigation) |
0 commit comments