DecisionGuideAI
Get the Scenario Sandbox PoC running in under 2 minutes:
./tools/poc-start.shThis starts all services with safe defaults (all features OFF):
- Gateway: http://localhost:3001
- Warp: http://localhost:4311
- Jobs: http://localhost:4500
- Usage Meter: http://localhost:4600
Quick test: curl http://localhost:3001/health
To enable specific features, edit .env.poc and restart with:
docker compose --profile poc --env-file .env.poc up -dFlagβgated SSE streaming for the Scenario Sandbox. OFF by default.
Enable locally:
- Set the flag (either env or localStorage):
VITE_FEATURE_SSE=1
// or in DevTools:
localStorage.setItem('feature.sseStreaming','1')
- Optional autoβreconnect (perβbrowser):
localStorage.setItem('feature.sseAuto','1')
- Ensure gateway URL is correct, e.g.:
VITE_EDGE_GATEWAY_URL=http://localhost:3001
- Start sandbox and open:
npm run dev:sandbox
// open http://localhost:5176/#/sandbox (use bumped port if needed)
Flags (all OFF by default; enable via env or localStorage):
- VITE_FEATURE_SSE=1 // or localStorage.setItem('feature.sseStreaming','1')
- VITE_FEATURE_JOBS_PROGRESS=1 // or localStorage.setItem('feature.jobsProgress','1')
- VITE_FEATURE_RUN_REPORT=1 // or localStorage.setItem('feature.runReport','1')
- VITE_USE_REAL_REPORT=1 // or localStorage.setItem('feature.realReport','1')
- VITE_FEATURE_CONFIDENCE_CHIPS=1 // or localStorage.setItem('feature.confidenceChips','1')
- VITE_FEATURE_TELEMETRY=1 // or localStorage.setItem('feature.telemetry','1')
- VITE_FEATURE_HINTS=1 // or localStorage.setItem('feature.hints','1') (enables terminal tooltips + limited budget tip) // Optional stream buffering knob (default ON):
- VITE_STREAM_BUFFER=0|1 // or localStorage.setItem('feature.streamBuffer','0|1') // Scenario Sandbox params (seed/budget/model):
- VITE_FEATURE_PARAMS=1 // or localStorage.setItem('feature.params','1') // Markdown preview and Copy code buttons:
- VITE_FEATURE_MD_PREVIEW=1 // or localStorage.setItem('feature.mdPreview','1')
- VITE_FEATURE_COPY_CODE=1 // or localStorage.setItem('feature.copyCode','1') // Transcript export buttons (.txt/.json/.md):
- VITE_FEATURE_EXPORT=1 // or localStorage.setItem('feature.export','1') // Run Report: Copy JSON button
- VITE_FEATURE_REPORT_COPY=1 // or localStorage.setItem('feature.reportCopy','1') // Run Report: Download JSON button
- VITE_FEATURE_REPORT_DOWNLOAD=1 // or localStorage.setItem('feature.reportDownload','1') // Run Report: Pretty JSON toggle
- VITE_FEATURE_REPORT_PRETTY=1 // or localStorage.setItem('feature.reportPretty','1')
Copy/Download JSON are developer aids. They're off by default and must be explicitly enabled via env or localStorage.
// TLdraw adapter (optional; requires package)
- VITE_FEATURE_TLDRAW=1 // or localStorage.setItem('feature.tldraw','1') TLdraw support is OFF by default and requires installing @tldraw/tldraw. When not installed, the app falls back to the built-in canvas.
// Scenarios (templates)
- VITE_FEATURE_SCENARIOS=1 // or localStorage.setItem('feature.scenarios','1') Templates are local. Share links encode data in the URL β no server storage.
Tip: See
.env.examplefor the common flags you can toggle locally.
E2E test mode:
- VITE_E2E=1 mounts the Sandbox surface directly in dev/test builds (no auth/providers). Playwright navigates to
/#/sandbox(may include/?e2e=1in URLs for clarity; the query is ignored at runtime when VITE_E2E drives build-time checks).
Required env:
- VITE_EDGE_GATEWAY_URL=http://localhost:3001
Routes:
- /sandbox (Scenario Sandbox PoC)
- /ghost (draft list; UI-only)
Notes:
- βStopβ feels instant; tokens stop locally, server later confirms with βAbortedβ.
- Run Report is read-only: seed, route, duration, totals, steps. Real report is used when
VITE_USE_REAL_REPORT=1, otherwise a safe mock is shown. - No PII is logged. Telemetry (if enabled) emits counters only.
- Developer aids (Replay and Report JSON Copy/Download/Pretty) are behind flags and OFF by default.
Prereqs: Node 18+, npm (or pnpm/yarn), dependencies installed.
- Install the browser engine (one-time)
npx playwright install chromium- Run the full E2E suite (Chromium)
npx playwright test --project=chromium -c playwright.config.ts- Run a few targeted specs
# Core sandbox + drawer flows
npx playwright test e2e/report-drawer.spec.ts --project=chromium -c playwright.config.ts
npx playwright test e2e/export-md.spec.ts --project=chromium -c playwright.config.ts
npx playwright test e2e/sandbox-resume.spec.ts --project=chromium -c playwright.config.ts
# Jobs + canvas + replay
npx playwright test e2e/jobs-progress.spec.ts --project=chromium -c playwright.config.ts
npx playwright test e2e/canvas-drawer.spec.ts --project=chromium -c playwright.config.ts
npx playwright test e2e/replay-run.spec.ts --project=chromium -c playwright.config.ts
# TLdraw adapter (auto-skips if @tldraw/tldraw isnβt installed)
npx playwright test e2e/tldraw-adapter.spec.ts --project=chromium -c playwright.config.tsTip: check .env.example for handy feature flags while developing.
- Useful dev runs
# Headed, slow-mo for debugging
npx playwright test --project=chromium -c playwright.config.ts --headed --debug
# Re-run failing tests only
npx playwright test --project=chromium -c playwright.config.ts --last-failedSome features are OFF by default and gated for development. You can toggle them at runtime in DevTools Console:
// Report tools
localStorage.setItem('feature.reportCopy', '1');
localStorage.setItem('feature.reportDownload', '1');
localStorage.setItem('feature.reportPretty', '1');
// Replay + Canvas (shim) + TLdraw adapter
localStorage.setItem('feature.replay', '1');
localStorage.setItem('feature.canvas', '1');
localStorage.setItem('feature.tldraw', '1'); // requires @tldraw/tldraw; otherwise falls back to built-in canvas
localStorage.setItem('cfg.gateway', 'http://localhost:8787');
// To reset:
['feature.reportCopy','feature.reportDownload','feature.reportPretty']
.forEach(k => localStorage.removeItem(k));
## Canvas (Rich Node Types & Edge Visualization)
Interactive decision graph with typed nodes and rich edge properties.
### Quick Start
```bash
npm run dev:sandbox
# Open http://localhost:5176/#/canvas5 Node Types (with Lucide icons):
- π― Goal - Strategic objectives
- π² Decision - Choice points
- π‘ Option - Alternatives
β οΈ Risk - Potential issues- π Outcome - Results
Edge Properties:
- Weight (1-5)
- Style (solid/dashed/dotted)
- Curvature (0-1)
- Label & Confidence
βK- Command Palette (add nodes)βZ- Undoββ§Z- RedoβS- Save SnapshotβA- Select AllDelete- Remove selected
Via Toolbar:
- Click "+ Node βΎ" button
- Select type (Goal/Decision/Option/Risk/Outcome)
- Node appears at viewport center
Via Command Palette:
- Press
βK - Type node type (e.g., "goal")
- Press Enter
Change Node Type:
- Click node to select
- Properties panel opens on right
- Use "Type" dropdown to switch
- Position & label preserved
- Click edge to select
- Edge inspector opens
- Adjust weight, style, curvature, label, confidence
- Changes apply immediately
- Undo/Redo supported
Export:
- Click "Export" button
- Copy JSON (v2 format)
- Save to file
Import:
- Click "Import" button
- Paste JSON (v1 or v2)
- Auto-migrates v1βv2
- Preserves node types & edge labels
V1 Format:
{
"version": 1,
"nodes": [{"id": "1", "position": {"x": 100, "y": 100}, "data": {"label": "Goal"}}],
"edges": [{"id": "e1", "source": "1", "target": "2", "label": "Path"}]
}V2 Format (current):
- Includes node
typefield - Edge
datawith weight/style/curvature - Backward compatible via migration
Health Check (Opt-In):
# .env.local
VITE_ENABLE_PLOT_HEALTH=true # Default: false (no network calls)History Debounce:
- Drag operations debounced at 200ms
- Configurable via
HISTORY_DEBOUNCE_MSin store
- Save up to 10 canvas snapshots
- Stored in localStorage
- Max 5MB per snapshot
- Auto-rotation (oldest deleted)
# Unit tests
npm run test:unit -- src/canvas
# E2E tests
npx playwright test e2e/canvas
# TypeScript
npx tsc --noEmit --skipLibCheck// Deployment Verification // 1. Check Version Fingerprint // 2. Check Route Guard // 3. Verify Rich UI Route // 4. Compare with GitHub
The Canvas route provides a React Flow whiteboard with an integrated Templates panel for answer-first decision templates using a mock adapter.
Prerequisites:
- Node.js 18-20
- npm 8+
Setup:
# Install dependencies
npm ci
# Start dev server
npm run dev
# or
npm run dev:canvasThe browser will open to http://localhost:5173/#/canvas
After the Canvas loads, verify:
- β Whiteboard visible as the main surface (React Flow graph editor)
- β Templates Button in top-right corner
- β Build Badge in top-left showing commit and mode
Open Templates Panel:
- Click "Templates" button (top-right)
- Panel slides in from the right (desktop) or bottom (mobile)
- Verify:
- β Panel header shows "Templates" with close button
- β "Show dev controls" toggle (off by default)
Enable Dev Controls:
- Toggle "Show dev controls" switch
- Yellow dev section appears with:
- β "Adapter: Mock" indicator
- β Template selector (6 templates)
- β Seed input (prefilled with 1337)
- β Run/Reset buttons
Run a Template:
- Select a template (e.g., "Pricing Strategy")
- Click "Run"
- Verify:
- β Conservative | Likely | Optimistic bands visible
- β Confidence badge shown
- β Verification hash pill displayed
- β Click hash pill β "Verification hash copied." toast
- β "Pin to Canvas" button appears
Test Error Handling:
- Set seed to
23(triggers BAD_INPUT) - Click "Run" β helpful error banner appears
- Set seed to
29(triggers RATE_LIMITED) - Click "Run" β countdown appears, retry disabled until 0
Accessibility:
- β Tab through all controls (visible focus rings)
- β Screen reader announces panel open/close
- β Errors announced via role="alert"
- β Reduced motion respected (no animations)
Close Panel:
- Click X button in panel header
- Click overlay (mobile)
- Press Escape key
- Focus returns to "Templates" button
Port 5173 already in use:
# Kill existing process
lsof -ti:5173 | xargs kill -9
# Restart dev server
npm run devHMR not working:
# Clear Vite cache
rm -rf node_modules/.vite
# Restart dev server
npm run devTemplates panel not loading:
- Check browser console for errors
- Verify
src/adapters/plot/mockAdapter.tsexists - Ensure fixtures in
src/fixtures/plot/are present - Check that
src/canvas/panels/TemplatesPanel.tsxexists
Build fails:
# Clean and rebuild
rm -rf dist node_modules/.vite
npm ci
npm run build# Run all tests
npm test
# Run Templates panel tests only
npm test -- tests/canvas/panels
# Run all Templates + adapter tests
npm test -- tests/routes/templates tests/adapters/plot.mockAdapter.test.ts tests/canvas/panels
# Check bundle sizes
npm run build && npm run size:check
# Lint and format
npm run lint- Route:
/#/canvas(hash-based routing) - Main Surface: React Flow whiteboard (
CanvasMVP) - Panel: Templates panel (lazy-loaded,
TemplatesPanel) - Adapter: Mock PLoT adapter (
src/adapters/plot/mockAdapter.ts) - Components: Reuses Templates UI components from
src/routes/templates/components/ - State:
useTemplatesRunhook manages run lifecycle
Bundle Sizes:
- CanvasMVP: 1.11 KB gzipped
- TemplatesPanel: 2.05 KB gzipped
- DecisionTemplates: 2.61 KB gzipped (well under 120 KB budget)
Panel Behavior:
- Desktop (β₯1024px): Fixed right drawer (360-420px width)
- Mobile (<1024px): Bottom sheet modal with overlay
- Focus Management: Focus moves to panel on open, returns to button on close
- Keyboard: Escape key closes panel, Tab navigates within panel
Templates Panel:
- Answer-first decision templates
- Mock adapter with deterministic runs
- Dev controls (toggle on/off)
- Error handling with friendly messages
- Copy actions (hash, seed)
- Pin to Canvas (creates summary node)
Whiteboard:
- React Flow graph editor
- Pan, zoom, draw
- Node creation and editing
- Summary nodes from pinned templates (TODO)