ID |
|
|---|---|
Status |
Backlog |
Bucket |
architecture |
Priority |
5 |
Theme |
model-cleanup |
Blocked by |
|
Created |
2026-08-31 |
Updated |
2026-09-03 |
The argMapping candidate tree stops one level above the key column
The argMapping candidate tree resolves a written right-hand side by matching its deepest prefix against a candidate path. It models the descent through input-object-typed fields, and it stops there.
A written path routinely spells one more level than the tree has. Where the leftover is a single
segment, the reading is a key-column projection: the path reached a candidate that is a node, and the
last name selects a column of that node’s key. intent_argmapping_binding_leaf carries that case as
trailing_segments = 1 and hands it on unresolved, so every reader that cares about it re-derives what
that leftover name refers to instead of joining to a row.
Which is the same defect this whole line of work has been finding, one level lower down. The tree exists because resolving a path by walking a positional segment list was being done a hundred times per statement; making the tree reach the key column would mean the projection resolves by the same prefix match as everything above it, rather than by a rule spelled separately in each reader.
What has to be settled first is whether the key column belongs in the same relation. A candidate is a point in the SDL’s input surface; a key column is a catalog fact reached through the node’s bound table. Putting both in one tree means one relation spanning two corpora, which the schema’s own ownership rule says belongs to a gatherer running after both. That is now possible, since the graphitron gatherer reads the catalog, but possible is not the same as correct: the alternative is a second keyed relation the leaf joins to, and the choice should be made on which one a reader can state its question against, not on which is fewer tables.
What R876 settled, and the one thing it found in the way
The candidate tree is now keyed by the schema coordinate the directive sits on and holds every legal
spelling at it, so "one more level than the tree has" is no longer a ranked prefix probe. A written
path either names a candidate or its head does. Which of those happened is
graphitron_argmapping_match.bound_path against the entry’s own written_path, equal or not, and
the leftover name where there is one is graphitron_argmapping_entry.tail_name, on the relation
that owns the author’s spelling. The trailing count is gone and with it the sixth
verdict, TRAILING_SEGMENTS_BEYOND_ONE: a path spelling two names past what it opened is a spelling
nothing at the coordinate has, so it is refused with every other unresolvable spelling rather than
carrying a count. That leaves this item one job, which is the one it was always about: making
trailing_name resolve to a row instead of being handed on.
The obstacle is ordering, not ownership. meta_gatherer_dependency declares
('graphitron', 'catalog'), and CatalogFactCapture does flush before ArgMappingCandidates.derive
inside the same transaction, so the catalog is readable there. What is not readable is
intent_resolved_node_key_column, because two of the relations under it, intent_spelled_table and
intent_resolved_type_binding, are materialized tables that Materializations.refresh refills
after the hand-written producers run. A candidate tree seeded from that view at capture cadence
reads the previous run’s key columns, or on a fresh store no key columns at all.
Three ways out, and the choice is this item’s:
-
read the
_liveviews instead, which is correct and evaluates the whole binding rule once per candidate seed; -
move
ArgMappingCandidates.deriveafter the refresh, which makes a hand-written producer depend on the registered order that R876 is trying to remove; -
register the candidate relation in
meta_materialize, which is lever four and the one R876’s lever order puts last.
None is obviously right, which is why this stayed its own item rather than riding along.