opengstack 0.14.0 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -4
- package/CLAUDE.md +127 -110
- package/README.md +10 -5
- package/SKILL.md +500 -70
- package/bin/opengstack.js +69 -69
- package/commands/autoplan.md +7 -9
- package/commands/benchmark.md +84 -91
- package/commands/browse.md +60 -64
- package/commands/canary.md +7 -9
- package/commands/careful.md +2 -2
- package/commands/codex.md +7 -9
- package/commands/connect-chrome.md +7 -9
- package/commands/cso.md +7 -9
- package/commands/design-consultation.md +7 -9
- package/commands/design-review.md +7 -9
- package/commands/design-shotgun.md +7 -9
- package/commands/document-release.md +7 -9
- package/commands/freeze.md +3 -3
- package/commands/guard.md +4 -4
- package/commands/investigate.md +7 -9
- package/commands/land-and-deploy.md +7 -9
- package/commands/office-hours.md +7 -9
- package/commands/{gstack-upgrade.md → opengstack-upgrade.md} +64 -65
- package/commands/plan-ceo-review.md +7 -9
- package/commands/plan-design-review.md +7 -9
- package/commands/plan-eng-review.md +7 -9
- package/commands/qa-only.md +7 -9
- package/commands/qa.md +7 -9
- package/commands/retro.md +7 -9
- package/commands/review.md +7 -9
- package/commands/setup-browser-cookies.md +22 -26
- package/commands/setup-deploy.md +7 -9
- package/commands/ship.md +7 -9
- package/commands/unfreeze.md +7 -7
- package/docs/designs/CHROME_VS_CHROMIUM_EXPLORATION.md +9 -9
- package/docs/designs/CONDUCTOR_CHROME_SIDEBAR_INTEGRATION.md +2 -2
- package/docs/designs/CONDUCTOR_SESSION_API.md +16 -16
- package/docs/designs/DESIGN_SHOTGUN.md +74 -74
- package/docs/designs/DESIGN_TOOLS_V1.md +111 -111
- package/docs/skills.md +483 -202
- package/package.json +42 -43
- package/scripts/analytics.ts +188 -0
- package/scripts/dev-skill.ts +83 -0
- package/scripts/discover-skills.ts +39 -0
- package/scripts/eval-compare.ts +97 -0
- package/scripts/eval-list.ts +117 -0
- package/scripts/eval-select.ts +86 -0
- package/scripts/eval-summary.ts +188 -0
- package/scripts/eval-watch.ts +172 -0
- package/scripts/gen-skill-docs.ts +473 -0
- package/scripts/resolvers/browse.ts +129 -0
- package/scripts/resolvers/codex-helpers.ts +133 -0
- package/scripts/resolvers/composition.ts +48 -0
- package/scripts/resolvers/confidence.ts +37 -0
- package/scripts/resolvers/constants.ts +50 -0
- package/scripts/resolvers/design.ts +950 -0
- package/scripts/resolvers/index.ts +59 -0
- package/scripts/resolvers/learnings.ts +96 -0
- package/scripts/resolvers/preamble.ts +505 -0
- package/scripts/resolvers/review.ts +884 -0
- package/scripts/resolvers/testing.ts +573 -0
- package/scripts/resolvers/types.ts +45 -0
- package/scripts/resolvers/utility.ts +421 -0
- package/scripts/skill-check.ts +190 -0
- package/scripts/cleanup.py +0 -100
- package/scripts/filter-skills.sh +0 -114
- package/scripts/filter_skills.py +0 -164
- package/scripts/install-commands.js +0 -45
- package/scripts/install-skills.js +0 -60
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Design: Design Shotgun — Browser-to-Agent Feedback Loop
|
|
2
2
|
|
|
3
3
|
Generated on 2026-03-27
|
|
4
|
-
Branch:
|
|
4
|
+
Branch:
|
|
5
5
|
Status: LIVING DOCUMENT — update as bugs are found and fixed
|
|
6
6
|
|
|
7
7
|
## What This Feature Does
|
|
@@ -18,17 +18,17 @@ The board is the feedback mechanism.
|
|
|
18
18
|
## The Core Problem: Two Worlds That Must Talk
|
|
19
19
|
|
|
20
20
|
```
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
┌─────────────────────┐ ┌──────────────────────┐
|
|
22
|
+
│ USER'S BROWSER │ │ CODING AGENT │
|
|
23
|
+
│ (real Chrome) │ │ (Claude Code / │
|
|
24
|
+
│ │ │ Conductor) │
|
|
25
|
+
│ Comparison board │ │ │
|
|
26
|
+
│ with buttons: │ ??? │ Needs to know: │
|
|
27
|
+
│ - Submit │ ──────── │ - What was picked │
|
|
28
|
+
│ - Regenerate │ │ - Star ratings │
|
|
29
|
+
│ - More like this │ │ - Comments │
|
|
30
|
+
│ - Remix │ │ - Regen requested? │
|
|
31
|
+
└─────────────────────┘ └──────────────────────┘
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
The "???" is the hard part. The user clicks a button in Chrome. The agent running in
|
|
@@ -38,27 +38,27 @@ no shared memory, no shared event bus, no WebSocket connection.
|
|
|
38
38
|
## Architecture: How the Linkage Works
|
|
39
39
|
|
|
40
40
|
```
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
41
|
+
USER'S BROWSER $D serve (Bun HTTP) AGENT
|
|
42
|
+
═══════════════ ═══════════════════ ═════
|
|
43
|
+
│ │ │
|
|
44
|
+
│ GET / │ │
|
|
45
|
+
│ ◄─────── serves board HTML ──────►│ │
|
|
46
|
+
│ (with __OpenGStack_SERVER_URL │ │
|
|
47
|
+
│ injected into <head>) │ │
|
|
48
|
+
│ │ │
|
|
49
|
+
│ [user rates, picks, comments] │ │
|
|
50
|
+
│ │ │
|
|
51
|
+
│ POST /api/feedback │ │
|
|
52
|
+
│ ─────── {preferred:"A",...} ─────►│ │
|
|
53
|
+
│ │ │
|
|
54
|
+
│ ◄── {received:true} ────────────│ │
|
|
55
|
+
│ │── writes feedback.json ──►│
|
|
56
|
+
│ [inputs disabled, │ (or feedback-pending │
|
|
57
|
+
│ "Return to agent" shown] │ .json for regen) │
|
|
58
|
+
│ │ │
|
|
59
|
+
│ │ [agent polls
|
|
60
|
+
│ │ every 5s,
|
|
61
|
+
│ │ reads file]
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
### The Three Files
|
|
@@ -72,34 +72,34 @@ no shared memory, no shared event bus, no WebSocket connection.
|
|
|
72
72
|
### The State Machine
|
|
73
73
|
|
|
74
74
|
```
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
75
|
+
$D serve starts
|
|
76
|
+
│
|
|
77
|
+
▼
|
|
78
|
+
┌──────────┐
|
|
79
|
+
│ SERVING │◄──────────────────────────────────────┐
|
|
80
|
+
│ │ │
|
|
81
|
+
│ Board is │ POST /api/feedback │
|
|
82
|
+
│ live, │ {regenerated: true} │
|
|
83
|
+
│ waiting │──────────────────►┌──────────────┐ │
|
|
84
|
+
│ │ │ REGENERATING │ │
|
|
85
|
+
│ │ │ │ │
|
|
86
|
+
└────┬─────┘ │ Agent has │ │
|
|
87
|
+
│ │ 10 min to │ │
|
|
88
|
+
│ POST /api/feedback │ POST new │ │
|
|
89
|
+
│ {regenerated: false} │ board HTML │ │
|
|
90
|
+
│ └──────┬───────┘ │
|
|
91
|
+
▼ │ │
|
|
92
|
+
┌──────────┐ POST /api/reload │
|
|
93
|
+
│ DONE │ {html: "/new/board"} │
|
|
94
|
+
│ │ │ │
|
|
95
|
+
│ exit 0 │ ▼ │
|
|
96
|
+
└──────────┘ ┌──────────────┐ │
|
|
97
|
+
│ RELOADING │─────┘
|
|
98
|
+
│ │
|
|
99
|
+
│ Board auto- │
|
|
100
|
+
│ refreshes │
|
|
101
|
+
│ (same tab) │
|
|
102
|
+
└──────────────┘
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
### Port Discovery
|
|
@@ -212,7 +212,7 @@ There is no port file written to disk.
|
|
|
212
212
|
**Potential fix:** Write a `serve.pid` or `serve.port` file next to the board HTML
|
|
213
213
|
on startup. Agent can read it anytime:
|
|
214
214
|
```bash
|
|
215
|
-
cat "$_DESIGN_DIR/serve.port"
|
|
215
|
+
cat "$_DESIGN_DIR/serve.port" # → 54321
|
|
216
216
|
```
|
|
217
217
|
|
|
218
218
|
### 7. The Feedback File Cleanup Problem
|
|
@@ -290,13 +290,13 @@ proving it's writable). But a try/catch with a 500 response would be cleaner.
|
|
|
290
290
|
2. $D serve starts Bun.serve() on random port (e.g. 54321)
|
|
291
291
|
3. $D serve opens http://127.0.0.1:54321 in user's browser
|
|
292
292
|
4. $D serve prints to stderr: SERVE_STARTED: port=54321 html=/path/board.html
|
|
293
|
-
5. $D serve writes board HTML with injected
|
|
293
|
+
5. $D serve writes board HTML with injected __OpenGStack_SERVER_URL
|
|
294
294
|
6. User sees comparison board with 3 variants side by side
|
|
295
295
|
7. User picks Option B, rates A: 3/5, B: 5/5, C: 2/5
|
|
296
296
|
8. User writes "B has better spacing, go with that" in overall feedback
|
|
297
297
|
9. User clicks Submit
|
|
298
298
|
10. Board JS POSTs to http://127.0.0.1:54321/api/feedback
|
|
299
|
-
|
|
299
|
+
Body: {"preferred":"B","ratings":{"A":3,"B":5,"C":2},"overall":"B has better spacing","regenerated":false}
|
|
300
300
|
11. Server writes feedback.json to disk (next to board.html)
|
|
301
301
|
12. Server prints feedback JSON to stdout
|
|
302
302
|
13. Server responds {received:true, action:"submitted"}
|
|
@@ -309,22 +309,22 @@ proving it's writable). But a try/catch with a 500 response would be cleaner.
|
|
|
309
309
|
### Regeneration Path: User Wants Different Options
|
|
310
310
|
|
|
311
311
|
```
|
|
312
|
-
1-6.
|
|
313
|
-
7.
|
|
314
|
-
8.
|
|
315
|
-
9.
|
|
316
|
-
|
|
312
|
+
1-6. Same as above
|
|
313
|
+
7. User clicks "Totally different" chiclet
|
|
314
|
+
8. User clicks Regenerate
|
|
315
|
+
9. Board JS POSTs to /api/feedback
|
|
316
|
+
Body: {"regenerated":true,"regenerateAction":"different","preferred":"","ratings":{},...}
|
|
317
317
|
10. Server writes feedback-pending.json to disk
|
|
318
318
|
11. Server state → "regenerating"
|
|
319
319
|
12. Server responds {received:true, action:"regenerate"}
|
|
320
320
|
13. Board shows spinner: "Generating new designs..."
|
|
321
321
|
14. Board starts polling GET /api/progress every 2s
|
|
322
322
|
|
|
323
|
-
|
|
323
|
+
Meanwhile, in the agent:
|
|
324
324
|
15. Agent's polling loop finds feedback-pending.json
|
|
325
325
|
16. Agent reads it, deletes it
|
|
326
326
|
17. Agent runs: $D variants --brief "totally different direction" --count 3
|
|
327
|
-
|
|
327
|
+
(ONE AT A TIME, not parallel)
|
|
328
328
|
18. Agent runs: $D compare --images "new-A.png,new-B.png,new-C.png" --output board-v2.html
|
|
329
329
|
19. Agent POSTs: curl -X POST http://127.0.0.1:54321/api/reload -d '{"html":"/path/board-v2.html"}'
|
|
330
330
|
20. Server swaps htmlContent to new board
|
|
@@ -341,7 +341,7 @@ proving it's writable). But a try/catch with a 500 response would be cleaner.
|
|
|
341
341
|
Same as regeneration, except:
|
|
342
342
|
- regenerateAction is "more_like_B" (references the variant)
|
|
343
343
|
- Agent uses $D iterate --image B.png --brief "more like this, keep the spacing"
|
|
344
|
-
|
|
344
|
+
instead of $D variants
|
|
345
345
|
```
|
|
346
346
|
|
|
347
347
|
### Fallback Path: $D serve Fails
|
|
@@ -350,7 +350,7 @@ Same as regeneration, except:
|
|
|
350
350
|
1. Agent tries $D compare --serve, it fails (binary missing, port error, etc.)
|
|
351
351
|
2. Agent falls back to: open file:///path/board.html
|
|
352
352
|
3. Agent uses AskUserQuestion: "I've opened the design board. Which variant
|
|
353
|
-
|
|
353
|
+
do you prefer? Any feedback?"
|
|
354
354
|
4. User responds in text
|
|
355
355
|
5. Agent proceeds with text feedback (no structured JSON)
|
|
356
356
|
```
|
|
@@ -408,7 +408,7 @@ Same as regeneration, except:
|
|
|
408
408
|
| Spinner after regenerate | DOM shows loading text | `feedback-roundtrip.test.ts` |
|
|
409
409
|
| Full regen → reload → submit | 2-round trip | `feedback-roundtrip.test.ts` |
|
|
410
410
|
| Server starts on random port | port 0 binding | `serve.test.ts` |
|
|
411
|
-
| HTML injection of server URL |
|
|
411
|
+
| HTML injection of server URL | __OpenGStack_SERVER_URL check | `serve.test.ts` |
|
|
412
412
|
| Invalid JSON rejection | 400 response | `serve.test.ts` |
|
|
413
413
|
| HTML file validation | exit 1 if missing | `serve.test.ts` |
|
|
414
414
|
| Timeout behavior | exit 1 after timeout | `serve.test.ts` |
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
# Design:
|
|
1
|
+
# Design: opengstack Visual Design Generation (`design` binary)
|
|
2
2
|
|
|
3
3
|
Generated by /office-hours on 2026-03-26
|
|
4
|
-
Branch:
|
|
5
|
-
Repo:
|
|
4
|
+
Branch:
|
|
5
|
+
Repo: opengstack
|
|
6
6
|
Status: DRAFT
|
|
7
7
|
Mode: Intrapreneurship
|
|
8
8
|
|
|
9
9
|
## Context
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
OpenGStack's design skills (/office-hours, /design-consultation, /plan-design-review, /design-review) all produce **text descriptions** of design — DESIGN.md files with hex codes, plan docs with pixel specs in prose, ASCII art wireframes. The creator is a designer who hand-designed HelloSign in OmniGraffle and finds this embarrassing.
|
|
12
12
|
|
|
13
13
|
The unit of value is wrong. Users don't need richer design language — they need an executable visual artifact that changes the conversation from "do you like this spec?" to "is this the screen?"
|
|
14
14
|
|
|
@@ -49,19 +49,19 @@ Codex independently validated the core thesis: "The failure is not output qualit
|
|
|
49
49
|
```
|
|
50
50
|
design/
|
|
51
51
|
├── src/
|
|
52
|
-
│
|
|
53
|
-
│
|
|
54
|
-
│
|
|
55
|
-
│
|
|
56
|
-
│
|
|
57
|
-
│
|
|
58
|
-
│
|
|
59
|
-
│
|
|
52
|
+
│ ├── cli.ts # Entry point, command dispatch
|
|
53
|
+
│ ├── commands.ts # Command registry (source of truth for docs + validation)
|
|
54
|
+
│ ├── generate.ts # Generate mockups from structured brief
|
|
55
|
+
│ ├── iterate.ts # Multi-turn iteration on existing mockups
|
|
56
|
+
│ ├── variants.ts # Generate N design variants from brief
|
|
57
|
+
│ ├── check.ts # Vision-based quality gate (GPT-4o)
|
|
58
|
+
│ ├── brief.ts # Structured brief type + assembly helpers
|
|
59
|
+
│ └── session.ts # Session state (response IDs for multi-turn)
|
|
60
60
|
├── dist/
|
|
61
|
-
│
|
|
62
|
-
│
|
|
61
|
+
│ ├── design # Compiled binary
|
|
62
|
+
│ └── .version # Git hash
|
|
63
63
|
└── test/
|
|
64
|
-
|
|
64
|
+
└── design.test.ts # Integration tests
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
### Commands
|
|
@@ -105,21 +105,21 @@ The workflow is sequential, not parallel. PNGs are for visual exploration (human
|
|
|
105
105
|
|
|
106
106
|
```
|
|
107
107
|
1. $D variants --brief "..." --count 3 --output-dir /tmp/mockups/
|
|
108
|
-
|
|
108
|
+
→ Generates 2-5 PNG mockup variations
|
|
109
109
|
|
|
110
110
|
2. $D compare --images /tmp/mockups/*.png --output /tmp/design-board.html
|
|
111
|
-
|
|
111
|
+
→ Generates HTML comparison board (spec below)
|
|
112
112
|
|
|
113
113
|
3. $B goto file:///tmp/design-board.html
|
|
114
|
-
|
|
114
|
+
→ User reviews all variants in headed Chrome
|
|
115
115
|
|
|
116
116
|
4. User picks favorite, rates, comments, clicks [Submit]
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
Agent polls: $B eval document.getElementById('status').textContent
|
|
118
|
+
Agent reads: $B eval document.getElementById('feedback-result').textContent
|
|
119
|
+
→ No clipboard, no pasting. Agent reads feedback directly from the page.
|
|
120
120
|
|
|
121
121
|
5. Claude generates HTML wireframe via DESIGN_SKETCH matching approved direction
|
|
122
|
-
|
|
122
|
+
→ Agent implements from the inspectable HTML, not the opaque PNG
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
### Comparison Board Design Spec (from /plan-design-review)
|
|
@@ -131,39 +131,39 @@ width for maximum image fidelity. Users scroll vertically through variants.
|
|
|
131
131
|
|
|
132
132
|
```
|
|
133
133
|
┌─────────────────────────────────────────────────────────────┐
|
|
134
|
-
│
|
|
135
|
-
│
|
|
136
|
-
│
|
|
134
|
+
│ HEADER BAR │
|
|
135
|
+
│ "Design Exploration" . project name . "3 variants" │
|
|
136
|
+
│ Mode indicator: [Wide exploration] | [Matching DESIGN.md] │
|
|
137
137
|
├─────────────────────────────────────────────────────────────┤
|
|
138
|
-
│
|
|
139
|
-
│
|
|
140
|
-
│
|
|
141
|
-
│
|
|
142
|
-
│
|
|
143
|
-
│
|
|
144
|
-
│
|
|
145
|
-
│
|
|
146
|
-
│
|
|
147
|
-
│
|
|
148
|
-
│
|
|
149
|
-
│
|
|
150
|
-
│
|
|
151
|
-
│
|
|
152
|
-
│
|
|
153
|
-
│
|
|
154
|
-
│
|
|
155
|
-
│
|
|
156
|
-
│
|
|
157
|
-
│
|
|
158
|
-
│
|
|
159
|
-
│
|
|
160
|
-
│
|
|
161
|
-
│
|
|
162
|
-
│
|
|
163
|
-
│
|
|
164
|
-
│
|
|
165
|
-
│
|
|
166
|
-
│
|
|
138
|
+
│ │
|
|
139
|
+
│ ┌───────────────────────────────────────────────────────┐ │
|
|
140
|
+
│ │ VARIANT A (full width) │ │
|
|
141
|
+
│ │ [ mockup PNG, max-width: 1200px ] │ │
|
|
142
|
+
│ ├───────────────────────────────────────────────────────┤ │
|
|
143
|
+
│ │ (●) Pick ★★★★☆ [What do you like/dislike?____] │ │
|
|
144
|
+
│ │ [More like this] │ │
|
|
145
|
+
│ └───────────────────────────────────────────────────────┘ │
|
|
146
|
+
│ │
|
|
147
|
+
│ ┌───────────────────────────────────────────────────────┐ │
|
|
148
|
+
│ │ VARIANT B (full width) │ │
|
|
149
|
+
│ │ [ mockup PNG, max-width: 1200px ] │ │
|
|
150
|
+
│ ├───────────────────────────────────────────────────────┤ │
|
|
151
|
+
│ │ ( ) Pick ★★★☆☆ [What do you like/dislike?____] │ │
|
|
152
|
+
│ │ [More like this] │ │
|
|
153
|
+
│ └───────────────────────────────────────────────────────┘ │
|
|
154
|
+
│ │
|
|
155
|
+
│ ... (scroll for more variants) │
|
|
156
|
+
│ │
|
|
157
|
+
│ ─── separator ───────────────────────────────────────── │
|
|
158
|
+
│ Overall direction (optional, collapsed by default) │
|
|
159
|
+
│ [textarea, 3 lines, expand on focus] │
|
|
160
|
+
│ │
|
|
161
|
+
│ ─── REGENERATE BAR (#f7f7f7 bg) ─────────────────────── │
|
|
162
|
+
│ "Want to explore more?" │
|
|
163
|
+
│ [Totally different] [Match my design] [Custom: ______] │
|
|
164
|
+
│ [Regenerate ->] │
|
|
165
|
+
│ ───────────────────────────────────────────────────────── │
|
|
166
|
+
│ [ ✓ Submit ] │
|
|
167
167
|
└─────────────────────────────────────────────────────────────┘
|
|
168
168
|
```
|
|
169
169
|
|
|
@@ -186,15 +186,15 @@ width for maximum image fidelity. Users scroll vertically through variants.
|
|
|
186
186
|
**Feedback JSON structure** (written to hidden #feedback-result element):
|
|
187
187
|
```json
|
|
188
188
|
{
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
189
|
+
"preferred": "A",
|
|
190
|
+
"ratings": { "A": 4, "B": 3, "C": 2 },
|
|
191
|
+
"comments": {
|
|
192
|
+
"A": "Love the spacing, header feels right",
|
|
193
|
+
"B": "Too busy, but good color palette",
|
|
194
|
+
"C": "Wrong mood entirely"
|
|
195
|
+
},
|
|
196
|
+
"overall": "Go with A, make the CTA bigger",
|
|
197
|
+
"regenerated": false
|
|
198
198
|
}
|
|
199
199
|
```
|
|
200
200
|
|
|
@@ -202,7 +202,7 @@ width for maximum image fidelity. Users scroll vertically through variants.
|
|
|
202
202
|
|
|
203
203
|
**Responsive:** >1200px: comfortable margins. 768-1200px: tighter margins. <768px: full-width, no horizontal scroll.
|
|
204
204
|
|
|
205
|
-
**Screenshot consent (first-time only for $D evolve):** "This will send a screenshot of your live site to OpenAI for design evolution. [Proceed] [Don't ask again]" Stored in ~/.
|
|
205
|
+
**Screenshot consent (first-time only for $D evolve):** "This will send a screenshot of your live site to OpenAI for design evolution. [Proceed] [Don't ask again]" Stored in ~/.opengstack/config.yaml as design_screenshot_consent.
|
|
206
206
|
|
|
207
207
|
Why sequential: Codex adversarial review identified that raster PNGs are opaque to agents (no DOM, no states, no diffable structure). HTML wireframes preserve a bridge back to code. The PNG is for the human to say "yes, that's right." The HTML is for the agent to say "I know how to build this."
|
|
208
208
|
|
|
@@ -218,13 +218,13 @@ Browse needs a persistent Chromium instance. Design is just API calls — no rea
|
|
|
218
218
|
The brief is the interface between skill prose and image generation. Skills construct it from design context:
|
|
219
219
|
```typescript
|
|
220
220
|
interface DesignBrief {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
221
|
+
goal: string; // "Dashboard for coding assessment tool"
|
|
222
|
+
audience: string; // "Technical users, YC partners"
|
|
223
|
+
style: string; // "Dark theme, cream accents, minimal"
|
|
224
|
+
elements: string[]; // ["builder name", "score badge", "narrative letter"]
|
|
225
|
+
constraints?: string; // "Max width 1024px, mobile-first"
|
|
226
|
+
reference?: string; // Path to existing screenshot or DESIGN.md excerpt
|
|
227
|
+
screenType: string; // "desktop-dashboard" | "mobile-app" | "landing-page" | etc.
|
|
228
228
|
}
|
|
229
229
|
```
|
|
230
230
|
|
|
@@ -242,7 +242,7 @@ After generating, optionally pass the image through GPT-4o vision to check:
|
|
|
242
242
|
Auto-retry once on failure. If still fails, present anyway with a warning.
|
|
243
243
|
|
|
244
244
|
**5. Output location: explorations in /tmp, approved finals in `docs/designs/`**
|
|
245
|
-
- Exploration variants go to `/tmp/
|
|
245
|
+
- Exploration variants go to `/tmp/opengstack-mockups-{session}/` (ephemeral, not committed)
|
|
246
246
|
- Only the **user-approved final** mockup gets saved to `docs/designs/` (checked in)
|
|
247
247
|
- Default output directory configurable via CLAUDE.md `design_output_dir` setting
|
|
248
248
|
- Filename pattern: `{skill}-{description}-{timestamp}.png`
|
|
@@ -250,7 +250,7 @@ Auto-retry once on failure. If still fails, present anyway with a warning.
|
|
|
250
250
|
- Design doc references the committed image path
|
|
251
251
|
- Always show to user via the Read tool (which renders images inline in Claude Code)
|
|
252
252
|
- This avoids repo bloat: only approved designs are committed, not every exploration variant
|
|
253
|
-
- Fallback: if not in a git repo, save to `/tmp/
|
|
253
|
+
- Fallback: if not in a git repo, save to `/tmp/opengstack-mockup-{timestamp}.png`
|
|
254
254
|
|
|
255
255
|
**6. Trust boundary acknowledgment**
|
|
256
256
|
Default-on generation sends design brief text to OpenAI. This is a new external data flow vs. the existing HTML wireframe path which is entirely local. The brief contains only abstract design descriptions (goal, style, elements), never source code or user data. Screenshots from $B are NOT sent to OpenAI (the reference field in DesignBrief is a local file path used by the agent, not uploaded to the API). Document this in CLAUDE.md.
|
|
@@ -268,22 +268,22 @@ Variant generation uses staggered parallel: start each API call 1 second apart v
|
|
|
268
268
|
**New HostPaths entry:** `types.ts`
|
|
269
269
|
```typescript
|
|
270
270
|
// claude host:
|
|
271
|
-
designDir: '~/.claude/skills/
|
|
271
|
+
designDir: '~/.claude/skills/opengstack/design/dist'
|
|
272
272
|
// codex host:
|
|
273
|
-
designDir: '$
|
|
273
|
+
designDir: '$OpenGStack_DESIGN'
|
|
274
274
|
```
|
|
275
|
-
Note: Codex runtime setup (`setup` script) must also export `
|
|
275
|
+
Note: Codex runtime setup (`setup` script) must also export `OpenGStack_DESIGN` env var, similar to how `OpenGStack_BROWSE` is set.
|
|
276
276
|
|
|
277
277
|
**`$D` resolution bash block** (generated by `{{DESIGN_SETUP}}`):
|
|
278
278
|
```bash
|
|
279
279
|
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
280
280
|
D=""
|
|
281
|
-
[ -n "$_ROOT" ] && [ -x "$_ROOT/.claude/skills/
|
|
282
|
-
[ -z "$D" ] && D=~/.claude/skills/
|
|
281
|
+
[ -n "$_ROOT" ] && [ -x "$_ROOT/.claude/skills/opengstack/design/dist/design" ] && D="$_ROOT/.claude/skills/opengstack/design/dist/design"
|
|
282
|
+
[ -z "$D" ] && D=~/.claude/skills/opengstack/design/dist/design
|
|
283
283
|
if [ -x "$D" ]; then
|
|
284
|
-
|
|
284
|
+
echo "DESIGN_READY: $D"
|
|
285
285
|
else
|
|
286
|
-
|
|
286
|
+
echo "DESIGN_NOT_AVAILABLE"
|
|
287
287
|
fi
|
|
288
288
|
```
|
|
289
289
|
If `DESIGN_NOT_AVAILABLE`: skills fall back to HTML wireframe generation (existing `DESIGN_SKETCH` pattern). Design mockup is a progressive enhancement, not a hard requirement.
|
|
@@ -337,7 +337,7 @@ If `DESIGN_NOT_AVAILABLE`: skills fall back to HTML wireframe generation (existi
|
|
|
337
337
|
| `scripts/resolvers/index.ts` | Register DESIGN_SETUP + DESIGN_MOCKUP resolvers |
|
|
338
338
|
| `package.json` | Add `design` build command |
|
|
339
339
|
| `setup` | Build design binary alongside browse |
|
|
340
|
-
| `scripts/resolvers/preamble.ts` | Add `
|
|
340
|
+
| `scripts/resolvers/preamble.ts` | Add `OpenGStack_DESIGN` env var export for Codex host |
|
|
341
341
|
| `test/gen-skill-docs.test.ts` | Update DESIGN_SKETCH test suite for new resolvers |
|
|
342
342
|
| `setup` | Add design binary build + Codex/Kiro asset linking |
|
|
343
343
|
| `office-hours/SKILL.md.tmpl` | Replace Visual Sketch section with `{{DESIGN_MOCKUP}}` |
|
|
@@ -359,9 +359,9 @@ If `DESIGN_NOT_AVAILABLE`: skills fall back to HTML wireframe generation (existi
|
|
|
359
359
|
**Generate:** OpenAI Responses API with `image_generation` tool
|
|
360
360
|
```typescript
|
|
361
361
|
const response = await openai.responses.create({
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
362
|
+
model: "gpt-4o",
|
|
363
|
+
input: briefToPrompt(brief),
|
|
364
|
+
tools: [{ type: "image_generation", size: "1536x1024", quality: "high" }],
|
|
365
365
|
});
|
|
366
366
|
// Extract image from response output items
|
|
367
367
|
const imageItem = response.output.find(item => item.type === "image_generation_call");
|
|
@@ -372,10 +372,10 @@ fs.writeFileSync(outputPath, Buffer.from(base64Data, "base64"));
|
|
|
372
372
|
**Iterate:** Same API with `previous_response_id`
|
|
373
373
|
```typescript
|
|
374
374
|
const response = await openai.responses.create({
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
375
|
+
model: "gpt-4o",
|
|
376
|
+
input: feedback,
|
|
377
|
+
previous_response_id: session.lastResponseId,
|
|
378
|
+
tools: [{ type: "image_generation" }],
|
|
379
379
|
});
|
|
380
380
|
```
|
|
381
381
|
**NOTE:** Multi-turn image iteration via `previous_response_id` is an assumption that needs prototype validation. The Responses API supports conversation threading, but whether it retains visual context of generated images for edit-style iteration is not confirmed in docs. **Fallback:** if multi-turn doesn't work, `iterate` falls back to re-generating with the original brief + accumulated feedback in a single prompt.
|
|
@@ -383,14 +383,14 @@ const response = await openai.responses.create({
|
|
|
383
383
|
**Check:** GPT-4o vision
|
|
384
384
|
```typescript
|
|
385
385
|
const check = await openai.chat.completions.create({
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
386
|
+
model: "gpt-4o",
|
|
387
|
+
messages: [{
|
|
388
|
+
role: "user",
|
|
389
|
+
content: [
|
|
390
|
+
{ type: "image_url", image_url: { url: `data:image/png;base64,${imageData}` } },
|
|
391
|
+
{ type: "text", text: `Check this UI mockup. Brief: ${brief}. Is text readable? Are all elements present? Does it look like a real UI? Return PASS or FAIL with issues.` }
|
|
392
|
+
]
|
|
393
|
+
}]
|
|
394
394
|
});
|
|
395
395
|
```
|
|
396
396
|
|
|
@@ -401,14 +401,14 @@ const check = await openai.chat.completions.create({
|
|
|
401
401
|
**Codex OAuth tokens DO NOT work for image generation.** Tested 2026-03-26: both the Images API and Responses API reject `~/.codex/auth.json` access_token with "Missing scopes: api.model.images.request". Codex CLI also has no native imagegen capability.
|
|
402
402
|
|
|
403
403
|
**Auth resolution order:**
|
|
404
|
-
1. Read `~/.
|
|
404
|
+
1. Read `~/.opengstack/openai.json` → `{ "api_key": "sk-..." }` (file permissions 0600)
|
|
405
405
|
2. Fall back to `OPENAI_API_KEY` environment variable
|
|
406
406
|
3. If neither exists → guided setup flow:
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
407
|
+
- Tell user: "Design mockups need an OpenAI API key with image generation permissions. Get one at platform.openai.com/api-keys"
|
|
408
|
+
- Prompt user to paste the key
|
|
409
|
+
- Write to `~/.opengstack/openai.json` with 0600 permissions
|
|
410
|
+
- Run a smoke test (generate a 1024x1024 test image) to verify the key works
|
|
411
|
+
- If smoke test passes, proceed. If it fails, show the error and fall back to DESIGN_SKETCH.
|
|
412
412
|
4. If auth exists but API call fails → fall back to DESIGN_SKETCH (existing HTML wireframe approach). Design mockups are a progressive enhancement, never a hard requirement.
|
|
413
413
|
|
|
414
414
|
**New command:** `$D setup` — guided API key setup + smoke test. Can be run anytime to update the key.
|
|
@@ -429,11 +429,11 @@ const check = await openai.chat.completions.create({
|
|
|
429
429
|
- If no DESIGN.md (bootstrap), explore WIDE across diverse directions
|
|
430
430
|
- Progressive constraint: more established design = narrower exploration band
|
|
431
431
|
- Comparison board gets REGENERATE section with exploration controls:
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
432
|
+
- "Something totally different" (wide exploration)
|
|
433
|
+
- "More like option ___" (narrow around a favorite)
|
|
434
|
+
- "Match my existing design" (constrain to DESIGN.md)
|
|
435
|
+
- Free text input for specific direction changes
|
|
436
|
+
- Regenerate refreshes the page, agent polls for new submission
|
|
437
437
|
|
|
438
438
|
### 2. Mockup Diffing
|
|
439
439
|
- `$D diff --before old.png --after new.png` generates visual diff
|
|
@@ -490,7 +490,7 @@ const check = await openai.chat.completions.create({
|
|
|
490
490
|
The design binary is compiled and distributed alongside the browse binary:
|
|
491
491
|
- `bun build --compile design/src/cli.ts --outfile design/dist/design`
|
|
492
492
|
- Built during `./setup` and `bun run build`
|
|
493
|
-
- Symlinked via existing `~/.claude/skills/
|
|
493
|
+
- Symlinked via existing `~/.claude/skills/opengstack/` install path
|
|
494
494
|
|
|
495
495
|
## Next Steps (Implementation Order)
|
|
496
496
|
|
|
@@ -502,7 +502,7 @@ The design binary is compiled and distributed alongside the browse binary:
|
|
|
502
502
|
|
|
503
503
|
### Commit 1: Design binary core (generate + check + compare)
|
|
504
504
|
- `design/src/` with cli.ts, commands.ts, generate.ts, check.ts, brief.ts, session.ts, compare.ts
|
|
505
|
-
- Auth module (read ~/.
|
|
505
|
+
- Auth module (read ~/.opengstack/openai.json, fallback to env var, guided setup flow)
|
|
506
506
|
- `compare` command generates HTML comparison board with per-variant feedback textareas
|
|
507
507
|
- `package.json` build command (separate `bun build --compile` from browse)
|
|
508
508
|
- `setup` script integration (including Codex + Kiro asset linking)
|
|
@@ -518,7 +518,7 @@ The design binary is compiled and distributed alongside the browse binary:
|
|
|
518
518
|
- Add `generateDesignSetup()` + `generateDesignMockup()` to existing `scripts/resolvers/design.ts`
|
|
519
519
|
- Add `designDir` to `HostPaths` in `scripts/resolvers/types.ts`
|
|
520
520
|
- Register DESIGN_SETUP + DESIGN_MOCKUP in `scripts/resolvers/index.ts`
|
|
521
|
-
- Add
|
|
521
|
+
- Add OpenGStack_DESIGN env var export to `scripts/resolvers/preamble.ts` (Codex host)
|
|
522
522
|
- Update `test/gen-skill-docs.test.ts` (DESIGN_SKETCH test suite)
|
|
523
523
|
- Regenerate SKILL.md files
|
|
524
524
|
|
|
@@ -606,7 +606,7 @@ Issues fixed:
|
|
|
606
606
|
- Failure modes: 0 critical gaps (all identified failure modes have error handling + tests planned)
|
|
607
607
|
- Lake Score: 7/7 recommendations chose complete option
|
|
608
608
|
|
|
609
|
-
##
|
|
609
|
+
## opengstack REVIEW REPORT
|
|
610
610
|
|
|
611
611
|
| Review | Trigger | Why | Runs | Status | Findings |
|
|
612
612
|
|--------|---------|-----|------|--------|----------|
|