Architecture
Supervision Tree
Section titled “Supervision Tree”The application starts via Annihilation.Application.start/2, which boots a flat :one_for_one supervisor with 11 children. The order is significant — the event registry must start first since downstream processes depend on it.
Annihilation.Supervisor (strategy: :one_for_one)|+-- Annihilation.Event.Registry # Registry (keys: :duplicate)| Event pub/sub backbone. All inter-process| communication flows through this registry.|+-- Annihilation.Beads.Keeper # GenServer| Owns the SQLite database connection.| Single writer, concurrent readers via WAL mode.| Schema: beads, bead_deps, bead_comments, pipelines,| pipeline_stages, bead_pipelines. FTS5 search index.|+-- Annihilation.Session.Store # GenServer| Manages append-only JSONL session files.| Writer/Reader for session persistence.|+-- Annihilation.Agent.Tool.Registry # GenServer| ETS-based tool registry. Maps tool names to modules.| Auto-registers built-in tools on startup.|+-- Annihilation.Agent.Supervisor # DynamicSupervisor| Raw DynamicSupervisor for child process management.|+-- Annihilation.Agent.DynamicSupervisor # GenServer| Named supervisor wrapper. Spawns and monitors individual| psychonaut (agent) processes on demand. Tracks agent_id -> pid| mapping. Provides start_agent/stop_agent/list_agents/get_agent.|+-- Annihilation.Agent.RecursionSemaphore # GenServer| Counting semaphore limiting global concurrent recursive| children (default: 16). Prevents resource exhaustion from| unbounded fan-out. Uses waiter queue when at capacity.|+-- Annihilation.Tether.QuestionQueue # GenServer| Buffers questions from psychonauts that need human input.| Priority-ordered (critical > high > normal > low).| Timeout detection with automatic drift notification.|+-- Annihilation.Tether.AssumptionsLedger # GenServer| Manages drift (assumption) lifecycle. JSONL persistence| at .annihilation/assumptions.jsonl with in-memory index.| Supports create/update/filter operations on drifts.|+-- Annihilation.Tether.LateBeaconHandler # GenServer| Subscribes to tether:reaching and tether:drifts events.| When the Tether answers a timed-out question, creates a| correction bead and supersedes the original drift.|+-- Annihilation.Burst.Manager # GenServer Orchestrates burst/wave lifecycle. State machine: :idle -> :collecting -> :running -> :draining -> :collecting -> :done -> :idleBoot Order Rationale
Section titled “Boot Order Rationale”- Event.Registry starts first because every other process may subscribe to or broadcast events during initialization.
- Beads.Keeper starts next to make the persistence layer available. Runs SQLite migrations on init.
- Session.Store depends on the filesystem but is independent of beads.
- Agent.Tool.Registry populates the ETS table of available tools.
- Agent.Supervisor and Agent.DynamicSupervisor are the agent infrastructure layer.
- RecursionSemaphore provides the global concurrency limiter for recursive sub-calls.
- QuestionQueue, AssumptionsLedger, and LateBeaconHandler form the tether interaction layer.
- Burst.Manager provides the top-level orchestration.
Supervisor Strategy
Section titled “Supervisor Strategy”The top-level supervisor uses :one_for_one, meaning if a child crashes, only that child is restarted. This is appropriate because the children are largely independent — a crash in Burst.Manager should not restart the Session.Store.
Event System
Section titled “Event System”All inter-process communication uses Annihilation.Event, a wrapper around OTP’s Registry with :duplicate keys. This allows multiple processes to subscribe to the same topic.
# Subscribe the current process to a topicAnnihilation.Event.subscribe("agent:*")
# Broadcast an event to all subscribersAnnihilation.Event.broadcast("agent:*", {:agent_started, id, template})
# UnsubscribeAnnihilation.Event.unsubscribe("agent:*")
# List all subscribers for a topicAnnihilation.Event.subscribers("agent:*")Events are delivered as messages in the format {:event, topic, payload}:
def handle_info({:event, "agent:*", {:agent_started, id, template}}, state) do # handle the event {:noreply, state}endEvent Topics
Section titled “Event Topics”| Topic Pattern | Payloads | Publishers |
|---|---|---|
"agent:#{id}" | {:phase_change, old, new, state}, {:delta, delta}, {:tool_results, results}, {:tool_update, call_id, partial}, :done, {:error, reason} | Agent.Server |
"agent:mail:#{id}" | %{type: :new_message, from, subject, message_id, priority} | Agent.Mailbox |
"agent:mail:broadcast" | %{type: :broadcast_message, from, subject, message_id} | Agent.Mailbox |
"tether:reaching" | {:question_asked, q}, {:question_answered, q}, {:question_timed_out, q}, {:late_answer, q, text} | QuestionQueue |
"tether:drifts" | {:drift_created, assumption}, {:drift_confirmed, info}, {:drift_rejected, info}, {:drift_noted, info}, {:drift_superseded, info}, {:pipeline_drift, info} | AssumptionsLedger, DriftReview, LateBeaconHandler, GroundingQueue |
"tether:questions" | {:pipeline_mutation_submitted, entry}, {:pipeline_mutation_responded, entry} | Pipeline.GroundingQueue |
"burst:events" | {:burst_start, info}, {:burst_complete, info}, {:wave_complete, stats} | Burst.Manager |
"reflection:*" | %{burst_id: id} for started/extracting/proposing/evaluating/curating/completed/cached/error | Reflection.Pipeline |
Persistence
Section titled “Persistence”SQLite (Beads.Keeper)
Section titled “SQLite (Beads.Keeper)”Single SQLite database at .annihilation/beads.db managed by Beads.Keeper. WAL mode for concurrent reads with single-writer pattern. Schema tables:
beads— task/issue tracking with status, type, priority, labelsbead_deps— dependency graph between beadsbead_comments— comments on beadspipelines— pipeline definitions with match rulespipeline_stages— ordered stages within pipelinesbead_pipelines— per-bead pipeline overrides- FTS5 virtual table for bead full-text search
JSONL Sessions (Session.Store)
Section titled “JSONL Sessions (Session.Store)”Append-only JSONL files in .annihilation/sessions/. One file per session (typically per burst). Session.Writer appends events, Session.Reader replays them.
Search Index (Search.Index)
Section titled “Search Index (Search.Index)”Separate SQLite database at .annihilation/search.db with FTS5 virtual table (session_search) over session content. Porter stemming with unicode61 tokenization. Supports boolean operators, phrase matching, prefix matching, and column-specific queries.
Assumptions Ledger
Section titled “Assumptions Ledger”JSONL file at .annihilation/assumptions.jsonl tracking all drifts. AssumptionsLedger GenServer maintains an in-memory index loaded from file on startup.
Playbook (Memory)
Section titled “Playbook (Memory)”YAML files at .annihilation/playbook.yaml (project) and ~/.annihilation/playbook.yaml (global). Atomic writes via temp file + rename.
Skills Catalog
Section titled “Skills Catalog”YAML file at .annihilation/skills.yaml. Stores reusable prompt/code templates with Thompson sampling parameters.
Dependencies
Section titled “Dependencies”| Dependency | Version | Purpose |
|---|---|---|
exqlite | ~> 0.23 | SQLite3 NIF for beads persistence and FTS5 search |
jason | ~> 1.4 | JSON encoding/decoding |
yaml_elixir | ~> 2.11 | YAML parsing for pipelines, playbook, skills |
mint | ~> 1.6 | HTTP client for SSE streaming to LLM APIs |
castore | ~> 1.0 | CA certificates for TLS |
stream_data | ~> 1.0 | Property-based testing (dev/test only) |
ex_doc | ~> 0.34 | Documentation generation (dev only) |
Project Structure
Section titled “Project Structure”lib/annihilation/+-- application.ex # OTP application entry point, 11-child supervision tree+-- config.ex # Project root detection+-- event.ex # Registry-based PubSub wrapper+-- beads/ # Bead persistence layer| +-- keeper.ex # GenServer: single-writer SQLite, bead/pipeline CRUD| +-- bead.ex # Bead struct and validation| +-- db.ex # Low-level SQLite wrapper (open, execute, query)| +-- migrations.ex # Schema migrations for beads, deps, comments, pipelines| +-- comment.ex # Comment struct| +-- dependency.ex # Dependency struct+-- session/ # Session persistence| +-- store.ex # GenServer for JSONL session management| +-- writer.ex # Append-only JSONL writer| +-- reader.ex # Session replay reader| +-- event.ex # SessionEvent struct| +-- meta.ex # SessionMeta struct+-- agent/ # Psychonaut core| +-- server.ex # GenServer with phase machine| +-- state.ex # Agent.State struct (phase, messages, tools, config)| +-- provider.ex # Provider behaviour (stream, format_messages, format_tools)| +-- provider/anthropic.ex # Anthropic Messages API via Mint HTTP/2| +-- provider/anthropic/sse_parser.ex # SSE stream parser -> Delta structs| +-- provider/mock.ex # Mock provider for testing| +-- tool.ex # Tool behaviour (name, description, parameters_schema, execute)| +-- tool/ # 20+ built-in tools| +-- tool/registry.ex # ETS-based tool name -> module registry| +-- message.ex # Message struct (role, content, tool_calls, metadata)| +-- delta.ex # Delta struct for streaming| +-- delta_accumulator.ex # Accumulates deltas into complete Messages| +-- tool_call.ex # ToolCall struct| +-- tool_result.ex # ToolResult struct| +-- identity.ex # AgentIdentity struct| +-- dynamic_supervisor.ex # Named supervisor for agent lifecycle| +-- recurse.ex # Recursive sub-call engine (call + fan_out)| +-- recursion_guard.ex # Depth limits, tool resolution, lease checks| +-- recursion_semaphore.ex # Global counting semaphore (default 16 slots)| +-- mailbox.ex # ETS-based inter-agent messaging| +-- agent_message.ex # AgentMessage struct| +-- file_lease.ex # File lease helpers| +-- schema.ex # JSON schema validation+-- tether/ # Human-agent tether| +-- question_queue.ex # Priority-ordered question queue with timeouts| +-- question.ex # Question struct (id, agent_id, text, priority, timeout)| +-- assumptions_ledger.ex # Drift lifecycle management (JSONL + in-memory)| +-- assumption_made.ex # AssumptionMade struct| +-- drift_review.ex # Ground/Reject/Note actions on drifts| +-- late_beacon_handler.ex # Late answers -> correction beads| +-- events.ex # Tether event helpers| +-- pipeline.ex # Tether pipeline override API| +-- pipeline_drift.ex # Pipeline drift struct| +-- pipeline_drift_review.ex # Ground/Reject pipeline drifts+-- burst/ # Burst orchestration| +-- manager.ex # GenServer state machine (idle/collecting/running/draining/done)| +-- bead_run.ex # BeadRun struct (bead + pipeline tracking)| +-- stage_executor.ex # Fan-out and sequential stage preparation+-- pipeline/ # Pipeline system| +-- pipeline.ex # Pipeline struct (name, match_labels, match_types, stages)| +-- stage.ex # Stage struct (agents, fan_out, condition, retries)| +-- bead_pipeline.ex # Per-bead pipeline override struct| +-- seed_loader.ex # YAML pipeline loading from config files| +-- grounding_queue.ex # Pipeline mutation grounding with timeout/drift+-- memory/ # Memory system| +-- diary_entry.ex # DiaryEntry struct (accomplishments, decisions, challenges, learnings)| +-- diary_writer.ex # JSONL diary writer| +-- playbook_rule.ex # PlaybookRule struct with confidence scoring| +-- playbook.ex # YAML storage for playbook rules (project + global)| +-- confidence.ex # Decay, feedback, maturity promotion/demotion, sweep| +-- anti_pattern.ex # Detection (failure_count >= 3 && > 2x successes) and inversion| +-- context.ex # Rule relevance scoring and prompt injection+-- skills/ # Skill catalog| +-- skill.ex # Skill struct (template, alpha/beta, usage tracking)| +-- catalog.ex # YAML storage for skills| +-- ranking.ex # Thompson sampling, UCB, mean-based ranking+-- search/ # Session search| +-- index.ex # FTS5 search index (session_search virtual table)| +-- writer.ex # Index events on session append+-- security/ # Security layer| +-- command_guard.ex # Three-tier risk classification (:danger/:caution/:safe)| +-- command_guard_integration.ex # Shell tool integration| +-- trauma_guard.ex # Experience-based escalation from past incidents| +-- trauma_record.ex # TraumaRecord struct| +-- trauma_store.ex # Trauma record persistence+-- file/ # File management| +-- lease_manager.ex # Cooperative file locking (exclusive/shared_read, TTL, sweep)| +-- lease_integration.ex # file_write tool integration+-- reflection/ # Post-burst reflection| +-- pipeline.ex # 6-stage reflection pipeline orchestrator| +-- agent_template.ex # Reflection psychonaut template| +-- diary_extractor.ex # Extract diary entries from session transcripts| +-- playbook_proposer.ex # Propose playbook rule changes| +-- playbook_delta.ex # PlaybookDelta struct (add/update/deprecate)| +-- evidence_gate.ex # Validate proposals against session search| +-- curator.ex # Dedup, conflict detection, anti-pattern inversion+-- tui/ # Terminal UI +-- terminal.ex # Raw mode, ANSI escape codes, screen buffer rendering +-- layout.ex # Panel layout system +-- input.ex # Key event parsing (CSI, SS3, control, printable) +-- event_bridge.ex # System events -> TUI panel updates (30fps batching) +-- mode.ex # Mode behaviour (init, handle_key, handle_events, render) +-- mode_manager.ex # Mode switching (Tab, number keys 1-6), state preservation +-- modes/overview.ex # All psychonauts + activity log +-- modes/focus.ex # Single psychonaut conversation view +-- modes/tether.ex # Questions + drifts panel +-- modes/grounding.ex # Code review / pipeline mutation approval +-- modes/beads.ex # Bead management +-- modes/shell.ex # Embedded command runner