docs(07): add plan and validation strategy
This commit is contained in:
parent
80cfd8b899
commit
94094f7563
|
|
@ -67,5 +67,15 @@ Plans:
|
|||
- [x] 06-04-ARCHIVED.md — 修订归档:原 gap-closure 计划与锁定决策 D-08(上限 10)冲突,保留追踪但不再执行
|
||||
- [ ] 06-05-PLAN.md — 关闭 verification 缺口:恢复 10 个上限/类型去歧义,并稳定 DF-INPUT-008/009 回归
|
||||
|
||||
### Phase 7: 发送时拼接附件与Skill优先提示词并在消息区过滤
|
||||
|
||||
**Goal:** 发送消息时拼接附件/Skill优先提示词,同时消息区仅展示用户原文。
|
||||
**Requirements**: P7-01, P7-02, P7-03, P7-04
|
||||
**Depends on:** Phase 6
|
||||
**Plans:** 1 executable plan
|
||||
|
||||
Plans:
|
||||
- [ ] 07-01-PLAN.md — 提交态增强文本组装 + 三入口统一透传 + 显示态/提交态分离回归
|
||||
|
||||
---
|
||||
*Next command:* `/gsd-verify-work`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,211 @@
|
|||
---
|
||||
phase: 07-phase-06-mention-upload
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- frontend/src/components/workspace/input-box.tsx
|
||||
- frontend/src/core/threads/hooks.ts
|
||||
- frontend/src/components/ai-elements/prompt-input.tsx
|
||||
- frontend/src/components/workspace/messages/message-list-item.tsx
|
||||
- frontend/src/core/i18n/locales/zh-CN.ts
|
||||
- frontend/src/core/i18n/locales/en-US.ts
|
||||
- frontend/src/core/i18n/locales/types.ts
|
||||
- frontend/src/core/threads/hooks.test.ts
|
||||
- frontend/tests/e2e/input-and-compose.spec.ts
|
||||
autonomous: true
|
||||
requirements:
|
||||
- P7-01
|
||||
- P7-02
|
||||
- P7-03
|
||||
- P7-04
|
||||
must_haves:
|
||||
truths:
|
||||
- "发送到后端的文本会拼接‘优先使用…附件和…Skill’,但消息区仅展示用户原文。"
|
||||
- "拼接规则固定:附件在前、Skill在后;单类单出;大小写不敏感去重。"
|
||||
- "按钮发送、回车发送、建议词自动发送三条入口行为一致。"
|
||||
artifacts:
|
||||
- path: "frontend/src/core/threads/hooks.ts"
|
||||
provides: "提交态增强文本与展示态原文分离"
|
||||
contains: "payload text composition"
|
||||
- path: "frontend/src/components/workspace/input-box.tsx"
|
||||
provides: "references + selectedSkills 元数据传递"
|
||||
contains: "handleSubmit"
|
||||
- path: "frontend/src/components/workspace/messages/message-list-item.tsx"
|
||||
provides: "人类消息渲染仍以原文为准"
|
||||
contains: "contentToDisplay"
|
||||
key_links:
|
||||
- from: "frontend/src/components/workspace/input-box.tsx"
|
||||
to: "frontend/src/core/threads/hooks.ts"
|
||||
via: "PromptInputMessage 扩展字段"
|
||||
pattern: "selectedSkills/references -> payload composition"
|
||||
- from: "frontend/src/core/threads/hooks.ts"
|
||||
to: "frontend/src/components/workspace/messages/message-list-item.tsx"
|
||||
via: "optimistic content + persisted display consistency"
|
||||
pattern: "original text only"
|
||||
---
|
||||
|
||||
<objective>
|
||||
实现 Phase 7 决策:发送时将附件与 Skill 提示文案拼接进提交给后端的提示词,但消息区不展示拼接内容。
|
||||
|
||||
Purpose: 在不破坏既有 `additional_kwargs.files` 语义和输入体验的前提下,增强模型侧提示优先级。
|
||||
Output: 形成稳定的“提交态增强文本/展示态原文”链路,并由单测 + E2E 回归覆盖。
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/home/mt/.codex/get-shit-done/workflows/execute-plan.md
|
||||
@/home/mt/.codex/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/REQUIREMENTS.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/07-phase-06-mention-upload/07-CONTEXT.md
|
||||
@.planning/phases/07-phase-06-mention-upload/07-RESEARCH.md
|
||||
@.planning/phases/07-phase-06-mention-upload/07-VALIDATION.md
|
||||
@frontend/src/components/workspace/input-box.tsx
|
||||
@frontend/src/core/threads/hooks.ts
|
||||
@frontend/src/components/ai-elements/prompt-input.tsx
|
||||
@frontend/src/components/workspace/messages/message-list-item.tsx
|
||||
@frontend/tests/e2e/input-and-compose.spec.ts
|
||||
|
||||
<interfaces>
|
||||
From frontend/src/components/ai-elements/prompt-input.tsx:
|
||||
```typescript
|
||||
export type PromptInputMessage = {
|
||||
text: string;
|
||||
files: FileUIPart[];
|
||||
references?: PromptInputReference[];
|
||||
};
|
||||
```
|
||||
|
||||
From frontend/src/core/threads/hooks.ts:
|
||||
```typescript
|
||||
const sendMessage = async (threadId: string | undefined, message: PromptInputMessage) => {
|
||||
const text = message.text.trim();
|
||||
// optimistic human message + submit payload
|
||||
};
|
||||
```
|
||||
|
||||
From frontend/src/components/workspace/input-box.tsx:
|
||||
```typescript
|
||||
onSubmit?.({ ...message, references });
|
||||
```
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: 设计并接入“提交态增强文本”组装器</name>
|
||||
<files>frontend/src/core/threads/hooks.ts, frontend/src/components/ai-elements/prompt-input.tsx</files>
|
||||
<read_first>
|
||||
- .planning/phases/07-phase-06-mention-upload/07-CONTEXT.md
|
||||
- frontend/src/core/threads/hooks.ts
|
||||
- frontend/src/components/ai-elements/prompt-input.tsx
|
||||
- frontend/src/core/threads/submit-files.ts
|
||||
</read_first>
|
||||
<action>
|
||||
扩展 `PromptInputMessage` 以承载发送时需要的 Skill 名列表(例如 `selectedSkills?: Array<{ title: string }>`),并在 `hooks.ts` 中新增纯函数组装器:输入原文、附件名集合(上传文件名 + references 文件名)、Skill 名集合,输出“提交态增强文本”。规则必须写死为:附件在前、Skill在后、单类单出、大小写不敏感去重、空集合不拼接。拼接模板使用 `优先使用【...】和【...】`。保持 `additional_kwargs.files` 现有逻辑不变,不新建并行 envelope。
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- `PromptInputMessage` 新增可选 Skill 元数据字段,类型定义与调用点一致。
|
||||
- `hooks.ts` 存在独立组装函数,且可单测验证 4 条决策规则(顺序、单类单出、去重、空值)。
|
||||
- 原 `buildFilesForSubmit` 与 `additional_kwargs.files` 流程未被改写为新结构。
|
||||
</acceptance_criteria>
|
||||
<verify>
|
||||
<automated>cd frontend && rg -n "selectedSkills\?:|build.*Priority|优先使用【" src/components/ai-elements/prompt-input.tsx src/core/threads/hooks.ts</automated>
|
||||
<automated>cd frontend && pnpm -s test -- --run src/core/threads/hooks.test.ts</automated>
|
||||
</verify>
|
||||
<done>提交链路具备可复用的“增强文本组装器”,且不破坏现有文件提交协议。</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: InputBox 透传引用与 Skill 元数据,统一三类发送入口</name>
|
||||
<files>frontend/src/components/workspace/input-box.tsx, frontend/src/app/workspace/chats/[thread_id]/page.tsx</files>
|
||||
<read_first>
|
||||
- .planning/phases/07-phase-06-mention-upload/07-CONTEXT.md
|
||||
- frontend/src/components/workspace/input-box.tsx
|
||||
- frontend/src/app/workspace/chats/[thread_id]/page.tsx
|
||||
- frontend/src/hooks/use-iframe-skill.ts
|
||||
</read_first>
|
||||
<action>
|
||||
在 `InputBox.handleSubmit` 中把当前 `references` 与已选 `selectedSkills` 一并传给 `onSubmit` 消息对象,确保按钮发送、回车发送、建议词自动发送都经过同一条 `requestSubmit -> handleSubmit` 链路,避免分支漏传。禁止直接修改 textarea 展示文本来承载拼接文案;输入框显示始终保持用户原文。
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- `onSubmit` 入参中包含 `references` 与 `selectedSkills`,且类型安全。
|
||||
- `handleFollowupClick/confirmReplaceAndSend/confirmAppendAndSend` 最终提交均走相同 `handleSubmit` 透传逻辑。
|
||||
- 输入框展示值不被拼接文案污染。
|
||||
</acceptance_criteria>
|
||||
<verify>
|
||||
<automated>cd frontend && rg -n "selectedSkills|onSubmit\?\(\{\.\.\.message" src/components/workspace/input-box.tsx</automated>
|
||||
<automated>cd frontend && pnpm -s test -- --run src/components/workspace/input-box</automated>
|
||||
</verify>
|
||||
<done>所有发送入口都带齐元数据并保持展示态原文。</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: 保证消息区仅展示原文并补齐回归</name>
|
||||
<files>frontend/src/core/threads/hooks.ts, frontend/src/components/workspace/messages/message-list-item.tsx, frontend/tests/e2e/input-and-compose.spec.ts, frontend/src/core/i18n/locales/zh-CN.ts, frontend/src/core/i18n/locales/en-US.ts, frontend/src/core/i18n/locales/types.ts</files>
|
||||
<read_first>
|
||||
- .planning/phases/07-phase-06-mention-upload/07-CONTEXT.md
|
||||
- frontend/src/core/threads/hooks.ts
|
||||
- frontend/src/components/workspace/messages/message-list-item.tsx
|
||||
- frontend/tests/e2e/input-and-compose.spec.ts
|
||||
- frontend/src/core/i18n/locales/zh-CN.ts
|
||||
- frontend/src/core/i18n/locales/en-US.ts
|
||||
- frontend/src/core/i18n/locales/types.ts
|
||||
</read_first>
|
||||
<action>
|
||||
在 `sendMessage` 中区分 `displayText`(原文)与 `submitText`(原文+拼接文案):optimistic human message 和消息渲染侧使用 `displayText`,提交给 `thread.submit` 使用 `submitText`。若后端回流的人类消息可能带拼接文案,则在渲染层加最小且明确的剥离逻辑(仅剥离本阶段固定模板尾段),但不得依赖宽泛正则误伤用户内容。新增 i18n 文案键用于提示拼接规则相关错误(若需要)。补 E2E:断言发送后消息区不出现“优先使用【”片段,同时请求提交内容包含拼接片段(可通过拦截请求或 mock 验证)。
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- 发送请求文本包含拼接文案;消息区可见文本不包含拼接文案。
|
||||
- 附件/Skill 名拼接顺序与去重规则符合 D-01~D-10。
|
||||
- 新增回归测试覆盖“显示态与提交态分离”主路径。
|
||||
</acceptance_criteria>
|
||||
<verify>
|
||||
<automated>cd frontend && pnpm -s test -- --run src/core/threads/hooks.test.ts</automated>
|
||||
<automated>cd frontend && pnpm -s test:e2e --grep "优先使用|input|compose"</automated>
|
||||
<automated>cd frontend && pnpm -s typecheck</automated>
|
||||
</verify>
|
||||
<done>端到端满足“拼接给模型但不展示给用户”的核心目标。</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
## Trust Boundaries
|
||||
|
||||
| Boundary | Description |
|
||||
|----------|-------------|
|
||||
| 输入框展示态 → 提交态 payload | 同一条用户消息在展示与提交存在双态,若处理不当会造成信息泄露或行为不一致。 |
|
||||
| 前端组装器 → 后端存档消息 | 拼接文案若回流到历史消息,会暴露内部引导提示并污染用户可见记录。 |
|
||||
|
||||
## STRIDE Threat Register
|
||||
|
||||
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|
||||
|-----------|----------|-----------|-------------|-----------------|
|
||||
| T-07-01 | I | `frontend/src/core/threads/hooks.ts` | mitigate | 明确区分 `displayText`/`submitText`,并通过测试验证消息区不回显拼接文本。 |
|
||||
| T-07-02 | T | `frontend/src/components/workspace/input-box.tsx` | mitigate | 强制三入口走同一提交链路,避免某入口漏传 references/skills 造成规则绕过。 |
|
||||
| T-07-03 | R | `frontend/tests/e2e/input-and-compose.spec.ts` | mitigate | 增加请求拦截断言,确保“显示态/提交态分离”可审计、可回归。 |
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
- `cd frontend && pnpm -s lint`
|
||||
- `cd frontend && pnpm -s typecheck`
|
||||
- `cd frontend && pnpm -s test -- --run src/core/threads/hooks.test.ts`
|
||||
- `cd frontend && pnpm -s test:e2e --grep "input|compose|优先使用"`
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- 拼接模板与数据口径完全符合 1A/2A/3A/4A 决策。
|
||||
- 消息区不展示拼接附加文本,且不影响现有附件/引用渲染。
|
||||
- 三类发送入口行为一致并被自动化回归覆盖。
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/07-phase-06-mention-upload/07-01-SUMMARY.md`
|
||||
</output>
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
phase: 07
|
||||
slug: phase-06-mention-upload
|
||||
status: draft
|
||||
nyquist_compliant: false
|
||||
wave_0_complete: false
|
||||
created: 2026-04-17
|
||||
---
|
||||
|
||||
# Phase 07 — Validation Strategy
|
||||
|
||||
> Per-phase validation contract for feedback sampling during execution.
|
||||
|
||||
---
|
||||
|
||||
## Test Infrastructure
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Framework** | Vitest + Playwright(frontend) |
|
||||
| **Config file** | `frontend/vitest.config.ts`, `frontend/playwright.config.ts` |
|
||||
| **Quick run command** | `cd frontend && pnpm -s test -- --run src/core/threads` |
|
||||
| **Full suite command** | `cd frontend && pnpm -s lint && pnpm -s typecheck && pnpm -s test:e2e --grep "input|compose|mention"` |
|
||||
| **Estimated runtime** | ~240 seconds |
|
||||
|
||||
---
|
||||
|
||||
## Sampling Rate
|
||||
|
||||
- **After every task commit:** Run `cd frontend && pnpm -s test -- --run src/core/threads`
|
||||
- **After every plan wave:** Run `cd frontend && pnpm -s lint && pnpm -s typecheck`
|
||||
- **Before `/gsd-verify-work`:** Full suite must be green
|
||||
- **Max feedback latency:** 300 seconds
|
||||
|
||||
---
|
||||
|
||||
## Per-Task Verification Map
|
||||
|
||||
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|
||||
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
|
||||
| 07-01-01 | 01 | 1 | P7-01, P7-02 | T-07-01 | 发送前拼接且消息区不回显拼接文案 | unit | `cd frontend && pnpm -s test -- --run src/core/threads` | ✅ | ⬜ pending |
|
||||
| 07-01-02 | 01 | 1 | P7-03 | T-07-02 | 附件/Skill 名来源、顺序与去重规则一致 | unit | `cd frontend && pnpm -s test -- --run src/components/workspace/input-box` | ✅ | ⬜ pending |
|
||||
| 07-01-03 | 01 | 1 | P7-04 | T-07-03 | 所有发送入口行为一致,不出现分叉 | e2e | `cd frontend && pnpm -s test:e2e --grep "send|suggestion|compose"` | ✅ | ⬜ pending |
|
||||
|
||||
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
|
||||
|
||||
---
|
||||
|
||||
## Wave 0 Requirements
|
||||
|
||||
- [ ] `frontend/src/core/threads/hooks.test.ts` — 补提交态增强文本断言
|
||||
- [ ] `frontend/src/components/workspace/input-box.test.tsx` — 补 selectedSkills/references 组装断言
|
||||
- [ ] `frontend/tests/e2e/input-and-compose.spec.ts` — 增加“消息区不显示拼接文案”回归
|
||||
|
||||
---
|
||||
|
||||
## Manual-Only Verifications
|
||||
|
||||
| Behavior | Requirement | Why Manual | Test Instructions |
|
||||
|----------|-------------|------------|-------------------|
|
||||
| 多语言文案下拼接语句可读性 | P7-01 | 文案自然性主观 | 在中文/英文 UI 下分别发送含附件+Skill消息,人工检查生成文本 |
|
||||
|
||||
---
|
||||
|
||||
## Validation Sign-Off
|
||||
|
||||
- [ ] All tasks have `<automated>` 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 < 300s
|
||||
- [ ] `nyquist_compliant: true` set in frontmatter
|
||||
|
||||
**Approval:** pending
|
||||
Loading…
Reference in New Issue