Child of #378. Depends on nothing; better once chant#2266 lands.
The boxes
A Terraform project's roots are its only grouping — there are no stacks, no components, no waves. chant graphs them all into one bucket today:
groups: {"byLexicon": {"terraform": 247}, "byStack": {"terraform": 247}}
node id: "prod/aws_s3_bucket.waterpark_artifacts"
attrs: {"root": "prod", ...}
chant#2266 asks for byStack keyed by root. If it lands, behold draws member boxes with no change at all — byStack is already what renderGraph boxes. If it does not, behold derives the same grouping from attrs.root (or the <root>/ id prefix, which is the lexicon's own convention). Either way the boxes are one join away, and this issue is where that join lives.
The lens
A logical-terraform.ts in the shape of src/logical-choudoufu.ts (#370): one box per root, every card in it, and only the edges the graph actually states. projectTopology's other projections filter on their own lexicon and ignore the rest, so a mixed estate merges byte-for-byte as before, and retainCrossLensEdges (#321) keeps an edge whose two ends are drawn by different lenses.
That last part is the point on a mixed estate: a chant project beside a Terraform root, with an edge between them, is exactly the seam #321 exists for.
Definition of done
- Root boxes on
/api/graph, from byStack when chant supplies it and from attrs.root when it does not, with one code path deciding which.
projectChoudoufuLogical's sibling for terraform, registered in projectTopology.
- A module used by several roots (waterpark's
modules/persona is used by three) is drawn once per root that calls it, not once globally — the node ids already say prod/module.desk_operator, so this is a consequence of the ids rather than a decision, but it should be asserted so nobody "fixes" it into a shared node later.
- The note when a Terraform estate has no edges says why (chant#2265), rather than the generic "nothing references anything else" the estate gets today. That sentence is currently true of the IR and false of the estate.
Acceptance
behold serve on a multi-root Terraform project draws one labelled box per root, and ?logical=1 draws the same boxes through the lens rather than dropping every card.
🤖 Claude Code — https://claude.ai/code/session_0124XP1LJTZxgJRy7Dh1UfXt
Child of #378. Depends on nothing; better once chant#2266 lands.
The boxes
A Terraform project's roots are its only grouping — there are no stacks, no components, no waves. chant graphs them all into one bucket today:
chant#2266 asks for
byStackkeyed by root. If it lands, behold draws member boxes with no change at all —byStackis already whatrenderGraphboxes. If it does not, behold derives the same grouping fromattrs.root(or the<root>/id prefix, which is the lexicon's own convention). Either way the boxes are one join away, and this issue is where that join lives.The lens
A
logical-terraform.tsin the shape ofsrc/logical-choudoufu.ts(#370): one box per root, every card in it, and only the edges the graph actually states.projectTopology's other projections filter on their own lexicon and ignore the rest, so a mixed estate merges byte-for-byte as before, andretainCrossLensEdges(#321) keeps an edge whose two ends are drawn by different lenses.That last part is the point on a mixed estate: a chant project beside a Terraform root, with an edge between them, is exactly the seam #321 exists for.
Definition of done
/api/graph, frombyStackwhen chant supplies it and fromattrs.rootwhen it does not, with one code path deciding which.projectChoudoufuLogical's sibling for terraform, registered inprojectTopology.modules/personais used by three) is drawn once per root that calls it, not once globally — the node ids already sayprod/module.desk_operator, so this is a consequence of the ids rather than a decision, but it should be asserted so nobody "fixes" it into a shared node later.Acceptance
behold serveon a multi-root Terraform project draws one labelled box per root, and?logical=1draws the same boxes through the lens rather than dropping every card.🤖 Claude Code — https://claude.ai/code/session_0124XP1LJTZxgJRy7Dh1UfXt