---
phase: 04-iframe-markdown-new-system-stabilization
plan: 01
type: execute
wave: 1
depends_on:
  - 03-legacy-visual-alignment-pass
files_modified:
  - frontend/src/core/iframe-messages.ts
  - frontend/src/hooks/use-iframe-skill.ts
  - frontend/src/hooks/use-selected-skill-listener.ts
  - frontend/src/lib/utils.ts
  - frontend/src/components/workspace/chats/use-thread-chat.ts
  - frontend/src/core/threads/export.ts
  - frontend/src/components/workspace/export-trigger.tsx
  - frontend/src/core/utils/markdown-download/use-markdown-download.ts
  - frontend/src/core/utils/markdown-download/converter.ts
  - frontend/tests/e2e/input-and-compose.spec.ts
  - frontend/tests/e2e/message-and-history.spec.ts
autonomous: true
requirements:
  - LOGIC-01
  - LOGIC-02
must_haves:
  truths:
    - "iframe 通信链路（selectedSkill / xclaw / fullscreen / clipboard）在前端侧具备可校验输入与容错，不因异常 payload 中断聊天主流程。"
    - "markdown 导出链路（markdown/json/docx/pdf）在成功/失败路径均可被用户感知，且失败不破坏会话使用。"
    - "artifact 与导出集成保持当前能力边界，不引入后端改造或新业务能力。"
  artifacts:
    - path: "frontend/src/core/iframe-messages.ts"
      provides: "iframe 消息协议真源与类型边界"
    - path: "frontend/src/hooks/use-selected-skill-listener.ts"
      provides: "selectedSkill 初始化幂等与容错强化"
    - path: "frontend/src/core/threads/export.ts"
      provides: "导出链路稳定与下载行为可预期"
    - path: "frontend/src/core/utils/markdown-download/use-markdown-download.ts"
      provides: "docx/pdf 下载状态与错误回调一致性"
  key_links:
    - from: "iframe-messages.ts"
      to: "use-iframe-skill.ts / use-selected-skill-listener.ts"
      via: "统一消息类型 + 接收端校验"
      pattern: "selectedSkill|XClawUsed|fullscreen|copyToClipboard"
    - from: "export-trigger.tsx"
      to: "core/threads/export.ts + markdown-download/*"
      via: "导出入口与转换实现分层"
      pattern: "export|download|docx|pdf"
---

<objective>
完成 Phase 4 的新系统能力稳定化：在不改后端协议、不扩 scope 的前提下，强化 iframe 通信与 markdown 导出的前端稳定性与可验证性。

Purpose: 落实 LOGIC-01 / LOGIC-02，消除前端可控链路中的不稳定点。  
Output: iframe 通信与导出链路具备明确容错、幂等和测试护栏。
</objective>

<context>
@.planning/PROJECT.md
@.planning/REQUIREMENTS.md
@.planning/ROADMAP.md
@.planning/phases/04-iframe-markdown-new-system-stabilization/04-CONTEXT.md
@.planning/phases/03-legacy-visual-alignment-pass/03-UAT.md
@.planning/phases/03-legacy-visual-alignment-pass/03-02-SUMMARY.md
@frontend/src/core/iframe-messages.ts
@frontend/src/hooks/use-iframe-skill.ts
@frontend/src/hooks/use-selected-skill-listener.ts
@frontend/src/core/threads/export.ts
@frontend/src/core/utils/markdown-download/use-markdown-download.ts
</context>

<tasks>

<task type="auto" tdd="true">
  <name>Task 1: Iframe 消息协议与技能联动容错加固（LOGIC-01）</name>
  <files>
    frontend/src/core/iframe-messages.ts
    frontend/src/hooks/use-iframe-skill.ts
    frontend/src/hooks/use-selected-skill-listener.ts
    frontend/src/lib/utils.ts
    frontend/src/components/workspace/chats/use-thread-chat.ts
  </files>
  <behavior>
    - Test 1: 接收非法/缺字段 postMessage 时不会抛出未捕获异常，也不会打断聊天输入与路由。
    - Test 2: selectedSkill 重复消息不会重复触发 bootstrap（幂等）。
    - Test 3: iframe 场景复制动作始终通过父页面消息代理，非 iframe 场景走原生 clipboard。
  </behavior>
  <action>
    统一消息类型入口，补齐接收端最小校验与早返回分支；保留现有成功链路行为不变，仅增强异常输入与重复输入的稳定性。确保 skill bootstrap 失败是“可恢复失败”，不阻断主流程。
  </action>
  <verify>
    <automated>cd frontend &amp;&amp; npm run lint</automated>
  </verify>
  <done>
    iframe 通信链路在异常输入下保持稳定，且核心聊天路径不中断。
  </done>
</task>

<task type="auto" tdd="true">
  <name>Task 2: Markdown 导出链路稳定化（LOGIC-02）</name>
  <files>
    frontend/src/components/workspace/export-trigger.tsx
    frontend/src/core/threads/export.ts
    frontend/src/core/utils/markdown-download/use-markdown-download.ts
    frontend/src/core/utils/markdown-download/converter.ts
  </files>
  <behavior>
    - Test 1: 无消息时导出入口禁止触发并给出明确反馈。
    - Test 2: markdown/json 导出文件名可预测且可下载。
    - Test 3: docx/pdf 转换失败时可见且不影响页面继续操作。
  </behavior>
  <action>
    维持“入口（ExportTrigger）- 格式化导出（threads/export）- 文档转换（markdown-download）”分层；补足失败分支可见性与保护逻辑，避免静默失败与状态错乱。
  </action>
  <verify>
    <automated>cd frontend &amp;&amp; npm run lint</automated>
  </verify>
  <done>
    导出链路成功/失败路径可解释，且对会话交互无副作用。
  </done>
</task>

<task type="auto" tdd="true">
  <name>Task 3: 前端可控回归护栏（Phase 4 Integration）</name>
  <files>
    frontend/tests/e2e/input-and-compose.spec.ts
    frontend/tests/e2e/message-and-history.spec.ts
    frontend/tests/e2e/support/chat-helpers.ts
  </files>
  <behavior>
    - Test 1: 关键路由/输入/发送场景在后端异常下仍能给出稳定、可解释结果。
    - Test 2: 与历史加载耦合的断言不再制造无意义级联失败。
    - Test 3: 导出相关可见状态（有无消息）具备稳定断言。
  </behavior>
  <action>
    对现有 E2E 用例做最小必要收敛，优先验证前端可控行为与页面状态；后端不稳定场景保留可定位证据但不污染无关断言。
  </action>
  <verify>
    <automated>cd frontend &amp;&amp; npm run test:e2e -- input-and-compose.spec.ts message-and-history.spec.ts</automated>
  </verify>
  <done>
    Phase 4 风险点拥有前端可控的自动化回归护栏。
  </done>
</task>

</tasks>

<threat_model>
## Trust Boundaries

| Boundary | Description |
|----------|-------------|
| `parent window -> iframe child` | postMessage 来源与 payload 不可信，前端需先校验再执行业务逻辑 |
| `UI export action -> file generation` | 导出链路涉及浏览器下载与第三方转换库，需显式处理异常 |

## STRIDE Threat Register

| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-04-01 | T (Tampering) | iframe postMessage payload | mitigate | 接收端 schema 最小校验 + 非法消息早返回 |
| T-04-02 | D (Denial of Service) | repeated selectedSkill bootstrap | mitigate | 幂等 key 去重与并发保护，避免重复请求风暴 |
| T-04-03 | R (Repudiation) | export failure observability | mitigate | 转换失败统一可见反馈与日志锚点 |
| T-04-04 | I (Information Disclosure) | artifact/export scope | accept | 本阶段不扩展后端数据面，仅前端稳定化 |
</threat_model>

<verification>
1. `lint` 无 error 级阻塞。  
2. Phase 4 目标 E2E 用例可执行并产出稳定结果。  
3. 手动抽查 iframe 消息异常输入场景与导出失败场景，确认主流程不被阻断。  
</verification>

<success_criteria>
- LOGIC-01：iframe 通信与 selectedSkill 链路具备前端容错与幂等，不因异常 payload 导致主流程失败。  
- LOGIC-02：markdown 导出链路稳定，失败可见且不中断会话。  
</success_criteria>

<output>
After completion, create `.planning/phases/04-iframe-markdown-new-system-stabilization/04-SUMMARY.md`
</output>
