viv-knowledge-diagrams
v0.2.0
Published
Knowledge-spread visualizations for Viv projects — who knows what, how they learned it, and how knowledge propagated through the world.
Downloads
256
Maintainers
Readme
viv-knowledge-diagrams
Text-based knowledge-spread visualizations for Viv projects. Shows who knows what, how they learned it, and how knowledge propagated through the world.
Works with any Viv project. Peer dependency on @siftystudio/viv-runtime.
Setup
With Claude Code
Ask Claude Code to add viv-knowledge-diagrams to your project. Claude will:
npm install viv-knowledge-diagrams- Create
.claude/commands/directory - Copy the knowledge diagram commands into your project
You'll then have three new commands available:
/knowledge-tree— who told whom about an action/knowledge-map— what a character knows/knowledge-wave— temporal spread of knowledge
Without Claude Code
- Install in your Viv project:
npm install viv-knowledge-diagrams- Import and call from your code:
import { fromAdapter, constructKnowledgeTreeDiagram } from "viv-knowledge-diagrams";
// After initializing the Viv runtime with your adapter:
const ds = fromAdapter(myAdapter);
// Pick an action ID from the chronicle and visualize its spread
const diagram = await constructKnowledgeTreeDiagram({
dataSource: ds,
actionID: someActionID,
showTellers: true,
});
console.log(diagram);Prerequisite: knowledge-relaying actions
The diagrams are only interesting if your .viv code has actions that relay knowledge about past events. This means actions that cast a past action in a role using search query:
action retell-market-drama:
roles:
@teller:
as: initiator
@audience:
as: partner
@pastEvent:
as: action
from:
search query noteworthy-event:
over: @teller
...
query noteworthy-event:
importance:
>=: 3
salience:
>=: 1When @pastEvent is cast, Viv automatically propagates knowledge of that event to everyone present. Without actions like this, all memories are first-person witnessed and there are no relay chains to visualize.
Three diagrams
Knowledge tree
"How did knowledge of this action spread?"
Characters are the nodes, actions are the labeled edges. Reads top-down: who knew, how they told, who learned next.
◉ whisper-rumor-about
Witnessed by: Bran, Lirael t=1560
Spread:
Bran (witness)
└──[warn-about-merchant]──▶ Brull, Cedric t=1620
Cedric (secondhand)
└──[retell-market-drama]──▶ Horik, Hrag, Korg, Gork t=1680
28 knowers / 164 charactersawait constructKnowledgeTreeDiagram({
dataSource: ds,
actionID: "...",
showTellers: true,
});Memory map
"What does this character know?"
Groups memories into witnessed vs. learned secondhand, with salience and the relay action that carried the knowledge.
◉ Varr — 133 memories (11 secondhand)
Witnessed (122):
retell-market-drama sal:6 t=1740
hold-court-from-bench sal:4 t=300
Learned secondhand (11):
whisper-rumor-about sal:5 t=1620 <- heard via elder-recounts-old-taleawait constructMemoryMapDiagram({
dataSource: ds,
characterID: "...",
sortBy: "salience",
limit: 15,
});Propagation wave
"In what order did knowledge spread?"
Timeline of waves. Each wave shows who learned, how (the relay action), and from whom (the teller).
◉ whisper-rumor-about
Wave 0 — t=1560
Witnessed: Bran, Lirael
Wave 1 — t=1620
Learned: Brull, Cedric
How: warn-about-merchant
From: Bran
Wave 2 — t=1680
Learned: Horik, Hrag, Korg, Gork, Krall, Mad Tilda
How: retell-market-drama
From: Cedric
28 / 164 characters know (17% penetration)await constructPropagationWaveDiagram({
dataSource: ds,
actionID: "...",
showTellers: true,
showStats: true,
});Adapter contract
fromAdapter() expects your HostApplicationAdapter.getEntityView() to return entity objects with specific properties:
Characters must have a memories object:
type CharacterMemories = {
[actionID: UID]: {
formationTimestamp: number; // When the character learned this
salience: number; // 0–infinity, higher = more important to remember
forgotten: boolean; // Whether the character forgot this
sources: UID[]; // Action IDs that caused knowledge formation
associations: string[]; // Tags for querying/filtering
};
};Actions must have a present array:
type ActionView = {
present: UID[]; // Character IDs who witnessed this action
// ... other action properties
};If your adapter doesn't populate these fields, fromAdapter() will throw a descriptive error explaining what's missing.
Custom data source
If you don't want to pass the full adapter, implement KnowledgeDataSource directly:
import type { KnowledgeDataSource } from "viv-knowledge-diagrams";
const ds: KnowledgeDataSource = {
getAllCharacterIDs: () => [...],
getCharacterMemories: (id) => characters[id].memories, // Returns CharacterMemories object
getActionPresent: (id) => actions[id].present, // Returns UID[] of witnesses
getEntityLabel: (id) => entities[id].name,
};Options
All three functions accept:
| Option | Default | Description |
|--------|---------|-------------|
| dataSource | required | KnowledgeDataSource or result of fromAdapter() |
| ansi | false | ANSI terminal colors |
| showForgotten | false | Include forgotten memories |
| showTellers | false | Identify who told whom (costs more but richer output) |
| formatCharacterLabel | getEntityLabel | Custom character name formatter |
| formatActionLabel | getEntityLabel | Custom action name formatter |
Plus per-diagram:
- Knowledge tree:
showTimestamps(defaulttrue) - Memory map:
sortBy("salience"|"timestamp"),limit - Propagation wave:
showStats(defaulttrue)
License
MIT
