Skip to content

The semantic layer gets measured, and exploration learns to align - #567

Merged
WaylandYang merged 17 commits into
devfrom
bench/mapping-truth
Sep 9, 2026
Merged

The semantic layer gets measured, and exploration learns to align#567
WaylandYang merged 17 commits into
devfrom
bench/mapping-truth

Conversation

@WaylandYang

@WaylandYang WaylandYang commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Three measuring benches for the semantic layer, the coverage cut of #503, and decision record 0036.

Benches (scripts/bench/)

  • mappings.mjs (A mapping proposal has never been scored #501) scores what exploration proposes. Judgement is by number: a truth entry is a definition plus one gold SQL, the proposal is run against the same rows, same number means same definition whatever the model named it. Four columns — covered, right, wrong, broken — and wrong (runs, matches nothing) is the one that decides whether automatic confirmation could ever be default-on. Two corpora: TPC-H (schema and definitions from the specification's 22 queries, rows from generate_series, comments as a separate file so their value is measurable) and wide, a flattened e-commerce order table whose every definition carries a convention the columns do not state.
  • ask.mjs (A chat answer is never checked against the data #520) scores chat end to end: it asks each question, re-runs the SQL the model actually ran, and compares with the gold — two columns, sql_right and answer_right, because they come apart. --replay re-scores from the conversations already in the base (seconds, not forty minutes); --seed writes the truth as confirmed definitions (the upper bound); --confirm confirms what exploration proposed (the product path); --parallel N asks several at once.
  • lib.mjs holds the one same() both benches use, so their numbers are on one scale.

Numbers, recorded on #501 and #520:

exploration covered chat right
TPC-H, none 8/24 after #503 (6/24 before) 23/24
TPC-H, exploration confirmed 24/24
wide, none 0/18 2/18
wide, conventions as one page of prose 14/18
wide, truth seeded 17/18

#503 — an exploration says what it covered

proposal_cap scales with the schema instead of a fixed 12 (TPC-H coverage 25% → 33%); the schema-text cap is now a real cross-source bound; a run writes a row in mapping_exploration_runs (tables and columns scanned, truncation, cap, returned, accepted, drops with an example each, tables covered, error); last_run on GET /kbs/{id}/mappings. Single-source bases accept whatever source the model echoes — the first bench run lost all twelve proposals to a source name with a timestamp in it. Migration 0044.

0036 — Exploration aligns a schema to the ontology

Exploration today inserts two classes and makes concepts entities of them; the wide base had 93 concept entities, most of them column names. The record moves the concept: an attribute of a real class, or a rule over such attributes; exploration proposes an alignment per table through ontology_proposals; conversions are 0032's expression tree; concept_mappings becomes rendered. Revision notes on 0009 and 0011. Decision 7 is implemented in #561; the written-definition door is #563; the conventions-as-prose dead end was measured at 14/18 and revised in place. Follow-ups: #554, #555, #556.

Also renumbers the exploration-ledger migration to 0044 (dev took 0041) and merges dev.

🤖 Generated with Claude Code

WaylandYang and others added 13 commits September 8, 2026 20:52
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
WaylandYang and others added 2 commits September 10, 2026 07:02
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
@WaylandYang

Copy link
Copy Markdown
Contributor Author

Review before merge. Two ledger gaps fixed, one bench guard, one renumber:

  • The cap was invisible. Proposals past cap were sliced off before the loop with no drop reason, so returned − accepted ≠ Σ dropped whenever the model returned more than the cap, which is exactly the wide-table case the ledger exists for. The excess is now recorded under cap with the count and the cap value.
  • A decided definition counted as accepted. propose upserts only WHERE status = 'proposed', but the loop counted every call. A second exploration on a base with confirmed or rejected definitions reported accepted = N while Review gained nothing. propose now returns whether it wrote (rows_affected), and a proposal that lands on a decision is recorded under decided. Coverage still counts the table: it has a definition, which is what coverage asks. Test a_rejected_mapping_does_not_come_back asserts the flag.
  • finish failing is logged instead of swallowed.
  • lib.mjs: BENCH_PSQL without -d used to make every onDb() fall through to the command's default database, DROP SCHEMA included; -d is now inserted when absent.
  • The decision record is 0036: dev took 0035 for the vector index (A vector index is built by a job #566) while this was open. README rows read 0032 … 0036 in order once this merges.

Not changed: migrations here use plain CREATE TABLE, like 0038–0042 on dev; CI's second sqlx migrate run skips applied versions, so IF NOT EXISTS only matters for a renumber after a base has run the old number, which 0044 has not.

@WaylandYang
WaylandYang merged commit 8c88776 into dev Sep 9, 2026
4 checks passed
@WaylandYang
WaylandYang deleted the bench/mapping-truth branch September 9, 2026 23:33
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