This document provides a comprehensive guide to setting up your development environment, using the provided tooling, and following best practices for contributing to WireTuner.
- Prerequisites
- Initial Setup
- Development Commands
- Editor Integration
- Atomic Write Expectations
- Diagram Development
- Viewport Keyboard Shortcuts
- Testing Strategy
- Mock Events & Demo Data
- CI/CD Integration
- Verification
- Troubleshooting
Before you begin, ensure you have the following tools installed:
- Flutter SDK (>=3.5.0): Installation Guide
- Dart SDK (included with Flutter)
- Git: Installation Guide
- Just: Command runner for development shortcuts
- macOS:
brew install just - Windows:
scoop install justorchoco install just - Linux:
cargo install justor download from releases
- macOS:
- Melos: Multi-package workspace management (installed via
just setup)- Manual install:
dart pub global activate melos
- Manual install:
- PlantUML: For rendering component, state, and other UML diagrams
- macOS:
brew install plantuml - Windows: Download
plantuml.jarfrom PlantUML website - Linux:
apt-get install plantumlor download JAR
- macOS:
- Mermaid CLI: For rendering sequence, ERD, and timeline diagrams
- All platforms:
npm install -g @mermaid-js/mermaid-cli
- All platforms:
- lcov: For code coverage visualization
- macOS:
brew install lcov - Linux:
apt-get install lcov
- macOS:
After cloning the repository, run the initial setup command:
just setupThis command will:
- Install Flutter dependencies (
flutter pub get) - Activate melos globally
- Bootstrap the melos workspace (links all packages)
Check that all prerequisites are properly installed:
just doctorThis will display the versions of all required tools and warn about any missing optional dependencies.
WireTuner uses just to provide cross-platform development shortcuts that mirror CI workflows. All commands work identically on macOS, Linux, and Windows (with Git Bash or WSL).
| Command | Description | CI Equivalent |
|---|---|---|
just setup |
Install all dependencies and bootstrap workspace | N/A |
just lint |
Run linting checks across all packages | tools/lint.sh |
just test |
Run all unit tests | tools/test.sh |
just format |
Auto-format all Dart code | melos run format |
just diagrams |
Validate and render all diagrams | scripts/ci/diagram_check.sh |
just ci |
Run complete CI check suite locally | scripts/ci/run_checks.sh |
just clean |
Remove build artifacts and dependencies | melos clean |
just doctor |
Verify development environment setup | N/A |
Work with individual packages:
# Test a specific package
just test-package event_core
# Analyze a specific package
just analyze-package vector_engineRun specific test suites:
# Widget tests only
just test-widgets
# Integration tests only
just test-integration
# Generate coverage report
just coverage# Validate and render all diagrams
just diagrams
# Render a specific diagram
just render-diagram docs/diagrams/component_architecture.pumlWireTuner includes pre-configured VS Code tasks and launch configurations.
Available debug configurations:
- WireTuner (Debug): Launch app in debug mode
- WireTuner (Profile): Launch app in profile mode for performance analysis
- WireTuner (Release): Launch app in release mode
- Event Core - Unit Tests: Run event_core package tests
- Vector Engine - Unit Tests: Run vector_engine package tests
- Tool Framework - Unit Tests: Run tool_framework package tests
- IO Services - Unit Tests: Run io_services package tests
- All Tests (Current File): Run tests in currently open file
Usage: Press F5 or select configuration from Run and Debug panel.
Run tasks via Cmd/Ctrl+Shift+P → "Tasks: Run Task":
- Setup: Install Dependencies - Initial project setup
- Lint: Run All Checks - Execute linting (default test task)
- Test: Run All Tests - Execute all tests (default test task)
- Test: Widget Tests Only - Widget tests only
- Test: Integration Tests Only - Integration tests only
- Test: Coverage Report - Generate coverage report
- Format: Format Code - Auto-format code
- Diagrams: Validate and Render - Process all diagrams
- CI: Run Full CI Checks - Local CI simulation (default build task)
- Clean: Remove Build Artifacts - Clean workspace
- Doctor: Check Environment - Verify setup
Quick Access:
- Run Build Task:
Cmd/Ctrl+Shift+B(runs "CI: Run Full CI Checks") - Run Test Task:
Cmd/Ctrl+Shift+T(runs "Test: Run All Tests")
Pre-configured run configurations are available in .idea/runConfigurations/:
- Run All Tests: Execute full test suite
- Run Lint: Execute linting checks
- Run Full CI Checks: Local CI simulation
- Validate Diagrams: Process and validate diagrams
Usage:
- Run configurations appear automatically in the run configurations dropdown (top-right toolbar)
- Select desired configuration and click Run/Debug button
- Or use
Ctrl+R/Ctrl+Dshortcuts
Note: IntelliJ configurations invoke just commands under the hood, ensuring consistency with VS Code and CLI workflows.
Per Plan Directive #2, all code modifications must follow the single atomic write principle:
- Mental Blueprint First: Before editing any file, construct the complete desired state in your mental model
- Single Write Operation: Stage entire file content in memory, then write via single atomic operation (using
>redirection or equivalent) - No Incremental Edits: Avoid partial edits that would violate sampling/undo requirements
- Editor Integration: Configure your editor to save entire buffers atomically
- Ensures consistent state for autonomous agents
- Prevents partial file updates during concurrent operations
- Maintains clean diffs and version control history
- Supports reliable rollback and undo operations
- VS Code: Files are saved atomically by default
- IntelliJ: Files are saved atomically by default
- CLI Editors: Use temp files and
mvfor atomic operations - Scripts: Always redirect complete output:
cat content > file(notecho line >> fileincrementally)
WireTuner uses two diagramming formats:
Used for: Component diagrams, state machines, class diagrams
File Location: docs/diagrams/*.puml
Rendering:
# Validate and render all diagrams
just diagrams
# Render specific diagram
just render-diagram docs/diagrams/component_architecture.pumlPreview:
- VS Code: Install "PlantUML" extension for live preview
- IntelliJ: Built-in PlantUML support (enable in preferences)
Syntax Reference: PlantUML Guide
Used for: Sequence diagrams, ERDs, timelines
File Location: docs/diagrams/*.mmd
Rendering:
# Validate all Mermaid diagrams (included in `just diagrams`)
mmdc -i docs/diagrams/sequence_event_flow.mmd -o docs/diagrams/sequence_event_flow.pngPreview:
- VS Code: Install "Mermaid Preview" extension
- IntelliJ: Install "Mermaid" plugin
- Online: Mermaid Live Editor
Syntax Reference: Mermaid Documentation
All diagrams are validated and rendered in CI via scripts/ci/diagram_check.sh. Local runs via just diagrams ensure your diagrams will pass CI before pushing.
WireTuner provides keyboard shortcuts for efficient viewport navigation and control. These shortcuts are implemented in Task I2.T8 and follow the communication patterns defined in Section 2 and the persistence principles of Decision 6 (snapshot-based state restoration).
| Shortcut | Action | Description |
|---|---|---|
| Space + Drag | Pan Mode | Hold space bar and drag to pan the canvas. Cursor changes to grab/grabbing hand. |
| + or Shift+= | Zoom In | Zoom in by 10% increments around current pan point |
| Numpad + | Zoom In | Alternative zoom in using numpad |
| - | Zoom Out | Zoom out by 10% increments around current pan point |
| Numpad - | Zoom Out | Alternative zoom out using numpad |
| Cmd+0 (Mac) | Reset Viewport | Reset zoom to 100% and pan to origin |
| Ctrl+0 (Win/Linux) | Reset Viewport | Reset zoom to 100% and pan to origin |
| Scroll Wheel | Zoom | Zoom in/out around cursor position |
Viewport zoom is clamped to maintain usability:
- Minimum Zoom: 5% (0.05) - maximum zoom out
- Maximum Zoom: 800% (8.0) - maximum zoom in
All viewport changes (pan, zoom, canvas size) are automatically persisted within the document model:
- Viewport state is saved when gestures end (pan end, zoom end, scroll)
- Keyboard shortcuts trigger immediate persistence via
DocumentProvider.updateViewport - Document serialization includes viewport state for restore on reopen
- Coordinate transformations between controller (screen space) and domain (world space) are handled by
ViewportStateconverters
The viewport integration follows Decision 7 (Provider for State Management) and Section 2 Communication Patterns:
- ViewportBinding provides keyboard shortcuts via Flutter's Shortcuts/Actions API
- Space bar pan mode uses RawKeyboardListener to track key down/up state
- ViewportState syncs controller changes to domain viewport via
onViewportChangedcallback - DocumentProvider persists viewport in the immutable Document aggregate
- Round-trip conversion preserves viewport state across save/restore cycles
References:
- Architecture: Communication Patterns
- Decision: Provider State Management
- Task: I2.T8 Viewport Integration
WireTuner follows a comprehensive testing approach:
-
Unit Tests (
test/unit/,packages/*/test/)- Test individual functions, classes, and services
- Fast execution, no external dependencies
- Target Coverage: 80%+
-
Widget Tests (
test/widget/)- Test Flutter UI components in isolation
- Verify canvas rendering, tool interactions, UI state
-
Integration Tests (
test/integration/)- End-to-end workflows (save/load, import/export)
- Multi-component interactions
- File I/O and persistence validation
# All tests
just test
# Specific test suite
just test-widgets
just test-integration
# Package-specific tests
just test-package event_core
# With coverage
just coveragetest/
├── unit/ # Unit tests mirroring package structure
├── widget/ # Flutter widget tests for UI components
└── integration/ # End-to-end workflow tests
└── fixtures/ # Sample event data for testing
Follow Dart test conventions:
- Use
test()for unit tests - Use
testWidgets()for widget tests - Use
integration_testpackage for integration tests - Group related tests with
group() - Use descriptive test names explaining expected behavior
Example:
group('EventStore', () {
test('should persist events to SQLite', () {
// Arrange
final store = EventStore();
final event = DrawEvent(...);
// Act
store.append(event);
// Assert
expect(store.length, equals(1));
});
});WireTuner provides pre-built event fixtures for testing tool workflows and event replay without manual interaction.
Fixture Location: test/integration/test/integration/fixtures/sample_events.json
Contents:
- Rectangle shape creation event
- Path creation with line anchors
- Selection event
- Realistic timestamps and UUIDs
Loading Fixtures in Tests:
import 'dart:convert';
import 'package:flutter/services.dart';
// Load fixture JSON
final fixtureJson = await rootBundle.loadString(
'test/integration/test/integration/fixtures/sample_events.json'
);
final events = jsonDecode(fixtureJson) as List;
// Iterate and process events
for (final eventData in events) {
final eventType = eventData['eventType'] as String;
// ... handle event
}Use Cases:
- Automated integration tests (see
tool_pen_selection_test.dart) - Manual QA with pre-populated documents
- Demo scenarios for presentations
- Event replay performance benchmarking
Integration tests validate tool workflows and emit performance metrics:
# Run pen + selection integration test with verbose output
flutter test test/integration/test/integration/tool_pen_selection_test.dart --verboseSample Console Output:
=== Telemetry Validation ===
Event Count: 5
Replay Time: 18 ms
============================
All tests passed!
Telemetry Metrics Captured:
- Event count per workflow
- Replay latency (for small event sets: <50ms)
- Event sampling intervals (50ms target)
- Deterministic replay verification (3+ runs)
Reference: Tooling QA Checklist - Telemetry Validation
To create your own event sequences for testing:
-
Generate Events via Tools:
- Run the application in debug mode
- Perform desired tool interactions (pen tool path, selection, etc.)
- Events are logged to console if telemetry enabled
-
Extract Event JSON:
- Check SQLite database:
eventstable contains full event payloads - Or copy logged events from console/debug output
- Check SQLite database:
-
Save to Fixture File:
[ { "eventType": "CreatePathEvent", "eventId": "evt-001", "timestamp": 1699305600000, "pathId": "path-1", "startAnchor": {"x": 100.0, "y": 100.0}, "strokeColor": "#000000", "strokeWidth": 2.0 }, { "eventType": "AddAnchorEvent", "eventId": "evt-002", "timestamp": 1699305601000, "pathId": "path-1", "position": {"x": 200.0, "y": 150.0}, "anchorType": "bezier", "handleOut": {"x": 50.0, "y": -20.0}, "handleIn": {"x": -50.0, "y": 20.0} } ] -
Load in Tests:
- Add to
test/integration/test/integration/fixtures/ - Load via
rootBundle.loadString()or direct file I/O - Replay via
EventReplayeror inject into tool tests
- Add to
Validation: Event schema must match Event Schema Reference
For live demonstrations without manual interaction:
Option 1: Replay Fixture Events
// In demo setup code
final replayer = EventReplayer(
eventStore: eventStore,
snapshotStore: snapshotStore,
dispatcher: dispatcher,
);
// Load and replay fixture
final fixtureEvents = await loadFixture('sample_events.json');
for (final event in fixtureEvents) {
await eventStore.insertEvent(documentId, event);
}
final state = await replayer.replayFromSnapshot(
documentId: documentId,
maxSequence: fixtureEvents.length - 1,
);Option 2: Programmatic Event Injection
// Inject events directly (for widget tests)
final mockEvents = [
CreatePathEvent(...),
AddAnchorEvent(...),
FinishPathEvent(...),
];
for (final event in mockEvents) {
await documentProvider.applyEvent(event);
}Use Cases:
- Conference demos with pre-built artwork
- UI screenshots without manual drawing
- Benchmark tests with large event volumes
To create screenshots or GIFs for documentation and demos:
Screenshots:
# Full screen: Cmd+Shift+3
# Selected area: Cmd+Shift+4 (then drag)
# Window capture: Cmd+Shift+4, then press Space, click windowScreen Recording:
# Built-in: Cmd+Shift+5 (opens recording toolbar)
# Or use QuickTime Player → File → New Screen RecordingRecommended Tools:
- Kap - Open-source screen recorder with GIF export
- CleanShot X - Professional screenshot/recording (paid)
Screenshots:
# Snipping Tool: Windows+Shift+S (select area)
# Full screen: PrtScn key
# Active window: Alt+PrtScnScreen Recording:
# Game Bar: Windows+G (opens recording controls)
# Or Windows+Alt+R to start/stop recordingRecommended Tools:
- ScreenToGif - Free recorder with built-in GIF editor
- ShareX - Open-source screenshot/recording suite
OBS Studio - Professional-grade screen recording
- Supports macOS, Windows, Linux
- Scene composition, overlays, custom layouts
- Export to MP4, MOV, etc.
GIF Conversion:
# FFmpeg (install via brew/choco)
ffmpeg -i input.mp4 -vf "fps=10,scale=800:-1" output.gifRecommended Directory Structure:
docs/assets/
├── screenshots/ # PNG/JPG static images
│ ├── pen_tool_bezier_demo.png
│ └── selection_marquee.png
└── gifs/ # Animated GIFs
├── pen_tool_workflow.gif
└── tool_switching.gif
Update .gitignore (if needed):
If screenshots/GIFs become large (>1 MB), consider excluding them from version control:
# Documentation media (large files)
docs/assets/screenshots/*.png
docs/assets/gifs/*.gif
# Keep a README or placeholder
!docs/assets/screenshots/README.md
!docs/assets/gifs/README.mdAlternative: Use Git LFS for large binary assets:
git lfs track "docs/assets/**/*.png"
git lfs track "docs/assets/**/*.gif"Current Status: .gitignore does not yet exclude media assets. Update if
binary files exceed 1 MB to keep repository lean.
Before pushing, always run the full CI suite locally:
just ciThis executes the same checks that run in GitHub Actions:
- Lint checks (
flutter analyze) - Format validation (
dart format --output=none --set-exit-if-changed) - Unit tests (
flutter test) - Widget tests
- Integration tests
- Diagram validation and rendering
- SQLite smoke checks
CI runs automatically on:
- Push to any branch
- Pull requests to
main
Workflow File: .github/workflows/ci.yml
Status Badges: Available in root README.md
✅ Run just ci successfully
✅ All tests passing
✅ No lint warnings
✅ Code formatted (just format)
✅ Diagrams render without errors
✅ Commit messages follow conventions
After initial setup, verify everything works:
# 1. Check environment
just doctor
# 2. Run lint checks
just lint
# 3. Run tests
just test
# 4. Validate diagrams
just diagrams
# 5. Run full CI suite
just ciExpected Outcome: All commands should complete successfully with no errors.
Solution: Install just:
- macOS:
brew install just - Windows:
scoop install justorchoco install just
Solution: Run just setup or manually install:
dart pub global activate melos
export PATH="$PATH":"$HOME/.pub-cache/bin" # Add to ~/.bashrc or ~/.zshrcSolution: Install PlantUML:
- macOS:
brew install plantuml - Verify:
plantuml -version
Solution: Install Mermaid CLI:
npm install -g @mermaid-js/mermaid-cli
mmdc --version # Verify installationIssue: Path separators or shell incompatibilities
Solution:
- Use Git Bash or WSL for consistent shell environment
- Ensure
bashis available in PATH - Check that file paths use forward slashes in test assertions
Solution:
- Ensure
justis in your PATH - Reload VS Code window:
Cmd/Ctrl+Shift+P→ "Developer: Reload Window" - Check Output panel for error details
If you encounter issues not covered here:
- Check existing GitHub Issues
- Review Architecture Documentation
- Consult ADR (Architectural Decision Records)
- Open a new issue with:
- Output of
just doctor - Full error message
- Steps to reproduce
- Output of
- Plan Overview
- Architecture Overview
- Event Schema Reference
- File Format Specification
- ADRs (Architectural Decision Records)
Last Updated: 2025-11-09 Maintained By: WireTuner Development Team Related Tasks: I3.T11 - Documentation Update