Accept any record wire on an input read only for its attributes

An element generic declared on a reading input, absent from the output
and from every other input, has nowhere to go and nothing to be: the
node reads its declared attributes and never the element. That is an
attr-to-element map, so it accepts any upstream record wire.

The blessing is inferred rather than marked, since the signature already
says it. The two substrate pieces were both in place: the element rides
as the byte-carried token, so the registry takes one generic row instead
of a row per element type, and the reads resolve against the input's own
layout as they always have. Only the passthrough rule stood in the way,
in the three places that enforced it.

A generic the output carries, or one on an input with no reads, is
unchanged and still owes an implementations list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Dennis Kobert
2026-09-09 12:15:40 +00:00
parent f04d439b33
commit 5baeb8fd46
6 changed files with 138 additions and 7 deletions

View File

@@ -791,12 +791,17 @@ mod test {
/// Reads `read_name` off a record that a write of `write_name` produced.
fn read_attribute_network(write_name: &str, read_name: &str, value: TaggedValue) -> ProtoNetwork {
read_attribute_network_over(TaggedValue::F64(7.), write_name, read_name, value)
}
/// The same graph over any content element, which the read never looks at.
fn read_attribute_network_over(content: TaggedValue, write_name: &str, read_name: &str, value: TaggedValue) -> ProtoNetwork {
ProtoNetwork {
stack_need: 0,
inputs: vec![],
output: NodeId(5),
nodes: vec![
(NodeId(0), ProtoNode::value(ConstructionArgs::Value(TaggedValue::F64(7.).into()), vec![])),
(NodeId(0), ProtoNode::value(ConstructionArgs::Value(content.into()), vec![])),
(NodeId(1), string_value(write_name)),
(NodeId(2), ProtoNode::value(ConstructionArgs::Value(value.into()), vec![])),
(NodeId(3), proto_node("graphic_nodes::graphic::WriteAttributeNode", vec![NodeId(0), NodeId(1), NodeId(2)])),
@@ -834,6 +839,21 @@ mod test {
assert_eq!(read_back(read_attribute_network("novel:count", "novel:absent", TaggedValue::F64(2.5))), 0.);
}
#[test]
fn one_read_node_serves_every_content_element() {
// The read never looks at the element, so one registry row covers any
// upstream record wire rather than a row per element type.
assert_eq!(read_back(read_attribute_network_over(TaggedValue::F64(7.), "novel:count", "novel:count", TaggedValue::F64(2.5))), 2.5);
assert_eq!(
read_back(read_attribute_network_over(TaggedValue::Bool(true), "novel:count", "novel:count", TaggedValue::F64(2.5))),
2.5
);
assert_eq!(
read_back(read_attribute_network_over(TaggedValue::DVec2(glam::DVec2::ONE), "novel:count", "novel:count", TaggedValue::F64(2.5))),
2.5
);
}
#[test]
fn a_census_named_read_round_trips_its_written_value() {
// A declared name folds onto its census field, so the read resolves