soul.demarkus.io:6309/journal/2026-07-14.md/v3 draft reader meta

Journal 2026-07-14

Graph hub seeding implemented (branch graph-hub-seed, PR pending)

Implemented /plans/graph-hub-seed.md end to end: graphstore SeedFromExport + persisted seed_etags (additive, schema v1), fetch.FetchConditional with explicit if-none-match, seedGraph hooks in demarkus-mcp's mark_backlinks/mark_graph/mark_explore, and per-world seedWorldGraph on the broker through dispatchWithAuth (FetchConditional added to worldDispatcher; trivial passthrough). Local-wins rule held as designed: authoritative = real fetched status plus non-zero CrawledAt, seeded nodes carry zero CrawledAt, and the rule is shared with Merge via extracted dropEdgesFromLocked/upsertEdgeLocked helpers. Never fatal, 5-minute per-host throttle. ParseExport's first production caller; the soul's live /graph.md is still two-column legacy (v6) and seeded fine.

The interesting find: the first live cold-start check returned no backlinks despite a successful seed. Root cause was URL canonicalization, not seeding. The hub aggregate keys rows on canonical mark://host:6309 URLs while mark_backlinks built its key as defaultHost + path, and the plugin's -host flag omits the port. A latent pre-existing mismatch (portless -host crawls vs full-URL queries) that seeding surfaced. Fixed by canonicalizing through resolveURL in markBacklinks, markGraph's start URL, and explore's backlinks section, with a regression test pinning the portless -host case. Recorded in the plan's implementation notes.

Verification: full client + tools suites green, pre-commit clean, live cold start (scratch HOME) answered 4 backlinks for /patterns.md with zero crawls (133 nodes / 190 edges seeded, etag persisted, all zero CrawledAt), then a depth-1 crawl of /conventions.md flipped it authoritative and its enriched edges replaced the seeded row while 130 nodes stayed seeded. FetchConditional got the client's first wire-level test (in-process QUIC listener, self-signed cert).

Roadmap updated (seeding item IMPLEMENTED; flip to DONE on merge). PR 251 bookkeeping (edge-semantics DONE flip, debt.md fetch-callback removal) was already done last session. Changes staged; Fritz commits.

Out of scope confirmed untouched: TUI seeding, Exported-timestamp arbitration, publish-time edge extraction.

PR 253 review round

CodeRabbit posted three findings; all valid, all fixed (details appended to the plan doc): seedGraph now seeds the resolved host from the tool URL instead of only defaultHost, and SeedFromExport's edge-drop set now includes observed seed nodes so a source whose outgoing set went to zero sheds its stale seeded edges (Merge's refreshed criterion, shared via a new observedStatus helper). One test-only guard: seedGraph tolerates a nil client since partial handlers in tests construct without one. Suites and pre-commit green, changes staged.

trail
  1. soul.demarkus.io:6309 v3