Skip to content

fix: enrichment now reaches the agent and the resolver - #18

Merged
kiyeonjeon21 merged 1 commit into
mainfrom
feat/enrichment-reaches-resolution
Jul 25, 2026
Merged

fix: enrichment now reaches the agent and the resolver#18
kiyeonjeon21 merged 1 commit into
mainfrom
feat/enrichment-reaches-resolution

Conversation

@kiyeonjeon21

Copy link
Copy Markdown
Owner

Why

Found while designing the harder trap dataset: enrich --apply was writing descriptions and synonyms that nothing ever read back. Any eval trap depending on a glossary would have failed in both arms, so this had to be fixed before the dataset work could mean anything.

Four separate links in the chain were broken:

  1. No readGlossary existed, and prepareDataset rebuilt the semantic model from profiles unconditionally - so enrichment was discarded before the next ask.
  2. mergeGlossary dropped any entry naming a column that is not a dimension. A numeric column always becomes a measure, so every money term in a glossary hit that continue and vanished.
  3. SemanticDimension/SemanticMeasure had no synonyms field, and no code path could add one to a measure.
  4. buildTermCatalog indexed only names; descriptions went into the embed-only text field and were never scored lexically.

What changed

glossary.json becomes the second curation layer, symmetric with the one that already exists:

file curates applied over
verdicts.json which joins are real freshly inferred relationships
glossary.json what things mean the freshly derived semantic model

Plus: column-level glossary entries resolve against measures as well as dimensions; dimensions and measures carry synonyms and the term catalog indexes them; and the grounding context renders descriptions and inline annotations so enrichment is visible to the agent rather than only to the YAML file.

The observable difference

Verified against the real engine, same dataset, with and without a glossary mapping "revenue" to a numeric column:

WITHOUT glossary: resolveTerms("net revenue") -> No matching terms.
WITH glossary:    resolveTerms("net revenue") -> net revenue => sum_unit_price, revenue => sum_unit_price

Verification

  • npm run check exit 0
  • npm run test:cli 136 pass / 0 fail - all 131 existing tests untouched, which is the proof this is additive
  • npm run eval:engine 18/18, unchanged
  • 5 new tests pin each link: measure-mapped entries survive, dimension synonyms skip the column's own name, the resolution flip, context rendering, and glossary.json curation end-to-end through prepareDataset (including that an eval-style outDir reads no curation and the explicit override is the way back in)

Stage 1 of 3 for the trap-dataset work; shipped separately so it can be judged on its own and so a later bisect can separate it from the dataset change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CKZ9UVgw2Mhiu6T5YAG7k6

querypad enrich --apply wrote descriptions and synonyms that nothing ever read
back. Four separate links in the chain were broken:

1. There was no readGlossary, and prepareDataset rebuilt the semantic model from
   profiles unconditionally, so enrichment was discarded before the next ask.
   glossary.json is now a curation input re-applied over the derived model,
   exactly as verdicts.json is re-applied over inferred relationships. Same
   contract: honored by every surface, preserved across re-runs.
2. mergeGlossary dropped any entry naming a column that was not a dimension. A
   numeric column always becomes a measure, so every money term in a glossary hit
   that continue and vanished. Column-level entries now resolve against measures
   too.
3. SemanticDimension and SemanticMeasure had no synonyms field, and there was no
   code path that could add one to a measure.
4. buildTermCatalog indexed only names; descriptions went into the embed-only
   text field and were never scored lexically.

Net effect, and the reason this matters for the trap dataset work: a business
word can now reach an opaque column. resolve_terms("net revenue") returns
sum_amt_c where it previously returned "No matching terms" - verified against
the real engine both ways.

The grounding context also renders descriptions and inline dimension/measure
annotations, so enrichment is visible to the agent instead of only to the YAML.

All 131 existing tests pass untouched (the change is additive); 5 new tests pin
the measure-mapping path, synonym indexing, the resolution flip, the context
rendering, and glossary.json curation through prepareDataset.
@kiyeonjeon21
kiyeonjeon21 merged commit 81f7c2a into main Jul 25, 2026
1 check passed
@kiyeonjeon21
kiyeonjeon21 deleted the feat/enrichment-reaches-resolution branch July 25, 2026 14:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant