feat(agent): add gap-aware liquidation watcher demo#30
Conversation
Adds a liquidation risk watcher agent that proves continuity through missing time — not just checkpoint/resume, but gap detection, catch-up replay of missed time slots, and retroactive event discovery. The agent monitors a simulated ETH position against a deterministic price curve (pure function of discrete time slots). On resume after downtime, it detects the gap, replays missed slots with [catch-up] prefix, discovers that the liquidation threshold was breached during the outage, and seamlessly transitions to [live] processing. Demo: make demo-liquidation (~55 seconds) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e9bff58c07
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
| w.LastNano = now | ||
|
|
||
| currentSlot := uint64((now - w.BirthNano) / 1_000_000_000) |
There was a problem hiding this comment.
Guard negative elapsed time before casting to uint64
If this checkpoint is resumed on a node whose clock is behind the node that created BirthNano (or after a backward clock adjustment), (now - w.BirthNano) becomes negative here and the cast to uint64 wraps to a huge value; that makes currentSlot enormous and drives a massive fake gap replay, so resume can hang/fail and produce incorrect catch-up behavior in cross-node scenarios.
Useful? React with 👍 / 👎.
| for slot := w.LastProcessedSlot + 1; slot < currentSlot; slot++ { | ||
| w.processSlot(slot, "catch-up") |
There was a problem hiding this comment.
Limit catch-up replay work per tick
This loop replays every missed slot in a single Tick, and each iteration calls processSlot (including igor.Logf), so replay cost grows linearly with downtime; because the runtime enforces a 15s tick deadline (internal/agent/instance.go), longer outages can cause timeout during catch-up and prevent the agent from reaching live mode after resume.
Useful? React with 👍 / 👎.
Summary
[catch-up]prefix, discovers the liquidation threshold was breached during the outage, and seamlessly transitions to[live]processingWhat this proves
Not just checkpoint/resume. Gap-awareness: the agent knows it was absent, the world advanced anyway, it reconstructs what happened, and reaches the correct conclusion. The
[catch-up]→[live]transition is the emotional center.Files
agents/liquidation/main.go— 227-line gap-aware watcher with authored price curveagents/liquidation/Makefile,go.mod,agent.manifest.json— build scaffoldingscripts/demo-liquidation.sh— full 5-scene demo script (~55 seconds)Makefile—agent-liquidationanddemo-liquidationtargetsCLAUDE.md— updated with new agent/demo referencesTest plan
make agent-liquidationbuilds successfullygo test -v -race ./...all tests passmake checkpasses (fmt, vet, lint, test)make demo-liquidationruns the full 55-second demo end-to-end🤖 Generated with Claude Code