Spaces:
Sleeping
Sleeping
Commit ·
d7b4377
1
Parent(s): d94aafc
docs: add smart gap analysis & question cards design spec
Browse filesCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
docs/superpowers/specs/2026-04-12-smart-gap-analysis-design.md
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Smart Gap Analysis & Question Cards
|
| 2 |
+
|
| 3 |
+
**Date:** 2026-04-12
|
| 4 |
+
**Status:** Draft
|
| 5 |
+
|
| 6 |
+
## Problem
|
| 7 |
+
|
| 8 |
+
When CAD, CNC, or CAM agents detect missing information, they respond with unstructured text ("NOT READY: need dimensions and material"). The orchestrator passes this message through to the user without analysis. The user must figure out what to provide and who to address. CNC and CAM agents lack any structured problem-reporting protocol at all.
|
| 9 |
+
|
| 10 |
+
## Solution
|
| 11 |
+
|
| 12 |
+
1. **Standardized NOT READY protocol** for CAD, CNC, and CAM agents.
|
| 13 |
+
2. **Gap analyzer** that scans agent responses for NOT READY prefixes and categorizes missing items via regex/keyword matching.
|
| 14 |
+
3. **Question cards** — actionable UI cards with the responsible agent, a question, and clickable suggestions — appended to the chat response.
|
| 15 |
+
4. **Answers go through normal `sendMessage()` flow** — full crew routing, no special handling.
|
| 16 |
+
|
| 17 |
+
## Agent Problem Reporting Protocol
|
| 18 |
+
|
| 19 |
+
All three output-producing agents (CAD, CNC, CAM) use the same prefix: `NOT READY:` followed by natural language listing what's missing.
|
| 20 |
+
|
| 21 |
+
### Agent Task Description Changes
|
| 22 |
+
|
| 23 |
+
**CNC agent** — currently only says "ask a SPECIFIC clarifying question". New instruction appended to task description:
|
| 24 |
+
|
| 25 |
+
```
|
| 26 |
+
If the design lacks critical manufacturability info (material, dimensions,
|
| 27 |
+
feature access, tolerance), start with 'NOT READY:' and list missing items.
|
| 28 |
+
If enough info exists, provide your manufacturability assessment.
|
| 29 |
+
```
|
| 30 |
+
|
| 31 |
+
**CAM agent** — currently only says "create optimal machining strategy". New instruction appended to task description:
|
| 32 |
+
|
| 33 |
+
```
|
| 34 |
+
If there is no CAD model generated yet or critical machining info is missing
|
| 35 |
+
(material, dimensions, surface finish requirements), start with 'NOT READY:'
|
| 36 |
+
and list missing items. If enough info exists, create the machining plan.
|
| 37 |
+
```
|
| 38 |
+
|
| 39 |
+
**CAD agent** — unchanged. Already uses `NOT READY:` protocol.
|
| 40 |
+
|
| 41 |
+
**Design and Engineering agents** — unchanged. They stay conversational and exploratory.
|
| 42 |
+
|
| 43 |
+
## Gap Analysis
|
| 44 |
+
|
| 45 |
+
### Data Models
|
| 46 |
+
|
| 47 |
+
```python
|
| 48 |
+
class MissingItem(BaseModel):
|
| 49 |
+
category: str # "dimension", "material", "feature", "constraint", etc.
|
| 50 |
+
description: str # "width", "wall thickness", "material selection"
|
| 51 |
+
agent_id: str # which agent flagged it
|
| 52 |
+
|
| 53 |
+
class GapAnalysis(BaseModel):
|
| 54 |
+
has_gaps: bool
|
| 55 |
+
missing_items: list[MissingItem]
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
### How It Works
|
| 59 |
+
|
| 60 |
+
1. After all agent responses are collected, `analyze_gaps(responses)` scans each response.
|
| 61 |
+
2. If an agent's message starts with `NOT READY:`, extract the text after the prefix.
|
| 62 |
+
3. Run keyword/regex matching on that text to categorize missing items:
|
| 63 |
+
|
| 64 |
+
| Keywords in NOT READY text | Category | Responsible Agent |
|
| 65 |
+
|---|---|---|
|
| 66 |
+
| width, height, depth, length, diameter, dimension, size | `dimension` | engineering |
|
| 67 |
+
| material, alloy, grade, aluminum, steel, metal | `material` | engineering |
|
| 68 |
+
| shape, form, type, profile, geometry, what kind | `shape` | design |
|
| 69 |
+
| hole, fillet, chamfer, pocket, slot, feature | `feature` | design |
|
| 70 |
+
| tolerance, wall thickness, constraint, min wall, max size | `constraint` | engineering |
|
| 71 |
+
| axis, machine, setup, fixture, tool access | `machining` | cnc |
|
| 72 |
+
| surface finish, roughness, Ra | `finish` | cnc |
|
| 73 |
+
| model, CAD, 3D, generate | `model` | cad |
|
| 74 |
+
|
| 75 |
+
4. Deduplicate — if both CAD and CNC flag "material", only one `MissingItem` is kept (first wins).
|
| 76 |
+
5. Return `GapAnalysis` with the deduplicated list.
|
| 77 |
+
|
| 78 |
+
### Agent Assignment
|
| 79 |
+
|
| 80 |
+
Each category maps to a "responsible agent" — the agent best suited to help the user provide that info. This mapping is configurable in `config.yaml` under `gap_analysis.category_agents`.
|
| 81 |
+
|
| 82 |
+
## Question Cards
|
| 83 |
+
|
| 84 |
+
### Data Model
|
| 85 |
+
|
| 86 |
+
```python
|
| 87 |
+
class QuestionCard(BaseModel):
|
| 88 |
+
category: str # from MissingItem
|
| 89 |
+
question: str # human-readable question
|
| 90 |
+
responsible_agent: str # agent_id
|
| 91 |
+
agent_name: str # display name
|
| 92 |
+
agent_color: str # for frontend rendering
|
| 93 |
+
suggestions: list[str] # clickable options
|
| 94 |
+
allow_custom: bool # show free-text input
|
| 95 |
+
```
|
| 96 |
+
|
| 97 |
+
### Question Templates
|
| 98 |
+
|
| 99 |
+
| Category | Question | Suggestions |
|
| 100 |
+
|---|---|---|
|
| 101 |
+
| `dimension` | "What are the part dimensions?" | (none — free input fields for width/height/depth) |
|
| 102 |
+
| `material` | "What material should this be made from?" | ["Aluminum 6061", "Aluminum 7075", "Steel 304", "Steel 316", "Brass", "Titanium"] |
|
| 103 |
+
| `shape` | "What type of part are you designing?" | ["Bracket", "Enclosure", "Plate", "Shaft", "Gear", "Flange"] |
|
| 104 |
+
| `feature` | "What features does the part need?" | ["Mounting holes", "Fillets", "Chamfers", "Pockets", "Slots"] |
|
| 105 |
+
| `constraint` | "Are there any manufacturing constraints?" | ["Min wall 2mm", "Min wall 3mm", "Min wall 5mm"] |
|
| 106 |
+
| `machining` | "What machining approach?" | ["3-axis", "3+2-axis", "5-axis", "Auto"] |
|
| 107 |
+
| `finish` | "What surface finish is required?" | ["Standard", "Fine (Ra 1.6)", "Mirror (Ra 0.4)"] |
|
| 108 |
+
| `model` | "A 3D model is needed first. Provide more design details or approve the plan to generate." | (no suggestions — informational only) |
|
| 109 |
+
|
| 110 |
+
These templates are defined in code (not config) — they are tightly coupled to the category set.
|
| 111 |
+
|
| 112 |
+
### Filtering Against Existing State
|
| 113 |
+
|
| 114 |
+
Before generating cards, `generate_question_cards(gap_analysis, design_state)` checks each `MissingItem` against the current `DesignState`:
|
| 115 |
+
- If `material` is already set, skip the material card even if an agent flagged it.
|
| 116 |
+
- If `dimensions` has entries, skip the dimension card.
|
| 117 |
+
- This prevents asking the user for info they already provided.
|
| 118 |
+
|
| 119 |
+
## Orchestrator Integration
|
| 120 |
+
|
| 121 |
+
### Position in the Flow
|
| 122 |
+
|
| 123 |
+
In `CrewOrchestrator._run_crew`, after agent responses are collected, before final return:
|
| 124 |
+
|
| 125 |
+
```
|
| 126 |
+
Agent responses collected
|
| 127 |
+
|
|
| 128 |
+
v
|
| 129 |
+
Extract decisions (existing) -> updated_state
|
| 130 |
+
|
|
| 131 |
+
v
|
| 132 |
+
analyze_gaps(responses) -> GapAnalysis
|
| 133 |
+
|
|
| 134 |
+
v
|
| 135 |
+
if has_gaps:
|
| 136 |
+
generate_question_cards(gap_analysis, updated_state) -> list[QuestionCard]
|
| 137 |
+
attach to response
|
| 138 |
+
|
|
| 139 |
+
v
|
| 140 |
+
Check score / auto-trigger plan (existing)
|
| 141 |
+
|
|
| 142 |
+
v
|
| 143 |
+
Return result
|
| 144 |
+
```
|
| 145 |
+
|
| 146 |
+
### Modified Response Shape
|
| 147 |
+
|
| 148 |
+
```json
|
| 149 |
+
{
|
| 150 |
+
"responses": [...],
|
| 151 |
+
"preview": null,
|
| 152 |
+
"design_state": {...},
|
| 153 |
+
"question_cards": [
|
| 154 |
+
{
|
| 155 |
+
"category": "material",
|
| 156 |
+
"question": "What material should this be made from?",
|
| 157 |
+
"responsible_agent": "engineering",
|
| 158 |
+
"agent_name": "Engineering Agent",
|
| 159 |
+
"agent_color": "#00b4d8",
|
| 160 |
+
"suggestions": ["Aluminum 6061", "Aluminum 7075", "Steel 304", "Brass"],
|
| 161 |
+
"allow_custom": true
|
| 162 |
+
},
|
| 163 |
+
{
|
| 164 |
+
"category": "dimension",
|
| 165 |
+
"question": "What are the part dimensions?",
|
| 166 |
+
"responsible_agent": "engineering",
|
| 167 |
+
"agent_name": "Engineering Agent",
|
| 168 |
+
"agent_color": "#00b4d8",
|
| 169 |
+
"suggestions": [],
|
| 170 |
+
"allow_custom": true
|
| 171 |
+
}
|
| 172 |
+
]
|
| 173 |
+
}
|
| 174 |
+
```
|
| 175 |
+
|
| 176 |
+
`question_cards` is an empty list when no gaps exist.
|
| 177 |
+
|
| 178 |
+
### Interaction with Planning Phase
|
| 179 |
+
|
| 180 |
+
- **`exploring` phase:** cards are generated normally.
|
| 181 |
+
- **`approved` phase:** if CAD/CNC/CAM say NOT READY, phase resets to `exploring` AND cards are generated from the gaps — the user sees both the reset and what to fix.
|
| 182 |
+
- **`planning` phase:** no cards (user is reviewing the plan, not chatting).
|
| 183 |
+
|
| 184 |
+
## Frontend Question Cards
|
| 185 |
+
|
| 186 |
+
### Layout
|
| 187 |
+
|
| 188 |
+
Rendered inline in the chat, after agent messages:
|
| 189 |
+
|
| 190 |
+
```
|
| 191 |
+
+------------------------------+
|
| 192 |
+
| MISSING INFO |
|
| 193 |
+
| |
|
| 194 |
+
| EA What material? |
|
| 195 |
+
| [Aluminum 6061] [Alu 7075] |
|
| 196 |
+
| [Steel 304] [Brass] |
|
| 197 |
+
| [Custom: ___________] |
|
| 198 |
+
| |
|
| 199 |
+
| EA Part dimensions? |
|
| 200 |
+
| Width: [____] mm |
|
| 201 |
+
| Height: [____] mm |
|
| 202 |
+
| Depth: [____] mm |
|
| 203 |
+
| [Submit] |
|
| 204 |
+
| |
|
| 205 |
+
+------------------------------+
|
| 206 |
+
```
|
| 207 |
+
|
| 208 |
+
### Card Behavior
|
| 209 |
+
|
| 210 |
+
- **Chip-based cards** (material, shape, features, machining, finish, constraint): clicking a chip immediately sends the value through `sendMessage()` as a natural language message. Cards are removed after submission.
|
| 211 |
+
- **Dimension cards:** render input fields (width/height/depth). A "Submit" button sends all dimension values at once as a composed message (e.g., "60mm wide, 40mm high, 20mm deep"). Cards are removed after submission.
|
| 212 |
+
- **Informational cards** (model category): no interaction — just a message explaining what's needed.
|
| 213 |
+
- Only one set of question cards is active at a time. New cards from a subsequent turn replace previous ones.
|
| 214 |
+
- Cards are removed on any `sendMessage()` call — whether the user interacts with a card or types freely in the chat input.
|
| 215 |
+
|
| 216 |
+
### Styling
|
| 217 |
+
|
| 218 |
+
- Reuses existing `.wizard-chip`, `.wizard-dim-input` classes for consistency with the guided wizard.
|
| 219 |
+
- New `.gap-card` container class with a left border colored by the responsible agent's color.
|
| 220 |
+
- Agent avatar dot shown next to the agent name in each card.
|
| 221 |
+
|
| 222 |
+
### Client-Side State Update
|
| 223 |
+
|
| 224 |
+
When the user clicks a suggestion or submits dimensions:
|
| 225 |
+
1. Update `designState` immediately on the client side (same as the wizard does).
|
| 226 |
+
2. Send the composed message through `sendMessage()`.
|
| 227 |
+
3. Normal crew routing handles it — no special routing.
|
| 228 |
+
|
| 229 |
+
## Configuration
|
| 230 |
+
|
| 231 |
+
### New `gap_analysis` section in `config.yaml`
|
| 232 |
+
|
| 233 |
+
```yaml
|
| 234 |
+
gap_analysis:
|
| 235 |
+
category_keywords:
|
| 236 |
+
dimension:
|
| 237 |
+
- width
|
| 238 |
+
- height
|
| 239 |
+
- depth
|
| 240 |
+
- length
|
| 241 |
+
- diameter
|
| 242 |
+
- dimension
|
| 243 |
+
- size
|
| 244 |
+
material:
|
| 245 |
+
- material
|
| 246 |
+
- alloy
|
| 247 |
+
- grade
|
| 248 |
+
- aluminum
|
| 249 |
+
- steel
|
| 250 |
+
- metal
|
| 251 |
+
shape:
|
| 252 |
+
- shape
|
| 253 |
+
- form
|
| 254 |
+
- type
|
| 255 |
+
- profile
|
| 256 |
+
- geometry
|
| 257 |
+
- what kind
|
| 258 |
+
feature:
|
| 259 |
+
- hole
|
| 260 |
+
- fillet
|
| 261 |
+
- chamfer
|
| 262 |
+
- pocket
|
| 263 |
+
- slot
|
| 264 |
+
- feature
|
| 265 |
+
constraint:
|
| 266 |
+
- tolerance
|
| 267 |
+
- wall thickness
|
| 268 |
+
- constraint
|
| 269 |
+
- min wall
|
| 270 |
+
- max size
|
| 271 |
+
machining:
|
| 272 |
+
- axis
|
| 273 |
+
- machine
|
| 274 |
+
- setup
|
| 275 |
+
- fixture
|
| 276 |
+
- tool access
|
| 277 |
+
finish:
|
| 278 |
+
- surface finish
|
| 279 |
+
- roughness
|
| 280 |
+
- Ra
|
| 281 |
+
model:
|
| 282 |
+
- model
|
| 283 |
+
- CAD
|
| 284 |
+
- 3D
|
| 285 |
+
- generate
|
| 286 |
+
category_agents:
|
| 287 |
+
dimension: engineering
|
| 288 |
+
material: engineering
|
| 289 |
+
shape: design
|
| 290 |
+
feature: design
|
| 291 |
+
constraint: engineering
|
| 292 |
+
machining: cnc
|
| 293 |
+
finish: cnc
|
| 294 |
+
model: cad
|
| 295 |
+
```
|
| 296 |
+
|
| 297 |
+
### Pydantic Config Model
|
| 298 |
+
|
| 299 |
+
```python
|
| 300 |
+
class GapAnalysisConfig(BaseModel):
|
| 301 |
+
category_keywords: dict[str, list[str]] = Field(default_factory=dict)
|
| 302 |
+
category_agents: dict[str, str] = Field(default_factory=dict)
|
| 303 |
+
```
|
| 304 |
+
|
| 305 |
+
Added to `Settings` alongside existing `planning` field.
|
| 306 |
+
|
| 307 |
+
## Files Changed
|
| 308 |
+
|
| 309 |
+
| File | Change |
|
| 310 |
+
|------|--------|
|
| 311 |
+
| `agents/gap_analyzer.py` | **New file.** `MissingItem`, `GapAnalysis`, `QuestionCard` models. `analyze_gaps()` and `generate_question_cards()` functions. Question templates. |
|
| 312 |
+
| `agents/crew_orchestrator.py` | Import gap analyzer. Call `analyze_gaps()` after response collection. Call `generate_question_cards()` if gaps found. Add `question_cards` to return dict. Update CNC/CAM task descriptions with NOT READY protocol. |
|
| 313 |
+
| `config/settings.py` | Add `GapAnalysisConfig` model, add `gap_analysis` field to `Settings`. |
|
| 314 |
+
| `config.yaml` | Add `gap_analysis` section. Update CNC and CAM agent backstories with NOT READY instructions. |
|
| 315 |
+
| `web/index.html` | Add `.gap-card` CSS. Add `renderQuestionCards()` JS function. Update `sendMessage()` to render cards when present. Add card interaction handlers (chip click, dimension submit). |
|
| 316 |
+
| `tests/test_gap_analyzer.py` | **New file.** Tests for `analyze_gaps()`, `generate_question_cards()`, deduplication, state filtering. |
|
| 317 |
+
|
| 318 |
+
## Files NOT Changed
|
| 319 |
+
|
| 320 |
+
| File | Reason |
|
| 321 |
+
|------|--------|
|
| 322 |
+
| `agents/design_state.py` | Gap analysis is separate from state accumulation |
|
| 323 |
+
| `server/routes.py` | No new endpoints — cards flow through existing `/api/chat` response |
|
| 324 |
+
| `server/web.py` | No new serving needs |
|
| 325 |
+
| `core/executor.py` | Unchanged |
|
| 326 |
+
| `core/cam.py` | Unchanged |
|
| 327 |
+
|
| 328 |
+
## Testing Strategy
|
| 329 |
+
|
| 330 |
+
- **Unit tests for `analyze_gaps()`** — verify NOT READY detection, keyword categorization, deduplication across agents, handling of responses without NOT READY prefix.
|
| 331 |
+
- **Unit tests for `generate_question_cards()`** — verify correct question/suggestion templates per category, filtering against populated DesignState fields, agent metadata lookup.
|
| 332 |
+
- **Integration test** — verify that a `chat_turn` with a CAD agent returning NOT READY produces `question_cards` in the response alongside agent messages.
|
| 333 |
+
- **Frontend manual testing** — verify cards render after NOT READY response, chip clicks send messages, dimension submit works, cards are removed after interaction.
|