Skip to content

Commit e9cc916

Browse files
committed
Ship chart/table modules and iframe editor upgrades
1 parent b092fcd commit e9cc916

36 files changed

Lines changed: 4302 additions & 935 deletions

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Claw Design
22
<img width="1774" height="887" alt="image" src="https://github.com/user-attachments/assets/ef455a0d-ec4c-4eeb-9c58-e1ea12abfa72" />
33

4-
Claw Design is a local-first AI presentation workbench with an Agent Bridge: a repo skill teaches your agent how to work, and a local bridge launches Studio in the browser so the result lands in a real editable 16:9 deck.
4+
Claw Design is a local-first, HTML-based AI presentation workbench with an Agent Bridge, letting you create Claude-level slide design with the coding agent you already use.
55

66
## What is Agent Bridge?
77

@@ -73,6 +73,7 @@ What this gives the agent:
7373

7474
- read source links first
7575
- shape a Studio-ready prompt
76+
- apply visual prompting for figure-led, chart-led, and matrix-first decks
7677
- launch Studio through the local bridge
7778
- open the result in your default browser
7879

server/src/lib/studio-engine/preflight.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,3 +331,50 @@ test("preflight parser synthesizes missing later page missions instead of reusin
331331
assert.notEqual(plan.pageMissions[0]?.title, plan.pageMissions[1]?.title);
332332
assert.equal(plan.pageMissions[1]?.missionScope, "page");
333333
});
334+
335+
test("explicit chart-heavy page plans keep distinct page missions after normalization", () => {
336+
const brief = `Create a 6-page English consulting-style data-story deck.
337+
Page 1: Executive headline and market shape.
338+
Page 2: Use a composite bar-and-line chart to compare regional AI infrastructure capex by region against utilization growth on a secondary axis.
339+
Page 3: Use a bubble chart to position major provider archetypes by scale, utilization, and margin quality.
340+
Page 4: Use a premium analytical data table to compare operators across capacity, power cost, gross margin, and deployment lead time.
341+
Page 5: Use a waterfall chart or economics bridge to explain how revenue converts into margin pressure through power, GPU depreciation, and networking cost.
342+
Page 6: Use a matrix-first recommendation page to show where investment should focus across regions and operating models.`;
343+
const summary = JSON.stringify({
344+
rawBrief: brief,
345+
subject: "Global AI infrastructure economics in 2026",
346+
deliverable: "6-page PPT",
347+
pageCount: 6,
348+
audienceOrQualityBar: "consulting-style data-story",
349+
coreTask: "Show consultant-grade data-storytelling.",
350+
evidencePolicy: {
351+
tier: "explicit assumption",
352+
summary: "Use internally consistent sample data.",
353+
lines: ["Do not present the scenario as a factual market report."],
354+
},
355+
pageMissions: [],
356+
visualThinking: {
357+
dominantVisualAnchor: "one dominant analytical object per page",
358+
readingPath: "headline to chart to compact annotation",
359+
regionStrategy: "one dominant chart field with minimal support",
360+
densityPosture: "low-to-medium",
361+
avoidPattern: "equal-weight card walls",
362+
},
363+
capabilityActivations: [],
364+
assumptionPolicy: ["Use illustrative numbers only."],
365+
});
366+
367+
const plan = parseStudioPreflightPlan({
368+
text: summary,
369+
brief,
370+
requestedPageCount: 6,
371+
});
372+
373+
assert.equal(plan.pageMissions.length, 6);
374+
assert.equal(plan.pageMissions[1]?.missionScope, "page");
375+
assert.equal(plan.pageMissions[4]?.missionScope, "page");
376+
assert.match(plan.pageMissions[1]?.mission ?? "", /regional ai infrastructure capex|utilization growth/i);
377+
assert.match(plan.pageMissions[4]?.mission ?? "", /margin pressure|gpu depreciation|networking cost/i);
378+
assert.notEqual(plan.pageMissions[1]?.mission, plan.pageMissions[4]?.mission);
379+
assert.notEqual(plan.pageMissions[1]?.headlineClaim, plan.pageMissions[4]?.headlineClaim);
380+
});

server/src/lib/studio-engine/preflight.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -442,11 +442,11 @@ function buildFallbackPageMission(args: {
442442
6,
443443
),
444444
mission: isLast
445-
? `Close the same ${subject} story without adding a new thesis.`
446-
: `Add one focused proof step for ${subject}.`,
445+
? `Close the ${subject} story with a distinct final synthesis step.`
446+
: `Develop proof step ${index - 1} for ${subject}.`,
447447
headlineClaim: isLast
448-
? `${subject} should close on the same through-line, not a new argument.`
449-
: `${subject} is best supported through one focused proof pattern per page.`,
448+
? `${subject} should end with a distinct closing synthesis instead of repeating an earlier proof page.`
449+
: `${subject} needs a distinct proof step on this page instead of reusing another page mission.`,
450450
supportPoints: ["Keep support short and subordinate.", "Do not split the page into equal-weight zones."],
451451
evidenceNotes:
452452
args.evidenceTier === "source-backed"
@@ -618,6 +618,7 @@ function buildMissionFromExplicitPageSegment(args: {
618618
evidenceTier: StudioEvidenceTier;
619619
}) {
620620
const structureCue = normalizeStructureCue(undefined, args.segment.text);
621+
const scopedSegmentSummary = clampText(args.segment.text, 140);
621622
const title = resolveExplicitMissionTitle({
622623
segment: args.segment.text,
623624
pageNumber: args.segment.pageNumber,
@@ -626,19 +627,19 @@ function buildMissionFromExplicitPageSegment(args: {
626627
});
627628
const mission =
628629
structureCue === "matrix" || structureCue === "quadrant"
629-
? `Frame ${args.subject || "the subject"} through one BCG-style 2x2 matrix.`
630+
? `Frame ${args.subject || "the subject"} through one BCG-style 2x2 matrix focused on ${scopedSegmentSummary}.`
630631
: structureCue === "chart"
631-
? `Explain ${args.subject || "the subject"} through one chart-led evidence view.`
632+
? `Explain ${args.subject || "the subject"} through one chart-led evidence view focused on ${scopedSegmentSummary}.`
632633
: /\b(?:3d|three-dimensional)\b/i.test(args.segment.text) || /(?:3D|||)/i.test(args.segment.text)
633-
? `Explain ${args.subject || "the subject"} through one 3D-model-centered page.`
634+
? `Explain ${args.subject || "the subject"} through one 3D-model-centered page focused on ${scopedSegmentSummary}.`
634635
: `Resolve page ${args.segment.pageNumber} around: ${clampText(args.segment.text, 140)}.`;
635636
const headlineClaim =
636637
structureCue === "matrix" || structureCue === "quadrant"
637-
? `${args.subject || "The subject"} should be positioned through one quadrant matrix before deeper explanation.`
638+
? `${args.subject || "The subject"} should be positioned through one quadrant matrix that specifically answers ${scopedSegmentSummary}.`
638639
: structureCue === "chart"
639-
? `${args.subject || "The subject"} is best supported through one chart-led proof pattern.`
640+
? `${args.subject || "The subject"} is best supported through one chart-led proof pattern that specifically answers ${scopedSegmentSummary}.`
640641
: /\b(?:3d|three-dimensional)\b/i.test(args.segment.text) || /(?:3D|||)/i.test(args.segment.text)
641-
? `${args.subject || "The subject"} is best explained through one dominant 3D product or system model.`
642+
? `${args.subject || "The subject"} is best explained through one dominant 3D product or system model focused on ${scopedSegmentSummary}.`
642643
: clampText(args.segment.text, 180);
643644

644645
return sanitizeMission(

skills/ppt-workbench-studio/SKILL.md

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ Use this skill when the current workspace is `ppt-workbench-studio`, or when the
1010
## What exists now
1111

1212
- **Prompt injection bridge**: `POST /api/studio/bridge/launch` creates a short-lived launch task and returns an `openUrl`.
13-
- **UI handoff path**: opening that `openUrl` in the user's default browser makes Studio consume the task, create a local project, and auto-start generation.
13+
- **UI handoff path**: opening that exact returned `openUrl` in the user's default browser makes Studio consume the task, create a local project, and auto-start generation.
1414
- **Headless fallback**: `/api/studio/generate-html` and `/api/studio/generate-html/stream` still exist for true headless use.
1515

1616
Because of that, URL or PDF tasks must be handled as:
1717

1818
1. the agent reads the source itself
1919
2. the agent writes a good Studio prompt
2020
3. the agent posts that prompt to the local bridge
21-
4. the agent opens the returned `openUrl` in the default browser
21+
4. the agent opens the returned `openUrl` exactly in the default browser
2222

2323
Do not treat URLs or PDFs as product-side attachments. The bridge is **prompt-only**, not source-grounded.
2424

@@ -30,11 +30,21 @@ Use this path by default whenever the goal is to generate in Studio and hand the
3030
2. Read the source and extract the facts, structure, and likely page split.
3131
3. Build a concise Studio-ready prompt.
3232
4. `POST` the prompt to `/api/studio/bridge/launch`.
33-
5. In the **same default browser profile**, open the returned `openUrl`.
34-
6. Stop as soon as the browser has opened the launch URL.
33+
5. Parse the returned `openUrl`.
34+
6. In the **same default browser profile**, open that exact `openUrl`.
35+
7. Do not replace it with the Studio homepage or a hand-written root URL.
36+
8. Stop as soon as the browser has opened the launch URL.
3537

3638
Do **not** keep waiting for `/projects/:id/edit`, review settle, or iframe readiness unless the user explicitly asks.
3739

40+
Opening `http://127.0.0.1:5174/` by itself is not enough. The bridge only works when the browser visits the specific returned launch URL, for example:
41+
42+
```bash
43+
open 'http://127.0.0.1:5174/?bridgeLaunch=<launch-id>'
44+
```
45+
46+
If you created a launch task but only opened the Studio homepage, assume the prompt was **not** injected.
47+
3848
Read `references/default-browser-flow.md` only when you need the exact stop point and browser expectations.
3949

4050
## Source reading rule
@@ -50,16 +60,54 @@ Do not dump the full article or PDF text into the prompt. The current engine res
5060

5161
## Prompt contract
5262

53-
Shape prompts around these five pieces:
63+
Shape prompts around these seven pieces:
5464

5565
- `Observed facts`
5666
- `Page plan`
57-
- `Layout/structure cue`
67+
- `Layout / structure cue`
68+
- `Visual thesis`
5869
- `Tone + density`
70+
- `Anti-patterns`
5971
- `Source constraint`
6072

6173
Read `references/prompt-shaping.md` when you need the detailed rules for what helps the engine and what only adds noise.
6274

75+
## Visual quality rule
76+
77+
The current Studio engine needs both a **content contract** and a **visual contract**.
78+
79+
- The content contract keeps the page factual and logically structured.
80+
- The visual contract decides whether the page feels designed or generic.
81+
- The preflight-aware budget decides whether that ambition survives without collapsing into overflow or clutter.
82+
83+
Default rule: each page should have **one visual thesis**.
84+
85+
That usually means:
86+
87+
- one dominant visual or structural idea
88+
- quiet secondary text
89+
- restrained annotation
90+
- strong hierarchy
91+
- not many equal-weight cards competing for attention
92+
93+
Prefer:
94+
95+
- `single dominant visual`
96+
- `figure-led`
97+
- `chart-led`
98+
- `matrix-first`
99+
- `timeline-led`
100+
- `hero + rail`
101+
102+
Avoid:
103+
104+
- equal-weight card walls
105+
- generic dashboard clutter
106+
- “beautiful” or “premium” with no structural cue
107+
- asking one page to carry several unrelated visual ideas
108+
109+
Read `references/visual-briefing.md` when you need the visual prompting rules, `references/data-story-patterns.md` when you need to map source material to an archetype, `references/premium-visual-cues.md` for effective visual language, and `references/preflight-aware-visual-budget.md` when you need to keep ambition inside the engine's fit limits.
110+
63111
## Meaningful prompt inputs
64112

65113
The current engine responds well to:
@@ -68,15 +116,17 @@ The current engine responds well to:
68116
- each page having a clear role
69117
- one main claim per page
70118
- structure cues like `chart`, `matrix`, `quadrant`, `figure`, `timeline`
119+
- one visual thesis per page
71120
- language and density posture
72121
- a clear instruction to stay inside the observed source facts
122+
- explicit anti-patterns like `not equal-weight cards` or `not dashboard clutter`
73123

74124
The current engine does **not** benefit much from:
75125

76126
- pasting the full article or PDF
77127
- repeating that the result should be editable
78128
- repeating iframe/export/tooling details
79-
- vague quality adjectives like “more premium” or “more top-tier
129+
- vague quality adjectives like `premium`, `top-tier`, `more advanced`
80130
- putting the AI's own operating steps into the brief
81131

82132
## Review and preflight reality
@@ -91,7 +141,14 @@ The review loop mainly cares about:
91141

92142
Pure semantic density by itself is only a `soft-warning`, not a hard repair trigger.
93143

94-
That means the best prompt is one that gives the model a clean page split and reasonable density budget up front.
144+
That means the best prompt is one that gives the model:
145+
146+
- a clean page split
147+
- a realistic visual budget
148+
- one dominant object per page where possible
149+
- concise labels and short titles
150+
151+
Read `references/preflight-aware-visual-budget.md` when you need the current budget logic.
95152

96153
## Product-intro default behavior
97154

@@ -100,6 +157,7 @@ When the user says something like “做个 PPT 来介绍我的产品” without
100157
- assume they mean the product represented by the current repo
101158
- infer the product story from `README.md` and, if needed, `docs/agent-playbook.md`
102159
- keep it concrete and product-led
160+
- default to one clear product claim, one workflow strip, and a few differentiated proof points
103161
- do not invent customers, traction, or fake metrics
104162

105163
## Default browser policy
@@ -116,7 +174,13 @@ Once generation has been triggered through the UI:
116174
- do not burn tokens watching review finish
117175
- do not continue into iframe manipulation by default
118176

119-
With the bridge path, opening `openUrl` is enough for Studio to start generation. The human is expected to take over from the browser after the launch URL is opened.
177+
With the bridge path, opening the exact returned `openUrl` is enough for Studio to start generation. The human is expected to take over from the browser after the launch URL is opened.
178+
179+
Be precise here:
180+
181+
- `POST /api/studio/bridge/launch` only creates the task
182+
- opening the exact returned `openUrl` is what consumes it
183+
- opening the root Studio page does not consume the task
120184

121185
## No-testing policy
122186

@@ -143,5 +207,9 @@ Even then:
143207

144208
- Read `README.md` in the workspace for product positioning.
145209
- Read `docs/agent-playbook.md` only when you need deeper Studio generation/review context.
146-
- Read `references/prompt-shaping.md` for the effective prompt contract.
210+
- Read `references/prompt-shaping.md` for the full 7-part prompt contract.
147211
- Read `references/default-browser-flow.md` for the exact browser-first workflow and stop point.
212+
- Read `references/visual-briefing.md` for the visual contract.
213+
- Read `references/data-story-patterns.md` for content-to-layout mapping.
214+
- Read `references/premium-visual-cues.md` for effective visual phrasing.
215+
- Read `references/preflight-aware-visual-budget.md` for fit-aware visual budgeting.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
interface:
22
display_name: "PPT Workbench Studio"
3-
short_description: "Read the source first, bridge the prompt into Studio, open the launch URL in the default browser, then stop"
4-
default_prompt: "Use $ppt-workbench-studio to read source links first in the user's default browser, synthesize a concise Studio prompt, call /api/studio/bridge/launch, open the returned launch URL in the same browser profile, and stop once the browser has opened that URL."
3+
short_description: "Read the source first, shape a visually strong Studio prompt, bridge it into Studio, open the exact returned launch URL in the default browser, then stop"
4+
default_prompt: "Use $ppt-workbench-studio to read source links first in the user's default browser, synthesize a concise Studio prompt with one visual thesis per page, prefer current Studio cues such as figure-led, chart-led, matrix-first, or hero + rail layouts where appropriate, avoid equal-weight card walls and dashboard clutter, call /api/studio/bridge/launch, parse the returned openUrl, open that exact launch URL in the same browser profile instead of the Studio homepage, and stop once the browser has opened that URL."

0 commit comments

Comments
 (0)