UX Research: Version/Subversion Relationship Complexity
Feature: 024-relationships-visualizer
Created: 2026-05-06
Status: Research
Focus: How to present multi-version/subversion relationship states without overwhelming users
Problem Statement
Objects in Aleido have a 5-level hierarchy (Version → Subversion → Language Variant → Format → Revision). Relationships between objects can exist at different hierarchy levels:
- Object-level: Applies to all versions (e.g., "this procedure always references that safety warning")
- Version-scoped: Applies only to a specific version (e.g., "v2 references a new hydraulic diagram that v1 doesn't need")
- Broken at a version boundary: A relationship that existed in v1 no longer exists in v2
Users need to understand which relationships are active for their current editing context without being buried in irrelevant version permutations.
Core Tension
SIMPLICITY ←──────────────────────────────────→ COMPLETENESS
"Show me what's relevant "I need to see ALL relationship
to what I'm working on" states across ALL versions to
make a governance decision"
Technical writers care about their current editing context. Content managers and architects need the full picture. The UI must serve both without being two completely different experiences.
Entry Points & UI Placement
Where the Visualizer Lives
The relationship visualizer is not a standalone page — it is a panel within the Author View (workbench) that can be promoted to full-screen or popped out.
┌──────┬──────────────────────────────────────────────────────────┐
│ │ ZONE A ZONE B ZONE C │
│ S │ Folder │ Object List │ Preview │
│ I │ Explorer │ │ │
│ D │ │ ├────────────────────────┤
│ E │ ├───────────────────┤ Relationships ← NEW │
│ B │ │ Properties │ (graph panel) │
│ A │ │ │ │
│ R │ ├───────────────────┤ │
│ │ │ Change History │ │
├──────┴─────────────┴───────────────────┴────────────────────────┤
│ [Status bar] │
└──────────────────────────────────────────────────────────────────┘
Panel placement: The Relationships panel is a peer to Preview, Properties, and Versions in Zone C. Users can rearrange it via the standard panel drag-drop system or switch to a Perspective that features it prominently.
Full-screen mode: The panel can expand to near full-screen (standard panel expand behaviour) for complex graphs that need more space.
Popout mode: The panel can pop out to a separate window (/ws/:workspaceId/authoring/popout/relationships) for multi-monitor workflows where the user wants the graph visible alongside the XML editor.
How Users Open the Visualizer
| Entry point | Location | Behaviour |
|---|---|---|
| **Panel selector** | Zone C panel tabs (Author View) | Add "Relationships" panel to current perspective. Panel loads for the currently selected object. |
| **Context menu → "Show Relationships"** | Right-click on object in Object List | Opens/focuses the Relationships panel and loads the graph for that object. |
| **Properties panel link** | "Relationships" count badge in object Properties | Clicking the badge scrolls/focuses the Relationships panel (or opens it if closed). |
| **Object Authoring toolbar** | Action bar in XML Editor | "View Relationships" button. Opens the visualizer in a side panel or popout while editing. |
| **Keyboard shortcut** | Global (when object is selected) | `Ctrl+Shift+R` — toggles the Relationships panel for the focused object. |
Context Inheritance
The visualizer inherits its context from where it was opened:
| Opened from | Auto-detected scope |
|---|---|
| Object List (object selected, no version open) | Object-level → latest released subversion |
| Object List after selecting a version in Versions panel | That specific version + latest subversion |
| XML Editor (actively editing v2, sv2) | Exact editing context: version 2, subversion 2 |
| Context menu on a specific version row | That version + latest subversion |
| Deep link URL with version params | Params from URL: `?object=...&version=...&subversion=...` |
This auto-detection feeds directly into the scope selector described in the design options below — users can always override, but the default is "show me what's relevant to where I already am."
URL State
Following app conventions, the visualizer's state is reflected in URL search params:
/ws/:workspaceId/authoring?object=obj-123&panel=relationships&versionScope=ver-002
| Param | Purpose |
|---|---|
| `panel=relationships` | Indicates the Relationships panel is active/visible |
| `versionScope` | `auto` (default) · `all` · `{versionId}` · `{versionId}/{subversionId}` |
This makes the visualizer state deep-linkable and shareable.
Perspective Integration
A pre-built "Impact Analysis" perspective can be offered that arranges panels for relationship-focused work:
┌──────────────────────────────────────────────────────────────┐
│ ZONE A (narrow) │ ZONE B (wide) │
│ Object List │ Relationships Visualizer (expanded) │
│ │ │
│ │ │
│ ├────────────────────────────────────────│
│ │ Properties (collapsed) │
└─────────────────────┴────────────────────────────────────────┘
This gives the graph maximum screen real estate while keeping the object list for quick selection changes.
Key Scenarios
Scenario A: Same relationship, all versions
Object "Replace Oil Filter" references Object "Safety Warning - Hot Surfaces" at the object level. This relationship is stable across all versions.
User expectation: This should look like a single, solid link. No version noise.
Scenario B: New relationship in a newer version
Object "Replace Oil Filter" v2 (2023+ hydraulic models) adds a reference to "Hydraulic Fluid Specification" that v1 doesn't have.
User expectation: When viewing v2, this link is visible. When viewing v1, it is not. When viewing the object as a whole, the user sees it's a v2-only link.
Scenario C: Removed relationship in a newer version
Object "Replace Oil Filter" v1 referenced "Torque Wrench Calibration Guide" but v2 moved to a simplified procedure that no longer needs it.
User expectation: The link disappears when viewing v2 context but remains for v1.
Scenario D: Different targets per version
Object "Replace Oil Filter" v1 references "Filter Part #1234" (discontinued) while v2 references "Filter Part #5678" (current). Same logical role (part reference), different targets.
User expectation: The user can see that the "part reference" slot changed between versions without needing to mentally merge two separate graph views.
Scenario E: Subversion progression
Object "Replace Oil Filter" v2 Subversion 1 references Object X. After errata, v2 Subversion 2 no longer references Object X but adds Object Y instead.
User expectation: When editing the latest subversion, only the current relationships are shown. Historical subversion links are available on demand but not in the default view.
Design Options
Option 1: Context-First with Version Scope Selector
Concept: The graph always shows relationships for a specific hierarchy context. A scope selector at the top lets users choose what they're viewing.
┌─────────────────────────────────────────────────────────────┐
│ Relationships for: Replace Oil Filter │
│ ┌─────────────────────────────────────┐ │
│ │ Scope: [Object ▾] [Version 2 ▾] [Subversion 2 ▾] │
│ └─────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────┐ │
│ │ Safety │──── object-level (all versions) │
│ │Warning │ │
│ └────────┘ │
│ │ │
│ ┌─────────┼─────────┐ │
│ │ │ │ │
│ ┌────┐ ┌──────┐ ┌──────────┐ │
│ │Hydr│ │Filter│ │ Disposal │ │
│ │Spec│ │#5678 │ │ Guide │ │
│ └────┘ └──────┘ └──────────┘ │
│ v2 v2 v2/sv2 │
│ │
└─────────────────────────────────────────────────────────────┘
Scope levels:
| Scope selection | Shows |
|---|---|
| Object (all) | Union of all relationships across all versions. Badges on edges show version scope. |
| Specific Version | Only relationships active in that version (object-level + version-scoped). |
| Specific Subversion | Only relationships active in the current subversion (most focused view). |
Pros:
- Simple default — users see exactly what's relevant to their editing context
- Progressive disclosure — full picture available on demand
- Aligns with how authors think ("I'm working on v2 sv2")
Cons:
- "Object (all)" view can get busy for objects with many versions
- Requires the user to understand the scope selector to unlock full value
Option 2: Unified Graph with Version Layers (Toggle Overlays)
Concept: A single graph showing all relationships, with version "layers" that can be toggled on/off. Relationships are color-coded or styled by the version that introduced them.
┌─────────────────────────────────────────────────────────────┐
│ Relationships for: Replace Oil Filter │
│ │
│ Layers: [✓ Object-level] [✓ Version 1] [✓ Version 2] │
│ [ Subversion 1] [✓ Subversion 2] │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────┐ │
│ │ Safety │━━━━━━━━ (solid black = object-level) │
│ │Warning │ │
│ └────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Torque │╌╌╌╌╌╌╌╌╌│ Filter │ │
│ │ Guide │ (faded) │ #1234 │╌╌╌╌ (faded, v1-only) │
│ └──────────┘ └──────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Hydraulic│──────────│ Filter │──── (blue = v2) │
│ │ Spec │ │ #5678 │ │
│ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Visual encoding:
| Relationship scope | Line style | Opacity |
|---|---|---|
| Object-level (all versions) | Solid, heavy weight | 100% |
| Active in selected version(s) | Solid, normal weight | 100% |
| Not active in selected version(s) | Dashed, light weight | 40% |
| Removed in newer version | Strikethrough/crossed | 30% |
Pros:
- Full picture always visible — nothing hidden
- Quick comparison between versions by toggling layers
- Visual diff is immediately apparent
Cons:
- Can become visually overwhelming for objects with many versions
- Requires understanding color/style encoding (learning curve)
- Cluttered default state
Option 3: Current Context + Ghost Nodes (Hybrid)
Concept: Default view shows relationships for the user's current editing context (auto-detected from what they have open). Relationships from other versions appear as "ghost" nodes — faded, non-interactive placeholders that hint at the full picture without cluttering.
┌─────────────────────────────────────────────────────────────┐
│ Relationships for: Replace Oil Filter │
│ Context: Version 2, Subversion 2 (auto-detected) │
│ [Show all versions ◻] │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────┐ │
│ │ Safety │━━━━━━━━ (always linked) │
│ │Warning │ │
│ └────────┘ │
│ │ │
│ ┌─────────┼─────────┐ │
│ │ │ │ │
│ ┌────┐ ┌──────┐ ┌──────────┐ │
│ │Hydr│ │Filter│ │ Disposal │ │
│ │Spec│ │#5678 │ │ Guide │ │
│ └────┘ └──────┘ └──────────┘ │
│ │
│ · · · · · ┌╌╌╌╌╌╌╌╌╌╌┐ │
│ (ghost) ╎ Torque ╎ ← "Was linked in v1" │
│ ╎ Guide ╎ │
│ └╌╌╌╌╌╌╌╌╌╌┘ │
│ │
│ [+2 relationships from other versions] │
│ │
└─────────────────────────────────────────────────────────────┘
Interaction model:
- Default: only current-context relationships are fully rendered
- Ghost nodes appear at the periphery for relationships in other versions
- Hovering a ghost shows a tooltip: "Linked in Version 1, Subversion 1. Not active in your current context."
- Clicking the ghost opens it as a full node (promoting it to the active graph)
- "Show all versions" checkbox expands to full overlay mode (Option 2)
Pros:
- Cleanest default state — no cognitive overload
- Hints at complexity without forcing it on the user
- Auto-detection removes the need for manual scope selection
- Progressive: ghost → full node on demand
Cons:
- Ghost nodes may confuse users who don't understand why faded items appear
- Auto-detection heuristic must be robust (what if user hasn't opened anything?)
- Edge case: "Object (all)" view needed for content managers not editing a specific version
Option 4: Summary Card + Drill-Down (Two-Level Approach)
Concept: The primary graph shows object-level relationships only (simplified). Each node has a "version detail" expansion that reveals version-specific relationship states.
┌─────────────────────────────────────────────────────────────┐
│ Relationships for: Replace Oil Filter (Object View) │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Safety │───────│ Replace │───────│ Disposal │ │
│ │Warning │ │Oil Filter│ │ Guide │ │
│ └────────┘ └────┬─────┘ └──────────┘ │
│ │ │
│ ┌─────────┼─────────┐ │
│ │ │ │ │
│ ┌────────┐ ┌──────┐ ┌──────────┐ │
│ │ Torque │ │Filter│ │ Hydraulic│ │
│ │ Guide │ │ Part │ │ Spec │ │
│ └───┬────┘ └──┬───┘ └────┬─────┘ │
│ │ │ │ │
│ [v1] [v1→#1234] [v2 only] │
│ [v2→#5678] │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────── Version Detail (expanded on click) ──────────┐
│ │
│ Filter Part — version breakdown: │
│ ┌──────────────────────────────────────────────┐ │
│ │ Version 1 → Filter Part #1234 (obsolete) │ │
│ │ Version 2 → Filter Part #5678 (current) │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ [Open #1234] [Open #5678] [Compare versions] │
└──────────────────────────────────────────────────────────┘
Interaction model:
- Primary graph collapses all version-specific relationships into a single "logical" edge
- Badges on edges indicate version variance: "v1 only", "v2 only", "all versions", "differs per version"
- Clicking a badge or edge opens a detail panel showing the per-version breakdown
- Detail panel offers quick actions: open target in specific version, compare
Pros:
- Simplest possible primary graph — no version explosion
- Still provides full detail on demand
- Works well for content managers who think in terms of logical relationships
- Natural for the "what changed between versions" question
Cons:
- Two-level interaction adds a click to reach full detail
- The collapsed view may hide important version-specific issues
- Badge proliferation on edges if many versions exist
Recommendation
Primary approach: Option 3 (Ghost Nodes) + elements of Option 1 (Scope Selector)
Rationale:
| Criterion | Winner | Why |
|---|---|---|
| Default simplicity for technical writers | Option 3 | Auto-context, clean default |
| Full picture for content managers | Option 1 | Explicit scope selection |
| Progressive disclosure | Option 3 | Ghost → full on demand |
| Minimizes learning curve | Option 3 | Familiar pattern (ghost/faded = inactive) |
| Handles the "differs per version" case | Option 4 (element) | Edge badge + detail panel |
| Performance at scale | Option 3 | Fewer nodes rendered by default |
Proposed Hybrid: "Context-First with Ghost + Scope Override"
┌─────────────────────────────────────────────────────────────────┐
│ Relationships: Replace Oil Filter │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Context: ● Auto (v2, sv2) ○ All Versions ○ Pick: [▾] │ │
│ └───────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [Active graph for current context] │
│ │
│ [Ghost nodes for other-version relationships, if any] │
│ │
│ ┌─── Legend (collapsible) ──────────────────────────────┐ │
│ │ ━━━ Object-level (all versions) │ │
│ │ ─── Active in current context │ │
│ │ ╌╌╌ Ghost (other version, click to explore) │ │
│ │ ⚠️ Incompatible │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ Summary: 5 active relationships, 2 from other versions │
│ │
└─────────────────────────────────────────────────────────────────┘
Detailed Interaction Design
1. Auto-Context Detection
When the user opens the relationship visualizer:
| Context | Detected from | Scope set to |
|---|---|---|
| Object selected in Object List (no version open) | `?object=...` URL param | Latest released subversion, or latest editable if none released |
| Object open in XML Editor | Editor state (version + subversion known) | That specific version + subversion |
| Object opened from version panel | Version panel selection | That specific version, latest subversion |
| No object context (opened from nav) | Last viewed, or prompt user | Prompt: "Select an object to visualize" |
2. Relationship Rendering Rules
| Relationship has... | Rendered as | Interaction |
|---|---|---|
| No version scope (object-level) | Heavy solid line, always visible | Normal node interaction |
| Version scope matching current context | Normal solid line | Normal node interaction |
| Version scope NOT matching current context | Ghost node + dashed line at 40% opacity | Hover: tooltip with version info. Click: "Switch to this version?" or promote to active |
| Version scope partially matching (e.g., active in v1 & v2 but viewing v2 sv1) | Normal line + small info badge | Badge shows "Also in: v1" |
3. Edge Badges for Multi-Version Relationships
When the same logical relationship exists but differs across versions:
┌──────────────────────────────────────────┐
│ │
│ ┌──────────┐ [v1→v2] ┌───────┐ │
│ │ Replace │─────────────────│Filter │ │
│ │Oil Filter│ │ Part │ │
│ └──────────┘ └───────┘ │
│ │
│ Badge: [v1→v2] means: │
│ "This link exists in both versions │
│ but points to different targets" │
│ │
└──────────────────────────────────────────┘
Clicking the badge opens an inline detail card:
┌─────────────────────────────────────────────┐
│ Filter Part — Per-version breakdown │
│ ──────────────────────────────────────── │
│ Version 1 (sv1): → Filter Part #1234 │
│ Version 2 (sv2): → Filter Part #5678 ● │
│ ──────────────────────────────────────── │
│ ● = your current context │
│ │
│ [Open in v1 context] [Open in v2 context] │
└─────────────────────────────────────────────┘
4. "All Versions" Mode
When the user switches to "All Versions":
- All ghost nodes become fully rendered
- Each edge gains a version badge (even previously solid edges now show "all" or specific version tags)
- Color-coding by version appears (legend updates)
- Node grouping: nodes that are version-specific cluster near their version badge
- Summary bar updates: "Showing all 12 relationships across 2 versions, 3 subversions"
5. Subversion Handling — Simplification Rule
Key insight: Users rarely need to compare subversion-level relationships because subversions are sequential (one obsoletes the previous). The visualizer should:
- Default: Always show the latest (or editable) subversion's relationships per version
- On demand: Allow viewing a specific historical subversion via the scope picker
- Never: Show all subversions simultaneously in the graph (this creates unmanageable noise)
Exception: When viewing compatibility violations, show if a subversion change introduced or resolved an incompatibility.
6. Empty and Transition States
| State | UI |
|---|---|
| Object has no relationships at any level | Single node + empty state message: "No relationships found. References will appear here when this object links to others." |
| Object has relationships but none in current version scope | Single node + ghost summary: "No active relationships in Version 2. [3 relationships exist in other versions →]" |
| Switching context scope | Brief skeleton pulse on the graph area (200ms), then re-render. No full-page loading state. |
| Ghost node clicked, expanding to new version | Animate: ghost → solid over 300ms. Connected edges draw in. |
Accessibility Considerations
| Concern | Solution |
|---|---|
| Ghost nodes hard to perceive at low contrast | In addition to opacity, add a dashed border pattern. High-contrast mode uses full opacity + distinct icon badge. |
| Color-coded version layers | Never rely on color alone. Each version has a distinct line pattern (solid, dashed, dotted, dash-dot). |
| Badge text too small | Badges are interactive and enlarge on focus/hover. Screen readers announce badge content on node focus. |
| Scope selector must be keyboard navigable | Radio group with arrow keys. Screen reader announces current context on scope change. |
Performance Implications
| Concern | Mitigation |
|---|---|
| "All Versions" could fetch many more nodes | Lazy-load per version on toggle. Don't fetch all upfront. |
| Ghost nodes still require data | Ghost data is minimal: object ID, title, version scope. Full metadata loaded on hover/click. |
| Re-render on scope change | Keep graph positions stable. Only add/remove/restyle nodes. No full layout recalculation unless node count changes by >50%. |
| Many versions (10+) in scope picker | Group and truncate: show latest 3 versions inline + "Show all N versions" expandable. |
API Implications
The existing GET /api/workspaces/{workspaceId}/objects/{objectId}/graph endpoint needs:
- New query parameter:
versionScope — all | objectId (object-level only) | {versionId} | {versionId}/{subversionId}
- Response enrichment: Each edge includes
scope field:
{
"sourceId": "obj-A",
"targetId": "obj-B",
"scope": {
"level": "version",
"versionId": "ver-002",
"subversionId": null,
"activeInVersions": ["ver-001", "ver-002"]
}
}
- Ghost node endpoint (lightweight):
GET .../graph/ghosts?currentScope={versionId} — returns minimal data for out-of-scope relationships (id, title, version badge, count).
Open Questions
| # | Question | Impact |
|---|---|---|
| 1 | Should ghost nodes count toward the 500-node performance limit? | If yes, complex objects with many versions may hit limits faster. Recommend: no, ghosts are a separate lightweight layer. |
| 2 | When an object has 5+ versions, should the "All Versions" view auto-cluster by version? | Prevents explosion. Propose: yes, auto-cluster when ≥4 versions. |
| 3 | Should the visualizer remember the user's last scope preference per object? | Helps repeat visitors. Propose: yes, stored in view state (FR-028). |
| 4 | How do we represent "same logical role, different target" across versions (Scenario D)? | Propose: single logical edge with a version-diff badge (see Section 3 above). Alternative: two separate edges with shared color. |
| 5 | Should subversion-level relationships be hidden entirely from the primary graph unless the user explicitly selects a subversion? | Reduces noise. Risk: user misses a subversion-specific change. Propose: show latest subversion only, badge if differs from previous. |
User Research Next Steps
- Card sort: Have 5 technical writers categorize relationships by "always relevant" vs "only when I'm working on a specific version" to validate the ghost-node threshold.
- Prototype test: Build a static clickable prototype of the hybrid approach (auto-context + ghosts + scope override) and observe 3 content managers attempting impact analysis tasks.
- Cognitive walkthrough: Walk through Scenarios A–E with stakeholders using paper wireframes to validate that the edge-badge detail card resolves Scenario D without confusion.
- Performance benchmark: Measure render time for "All Versions" view on a test object with 8 versions × ~15 relationships each to validate the lazy-load-per-version strategy.