diff --git a/.planning/STATE.md b/.planning/STATE.md index 6b57c790..e1d1c87e 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,12 +2,12 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone -status: v1.0 milestone complete -last_updated: "2026-04-15T05:27:38.358Z" +status: Executing Phase 06 +last_updated: "2026-04-15T07:35:15.855Z" progress: total_phases: 6 completed_phases: 6 - total_plans: 10 + total_plans: 11 completed_plans: 13 percent: 100 --- @@ -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 06 — phase-06 +**Current focus:** Phase 06 — 06 ## Workflow State diff --git a/.planning/phases/06-/06-06-SUMMARY.md b/.planning/phases/06-/06-06-SUMMARY.md new file mode 100644 index 00000000..afd8dac3 --- /dev/null +++ b/.planning/phases/06-/06-06-SUMMARY.md @@ -0,0 +1,56 @@ +--- +phase: 06- +plan: 06 +subsystem: backend-middleware +tags: [uploads, mentions, context, gap-closure] +requires: + - phase: 06-05 + provides: UAT gap diagnosis and closure plan +provides: + - 过滤 ref_kind=mention,避免被识别为本次上传 + - UploadsMiddleware 新增 mention 过滤回归测试 +affects: [06-UAT, uploads-middleware, thread-context] +tech-stack: + added: [] + patterns: [metadata-discriminator, middleware-guard-rail] +key-files: + created: + - .planning/phases/06-/06-06-SUMMARY.md + modified: + - backend/packages/harness/deerflow/agents/middlewares/uploads_middleware.py + - backend/tests/test_uploads_middleware_core_logic.py +key-decisions: + - "后端以 ref_kind=mention 作为强判定,明确将 mention 引用排除出 new_files。" + - "保留原有 filename/path/sync 行为,只做最小补丁以降低回归风险。" +requirements-completed: [ATREF-04] +duration: 12min +completed: 2026-04-15 +--- + +# Phase 06 Plan 06: Mention/Upload Misclassification Fix Summary + +修复了“提及文件被误判为本次上传文件”的核心问题:`additional_kwargs.files` 中 `ref_kind=mention` 条目现在不会进入 UploadsMiddleware 的 `new_files`。 + +## Accomplishments + +- 在 `UploadsMiddleware._files_from_kwargs` 增加判定:`ref_kind == "mention"` 直接跳过。 +- 新增两条回归测试: + - 纯 mention 条目应被完全过滤; + - mixed list 中真实 upload 保留、mention 过滤。 + +## Files Created/Modified + +- `.planning/phases/06-/06-06-SUMMARY.md` +- `backend/packages/harness/deerflow/agents/middlewares/uploads_middleware.py` +- `backend/tests/test_uploads_middleware_core_logic.py` + +## Verification + +- 尝试执行:`cd backend && pytest -q tests/test_uploads_middleware_core_logic.py -k "mention or files_from_kwargs"` +- 环境结果:`pytest` 不可用(`python3 -m pytest` 报 `No module named pytest`) + +## Self-Check: PASSED (code) / PARTIAL (runtime) + +- FOUND: mention 过滤逻辑已在 middleware 生效 +- FOUND: 单测覆盖已补齐 +- BLOCKED: 当前环境缺少 pytest,未能本地运行后端测试 diff --git a/.planning/phases/06-/06-VERIFICATION.md b/.planning/phases/06-/06-VERIFICATION.md index 1140c6ce..90bcc2c9 100644 --- a/.planning/phases/06-/06-VERIFICATION.md +++ b/.planning/phases/06-/06-VERIFICATION.md @@ -1,18 +1,45 @@ --- phase: 06- -verified: 2026-04-15T05:24:24Z -status: verified -score: 8/8 must-haves verified +verified: 2026-04-15T07:42:05Z +status: gaps_found +score: 8/10 must-haves verified overrides_applied: 0 -gaps: [] +re_verification: + previous_status: verified + previous_score: 8/8 + gaps_closed: + - "提及文件(ref_kind=mention)发送时不再被识别为本次新上传文件。" + gaps_remaining: + - "Validation/UAT/Requirements 文档闭环未完成,状态与当前实现不一致。" + regressions: [] +gaps: + - truth: "Validation 文档的 Wave 0 缺口被关闭或显式替换为可执行命令。" + status: failed + reason: "06-VALIDATION.md 仍包含 pending/未签核项,未体现 06-05/06-06 后的最新验证结果。" + artifacts: + - path: ".planning/phases/06-/06-VALIDATION.md" + issue: "Per-Task 状态仍有 ⚠️/⬜ pending,Validation Sign-Off 全部未勾选,Approval 仍为 pending。" + missing: + - "回写 06-05/06-06 最新自动化结果并完成 Validation Sign-Off。" + - truth: "must_haves、requirements-completed、UAT gaps 已形成一致闭环。" + status: failed + reason: "实现已前进,但 UAT/REQUIREMENTS 追踪状态仍停留在 diagnosed/pending,文档闭环不一致。" + artifacts: + - path: ".planning/phases/06-/06-UAT.md" + issue: "status 仍为 diagnosed,且仍记录“mention 被当作 upload”为 failed。" + - path: ".planning/REQUIREMENTS.md" + issue: "ATREF-01..04 在需求与 Traceability 表中仍为 Pending。" + missing: + - "按当前代码与测试结果更新 06-UAT.md 的 test/gap 状态。" + - "回写 REQUIREMENTS.md 中 ATREF-01..04 的状态(至少 Traceability)。" --- # Phase 6: 在输入框输入@时,可引用已生成文件和已上传附件 Verification Report **Phase Goal:** 在当前线程聊天输入框中实现 `@` 文件引用(artifacts + uploads),并通过 `additional_kwargs.files` 稳定提交且具备回归测试。 -**Verified:** 2026-04-15T05:24:24Z -**Status:** verified -**Re-verification:** Yes — after 06-05 gap closure +**Verified:** 2026-04-15T07:42:05Z +**Status:** gaps_found +**Re-verification:** Yes — after 06-06 gap closure ## Goal Achievement @@ -20,56 +47,65 @@ gaps: [] | # | Truth | Status | Evidence | | --- | --- | --- | --- | -| 1 | 输入 `@` 时仅展示当前线程候选并支持连续过滤(ATREF-01) | ✓ VERIFIED | `input-box.tsx` 基于 `thread.values.artifacts` + `useUploadedFiles(threadId)` 聚合候选,`findMentionToken` + `mentionQuery` 做过滤。 | -| 2 | 选中后展示可删除 chip,而非纯文本 | ✓ VERIFIED | `input-box.tsx` 渲染 `reference-chip`,并支持按钮删除与空输入 `Backspace` 删除最后一项。 | -| 3 | 同名场景显示“文件名+类型+路径尾段”,且上限 10(ATREF-02) | ✓ VERIFIED | `MAX_REFERENCES_PER_MESSAGE = 10`;候选与预览均显示 `filename + typeLabel + pathTail`;超过上限提示“单条消息最多引用 10 个文件”。 | -| 4 | 引用通过 `additional_kwargs.files` 提交,不新增并行主结构 | ✓ VERIFIED | `hooks.ts` 提交链路写入 `additional_kwargs: { files: filesForSubmit }`。 | -| 5 | 引用提交带来源元信息且兼容既有渲染链路(ATREF-03) | ✓ VERIFIED | `FileInMessage` 保留 `ref_kind/ref_source` 可选字段,消息渲染链路保持兼容。 | -| 6 | 失效引用软剔除并继续发送文本(ATREF-03) | ✓ VERIFIED | `buildFilesForSubmit` 丢弃 `stale`;`hooks.ts` toast 后继续发送。 | -| 7 | 回归测试覆盖候选/chip/上限/软失败(ATREF-04) | ✓ VERIFIED | `DF-INPUT-007/008/009` 重新验证通过;008 不再永久跳过。 | -| 8 | 存在 style/logic/tests/docs 提交分组计划(ATREF-04) | ✓ VERIFIED | `06-COMMIT-GUIDE.md` 保持 `style -> logic -> tests -> docs` 分组约束。 | +| 1 | `@` 仅展示当前线程候选并支持过滤(ATREF-01) | ✓ VERIFIED | `input-box.tsx` 使用 `thread.values.artifacts` + `useUploadedFiles(threadId)` 聚合,`findMentionToken`+`mentionQuery` 过滤。 | +| 2 | 选中候选后显示可删除引用 chip(ATREF-02) | ✓ VERIFIED | [input-box.tsx](/home/mt/Project/deerflow2/frontend/src/components/workspace/input-box.tsx:562) 渲染 `reference-inline-preview/reference-chip`,并支持 remove。 | +| 3 | 同名去歧义“文件名+类型+路径尾段”且上限 10(ATREF-02) | ✓ VERIFIED | [input-box.tsx](/home/mt/Project/deerflow2/frontend/src/components/workspace/input-box.tsx:568) 展示 type+pathTail;[input-box.tsx](/home/mt/Project/deerflow2/frontend/src/components/workspace/input-box.tsx:348) 限制第 11 个并 toast。 | +| 4 | 引用通过 `additional_kwargs.files` 单一 envelope 提交(ATREF-03) | ✓ VERIFIED | [hooks.ts](/home/mt/Project/deerflow2/frontend/src/core/threads/hooks.ts:610) 提交 `additional_kwargs: { files }`;[submit-files.ts](/home/mt/Project/deerflow2/frontend/src/core/threads/submit-files.ts:82) 写入 `ref_kind/ref_source`。 | +| 5 | stale 引用软剔除且文本继续发送(ATREF-03) | ✓ VERIFIED | [submit-files.ts](/home/mt/Project/deerflow2/frontend/src/core/threads/submit-files.ts:73) 跳过 stale;[hooks.ts](/home/mt/Project/deerflow2/frontend/src/core/threads/hooks.ts:596) 仅 toast 后继续 submit。 | +| 6 | **06-06**:mention 不被识别为新上传文件 | ✓ VERIFIED | [uploads_middleware.py](/home/mt/Project/deerflow2/backend/packages/harness/deerflow/agents/middlewares/uploads_middleware.py:172) `ref_kind=="mention"` 直接跳过。 | +| 7 | `` new_files 仅包含真实上传 | ✓ VERIFIED | `_files_from_kwargs` 过滤 mention 后才进入 `new_files`;回归测试 [test_uploads_middleware_core_logic.py](/home/mt/Project/deerflow2/backend/tests/test_uploads_middleware_core_logic.py:146) 与 [test_uploads_middleware_core_logic.py](/home/mt/Project/deerflow2/backend/tests/test_uploads_middleware_core_logic.py:162)。 | +| 8 | ATREF-04 自动化回归可执行(单测+E2E) | ✓ VERIFIED | `node --test hooks.test.ts` 4 通过;`pnpm test:e2e --grep DF-INPUT-007/008/009` 3 通过;`uv run pytest -k \"mention or files_from_kwargs\"` 2 通过。 | +| 9 | Validation 的 Wave 0 闭环完成 | ✗ FAILED | [06-VALIDATION.md](/home/mt/Project/deerflow2/.planning/phases/06-/06-VALIDATION.md:45) 仍有 `pending`;[06-VALIDATION.md](/home/mt/Project/deerflow2/.planning/phases/06-/06-VALIDATION.md:68) Sign-Off 未完成。 | +| 10 | must_haves / requirements-completed / UAT gaps 闭环一致 | ✗ FAILED | [06-UAT.md](/home/mt/Project/deerflow2/.planning/phases/06-/06-UAT.md:2) 仍 `diagnosed` 且 mention 误判仍记 failed;[REQUIREMENTS.md](/home/mt/Project/deerflow2/.planning/REQUIREMENTS.md:72) `ATREF-01..04` 仍 Pending。 | -**Score:** 8/8 truths verified +**Score:** 8/10 truths verified ### Required Artifacts | Artifact | Expected | Status | Details | | --- | --- | --- | --- | -| `frontend/src/components/workspace/input-box.tsx` | `@` 候选、过滤、chip、键盘交互、上限 10 | ✓ VERIFIED | 使用 `DropdownMenu` 候选层,包含类型/路径去歧义显示。 | -| `frontend/src/core/threads/hooks.ts` | 统一提交 `additional_kwargs.files` | ✓ VERIFIED | `filesForSubmit` 汇总后进入提交 envelope。 | -| `frontend/src/core/threads/submit-files.ts` | uploads/references 合并与 artifact 物化 | ✓ VERIFIED | `materializeArtifactReferences` + `buildFilesForSubmit` 正常工作。 | -| `frontend/src/core/messages/utils.ts` | `FileInMessage` 扩展兼容 | ✓ VERIFIED | 字段扩展为可选,未破坏旧数据。 | -| `frontend/src/core/threads/hooks.test.ts` | 提交流程与软失败单测 | ✓ VERIFIED | 4 条测试通过。 | -| `frontend/tests/e2e/input-and-compose.spec.ts` | `@` 引用 E2E 回归 | ✓ VERIFIED | `DF-INPUT-007/008/009` 全部通过。 | -| `.planning/phases/06-/06-COMMIT-GUIDE.md` | 分组提交计划 | ✓ VERIFIED | 分组与执行顺序清晰。 | +| `backend/packages/harness/deerflow/agents/middlewares/uploads_middleware.py` | mention 与 upload 语义分离 | ✓ VERIFIED | `_files_from_kwargs` 过滤 `ref_kind=mention`。 | +| `backend/tests/test_uploads_middleware_core_logic.py` | mention 过滤回归测试 | ✓ VERIFIED | 新增 mention-only / mixed-list 两条测试。 | +| `frontend/src/components/workspace/input-box.tsx` | 候选、chip、上限、去歧义 | ✓ VERIFIED | UI 合同字段和 testid 都在位。 | +| `frontend/src/core/threads/hooks.ts` | 单一 files envelope + soft-fail | ✓ VERIFIED | 两条提交流程都接入 `buildFilesForSubmit`。 | +| `.planning/phases/06-/06-VALIDATION.md` | 与当前验证状态一致 | ⚠️ PARTIAL | 文档仍有 pending/未签核项。 | +| `.planning/phases/06-/06-UAT.md` | gap closure 已回写 | ✗ FAILED | 仍停留在旧诊断结果。 | ### Key Link Verification | From | To | Via | Status | Details | | --- | --- | --- | --- | --- | -| `input-box.tsx` | `uploads/hooks.ts` | `useUploadedFiles(threadId)` | ✓ WIRED | 候选来源连接正常。 | -| `input-box.tsx` | `thread.values.artifacts` | thread artifacts 候选源 | ✓ WIRED | 直接读取。 | -| `input-box.tsx` | `hooks.ts` | `PromptInputMessage.references` | ✓ WIRED | `handleSubmit` 将 references 合并后提交。 | -| `hooks.ts` | `submit-files.ts` | `buildFilesForSubmit/materializeArtifactReferences` | ✓ WIRED | 提交前标准化已接入。 | -| `hooks.ts` | `additional_kwargs.files` | 提交 envelope | ✓ WIRED | 主链路输出一致。 | -| `input-box.tsx` | `dropdown-menu.tsx` | Dropdown 候选面板 | ✓ WIRED | 使用 `DropdownMenuContent/Item`。 | +| `input-box.tsx` | `hooks.ts` | `PromptInputMessage.references` | ✓ WIRED | `onSubmit` 注入 `references` 并发送。 | +| `hooks.ts` | `submit-files.ts` | `buildFilesForSubmit/materializeArtifactReferences` | ✓ WIRED | 提交前统一归一化并构建 files。 | +| `submit-files.ts` | `uploads_middleware.py` | `additional_kwargs.files[*].ref_kind/ref_source` | ✓ WIRED | 前端写 `ref_kind=mention`,后端读取并过滤 mention。 | +| `uploads_middleware.py` | agent context | `` 注入 | ✓ WIRED | `new_files` 过滤后再注入内容。 | +| `06-UAT.md` | 06-05/06-06 实现结果 | gap 状态回写 | ✗ NOT_WIRED | 文档未更新到最新实现。 | + +### Data-Flow Trace (Level 4) + +| Artifact | Data Variable | Source | Produces Real Data | Status | +| --- | --- | --- | --- | --- | +| `hooks.ts` | `filesForSubmit` | `buildFilesForSubmit(uploadedFileInfo, normalizedReferences)` | Yes | ✓ FLOWING | +| `submit-files.ts` | `referenceFiles[*].ref_kind/ref_source` | `message.references`(含 artifact materialization) | Yes | ✓ FLOWING | +| `uploads_middleware.py` | `new_files` | `message.additional_kwargs.files` | Yes(过滤 mention,仅保留真实 upload) | ✓ FLOWING | ### Behavioral Spot-Checks | Behavior | Command | Result | Status | | --- | --- | --- | --- | -| 提交构建与软失败单测 | `cd frontend && node --test src/core/threads/hooks.test.ts` | 4 passed, 0 failed | ✓ PASS | -| 类型检查 | `cd frontend && pnpm -s typecheck` | exit 0 | ✓ PASS | -| 引用回归 E2E | `cd frontend && pnpm -s test:e2e --grep "DF-INPUT-007|DF-INPUT-008|DF-INPUT-009"` | 3 passed | ✓ PASS | +| 引用构建与软失败单测 | `cd frontend && node --test src/core/threads/hooks.test.ts` | 4 passed, 0 failed | ✓ PASS | +| `@` 引用 E2E 主链路 | `cd frontend && pnpm -s test:e2e --grep "DF-INPUT-007|DF-INPUT-008|DF-INPUT-009"` | 3 passed | ✓ PASS | +| mention 过滤后端回归 | `cd backend && uv run pytest -q tests/test_uploads_middleware_core_logic.py -k "mention or files_from_kwargs"` | 2 passed | ✓ PASS | +| 直接 `pytest` 入口可用性 | `cd backend && python3 -m pytest -q ...` | `No module named pytest` | ? SKIP(需使用 `uv run`) | ### Requirements Coverage | Requirement | Source Plan | Description | Status | Evidence | | --- | --- | --- | --- | --- | -| ATREF-01 | 06-02, 06-05 | `@` 仅显示当前线程候选并支持过滤 | ✓ SATISFIED | 候选来源与过滤行为已验证。 | -| ATREF-02 | 06-02, 06-05 | chip 展示 + 同名去歧义(文件名+类型+路径尾段)+ 上限 10 | ✓ SATISFIED | 代码常量/文案/E2E 断言已统一为 10。 | -| ATREF-03 | 06-01, 06-05 | `additional_kwargs.files` 提交 + 元信息 + stale 软剔除 | ✓ SATISFIED | hooks + submit-files + 单测通过。 | -| ATREF-04 | 06-03, 06-05 | 单测+E2E 回归 + 提交分组计划 | ✓ SATISFIED | 关键 E2E 用例稳定通过,分组文档完整。 | +| ATREF-01 | 06-02, 06-05 | `@` 候选限定当前线程并可过滤 | ✓ SATISFIED | 代码链路 + DF-INPUT-007 通过。 | +| ATREF-02 | 06-02, 06-05 | chip 展示 + 去歧义 + 上限 10 | ✓ SATISFIED | 输入框合同与 DF-INPUT-009 通过。 | +| ATREF-03 | 06-01, 06-05 | `additional_kwargs.files` 提交 + stale 软剔除 | ✓ SATISFIED | hooks/submit-files + hooks.test 通过。 | +| ATREF-04 | 06-03, 06-05, 06-06 | 自动化回归 + 提交分组计划 | ✓ SATISFIED | E2E/单测/后端回归 + COMMIT-GUIDE。 | Orphaned requirements for Phase 6: None. @@ -77,13 +113,22 @@ Orphaned requirements for Phase 6: None. | File | Line | Pattern | Severity | Impact | | --- | --- | --- | --- | --- | -| `frontend/src/components/workspace/input-box.tsx` | 745 | `TODO` connector 占位注释 | ℹ️ Info | 与 Phase 6 验证目标无阻断关系。 | +| `frontend/src/components/workspace/input-box.tsx` | 745 | TODO 注释 | ℹ️ Info | 与 Phase 6 核心目标无阻断。 | +| `frontend/src/components/workspace/input-box.tsx` | 1128 | TODO 注释 | ℹ️ Info | 与 mention/upload 链路无直接关系。 | + +### Human Verification Required + +### 1. 候选面板视觉锚定 + +**Test:** 在真实页面滚动和不同窗口宽度下,输入 `@` 观察候选面板是否“紧贴输入框上方”。 +**Expected:** 面板稳定贴近输入框上边缘,不出现明显漂移。 +**Why human:** 这是视觉/交互感知问题,自动化命中无法覆盖所有布局场景。 ### Gaps Summary -No unresolved verification gaps in Phase 6. +代码与自动化层面,06-06 新增 gap(mention 被当作 upload)已关闭,且回归测试通过。当前阻塞来自**文档闭环**:`06-VALIDATION.md`、`06-UAT.md`、`REQUIREMENTS.md` 未同步到最新验证状态,导致“must_haves / requirements-completed / UAT gaps”三者不一致。 --- -_Verified: 2026-04-15T05:24:24Z_ -_Verifier: Codex (re-verified with current workspace state)_ +_Verified: 2026-04-15T07:42:05Z_ +_Verifier: Codex (gsd-verifier)_