Feature: Initialize architecture model
Scenario: Create new model in empty directory
Given an empty project directory
When the user runs "bausteinsicht init"
Then a model file is created with a default specification
And the specification contains element kinds "actor", "system", "container", "component"
And a sample model with example elements exists
And a default draw.io template file is created
And the model file references a JSON Schema
Scenario: Refuse to overwrite existing model
Given a project directory with an existing Bausteinsicht model
When the user runs "bausteinsicht init"
Then the command exits with a non-zero exit code
And a warning message indicates that model files already exist
And no existing files are modified
Acceptance Criteria
Conventions
Acceptance criteria are written in Gherkin format (Given-When-Then).
They are grouped by feature area and reference the corresponding use cases from 01_use_cases.adoc.
Model Initialization (UC-1)
AC-1.1: Default model creation
Element Definition (UC-2)
AC-2.1: Element creation with unique IDs
Feature: Define architecture elements
Scenario: Add element with unique ID
Given a valid architecture model
When the user adds an element with ID "payment_service", kind "container", and title "Payment Service"
Then the model contains an element "payment_service" of kind "container"
And the element has the title "Payment Service"
Scenario: Reject duplicate element ID
Given a valid architecture model containing element "api_gateway"
When the user adds another element with ID "api_gateway"
Then the JSON Schema validation reports an error
And the model is not modified
Scenario: Nested elements
Given a valid architecture model with element "backend" of kind "container"
When the user adds element "auth_module" of kind "component" as a child of "backend"
Then the model contains "backend.auth_module"
And "auth_module" is nested inside "backend"
Scenario: Deeply nested elements (flexible hierarchy)
Given a valid architecture model
When the user creates elements nested 5 levels deep
Then the model validates successfully
And all 5 levels are represented correctly
AC-2.2: Relationship definition
Feature: Define relationships
Scenario: Add relationship between elements
Given a model with elements "frontend" and "api"
When the user adds a relationship from "frontend" to "api" with label "calls"
Then the model contains a relationship from "frontend" to "api"
And the relationship has label "calls"
Scenario: Relationship with nested element reference
Given a model with element "backend.api" (nested)
When the user adds a relationship from "frontend" to "backend.api"
Then the relationship correctly references the nested element using dot notation
Forward Sync — Model to draw.io (UC-3)
AC-3.1: Initial diagram generation
Feature: Generate draw.io diagrams from model
Scenario: Generate new diagram
Given a valid architecture model with 3 elements and 2 relationships
And a draw.io template with styled reference elements
And no draw.io output file exists
When the user runs "bausteinsicht sync"
Then a draw.io file is created
And all 3 elements appear as styled mxCell elements
And all 2 relationships appear as connectors
And each element carries its Bausteinsicht ID as a custom property
And elements are placed side-by-side (no overlapping)
And connectors are attached to element centers
Scenario: Template styling is applied
Given a template with a blue rounded rectangle for kind "system"
And the model contains element "webshop" of kind "system"
When the user runs "bausteinsicht sync"
Then "webshop" appears as a blue rounded rectangle in the draw.io output
AC-3.2: Incremental sync preserving layout
Feature: Incremental forward sync
Scenario: Add new element to existing diagram
Given an existing draw.io diagram with elements "A" and "B" at specific positions
And the model now contains a new element "C"
When the user runs "bausteinsicht sync"
Then element "C" appears in the draw.io file
And element "C" has a visual marker indicating it needs manual positioning
And elements "A" and "B" retain their original positions
Scenario: Update element description
Given a model where element "api" has description changed to "REST API v2"
And an existing draw.io diagram containing "api"
When the user runs "bausteinsicht sync"
Then the draw.io element for "api" shows the updated description
And the position of "api" is unchanged
Scenario: Remove deleted element
Given a model where element "legacy_db" has been removed
And an existing draw.io diagram containing "legacy_db"
When the user runs "bausteinsicht sync"
Then "legacy_db" no longer appears in the draw.io file
And connectors that referenced "legacy_db" are removed
Reverse Sync — draw.io to Model (UC-4)
AC-4.1: Detect changes from draw.io
Feature: Reverse sync from draw.io to model
Scenario: Renamed element in draw.io
Given a draw.io diagram where element with ID "api" has been renamed to "REST API v2"
When the user runs "bausteinsicht sync"
Then the model element "api" has its title updated to "REST API v2"
And the element ID "api" remains unchanged
Scenario: New element added in draw.io
Given a draw.io diagram where the user has added a new rectangle labeled "Cache"
And the new element has no Bausteinsicht ID
When the user runs "bausteinsicht sync"
Then a new element is added to the model with ID "cache" (sanitized from label: lowercase, hyphen-separated)
And the element is assigned the first alphabetically-sorted kind from the specification
And the element appears in other views on the next forward sync
Scenario: New element with colliding ID is skipped
Given a draw.io diagram where the user has added a new rectangle labeled "API"
And the model already contains an element with ID "api"
When the user runs "bausteinsicht sync"
Then the new element is NOT imported
And a warning is displayed indicating the ID "api" already exists
Scenario: Navigation buttons are excluded from reverse sync
Given a draw.io diagram containing navigation buttons with IDs prefixed "nav-back-"
When the user runs "bausteinsicht sync"
Then the navigation buttons are not detected as new elements
And no model changes are made for navigation buttons
Scenario: New relationship drawn in draw.io
Given a draw.io diagram where the user has drawn an arrow from "api" to "cache" with label "reads"
When the user runs "bausteinsicht sync"
Then a new relationship is added to the model from "api" to "cache" with label "reads"
Scenario: Layout-only change does not modify model
Given a draw.io diagram where element "api" has been moved to a different position
And no other changes were made
When the user runs "bausteinsicht sync"
Then the model file is not modified
AC-4.2: Conflict handling
Feature: Sync conflict handling
Scenario: Same element changed in both model and draw.io
Given element "api" has title "API" in the model
And element "api" has title "REST API" in draw.io
And both changes happened since the last sync
When the user runs "bausteinsicht sync"
Then a warning is displayed showing both values
And no silent overwrite occurs
Watch Mode (UC-5)
AC-5.1: Continuous synchronization
Feature: Watch mode
Scenario: Auto-sync on model change
Given "bausteinsicht watch" is running
When the user saves a change to the model file
Then the draw.io diagram is updated within 2 seconds
And a sync summary is displayed
Scenario: Auto-sync on draw.io change
Given "bausteinsicht watch" is running
When the user saves a change to the draw.io file
Then the model is updated within 2 seconds
And a sync summary is displayed
Scenario: Debounce rapid changes
Given "bausteinsicht watch" is running
When the user saves the model file 5 times within 1 second
Then only 1 sync operation is performed
CLI Interface (UC-6)
AC-6.1: Validation
Feature: Model validation
Scenario: Valid model
Given a valid architecture model
When the user runs "bausteinsicht validate"
Then the command exits with exit code 0
And a success message is displayed
Scenario: Invalid model
Given a model with a relationship referencing non-existent element "ghost"
When the user runs "bausteinsicht validate"
Then the command exits with a non-zero exit code
And an error message identifies the invalid reference
Scenario: Version display
When the user runs "bausteinsicht --version"
Then the current version number is displayed
AC-6.2: LLM-friendly CLI
Feature: LLM-driven model manipulation
Scenario: Add element via CLI
Given a valid architecture model
When an LLM runs "bausteinsicht add element --id cache --kind container --title Cache"
Then the model contains a new element "cache" of kind "container" with title "Cache"
Scenario: Add relationship via CLI
Given a model with elements "api" and "cache"
When an LLM runs "bausteinsicht add relationship --from api --to cache --label reads"
Then the model contains a new relationship from "api" to "cache" with label "reads"
Scenario: Machine-readable output
Given a valid architecture model
When the user runs "bausteinsicht validate --format json"
Then the output is valid JSON with structured validation results
Navigation and Drill-Down (UC-7)
AC-7.1: Zoom-based navigation
Feature: Drill-down navigation in draw.io
Scenario: Link from context to container view
Given a model with system "webshop" containing containers "api" and "db"
And views exist for both context and container level
When "bausteinsicht sync" generates the draw.io file
Then the "webshop" element in the context view contains a link
And clicking the link navigates to the container view area
Scenario: Parent view visible after drill-down
Given views at context and container level on a single draw.io page
When the user navigates from context to container level
Then the context view remains visible (smaller) above the container view
And clicking the context view navigates back
Export Command (UC-8)
AC-8.1: Diagram export
Feature: Export diagram views as images
Scenario: Export all views as PNG
Given a synced architecture model with 3 views
When the user runs "bausteinsicht export"
Then PNG files are generated for each view in the output directory
And the exit code is 0
Scenario: Export specific view
Given a synced architecture model
When the user runs "bausteinsicht export --view context"
Then only the "context" view is exported
Scenario: Export non-existent view
Given a synced architecture model
When the user runs "bausteinsicht export --view nonexistent"
Then the exit code is 2
And the error message mentions "view not found"
Scenario: Export as SVG
Given a synced architecture model
When the user runs "bausteinsicht export --image-format svg"
Then SVG files are generated for each view
Scenario: Export to custom directory
Given a synced architecture model
When the user runs "bausteinsicht export --output ./docs/images"
Then image files are written to the "./docs/images" directory
Bugfix Acceptance Criteria
AC-9.1: Self-referencing relationship rendering (#111)
Feature: Self-referencing relationships
Scenario: Element with relationship to itself
Given a model with element "api" that has a relationship from "api" to "api" with label "recurse"
When the user runs "bausteinsicht sync"
Then a loopback connector is rendered on the "api" element in draw.io
And the connector label shows "recurse"
And the connector does not overlap the element text
AC-9.2: View include cleanup on element deletion (#114)
Feature: View cleanup on element deletion
Scenario: Deleted element is removed from view includes
Given a model with element "legacy" included in views "context" and "container"
When the user deletes element "legacy" from the model
And the user runs "bausteinsicht sync"
Then "legacy" is removed from the include lists of all views
And no dangling references remain in the view definitions
AC-9.3: Lifted connector deduplication (#197)
Feature: Lifted connector deduplication
Scenario: Multiple child relationships produce single lifted connector
Given a model where "a.child1" and "a.child2" both relate to "b"
And a view that shows "a" and "b" but not their children
When the user runs "bausteinsicht sync"
Then only one lifted connector is drawn from "a" to "b"
And the connector is not duplicated
AC-9.4: Connector to scope element (#217)
Feature: Connector to scope element
Scenario: Relationship targets the scope element of a view
Given a model where element "api" has a relationship to the scope element "system"
And a view with scope "system" that includes "api"
When the user runs "bausteinsicht sync"
Then a connector is drawn from "api" to the scope boundary of the view
And the connector is correctly attached
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.