Repository navigation
fix(dashboard): keep completed task history read-only - #6656
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> (cherry picked from commit f641857ec10f78402cb270b603f65ab0ef4d7fb9)
|
Validated exact head Production packaged UI with disposable real SQLite verified context-preserving resume, terminal-proof refusal, owner lease retirement, completed-history read-only controls, Escape focus return and measured 390 px/reduced motion. The exercised UI/lifecycle bytes are preserved in this latest-main follow-up. There are no runtime/API/provider or configuration changes, and no installed-App adoption claim. Independent exact-head review, required hosted checks, merge readiness and maintainer authority remain separate. |
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
APPROVE · head 07aabe6f6c62d01d963a7ecb5ba6aaf6742d64e1
动机
查看 Goal 已完成历史的用户,会遇到旧来源只记录 done=true、没有可选 status 的任务。旧详情页把这条已完成记录显示为“待执行”,还提供管理与再次完成按钮;阅读历史变成了一个容易误操作的入口。本次修改让同一记录显示“已完成”、保留要求与证据,并明确为只读记录。独立构建页面已复现这个前后差异;显式暂停的任务仍有恢复入口,普通未完成任务继续使用原操作流程。
这里交付的是历史详情的状态与操作一致性,不是一次新的任务生命周期设计。它不证明已安装 App 已采用,也不证明整个暂停、恢复、长期执行或跨平台旅程已完成。用户查看已知历史不需要重复描述任务、填写证明或新增确认;真正修改未完成任务仍经过原有预览与权限检查。
我先读原 PR、已有评论与其所接续的已合入 #6632,再按实际基线 488e4438e0e51eca023ac3f5e690603120851b0c 的 frontend-delivery.md Task-first delivery / 从用户任务开始 和使用指南 4.1 Tasks 列表与看板视图 判断:既有记录必须可理解、失败读取保留已显示内容,实际打包页面要与真实状态 owner 配合验证。作者声明和测试数量不代替这个用户结果。
改动思路
最小可行方案就是让详情页已有的 todoCompleted 判断负责全部完成呈现。什么也不改会保留可复现的误导;在后端重写旧记录、另建状态版本或新增前端生命周期 owner 都超出了这个问题。当前提案复用现有判断,没有引入这些机制。
本 PR 的边界是完成历史详情的兼容呈现;行政写回的最终投递和已安装 App 的采用继续独立验收。
这个判断优先使用显式状态,仅在状态缺失时回退到记录的 done。所以不能简单把所有判断改成 done:持久化的延期记录可能还带着 done=true,它仍须可恢复。以下是准确头的源码与实测摘要:
| 任务输入 | 旧详情 | 当前详情 |
|---|---|---|
done=true,状态缺失 |
待执行、可发起修改 | 已完成、只读、完成提示 |
显式 status=done |
已完成、只读 | 保持相同 |
显式延期,保留 done=true |
仍可恢复 | 保持相同 |
| 显式受阻或普通未完成 | 原状态和原操作 | 保持相同 |
表格说明的是显示分支,不是新的执行权限。实际修改仍由原有 TypeScript Todo、租约与 Chat action owner 决定;页面隐藏按钮既不替代后端拒绝,也不会启动工作。只读来源、当前任务不可读及仅能查看原请求的分支仍先于操作区生效。
具体改动
完整提案只有两个文件,+25/-6。context-drawer.tsx 的六处表达式统一复用完成判断:顶部样式与标签、状态字段、下一转换的默认文案、操作区是否出现,以及底部只读提示。文案、导航、回调、序列化和实际状态转换都沿用原实现。todo-ownership-smoke.mjs 在原真实消费者 smoke 中增加四类数据与双语断言,直接经过现有 schema、adapter 和 React 详情组件,没有用一个返回“已完成”的替身代替被评审规则。
关键代码讲解
ContextDrawer.todoCompleted(context-drawer.tsx:435)是原来已有的局部判断:显式完成优先,状态缺失才读取兼容字段。当前 :649 和 :665 的标签与字段采用它,避免同一个任务在卡片与详情中出现相反状态。
ContextDrawer 的操作区(:685)现在同时要求本地可操作且任务未完成;底部 :753 则为同一完成记录显示只读说明。它只控制当前详情的可见交互,原 previewTodoTransition 和真实 effect admission 没有改变。
workspaceAgentTodoFromItem(personal-workspace-model.ts:70)保持原归属:原始要求、负责人和证据被传给详情,显式延期记录不会被兼容完成标记冻结。新增 smoke(todo-ownership-smoke.mjs:47)特意检验相反方向,避免修好历史展示却误伤恢复入口。
我独立执行了实际 base 与当前头的原 ownership SSR、workspace contract,以及普通 Chat 构建和源码完整性验证;两端都通过。随后把同一份当前消费者断言以相同的相对导入调整方式编译到两端:原基线明确失败于 Completed history remains read-only,当前头通过。原基线自己的旧 smoke 仍通过,因此新增用例确实补到了缺失分支。
实际 Ego 页面使用正常构建资产和独立的真实 SQLite/HTTP owner。中文页面对照覆盖旧记录、显式完成、延期、受阻和普通未完成;后四类显示与操作保持相同。英文 390px 页面进一步只在 status 传输中省略旧记录的可选状态,并使历史请求明确返回 503;旧页面仍展示修改按钮,当前页面保持完成只读。恢复真实历史接口到 200 后,两端都能读到真实分页记录,当前页继续保持只读。没有把历史接口伪造为一个“修好”的结果。
最后的窄屏完成详情实际读到了原备注与证据,页面宽度和文档宽度都是 390px;该次 prefers-reduced-motion 读回为 true,Escape 返回原历史卡片。较早一次设置在刷新后失效、观察为 false,未把那些状态算作 reduced-motion 验证。直接从普通未完成任务发起无执行证明的完成预览,真实后端拒绝,页面明确说明“尚未标记完成”;没有由本次显示修复取得完成权。
对主干的风险
主要风险是把延期误当完成,或在历史暂时不可读时重新暴露修改入口;本轮分别从显式状态反例和真实构建页面的 503→200 路径核验。这里只扩展既有兼容显示,不新增枚举、协议、激活开关、消息或调度规则,也没有 Agent 指令压缩、默认关闭能力隔离或账户权限变化。没有新增 Python 决策源;同一已有局部判断足以承担这个边界。
差分语义 advisory 在完整 semantic smoke 之前执行,两者通过。原生 premerge 的 3 项 direct、5 项 selected 全部通过,两文件公开边界扫描无错误或警告;普通构建包含 Dashboard 类型检查。未查询、轮询或等待 hosted CI,也不把这些局部检查当作安装、原生 Windows或持续运行资格。
补充的真实 SQLite 恢复操作保留一个独立限制:base 与 head 都提交了 status=open,保留原备注和证据,然后返回 canonical_update_projection_pending。当前头原操作重试也仍是显示投递待恢复,不能写成恢复旅程成功。两端 action、生命周期、provider 和投递源码完全相同,错误代码与失败阶段相同;本 PR 改动的完成呈现则有独立的基线失败、当前通过和真实页面证据。因此保留该原有投递失败,未用它为本次修改背书,也不要求这两处 UI 表达式承担另一个 owner 的修复。
早期私有浏览器夹具还错误省略了历史 API 的必填状态,导致前端 schema 拒绝;后续资格验证已改为仅省略 status 来源的可选字段、显式历史 503 和未修改的真实 200 接口。没有通过改产品断言、改阈值或隐去失败让结果变绿。
我的整体评价
批准这个准确头。它完成了与原问题相称的兼容呈现修复:原已完成记录能被准确阅读,不再要求用户面对无意义的修改入口;显式暂停和未完成任务也没有被一并冻结。整个两文件提案已读,实际打包消费者与相反状态均有独立证据。
面向后续维护的小重构已经包含在本 PR:六处判断收敛到原有局部 predicate,原消费者 smoke 同时约束完成与暂停语义。没有必要新增共享状态机、再拆 helper 或制造后续任务。行政写回最终投递、已安装 App、完整暂停恢复及长期资格仍保留各自未验证状态;这份 COMMENTED 作者账户结论不是 GitHub 正式自批准,也不授予合并权限。
English verdict: APPROVE — 07aabe6f6c62d01d963a7ecb5ba6aaf6742d64e1 consistently renders legacy completed Tasks read-only while preserving explicit paused/open behavior. Identical consumer red/green, normal builds, real compiled SQLite-backed UI, history failure/retry and proof refusal cover the changed invariant. The identical baseline/head projection-delivery failure remains separate and unresolved.
Task details could treat a retained completed record as open when its older projection had
done=trueand no explicitstatus. Reuse the existing completion predicate for labels, action visibility and the read-only notice. Explicit blocked/deferred status still offers resume. No lifecycle, API or navigation contract changes.This is a two-file follow-up to #6632. The existing real-consumer SSR smoke reproduces the regression before the fix and covers both locales, legacy/canonical completion and blocked/deferred resume after it. The package was rebuilt and verified; Ego with disposable real SQLite also checked resume/context preservation, terminal-proof refusal, atomic owner pause, completed history without mutation controls, Escape focus return and 390 px/reduced motion. The UI and lifecycle owner blobs match the exercised package. Installed App adoption is not claimed.
The future-facing pass reuses one existing predicate and the existing consumer smoke; it introduces no new abstraction or decision owner. Required hosted checks, independent exact-head review and merge readiness remain separate.