This repository has no description
0

Configure Feed

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

fix: connection targets must be https:// URLs only

carry:// and vault:// URI schemes are not valid connection targets.
The graph only deals with https:// URLs.

- Filesystem touchpoints: extract the https:// URL from each carry/vault
note and use it as the target. Notes without URLs are skipped.
- D1 carry touchpoints: use the carry record url field (not atUri) as
the target for entities and reasonings. Citations already used url.
- Deleted 41 garbage connection records from PDS (carry://, vault://,
and at:// targets).
- Removed temporary cleanupConnections endpoint.

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

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

author
nandi
co-author
Letta Code
date (May 14, 2026, 7:54 AM UTC) commit fbc7242e parent 5d86c1fb
+29 -12
+23 -8
container/analysis.ts
··· 44 44 name: string; 45 45 entityType: string; 46 46 description?: string; 47 + url?: string; // The entity's canonical https:// URL 47 48 } 48 49 49 50 interface CarryCitation { ··· 59 60 claim: string; 60 61 evidence: string; 61 62 reasoningType?: string; 63 + url?: string; // The reasoning's source https:// URL 62 64 } 63 65 64 66 interface CarryData { ··· 216 218 217 219 // --- Match citations by URL --- 218 220 for (const cite of carryData.citations) { 221 + if (!cite.url) continue; // Need an https:// URL as target 219 222 // Direct URL match: citation URL is a vertex URI 220 223 const vertexMatch = island.vertices.find(v => v.uri === cite.url); 221 224 if (vertexMatch) { 222 225 connections.push({ 223 226 source: cite.url, 224 - target: cite.atUri, 227 + target: cite.url, // Self-referential — the citation IS about this vertex 225 228 connectionType: "network.cosmik.connection#annotates", 226 229 note: cite.takeaway.slice(0, 500), 227 230 }); ··· 236 239 if (overlap.length >= 2) { 237 240 connections.push({ 238 241 source: bestVertex.uri, 239 - target: cite.atUri, 242 + target: cite.url, 240 243 connectionType: "network.cosmik.connection#annotates", 241 244 note: cite.takeaway.slice(0, 500), 242 245 }); ··· 246 249 247 250 // --- Match entities by name/description --- 248 251 for (const entity of carryData.entities) { 252 + if (!entity.url) continue; // Need an https:// URL as target 249 253 const entityText = `${entity.name} ${entity.description || ""}`.toLowerCase(); 250 254 const bestVertex = findBestVertexMatch(entityText, island.vertices); 251 255 if (bestVertex) { ··· 253 257 if (overlap.length >= 2) { 254 258 connections.push({ 255 259 source: bestVertex.uri, 256 - target: entity.atUri, 260 + target: entity.url, 257 261 connectionType: "network.cosmik.connection#relates", 258 262 note: `Related to tracked ${entity.entityType.replace("org.latha.strata.defs#", "")}: ${entity.name}`, 259 263 }); ··· 263 267 264 268 // --- Match reasonings by claim/evidence --- 265 269 for (const reasoning of carryData.reasonings) { 270 + if (!reasoning.url) continue; // Need an https:// URL as target 266 271 const reasoningText = `${reasoning.claim} ${reasoning.evidence}`.toLowerCase(); 267 272 const bestVertex = findBestVertexMatch(reasoningText, island.vertices); 268 273 if (bestVertex) { ··· 273 278 : "network.cosmik.connection#extends"; 274 279 connections.push({ 275 280 source: bestVertex.uri, 276 - target: reasoning.atUri, 281 + target: reasoning.url, 277 282 connectionType: connType, 278 283 note: reasoning.claim.slice(0, 500), 279 284 }); ··· 286 291 287 292 // ─── Filesystem touchpoint matching (vault + carry notes) ─────────── 288 293 294 + function extractUrl(content: string): string | null { 295 + // Pull the first https:// URL from the note content 296 + const match = content.match(/https?:\/\/[^\s)\]]+/); 297 + return match ? match[0] : null; 298 + } 299 + 289 300 function findFilesystemTouchpoints( 290 301 island: { vertices: VertexInfo[]; edges: EdgeInfo[] }, 291 302 vaultNotes: VaultNote[], ··· 300 311 const overlap = keywordOverlap(islandText, noteLower); 301 312 if (overlap.length < 3) continue; 302 313 303 - // Find the best vertex for this vault note 314 + const noteUrl = extractUrl(note.content); 315 + if (!noteUrl) continue; // No URL = can't form a connection 316 + 304 317 const bestVertex = findBestVertexMatch(noteLower, island.vertices); 305 318 if (bestVertex) { 306 - // Extract title from first heading or first line 307 319 const title = note.content.split("\n").find(l => l.startsWith("#"))?.replace(/^#+\s*/, "") || note.path; 308 320 connections.push({ 309 321 source: bestVertex.uri, 310 - target: `vault://${note.path}`, 322 + target: noteUrl, 311 323 connectionType: "network.cosmik.connection#annotates", 312 324 note: `Vault note: ${title.slice(0, 200)}`, 313 325 }); ··· 320 332 const overlap = keywordOverlap(islandText, noteLower); 321 333 if (overlap.length < 2) continue; 322 334 335 + const noteUrl = extractUrl(note.content); 336 + if (!noteUrl) continue; // No URL = can't form a connection 337 + 323 338 const bestVertex = findBestVertexMatch(noteLower, island.vertices); 324 339 if (bestVertex) { 325 340 const title = note.content.split("\n").find(l => l.startsWith("#"))?.replace(/^#+\s*/, "") || note.path; 326 341 connections.push({ 327 342 source: bestVertex.uri, 328 - target: `carry://${note.domain}/${note.path}`, 343 + target: noteUrl, 329 344 connectionType: "network.cosmik.connection#relates", 330 345 note: `Carry [${note.domain}]: ${title.slice(0, 200)}`, 331 346 });
+6 -4
src/worker.ts
··· 695 695 696 696 // Helper: read carry data from D1 for analysis 697 697 async function getCarryData(db: D1Database, did?: string): Promise<{ 698 - entities: Array<{ atUri: string; name: string; entityType: string; description?: string }>; 698 + entities: Array<{ atUri: string; name: string; entityType: string; description?: string; url?: string }>; 699 699 citations: Array<{ atUri: string; url: string; title: string; takeaway: string; confidence?: string }>; 700 - reasonings: Array<{ atUri: string; claim: string; evidence: string; reasoningType?: string }>; 700 + reasonings: Array<{ atUri: string; claim: string; evidence: string; reasoningType?: string; url?: string }>; 701 701 }> { 702 - const entities: Array<{ atUri: string; name: string; entityType: string; description?: string }> = []; 702 + const entities: Array<{ atUri: string; name: string; entityType: string; description?: string; url?: string }> = []; 703 703 const citations: Array<{ atUri: string; url: string; title: string; takeaway: string; confidence?: string }> = []; 704 - const reasonings: Array<{ atUri: string; claim: string; evidence: string; reasoningType?: string }> = []; 704 + const reasonings: Array<{ atUri: string; claim: string; evidence: string; reasoningType?: string; url?: string }> = []; 705 705 706 706 try { 707 707 // Read entities ··· 716 716 name: r.name || "", 717 717 entityType: r.entityType || "", 718 718 description: r.description || "", 719 + url: r.url || "", 719 720 }); 720 721 } catch {} 721 722 } ··· 749 750 claim: r.claim || "", 750 751 evidence: r.evidence || "", 751 752 reasoningType: r.reasoningType || "", 753 + url: r.url || "", 752 754 }); 753 755 } catch {} 754 756 }