Skip to content

Render: long roles wreck Mermaid edge labels, and ownership is dropped when a role is set #27

Description

@jbeda

Two related problems in relationshipLabel (internal/render/mermaid/mermaid.go), both
found while investigating #26 on a real 13-entity model.

1. Long role values collide as edge labels

The schema documents role as "What role the related entity plays ... A role name like
Owner should be defined in the glossary"
— i.e. a short noun phrase. Nothing enforces
that. modelith lint only inspects backticked PascalCase tokens inside a role
(entityRefs), so a freeform prose role passes clean:

- entity: AcceptancePlan
  cardinality: "1:0..1"
  role: "the run's contract, present at capability scale"

The renderer passes it verbatim into the Mermaid edge label. Mermaid's dagre ER layout
reserves no space for edge labels, so on a model with several such roles the labels overlap
each other and the entity boxes, and drift onto lines they don't belong to. Replacing every
label with a single word cleared the overlap entirely — confirming the label text, not the
graph shape, is the cause.

Modelith has a better home for prose: relationship.note. But nothing steers an author
there, and the failure mode only shows up after rendering.

Options: lint warning when a role exceeds ~N words or contains sentence punctuation
(pointing at note); and/or wrap or truncate the label in the Mermaid renderer while
keeping the full text in the Markdown table.

2. Ownership is silently dropped when a role is present

func relationshipLabel(rel model.Relationship) string {
	switch {
	case rel.Role != "":
		return sanitize(rel.Role)
	case rel.Ownership != "":
		return rel.Ownership
	default:
		return rel.Cardinality
	}
}

Crow's-foot notation cannot express composition, so "owned" on the edge is the only place
that signal appears in the diagram. But the role branch wins, so:

  • an owned relationship with a role renders the role, and looks identical to a
    referenced one;
  • an owned relationship without a role renders "owned".

On the model I looked at, four relationships were ownership: owned; two showed owned and
two did not, purely because the latter also had a role. The diagram reads as though the
composition structure is inconsistent when the source is not.

Worth considering: combine them (owned — <role>), or drop the ownership fallback and
express composition through styling instead. Either way the current behaviour is information
loss that depends on an unrelated field being set.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions