Skip to content

fix(context): residual Concept label demotion via pre-loop definitions arg + cross-chunk first-wins ordering #360

@arthurfantaci

Description

@arthurfantaci

Follow-up to #359

Issue #359 fixed the most common Concept-demotion trigger: the per-chunk glossary_definitions path unconditionally overwriting an existing entity's label to "Definition". That fix lands in PR (in flight at time of filing).

A code-review subagent on the #359 PR flagged two residual triggers of the SAME bug class that are out of scope for #359 but still suppress purple Concept badges in less common situations. Filing this issue so the work isn't lost.

Residual trigger 1 — pre-loop definitions parameter

backend/src/requirements_graphrag_api/core/context.py:200-221 runs BEFORE the per-chunk loop:

```python
if definitions:
for defn in definitions:
if defn.get("score", 0) >= 0.5:
...
all_entities[defn["term"]] = {
"definition": defn.get("definition"),
"label": "Definition", # <-- hardcoded
}
```

If a chat-flow caller ever passes the definitions parameter (currently the orchestrator at core/agentic/orchestrator.py:163 does NOT pass it — only the structured-search path may), entries land first as label "Definition". When the per-chunk entity-path subsequently encounters the same name as a :Concept graph node, the if name not in all_entities check at line 235 is False, the elif at line 237 only updates definition (never label), and the Concept label is silently suppressed.

Residual trigger 2 — cross-chunk first-wins ordering

Within the per-chunk loop, if chunk N's glossary_definitions populates {label: \"Definition\"} for a term first, chunk N+1's :Concept entity with the same name cannot upgrade the label. Same root cause as Trigger 1: the entity-path's elif at line 237-238 never updates label.

Why this is a separate issue from #359

#359 fixed the unconditional STOMP on existing entries (line 253). These two residuals are about FIRST-WRITER-WINS preventing a Concept upgrade. Different mechanism, same outcome.

Suggested fix sketch (not committing to an approach)

Make the entity-path's elif (line 237-238) ALSO upgrade the label when the new label is more specific than the existing one. "Definition" should be considered the LEAST specific label (it's a fallback for glossary-only entries); any actual Neo4j node label (Concept, Standard, Bestpractice, Challenge, Methodology, Artifact, Tool, Role, Processstage, Industry, Organization, Outcome) should win over Definition.

Pseudocode:

```python
elif definition and not all_entities[name].get("definition"):
all_entities[name]["definition"] = definition
elif all_entities[name].get("label") == "Definition" and label != "Definition":
all_entities[name]["label"] = label # upgrade Definition -> Concept/Standard/etc.
```

This needs a regression test asserting the upgrade direction works correctly without re-introducing the demotion direction.

HITL gates

Same as #359: backend-only, no preview verification path, post-merge production check by user.

Workflow

Defer until #359 ships and is production-verified. Then re-evaluate based on whether either trigger is firing in practice (data probe production Neo4j; check if definitions arg is being passed anywhere in the chat flow; check if cross-chunk ordering produces demotions for any Concept the user actually retrieves).

If neither trigger is firing in practice, this issue can be closed as not-reproducible-in-production with a note that the code paths still have the latent bug and would need addressing if a future caller adds the trigger.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions