Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .trellis/spec/flowscope-app/frontend/ui-change-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,11 @@ cargo build -p flowscope-cli --features serve # 2. embed 进 binary
pkill -f 'flowscope.*--serve'; ./target/debug/flowscope --serve ... # 3. 重启
```

**agent-browser 的限制**:Radix UI DropdownMenu 内部的 button 无法被 `click @ref` 可靠点击(DOM 会被提前删除)。需要通过手动 Chrome 操作或 JS 注入验证。
**浏览器自动化分两档**:

| 工具 | Radix DropdownMenu / Popover 内的 button | 备注 |
|------|------------------------------------------|------|
| Cursor IDE 浏览器 MCP(`cursor-ide-browser`,基于 Playwright) | ✅ 可靠 | snapshot 拿 ref → click,DOM detach 前 Playwright 会等待事件冒泡完成 |
| 外部 `agent-browser` CLI | ❌ 不可靠 | DOM 会在 click 落地前被 Radix 卸载,需手动 Chrome 或 JS 注入 |

优先用 Cursor 浏览器 MCP 做端到端验证;仅在没有 Cursor 上下文(独立 CI、远程 SSH)时退化到 agent-browser CLI + 手动验证。
1 change: 1 addition & 0 deletions .trellis/tasks/05-14-fix-complex-sql-parse/check.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
1 change: 1 addition & 0 deletions .trellis/tasks/05-14-fix-complex-sql-parse/implement.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
39 changes: 39 additions & 0 deletions .trellis/tasks/05-14-fix-complex-sql-parse/prd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# PRD: 修复 6 个 Hive SQL 复杂语法解析失败

## 目标

定位并修复 `auditId ∈ {2479, 2482, 2497, 2550, 2568, 2571}` 共 6 条 SQL 解析失败的根因,分门别类提交 PR。

## 最终归类(已全部最小复现验证)

用户决定:只修 flowscope 引擎、按根因分组(每个根因 1 个 PR)。SQL 写错类(id=2550 CTE 缺 as)略过。

### 3 个根因 → 3 个 PR

| PR# | 根因 | 影响 auditId | 最小复现 | 修复方案 |
|-----|------|--------------|----------|----------|
| PR1 | **STRUCT 命名字段 AS**:`STRUCT(a AS w, b AS l)` Spark/Hive 语法 | 2479, 2482, 2571 | `SELECT STRUCT(a AS w) FROM t` → FAIL | 新增 `sanitize_hive_struct_named_fields()`:剥离 `AS xxx`,保留位置 |
| PR2 | **DIV 整除运算符**:sqlparser MySQL 方言支持但 Hive 方言不支持 | 2568 | `SELECT x DIV 1000 FROM t` → FAIL | 新增 `sanitize_hive_div_operator()`:`a DIV b` → `CAST(a/b AS BIGINT)` |
| PR3 | **INSERT 带外层括号的 SELECT**:`INSERT ... PARTITION (...) (SELECT ...)` | 2497 | `INSERT ... PARTITION(dt='x') (SELECT ...)` → FAIL | 新增 `sanitize_hive_parenthesized_insert_select()`:去掉 SELECT 外层括号 |

### 略过项

| auditId | 原因 |
|---------|------|
| 2550 | 用户 SQL bug:CTE `account_info_tencent (SELECT...)` 缺 `as` 关键字,是 SQL 真错误,引擎层不应纵容 |

## 实现规范

- 修改文件:`crates/flowscope-core/src/parser/mod.rs`
- 注册触发条件:`dialect == Dialect::Hive` 且关键字预检测命中
- 接入位置:`parse_sql_with_dialect_output()` 的 fallback 链路
- 每个 PR 必须包含:
- 单元测试(覆盖正例 + 反例)
- 最小失败 SQL 加入 `tests/fixtures/` 作回归保护
- PR 描述:含失败 SQL 最小复现 + 修复前后对比

## 验收标准

1. 每个 PR 独立通过 `just test-core`
2. 合并 3 个 PR 后,对 6 条失败 SQL 重跑 `flowscope-cli` 至少 5 条变 `success=1`
3. 不引入对 931 个文件中其它 SQL 的回归(重跑 `batch_parse_sql_final.py` 失败数 ≤ 1)
26 changes: 26 additions & 0 deletions .trellis/tasks/05-14-fix-complex-sql-parse/task.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"id": "fix-complex-sql-parse",
"name": "fix-complex-sql-parse",
"title": "修复 6 个 Hive SQL 复杂语法解析失败",
"description": "",
"status": "in_progress",
"dev_type": null,
"scope": null,
"package": null,
"priority": "P2",
"creator": "wangliang",
"assignee": "wangliang",
"createdAt": "2026-05-14",
"completedAt": null,
"branch": null,
"base_branch": "master",
"worktree_path": null,
"commit": null,
"pr_url": null,
"subtasks": [],
"children": [],
"parent": null,
"relatedFiles": [],
"notes": "",
"meta": {}
}
1 change: 1 addition & 0 deletions .trellis/tasks/05-14-matrix-hide-cte/check.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
1 change: 1 addition & 0 deletions .trellis/tasks/05-14-matrix-hide-cte/implement.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
61 changes: 61 additions & 0 deletions .trellis/tasks/05-14-matrix-hide-cte/prd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Matrix 隐藏 CTE 开关与传递性依赖补全

## Goal

在 Matrix 视图的 Tables 子模式下,**默认隐藏 CTE 节点**,并提供工具栏开关供用户按需展开。隐藏时通过 BFS 传递性补全,避免「仅通过 CTE 链相连」的物理表对依赖在矩阵中消失。

## Background

- Matrix 当前用 `isTableLikeType()` 收集表节点,把 `'table' | 'view' | 'cte'` 一锅端到矩阵里(`packages/react/src/utils/matrixUtils.ts:76`)。
- 截图实测:典型多 CTE 脚本里 CTE 节点能占矩阵 ≥30% 的行/列,把真物理表标签挤变形、稀释信号。
- FlowScope 数据模型已经承认 CTE 不是物理对象(`audit-api-spec.md` 中 `table_count` 只计 `Table | View`)。
- CTE 在跨脚本对比、聚类、heatmap 这些 Matrix 核心场景里没有语义价值。

## Requirements

### 数据层(matrixUtils)

- `MatrixData` 维持现接口,不破坏 Worker 协议。
- Worker payload 新增 `cteItemSet: string[]`(序列化用 array,主线程转 Set),用于主线程识别哪些 item 是 CTE。
- `extractTableDependenciesWithDetails` 已经会经由 column-level 路径建立 `cte→cte`、`cte→table`、`table→cte` 三种依赖;不修改这部分逻辑。
- 新增主线程工具函数 `collapseCteFromMatrix(matrix, cteSet) → MatrixData`:
- 过滤掉 CTE item 行/列;
- 对每对剩余的物理表 `(A, B)`,若原 cells 中 `A→...→B` 仅经由 CTE 链可达(且原本无直接 write/read),则在新矩阵中补一条 `write` 边,details 用 transitive 链上首尾任一段的 details(标记 `indirect: true` 字段供后续 tooltip 区分)。
- 已存在的直接边保留原样。

### 状态管理

- `MatrixViewControlledState` 新增 `hideCte: boolean`,默认 `true`。
- 走 `useImmediateControlledMatrixState` pipeline,可被外部 controlled。

### UI

- Tables 工具栏(`subMode === 'tables'`)新增一个开关按钮(lucide `Layers` 图标),位置紧挨 Heatmap / Cluster / Complexity 这一组。
- Scripts 子模式下不显示该按钮。
- 按下时切换 `hideCte`,开启状态视觉与其他 toggle 一致(`bg-cyan-100 text-cyan-600 ring-1 ring-cyan-500`)。
- Tooltip 文案中文 + 英文:
- 标题:`Hide CTE Aliases`
- 说明:`Collapse CTE rows/columns and connect physical tables transitively.`

### 渲染层

- `MatrixView` 在 `fullMatrixData` 之后新增一个 useMemo 衍生的 `displayMatrixData`,根据 `hideCte && subMode === 'tables'` 决定是否调用 `collapseCteFromMatrix`。
- 后续所有 `sortedItems` / 过滤 / 渲染均基于 `displayMatrixData`。
- legend 区在 `hideCte` 开启时显示一个 `CTE Hidden` 状态标识。

## Acceptance Criteria

- [ ] 默认进入 Matrix-Tables 视图,CTE 节点(`a / before / t1` 这类)不出现在行列里。
- [ ] 工具栏 `Layers` 按钮可以一键切换显示/隐藏 CTE。
- [ ] 隐藏 CTE 时,原本通过 CTE 链相连的物理表之间能在矩阵里看到 `write` 箭头。
- [ ] Scripts 子模式工具栏不显示该按钮。
- [ ] 单测覆盖:`collapseCteFromMatrix` 至少覆盖 3 种场景:
- 物理表 → CTE → 物理表(间接,应补全);
- 物理表 → CTE → CTE → 物理表(多跳间接);
- 物理表 → 物理表 同时也途径 CTE(直接边优先,不重复补)。
- [ ] `yarn workspace @pondpilot/flowscope-react lint && typecheck && test` 全部通过。

## Notes

- 不动 Rust 引擎、不动 worker 内 build 逻辑,纯前端聚合 + 渲染层改造。
- `details.indirect` 字段为可选扩展,TS 类型在 `TableDependencyWithDetails` 上标记为 `indirect?: true`。
26 changes: 26 additions & 0 deletions .trellis/tasks/05-14-matrix-hide-cte/task.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"id": "matrix-hide-cte",
"name": "matrix-hide-cte",
"title": "Matrix \\u9690\\u85cf CTE \\u5f00\\u5173\\u4e0e\\u4f20\\u9012\\u6027\\u4f9d\\u8d56\\u8865\\u5168",
"description": "",
"status": "planning",
"dev_type": null,
"scope": null,
"package": null,
"priority": "P2",
"creator": "wangliang",
"assignee": "wangliang",
"createdAt": "2026-05-14",
"completedAt": null,
"branch": null,
"base_branch": "master",
"worktree_path": null,
"commit": null,
"pr_url": null,
"subtasks": [],
"children": [],
"parent": null,
"relatedFiles": [],
"notes": "",
"meta": {}
}
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ This file is intentionally short. `AGENTS.md` is the canonical source of build,

1. **组件文件定位**:精确到文件路径 + 行号(不是"某个地方")。
2. **API 数据先验证**:血缘/数据逻辑问题先用 curl 验证 API 返回;API 不对 → **先修 Rust 引擎**;API 对、图不对 → 才改前端渲染。
3. **验证方式**:`agent-browser` 无法可靠点击 Radix UI DropdownMenu 内的 button,需手动 Chrome 验证或 JS 注入。
3. **验证方式**:Cursor IDE 浏览器 MCP(基于 Playwright)可以可靠点击 Radix UI DropdownMenu / Popover 内的 button,无需手动 Chrome;外部 `agent-browser` CLI 在该场景仍不可靠,需走手动 Chrome 或 JS 注入。

完整规范、curl 模板、验证 SOP 见 `.trellis/spec/flowscope-app/frontend/ui-change-protocol.md`。

Expand Down
Loading
Loading