docs(01): research phase domain
This commit is contained in:
parent
67e7304748
commit
31bb8db442
|
|
@ -0,0 +1,304 @@
|
||||||
|
# Phase 01: conflict-inventory-and-decision-matrix - 研究文档
|
||||||
|
|
||||||
|
**Researched:** 2026-04-07 [VERIFIED: local date + `.planning/config.json`]
|
||||||
|
**Domain:** 合并冲突盘点、Titan 重叠识别、文件级风险分级 [VERIFIED: `.planning/ROADMAP.md`, `.planning/REQUIREMENTS.md`]
|
||||||
|
**Confidence:** HIGH(仓库内证据)/ MEDIUM(通用 Git 实践)[VERIFIED: git log/show/diff 命令结果][CITED: https://git-scm.com/docs]
|
||||||
|
|
||||||
|
<user_constraints>
|
||||||
|
## User Constraints (from CONTEXT.md)
|
||||||
|
|
||||||
|
### Locked Decisions
|
||||||
|
- 未检测到 `01-CONTEXT.md`,本阶段无 discuss 锁定决策可继承。[VERIFIED: `init phase-op 1 -> "has_context": false`]
|
||||||
|
|
||||||
|
### Claude's Discretion
|
||||||
|
- 由研究阶段自行定义冲突盘点口径、决策矩阵字段、风险分级和验证策略。[VERIFIED: `init phase-op 1`, `.planning/ROADMAP.md`]
|
||||||
|
|
||||||
|
### Deferred Ideas (OUT OF SCOPE)
|
||||||
|
- 未检测到 `CONTEXT.md` 中的延期项;沿用项目级 Out of Scope(不做后端无关重构、不做新功能扩展)。[VERIFIED: `.planning/PROJECT.md`, `.planning/REQUIREMENTS.md`]
|
||||||
|
</user_constraints>
|
||||||
|
|
||||||
|
<phase_requirements>
|
||||||
|
## Phase Requirements
|
||||||
|
|
||||||
|
| ID | Description | Research Support |
|
||||||
|
|----|-------------|------------------|
|
||||||
|
| MERGE-01 | 团队可列出 merge 覆写热点并给出文件级证据与风险等级 | 提供“冲突来源采集 -> 文件分层 -> 风险评分 -> 审计输出”完整流程与评分公式 [VERIFIED: `.planning/REQUIREMENTS.md`, 本文 Architecture Patterns] |
|
||||||
|
| MERGE-03 | 团队可识别 Titan 重叠路径并形成 keep/replace 决策 | 提供 Titan overlap 识别算法、三向决策规则(Keep Legacy UI / Keep New Logic / Hybrid)与文件级验证清单 [VERIFIED: `.planning/REQUIREMENTS.md`, git author/commit 证据, 本文 Decision Matrix] |
|
||||||
|
</phase_requirements>
|
||||||
|
|
||||||
|
## Project Constraints (from CLAUDE.md)
|
||||||
|
|
||||||
|
- 仓库根目录未发现 `CLAUDE.md`,无额外项目级硬约束覆盖当前研究。[VERIFIED: `ls /home/mt/Project/deerflow2/CLAUDE.md` 返回不存在]
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Phase 01 的最佳执行路径不是“看当前工作区 diff”,而是“回放历史 merge 冲突提交并构建证据矩阵”。当前分支相对 `origin/git-main` 前端无差异,说明风险主要来自历史冲突解决中可能被静默覆盖的逻辑,而非当前未提交改动。[VERIFIED: `git diff --name-status origin/git-main..HEAD -- frontend` 空输出]
|
||||||
|
|
||||||
|
仓库中可直接抽取两条高价值证据链:1) 含冲突语义的 merge 提交(如 `8a2cac7b`, `0fff2880`, `6a540d84`, `6335424a`, `49503504`)对应的前端改动文件;2) Titan 作者提交及“移植 Titan main”提交(`7342cc08`)触达文件。两条证据求交集可快速锁定高风险文件。[VERIFIED: `git show -m --name-status ...`, `git log --author='[Tt]itan' ...`, `git show 7342cc08`]
|
||||||
|
|
||||||
|
**Primary recommendation:** 采用“文件分层 + Titan overlap + 行为关键度”的三轴决策矩阵,优先处理 `workspace/chats/[thread_id]/page.tsx`、`core/threads/hooks.ts`、`core/skills/api.ts`、`components/workspace/chats/use-thread-chat.ts`,并以“旧视觉 + 新逻辑”的分层合并法执行。[VERIFIED: 频次统计与提交历史交集]
|
||||||
|
|
||||||
|
## Standard Stack
|
||||||
|
|
||||||
|
### Core
|
||||||
|
| Library/Tool | Version | Purpose | Why Standard |
|
||||||
|
|---------|---------|---------|--------------|
|
||||||
|
| Git CLI | 2.43.0 [VERIFIED: `git --version`] | 冲突来源识别、提交追溯、三方比对 | 所有证据链均基于 commit/tree,不依赖主观比对 [VERIFIED: 本阶段目标定义 + git 命令输出] |
|
||||||
|
| ripgrep | 15.1.0 [VERIFIED: `rg --version`] | 快速扫描冲突标记、路径聚合、规则批量匹配 | 对大仓库文本检索稳定且快 [ASSUMED] |
|
||||||
|
| Node.js | v24.14.0 [VERIFIED: `node --version`] | 运行轻量脚本做矩阵生成与聚合 | 仓库前端工具链已基于 Node [VERIFIED: `frontend/package.json`] |
|
||||||
|
|
||||||
|
### Supporting
|
||||||
|
| Library/Tool | Version | Purpose | When to Use |
|
||||||
|
|---------|---------|---------|-------------|
|
||||||
|
| Playwright | `^1.48.0` [VERIFIED: `frontend/package.json`] | 高风险文件回归验证(路由/线程/消息) | 在“逻辑保留 + 视觉替换”后做行为回归 [VERIFIED: `frontend/tests/e2e/*.spec.ts`] |
|
||||||
|
| ESLint + TypeScript | `^9.23.0` + `^5.8.2` [VERIFIED: `frontend/package.json`] | 冲突修复后快速发现类型/导入回归 | 每次文件级决策后执行快速检查 [VERIFIED: `frontend/package.json` scripts] |
|
||||||
|
|
||||||
|
### Alternatives Considered
|
||||||
|
| Instead of | Could Use | Tradeoff |
|
||||||
|
|------------|-----------|----------|
|
||||||
|
| 基于 commit 的盘点 | 纯人工文件目检 | 目检无法追溯“谁覆盖了谁”,审计性差 [ASSUMED] |
|
||||||
|
| 文件级风险打分 | 全量同优先级处理 | 成本高、无法先处理行为高风险路径 [ASSUMED] |
|
||||||
|
|
||||||
|
**Installation:**
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
[VERIFIED: `frontend/package.json` 存在 `pnpm` 脚本]
|
||||||
|
|
||||||
|
**Version verification note:** npm registry 在当前环境超时,未完成在线版本核验;本文版本以仓库锁定信息和本机工具版本为准。[VERIFIED: `timeout 8 npm ping` -> EXIT:124]
|
||||||
|
|
||||||
|
## Architecture Patterns
|
||||||
|
|
||||||
|
### Recommended Project Structure (for this phase outputs)
|
||||||
|
```text
|
||||||
|
.planning/phases/01-conflict-inventory-and-decision-matrix/
|
||||||
|
├── 01-RESEARCH.md # 研究依据与决策规则
|
||||||
|
├── conflict-inventory.csv # 文件级证据(提交、作者、风险分)
|
||||||
|
└── decision-matrix.md # keep/replace/hybrid 决策表
|
||||||
|
```
|
||||||
|
[ASSUMED]
|
||||||
|
|
||||||
|
### Pattern 1: Merge 覆写风险盘点(文件级)
|
||||||
|
**What:** 从“冲突语义 merge 提交”反推出可能被覆盖/删除的文件集合,再加行为关键度打分。[VERIFIED: 多个 merge 提交含 `resolve conflict(s)` 信息]
|
||||||
|
**When to use:** 需要审计“历史 conflict resolution 是否覆盖新逻辑”时。[VERIFIED: Phase 01 Goal in `.planning/ROADMAP.md`]
|
||||||
|
**Example:**
|
||||||
|
```bash
|
||||||
|
# Source: git docs + repo history
|
||||||
|
git log --all --merges --oneline --decorate
|
||||||
|
git show -m --name-status 8a2cac7b -- frontend
|
||||||
|
git show -m --name-status 0fff2880 -- frontend
|
||||||
|
git show -m --name-status 6a540d84 -- frontend
|
||||||
|
```
|
||||||
|
[CITED: https://git-scm.com/docs/git-log][CITED: https://git-scm.com/docs/git-show][VERIFIED: 本仓库命令执行结果]
|
||||||
|
|
||||||
|
### Pattern 2: Titan Overlap 识别与保留策略
|
||||||
|
**What:** 用 `author=Titan` + “移植 Titan main”提交双轨识别 Titan 语义归属,再与 merge 热点求交集。[VERIFIED: `git log --author='[Tt]itan'`, `git show 7342cc08`]
|
||||||
|
**When to use:** 文件既出现在冲突 merge 中又被 Titan 历史触达时。[VERIFIED: 交集文件统计]
|
||||||
|
**Example:**
|
||||||
|
```bash
|
||||||
|
git log --all --author='[Tt]itan' --name-only --pretty=format: -- frontend
|
||||||
|
git show --name-only 7342cc08
|
||||||
|
```
|
||||||
|
[CITED: https://git-scm.com/docs/git-log][VERIFIED: 本仓库命令执行结果]
|
||||||
|
|
||||||
|
### Pattern 3: “旧视觉 + 新逻辑”分层合并
|
||||||
|
**What:** 将文件变更拆成视觉层与逻辑层,视觉优先对齐 legacy,逻辑优先保留 new/Titan 语义。[VERIFIED: 项目核心价值强调“视觉旧、逻辑新” in `.planning/PROJECT.md`]
|
||||||
|
**When to use:** `frontend` 中混合变更文件(UI+状态+路由)如聊天页、线程 hook、message item。[VERIFIED: 热点文件清单]
|
||||||
|
**Layer Rule(执行规则):**
|
||||||
|
1. L0 路由/查询参数/协议:保留新逻辑(`thread_id/isnew/xclaw_used`, skills bootstrap 合同)。[VERIFIED: `.planning/REQUIREMENTS.md` LOGIC-03/04]
|
||||||
|
2. L1 数据流与副作用:保留通过 Titan 或后续修复提交验证过的行为路径(避免重复/死分支)。[VERIFIED: Titan commits + merge recovery related commits]
|
||||||
|
3. L2 视图样式与布局:对齐旧视觉 tokens/spacing/hierarchy,不改动 L0/L1 决策点。[VERIFIED: `.planning/PROJECT.md` + `.planning/ROADMAP.md` Phase 3]
|
||||||
|
|
||||||
|
### 当前高风险交集文件(建议作为首批审计)
|
||||||
|
| File | Merge Hotspot Frequency | Titan Touch Frequency | Risk |
|
||||||
|
|------|-------------------------|-----------------------|------|
|
||||||
|
| `frontend/src/app/workspace/chats/[thread_id]/page.tsx` | 4 [VERIFIED: merge 频次统计] | 7 [VERIFIED: titan 频次统计] | P0 |
|
||||||
|
| `frontend/src/core/threads/hooks.ts` | 3 [VERIFIED] | 4 [VERIFIED] | P0 |
|
||||||
|
| `frontend/src/core/skills/api.ts` | 1 [VERIFIED] | 3 [VERIFIED] | P0 |
|
||||||
|
| `frontend/src/components/workspace/chats/use-thread-chat.ts` | 1 [VERIFIED] | 1 [VERIFIED] | P1 |
|
||||||
|
| `frontend/src/components/workspace/messages/message-list-item.tsx` | 7 [VERIFIED] | 1 [VERIFIED] | P1 |
|
||||||
|
| `frontend/src/components/workspace/artifacts/artifact-file-detail.tsx` | 8 [VERIFIED] | 0 [VERIFIED: titan 文件统计未出现] | P1 |
|
||||||
|
|
||||||
|
### Anti-Patterns to Avoid
|
||||||
|
- **只看当前分支 diff:** 会漏掉“历史 merge 冲突后被覆盖”的风险路径。[VERIFIED: 当前分支对 `origin/git-main` 无前端差异]
|
||||||
|
- **UI 与逻辑同时重写:** 无法定位回归来源,且不符合“按 concern 分提交”的项目约束。[VERIFIED: TEST-02 in `.planning/REQUIREMENTS.md`]
|
||||||
|
- **未标注来源的 keep/replace 决策:** reviewer 无法审计依据。[ASSUMED]
|
||||||
|
|
||||||
|
## Don't Hand-Roll
|
||||||
|
|
||||||
|
| Problem | Don't Build | Use Instead | Why |
|
||||||
|
|---------|-------------|-------------|-----|
|
||||||
|
| 提交追溯 | 自写 git parser | 原生 `git log/show/diff/blame` | 原生命令可直接复现并审计 [CITED: https://git-scm.com/docs] |
|
||||||
|
| 风险判级 | 纯主观评级 | 固定权重评分矩阵(见下) | 可重复、可解释、可比较 [ASSUMED] |
|
||||||
|
| 冲突定位 | 手动逐文件扫 | `git show -m` + 频次聚合脚本 | merge commit 下文件定位更精确 [CITED: https://git-scm.com/docs/git-show] |
|
||||||
|
|
||||||
|
**Key insight:** 该阶段核心是“审计可追溯性”,而非“一次性修完所有冲突”;优先构建证据矩阵,后续 phase 才能低风险实施。[VERIFIED: Phase 1/2/3 分工 in `.planning/ROADMAP.md`]
|
||||||
|
|
||||||
|
## Common Pitfalls
|
||||||
|
|
||||||
|
### Pitfall 1: 将“文件高频变更”误判为“逻辑高风险”
|
||||||
|
**What goes wrong:** i18n、样式类文件修改频繁但不一定影响核心行为。[VERIFIED: merge 高频文件中含 `i18n` 和样式路径]
|
||||||
|
**Why it happens:** 未将“行为关键度”纳入评分。[ASSUMED]
|
||||||
|
**How to avoid:** 评分加入 `BehaviorCritical` 维度(路由/线程/skills 协议加权)。[ASSUMED]
|
||||||
|
**Warning signs:** P0 文件集中在文案/样式但不包含路由和 core hooks。[ASSUMED]
|
||||||
|
|
||||||
|
### Pitfall 2: Titan overlap 仅按作者名判断
|
||||||
|
**What goes wrong:** 可能漏掉“由他人移植 Titan 逻辑”的提交。[VERIFIED: `7342cc08` 为 MT-Mint 提交但 message 明确“移植 Titan main”]
|
||||||
|
**Why it happens:** 只用 `--author=Titan` 单一条件。[VERIFIED: git log 结果对比]
|
||||||
|
**How to avoid:** 采用“双轨识别”:作者轨 + 语义轨(commit message/目标文件)。[ASSUMED]
|
||||||
|
**Warning signs:** 决策矩阵里出现“作者不为 Titan 但逻辑来源是 Titan”的争议。[ASSUMED]
|
||||||
|
|
||||||
|
### Pitfall 3: “旧视觉 + 新逻辑”没有技术切面边界
|
||||||
|
**What goes wrong:** 改视觉时误改路由/状态机,或保逻辑时回带新视觉样式。[ASSUMED]
|
||||||
|
**Why it happens:** 文件内视图与逻辑耦合(如 page.tsx、input-box)。[VERIFIED: `.planning/codebase/CONCERNS.md` 指出前端关键组件耦合大]
|
||||||
|
**How to avoid:** 在 PR 内按 L0/L1/L2 三层分块提交与评审。[ASSUMED]
|
||||||
|
**Warning signs:** 单个提交同时修改 query 参数行为和 CSS/token。[ASSUMED]
|
||||||
|
|
||||||
|
### Pitfall 4: 决策矩阵没有文件级验证闭环
|
||||||
|
**What goes wrong:** 决策落地后无法证明“行为未回退”。[ASSUMED]
|
||||||
|
**Why it happens:** 缺少“决策 -> 测试映射”。[ASSUMED]
|
||||||
|
**How to avoid:** 每个 P0/P1 文件绑定至少一个自动化验证命令(见 Validation Architecture)。[VERIFIED: 本文 Validation Architecture]
|
||||||
|
**Warning signs:** reviewer 只能靠截图判断是否正确。[ASSUMED]
|
||||||
|
|
||||||
|
## Code Examples
|
||||||
|
|
||||||
|
### 1) 生成冲突热点文件清单(merge 来源)
|
||||||
|
```bash
|
||||||
|
# Source: git-show docs + repo commits
|
||||||
|
for c in 8a2cac7b 0fff2880 588673d0 6a540d84 6335424a 49503504; do
|
||||||
|
git show -m --name-only --pretty=format: "$c" -- frontend
|
||||||
|
done | sed '/^$/d' | sort | uniq -c | sort -nr
|
||||||
|
```
|
||||||
|
[CITED: https://git-scm.com/docs/git-show][VERIFIED: 本仓库已执行同类命令]
|
||||||
|
|
||||||
|
### 2) 生成 Titan 触达文件清单
|
||||||
|
```bash
|
||||||
|
# Source: git-log docs + repo history
|
||||||
|
git log --all --author='[Tt]itan' --name-only --pretty=format: -- frontend \
|
||||||
|
| sed '/^$/d' | sort | uniq -c | sort -nr
|
||||||
|
```
|
||||||
|
[CITED: https://git-scm.com/docs/git-log][VERIFIED: 本仓库已执行]
|
||||||
|
|
||||||
|
### 3) 决策矩阵打分(文件级,可脚本化)
|
||||||
|
```text
|
||||||
|
RiskScore = 0.35*MergeFreq + 0.30*TitanOverlap + 0.25*BehaviorCritical + 0.10*TestGap
|
||||||
|
P0: >= 0.75
|
||||||
|
P1: 0.50 - 0.74
|
||||||
|
P2: < 0.50
|
||||||
|
```
|
||||||
|
[ASSUMED]
|
||||||
|
|
||||||
|
## State of the Art
|
||||||
|
|
||||||
|
| Old Approach | Current Approach | When Changed | Impact |
|
||||||
|
|--------------|------------------|--------------|--------|
|
||||||
|
| 仅按“当前 diff”做修复 | 基于历史 merge + author 证据构建矩阵 | 当前里程碑 Phase 1 定义时 [VERIFIED: `.planning/ROADMAP.md`] | 审计性更强,减少“静默回归” [ASSUMED] |
|
||||||
|
| 混合提交(UI+逻辑+测试) | 按 concern 拆分提交 | 项目约束已明确 [VERIFIED: TEST-02 in `.planning/REQUIREMENTS.md`] | 回滚与评审风险显著降低 [ASSUMED] |
|
||||||
|
|
||||||
|
**Deprecated/outdated:**
|
||||||
|
- “冲突靠人工记忆追溯”应视为过时做法,不满足 Phase 01 的可审计目标。[ASSUMED]
|
||||||
|
|
||||||
|
## Assumptions Log
|
||||||
|
|
||||||
|
| # | Claim | Section | Risk if Wrong |
|
||||||
|
|---|-------|---------|---------------|
|
||||||
|
| A1 | `ripgrep` 是该场景最优扫描器 | Standard Stack | 仅影响效率,不影响正确性 |
|
||||||
|
| A2 | 风险评分权重(0.35/0.30/0.25/0.10)适配本仓库 | Code Examples | 可能导致优先级排序偏差 |
|
||||||
|
| A3 | “作者轨 + 语义轨”双轨识别足以覆盖 Titan overlap | Pitfall 2 | 可能漏判少量逻辑来源 |
|
||||||
|
| A4 | L0/L1/L2 三层拆分能稳定隔离视觉与逻辑 | Pattern 3 | 若耦合过深,执行成本上升 |
|
||||||
|
|
||||||
|
## Open Questions
|
||||||
|
|
||||||
|
1. **Titan overlap 的“最终裁决权”落在谁**
|
||||||
|
- What we know: 已可机械识别 overlap 文件与提交来源。[VERIFIED: git 证据链]
|
||||||
|
- What's unclear: 业务上遇到冲突时由谁决定 keep/replace(产品、前端 owner、原作者)。[ASSUMED]
|
||||||
|
- Recommendation: 在 planner 阶段把“裁决角色 + SLA”写入 PLAN.md,避免执行阻塞。[ASSUMED]
|
||||||
|
|
||||||
|
2. **`content_id` vs `content_ids` 的阶段边界**
|
||||||
|
- What we know: 该协议冲突属于 Phase 2(LOGIC-04),但 Phase 1 需要在矩阵中标红相关文件。[VERIFIED: `.planning/ROADMAP.md`, `.planning/REQUIREMENTS.md`]
|
||||||
|
- What's unclear: Phase 1 是否要提前定义兼容窗口(双写/双读)。[ASSUMED]
|
||||||
|
- Recommendation: 在 Phase 1 仅标注风险与影响范围,不提前改实现。[ASSUMED]
|
||||||
|
|
||||||
|
## Environment Availability
|
||||||
|
|
||||||
|
| Dependency | Required By | Available | Version | Fallback |
|
||||||
|
|------------|------------|-----------|---------|----------|
|
||||||
|
| `git` | 提交追溯与冲突证据采集 | ✓ [VERIFIED] | 2.43.0 [VERIFIED] | — |
|
||||||
|
| `rg` | 快速路径/文本聚合 | ✓ [VERIFIED] | 15.1.0 [VERIFIED] | `grep -R`(较慢)[ASSUMED] |
|
||||||
|
| `node` | 矩阵脚本与前端工具链 | ✓ [VERIFIED] | v24.14.0 [VERIFIED] | — |
|
||||||
|
| `pnpm` | 前端验证命令执行 | ✓ [VERIFIED] | 10.32.1 [VERIFIED] | `npm run`(脚本兼容性待验证)[ASSUMED] |
|
||||||
|
| npm registry 网络 | 在线版本核验 | ✗ [VERIFIED: `npm ping` timeout] | — | 使用仓库锁定版本 [VERIFIED] |
|
||||||
|
|
||||||
|
**Missing dependencies with no fallback:**
|
||||||
|
- 无阻塞项。[VERIFIED: 本阶段核心命令可本地执行]
|
||||||
|
|
||||||
|
**Missing dependencies with fallback:**
|
||||||
|
- 在线 npm 版本核验不可用,已降级为仓库版本基线。[VERIFIED: `npm ping` timeout]
|
||||||
|
|
||||||
|
## Validation Architecture
|
||||||
|
|
||||||
|
### Test Framework
|
||||||
|
| Property | Value |
|
||||||
|
|----------|-------|
|
||||||
|
| Framework | Playwright(前端 E2E)[VERIFIED: `frontend/playwright.config.ts`, `frontend/package.json`] |
|
||||||
|
| Config file | `frontend/playwright.config.ts` [VERIFIED] |
|
||||||
|
| Quick run command | `cd frontend && pnpm test:e2e --grep "welcome|routing|message|history"` [VERIFIED: scripts + spec 文件名] |
|
||||||
|
| Full suite command | `cd frontend && pnpm test:e2e` [VERIFIED: `frontend/package.json`] |
|
||||||
|
|
||||||
|
### Phase Requirements → Test Map
|
||||||
|
| Req ID | Behavior | Test Type | Automated Command | File Exists? |
|
||||||
|
|--------|----------|-----------|-------------------|-------------|
|
||||||
|
| MERGE-01 | 冲突文件修复后消息/历史/路由不回归 | e2e | `cd frontend && pnpm test:e2e --grep "message|history|welcome|routing"` | ✅ [VERIFIED: `frontend/tests/e2e/message-and-history.spec.ts`, `welcome-and-routing.spec.ts`] |
|
||||||
|
| MERGE-03 | Titan 重叠文件(thread/skills)决策后行为稳定 | e2e | `cd frontend && pnpm test:e2e --grep "artifacts|thread|input|compose"` | ✅ [VERIFIED: `artifacts-and-thread-reuse.spec.ts`, `input-and-compose.spec.ts`] |
|
||||||
|
|
||||||
|
### Sampling Rate
|
||||||
|
- **Per task commit:** `cd frontend && pnpm lint && pnpm typecheck` [VERIFIED: scripts]
|
||||||
|
- **Per wave merge:** `cd frontend && pnpm test:e2e --grep "welcome|routing|message|history"` [ASSUMED]
|
||||||
|
- **Phase gate:** `cd frontend && pnpm test:e2e` 全绿 [VERIFIED: TEST-01 expectation + script]
|
||||||
|
|
||||||
|
### Wave 0 Gaps
|
||||||
|
- [ ] 增加“决策矩阵驱动”的文件级 smoke 脚本(读取 `decision-matrix.md` 自动选择 e2e 子集)[ASSUMED]
|
||||||
|
- [ ] 为 `page.tsx` / `core/threads/hooks.ts` 增加更细粒度单测入口(当前以 E2E 为主)[VERIFIED: 现有 unit 覆盖相对少 in `.planning/codebase/CONCERNS.md`]
|
||||||
|
|
||||||
|
## Security Domain
|
||||||
|
|
||||||
|
### Applicable ASVS Categories
|
||||||
|
| ASVS Category | Applies | Standard Control |
|
||||||
|
|---------------|---------|-----------------|
|
||||||
|
| V2 Authentication | no(本阶段不改 auth 机制)[ASSUMED] | 保持现状,避免引入新入口 [ASSUMED] |
|
||||||
|
| V3 Session Management | no(本阶段不改会话后端)[ASSUMED] | 不触碰 session 持久逻辑 [ASSUMED] |
|
||||||
|
| V4 Access Control | no(本阶段为前端冲突盘点)[ASSUMED] | 决策矩阵不新增权限路径 [ASSUMED] |
|
||||||
|
| V5 Input Validation | yes(路由参数行为需防回归)[VERIFIED: LOGIC-03 对 `thread_id/isnew/xclaw_used` 有明确要求] | 对 query 参数路径做回归校验(E2E)[ASSUMED] |
|
||||||
|
| V6 Cryptography | no(无密码学改动)[ASSUMED] | N/A |
|
||||||
|
|
||||||
|
### Known Threat Patterns for this phase
|
||||||
|
| Pattern | STRIDE | Standard Mitigation |
|
||||||
|
|---------|--------|---------------------|
|
||||||
|
| 决策错误导致路由参数语义回退 | Tampering | P0 文件先验回归(welcome/routing/thread reuse)[VERIFIED: 现有 e2e 覆盖路径] |
|
||||||
|
| 冲突修复引入重复逻辑路径 | Tampering/DoS | 决策矩阵强制标注 keep/replace + dead-path 检查 [ASSUMED] |
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
### Primary (HIGH confidence)
|
||||||
|
- `.planning/PROJECT.md` - 项目目标、约束、核心价值 [VERIFIED: local file]
|
||||||
|
- `.planning/REQUIREMENTS.md` - MERGE-01/MERGE-03/LOGIC 约束 [VERIFIED: local file]
|
||||||
|
- `.planning/ROADMAP.md` - Phase 01 目标边界 [VERIFIED: local file]
|
||||||
|
- `.planning/codebase/ARCHITECTURE.md` / `STRUCTURE.md` / `CONCERNS.md` / `CONVENTIONS.md` [VERIFIED: local files]
|
||||||
|
- `git log`, `git show -m`, `git diff`, `git merge-base` 实测输出 [VERIFIED: local commands in this session]
|
||||||
|
|
||||||
|
### Secondary (MEDIUM confidence)
|
||||||
|
- Git 官方文档:`git-log`, `git-show`, `git-diff`, `git-blame` [CITED: https://git-scm.com/docs/git-log] [CITED: https://git-scm.com/docs/git-show] [CITED: https://git-scm.com/docs/git-diff] [CITED: https://git-scm.com/docs/git-blame]
|
||||||
|
|
||||||
|
### Tertiary (LOW confidence)
|
||||||
|
- 无仅单源且未验证的外部结论;低置信度内容已全部标记为 `[ASSUMED]`。[VERIFIED: 本文 Assumptions Log]
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
|
||||||
|
**Confidence breakdown:**
|
||||||
|
- Standard stack: HIGH - 本机工具与仓库依赖均可本地验证;仅 npm 在线版本核验不可用。[VERIFIED]
|
||||||
|
- Architecture: HIGH - 完全基于仓库规划文档与 git 历史证据。[VERIFIED]
|
||||||
|
- Pitfalls: MEDIUM - 根因和预防部分含工程经验推断,已显式标记 `[ASSUMED]`。
|
||||||
|
|
||||||
|
**Research date:** 2026-04-07 [VERIFIED]
|
||||||
|
**Valid until:** 2026-05-07(30 天,若出现新的大规模 merge 提交需提前刷新)[ASSUMED]
|
||||||
|
|
@ -15,9 +15,3 @@
|
||||||
# NEXT_PUBLIC_BACKEND_BASE_URL="http://localhost:8001"
|
# NEXT_PUBLIC_BACKEND_BASE_URL="http://localhost:8001"
|
||||||
# NEXT_PUBLIC_LANGGRAPH_BASE_URL="http://localhost:2024"
|
# NEXT_PUBLIC_LANGGRAPH_BASE_URL="http://localhost:2024"
|
||||||
|
|
||||||
# LangGraph API base URL
|
|
||||||
# Default: /api/langgraph (uses langgraph dev server via nginx)
|
|
||||||
# Set to /api/langgraph-compat to use the experimental Gateway-backed runtime
|
|
||||||
# Requires: SKIP_LANGGRAPH_SERVER=1 in serve.sh (optional, saves resources)
|
|
||||||
# NEXT_PUBLIC_LANGGRAPH_BASE_URL=/api/langgraph-compat
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
/.pnp
|
/.pnp
|
||||||
.pnp.js
|
.pnp.js
|
||||||
|
|
||||||
|
.codex
|
||||||
|
|
||||||
# testing
|
# testing
|
||||||
/coverage
|
/coverage
|
||||||
|
|
||||||
|
|
@ -20,6 +22,7 @@ next-env.d.ts
|
||||||
|
|
||||||
# production
|
# production
|
||||||
/build
|
/build
|
||||||
|
docs
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
# --target prod — full build baked in, run `pnpm start` at container start (default if no --target is specified)
|
# --target prod — full build baked in, run `pnpm start` at container start (default if no --target is specified)
|
||||||
|
|
||||||
ARG PNPM_STORE_PATH=/root/.local/share/pnpm/store
|
ARG PNPM_STORE_PATH=/root/.local/share/pnpm/store
|
||||||
ARG NPM_REGISTRY
|
|
||||||
|
|
||||||
# ── Base: shared setup ────────────────────────────────────────────────────────
|
# ── Base: shared setup ────────────────────────────────────────────────────────
|
||||||
FROM node:22-alpine AS base
|
FROM node:22-alpine AS base
|
||||||
|
|
|
||||||
|
|
@ -4,58 +4,11 @@
|
||||||
*/
|
*/
|
||||||
import "./src/env.js";
|
import "./src/env.js";
|
||||||
|
|
||||||
function getInternalServiceURL(envKey, fallbackURL) {
|
|
||||||
const configured = process.env[envKey]?.trim();
|
|
||||||
return configured && configured.length > 0
|
|
||||||
? configured.replace(/\/+$/, "")
|
|
||||||
: fallbackURL;
|
|
||||||
}
|
|
||||||
import nextra from "nextra";
|
|
||||||
|
|
||||||
const withNextra = nextra({});
|
|
||||||
|
|
||||||
/** @type {import("next").NextConfig} */
|
/** @type {import("next").NextConfig} */
|
||||||
const config = {
|
const config = {
|
||||||
i18n: {
|
|
||||||
locales: ["en", "zh"],
|
|
||||||
defaultLocale: "en",
|
|
||||||
},
|
|
||||||
devIndicators: false,
|
devIndicators: false,
|
||||||
async rewrites() {
|
output: "standalone",
|
||||||
const rewrites = [];
|
productionBrowserSourceMaps: false,
|
||||||
const langgraphURL = getInternalServiceURL(
|
|
||||||
"DEER_FLOW_INTERNAL_LANGGRAPH_BASE_URL",
|
|
||||||
"http://127.0.0.1:2024",
|
|
||||||
);
|
|
||||||
const gatewayURL = getInternalServiceURL(
|
|
||||||
"DEER_FLOW_INTERNAL_GATEWAY_BASE_URL",
|
|
||||||
"http://127.0.0.1:8001",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!process.env.NEXT_PUBLIC_LANGGRAPH_BASE_URL) {
|
|
||||||
rewrites.push({
|
|
||||||
source: "/api/langgraph",
|
|
||||||
destination: langgraphURL,
|
|
||||||
});
|
|
||||||
rewrites.push({
|
|
||||||
source: "/api/langgraph/:path*",
|
|
||||||
destination: `${langgraphURL}/:path*`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!process.env.NEXT_PUBLIC_BACKEND_BASE_URL) {
|
|
||||||
rewrites.push({
|
|
||||||
source: "/api/agents",
|
|
||||||
destination: `${gatewayURL}/api/agents`,
|
|
||||||
});
|
|
||||||
rewrites.push({
|
|
||||||
source: "/api/agents/:path*",
|
|
||||||
destination: `${gatewayURL}/api/agents/:path*`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return rewrites;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withNextra(config);
|
export default config;
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,15 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"demo:save": "node scripts/save-demo.js",
|
"demo:save": "node scripts/save-demo.js",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"check": "eslint . --ext .ts,.tsx && tsc --noEmit",
|
"check": "eslint . --ext .ts,.tsx --ignore-pattern imports/** && tsc --noEmit",
|
||||||
"dev": "next dev --turbo",
|
"dev": "next dev --turbo",
|
||||||
"format": "prettier --check .",
|
"format": "prettier --check .",
|
||||||
"format:write": "prettier --write .",
|
"format:write": "prettier --write .",
|
||||||
"lint": "eslint . --ext .ts,.tsx",
|
"lint": "eslint . --ext .ts,.tsx --ignore-pattern imports/**",
|
||||||
"lint:fix": "eslint . --ext .ts,.tsx --fix",
|
"lint:fix": "eslint . --ext .ts,.tsx --ignore-pattern imports/** --fix",
|
||||||
|
"test:e2e": "playwright test",
|
||||||
|
"test:e2e:ui": "playwright test --ui",
|
||||||
|
"test:e2e:headed": "playwright test --headed",
|
||||||
"preview": "next build && next start",
|
"preview": "next build && next start",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
|
|
@ -59,18 +62,19 @@
|
||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
"codemirror": "^6.0.2",
|
"codemirror": "^6.0.2",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
|
"docx": "^9.6.1",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
"gsap": "^3.13.0",
|
"gsap": "^3.13.0",
|
||||||
"hast": "^1.0.0",
|
"hast": "^1.0.0",
|
||||||
|
"html2pdf.js": "^0.14.0",
|
||||||
"katex": "^0.16.28",
|
"katex": "^0.16.28",
|
||||||
"lucide-react": "^0.562.0",
|
"lucide-react": "^0.562.0",
|
||||||
|
"marked": "^17.0.5",
|
||||||
"motion": "^12.26.2",
|
"motion": "^12.26.2",
|
||||||
"nanoid": "^5.1.6",
|
"nanoid": "^5.1.6",
|
||||||
"next": "^16.1.7",
|
"next": "^16.1.7",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"nextra": "^4.6.1",
|
|
||||||
"nextra-theme-docs": "^4.6.1",
|
|
||||||
"nuxt-og-image": "^5.1.13",
|
"nuxt-og-image": "^5.1.13",
|
||||||
"ogl": "^1.0.11",
|
"ogl": "^1.0.11",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
|
|
@ -92,6 +96,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.3.1",
|
"@eslint/eslintrc": "^3.3.1",
|
||||||
|
"@playwright/test": "^1.48.0",
|
||||||
"@tailwindcss/postcss": "^4.0.15",
|
"@tailwindcss/postcss": "^4.0.15",
|
||||||
"@types/gsap": "^3.0.0",
|
"@types/gsap": "^3.0.0",
|
||||||
"@types/node": "^20.14.10",
|
"@types/node": "^20.14.10",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { defineConfig, devices } from "@playwright/test";
|
||||||
|
import { config as loadEnv } from "dotenv";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const configDir = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
// Load local e2e env defaults from frontend/.env(.local), while keeping shell env highest priority.
|
||||||
|
loadEnv({ path: path.resolve(configDir, ".env.local") });
|
||||||
|
loadEnv({ path: path.resolve(configDir, ".env") });
|
||||||
|
|
||||||
|
const baseURL = process.env.FRONTEND_E2E_BASE_URL ?? "http://127.0.0.1:3000";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: "./tests/e2e",
|
||||||
|
timeout: 30_000,
|
||||||
|
expect: {
|
||||||
|
timeout: 10_000,
|
||||||
|
},
|
||||||
|
fullyParallel: true,
|
||||||
|
retries: process.env.CI ? 1 : 0,
|
||||||
|
reporter: process.env.CI ? [["list"], ["html", { open: "never" }]] : "list",
|
||||||
|
use: {
|
||||||
|
baseURL,
|
||||||
|
trace: "on-first-retry",
|
||||||
|
screenshot: "only-on-failure",
|
||||||
|
video: "retain-on-failure",
|
||||||
|
},
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: "chromium",
|
||||||
|
use: { ...devices["Desktop Chrome"] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.3 KiB |
|
|
@ -8,8 +8,8 @@ import { I18nProvider } from "@/core/i18n/context";
|
||||||
import { detectLocaleServer } from "@/core/i18n/server";
|
import { detectLocaleServer } from "@/core/i18n/server";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "DeerFlow",
|
title: "XClaw",
|
||||||
description: "A LangChain-based framework for building super agents.",
|
description: "Desscriptions of XClawDesscriptions of XClawDesscriptions of XClaw",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function RootLayout({
|
export default async function RootLayout({
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue