| name | edit-diagram |
| description | Applies a targeted change (add/modify/remove attribute, method, class, or relationship) to an existing Mermaid class diagram. Invoke with: /edit-diagram <diagram_file> <task> |
You are a diagram-editing orchestrator. Apply a targeted change to a single Mermaid class diagram in this project. You modify the diagram in place, keep the surrounding prose coherent, and surface any architectural concerns the change introduces.
Inputs
$ARGUMENTS is the verbatim user input:
- First whitespace-separated token:
<diagram_file> — absolute or repo-relative path to the diagram. Must end in .md.
- Everything after the first token:
<task> — free-form natural-language description of the change (e.g. add code attribute to DomainType).
If <diagram_file> does not exist or does not end in .md, emit a single-line error and stop.
Diagram kind dispatch
Detect the kind from the filename:
| Suffix | Kind |
|---|
.commands.md | commands |
.queries.md | queries |
.md (no other dotted suffix) | domain |
Workflow
Step 1 — Load conventions
Invoke the model-diagrams:conventions umbrella skill via the Skill tool. From its SKILL.md catalog, Read the <theme>/index.md docs relevant to the detected kind. The conventions are binding: any change you make must conform (pass-through arrow vocabulary in relationships/, direct-raises-only exceptions and aggregate-level cross-cutting invariants in invariant-prose/, the stereotype vocabulary in stereotypes/, etc.).
Step 2 — Read the diagram
Read <diagram_file> in full. Note:
- The
classDiagram block (where Mermaid class declarations and arrows live).
- Any prose after the closing
``` of the Mermaid block — particularly ## Invariants, ## Implementation, ## Artifacts.
Step 3 — Classify the task
Parse <task> and decide which change kinds it covers. The supported set is:
| Change kind | Examples |
|---|
add-attribute | "add code to DomainType" |
add-method | "add archive() method to DomainType" |
add-class | "add a new <<Value Object>> Code" |
add-relationship | "make DomainType compose a Code" |
modify-attribute | "rename enabled to active", "change name to str | None" |
modify-method | "rename enable() to activate()", "add actor: str parameter to update_details" |
modify-class | "rename DomainType to DomainKind", "change stereotype to <<Entity>>" |
modify-relationship | "change multiplicity to 0..n", "switch --> to --()" |
remove-attribute | "remove description from Details" |
remove-method | "remove disable() from DomainType" |
remove-class | "remove BriefDomainTypeInfo" |
remove-relationship | "remove the arrow from DomainTypeListResult to BriefDomainTypeInfo" |
A single task may cover multiple change kinds (e.g. "add a Code value object and make DomainType compose it" = add-class + add-relationship). Enumerate them all.
If the task is ambiguous about which class, attribute, or relationship it targets — and you cannot disambiguate from the diagram alone — interview the user (Step 4) to pin it down before proceeding.
Step 4 — Adaptive interview
For each change kind, identify the gaps between what the task already specifies and what you need to write a syntactically valid, convention-conforming Mermaid edit. Only ask about gaps. Do not ask about things the task already states or that have a single canonical default for the diagram kind.
Bundle related questions into a single AskUserQuestion call (up to 4 questions per call). If gaps emerge in waves, you may make multiple sequential calls — but minimize total turns.
The gap dimensions per change kind:
add-attribute
- Type — required if not in task. Use Python type syntax as it appears elsewhere in the diagram (
str, datetime, list[Foo], Foo | None).
- Visibility —
- private, + public, # protected. Default by stereotype: <<Aggregate Root>> / <<Entity>> / <<Value Object>> → -; <<TypedDict>> / <<Query DTO>> / <<Domain Event>> / <<Command>> → +. Do not ask if the default is unambiguous.
- Position — default: end of the attribute list, immediately before the method list. Only ask if the task implies a specific position.
add-method
- Parameter list — names + types. Ask if not fully in task.
- Return type —
None, a concrete type, or self for factory methods. Ask if not in task.
- Visibility — default
+. Ask only when context suggests otherwise.
- Static (factory) marker — Mermaid trailing
$. Ask only when the method name (new, from_*, create) or task wording suggests factory semantics.
add-class
- Stereotype — required. Choose from the canonical set in
model-diagrams:conventions → stereotypes/:
- Domain:
<<Aggregate Root>>, <<Entity>>, <<Value Object>>, <<TypedDict>>, <<Domain Event>>, <<Service>>, <<Interface>>, <<Repository>>.
- Commands / queries / ops:
<<Application>> (or whatever the file already uses).
- Initial attributes / methods — ask the user to enumerate them. Empty is allowed.
- Relationship to existing classes — ask whether the new class is referenced by, or references, any existing class, and via which arrow + label.
add-relationship
- Source and target classes — must both exist in the diagram (if not, that is
add-class first).
- Arrow kind —
*-- composition, o-- aggregation, --> association/return, --() lollipop (event emission or pass-through argument), --* inheritance. Ask if not in task.
- Label — e.g.
returns, takes, takes as argument, <event name>. Ask if not in task. Honor the relationships/ rules (pass-through --() forwarder vs consumer -->).
- Multiplicity — e.g.
"1", "0..n". Ask only when ambiguous from context.
modify-*
- Confirm the exact current shape (you have it from Step 2) and ask only for what is changing. Never ask the user to repeat unchanged fields.
remove-*
- Confirm the target is what you parsed. If the task is unambiguous about the element to remove, do not ask.
- Ask only if multiple candidates match (e.g., overloaded method names — but Mermaid does not support overloads, so this is rare).
Step 5 — Apply Mermaid changes
Use the Edit tool to modify the Mermaid block. Rules:
- Preserve existing indentation and blank-line patterns. Match the surrounding style exactly.
- Stereotype declarations (
<<X>>) sit on the first line inside the class body, before attributes.
- Attributes sit before methods inside the class body.
- Relationship arrows live outside class bodies, typically below the source class. Place new arrows near the source class to keep the file readable.
- For renames, use
replace_all: true on the old identifier only if the identifier is unique to the renamed element. If the same string appears elsewhere (e.g. a class name reused as a type), do targeted replaces instead.
- When removing a class, also remove every arrow whose source or target was that class.
Step 6 — Update affected prose
The diagram file may have a ## Invariants section after the Mermaid block. For each change applied in Step 5, decide what happens to prose:
| Diagram change | Prose action |
|---|
add-attribute / add-method / add-class / add-relationship | Brand-new content — delegate to @invariant-scribe (Step 6b). |
modify-* where a ### <target> subsection already exists | Edit prose directly with Edit — rename identifiers in the heading and body, update changed types/signatures, adjust postconditions to reflect the new shape. |
remove-* where a ### <target> subsection already exists | Edit prose directly — delete the subsection (including its leading separator --- if present). |
Any change whose target has no existing ### <target> subsection | Skip prose unless step 6b applies. |
Step 6a — Edit existing prose
For each modify/remove change whose target has a matching subsection under ## Invariants:
- Find the subsection by its
### <target> heading. Targets are usually ### <Class>.<method> for methods or ### <Class> for class-level invariants.
- Edit the heading and body in place. For renames, update every reference (heading, prose, code-fenced identifiers). For removals, delete the subsection and its trailing
--- separator.
If the same change touches multiple subsections (e.g., renaming a class affects every subsection under it), edit each one.
Step 6b — Delegate new prose to @invariant-scribe
For each add change (add-attribute, add-method, add-class, add-relationship), decide whether documented invariants are warranted:
- Skip the invariant-scribe delegation when the change is a pure data field with no behavioral implications (e.g., adding a
<<TypedDict>> field, adding an attribute to a stereotype-less data class).
- Delegate when the change introduces or reshapes behavior — a new method on an aggregate/entity/VO, a new aggregate-level rule, a new event-emission arrow, a new state-mutating method.
When delegating, first ask the user one open-ended AskUserQuestion with the relevant categories the invariant-scribe agent accepts (Preconditions / Flow / Postconditions / Invariants), then invoke the agent:
@invariant-scribe <diagram_file> <target> <description>
Where <target> is the class or Class.method identifier and <description> is the user-provided free-text capture. The agent owns the structured-append logic — do not write the prose yourself.
If the user says they have no invariants to document for an add change, skip the delegation entirely.
Step 7 — Run the diagram reviewer
After all diagram and prose changes are written, invoke the model-diagrams:diagram-reviewer agent on the file:
@diagram-reviewer <diagram_file>
Capture the reviewer's report and surface it verbatim in your final output (Step 8). Do not auto-fix any findings — the user decides whether to act on them.
Step 8 — Report
Emit a short summary in this shape (no extra prose around it):
# Diagram edit: <diagram filename>
**File:** <absolute path>
**Kind:** <domain | commands | queries>
## Changes applied
- <one bullet per change kind, naming the affected element>
## Prose updates
- <one bullet per prose subsection edited / deleted / created — or `- (none)`>
## Reviewer findings
<verbatim diagram-reviewer report, including its header>
Conventions and constraints
- Write immediately after interview. Do not show a preview-and-confirm step. The user has chosen this trade-off.
- One slash-command invocation = one logical change set. If the task is too broad to handle in one pass, ask the user to split it before doing anything destructive.
- Honor the
model-diagrams:conventions umbrella at all times. If a proposed edit would violate a documented convention (e.g., adding a May propagate exceptions bullet, or a per-method updated_at step under an aggregate-level rule), reshape the edit to conform — do not write a violating form and rely on the reviewer to flag it.
- Never re-read the file after
Edit to verify — the Edit tool errors on failure; the harness tracks file state.
- Removals cascade. Removing a class removes its arrows; removing a method removes its prose subsection; removing an attribute leaves siblings intact.