# Source Attribution ## Goal Every fact in the brain traces to where it came from -- who said it, in what context, and when. ## What the User Gets Without this: six months from now, someone reads a brain page and has no idea if "Pedro co-founded Brex" came from Pedro himself, a LinkedIn scrape, or a hallucination. With this: every claim is auditable, conflicts are surfaced, and the brain is a court-admissible record of reality. ## Implementation ``` on brain_write(page, fact): # EVERY fact gets a citation -- compiled truth AND timeline citation = format_citation(source) # format: [Source: {who}, {channel/context}, {date} {time} {tz}] # Category-specific formats: if source.type == "direct": # [Source: User, direct message, 2026-04-07 12:33 PM PT] elif source.type == "meeting": # [Source: Meeting notes "Team Sync" #12345, 2026-04-03 12:11 PM PT] elif source.type == "api_enrichment": # [Source: Crustdata LinkedIn enrichment, 2026-04-07 12:35 PM PT] elif source.type == "social_media": # MUST include full URL -- not just @handle # [Source: X/@pedroh96 tweet, product launch, 2026-04-07](https://x.com/pedroh96/status/...) elif source.type == "email": # [Source: email from Sarah Chen re Q2 board deck, 2026-04-05 2:30 PM PT] elif source.type == "workspace": # [Source: Slack #engineering, Keith re deploy schedule, 2026-04-06 11:45 AM PT] elif source.type == "web": # [Source: Happenstance research, 2026-04-07 12:35 PM PT] elif source.type == "published": # [Source: [Wall Street Journal, 2026-04-05](https://wsj.com/...)] elif source.type == "funding": # [Source: Captain API funding data, 2026-04-07 2:00 PM PT] # Attach citation inline with the fact gbrain put --content "...fact [Source: ...]..." # When sources conflict, note BOTH -- never silently pick one if conflicts_exist(fact, existing_page): append_to_compiled_truth( "Conflict: Source A says X, Source B says Y. " "[Source: A] [Source: B]" ) # Source hierarchy for conflict resolution (highest authority first): SOURCE_PRIORITY = [ "User direct statements", # 1 -- always wins "Primary sources", # 2 -- meetings, emails, direct conversations "Enrichment APIs", # 3 -- Crustdata, Happenstance, Captain "Web search results", # 4 "Social media posts", # 5 ] ``` ## Tricky Spots 1. **Compiled truth is NOT exempt from citations.** "Pedro co-founded Brex" in the synthesis section needs `[Source: ...]` just as much as a timeline entry does. Most agents skip citations above the bar. 2. **Tweet URLs are mandatory.** `[Source: X/@handle tweet, topic, date]` without a URL is a broken citation. Hundreds of brain pages end up with unreachable tweet references when the URL is omitted. Always: `[Source: X/@handle tweet, topic, date](https://x.com/handle/status/ID)`. 3. **"User said it" isn't enough.** WHERE, ABOUT WHAT, WHEN. `[Source: User, direct message, 2026-04-07 12:33 PM PT]` -- not just `[Source: User]`. 4. **Don't silently resolve conflicts.** When the user says one thing and an API says another, note the contradiction in compiled truth with both citations. Let the reader decide. 5. **Timeline entries need sources too.** Every append to the timeline carries provenance. A timeline entry without a source is an orphan fact. ## How to Verify 1. Open any brain page with `gbrain get `. Read the compiled truth section above the bar. Every factual claim should have an inline `[Source: ...]` citation. 2. Search for tweet references: `gbrain search "X/@"`. Every result should have a full URL, not just an @handle. 3. Find a page with data from multiple sources (e.g., a person enriched via API + mentioned in a meeting). Confirm both sources are cited independently. 4. Check timeline entries on 3 random pages. Each entry should have a source citation with date and context. 5. Look for a page where the user stated something that contradicts an API result. Confirm the contradiction is noted, not silently resolved. --- *Part of the [GBrain Skillpack](../GBRAIN_SKILLPACK.md).*