What happens
The Arguments slot is declared as AstSlotKind.Expression:
// Coder.Graph/AstSchema.cs:41
private static readonly AstSlot ArgumentsSlot = new(ArgumentsSlotName, AstSlotCardinality.Many, AstSlotKind.Expression);
and Accepts resolves that kind through IsExpression, which does not admit MemberInitialiser:
// Coder.Graph/AstSchema.cs:430
AstSlotKind.Expression => IsExpression(candidate),
// Coder.Graph/AstSchema.cs:449-454
public static bool IsExpression(AstNode node) =>
node is Expression
or AstLeafNode<string>
or AstLeafNode<int>
or AstLeafNode<bool>
or AstLeafNode<double>;
MemberInitialiser derives from AstNode, not Expression (Coder/Ast/MemberInitialiser.cs:17).
Attachment is gated on that check:
// Coder.Graph/AstSchema.cs:133
if (!Accepts(slot, child))
{
return false;
}
which makes the handling two cases further down unreachable for a MemberInitialiser:
// Coder.Graph/AstSchema.cs:175
case (ConstructionExpression construction, ArgumentsSlotName):
construction.Arguments.Add(child);
return true;
Note that this case deliberately carries no when child is Expression guard, unlike all five neighbouring cases — and ConstructionExpression.Arguments is typed Collection<AstNode> rather than Collection<Expression> (Coder/Ast/ConstructionExpression.cs:38). Both say the intent was to accept it.
Failure scenario
AstSchema.TryAttachAt(
constructionExpr,
ArgumentsSlot,
0,
new MemberInitialiser("x") { Value = Literal.Number(1) });
returns false and attaches nothing. In the editor, AstGraph.TryConnect refuses the link (Coder.Graph/AstGraph.cs:561), so a designated or named initialiser can never be built in the graph — and one loaded from YAML cannot be detached and reattached.
Why it matters
All four generators implement this node in exactly this position — CSharpGenerator.cs:252,343, CppGenerator.cs:544,567, PythonGenerator.cs:126,137, JavaScriptGenerator.cs:125,172 — and YamlSerializer/YamlDeserializer round-trip it. CLAUDE.md states it as a design rule: "a MemberInitialiser among its arguments is an element that names the member it is for — a designated initialiser in C++, an object initialiser in C#, a keyword argument in Python, an object literal in JavaScript."
The graph is documented as the uniform view of the AST. Here it cannot express a shape that the AST, the serializer and every generator all handle.
Missing coverage
Coder.Test/Graph/DeclarationSlotsTests.cs:126 covers MemberInitialiser's own Value slot only. Nothing tests attaching one into a ConstructionExpression.
Suggested fix
Either give construction arguments a dedicated slot kind accepting IsExpression(candidate) || candidate is MemberInitialiser, or widen the Expression arm for this slot specifically. Add a DeclarationSlotsTests case attaching a MemberInitialiser to ConstructionExpression.Arguments.
Related: #48 covers MemberInitialiser and ConstructionExpression having no editable fields; this is the separate problem of the node not being attachable at all.
What happens
The
Argumentsslot is declared asAstSlotKind.Expression:and
Acceptsresolves that kind throughIsExpression, which does not admitMemberInitialiser:MemberInitialiserderives fromAstNode, notExpression(Coder/Ast/MemberInitialiser.cs:17).Attachment is gated on that check:
which makes the handling two cases further down unreachable for a
MemberInitialiser:Note that this case deliberately carries no
when child is Expressionguard, unlike all five neighbouring cases — andConstructionExpression.Argumentsis typedCollection<AstNode>rather thanCollection<Expression>(Coder/Ast/ConstructionExpression.cs:38). Both say the intent was to accept it.Failure scenario
returns
falseand attaches nothing. In the editor,AstGraph.TryConnectrefuses the link (Coder.Graph/AstGraph.cs:561), so a designated or named initialiser can never be built in the graph — and one loaded from YAML cannot be detached and reattached.Why it matters
All four generators implement this node in exactly this position —
CSharpGenerator.cs:252,343,CppGenerator.cs:544,567,PythonGenerator.cs:126,137,JavaScriptGenerator.cs:125,172— andYamlSerializer/YamlDeserializerround-trip it. CLAUDE.md states it as a design rule: "aMemberInitialiseramong its arguments is an element that names the member it is for — a designated initialiser in C++, an object initialiser in C#, a keyword argument in Python, an object literal in JavaScript."The graph is documented as the uniform view of the AST. Here it cannot express a shape that the AST, the serializer and every generator all handle.
Missing coverage
Coder.Test/Graph/DeclarationSlotsTests.cs:126coversMemberInitialiser's ownValueslot only. Nothing tests attaching one into aConstructionExpression.Suggested fix
Either give construction arguments a dedicated slot kind accepting
IsExpression(candidate) || candidate is MemberInitialiser, or widen theExpressionarm for this slot specifically. Add aDeclarationSlotsTestscase attaching aMemberInitialisertoConstructionExpression.Arguments.Related: #48 covers
MemberInitialiserandConstructionExpressionhaving no editable fields; this is the separate problem of the node not being attachable at all.