Tick Engine — First Autonomous Agents
activeThe 4-phase Tick cycle — Observation, Intent, Resolution, Telemetry. Signals published via the Context Bus. Time-series stored in VictoriaMetrics. Implementation: LIVE.
Tick Engine — First Autonomous Agents
See also: genesis-protocol | constitution | context-bus | universe
Status: LIVE — The Tick Engine is implemented and running. This document is the canonical architecture reference.
The Core Insight
The Dynamic Control Plane (defined in genesis-protocol.md) states that U_global moves — and when it moves, Sal moves the system. Until now, Sal had no mechanism to move automatically. He was reactive: a human had to call the health endpoint and read the result.
The Tick Engine makes Sal proactive. When something happens in the pipeline — an issue created, a release published, a webhook failing — the whole crew observes the new state simultaneously, each member surfaces their intent, Sal resolves the conflicts, and the universe updates itself.
Pipeline events are now the universe’s heartbeat. Every significant event fires a Tick. The universe is always current.
Architecture
Pipeline Event (issue created, release published, webhook failed, etc.) │ ▼ triggerTick(projectId) │ ┌──────▼──────────────────────────────────────────┐ │ Phase 1: OBSERVATION │ │ takeSnapshot(projectId) → UniverseState │ └──────┬──────────────────────────────────────────┘ │ State_t passed in-process to publishIntents() ▼ ┌──────────────────────────────────────────────────┐ │ Phase 2: INTENT │ │ publishIntents(state) calls observe() on each │ │ agent synchronously: margot, kael, wren, harlan│ │ Returns AgentIntent[] — zero network hops │ └──────┬───────────────────────────────────────────┘ │ Intents returned as in-process array ▼ ┌──────────────────────────────────────────────────┐ │ Phase 3: RESOLUTION (Sal orchestrates) │ │ Receives AgentIntent[] from Phase 2 │ │ Applies physics rules, resolves conflicts │ │ Computes State_t+1 │ └──────┬───────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────┐ │ Phase 4: TELEMETRY │ │ → Context Bus: publish slim cache-invalidation │ │ signal — browsers refetch fresh state via REST│ │ → VictoriaMetrics: write time-series metrics │ │ → Structured log: emit tick audit record │ └──────────────────────────────────────────────────┘Time-Series Memory — VictoriaMetrics
VictoriaMetrics is the universe’s long-term memory — the agent-facing telemetry store. The events table is the user-facing activity record (The Feed). VictoriaMetrics answers the temporal questions: “What was U_global at Tick 84,200?” and “How has pipeline state shifted over 30 days?”
The HUD’s epoch sparkline renders U_global as a time-series — not a snapshot, but a trajectory. This is how the Creator sees whether the universe is ascending or descending.
Structured Logs — The Tick Audit Trail
Status: LIVE — Each Tick emits a structured pino log entry with the full TickResult.
Every Tick produces one log line:
{ "level": 30, "time": 1234567890, "tickId": "tick_abc123", "projectId": "proj_xyz", "pipelineState": "FLOWING", "uGlobal": 78, "intents": [ { "agentId": "margot", "action": "release.cadence.alert", "priority": "high", ... }, { "agentId": "harlan", "action": "signal.quiet", "priority": "medium", ... } ], "resolutions": [ { "intent": {...}, "outcome": "Release cadence critical — 0 releases in 30 days. Prioritize shipping." } ]}This log is the replay record. “Load snapshot from Tick 84,200” means: find the log entry with tickId: tick_84200 and reconstruct the agent’s intent sequence. The log is the audit trail of the universe’s decisions.
Agent Intent Vocabulary
Each agent runs a deterministic observe(state: UniverseState): AgentIntent[] function. No LLM calls — rule-based, instant, cost-free per Tick.
Margot — Product & Strategy
| Action | Trigger | Priority |
|---|---|---|
intake.prioritize | backlog > 20, no planned items | high |
release.cadence.alert | 0 releases in 30 days | high |
intel.activate | 0 active Kano studies, 0 active personas | medium |
Kael — Engineering & Operations
| Action | Trigger | Priority |
|---|---|---|
wip.limit.exceeded | inProgress > 5 | high |
capacity.available | inProgress < 2, backlog > 0 | medium |
tech.debt.signal | bug ratio > 0.4 of total issues | medium |
Wren — Design & Quality
| Action | Trigger | Priority |
|---|---|---|
quality.signal | bugs > 5 in backlog | medium |
experience.friction | improvements > 10 unaddressed | low |
Harlan — Comms & Customer
| Action | Trigger | Priority |
|---|---|---|
comms.degraded | failedWebhooks > 0 | high |
signal.quiet | 0 releases in 30 days | high |
persona.gap | 0 active personas | low |
Sal — Orchestration & Resolution
Sal doesn’t submit intents. He resolves them. Sal’s resolution rules (from universe/constitution.md):
- High-priority intents always processed first
wip.limit.exceededblockscapacity.available(Kael can’t signal capacity when WIP is over limit)comms.degradedforcespipelineState → DEGRADEDregardless of other signals- If
pipelineStatechanges, State_t+1 reflects it immediately - Multiple high-priority intents from different agents stack without conflict (each gets a resolution)
Observability Stack
The Tick Engine introduces a three-layer observability stack:
| Layer | Technology | What It Stores | Retention |
|---|---|---|---|
| Time-series metrics | VictoriaMetrics (time-series storage) | U_global, dial values, issue stats, intent counters | 12 months |
| Tick audit trail | pino structured logs | Full TickResult per tick — intents, resolutions, state transitions | Log rotation policy |
| User-facing events | SQLite events table | Human-readable activity for The Feed | Indefinite |
The three layers serve different consumers:
- Time-series store → HUD epoch view, trend queries, anomaly detection
- Logs → Debug, replay, incident investigation (“what did the crew think at Tick X?”)
- Events table → The Feed, notification inbox, public activity
They don’t overlap. Each is the right tool for its consumer.
Implementation
Packages
| Package | Description |
|---|---|
apps/app | Core system — Tick Engine runtime, Context Bus client, telemetry layer |
packages/sdk | TypeScript SDK — CrewActivity, TickSummary types, getCrewActivity() |
Files
| File | Status |
|---|---|
docker-compose.yml | LIVE — Infrastructure services |
apps/app/src/lib/nats-client.ts | LIVE — Context Bus connection singleton |
apps/app/src/lib/vm-client.ts | LIVE — Time-series telemetry writes |
apps/app/src/lib/tick-engine/types.ts | LIVE — UniverseState, AgentIntent, TickResult |
apps/app/src/lib/tick-engine/snapshot.ts | LIVE — takeSnapshot() refactored from universe.ts |
apps/app/src/lib/tick-engine/agents/margot.ts | LIVE — Product intent rules |
apps/app/src/lib/tick-engine/agents/kael.ts | LIVE — Engineering intent rules |
apps/app/src/lib/tick-engine/agents/wren.ts | LIVE — Design intent rules |
apps/app/src/lib/tick-engine/agents/harlan.ts | LIVE — Comms intent rules |
apps/app/src/lib/tick-engine/orchestrator.ts | LIVE — Sal’s resolution logic |
apps/app/src/lib/tick-engine/index.ts | LIVE — 4-phase trigger + Context Bus + telemetry |
apps/app/src/routes/api/v1/universe.ts | LIVE — SSE bridge + /crew-activity + refactored /health |
apps/app/client/src/hooks/use-dashboard.ts | LIVE — useCrewActivity, usePipelineStats |
apps/app/client/src/hooks/use-nats.ts | LIVE — useNatsRealtime(projectId) — subscribes to Context Bus signals; invalidates crew-activity + universe-health caches on each tick signal |
apps/app/client/src/pages/universe-hud.tsx | LIVE — U_global gauge, The Feed (filterable event log), Agent Roster with profile images, Crew Status widget; wired to Context Bus via useNatsRealtime |
apps/app/client/src/pages/universe-crew-tab.tsx | LIVE — Dedicated Crew tab: agent registry (profile images, capabilities, activate/deactivate) + real-time Crew Activity panel; agent cards clickable → crew detail page |
apps/app/client/src/components/dashboard/briefing-widget.tsx | LIVE — Canon v0.8.0 Layer 2. Project-level Briefing Widget: pipeline state + crew intercepts (action/outcome per agent) + Sal’s voice summary. First crew-voiced surface in the product. |
apps/app/client/src/components/dashboard/pipeline-card.tsx | LIVE — Pipeline sidebar card: 14-day throughput stats (completed/created), current WIP, active items list |
packages/sdk/src/types.ts | LIVE — CrewActivity, AgentIntentSummary, TickSummary |
packages/sdk/src/resources/dashboard.ts | LIVE — getCrewActivity(), getPipelineStats() |