Skip to content

Python definitions registry: token expansion, the prompt index, and grain - #261

Open
jat255 wants to merge 2 commits into
jat255/m2-shared-definitionsfrom
jat255/m2-definitions-registry
Open

Python definitions registry: token expansion, the prompt index, and grain#261
jat255 wants to merge 2 commits into
jat255/m2-shared-definitionsfrom
jat255/m2-definitions-registry

Conversation

@jat255

@jat255 jat255 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Fifth PR of M2. Adds the definitions registry, the surface commons owns until data-dict provides one. Closes the registry issue plus the two items that moved to it from the dictionary reader.

Base is #255. Review that first; the diff here is only the registry.

What it does

  • Expands {{name}} and {{table::name}} tokens in run_sql queries.
  • Builds the kind index shown in the system prompt.
  • Carries the grain metadata that call_metrics' mixed-grain guard needs.
  • Checks at construction time that each definition's table is one its source exposes.
  • Renders a table's definitions in the dictionary's first-touch entry and retrieval chunks, which the reader left as a marked seam.

Everything consumes ExportRecord; nothing reaches into an expression parser or a typed IR. When a shared data-dict interface arrives, swapping it in is a deletion rather than a rewrite. That is why the registry exists, and why it is tested before the compiler is.

First Python code to assert the shared contract

Tests run the registry over tests/shared/definitions.json as well as hand-built records. They check that every definition data-dict produced expands to its own compiled SQL, that every kind is one the index groups, and that the grain flags reach the records. #255 landed that fixture with only R asserting it; this is the Python half.

Four defects found in review

Each was reproduced before fixing.

  • An expansion could widen scope for a later token. Tokens were resolved against SQL that earlier expansions had already rewritten, so a definition compiling to sum(returns.x) put returns in scope for a later bare token, defeating the check that keeps a token bound to its own table. Tokens now resolve against the query as written.
  • Retrieval chunks named a token without saying what it expands to. They carried only the kind and type; they now carry the full gist, compiled SQL and notes, matching what first touch shows.
  • An absent type reached the prompt as the word None. data-dict omits type when it cannot infer a single one, so it is left out of the prompt too.
  • The index cap counted lines but not the newlines joining them, so the rendered index could exceed the cap.

Three R defects this surfaced

Filed rather than fixed here, since pkg-r is a separate package and each fix needs its own R reviewer summary. The first two mean the implementations disagree on observable behavior until R is fixed.

No shared fixture for these yet. A fixture would have to pin a single behavior, and R would fail it immediately; the plan is to fix R first and pin the agreement then.

Verification

325 tests, ruff and pyrefly clean.

The registry surface commons owns whatever data-dict eventually provides:
{{name}} and {{table::name}} expansion, the kind index for the prompt,
grain metadata for call_metrics' mixed-grain guard, and the check that a
definition's table is one the source exposes.

Everything consumes ExportRecord and nothing reaches into an expression
parser or a typed IR. That rule is what makes replacing this with a shared
data-dict interface a deletion rather than a rewrite, and it is why the
registry can be built and tested before the compiler exists.

The dictionary's first-touch entry and its retrieval chunks now render a
table's definitions, which the reader left as a marked seam. Both show
compiled SQL rather than the authored expression, since the expression is
in data-dict's language and the model writes SQL.

Tests run the registry against tests/shared/definitions.json as well as
against hand-built records: every definition data-dict produced expands to
its own compiled SQL, and each kind is one the index groups. This is the
first Python code to consume that contract.
…e gist

Four defects, each reproduced first.

Token resolution ran against SQL that earlier expansions had already
rewritten, so a definition whose compiled SQL named another table brought
that table into scope for a later bare token. Every token now resolves
against the query as written, and substitution happens afterwards.

Retrieval chunks carried only the kind and type, so a retrieved definition
named a token without saying what it expands to. They carry the same gist
as the first-touch entry now, which is compiled SQL and notes, never the
authored expression.

An absent type reached the prompt as the word "None". data-dict omits the
type when no single one is inferred, so it is left out rather than printed.
pkg-r loses the entire gist in this case, filed as #259.

The index cap counted line lengths but not the newlines joining them, so
the result could exceed the cap. It measures the joined text.
@jat255 jat255 added the py Affects the Python implementation label Sep 3, 2026
@jat255 jat255 added this to the py-M2: data layer milestone Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

py Affects the Python implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant