Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a73c84b5be | ||
|
|
05c13a42b1 | ||
|
|
53354996f2 | ||
|
|
cf74a200e8 | ||
|
|
f7ae1ecce6 | ||
|
|
b184bfb109 | ||
|
|
f76cce9e32 | ||
|
|
95c2ec260c | ||
|
|
733f32c671 | ||
|
|
8d8600024d | ||
|
|
cb7e25439a | ||
|
|
3cc6438030 | ||
|
|
0952b50aef | ||
|
|
9c31d3c308 | ||
|
|
b8319d24f2 | ||
|
|
dbdec82466 | ||
|
|
fe8d08be21 | ||
|
|
dca4265e37 |
@@ -8,10 +8,10 @@ product_contract_source: ce-plan-bootstrap
|
||||
|
||||
# 多人协作存储与分布式演进方案 - Plan
|
||||
|
||||
修订:r2;确认状态:**已批准(2026-10-11 用户指示「按方案开始改造」)**;推进状态:U1–U7 **代码与测试已合入**(Backend [#164](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Backend/pulls/164);Dev [#410](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/410)/[#439](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/439)/[#442](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/442);闭卡 [#424](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/424) 等)。正确性矩阵 A1–A7 与 B1 冒烟已绿(CI/SELF);容量合同 B2/B3/B5 contract 与 C2 正式双实例负载 **测量中/待回填**;双主机 C3、运维演练 C4/C5 未做。**不承诺容量数字,不放行第二实例承接写请求**,直至检查单对应项有可复核证据。
|
||||
修订:r2.3;确认状态:**已批准(2026-10-11 用户指示「按方案开始改造」)**;推进状态:U1–U7 **代码与测试已合入**(Backend [#164](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Backend/pulls/164);Dev [#410](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/410)/[#439](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/439)/[#442](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/442);闭卡 [#424](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/424) 等)。正确性 A1–A7 与 B1 已绿(CI/SELF)。容量合同 B2/B3/B5 contract 与双实例 C2 **本机 SELF 窗口已跑通**(见[容量报告](../records/2026-10-12-u7-capacity-window-report.md))。2026-10-12 用户决定不做容量重放;同日 B6 pgbench、C4 断连、C5 库恢复已有本机 SELF(见[运维演练报告](../records/2026-10-12-u7-ops-drill-report.md))。2026-10-13 未配置对象存储时的上传 panic 已修,C5 工件恢复 K4 重测为 SELF 通过。**SELF≠GATE/REPLAY**,双主机 C3 未做——**仍不放行第二实例承接写请求**。
|
||||
需求来源:2026-10-11 用户要求完善 SQLite、PostgreSQL/pgvector、Redis 分工;随后确认“10–100 人,多人多项目多会话并行,未来支持多服务分布式”。
|
||||
需求负责人:weichen;方案编制:Codex;实施及运维负责人:待指定。更新时间:2026-10-12(Asia/Shanghai)。
|
||||
关联任务:方案卡已归档 `.task/archive/feature-collaboration-storage-plan.md`;U1–U7 实施卡均已归档;当前收尾与容量窗口见 Dev `.task/feature-u7-capacity-wrap-measure.md`。放行检查单:Dev `docs/release-multi-instance.md`。
|
||||
需求负责人:weichen;方案编制:Codex;实施及运维负责人:待指定。更新时间:2026-10-13(Asia/Shanghai)。
|
||||
关联任务:方案与 U1–U7 实施卡已归档;容量收尾见 Dev `.task/feature-u7-capacity-wrap-measure.md`。放行检查单:Dev `docs/release-multi-instance.md`。
|
||||
正文中的源码路径以 Agent-System-Dev 为根;工作包中的 `internal/` 简写指 `modules/backend/internal/`;文内相对链接以本文为根。
|
||||
|
||||
## 1. 推荐结论与边界
|
||||
@@ -246,8 +246,8 @@ SQLite 本身支持可靠事务与多人经同一应用访问;WAL 提升读写
|
||||
|
||||
必需观测:API P95/P99与预期/非预期错误,DB pool wait/连接数/慢查询/锁等待,队列长度/最老年龄,run 租约/过期写拒绝/未知副作用,SSE cursor lag/补查次数,Redis 错误与降级,检索耗时/召回抽样,备份时间与恢复结果。日志只记录 request/run/owner 的安全标识,不记录 DSN、密钥或文档正文。
|
||||
|
||||
r1 为方案与 SELF 调查记录。r2 起:U1–U7 代码与测试已合入且正确性 CI 绿;容量阈值的正式测量、双主机部署目标、灾难恢复运维演练仍待窗口证据。本地 SELF 压测不能冒充 GATE/REPLAY 放行。部署与第二实例写流量仍未授权。
|
||||
r1 为方案与 SELF 调查记录。r2 起:U1–U7 代码与测试已合入且正确性 CI 绿。r2.1:本机双实例 contract 容量窗口(ladder / 60m / 2h)SELF 全过,见[容量报告](../records/2026-10-12-u7-capacity-window-report.md)。r2.2:用户于 2026-10-12 明确不做容量重放;同日完成 B6 pgbench、C4 PG/Redis 断连、C5 物理备份与 pg_dump 恢复的本机 SELF,见[运维演练报告](../records/2026-10-12-u7-ops-drill-report.md)。C4 通过。C5 的库恢复通过(RPO 64 秒,RTO 4 秒),工件上传在未配置对象存储时 panic,K4 失败,产品代码未改。r2.3:2026-10-13 在 store 边界把带类型的空对象存储当作未配置并回落本地目录;同日 C5 重测 K1–K7 均为 SELF 通过(RPO 65 秒,RTO 3 秒,K4 五个工件 sha256 一致且跨用户拒绝)。本地 SELF 不能冒充 GATE/REPLAY 放行;双主机仍缺。部署与第二实例写流量仍未授权。
|
||||
|
||||
方案静态审阅及修订处置见[审阅记录](../records/2026-10-11-collaboration-storage-plan-review.md)。进程级黑盒相对库级 Manager 测试的漏检教训见[经验条目](../records/2026-10-12-lesson-http-multi-instance-vs-manager-tests.md)。Agent 审阅不替代人工批准或实现验收。
|
||||
|
||||
首选下一增量是 **完成本机容量测量窗口并回填检查单**(`--seed contract` + 双实例 `ladder` / `sustained60m` / `sustained2h`,入口 `tests/load/collaboration/`;结果写入 Dev `docs/release-multi-instance.md` 与本仓容量报告)。其后候选项:**C3 双主机验证**(需用户指定第二主机)或 **C4/C5 运维演练**(PG/Redis 断连恢复与备份恢复)。不要在容量与双进程负载未过前开放第二实例写。各实现任务启动前复核在途 PR 与依赖 SHA,再按 Dev 的 evidence/task-sync/组合验证流程交付。
|
||||
首选下一增量不要自动开工。剩余放行门槛是:独立 REPLAY,或把 C4/C5 快速档接入 CI 形成 GATE(需平台准入);以及 C3 双主机(需第二台机器)。2026-10-13 的上传修复与 K4 SELF 重测不替代这两项。GATE/REPLAY 与 C3 未齐前,不要开放第二实例写。各实现任务启动前复核在途 PR 与依赖 SHA,再按 Dev 的 evidence/task-sync/组合验证流程交付。
|
||||
|
||||
@@ -7,10 +7,12 @@ execution: code
|
||||
product_contract_source: ce-plan-bootstrap
|
||||
---
|
||||
|
||||
# 服务重启与全量数据恢复方案 r2
|
||||
# 服务重启与全量数据恢复方案 r3
|
||||
|
||||
确认状态:待人工评审。当前交付为源码调查、方案与实施/验收计划;业务实施、故障注入、部署、运行验收均为 NOT_RUN。
|
||||
确认状态:原 r2 批准记录保留(Dev PROJECT.md 记录 2026-10-12 五阶段批准);**r3 本轮增补待人工评审**。本轮仅调查、修订方案及本地文档核查,不代签历史批准,不授权业务实施、账户变更、迁移、故障注入、部署、推送或合入。
|
||||
修订记录:r1=2026-10-12 初稿并完成六角色文档自审(见同名审阅记录第一轮);r2=2026-10-12 吸收外部源码复核(U1/U3/U4/第9节四处修订,见审阅记录第二轮),需求范围与量化指标未变。
|
||||
r3=同日根据 dev 8788 账户故障续查刷新源码/运行事实,保留 R1–R10、KTD1–KTD12、U1–U7;补充 R11/R12、KTD13–KTD15、U8 单实例保护及近期验证合同。原故障档和时间指标保持候选值,未宣称实测达标。
|
||||
r3.1=同日增补 D1/D2/D3(部署根治;编号避开本案 U1–U8)。映射:D1 补 U1 身份消费缺口,D2 补 U6 部署回退,D3 补 U7 真实组合门禁。确认状态:用户 2026-10-12 授权按实施计划连续推进到 PR 可合入;本节新增条款仍供人工评审,不代签 r3 其余未批内容。
|
||||
需求来源:2026-10-12(Asia/Shanghai)用户要求“系统应该在停止并再次启动(通过 svc 或异常终止)后,应当能够恢复所有服务和数据,给我一个完善方案”。负责人:weichen;编制:Codex;实施与运维负责人在启动对应增量时指定。
|
||||
主记录:本文;任务卡:Dev `.task/feature-service-restart-recovery-plan.md`。本文的源码路径以 Dev 根目录为基准。
|
||||
|
||||
@@ -34,20 +36,26 @@ product_contract_source: ce-plan-bootstrap
|
||||
|
||||
## 2. 当前事实及重点差距
|
||||
|
||||
本次源码基线:Dev `5e57029b439e5690f28dc6002f9784f0b08920eb`;Backend `eb12f102f23d8d026c3458be7ea8b2fef07ada93`;Core `89f3906c390027512ef47b5333088c3d3a019e84`;Frontend `aaced8796bb45d151833e12bc1cc17fc5090ef6d`;Documents `23e2276905eaf3d5b266a5218a53a12a38321284`。来源为 SELF·源码观察,原始命令和输出由 Dev `make evidence` 写入本任务卡;风险是源码推断,不是已重现事故。
|
||||
本轮源码基线:权威 Dev `2723e452440fc11022c0f6d916cd34cc4cd17335`;文档任务同步后 HEAD `26f2045e33516207959b5983acd32e1d3ea66bca`(任务元数据提交);Backend `5e8ada727c358438f8ff9f94eabb697e99fe28dc`;Core `89f3906c390027512ef47b5333088c3d3a019e84`;Frontend `cc233fec908d0f8c12193042942b94ad68508091`;固定 Documents `8d0810bd35f4934e0ad37fb96d7bab6d7a732473`。草案独立 Documents 基线 `1048e7c6afc2bb4efc541e68575c3fb2669ee332`,未推进 Dev gitlink。原 r2 对象为历史,不用于证明当前运行行为。
|
||||
来源为 SELF·只读观察;原始脱敏命令和运行输出由 Dev `make evidence` 写入 `.task/feature-svc-account-durability-plan.md`。故障表现为源码推导,故障/恢复/耐久性验收 NOT_RUN。
|
||||
最终 Dev 同步基线 `d6d46fde6d903d0d8e37440d830fb5183d6ef5e9` 已纳入主干的 svc 实例内存态修复和 Documents 指针 `1048e7c6afc2bb4efc541e68575c3fb2669ee332`;Backend/Frontend 未变。旧 gitlink 是启动时点,本轮仅同步权威上游,未推进本轮草案组合或重复实现该修复。
|
||||
|
||||
| 对象 | 已存在的基础 | 尚需解决的恢复缺口 |
|
||||
|---|---|---|
|
||||
| 数据库绑定 | `scripts/svc.sh:1373` 已统一解析 dbref/DSN/config;裸启动、restart/deploy 停前预检已接入 | 自定义 data/plugins 在参数重建时可能漂移;临时环境配置无法保证下次存在;配置多次逐键更新有崩溃中间态 |
|
||||
| 服务生命周期 | svc 管理 agent/static/postgres;PostgreSQL 复用 pgdata;分发仓有单应用 systemd 模板 | svc 没有服务组依赖恢复与持久启动意图;无统一进程组监管;不管理 Redis 类型 |
|
||||
| 数据库绑定与身份 | svc 统一解析已接线;manifest/marker 和 Backend DB identity 已存在;manifest 写入已有 file/dir fsync | 部分消费方仍读派生 svc.env;自定义根和 legacy/direct 启动需要完整核验;identity 不等于活动服务独占锁 |
|
||||
| 服务生命周期 | svc 已有 desired/autostart、recover、watchdog timer;PG 优先拉起 | 没有完整服务组依赖/单一进程组监管;不管理 Redis 类型;登记版本与实际二进制可能不一致 |
|
||||
| 启动与停机 | 启动对账开放 run;优雅停机尝试中断和事件 flush | 恢复通知/子代理发生在完整接线前;HTTP停机超时可跳过flush;无所有worker等待;子代理 cancelled 可覆盖 interrupted |
|
||||
| 运行恢复 | `runmgr.go:2046` 对账、子代理派生请求/转录、pending_notices持久化、恢复hold检查 | 主run与HITL统一收为中断/取消;子代理先派生再写文件标记;notice消费非事务且绕过PG会话占用 |
|
||||
| 执行所有权与额度 | `store/execution.go` 有 owner/epoch/lease,终态有fencing;额度有持久表 | 续租只有定义未接入生产调用;15分钟租约可过期;额度无崩溃回收;不能据此宣称安全接管 |
|
||||
| 命令与投影 | 取消/HITL持久收件箱、Surface待投递标志、事件seq与SSE续传 | 命令先 consumed 后执行,kill窗口丢命令;跨实例取消入队缺conversation;Surface失败仍可清pending且仅扫100条 |
|
||||
| 工具副作用 | Native Session已有tool intent/result转录、安全重放判定;Backend有hold表及管理员释放入口 | `SetRecoveryHold`仅定义;Native的未知效果被写成工具错误后仍可继续模型,尚未与Backend run/owner/epoch和持久hold形成统一隔离闭环 |
|
||||
| 文件与备份 | blob临时写+rename;工件元数据在DB;SQLite在线备份;svc有pg_dump | 覆写文件与更新元数据不是同一原子提交;未显式fsync;DB备份不含上传、工件、工作区、转录、配置/版本 |
|
||||
| 文件与备份 | blob temp+rename、SQLite 一致性快照、pg_dump 已存在;Native 转录 Write→Sync;manifest 有原子同步链 | 工件原文先覆写再更新 DB,无不可变版本;agent 快照缺权威 manifest,PG 和文件快照不是同一恢复点 |
|
||||
| SQLite 服务所有权 | WAL、30 秒 busy_timeout、每进程一连接;数据库事务可排队 | 无跨进程活动服务独占;恢复扫描全部开放 run,第二个服务可打断第一服务;不具备 PG 的会话执行租约 |
|
||||
|
||||
当前登记元数据显示 dev 绑定 `pg1/agent`,部署制品的 Backend revision 与上述Backend一致;这只证明登记和制品元数据。**实际运行进程的数据库身份、全栈恢复、数据耐久性尚未实测,不能写为PASS。**
|
||||
2026-10-12 17:37:03(Asia/Shanghai)实际 dev 进程打开 `runtime/dev/data/agent-system.db`,DB marker 为 `sqlite`,运行 Backend `5e8ada7`;没有登记 PG 绑定。候选 rdmcand 已停止且登记来源与实际文件版本不符。前一轮共享数据观察是历史风险线索,不冒充当前双进程事实。**实际文件/marker 已核对,不等于全栈恢复或断电耐久性 PASS。**
|
||||
|
||||
当前 PG 事件总线已有真重连、分页追赶和周期补查,Native 已接持久工具转录;这些基础不重复建设。SQLite 应用连接未显式声明 synchronous;诊断连接 PRAGMA 不能证明应用配置,见 R12。
|
||||
18:14:09(Asia/Shanghai)重新实测:外部流程已将 rdmcand 拉起于独立数据根,实际 DB inode 与 dev 不同且制品/登记版本一致;dev 仍打开原库、账户最后设密时间未前进。当前共享现场已缓解;U8 的剩余任务是强制运行时防误用和隔离验收,不重复执行已完成的人工分根。完整停机/恢复和锁能力仍 NOT_RUN,本轮没有改变服务或数据。
|
||||
|
||||
旧报告中“DSN重启丢失”“迁移DDL与版本分开提交”“通知仅内存”等问题已有源码改进,本案只验证并复用这些基础,不把旧缺陷重新列成新建设。
|
||||
|
||||
@@ -65,6 +73,8 @@ product_contract_source: ce-plan-bootstrap
|
||||
| R8 | 停机与就绪 | 停机先拒绝新工作再排空;全部worker、sidecar和工具子进程收口;错误不跳过后续清理;ready反映业务可用 |
|
||||
| R9 | 升级与灾难 | 保留上一程序/插件/资产组合及兼容合同;备份恢复到新目标并完成业务/权限/文件对账;不在普通启动覆盖现库 |
|
||||
| R10 | 可见与证据 | 用户能区分继续、等待审批、等待恢复确认、失败;运维能定位阻塞依赖;每项验收绑定精确组合、制品、配置与原始输出 |
|
||||
| R11 | 本地服务隔离 | 同一 SQLite/数据资源只允许一个活动服务运行时;直接二进制、路径别名和 legacy 入口同样受保护;账户短事务 CLI 不启动第二运行时;测试实例使用独立根 |
|
||||
| R12 | 耐久性档 | 显式设置并从应用实际连接核验 DB 耐久策略;文件和目录同步覆盖权威对象;DB/文件持久失败不能确认成功;未实测的断电 RPO 保持候选 |
|
||||
|
||||
覆盖“所有数据”需要先完成数据归属清单:除Backend业务表,还含插件自有持久库/目录和下游RDM等已启用模块。每个插件声明恢复适配器、版本、权威位置、必需程度与兼容性;无法证明可恢复的必需插件阻塞全系统签收,不能只恢复Backend便宣称全部完成。
|
||||
|
||||
@@ -114,6 +124,12 @@ flowchart TB
|
||||
|
||||
systemd的顺序依赖不能替代DB可用性检测;需真实探测,且明确依赖断开后的重连/恢复政策。监管策略参考systemd官方[service契约](https://github.com/systemd/systemd/blob/main/man/systemd.service.xml)与[进程组停止契约](https://github.com/systemd/systemd/blob/main/man/systemd.kill.xml)。
|
||||
|
||||
KTD13. **SQLite 活动服务锁由 Backend 强制。** 在迁移和启动 run 对账之前按实际 DB/数据资源取得 OS advisory lock,持有至运行时退出;覆盖规范化路径和文件别名。marker/PID 不替代锁,SIGKILL 后由 OS 释放。合法账户 CLI 只核验同实例和兼容 schema 后做 DB 短事务,不启动 Manager;迁移独立维护。锁文件丢失或 DB 替换导致身份改变时拒绝自动续跑,不能新建可绕过的锁继续。
|
||||
|
||||
KTD14. **初始化与事故后缺库分开。** 已登记实例启动和运维先验证预期库/marker,缺失则阻塞;显式 init 才允许创建。SQLite 可靠档明确 WAL+FULL 并核验每个连接;PG 核验实际 fsync/synchronous_commit/full_page_writes 等,不用诊断连接默认值证明应用配置。[SQLite WAL](https://www.sqlite.org/wal.html)、[PostgreSQL WAL](https://www.postgresql.org/docs/current/runtime-config-wal.html)。
|
||||
|
||||
KTD15. **manifest 单一权威与派生视图修复。** 复用现有 temp→fsync→rename→dirsync;读侧直接消费 manifest 或验证派生 revision。manifest 提交后、svc.env 派生前崩溃可重新生成视图,不能按旧派生配置换库。未知制品能力、登记/实际版本不符报告并拒绝危险操作,不猜测。
|
||||
|
||||
## 5. 启停流程与恢复政策
|
||||
|
||||
### 5.1 启动和优雅停止
|
||||
@@ -127,6 +143,7 @@ sequenceDiagram
|
||||
C->>D: 校验manifest、数据身份与操作锁
|
||||
C->>C: 启动归本组管理的依赖并探测
|
||||
C->>A: 启动固定版本
|
||||
A->>A: SQLite取得活动服务锁;PG按既有执行所有权合同
|
||||
A->>D: 校验schema、文件与恢复候选
|
||||
A->>W: 完成插件/权限/预算/工作区全部装配
|
||||
A->>D: 分类认领、对账未知效果、恢复命令与额度
|
||||
@@ -138,6 +155,7 @@ sequenceDiagram
|
||||
W-->>A: bounded join与子进程结果
|
||||
A->>D: 持久化恢复意图、flush、收口许可/所有权
|
||||
A->>D: 关闭存储
|
||||
A->>A: 释放本进程SQLite活动服务锁
|
||||
A-->>C: 停机结果(含未完成原因)
|
||||
C->>C: 复核进程组消失;逆序停止独占依赖
|
||||
```
|
||||
@@ -178,7 +196,7 @@ stateDiagram-v2
|
||||
|
||||
`recovering/hold`在这里是目标业务语义,**不是声称现有Core枚举已支持**。过渡可用恢复账本表达;若新增公开状态,Core/Backend/Frontend/下游契约兼容必须同增量处理。已有interrupted历史记录保留,不强改成成功。
|
||||
|
||||
用户侧复用现有任务状态、对话卡和管理员恢复入口,显示恢复原因、进度和允许动作;SSE按持久seq补发并丢弃旧事件,页面刷新重载权威快照。断连或无增量不能推断任务完成。实施界面前重读根DESIGN.md并遵循UI令牌、Collapsible和单异步状态所有者规则。
|
||||
用户侧复用现有任务状态、对话卡和系统管理区,显示恢复原因、进度和动作。当前只有管理员恢复 API 基础,Frontend 对账接线待 U4 实施,不宣称已有可用界面。SSE按持久seq补发并丢弃旧事件,刷新重载权威快照;断连不推断完成。实施界面先读 DESIGN.md,遵守令牌、Collapsible和单异步状态所有者。
|
||||
|
||||
## 6. 全量数据与组合备份
|
||||
|
||||
@@ -193,12 +211,16 @@ stateDiagram-v2
|
||||
|
||||
普通启停不从备份还原;数据库与文件继续使用同一身份及位置。灾难恢复由显式受管入口在新目标进行,禁止start自动覆盖当前数据。
|
||||
|
||||
当前 agent backup 只复制 svc.env、history 和 data(逐 SQLite 一致性导出),不含权威 manifest,在线非 DB 文件与 DB 没有统一快照时点;它是数据目录快照,不是完整恢复包。当前 pg_dump 默认在 runtime 子目录,完整包及副本须放在数据/runtime 生命周期之外;生成时使用受限临时目录,校验成功后原子发布完成标记。半成品不列作恢复点,完成且验证的新备份存在前不执行保留策略删除。
|
||||
|
||||
首期备份取得明确停写窗口:关闭准入、排空或隔离在途操作、停止全部相关写者,核对独占管理边界后备份DB及文件并生成manifest。共享PG不能仅停一个API实例便宣称一致;写者无法证明停止则阻塞此类快照。后续可用不可变对象、DB发布记录、物理基础备份+连续WAL/PITR建立在线恢复点,manifest关联source snapshot、时间/LSN、schema、源码/制品/插件组合和对象版本。
|
||||
|
||||
恢复到新目标首先处于隔离验证模式,不启动任务调度/副作用,也不自动连接生产外部写目标。正式切换须证明旧实例、worker、sidecar、工具子进程及已发请求的写路径已经隔离:可采用停止并验证、资源侧拒绝旧执行代次、专用执行凭据失效或网络写路径隔离;不得为此擅自轮换共享凭据。生成新的恢复权威代次,并保证实际写目标能够拒绝旧路径。两个独立恢复库各自认可的epoch不能互相围栏;旧实例不可联系不能当作停止证明。无法核实则保持副作用hold,只开放受权的数据核验。
|
||||
|
||||
同时对账恢复点至故障/隔离完成期间的外部效果:它们可能已执行却不在恢复后的账本里。结合独立receipt、目标日志或人工核对,将已确认动作登记到恢复账本,确认安全后逐项解锁;不能仅扫描备份里的started记录就自动重试。灾难档报告批准RPO内可能丢失的写入范围、恢复点内完整性与外部对账结果。
|
||||
|
||||
灾难恢复另设安全状态门禁:开放正常认证前作废备份中的全部会话和未使用登录 Key,防止已注销/消费的凭据复活。恢复点后的改密、长期 Key 撤销、角色/成员/插件授权变更与独立受信记录核对;缺记录或无法证明当前有效性时,相关主体/资源保持鉴权隔离,有权 owner/运维重新建立凭据或确认授权后开放。新执行 epoch 不代替认证撤销。普通启停/更新不执行此规则;普通账户恢复保留集成 Key 的合同也不允许灾难恢复盲目启用旧 Key。
|
||||
|
||||
PG逻辑pg_dump用于独立逻辑恢复;PITR须有物理基础备份和连续WAL,不能用pg_dump冒充其基础备份,依据[PostgreSQL备份与PITR](https://www.postgresql.org/docs/current/continuous-archiving.html)。SQLite使用现有一致性备份接口,不能在线只复制.db遗漏WAL。文件内容先耐久发布再提交DB引用,备份保留覆盖恢复点所需的对象版本。
|
||||
|
||||
备份副本及密钥与原数据同级保护:加密、专用受限目录/角色、异机或异故障域副本、保留期限与清理owner;密钥须独立可恢复。拟定每日日常备份、持续WAL、每月及重大升级前恢复演练,频率按批准的RPO与数据量固定。实际恢复须验证登录、跨项目隔离、历史文档与附件、任务/HITL、工件下载和插件业务链;恢复时间从故障触发开始计时。
|
||||
@@ -211,12 +233,16 @@ PG逻辑pg_dump用于独立逻辑恢复;PITR须有物理基础备份和连续W
|
||||
|
||||
### U1. 实例与数据恢复身份
|
||||
|
||||
当前 manifest/DB identity 基础已在源码,既有合同见 Dev `docs/recovery/u1-identity-manifest.md`;本轮只规划消费缺口、派生修复和显式 init/restore,不重复建立身份层。
|
||||
|
||||
对应R2/R3/R9;无前置。范围:`scripts/svc.sh`、`docs/svc.md`、`tests/test_svc.py`、`tests/test_svc_precheck.py`及新增manifest/identity验证模块。
|
||||
做完整配置、逐字段覆盖、原子revision与操作锁、稳定秘密引用、DB/数据目录身份marker、独立init/restore入口;保留现有dbref修复并提供旧登记一次性兼容迁移。先补现状刻画回归,再改解析器。
|
||||
验收:连续两次裸启停保持同一DB与原始记录;只改端口保持data/plugins;单独data覆盖按合同生效/拒绝;配置迁移每个写边界kill后只能读到完整旧/新版;缺凭据、错DB、丢marker不得新建空系统;更换二进制路径/程序版本或以不同cwd调用svc后,DB identity、数据/工件/工作区根与插件组合保持一致(对应R2更换程序/cwd条款)。使用真实PG特有测试记录核对,桩测试只能辅助。
|
||||
|
||||
### U2. 服务组与进程监管
|
||||
|
||||
当前 recover/watchdog/desired 已有首切片,余量为服务组、依赖 readiness、唯一监管与完整操作恢复,不再记为全部未实现。
|
||||
|
||||
对应R1/R8;依赖U1。范围:svc组编排、可选Redis适配、分发仓`deploy/agent-system.service`及安装接线、新增隔离服务组故障测试。
|
||||
按KTD3/KTD4建立依赖图、desired state、可恢复lifecycle operation与单一监管;加入boot/start/exe身份与进程组校验。必需/可选、受管/外部资源由manifest决定。首次切监管在明确停机窗口完成,失败回到原监管且不形成双启动。
|
||||
验收:全组停止后启动;先PG后应用;主动stop保持停止;kill自动退避恢复;主机重启按策略恢复;PID复用、残留子进程、端口冲突、依赖启动失败、不透明外部DB均正确拒绝/报告;不得停止其他服务组的共享依赖。
|
||||
@@ -231,6 +257,7 @@ PG逻辑pg_dump用于独立逻辑恢复;PITR须有物理基础备份和连续W
|
||||
|
||||
对应R4/R5/R7;依赖U3,并复用U5所有权接口;U4/U5作为同一安全交付批次,完整性验收前不开放自动续跑。范围:runmgr/runtime工具入口、store运行/恢复/hold表、checkpoint适配、Core公开状态及Frontend兼容、对应恢复与真实工具替身测试。
|
||||
落实KTD7/KTD8,主run、Workflow、子代理、已配置后台executor共享恢复政策;持久化步骤/输入/结果/operation;自动hold连接到工具与启动扫描。HITL保持gate、答案和权限;修复子代理恢复链唯一性。文件checkpoint仅承担其明确的文件修改范围;若新增recovering/hold为公开状态,设计阶段先交付Core枚举→Backend→Frontend及下游契约的最小状态映射表,作为设计评审前提。
|
||||
Frontend 接线复用任务/对话卡和系统管理区:有权 owner/admin 查看具体 operation、未知原因和证据引用,提交已完成 receipt、未执行终态及旧请求隔离证明,或明确放弃。提交防重复,失败保留输入与原因,成功重载权威状态;Backend 按 operation 权限/版本/epoch 裁决,不以当前整 run release API 代替逐项对账。浏览器验收覆盖发现 hold→对账→剩余步骤恢复,拒绝越权和「放行即重跑」,不新增页面。
|
||||
验收:排队/主run/子run/HITL/索引各类任务kill并两次恢复;工具“完成外部动作、结果未提交”只hold不重做;查询暂未发现但外部请求稍后完成时不发送第二次请求;幂等目标使用同operation key;Native pending intent只由统一账本决策,不生成普通错误后绕过hold;确认一个operation完成后执行剩余必要步骤,不假结算整run;未知工具默认隔离;撤权后禁止续跑;无executor类型明确blocked。真实模型最小任务级恢复对照单独申请测试资源,未跑标NOT_RUN。
|
||||
|
||||
### U5. 所有权、额度、命令、通知与投影闭环
|
||||
@@ -244,6 +271,7 @@ PG逻辑pg_dump用于独立逻辑恢复;PITR须有物理基础备份和连续W
|
||||
对应R3/R7/R9;依赖U1/U3,恢复账本完整验收依赖U4/U5。范围:blobstore/content、workspace与checkpoint、插件恢复适配合同、svc deploy/update/backup、分发仓安装、备份manifest与restore测试。
|
||||
按KTD11发布不可变版本,扫描缺失/孤立对象;登记全部插件/下游存储;按第6节生成一致恢复点、保护副本、恢复到新目标;候选完整构建后切版本,保留兼容上一组合。
|
||||
验收:对象写后DB提交前kill;覆盖发布过程中kill;日志尾截断/文件缺失保留现场;备份恢复后原文hash/权限/插件链一致;恢复新目标后旧实例复活仍不能产生外部效果,未完成旧写路径隔离时新目标不调度;恢复点后已发生的外部效果对账完成前保持hold;升级ready失败可在兼容条件下回退;不兼容schema拒绝程序自动回退;数据回退不静默丢新写入。
|
||||
另覆盖恢复点后注销会话、消费/撤销登录 Key、撤销集成 Key、改密与撤回角色/项目/插件权限:恢复旧包后旧会话和登录 Key 不再有效,无法证明有效的长期 Key/授权保持隔离;owner 正常确认后的新凭据可用。与普通重启原密码保持分别签收。
|
||||
|
||||
### U7. 故障验收与交付放行
|
||||
|
||||
@@ -253,11 +281,28 @@ PG逻辑pg_dump用于独立逻辑恢复;PITR须有物理基础备份和连续W
|
||||
|
||||
建议交付批次:A=U1/U2/U3(可靠启动及安全停机,自动任务续跑关闭);B=U4/U5(安全自动续跑与命令闭环);C=U6/U7(文件耐久性、灾难恢复及全系统签收)。只交付A不能宣称完成用户的全部需求。
|
||||
|
||||
### U8. SQLite 活动服务隔离与既有存储门禁
|
||||
|
||||
覆盖 R2/R3/R6/R11/R12,复用 U1 身份;近期优先于自动恢复和共享库测试。范围:Backend `internal/app/app.go`、`internal/store/store.go`、`internal/store/system_identity.go`、新增 `internal/instanceguard/`(拟定);Dev `scripts/svc.sh`、`docs/svc.md`。锁只控制活动服务运行时,CLI 身份/schema 合同由[账户方案](2026-10-12-svc-unified-deploy-and-login-key.md) U7 负责。负责人待实施批准时指定。
|
||||
依赖:既有 U1;联合确认 service/CLI/migration 模式,先刻画原例和别名冲突,再实现;不直接把当前 dev 数据迁往 PG。
|
||||
测试:新增 Backend `internal/instanceguard/guard_test.go`,扩展 `internal/store/system_identity_test.go`;Dev 新增 `tests/test_svc_storage_ownership.py`,复用 `tests/test_svc_identity.py`。新增路径为计划。
|
||||
T8-1:两个独立进程同时启动同 SQLite,只有一个进入迁移/恢复;第二个明确拒绝,第一个 run/HITL 不变。
|
||||
T8-2:直接二进制、legacy、符号链接和可构造的文件别名不能绕过;真实 DB 替换/锁根丢失被识别。
|
||||
T8-3:活动服务 SIGKILL 后合法同实例可重启,OS 释放锁;主动停止不被 watchdog 错拉起。
|
||||
T8-4:服务运行期间合法账户 CLI 可提交短事务;错实例/缺库拒绝、不建目录、不 migrate;迁移不与活动服务并发。
|
||||
T8-5:更换端口、cwd、程序版本保持同一资源;测试候选默认独立根,显式指定共享根也不得绕过保护。
|
||||
T8-6:参数来自应用实际连接;SQLite FULL/PG 同步设置按批准合同核验,磁盘满/写失败不返回成功。
|
||||
环境:独立 SQLite 根与端口、真实 PG 独立库回归;双进程和 kill 禁止在当前 dev/candidate 执行。全部 T8 当前 NOT_RUN。
|
||||
|
||||
近期批次 A0=U8+账户方案 U7/U5:先稳定数据归属和账户链路;另行授权后完成 dev 原账户正常登录/重启/更新验收,见账户方案 §7。A/B/C 保留;U4/U5 联合验收后才开放自动续跑,A0 不代替全量恢复。
|
||||
|
||||
## 8. 验证合同
|
||||
|
||||
| 故障/操作 | 最小判据 | 对应需求 |
|
||||
|---|---|---|
|
||||
| `svc stop/start`连续两次、restart、地址与版本变更 | 原DB identity、记录/权限、data/plugins/artifacts根和固定组合一致 | R1/R2/R3 |
|
||||
| SQLite 双进程、直接启动、别名、锁释放 | 第二活动服务在迁移/run对账前拒绝;合法 CLI 可用;kill 后同实例可重启 | R2/R6/R11 |
|
||||
| 实际 DB 耐久档、权威文件发布点、磁盘满 | 参数来自应用连接;确认结果已耐久;失败不发布成功;旧版本可读 | R3/R7/R12 |
|
||||
| 应用SIGTERM/SIGKILL/OOM | 持久数据完整;安全工作可恢复;额度无永久占用;无残留写者 | R3/R4/R6/R8 |
|
||||
| PG停止/重启、断连或提交响应丢失 | 不切SQLite;不假接受;按幂等记录对账;重连后可用 | R2/R3/R5 |
|
||||
| 主动stop与异常退出、监管/编排中途kill | 主动停止不拉起;异常按running意图恢复;操作重复安全 | R1/R2/R8 |
|
||||
@@ -280,16 +325,59 @@ PG逻辑pg_dump用于独立逻辑恢复;PITR须有物理基础备份和连续W
|
||||
|
||||
本案补充[多人协作存储与分布式演进方案](2026-10-11-collaboration-storage-and-distribution.md)的R7及恢复/运维合同;不覆盖其批准记录或迁移、多实例放行条件。已存在的执行所有权、命令、outbox实现以当前代码为基础继续,不另起重复模块。
|
||||
|
||||
调查时发现`feature/svc-autorecover`在途工作区,任务卡为manual且目标/方案仍待填;其实施与批准范围未经本轮证实。**U1/U2启动实施前必须人工二选一**:(a) 以`feature/svc-autorecover`为实施载体,把本案r2作为其需求与方案来源填入该任务卡后按其流程推进;(b) 记录原因后放弃或合并该任务卡,由本案派生的独立任务实施;两任务不得同时充当svc启动/监管改动的权威,该归属决定与首批实施范围一并报批;`feature/collab-storage-u5-outbox`也存在工作区,其变化未纳入当前固定源码。实施前核对当前主记录、卡片、PR、owner及组合SHA,不能依据分支名断言能力已完成。相关RDM/插件只有纳入兼容和恢复清单并验收后才能覆盖“所有数据”承诺。
|
||||
原 r2 的 svc-autorecover 二选一属于历史启动现场;当前 recover/watchdog 和 U1 身份已有源码,不再要求重新启动同一基础任务。新实施前仍核对在途 svc 监管/RDM UI/端口回收任务,避免重复修改入口。RDM/插件只有纳入兼容与恢复清单并验收后才能覆盖「所有数据」承诺。
|
||||
|
||||
备选:仅修svc脚本成本较小,只能覆盖启动配置/进程,无法满足在途任务和副作用恢复;另造常驻恢复daemon会增加新的监管者与恢复责任,首期无需。推荐现有svc+系统监管+Backend恢复协调的职责划分。
|
||||
|
||||
实施批准时需要固定:目标实例/服务组及独占管理权、实际数据归属清单、故障档与RPO/RTO、正常停机预算、既有在途任务分工。本文已给默认建议;没有这些确认不在共享运行环境做故障/迁移/监管切换。后台是否自动重做模型回合可按任务政策配置,但未知副作用不得靠默认重试放行。
|
||||
|
||||
下一任务建议为U1并同步审查U3生命周期缺口:先保证再次启动绝不换库、换数据根或假就绪,再接监管和自动续跑。预计产物为兼容manifest合同、数据归属清单、隔离真实PG恢复回归与生命周期设计;进入实施前人工批准本案的需求、设计和首批测试范围。后续数据库备份、systemd安装、部署/启停与故障实验分别按授权执行。
|
||||
下一任务建议为 U8 与账户方案 U7/U5 的首批设计/实施评审:先保护 dev 原数据,补足账户一致性与登录语义;随后 U3 停机/就绪、U4/U5 任务恢复、U6/U7 文件与灾难演练。新增 U8 未批准前不实施。数据清单、故障档预算、正式组合验证仍为放行条件;PG 迁移、监管切换、备份恢复、部署和故障实验分别授权。
|
||||
|
||||
## 10. 全系统完成条件
|
||||
|
||||
只有在所有启用的必需服务/插件被纳入清单、R1–R10均有当前组合与运行对象的重放证据、第8节故障矩阵通过、未知副作用有可处理隔离状态、组合备份实际恢复成功、人工验收及代码Review通过并完成合入/部署后,才可声明“系统停止或异常终止后能够恢复所有服务和数据”。
|
||||
只有在所有启用的必需服务/插件被纳入清单、R1–R12均有当前组合与运行对象的重放证据、第8节故障矩阵通过、未知副作用有可处理隔离状态、组合备份实际恢复成功、人工验收及代码Review通过并完成合入/部署后,才可声明“系统停止或异常终止后能够恢复所有服务和数据”。
|
||||
|
||||
本轮交付状态止于**待审核方案**;不以记录、源码能力、桩测试、健康接口或本地文档检查代替上述完成条件。
|
||||
|
||||
## 11. D1/D2/D3 部署根治补充(r3.1)
|
||||
|
||||
编号 D1/D2/D3 只属于本补充,避免与本案 U1–U8 重名。已合入且不再重做:Dev #474(按实例重置身份变量、停旧前候选门禁、update 走 manifest 迁移、普通启动只验证)、Backend #180(`pkg/identity`)、RDM #276(identity 子命令与未知位置参数退出)、Dev #477(backend pin 到含 #180 的 `acabb85`)。
|
||||
|
||||
### 11.1 现场快照与 rdmcand 数据归属(SELF,2026-10-12T13:39:21Z)
|
||||
|
||||
快照目录(在线 `sqlite3 .backup` / RDM `VACUUM INTO`,未停服务):
|
||||
|
||||
- `runtime-backups/{dev,rdm1,rdmcand}/20261012T133921Z`
|
||||
- `runtime-backups/{dev,rdm1,rdmcand}/domain-20261012T133921Z`
|
||||
|
||||
只读核对副本,未移动任何业务数据。rdmcand 在 `2026-10-12T06:51:14Z`–`10:02:40Z` 使用 `runtime/dev/data`。该窗口内:
|
||||
|
||||
- dev 库的会话、消息、事件均不落在窗口内。最后一条消息时间 `06:50:43Z`,早于 rdmcand 挂上该目录。会话与用户属于 dev(owner `weichen`、`genui-smoke`)。
|
||||
- 窗口内仅有 13 条 `command_audit`,全部是 `rdm.inspect.*`,owner `weichen`,没有领域事件。
|
||||
- 三份 `rdm.db` 的 `events` 均为 0。dev 的领域库更大(含权限表,schema_version=6),rdm1/rdmcand 的领域库只有字典与 schema 行。
|
||||
- rdm1/rdmcand 的 `agent-system.db` 只有 `2026-10-12T13:19:47Z` / `13:20:12Z` 由候选门禁写入的身份行,没有业务行。
|
||||
|
||||
处置(未执行,需逐项授权):不把 dev 的会话或领域库迁到 rdmcand。没有一份应属于 rdmcand 的历史领域数据需要回迁,因此不触发身份 `adopt` 重审。rdm1/rdmcand 当前库是空壳加已建立的身份行。
|
||||
|
||||
### 11.2 D1 身份流程收尾
|
||||
|
||||
对应 U1 的消费缺口。完成条件:
|
||||
|
||||
- 身份 CLI 只打开既有库:不建文件、不建目录、不迁移。`agent_system_identity` 表(v27 起,列冻结为 instance_id/dbref/schema_version/created_at)缺失则拒绝并提示受控迁移。比本二进制更旧或更新的 schema,只要该表仍在,verify 仍可读。
|
||||
- verify 输出带 `schema_version`。DSN 走 `AGENT_SYSTEM_DSN` 或权限恰好 0600 的 `--dsn-file`;`--dsn` 保留并告警。
|
||||
- 能力文档一份 JSON,经 `version --json` 与 `identity capabilities` 输出。探测只跑 `version --json`,在空目录、清空环境、超时内执行。非 JSON 视为无能力。
|
||||
- 顶层未知子命令 exit 2,不以 `-` 开头才拦截,避免落入 serve。
|
||||
- manifest `identity.db_marker`:`fresh` | `pending` | `established`。新实例首次部署目标目录必须为空,启动建库后 ensure 变为 established。领养时有能力且库已存在则 ensure,否则 pending。pending 只在库文件存在时补齐,不迁移。established 缺行或不匹配时,start/restart/deploy/update/recover/init 全部拒绝;唯一修复入口是显式 `adopt --confirm <instance_id>`,并先打印库大小、关键表行数和最近写入时间。
|
||||
- `svc_lifecycle` 是 start/restart/deploy/update/recover 的共同入口。update 与 recover 逐服务以 `env -i` 启动子进程,不传入 `AGENT_SYSTEM_*`。serve 使用显式环境,并写入 0600 的 `serve.env` 供裸启动与 recover 复用。
|
||||
|
||||
### 11.3 D2 切换事务
|
||||
|
||||
对应 U6 的部署回退。制品进入 `runtime/<name>/releases/<rid>/`,`current` 用临时符号链接加 `mv -T` 切换。`bin`/`plugins`/`htdocs` 改为指向 `current/` 的稳定链接。切换日志 `deploy-journal.json`(0600)先写 phase 再执行。失败回到上一版本并恢复原期望运行态,不覆盖业务库。schema 不兼容时在停旧服务前拒绝。前进迁移必须 `deploy --migrate-schema --confirm <instance_id>` 且先 backup,日志标记 forward-only。能力文档增加 `schema.target` 与 `schema.compatFloor`;每条迁移登记是否破坏旧版读取,漏登记则测试失败。
|
||||
|
||||
### 11.4 D3 真实组合门禁
|
||||
|
||||
对应 U7 的故障验收入口,范围限于部署生命周期。Dev 用 `tests/integration/lifecycle/rdm.pin` 固定 RDM SHA(当前、上一版、无 identity 的旧版)。CI test-pg 按 pin 取固定 SHA,白名单加入 RDM 及其 pins。`make test-lifecycle` 缺 PG、源码或制品即失败,不静默跳过。桩测试不能代替该门禁。RDM 登录入口与账户 CLI 的 DSN 退出命令行依赖账户方案 U7/U5;未就绪的项保持 NOT_RUN,D3 不得标完成。
|
||||
|
||||
### 11.5 验收
|
||||
|
||||
缺一项则对应增量保持未完成:双向混合批次身份不串用;无 manifest 时 deploy/update/recover 一致;无能力、缺行、不匹配在停旧前拒绝且不建库;两次裸重启及换端口、换版本、换目录后身份不变;构建失败、启动即退、健康超时、工作台失败可回滚;切换中断后登记与制品一致;真实 PG 绑定与多实例检查通过且凭据不进命令行、日志和证据;RDM 页面、登录、领域命令和原有数据可验证,不能只看 HTTP 200。
|
||||
|
||||
@@ -7,10 +7,11 @@ execution: code
|
||||
product_contract_source: ce-plan-bootstrap
|
||||
---
|
||||
|
||||
# svc 统一部署与一次性登录 Key 方案 r1
|
||||
# svc 统一部署与一次性登录 Key 方案 r2
|
||||
|
||||
确认状态:**已批准**(2026-10-12 用户「批准,继续推进」:需求拆解→实施计划五阶段及 U1/U4 规格一并批准;授权推送/PR 与启动 U1/U4 实施;合入仍由 owner 执行)。业务实施、测试、部署与运行验收在批准时仍为 **NOT_RUN**,由后续实施任务推进。
|
||||
确认状态:**r1 原批准保留;r2 本轮增补待人工评审**。r1 的批准记录为 2026-10-12 用户「批准,继续推进」(五阶段及 U1/U4 规格,允许对应实施和 PR)。本轮用户要求仔细调研、详细方案并「继续」,覆盖方案修订及本地文档准备,不扩展为业务实施、账户变更、迁移、部署、故障注入、推送或合入授权。
|
||||
修订记录:r1=2026-10-12 草案经源码复核后定稿(四项取舍采纳;补齐 §6 合同;对齐恢复方案 KTD 与已合入的 recovery U1 实例身份);同日获批并进入推送与 U1/U4 实施。
|
||||
r2=同日复核 dev 登录故障、当前 U1/U4 源码和帮助缺口;保留 R1–R12、KTD1–KTD10、U1–U6 的含义与编号,补充 R13–R15、KTD11–KTD14、U7/U8,并细化 U5。新增内容未批准;不以原批准记录代签新增范围。
|
||||
需求来源:2026-10-12 用户提出将 `svc.sh` 增强为统一部署入口(二进制与源码、环境准备、无初始密码开户与账户恢复),并要求一次性 API Key 只能兑换「设置密码」受限会话。负责人:weichen;编制:Cursor Agent。
|
||||
主记录:本文;任务卡:Dev `.task/feature-svc-unified-deploy-login-key.md`。源码路径以 Dev 根目录为基准。
|
||||
|
||||
@@ -26,7 +27,7 @@ product_contract_source: ce-plan-bootstrap
|
||||
| 环境检测与准备 | `doctor` 只报告;`env prepare` 按模式执行可幂等计划 | 不把任意发行版 Go/Node 标为可构建;工具链版本读自所选提交或发布清单 |
|
||||
| 账户激活 / 恢复 | 无预设密码开户或签发恢复 Key;原子兑换 → 受限会话 → 设密 → 正常登录 | 不删除重建用户;不迁移业务归属;普通找回默认不撤销长期集成 Key |
|
||||
|
||||
与 [服务重启与全量数据恢复方案 r2](2026-10-12-service-restart-data-recovery.md) 的关系:
|
||||
与 [服务重启与全量数据恢复方案](2026-10-12-service-restart-data-recovery.md) 的关系:
|
||||
|
||||
- **复用** KTD1–5、KTD12:持久 manifest、唯一监管者、team=PG 且失败不回落 SQLite、readiness 与身份。
|
||||
- **复用** 已合入的 recovery U1(Dev #415):`runtime/<name>/manifest.json`、启动身份校验、`svc init`、原子写路径(见 Dev `docs/recovery/u1-identity-manifest.md`)。
|
||||
@@ -35,7 +36,10 @@ product_contract_source: ce-plan-bootstrap
|
||||
|
||||
## 2. 当前事实及重点差距
|
||||
|
||||
源码基线(SELF·工作区观察,启动 precheck READY):Dev `af9c2de663be5ff102dcab7698464a645832f569`;Backend gitlink 以该提交为准;本地评审时曾对照 `3fa0d3a` / Backend `696ef15`,与当前 main 可能有漂移,实施前以 `task-sync` 后 SHA 为准。运行验收 **NOT_RUN**。
|
||||
本轮 source 基线(SELF):权威 Dev `2723e452440fc11022c0f6d916cd34cc4cd17335`;文档任务同步后 HEAD `26f2045e33516207959b5983acd32e1d3ea66bca`(增加任务元数据);Backend `5e8ada727c358438f8ff9f94eabb697e99fe28dc`;Frontend `cc233fec908d0f8c12193042942b94ad68508091`;Dev 固定 Documents `8d0810bd35f4934e0ad37fb96d7bab6d7a732473`。本轮 Documents 草案从其独立权威 main `1048e7c6afc2bb4efc541e68575c3fb2669ee332` 起步;与 Dev 固定版相比,两份目标方案正文没有上游差异。Dev gitlink 未推进。原 r1 基线只作历史,不用于当前能力判断。
|
||||
|
||||
2026-10-12 17:37:03(Asia/Shanghai)的只读运行观察和启动/同步命令,原始脱敏输出由 Dev `make evidence` 写入 `.task/feature-svc-account-durability-plan.md`。这是 SELF 观察,不是登录、故障或恢复验收,后者均 NOT_RUN。
|
||||
最终同步基线为 Dev `d6d46fde6d903d0d8e37440d830fb5183d6ef5e9`:主干另已推进固定 Documents 至 `1048e7c6afc2bb4efc541e68575c3fb2669ee332`,并修复 svc 批量操作的 PIDCHECK/EXEC 等内存态串用;本轮未重复该修复,也未推进本轮 Documents 草案 gitlink。Backend/Frontend 固定 SHA 未变;上述初始基线和17:37观察保留历史时点,不冒充最终 HEAD。
|
||||
|
||||
| 对象 | 已存在的基础 | 尚需补齐 |
|
||||
|---|---|---|
|
||||
@@ -43,15 +47,32 @@ product_contract_source: ce-plan-bootstrap
|
||||
| 部署生命周期 | 预检失败不停机;预检通过后 **先停再构建**;无程序备份/自动回滚 | 候选获取与校验全程不停旧服务;缺摘要硬失败;迁移后回退独立判断 |
|
||||
| 实例身份 | recovery U1:manifest + marker + init;`svc.env` 派生 | 账户 CLI 必须绑定实例最终配置;缺绑定拒绝,禁止回落 `./data` |
|
||||
| 环境 | 端口/`flock`/pg 工具链按需检查;文档列前提 | `doctor` / `env prepare`;无 `flock` 时不得放行冲突操作(现状直通) |
|
||||
| 账户 CLI | `user create\|reset-password\|list`;省略密码 → 随机明文一次 + `must_change` | 无密码创建 + 激活 Key;恢复 Key;OpenExisting(不建空库、不静默 migrate) |
|
||||
| API Key | 明文只显示一次;可长期复用;无 TTL/次数 | **独立**一次性登录凭据表;不可走 Bearer/`?key=` |
|
||||
| 强制改密 | 前端门控 + `/api/me` 标志;`changePassword` 要求原密码 | 服务端中间件拦截待改密/受限会话;设密分型(一次性会话不要求原密码) |
|
||||
| 账户 CLI | Backend 已有 create/reset-password/list/issue-login-key/revoke-login-key/bootstrap-admin;svc 已接 `user` 且附加 OpenExisting | 顶层/专题帮助未列账户入口;OpenExisting 仍 migrate;账户路径未完整验证 DB identity;参数回显及 argv 凭据需整改 |
|
||||
| 登录凭据 | 长期 `api_keys` 与独立 `login_keys` 已分离;一次性 Key 原子兑换为短期受限会话 | 原子开户+签发、统一密码变更及审计仍有缺口;不能把基础实现等同于整体验收 |
|
||||
| 强制改密 | Backend 已有受限会话和 must-change 中间件,强制设密成功销毁会话并要求重新登录 | Frontend 仍只有密码/长期 Key 两个入口,未接兑换及 sessionScope/reloginRequired;设密后直接 onDone 与后端不兼容 |
|
||||
| 安装双轨 | Dev `svc deploy` 多实例;Releases `install.sh` 系统 systemd | 统一部署计划;`install.sh` 薄封装或明确遗留 |
|
||||
|
||||
命题裁定(源码复核):
|
||||
|
||||
1. 长期 API Key 是 **show-once plaintext,不是 single-use** — **成立**。
|
||||
2. **无**统一中间件拦截 `must_change_password` — **成立**。
|
||||
1. 长期 API Key 是 show-once plaintext,不是 single-use;一次性登录 Key 是独立类型,当前代码已区分。
|
||||
2. r1 所记「无统一改密门」已被 U4 源码覆盖,不能继续作为待建能力;普通改密/管理员重置仍缺统一事务及旧恢复 Key 作废,见 `modules/backend/internal/server/accounts.go:208`、`modules/backend/internal/store/auth.go:244`。
|
||||
3. `scripts/svc.sh:1503` 已实现 user 转发,但帮助未列;`modules/backend/internal/app/app.go:743` 的账户插入和 Key 签发分别提交,不能采信注释中的「同事务」。
|
||||
|
||||
### 2.1 dev 8788 事件与归因边界
|
||||
|
||||
用户明确故障对象为 dev(127.0.0.1:8788)。17:37 的实际进程打开 `runtime/dev/data/agent-system.db`,数据库 marker 为 dev 的 SQLite 身份;该现场没有使用 PostgreSQL,不能沿用旧报告的 pg1/agent 描述。
|
||||
|
||||
| 只读对象(北京时间) | 账户身份 | 最后设密时间 | 与 live 摘要比较 |
|
||||
|---|---|---|---|
|
||||
| 12:35:03 快照 | 与 live 用户 ID 相同 | 09:52:11 | 不同 |
|
||||
| 14:50:37 快照 | 与 live 用户 ID 相同 | 09:52:11 | 不同 |
|
||||
| 17:37 的 live | 同一账户,must-change=0 | 16:03:20 | 当前值 |
|
||||
|
||||
比较仅输出时间、状态及相等性,不输出摘要或凭据。它证明字段重写,不证明明文改变;随机盐使同一明文的重新散列也可能不同。未发现正常启动/更新/迁移 up/设置播种自动覆盖既有密码的路径;现有 audit_events 只有 Surface 事件,无法归因此次写入。另有已消费恢复 Key,但其消费时间不能证明之后哪次设密由它触发。
|
||||
|
||||
前一轮观察到 dev 与候选 rdmcand 指向同一数据根;17:37 候选处于停止,因此历史共享不写成该时点双进程事实。18:14:09 续查时,外部流程已将候选重新启动于独立的 `runtime/rdmcand/data/agent-system.db`,实际文件 inode 与 dev 不同,登记和制品版本相符;dev 最后设密时间仍为16:03:20。这缓解了当前共享现场,不能代替 Backend 防误用锁或完整验收。历史共享说明跨实例影响范围,不证明某次更新主动改密;本轮未执行这些现场变更。
|
||||
|
||||
本轮不进行真实账户登录尝试或再次重置来验证旧密码;故障重放仅在脱敏、独立数据副本上执行。首批完成还需另行授权的 dev 原账户正常登录验收,见 U5/U8 合同;该验收不在 live 进行 kill、并发或故障注入。历史操作者归因仍未证实,新增审计不能反向补造旧事件。
|
||||
|
||||
## 3. 需求合同
|
||||
|
||||
@@ -69,6 +90,9 @@ product_contract_source: ce-plan-bootstrap
|
||||
| R10 | 集成 Key | 普通找回默认保留长期 API Key;失陷恢复显式 `--revoke-all-credentials` |
|
||||
| R11 | 首次管理员 | 仅核验为新实例(无用户且无历史业务标记);事务防并发;不得因「未发现管理员」接管有数据环境 |
|
||||
| R12 | 证据 | 验收绑定固定源码/制品摘要/环境;SELF/REPLAY/GATE 分源 |
|
||||
| R13 | 可发现与兼容 | 完整/短帮助、help user、实例 user --help 和文档列出实际账户能力;不支持的制品在调用前拒绝;帮助/探测不建库、不迁移、不启动服务 |
|
||||
| R14 | 账户稳定与审计 | 普通启停/更新不隐式重置;密码变更、恢复凭据/会话处理及成功审计原子提交;记录 actor、入口、实例、operation 与时间,不记录密码、摘要或 Key 明文 |
|
||||
| R15 | 运维既有库 | 账户操作核验预期库和实例;读操作不建库或 migrate;schema 不兼容明确拒绝,迁移走独立入口;CLI 参数和日志不暴露凭据 |
|
||||
|
||||
## 4. 技术决策(KTD)
|
||||
|
||||
@@ -92,6 +116,15 @@ KTD9. **候选校验完成前不停旧服务**;切换短窗;schema 迁移后
|
||||
|
||||
KTD10. **双轨收敛到同一部署计划。** 新旧 CLI 同后端;Releases `install.sh` 变为薄封装或文档降级为遗留,禁止第三套生命周期。
|
||||
|
||||
KTD11. **能力声明与帮助同源,但后端仍是执行权威。** 新制品提供无副作用的结构化能力声明;旧制品仅按已验证版本兼容,未知形态拒绝。禁止尝试未知子命令或靠 strings 包含某词推断能力。保留 reset-password 的直接重置语义,不偷偷改成签发恢复 Key。
|
||||
|
||||
KTD12. **统一密码与开户事务。** 严格唯一 INSERT;散列计算在事务外,事务内重新核验权限/账户版本。主动改密、CLI/管理员重置、恢复设密共同执行密码+标志+旧登录 Key 作废+规定会话处理+审计。普通路径保留集成 Key,失陷模式按 KTD8 明确撤销;失败全部回滚。
|
||||
首次管理员按实例串行,不能只依赖 owner UNIQUE:PG 锁定既有实例身份行,SQLite 使用立即事务,取得串行权后重新核验无用户、无历史业务;引导与能改变此前置条件的开户共用串行点。管理员、激活 Key 和审计共同提交;marker 缺失时由显式 init 处理,账户命令不得补建身份。
|
||||
|
||||
KTD13. **审计可归因,运维不隐式迁移。** 成功审计与变化同事务;失败记录注明未提交;HTTP actor 来自已认证会话,CLI 记录受信 OS 运维 UID/身份来源,不接受调用方填写的 actor 作为证明。实例身份和操作 ID 实填。既有库读命令只校验兼容性;迁移另行批准和执行。
|
||||
|
||||
KTD14. **凭据只经安全输入和单次交付。** 优先无回显输入/stdin/受保护文件,DSN 不传 argv。serve 已消费 AGENT_SYSTEM_DSN,账户 CLI 的等价安全输入需在 U7 显式接入并以能力声明核验,不能假定当前 user flags 已读取环境。非交互输出独占创建 0600 文件,日志/evidence 只记凭据 ID。提交后交付失败按 operation 查询,再撤销/重发;库存摘要不能重新打印旧明文,不把重试当首次创建。
|
||||
|
||||
## 5. 职责划分与接口示例
|
||||
|
||||
| 部分 | 负责 |
|
||||
@@ -123,7 +156,7 @@ Linux 服务账户与应用账户分开管理。
|
||||
2. 会话 scope / 中间件 allowlist;覆盖 `must_change` 普通首登。
|
||||
3. 设密接口分型:受限会话不校验原密码;普通改密继续要求原密码;同事务完成写 hash / 清标志 / 作废 Key / 吊销会话。
|
||||
4. 密码未设置状态:`password_hash` 可空或 sentinel;`VerifyLogin` 拒绝未设密;创建 = 用户行 + 激活 Key 同事务。
|
||||
5. CLI `OpenExisting`:目录/DB 不存在则失败;运维模式可禁止自动 migrate / 要求 schema 兼容。
|
||||
5. CLI `OpenExisting`:目录/DB 不存在则失败;账户运维默认只校验兼容 schema,不 migrate;迁移独立执行。配套 U1 v0.2 候选同此合同,原 requireCompatible 自动 migrate 是历史实现。
|
||||
6. `release@<ver>` 必须解析到该版本目录;缺摘要硬失败。
|
||||
7. 部署:获取/构建/校验不停旧服务;组合切换;迁移后回退独立判断。
|
||||
8. `install` 与 `--from` 同一计划;双轨收敛(KTD10)。
|
||||
@@ -144,10 +177,40 @@ Linux 服务账户与应用账户分开管理。
|
||||
| **U2** 二进制与源码来源 | 下载/离线导入、仓库物化、版本清单、候选先校验 | 无开发仓可部署;固定版本与摘要可核验;修复 release 钉扎 |
|
||||
| **U3** 环境检测与准备 | 系统适配器、依赖计划、专用工具链、监管配置 | Ubuntu/Debian 首验;幂等;不接管共享服务;binary 不装 Go/Node |
|
||||
| **U4** 一次性凭据与认证限制 | Backend CLI/Store/Server/迁移 | 原子开户/兑换/设密;受限会话无法调业务 API;并发兑换单胜 |
|
||||
| **U5** 脚本与登录页接线 | 账户命令、首次管理员、凭据交付、Login/设密页 | 新建与恢复走通;刷新与异常可续;DESIGN.md |
|
||||
| **U5** 脚本与登录页接线 | 账户帮助、无副作用能力探测、凭据安全交付、Login/设密页 | 新建与恢复走通;设密后清受限会话并返回密码登录;不支持的产品明确拒绝;DESIGN.md |
|
||||
| **U6** 组合与故障验收 | Dev 组合、发布包、真机、数据保护 | 两种部署 × 存储档;故障注入;浏览器 + 真机;治理回归 |
|
||||
| **U7** 账户事务与稳定性补齐 | 原子开户/引导、统一改密与撤销、审计、只读兼容打开 | 并发建号不覆盖;中断无半状态;旧恢复 Key 失效;身份缺失不改库;升级保持登录能力 |
|
||||
| **U8** 实例运维核验与凭据诊断 | 账户状态/事件查询、绑定和制品诊断;补齐 U1 身份消费 | 可定位合法变更来源、识别错库/失效会话/错误 Key 类型;只展示非秘密元信息 |
|
||||
|
||||
**近期优先 U1、U4**(可并行兄弟分支、共用 R0)。跨仓顺序:Backend(U4)→ Frontend(U5)→ Dev gitlink + `svc.sh`(U1/U2/U3/U5);组合 `make test` 后宣称可合入。
|
||||
**当前 U1/U4 基础已在源码中,近期优先 U7 和 U5,并与恢复方案 U8 隔离保护协调。** U7 先冻结后端账户事务/审计及能力声明合同;U5 随后完成浏览器与脚本;U8 诊断复用其记录。U2/U3 保留后续,不让通用安装器阻塞 dev 账户稳定。各仓从共同批准基线起独立任务;Backend → Frontend → Dev 组合,正式组合验证后才推进 gitlink。
|
||||
|
||||
### U7 近期实施与验证合同
|
||||
|
||||
覆盖 R5/R6/R9/R10/R11/R14/R15;依赖既有 U1/U4,实施负责人待指定。
|
||||
范围(相对于 Backend):`internal/store/auth.go`、`internal/store/login_keys.go`、`internal/store/platform.go`、`internal/app/app.go`、`internal/server/accounts.go`、`cmd/agent-system/main.go`;迁移目录仅在 schema 需要时改动。
|
||||
先刻画现有显式改密、重置及建号行为,再修复并发与中断窗口。账户校验、禁止隐式 migrate、严格 INSERT 和统一密码事务是单一后端实现,脚本不直接写表。
|
||||
|
||||
现有测试参考 `internal/store/login_keys_test.go`、`internal/server/login_key_test.go`、`auth_e2e_test.go`;新增 `internal/store/account_lifecycle_test.go` 与真实 PG 跨进程用例(路径相对于 Backend)。
|
||||
T7-1:两个独立进程同名开户,只有一个账户/激活 Key 成功,败者不改变胜者角色、密码和成员。
|
||||
T7-2:开户、Key 签发、改密、会话处理、审计提交各故障点,最终只见完整旧态/新态;输出失败但提交未知时按 operation 查询。
|
||||
T7-3:普通改密、临时重置、恢复设密后旧未用 Key 都不可兑换;长期集成 Key 按 R10 保留/撤销。
|
||||
T7-4:读命令命中旧 schema、缺库、错 marker 均拒绝且不 DDL/建库;两个独立进程以不同 owner 并发首次引导单胜,另覆盖引导与普通开户竞争;有历史业务而无用户时拒绝。
|
||||
T7-5:普通重启、两次更新、SIGTERM/SIGKILL 后测试账户原密码仍验证成功,账户权限及成员不变;不以摘要是否变化替代密码可用性。
|
||||
执行环境:独立 SQLite 副本、真实 PostgreSQL 独立库、独立端口;不在当前 weichen 账户上故障注入。所有 T7 用例当前 NOT_RUN。
|
||||
|
||||
### U5/U8 近期接线与验证合同
|
||||
|
||||
U5 覆盖 R7/R8/R9/R13/R15,依赖 U7 对外字段合同;范围 `scripts/svc.sh`、`docs/svc.md`、Frontend `src/api.ts`、`src/auth.ts`、`src/components/LoginPage.tsx`、`src/App.tsx`。复用现有登录/设密页,类型明确消费 sessionScope、passwordSet、reloginRequired;恢复 Key 不写持久浏览器存储或 URL。
|
||||
同一登录页保留默认账号密码入口,增加「激活/恢复 Key」入口并说明只用于设密;长期 API 密钥入口标清集成用途。错类型提示指向正确入口,切换清输入,更新初始密码旧说明,不新增独立恢复页面。
|
||||
刷新/兑换响应不确定时先查询会话,有效受限会话恢复设密;会话不存在且 Key 已消费/过期时提示联系账户管理员重发,返回「激活/恢复 Key」入口。无密码账户不得被引导用旧密码登录。
|
||||
测试参考 `tests/test_svc_user_binding.py`、Frontend `test/auth.test.ts`、`e2e/changepw-form.playwright.ts`;新增 Dev `tests/test_svc_user_help.py`、Frontend `e2e/login-key.playwright.ts`(计划文件)。
|
||||
T5-1:完整/短/专题/实例帮助覆盖六个账户命令,并均无 DB/目录/服务副作用。
|
||||
T5-2:旧产品和 RDM 不支持账户 CLI 时在执行前拒绝;stdout 单次交付,stderr/进程参数/history 无秘密;两类 Key 双向填错有正确引导且切换清输入。
|
||||
T5-3:激活/恢复完成兑换→设密→重新密码登录;刷新/响应丢失先核会话;Key 已消费而会话失效时经管理员重发的新 Key 可以续办;过期、重复兑换、CSRF 错误有准确提示。
|
||||
T5-4:受限会话无法访问业务/下载/SSE/admin/插件;设密成功后不得因直接 onDone 误放行。
|
||||
U8 覆盖 R2/R14/R15,依赖 U7 审计;在 `user info`/账户事件查询(拟新增)展示实例、设密时间、凭据类型及状态。错误配置、注销、Key 失效与密码错误分别诊断,普通登录错误不泄漏他人账户信息。CLI/HTTP 两入口产生可追溯同一 operation 记录;历史无审计事件保持未知。
|
||||
|
||||
首批 dev 原账户闭环(NOT_RUN):实现及隔离验证通过后,另行确认运行验收窗口/实例/版本,由 owner 在浏览器输入已知密码,检查原 user ID、角色、成员及原数据访问。若确实不能登录,明确恢复授权后才签发恢复 Key,保持账户和业务归属;不能为验收先重置能用的密码。随后在授权窗口验证普通重启及两次受控更新后原账户仍可登录。密码不交给 Agent、不进入证据;本轮不操作 live。
|
||||
|
||||
### 必须覆盖的验收场景(摘要)
|
||||
|
||||
@@ -172,11 +235,11 @@ flowchart LR
|
||||
## 9. 风险与未授权范围
|
||||
|
||||
- 实施、故障注入、真机部署、浏览器验收:**未授权 / NOT_RUN**。
|
||||
- 本任务交付终点:正式提案 r1 + U1/U4 规格 + 任务卡与索引入口;推送/PR 须另获授权。
|
||||
- 本轮交付终点:r2 本地草案、恢复配套修订、任务卡与索引、文档核查和审阅记录;以本地文档提交固定审阅对象并满足同步门禁。新增修订仍待批准,不推进 Dev gitlink、不推送/建 PR;启动/同步工具的任务元数据提交单独记录。
|
||||
- 与 recovery U1 重叠处只做增量,不重做已合入的 manifest 层。
|
||||
|
||||
## 10. 规划进展与下一步
|
||||
|
||||
- 本次推进:源码复核;四项取舍定案;正式提案 r1;U1/U4 规格细化。
|
||||
- 首选下一任务(**待授权**):并行启动 U1 实施与 U4 实施(兄弟分支、共用 R0);U2/U3 规格可随后写作但不阻塞 U1/U4。
|
||||
- 前置:人工批准本提案 r1(至少需求表 + 方案设计 + U1/U4 实施计划阶段);实施前 `make precheck` 与 `task-sync`。
|
||||
- r1 已批准;U1/U4 基础实现存在于当前固定源码,完整浏览器/故障/运行验收不可据此推断通过。r2 的新增需求和设计仍待人工评审。
|
||||
- 首选下一任务(待授权):恢复方案 U8 的 SQLite 服务隔离+本案 U7 账户一致性;先消除共享测试数据和不可归因密码变化,再落实 U5。U2/U3 保持后续。
|
||||
- 前置:审核新增 R13–R15、U7/U8 及 U5 更新,明确实现和隔离测试范围/owner;实现、测试、部署分别授权。Documents 与 Dev 文档草案位于各自独立工作区;正式组合、gitlink 推进与运行验收未执行。
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
---
|
||||
title: 面向非专业用户的工作台整体界面重设计
|
||||
revision: r0.2
|
||||
status: approved-for-continuous-implementation
|
||||
date: 2026-10-12
|
||||
owner: weichen
|
||||
scope: requirements-and-design
|
||||
implementation: implemented
|
||||
delivery: tracked-in-dev-task-record
|
||||
project-record: persisted
|
||||
---
|
||||
|
||||
# 工作台整体界面重设计 r0.2
|
||||
|
||||
用户在评审 r0.1 后明确授权“开始实施直到完成”。本稿 r0.2 保留已选设计,并通过本次独立任务连续实施、验证、Review 与合入。已有快慢通道执行方案的其他增量不由界面授权自动扩大。
|
||||
|
||||
## 1. 设计目标
|
||||
|
||||
让不懂命令、脚本、模型和代理的用户,通过表达目标、提供材料、查看结果、完成必要确认来推进工作。
|
||||
|
||||
默认界面回答三件事:现在在做什么,已经得到什么,下一步是否需要我处理。用户能够只用对话完成主要工作,也能在需要时展开工作摘要、阅读文件、核对依据。
|
||||
|
||||
用户明确要求:不要过于复杂;以辅助工作为中心;渐进、多层级展示;减少命令和脚本细节;大气、现代、简约、美观、易用。
|
||||
|
||||
本稿的场景假设:主要工作包括材料整理、分析比较、问题审查和文档生成,兼顾日常问答。业务领域的具体审批和发布入口按当前服务端能力提供。
|
||||
|
||||
## 2. 推荐形态与备选
|
||||
|
||||
推荐**渐进展开的三栏工作台**。左侧找项目与历史,中间通过对话推进工作,右侧按需处理工作或文件。普通问答默认收起右栏,复杂工作时提供概览;用户手动收起后不因普通更新反复打开。
|
||||
|
||||
| 形态 | 适用和取舍 | 本稿选择 |
|
||||
|---|---|---|
|
||||
| 渐进三栏 | 对话入口清晰,复杂任务可展开,文件有稳定位置 | 推荐 |
|
||||
| 纯对话 | 学习成本低;长文件、并行工作和多次确认容易淹没在历史消息中 | 作为轻量状态 |
|
||||
| 总览仪表盘 | 跨任务监控方便;默认要求用户理解更多指标和导航 | 仅在确有项目总览需求时另审 |
|
||||
|
||||
不单独建设快通道页、慢通道页或后台管理页。新增功能先判断能否放进现有对话、工作和文件入口。
|
||||
|
||||
## 3. 界面布局
|
||||
|
||||
**左栏:上下文。** 项目身份集中出现一次;新建对话、最近对话、搜索;文件和已启用的领域工作区放底部;账户与个人设置沉底。管理员操作只由管理员入口提供。
|
||||
|
||||
**中栏:推进工作。** 当前对话标题;用户的目标和材料;助手的结论、简短说明、必要动作;输入区上方一条工作状态。附件入口始终易找。权限设置保留清晰入口,展开说明其实际含义;初次使用采用现有默认值,不暗中扩大授权。
|
||||
|
||||
**右栏:工作 / 文件。** 工作按需要你处理、当前关注的工作、其他进行中或排队、新成果排列。完成历史收纳后仍可找回。文件负责列表、预览、编辑和下载;全屏阅读是同一个预览的放大。来源点击也进入同一预览对象,定位能力不足时说明定位范围。
|
||||
|
||||
左栏约 200–240,工作右栏约 320–420,中央弹性。正式落地继续消费已有拖拽宽度和文件阅读档规则。空间不足时先隐藏辅助栏;手机显示一个主视图,工作和文件按需打开,并有明确返回对话入口。
|
||||
|
||||
## 4. 渐进展示层级
|
||||
|
||||
| 层级 | 显示内容 | 打开方式 |
|
||||
|---|---|---|
|
||||
| L0 概览 | 后台工作数量、必要确认、新成果 | 一条状态行或小徽标 |
|
||||
| L1 摘要 | 业务目标、真实状态、当前工作、最多 3 条重要发现、缺项、下一步 | 当前任务卡或对话锚点 |
|
||||
| L2 依据与范围 | 阶段结果、来源、覆盖范围、未决问题和结论更正 | 原位置展开 |
|
||||
| L3 执行记录 | 按工作阶段分组的动作、结果和有权限查看的诊断信息 | 明确点击执行记录 |
|
||||
|
||||
默认 L0/L1,不展开所有任务。必要确认、重要限制和失败影响不能藏在 L2/L3。L3 不是模型内部思考的展示入口,也不改变日志和来源的访问权限。
|
||||
|
||||
示例任务卡:
|
||||
|
||||
> 整理三份项目材料 · 进行中
|
||||
> 正在核对:会议结论与需求说明
|
||||
> 当前发现:上线时间出现两种说法;3 项需求缺少验收条件
|
||||
> 待核查:评审意见中的补充要求
|
||||
> 查看依据与范围
|
||||
|
||||
没有阶段成果时诚实显示“尚无阶段结论,正在读取材料”。以上业务发现是示例数据,当前 U1 骨架并不证明已经具备真实阶段发现发布能力。
|
||||
|
||||
## 5. 快慢通道的连续体验
|
||||
|
||||
用户界面主要使用“助手正在处理”“后台继续整理”等业务语言。快通道是当前对话回合,慢通道是后台工作,不是由用户选择的快慢速度档位。
|
||||
|
||||
| 时刻 | 用户看到的内容 | 表述边界 |
|
||||
|---|---|---|
|
||||
| 发消息或材料 | 接收结果、可先回答的内容、接下来处理的范围 | 已选文件不等于上传成功;解析不等于分析完成 |
|
||||
| 任务登记或排队 | 同一工作对象显示已登记、排队中 | 登记成功才能说已登记;未开跑不能写进行中 |
|
||||
| 工作进行中 | 当前工作、真实阶段结果、缺项 | 没有可信进度就不显示百分比或预计完成时间 |
|
||||
| 用户继续输入 | 后台继续工作时可继续对话;前台忙时说明消息排队 | 发送不等于即时执行,不承诺已改变正在跑的任务 |
|
||||
| 有新成果 | 更新原卡;重要结果提供一条对话通知 | 不逐条回投工具动作,不把所有任务复制成另一条聊天流 |
|
||||
| 等待用户 | 操作、范围、影响和明确选择 | 等待、执行、生成、用户认可和正式发布分开 |
|
||||
| 完成或失败 | 结论、最多 3 个要点、范围或缺项、文件和下一步 | 保存失败不得声称已交付;部分完成不能冒充完整结果 |
|
||||
|
||||
后台更新不切换用户正在读的文件,不抢焦点,不把历史阅读强行滚到底部。状态恢复期间保留最后已知内容并注明“正在重新连接,最新进展待确认”。
|
||||
|
||||
## 6. 按工作选择展示形式
|
||||
|
||||
统一骨架保持稳定,内容形态随任务改变。默认由工作目的决定,用户无需先学习或配置一种展示模式。
|
||||
|
||||
| 工作 | 默认成果形式 | 进一步展开 |
|
||||
|---|---|---|
|
||||
| 简单问答 | 一段结论,必要说明 | 依据与例子 |
|
||||
| 材料整理 | 主要结论、问题和缺项 | 材料覆盖清单、来源 |
|
||||
| 方案比较 | 一条建议、关键差异表 | 判断依据、取舍和适用条件 |
|
||||
| 问题审查 | 按影响排列的问题清单 | 原文、影响、处理建议 |
|
||||
| 文档生成 | 草稿文件、完成范围、需要评审的事项 | 文件预览与后续修订 |
|
||||
| 多步骤流程 | 当前阶段、已完成阶段、必要动作 | 阶段结果与历史 |
|
||||
| 用户确认 | 简明操作说明、影响、选择 | 参数与诊断详情 |
|
||||
|
||||
图表仅在数量、趋势或关系能帮助判断时使用;可理解的短表不升级成图表。生成式任务页面作为可选增强,关闭插件后仍能通过任务卡、文字和文件读到主要结果。领域审批不能成为所有基座任务的固定步骤。
|
||||
|
||||
## 7. 等待确认与异常
|
||||
|
||||
确认卡先写操作及影响,例如“依据三份材料新增 1 份项目草稿,保留原件,不对外发送”。涉及覆盖、发送、发布或权限变化时,关键对象和影响必须在默认层显示。避免只有“是否执行”而没有范围。
|
||||
|
||||
对话和右栏操作同一确认对象。提交中阻止重复提交;已处理同步更新;超时显示“正在核实处理结果”,查清后再允许后续动作。示例稿只演示本地状态同步,不证明服务端幂等和恢复。
|
||||
|
||||
异常表述使用“发生了什么 → 对结果的影响 → 用户可以做什么”。例:“评审意见未能读取;已整理另外两份材料,完整结论尚未生成;可补充清晰版本或先讨论已有结果”。错误代码、脚本与输出置于授权可读的详情。动作只按服务端当前能力显示;未核验的暂停、独立取消、续跑、自动重试不进入默认设计。
|
||||
|
||||
## 8. 视觉规则
|
||||
|
||||
沿用 DESIGN.md 和 @ui/tokens.css:灰白表面阶梯、单色反色主按钮、发丝边框、克制语义色;清晰的标题与正文层级;常用信息保持可读,不以缩小字号装下所有内容。
|
||||
|
||||
大气来自稳定分栏、整齐对齐、合理阅读行长和区块间距;简约来自减少同时出现的内容。没有营销式大标题、装饰渐变、速度表盘、满屏彩色卡片或默认工具日志。
|
||||
|
||||
字型走 --fs-ui-*,界面字号可调。状态同时有文字和形状。折叠消费 @ui Collapsible,动效只用 mk-* 并响应减少动效。交互稿复制固定 UI 令牌,实际使用当前 Collapsible 源码与 MotionKit,不新建颜色和动效体系。
|
||||
|
||||
## 9. 当前依据与依赖
|
||||
|
||||
本轮只读源码核对,来源 SELF;没有对生产或当前 dev 服务作功能验收。
|
||||
|
||||
| 对象 | 固定提交 | 核对点 |
|
||||
|---|---|---|
|
||||
| Dev | 4d362537d0e8755a03b1757b5bad92779a064b33 | DESIGN.md、policy/delivery.md、既有规划 |
|
||||
| Frontend | 1edd872c554f666ba43353da7e6f0605ecec311b | Workbench.tsx、Conversation.tsx、Workspaces.tsx |
|
||||
| Backend | acabb85e2ae970f834defae916c7539d0a47993d | spawnBackgroundOpts、CancelRun、createBackgroundCard、finishBackgroundCard |
|
||||
| UI | 83e80f5648649c3cc070f4dbc6bf118996828ae8 | tokens.css、Collapsible.tsx、motion.css |
|
||||
| Documents | 3cc6438030803b8e2355d2867766e9654203f265 | 快慢通道展示 r1.1 及 U1 实施计划 |
|
||||
|
||||
当前读到的源码已有三栏“工作 / 文件”、前台忙时输入排队、后台并行限制、排队工作、精炼卡片骨架以及失败 CardFailed 映射。这里只说明源码形状,不推断已部署与运行表现。
|
||||
|
||||
与既有方案衔接:`modules/documents/docs/proposals/2026-10-12-fast-slow-channel-display.md` 是快慢通道摘要与异步投影的已有主记录;本稿补充整体交互与各种成果形式,不另起一套状态或快照契约。U2/U3/U4 的真实阶段发现、持久恢复、确认闭环和窄屏完善继续以原记录及后续批准为准。
|
||||
|
||||
## 10. 实施需求
|
||||
|
||||
以下为本次界面实施与验收范围;实现消费真实已有能力,不伪造尚未发布的阶段发现。
|
||||
|
||||
| ID | 需求 | 优先级 | 可判定的验收方向 |
|
||||
|---|---|---|---|
|
||||
| UI01 | 对话能完成主要工作 | P0 | 关右栏仍能读摘要、核对依据、处理确认、打开成果 |
|
||||
| UI02 | 普通问答保持轻量 | P0 | 无后台工作时不生成空任务卡和空进度条 |
|
||||
| UI03 | 默认内容可支持下一步 | P0 | 用户能说明当前工作、结果范围、必要下一动作 |
|
||||
| UI04 | 快慢通道连续展现 | P0 | 前后台并行、排队和完成状态归属正确且不重复刷屏 |
|
||||
| UI05 | 四层渐进阅读 | P0 | 默认无命令日志,关键限制和确认不被折叠藏起 |
|
||||
| UI06 | 成果按目的呈现 | P1 | 整理、比较、审查和生成各能支持对应工作判断 |
|
||||
| UI07 | 状态与动作忠实 | P0 | 不伪造进度,不暴露未支持控制,不把失败显示成功 |
|
||||
| UI08 | 同一文件同一预览 | P0 | 对话、来源、文件列表均进入同一预览位置 |
|
||||
| UI09 | 确认结果一致 | P0 | 双入口、重复点击、超时未知和已处理均有一致表现 |
|
||||
| UI10 | 阅读稳定 | P0 | 普通后台更新不抢焦点、换文件或改阅读位置 |
|
||||
| UI11 | 窄屏和大字可用 | P0 | 320/390/736/1024/1440 及 18px 字号必要动作可达 |
|
||||
| UI12 | 遵守设计系统 | P0 | 令牌、Collapsible、MotionKit、对比度守护符合规范 |
|
||||
| UI13 | 能力与权限匹配 | P0 | 未启用领域入口不显示;摘要与来源不绕过访问控制 |
|
||||
|
||||
最终产品验收场景:三个附件无文字发送;前后台并行及排队;确认双入口;完整/部分/失败结果;查看来源与文件;刷新和断线;新对话;窄屏、大字、键盘及减少动效。r0.1 设计评审时,真实模型、真实后端和真实浏览器任务验收均为 NOT_RUN;实施期结果见第 13 节,示例交互稿不能代替验收。
|
||||
|
||||
## 11. 落地次序建议
|
||||
|
||||
1. **整体界面与文案。** 在既有三栏和 U1 上整理默认内容、必要操作和阅读路径。优先确定 UI01–UI03/UI05/UI08/UI12;不在此增量改变后台执行契约。
|
||||
2. **动态工作摘要。** 接续既有快慢通道 U2/U3,在真实快照与检查点之上显示业务发现、范围和恢复状态;避免另外安排重复任务。
|
||||
3. **成果形式与适配。** 衔接 U4,完成比较、审查、可选任务页面、窄屏和具体领域入口。先用结构化文字/表格,再增强生成式展示。
|
||||
|
||||
r0.1 布局与展示已获连续实施授权,当前按 r1 计划交付界面。完成本增量后的首选衔接仍是既有快慢通道 U2/U3 的真实阶段发现与恢复验收;需先核对其在途任务和批准范围,不能由本界面任务重复启动或改变路由。
|
||||
|
||||
## 12. 授权与实施记录
|
||||
|
||||
来源:2026-10-12 用户在本聊天评审 r0.1 后指示“开始实施直到完成”。模式 authorized-continuous;阶段 1–10 在本稿界面范围内连续推进,平台门禁和高后果双钥匙保留。启动检查从已登记干净 Dev 检出捕获,后由 make task-start 创建 feature/work-companion-ui,并导入原始 SELF 收据。保护主检出的 Frontend 更新与其他任务现场。
|
||||
|
||||
实施计划见 [r1](2026-10-12-work-companion-ui-plan.md);进展和原始证据仅维护于 Dev .task/feature-work-companion-ui.md。PR、CI、Review、合入与部署分别记载,不因本授权预先标为通过。
|
||||
|
||||
## 13. 实施进展与能力边界
|
||||
|
||||
2026-10-12:渐进任务卡、轻量对话/输入、响应三栏和单一异步状态投影已形成可审阅候选。SELF 验证包括 Frontend 210 与 UI 155 单元测试、类型/设计守护/knip、Dev make test 与 make build;现有 Playwright 11 个展示场景、6 个移动导航场景及隔离 HTTP/MockRunner 2 个真实接口链路场景通过。原始命令、精确对象和完整输出以 Dev 任务卡为准,测试成功不推断已经合入或部署。
|
||||
|
||||
原始独立代码 Review 已完成,必要问题均已有整改候选;最终精确版本复审、组合 CI 与合入进展只维护在 Dev 任务主记录,方案正文不复制第二份交付状态。UI 仓原 CI 在下载 GitHub action 时失败,交付补充改用既有平台固定 SHA 检出和 Node22 镜像,保留原测试;安全和规范 Review 及实际平台结果均须记录。
|
||||
|
||||
动态摘要只消费系统发布的真实内容:缺少阶段发现时显示诚实占位,不生成示例百分比、ETA 或虚构成果。真实模型阶段发现质量 NOT_RUN,后台自动路由和模型提示词未在本增量修改。旧运行服务未更新;最终组合、Review、GATE 和本任务安全收口以 Dev 主记录为准。
|
||||
@@ -0,0 +1,154 @@
|
||||
# Work companion interface implementation plan r1
|
||||
|
||||
> **For agentic workers:** Implement in independent units with ce-work native workers; the orchestrator owns integration, evidence, commits, Review and Gitea delivery. Use test-first coverage for behavior changes. User authorization: “开始实施直到完成”; continuous execution is limited to the approved interface design.
|
||||
|
||||
**Goal:** Deliver the approved simple, modern, progressive workbench through real project, conversation, activity-card, confirmation and file APIs.
|
||||
|
||||
**Architecture:** Keep the three existing pane responsibilities. Project existing ActivityCard bodies into readable summaries in the UI library; Frontend integrates them into conversation and work panes. Preserve server authority and harden event, query and action races in the one Frontend store. No new task executor, model routing, database schema or UI vocabulary is required.
|
||||
|
||||
**Tech Stack:** React 19, TypeScript, existing @ui Collapsible/MotionKit/tokens, Vitest, Playwright, Go backend with existing API and SSE.
|
||||
|
||||
**Spec:** [Approved interface design](2026-10-12-work-companion-ui-design.md), UI01–UI13; [existing fast/slow design](2026-10-12-fast-slow-channel-display.md), U1 skeleton and applicable presentation rules. Dynamic model-generated findings remain dependent on the existing U2/U3 work; this interface renders real available content and an honest placeholder otherwise.
|
||||
|
||||
## Global constraints
|
||||
|
||||
- Settled user decision: three pane workbench, conversation first, “工作 / 文件” in the same right pane, one preview object.
|
||||
- Settled user decision: concise default content and progressive depth; necessary confirmation and outcome limits stay visible.
|
||||
- Colors/radii/type consume @ui/tokens.css, type uses --fs-ui-*, motion only mk-*, folds use Collapsible.
|
||||
- No percentage, ETA, pause, independent cancel, resume or retry buttons unless supplied by a verified server action.
|
||||
- State is derived from real cards, runs, files and responses; no prototype example data enters production.
|
||||
- Model internal thinking and command parameters/output do not occupy the normal reading layer.
|
||||
- Main checkout and other task worktrees are protected. All owned changes live in feature/work-companion-ui.
|
||||
- Evidence uses the Dev make evidence tool. Local checks are SELF; current PR HEAD CI is GATE.
|
||||
- Component branches are based on their authoritative origin/main. Dev is based on R0 4d362537d0e8755a03b1757b5bad92779a064b33.
|
||||
- No deployment/restart of existing services, data migration, credentials or branch-protection changes.
|
||||
|
||||
## Review focus
|
||||
|
||||
1. Older SSE frames or delayed queries must not replace newer cards or inject data into a different conversation/project.
|
||||
2. Replay of a currently running conversation must still reconstruct its live output while duplicates are dropped.
|
||||
3. A confirmation submitted through either view must block duplicate submission and represent unknown results honestly.
|
||||
4. Closing auxiliary panes and opening files must leave necessary work and confirmation paths accessible at 320px and 18px UI type.
|
||||
5. New background results must not take over an existing file, focus or reading position; result summaries must retain failure and coverage limits.
|
||||
|
||||
## U1 — Progressive activity cards and work groups
|
||||
|
||||
**Own files:** UI src/ActivityCardView.tsx, src/InlineConfirmCard.tsx, src/InboxList.tsx, src/index.ts, src/ui.css, new src/activitySummary.ts, src/ProgressCardBody.tsx and focused UI tests. Do not change generated contracts or tokens.
|
||||
|
||||
**Consumes:** Existing ActivityCard/UINode and DocBridge; U1 body keys 状态/正在做/当前发现/剩余/下一步. Unknown words remain supported by the generic renderer.
|
||||
|
||||
**Produces:** Existing ActivityCardView remains source-compatible; export activitySummary/cardStatusLabel/groupActivityCards as pure projections. CardViewCallbacks and InlineConfirmCallbacks may add `actionState?: (card: ActivityCard) => 'submitting' | 'unknown' | undefined`; existing callbacks remain optional. Core vocabulary is unchanged.
|
||||
|
||||
- [ ] Add tests for queued and running labels, modern failed and legacy done+danger, no-findings placeholder, internal material keys hidden by default, real document nodes still reachable, and confirmation buttons disabled for submitting/unknown.
|
||||
- [ ] Run the focused Vitest tests before production edits; record expected red assertions through evidence.
|
||||
- [ ] Build the projection with literal canonical body keys and card states; never interpret arbitrary output as a new execution fact.
|
||||
- [ ] Render L1 summary first, remaining body and source/range information in Collapsible, diagnostic metadata behind a nested explicit record entry. Known failure/remaining/next-step content must remain visible.
|
||||
- [ ] Keep unknown/legacy bodies intact in the generic detail renderer. Tables, structured lists and document references retain their current renderer.
|
||||
- [ ] Group unpinned work as needs-action, active, results, history, preserving order inside each group. Pinned items remain stable.
|
||||
- [ ] Simplify chrome; use text plus status shape and existing neutral surfaces.
|
||||
- [ ] Verify full UI suite, tsc and design/contrast guards; hand off files and red/green evidence without committing.
|
||||
|
||||
Example behavioral expectation:
|
||||
|
||||
```ts
|
||||
const queued = { ...card, status: 'active', body: [{ type: 'kv', kv: [['状态', '排队中'], ['材料键', 'mk_private']] }] }
|
||||
expect(cardStatusLabel(queued)).toBe('排队中')
|
||||
expect(groupActivityCards([completed, pending, queued]).map(g => g.key)).toEqual(['needs-action', 'active', 'results'])
|
||||
```
|
||||
|
||||
## U2 — Conversation, input and inline work reading
|
||||
|
||||
**Own files:** Frontend src/components/Conversation.tsx, src/components/ProcessTimeline.tsx, src/messageparts.ts if required by process policy, new src/components/ConversationWork.tsx, new src/companion-conversation.css, focused conversation/messagepart tests. Do not edit styles.css, App, Workbench or store.
|
||||
|
||||
**Consumes:** Existing store fields and actions; existing UI ActivityCardView/Collapsible/DocBridge, including the additive actionState callback. The orchestrator supplies state.cardActionStates.
|
||||
|
||||
**Produces:** ConversationWork renders current cards from the same store in an inline Collapsible; default ordinary Q&A has no empty progress. Component CSS imports live in the owned component file.
|
||||
|
||||
- [ ] Add failing behavior tests for normal Q&A without progress, task summary reachable while right pane is closed, progress record folded by default, failure/limits visible, and process final answer outside its fold.
|
||||
- [ ] Replace command-oriented empty states with goal/material prompts and three optional natural-language examples that fill input rather than trigger hidden work.
|
||||
- [ ] Simplify header; keep execution profile, cross-reading and session settings inside a clearly labeled settings fold, preserving existing behavior and consent.
|
||||
- [ ] Keep add-materials and send visible; move permission selector into operation settings without changing its effective value. Explain queue state and upload failures in user language.
|
||||
- [ ] Show a light continuity line from real runs/cards with confirmed counts; inline work uses the same cards/actions as the work pane.
|
||||
- [ ] Fold tool parameters and output even during running by default; keep a compact real phase label and preserve manual expansion. Do not display model internal thinking as ordinary content.
|
||||
- [ ] Protect scroll reading and reset compose/expanded context correctly on conversation switches; do not remove artifact or rewind capabilities.
|
||||
- [ ] Verify focused tests and the integrated Frontend suite; hand off files and evidence without committing.
|
||||
|
||||
Example behavioral expectation:
|
||||
|
||||
```ts
|
||||
expect(showProcessInline(live, true)).toBe(false)
|
||||
expect(showProcessInline(live, false)).toBe(true)
|
||||
// Render real ConversationWork with zero cards: no progress object is produced.
|
||||
// Render with a real active progress card: summary is present independent of rightCollapsed.
|
||||
```
|
||||
|
||||
## U3 — Responsive shell and context navigation
|
||||
|
||||
**Own files:** Frontend src/App.tsx, src/components/TopBar.tsx, src/components/TaskSidebar.tsx, new src/companion-shell.css, new src/workbenchLayout.ts and focused shell/layout tests. Do not edit store, Conversation, Workbench, shared styles.css or UI.
|
||||
|
||||
**Consumes:** Existing leftCollapsed/rightCollapsed/rightTab/previewExpanded and store pane/file operations. May add only local ephemeral responsive state, not another asynchronous task owner.
|
||||
|
||||
**Produces:** Desktop three pane layout; narrow screen one active pane with clear contextual return actions, using the same Workbench/PreviewPane objects. Export a pure layout selector if a decision is needed for tests.
|
||||
|
||||
- [ ] Write failing behavioral tests for single-pane navigation, restoring conversation, expanded file reading, and no hidden-only essential operation.
|
||||
- [ ] Match the approved calm prototype through spacing and type hierarchy, preserving canonical palette and default existing theme preferences.
|
||||
- [ ] Keep project identity on the left, conversation identity central, work/files on the right. Rename primary creation to 新建对话 where it actually creates a conversation.
|
||||
- [ ] Reduce duplicate permanent chrome; retain project creation/search/account/admin/available workspace paths.
|
||||
- [ ] Adapt to 320/390/736/1024/1440; hide/return controls remain keyboard- and touch-accessible. Do not let stored pane widths force horizontal overflow.
|
||||
- [ ] Keep file expansion as one preview enlargement, not another overlay or fourth pane.
|
||||
- [ ] Verify layout tests and report desktop/mobile screenshots after integration; hand off owned files without committing.
|
||||
|
||||
## U4 — One state owner, safe updates and confirmation feedback
|
||||
|
||||
**Own files:** Frontend src/store.ts, new src/eventProjection.ts if a pure helper is useful, src/components/Workbench.tsx, src/components/PreviewPane.tsx only when integration requires it, focused store tests. Orchestrator implements this unit.
|
||||
|
||||
**Consumes:** Existing SSE event identity/seq/runId, conversation detail resumeSeq/lastSeq, cards API, project events, cardAction and resolveHITL APIs.
|
||||
|
||||
**Produces:** Store `cardActionStates: Record<string, 'submitting' | 'unknown'>`; both work and inline confirmation callbacks read this same map. Current session/project cursors and query generation checks remain in one store.
|
||||
|
||||
- [ ] Add red tests for duplicated and stale cards; delayed conversation/project list queries after switching contexts; foreground replay versus background agent notes; duplicate action submission; unknown response followed by a server query; new Surface while reading a file.
|
||||
- [ ] Guard event application by current context and per-stream applied sequence. Live replay uses its own replay cursor and never re-applies older card/plan/status projection effects.
|
||||
- [ ] Guard asynchronous queries by their requested context and generation/sequence so slow snapshots do not wipe newer events or another context's state.
|
||||
- [ ] Suppress background progress in foreground token output; update actual runs/cards instead of creating an unrelated LiveState.
|
||||
- [ ] Lock confirmation/action submission by card or HITL identity before awaiting. Clear on observed server outcome. Unknown results remain disabled until read-only reconciliation determines the current state; do not blindly resend an effect.
|
||||
- [ ] Show submitting and unknown feedback at both entrances. Preserve all server-supplied actions and their original scope.
|
||||
- [ ] Leave current file/Surface selection and explicit pane preference intact on background updates; show a small new-result cue rather than auto-opening.
|
||||
- [ ] Default new users to a light, compact conversation layout with right pane closed; keep saved theme/layout choices and explicit file opening.
|
||||
- [ ] Verify focused store tests, integrated Frontend tests, and browser cross-view flows.
|
||||
|
||||
Example behavioral expectations:
|
||||
|
||||
```ts
|
||||
store.applyEvent({ ...newerStatus, seq: 12 })
|
||||
store.applyEvent({ ...olderStatus, seq: 11 })
|
||||
expect(store.getState().cards[0].status).toBe('done')
|
||||
// Hold the first action response; call through the second view and assert one API request.
|
||||
// Resolve or query the real returned card and assert both views leave submitting together.
|
||||
```
|
||||
|
||||
## U5 — Integration, browser acceptance and delivery
|
||||
|
||||
**Own files:** Dev DESIGN.md, PROJECT.md, task card and exact gitlinks; Documents design/plan/index and delivery record; Frontend e2e/work-companion.playwright.ts and isolated browser fixtures if required; external screenshots and receipts.
|
||||
|
||||
- [x] Record authorization and implementation units; retain original startup evidence unchanged.
|
||||
- [x] Integrate all workers, inspect owned paths and contracts, run authoritative focused tests, and commit logical component changes with Why/Evidence/Impact/Refs bodies.
|
||||
- [x] Update DESIGN §9.6 and information architecture to the approved progressive behavior; no palette changes are planned, so do not change canonical token values merely to create a paired diff.
|
||||
- [ ] Run make task-sync through evidence at acceptance, review and merge checkpoints; resolve any parent/component conflicts without altering unrelated owner work.
|
||||
- [x] Pin exact committed component revisions and run Dev make test plus make build through evidence.
|
||||
- [x] Browser checks: normal conversation; three selected attachments; background task plus foreground input/queue; pending confirmation through either entrance; done/failed/partial results; real file preview; reading preserved during update; duplicate/stale updates; refresh/switch; all five widths and 18px type.
|
||||
- [x] UI fixture-driven browser cases validate presentation only. Use an isolated real backend/browser smoke for API wiring, file/confirmation/card persistence where feasible. No mock model findings are reported as live-model acceptance.
|
||||
- [ ] Run required simplification and independent code review; fix findings, re-run affected checks, and record reviewer/object identity.
|
||||
- [ ] Push component branches, create and attach Gitea PRs, verify their current HEAD required CI and merge in dependency order. Update Dev pins to merged revisions, verify combination CI at current Dev HEAD, Review and merge Dev PR.
|
||||
- [ ] Fold/close only this task card under continuous authorization. Preserve or safely reclaim only owned workspace artifacts. Do not modify active main checkout state for other tasks.
|
||||
|
||||
## Definition of done
|
||||
|
||||
UI01–UI13 are mapped to observed source/tests/browser outcomes or an explicit inherited capability limit; no prototype fixture enters product state. All changed components compile and relevant tests pass. Current-head mandatory CI is verified before merge. Review findings are closed. The actual merged Dev combination and saved evidence are recorded. Existing running services remain unchanged; deployment is a separately identified operation.
|
||||
|
||||
Continuous authorization covers implementation, verification, reversible isolation, documentation, commit/push/PR, agent Review/merge and task-specific safe closure. Stops apply to genuine scope changes, unowned content collisions, missing current-head platform gates and high-consequence dual-key operations. These conditions do not require re-approval of routine already-authorized work.
|
||||
|
||||
## Delivery status
|
||||
|
||||
2026-10-12: U1–U4 implementation candidates are integrated; U5 local combination and browser checks passed as SELF evidence. Original independent review is complete; the required fixes are implemented and locally verified. Final fixed-version review, current-head platform CI/merge and safe closure are tracked only in the Dev task main record; this plan does not maintain a second delivery-status copy. Code review may produce small corrective iterations; each has its own fixed object and relevant replay. The UI CI bootstrap repair is required to run the retained checks, not a waiver of them. Actual merged versions and final verification remain recorded in the Dev task card; no existing service is deployed by this task.
|
||||
|
||||
2026-10-12 corrective candidate: UI0da2e3a / Frontend43d1933. SELF: UI155 and Frontend210 tests with type/knip checks, 11 presentation plus6 mobile-navigation browser cases,2 isolated realHTTP/MockRunner cases. The live attachment case now proves exact upload→send→persist associations across reload. The review repairs cover source links, per-option context, real browser scroll/focus, terminal reconciliation, action feedback ownership, explicit preview intent, latest outcomes and visible public explanations. These are interface and state-projection corrections; no live-model routing, prompt or existing-service deployment change. Final delivery facts are recorded in the linked Dev PR/task archive.
|
||||
@@ -0,0 +1,243 @@
|
||||
---
|
||||
title: RDM 设置归属、成员、文档职责与权限矩阵完善增量方案
|
||||
date: 2026-10-13
|
||||
type: feature
|
||||
execution: code
|
||||
artifact_contract: rdm-increment-plan/v1
|
||||
product_contract_source: legacy-requirements
|
||||
---
|
||||
|
||||
# RDM 设置归属、成员、文档职责与权限矩阵完善增量方案 r1
|
||||
|
||||
负责人:weichen;编制:ZCode;核对日期:2026-10-13(北京时间)。
|
||||
上游方案:[2026-10-12 RDM 功能、实现与计划矩阵及整改方案](2026-10-12-rdm-function-implementation-plan.md)(下称"总案"),本增量承接其本稿 U3、U4、U6,涉及职责一致性的部分衔接 U5。
|
||||
|
||||
评审状态:2026-10-13 用户评审通过(同意方案及技术评审意见),并授权按本方案实施(P1–P8 两批推进;正式验收与清理回收节点保留人工确认)。技术评审对源码声明的逐项核查结论见文末「评审核查记录」。
|
||||
|
||||
## Goal Capsule
|
||||
|
||||
以现有 RDM 实施总案的一个完整增量,先厘清设置归属和服务端权限,再补齐搜索、选择、职责分配与权限矩阵交互,保证界面显示、保存结果和实际执行一致。终点:创建者、普通成员、职责人员在真实账号浏览器流程中完成成员添加、职责分配、权限查看与设置保存,且服务端边界(受管设置、成员校验、原子职责变更、权限范围)全部经真实请求验证。
|
||||
|
||||
非目标:不扩展飞书集成、组织架构、多角色叠加或全量文档生成工程。
|
||||
|
||||
## 一、当前实现与需要补齐的内容
|
||||
|
||||
| 方面 | 当前源码情况 | 本次需要完成 |
|
||||
|---|---|---|
|
||||
| 设置归属 | 项目设置展示完整 schema;用户、项目设置都能覆盖模型等配置 | 设置作用域、管理员系统设置入口、写入与最终生效值双重约束 |
|
||||
| 成员管理 | 手填账号;已有分页账号目录,但只有账号和有效态 | 账号/姓名搜索、提示选择、下拉浏览、专业角色过滤、明确的项目身份修改 |
|
||||
| 文档职责 | 手填文档 ID 和人员账号;主要读取提交快照 | 文档搜索/列表/树选择、当前职责回填、项目成员选择、提交校验 |
|
||||
| 权限查看 | 已有单成员权限解释表 | 单成员详情与多人矩阵、中文标签、项目动作范围、上限内配置 |
|
||||
| 一致性 | 存在职责目标未校验成员、职责更新与审签失效分步执行等缺口 | 服务端统一校验、原子变更、版本冲突、撤权及历史保全 |
|
||||
|
||||
对应实现锚点:Frontend `src/components/ProjectSettingsModal.tsx`、`src/components/adminRdmSections.tsx`;Backend `internal/settings/settings.go`(覆盖链 `defaults → system → user → project`);RDM `plugins/rdm/plugin.go`、`internal/perms/perms.go`、`internal/rdmapp/docsubmission.go`。
|
||||
|
||||
## 二、设置归属与界面结构
|
||||
|
||||
沿用现有设置入口和 `SettingsShell`,项目设置收敛为四个页面:
|
||||
|
||||
| 页面 | 内容 |
|
||||
|---|---|
|
||||
| 项目设置 | 真正属于本项目的共享配置与协作规则 |
|
||||
| 项目成员 | 成员搜索、添加、项目身份调整、移除 |
|
||||
| 文档职责 | 文档查找、职责查看与分配、相关审签状态 |
|
||||
| 项目权限 | 单成员权限详情、成员权限矩阵、允许范围内的配置 |
|
||||
|
||||
系统管理中补齐“模型与服务配置”,承接主模型、轻量模型、Embedding、Rerank、模型密钥与 Tavily 等系统配置;Agent 工具限制、系统插件、全局专业角色和权限上限也归系统管理。个人设置只保留个人偏好。
|
||||
|
||||
实施时需要处理三个层面:
|
||||
|
||||
- **展示范围**:设置描述携带允许作用域、管理资格、生效时机;项目页面只消费项目项。
|
||||
- **写入范围**:用户/项目 API 拒绝写入系统受管项,包括嵌套字段和点路径形式,插件设置也遵守同一规则。
|
||||
- **实际生效**:旧用户/项目覆盖值不能继续影响系统模型;个人画像的模型路由及个人模型密钥也必须纳入受管校验,堵住其他覆盖入口。
|
||||
|
||||
另外,当前“项目设置”实际上按“用户+项目”保存(Backend `Effective(owner, projectID)`,project scope 物理存储在各 owner 名下)。需要区分:
|
||||
|
||||
- **共享项目业务配置**:以项目为权威,同一项目不同成员读取一致。
|
||||
- **个人在该项目中的偏好**:继续属于个人。
|
||||
|
||||
跨会话读取必须保留本人会话的隐私边界,不能因项目配置共享而开放其他成员的私聊、上传原件或个人草稿。
|
||||
|
||||
## 三、成员管理交互
|
||||
|
||||
采用**一个可搜索的人员选择器**,同时支持输入、提示选择和下拉浏览,不为每种途径增加独立页面。
|
||||
|
||||
添加流程:打开人员选择器 → 输入账号或姓名,或浏览候选 → 可按专业角色过滤 → 选择人员 → 设置项目身份 → 添加。
|
||||
|
||||
具体行为:
|
||||
|
||||
- 输入账号支持精确匹配;姓名、账号支持模糊检索。
|
||||
- 未输入时显示分页候选;选择器内提供“全部专业角色/系统工程师/软件工程师……”筛选。
|
||||
- 候选显示“姓名、账号、专业角色”;同名人员通过账号区分,姓名为空时使用账号。
|
||||
- 已加入人员标记“已加入”,避免重复添加造成隐式身份变更。
|
||||
- 最终提交稳定账号标识,不能直接提交搜索文字。
|
||||
- 成员表分别展示“专业角色”和“项目身份”,不混用两者。
|
||||
|
||||
项目身份使用“项目负责人/项目成员”等中文名称。成员行提供明确的“调整项目身份”和“移除”操作;继续保护最后一位负责人。
|
||||
|
||||
服务端复用已有 `rdm.account.list`,补齐受限的姓名搜索、精确账号校验和专业角色摘要。**不能直接把管理员用户列表或包含全部账号绑定的角色管理接口开放给项目负责人。**
|
||||
|
||||
角色筛选只帮助找到人员;项目负责人不能借此修改账号的全局专业角色。账号有效状态必须来自基座实际能力,不能把当前简单的 `valid=true` 当作完整的账号停用机制。
|
||||
|
||||
## 四、文档查找与职责分配
|
||||
|
||||
文档职责页面采用“**文档清单+选中文档的职责详情**”:
|
||||
|
||||
- 上方提供统一搜索框,支持文档 ID 精确检索、标题精确/模糊匹配。
|
||||
- 支持文档列表与树形浏览;阶段、文档类型、未分配/已分配、审签状态可用于筛选。
|
||||
- 树形视图忠实呈现当前文档结构,只有文档节点可以作为职责分配对象,章节不能误作 `docId`。
|
||||
- 搜索、列表和树选择共用同一目录与选中状态。
|
||||
- 结果显示名称、阶段/类型、职责概况和状态;ID 保留为辅助定位信息。
|
||||
|
||||
已有文档树查询属于审计面,不能降低它的授权规则来供选择器使用。应补齐专用的职责管理元数据读面:
|
||||
|
||||
- 有职责分配权的管理者可以读取必要的管理元数据。
|
||||
- 普通成员只获得其有权查看的文档范围。
|
||||
- 标题、数量、筛选结果和树节点均在服务端过滤,避免通过搜索泄露不可见资源。
|
||||
|
||||
选中文档后,立即读取并回填**当前职责**,包括尚未提交过审签的文档。当前职责与“某轮提交冻结的职责名单”分别展示,不能混为一份数据。
|
||||
|
||||
人员选择规则:
|
||||
|
||||
| 职责 | 选择方式 | 约束 |
|
||||
|---|---|---|
|
||||
| 编制人 | 搜索、下拉、专业角色过滤 | 单选 |
|
||||
| 审核人 | 搜索、下拉、专业角色过滤 | 多选,至少一人 |
|
||||
| 批准人 | 搜索、下拉、专业角色过滤 | 单选 |
|
||||
|
||||
**所有候选只能来自当前项目成员。**保存时服务端再次校验账号、项目成员关系、对象归属、操作资格和职责版本;文档级(`rdm.review.assign.doc`)、章节级(`rdm.review.assign`)及旧命令入口均遵守同一规则。
|
||||
|
||||
保留编制、审核、批准互异的规则。专业角色筛选不自动授予文档职责;管理权也不自动获得代编、代审或代批资格。
|
||||
|
||||
职责变更需要补齐以下行为:
|
||||
|
||||
- 在途审签受影响时,先显示受影响轮次与“需要重新提交”的提示。
|
||||
- 明确确认后,职责更新、在途审签失效和事件记录原子完成。
|
||||
- 保留旧冻结名单、审核记录和已批准历史,不把旧票带入新轮次。
|
||||
- 无变化保存保持幂等;并发修改返回明确冲突。
|
||||
- 移除仍承担当前职责的成员前,展示受影响文档并引导处理,防止留下无人可执行的职责。
|
||||
|
||||
总案要求的批量分配放在同一文档清单中:勾选文档、预览统一职责方案、确认提交。首版采用有界批次,任一文档校验失败则整批不写入,并列出原因。
|
||||
|
||||
## 五、单成员权限与多人矩阵
|
||||
|
||||
“项目权限”提供两个视图,共享同一服务端权限解释:
|
||||
|
||||
| 视图 | 默认行为 | 用途 |
|
||||
|---|---|---|
|
||||
| 按成员查看 | 普通成员查看自己;管理者可搜索其他成员 | 查看具体权限、配置来源和拒绝原因 |
|
||||
| 权限矩阵 | 管理者查看成员×项目动作 | 比较成员权限,发现缺失或差异 |
|
||||
|
||||
矩阵支持成员搜索、专业角色/项目身份过滤、分页及权限分组。点击单元格可展开解释,显示角色默认、管理员上限、项目覆盖及结果。
|
||||
|
||||
项目覆盖使用三态:沿用角色默认/项目内允许/项目内禁止。管理员上限禁止的动作不能通过项目覆盖授予;“恢复默认”需要实际撤销覆盖,不能用一个布尔值模拟。
|
||||
|
||||
权限目录必须明确动作所属范围:
|
||||
|
||||
| 内部标识 | 显示名称 | 所属范围 |
|
||||
|---|---|---|
|
||||
| `project.create` | 创建项目 | 系统角色权限,项目页面不出现 |
|
||||
| `member.manage` | 管理项目成员 | 项目 |
|
||||
| `duty.assign` | 分配文档职责 | 项目 |
|
||||
| `stage.advance` | 推进项目阶段 | 项目 |
|
||||
| `doc.read` | 读取文档 | 项目动作,具体文档仍须授权 |
|
||||
| `doc.write` | 编制与编辑文档 | 项目动作,仍受职责和状态限制 |
|
||||
| `knowledge.publish` | 发布项目知识 | 项目 |
|
||||
|
||||
这个范围划分同时约束矩阵读面和覆盖写面:**不能只是隐藏 `project.create`,服务端也必须拒绝在项目中配置它。**
|
||||
|
||||
权限名称、项目身份、来源、状态及拒绝原因统一使用人类可读文案。内部标识只保留在按需展开的技术详情中。
|
||||
|
||||
同时核对每项权限与真实操作门禁。例如当前项目归档还有创建者/域管理员条件,矩阵解释必须反映真实条件。矩阵中的“允许编制文档”也不能意味着能修改项目内所有文档。
|
||||
|
||||
普通成员自查权限的条件收敛为“当前有效项目成员”,避免文档读取权限被收回后,连自身权限与原因也无法查看。
|
||||
|
||||
## 六、技术划分与实施工作包
|
||||
|
||||
基座负责身份、基本资料、受管设置机制与通用契约;RDM 负责项目成员、专业角色、权限策略及文档职责;Frontend 负责业务交互;UI 仓提供通用选择器原语。
|
||||
|
||||
| 工作包 | 内容与主要范围 | 依赖 | 完成条件 |
|
||||
|---|---|---|---|
|
||||
| P1 契约与需求固定 | 设置作用域、项目动作目录、人员/文档候选 DTO、能力与版本语义;更新关联方案 | 无 | 本次五项要求都有稳定验收条件,四类身份/角色/职责概念明确 |
|
||||
| P2 系统设置闭环 | Core 设置描述、Backend 设置 API/存储/生效链/模型及密钥解析;系统管理入口 | P1;**基座发版与 RDM/Dev 升 pins**(见评审补充 1) | 系统受管项只能由有权管理员配置,旧个人/项目值不能覆盖 |
|
||||
| P3 人员与成员接口 | 扩展公开账号搜索;RDM 专业角色摘要、成员查询、项目身份调整与提交校验 | P1;姓名来源核实(见评审补充 3) | 账号/姓名/角色过滤同源,添加与身份调整明确分离 |
|
||||
| P4 文档与职责接口 | 专用文档目录、当前职责读取、统一职责服务、版本校验、变更失效及成员移除联动 | P1、P3 | 跨项目/非成员指派被拒,职责与审签变更全成或全败 |
|
||||
| P5 通用选择器 | UI 仓搜索选择、单/多选、键盘操作、分页与状态;Frontend 人员/文档适配 | P1,接线依赖 P3、P4 | 三类使用场景共享交互,无自由文本误提交 |
|
||||
| P6 权限解释与矩阵 | RDM 项目动作目录、单人/批量解释、覆盖三态、来源与拒绝原因 | P1、P3 | 矩阵与执行规则一致,系统动作无法写入项目覆盖 |
|
||||
| P7 项目设置集成 | 重构现有项目页,连接四个页面、能力状态、读取回填与保存结果 | P2—P6 | 创建者、普通成员、职责人员均有对应可用流程 |
|
||||
| P8 迁移与组合验收 | 旧配置处置、真实数据库与浏览器验收、精确组件组合验证、证据回填 | P2—P7 | 需求到证据闭合,无越权、隐私泄露或数据丢失 |
|
||||
|
||||
前端主要改动落在现有 `ProjectSettingsModal`、`adminRdmSections`、`rdmManagement`、`api` 和 `store`;按业务拆分成员、职责及权限组件,避免继续扩大一个管理组件文件。
|
||||
|
||||
目前 Dev 与 RDM 固定的 Backend 版本存在能力差异。实施时必须按公开契约推进相关版本,再完成组合验证,不能因为独立 RDM 仓已有某个接口就假定 Dev 组合可直接使用。
|
||||
|
||||
## 七、界面与异步状态要求
|
||||
|
||||
按根目录 `DESIGN.md` 实施,复用现有令牌、动效、设置外壳和折叠原语。
|
||||
|
||||
- 一种对象只有一个主要选择路径,搜索和浏览在同一选择器完成。
|
||||
- 姓名、文档名为主要信息,账号和 ID 为辅助信息。
|
||||
- 下拉支持键盘移动、确认、关闭;审核人多选使用清晰标签。
|
||||
- 加载、空结果、权限不足、接口未装配、查询失败分别呈现。
|
||||
- 切项目、切文档、改筛选时清除不适用的选中项和结果;迟到响应不能覆盖当前对象。
|
||||
- 异步状态只有一个所有者,按请求代次/事件顺序丢弃过期结果。
|
||||
- 保存后读取服务端结果;网络断开且结果未知时先核对状态,避免盲目重放。
|
||||
- 未保存改动提供轻量离开提示;需重启的设置明确显示待生效,不能统一宣称即时生效。
|
||||
- 窄屏按成员查看权限,矩阵可横向浏览,不压缩成不可读的小格子。
|
||||
|
||||
## 八、迁移、验证与交付安排
|
||||
|
||||
旧配置先做脱敏盘点,列出配置路径、来源和冲突状态。不能任取某个用户/项目的模型配置提升为全系统配置。先确定并验证系统配置,再启用受管策略;旧值保留受保护的恢复依据,退出生效链。
|
||||
|
||||
旧项目内 `project.create` 覆盖退出项目策略,保留历史依据。历史职责、审核与批准记录保留;无效的当前职责列入修复清单,不自动替换人员。
|
||||
|
||||
正式验收至少覆盖:
|
||||
|
||||
| 验收场景 | 预期结果 |
|
||||
|---|---|
|
||||
| 项目与个人设置写入系统模型项,包括手造请求 | 拒绝;旧覆盖也不影响运行结果 |
|
||||
| 账号、姓名、下拉、专业角色过滤查找成员 | 能找到并选择稳定账号;同名不会误选 |
|
||||
| 重复添加已有负责人、并发修改最后负责人 | 不发生隐式降级,不破坏负责人约束 |
|
||||
| 文档 ID、标题、列表、树查找 | 指向同一文档;章节及其他项目对象不能误提交 |
|
||||
| 搜索后人员被移出项目,再保存职责 | 服务端拒绝 |
|
||||
| 职责变更中途失败 | 职责、审签状态与事件完整回滚 |
|
||||
| 单成员详情与多人矩阵对照实际操作 | 结果与原因一致;具体资源限制清晰 |
|
||||
| 项目覆盖授予超上限动作或 `project.create` | 拒绝;恢复默认真正生效 |
|
||||
| 快速切项目/文档、断网、迟到响应 | 不显示旧对象数据,不误报成功 |
|
||||
| 同项目多成员使用、刷新及重启 | 共享配置一致,个人会话与原件仍私有 |
|
||||
|
||||
验证分为领域与契约测试、真实 SQLite/PostgreSQL 集成、真实身份浏览器流程,以及 Dev 精确组合的 `make test`、`make build`。浏览器需要覆盖非管理员项目负责人、普通成员、互异的编制/审核/批准人员及两个项目;不能用全管理员账号代替权限验收。
|
||||
|
||||
分两批形成可审查实现:先完成 P1—P4、P6 的服务端边界与契约,再完成 P5、P7 和 P8 的交互及组合验收。界面设计可在第一批同时评审。
|
||||
|
||||
## 评审补充(2026-10-13 技术评审并入,随方案一并批准)
|
||||
|
||||
1. **P2 显式依赖基座发版。** 受管设置机制是基座(Backend/Core)公开契约扩展,按总案交付顺序走“扩展申请评审→基座实现→基座发版→RDM/Dev 升 pins→组合验证”。P2 完成条件在原基础上追加:基座版本已发、pins 已升、Dev 组合 `make test` 通过。
|
||||
2. **项目共享配置的存储迁移规则。** 当前 project scope 物理存储在各 owner 名下;改为“以项目为权威”需要:新项目作用域存储、存量多 owner 副本的合并策略(默认规则:同键取最近写入时间,冲突清单列出不自动合并的键并交项目负责人裁定)、旧键退出生效链并保留只读恢复依据。P8 交付物含迁移清单与执行记录。
|
||||
3. **姓名来源与账号停用能力须先过 facts。** 基座账号目录当前明确“不含姓名/联系方式”。P3 的姓名搜索依赖基座账号模型是否存有姓名/显示名字段;P1 契约先定姓名来源(基座扩契约,或 RDM 专业角色档案补姓名)。账号停用机制现状同样按 `policy/facts.md` 登记验证,未证实前不把 `valid=true` 当作停用语义。
|
||||
|
||||
## 顺序裁定(2026-10-13)
|
||||
|
||||
本增量按自身 P1→P8 顺序推进;P2 的基座契约扩展按总案 369 行发版顺序执行,与总案 U1/U9 残余项的交织在扩展申请评审时统一排队,不因本增量跳过 U1(正式产物)与 U9(公开授权契约)的既有优先级。
|
||||
|
||||
## 评审核查记录(2026-10-13,源码 3fb8210 / RDM 255f9cb)
|
||||
|
||||
评审对方案“当前源码情况”逐项核查,全部属实:
|
||||
|
||||
| 声明 | 证据 |
|
||||
|---|---|
|
||||
| 项目设置按“用户+项目”保存 | Backend `settings.go` `Effective(owner, projectID)`,project scope 以 owner 为键 |
|
||||
| user/project 覆盖可改模型设置,无受管拦截 | 同上覆盖链,无“系统受管”概念 |
|
||||
| 成员手填账号 | `adminRdmSections.tsx` RdmMembersSection |
|
||||
| 账号目录仅 owner+有效态 | RDM `rdm.account.list` 描述“owner+有效态;不含姓名/联系方式” |
|
||||
| 职责手填 docId 与账号 | RdmDutiesSection placeholder |
|
||||
| 已有单成员权限解释表 | `rdm.perm.check`(动作/生效/来源/原因),前端默认自省 |
|
||||
| 权限标识与所属范围 | RDM `internal/perms/perms.go:21-31`,`project.create` 注释即“全局动作” |
|
||||
| 职责目标未校验成员 | `rdmReviewAssign` handler 注释“数据,非身份”——按 G1-5 旧裁定绕过成员校验;**本方案 P4 推翻该裁定,属规则变更,在 P1 契约中记录** |
|
||||
| 职责更新与审签失效分步 | 文档级 assign 先写职责再调 `InvalidateActiveDocSubmission`,两步顺序非原子;**章节级 assign 完全未接失效** |
|
||||
|
||||
## 主记录与推进
|
||||
|
||||
- 主记录:本文件(唯一正文);任务卡 `.task/feature-rdm-increment-settings-duties.md` 承载需求表、证据与阶段结论。
|
||||
- 来源:`.tmp/Discussion-Meetings/2026-10-08_12-24/.tmp/user-supplement.txt`(原始用户补充)、2026-10-13 会话评审。
|
||||
- 下一步:P1 已随本稿固定;按两批顺序进入 P2(基座受管设置契约扩展申请)与 P3/P4/P6 服务端实现。
|
||||
@@ -170,6 +170,10 @@ RDM 总案把库分期作为支撑与依赖,不覆盖库分期的原始范围
|
||||
后续维护:主案或任务变化时先更新其唯一主记录,再更新这里的导航和核验快照。
|
||||
更换 Docs/Dev 基线后重新核对 PR、版本与在途任务;新的索引状态不自动产生实施授权。
|
||||
|
||||
## 2026-10-13 规划补充
|
||||
|
||||
- [RDM 设置归属、成员、文档职责与权限矩阵完善增量方案 r1](2026-10-13-rdm-settings-members-duties-perms-increment.md):承接总案 U3/U4/U6(衔接 U5)的完整增量——设置作用域与受管项、可搜索人员选择器、文档清单+职责分配、单成员/多人权限矩阵与三态项目覆盖;含服务端一致性修复(职责目标成员校验推翻 G1-5 旧裁定、职责变更与审签失效原子化)与 P1–P8 工作包。**2026-10-13 用户评审通过并授权实施**(两批推进;正式验收与清理回收保留人工节点);P1 契约随本稿固定,P2 基座契约扩展按总案发版顺序排队。
|
||||
|
||||
## 2026-10-12 规划补充
|
||||
|
||||
- [svc 统一部署与一次性登录 Key 方案 r1](2026-10-12-svc-unified-deploy-and-login-key.md):将 `svc.sh` 增强为二进制/源码统一部署入口,并补齐无初始密码开户与账户恢复;一次性登录 Key 只能兑换设密受限会话。r1 含源码复核与四项取舍定案;复用恢复方案 KTD 与已合入的 recovery U1(Dev #415)。**2026-10-12 已批准**(五阶段+U1/U4 规格);授权推送/PR 与 U1/U4 实施启动;合入由 owner 执行。规格见 Dev `docs/svc-deploy/`。
|
||||
@@ -183,3 +187,5 @@ RDM 总案把库分期作为支撑与依赖,不覆盖库分期的原始范围
|
||||
- [RDM 模板与两树一网对话文档生成方案 r1.1](2026-10-11-rdm-template-dialog-generation.md):69 类旧资产、4 个当前注册模板的盘点及生成闭环设计;待评审,实施/迁移/模型试验/运行验收 NOT_RUN。与两树一网集成方案共用项目授权、原子事件与历史能力。 首批项目建议书/竞品分析、随后扩展全部文档已确认(2026-10-11),其余方案与实施仍待评审。
|
||||
|
||||
- [RDM 最终目标核对与完整交付方案 r1](2026-10-11-rdm-final-target-completion.md):本轮用户确认系统级唯一项目、管理员上限内覆盖、私域与三权读取边界;覆盖 34 UR/68 SR/10 F、全部69类模板及现有XLSX,当前源复核 RDM d8d7e743。总体方案待评审,实施/迁移/运行验收 NOT_RUN;模板方案为子方案。
|
||||
|
||||
- [工作台界面重设计 r0.2](2026-10-12-work-companion-ui-design.md)及[实施计划 r1](2026-10-12-work-companion-ui-plan.md):对话优先、渐进任务摘要、窄屏与单一状态投影;已获本次连续实施授权。
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# U7 容量测量窗口报告(SELF,2026-10-12)
|
||||
|
||||
来源标注:**SELF**(本机隔离栈执行;非 CI GATE、非独立 REPLAY)。不得单独据此放行第二实例写流量或双主机部署。
|
||||
|
||||
## 1. 环境与被测对象
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 主机 | Linux,32 逻辑 CPU,122 GiB RAM(约 98 GiB available),磁盘 1.9T/余 1.1T |
|
||||
| k6 | v2.3.0(Homebrew 固定位 `/home/linuxbrew/.linuxbrew/bin/k6`) |
|
||||
| 拓扑 | 双 `serve` 进程共享隔离 PG(`u7load`),`--tier team --auth on --mock --disable-exec-tools` |
|
||||
| Dev HEAD(任务分支测量时) | `b6f78b503ee2e3d6f71663d5330a18adbe743239`(ladder/s60 证据点;s2h 同工作区续跑) |
|
||||
| Backend gitlink | `5e8ada727c358438f8ff9f94eabb697e99fe28dc` |
|
||||
| Documents gitlink(测量时) | `8d0810bd35f4934e0ad37fb96d7bab6d7a732473` |
|
||||
| 入口 | Dev `tests/load/collaboration/run_load.sh --seed contract --instances 2` |
|
||||
|
||||
## 2. 数据集(B5 contract)
|
||||
|
||||
每段窗口独立灌库(编排脚本每次 `DROP/CREATE u7load_app`,无法跨次复用):
|
||||
|
||||
| profile | results 目录 | messages | knowledge | seed 耗时 |
|
||||
|---|---|---|---|---|
|
||||
| ladder | `tests/load/collaboration/results/20261012-064730/` | 1 000 000 | 100 000 | ≈12.0 s |
|
||||
| sustained60m | `…/20261012-070510/` | 1 000 000 | 100 000 | ≈14.5 s |
|
||||
| sustained2h | `…/20261012-081025/` | 1 000 000 | 100 000 | ≈11.2 s |
|
||||
|
||||
拓扑:10 seed 用户 × 5 项目 × 10 会话;约 10% knowledge `owner=''`(共享基座);**未**写入 `knowledge_vectors`。
|
||||
|
||||
## 3. 负载结果(阈值:读 P95≤300ms、P99≤1s、失败率≤0.1%;SSE P95≤1s;dup_seq=0)
|
||||
|
||||
| profile | 读 P95 | 读 P99 | fail_rate | checks | expected_contention | SSE A p95 | SSE B p95 | dup_seq | orphan runs |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| ladder(10→30→100,~12m) | 15.5 ms | 44.3 ms | 0 | 134922/0 | 549 | 17.5 ms | 33.0 ms | 0 | 0 |
|
||||
| sustained60m(~60m @30 VU) | 3.9 ms | 6.5 ms | 0 | 504399/0 | 69 | 5.7 ms | 4.4 ms | 0 | 0 |
|
||||
| sustained2h(~2h @30 VU) | 6.2 ms | 13.5 ms | 0 | 1008771/0 | 477 | 3.9 ms | 4.2 ms | 0 | 0 |
|
||||
|
||||
命令(每段):
|
||||
|
||||
```bash
|
||||
tests/load/collaboration/run_load.sh --seed contract --profile <ladder|sustained60m|sustained2h> --instances 2
|
||||
```
|
||||
|
||||
原始产物(gitignore,留在任务 worktree `results/<ts>/`):`k6-summary.json`、`sse-probe-a.json` / `-b.json`、`seed-manifest.json`、`invariants.txt`。任务卡经 `make evidence` 写入阈值复核脚本输出(SELF)。
|
||||
|
||||
## 4. 结论与边界
|
||||
|
||||
- **容量合同(B2/B3/B5/B4/C2)本机 SELF 全过**:阈值与不变量满足建议合同;数字绑定上表 SHA 与 results 目录。
|
||||
- **仍不放行第二实例写**:检查单要求 CI GATE 或独立 REPLAY 才用于放行;本报告仅为 SELF。C3 双主机、C4/C5 运维演练、B6 pgbench 未做。
|
||||
- **不承诺跨机/生产容量**:mock 模型、同机双进程、NVMe/本机 PG;换硬件或真实模型须重测。
|
||||
|
||||
## 5. 建议下一步
|
||||
|
||||
1. 独立审阅者 REPLAY 最小集(至少 `ladder --seed contract --instances 2`)后,方可讨论双进程写放行。
|
||||
2. 用户指定第二主机后跑 C3。
|
||||
3. 排期 C4/C5 运维演练;可选 B6 pgbench 只读基线。
|
||||
@@ -0,0 +1,100 @@
|
||||
# U7 运维演练与数据库基线报告(SELF,2026-10-12)
|
||||
|
||||
来源标注:**SELF**(本机隔离栈执行;非 CI GATE、非独立 REPLAY)。用户 2026-10-12 决定不做容量重放。不得据此放行第二实例写流量。
|
||||
|
||||
## 1. 被测对象
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| Backend gitlink | `8e509775d39d1455b69be44803037faa7af844b4` |
|
||||
| B6 Dev HEAD | `b2e129ab3f3bdf222f16040fcd0513872d0e2a3c` |
|
||||
| C4 Dev HEAD | `308f33665eb2dfaf9ae661e87df8898c3c2ecb3a` |
|
||||
| C5 Dev HEAD | `792574692609d9bfdf113e2dc5af6f43c9a176dd` |
|
||||
| 主机 | 32 逻辑 CPU,122 GiB RAM;演练开始时 load average 见各 `host.txt` |
|
||||
| 入口 | `tests/load/collaboration/run_pgbench.sh`;`tests/ops/run_fault_drill.sh`;`tests/ops/run_backup_drill.sh` |
|
||||
|
||||
原始输出在测量 worktree 的 `results/`(gitignore),不入库。任务卡 evidence 为 SELF。
|
||||
|
||||
## 2. B6 pgbench
|
||||
|
||||
结果目录 `tests/load/collaboration/results/pgbench-20261012-131948`。隔离实例 `u7bench`,scale 100,每档 60 秒,`-M prepared`。`max_connections=100`,`superuser_reserved_connections=3`,100 客户端封顶为 95。六档失败事务均为 0。
|
||||
|
||||
| 模式 | 客户端 | tps | P50 | P95 | P99 |
|
||||
|---|---|---|---|---|---|
|
||||
| select-only | 10 | 535646 | 0.018 ms | 0.024 ms | 0.030 ms |
|
||||
| TPC-B 类 | 10 | 18798 | 0.339 ms | 0.673 ms | 5.560 ms |
|
||||
| select-only | 30 | 952115 | 0.026 ms | 0.057 ms | 0.078 ms |
|
||||
| TPC-B 类 | 30 | 52224 | 0.493 ms | 1.002 ms | 1.777 ms |
|
||||
| select-only | 95 | 904708 | 0.087 ms | 0.180 ms | 0.417 ms |
|
||||
| TPC-B 类 | 95 | 50607 | 1.041 ms | 3.361 ms | 18.106 ms |
|
||||
|
||||
主机不空闲。这是数据库参考基线,没有业务阈值,也不替代容量窗口。
|
||||
|
||||
## 3. C4 断连
|
||||
|
||||
结果目录 `tests/ops/results/fault-20261012-142734`。PG 18991,应用 18990/18992,Redis 18993。
|
||||
|
||||
| 判据 | pg-stop | pg-kill |
|
||||
|---|---|---|
|
||||
| F1 有界失败、进程仍在 | 过 | 过 |
|
||||
| F2 不回落 SQLite,新进程拒绝就绪 | 过 | 过 |
|
||||
| F3 恢复后两侧各 5 次写入 | 过,RTO 不到 1 秒,未重启应用 | 同左 |
|
||||
| F4 失败 requestId 重放恰好一条 | 过 | 过 |
|
||||
| F5 dup_seq=0、seq 无洞、无非终态 run | 过 | 过 |
|
||||
|
||||
Redis 限额 20 次/分钟,两实例各突发 40 个读:
|
||||
|
||||
| 判据 | 结果 |
|
||||
|---|---|
|
||||
| G1 共享限额 | 放行 20、429 为 60、其他错误 0 |
|
||||
| G2 断连 | 放行 40、429 为 40、其他错误 0;已确认写入仍在 |
|
||||
| G3 只拉起 Redis | 放行回到 20;`rl:*` 均有过期时间 |
|
||||
| G4 | 发现:日志看不到降级计数 |
|
||||
| G5 | 发现:Redis 不通时新进程拒绝启动 |
|
||||
|
||||
`runtime.redisAddr` 没有调用者可写的产品入口。演练用 SQL 写入默认 owner `local` 的 `user` 设置,并保留 mock。
|
||||
|
||||
## 4. C5 备份与恢复
|
||||
|
||||
结果目录 `tests/ops/results/backup-20261012-153441`。源 PG 18994,恢复目标 18997。合同数据量 seed 约 12 秒。
|
||||
|
||||
| 判据 | 结果 |
|
||||
|---|---|
|
||||
| K1 备份有效 | 过。`failed_count=0`,`archived_count=80`,`pg_verifybackup` 与 `pg_restore --list` 退出码 0 |
|
||||
| K2 RPO≤5 分钟 | 过。64 秒 |
|
||||
| K3 RTO≤60 分钟 | 过。4 秒。恢复后登录、列项目、读会话均为 200 |
|
||||
| K4 工件与权限 | **FAIL**。五次上传都没有拿到工件编号 |
|
||||
| K5 不变量 | 过。dup_seq=0,seq 无洞;恢复后消息/事件/知识/run 计数与故障前一致(消息 1 000 120);非终态 run 为 0 |
|
||||
| K6 逻辑恢复 | 过。`pg_restore` 退出码 0,约 4 秒;计数等于 dump 时快照(消息 1 000 000,知识 100 000) |
|
||||
| K7 权限与泄密 | 过。备份目录 700、文件 600;结果文本里没有连接串。静态加密与凭据演练记 N/A。归档和数据在同一块盘,没有模拟存储全毁 |
|
||||
|
||||
恢复后的计数与故障前一致,说明已提交的标记都在。64 秒是最后一条成功标记的确认时间到故障时刻的间隔;窗口末尾有的写入因为会话仍被 mock run 占用而没有落库。
|
||||
|
||||
K4 的原因在源应用日志:未设置 `BLOBSTORE_S3_ENDPOINT` 时,`NewS3FromEnv` 返回空的 `*S3`。这个空指针被放进 `blobstore.Store` 接口后不再等于 nil,`finishOpen` 不会回落本地目录,上传在 `blobstore.(*S3).Put` 空指针 panic。产品代码未改。因此工件 sha256 和跨用户拒绝没有测成。代码里本地后端的 `content_path` 是绝对路径;这次没有成功上传,所以没有用恢复后的下载来核验。
|
||||
|
||||
同日另一次恢复(`backup-20261012-150713`)在数据目录复制之后起不来,因为 socket 路径超过 107 字节。正式这次把 socket 放到 `/tmp/u7bk-18997`。
|
||||
|
||||
## 5. 放行(2026-10-12 当时)
|
||||
|
||||
B6、C4 为 SELF 通过。C5 的库恢复为 SELF 通过,工件恢复失败。第二实例写流量仍不放行。
|
||||
|
||||
当时还没做、该任务不启动的三项:
|
||||
|
||||
- 独立 REPLAY,或把 C4/C5 的快速档接进 CI 成为 GATE(需要平台准入)。
|
||||
- C3 双主机。
|
||||
- 上传在未配置对象存储时 panic,需要单独的产品修复后才能重测 K4。
|
||||
|
||||
## 6. 2026-10-13 K4 重测
|
||||
|
||||
上传 panic 已在 store 边界修复:带类型的空对象存储(未设置 `BLOBSTORE_S3_ENDPOINT` 时的 `(*S3)(nil)`)视为未配置,回落本地工件目录。已构造的对象存储保持不变。Backend 提交 `46073d30`,Dev 被测头 `a83588dd`,backend gitlink 同为 `46073d30`。
|
||||
|
||||
重跑入口仍是 `tests/ops/run_backup_drill.sh`。结果目录 `tests/ops/results/backup-20261013-013354`(SELF)。原始结果另存于仓外 `/home/weichen/projects/u7-k4-retest-preserved-20261013`。
|
||||
|
||||
| 判据 | 结果 |
|
||||
|---|---|
|
||||
| K1–K3、K5–K7 | 过。RPO 65 秒,RTO 3 秒。`pg_verifybackup` 与 `pg_restore --list` 退出码 0,逻辑恢复约 5 秒,恢复后计数与故障前一致 |
|
||||
| K4 工件与权限 | **过**。5 个工件 `checked=5`、`missing=0`、`mismatch=0`。跨用户访问项目和工件均为 404 |
|
||||
|
||||
`content_path` 仍是绝对路径,快照继续还原到原目录。静态加密、凭据演练和整盘损坏仍是 N/A。
|
||||
|
||||
第二实例写流量仍不放行。剩下的门槛是独立 REPLAY 或经平台准入后的 C4/C5 CI 快速档,以及 C3 双主机。
|
||||
Reference in New Issue
Block a user