Graph-native application state chronicle — zero-effort observability through PluresDB state diffs.
"The best log is one no developer had to write."
Traditional application logging is broken:
- Manual — developers decide what to log, inevitably missing what matters
- Flat — lines in a file with no relationships or causality
- Lossy — you only see what someone thought to capture
- Noisy — 90% garbage until something breaks, then the 10% you need is missing
If your application state is already reactive (via plures/unum), then logging is just the chain of diffs recorded in time. Every state change is a graph node. Every causal relationship is an edge. No developer effort required.
Application (using unum)
│
│ state diffs (automatic via unum subscriptions)
▼
┌─────────────────────────────┐
│ Chronos │
│ • Captures unum state diffs│
│ • Builds causal chain │
│ • Timestamps each node │
│ • Zero configuration │
└─────────────┬───────────────┘
│
▼
┌─────────────────────────────┐
│ PluresDB │
│ • Graph storage │
│ • Time-series indexing │
│ • Vector search │
│ • Hyperswarm P2P sync │
└─────────────────────────────┘
Instead of flat log lines:
[INFO] 2026-03-18T15:30:00 User clicked submit
[INFO] 2026-03-18T15:30:01 Form validated
[INFO] 2026-03-18T15:30:01 API call POST /submit
[ERROR] 2026-03-18T15:30:02 Request failed: 500
Chronos captures a state graph:
UserAction(click_submit)
├─causes→ StateChange(form.validated = true)
│ ├─causes→ APICall(POST /submit)
│ │ └─causes→ StateChange(request.error = "500")
│ └─causes→ UIUpdate(spinner.visible = true)
└─context→ Session(user_id: 7, page: /checkout)
Replace grep "ERROR" | tail -100 with graph queries:
import { chronos } from '@plures/chronos';
// What caused this error state?
const causes = await chronos.trace('request.error', { direction: 'backward' });
// What did this user action affect?
const effects = await chronos.trace(actionNode, { direction: 'forward' });
// Everything that happened in this session
const session = await chronos.subgraph({ context: 'session:abc123' });
// Semantic search across all state changes
const results = await chronos.search('authentication failures');
// Diff between working and broken states
const diff = await chronos.diff(workingSnapshot, brokenSnapshot);Chronos hooks into unum's reactive subscriptions automatically:
import { createChronos } from '@plures/chronos';
import { pluresData } from '@plures/unum';
// One line. That's it. Every state change is now chronicled.
const chronicle = createChronos(db);
// Your app code doesn't change at all
const todos = pluresData('todos');
todos.add({ text: 'Ship chronos', completed: false });
// ^ This state change is automatically captured with full causal contextEach state change becomes a ChronicleNode:
interface ChronicleNode {
id: string; // Unique node ID
timestamp: number; // Unix ms
path: string; // PluresDB path that changed (e.g. "todos.abc123")
diff: {
before: any; // Previous value (null for creates)
after: any; // New value (null for deletes)
};
cause?: string; // ID of the node that caused this change
context?: string; // Session/request/transaction context ID
stack?: string[]; // Async context chain (automatic)
}| Edge | Meaning |
|---|---|
causes |
This state change directly caused another |
context |
Belongs to this session/request/transaction |
reverts |
Undoes a previous state change |
concurrent |
Happened simultaneously (same tick) |
Chronos uses async context (AsyncLocalStorage in Node.js) to automatically track causality:
- User action triggers a state change → root node
- That change triggers a subscriber → child node with
causesedge to root - Subscriber makes an API call → grandchild node
- API response triggers more state changes → great-grandchildren
All connected automatically. No manual instrumentation.
- Zero effort — If you use unum, you get chronos for free
- Complete — Every state change captured, not just what devs remember to log
- Structural — Graph, not text. Relationships, not lines.
- Queryable — Semantic search, graph traversal, time-range queries
- Distributed — PluresDB Hyperswarm sync means multi-node observability with just a topic key
- Minimal overhead — Append-only writes, async batching, configurable retention
- Core: unum subscription → PluresDB graph writer
- Causal chain inference via AsyncLocalStorage
- Time-range queries
- Semantic search over state changes
- Graph traversal API (trace forward/backward)
- Subgraph extraction (by context/session)
- Snapshot diff (compare two points in time)
- Retention policies (TTL, importance-based pruning)
- Dashboard UI (design-dojo component)
- PluresDB Hyperswarm sync for distributed observability
| Package | Role |
|---|---|
| PluresDB | Graph database with vector search + Hyperswarm |
| Unum | Reactive state bindings (Svelte 5 ↔ PluresDB) |
| Chronos | State chronicle (zero-effort observability) |
| Pares Agens | AI agent framework |
| Design Dojo | UI component library |
| Plures Vault | Encrypted secret storage |
AGPL-3.0-or-later