This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

Island edges are AT URI references only

Edges in org.latha.island now contain just the uri field — pointing
to the network.cosmik.connection record rather than restating its
data. The connection record is the source of truth.

- Lexicon: edge type reduced to just uri (required, at-uri format)
- island:publish: connections are {uri: atUri} only
- Analysis new connections excluded (no AT URI to reference)
- Dry-run display shows just URIs

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>

author
nandi
co-author
Letta Code
date (May 15, 2026, 6:53 AM UTC) commit ddcf359c parent 5c14f630
+18 -50
+3 -20
lexicons/org/latha/island/island.json
··· 54 54 }, 55 55 "edge": { 56 56 "type": "object", 57 - "description": "A connection edge within the island.", 58 - "required": ["uri", "source", "target"], 57 + "description": "A reference to a connection record within the island. The AT URI is the source of truth — all edge data lives in the network.cosmik.connection record.", 58 + "required": ["uri"], 59 59 "properties": { 60 60 "uri": { 61 61 "type": "string", 62 62 "format": "at-uri", 63 - "description": "AT URI of the connection record" 64 - }, 65 - "source": { 66 - "type": "string", 67 - "description": "Source vertex URI" 68 - }, 69 - "target": { 70 - "type": "string", 71 - "description": "Target vertex URI" 72 - }, 73 - "connectionType": { 74 - "type": "string", 75 - "description": "Type of connection (relates, supports, contradicts, etc.)" 76 - }, 77 - "note": { 78 - "type": "string", 79 - "maxGraphemes": 500, 80 - "description": "Optional note about the connection" 63 + "description": "AT URI of the network.cosmik.connection record" 81 64 } 82 65 } 83 66 },
+15 -30
src/island-publish.ts
··· 5 5 * on the user's PDS. Reads the SQLite cache from island:discover. 6 6 * 7 7 * The canonical island ID is the first 12 hex chars of the SHA-256 of the 8 - * lexmin vertex (lexicographically smallest URL in the component). This is 9 - * stable across runs — the same component always gets the same ID. 8 + * centroid vertex (highest closeness centrality in the component). This is 9 + * more stable than lexmin — adding a peripheral node doesn't shift the centroid. 10 10 * 11 11 * Usage: 12 12 * bun island:publish # list islands with their IDs ··· 54 54 } 55 55 56 56 function buildIslandRecord(component: Component, edges: EdgeRow[], analysis: AnalysisRow | null) { 57 - const lexmin = component.lexmin; 58 - const domain = domainFromUrl(lexmin); 57 + const centroid = component.centroid; 58 + const domain = domainFromUrl(centroid); 59 59 const nodeCount = component.nodes.size; 60 60 const edgeCount = edges.length; 61 61 const contributorCount = component.dids.size; 62 62 63 - const connections = edges.map((e) => ({ 64 - uri: e.atUri ?? '', 65 - source: e.source, 66 - target: e.target, 67 - ...(e.relation ? { connectionType: e.relation } : {}), 68 - })); 63 + const connections = edges 64 + .filter((e) => e.atUri) 65 + .map((e) => ({ uri: e.atUri })); 69 66 70 - // Merge new connections from analysis 71 - if (analysis?.new_connections) { 72 - try { 73 - const newConns = JSON.parse(analysis.new_connections) as Array<{ source: string; target: string; connectionType: string; note: string }>; 74 - for (const nc of newConns) { 75 - connections.push({ 76 - uri: '', 77 - source: nc.source, 78 - target: nc.target, 79 - connectionType: nc.connectionType, 80 - note: nc.note, 81 - }); 82 - } 83 - } catch {} 84 - } 67 + // New connections from analysis don't have AT URIs — skip them. 68 + // They belong in the analysis synthesis text, not as edge references. 85 69 86 70 // Use analysis data if available, otherwise fall back to generic 87 71 const title = analysis?.title ?? `Island: ${domain} (${nodeCount} nodes, ${edgeCount} edges)`; ··· 89 73 const synthesis = analysis?.synthesis ?? [ 90 74 `Discovered island centered on ${domain}.`, 91 75 `${nodeCount} nodes connected by ${edgeCount} edges, contributed by ${contributorCount} DIDs.`, 92 - `Lexmin vertex: ${lexmin}`, 76 + `Centroid vertex: ${centroid}`, 93 77 ].join('\n\n'); 94 78 95 79 const record: Record<string, unknown> = { 96 80 $type: 'org.latha.island', 97 81 source: { 98 - uri: lexmin, 82 + uri: centroid, 99 83 collection: 'network.cosmik.connection', 100 84 }, 101 85 connections, ··· 149 133 console.log(JSON.stringify(components.map((c) => ({ 150 134 id: c.islandId, 151 135 lexmin: c.lexmin, 136 + centroid: c.centroid, 152 137 nodeCount: c.nodes.size, 153 138 didCount: c.dids.size, 154 139 })), null, 2)); 155 140 } else { 156 141 console.log(`\n${components.length} islands:\n`); 157 142 for (const c of components.slice(0, 50)) { 158 - console.log(` ${c.islandId} ${c.nodes.size} nodes ${domainFromUrl(c.lexmin)}`); 143 + console.log(` ${c.islandId} ${c.nodes.size} nodes ${domainFromUrl(c.centroid)}`); 159 144 } 160 145 if (components.length > 50) console.log(` ... and ${components.length - 50} more`); 161 146 console.log(`\nUsage: bun island:publish <island-id> [--dry-run] [--json]`); ··· 170 155 process.exit(1); 171 156 } 172 157 173 - console.error(`Island ${component.islandId}: ${component.nodes.size} nodes, ${component.dids.size} DIDs (lexmin: ${component.lexmin})`); 158 + console.error(`Island ${component.islandId}: ${component.nodes.size} nodes, ${component.dids.size} DIDs (centroid: ${component.centroid})`); 174 159 175 160 const edges = fetchComponentEdges(db, component); 176 161 const analysis = loadAnalysis(db, component.islandId); ··· 194 179 } 195 180 console.log(`\nConnections:`); 196 181 for (const c of record.connections as Array<Record<string, string>>) { 197 - console.log(` ${c.source} -> ${c.target} ${c.connectionType ?? ''} (${c.note})`); 182 + console.log(` ${c.uri}`); 198 183 } 199 184 } 200 185 db.close();