修复: CR-01审查待修项①类7项(CSS补testing/blocked徽章+CAS防回收站推进+DRY+注释+测试改名+advancing接文案)+新增待审查.md审查队列(职责分离:主会话写/审查agent读)+todo销账
This commit is contained in:
@@ -20,7 +20,7 @@ use df_storage::db::Database;
|
|||||||
use df_storage::models::TaskRecord;
|
use df_storage::models::TaskRecord;
|
||||||
use df_workflow::node::{Node, NodeContext, NodeOutput, NodeResult, NodeSchema};
|
use df_workflow::node::{Node, NodeContext, NodeOutput, NodeResult, NodeSchema};
|
||||||
|
|
||||||
use crate::task_state_machine::{can_transition, is_regression, is_valid_state};
|
use crate::task_state_machine::{can_transition, is_regression, is_valid_state, ALL_STATES};
|
||||||
|
|
||||||
/// 推进任务到目标状态(核心逻辑,DAG 节点与 IPC 入口共用)。
|
/// 推进任务到目标状态(核心逻辑,DAG 节点与 IPC 入口共用)。
|
||||||
///
|
///
|
||||||
@@ -45,8 +45,9 @@ pub async fn advance_task_atomic(
|
|||||||
// 1. target 合法性(7 态之一)。先于读库校验:即便任务不存在,也先拒绝非法状态值。
|
// 1. target 合法性(7 态之一)。先于读库校验:即便任务不存在,也先拒绝非法状态值。
|
||||||
if !is_valid_state(target_status) {
|
if !is_valid_state(target_status) {
|
||||||
return Err(df_core::error::Error::Validation(format!(
|
return Err(df_core::error::Error::Validation(format!(
|
||||||
"非法 target_status {:?},合法值: todo/in_progress/in_review/testing/done/blocked/cancelled",
|
"非法 target_status {:?},合法值: {}",
|
||||||
target_status
|
target_status,
|
||||||
|
ALL_STATES.join("/")
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,15 +296,15 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn concurrent_cas_change_detected() {
|
async fn advance_succeeds_after_prior_status_change() {
|
||||||
// 模拟 TOCTOU:推进前已被旁路改 status。CAS 的 expected 与库内不符 → None → 报错。
|
// 前序旁路改 status 后,推进链基于「当前」status 判定合法转换并正常写入。
|
||||||
|
// 注:这并非 CAS 并发失败场景(真 CAS 失败由 cas_returns_none_when_status_mismatch 覆盖),
|
||||||
|
// 而是验证读后改路径在 from=当前库内 status 时正常推进。
|
||||||
let repo = setup().await;
|
let repo = setup().await;
|
||||||
repo.insert(rec("t1", "todo")).await.unwrap();
|
repo.insert(rec("t1", "todo")).await.unwrap();
|
||||||
// 旁路把 status 改成 in_progress(模拟另一路并发推进)
|
// 旁路把 status 改成 in_progress(模拟另一路并发推进)
|
||||||
repo.update_field("t1", "status", "in_progress").await.unwrap();
|
repo.update_field("t1", "status", "in_progress").await.unwrap();
|
||||||
// 此时读出来是 in_progress,推进到 in_review 是合法的——这测的不是 CAS 失败,
|
// 读出来是 in_progress,推进到 in_review 合法 → 正常成功
|
||||||
// 而是验证「读后改」路径在 status 一致时正常。CAS 失败路径靠 advance_status_atomic
|
|
||||||
// 自身的 None 返回覆盖(下方 cas_returns_none_when_status_mismatch 单测)。
|
|
||||||
let r = advance_task_atomic(&repo, "t1", "in_review").await.unwrap();
|
let r = advance_task_atomic(&repo, "t1", "in_review").await.unwrap();
|
||||||
assert_eq!(r.status, "in_review");
|
assert_eq!(r.status, "in_review");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -325,6 +325,10 @@ pub fn allowed_columns_for(table: &str) -> Option<&'static [&'static str]> {
|
|||||||
"tasks" => &[
|
"tasks" => &[
|
||||||
// id/created_at 不列入:主键与创建时间不可通过通用 update_field 改写
|
// id/created_at 不列入:主键与创建时间不可通过通用 update_field 改写
|
||||||
// (防篡改主键/伪造创建时间/跨项目移动)。
|
// (防篡改主键/伪造创建时间/跨项目移动)。
|
||||||
|
// review_rounds 不列入:它仅 advance_status_atomic 退回转换
|
||||||
|
// (in_review→in_progress / testing→in_review)时原子 +1(收口:仅该专用路径可改,
|
||||||
|
// update_task/update_field 白名单均不含)。后人勿把 review_rounds 补进白名单,
|
||||||
|
// 否则破坏「review_rounds 唯一写入路径」收口、引入旁路写导致计数错乱。
|
||||||
"project_id", "title", "description", "status", "priority", "branch_name",
|
"project_id", "title", "description", "status", "priority", "branch_name",
|
||||||
"assignee", "workflow_def_id", "base_branch", "updated_at",
|
"assignee", "workflow_def_id", "base_branch", "updated_at",
|
||||||
// TODO(B-260616-16): project_id 跨表存在性校验待 commands/task.rs 层补。
|
// TODO(B-260616-16): project_id 跨表存在性校验待 commands/task.rs 层补。
|
||||||
@@ -846,12 +850,14 @@ impl TaskRepo {
|
|||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let guard = conn.blocking_lock();
|
let guard = conn.blocking_lock();
|
||||||
// CAS:WHERE id AND status=expected 锁定当前态;affected==0 即并发已改动。
|
// CAS:WHERE id AND status=expected 锁定当前态;affected==0 即并发已改动。
|
||||||
|
// deleted_at IS NULL:回收站任务(soft_delete 设了 deleted_at)CAS 必败→affected=0,
|
||||||
|
// 返回 None,杜绝回收站任务被推进(D-02 软删语义收口,一处关闭)。
|
||||||
let sql = if bump_rounds {
|
let sql = if bump_rounds {
|
||||||
"UPDATE tasks SET status = ?1, review_rounds = review_rounds + 1, updated_at = ?2 \
|
"UPDATE tasks SET status = ?1, review_rounds = review_rounds + 1, updated_at = ?2 \
|
||||||
WHERE id = ?3 AND status = ?4"
|
WHERE id = ?3 AND status = ?4 AND deleted_at IS NULL"
|
||||||
} else {
|
} else {
|
||||||
"UPDATE tasks SET status = ?1, updated_at = ?2 \
|
"UPDATE tasks SET status = ?1, updated_at = ?2 \
|
||||||
WHERE id = ?3 AND status = ?4"
|
WHERE id = ?3 AND status = ?4 AND deleted_at IS NULL"
|
||||||
};
|
};
|
||||||
let affected = guard
|
let affected = guard
|
||||||
.execute(sql, params![new_status, now, id, expected])
|
.execute(sql, params![new_status, now, id, expected])
|
||||||
|
|||||||
21
docs/todo.md
21
docs/todo.md
@@ -56,6 +56,12 @@
|
|||||||
- [ ] B-260616-11 [P2] — **AI 消息 `-`/`+` 列表/diff 无视觉效果**。marked 实测两个出口:①裸 `-`/`+` 混用 → GFM 要求同列表标记一致,marked 拆成**两个独立 `<ul>`** 且 `-`/`+` 被 eat 当 marker(用户看到的符号消失,两个分离单项列表);②```diff 代码块 → `<pre><code class="language-diff">` **无 hljs 高亮**(ai-md.css 未集成 highlight.js),`-`/`+` 字面纯文本无红绿。根因层 marked 行为合规,缺的是 **diff 高亮集成 + 裸 diff 文本识别**。改动(待定):①集成 hljs 覆盖 ```diff(关联已知待办「aichat交互体验改进方案-2026-06-14」2.2 代码块高亮)②裸 `-`/`+` diff 文本预处理识别。— src/composables/useMarkdown.ts + src/styles/ai-md.css。**②子项已修(第㉖批 2026-06-16·主代理直修)**:useMarkdown.ts L40-41 import diff + L63 registerLanguage('diff', diff)(16→17 语言),```diff 代码块经 highlightCode getLanguage('diff') 命中 → hljs-addition/deletion token class → github-dark.css 红绿。**①子项仍②类待复现**:裸 -/+ 文本预处理识别(需确认 AI 实际输出格式)。vue-tsc exit 0。
|
- [ ] B-260616-11 [P2] — **AI 消息 `-`/`+` 列表/diff 无视觉效果**。marked 实测两个出口:①裸 `-`/`+` 混用 → GFM 要求同列表标记一致,marked 拆成**两个独立 `<ul>`** 且 `-`/`+` 被 eat 当 marker(用户看到的符号消失,两个分离单项列表);②```diff 代码块 → `<pre><code class="language-diff">` **无 hljs 高亮**(ai-md.css 未集成 highlight.js),`-`/`+` 字面纯文本无红绿。根因层 marked 行为合规,缺的是 **diff 高亮集成 + 裸 diff 文本识别**。改动(待定):①集成 hljs 覆盖 ```diff(关联已知待办「aichat交互体验改进方案-2026-06-14」2.2 代码块高亮)②裸 `-`/`+` diff 文本预处理识别。— src/composables/useMarkdown.ts + src/styles/ai-md.css。**②子项已修(第㉖批 2026-06-16·主代理直修)**:useMarkdown.ts L40-41 import diff + L63 registerLanguage('diff', diff)(16→17 语言),```diff 代码块经 highlightCode getLanguage('diff') 命中 → hljs-addition/deletion token class → github-dark.css 红绿。**①子项仍②类待复现**:裸 -/+ 文本预处理识别(需确认 AI 实际输出格式)。vue-tsc exit 0。
|
||||||
- [x] ✅(第㉗批 2026-06-16·workflow) B-260616-19 [P2] — **知识库详情窄屏标题挤压成竖线(一行一字)**。三因子叠加(Knowledge.vue):①`.kn-layout` grid `grid-template-columns: 360px 1fr`(L567)——左列表死钉 360px、右详情 `1fr` 拿剩余,**无响应式断点**;窗口窄(如总宽 500px,减 padding 40+gap)详情列塌缩到 ~80px 甚至更小。②`.detail-title`(L625)`font-size:18px` + `word-break:break-word` —— 窄列里中文每字宽度 > 列宽,逐字换行 → 竖线化。③`.detail-actions`(L626)`flex-shrink:0` —— 编辑/发布/拒绝 3 按钮不缩,优先占位,把 `.detail-title-row`(`flex:1`) 挤到零头。`.kn-detail-panel`(L570-576) 无 `min-width` 兜底。改动(待定):①grid 列宽改 `minmax(240px,360px) 1fr` + `@media (max-width:760px)` 切单列(`grid-template-columns:1fr`,列表详情上下堆叠);②详情面板加 `min-width:0` 配合标题行 `min-width` 防塌缩;③可选标题字号响应式降级(18px→15px)。— src/views/Knowledge.vue。**低风险纯 CSS**,无逻辑/i18n/数据变动。
|
- [x] ✅(第㉗批 2026-06-16·workflow) B-260616-19 [P2] — **知识库详情窄屏标题挤压成竖线(一行一字)**。三因子叠加(Knowledge.vue):①`.kn-layout` grid `grid-template-columns: 360px 1fr`(L567)——左列表死钉 360px、右详情 `1fr` 拿剩余,**无响应式断点**;窗口窄(如总宽 500px,减 padding 40+gap)详情列塌缩到 ~80px 甚至更小。②`.detail-title`(L625)`font-size:18px` + `word-break:break-word` —— 窄列里中文每字宽度 > 列宽,逐字换行 → 竖线化。③`.detail-actions`(L626)`flex-shrink:0` —— 编辑/发布/拒绝 3 按钮不缩,优先占位,把 `.detail-title-row`(`flex:1`) 挤到零头。`.kn-detail-panel`(L570-576) 无 `min-width` 兜底。改动(待定):①grid 列宽改 `minmax(240px,360px) 1fr` + `@media (max-width:760px)` 切单列(`grid-template-columns:1fr`,列表详情上下堆叠);②详情面板加 `min-width:0` 配合标题行 `min-width` 防塌缩;③可选标题字号响应式降级(18px→15px)。— src/views/Knowledge.vue。**低风险纯 CSS**,无逻辑/i18n/数据变动。
|
||||||
|
|
||||||
|
### 💡 2026-06-16 新需求(已分析·待实施)
|
||||||
|
|
||||||
|
> 功能需求,已走查定位链路 + 方案记录,待用户确认后实施。
|
||||||
|
|
||||||
|
- [ ] F-260616-01 [P2] — **aichat Agentic 最大循环轮次支持配置(Settings)**。现状:`MAX_AGENT_ITERATIONS=10` 硬编码常量(`agentic.rs:33`),复杂 agentic 任务未收敛即被截断,用户无法调。**黄金参考:`llm_concurrency`**——项目唯一成熟的「前端数字配置→AppState 字段→热改 command→透传 loop 形参」范式,本需求 1:1 复刻。改动 8 处:①`state.rs` AppState 加 `agent_max_iterations: Arc<AtomicUsize>`(默认 10) ②`agentic.rs` 常量改名 `DEFAULT_MAX_AGENT_ITERATIONS` + `run_agentic_loop` 增形参 `max_iterations` + 循环(L156)/超限消息(L321-332)用形参 + `try_continue_agent_loop`(L478) 补传 ③`commands.rs` `ai_chat_send`(L114) 补传 + 新 command `ai_set_agent_max_iterations`(clamp 1-50 store) ④`lib.rs` invoke_handler(L125 区)注册 ⑤`api/ai.ts` 新 `setAgentMaxIterations`(仿 L73 `setConcurrencyConfig`) ⑥`Settings.vue` reactive(L615 区)+UI 数字 input(min1 max50,紧挨并发控制 L268)+watch 持久化+`syncAgentMaxIterations`+onMounted 推后端 ⑦i18n 补 zh/en 键。**生效时机**:loop 入口 `load` 取快照传值,当前 loop 锁定边界,热改下次发消息生效(防边界飘移;与 `llm_concurrency` 传 Arc 实时反映的区别)。key `df-ai-agent-max-iterations`,范围 1-50 双 clamp。`agentic.rs:27-32` 注释已预留此扩展点。**低风险,复刻现成范式无新机制**。— 详案见本地 plan 文件 `quizzical-prancing-hennessy.md`。
|
||||||
|
|
||||||
### 🔧 任务模块全栈核对(2026-06-16 · Explore 代理并行取证)
|
### 🔧 任务模块全栈核对(2026-06-16 · Explore 代理并行取证)
|
||||||
|
|
||||||
> 来源:[任务模块问题分析-2026-06-16.md](./05-代码审查/任务模块问题分析-2026-06-16.md)。原清单 18 项核对:真 bug 7 项 + #8 路由漏注册去重(B-260616-09 已存在)、增强 5 项、假/部分假 3 项、去重 3 项。详见文档速览矩阵。
|
> 来源:[任务模块问题分析-2026-06-16.md](./05-代码审查/任务模块问题分析-2026-06-16.md)。原清单 18 项核对:真 bug 7 项 + #8 路由漏注册去重(B-260616-09 已存在)、增强 5 项、假/部分假 3 项、去重 3 项。详见文档速览矩阵。
|
||||||
@@ -85,7 +91,20 @@
|
|||||||
- [ ] F-260616-06 阶段2 工作流联动(task_id+回调+DAG模板)
|
- [ ] F-260616-06 阶段2 工作流联动(task_id+回调+DAG模板)
|
||||||
- [ ] F-260616-07 阶段3 AI 执行闭环(advance_task/run_workflow 工具+AiNode+自审)+ **F-03收口三件**(advance_task注册AI工具+update_task描述/schema移status+df-storage tasks白名单移status,同步落地防AI工具行为不一致)
|
- [ ] F-260616-07 阶段3 AI 执行闭环(advance_task/run_workflow 工具+AiNode+自审)+ **F-03收口三件**(advance_task注册AI工具+update_task描述/schema移status+df-storage tasks白名单移status,同步落地防AI工具行为不一致)
|
||||||
- [ ] F-260616-08 阶段4 Git 集成(kind+git闸门+worktree)
|
- [ ] F-260616-08 阶段4 Git 集成(kind+git闸门+worktree)
|
||||||
- [ ] **CR-260616-01 代码审查 — 阶段1推进链(batch㉘)** 范围:df-nodes/{task_state_machine.rs,task_advance_node.rs,lib.rs,Cargo.toml}+crud.rs(advance_status_atomic)+models.rs+migrations.rs(V15)+task.rs(advance_task IPC)+lib.rs注册+TaskDetail.vue(ADVANCE_MAP)+api/task.ts(advance)+i18n zh/en taskDetail.ts+tool_registry.rs/tests project_soft_delete.rs/types.ts(补review_rounds字段)。内容:①状态机转换矩阵正确性(对照报告§8,退回/终态/非法跳过)②advance_task CAS原子写`WHERE status=expected`防TOCTOU ③advance_status_atomic是否唯一status/review_rounds写入路径(防旁路写)④review_rounds退回递增逻辑+V15迁移幂等(PRAGMA column_exists)⑤F-03停下决策正确性(AI update_task依赖status,收口延后阶段3三件)⑥前端ADVANCE_MAP与后端can_transition一致性(勿前端臆断合法性)⑦指派外补字段(tool_registry create_task/tests fixture/types.ts)最小性非超范围 ⑧TaskAdvanceNode Node trait实现正确性(阶段2 DAG预留,config读task_id/target_status)
|
- [x] ✅ **CR-260616-01 代码审查完成** → 审查登记已迁 [待审查.md](./待审查.md)(职责分离:审查队列独立,不进 todo)。结论 🔴0 🟡6 ⚪4 质量优,8 维度全过。**待修项 CR-01-A~I 见下方推进区**。
|
||||||
|
|
||||||
|
> **审查发现待修项(2026-06-16 · CR-260616-01)**:
|
||||||
|
- [x] ✅(cr01-fixes·wu4r8ejcp) **CR-01-A** [P1] TaskDetail.vue 补 `.status-testing`(橙)/`.status-blocked`(红 danger 边框)CSS;Tasks.vue 已有/Dashboard 不用此体系无需补
|
||||||
|
- [x] ✅(cr01-fixes·wu4r8ejcp) **CR-01-B** [P1] crud.rs advance_status_atomic 两分支 CAS SQL 加 `AND deleted_at IS NULL`,回收站任务 CAS 必败返 None(D-02 软删收口)
|
||||||
|
- [x] ✅(cr01-fixes·wu4r8ejcp) **CR-01-C** [P2] task_advance_node.rs:50 错误信息改 `ALL_STATES.join("/")` DRY(运行时文案不变)
|
||||||
|
- [ ] **CR-01-D** [P2] task_advance_node.rs:62 同态拒绝(from==to)/非法转换(can_transition false)错误区分(现合并 `InvalidState`,前端无法分辨)— **②类留**(需改错误枚举判断)
|
||||||
|
- [x] ✅(cr01-fixes·wu4r8ejcp) **CR-01-E** [P2] src-tauri/src/state.rs:240 build_registry 补注释「TaskAdvanceNode 未注册(阶段2联动时加),勿删」
|
||||||
|
- [x] ✅(cr01-fixes·wu4r8ejcp) **CR-01-F** [P2] crud.rs 白名单注释补 review_rounds 专用路径(仅 advance_status_atomic,防误补破坏收口)
|
||||||
|
- [ ] **CR-01-G** [P3] TaskDetail.vue:218 advance 失败错误走 i18n 分级(`e.toString()` 非空直显后端中文,en locale 也中文)— **②类留**(需 i18n 分级改造)
|
||||||
|
- [x] ✅(cr01-fixes·wu4r8ejcp) **CR-01-H** [P3] task_advance_node.rs 测试改名 `concurrent_cas_change_detected` → `advance_succeeds_after_prior_status_change`(反映实际测正常推进)
|
||||||
|
- [x] ✅(cr01-fixes·wu4r8ejcp) **CR-01-I** [P3] i18n `taskDetail.advancing` 接文案(推进按钮 advancing 时显示「推进中...」,冗余 key 转实引用)
|
||||||
|
>
|
||||||
|
> **修复核查(主代理独立·2026-06-16)**:7 项真实落地(Read+git diff+cargo check --workspace exit 0.83s+vue-tsc 0 核实)。**注意:验证 agent CR-01-E 证据张冠李戴**(报 df-workflow/state.rs,实改 src-tauri/state.rs),改动正确但证据幻觉——验证 agent 可信度打折,主代理核查兜底。D/G ②类留。
|
||||||
|
|
||||||
### ⏸️ 待用户授权/确认(巡检悬挂项·2026-06-16)
|
### ⏸️ 待用户授权/确认(巡检悬挂项·2026-06-16)
|
||||||
|
|
||||||
|
|||||||
69
docs/待审查.md
Normal file
69
docs/待审查.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# 待审查队列
|
||||||
|
|
||||||
|
> **职责分离**:
|
||||||
|
> - **主会话**(编码合并后 / 巡检)→ 【**写入**】"当前队列"区,登记待审查项(范围 + 维度 + commit)。
|
||||||
|
> - **审查 agent**(独立会话 / workflow)→ 【**读取**】"当前队列",执行审查,完成回填结论 + 移到"已审归档"。
|
||||||
|
>
|
||||||
|
> 这里**只放审查登记**,不放推进待办(推进待办见 [todo.md](./todo.md))。
|
||||||
|
> 主会话**不在这里做审查**,只登记 + 读 todo 推进。审查发现的【待修代码项】回流 todo 作推进待办。
|
||||||
|
|
||||||
|
## 审查规则(审查 agent 遵守)
|
||||||
|
|
||||||
|
- 只读审查,**不改代码**。
|
||||||
|
- **独立 grep/read 核验源码,不信文档 / 会话描述 / 设计声明的结论**(防上下文污染)。
|
||||||
|
- 每条 finding 须 `file:line` 源码佐证 + evidence。
|
||||||
|
- 严重度:high(破坏性 / 数据错 / 回归) / med(逻辑瑕疵 / 边界漏) / low(风格 / 可读)。
|
||||||
|
- 完成回填:总体 verdict(PASS / ISSUES / WATCH)+ high/med/low 清单 + 待修项回流 todo。
|
||||||
|
|
||||||
|
## 状态图例
|
||||||
|
|
||||||
|
🟡 待审 / 🔵 审查中 / ✅ 已审(结论) / 🔴 待修(有 high 问题)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 当前队列
|
||||||
|
|
||||||
|
### CR-260616-01-fixes 审查待修项修复批次 — 🟡 待审(低优先,主代理已核查)
|
||||||
|
|
||||||
|
- **状态**: 🟡 待审(低优先 — 小修+主代理已独立核查双绿,独立审查 agent 可选核)
|
||||||
|
- **来源**: CR-260616-01 审查待修项①类7项(cr01-fixes workflow `wu4r8ejcp`)
|
||||||
|
- **改动文件**:
|
||||||
|
- `src/views/TaskDetail.vue`(.status-testing/.status-blocked CSS + advancing 接文案)
|
||||||
|
- `crates/df-storage/src/crud.rs`(CAS SQL 加 `AND deleted_at IS NULL` 两分支 + 白名单注释)
|
||||||
|
- `crates/df-nodes/src/task_advance_node.rs`(ALL_STATES.join DRY + 测试改名)
|
||||||
|
- `src-tauri/src/state.rs`(build_registry 补 TaskAdvanceNode 未注册注释)
|
||||||
|
- **主代理核查**: cargo check --workspace exit 0(仅 pre-existing warning)+ vue-tsc exit 0 + git diff 边界合规(4 文件符合 agent 领地)
|
||||||
|
- **审查关注点**:①CR-01-B CAS 补 deleted_at 语义正确性(回收站任务必败)②CR-01-A CSS 配色跨视图一致 ③CR-01-C DRY 无运行时文案变更
|
||||||
|
- **未做**: CR-01-D(错误枚举区分)/CR-01-G(i18n 分级)②类留 todo
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 已审归档
|
||||||
|
|
||||||
|
### CR-260616-01 任务推进链(batch28) — ✅ 已审
|
||||||
|
|
||||||
|
- **commit**: `d2cb38c` 新增: 任务推进链(7态状态机+advance_task CAS原子写)+软删除+前后端7态对齐
|
||||||
|
- **审查时间**: 2026-06-16(5 路并行多角度·防代入独立核验)
|
||||||
|
- **决策依据**: D-260616-01(前端7态对齐) / D-02(任务软删除) / D-03(advance_task 走 df-nodes Node trait) / D-04(阶段1先行)
|
||||||
|
- **总体结论**: 🔴0 🟡6 ⚪4 — **质量优**
|
||||||
|
- **8 点 checklist 全过**:
|
||||||
|
- 状态机矩阵 ✅(7态15转换,前后端单一真相源)
|
||||||
|
- CAS 原子 ✅(`WHERE id AND status=expected` + affected=0 报错)
|
||||||
|
- 退回累加原子 ✅(同 UPDATE)
|
||||||
|
- V15 迁移幂等 ✅(版本门控 + column_exists 双层,八版零事故)
|
||||||
|
- IPC 真 thin ✅(D-03 守住,task.rs 仅 3 行转发)
|
||||||
|
- i18n 成对零遗漏 ✅(28 key)
|
||||||
|
- create_task 不暴露 rounds ✅
|
||||||
|
- 测试 25 个 ✅
|
||||||
|
- **F-03 status 双写 = 已知延后**(阶段3 三件同落地,非新缺陷)
|
||||||
|
- **范围外澄清**: df-ai/lib.rs(`mod retry`) + script_node.rs(`shell_type`) = 同 commit 无关连带改,零风险误报
|
||||||
|
- **待修项回流 todo**(CR-01-A~I,见 [todo.md](./todo.md) "审查发现待修项"区):
|
||||||
|
- [P1] **CR-01-A** TaskDetail.vue scoped style 补 `.status-testing`/`.status-blocked`(D-01 前端7态遗漏,testing/blocked 徽章裸渲染丢样式;同查 Tasks.vue/Dashboard)
|
||||||
|
- [P1] **CR-01-B** crud.rs advance_status_atomic CAS SQL 加 `AND deleted_at IS NULL`(get_by_id 宏无软删过滤→回收站任务可被 advance,D-02 软删对齐遗漏,语义错乱)
|
||||||
|
- [P2] **CR-01-C** task_advance_node.rs:46 错误7态硬编码改 `ALL_STATES.join("/")`(DRY 单一事实源)
|
||||||
|
- [P2] **CR-01-D** task_advance_node.rs:62 同态拒绝(from==to)/非法转换区分(现合并 InvalidState,前端无法分辨)
|
||||||
|
- [P2] **CR-01-E** state.rs build_registry 注释补「task_advance 未注册(阶段2联动时加)」
|
||||||
|
- [P2] **CR-01-F** crud.rs:325 白名单注释补 review_rounds 专用路径
|
||||||
|
- [P3] **CR-01-G** TaskDetail.vue:218 advance 失败错误走 i18n 分级(en locale 也中文)
|
||||||
|
- [P3] **CR-01-H** task_advance_node.rs:297 测试改名(实际未测 CAS 失败)
|
||||||
|
- [P3] **CR-01-I** i18n `taskDetail.advancing` 冗余 key 处理
|
||||||
@@ -237,6 +237,12 @@ fn build_registry() -> NodeRegistry {
|
|||||||
registry.register("ai", |_config| {
|
registry.register("ai", |_config| {
|
||||||
Box::new(df_nodes::ai_node::AiNode)
|
Box::new(df_nodes::ai_node::AiNode)
|
||||||
});
|
});
|
||||||
|
// 未在此注册的已实现节点:
|
||||||
|
// - TaskAdvanceNode(df_nodes::task_advance_node, impl Node trait 已就绪):
|
||||||
|
// 推进链 F-01~04 当前手动推进(IPC 直驱 advance_task),DAG 形态为阶段 2
|
||||||
|
// 工作流联动(run_workflow task_id + 完成回调 advance_task + DAG 模板)预留。
|
||||||
|
// 届时在此 register("task_advance", ...) 注入 Arc<Database>。
|
||||||
|
// 非遗漏,勿删 task_advance_node.rs。
|
||||||
registry
|
registry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
:class="act.variant"
|
:class="act.variant"
|
||||||
:disabled="advancing"
|
:disabled="advancing"
|
||||||
@click="handleAdvance(act.target)"
|
@click="handleAdvance(act.target)"
|
||||||
>{{ $t(act.label) }}</button>
|
>{{ advancing ? $t('taskDetail.advancing') : $t(act.label) }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-item">
|
<div class="info-item">
|
||||||
@@ -340,6 +340,9 @@ onBeforeUnmount(() => {
|
|||||||
.status-review { background: rgba(255,217,61,0.2); color: var(--df-warning); }
|
.status-review { background: rgba(255,217,61,0.2); color: var(--df-warning); }
|
||||||
.status-done { background: rgba(100,255,218,0.15); color: var(--df-success); }
|
.status-done { background: rgba(100,255,218,0.15); color: var(--df-success); }
|
||||||
.status-abandoned { background: rgba(255,107,107,0.2); color: var(--df-danger); }
|
.status-abandoned { background: rgba(255,107,107,0.2); color: var(--df-danger); }
|
||||||
|
/* D-260616-01:7 态新增 — testing(橙警告,近 review 区分)/blocked(红 danger,与 cancelled 区分用实心边框)。配色与 Tasks.vue 一致保持跨视图统一 */
|
||||||
|
.status-testing { background: rgba(255,152,0,0.2); color: #ff9800; }
|
||||||
|
.status-blocked { background: rgba(255,107,107,0.12); color: var(--df-danger); border: 0.5px solid var(--df-danger); }
|
||||||
|
|
||||||
.priority-badge {
|
.priority-badge {
|
||||||
font-size: 10px; font-weight: 500;
|
font-size: 10px; font-weight: 500;
|
||||||
|
|||||||
Reference in New Issue
Block a user