diff --git a/.planning/STATE.md b/.planning/STATE.md index 4a9881f9..aadce455 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,14 +2,14 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone -status: v1.0 milestone complete -last_updated: "2026-04-07T06:26:30.389Z" +status: Executing Phase 06 +last_updated: "2026-04-15T02:13:10.002Z" progress: - total_phases: 5 + total_phases: 6 completed_phases: 5 - total_plans: 6 + total_plans: 9 completed_plans: 6 - percent: 100 + percent: 67 --- # STATE.md @@ -19,7 +19,7 @@ progress: See: .planning/PROJECT.md (updated 2026-04-07) **Core value:** Keep the frontend visually familiar while preserving and hardening new-system behavior end to end. -**Current focus:** Phase 01 — conflict-inventory-and-decision-matrix +**Current focus:** Phase 06 — 在输入框输入@时,可引用已生成文件和已上传附件 ## Workflow State @@ -38,3 +38,9 @@ See: .planning/PROJECT.md (updated 2026-04-07) - Repository is brownfield with active uncommitted merge-recovery changes in frontend. - Planning docs were initialized specifically for merge recovery and alignment. + +## Accumulated Context + +### Roadmap Evolution + +- Phase 6 added: 在输入框输入@时,可引用已生成文件和已上传附件 diff --git a/.planning/phases/06-/.gitkeep b/.planning/phases/06-/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/.planning/phases/06-/06-COMMIT-PLAN.md b/.planning/phases/06-/06-COMMIT-PLAN.md new file mode 100644 index 00000000..3a0eb3da --- /dev/null +++ b/.planning/phases/06-/06-COMMIT-PLAN.md @@ -0,0 +1,59 @@ +# Phase 06 Commit Plan + +## Commit Order + +`style -> logic -> tests -> docs` + +## Rules + +- 禁止跨组混提。 +- 每个提交仅包含该组文件,便于回滚与审阅。 +- 每组提交后至少执行一次对应最小验证命令。 + +## Group 1: style + +- 文件清单: + - `frontend/src/components/workspace/input-box.tsx`(仅样式 class、chip 展示视觉) + - `frontend/src/components/ui/dropdown-menu.tsx`(如有样式微调) +- commit message 示例: + - `style(phase-06): polish @ reference chip and dropdown visuals` +- 最小验证: + - `cd frontend && pnpm -s typecheck` + +## Group 2: logic + +- 文件清单: + - `frontend/src/components/ai-elements/prompt-input.tsx` + - `frontend/src/core/messages/utils.ts` + - `frontend/src/core/threads/submit-files.ts` + - `frontend/src/core/threads/hooks.ts` + - `frontend/src/components/workspace/input-box.tsx`(@候选/交互逻辑) +- commit message 示例: + - `feat(phase-06): implement @ reference submission and soft-fail flow` +- 最小验证: + - `cd frontend && pnpm -s typecheck` + +## Group 3: tests + +- 文件清单: + - `frontend/src/core/threads/hooks.test.ts` + - `frontend/tests/e2e/input-and-compose.spec.ts` + - `frontend/tests/e2e/support/chat-helpers.ts`(如有辅助变更) +- commit message 示例: + - `test(phase-06): cover @ reference flow and stale-reference handling` +- 最小验证: + - `cd frontend && node --test src/core/threads/hooks.test.ts` + - `cd frontend && pnpm -s test:e2e --grep "DF-INPUT-007|DF-INPUT-008"` + +## Group 4: docs + +- 文件清单: + - `.planning/phases/06-/06-VALIDATION.md` + - `.planning/phases/06-/06-CONTEXT.md` + - `.planning/phases/06-/06-UI-SPEC.md` + - `.planning/phases/06-/06-RESEARCH.md` + - `.planning/phases/06-/06-0*-SUMMARY.md` +- commit message 示例: + - `docs(phase-06): update validation and execution summaries` +- 最小验证: + - `rg -n "style -> logic -> tests -> docs|nyquist_compliant:\\s*true" .planning/phases/06-/` diff --git a/.planning/phases/06-/06-CONTEXT.md b/.planning/phases/06-/06-CONTEXT.md new file mode 100644 index 00000000..7b39da7a --- /dev/null +++ b/.planning/phases/06-/06-CONTEXT.md @@ -0,0 +1,111 @@ +# Phase 06: 输入框 @ 引用文件能力 - Context + +**Gathered:** 2026-04-15 +**Status:** Ready for planning + + +## Phase Boundary + +本阶段仅实现输入框中 `@` 引用文件能力:用户在聊天输入框输入 `@` 时,可从“当前线程已生成 artifacts 与已上传附件”中选择并引用文件,随消息提交给后端。 + +不扩展跨线程/全局检索,不新增后端能力边界外的文件系统能力。 + + + + +## Implementation Decisions + +### 引用来源与触发方式 +- **D-01:** 引用来源限定为“当前线程”的 `artifacts + uploads`,不做跨线程或全局文件池。 +- **D-02:** 输入 `@` 即刻弹出候选面板;继续输入即进行过滤。 + +### 输入框交互与展示 +- **D-03:** 选中文件后,在输入框内展示为可删除标签(chip),而非纯文本 `@文件名`。 +- **D-04:** 同名文件场景下,候选项展示“文件名 + 类型徽标 + 路径尾段”,避免歧义。 +- **D-09:** `@` 触发后的文件选择面板必须使用 dropdown 组件实现(不使用自定义浮层替代)。 + +### 提交协议与兼容策略 +- **D-05:** 复用 `additional_kwargs.files` 作为提交数据结构,不新增并行主结构。 +- **D-06:** 在 `files` 项内增加来源/类型元信息(如 `ref_kind` / `ref_source`),用于区分“引用文件”与“上传文件”,保持与现有渲染链路兼容。 + +### 失效与上限策略 +- **D-07:** 采用软失败:引用项失效时自动剔除并给出 toast,不阻止整条消息发送。 +- **D-08:** 每条消息最多允许 10 个引用文件,超限时给出提示并阻止继续添加。 + +### the agent's Discretion +- `@` 候选面板的具体键盘交互细节(上下选择、回车确认、Esc 关闭)的实现方式。 +- chip 的具体视觉样式与动画,不改变已确认交互语义。 +- `ref_kind` / `ref_source` 的精确字段命名(前提是语义清晰且不破坏现有消费逻辑)。 + + + + +## Canonical References + +**Downstream agents MUST read these before planning or implementing.** + +### 阶段边界与需求来源 +- `.planning/ROADMAP.md` — Phase 6 条目与依赖关系(Depends on Phase 5)。 +- `.planning/STATE.md` — Phase 6 来源说明(Roadmap Evolution)。 +- `.planning/PROJECT.md` — 核心原则:旧视觉一致性与新逻辑稳定并存。 +- `.planning/REQUIREMENTS.md` — 既有质量与回归约束(尤其测试与稳定性约束)。 + +### 输入框与提交主链路 +- `frontend/src/components/workspace/input-box.tsx` — 输入框容器、按钮区与 `PromptInput` 接入点。 +- `frontend/src/components/ai-elements/prompt-input.tsx` — 输入/附件状态、提交时 `PromptInputMessage` 组装、键盘行为。 +- `frontend/src/core/threads/hooks.ts` — 发送消息主流程、optimistic files、上传后写入 `additional_kwargs.files`。 +- `frontend/src/app/workspace/chats/[thread_id]/page.tsx` — 页面层输入框挂载与提交入口。 +- `frontend/src/components/ui/dropdown-menu.tsx` — dropdown 交互基座(Phase 6 强制用于 `@` 文件候选面板)。 + +### 文件来源与展示链路 +- `frontend/src/components/workspace/chats/chat-box.tsx` — 当前线程 artifact 列表来源(`thread.values.artifacts`)。 +- `frontend/src/components/workspace/artifacts/artifact-file-list.tsx` — artifact 文件列表与路径展示语义。 +- `frontend/src/core/uploads/api.ts` — 当前线程 uploads 列表/上传/删除 API 契约。 +- `frontend/src/core/uploads/hooks.ts` — uploads 查询与提交流程封装。 +- `frontend/src/components/workspace/messages/message-list-item.tsx` — `additional_kwargs.files` 渲染与文件卡片展示逻辑。 +- `frontend/src/core/messages/utils.ts` — 文件相关消息结构解析与兼容逻辑。 + + + + +## Existing Code Insights + +### Reusable Assets +- `PromptInput` 已具备附件状态、文件选择、粘贴/拖拽、提交流程,可在同一输入域扩展 `@` 引用交互。 +- `useThreadWithOptimistic`(`core/threads/hooks.ts`)已处理 `additional_kwargs.files` 的上传态与已上传态,适合复用为引用态承载容器。 +- `chat-box.tsx + artifacts context` 已提供当前线程 artifact 文件集合,不需要新增跨线程聚合层。 +- `uploads/api.ts + uploads/hooks.ts` 已提供当前线程上传文件可查询能力,可直接作为 `@` 候选数据源之一。 + +### Established Patterns +- 文件相关元数据统一挂载在消息 `additional_kwargs.files`,渲染侧已依赖该模式。 +- 输入框行为尽量在 `PromptInput / InputBox` 层闭环,页面层主要做组合。 +- 错误处理倾向非阻断(toast + 继续主流程),与本次“软失败”决策一致。 + +### Integration Points +- `InputBox`/`PromptInputTextarea` 负责 `@` 触发、候选过滤、chip 编辑交互。 +- 发送前在 `core/threads/hooks.ts` 汇总“上传文件 + 引用文件”并统一写入 `additional_kwargs.files`。 +- `message-list-item.tsx` 消费 `additional_kwargs.files`;需保证新增引用元信息不会破坏现有显示。 +- uploads 与 artifacts 作为候选数据源,仅限当前线程 `threadId`。 + + + + +## Specific Ideas + +- 你明确要求沿用当前消息扩展结构:引用文件“复用 `additional_kwargs.files`”,不另起并行主结构。 +- 你明确要求一次性覆盖全部灰区并锁定 A 方案(来源/触发/展示/去歧义/失效策略)。 + + + + +## Deferred Ideas + +- 跨线程/全局文件引用能力(可作为后续独立 phase)。 +- 基于语义检索或标签检索的高级文件查找(超出本阶段范围)。 + + + +--- + +*Phase: 06-* +*Context gathered: 2026-04-15* diff --git a/.planning/phases/06-/06-DISCUSSION-LOG.md b/.planning/phases/06-/06-DISCUSSION-LOG.md new file mode 100644 index 00000000..499d375c --- /dev/null +++ b/.planning/phases/06-/06-DISCUSSION-LOG.md @@ -0,0 +1,94 @@ +# Phase 06: 输入框 @ 引用文件能力 - Discussion Log + +> **Audit trail only.** Do not use as input to planning, research, or execution agents. +> Decisions are captured in CONTEXT.md — this log preserves alternatives considered. + +**Date:** 2026-04-15 +**Phase:** 06-input-mention-files +**Areas discussed:** 引用来源范围, @触发方式, 输入框展示形态, 提交数据结构, 同名去歧义, 失效与上限策略 + +--- + +## 引用来源范围 + +**Options presented** +- A: 仅当前线程(artifacts + uploads) +- B: 当前 workspace 最近线程 +- C: 全局跨线程 + +**User selection** +- A + +**Notes** +- 用户选择稳定优先,避免跨线程复杂度与歧义扩散。 + +--- + +## @ 触发方式 + +**Options presented** +- A: 输入 `@` 立即弹候选,继续输入即过滤 +- B: `@` 后至少 1 字符才弹 +- C: 不靠 `@`,仅按钮打开 + +**User selection** +- A + +--- + +## 输入框展示形态 + +**Options presented** +- A: 可删除标签(chip) +- B: 纯文本 `@文件名` +- C: 标签 + 文本混合 + +**User selection** +- A + +--- + +## 提交数据结构 + +**Options presented** +- A: 复用 `additional_kwargs.files` 并增加来源元信息 +- B: 新增 `additional_kwargs.referenced_files` +- C: 正文特殊标记 + +**User clarification** +- 用户先询问“`additional_kwargs` 是什么数据结构”,确认后给出“复用”。 + +**Final selection** +- A(复用) + +--- + +## 同名文件去歧义 + +**Options presented** +- A: 文件名 + 类型徽标 + 路径尾段 +- B: 仅文件名 +- C: 发送时二次确认 + +**User selection** +- A + +--- + +## 失效与上限策略 + +**Options presented** +- A: 软失败 + 最多 10 个 +- B: 硬失败 + 最多 20 个 +- C: 不设上限 + +**User selection** +- A + +--- + +## Final Decision Snapshot + +- 1A 2A 3A 4A(复用) 5A 6A 全部锁定。 +- 本阶段目标保持在“当前线程内 @ 引用文件”边界,不引入跨线程能力。 +- 新增要求:`@` 触发后的文件候选面板必须使用 dropdown 组件实现。 diff --git a/.planning/phases/06-/06-VALIDATION.md b/.planning/phases/06-/06-VALIDATION.md new file mode 100644 index 00000000..74bcd148 --- /dev/null +++ b/.planning/phases/06-/06-VALIDATION.md @@ -0,0 +1,72 @@ +--- +phase: 06 +slug: 06- +status: draft +nyquist_compliant: true +wave_0_complete: true +created: 2026-04-15 +--- + +# Phase 06 — Validation Strategy + +> Per-phase validation contract for feedback sampling during execution. + +--- + +## Test Infrastructure + +| Property | Value | +|----------|-------| +| **Framework** | Playwright E2E + TypeScript static checks | +| **Config file** | `frontend/playwright.config.ts` | +| **Quick run command** | `cd frontend && pnpm -s typecheck` | +| **Full suite command** | `cd frontend && pnpm -s test:e2e` | +| **Estimated runtime** | ~180 seconds | + +--- + +## Sampling Rate + +- **After every task commit:** Run `cd frontend && pnpm -s typecheck` +- **After every plan wave:** Run `cd frontend && pnpm -s test:e2e` +- **Before `/gsd-verify-work`:** Full suite must be green +- **Max feedback latency:** 180 seconds + +--- + +## Per-Task Verification Map + +| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status | +|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------| +| 06-01-01 | 01 | 1 | ATREF-03 | T-06-01-01 | 提交结构保持 `additional_kwargs.files` 且包含引用元信息 | unit | `cd frontend && node --test src/core/threads/hooks.test.ts` | ✅ | ✅ green | +| 06-02-01 | 02 | 2 | ATREF-01, ATREF-02 | T-06-02-01 | 输入 `@` 显示 thread 内候选并支持 chip 选择 | e2e | `cd frontend && pnpm -s test:e2e --grep "DF-INPUT-007"` | ✅ | ⚠️ 环境未启动(ERR_CONNECTION_REFUSED) | +| 06-03-01 | 03 | 3 | ATREF-04 | T-06-03-02 | 失效引用场景具备可解释 skip 与单测兜底 | e2e+unit | `cd frontend && pnpm -s test:e2e --grep "DF-INPUT-008" && node --test src/core/threads/hooks.test.ts` | ✅ | ⚠️ E2E 环境依赖,单测已通过 | + +*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky* + +--- + +## Wave 0 Requirements + +Existing infrastructure covers all phase requirements. + +--- + +## Manual-Only Verifications + +| Behavior | Requirement | Why Manual | Test Instructions | +|----------|-------------|------------|-------------------| +| 中文输入法组合态下 `@` 不误触发 | TBD | 浏览器/输入法差异较大 | 在 macOS/Windows 中文输入法下输入拼音并含 `@`,确认只在非 composing 触发候选 | + +--- + +## Validation Sign-Off + +- [ ] All tasks have `` verify or Wave 0 dependencies +- [ ] Sampling continuity: no 3 consecutive tasks without automated verify +- [ ] Wave 0 covers all MISSING references +- [ ] No watch-mode flags +- [ ] Feedback latency < 180s +- [ ] `nyquist_compliant: true` set in frontmatter + +**Approval:** pending