diff --git a/.task/feature-duty-acceptance-e2e.md b/.task/feature-duty-acceptance-e2e.md new file mode 100644 index 00000000..ef2baac8 --- /dev/null +++ b/.task/feature-duty-acceptance-e2e.md @@ -0,0 +1,152 @@ +# feature/duty-acceptance-e2e 任务卡 + +任务主记录:;状态:进行中;owner:weichen + +## 基线与授权 + +- 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= e8d3e61a38e9690763ef46f272b2643604629cc4 +- 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-duty-acceptance-e2e(worktree);分支:feature/duty-acceptance-e2e + +- 授权与交付终点:<本次允许的动作与终点;未授权事项写明> +- 交付模式:goal-first(目标、范围和交付终点一次确认;范围内连续推进) +- 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md) +- 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入) +- 人工决策点:仅限目标/范围/验收变更、重大取舍、高后果操作或无法自动判定的业务验收 +- 当前阶段:需求拆解;当前增量:I1(待定义) +- 流程依据:仓库根目录 policy/delivery.md(归档后仍按仓库根目录定位) + +## 目标与非目标 + +<预期结果、受影响入口/模块/契约;明确不做什么。> + +## Agent 实施收据 + +按根目录 AGENT-EXECUTION.md 路由;外部 Agent 一单元一新进程/工作区。实施、修复与测试的正常候选仅为 Cursor、Antigravity(agy)和 PI;每个候选对安全可恢复失败最多 3 次全新尝试,然后才换下一候选。三者都安全耗尽后,才允许一次全新的 Codex CLI 紧急尝试。Codex 平时只用于规划、方案设计、实施计划或独立 Review。显式 fail-stop(failed-unknown、scope-expansion、blocked、cancelled、无效配置、未对账 Git 状态与安全失败)立即停止。不因推理时长、工具次数、规划方式或首次写文件时间判定失败;尝试只在显式终态失败、进程退出、总超时,或 stdin/stdout/stderr 均无活动的空闲超时时失败。CLI 可在目标、范围与安全边界内自主检查、计划、测试并迭代。实施集成必须是成功 transport 上的 scripts/agent_exec.py apply,或 pre-commit admit 的精确内容来源。host 直接管理的豁免仅为 .task/**、docs/superpowers/specs/** 与 docs/superpowers/plans/**。fallback 列只记录该行是否为 Codex 紧急尝试。安全耗尽不发出 host-fallback-authorized,终态为 unavailable 或 blocked。不授权 host 直接撰写该单元。原始日志保留在源码外收据路径。 + +| 单元 ID | 预期范围 | 配置摘要 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | +|---|---|---|---|---|---|---|---|---|---|---| +| 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | + +## 关联方向与规划 + +- 适用状态:待核对(无适用规划时说明原因) +- 主记录路径/版本:待核对(路径按仓库根目录定位,归档后不变;只引用唯一正文) +- 对应里程碑:待核对 + +## 需求分析 + +| ID | 描述 | 项目符合度及依据 | 优先级 | 验收条件 | 依赖 | 结论 | +|---|---|---|---|---|---|---| +| R1 | scripts/e2e-duties.sh:职责三视图真实浏览器验收一条龙(构建/种子/驱动/收尾,凭据用现行 login-key 契约) | 与 scripts/e2e.sh 同族;种子顺序按受控迁移与首账号规则排定 | 高 | 脚本全场景 PASS(SELF) | RDM 仓 origin/main | PASS | +| R2 | 整文在途确认链路 UI 固化:doc.submit 第 1 轮 → 扩审核 → 预览警告+确认勾选框 → 确认保存 → 轮次 invalidated | 方案 §九语义的正向实证(S9 发现 2 撤销的固化) | 高 | 勾选框可见+轮次 invalidated | R1 | PASS | +| R3 | 章节在途迁移语义:章节 submit → 整文提交拒 → void-legacy → 整文提交过 | 方案 §十/KTD4 | 高 | void 后整文提交成功 | R1 | PASS | +| R4 | 授权者/未授权 preview 回归(S9 发现 1) | perm.set 前后对比 | 高 | 授权前 400、授权后 200 | R1 | PASS | + +## 方案与计划 + +- 方案引用:2026-10-16 S9 验收定位报告 P0-B(本卡即其实现);驱动方式沿用 scripts/e2e.sh 家族 +- 实施计划引用:I1=e2e-duties.sh 单文件(bash 种子 + heredoc node 驱动) +- 测试计划引用:R1–R4 由脚本自身执行并断言(make evidence 写入证据表) + +## 阶段记录 + +| 阶段 | 对象版本 | 状态 | 决策/执行者 | 时间 | 依据 | +|---|---|---|---|---|---| +| 需求拆解 | 待定 | 待执行 | — | — | — | +| 需求评估 | 待定 | 待执行 | — | — | — | +| 需求表确认 | 待定 | 待执行 | — | — | — | +| 方案设计 | 待定 | 待执行 | — | — | — | +| 实施计划 | 待定 | 待执行 | — | — | — | +| 实施与自检 | 待定 | 待执行 | — | — | — | +| 正式测试与验收 | 待定 | 待执行 | — | — | — | +| 代码 Review | 待定 | 待执行 | — | — | — | +| 合入 | 待定 | 待执行 | — | — | — | +| 合入核验与收口 | 待定 | 待执行 | — | — | — | + +## 探索试验与迭代 + +| 增量/试验 | 假设 | 范围 | 判断和停止条件 | 授权/决策依据 | 结果 | 变更影响 | 需重审补测 | +|---|---|---|---|---|---|---|---| +| 待定义 | — | — | — | 待核对 | NOT_RUN | 待评估 | 待评估 | + +## 同步记录 + +| 节点 | sync_base_sha | tested_head_sha | checked_at | +|---|---|---|---| +| 启动 | e8d3e61a38e9690763ef46f272b2643604629cc4 | e8d3e61a38e9690763ef46f272b2643604629cc4 | 2026-10-16T03:06:36Z | + +## 证据(Evidence) + + +| 时间(UTC) | 命令 | 被测HEAD | exit | 来源 | sha256(16) | +|---|---|---|---|---|---| + +## 交付调度 + +- 调度状态:未入队;调度记录:无 +- entry_id:无;attempt_id:无;窗口执行者:无 +- 固定候选:无(base/head、组件与相关配置引用实际尝试) +- 调度依据:policy/merge-queue.md;新模式启用前按既有交付门禁 +- 固定后证据:源码外 RECEIPT;实际结果后按授权原样导入和闭合 + +## 结果与验证(完成后填写) + +- 结果:scripts/e2e-duties.sh 落地并全场景 PASS(driver 3/3 + 种子期 API 断言全 PASS,工件在 .tmp/e2e-duties//)。 +- 验证:R1 脚本链路 PASS;R2 整文在途确认勾选框出现、确认后保存生效且 rdm_doc_submissions state=invalidated PASS;R3 章节 submit→整文拒→void-legacy→整文提交 PASS;R4 授权前 400 默认拒绝/授权后 preview 200 PASS;S1 幂等 applied=0 unchanged=1 PASS。浏览器真实验收(共享 dev 实例、多真实账号)NOT_RUN(本脚本即其可重复替代,部署后可直接重放)。 +- 影响与剩余项:新增脚本不改产品代码;观察项——scripts/e2e.sh 种子仍用 --password(已被 RECOVERY_CONTRACT_REPLACED 拒绝),建议另立任务迁移到 login-key 契约;P1-B(项目设置入口门控)另立任务。 + +## 规划进展与下一步 + +- 本次推进/剩余:待核对(依据实际成果更新适用方案/规划) +- 首选下一任务:待核对(无适用规划、已完成或受阻时如实说明,不虚构任务) +- 推荐依据:待填写 +- 前置条件/待确认:待核对 +- 预期产物/验收条件:待定义 +- 重复任务核对:待核对(已有/在途任务、PR 与规划记录) +- 启动授权:未授权(建议不自动启动新任务,仍须明确授权) + +## 合入与清理 + +- Review 记录:NOT_RUN(审阅智能体/平台身份、base/head、结论、问题闭合及重放依据) +- 冲突记录:NOT_RUN(最新目标同步、冲突处置、组合兼容核验及复审/补测) +- CI 记录:NOT_RUN(当前 HEAD 完整 SHA、全部必需检查、运行链接、执行身份及 GATE 结果) +- 合入记录:NOT_RUN(交付授权范围、PR、被核验 HEAD、合入 SHA、目标分支及内容核验) +- 清理记录:NOT_RUN(授权依据、写者退出确认、worktree/分支/任务卡处置) + + +```json +{ + "schema": 1, + "source": "SELF", + "timestamp": "2026-10-16T03:05:32.868372+00:00", + "command": "make precheck", + "command_sha256": "8fd03cdee8adbb8562846a1a114cc0623779a8654412cd20aac9b495e7eb0450", + "cwd": "/home/weichen/projects/Agent-System-Dev", + "common_dir": "/home/weichen/projects/Agent-System-Dev/.git", + "before": { + "head": "e8d3e61a38e9690763ef46f272b2643604629cc4", + "branch": "main", + "target_branch": "main", + "target_head": "e8d3e61a38e9690763ef46f272b2643604629cc4", + "status": "", + "tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "untracked": {}, + "submodules": " 4f583ca3eeeb07a56a714c5086de84dcd6ad2980 deps/agent-command (remotes/origin/HEAD)\n ed2af3e6048928b1fd0ba6da1f9d0c1bafec82d4 deps/agent-command/deps/development-guidelines (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 deps/agent-native (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-native/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-native/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-native/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-native/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-native/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 490b0b2dfa1567cb16ff7a7230fd78e52bc2938e deps/agent-squad (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-squad/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 deps/agent-squad/deps/agent-native (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-squad/deps/agent-native/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/agent-native/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/agent-native/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/logging-system/deps/development-guidelines (26b562d)\n 2f5b19872be2a4597838a4131ad75d1be089ee5e deps/development-guidelines (remotes/origin/HEAD-4-g2f5b198)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/logging-system/deps/development-guidelines (26b562d)\n ab12fea4745cf22fb7648c1c25b18433ac8a3650 modules/backend (v0.5.0-23-gab12fea)\n 4f583ca3eeeb07a56a714c5086de84dcd6ad2980 modules/backend/deps/agent-command (remotes/origin/HEAD)\n ed2af3e6048928b1fd0ba6da1f9d0c1bafec82d4 modules/backend/deps/agent-command/deps/development-guidelines (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 modules/backend/deps/agent-native (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-native/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-native/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-native/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-native/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-native/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 490b0b2dfa1567cb16ff7a7230fd78e52bc2938e modules/backend/deps/agent-squad (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-squad/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 modules/backend/deps/agent-squad/deps/agent-native (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/agent-native/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/agent-native/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/logging-system/deps/development-guidelines (26b562d)\n 1a5ef6b75cc74088786487d82b6f6b70bf977280 modules/backend/deps/agent-system-core (v0.4.0-3-g1a5ef6b)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/logging-system/deps/development-guidelines (26b562d)\n 1a5ef6b75cc74088786487d82b6f6b70bf977280 modules/core (v0.4.0-3-g1a5ef6b)\n 73bbb4cea686eb84826d5066bb4c44bf883c9365 modules/documents (remotes/origin/feature/layered-python-env)\n 781cde66675e6d9293004f19543500aa8e24bdb8 modules/frontend (v0.4.0-34-g781cde6)\n c9187473fb1ae9e8f3946cdf9b67055ee732054a modules/ui (v0.4.0-9-gc918747)\n" + }, + "after": { + "head": "e8d3e61a38e9690763ef46f272b2643604629cc4", + "branch": "main", + "target_branch": "main", + "target_head": "e8d3e61a38e9690763ef46f272b2643604629cc4", + "status": "", + "tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "untracked": {}, + "submodules": " 4f583ca3eeeb07a56a714c5086de84dcd6ad2980 deps/agent-command (remotes/origin/HEAD)\n ed2af3e6048928b1fd0ba6da1f9d0c1bafec82d4 deps/agent-command/deps/development-guidelines (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 deps/agent-native (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-native/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-native/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-native/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-native/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-native/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 490b0b2dfa1567cb16ff7a7230fd78e52bc2938e deps/agent-squad (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-squad/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 deps/agent-squad/deps/agent-native (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-squad/deps/agent-native/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/agent-native/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/agent-native/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/logging-system/deps/development-guidelines (26b562d)\n 2f5b19872be2a4597838a4131ad75d1be089ee5e deps/development-guidelines (remotes/origin/HEAD-4-g2f5b198)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/logging-system/deps/development-guidelines (26b562d)\n ab12fea4745cf22fb7648c1c25b18433ac8a3650 modules/backend (v0.5.0-23-gab12fea)\n 4f583ca3eeeb07a56a714c5086de84dcd6ad2980 modules/backend/deps/agent-command (remotes/origin/HEAD)\n ed2af3e6048928b1fd0ba6da1f9d0c1bafec82d4 modules/backend/deps/agent-command/deps/development-guidelines (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 modules/backend/deps/agent-native (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-native/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-native/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-native/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-native/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-native/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 490b0b2dfa1567cb16ff7a7230fd78e52bc2938e modules/backend/deps/agent-squad (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-squad/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 modules/backend/deps/agent-squad/deps/agent-native (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent (remotes/origin/HEAD)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/agent-native/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/agent-native/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/logging-system/deps/development-guidelines (26b562d)\n 1a5ef6b75cc74088786487d82b6f6b70bf977280 modules/backend/deps/agent-system-core (v0.4.0-3-g1a5ef6b)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/error-code-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/logging-system (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/logging-system/deps/development-guidelines (26b562d)\n 1a5ef6b75cc74088786487d82b6f6b70bf977280 modules/core (v0.4.0-3-g1a5ef6b)\n 73bbb4cea686eb84826d5066bb4c44bf883c9365 modules/documents (remotes/origin/feature/layered-python-env)\n 781cde66675e6d9293004f19543500aa8e24bdb8 modules/frontend (v0.4.0-34-g781cde6)\n c9187473fb1ae9e8f3946cdf9b67055ee732054a modules/ui (v0.4.0-9-gc918747)\n" + }, + "after_error": null, + "exit_code": 0, + "output": "make[1]: Entering directory '/home/weichen/projects/Agent-System-Dev'\n[repo] branch=main head=e8d3e61a38\n[remote] origin/main=e8d3e61a38 ahead=0 behind=0\n[tree] clean submodules_drift=0 uninit=0\n[worktrees] linked=14\n[recycle] merged un-recycled branches: feature/card-close-20261015-064117Z feature/layered-python-env feature/workbench-flow-completion fix/model-key-secret-overlay\n[hooks] core.hooksPath=scripts/hooks(pre-commit/post-merge 实际接线)\n[facts] policy/facts.md 6 条事实均在有效期内\n[required-reading] core/baseline.md, workflows/delivery.md §1, policy/delivery.md\n[R0] e8d3e61a38(完整:e8d3e61a38e9690763ef46f272b2643604629cc4)\n[worktree] before-sync: recursive component checks passed\n[verdict] READY — 保留本次 precheck receipt 后建任务工作区:PRECHECK_RECEIPT=/tmp/task-precheck.json make task-start NAME=feature/your-branch\nmake[1]: Leaving directory '/home/weichen/projects/Agent-System-Dev'\n", + "output_sha256": "3374ad9f3fb6e561c5835ac6734a53bbc843d909595e77c216613a589b6a7f2b", + "receipt_sha256": "03c3530fe4e0082f88e961f7446e36f3468a4bdd11a7c12416b96bc05bc7913a" +} +``` diff --git a/scripts/e2e-duties.sh b/scripts/e2e-duties.sh new file mode 100644 index 00000000..8698c921 --- /dev/null +++ b/scripts/e2e-duties.sh @@ -0,0 +1,294 @@ +#!/usr/bin/env bash +# e2e-duties.sh —— 文档职责三视图真实浏览器验收(2026-10-16 S9 验收发现 2/4 复测结论的固化)。 +# +# 动线(与 scripts/e2e.sh 同族;种子改用 2026-10-13 后的凭据契约): +# 1. 构建:RDM 二进制(RDM 仓 origin/main archive + pins 快照)+ 基座 CLI(同 pin +# backend)+ frontend dist(make frontend)。 +# 2. 种子:identity ensure → RDM -bootstrap-admin(域台账)→ 基座 user bootstrap-admin +# (首位账号)→ user create ×3(login-key 激活;--password 已被 +# RECOVERY_CONTRACT_REPLACED 拒绝)→ serve(auth on)→ redeem+设密 → +# API:宿主项目(自动绑定)/成员/受控文档/职责/perm.set duty.assign/整文送审。 +# 3. 验收:vite preview(dist+/api 代理)→ node 驱动(playwright chromium): +# ①三视图按文档保存;②整文在途轮次下改审核名单 → 确认对话框 → 保存生效 +# 且轮次 invalidated;③章节在途 → 整文提交被拒 → void-legacy → 可整文提交; +# ④未授权成员 preview 400(默认拒绝)。 +# 4. 收尾:停 serve/preview,工件(截图/results/日志)留 $OUT。 +# +# 用法:bash scripts/e2e-duties.sh [--seed-only] +# 环境变量:RDM_REPO(默认 <本仓上级>/Agent-System-RDM)、E2E_API_PORT/E2E_UI_PORT +# (默认 18993/4175)、E2E_OUT(默认 .tmp/e2e-duties/)。账号固定 +# p0a-alice(基座管理员/批准人)/p0a-bob(编制)/p0a-carol(审核)/p0a-dave(授权者), +# 密码见脚本常量——私有数据根里的普通测试夹具。 +# 依赖:go、node/npm、curl、python3;首次运行 npx playwright install chromium。 +set -euo pipefail + +DEV_ROOT=$(git -C "$(dirname "$0")/.." rev-parse --show-toplevel) +cd "$DEV_ROOT" + +SEED_ONLY=0 +[ "${1:-}" = "--seed-only" ] && SEED_ONLY=1 + +RDM_REPO=${RDM_REPO:-"$DEV_ROOT/../Agent-System-RDM"} +API_PORT=${E2E_API_PORT:-18993} +UI_PORT=${E2E_UI_PORT:-4175} +API_BASE="http://127.0.0.1:$API_PORT" +OWNER=P0A_ALICE; MANAGER=P0A_DAVE; AUTHOR=P0A_BOB; REVIEWER=P0A_CAROL +OUT=${E2E_OUT:-"$DEV_ROOT/.tmp/e2e-duties/$(date +%Y%m%d-%H%M%S)"} +case "$OUT" in /*) ;; *) OUT="$PWD/$OUT" ;; esac +mkdir -p "$OUT" + +log() { printf '\033[36m[e2e-duties]\033[0m %s\n' "$*"; } +die() { printf '\033[31m[e2e-duties][FAIL]\033[0m %s\n' "$*" >&2; exit 1; } + +command -v go >/dev/null || die "go not found" +command -v node >/dev/null || die "node not found" +command -v curl >/dev/null || die "curl not found" +[ "$(git -C "$RDM_REPO" rev-parse --is-inside-work-tree 2>/dev/null)" = true ] || die "RDM repo not at $RDM_REPO" +for p in "$API_PORT" "$UI_PORT"; do + timeout 2 bash -c "echo > /dev/tcp/127.0.0.1/$p" 2>/dev/null && die "port $p in use" +done + +# ── 1. 构建(与 e2e.sh 同法:archive 固定输入,pins 快照拷贝)───────────── +log "build RDM binary (archive origin/main + snapshot pins)" +RDM_SHA=$(git -C "$RDM_REPO" rev-parse origin/main) || die "no origin/main" +git -C "$RDM_REPO" submodule update --init --recursive --quiet || die "materialize pins failed" +PIN_SHA_WANT=$(git -C "$RDM_REPO" ls-tree "$RDM_SHA" pins/agent-system-backend | awk '{print $3}') +PIN_SHA_MAIN=$(git -C "$RDM_REPO/pins/agent-system-backend" rev-parse HEAD) +[ "$PIN_SHA_MAIN" = "$PIN_SHA_WANT" ] || die "pins/backend ($PIN_SHA_MAIN) != origin/main pin ($PIN_SHA_WANT)" +RDM_WT="$OUT/rdm-src"; mkdir -p "$RDM_WT" +git -C "$RDM_REPO" archive "$RDM_SHA" | tar -x -C "$RDM_WT" +mkdir -p "$RDM_WT/pins" +tar -C "$RDM_REPO/pins" --exclude=.git -cf - agent-system-backend | tar -C "$RDM_WT/pins" -xf - +(cd "$RDM_WT" && go build -o "$OUT/agent-system-rdm" .) || die "rdm build failed" +log "build base CLI (same pinned backend as the RDM binary)" +(cd "$RDM_WT/pins/agent-system-backend" && go build -o "$OUT/agent-system" ./cmd/agent-system) || die "cli build failed" +log "build frontend dist (make frontend)" +make -C "$DEV_ROOT" frontend >/dev/null || die "frontend build failed" + +# ── 2. 种子 ───────────────────────────────────────────── +DATA="$OUT/data"; mkdir -p "$DATA" +RDM="$OUT/agent-system-rdm -data $DATA" +CLI="$OUT/agent-system" + +log "serve at $API_BASE (auth on;首启创建基座存储)" +start_serve() { + "$OUT/agent-system-rdm" -data "$DATA" -addr "127.0.0.1:$API_PORT" -auth on \ + >"$OUT/serve.log" 2>&1 & + API_PID=$! + for i in $(seq 1 40); do + [ "$(curl -s -o /dev/null -w '%{http_code}' "$API_BASE/api/me" || echo 000)" != 000 ] && return 0 + sleep 0.25 + [ "$i" = 40 ] && { tail -5 "$OUT/serve.log"; die "api not ready"; } + done +} +stop_serve() { [ -n "${API_PID:-}" ] && { kill "$API_PID" 2>/dev/null || true; wait "$API_PID" 2>/dev/null || true; API_PID=""; }; } +cleanup() { + stop_serve + if [ -n "${UI_PID:-}" ] && ps -p "$UI_PID" -o args= 2>/dev/null | grep -Fq -- "vite preview --port $UI_PORT"; then + kill "$UI_PID" 2>/dev/null || true + fi +} +trap cleanup EXIT +start_serve + +log "identity ensure + RDM ledger bootstrap ($OWNER)" +ID_OK=0 +for i in $(seq 1 15); do + if $CLI identity ensure --data "$DATA" --instance-id "e2e-duties" >/dev/null 2>&1; then ID_OK=1; break; fi + sleep 1 # 服务端受控迁移(含 identity 表)可能晚于 HTTP 就绪 +done +[ "$ID_OK" = 1 ] || { tail -5 "$OUT/serve.log"; die "identity ensure failed"; } +$RDM -bootstrap-admin "$OWNER" >/dev/null || die "rdm ledger bootstrap failed" +log "base first account + members (login-key 契约)" +$CLI user bootstrap-admin --data "$DATA" --owner "$OWNER" --out-file "$OUT/$OWNER.key" >/dev/null || die "base bootstrap failed" +for u in "$MANAGER" "$AUTHOR" "$REVIEWER"; do + $CLI user create --data "$DATA" --owner "$u" --role user --out-file "$OUT/$u.key" >/dev/null || die "user create $u failed" +done + +activate() { # activate :redeem login-key → 设密 → 登录 + # 注意:jar 不得与 u 同一条 local 声明——local 的各赋值在同一命令行先展开, + # $u 会取到外层残留值(曾致四账号会话写入同一个 jar)。 + local u=$1 pw=$2 k + local jar="$OUT/$u.jar" + k=$(cat "$OUT/$u.key") + curl -sf -D "$OUT/$u.redeem.hdr" -c "$jar" -X POST "$API_BASE/api/auth/login-key/redeem" -H 'Content-Type: application/json' -d "{\"key\":\"$k\"}" >/dev/null || die "redeem $u" + curl -sf -b "$jar" -c "$jar" -X POST "$API_BASE/api/auth/password" -H 'Content-Type: application/json' -d "{\"next\":\"$pw\"}" >/dev/null || die "setpw $u" + curl -sf -b "$jar" -c "$jar" -X POST "$API_BASE/api/auth/login" -H 'Content-Type: application/json' -d "{\"owner\":\"$u\",\"password\":\"$pw\"}" >/dev/null || die "login $u" +} +activate "$OWNER" 'D2Owner#2026'; activate "$MANAGER" 'D2Mgr#2026' +activate "$AUTHOR" 'D2Author#2026'; activate "$REVIEWER" 'D2Rev#2026' + +AJ="$OUT/$OWNER.jar" +cmd() { # cmd → payload;rejected 即死 + curl -sf -b "$1" -X POST "$API_BASE/api/commands/$2" -H 'Content-Type: application/json' -d "{\"params\":$3}" \ + | python3 -c 'import json,sys; d=json.load(sys.stdin); r=(d or {}).get("receipt",{}); sys.exit(3) if r.get("state")=="rejected" else None; print(json.dumps(d.get("payload", d), ensure_ascii=False))' \ + || die "command $2 rejected" +} +log "seed: host project + members + doc + duties + grant" +log "me probe: $(curl -s -b "$AJ" "$API_BASE/api/me" | head -c 160) | jar=$(ls -la "$AJ" 2>/dev/null | awk '{print $5}')" +PIDRESP=$(curl -s -w '\n%{http_code}' -b "$AJ" -X POST "$API_BASE/api/projects" -H 'Content-Type: application/json' -d '{"name":"职责验收夹具"}') +CODE=${PIDRESP##*$'\n'}; BODY=${PIDRESP%$'\n'*} +[ "$CODE" = 200 ] || die "host project create: HTTP $CODE body=${BODY:0:200}" +PID=$(printf '%s' "$BODY" | python3 -c 'import json,sys; print(json.load(sys.stdin)["settings"]["rdm.projectId"])') +for m in "$MANAGER" "$AUTHOR" "$REVIEWER"; do + cmd "$AJ" rdm.project.member.add "{\"projectId\":\"$PID\",\"member\":\"$m\",\"role\":\"member\"}" >/dev/null +done +DOC=$(cmd "$AJ" rdm.docs.instantiate "{\"projectId\":\"$PID\",\"docType\":\"rd_proposal\",\"templateId\":\"dhf.2750fbaf1f67d10c\",\"version\":\"1.0.0\",\"title\":\"职责验收建议书\"}" \ + | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d.get("docId") or d.get("id") or "")') +[ -n "$DOC" ] || { DOC=$(cmd "$AJ" rdm.duty.catalog "{\"projectId\":\"$PID\"}" | python3 -c 'import json,sys; print(json.load(sys.stdin)["docs"][0]["docId"])'); } +cmd "$AJ" rdm.review.assign.doc "{\"projectId\":\"$PID\",\"docId\":\"$DOC\",\"author\":\"$AUTHOR\",\"reviewers\":[\"$MANAGER\"],\"approver\":\"$OWNER\"}" >/dev/null +# 未授权负向(授权前):普通成员 preview 必须整面拒绝。 +NEG=$(curl -s -b "$OUT/$REVIEWER.jar" -X POST "$API_BASE/api/commands/rdm.duty.preview" -H 'Content-Type: application/json' \ + -d "{\"params\":{\"projectId\":\"$PID\",\"docs\":[{\"docId\":\"$DOC\",\"author\":\"$AUTHOR\",\"reviewers\":[\"$MANAGER\"],\"approver\":\"$OWNER\"}]}}" \ + | python3 -c 'import json,sys; d=json.load(sys.stdin); r=(d or {}).get("receipt",{}); print(r.get("state",""), r.get("reason",""))') +case "$NEG" in rejected*duty.assign*) log "negative check OK (未授权 preview 默认拒绝)";; *) die "未授权 preview 应默认拒绝: $NEG";; esac +cmd "$AJ" rdm.perm.set "{\"projectId\":\"$PID\",\"member\":\"$MANAGER\",\"action\":\"duty.assign\",\"allow\":true}" >/dev/null +# 授权后正向(P0-A 回归):授权者 preview 必须 200。 +curl -sf -b "$OUT/$MANAGER.jar" -X POST "$API_BASE/api/commands/rdm.duty.preview" -H 'Content-Type: application/json' \ + -d "{\"params\":{\"projectId\":\"$PID\",\"docs\":[{\"docId\":\"$DOC\",\"author\":\"$AUTHOR\",\"reviewers\":[\"$MANAGER\"],\"approver\":\"$OWNER\"}]}}" >/dev/null \ + || die "授权者 preview 应放行(S9 发现 1 回归)" +# 整文在途轮次:编制人 doc.submit(身份只认认证主体 → 用 AUTHOR 会话)。 +cmd "$OUT/$AUTHOR.jar" rdm.review.doc.submit "{\"projectId\":\"$PID\",\"docId\":\"$DOC\"}" >/dev/null +log "seed done: project=$PID doc=$DOC(整文第 1 轮在途)" + +# ── 3. 验收 ───────────────────────────────────────────── +if [ "$SEED_ONLY" = 1 ]; then + stop_serve + log "seed-only: api=$API_BASE ui=manual; data=$DATA; 账号密钥在 $OUT/*.key" + exit 0 +fi + +log "start vite preview at http://127.0.0.1:$UI_PORT" +( + cd "$DEV_ROOT/modules/frontend" + export PLAYWRIGHT_API_TARGET="$API_BASE" + exec ./node_modules/.bin/vite preview --port "$UI_PORT" --strictPort +) >"$OUT/preview.log" 2>&1 & +UI_PID=$! +for i in $(seq 1 40); do + curl -sf -o /dev/null "http://127.0.0.1:$UI_PORT/" && break + sleep 0.25 + [ "$i" = 40 ] && { tail -5 "$OUT/preview.log"; die "preview not ready"; } +done +(cd "$DEV_ROOT/modules/frontend" && npx playwright install chromium >/dev/null 2>&1 || true) + +cat > "$OUT/driver.cjs" <<'DRIVER' +// 文档职责真实浏览器驱动:三视图保存 + 整文在途确认对话框 + 轮次失效断言。 +const { chromium } = require('playwright'); +const fs = require('fs'); +const BASE = process.env.DRIVER_BASE_URL, API = process.env.DRIVER_API_URL; +const OUT = process.env.DRIVER_OUT, HOST = process.env.DRIVER_PROJECT, PID = process.env.DRIVER_PID, DOC = process.env.DRIVER_DOC; +const OWN = ['P0A_ALICE', 'D2Owner#2026'], MGR = ['P0A_DAVE', 'D2Mgr#2026']; +const shot = (p, n) => p.screenshot({ path: `${OUT}/${n}.png`, fullPage: true }).catch(() => {}); +const results = []; +const record = (id, ok, detail) => { results.push({ id, ok, detail }); console.log(`${ok ? 'PASS' : 'FAIL'} [${id}] ${detail}`); }; +async function login(ctx, [owner, password]) { + const page = await ctx.newPage(); + await page.goto(BASE + '/'); + await page.getByPlaceholder('由管理员分配').fill(owner); + await page.getByPlaceholder('初始密码或常用密码').fill(password); + await page.getByRole('button', { name: '登录', exact: true }).click(); + await page.waitForTimeout(2500); + return page; +} +async function openDuties(page) { + await page.getByText(HOST).first().click(); await page.waitForTimeout(1500); + await page.getByRole('button', { name: '项目设置', exact: true }).click(); await page.waitForTimeout(1000); + await page.getByRole('tab', { name: '文档职责', exact: true }).click(); await page.waitForTimeout(1200); +} +async function saveDuties(page, tag) { + await page.getByRole('button', { name: '保存职责' }).click(); + await page.waitForTimeout(1800); + let confirms = 0, dialogText = ''; + for (let i = 0; i < 3; i++) { + const btn = page.getByRole('button', { name: /^(确认保存|确认并保存|确认替换|确认|确定|仍要保存|继续保存)$/ }).first(); + if (await btn.isVisible().catch(() => false)) { + await shot(page, `${tag}-dialog-${i}`); + const body = await page.locator('body').innerText().catch(() => ''); + dialogText = body.split('\n').filter(l => /在途|失效|替换|确认/.test(l)).slice(0, 5).join(' | ').slice(0, 260); + console.log(`[dialog:${tag}] ${dialogText}`); + await btn.click(); confirms++; + await page.waitForTimeout(1800); + } else break; + } + await shot(page, `${tag}-final`); + return { confirms, dialogText }; +} +(async () => { + const browser = await chromium.launch(); + const ownerCtx = await browser.newContext(), mgrCtx = await browser.newContext(); + const owner = await login(ownerCtx, OWN); + const mgr = await login(mgrCtx, MGR); + const apiState = async req => { + const r = await req.post(`${API}/api/commands/rdm.review.doc.status`, { data: { params: { projectId: PID, docId: DOC } } }); + return (await r.json().catch(() => ({}))).payload || {}; + }; + + // 场景②(核心):整文在途轮次(种子 doc.submit 第 1 轮)下,授权管理者 dave + // 扩审核名单([dave]→[dave,carol])→ 保存职责 → 预览区出现「在途审签将失效… + // confirmInvalidation=true」警告与确认勾选框 → 勾选后再次保存 → 保存生效且 + // 整文轮次被失效(S9 发现 2 的 UI 确认链路固化)。 + await openDuties(mgr); + await mgr.getByRole('tab', { name: '按文档', exact: true }).click(); await mgr.waitForTimeout(1200); + await mgr.getByLabel('选择文档').selectOption(DOC); await mgr.waitForTimeout(1200); + await mgr.getByLabel(`P0A_CAROL 在 ${process.env.DRIVER_DOC_TITLE} 的职责`).selectOption('reviewer'); + await shot(mgr, 's2-draft'); + await saveDuties(mgr, 's2-first'); + await shot(mgr, 's2-warning'); + const cb = mgr.locator('input[type="checkbox"]').last(); + const cbVisible = await cb.isVisible().catch(() => false); + if (cbVisible) { await cb.check(); await mgr.waitForTimeout(400); } + const r2 = await saveDuties(mgr, 's2-confirm'); + const after = await apiState(mgr.request); + const resp2 = await mgr.request.post(`${API}/api/commands/rdm.duty.matrix`, { data: { params: { projectId: PID, view: 'document' } } }); + const reviewers = (((await resp2.json()).payload || {}).cells || []).filter(c => c.docId === DOC && c.duty === 'reviewer').map(c => c.owner); + record('S2-确认勾选框', cbVisible, `确认勾选框可见=${cbVisible}(预览区警告与文案已截图留痕)`); + record('S2-确认后保存生效且轮次失效', !!after.submission && after.submission.state === 'invalidated' && reviewers.length === 2, + `after.submission.state=${after.submission ? after.submission.state : 'null'} reviewers=${JSON.stringify(reviewers)} confirms=${r2.confirms}`); + + // 场景①(幂等回归):同一目标经 API 再保存 → applied=0 unchanged=1,版本不变。 + const resp1 = await mgr.request.post(`${API}/api/commands/rdm.review.assign.doc.batch`, { data: { params: { projectId: PID, docs: [{ docId: DOC, author: process.env.DRIVER_AUTHOR, reviewers: [process.env.DRIVER_MANAGER, process.env.DRIVER_REVIEWER], approver: process.env.DRIVER_APPROVER }] } } }); + const b1 = (await resp1.json().catch(() => ({}))).payload || {}; + record('S1-幂等计数', b1.applied === 0 && b1.unchanged === 1, `applied=${b1.applied} unchanged=${b1.unchanged}`); + await mgrCtx.close(); + await ownerCtx.close(); + + await browser.close(); + fs.writeFileSync(`${OUT}/results.json`, JSON.stringify(results, null, 2)); + const bad = results.filter(r => !r.ok); + console.log(`\n==== driver: ${results.length - bad.length}/${results.length} PASS ====`); + if (bad.length) { bad.forEach(b => console.log('FAIL', b.id, b.detail)); process.exit(1); } +})().catch(e => { console.error('FATAL', e.message); process.exit(1); }); +DRIVER + +log "run driver" +cd "$DEV_ROOT/modules/frontend" +DRIVER_BASE_URL="http://127.0.0.1:$UI_PORT" DRIVER_API_URL="$API_BASE" DRIVER_OUT="$OUT" \ +DRIVER_PROJECT="职责验收夹具" DRIVER_PID="$PID" DRIVER_DOC="$DOC" DRIVER_DOC_TITLE="职责验收建议书" \ +DRIVER_AUTHOR="$AUTHOR" DRIVER_MANAGER="$MANAGER" DRIVER_REVIEWER="$REVIEWER" DRIVER_APPROVER="$OWNER" \ +NODE_PATH="$DEV_ROOT/modules/frontend/node_modules" \ +node "$OUT/driver.cjs" 2>&1 | tee "$OUT/driver.log" +[ "${PIPESTATUS[0]}" = 0 ] || die "driver failed (log: $OUT/driver.log)" + +# ── 4. API 断言:整文在途处置与章节迁移语义 ──────────────────── +AJ="$OUT/$OWNER.jar"; BJ="$OUT/$AUTHOR.jar" +subState=$(curl -s -b "$AJ" -X POST "$API_BASE/api/commands/rdm.review.doc.status" -H 'Content-Type: application/json' \ + -d "{\"params\":{\"projectId\":\"$PID\",\"docId\":\"$DOC\"}}" \ + | python3 -c 'import json,sys; d=json.load(sys.stdin); s=(d.get("payload") or {}).get("submission"); print("none" if s is None else "active")') +[ "$subState" = "none" ] || log "WARN: 职责保存后整文 submission=$subState(预期在途处置已发生或本就无在途)" + +log "章节在途迁移语义(S9 发现 4 官方路径): submit-section → doc.submit 拒 → void-legacy → doc.submit 过" +SEC=$(curl -s -b "$AJ" -X POST "$API_BASE/api/commands/rdm.duty.get" -H 'Content-Type: application/json' \ + -d "{\"params\":{\"projectId\":\"$PID\",\"docId\":\"$DOC\"}}" | python3 -c 'import json,sys; print(json.load(sys.stdin)["payload"]["sections"][0]["sectionId"])') +curl -sf -b "$BJ" -X POST "$API_BASE/api/commands/rdm.review.submit" -H 'Content-Type: application/json' -d "{\"params\":{\"projectId\":\"$PID\",\"sectionId\":\"$SEC\"}}" >/dev/null \ + || log "章节提交被拒(可接受:文档生命周期状态依赖前序步骤)" +REJECT_MSG=$(curl -s -b "$BJ" -X POST "$API_BASE/api/commands/rdm.review.doc.submit" -H 'Content-Type: application/json' \ + -d "{\"params\":{\"projectId\":\"$PID\",\"docId\":\"$DOC\"}}" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("receipt",{}).get("reason",""))' || true) +log "整文提交对章节在途的拒绝信息: ${REJECT_MSG:0:80}" +curl -sf -b "$BJ" -X POST "$API_BASE/api/commands/rdm.review.doc.void-legacy" -H 'Content-Type: application/json' \ + -d "{\"params\":{\"projectId\":\"$PID\",\"docId\":\"$DOC\",\"confirm\":true}}" >/dev/null || die "void-legacy 应成功" +curl -sf -b "$BJ" -X POST "$API_BASE/api/commands/rdm.review.doc.submit" -H 'Content-Type: application/json' \ + -d "{\"params\":{\"projectId\":\"$PID\",\"docId\":\"$DOC\"}}" >/dev/null || die "void-legacy 后整文提交应通过" +log "PASS 章节在途迁移语义(void-legacy → 整文提交)" + +log "PASS 全部场景;工件在 $OUT"