diff --git a/ai-context/workbench-ui/.github/workflows/pull-request.yaml b/ai-context/workbench-ui/.github/workflows/pull-request.yaml
new file mode 100644
index 00000000..b281c874
--- /dev/null
+++ b/ai-context/workbench-ui/.github/workflows/pull-request.yaml
@@ -0,0 +1,28 @@
+
+name: Test pull request
+
+on:
+ pull_request:
+
+permissions:
+ contents: read
+
+jobs:
+
+ container-push:
+
+ name: Build
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Install Typescript support
+ run: npm install
+
+ - name: Run tests
+ run: npm test -- --run
+
+ - name: Build
+ run: make service-package VERSION=0.0.0
diff --git a/ai-context/workbench-ui/.github/workflows/release.yaml b/ai-context/workbench-ui/.github/workflows/release.yaml
new file mode 100644
index 00000000..d9cf463b
--- /dev/null
+++ b/ai-context/workbench-ui/.github/workflows/release.yaml
@@ -0,0 +1,70 @@
+
+name: Build
+
+on:
+ workflow_dispatch:
+ push:
+ tags:
+ - v*
+
+permissions:
+ contents: read
+
+jobs:
+
+ deploy:
+
+ name: Build everything
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ id-token: write
+ environment:
+ name: release
+
+ steps:
+
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Log in to Docker Hub
+ uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
+ with:
+ username: ${{ vars.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_SECRET }}
+
+ - name: Get version
+ id: version
+ run: echo VERSION=$(git describe --exact-match --tags | sed 's/^v//') >> $GITHUB_OUTPUT
+
+ - name: Install Typescript support
+ run: npm install
+
+ - name: Run tests
+ run: npm test -- --run
+
+ - name: Extract metadata for container
+ id: meta
+ uses: docker/metadata-action@v4
+ with:
+ images: trustgraph/workbench-ui
+ tags: |
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=sha
+
+ - name: Build
+ run: make service-package VERSION=${{ steps.version.outputs.VERSION }}
+
+ - name: Build and push Docker image
+ id: push
+ uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
+ with:
+ context: .
+ file: ./Containerfile
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+
diff --git a/ai-context/workbench-ui/.gitignore b/ai-context/workbench-ui/.gitignore
new file mode 100644
index 00000000..32183714
--- /dev/null
+++ b/ai-context/workbench-ui/.gitignore
@@ -0,0 +1,29 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+*~
+workbench-ui/workbench/__pycache__/
+workbench-ui/workbench/ui/
+workbench-ui/workbench/version.py
+*.egg-info/
\ No newline at end of file
diff --git a/ai-context/workbench-ui/.prettierignore b/ai-context/workbench-ui/.prettierignore
new file mode 100644
index 00000000..eac61925
--- /dev/null
+++ b/ai-context/workbench-ui/.prettierignore
@@ -0,0 +1,7 @@
+*.json
+*.yaml
+*.md
+pulumi
+**/node_modules
+env
+dist
diff --git a/ai-context/workbench-ui/.prettierrc b/ai-context/workbench-ui/.prettierrc
new file mode 100644
index 00000000..8b6b8803
--- /dev/null
+++ b/ai-context/workbench-ui/.prettierrc
@@ -0,0 +1,3 @@
+{
+ "printWidth": 79
+}
diff --git a/ai-context/workbench-ui/CODEBOT-INSTRUCTIONS.md b/ai-context/workbench-ui/CODEBOT-INSTRUCTIONS.md
new file mode 100644
index 00000000..24ce203a
--- /dev/null
+++ b/ai-context/workbench-ui/CODEBOT-INSTRUCTIONS.md
@@ -0,0 +1,836 @@
+# UI Toolkits and Framework Notes
+
+## Change Management and API Stability
+
+**CRITICAL**: Components in `src/components/common/` are foundational to the entire application. DO NOT modify these components without explicit approval from the application design authority. Changes to common components have extensive downstream impact and can break multiple features across the application.
+
+### Change Impact Assessment
+Before modifying any common component:
+1. **Document all consumers** - Search the entire codebase for usage
+2. **Assess breaking changes** - Any interface changes affect all consumers
+3. **Test extensively** - Changes can break seemingly unrelated features
+4. **Get approval** - Design authority must approve all common component changes
+
+### Lessons from SelectField Issues
+Recent issues with SelectField demonstrate why common component changes are dangerous:
+- **September 2025**: Changes to SelectField to support one feature (Ontology editor) broke document submission
+- **Root cause**: Interface contract violations between array/string APIs
+- **Impact**: Multiple components across different domains affected
+- **Resolution required**: Systematic updates to 15+ components across the application
+
+**Key takeaway**: Changing common components to fix one feature often breaks others. Always prefer adapter patterns or feature-specific solutions over modifying shared infrastructure.
+
+## Directory Structure and Organization Rationale
+
+### Core Principles
+
+We follow a **domain-driven, flat structure** that avoids unnecessary nesting and keeps related code together:
+
+1. **Avoid generic aggregation directories** - No `src/hooks/`, `src/constants/`, `src/utils/` that become dumping grounds
+2. **Colocate by domain** - Keep related code together in feature-specific directories
+3. **Flat when possible** - Single files don't need their own subdirectories
+4. **Clear separation of concerns** - Different types of logic go in appropriate places
+
+### Directory Layout
+
+```
+src/
+├── components/ # UI components organized by domain
+│ ├── schemas/ # All schema-related UI components
+│ │ ├── EditSchemaDialog.tsx # Main orchestrator component
+│ │ ├── SchemaFieldEditor.tsx # Individual field editing
+│ │ ├── SchemaFieldsList.tsx # Fields list management
+│ │ ├── SchemaTableStates.tsx # Reusable table states
+│ │ ├── useSchemaForm.ts # Form state logic (colocated)
+│ │ └── ...
+│ ├── taxonomies/ # All taxonomy-related UI components
+│ └── common/ # Truly shared/generic components
+├── model/ # Data models, types, and domain constants
+│ ├── schemas-table.tsx # Schema data models
+│ ├── schemaTypes.ts # Schema type constants
+│ └── ...
+├── state/ # Application state management
+│ ├── schemas.ts # Schema API calls and state
+│ └── ...
+├── api/ # Direct API communication
+└── utils/ # Pure utility functions (no React/UI)
+```
+
+### Rationale by Directory
+
+**`src/components/[domain]/`**
+- Contains ALL UI components for a specific domain (schemas, taxonomies, etc.)
+- Includes domain-specific hooks like `useSchemaForm.ts`
+- **Why**: Keeps everything needed to work on a feature in one place
+- **Avoid**: Generic `src/hooks/` that becomes a dumping ground
+
+**`src/model/`**
+- Data types, interfaces, constants, and domain models
+- **Why**: Centralized data definitions that can be imported anywhere
+- **Example**: `schemaTypes.ts` contains `SCHEMA_TYPE_OPTIONS` and `DEFAULT_FIELD`
+
+**`src/state/`**
+- High-level application state management
+- React Query hooks for API calls and caching
+- **Why**: Separates data fetching/caching from UI logic
+
+**`src/api/`**
+- Direct API communication layer
+- WebSocket management
+- **Why**: Abstracts network concerns from business logic
+
+### Benefits of This Approach
+
+1. **Discoverability**: All schema-related code is in `src/components/schemas/`
+2. **Maintainability**: Changes to schema features are localized
+3. **Reusability**: Shared types in `src/model/` can be imported anywhere
+4. **Scalability**: New domains get their own component directories
+5. **Avoids Anti-patterns**: No generic directories that accumulate unrelated files
+
+### Example: Schema Feature Organization
+
+When working on schema-related features, everything you need is in one place:
+- UI components: `src/components/schemas/`
+- Data models: `src/model/schemas-table.tsx`, `src/model/schemaTypes.ts`
+- API/state: `src/state/schemas.ts`
+
+This eliminates the need to hunt through multiple generic directories to understand or modify a feature.
+
+## Icon Library
+
+**CRITICAL**: Always use `lucide-react` for icons throughout the application. Do NOT use `react-icons` or any other icon library.
+
+```tsx
+// ✅ Correct - Use lucide-react
+import { Plus, Save, Trash2, Edit, Settings } from "lucide-react";
+
+// ❌ Wrong - Don't use react-icons
+import { FiPlus, FiSave } from "react-icons/fi";
+```
+
+**Common icon mappings from react-icons to lucide-react:**
+- `FiPlus` → `Plus`
+- `FiX` → `X`
+- `FiSave` → `Save`
+- `FiTrash2` → `Trash2`
+- `FiEdit/FiEdit3` → `Edit`
+- `FiSettings` → `Settings`
+- `FiDownload` → `Download`
+- `FiUpload` → `Upload`
+- `FiMove` → `Move`
+- `FiMoreVertical` → `MoreVertical`
+- `FiList` → `List`
+
+## Chakra UI Version
+
+**CRITICAL**: This project uses **Chakra UI v3**, NOT v2. Always check component APIs against v3 documentation.
+
+## Key Chakra v3 Migration Points
+
+### Modal → Dialog
+```tsx
+// ❌ Chakra v2
+
+
+
+ Title
+ Content
+
+
+
+// ✅ Chakra v3
+ onOpenChange(x.open)}>
+
+
+
+
+
+ Title
+
+ Content
+
+
+
+
+```
+
+### Toast System
+```tsx
+// ❌ Chakra v2
+const toast = useToast();
+toast({ title: "Success", status: "success" });
+
+// ✅ Chakra v3
+import { toaster } from "../ui/toaster";
+toaster.create({ title: "Success", status: "success" });
+```
+
+### Form Components
+```tsx
+// ❌ Chakra v2
+
+ Label
+
+
+
+// ✅ Chakra v3
+
+ Label
+
+
+```
+
+### Tabs Structure
+```tsx
+// ❌ Chakra v2
+
+
+ Tab 1
+
+
+ Content
+
+
+
+// ✅ Chakra v3
+
+
+ Tab 1
+
+ Content
+
+```
+
+### Menu Components
+```tsx
+// ❌ Chakra v2
+
+
+// ✅ Chakra v3
+
+ Button
+
+ Item
+
+
+```
+
+### Props Changes
+```tsx
+// ❌ Chakra v2 props
+colorScheme="blue"
+isDisabled={true}
+
+// ✅ Chakra v3 props
+colorPalette="blue"
+disabled={true}
+```
+
+### Layout Components
+```tsx
+// ❌ Chakra v2
+
+
+// ✅ Chakra v3
+
+```
+
+### Spacing Props
+```tsx
+// ❌ Old pattern
+
+
+
+// ✅ Chakra v3
+
+
+```
+
+### Button Icons
+```tsx
+// ❌ Old pattern
+}>Add
+} aria-label="Upload" />
+
+// ✅ Chakra v3
+
+
+```
+
+### Input Groups (Simplified)
+```tsx
+// ❌ Chakra v2
+
+ 🔍
+
+
+
+// ✅ Chakra v3 (simplified approach)
+
+```
+
+### Avatar Structure
+```tsx
+// ❌ Chakra v2
+
+
+// ✅ Chakra v3
+
+
+
+```
+
+### Alert Component
+```tsx
+// ❌ Chakra v2
+
+
+ Error message
+
+
+// ✅ Chakra v3
+
+
+
+ Error message
+
+
+```
+
+**Alert Status Options:**
+- `status="error"` - Red error alerts
+- `status="warning"` - Orange warning alerts
+- `status="success"` - Green success alerts
+- `status="info"` - Blue info alerts
+
+**Alert with Title:**
+```tsx
+
+
+
+ Warning Title
+ Warning description text
+
+
+```
+
+### Progress Component
+```tsx
+// ❌ Chakra v2
+
+
+// ✅ Chakra v3
+
+
+
+
+
+
+
+```
+
+**Progress with custom styling:**
+```tsx
+
+
+
+
+
+```
+
+## Layout Components Still Work
+
+**Important**: VStack, HStack, Box, Grid, GridItem, Text, Button, Input, etc. still work the same way in v3. The confusion around VStack/HStack causing "invalid component type" errors is usually due to **circular import dependencies**, not Chakra version issues.
+
+## Common Debugging Steps
+
+1. **Check imports**: Ensure all Chakra components are imported from `@chakra-ui/react`
+2. **Verify component structure**: Use the v3 nested component patterns (Component.Root, Component.Trigger, etc.)
+3. **Check props**: Use `colorPalette` instead of `colorScheme`, `disabled` instead of `isDisabled`
+4. **Circular imports**: If getting "invalid component type" errors with basic components like VStack, check for circular import dependencies
+
+## Migration Verification Checklist
+
+When migrating components to Chakra v3:
+- [ ] Replace `` with ``
+- [ ] Replace `` with ``
+- [ ] Wrap text in `...`
+- [ ] Replace `