Lossless Changelog
component

Assure Disambiguation During Research

Strengthens entity disambiguation to prevent research agents from conflating similarly-named organizations. Adds both improved prompt language and a mechanical post-synthesis override that forces correct company identity regardless of what the LLM returns.

Changelog - 2026-03-23_03

Assure Disambiguation During Research

Strengthens entity disambiguation to prevent research agents from conflating similarly-named organizations. Adds both improved prompt language and a mechanical post-synthesis override that forces correct company identity regardless of what the LLM returns.


Why

The Metabologic deal has been plagued by disambiguation failures across four versions (v0.0.1 through v0.2.3). Despite the company JSON containing explicit disambiguation exclusions for metabolic.nl, metabolic.ai, and metabolic.com, Perplexity consistently returned research about "Metabolic AI" (a different company at metabolic.ai) instead of Metabologic (metabologic.ai).

The contamination path:

research_enhanced.py sends queries to Perplexity
    → Perplexity finds metabolic.ai (more prominent company)
    → Claude synthesizes results into JSON with website: "metabolic.ai"
    → fact_checker detects entity mismatch
    → ALL sections flagged for rewrite, overall score forced to 0%

The entity mismatch cascaded through the entire pipeline, making the memo useless despite most content being accurate.


What Changed

Layer 1: Improved Prompt Language

Both research_enhanced.py and perplexity_section_researcher.py now use stronger disambiguation prompts that frame the problem from the LLM's perspective:

Before:

EXCLUDED ENTITIES - DO NOT USE DATA FROM THESE DOMAINS:
- metabolic.nl (WRONG company, different entity)
- metabolic.ai (WRONG company, different entity)

If you find information from these domains, DISCARD IT completely.

After:

WARNING — COMMONLY CONFUSED ORGANIZATIONS:
Research agents often find similar-sounding organizations, then incorrectly
include information about them in the research. The following have been
identified as confusing and require disambiguation. These are NOT Metabologic:

- metabolic.nl — This is a DIFFERENT organization, NOT Metabologic
- metabolic.ai — This is a DIFFERENT organization, NOT Metabologic
- metabolic.com — This is a DIFFERENT organization, NOT Metabologic

MANDATORY RULES FOR DISAMBIGUATION:
1. Do NOT include any information sourced from the domains listed above.
2. Do NOT reference, cite, or describe the organizations at those domains.
3. If a search result comes from one of those domains, SKIP IT entirely.
4. If you cannot find information about Metabologic specifically
   (website: https://www.metabologic.ai/), say "Data not available"
   rather than substituting information from a similar-sounding organization.
5. The ONLY correct company is at https://www.metabologic.ai/.

Key changes: leads with why LLMs make this mistake, gives explicit safe fallback ("say Data not available"), anchors the correct entity positively.

Commit: 39bad3d

Layer 2: Mechanical Post-Synthesis Override

After Claude synthesizes web research into structured JSON, the agent now mechanically overrides company.website and company.name with known-correct values from state. This runs regardless of what the LLM decided.

PYTHON
# After LLM returns research JSON:
if company_url and "company" in research_data:
    llm_website = research_data["company"].get("website", "")
    if llm_website and llm_website != company_url:
        llm_domain = extract_domain(llm_website)
        is_excluded = any(llm_domain == excl for excl in disambiguation_excludes)
        if is_excluded:
            print(f"  DISAMBIGUATION OVERRIDE: '{llm_website}' is an excluded domain")
        # Always force the known-correct URL
        research_data["company"]["website"] = company_url

if company_name and "company" in research_data:
    llm_name = research_data["company"].get("name", "")
    if llm_name and company_name.lower() not in llm_name.lower():
        print(f"  DISAMBIGUATION OVERRIDE: LLM returned '{llm_name}', expected '{company_name}'")
        research_data["company"]["name"] = company_name

Commit: 06e71be

What This Does NOT Fix

The mechanical override prevents wrong-company identity from propagating (URL, name). It does NOT filter wrong-company content — if Perplexity returns team bios, funding data, or metrics about the wrong company, those may still appear in the research narrative. Content-level filtering would require a post-research validation agent that semantically evaluates each research finding against the known company identity.


Verification (Metabologic v0.2.3 → v0.2.4)

Metricv0.2.3 (before)v0.2.4 (after)
Entity mismatch detectedYes (metabolic.ai vs metabologic.ai)None
Fact-check overall score0% (forced by mismatch)66%
Disambiguation override firedN/AYes (both website and name)
Sections flagged for rewrite7/7 (all)Based on actual claim quality
Scorecard score2.8/53.2/5

Files Changed

FileChange
src/agents/research_enhanced.pyRewrote disambiguation prompt; added mechanical post-synthesis override
src/agents/perplexity_section_researcher.pyRewrote disambiguation prompt with same stronger language