Planning Phase 15 - huqianghui/AI-Coach-vibe-coding GitHub Wiki

Phase 15: Hcp Editor Agent Config Center

Auto-generated from .planning/phases/15-hcp-editor-agent-config-center
Last synced: 2026-04-28

Context & Decisions

Phase 15: HCP Editor Agent Config Center - Context

Gathered: 2026-04-07 Status: Ready for planning Source: PRD Express Path (/Users/huqianghui/.claude/plans/deep-foraging-hammock.md)

## Phase Boundary

重构 HCP 编辑器页面为 Agent 配置中心,对齐 Azure AI Foundry Agent 编辑体验:

  1. 移除空 Knowledge 和 Tools tab(Phase 14-03 添加的占位符)
  2. Voice & Avatar tab 升级为完整 Agent 配置中心布局
  3. 左侧面板:Model Deployment + Voice Mode 开关 + Instructions + Knowledge & Tools 配置
  4. 右侧面板:Playground 预览(数字人/音波球 + Start 测试 + Transcript)

前提:Phase 14 已完成 VL Instance CRUD、HCP Voice Tab 只读预览、unassign endpoint 等基础设施。

## Implementation Decisions

Tab 结构调整

  • 移除 Knowledge 和 Tools 两个空 tab(从 hcp-profile-editor.tsx 删除 tab trigger + content)
  • 保留 Profile tab(HCP 基本信息)
  • Voice & Avatar tab 重构为 Agent 配置中心

Voice & Avatar tab 左侧面板

  • Model Deployment 选择器: 下拉 + 自定义输入(类似 Azure Foundry 截图 Image #3 gpt-5.4-mini 风格)
  • Voice Mode 开关: "Switch the agent to a voice-first experience"
    • 开启时显示 VL Instance 选择器(复用已有 hooks)
    • 关闭时隐藏 voice 配置
  • Instructions 区域:
    • 自动生成的 instructions(基于 profile 数据调用 build_agent_instructions)
    • 可编辑 override(agent_instructions_override 字段)
    • 魔法棒按钮重新生成
  • Knowledge & Tools 配置:
    • Knowledge: 文件上传 / 知识库配置(内联在 tab 中,不是独立 tab)
    • Tools: 工具配置(内联在 tab 中,不是独立 tab)

Voice & Avatar tab 右侧面板(Playground)

  • 根据 avatar_enabled 显示数字人形象或音波球
  • Start 测试按钮(复用 VL Instance Editor 的测试逻辑)
  • 对话 transcript 区域

Backend: agent_instructions_override 数据流修复

  • to_prompt_dict() 需要包含 agent_instructions_override
  • 确保 build_agent_instructions 正确读取 override
  • 新增 GET endpoint 获取 auto-generated instructions preview

i18n

  • 添加 model deployment、voice mode 开关、instructions 等新 keys
  • 中英文双语(en-US + zh-CN)

Claude's Discretion

  • Knowledge & Tools 内联区域的具体 UI 组件实现细节
  • Playground 预览面板的音波球动画效果
  • Instructions 自动生成的 API 调用时机(实时 vs 按需)

<canonical_refs>

Canonical References

Downstream agents MUST read these before planning or implementing.

前端 — HCP 编辑器(主要重构目标)

  • frontend/src/pages/admin/hcp-profile-editor.tsx — 主编辑页面(572行,当前 4 tab)
  • frontend/src/components/admin/voice-avatar-tab.tsx — 当前 Voice & Avatar tab(Phase 14 已简化为只读预览)
  • frontend/src/components/admin/agent-status-section.tsx — Agent 状态显示

前端 — 类型和 Hooks

  • frontend/src/types/hcp.ts — HCP TypeScript 类型定义
  • frontend/src/hooks/use-hcp-profiles.ts — HCP Query hooks
  • frontend/src/hooks/use-voice-live.ts — Voice Live WebSocket hook
  • frontend/src/hooks/use-voice-live-instances.ts — VL Instance CRUD hooks

后端 — Agent Instructions

  • backend/app/services/agent_sync_service.py — build_agent_instructions()
  • backend/app/models/hcp_profile.py — HCP ORM 模型(含 agent_instructions_override)
  • backend/app/schemas/hcp_profile.py — Pydantic schemas
  • backend/app/services/voice_live_websocket.py — WebSocket 代理

i18n

  • frontend/public/locales/en-US/admin.json
  • frontend/public/locales/zh-CN/admin.json

参考截图(用户提供)

  • Image #3: Model deployment 选择器(gpt-5.4-mini)
  • Image #4: Instructions 区域(自动生成 + 可编辑)
  • Image #5: 数字人形象 + Start 测试按钮(Azure Foundry 风格)

</canonical_refs>

## Specific Ideas
  1. 对齐 Azure AI Foundry Agent 编辑体验 — Model Deployment + Instructions + Playground 三栏布局
  2. Voice Mode 开关模式 — 参考 Azure Foundry "Switch to voice-first experience" toggle
  3. Instructions 魔法棒 — 调用 build_agent_instructions 实时预览 auto-generated instructions
  4. Knowledge & Tools 内联 — 不作为独立 tab,而是 Voice & Avatar tab 内的折叠区域
## Deferred Ideas
  • Knowledge 区域的完整文件上传功能(可先做 UI 框架,后端集成后续 phase)
  • Tools 区域的完整 Function Call 配置(可先做 UI 框架)
  • Playground 的完整实时对话功能(先做 UI 结构 + Start 按钮)

Phase: 15-hcp-editor-agent-config-center Context gathered: 2026-04-07 via PRD Express Path

Plans (3)

# Plan File Status
15-01 15-01-PLAN.md Complete
15-02 15-02-PLAN.md Complete
15-03 15-03-PLAN.md Complete

Research

Click to expand research notes

Phase 15: HCP Editor Agent Config Center - Research

Researched: 2026-04-07 Domain: React frontend refactoring + FastAPI backend endpoint + i18n Confidence: HIGH

Summary

Phase 15 is a frontend-heavy refactoring phase that transforms the HCP Profile Editor's tab structure to align with Azure AI Foundry's Agent editing experience. The core work involves: (1) removing two placeholder tabs (Knowledge, Tools), (2) rebuilding the Voice & Avatar tab as a two-panel Agent configuration center with left-side controls and right-side Playground preview, and (3) adding a new backend endpoint to preview auto-generated instructions.

The codebase already has nearly all building blocks in place. The VL Instance Editor page (vl-instance-editor.tsx) implements a nearly identical Playground pattern with AvatarView, AudioOrb, useVoiceLive, useAvatarStream, useAudioHandler, and transcript display. The VoiceLiveModelSelect component provides tiered model selection. The build_agent_instructions function in agent_sync_service.py handles instruction generation with override priority. The only net-new backend work is a preview endpoint that calls build_agent_instructions with profile form data and returns the generated text.

Primary recommendation: Extract the Playground preview panel from vl-instance-editor.tsx into a reusable component, then compose the new Voice & Avatar tab as a left-right split layout importing existing components (VoiceLiveModelSelect, VL Instance selector, Instructions textarea, and the new Playground panel).

<user_constraints>

User Constraints (from CONTEXT.md)

Locked Decisions

  • Tab structure: remove Knowledge and Tools tabs, keep Profile and Voice & Avatar only
  • Voice & Avatar tab left panel: Model Deployment selector, Voice Mode toggle + VL Instance selector, Instructions area (auto-generate + editable override), Knowledge & Tools inline config
  • Voice & Avatar tab right panel: Playground preview (avatar/audio orb + Start button + transcript)
  • Backend: to_prompt_dict() must include agent_instructions_override; new GET endpoint for instructions preview
  • i18n: new keys for model deployment, voice mode toggle, instructions area (en-US + zh-CN)

Claude's Discretion

  • Knowledge & Tools inline section UI component details
  • Playground audio orb animation effect
  • Instructions auto-generation API call timing (realtime vs on-demand)

Deferred Ideas (OUT OF SCOPE)

  • Knowledge area full file upload functionality (UI skeleton only, backend integration later)
  • Tools area full Function Call configuration (UI skeleton only)
  • Playground full real-time conversation functionality (UI structure + Start button first) </user_constraints>

<phase_requirements>

Phase Requirements

ID Description Research Support
HCP-15-01 HCP editor has only Profile and Voice & Avatar tabs (Knowledge/Tools removed) Direct code change in hcp-profile-editor.tsx lines 285-554 -- remove 2 TabsTrigger + 2 TabsContent blocks and unused imports
HCP-15-02 Voice & Avatar tab left panel: Model Deployment + Voice Mode toggle + VL Instance + Instructions Reuse VoiceLiveModelSelect, existing VL Instance assign/unassign hooks, existing agent_instructions_override form field; new preview endpoint
HCP-15-03 Voice & Avatar tab right panel: Playground preview with avatar/orb + Start + transcript Extract from vl-instance-editor.tsx (lines 248-367) -- AvatarView, AudioOrb, useVoiceLive, useAvatarStream, useAudioHandler already exist
HCP-15-04 Instructions magic wand button calls build_agent_instructions to regenerate New backend POST /{profile_id}/preview-instructions endpoint calling build_agent_instructions; frontend hook + button
HCP-15-05 Tests + i18n (en-US + zh-CN) + TypeScript compilation passes Follow existing test patterns; add i18n keys to both locale files
</phase_requirements>

Standard Stack

Core (already installed -- no new packages needed)

Library Version Purpose Why Standard
React 18.3+ UI framework Project standard [VERIFIED: codebase]
react-hook-form existing Form state management Used across all admin forms [VERIFIED: codebase]
zod existing Schema validation Used with zodResolver in HCP editor [VERIFIED: codebase]
@tanstack/react-query ^5.60 Server state + mutations Project standard [VERIFIED: codebase]
react-i18next existing i18n framework Project standard since Phase 1 [VERIFIED: codebase]
lucide-react ^0.460 Icons (Wand2, Play, etc.) Project icon library [VERIFIED: codebase]
FastAPI >=0.115 Backend API Project standard [VERIFIED: codebase]

Supporting (reusable existing components)

Component Location Purpose Reuse Strategy
VoiceLiveModelSelect components/admin/voice-live-model-select.tsx Tiered model dropdown Import directly
AudioOrb components/voice/audio-orb.tsx Voice-only animation Import directly
AvatarView components/voice/avatar-view.tsx Avatar video + fallback Import directly
useVoiceLive hooks/use-voice-live.ts WebSocket proxy hook Import directly
useAvatarStream hooks/use-avatar-stream.ts WebRTC avatar stream Import directly
useAudioHandler hooks/use-audio-handler.ts Mic input capture Import directly
useAudioPlayer hooks/use-audio-player.ts Audio playback Import directly
VoiceControls components/voice/voice-controls.tsx Mute/disconnect buttons Import directly
useVoiceLiveInstances hooks/use-voice-live-instances.ts VL Instance CRUD hooks Import directly
AVATAR_CHARACTER_MAP data/avatar-characters.ts Avatar metadata Import directly

Installation: No new packages required. This phase only uses existing dependencies. [VERIFIED: codebase analysis]

Architecture Patterns

Recommended Component Structure

frontend/src/
├── pages/admin/
│   └── hcp-profile-editor.tsx       # Modified: remove Knowledge/Tools tabs
├── components/admin/
│   ├── voice-avatar-tab.tsx          # REWRITE: 2-panel agent config center
│   ├── agent-config-left-panel.tsx   # NEW: left panel (model, voice mode, instructions)
│   ├── playground-preview-panel.tsx  # NEW: right panel (avatar/orb + start + transcript)
│   └── instructions-section.tsx      # NEW: auto-gen + override + magic wand
├── hooks/
│   └── use-hcp-profiles.ts           # Modified: add usePreviewInstructions hook
└── api/
    └── hcp-profiles.ts               # Modified: add previewInstructions API call

Pattern 1: Two-Panel Split Layout

What: Voice & Avatar tab uses CSS Grid with grid-cols-1 lg:grid-cols-2 for responsive left-right split. When to use: Admin editor pages that need both configuration controls and live preview. Example:

// Source: existing pattern from vl-instance-editor.tsx
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
  <div className="space-y-4"> {/* Left: Config controls */}
    <AgentConfigLeftPanel />
  </div>
  <div className="sticky top-4"> {/* Right: Playground preview */}
    <PlaygroundPreviewPanel />
  </div>
</div>

Pattern 2: Instructions Auto-Generate with Override

What: Display auto-generated instructions text, allow user to type an override, provide magic wand button to re-generate. When to use: When system prompt is derived from structured data but users may want customization. Backend flow:

# Source: agent_sync_service.py build_agent_instructions() [VERIFIED: codebase]
# 1. If agent_instructions_override is non-empty -> return override
# 2. Otherwise -> format DEFAULT_AGENT_TEMPLATE with profile data

Frontend flow:

  1. On tab load, call GET /api/v1/hcp-profiles/{id}/preview-instructions to get auto-generated text
  2. Show in read-only textarea (collapsed/dimmed when override is active)
  3. Override textarea bound to agent_instructions_override form field
  4. Magic wand button: re-call preview endpoint, show result in auto-gen area

Pattern 3: Playground Panel Extraction

What: Extract test session logic from vl-instance-editor.tsx into a reusable Playground component. Why: The VL Instance Editor page (lines 248-367) already implements the complete pattern: useVoiceLive + useAvatarStream + useAudioHandler + transcript accumulation + start/stop logic. The HCP editor needs the exact same functionality. Interface:

interface PlaygroundPreviewPanelProps {
  hcpProfileId?: string;
  vlInstanceId?: string;
  systemPrompt?: string;
  avatarCharacter?: string;
  avatarStyle?: string;
  avatarEnabled: boolean;
  disabled?: boolean;  // true for new profiles (no id yet)
}

Anti-Patterns to Avoid

  • Duplicating Playground code: Do NOT copy-paste the test session logic from vl-instance-editor.tsx. Extract into a shared component.
  • Inlining useQuery in components: Follow project convention -- all queries go through hooks in hooks/ directory. [VERIFIED: CLAUDE.md rule]
  • Static route ordering violation: Any new endpoint added to hcp_profiles.py must come BEFORE /{profile_id} routes. Add preview-instructions route after batch-sync but before /{profile_id}. [VERIFIED: CLAUDE.md Gotcha #3]

Don't Hand-Roll

Problem Don't Build Use Instead Why
Model tier dropdown Custom select with tiers VoiceLiveModelSelect component Already groups models by Pro/Standard/Lite tiers with i18n [VERIFIED: codebase]
Audio visualization CSS animation from scratch AudioOrb component Already matches AI Foundry style with listening/speaking states [VERIFIED: codebase]
Avatar preview Manual video element management AvatarView component Handles WebRTC video, static thumbnail fallback, AudioOrb fallback [VERIFIED: codebase]
Voice Live WebSocket Raw WebSocket code useVoiceLive hook Complete proxy flow with reconnect, transcript, audio delta [VERIFIED: codebase]
VL Instance assignment Custom mutation logic useAssignVoiceLiveInstance / useUnassignVoiceLiveInstance hooks Already handle cache invalidation for both VL and HCP query keys [VERIFIED: codebase]
Instructions generation Frontend string templating Backend build_agent_instructions() Server-side generation ensures consistency with agent sync [VERIFIED: codebase]

Key insight: This phase is primarily a UI restructuring and composition phase. Nearly every functional building block already exists in the codebase. The risk is in duplicating rather than reusing existing components.

Common Pitfalls

Pitfall 1: to_prompt_dict() Missing agent_instructions_override

What goes wrong: The CONTEXT.md explicitly calls out that to_prompt_dict() needs to include agent_instructions_override. Currently it does NOT (verified in hcp_profile.py lines 84-100). Why it happens: to_prompt_dict() was originally designed for system prompt construction and predates the override field. How to avoid: Add agent_instructions_override to the return dict in to_prompt_dict(). The build_agent_instructions function already checks for it (line 62-63 of agent_sync_service.py). Warning signs: Instructions preview always returns template-generated text, never the override.

Pitfall 2: Static Route Ordering in hcp_profiles.py

What goes wrong: New route /{profile_id}/preview-instructions added after /{profile_id} gets shadowed by the /{profile_id} route. Why it happens: FastAPI matches the first route that fits the pattern. How to avoid: Place the new endpoint after batch-sync (line 161) but before /{profile_id} (line 120). Better yet, use a path like POST /{profile_id}/preview-instructions which won't conflict because it uses POST and has a sub-path. Warning signs: 404 or wrong handler executing.

Pitfall 3: Form State Persistence Across Tabs

What goes wrong: Switching between Profile and Voice & Avatar tabs loses form state. Why it happens: If Form wrapper doesn't encompass both tabs. How to avoid: The current architecture already wraps <Form {...form}> around <Tabs> (line 276 of hcp-profile-editor.tsx). This pattern MUST be preserved. [VERIFIED: codebase decision from Phase 12] Warning signs: Data entered in one tab disappears when switching.

Pitfall 4: Playground Connecting Without Saved Profile

What goes wrong: Clicking Start on a new (unsaved) profile attempts WebSocket connection with no profile ID. Why it happens: New profiles have isNew=true and no database ID. How to avoid: Disable the Start button when isNew is true. Show helper text: "Save profile first to test." Warning signs: WebSocket errors or empty sessions.

Pitfall 5: Knowledge & Tools Inline Sections Scope Creep

What goes wrong: Building full file upload / function call UI instead of placeholder skeleton. Why it happens: The CONTEXT.md's decision section mentions Knowledge & Tools inline config, but the Deferred section explicitly marks full functionality as out of scope. How to avoid: Build collapsible sections with descriptive placeholder content only. No actual upload/API integration. Warning signs: Sprint overrun, blocked on unbuilt backend features.

Pitfall 6: Unused Imports After Tab Removal

What goes wrong: TypeScript compilation fails due to unused imports (BookOpen, Wrench) after removing Knowledge/Tools tabs. Why it happens: Tab placeholder components imported icons that are no longer needed. How to avoid: Clean up imports when removing tab content. npx tsc -b will catch these. [VERIFIED: CLAUDE.md pre-commit checklist] Warning signs: Build failures in CI.

Code Examples

Backend: Instructions Preview Endpoint

# Source: pattern derived from agent_sync_service.build_agent_instructions [VERIFIED: codebase]
# Place AFTER /batch-sync but BEFORE /{profile_id} routes

class InstructionsPreviewRequest(BaseModel):
    """Profile data for instructions generation preview."""
    name: str = ""
    specialty: str = ""
    hospital: str = ""
    title: str = ""
    personality_type: str = "friendly"
    emotional_state: int = 50
    communication_style: int = 50
    expertise_areas: list[str] = []
    prescribing_habits: str = ""
    concerns: str = ""
    objections: list[str] = []
    probe_topics: list[str] = []
    difficulty: str = "medium"
    agent_instructions_override: str = ""

class InstructionsPreviewResponse(BaseModel):
    """Generated instructions text."""
    instructions: str
    is_override: bool

@router.post("/preview-instructions", response_model=InstructionsPreviewResponse)
async def preview_instructions(
    body: InstructionsPreviewRequest,
    user: User = Depends(require_role("admin")),
):
    """Preview auto-generated agent instructions from profile data. Admin only."""
    from app.services.agent_sync_service import build_agent_instructions
    profile_data = body.model_dump()
    instructions = build_agent_instructions(profile_data)
    is_override = bool(body.agent_instructions_override and body.agent_instructions_override.strip())
    return InstructionsPreviewResponse(instructions=instructions, is_override=is_override)

Frontend: Voice & Avatar Tab Layout

// Source: composition pattern from vl-instance-editor.tsx [VERIFIED: codebase]
export function VoiceAvatarTab({ form, profile, isNew }: VoiceAvatarTabProps) {
  return (
    <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
      {/* Left Panel: Configuration */}
      <div className="space-y-4">
        <AgentConfigLeftPanel form={form} profile={profile} isNew={isNew} />
      </div>
      {/* Right Panel: Playground Preview */}
      <div>
        <PlaygroundPreviewPanel
          hcpProfileId={profile?.id}
          vlInstanceId={form.watch("voice_live_instance_id") ?? undefined}
          systemPrompt={form.watch("agent_instructions_override") ?? ""}
          avatarCharacter={form.watch("avatar_character")}
          avatarStyle={form.watch("avatar_style")}
          avatarEnabled={!!form.watch("avatar_character")}
          disabled={isNew}
        />
      </div>
    </div>
  );
}

Frontend: Instructions Section with Magic Wand

// Source: pattern derived from existing form fields + new preview hook [VERIFIED: codebase]
import { Wand2 } from "lucide-react";

function InstructionsSection({ form, profileId }: { form: UseFormReturn<HcpFormValues>; profileId?: string }) {
  const { t } = useTranslation("admin");
  const [autoInstructions, setAutoInstructions] = useState("");
  const [isGenerating, setIsGenerating] = useState(false);

  const handleGenerate = async () => {
    setIsGenerating(true);
    try {
      const formValues = form.getValues();
      const result = await previewInstructions(formValues);
      setAutoInstructions(result.instructions);
    } finally {
      setIsGenerating(false);
    }
  };

  return (
    <Card>
      <CardHeader>
        <div className="flex items-center justify-between">
          <CardTitle className="text-sm">{t("admin:hcp.autoInstructions")}</CardTitle>
          <Button variant="ghost" size="sm" onClick={handleGenerate} disabled={isGenerating}>
            <Wand2 className="size-4 mr-1" />
            {isGenerating ? "..." : t("common:generate")}
          </Button>
        </div>
      </CardHeader>
      <CardContent className="space-y-3">
        {autoInstructions && (
          <pre className="text-xs bg-muted/50 rounded p-3 max-h-48 overflow-y-auto whitespace-pre-wrap">
            {autoInstructions}
          </pre>
        )}
        <FormField
          control={form.control}
          name="agent_instructions_override"
          render={({ field }) => (
            <FormItem>
              <FormLabel>{t("admin:hcp.overrideInstructions")}</FormLabel>
              <FormControl>
                <Textarea rows={4} placeholder={t("admin:hcp.overridePlaceholder")} {...field} />
              </FormControl>
            </FormItem>
          )}
        />
      </CardContent>
    </Card>
  );
}

State of the Art

Old Approach Current Approach When Changed Impact
4 tabs (Profile, Voice & Avatar, Knowledge, Tools) 2 tabs (Profile, Agent Config Center) Phase 15 Knowledge/Tools become inline sections in Voice & Avatar
Voice & Avatar tab = read-only VL preview (303 lines) Voice & Avatar tab = full Agent config center (left+right panels) Phase 15 Major rewrite of voice-avatar-tab.tsx
No instructions preview API POST /preview-instructions endpoint Phase 15 Enables magic wand button for instruction regeneration
to_prompt_dict() excludes override to_prompt_dict() includes agent_instructions_override Phase 15 Fixes data flow for instruction preview

Deprecated/outdated:

  • Knowledge tab placeholder (added Phase 14-03, removed Phase 15)
  • Tools tab placeholder (added Phase 14-03, removed Phase 15)

Assumptions Log

# Claim Section Risk if Wrong
A1 Wand2 icon exists in lucide-react ^0.460 for the magic wand button Code Examples LOW -- fallback to Sparkles or RefreshCw icon if not available
A2 POST method for preview-instructions won't conflict with existing route patterns Architecture LOW -- POST to a static path before /{profile_id} is unambiguous
A3 Knowledge & Tools inline sections should be collapsible Card components with placeholder content Architecture LOW -- CONTEXT.md says "inline in tab, not independent tab"; UI details are Claude's Discretion

Open Questions

  1. Instructions generation timing

    • What we know: The magic wand button calls backend on-demand (CONTEXT.md: Claude's Discretion area)
    • What's unclear: Should auto-generated instructions load automatically when tab opens (initial load), or only when user clicks the wand?
    • Recommendation: Load on tab mount for existing profiles (cheap GET call), require explicit click for new profiles. This provides immediate feedback while keeping UX responsive.
  2. Playground test scope

    • What we know: CONTEXT.md says "Start test button (reuse VL Instance Editor test logic)" and Deferred says "full real-time conversation first phase = UI structure + Start button"
    • What's unclear: Should the Start button actually connect to Voice Live (full test), or just show UI skeleton?
    • Recommendation: Implement full Start/Stop functionality by extracting from vl-instance-editor.tsx. The hooks already exist and the code is proven. Only defer if Azure credentials are not configured (show appropriate message).
  3. Playground preview for new profiles

    • What we know: New profiles have no ID, can't test
    • What's unclear: Should we show a static avatar preview image even without a live connection?
    • Recommendation: Show static avatar thumbnail based on selected avatar_character + avatar_style from form state, with disabled Start button and helper text.

Environment Availability

Step 2.6: SKIPPED (no external dependencies identified -- this phase is code/config changes only using existing project dependencies).

Security Domain

Applicable ASVS Categories

ASVS Category Applies Standard Control
V2 Authentication no --
V3 Session Management no --
V4 Access Control yes require_role("admin") on new endpoint [VERIFIED: all HCP endpoints use this]
V5 Input Validation yes Pydantic schema validation on preview request body [VERIFIED: existing pattern]
V6 Cryptography no --

Known Threat Patterns

Pattern STRIDE Standard Mitigation
Unauthorized instructions preview Elevation of Privilege require_role("admin") dependency [VERIFIED: codebase]
XSS via instructions override text Tampering React auto-escapes JSX; Textarea value is text-only [VERIFIED: React default]

Sources

Primary (HIGH confidence)

  • Codebase analysis of all files listed in CONTEXT.md canonical_refs -- verified current state of every component
  • hcp-profile-editor.tsx (572 lines) -- current 4-tab structure, Form wrapping Tabs
  • voice-avatar-tab.tsx (307 lines) -- current read-only VL preview, will be rewritten
  • vl-instance-editor.tsx (~700+ lines) -- Playground test pattern to extract
  • agent_sync_service.py (565 lines) -- build_agent_instructions function
  • hcp_profile.py (100 lines) -- to_prompt_dict() missing override field
  • hcp_profiles.py API router -- route ordering, existing endpoints

Secondary (MEDIUM confidence)

  • Project STATE.md accumulated decisions -- confirmed Form-wraps-Tabs pattern (Phase 12), VoiceAvatarTab rewrite (Phase 14)

Metadata

Confidence breakdown:

  • Standard stack: HIGH - all components already exist in codebase, no new dependencies
  • Architecture: HIGH - pattern directly extracted from existing vl-instance-editor.tsx
  • Pitfalls: HIGH - identified from concrete codebase analysis (route ordering, form state, missing field)

Research date: 2026-04-07 Valid until: 2026-05-07 (stable -- internal refactoring phase, no external API changes)

UI Specification

Click to expand UI spec

Phase 15 — UI Design Contract

Visual and interaction contract for the HCP Editor Agent Config Center phase. Generated by gsd-ui-researcher, verified by gsd-ui-checker.


Design System

Property Value
Tool none (Radix UI wrappers, no shadcn CLI)
Preset not applicable
Component library Radix UI (via existing components/ui/ wrappers)
Icon library lucide-react ^0.460
Font Inter + Noto Sans SC (sans), JetBrains Mono (mono)

Source: Pre-populated from codebase analysis (frontend/src/styles/index.css, frontend/src/components/ui/). Project has been using this stack since Phase 01.


Spacing Scale

Declared values (must be multiples of 4):

Token Value Usage
xs 4px Icon-to-label gap inside buttons, inline icon padding
sm 8px Compact element spacing within form groups, badge padding
md 16px Default gap between form fields, card internal padding
lg 24px Gap between left/right panels, section spacing within panels
xl 32px Top-level tab content margin, page header padding
2xl 48px Empty state vertical padding (Knowledge/Tools placeholder area)
3xl 64px Not used in this phase

Exceptions:

  • Playground preview panel avatar/orb container uses 240px min-height (fixed to match VL Instance Editor pattern in vl-instance-editor.tsx)
  • Touch target for Start/Stop test button: 44px height minimum (accessibility)

Typography

Role Size Weight Line Height Usage in This Phase
Body 16px (--text-base) 400 (--font-weight-normal) 1.5 Form field values, transcript text, instructions body
Label 14px (--text-sm) 500 (--font-weight-medium) 1.5 Form labels, section headers, card titles
Heading 18px (--text-lg) 500 (--font-weight-medium) 1.5 Tab names, panel titles ("Agent Configuration", "Playground")
Code 12px (--text-xs) 400 (--font-weight-normal) 1.5 Auto-generated instructions preview (monospace --font-mono)

Source: Pre-populated from frontend/src/styles/index.css base layer rules (lines 252-297). Matches project-wide typography contract established in Phase 01.


Color

Role Value Usage
Dominant (60%) var(--background) / #FFFFFF Page background, tab content area, form field backgrounds
Secondary (30%) var(--card) / #FFFFFF with var(--border) Card surfaces for left panel sections, right panel playground container
Accent (10%) var(--primary) / #1E40AF See reserved list below
Destructive var(--destructive) / #EF4444 Disconnect/stop test button when active
Muted var(--muted) / #F9FAFB Auto-generated instructions preview background, disabled form fields
Voice Listening var(--voice-listening) / #A855F7 AudioOrb ring when recording mic input
Voice Speaking var(--voice-speaking) / #22C55E AudioOrb ring when AI is speaking

Accent reserved for:

  1. "Save" button (primary CTA)
  2. "Start" test button in Playground panel
  3. Voice Mode toggle switch when enabled (on state)
  4. Magic wand (regenerate instructions) button icon on hover
  5. Active tab indicator underline
  6. VL Instance link badge when connected

Component Inventory

New Components (to be created)

Component File Description
AgentConfigLeftPanel components/admin/agent-config-left-panel.tsx Left panel container: Model Deployment + Voice Mode + Instructions + Knowledge/Tools inline
PlaygroundPreviewPanel components/admin/playground-preview-panel.tsx Right panel: avatar/orb display + Start/Stop + transcript
InstructionsSection components/admin/instructions-section.tsx Auto-generated preview + editable override + magic wand button

Modified Components

Component File Changes
VoiceAvatarTab components/admin/voice-avatar-tab.tsx Full rewrite: 2-panel grid layout (left config, right playground)
hcp-profile-editor pages/admin/hcp-profile-editor.tsx Remove Knowledge/Tools tabs (2 TabsTrigger + 2 TabsContent), remove unused imports (BookOpen, Wrench)

Reused Components (no changes)

Component Source Used For
VoiceLiveModelSelect components/admin/voice-live-model-select.tsx Model Deployment dropdown with tiered groups
AudioOrb components/voice/audio-orb.tsx Voice-only animation in Playground
AvatarView components/voice/avatar-view.tsx Digital human video + fallback in Playground
VoiceControls components/voice/voice-controls.tsx Mute/disconnect in Playground test session
Switch components/ui/switch.tsx Voice Mode on/off toggle
Card/CardHeader/CardContent/CardTitle components/ui/card.tsx Section containers in left panel
Textarea components/ui/textarea.tsx Instructions override editor
Button components/ui/button.tsx Magic wand, Start/Stop, Save
Select components/ui/select.tsx VL Instance selector dropdown
Badge components/ui/badge.tsx VL Instance connection status
Separator components/ui/separator.tsx Section dividers in left panel

Layout Contract

Voice & Avatar Tab: Two-Panel Split

+------------------------------------------------------------------+
| [Profile Tab]  [Voice & Avatar Tab (active)]                     |
+------------------------------------------------------------------+
| LEFT PANEL (config)          | RIGHT PANEL (playground)          |
| 50% width on lg+             | 50% width on lg+                 |
| 100% width on mobile         | 100% width on mobile (stacks)    |
|                              |                                   |
| +-- Model Deployment ------+ | +-- Playground ----------------+ |
| | [tiered model dropdown]  | | |                               | |
| +--------------------------+ | |  [AvatarView or AudioOrb]     | |
|                              | |   240px min-height             | |
| +-- Voice Mode ------------+ | |                               | |
| | [toggle switch]           | | |  [Start / Stop button]       | |
| | [VL Instance selector]   | | |                               | |
| | (visible when enabled)    | | |  +-- Transcript -----------+ | |
| +--------------------------+ | |  | [scrollable chat log]    | | |
|                              | |  | 200px max-height         | | |
| +-- Instructions ----------+ | |  +--------------------------+ | |
| | [auto-gen preview (ro)]  | | +-------------------------------+ |
| | [magic wand button]      | |                                   |
| | [override textarea]      | |                                   |
| +--------------------------+ |                                   |
|                              |                                   |
| +-- Knowledge & Tools -----+ |                                   |
| | [collapsible section]     | |                                   |
| | [placeholder content]     | |                                   |
| +--------------------------+ |                                   |
+------------------------------------------------------------------+

CSS Grid: grid grid-cols-1 lg:grid-cols-2 gap-6 Left panel: space-y-4 for vertical section stacking Right panel: sticky top-4 for scroll-following on large screens

Tab Structure (After Phase 15)

Tab Value Content
Profile profile HCP identity, personality, objections, difficulty (unchanged)
Voice & Avatar voice-avatar Agent Config Center (new 2-panel layout)

Removed tabs: knowledge, tools (were placeholders from Phase 14-03)


Interaction Contract

1. Model Deployment Selector

Property Specification
Component VoiceLiveModelSelect (reused)
Default value gpt-4o (from existing VOICE_LIVE_MODEL_OPTIONS)
Bound form field voice_live_model
Behavior Dropdown with Pro/Standard/Lite tier groups

2. Voice Mode Toggle

Property Specification
Component Switch from components/ui/switch.tsx
Label "Switch the agent to a voice-first experience" (i18n key: admin:hcp.voiceModeToggle)
Default state OFF for new profiles, derived from voice_live_instance_id presence for existing
When ON Show VL Instance selector dropdown below the toggle
When OFF Hide VL Instance selector; clear voice_live_instance_id from form
VL Instance selector Select component with available instances from useVoiceLiveInstances hook

3. Instructions Section

Property Specification
Auto-generated preview Read-only pre block, bg-muted/50 rounded p-3, text-xs font-mono, max-height 192px with overflow-y-auto
Override textarea Textarea component, 4 rows, bound to agent_instructions_override form field
Magic wand button Button variant="ghost" size="sm" with Wand2 icon from lucide-react
API call timing Existing profiles: auto-load on tab mount via POST /api/v1/hcp-profiles/preview-instructions. New profiles: load only on wand click.
Loading state Wand button shows spinner icon while generating, disabled during request
Empty state When no auto-generated instructions yet, show muted text: "Click the wand to generate instructions from profile data"

4. Knowledge & Tools Inline Section

Property Specification
Layout Single collapsible Card at bottom of left panel
Header "Knowledge & Tools" with ChevronRight/ChevronDown toggle icon
Default state Collapsed
Expanded content Two sub-sections with placeholder content (no functional backend)
Knowledge placeholder FileText icon (12px muted) + "Knowledge base configuration coming soon"
Tools placeholder Wrench icon (12px muted) + "Function Call tools configuration coming soon"
Scope UI skeleton only. No file upload, no API integration. (Deferred per CONTEXT.md)

5. Playground Preview Panel

Property Specification
Container Card with CardHeader title "Playground"
Avatar/Orb area 240px min-height centered container. Show AvatarView if avatar_character is selected, else show AudioOrb.
Start button Button with Play icon, centered below avatar/orb area. Label: "Start" (i18n). Disabled when isNew === true or no VL Instance assigned.
Stop button Replaces Start when test is active. Button variant="destructive" with Square icon. Label: "Stop".
Disabled helper When button is disabled, show muted text below: "Save profile and assign a Voice Live instance to test"
Transcript area Scrollable div, 200px max-height, bg-muted/30 rounded, displays TranscriptSegment[] with role labels (User/Agent)
Voice controls VoiceControls component shown during active test (mute toggle)
Connection Reuse useVoiceLive + useAvatarStream + useAudioHandler hooks (extracted pattern from vl-instance-editor.tsx)

6. State Transitions

[New Profile]
  -> Playground: Start disabled, helper text shown
  -> Instructions: Wand click only (no auto-load)
  -> Voice Mode: Toggle available but no persistence until save

[Saved Profile, No VL Instance]
  -> Playground: Start disabled, "Assign VL Instance to test"
  -> Instructions: Auto-load on tab mount
  -> Voice Mode: OFF

[Saved Profile, VL Instance Assigned]
  -> Playground: Start enabled
  -> Instructions: Auto-load on tab mount
  -> Voice Mode: ON with instance shown

[Playground Test Active]
  -> Start button -> Stop button
  -> VoiceControls visible (mute)
  -> Transcript accumulates in real-time
  -> Avatar/Orb shows speaking/listening state
  -> Other form fields remain editable

[Playground Test Stopped]
  -> Stop button -> Start button
  -> Transcript preserved (not cleared until next Start)
  -> VoiceControls hidden

Copywriting Contract

Element en-US zh-CN i18n Key
Tab label Voice & Avatar 语音与数字人 admin:hcp.tabVoiceAvatar (existing)
Model Deployment section title Model Deployment 模型部署 admin:hcp.modelDeployment (new)
Voice Mode toggle label Switch to voice-first experience 切换到语音优先体验 admin:hcp.voiceModeToggle (new)
Voice Mode description Enable Voice Live for real-time voice interaction with this agent 启用 Voice Live 实现与此 Agent 的实时语音交互 admin:hcp.voiceModeDescription (new)
VL Instance label Voice Live Instance Voice Live 实例 admin:hcp.vlInstanceLabel (new)
VL Instance empty No instance assigned 未分配实例 admin:hcp.vlInstanceNone (new)
Instructions auto title Auto-generated Instructions 自动生成指令 admin:hcp.autoInstructions (existing)
Instructions override label Override Instructions 自定义指令 admin:hcp.overrideInstructions (existing)
Instructions override placeholder Leave empty to use auto-generated instructions 留空则使用自动生成的指令 admin:hcp.overridePlaceholder (existing)
Instructions generate hint Click the wand to generate instructions from profile data 点击魔法棒从 Profile 数据生成指令 admin:hcp.instructionsHint (new)
Generate button Generate 生成 common:generate (new)
Regenerate button Regenerate 重新生成 common:regenerate (new)
Knowledge & Tools header Knowledge & Tools 知识库与工具 admin:hcp.knowledgeAndTools (new)
Knowledge placeholder Knowledge base configuration coming soon 知识库配置即将推出 admin:hcp.knowledgePlaceholder (new)
Tools placeholder Function Call tools configuration coming soon Function Call 工具配置即将推出 admin:hcp.toolsPlaceholder (new)
Playground title Playground 工作台 admin:hcp.playgroundTitle (new)
Playground start Start 开始 admin:hcp.playgroundStart (new)
Playground stop Stop 停止 admin:hcp.playgroundStop (new)
Playground disabled (new profile) Save profile first to test 请先保存 Profile 后再测试 admin:hcp.playgroundDisabledNew (new)
Playground disabled (no VL) Assign a Voice Live instance to test 请分配 Voice Live 实例后再测试 admin:hcp.playgroundDisabledNoVl (new)
Transcript user label You admin:hcp.transcriptUser (new)
Transcript agent label Agent Agent admin:hcp.transcriptAgent (new)
Primary CTA Save Profile 保存 Profile admin:hcp.save (existing)
Error: instructions generation failed Failed to generate instructions. Check profile data and try again. 生成指令失败,请检查 Profile 数据后重试 admin:hcp.instructionsError (new)
Error: test connection failed Voice Live connection failed Voice Live 连接失败 admin:hcp.testConnectionError (new)

Total new i18n keys: 17 (both en-US and zh-CN) Existing reused i18n keys: 6


Responsive Behavior

Breakpoint Layout
< 1024px (mobile/tablet) Single column: left panel stacks above right panel. Playground scrolls below config.
>= 1024px (lg desktop) Two-column grid: left panel 50%, right panel 50% with sticky top-4.

Tab bar: Full-width TabsList with 2 tabs (Profile, Voice & Avatar), each flex-1.


Accessibility

Element Requirement
Voice Mode toggle Switch component with aria-label from i18n key
Magic wand button aria-label="Generate instructions" from i18n
Start/Stop button aria-label toggles between "Start voice test" and "Stop voice test"
Instructions preview role="log" on auto-generated instructions container
Transcript panel role="log" with aria-live="polite" for real-time updates
Keyboard navigation All interactive elements reachable via Tab key; Enter/Space to activate
Color contrast All text meets WCAG AA (4.5:1 for body, 3:1 for large text) -- inherited from design token system

Registry Safety

Registry Blocks Used Safety Gate
No shadcn CLI N/A N/A
No third-party registries N/A N/A

This phase uses only existing Radix UI wrapper components from frontend/src/components/ui/. No new component library installations or registry imports required.


Checker Sign-Off

  • Dimension 1 Copywriting: PASS
  • Dimension 2 Visuals: PASS
  • Dimension 3 Color: PASS
  • Dimension 4 Typography: PASS
  • Dimension 5 Spacing: PASS
  • Dimension 6 Registry Safety: PASS

Approval: pending

Verification

Click to expand verification report

Phase 15: HCP Editor Agent Config Center Verification Report

Phase Goal: Refactor HCP editor to Agent Config Center aligned with Azure AI Foundry Agent editing experience. Remove empty Knowledge/Tools tabs, upgrade Voice & Avatar tab to full Agent config layout: Model Deployment selector, Voice Mode toggle + VL Instance binding, auto-generated + editable override Instructions, right-side Playground preview panel (digital human/audio orb + Start test).

Verified: 2026-04-07T10:15:00Z Status: human_needed Re-verification: No -- initial verification

Goal Achievement

Observable Truths

# Truth Status Evidence
1 HCP editor has only Profile and Voice & Avatar tabs (Knowledge/Tools removed) VERIFIED hcp-profile-editor.tsx has exactly 2 <TabsTrigger> (profile, voice-avatar), 2 <TabsContent>. No value="knowledge" or value="tools". No BookOpen or Wrench imports. VALID_TABS fallback set at line 116.
2 Voice & Avatar tab left panel: Model Deployment + Voice Mode toggle + VL Instance + Instructions VERIFIED agent-config-left-panel.tsx (294 lines) contains VoiceLiveModelSelect, Switch for Voice Mode, Select for VL Instance with assign/unassign mutation hooks, InstructionsSection composition, Knowledge & Tools collapsible skeleton.
3 Voice & Avatar tab right panel: Playground preview with avatar/orb + Start + transcript VERIFIED playground-preview-panel.tsx (302 lines) contains AvatarView/AudioOrb conditional rendering, Start/Stop buttons with session state machine (idle/connecting/connected/error/stopping), transcript area with role="log" aria-live="polite", MAX_TRANSCRIPTS=100 cap.
4 Instructions magic wand calls build_agent_instructions to regenerate VERIFIED instructions-section.tsx contains Wand2 button calling previewInstructions API -> backend POST /preview-instructions -> build_agent_instructions. AbortController race guard confirmed. Override precedence verified: non-empty override returns directly, empty triggers auto-generation.
5 Frontend + backend tests, i18n (en-US + zh-CN), TypeScript compilation VERIFIED 9 backend tests (TestPreviewInstructionsEndpoint 6 + TestToPromptDictOverride 2 + TestPreviewInstructionsRouteOrder 1). 11 frontend structural tests. 19 Phase 15 i18n keys present in both locales. generate/regenerate keys in common.json for both locales.

Score: 5/5 truths verified

Required Artifacts

Artifact Expected Status Details
backend/app/api/hcp_profiles.py POST /preview-instructions endpoint VERIFIED Lines 164-205: InstructionsPreviewRequest, InstructionsPreviewResponse models + endpoint with require_role("admin") and build_agent_instructions call
backend/app/models/hcp_profile.py to_prompt_dict includes agent_instructions_override VERIFIED Line 100: "agent_instructions_override": self.agent_instructions_override in return dict
frontend/src/components/admin/agent-config-left-panel.tsx AgentConfigLeftPanel component VERIFIED 294 lines, exports AgentConfigLeftPanel with Model Deployment, Voice Mode, VL Instance assign/unassign (migrated from voice-avatar-tab.tsx), InstructionsSection, Knowledge & Tools
frontend/src/components/admin/instructions-section.tsx InstructionsSection with AbortController VERIFIED 153 lines, abortControllerRef, handleGenerate with abort/recreate pattern, Wand2 button, auto-gen preview + override textarea
frontend/src/components/admin/playground-preview-panel.tsx PlaygroundPreviewPanel with session state machine VERIFIED 302 lines, SessionState type, useVoiceLive/useAvatarStream/useAudioHandler/useAudioPlayer hooks, NotAllowedError mic permission handling, unmount cleanup useEffect, profile change cleanup useEffect
frontend/src/components/admin/voice-avatar-tab.tsx Two-panel grid layout VERIFIED 34 lines, thin composition: grid grid-cols-1 lg:grid-cols-2 gap-6 composing AgentConfigLeftPanel + PlaygroundPreviewPanel
frontend/src/pages/admin/hcp-profile-editor.tsx 2 tabs only, legacy fallback VERIFIED 545 lines, VALID_TABS Set, handleTabChange fallback, Form wraps Tabs (line 284 before 285), no BookOpen/Wrench imports
backend/tests/test_hcp_profiles_api.py Tests for preview-instructions VERIFIED TestPreviewInstructionsEndpoint (6 tests), TestToPromptDictOverride (2 tests), TestPreviewInstructionsRouteOrder (1 test)
frontend/src/__tests__/hcp-editor-tabs.test.tsx Frontend structural tests VERIFIED 181 lines, 11 tests covering i18n parity, tab structure, lifecycle safeguards, AbortController
frontend/src/api/hcp-profiles.ts previewInstructions with AbortSignal VERIFIED Lines 117-127: previewInstructions function with signal?: AbortSignal parameter
frontend/src/hooks/use-hcp-profiles.ts usePreviewInstructions hook VERIFIED Line 85: usePreviewInstructions mutation hook
frontend/public/locales/en-US/admin.json Phase 15 i18n keys VERIFIED 19 keys present (modelDeployment, playgroundTitle, permissionDeniedMic, etc.)
frontend/public/locales/zh-CN/admin.json Phase 15 i18n keys (Chinese) VERIFIED 19 keys present with Chinese translations
frontend/public/locales/en-US/common.json generate/regenerate keys VERIFIED Lines 55-56: generate, regenerate
frontend/public/locales/zh-CN/common.json generate/regenerate keys (Chinese) VERIFIED Lines 55-56: Chinese translations

Key Link Verification

From To Via Status Details
voice-avatar-tab.tsx agent-config-left-panel.tsx import AgentConfigLeftPanel WIRED Line 2: import, Line 18: JSX usage in grid left cell
voice-avatar-tab.tsx playground-preview-panel.tsx import PlaygroundPreviewPanel WIRED Line 3: import, Line 22-29: JSX usage in grid right cell with form.watch props
agent-config-left-panel.tsx instructions-section.tsx import InstructionsSection WIRED Line 35: import, Line 225-229: JSX composition with form, profileId, isNew props
instructions-section.tsx /api/v1/hcp-profiles/preview-instructions previewInstructions API call with AbortController WIRED Line 15: import previewInstructions, Line 42+70: called with form.getValues() and controller.signal
hcp_profiles.py agent_sync_service.py build_agent_instructions import WIRED Line 199: inline import, Line 202: called with body.model_dump()
agent-config-left-panel.tsx use-voice-live-instances.ts assign/unassign VL instance hooks WIRED Lines 36-40: import useVoiceLiveInstances, useAssignVoiceLiveInstance, useUnassignVoiceLiveInstance; Lines 73-115: handleInstanceChange + handleConfirmRemove logic
hcp-profile-editor.tsx voice-avatar-tab.tsx VoiceAvatarTab composition WIRED Line 34: import, Line 525: JSX usage in TabsContent

Data-Flow Trace (Level 4)

Artifact Data Variable Source Produces Real Data Status
instructions-section.tsx autoInstructions previewInstructions API -> build_agent_instructions Yes -- calls backend endpoint that runs template generation FLOWING
agent-config-left-panel.tsx instances useVoiceLiveInstances() Yes -- fetches from /api/v1/voice-live-instances FLOWING
playground-preview-panel.tsx transcripts onTranscript callback from useVoiceLive Yes -- populated by WebSocket events during active session FLOWING (when connected)

Behavioral Spot-Checks

Behavior Command Result Status
Backend import succeeds python3 -c "from app.api.hcp_profiles import router, InstructionsPreviewRequest, InstructionsPreviewResponse" All imports successful PASS
InstructionsPreviewRequest model validates python3 -c "...InstructionsPreviewRequest(name='Test', specialty='Oncology')" Model created with correct values PASS
to_prompt_dict includes override python3 -c "...HcpProfile(...).to_prompt_dict()" agent_instructions_override present in dict PASS
Override precedence: override wins build_agent_instructions({..., agent_instructions_override: 'Custom'}) Returns 'Custom override text' directly PASS
Override precedence: empty triggers auto-gen build_agent_instructions({..., agent_instructions_override: ''}) Returns text containing 'Dr. Test' and 'Oncology' PASS
Route not shadowed POST route order analysis /preview-instructions at position 3, no bare POST /{profile_id} before it PASS

Requirements Coverage

Requirement Source Plan Description Status Evidence
HCP-15-01 15-02 HCP editor has only Profile and Voice & Avatar tabs (Knowledge/Tools removed) SATISFIED hcp-profile-editor.tsx: 2 TabsTrigger, 2 TabsContent, no knowledge/tools values
HCP-15-02 15-01 Voice & Avatar tab left panel: Model Deployment + Voice Mode toggle + VL Instance + Instructions SATISFIED agent-config-left-panel.tsx: VoiceLiveModelSelect, Switch, Select + assign/unassign, InstructionsSection
HCP-15-03 15-02 Voice & Avatar tab right panel: Playground preview with avatar/orb + Start + transcript SATISFIED playground-preview-panel.tsx: AvatarView/AudioOrb, Start/Stop, transcript area, session state machine
HCP-15-04 15-01 Instructions magic wand button calls build_agent_instructions to regenerate SATISFIED instructions-section.tsx: Wand2 button -> previewInstructions API -> build_agent_instructions
HCP-15-05 15-01, 15-03 Tests + i18n (en-US + zh-CN) + TypeScript compilation passes SATISFIED 9 backend + 11 frontend tests, 19+2 i18n keys in both locales, TypeScript compiles per summary

Anti-Patterns Found

File Line Pattern Severity Impact
agent-config-left-panel.tsx 252, 256 knowledgePlaceholder / toolsPlaceholder i18n keys referencing "coming soon" text Info Intentional non-functional skeleton per phase scope. Knowledge & Tools deferred to future phases. Not a stub -- explicit placeholder with i18n.

Human Verification Required

1. Two-Panel Layout Visual Verification

Test: Open HCP editor, click Voice & Avatar tab, verify the two-panel responsive grid layout Expected: Left panel shows Model Deployment, Voice Mode toggle, VL Instance selector, Instructions section, Knowledge & Tools. Right panel shows Playground with avatar/orb area, Start button, transcript. Why human: Visual layout, responsive behavior, and UX alignment with Azure AI Foundry style cannot be verified programmatically

2. Magic Wand Instructions Generation

Test: Click magic wand button in Instructions section on an existing HCP profile Expected: Auto-generated instructions appear in preview area containing profile name and specialty Why human: End-to-end flow through backend endpoint requires running server and human observation

3. Voice Mode Toggle Interaction

Test: Toggle Voice Mode switch ON/OFF Expected: VL Instance selector appears/disappears, form value cleared on toggle off Why human: Interactive toggle behavior requires visual confirmation

4. Tab State Persistence

Test: Enter data on Profile tab, switch to Voice & Avatar, switch back Expected: Form data persists across tab switches Why human: State persistence across UI interactions needs human observation

5. i18n Chinese Translation Verification

Test: Switch language to zh-CN and navigate to HCP editor Voice & Avatar tab Expected: All new labels display in Chinese (model deployment, voice mode, playground, etc.) Why human: Translation quality and completeness requires visual inspection

6. Legacy Tab ID Fallback

Test: Navigate directly to HCP editor URL with ?tab=knowledge or ?tab=tools Expected: Falls back to Profile tab without console errors Why human: URL-based navigation testing requires browser interaction

Gaps Summary

No code-level gaps found. All 5 observable truths verified with full artifact existence, substantive implementation, wiring, and data-flow confirmation. All 5 phase requirements (HCP-15-01 through HCP-15-05) satisfied.

6 items require human visual verification before the phase can be marked as fully passed -- all relate to interactive UI behavior and visual layout that cannot be assessed through static code analysis or programmatic checks.


Verified: 2026-04-07T10:15:00Z Verifier: Claude (gsd-verifier)

⚠️ **GitHub.com Fallback** ⚠️