${escapeHtml(room.name)}${escapeHtml(room.displayName ?? room.name)}
${escapeHtml(room.purpose)}
${escapeHtml(latest.summary ?? "No state snapshot yet.")}
const app = document.querySelector("#app");
const ROOM_LABELS = {
"void/research": "Research",
"void/art": "Art",
"void/homelab": "Homelab",
};
const KIND_LABELS = {
roomDefinitions: "definition",
roomStates: "state",
submissions: "submission",
artifacts: "artifact",
actions: "action",
moderation: "moderation",
digests: "digest",
provenance: "provenance",
};
function escapeHtml(value) {
return String(value ?? "")
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """)
.replaceAll("'", "'");
}
function formatDate(value) {
if (!value) return "undated";
const date = new Date(value);
if (Number.isNaN(date.getTime())) return value;
return date.toLocaleString(undefined, { year: "numeric", month: "short", day: "2-digit", hour: "2-digit", minute: "2-digit" });
}
function recordText(record) {
const value = record?.value ?? {};
return value.summary ?? value.text ?? value.purpose ?? value.body ?? value.action ?? value.method ?? value.status ?? JSON.stringify(value, null, 2);
}
function recordRoom(record) {
return record?.value?.room ?? record?.value?.scope ?? "network";
}
function recordTitle(record) {
const value = record?.value ?? {};
return value.title ?? value.action ?? value.status ?? KIND_LABELS[record.kind] ?? "record";
}
function truncate(value, max = 360) {
const text = String(value ?? "").trim();
if (text.length <= max) return text;
return `${text.slice(0, max).trim()}…`;
}
function shortUri(uri) {
return String(uri ?? "").split("/").at(-1) || uri;
}
function totalRecords(counts = {}) {
return Object.values(counts).reduce((sum, value) => sum + Number(value ?? 0), 0);
}
function allRecords(data) {
const records = [];
for (const room of data.rooms ?? []) records.push(...(room.timeline ?? []));
records.push(...(data.recent ?? []));
const byUri = new Map();
for (const record of records) byUri.set(record.uri, record);
return [...byUri.values()].sort((a, b) => new Date(b.createdAt ?? 0) - new Date(a.createdAt ?? 0));
}
function roomClass(name) {
return `room-${String(name ?? "network").replace("void/", "").replace(/[^a-z0-9-]/gi, "-")}`;
}
function roomCard(room) {
const latest = room.latestState?.value ?? {};
const counts = room.counts ?? {};
return ` ${escapeHtml(room.purpose)} ${escapeHtml(latest.summary ?? "No state snapshot yet.")} ${escapeHtml(truncate(recordText(record)))} ${escapeHtml(data.namespace)} This page is the plain data browser: room state, open seams, and recent canonical records. The main site explains the experience; this page keeps the trail inspectable.${escapeHtml(room.name)}${escapeHtml(room.displayName ?? room.name)}
${escapeHtml(recordTitle(record))}
record value
${escapeHtml(JSON.stringify(record.value, null, 2))}
${escapeHtml(shortUri(record.uri))}
${items.map((item) => `
Void room records.
network.comind.void.*
${escapeHtml(error.message)}