fix(ai): route workspace/console fallback prompts to desktop-screen, not landing-page

Why: Codex stop-time review #6 — C6 added workspace / console / 工作台 /
工作区 to the component DISQUALIFIER, but the dashboard detector regex
still only matched dashboard|admin|管理|后台|控制台. So "design a
workspace with side panel" skipped component (correct) AND skipped
dashboard (regex miss) and fell through to landing-page (1200×0,
4-section), which is the wrong shape for a workspace UI — the user
wants a 3-section desktop-screen with header/main/actions.

What: dashboard detector regex extended in lockstep with the
disqualifier — dashboard|admin|workspace|console|管理|后台|控制台|
工作台|工作区. Comment makes the "keep in sync" invariant explicit.

Tests: 4 new positive cases (Latin workspace + console, zh-Hans 工作台
+ 工作区 with 卡片) assert the plan returns 1200×800 with the 3-
section ['Header','Main Content','Actions'] layout, not the 4-section
landing-page default.

1066 / 1066 AI tests pass (was 1062; +4).
This commit is contained in:
Fini 2026-05-09 20:59:29 +08:00
parent ed54656b08
commit f34958544b
2 changed files with 29 additions and 3 deletions

View file

@ -208,6 +208,27 @@ describe('buildFallbackPlanFromPrompt', () => {
expect(plan.rootFrame.width).not.toBe(400);
});
// Codex review #6: keywords disqualifying a component fallback MUST
// also route the prompt to the right non-component preset. Otherwise
// "design a workspace with side panel" skipped component AND skipped
// dashboard (the regex only matched dashboard|admin|管理|后台|控制台)
// and fell through to landing-page (1200×0), which is the wrong shape
// for a workspace UI.
it.each([
['design a workspace with side panel and metrics'],
['design a console with charts and live metrics'],
['设计一个工作台 with charts'],
['设计一个工作区 with 卡片'],
])('classifies "%s" as desktop-screen (1200×800), not landing-page', (prompt) => {
const plan = buildFallbackPlanFromPrompt(prompt);
expect(plan.rootFrame.width).toBe(1200);
expect(plan.rootFrame.height).toBe(800); // desktop-screen preset has rootHeight=800
// 3 default sections (Header / Main Content / Actions) — not the
// 4 sections of landing-page (Header / Main / Supporting / Footer).
expect(plan.subtasks).toHaveLength(3);
expect(plan.subtasks.map((st) => st.label)).toEqual(['Header', 'Main Content', 'Actions']);
});
it('uses design.md background and style-guide name when designMd is present', () => {
const designMd: DesignMdSpec = {
raw: '# Test',

View file

@ -45,7 +45,7 @@ const COMPONENT_TRIGGER_CJK_RE = /(卡片|徽章|标签|按钮|开关|对话框|
// the prompt also names a tile/panel/chart/metric inside it
// ("admin dashboard with metric tiles" must not become a Type 0 tile).
const COMPONENT_DISQUALIFIER_RE =
/\b(screen|page|app|home|onboarding|flow|mobile|phone|ios|android|dashboard|admin|workspace|console)\b|网页|页面|屏幕|手机|移动端|管理|后台|控制台/i;
/\b(screen|page|app|home|onboarding|flow|mobile|phone|ios|android|dashboard|admin|workspace|console)\b|网页|页面|屏幕|手机|移动端|管理|后台|控制台|工作台|工作区/i;
/**
* Minimal fallback design type detection.
@ -87,8 +87,13 @@ export function detectDesignType(prompt: string): DesignTypePreset {
};
}
// Fixed-height desktop screens
if (/dashboard|admin|管理|后台|控制台/i.test(prompt)) {
// Fixed-height desktop screens. Keep in sync with the workspace markers
// in COMPONENT_DISQUALIFIER_RE — every keyword that disqualifies a
// component fallback for "workspace context" MUST also be detected here,
// otherwise the prompt skips component AND skips dashboard and falls
// through to landing-page (1200×0) which is wrong for "design a workspace
// with side panel" / "design a console with metrics" (Codex review #6).
if (/dashboard|admin|workspace|console|管理|后台|控制台|工作台|工作区/i.test(prompt)) {
return {
type: 'desktop-screen',
width: 1200,