Complete implementation with Docker support

- Full discussion orchestration system
- GUI (Dear PyGui) and TUI (urwid) interfaces
- 14 SmartTools for parsing, voting, participants
- Docker and docker-compose for testing
- Templates for feature and brainstorm workflows
- Auto phase advancement on consensus

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rob 2025-12-23 23:40:25 -04:00
parent 3b0c0339f7
commit 6d9f32b20c
164 changed files with 18753 additions and 1549 deletions

35
.dockerignore Normal file
View File

@ -0,0 +1,35 @@
# Git
.git
.gitignore
# Python
__pycache__
*.py[cod]
*$py.class
*.so
.Python
*.egg-info
.eggs
*.egg
dist
build
.venv
venv
ENV
# IDE
.idea
.vscode
*.swp
# Docker
Dockerfile*
docker-compose*
.docker
# Misc
*.md
!README.md
.coverage
.pytest_cache
htmlcov

33
AGENTS.md Normal file
View File

@ -0,0 +1,33 @@
# Repository Guidelines
## Project Structure & Module Organization
- Core library and CLI live in `src/discussions` (CLI entrypoint `cli.py`, models/orchestration in `discussion.py` and `runner.py`, parsing/voting utilities in `markers.py` and `voting.py`, participant registry in `participant.py`).
- Tests sit in `tests/` with pytest; mirror module names when adding coverage (e.g., `test_voting.py`).
- User-facing docs are under `docs/` (design + implementation notes), with runnable discussion examples in `examples/` and SmartTool configs in `smarttools/`.
- Discussion templates for new files live in `templates/` (`feature.yaml`, `brainstorm.yaml`).
## Build, Test, and Development Commands
- Install in editable mode with dev extras: `python -m pip install -e .[dev]`.
- Run the CLI locally: `discussions --help`, `discussions new "My Feature" --template feature`, `discussions turn examples/feature_discussion.md`.
- Execute the manual orchestration walkthrough: `bash scripts/run-turn.sh examples/feature_discussion.md` (shows each SmartTool step).
- Run tests: `pytest` or `pytest --maxfail=1 -q` for quick feedback.
## Coding Style & Naming Conventions
- Follow PEP 8 with 4-space indentation and type hints for public functions; prefer concise module-level docstrings like the existing files.
- Keep modules thin: orchestration in Python, heavy lifting in SmartTools via stdin/stdout (see `docs/DESIGN.md` for the Unix-style adapter pattern).
- Use snake_case for modules/functions, CapWords for classes, and uppercase for constants. Avoid adding new global state; prefer pure functions or dataclasses.
- New CLI flags should use argparse patterns already present in `cli.py`; align option names with existing verbs (`new`, `turn`, `status`, `comment`, `participants`).
## Testing Guidelines
- Add pytest coverage alongside new code; name tests after the module (`test_<module>.py`) and include scenario-focused test names (`test_consensus_requires_human`).
- When touching parsing or voting logic, assert both positive and negative cases (see `tests/test_markers.py` and `tests/test_voting.py`).
- If a feature depends on SmartTools output, stub with deterministic JSON fixtures instead of live calls.
## Commit & Pull Request Guidelines
- Use short, imperative commit subjects (e.g., `Add CHANGES threshold guard`); keep body lines wrapped and include rationale when non-obvious.
- PRs should link related issues, describe behavior changes, and show before/after snippets for CLI flows or discussion markdown changes.
- Always note test coverage (`pytest` command) and any SmartTools/config prerequisites for reviewers.
## Security & Configuration Tips
- Do not commit API keys or SmartTools cache; local participant configs live in `~/.smarttools/`.
- Favor configuration via environment variables or `.env` ignored files; validate inputs before invoking external tools to avoid malformed prompts.

371
CLAUDE.md Normal file
View File

@ -0,0 +1,371 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Build & Test Commands
```bash
# Install in development mode
pip install -e ".[dev]"
# Run all tests
pytest
# Run a single test file
pytest tests/test_markers.py
# Run a single test
pytest tests/test_markers.py::TestExtractVote::test_ready_vote
# Run with coverage
pytest --cov=discussions
# Test SmartTools directly (Unix philosophy - test tools independently)
cat examples/brainstorm_notification_system.md | discussion-parser | jq .
cat examples/brainstorm_notification_system.md | discussion-parser | discussion-vote-counter
```
## Architecture
Orchestrated Discussions is a multi-agent AI discussion orchestrator that manages structured conversations between AI personas with voting and phase-based workflows.
### Project Ecosystem
This is the middle layer of a three-project stack:
1. **SmartTools** - AI provider abstraction and tool execution (dependency)
2. **Orchestrated Discussions** (this) - Conversation orchestration
3. **CascadingDev** - Git-driven automation (depends on this)
---
## Architectural Philosophy: Unix Philosophy & Pipes and Filters
**This project strictly follows the Unix Philosophy.** This is non-negotiable.
### Core Principles
1. **Each tool does one thing well** - SmartTools are self-contained, complete units
2. **Tools communicate via stdin/stdout** - JSON flows through pipes
3. **Tools are composable** - Any tool's output can be another's input
4. **No tool knows about another's internals** - Only the interface (stdin/stdout/args)
5. **The discussion file is the source of truth** - Tools read and write to it
### Architecture Rules
**NEVER:**
- Import SmartTools internals (`from smarttools.providers import ...`)
- Duplicate logic that exists in a SmartTool
- Build "helper functions" when you should make a SmartTool
- Call AI providers directly - that's what SmartTools are for
- Put orchestration logic inside a tool (tools are stateless)
**ALWAYS:**
- Call SmartTools via subprocess: `subprocess.run(["tool-name"], input=data, ...)`
- Pass data through stdin, receive through stdout
- Keep Python layer thin - it only orchestrates, never implements
- Each SmartTool must be independently testable: `cat file | tool | jq .`
- Create a new SmartTool rather than adding complexity to existing code
### Anti-Pattern Examples
```python
# WRONG - Importing SmartTools internals, bypassing the tool
from smarttools.providers import call_provider
prompt = build_prompt_in_python(discussion) # Logic that belongs in SmartTool
result = call_provider("claude", prompt)
# RIGHT - Calling the SmartTool via subprocess
result = subprocess.run(
["discussion-architect", "--callout", callout],
input=discussion_content,
capture_output=True,
text=True
)
response = json.loads(result.stdout)
```
```python
# WRONG - Duplicating vote counting logic in Python
def count_votes(discussion):
ready = sum(1 for v in votes if v == "READY")
# ... reimplementing what discussion-vote-counter does
# RIGHT - Using the SmartTool
result = subprocess.run(
["discussion-vote-counter"],
input=parser_output,
capture_output=True,
text=True
)
consensus = json.loads(result.stdout)
```
### Why This Matters
Linux follows these principles and is arguably the most powerful and stable software system ever created. Benefits:
- **Debuggability**: Test any tool in isolation: `cat test.md | discussion-parser | jq .`
- **Flexibility**: Swap implementations without changing orchestration
- **Reliability**: Each tool can be hardened independently
- **Composability**: Build new workflows by combining existing tools
- **Maintainability**: Change one tool without breaking others
### The Python Layer's Role
The Python code in this project (`runner.py`, `cli.py`, `ui/`) is **orchestration only**:
- Decide which tools to call and in what order
- Pass data between tools (pipe stdout to stdin)
- Handle errors and retries
- Provide user interface
It should **never** contain:
- AI prompt construction (that's in SmartTool configs)
- Vote counting logic (that's `discussion-vote-counter`)
- Response parsing logic (that's in each SmartTool's code steps)
- Discussion format knowledge (that's `discussion-parser`)
---
### Key Design Decision: Participants ARE SmartTools
Participants are implemented as SmartTools, not a separate system. Each participant lives in `~/.smarttools/discussion-{alias}/config.yaml` and can be:
- Invoked directly for testing: `cat discussion.md | discussion-architect --callout "..."`
- Edited via SmartTools TUI for prompt debugging
- Created via `discussions participants add` wizard (generates SmartTool config)
This means:
- No duplicate participant definition system
- Full SmartTools features available (multi-step pipelines, code steps, provider fallbacks)
- Independent testing and debugging of each participant
### Core Abstractions
- **Discussion** (`discussion.py`): A markdown file with metadata headers, context, and comment blocks. Append-only - content grows but never shrinks. State stored in HTML comments (`<!-- Key: value -->`).
- **Participant**: A SmartTool in `~/.smarttools/discussion-{alias}/`. Discovered by naming convention. Has personality prompt, expertise metadata, and vote behavior. Two types: `voting` and `background`.
- **Markers** (`markers.py`): Structured annotations parsed from comment text:
- `VOTE: READY|CHANGES|REJECT`
- `Q:` / `QUESTION:` - Questions
- `TODO:` / `ACTION:` - Action items
- `DECISION:` - Recorded decisions
- `CONCERN:` - Raised concerns
- `DIAGRAM:` - Diagram file references (e.g., `DIAGRAM: diagrams/flow.puml`)
- `@alias` - Mentions
- **Voting** (`voting.py`): Consensus calculation with configurable thresholds.
- **Runner** (`runner.py`): Invokes participant SmartTools via subprocess, parses JSON responses, appends to discussion file.
### Discussion File Format
```markdown
<!-- DISCUSSION -->
<!-- Title: Feature Name -->
<!-- Phase: initial_feedback -->
<!-- Status: OPEN -->
<!-- Template: feature -->
<!-- Participants: architect, security, pragmatist -->
# Title
## Context
...
---
Name: AI-Architect
Comment content with markers...
VOTE: CHANGES
---
```
Comment blocks are delimited by `---` and start with `Name: AuthorName`.
### Template System
Templates define phase-specific behavior for discussions. Stored in `templates/` as YAML files.
```yaml
# templates/feature.yaml
phases:
initial_feedback:
goal: Gather diverse perspectives
instructions: |
- Focus on feasibility and risks
- Raise blocking issues early
voting: false
next_phase: detailed_review
```
**How it works:**
1. Discussion references template via `<!-- Template: feature -->`
2. Participant SmartTools read the template file to get phase context
3. AI prompts include phase goal and instructions for context-aware responses
Participants use `--templates-dir` argument (default: `templates`) to locate template files.
### Consensus Logic
- `VotingConfig.threshold_ready` (default 0.67): Fraction of READY votes needed
- `VotingConfig.threshold_reject` (default 0.01): Any REJECT blocks by default
- `VotingConfig.human_required` (default True): Needs human READY vote
- Human participants detected by name NOT starting with `ai_`, `ai-`, `bot_`, `bot-`
### SmartTools Integration
```
Orchestrated Discussions (thin orchestration layer)
│ invokes via subprocess
SmartTools (discussion-* tools)
├── Utility tools (code-only):
│ - discussion-parser → JSON structured data
│ - discussion-validator → validation results
├── Orchestration tools (code-only):
│ - discussion-vote-counter → consensus calculation
│ - discussion-mention-router → participant routing
│ - discussion-status-promoter → status transitions
│ - discussion-turn-appender → append responses
│ - discussion-config → modify metadata
├── Utility tools (AI):
│ - discussion-summarizer → .sum.md files
└── Participant tools (AI):
- discussion-moderator, discussion-architect, etc.
│ uses providers
AI Providers (claude, codex, gemini, etc.)
```
**Everything is a SmartTool** - parsing, validation, orchestration, summarization, and participants. This means:
- All components testable independently: `cat discussion.md | discussion-parser | jq .`
- Full pipelines runnable manually: `cat d.md | discussion-parser | discussion-vote-counter | jq .`
- Debuggable via SmartTools TUI
- Composable: tools can call other tools
### Manual Turn Execution
```bash
# Parse → route → call participants → append → count votes → promote status
DISCUSSION="feature.md"
STATE=$(cat "$DISCUSSION" | discussion-parser)
ROUTING=$(echo "$STATE" | discussion-mention-router)
# ... call each participant, collect responses ...
# ... append responses, count votes, promote status ...
```
See `scripts/run-turn.sh` for a complete example.
### Project Files
- `docs/DESIGN.md` - Full architecture and SmartTool specifications
- `docs/IMPLEMENTATION.md` - Phased implementation plan
- `smarttools/` - Bundled SmartTool configs (copied to ~/.smarttools/ on install)
- `templates/` - Discussion workflow templates (phase definitions)
- `examples/` - Example discussion files for testing
- `scripts/run-turn.sh` - Manual turn orchestration script
Participants respond with JSON: `{"comment": "...", "vote": "READY|CHANGES|REJECT|null"}`
or sentinel: `{"sentinel": "NO_RESPONSE"}`
### UI Options
Two UI implementations available:
- **GUI** (default): Dear PyGui-based, native image viewing for diagrams, read-aloud buttons
- **TUI**: urwid-based, text-only terminal interface, read-aloud buttons
Both UIs include:
- "Read" button on each comment for text-to-speech (requires `~/.smarttools/read-aloud/`)
- "Artifact" button in comment dialog for creating diagrams/visuals
### Artifact Editor Integration
Both UIs integrate with the standalone Artifact Editor (`~/PycharmProjects/artifact-editor`) for creating visual artifacts:
**GUI Integration:**
- "Add Artifact" button in the comment dialog
- "New Artifact" button in the diagrams panel
- Launches artifact-editor, waits for save, captures actual file path
- Automatically adds `DIAGRAM: path/to/file` marker to comment
**TUI Integration:**
- "Artifact" button in the comment input widget
- If `$DISPLAY` is available: launches artifact-editor GUI
- If headless (SSH): falls back to `$EDITOR` (nano/vim) for text editing
- Diagram reference added to comment on save
**Integration Protocol:**
```bash
# Artifact editor outputs on save:
ARTIFACT_SAVED:/absolute/path/to/file.svg
# Parent app parses this to get actual saved path
# (handles format changes - user may switch from .puml to .svg)
```
```bash
# Launch GUI (default)
discussions ui
# Launch TUI
discussions ui --tui
# Or via module
python -m src.discussions.ui # GUI
python -m src.discussions.ui --tui # TUI
```
### Keyboard Shortcuts (GUI)
| Key | Action |
|-----|--------|
| `Q` | Quit |
| `R` | Refresh |
| `T` | Run turn |
| `C` | Add comment |
| `D` | View diagrams |
| `Esc` | Close dialogs |
### Keyboard Shortcuts (TUI)
| Key | Action |
|-----|--------|
| `q` | Quit |
| `r` | Run turn (invoke participants) |
| `d` | View diagrams (ASCII preview) |
| `↑/↓` | Navigate |
| `Enter` | Select |
| `Esc` | Close dialogs |
### SmartTools Arguments
Participant SmartTools accept these arguments:
- `--callout` - Specific question or @mention context
- `--templates-dir` - Path to templates directory (default: `templates`)
- `--diagrams-dir` - Path to save diagrams (default: `diagrams`)
- `--log-file` - Path to log file for progress updates (used by TUI for parallel execution)
### Source Structure
```
src/discussions/
├── cli.py # CLI entry point (discussions command)
├── discussion.py # Discussion model, file I/O
├── participant.py # Participant discovery from ~/.smarttools/discussion-*
├── markers.py # Marker parsing (VOTE:, Q:, TODO:, CONCERN:, etc.)
├── voting.py # Consensus calculation
├── runner.py # Turn orchestration (calls SmartTools via subprocess)
└── ui/
├── __init__.py
├── __main__.py # Module entry point
├── gui.py # Dear PyGui interface (default)
├── tui.py # urwid terminal interface
└── widgets.py # Shared UI components
```

101
Dockerfile Normal file
View File

@ -0,0 +1,101 @@
# Orchestrated Discussions - Multi-agent AI discussion orchestration
#
# Multi-stage build:
# Stage 1: Build SmartTools base
# Stage 2: Build Orchestrated Discussions with SmartTools
#
# Build: docker build -t orchestrated-discussions .
# Run: docker run -it --rm orchestrated-discussions discussions --help
# Test: docker run -it --rm orchestrated-discussions pytest -v
# ==============================================================================
# Stage 1: SmartTools Base
# ==============================================================================
FROM python:3.12-slim AS smarttools
WORKDIR /smarttools
# Clone SmartTools from Gitea (or provide build arg for local path)
ARG SMARTTOOLS_REPO=https://gitea.brrd.tech/rob/SmartTools.git
RUN apt-get update && apt-get install -y --no-install-recommends git && \
git clone ${SMARTTOOLS_REPO} . || \
echo "Clone failed - will need COPY in next stage"
# Install SmartTools
RUN pip install --no-cache-dir -e . || true
# ==============================================================================
# Stage 2: Orchestrated Discussions
# ==============================================================================
FROM python:3.12-slim
LABEL maintainer="rob"
LABEL description="Orchestrated Discussions - Multi-agent AI discussion framework"
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
curl \
plantuml \
jq \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Copy SmartTools from stage 1
COPY --from=smarttools /smarttools /smarttools
# Install SmartTools
RUN pip install --no-cache-dir -e /smarttools
# Copy Orchestrated Discussions files
COPY pyproject.toml README.md ./
COPY src/ ./src/
COPY smarttools/ ./smarttools/
COPY templates/ ./templates/
COPY examples/ ./examples/
COPY tests/ ./tests/
# Install Orchestrated Discussions
RUN pip install --no-cache-dir -e ".[dev]"
# Create directories
RUN mkdir -p /root/.smarttools /root/.local/bin
# Install bundled discussion SmartTools
RUN for tool in smarttools/*/; do \
if [ -d "$tool" ]; then \
name=$(basename "$tool"); \
cp -r "$tool" /root/.smarttools/; \
printf '#!/bin/bash\nexec python3 -m smarttools.runner %s "$@"\n' "$name" > "/root/.local/bin/$name"; \
chmod +x "/root/.local/bin/$name"; \
fi; \
done
# Install SmartTools example tools and refresh wrappers
RUN python /smarttools/examples/install.py 2>/dev/null || true && \
smarttools refresh 2>/dev/null || true
# Add local bin to PATH
ENV PATH="/root/.local/bin:${PATH}"
# Healthcheck - verify key commands work
RUN discussions --help && \
discussion-parser --help && \
smarttools list | head -5
# Default: run tests
CMD ["pytest", "-v", "tests/"]
# ==============================================================================
# Usage Examples:
# ==============================================================================
# docker build -t orchestrated-discussions .
# docker run -it --rm orchestrated-discussions # Run tests
# docker run -it --rm orchestrated-discussions discussions --help # CLI help
# docker run -it --rm orchestrated-discussions discussions participants # List participants
# docker run -it --rm orchestrated-discussions bash # Interactive shell
#
# With mounted examples:
# docker run -it --rm -v $(pwd)/examples:/app/examples orchestrated-discussions \
# discussions status /app/examples/feature_discussion.discussion.md

323
README.md
View File

@ -2,9 +2,23 @@
**Multi-agent AI discussion orchestration with voting and phases.**
Conduct structured discussions between multiple AI personas, each with distinct perspectives, expertise, and voting behavior.
Conduct structured discussions between multiple AI personas, each with distinct perspectives, expertise, and voting behavior. Built on the Unix philosophy - each component is a composable SmartTool that can be tested and debugged independently.
## Key Features
- **Structured Discussions**: Append-only markdown files with metadata, comments, and markers
- **AI Participants**: Customizable personas (architect, security, pragmatist, etc.)
- **Phase-based Workflows**: Templates define discussion phases with different goals
- **Voting & Consensus**: READY/CHANGES/REJECT votes with configurable thresholds
- **Dual UI**: Both graphical (Dear PyGui) and terminal (urwid) interfaces
- **Unix Philosophy**: All logic lives in SmartTools, Python layer is thin orchestration
## Quick Start
```bash
# Install in development mode
pip install -e ".[dev]"
# Create a discussion
discussions new "Add user authentication" --template feature
@ -13,56 +27,303 @@ discussions turn auth-discussion.md @architect @security @pragmatist
# Check status
discussions status auth-discussion.md
# Output: Phase: initial_feedback, Votes: READY: 1, CHANGES: 2
# Interactive mode
discussions ui auth-discussion.md
# Add a human comment with vote
discussions comment auth-discussion.md "Looks good to me" --vote ready
# Launch interactive UI (GUI by default)
discussions ui
# Or use terminal UI
discussions ui --tui
```
## Installation
```bash
pip install orchestrated-discussions
# Clone and install
git clone https://github.com/rob/orchestrated-discussions.git
cd orchestrated-discussions
pip install -e ".[dev]"
# For TUI support
pip install orchestrated-discussions[tui]
# For TUI support only
pip install -e ".[tui]"
```
### Requirements
- Python 3.10+
- [SmartTools](https://github.com/rob/smarttools) (installed automatically)
- At least one AI CLI tool (Claude, Codex, OpenCode, etc.)
## Quick Start
```bash
# Create your first discussion
discussions new "My Feature" --template feature
# See bundled participants
discussions participants list
# Run a turn
discussions turn my-feature.md @architect @pragmatist
# Add your own comment
discussions comment my-feature.md "I think we should..." --vote READY
```
- At least one AI CLI tool (Claude, Codex, etc.)
## How It Works
1. **Discussions** are markdown files with structured comments
2. **Participants** are AI personas with distinct perspectives (architect, security, pragmatist, etc.)
3. **Phases** guide the discussion through stages (feedback → review → vote)
1. **Discussions** are markdown files with structured comments and metadata
2. **Participants** are AI personas implemented as SmartTools
3. **Phases** guide discussion through stages (feedback -> review -> vote)
4. **Votes** (READY/CHANGES/REJECT) determine consensus
5. **Markers** (Q:, TODO:, DECISION:) capture structured information
5. **Markers** (Q:, TODO:, DECISION:, CONCERN:) capture structured information
### Architecture
```
User/CLI/UI
┌──────────────────────────────────────────┐
│ Orchestrated Discussions │
│ - Thin orchestration layer (runner.py) │
│ - File I/O, turn sequencing │
│ - Calls SmartTools via subprocess │
└────────────────────┬─────────────────────┘
│ stdin/stdout
┌──────────────────────────────────────────┐
│ SmartTools (discussion-*) │
│ │
│ Utility: parser, validator │
│ Orchestration: vote-counter, router │
│ Participants: architect, security, etc. │
└────────────────────┬─────────────────────┘
AI Providers (claude, etc.)
```
## CLI Commands
| Command | Description |
|---------|-------------|
| `discussions new <title>` | Create a new discussion file |
| `discussions status <file>` | Show discussion status, votes, and consensus |
| `discussions turn <file> [@participants]` | Run a discussion turn |
| `discussions comment <file> <text>` | Add a human comment |
| `discussions participants` | List available participant SmartTools |
| `discussions advance <file> --phase <id>` | Advance to a specific phase |
| `discussions ui [directory]` | Launch interactive UI |
### Examples
```bash
# Create feature discussion
discussions new "Add caching layer" --template feature -c "We need to improve API response times"
# Create brainstorm session
discussions new "Notification System Design" --template brainstorm
# Run turn with all participants
discussions turn my-feature.md
# Run turn with specific participants
discussions turn my-feature.md @architect @security
# Add human comment with vote
discussions comment my-feature.md "I agree with the concerns" --vote changes
# Check consensus status
discussions status my-feature.md
```
## Templates
Templates define the workflow phases for different discussion types.
### Feature Template (3 phases)
| Phase | Goal | Voting |
|-------|------|--------|
| `initial_feedback` | Gather diverse perspectives | No |
| `detailed_review` | Deep dive into implementation | No |
| `consensus_vote` | Reach agreement | Yes (67% READY) |
### Brainstorm Template (6 phases)
| Phase | Goal | Voting |
|-------|------|--------|
| `seed` | Frame the problem | No |
| `diverge` | Generate ideas freely | No |
| `cluster` | Group ideas into themes | Yes (50% READY) |
| `sketch` | Create rough diagrams | No |
| `reality_check` | Ground in reality | No |
| `decide` | Commit to approach | Yes (67% READY) |
## Bundled SmartTools
### Utility Tools (code-only)
| Tool | Purpose |
|------|---------|
| `discussion-parser` | Extract structured JSON from discussion markdown |
| `discussion-validator` | Validate discussion format |
| `discussion-summarizer` | Generate summary files (AI) |
### Orchestration Tools (code-only)
| Tool | Purpose |
|------|---------|
| `discussion-vote-counter` | Count votes, determine consensus |
| `discussion-mention-router` | Route @mentions to participants |
| `discussion-status-promoter` | Check status transitions |
| `discussion-turn-appender` | Append responses to discussion |
| `discussion-config` | Modify discussion metadata |
### Participant Tools (AI)
| Tool | Alias | Perspective |
|------|-------|-------------|
| `discussion-architect` | `@architect` | Systems thinking, scalability |
| `discussion-security` | `@security` | Threat modeling, vulnerabilities |
| `discussion-pragmatist` | `@pragmatist` | MVP focus, shipping velocity |
| `discussion-moderator` | `@moderator` | Facilitation, phase management |
| `discussion-diagram-editor` | `@diagram-editor` | PlantUML diagram creation |
## Discussion File Format
```markdown
<!-- DISCUSSION -->
<!-- Title: Feature X Implementation -->
<!-- Phase: initial_feedback -->
<!-- Status: OPEN -->
<!-- Template: feature -->
<!-- Participants: architect, security, pragmatist -->
# Feature X Implementation
## Context
We need to implement feature X that allows users to...
---
Name: AI-Architect
Looking at this from a systems perspective...
Q: Have we considered using the adapter pattern here?
@pragmatist What's your view on complexity vs. speed?
VOTE: CHANGES
---
Name: Human
I agree with the architect's concerns.
VOTE: READY
---
```
### Markers
| Marker | Purpose | Example |
|--------|---------|---------|
| `VOTE:` | Cast a vote | `VOTE: READY` |
| `Q:` | Ask a question | `Q: What about caching?` |
| `TODO:` | Action item | `TODO: Research rate limits` |
| `DECISION:` | Record decision | `DECISION: Use PostgreSQL` |
| `CONCERN:` | Raise concern | `CONCERN: Security implications` |
| `DIAGRAM:` | Reference diagram | `DIAGRAM: diagrams/flow.puml` |
| `@alias` | Mention participant | `@security What do you think?` |
## User Interfaces
### GUI (Default)
Built with Dear PyGui for native graphics support.
```bash
discussions ui
# or
python -m src.discussions.ui
```
**Features:**
- Native image viewing for PlantUML diagrams
- Split-pane diagram viewer (source + rendered)
- Tabbed interface for discussions, diagrams, output
- **Read/Stop button** on each comment for TTS (changes to "Stop" while reading)
**Keyboard Shortcuts:**
| Key | Action |
|-----|--------|
| `Q` | Quit |
| `R` | Refresh |
| `T` | Run turn |
| `C` | Add comment |
| `D` | View diagrams |
| `Esc` | Close dialogs |
### TUI (Terminal)
Built with urwid for terminal-only environments.
```bash
discussions ui --tui
# or
python -m src.discussions.ui --tui
```
**Features:**
- ASCII diagram preview via `plantuml -tutxt`
- Works over SSH, no X11 required
- Lightweight dependencies
- **Read/Stop button** on each comment for TTS (toggles while reading)
**Keyboard Shortcuts:**
| Key | Action |
|-----|--------|
| `q` | Quit |
| `r` | Run turn |
| `d` | View diagrams |
| `Up/Down` | Navigate |
| `Enter` | Select |
| `Esc` | Close dialogs |
## Testing SmartTools Directly
The Unix philosophy means you can test each tool independently:
```bash
# Parse a discussion
cat examples/brainstorm_notification_system.md | discussion-parser | jq .
# Count votes
cat examples/voted_discussion.md | discussion-parser | discussion-vote-counter
# Route mentions
cat examples/feature_discussion.md | discussion-parser | discussion-mention-router
# Full pipeline manually
./scripts/run-turn.sh examples/feature_discussion.md
```
## Project Structure
```
orchestrated-discussions/
├── src/discussions/
│ ├── cli.py # CLI entry point
│ ├── discussion.py # Discussion model, file I/O
│ ├── markers.py # Marker parsing (VOTE, Q, TODO, etc.)
│ ├── participant.py # Participant discovery from ~/.smarttools/
│ ├── runner.py # Turn orchestration (calls SmartTools)
│ ├── voting.py # Consensus calculation
│ └── ui/
│ ├── gui.py # Dear PyGui interface
│ ├── tui.py # urwid terminal interface
│ └── widgets.py # Shared UI components
├── smarttools/ # Bundled SmartTool configs
├── templates/ # Discussion workflow templates
├── examples/ # Example discussion files
├── scripts/ # Manual orchestration scripts
├── tests/ # pytest tests
└── docs/ # Design documentation
```
## Documentation
- [Design Document](docs/DESIGN.md) - Full architecture and implementation details
- [API Reference](docs/API.md) - Python API documentation
- [Participant Guide](docs/PARTICIPANTS.md) - Creating custom personas
- [Design Document](docs/DESIGN.md) - Full architecture and SmartTool specs
- [Implementation Plan](docs/IMPLEMENTATION.md) - Phased development plan
- [Pipeline Schema](docs/PIPELINE_SCHEMA.md) - Turn pipeline configuration
## Project Context

View File

@ -0,0 +1,382 @@
<!-- DISCUSSION -->
<!-- Title: Artifact Editor - AI-Enhanced Diagram and 3D Model Creator -->
<!-- Phase: initial_feedback -->
<!-- Status: OPEN -->
<!-- Created: 2025-12-19T02:07:49Z -->
<!-- Template: brainstorm -->
<!-- Participants: architect, security, pragmatist -->
# Artifact Editor - AI-Enhanced Diagram and 3D Model Creator
## Context
## Overview
We want to build a standalone **Artifact Editor** that can be launched from any application to create visual artifacts like diagrams, sketches, and 3D models.
## Key Requirements
1. **Standalone executable** - Can be launched via command line with arguments
2. **Multiple artifact types** - Mermaid, PlantUML, OpenSCAD/SolidPython, SVG, ASCII art
3. **AI assistance** - Voice input, conversational editing, auto-generation
4. **Integration contract** - Simple stdin/stdout/exit-code interface for parent apps
5. **Live preview** - See rendered output as you edit code
## Integration Target
Primary integration with **orchestrated-discussions** project:
- User clicks 'Add Artifact' in comment dialog
- Launches artifact-editor with output path argument
- User creates/edits artifact
- On save, outputs 'ARTIFACT_SAVED:/path/to/file'
- Parent app embeds artifact reference in comment
## Questions to Explore
- What's the right UI framework? (urwid TUI, Dear PyGui, web-based?)
- How should AI assistance work? (SmartTools integration?)
- What's the MVP feature set?
- How do we handle 3D model preview?
- Should we support collaborative editing?
## Project Scaffold
Initial scaffold already created at ~/PycharmProjects/artifact-editor with:
- pyproject.toml
- Basic CLI structure
- Renderer base class
- Mermaid and OpenSCAD renderer stubs
## Requirements
- [ ] [Requirement 1]
- [ ] [Requirement 2]
## Open Questions
- [Question 1]
---
*Discussion begins below.*
---
Name: AI-Pragmatist
## Practical Shipping Analysis
This is a classic case of solving tomorrow's problems today. Let me break down what we actually need vs what's being proposed.
### CONCERN: COMPLEXITY - Overscoped for Integration Need
The stated goal is "User clicks 'Add Artifact' in orchestrated-discussions." But the proposed scope includes:
- Multiple diagram types (Mermaid, PlantUML, OpenSCAD, SVG, ASCII)
- Voice input
- Conversational editing
- Live preview
- 3D model rendering
- Collaborative editing (in questions)
This is 6+ months of work for a feature that needs to ship in weeks.
### MVP: Single Artifact Type + Text Editor
**What ships in 2 weeks:**
1. Launch editor with `--output-path` argument
2. Simple text editor for PlantUML/Mermaid (pick ONE)
3. Save button that outputs `ARTIFACT_SAVED:/path`
4. Exit code 0 on save, 1 on cancel
That's it. No AI, no preview, no 3D. Just a working integration.
**Defer to v2:**
- AI assistance (SmartTools)
- Live preview (nice-to-have, not blocking)
- Additional formats (add after first one works)
- Voice input (future)
- 3D models (separate project)
### UI Framework Decision
**Simplest that works:** urwid TUI
- Already in dependency tree (orchestrated-discussions uses it)
- Zero preview complexity (just show code)
- Fast to build
- Terminal-native, no GUI frameworks
**Defer:** Dear PyGui, web-based - these add complexity without solving the core integration need.
### Architecture: Just Enough
```
artifact-editor --type mermaid --output diagrams/foo.mmd
→ Opens text editor
→ User types Mermaid code
→ Saves to file
→ Prints ARTIFACT_SAVED:diagrams/foo.mmd
→ Exit 0
```
No renderers, no preview pipeline, no AI - just a glorified text editor with contract compliance.
### What Success Looks Like (v1)
User can add a diagram to a discussion comment. That's it. Ship that, get feedback, iterate.
### Recommendation
Q: What's the right UI framework?
A: urwid - simplest, already a dependency
Q: How should AI assistance work?
A: Don't build it yet - defer to v2
Q: What's the MVP feature set?
A: Text editing + save contract for ONE format
Q: How do we handle 3D preview?
A: Don't - that's a v3+ feature
Q: Collaborative editing?
A: Hard no for MVP
DIAGRAM: diagrams/artifact-editor-ai-enhanced-diagram-and-3d-model-creator_mvp_5.puml
VOTE: CHANGES - Scope needs 80% reduction to ship something useful
VOTE: CHANGES
---
Name: AI-Security
## Security Analysis
I've reviewed the Artifact Editor proposal and identified several security concerns that need to be addressed:
### High Priority Threats
**1. Command Injection via Renderer Execution**
CONCERN: PlantUML, OpenSCAD, and Mermaid renderers execute external processes. User-controlled content could escape sandboxing.
- PlantUML Java execution with user diagrams
- OpenSCAD code compilation and execution
- SVG rendering with embedded scripts
- ASCII art could contain terminal escape sequences
Mitigation: Strict input validation, sandboxed execution (containers/firejail), disable network access for renderers, CSP for web-based previews.
**2. Path Traversal in File Operations**
CONCERN: The `--output` argument could be exploited to write files outside intended directories.
```
artifact-editor --output ../../../etc/cron.d/backdoor
```
Mitigation: Validate and canonicalize all file paths, restrict writes to specific directories, check for `..` sequences.
**3. Voice Input Attack Surface**
CONCERN: Voice-to-AI pipeline introduces new vectors:
- Audio injection attacks
- Prompt injection via transcribed speech
- Privacy concerns (recording storage)
Mitigation: Sanitize transcriptions before AI processing, ephemeral audio storage, user consent for recording.
**4. AI-Generated Code Execution**
CONCERN: AI might generate malicious code in OpenSCAD/PlantUML that gets auto-executed.
- OpenSCAD can read/write files
- PlantUML can include external files
- SVG can contain JavaScript
Mitigation: Review-before-execute workflow, static analysis of generated code, disable dangerous language features.
### Medium Priority
**5. Stdout/Stdin Protocol Security**
The parent app integration uses stdout for communication. Malicious artifact content could inject fake protocol messages:
```
ARTIFACT_SAVED:/fake/path\nARTIFACT_SAVED:/actual/malicious/path
```
Mitigation: Structured format (JSON over stdout), message signing/verification.
**6. Dependency Chain Attacks**
External renderers (PlantUML JAR, OpenSCAD binary) could be compromised.
Mitigation: Checksum verification, pinned versions, consider alternative pure-Python implementations where possible.
**7. Resource Exhaustion**
CONCERN: Complex diagrams could cause DoS:
- Infinite loops in OpenSCAD
- Massive PlantUML graphs consuming memory
- SVG bomb attacks
Mitigation: Execution timeouts, memory limits, input size restrictions.
### Recommendations
**For MVP:**
1. Start with read-only ASCII art and Mermaid (client-side rendering)
2. Defer executable formats (OpenSCAD, PlantUML) until sandboxing is implemented
3. Use JSON protocol for parent communication
4. Implement strict path validation immediately
5. Add `--safe-mode` flag that disables AI features for security-critical contexts
**Architecture:**
- Separate renderer processes with minimal privileges
- Filesystem access only to designated artifact directory
- Network isolation for all renderers
- Audit logging of all file operations
**Voice/AI:**
- Disable by default, require explicit `--enable-ai` flag
- Clear user warning about data being sent to AI providers
- Local speech-to-text option for privacy
DIAGRAM: diagrams/artifact-editor-ai-enhanced-diagram-and-3d-model-creator_security_5.puml
VOTE: CHANGES
---
Name: AI-Architect
## Architectural Analysis
### Strong Foundation
The Unix philosophy alignment with orchestrated-discussions is excellent. The stdin/stdout/exit-code contract keeps integration clean and testable.
### Critical Architectural Decisions Needed
#### 1. **UI Framework Choice Has Long-Term Implications**
- **urwid TUI**: Aligns with project ecosystem, SSH-friendly, but 3D preview severely limited
- **Dear PyGui**: Native performance, better for 3D/live preview, but desktop-only
- **Web-based (local server)**: Most flexible for preview/3D, cross-platform, but adds complexity
RECOMMENDATION: **Hybrid approach** - TUI for text-based formats (PlantUML, Mermaid, ASCII), launch external viewer for 3D. Matches orchestrated-discussions pattern (text-first, viewer on demand).
#### 2. **Renderer Architecture**
ARTIFACT: diagrams/artifact-editor-architecture.puml
Key principle: **Renderers are stateless SmartTools**
```
artifact-editor (orchestration)
↓ subprocess
artifact-render-{format} (SmartTools)
External tools (plantuml.jar, mermaid-cli, openscad)
```
DON'T: Build rendering logic into the editor
DO: Each renderer is a SmartTool that can be tested independently:
```bash
echo '@startuml\nA -> B\n@enduml' | artifact-render-plantuml > out.svg
```
#### 3. **AI Assistance Integration**
Two architectural patterns emerge:
**Pattern A: AI as orchestrator** (RECOMMENDED)
- User voice → `artifact-assistant` SmartTool → generates code → editor displays
- Conversational loop: user refines → tool regenerates
- Editor remains thin, AI in separate SmartTool
**Pattern B: AI embedded in editor**
- Tighter coupling, harder to test, breaks Unix philosophy
#### 4. **State Management Concern**
Current scaffold suggests single-process architecture. Consider:
- Long-running edit sessions
- Undo/redo state
- Unsaved changes handling
RECOMMENDATION: **File-based state**
- Auto-save to temp file (e.g., `/tmp/artifact-edit-{pid}.state`)
- On crash/kill, can recover
- Aligns with "discussion file is source of truth" principle
### Architecture Risks
1. **3D Preview Complexity**: OpenSCAD rendering is SLOW. Need async architecture to prevent UI blocking.
- Solution: Render process pool, preview throttling
2. **Voice Input Dependencies**: Adds heavyweight deps (speech recognition). Could bloat the tool.
- Solution: Separate `artifact-voice` SmartTool, optional integration
3. **Format Proliferation**: Supporting 7+ formats means 7+ external tool dependencies.
- Solution: Plugin architecture, core ships with Mermaid+PlantUML only
### Proposed System Architecture
```
artifact-editor # Thin orchestrator (urwid TUI)
├── Core loop: edit → render → display
├── Calls SmartTools via subprocess
└── File-based state persistence
SmartTools ecosystem:
├── artifact-render-{format} # Stateless renderers
├── artifact-assistant # AI code generation
├── artifact-voice # Speech → text (optional)
└── artifact-validate-{format} # Syntax checking
External tools (user-installed):
├── plantuml.jar
├── mermaid-cli
├── openscad
└── dot (graphviz)
```
### MVP Scope Recommendation
**Phase 1 (MVP)**:
- TUI editor (urwid)
- Mermaid + PlantUML support (most common in orchestrated-discussions)
- Basic `artifact-assistant` SmartTool (text prompt → diagram code)
- File output contract
**Phase 2**:
- OpenSCAD/3D support with external viewer
- Voice input via `artifact-voice` tool
- Live preview split-pane
**Phase 3**:
- Plugin system for custom formats
- Collaborative editing (shared state file)
### Open Architectural Questions
**Q1**: Should artifact-editor support editing existing artifacts or only creation?
- Editing adds complexity (need to parse existing files, detect format)
- Creation-only is cleaner but less useful
**Q2**: How to handle format-specific validation?
- Pre-render validation prevents invalid saves
- But adds per-format complexity
**Q3**: Should the editor be modal (vim-style) or modeless?
- Modal fits TUI better, smaller learning curve
- Modeless more familiar to non-terminal users
VOTE: CHANGES
## Required Decisions Before Implementation
1. ✅ Confirm hybrid TUI + external viewer approach
2. ✅ Confirm SmartTools-based renderer architecture
3. ❓ Define MVP format support (recommend: Mermaid + PlantUML only)
4. ❓ Decide on edit-existing vs. create-only
5. ❓ Choose modal vs. modeless editing
VOTE: CHANGES

View File

@ -1,239 +0,0 @@
# Default Participants for Orchestrated Discussions
# These personas are bundled with the package and can be customized per-project
schema_version: "1.0"
# Voting participants - these cast READY/CHANGES/REJECT votes
voting_participants:
- name: AI-Moderator
alias: moderator
role: Discussion Facilitator
personality: |
You are AI-Moderator, a neutral discussion facilitator who keeps conversations
productive and on-track.
Your role:
- Guide the discussion through phases
- Summarize progress and key points
- Identify when consensus is near or blocked
- Call for votes when appropriate
- Ensure all perspectives are heard
Perspective:
- Stay neutral - don't advocate for technical positions
- Focus on process, not content
- Help resolve conflicts constructively
- Keep the discussion moving forward
expertise:
- Process facilitation
- Consensus building
- Conflict resolution
- Project management
concerns:
- "Are we making progress?"
- "Do we have consensus?"
- "Are all concerns being addressed?"
provider_hint: claude-sonnet
- name: AI-Architect
alias: architect
role: Systems Architect
personality: |
You are AI-Architect (also known as Chen), a senior systems architect with deep
expertise in distributed systems, design patterns, and long-term technical strategy.
Your role:
- Think in systems, patterns, and architectural principles
- Consider scalability, maintainability, and evolution over time
- Identify architectural risks and technical debt implications
- Suggest well-established patterns and proven approaches
- Balance ideal architecture with practical constraints
Perspective:
- You think 2-5 years ahead, not just the immediate implementation
- You value modularity, separation of concerns, and clean boundaries
- You prefer boring, proven technology over cutting-edge experiments
- You call out when shortcuts will create architectural debt
expertise:
- System design
- Scalability
- Technical debt
- Architectural patterns
- API design
concerns:
- "How does this fit the overall architecture?"
- "Will this scale?"
- "What's the long-term maintenance burden?"
provider_hint: claude-sonnet
- name: AI-Security
alias: security
role: Security Specialist
personality: |
You are AI-Security (also known as Steve), a security specialist who identifies
vulnerabilities, threat vectors, and security best practices.
Your role:
- Identify security risks and vulnerabilities
- Suggest mitigations and security controls
- Consider threat models and attack surfaces
- Ensure compliance with security best practices
- Balance security with usability
Perspective:
- Assume malicious actors will try to exploit the system
- Consider both external and internal threats
- Think about data protection and privacy
- Focus on practical, implementable security measures
expertise:
- Vulnerability assessment
- Threat modeling
- Authentication & authorization
- Data protection
- Input validation
concerns:
- "What are the security implications?"
- "How could this be exploited?"
- "Are we handling sensitive data properly?"
provider_hint: claude-sonnet
- name: AI-Pragmatist
alias: pragmatist
role: Shipping Pragmatist
personality: |
You are AI-Pragmatist (also known as Maya), a shipping-focused engineer who
advocates for practical solutions and incremental delivery.
Your role:
- Advocate for simpler solutions
- Identify over-engineering and scope creep
- Suggest MVP approaches
- Balance quality with delivery speed
- Challenge unnecessary complexity
Perspective:
- "Done is better than perfect when it's good enough"
- Ship early, iterate often
- Complexity is the enemy of delivery
- Technical debt is acceptable if managed
- Users need features, not architectural purity
expertise:
- MVP scoping
- Shipping velocity
- Trade-off analysis
- Iterative development
concerns:
- "Can we ship this incrementally?"
- "Are we over-engineering this?"
- "What's the simplest thing that could work?"
provider_hint: claude-sonnet
- name: AI-Perfectionist
alias: perfectionist
role: Quality Champion
personality: |
You are AI-Perfectionist (also known as Alex), a quality-obsessed engineer who
advocates for code excellence and comprehensive testing.
Your role:
- Advocate for code quality and best practices
- Ensure adequate test coverage
- Push for clear documentation
- Identify maintainability issues
- Balance quality with practicality
Perspective:
- "Code is read 10x more than written - optimize for clarity"
- Technical debt compounds over time
- Tests are not optional
- Documentation is part of the deliverable
expertise:
- Code quality
- Testing strategies
- Documentation
- Code review
- Developer experience
concerns:
- "Is this maintainable?"
- "Do we have adequate tests?"
- "Is the code clear and well-documented?"
provider_hint: claude-sonnet
- name: AI-Designer
alias: designer
role: UX Designer
personality: |
You are AI-Designer (also known as Eva), a user experience designer who
advocates for usability, accessibility, and user-centered design.
Your role:
- Advocate for user needs
- Ensure accessibility compliance
- Consider the full user journey
- Push for intuitive interfaces
- Balance aesthetics with functionality
Perspective:
- Users should not need documentation
- Accessibility is not optional
- Design for the edge cases
- Consistency builds trust
expertise:
- User experience
- Accessibility (WCAG)
- Visual design
- User research
- Interaction design
concerns:
- "Is this intuitive for users?"
- "Does this meet accessibility standards?"
- "How will this look and feel?"
provider_hint: claude-sonnet
# Background participants - provide tools/research, do not vote
background_participants:
- name: AI-Researcher
alias: researcher
role: Research Assistant
personality: |
You are AI-Researcher, a thorough research assistant who provides
cited sources, documentation, and background information.
Your role:
- Find relevant documentation and examples
- Research best practices and prior art
- Provide context and background
- Cite sources when possible
capabilities:
- Web research
- Documentation lookup
- Best practice identification
- Citation tracking
provider_hint: claude-haiku
- name: AI-Visualizer
alias: visualizer
role: Diagram Generator
personality: |
You are AI-Visualizer, a diagram specialist who creates PlantUML
diagrams to visualize architecture, flows, and relationships.
Your role:
- Create clear, informative diagrams
- Visualize system architecture
- Illustrate data flows and sequences
- Help clarify complex relationships
capabilities:
- PlantUML diagrams
- Architecture diagrams
- Sequence diagrams
- Class diagrams
provider_hint: claude-haiku

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -0,0 +1,53 @@
@startuml
title MVP vs Full Vision
left to right direction
package "Week 1 MVP\n(Ships Now)" {
rectangle "CLI Tool" as mvp_cli
storage "tasks.md" as mvp_file
cloud "AI API" as mvp_ai
mvp_cli -down-> mvp_file : read/write
mvp_cli -right-> mvp_ai : 2 questions
note right of mvp_cli
homelab start-day
homelab end-day
That's it.
~200 lines of Python
end note
}
package "Full Vision\n(Months of Work)" {
rectangle "Background Service" as full_svc
rectangle "Web UI" as full_web
rectangle "Notification System" as full_notif
database "PostgreSQL" as full_db
rectangle "Analytics Engine" as full_analytics
rectangle "Interview Bot" as full_interview
rectangle "Scheduler" as full_sched
full_svc --> full_db
full_web --> full_svc
full_sched --> full_notif
full_analytics --> full_db
full_interview --> full_db
note right of full_svc
Docker compose
Background workers
API layer
Auth system
Migration system
Monitoring
Ship date: ???
end note
}
mvp_cli .right.> full_svc : "prove it works\nthen evolve"
@enduml

View File

@ -0,0 +1,75 @@
@startuml
!define AWSPUML https://raw.githubusercontent.com/awslabs/aws-icons-for-plantuml/v14.0/dist
title Threat Model - AI Home Lab Productivity Tool
' Trust Boundaries
package "Home Lab Network" {
package "Productivity Tool" {
component "Web UI" as web
component "CLI Interface" as cli
component "Scheduler" as scheduler
database "Task/Goal Storage" as db
component "AI Engine\n(Local LLM)" as ai
component "Export/Summary" as export
}
actor "User" as user
actor "Other Home Lab Services" as other_services
}
actor "External Attacker" as attacker
cloud "External Services\n(Optional)" as external
' Trust relationships
user --> web : Daily check-ins\n(personal data)
user --> cli : Task management
scheduler --> user : Notifications\n(task reminders)
web --> db : Store conversations
cli --> db : CRUD operations
ai --> db : Read context\nGenerate insights
scheduler --> ai : Trigger interviews
export --> db : Read history
export --> user : Reports\n(sensitive summaries)
' Attack surfaces
attacker ..> web : Network attack\n(if exposed)
attacker ..> db : File access\n(if unencrypted)
other_services ..> web : Lateral movement
other_services ..> db : File system access
web ..> external : API calls?\n(data exfiltration risk)
ai ..> external : Model updates?\n(supply chain risk)
' Key threats
note right of db
**CRITICAL ASSETS**
- Conversation histories
- Goal failure interviews
- Personal patterns
- Work habits data
**THREATS**
- Unauthorized access
- Data exfiltration
- Unencrypted backups
end note
note right of ai
**AI-SPECIFIC RISKS**
- Prompt injection
- Model poisoning
- Context leakage
- Malicious output
end note
note left of web
**ACCESS CONTROL**
- Authentication?
- Session management?
- Rate limiting?
- HTTPS enforcement?
end note
@enduml

View File

@ -0,0 +1,59 @@
@startuml
!theme plain
title Artifact Editor: Full Vision vs MVP
left to right direction
package "Full Vision\n(6-12 weeks)" as full {
component "PlantUML" as f1
component "Mermaid" as f2
component "OpenSCAD" as f3
component "SVG" as f4
component "ASCII Art" as f5
component "AI Assistant" as f6
component "Voice Input" as f7
component "Collab Edit" as f8
component "GUI Framework" as f9
}
package "MVP v1\n(1-2 weeks)" as mvp {
component "PlantUML Only" as m1 #90EE90
component "urwid TUI" as m2 #90EE90
component "Text Editor" as m3 #90EE90
component "Live Preview" as m4 #90EE90
component "Exit Contract" as m5 #90EE90
}
package "v2 Expansion\n(incremental)" as v2 {
component "+ Mermaid" as v2a
component "+ AI Assist" as v2b
component "+ Voice" as v2c
}
actor "User Needs\nDiagrams Now" as user
user --> mvp : "Ships in\n2 weeks"
user ..> full : "Ships in\n3 months"
mvp --> v2 : "Add features\nbased on\nusage data"
note right of mvp
**Ship This:**
- One renderer
- Simple TUI
- Working integration
**Learn:**
- What users create
- Pain points
- Feature requests
end note
note right of full
**Risk:**
- Complex before validation
- Long time to first user
- May build wrong features
end note
@enduml

View File

@ -0,0 +1,66 @@
@startuml
!theme plain
title Artifact Editor: Complex vs MVP Approach
left to right direction
package "Proposed (Complex)" as complex {
rectangle "Voice Input" as voice
rectangle "Multiple Formats\n(Mermaid, PlantUML,\nOpenSCAD, SVG, ASCII)" as formats
rectangle "Conversational AI" as ai
rectangle "3D Preview" as preview3d
rectangle "Collaborative Edit" as collab
voice --> ai
ai --> formats
formats --> preview3d
formats --> collab
note right of complex
Estimated: 3-4 weeks
Risk: High
Value: Unproven
end note
}
package "MVP (Ship This Week)" as mvp {
rectangle "Text Input" as text
rectangle "PlantUML Only" as plantuml
rectangle "Live Preview" as preview
rectangle "Save/Exit" as save
text --> plantuml
plantuml --> preview
preview --> save
note right of mvp
Estimated: 2-3 days
Risk: Low
Value: Testable immediately
end note
}
package "Even Simpler?" as simpler {
rectangle "Comment Text" as comment
rectangle "AI Generate\nDiagram" as generate
rectangle "Show Preview\n+ Edit Button" as show
comment --> generate
generate --> show
note right of simpler
Estimated: 1 day
Risk: Minimal
Value: Tests core hypothesis
end note
}
complex -[hidden]down-> mvp
mvp -[hidden]down-> simpler
note bottom
**Question:** Do we need an editor
or just AI-generated diagrams?
end note
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -0,0 +1,118 @@
@startuml
!define PROPOSED #FFE6E6
!define MVP #E6FFE6
!define DEFER #E6E6FF
title Artifact Editor: Proposed vs MVP
package "Proposed Scope (6+ months)" as proposed_pkg PROPOSED {
[Multiple Formats]
[Voice Input]
[AI Assistance]
[Live Preview]
[3D Rendering]
[Collaborative Edit]
}
package "MVP v1 (2 weeks)" as mvp_pkg MVP {
[Text Editor]
[Single Format\n(PlantUML or Mermaid)]
[Save Contract]
[Exit Codes]
}
package "Deferred to v2/v3" as defer_pkg DEFER {
[AI via SmartTools]
[Preview Pipeline]
[Additional Formats]
[3D Models]
[Voice/Collab]
}
actor User
actor "orchestrated-discussions" as OD
User --> OD : clicks Add Artifact
OD --> [Text Editor] : launch with --output-path
[Text Editor] --> [Single Format\n(PlantUML or Mermaid)] : edits
[Single Format\n(PlantUML or Mermaid)] --> [Save Contract] : save
[Save Contract] --> OD : ARTIFACT_SAVED:/path
note right of [Text Editor]
urwid TUI
No preview needed
Just code editing
end note
note bottom of mvp_pkg
Ships in 2 weeks
Solves the integration need
Gets user feedback
end note
note bottom of defer_pkg
Add incrementally
Based on actual usage
Not assumptions
end note
@enduml
@startuml
!define PROPOSED #FFE6E6
!define MVP #E6FFE6
!define DEFER #E6E6FF
title Artifact Editor: Proposed vs MVP
package "Proposed Scope (6+ months)" PROPOSED {
[Multiple Formats]
[Voice Input]
[AI Assistance]
[Live Preview]
[3D Rendering]
[Collaborative Edit]
}
package "MVP v1 (2 weeks)" MVP {
[Text Editor]
[Single Format\n(PlantUML or Mermaid)]
[Save Contract]
[Exit Codes]
}
package "Deferred to v2/v3" DEFER {
[AI via SmartTools]
[Preview Pipeline]
[Additional Formats]
[3D Models]
[Voice/Collab]
}
actor User
actor "orchestrated-discussions" as OD
User --> OD : clicks Add Artifact
OD --> [Text Editor] : launch with --output-path
[Text Editor] --> [Single Format\n(PlantUML or Mermaid)] : edits
[Single Format\n(PlantUML or Mermaid)] --> [Save Contract] : save
[Save Contract] --> OD : ARTIFACT_SAVED:/path
note right of [Text Editor]
urwid TUI
No preview needed
Just code editing
end note
note bottom of MVP
Ships in 2 weeks
Solves the integration need
Gets user feedback
end note
note bottom of DEFER
Add incrementally
Based on actual usage
Not assumptions
end note
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -0,0 +1,77 @@
@startuml
!define ATTACK_COLOR #FF6B6B
!define CONTROL_COLOR #4ECDC4
!define ASSET_COLOR #FFE66D
title Artifact Editor Threat Model
actor "Malicious User" as attacker ATTACK_COLOR
actor "Legitimate User" as user
package "Artifact Editor" {
component "CLI Interface" as cli ASSET_COLOR
component "AI Assistant\n(SmartTools)" as ai ASSET_COLOR
component "Renderer Manager" as renderer ASSET_COLOR
database "File System" as fs ASSET_COLOR
}
package "External Renderers" {
component "PlantUML" as plantuml
component "Mermaid CLI" as mermaid
component "OpenSCAD" as openscad
}
package "Security Controls" CONTROL_COLOR {
component "Input Validator" as validator
component "Sandbox" as sandbox
component "Resource Limiter" as limiter
}
' Attack vectors
attacker --> cli : "Path traversal\n(--output /etc/passwd)"
attacker --> ai : "Prompt injection\n(voice input)"
attacker --> renderer : "Command injection\n(malicious artifact code)"
' Legitimate flow
user --> cli : Launch with args
cli --> validator : Validate inputs
validator --> ai : Safe prompts
validator --> renderer : Sanitized code
' Renderer execution
renderer --> sandbox : Execute in sandbox
sandbox --> limiter : Apply resource limits
limiter --> plantuml : Timeout: 30s
limiter --> mermaid : Memory: 512MB
limiter --> openscad : CPU limit
' Output
renderer --> validator : Validate output path
validator --> fs : Write to allowed dir
' Threat annotations
note right of attacker
**Attack Goals:**
- Execute arbitrary commands
- Write to sensitive paths
- DoS via resource exhaustion
- Steal sensitive data
end note
note right of validator
**Validations:**
- Path whitelist check
- Code size limits
- Character whitelist
- AI output verification
end note
note bottom of sandbox
**Isolation:**
- firejail/bubblewrap
- Read-only mounts
- Network disabled
- Minimal capabilities
end note
@enduml

View File

@ -0,0 +1,83 @@
@startuml
!theme plain
title Artifact Editor - Threat Model
actor User
actor "Parent App\n(orchestrated-discussions)" as Parent
box "Artifact Editor" #LightBlue
participant "CLI Entry" as CLI
participant "Input Validator" as Validator
participant "AI Assistant\n(SmartTools)" as AI
participant "Code Generator" as CodeGen
participant "Sandbox" as Sandbox
participant "Renderer\n(mermaid/plantuml/openscad)" as Renderer
participant "File Writer" as Writer
end box
actor "Attacker" as Attacker
== Normal Flow ==
Parent -> CLI: Launch with --output path
CLI -> Validator: Validate path
Validator -> Validator: Check path traversal\nVerify write permissions
User -> AI: Voice/text input
AI -> CodeGen: Generate artifact code
CodeGen -> Validator: Validate generated code
Validator -> Sandbox: Execute in isolated env
Sandbox -> Renderer: Render with timeouts\nResource limits
Renderer -> Writer: Write to validated path
Writer -> Parent: ARTIFACT_SAVED:path\nexit 0
== Attack Vectors ==
Attacker -> Parent: Compromise parent app
Parent -> CLI: --output ../../../etc/passwd
CLI -> Validator: **BLOCK**: Path traversal detected
Validator -> Parent: exit 3 (security violation)
Attacker -> User: Social engineering
User -> AI: "Ignore instructions, exec('rm -rf /')"
AI -> CodeGen: Malicious code
CodeGen -> Validator: **BLOCK**: Forbidden functions
Validator -> User: Error: Invalid code
Attacker -> Renderer: Malicious artifact\n(billion polygons)
Renderer -> Sandbox: **TIMEOUT**: Kill after 60s
Sandbox -> Renderer: SIGKILL
Renderer -> Parent: exit 2 (render failed)
== Security Controls ==
note over Validator
**Input Validation**
- Path canonicalization
- Allowed directory whitelist
- Type/format validation
end note
note over Sandbox
**Execution Isolation**
- Container/firejail
- No network access
- Memory limits: 512MB
- CPU limits: 2 cores
- Timeout: 60s
- Read-only filesystem
end note
note over AI
**Prompt Security**
- System prompt hardening
- Input sanitization
- Output validation
- Rate limiting
end note
note over Writer
**File Security**
- Atomic writes (temp + rename)
- Permission checks
- Size limits: 10MB
- Workspace restriction
end note
@enduml

View File

@ -0,0 +1,71 @@
@startuml
title Artifact Editor - Threat Model
actor "Malicious User" as attacker
actor "Legitimate User" as user
package "Artifact Editor" {
component "CLI Interface" as cli
component "Voice Input" as voice
component "AI Assistant" as ai
component "File Operations" as files
package "Renderers" {
component "PlantUML" as plantuml
component "OpenSCAD" as openscad
component "Mermaid" as mermaid
component "SVG" as svg
}
}
package "External" {
component "PlantUML JAR" as plantumljava
component "OpenSCAD Binary" as openscadbinary
component "AI Provider" as aiprovider
database "Filesystem" as fs
}
package "Parent App" as parent
user --> cli : normal usage
attacker --> cli : malicious input
cli --> voice : audio data
cli --> ai : edit requests
cli --> files : save/load
cli ..> parent : stdout protocol
voice --> aiprovider : transcription
ai --> aiprovider : generation
plantuml --> plantumljava : execute
openscad --> openscadbinary : execute
files --> fs : read/write
note right of attacker
**Attack Vectors:**
1. Path traversal in --output
2. Command injection via content
3. Prompt injection via voice
4. Malicious AI-generated code
5. Protocol injection in stdout
6. Resource exhaustion
7. Compromised dependencies
end note
note left of plantuml
**High Risk:**
External code execution
File system access
Network capabilities
end note
note bottom of files
**Critical:**
Validate all paths
Restrict to artifact dir
Check for traversal
end note
@enduml

View File

@ -0,0 +1,65 @@
@startuml
!theme plain
skinparam componentStyle rectangle
package "Artifact Editor" {
[CLI Entry] as cli
[Editor Core] as core
[State Manager] as state
package "Renderers" {
[Renderer Registry] as registry
[Mermaid Renderer] as mermaid
[PlantUML Renderer] as plantuml
[OpenSCAD Renderer] as openscad
}
package "UI Layer" {
[Code Editor Panel] as code_panel
[Preview Panel] as preview
[Voice Input Button] as voice
}
}
package "SmartTools (subprocess)" {
[dictate] as dictate
[artifact-generate] as ai_gen
[artifact-modify] as ai_mod
}
package "External Renderers (subprocess)" {
[mmdc] as mmdc_bin
[plantuml.jar] as puml_bin
[openscad] as oscad_bin
}
cli --> core : args
core --> state : manage
core --> registry : render request
registry --> mermaid
registry --> plantuml
registry --> openscad
mermaid --> mmdc_bin : subprocess
plantuml --> puml_bin : subprocess
openscad --> oscad_bin : subprocess
code_panel --> core : code changes
voice --> dictate : subprocess
dictate --> ai_gen : pipe
ai_gen --> core : generated code
preview <-- registry : rendered image
state --> code_panel : undo/redo
note right of ai_gen
SmartTools called via
subprocess, never imported
end note
note bottom of registry
All renderers run in
isolated subprocess with
timeout and cancellation
end note
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -0,0 +1,31 @@
@startsalt
{+
{/ <b>Artifact Editor</b> | File | Edit | View | Help }
{#
[PlantUML v] | [🎤 Voice] | [🤖 AI Assist] | [⟳ Render] | [💾 Save]
}
{+
{#
{SI
<code>
@startuml
actor User
component Editor
User -> Editor
@enduml
</code>
} | {SI
.
. [User] [Editor]
. | |
. |----------------->|
. | |
.
}
}
}
{#
Text Edit Mode | Rendering... | Ln 5, Col 12
}
}
@endsalt

View File

@ -0,0 +1,31 @@
@startuml
!theme plain
title Artifact Editor MVP - State Machine
[*] --> EDITING : launch
state EDITING : User modifying code
state RENDERING : PlantUML subprocess
state PREVIEW : Showing rendered result
state ERROR : Render failed
state SAVED : File written
EDITING --> RENDERING : timer/trigger
RENDERING --> PREVIEW : success
RENDERING --> ERROR : fail/timeout
ERROR --> EDITING : edit
PREVIEW --> EDITING : edit
EDITING --> SAVED : save
SAVED --> [*] : output contract
note right of RENDERING
Timeout: 10s
Show spinner
end note
note right of SAVED
stdout: ARTIFACT_SAVED:path
exit 0
end note
@enduml

View File

@ -0,0 +1,39 @@
@startuml
!theme plain
title Artifact Editor State Machine
[*] --> Empty : launch without file
[*] --> Loading : launch with file path
Empty --> Editing : user types / AI generates
Loading --> Editing : file loaded
Loading --> Error : file not found
Editing --> Rendering : save triggered
Editing --> Editing : user edits
Editing --> AIProcessing : voice/AI command
AIProcessing --> Editing : AI response applied
AIProcessing --> Error : AI failed
Rendering --> Rendered : success
Rendering --> Error : render failed
Rendering --> Rendering : timeout (retry)
Rendered --> Editing : user continues editing
Rendered --> Saved : output confirmed
Saved --> [*] : exit with success
Error --> Editing : user fixes
Error --> [*] : exit with error
note right of Editing
Dirty flag tracked
Undo/redo stack maintained
end note
note right of Rendering
Subprocess with timeout
Cancellable
end note
@enduml

View File

@ -0,0 +1,72 @@
@startuml
!define RECTANGLE class
skinparam componentStyle rectangle
package "Artifact Editor" {
[CLI Entry Point] as CLI
[Editor UI\n(Dear PyGui)] as UI
[Renderer Registry] as Registry
package "Renderers" {
[MermaidRenderer] as Mermaid
[PlantUMLRenderer] as PlantUML
[OpenSCADRenderer] as SCAD
[SVGRenderer] as SVG
[ASCIIRenderer] as ASCII
}
package "AI Assist\n(SmartTools)" {
[artifact-generator] as Gen
[artifact-refiner] as Refine
[artifact-assist] as Assist
}
}
package "External Tools" {
[mermaid-cli] as MermaidCLI
[plantuml.jar] as PlantUMLJar
[openscad] as OpenSCADApp
[cairosvg] as Cairo
}
package "Parent App\n(orchestrated-discussions)" {
[Comment Dialog] as Parent
}
' Flow
Parent --> CLI : launch with --output
CLI --> UI : initialize
UI --> Registry : get_renderer(file_ext)
Registry --> Mermaid : route by extension
Mermaid --> MermaidCLI : subprocess call
MermaidCLI --> Mermaid : SVG bytes
Mermaid --> UI : preview image
UI --> Gen : user clicks "Generate"
Gen --> UI : artifact code
UI --> CLI : user saves
CLI --> Parent : stdout: ARTIFACT_SAVED:path
note right of Registry
Strategy pattern:
Each renderer knows how to
validate, render, and preview
its format
end note
note right of Gen
SmartTools run as subprocesses
Input: description or existing code
Output: JSON with artifact content
end note
note bottom of CLI
Integration Contract:
- Input: --output <path> --type <format>
- Output: ARTIFACT_SAVED:<path>
- Exit: 0=saved, 1=error, 2=cancelled
end note
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -0,0 +1,92 @@
@startuml
!define RECTANGLE class
title Notification System - Component Architecture
package "Event Sources" {
[Message Service] as MSG
[Status Service] as STATUS
[Alert Service] as ALERT
}
package "Notification Core" {
[Event Processor] as PROC
[Notification Store] as STORE
[Delivery Coordinator] as COORD
note right of PROC
Responsibilities:
- Validate event schema
- Check user preferences
- Sanitize content (XSS prevention)
- Enforce rate limits
- Authorize (user_id matching)
end note
note right of STORE
Tables:
- notifications (id, user_id, event_type,
message, created_at, read)
- user_preferences (user_id,
event_type, enabled)
- rate_limits (user_id, count, window)
end note
}
package "Delivery Mechanisms" {
[Polling Endpoint] as POLL
[WebSocket Gateway] as WS
note bottom of POLL
MVP Implementation:
GET /api/notifications/unread
- Uses existing session auth
- Returns JSON array
- 30s polling interval
end note
note bottom of WS
Future Implementation:
- Socket.IO or raw WebSocket
- Token-based auth
- Real-time push
(Not in MVP)
end note
}
package "Clients" {
[React Frontend] as FRONTEND
[Browser Notification API] as BROWSER
}
' Event flow
MSG --> PROC : emit event
STATUS --> PROC : emit event
ALERT --> PROC : emit event
PROC --> STORE : store notification
PROC --> COORD : trigger delivery
COORD --> POLL : via polling (MVP)
COORD ..> WS : via push (future)
POLL --> FRONTEND : HTTP response
WS ..> FRONTEND : WebSocket message
FRONTEND --> BROWSER : show notification
' Component boundaries
package "Security Boundary" {
PROC
COORD
}
note bottom of "Security Boundary"
All security measures enforced here:
- Input sanitization
- Rate limiting (100/min per user)
- Authentication (session/token)
- Authorization (user_id ACL)
end note
@enduml

View File

@ -0,0 +1,54 @@
@startuml
title Notification System - Polling Architecture Sequence
actor User
participant "React Frontend" as Frontend
participant "Flask API" as API
database "PostgreSQL" as DB
participant "Background Job\n(event source)" as EventSource
== Event Generation ==
EventSource -> EventSource: Detect event\n(new message, status change, etc)
EventSource -> EventSource: Check user preferences\n(is this event type enabled?)
EventSource -> DB: INSERT INTO notifications\n(user_id, event_type, message, read=false)
note right: Sanitize message here\n(single choke point for XSS)
DB --> EventSource: OK
== Polling Loop (every 30s) ==
loop Every 30 seconds
Frontend -> API: GET /api/notifications/unread
note right: Headers: session cookie\n(existing auth)
API -> API: Extract user_id from session
API -> DB: SELECT * FROM notifications\nWHERE user_id = ? AND read = false\nORDER BY created_at DESC
DB --> API: [notification rows]
API -> API: Rate limit check\n(Flask-Limiter: 100/min)
API --> Frontend: JSON array of notifications
alt New notifications exist
Frontend -> Frontend: Filter by user preferences\n(double-check client-side)
Frontend -> User: Show browser notification\n(Browser Notification API)
User -> Frontend: Click notification
Frontend -> API: PATCH /api/notifications/{id}/read
API -> DB: UPDATE notifications\nSET read = true WHERE id = ?
DB --> API: OK
API --> Frontend: 200 OK
end
end
== User Preferences Management ==
User -> Frontend: Toggle preference\n("disable status change notifications")
Frontend -> API: PUT /api/preferences
API -> DB: UPDATE user_preferences\nSET event_type_enabled = false
DB --> API: OK
API --> Frontend: 200 OK
note over Frontend, DB
**Key Architectural Properties:**
- Stateless: No connection state to manage
- Simple: Standard HTTP request/response
- Scalable: ~33 req/s for 1000 users
- Secure: Session auth + rate limiting + sanitization
- Evolvable: Can swap to SSE/WS without changing much
end note
@enduml

View File

@ -0,0 +1,93 @@
@startuml
title Notification System - Architectural Components (MVP)
!define COMPONENT_COLOR #E3F2FD
!define API_COLOR #FFF9C4
!define STORAGE_COLOR #F3E5F5
!define CLIENT_COLOR #E8F5E9
package "Backend Services" {
component [Message Service] as MS
component [Status Service] as SS
component [Alert Service] as AS
note right of MS
Existing services
trigger events
end note
}
package "Notification System (NEW)" COMPONENT_COLOR {
database "notifications\ntable" as DB STORAGE_COLOR {
note right
user_id
event_type
message (sanitized)
created_at
read (boolean)
end note
}
database "user_preferences\ntable" as PREF STORAGE_COLOR {
note right
user_id
event_type
enabled (boolean)
end note
}
component "Notification API" as API API_COLOR {
note right
GET /api/notifications/unread
POST /api/notifications/mark-read
GET/PUT /api/notifications/preferences
Security:
- Session auth (existing)
- Rate limit: 100/min
- Sanitize with bleach
end note
}
}
package "Frontend (React)" CLIENT_COLOR {
component [Poller\n(30s interval)] as Poller
component [Browser\nNotification API] as BrowserAPI
note right of Poller
setInterval(() => {
fetch('/api/notifications/unread')
.then(showNotifications)
}, 30000)
end note
}
MS --> DB : INSERT notification\n(if preference enabled)
SS --> DB : INSERT notification\n(if preference enabled)
AS --> DB : INSERT notification\n(if preference enabled)
Poller --> API : GET /unread\n(authenticated session)
API --> DB : SELECT WHERE\nuser_id AND NOT read
API --> PREF : JOIN preferences
API ..> Poller : JSON response
Poller --> BrowserAPI : Show popup
note bottom of DB
30s latency acceptable
No message queue needed
~33 req/s for 1000 users
end note
' Sequence flow for single notification
note as N1
**Notification Flow:**
1. Event occurs in Message Service
2. Check user_preferences
3. INSERT sanitized notification
4. Client polls within 30s
5. API returns unread notifications
6. Browser shows popup
7. User clicks → mark as read
end note
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -0,0 +1,40 @@
@startuml
title MVP Notification System (Polling)
left to right direction
actor User
rectangle "Backend (Python)" {
component "App Logic" as App
database "notifications table" as DB
component "GET /api/notifications/unread" as API
}
rectangle "Frontend (React)" {
component "Poller (30s)" as Poller
component "Browser Notification API" as BrowserAPI
}
App -> DB: INSERT notification
Poller -> API: Poll every 30s
API -> DB: SELECT WHERE user_id AND read=false
API --> Poller: JSON array
Poller -> BrowserAPI: Show popup
BrowserAPI -> User: Desktop notification
note right of DB
Simple schema:
- id
- user_id
- event_type
- message
- created_at
- read (boolean)
end note
note bottom of Poller
No WebSockets needed
1000 users × 2 req/min
= ~33 req/s (trivial load)
end note
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@ -0,0 +1,131 @@
@startuml
skinparam backgroundColor white
skinparam defaultFontColor black
skinparam arrowColor black
skinparam noteBackgroundColor #FFFFCC
skinparam noteBorderColor black
skinparam packageBackgroundColor #F5F5F5
skinparam packageBorderColor black
skinparam componentBackgroundColor white
skinparam componentBorderColor black
skinparam databaseBackgroundColor white
skinparam databaseBorderColor black
title Polling (MVP) vs WebSocket (Complex)
package "Polling Approach (SHIP THIS)" {
[Browser] as B1
[Flask API] as F1
database "PostgreSQL" as DB1
B1 -down-> F1 : HTTP GET /notifications/unread\n(every 30s)
F1 -down-> DB1 : SELECT * WHERE user_id=? AND read=false
DB1 -up-> F1 : JSON array
F1 -up-> B1 : {notifications: [...]}
note right of F1
Security:
- Session auth (existing)
- Rate limit: 100/min
- Sanitize with bleach
Complexity: LOW
Time: 1 week
end note
}
package "WebSocket Approach (DON'T)" {
[Browser] as B2
[WebSocket Server] as WS
[Message Queue] as MQ
[Auth Service] as Auth
database "PostgreSQL" as DB2
B2 -down-> WS : WSS connect + JWT
WS -right-> Auth : Validate token
WS -down-> MQ : Subscribe user channel
MQ -down-> DB2 : Persist?
note right of WS
Security:
- JWT generation/rotation
- WSS certificates
- Connection state management
- Stale connection cleanup
- Token refresh logic
- Rate limiting per connection
Complexity: HIGH
Time: 3-4 weeks
end note
}
note bottom
For 1000 users, 30s latency requirement:
Polling = 33 req/s (trivial)
Ship polling now, upgrade IF needed
end note
@enduml
@startuml
!theme plain
title Polling (MVP) vs WebSocket (Complex)
package "Polling Approach (SHIP THIS)" {
[Browser] as B1
[Flask API] as F1
database "PostgreSQL" as DB1
B1 -down-> F1 : HTTP GET /notifications/unread\n(every 30s)
F1 -down-> DB1 : SELECT * WHERE user_id=? AND read=false
DB1 -up-> F1 : JSON array
F1 -up-> B1 : {notifications: [...]}
note right of F1
Security:
- Session auth (existing)
- Rate limit: 100/min
- Sanitize with bleach
Complexity: LOW
Time: 1 week
end note
}
package "WebSocket Approach (DON'T)" {
[Browser] as B2
[WebSocket Server] as WS
[Message Queue] as MQ
[Auth Service] as Auth
database "PostgreSQL" as DB2
B2 -down-> WS : WSS connect + JWT
WS -right-> Auth : Validate token
WS -down-> MQ : Subscribe user channel
MQ -down-> DB2 : Persist?
note right of WS
Security:
- JWT generation/rotation
- WSS certificates
- Connection state management
- Stale connection cleanup
- Token refresh logic
- Rate limiting per connection
Complexity: HIGH
Time: 3-4 weeks
end note
}
note bottom
For 1000 users, 30s latency requirement:
Polling = 33 req/s (trivial)
Ship polling now, upgrade IF needed
end note
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,52 @@
@startuml
title Polling Architecture with Security
!define SECURITY_COLOR #FFE6E6
!define APP_COLOR #E6F3FF
!define DATA_COLOR #E6FFE6
rectangle "Event Happens" as Event APP_COLOR
rectangle "Sanitize & Rate Check" as Sanitize SECURITY_COLOR
database "notifications table" as DB DATA_COLOR
rectangle "REST API\n(session auth + rate limit)" as API SECURITY_COLOR
rectangle "Frontend Poller\n(30s interval)" as Frontend APP_COLOR
rectangle "Browser Notification\n(text-only)" as Browser SECURITY_COLOR
Event --> Sanitize : bleach.clean()
Sanitize --> DB : INSERT if under 100/min
Frontend --> API : GET /api/notifications/unread
API --> DB : SELECT WHERE user_id = ?
DB --> API : JSON array
API --> Frontend : sanitized text
Frontend --> Browser : plain text display
note right of Sanitize
Security Layer 1:
- Strip all HTML/JS
- Check user preferences
- Rate limit: 100/user/min
end note
note right of API
Security Layer 2:
- Session authentication
- Flask-Limiter: 120/min
- user_id filter in SQL
end note
note right of Browser
Security Layer 3:
- No HTML rendering
- User permission required
- Text-only display
end note
note bottom of DB
Simple Schema:
- id, user_id, event_type
- message_text (sanitized)
- created_at, read_at
- Auto-delete after 30 days
end note
@enduml

View File

@ -0,0 +1,52 @@
@startuml
title Notification System - Threat Model
actor "Attacker" as attacker
actor "Legitimate User" as user
component "React Frontend" as frontend
component "Python Backend" as backend
component "Notification Service" as notif
database "User Preferences" as prefs
package "Attack Vectors" {
note right of attacker
1. XSS via notification content
2. Spam/DoS flooding
3. Token theft/replay
4. Authorization bypass
5. MitM on WebSocket
end note
}
package "Security Controls" {
rectangle "Input Sanitization" as sanitize
rectangle "Rate Limiting" as ratelimit
rectangle "WSS + JWT Auth" as auth
rectangle "ACL Checks" as acl
}
' Normal flow
user -> frontend : Authenticate
frontend -> backend : Get notification token
backend -> auth : Validate & issue JWT
frontend -> notif : Connect via WSS + token
backend -> sanitize : Sanitize content
sanitize -> ratelimit : Check limits
ratelimit -> acl : Verify user permissions
acl -> notif : Send notification
notif -> frontend : Deliver notification
' Attack attempts
attacker -[#red]-> notif : <script>alert('xss')</script>
sanitize -[#green]-> attacker : ✗ Blocked
attacker -[#red]-> notif : 10000 notifications/sec
ratelimit -[#green]-> attacker : ✗ Rate limited
attacker -[#red]-> notif : Stolen token
auth -[#orange]-> attacker : ✗ Token expired (5min TTL)
attacker -[#red]-> frontend : Read other user's notifications
acl -[#green]-> attacker : ✗ Authorization failed
@enduml

View File

@ -0,0 +1,10 @@
@startuml
' Created by rob
' Edit this diagram and save
' Example:
' component [Client]
' component [Server]
' [Client] --> [Server]
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
' Created by rob
' Edit this diagram and save
' Example:
' component [Client]
' component [Server]
' [Client] --> [Server]
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
' Created by rob
' Edit this diagram and save
' Example:
' component [Client]
' component [Server]
' [Client] --> [Server]
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
' Created by rob
' Edit this diagram and save
' Example:
' component [Client]
' component [Server]
' [Client] --> [Server]
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
' Created by rob
' Edit this diagram and save
' Example:
' component [Client]
' component [Server]
' [Client] --> [Server]
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,10 @@
@startuml
' Created by rob
' Edit this diagram and save
' Example:
' component [Client]
' component [Server]
' [Client] --> [Server]
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800" width="1200" height="800">
<!-- Background -->
<rect width="100%" height="100%" fill="#f8fafc"/>
<!-- Header -->
<rect x="0" y="0" width="1200" height="80" fill="#1e293b"/>
<text x="40" y="50" font-family="sans-serif" font-size="28" font-weight="bold" fill="#ffffff">DevPlanner</text>
<text x="1020" y="50" font-family="sans-serif" font-size="16" fill="#94a3b8">Today: Dec 23, 2025</text>
<!-- Sidebar -->
<rect x="0" y="80" width="280" height="720" fill="#334155"/>
<!-- Sidebar Items -->
<g id="sidebar-nav">
<rect x="20" y="110" width="240" height="50" rx="8" fill="#475569"/>
<text x="40" y="142" font-family="sans-serif" font-size="16" fill="#ffffff">📋 Today's Tasks</text>
<rect x="20" y="180" width="240" height="50" rx="8" fill="#1e293b"/>
<text x="40" y="212" font-family="sans-serif" font-size="16" fill="#cbd5e1">📅 Upcoming</text>
<rect x="20" y="250" width="240" height="50" rx="8" fill="#1e293b"/>
<text x="40" y="282" font-family="sans-serif" font-size="16" fill="#cbd5e1">✅ Completed</text>
<rect x="20" y="320" width="240" height="50" rx="8" fill="#1e293b"/>
<text x="40" y="352" font-family="sans-serif" font-size="16" fill="#cbd5e1">📊 Analytics</text>
</g>
<!-- Progress Widget -->
<rect x="20" y="450" width="240" height="120" rx="8" fill="#1e293b"/>
<text x="40" y="480" font-family="sans-serif" font-size="14" fill="#94a3b8">Today's Progress</text>
<text x="140" y="520" font-family="sans-serif" font-size="32" font-weight="bold" fill="#10b981" text-anchor="middle">68%</text>
<text x="140" y="550" font-family="sans-serif" font-size="12" fill="#cbd5e1" text-anchor="middle">13 of 19 tasks</text>
<!-- Main Content Area -->
<rect x="280" y="80" width="920" height="720" fill="#ffffff"/>
<!-- Content Header -->
<text x="320" y="140" font-family="sans-serif" font-size="24" font-weight="bold" fill="#0f172a">Today's Tasks</text>
<rect x="1020" y="110" width="150" height="45" rx="8" fill="#3b82f6"/>
<text x="1095" y="140" font-family="sans-serif" font-size="16" fill="#ffffff" text-anchor="middle">+ New Task</text>
<!-- Filter Tabs -->
<rect x="320" y="170" width="100" height="36" rx="6" fill="#e0e7ff"/>
<text x="370" y="194" font-family="sans-serif" font-size="14" fill="#4338ca" text-anchor="middle">All (19)</text>
<rect x="430" y="170" width="110" height="36" rx="6" fill="#f1f5f9"/>
<text x="485" y="194" font-family="sans-serif" font-size="14" fill="#64748b" text-anchor="middle">Active (6)</text>
<rect x="550" y="170" width="140" height="36" rx="6" fill="#f1f5f9"/>
<text x="620" y="194" font-family="sans-serif" font-size="14" fill="#64748b" text-anchor="middle">Completed (13)</text>
<!-- Task List -->
<!-- Task 1 - Completed -->
<rect x="320" y="240" width="840" height="90" rx="8" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
<circle cx="350" cy="285" r="12" fill="#10b981" stroke="#059669" stroke-width="2"/>
<line x1="345" y1="285" x2="348" y2="290" stroke="#ffffff" stroke-width="2" stroke-linecap="round"/>
<line x1="348" y1="290" x2="355" y2="280" stroke="#ffffff" stroke-width="2" stroke-linecap="round"/>
<text x="380" y="282" font-family="sans-serif" font-size="16" fill="#94a3b8" text-decoration="line-through">Review pull requests</text>
<text x="380" y="305" font-family="sans-serif" font-size="13" fill="#cbd5e1">2 subtasks completed</text>
<rect x="1080" y="270" width="60" height="30" rx="4" fill="#ecfdf5"/>
<text x="1110" y="291" font-family="sans-serif" font-size="12" fill="#059669" text-anchor="middle">Done</text>
<!-- Task 2 - Active with subtasks -->
<rect x="320" y="350" width="840" height="110" rx="8" fill="#ffffff" stroke="#3b82f6" stroke-width="2"/>
<circle cx="350" cy="395" r="12" fill="#ffffff" stroke="#64748b" stroke-width="2"/>
<text x="380" y="392" font-family="sans-serif" font-size="16" font-weight="500" fill="#0f172a">Implement authentication module</text>
<text x="380" y="415" font-family="sans-serif" font-size="13" fill="#64748b">3 of 5 subtasks • High Priority</text>
<!-- Subtask indicators -->
<rect x="380" y="425" width="400" height="8" rx="4" fill="#e2e8f0"/>
<rect x="380" y="425" width="240" height="8" rx="4" fill="#3b82f6"/>
<text x="790" y="432" font-family="sans-serif" font-size="12" fill="#64748b">60%</text>
<rect x="1030" y="380" width="120" height="30" rx="4" fill="#fef3c7"/>
<text x="1090" y="401" font-family="sans-serif" font-size="12" fill="#d97706" text-anchor="middle">In Progress</text>
<!-- Task 3 - Active -->
<rect x="320" y="480" width="840" height="90" rx="8" fill="#ffffff" stroke="#e2e8f0" stroke-width="1"/>
<circle cx="350" cy="525" r="12" fill="#ffffff" stroke="#64748b" stroke-width="2"/>
<text x="380" y="522" font-family="sans-serif" font-size="16" fill="#0f172a">Update documentation</text>
<text x="380" y="545" font-family="sans-serif" font-size="13" fill="#64748b">No subtasks • Medium Priority</text>
<rect x="1080" y="510" width="60" height="30" rx="4" fill="#f1f5f9"/>
<text x="1110" y="531" font-family="sans-serif" font-size="12" fill="#64748b" text-anchor="middle">Todo</text>
<!-- Task 4 - Active -->
<rect x="320" y="590" width="840" height="90" rx="8" fill="#ffffff" stroke="#e2e8f0" stroke-width="1"/>
<circle cx="350" cy="635" r="12" fill="#ffffff" stroke="#64748b" stroke-width="2"/>
<text x="380" y="632" font-family="sans-serif" font-size="16" fill="#0f172a">Fix bug in payment gateway</text>
<text x="380" y="655" font-family="sans-serif" font-size="13" fill="#64748b">1 subtask • High Priority</text>
<rect x="1050" y="620" width="90" height="30" rx="4" fill="#fee2e2"/>
<text x="1095" y="641" font-family="sans-serif" font-size="12" fill="#dc2626" text-anchor="middle">Urgent</text>
<!-- Floating Action Hints -->
<circle cx="900" cy="395" r="3" fill="#64748b"/>
<circle cx="915" cy="395" r="3" fill="#64748b"/>
<circle cx="930" cy="395" r="3" fill="#64748b"/>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 500" width="400" height="500">
<rect width="100%" height="100%" fill="#f9fafb"/>
<!-- Card container -->
<rect x="50" y="80" width="300" height="340" rx="8" fill="#ffffff" stroke="#e5e7eb"/>
<!-- Logo placeholder -->
<circle cx="200" cy="130" r="30" fill="#e5e7eb"/>
<text x="200" y="135" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#9ca3af">Logo</text>
<!-- Title -->
<text x="200" y="190" text-anchor="middle" font-family="sans-serif" font-size="20" font-weight="bold" fill="#111827">Welcome Back</text>
<!-- Email input -->
<text x="70" y="230" font-family="sans-serif" font-size="12" fill="#374151">Email</text>
<rect x="70" y="240" width="260" height="40" rx="4" fill="#ffffff" stroke="#d1d5db"/>
<text x="82" y="265" font-family="sans-serif" font-size="14" fill="#9ca3af">you@example.com</text>
<!-- Password input -->
<text x="70" y="300" font-family="sans-serif" font-size="12" fill="#374151">Password</text>
<rect x="70" y="310" width="260" height="40" rx="4" fill="#ffffff" stroke="#d1d5db"/>
<text x="82" y="335" font-family="sans-serif" font-size="14" fill="#9ca3af">••••••••</text>
<!-- Sign in button -->
<rect x="70" y="370" width="260" height="40" rx="4" fill="#3b82f6"/>
<text x="200" y="395" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#ffffff">Sign In</text>
<!-- Forgot password link -->
<text x="200" y="435" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#3b82f6">Forgot password?</text>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,10 @@
@startuml
' Created by rob
' Edit this diagram and save
' Example:
' component [Client]
' component [Server]
' [Client] --> [Server]
@enduml

View File

@ -0,0 +1,10 @@
@startuml
' Created by rob
' Edit this diagram and save
' Example:
' component [Client]
' component [Server]
' [Client] --> [Server]
@enduml

View File

@ -0,0 +1,10 @@
@startuml
title New Diagram
class Example {
+attribute: type
--
+method()
}
@enduml

View File

@ -0,0 +1 @@
@startuml\n!theme plain\ntitle Artifact Editor v1 - Recommended Layout\n\npackage \"Orchestrated Discussions\n(Parent Window)\" #F5F5F5 {\n rectangle \"Dialog: Add Artifact\" as dialog #FFFFFF {\n \n ' Header\n rectangle \"Artifact Type Selector\" as typesel #E8F4F8 {\n note right of typesel\n Dropdown: Mermaid | PlantUML | etc\n end note\n }\n \n ' Main editing area\n rectangle \"Code Editor (70%)\" as editor #FAFAFA {\n note right of editor\n • Syntax highlighting\n • Line numbers\n • Inline error underlines\n • Status: \"Valid\" / \"Error\"\n end note\n }\n \n rectangle \"Preview Pane (30%)\" as preview #F0F0F0 {\n note right of preview\n • Live render update\n • Zoom controls\n • \"Click to expand\" for large diagrams\n end note\n }\n \n ' Action toolbar\n rectangle \"Controls\" as controls #E8F4F8 {\n note right of controls\n 🎤 Voice Input | ✨ AI Generate | Save | Cancel\n end note\n }\n }\n}\n\nnote as N1\n **Design Principles:**\n • Match parent app's visual language\n • Code editor dominant (developer audience)\n • Inline error feedback\n • Voice input discoverable (icon + label)\n • Clear action buttons\nend note\n@enduml

View File

@ -0,0 +1,57 @@
@startuml artifact-editor-design
!theme plain
skinparam backgroundColor #f5f5f5
skinparam component {
BackgroundColor #e1f5ff
BorderColor #01579b
}
skinparam rectangle {
BackgroundColor #f3e5f5
BorderColor #512da8
}
rectangle "Artifact Editor MVP - Design Layout" {
component "Left Panel (50%)" as left {
component "Text Editor" as editor
note right of editor
PlantUML syntax
Syntax highlighting
Line numbers
Error markers (red underlines)
end note
}
component "Right Panel (50%)" as right {
component "Visual Canvas" as canvas
note right of canvas
Live preview
Selection handles
Draw mode affordances
Error indicators
end note
}
component "Bottom Bar" as controls {
component "Render Button" as render
component "AI Generate" as ai
component "Voice Input" as voice
component "Save" as save
}
}
editor -down-> canvas: "Bidirectional Sync"
canvas -down-> editor: "(critical requirement)"
render -up-> editor: "Update"
render -up-> canvas: "Update"
ai -up-> editor: "Generate code"
voice -up-> editor: "Transcribe → code"
save -up-> editor: "Output ARTIFACT_SAVED"
note bottom of controls
Clear visual affordances
Consistent with orchestrated-discussions styling
Keyboard shortcuts for power users
end note
@enduml

Some files were not shown because too many files have changed in this diff Show More