🏭 GooseFactory HITL Modals
Interactive MCP App modals for Human-in-the-Loop feedback collection.
What's Here
5 production-ready, self-contained HTML modals designed for sandboxed iframes inside AI chat interfaces:
| Modal | File | Use Case | Key Feature |
|---|---|---|---|
| 🚦 Traffic Light | src/traffic-light.html |
Pass/Polish/Rework decisions | LED glow, tag pills, response time tracking |
| 📋 Report Card | src/report-card.html |
Multi-dimension grading (A-F) | Bubble-fill animation, GPA auto-calc, grade change tracking |
| ⚡ Speed Round | src/speed-round.html |
Batch pass/fail (timed) | 60s timer, streak counter, skip detection, full stats |
| ⚔️ Side-by-Side Arena | src/side-by-side.html |
A/B comparison | Hover time tracking, per-dimension breakdown, winner celebration |
| 🌡️ Thermometer | src/thermometer.html |
Subjective quality (0-100) | Draggable mercury, bg color transitions, particles, drag journey capture |
Quick Start
# Serve the preview page
npx serve src/preview -p 3333
# Or serve all files for direct access
npx serve src -p 3334
Then open http://localhost:3333 for the interactive preview environment.
Architecture
Self-Contained
Each modal is a single HTML file with inline CSS and JS. No external dependencies. This is intentional — modals are served as MCP App resources inside sandboxed iframes.
Communication Protocol
Every modal follows the CONTRACTS.md §3 "Modal Data Contract":
Host → Modal: window.__FACTORY_CONTEXT__ (injected before load)
Modal → Host: window.parent.postMessage()
Message Types
| Type | Direction | When |
|---|---|---|
factory_modal_ready |
Modal → Host | Modal loaded and interactive |
factory_modal_response |
Modal → Host | User submitted feedback |
factory_modal_close |
Modal → Host | Modal wants to close |
factory_modal_resize |
Modal → Host | Modal wants to change size |
factory_modal_error |
Modal → Host | Modal hit an error |
Hidden Behavioral Metrics
Every modal automatically captures:
timeToFirstInteractionMs— How long before user engagedtimeToDecisionMs— Total time from open to submittotalInteractions— Click/tap countfieldsModified— Which inputs were changeddeviceType— Mobile vs desktopviewportSize— Screen dimensions
Plus modal-specific metrics:
- Traffic Light:
responseTimeMs(fast = high confidence) - Report Card:
gradeChanges(mind-change tracking) - Speed Round: Per-item
timeMs, streaks, speed curve - Side-by-Side:
hoverTimeA/B(attention distribution) - Thermometer:
dragJourney(full temperature path during drag)
File Structure
packages/modals/
├── package.json
├── README.md ← You are here
├── src/
│ ├── traffic-light.html ← 🚦 Pass/Polish/Rework
│ ├── report-card.html ← 📋 A-F grading
│ ├── speed-round.html ← ⚡ Timed batch review
│ ├── side-by-side.html ← ⚔️ A/B comparison
│ ├── thermometer.html ← 🌡️ Quality temperature
│ ├── shared/
│ │ └── modal-utils.js ← Canonical utility functions
│ └── preview/
│ └── index.html ← Dev preview page with mock context & console
Design Principles
- 3-Second Rule — Instantly obvious what to do
- Dopamine Design — Every interaction feels satisfying
- Data Density — Rich signal from every tap/drag/click
- Dark Mode First —
#111background, designed for chat panels - Touch-Friendly — 48px minimum tap targets
- 400-600px Width — Optimized for chat panel constraints
Integrating with GooseFactory
MCP App Host Usage
// In your MCP tool response:
const response = {
_meta: {
goose: {
toolUI: {
displayType: "inline",
name: "Traffic Light Review",
renderer: "mcp-ui",
},
},
},
content: [{
uri: "ui://factory-modal",
mimeType: "text/html",
text: trafficLightHtml, // The full HTML file content
}],
};
McpAppHost Component
The host component (React/Desktop) should:
- Create a sandboxed iframe with
allow-scripts allow-forms - Inject
window.__FACTORY_CONTEXT__before the modal HTML - Listen for
postMessageevents - Forward
factory_modal_responsetoPOST /v1/feedback - Handle timeouts gracefully
See CONTRACTS.md §4.4 for the full McpAppHost component contract.
Preview Page
The preview page at src/preview/index.html provides:
- Sidebar with all 5 modals
- 500px-wide iframe with simulated device chrome
- Mock context data (editable pipeline/item names)
- Real-time
postMessageconsole showing all events - Reload and new-window buttons for testing
Next Modals (Planned)
The design doc (design-hitl-modal-collection.md) defines 25 total modals. Next batch:
- 🃏 Tinder Swipe — Batch card swiping
- 🎯 Spotlight — Code annotation with attention heatmap
- 🏆 Judge's Scorecard — Olympic-style weighted scoring
- 🎲 Priority Poker — Fibonacci estimation cards
- 🔫 Mission Briefing — High-stakes go/no-go with flight checks