# ActiveGraph-Inspired Runtime
`yoagent-state` is inspired by Yohei Nakajima's ActiveGraph work, adapted into an idiomatic Rust runtime for `yoagent` and `yoyo evolve`.
The full concept is:
```text
append-only event log
-> deterministic replay
-> typed graph projection
-> pattern subscriptions
-> behaviors
-> policy-gated patches
-> replay, fork, and diff
```
```mermaid
flowchart LR
log["append-only event log"]
replay["deterministic replay"]
graphNode["typed graph projection"]
patterns["pattern subscriptions"]
behaviors["behaviors"]
policies["policy gates"]
forks["replay / fork / diff"]
log --> replay --> graphNode --> patterns --> behaviors
graphNode --> policies
graphNode --> forks
behaviors --> log
policies --> log
```
## What changed in v0.2
The core lineage path now starts from goals:
```text
goal -> task -> run -> observation -> failure -> hypothesis -> patch -> artifact -> eval -> decision -> promotion
```
```mermaid
flowchart LR
goal["goal"]
task["task"]
run["run"]
observation["observation"]
failure["failure"]
hypothesis["hypothesis"]
patch["patch"]
artifact["artifact"]
eval["eval"]
decision["decision"]
promoted["promoted status"]
task -- serves --> goal
run -- produces --> observation
observation -- observes --> failure
hypothesis -- explains --> failure
patch -- addresses --> failure
patch -- advances --> goal
patch -- references --> artifact
patch -- validated_by --> eval
patch -- approved_by --> decision
decision -- allows --> promoted
```
This is the common graph spine. It is not a claim that every agent run must create every node. `artifact` includes diffs, logs, screenshots, files, eval output, and other external evidence. `promotion` is represented by the patch lifecycle status.
`yoagent-state` now has first-class IDs and helpers for:
- goals
- tasks
- runs
- observations
- hypotheses
- evals
- decisions
- project snapshots
- model calls
- tool calls
- frames
- forks
- behaviors
- policies
- packs
- views
## Runtime layers
`YoAgentState` remains the simple state API: record events, apply ops, query graph, query lineage.
`YoAgentRuntime` adds the ActiveGraph-inspired runtime layer:
- register typed packs
- validate typed nodes and relations
- register behavior subscriptions
- enforce policy gates
- create approval requests
This keeps simple usage simple while allowing richer agent systems to use the full concept.
## Extensible storage
The event log remains the source of truth.
Storage is split into traits:
- `EventStore`
- `SnapshotStore`
- `ForkStore`
- `IndexStore`
- `ArtifactStore`
JSONL is implemented first because it is inspectable. SQLite, PostgreSQL, and graph-backed projections can be added later behind the same traits.
## Behaviors
Behaviors subscribe to event patterns and return state ops.
They do not mutate the graph directly.
```text
event -> matching behavior -> new events/state ops -> replayable state
```
```mermaid
flowchart LR
event["failure.observed"]
behavior["matching behavior"]
task["create investigation task"]
ops["state.ops_applied event"]
graphNode["replayed graph"]
event --> behavior --> task --> ops --> graphNode
```
This keeps behavior execution auditable.
## Policies
Policies can allow, deny, or require approval for sensitive actions.
The current policy foundation supports approval requests for runtime operations. More policy surfaces can be added without changing the event-sourced model.
```mermaid
flowchart TB
action["runtime action"]
policy["policy check"]
allow["allow"]
deny["deny"]
approval["approval request node"]
action --> policy
policy --> allow
policy --> deny
policy --> approval
```
## Replay, fork, diff
Replay rebuilds graph state from events.
Fork creates an alternate event history from a parent event cutoff.
Diff compares projected graphs so agents can inspect what changed between histories.
```mermaid
flowchart LR
events["events"]
cutoff["event cutoff"]
fork["fork graph"]
current["current graph"]
diff["graph diff"]
events --> cutoff --> fork
events --> current
fork --> diff
current --> diff
```