Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0650e81133 | ||
|
|
9aa18eb30b | ||
|
|
a648579519 | ||
|
|
226bf8d38c | ||
|
|
27cd65e450 | ||
|
|
b497f75e03 | ||
|
|
3b78ccb6b0 | ||
|
|
8e3f9edb24 | ||
|
|
56ca0ee7c7 | ||
|
|
c45fbf9569 | ||
|
|
29d97aec39 | ||
|
|
06d0afb76c |
@@ -0,0 +1,168 @@
|
||||
# feature/recall-misexec-fixes 任务卡
|
||||
|
||||
任务主记录:PR #717 https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/717;状态:已完成(合入前闭合);owner:weichen
|
||||
|
||||
## 基线与授权
|
||||
|
||||
- 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= bccb88f294038ce52a37fc5592a6daebd10e88b4
|
||||
- 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-recall-misexec-fixes(worktree);分支:feature/recall-misexec-fixes
|
||||
- 分支类型:standalone;root_target:main;immediate_target:main;accepting_requirements:false
|
||||
- 需求分流:verdict=NEW;selected_initiative=无;requirement_sha256=5510782fe6debd449a832c3353d191c6efb76f50c77932c5adf387a2f0a27bcd;triage_receipt=/tmp/triage-misexec-1792727028.json;receipt_sha256=914545afa88ab6ce4cbe9bd48240e8a8b2f829c970d245c24fb1a7c0d8ca495c
|
||||
|
||||
- 授权与交付终点:用户已批准启动 A3 基线驱动的规则层修复(评测集暴露的 6 次误执行:语义否定被当作肯定 ×5、多意图平分误选寒暄 ×1;另有错误槽位未澄清 3 例)。范围内连续推进至合入;检索/调模型决策留待修复后基线。未授权:A4、部署。
|
||||
- 设计决定(2026-10-22,host):
|
||||
1. 否定修复放 compiledSpec.evaluate 匹配层:正命中若被前置否定词(不要/别/不用/先不要/先别/无需/不需要,紧邻或间隔≤2字)限定,且该 spec 的全部正命中均被否定 → reject "negated_match"(确定性,不逐 spec 配置)。
|
||||
2. 平分裁决加确定性 tie-break:优先级相同 → 已抽取到槽位值多者优先(带槽位信号的动作胜过裸寒暄)→ id 字典序。不引入新配置。
|
||||
3. 槽位抽取修正:抽取跨度内含多值分隔(和/还是/、/,)→ 视为多候选无效(clarify);规范化后仅剩符号/空 → 无效;字符集违规(如声明字母数字却抽出 abc_def 的部分截取)→ 无效。无效一律走 clarify,不 start。
|
||||
4. 验收即评测集:上述用例从 record_only FAIL 翻为 PASS;overall mis_exec 须为 0;gen_agree 与其余类别不回退。
|
||||
- 交付模式:goal-first(目标、范围和交付终点一次确认;范围内连续推进)
|
||||
- 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md)
|
||||
- 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入)
|
||||
- 人工决策点:仅限目标/范围/验收变更、重大取舍、高后果操作或无法自动判定的业务验收
|
||||
- 当前阶段:需求拆解;当前增量:I1(待定义)
|
||||
- 流程依据:仓库根目录 policy/delivery.md(归档后仍按仓库根目录定位)
|
||||
|
||||
## 目标与非目标
|
||||
|
||||
**目标**:消除评测集 6 次误执行 + 3 例错误槽位未澄清:匹配层否定感知、裁决 specificity tie-break、槽位多值/字符集无效化;评测指标 mis_exec 归零且其余类别不回退;既有测试全绿。
|
||||
|
||||
**非目标**:检索/召回增强;模型/提示词调整;「刚才那个」跨会话指代解析(A1 会话域);真实语料;gen_agree 的 3 例生成器分歧(回放器行为,另行处理)。
|
||||
|
||||
## Agent 实施收据
|
||||
|
||||
路由与 fail-stop 规则见根目录 AGENT-EXECUTION.md 与 policy/delivery.md;每次尝试一行,原始日志留在源码外收据路径。
|
||||
|
||||
| 单元 ID | 预期范围 | 配置摘要 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 |
|
||||
|---|---|---|---|---|---|---|---|---|---|---|
|
||||
| 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — |
|
||||
|
||||
## 关联方向与规划
|
||||
|
||||
- 适用状态:待核对(无适用规划时说明原因)
|
||||
- 主记录路径/版本:待核对(路径按仓库根目录定位,归档后不变;只引用唯一正文)
|
||||
- 对应里程碑:待核对
|
||||
|
||||
## 需求分析
|
||||
|
||||
| ID | 描述 | 项目符合度及依据 | 优先级 | 验收条件 | 依赖 | 结论 |
|
||||
|---|---|---|---|---|---|---|
|
||||
| R1 | 待填写 | 待评估 | 待定 | 待定义 | 待确认 | 待评审 |
|
||||
|
||||
## 方案与计划
|
||||
|
||||
- 方案引用:待填写(含对象版本)
|
||||
- 实施计划引用:待填写(含增量与需求 ID)
|
||||
- 测试计划引用:待填写(含需求 ID 与验收条件)
|
||||
|
||||
## 阶段记录
|
||||
|
||||
| 阶段 | 对象版本 | 状态 | 决策/执行者 | 时间 | 依据 |
|
||||
|---|---|---|---|---|---|
|
||||
| 需求拆解 | 待定 | 待执行 | — | — | — |
|
||||
| 需求评估 | 待定 | 待执行 | — | — | — |
|
||||
| 需求表确认 | 待定 | 待执行 | — | — | — |
|
||||
| 方案设计 | 待定 | 待执行 | — | — | — |
|
||||
| 实施计划 | 待定 | 待执行 | — | — | — |
|
||||
| 实施与自检 | 待定 | 待执行 | — | — | — |
|
||||
| 正式测试与验收 | 待定 | 待执行 | — | — | — |
|
||||
| 代码 Review | 待定 | 待执行 | — | — | — |
|
||||
| 合入 | 待定 | 待执行 | — | — | — |
|
||||
| 合入核验与收口 | 待定 | 待执行 | — | — | — |
|
||||
|
||||
## 探索试验与迭代
|
||||
|
||||
| 增量/试验 | 假设 | 范围 | 判断和停止条件 | 授权/决策依据 | 结果 | 变更影响 | 需重审补测 |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 待定义 | — | — | — | 待核对 | NOT_RUN | 待评估 | 待评估 |
|
||||
|
||||
## 同步记录
|
||||
|
||||
| 节点 | sync_base_sha | tested_head_sha | checked_at |
|
||||
|---|---|---|---|
|
||||
| 启动 | bccb88f294038ce52a37fc5592a6daebd10e88b4 | bccb88f294038ce52a37fc5592a6daebd10e88b4 | 2026-10-23T03:45:01Z |
|
||||
|
||||
## 证据(Evidence)
|
||||
|
||||
<!-- CMD="<命令>" make evidence 写入;手抄/转写输出视为无效证据(AGENTS.md 证据与验证门禁)。 -->
|
||||
| 时间(UTC) | 命令 | 被测HEAD | exit | 来源 | sha256(16) |
|
||||
|---|---|---|---|---|---|
|
||||
|
||||
## 交付调度
|
||||
|
||||
- 调度状态:未入队;调度记录:无
|
||||
- entry_id:无;attempt_id:无;窗口执行者:无
|
||||
- 固定候选:无(base/head、组件与相关配置引用实际尝试)
|
||||
- 调度依据:policy/delivery.md#合入调度
|
||||
- 固定后证据:源码外 RECEIPT;实际结果后按授权原样导入和闭合
|
||||
|
||||
## 结果与验证
|
||||
|
||||
- 结果:
|
||||
- 验证:<结论摘要 PASS/FAIL/SKIP/NOT_RUN 逐项;逐条证据由 make evidence 写入上方证据表>
|
||||
- 影响与剩余项:
|
||||
|
||||
## 规划进展与下一步
|
||||
|
||||
- 本次推进/剩余:待核对(依据实际成果更新适用方案/规划)
|
||||
- 首选下一任务:待核对(无适用规划、已完成或受阻时如实说明,不虚构任务)
|
||||
- 推荐依据:待填写
|
||||
- 前置条件/待确认:待核对
|
||||
- 预期产物/验收条件:待定义
|
||||
- 重复任务核对:待核对(已有/在途任务、PR 与规划记录)
|
||||
- 启动授权:未授权(建议不自动启动新任务,仍须明确授权)
|
||||
|
||||
## 合入与清理
|
||||
|
||||
- 实施收据:misexec-rules-fix(cursor attempt1,否定感知匹配+specificity tie-break+槽位 fail-closed,intent 7f3ff6a,eval mis_exec=0/37 全过,verify-misexec2 exit=0);pin 级联嵌套提升(host 提交 N4/S4/B4')与 Dev 集成(misexec-git3-run.json)。
|
||||
- 组合验证:全量 make test PASS(verify-misexec-combo2.json exit=0)。
|
||||
- Review 记录:独立 CLI 评审单元 misexec-independent-review(收据 /tmp/agent-stack-b2/reviewm-run.json);结论 APPROVE;报告 .task/reviews/2026-10-22-misexec-fixes-independent-review.md;被审对象 8e3f9edb 组合 vs main
|
||||
- 冲突记录:NOT_RUN(最新目标同步、冲突处置、组合兼容核验及复审/补测)
|
||||
- CI 记录:NOT_RUN(当前 HEAD 完整 SHA、全部必需检查、运行链接、执行身份及 GATE 结果)
|
||||
- 合入记录:NOT_RUN(交付授权范围、PR、被核验 HEAD、合入 SHA、目标分支及内容核验)
|
||||
- 清理记录:NOT_RUN(授权依据、写者退出确认、worktree/分支/任务卡处置)
|
||||
|
||||
<!-- Local receipt: SELF. Digests detect corruption; they do not authenticate a reviewer or CI. -->
|
||||
```json
|
||||
{
|
||||
"summary_schema": 1,
|
||||
"source": "SELF",
|
||||
"timestamp": "2026-10-23T03:44:02.622816+00:00",
|
||||
"command": "make precheck",
|
||||
"exit_code": 0,
|
||||
"cwd": "/home/weichen/projects/Agent-System-Dev",
|
||||
"before_head": "bccb88f294038ce52a37fc5592a6daebd10e88b4",
|
||||
"after_head": "bccb88f294038ce52a37fc5592a6daebd10e88b4",
|
||||
"branch": "main",
|
||||
"target_branch": "main",
|
||||
"target_head": "bccb88f294038ce52a37fc5592a6daebd10e88b4",
|
||||
"root_target": "main",
|
||||
"immediate_target": "main",
|
||||
"before_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"after_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"output_tail": [
|
||||
"make[1]: Entering directory '/home/weichen/projects/Agent-System-Dev'",
|
||||
"[repo] branch=main head=bccb88f294",
|
||||
"[remote] origin/main=bccb88f294 ahead=0 behind=0",
|
||||
"[tree] clean submodules_drift=0 uninit=0",
|
||||
"[worktrees] linked=7",
|
||||
"[recycle] merged un-recycled branches: feature/exec-recovery-diagnostics-a2 fix/gitea-endpoint-facts",
|
||||
"[initiatives] local cards (not authoritative): none",
|
||||
"[hooks] core.hooksPath=scripts/hooks(pre-commit/post-merge 实际接线)",
|
||||
"[facts] policy/facts.md 6 条事实均在有效期内",
|
||||
"[required-reading] core/baseline.md, workflows/delivery.md §1, policy/delivery.md",
|
||||
"[R0] bccb88f294(完整:bccb88f294038ce52a37fc5592a6daebd10e88b4)",
|
||||
"[worktree] before-sync: recursive component checks passed",
|
||||
"[verdict] READY — 保留本次 precheck receipt 后建任务工作区:PRECHECK_RECEIPT=/tmp/task-precheck.json make task-start NAME=feature/your-branch",
|
||||
"make[1]: Leaving directory '/home/weichen/projects/Agent-System-Dev'"
|
||||
],
|
||||
"output_sha256": "6a6f70969d0b85288dde21bf2011b0485af1251a29fbb677ba7d7d9e94c79785",
|
||||
"receipt_sha256": "b5fc6e81a92e8ecb97bbf51630a10608507425dfe27220efb75341b4f607bffd",
|
||||
"receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/b5fc6e81a92e8ecb97bbf51630a10608507425dfe27220efb75341b4f607bffd.json"
|
||||
}
|
||||
```
|
||||
|
||||
## 闭合记录(合入前折叠)
|
||||
|
||||
- 本卡在 PR #717(https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/717)合入前闭合并归档,随该 PR 一同合入。
|
||||
- 该 PR 的合并提交即本任务的落地记录。
|
||||
- 合入后无需回填,也无需单独的闭合 PR。
|
||||
@@ -0,0 +1,47 @@
|
||||
# 独立代码 Review:feature/recall-misexec-fixes(mis-exec 规则层修复)
|
||||
|
||||
- 日期:2026-10-22(评审执行于 2026-10-23 UTC 的分支对象上)
|
||||
- 评审人:独立 CLI 会话(未参与实施;本文件为本次唯一变更)
|
||||
- 评审对象:`git diff bccb88f2...HEAD`(= origin/main...HEAD;本 worktree 无 origin remote,bccb88f2 为 main 顶端合并提交,是 feature 分支的 merge-base)
|
||||
- 组件范围:deps/agent-intent @6aa4925..7f3ff6a(单提交 "Make intent matching negation-aware and slots fail closed")+ gitlink 级联(native d1f72aa→be556f4、squad a5afe9c8→95b387d、backend 8dc91c17→8031855e→bd5c0f3)+ 任务卡 `.task/feature-recall-misexec-fixes.md`
|
||||
- 方法:全文精读 9 个变更文件 + 逐条手工追踪语料用例 + 对否定判定函数做 stdlib-only 逐字提取探针验证(/tmp,脱离工作区);未修改任何代码。
|
||||
|
||||
## 验证(本工作区内的执行情况)
|
||||
|
||||
- `git status --porcelain`:评审开始时为空(clean);四个组件 checkout 均精确处于被 pin 的 SHA 且无脏文件(agent-intent 7f3ff6a、native be556f4、squad 95b387d、backend bd5c0f3)。
|
||||
- `gofmt -l intent/ cmd/`:无输出(格式干净)。
|
||||
- `go test`:**NOT_RUN(环境不可编译)**。agent-intent/go.mod 的 `replace error-code-system => ./deps/error-code-system` 所指嵌套子模块在本工作区任何层级都未物化(superrepo、agent-intent、backend 三处的 error-code-system/logging-system 目录均为空挂载点),且相应 commit 对象不存在于任何本地对象库;单元约束禁止 `git submodule init/update`、禁止网络。`GOWORK=off go test ./intent/...` 如预期在包 setup 阶段失败(reading deps/error-code-system/go.mod: no such file)。诚实出口:本报告的测试结论为读码+探针+追踪,非重放。
|
||||
- 否定判定探针(negatedAt/inNonNegatingBie 逐字提取、21 组用例):全部 corpus 否定序列判否定;「不断」「无偿」不触发误否定;「不要马上重启」(间隔 2 字)判否定、「不要立刻马上重启」(间隔 3 字)不判(窗口语义);「特别的,重启任务」跨标点正确豁免;「任务别名重启」豁免成功;「判别任务进度」被误判否定(见 F1)。
|
||||
|
||||
## 评审发现
|
||||
|
||||
### Blocker
|
||||
|
||||
无。
|
||||
|
||||
### Major
|
||||
|
||||
无。
|
||||
|
||||
### Minor
|
||||
|
||||
- **F1(recall 损失,fail-safe 方向)**:「别」字白名单 `nonNegatingBie`(intent/registry.go:211-214)是封闭列表,「判别」「辨识」「作别」等含「别」的常用词不在列。探针实测「判别任务进度」→「进度」命中被 `negatedAt`(registry.go:263-275)判为否定 → status_query 以 `negated_match` 排除 → 回落 fallback。方向是安全的(少执行而非误执行),但对该输入是误回落。建议后续把「别」的否定判定改为右边界词表或按「别+动词」结构判断。
|
||||
- **F2(残余否定词缺口,符合既定设计范围)**:token 表(registry.go:204)无「无须」「勿」「先不」「暂不」「不必」等变体,如「无须重启任务」仍会正向命中 restart。任务卡设计决定明确固定了这 7 个词,故不算实施偏差;作为残余风险记录:negation_reference 类的其他说法仍可能误执行。
|
||||
|
||||
### Notes
|
||||
|
||||
- **N1(tie-break 只认“有效”槽位)**:`resolveTie`(intent/recognizer.go:152-185)用 `len(slots)` 计数,invalid 捕获(如多候选值)不计。因此「你好,取消任务 42 和任务 43」这类输入中 cancel 的 run_id 无效 → filled=0,与寒暄同为 0 时按 priority(greet=10 > cancel=0)裁决到寒暄,动作侧的 clarify 丢失。仅在同分且优先级不同时可达,且寒暄无副作用、动作未启动,属可接受行为选择;若希望「带槽位信号」包含无效捕获信号,需另行设计。
|
||||
- **N2(fail-closed 误伤面)**:`hasInnerSeparator`(slots.go:221)/`captureTruncated`(slots.go:201)对合法值也拦截——如主题「和平与发展」会因内部分隔词判多候选、值后紧跟 ASCII 词字符即判截断,一律 clarify 而非 start。与「无效一律 clarify」的设计一致,代价是 clarify 率上升(metrics 中 wrong_slot clarify 7/7=1.0),方向安全。
|
||||
- **N3(测试夹具标签失真,表面问题)**:cmd/intentctl/main_test.go:82-85 把 record_only 的 miss 用例从「不用查进度了」换成「进度条的颜色真好看」是必要的(旧输入修复后正确回落,不再产生 miss 计数;新输入在 testSpecJSON 下确会命中 status_query,仍覆盖 miss 记账路径,断言 MisExecutions==1 成立),但 category 仍标 `negation_reference`,语义已不属否定类——建议下次触及时改名或换语料类别。
|
||||
- **N4(验收证据等级)**:mis_exec=0 / 37/37 的验收来自 intent@7f3ff6a 内提交的 evaluation/metrics.json 与 BASELINE.md(作者证据,SELF 级)。本工作区无法重放(见上)。数字内部一致性已人工复核:各类 passed 7+8+7+8+7=37、clarify 5+0+5+0+7=17、fallback 3+1+0+7+0=11、top1 11+7+3+3+7=31/31、mis_exec 全 0,与 overall 行及 I2 段(TP=30/FP=0/FN=0,较基线同向 +1)全部吻合;gen_agree 5/8 未动(3 例 gen_agree 分歧按范围未处理,BASELINE.md 如实保留)。CI(`.gitea/workflows/ci.yaml` @ PR HEAD)是测试通过的权威源,合入门禁照常。
|
||||
- **N5(单元包描述与实际 diff 的 pin 基线不符,仅描述性)**:包内写 squad b6d8763→95b387d、backend 330c1a3→bd5c0f3;实际 vs main 为 squad a5afe9c8→95b387d、backend 8dc91c17→8031855e→bd5c0f3(两个 backend tip 树完全相同,bd5c0f3 非 8031855e 的后代而是同树重提交)。终态与包目标一致,无内容影响。
|
||||
- **N6(任务卡整理欠账)**:`.task/feature-recall-misexec-fixes.md` 的「Agent 实施收据」表仍是全 NOT_RUN/待定义,而「合入与清理」已记录实施收据;需求分析/阶段记录等模板段未填。卡片债务,非阻塞;Review 记录待本评审随 PR 流程回填。
|
||||
- **N7(正面确认,范围)**:变更严格限于三个修复+pin 级联+任务卡:intent 单提交共 9 文件(boundary.go 为纯重构抽取 `boundedAt`,语义等价);squad@95b387d、native@be556f4 两提交均只改 gitlink;嵌套 pin 全链一致(native→intent@7f3ff6a;squad→intent@7f3ff6a+native@be556f4;backend→intent@7f3ff6a+native@be556f4+squad@95b387d,与 superrepo 四个 gitlink 完全对应)。语料文件 recall_corpus.json 未改动(验收基准未被移动)。
|
||||
- **N8(正面确认,正确性要点)**:否定为逐次出现判断,同词条存在任一未否定出现即正向(TestNegationCountsUnnegatedOccurrence/TestNegatedPatternHit 覆盖了否定+未否定同词双情形);守卫域豁免否定(registry.go:236、254,宁可多拦,TestGuardIgnoresNegation);excludes_any/includes_all 语义未动;r2 回归测试改名并反转断言是对旧契约的有意修订且注释说明清楚;`resolveTie` 确定性(filled 降序→priority 降序→合并序,胜者须压过组内全体,平 priority 仍 ambiguous),仅在胜出时原位重排 hits,Explain/Recognize 双路径一致,I5 行为保留(TestRecognizeTieBreakPrefersPriority 未改);槽位新检查在 format/enum/validator 之前(slots.go:186-198),空白归一化后进 missing(slots.go:123),overlap 检测未动;misexec_test.go 逐条 pin 了 6 次误执行序列与 4 个错槽位序列(含 start+clarify 命令断言),非否定输入行为回归用例齐备。
|
||||
- **N9(字节级安全性)**:`termHit` 以 `i+1+j` 推进的重叠出现扫描与 `negatedAt` 的 `DecodeLastRuneInString` 回退均为 rune 安全;否定判定在折叠文本上进行,否定词为 CJK,大小写折叠/NFKC 不影响。
|
||||
|
||||
## 结论
|
||||
|
||||
三个修复(否定感知匹配、specificity tie-break、槽位 fail-closed)实现与任务卡设计决定一致,验收序列全部有单元级 pin,pin 级联自洽,范围无外溢。发现集中在启发式边界的已记录取舍(F1/F2)与非阻塞整理项;无阻断合入的问题。测试在本评审工作区因嵌套依赖未物化而 NOT_RUN,以探针与读码代替,合入前按门禁以 CI 为准。
|
||||
|
||||
REVIEW VERDICT: APPROVE
|
||||
Vendored
+1
-1
Submodule deps/agent-intent updated: 6aa4925301...7f3ff6a187
Vendored
+1
-1
Submodule deps/agent-native updated: d1f72aa974...be556f4641
Vendored
+1
-1
Submodule deps/agent-squad updated: a5afe9c8cc...95b387d722
+1
-1
Submodule modules/backend updated: 8dc91c1783...bd5c0f39e6
+1
-1
Submodule modules/frontend updated: 807c656886...279b2d02a2
+55
-124
@@ -3,13 +3,11 @@
|
||||
#
|
||||
# 动线(与 frontend/e2e/rdm-audit.spec.ts 的环境契约一一对应):
|
||||
# 1. 构建:RDM 二进制(RDM 仓 origin/main 临时 worktree,pins 物化)
|
||||
# + 基座 CLI(与 RDM pin 同源;identity ensure / plain-base serve)
|
||||
# + 基座 CLI(本 worktree modules/backend,建号用)
|
||||
# + frontend dist(本 worktree modules/frontend)
|
||||
# 2. 种子:RDM -bootstrap-admin(域管理员)→ SUPER_ADMIN_* → serve 首启建基座存储
|
||||
# (超管)→ identity ensure → 超管密码登录会话 → API rdm.project.create×2
|
||||
# → 主项目宿主会话来源(会话+一条用户消息)→ 正式命令 rdm.reqs.import /
|
||||
# rdm.ingest 等携 conversationId/anchorMessageId;
|
||||
# 普通账号(e2e-auditor 等)经超管会话 POST /api/admin/users 创建
|
||||
# 2. 种子:RDM -bootstrap-admin(域管理员)→ serve 首启建基座存储 → identity ensure →
|
||||
# 基座 user bootstrap-admin(login-key 激活契约;--password 已被拒绝)→
|
||||
# redeem+设密 → API rdm.project.create×2 + rdm.ingest(主项目)
|
||||
# 3. 验收:vite preview(dist+/api 代理)→ npx playwright test
|
||||
# 4. 收尾:停 serve/preview,保存认证/失败工件到 $E2E_OUT
|
||||
#
|
||||
@@ -19,7 +17,7 @@
|
||||
# RDM_REPO RDM 仓路径(默认 <本仓上级>/Agent-System-RDM)
|
||||
# E2E_API_PORT/E2E_UI_PORT 服务端口(默认 18791/4173)
|
||||
# E2E_OWNER/E2E_PASSWORD 登录账号(默认 e2e-auditor/E2eAudit#2026)
|
||||
# E2E_PASSWORD2 首次登录后的设密结果(默认 E2eAudit#2026b;Playwright 改密门消费)
|
||||
# E2E_PASSWORD2 首次登录后的设密结果(默认 E2eAudit#2026b;种子命令用它)
|
||||
# E2E_PROJECT_MAIN/E2E_PROJECT_ISOLATED 项目名(默认 审计演示项目/隔离检查项目)
|
||||
# E2E_OUT 工件目录(默认 .tmp/e2e/<ts>;.gitignore 已覆盖 .tmp)
|
||||
# 依赖:go、node/npm、curl;首次运行会 npx playwright install chromium。
|
||||
@@ -93,23 +91,14 @@ trap cleanup EXIT
|
||||
(cd "$RDM_WT" && go build -o "$OUT/agent-system-rdm" .) || die "rdm build failed"
|
||||
log "rdm binary: $OUT/agent-system-rdm (RDM@${RDM_SHA:0:12}, pins@${PIN_SHA_WANT:0:12})"
|
||||
|
||||
log "build base CLI (identity ensure + plain-base serve) from the same pinned backend as the RDM binary"
|
||||
# 版本一致性:基座 CLI 必须与被测 RDM 二进制共用同一基座 pin——用 Dev 顶层
|
||||
# backend(main 最新)会把库迁到更高 schema,RDM pins(较旧)打不开。
|
||||
log "build base CLI (account bootstrap/activation) from the same pinned backend as the RDM binary"
|
||||
# 版本一致性:建号 CLI 必须与被测 RDM 二进制共用同一基座 pin——用 Dev 顶层
|
||||
# backend(main 最新)建号会把库迁到更高 schema,RDM pins(较旧)打不开。
|
||||
(cd "$RDM_WT/pins/agent-system-backend" && go build -o "$OUT/agent-system" ./cmd/agent-system) \
|
||||
|| die "backend cli build failed"
|
||||
|
||||
# 直接构建 FE dist:不走 make frontend(其 contracts→test-worktree 要求全部
|
||||
# submodule 已物化;本脚本只需 FE+@ui 源码组合)。contracts.ts 以 FE pin 为准。
|
||||
log "build frontend dist (npm ci @ui + frontend, vite build)"
|
||||
[ -f "$DEV_ROOT/modules/ui/package.json" ] \
|
||||
|| die "modules/ui missing (need gitlink checkout for @ui alias)"
|
||||
[ -f "$DEV_ROOT/modules/frontend/package.json" ] \
|
||||
|| die "modules/frontend missing"
|
||||
(cd "$DEV_ROOT/modules/ui" && npm ci --no-fund --no-audit) >/dev/null \
|
||||
|| die "ui npm ci failed"
|
||||
(cd "$DEV_ROOT/modules/frontend" && npm ci --no-fund --no-audit && npm run build) \
|
||||
|| die "frontend build failed"
|
||||
log "build frontend dist (contracts + ui deps + bundle, via make frontend)"
|
||||
make -C "$DEV_ROOT" frontend >/dev/null || die "frontend build failed"
|
||||
|
||||
# ── 2. 种子 ─────────────────────────────────────────────
|
||||
DATA="$OUT/data"
|
||||
@@ -119,13 +108,9 @@ RDM="$OUT/agent-system-rdm -data $DATA"
|
||||
log "bootstrap: RDM domain admin = $OWNER"
|
||||
$RDM -bootstrap-admin "$OWNER" >/dev/null
|
||||
|
||||
# ── 凭据契约:auth on 时超管由 serve 启动期 SUPER_ADMIN_OWNER/SUPER_ADMIN_PASSWORD
|
||||
# 建立(基座已禁用 bootstrap-admin)。种子 API 会话走超管密码登录;普通账号
|
||||
# (e2e-auditor 等)经 POST /api/admin/users 创建(初始密码合成值,mustChangePassword
|
||||
# 由 Playwright 首登改密门处理)。合成测试凭据(非真实秘密)。
|
||||
: "${SUPER_ADMIN_OWNER:=e2e-superadmin}"
|
||||
: "${SUPER_ADMIN_PASSWORD:=E2eSuperAdmin#FixedTest9kQm2NpR}"
|
||||
export SUPER_ADMIN_OWNER SUPER_ADMIN_PASSWORD
|
||||
# ── 凭据契约(2026-10-13 起):--password 建号被 RECOVERY_CONTRACT_REPLACED 拒绝,
|
||||
# 改走 login-key 激活:serve 首启创建基座存储 → identity ensure → 基座首位账号
|
||||
# bootstrap-admin(激活 Key 交付)→ API redeem → 设密(PASSWORD2 为登录密码)。
|
||||
log "serve RDM at $API_BASE (auth on;首启创建基座存储)"
|
||||
start_serve() {
|
||||
"$OUT/agent-system-rdm" -data "$DATA" -addr "127.0.0.1:$API_PORT" -auth on \
|
||||
@@ -143,115 +128,64 @@ stop_serve() {
|
||||
[ -n "${API_PID:-}" ] && { kill "$API_PID" 2>/dev/null || true; wait "$API_PID" 2>/dev/null || true; API_PID=""; }
|
||||
}
|
||||
login() {
|
||||
# Seed API session uses serve-established superadmin (not E2E_OWNER).
|
||||
local i
|
||||
for i in $(seq 1 20); do
|
||||
if curl -sf -c "$JAR" -X POST "$API_BASE/api/auth/login" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"owner\":\"$SUPER_ADMIN_OWNER\",\"password\":\"$SUPER_ADMIN_PASSWORD\"}" >/dev/null; then
|
||||
-d "{\"owner\":\"$OWNER\",\"password\":\"$PASSWORD\"}" >/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
sleep 0.25
|
||||
done
|
||||
die "superadmin login failed"
|
||||
die "login failed"
|
||||
}
|
||||
cmd() { # cmd <id> <params-json> [extra-body-fields] → payload(失败即死,种子步骤不容忍部分成功)
|
||||
local id=$1 params=${2:-{\}} extra=${3:-}
|
||||
cmd() { # cmd <id> <params-json> → payload(失败即死,种子步骤不容忍部分成功)
|
||||
local id=$1 params=${2:-{\}}
|
||||
curl -sf -b "$JAR" -X POST "$API_BASE/api/commands/$id" \
|
||||
-H 'Content-Type: application/json' -d "{${extra:+$extra,}\"params\":$params}" \
|
||||
-H 'Content-Type: application/json' -d "{\"params\":$params}" \
|
||||
| python3 -c 'import json,sys; d=json.load(sys.stdin); r=(d or {}).get("receipt",{}); sys.exit(1) if r.get("state")=="rejected" else None; print(json.dumps(d.get("payload", d), ensure_ascii=False))' \
|
||||
|| die "command $id rejected"
|
||||
}
|
||||
admin_create_user() { # admin_create_user <owner> <password> [display-name] [isAdmin]
|
||||
# 超管会话 POST /api/admin/users;200 且 mustChangePassword:true(Playwright 首登改密)。
|
||||
# 第 4 参为 true 时任命基座管理员(admin-user-create 需「系统管理…」入口;仅超管可任命)。
|
||||
local owner=$1 password=$2 name=${3:-$1} is_admin=${4:-false} body
|
||||
body=$(curl -sf -b "$JAR" -X POST "$API_BASE/api/admin/users" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"owner\":\"$owner\",\"password\":\"$password\",\"profile\":{\"name\":\"$name\"},\"isAdmin\":$is_admin}") \
|
||||
|| die "admin create user $owner failed"
|
||||
printf '%s' "$body" | python3 -c 'import json,sys; d=json.load(sys.stdin); sys.exit(0 if d.get("mustChangePassword") is True else 1)' \
|
||||
|| die "admin create user $owner: expected mustChangePassword:true"
|
||||
}
|
||||
# 浏览器用例若不以改密门处理该账号(如 cockpit 的 e2e-reader),种子阶段代完 must-change。
|
||||
complete_must_change() { # complete_must_change <owner> <initial> <final>
|
||||
local owner=$1 initial=$2 final=$3 jar i
|
||||
jar="$OUT/${owner}.changepw.jar"
|
||||
for i in $(seq 1 20); do
|
||||
if curl -sf -c "$jar" -X POST "$API_BASE/api/auth/login" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"owner\":\"$owner\",\"password\":\"$initial\"}" >/dev/null; then
|
||||
break
|
||||
fi
|
||||
sleep 0.25
|
||||
[ "$i" = 20 ] && die "must-change login failed for $owner"
|
||||
done
|
||||
curl -sf -b "$jar" -c "$jar" -X POST "$API_BASE/api/auth/password" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"current\":\"$initial\",\"next\":\"$final\"}" >/dev/null \
|
||||
|| die "must-change password failed for $owner"
|
||||
}
|
||||
# 正式项目命令(rdm.reqs.*/rdm.review.*/rdm.draft.*/rdm.ingest 等,基座
|
||||
# cmdbus.RequiresProjectWorkDecision)须带已认证会话来源:conversationId 绑定宿主项目,
|
||||
# anchorMessageId 为该会话中已提交、经 RDM 来源分析放行的用户消息;裸调用被预检拒绝。
|
||||
seed_source() { # seed_source <hostProjectId>:超管在宿主项目建种子会话并提交一条来源消息
|
||||
local host=$1 body
|
||||
body=$(curl -sf -b "$JAR" -X POST "$API_BASE/api/projects/$host/conversations" \
|
||||
-H 'Content-Type: application/json' -d '{"title":"e2e seed source"}') \
|
||||
|| die "seed source conversation create failed"
|
||||
SRC_CONV=$(printf '%s' "$body" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')
|
||||
body=$(curl -sf -b "$JAR" -X POST "$API_BASE/api/conversations/$SRC_CONV/messages" \
|
||||
-H 'Content-Type: application/json' -d '{"text":"e2e 种子:导入需求台账、入库需求语料、登记驾驶舱探针与文档职责"}') \
|
||||
|| die "seed source message failed"
|
||||
SRC_MSG=$(printf '%s' "$body" | python3 -c 'import json,sys; print(json.load(sys.stdin)["message"]["id"])')
|
||||
}
|
||||
fcmd() { # fcmd <id> <params-json>:正式项目命令,附种子会话来源
|
||||
[ -n "${SRC_MSG:-}" ] || die "formal command $1 needs seed_source first"
|
||||
cmd "$1" "$2" "\"conversationId\":\"$SRC_CONV\",\"anchorMessageId\":\"$SRC_MSG\""
|
||||
}
|
||||
|
||||
# 阶段①:超管会话 + 管理 API 建号,再建项目与需求台账(API;需 serve)。
|
||||
# 阶段①:激活账号并建项目与需求台账(API;需 serve)。
|
||||
start_serve
|
||||
JAR="$OUT/cookies.txt"
|
||||
log "seed: identity ensure + base first account (SUPER_ADMIN session)"
|
||||
log "seed: identity ensure + base first account (login-key 契约)"
|
||||
ID_OK=0
|
||||
for i in $(seq 1 15); do
|
||||
if "$OUT/agent-system" identity ensure --data "$DATA" --instance-id "e2e-audit" >/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"; }
|
||||
# Legacy bootstrap-admin is disabled; super admin is established at serve startup
|
||||
# from SUPER_ADMIN_OWNER/SUPER_ADMIN_PASSWORD. Login via the normal session endpoint.
|
||||
"$OUT/agent-system" user bootstrap-admin --data "$DATA" --owner "$OWNER" \
|
||||
--name "E2E 审计员" --out-file "$OUT/$OWNER.bootstrap.key" >/dev/null \
|
||||
|| die "base bootstrap-admin failed"
|
||||
K=$(cat "$OUT/$OWNER.bootstrap.key")
|
||||
curl -sf -c "$JAR" -X POST "$API_BASE/api/auth/login-key/redeem" \
|
||||
-H 'Content-Type: application/json' -d "{\"key\":\"$K\"}" >/dev/null || die "login-key redeem failed"
|
||||
# 激活会话仅能设密:设为 PASSWORD2(后续登录与规格消费一致)。
|
||||
curl -sf -b "$JAR" -c "$JAR" -X POST "$API_BASE/api/auth/password" \
|
||||
-H 'Content-Type: application/json' -d "{\"next\":\"$PASSWORD2\"}" >/dev/null || die "password setup failed"
|
||||
PASSWORD=$PASSWORD2
|
||||
login
|
||||
# Fixture owner(默认 e2e-auditor):RDM -bootstrap-admin 已授域管理员;此处再建基座账号
|
||||
# 并任命 isAdmin(admin-user-create 需「系统管理…」)。初始密码=PASSWORD,mustChange
|
||||
# 由 Playwright 首登改密门处理为 PASSWORD2(不覆盖超管会话 jar)。
|
||||
admin_create_user "$OWNER" "$PASSWORD" "$OWNER" true
|
||||
log "seed: create projects"
|
||||
read -r PID_MAIN HOST_MAIN < <(cmd rdm.project.create "{\"name\":\"$PROJ_MAIN\"}" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["projectId"], d["hostProjectId"])')
|
||||
[ -n "${HOST_MAIN:-}" ] || die "rdm.project.create: missing projectId/hostProjectId"
|
||||
PID_MAIN=$(cmd rdm.project.create "{\"name\":\"$PROJ_MAIN\"}" | python3 -c 'import json,sys; print(json.load(sys.stdin)["projectId"])')
|
||||
PID_ISO=$(cmd rdm.project.create "{\"name\":\"$PROJ_ISO\"}" | python3 -c 'import json,sys; print(json.load(sys.stdin)["projectId"])')
|
||||
log "seed: projects main=$PID_MAIN (host $HOST_MAIN) iso=$PID_ISO"
|
||||
log "seed: projects main=$PID_MAIN iso=$PID_ISO"
|
||||
|
||||
# Projects are created under the SUPER_ADMIN session (immutable creator). The
|
||||
# Playwright fixture owner is a separate account: add it as project owner so
|
||||
# doc visibility comes from membership + member-role defaults.
|
||||
log "seed: add fixture owner as project member (owner role; doc via member defaults)"
|
||||
cmd rdm.project.member.add "{\"projectId\":\"$PID_MAIN\",\"member\":\"$OWNER\",\"role\":\"owner\"}" >/dev/null
|
||||
cmd rdm.project.member.add "{\"projectId\":\"$PID_ISO\",\"member\":\"$OWNER\",\"role\":\"owner\"}" >/dev/null
|
||||
# audit.read is never a member-role default and its platform cap ships closed
|
||||
# (rdm_perm_caps audit.read=0): open the cap, then grant it explicitly per project
|
||||
# (rdm.perm.set is rejected above the cap).
|
||||
log "seed: audit.read cap + explicit grant to fixture owner on both projects"
|
||||
# I1 requires a current business grant even for a project creator or system
|
||||
# administrator. Both projects are ordinary test fixtures in this private data root.
|
||||
log "seed: grant explicit audit.read for the fixture owner"
|
||||
cmd rdm.perm.cap '{"action":"audit.read","allow":true}' >/dev/null
|
||||
for p in "$PID_MAIN" "$PID_ISO"; do
|
||||
cmd rdm.perm.set "{\"projectId\":\"$p\",\"member\":\"$OWNER\",\"action\":\"audit.read\",\"allow\":true}" >/dev/null
|
||||
done
|
||||
cmd rdm.perm.set "{\"projectId\":\"$PID_MAIN\",\"member\":\"$OWNER\",\"action\":\"audit.read\",\"allow\":true}" >/dev/null
|
||||
cmd rdm.perm.set "{\"projectId\":\"$PID_ISO\",\"member\":\"$OWNER\",\"action\":\"audit.read\",\"allow\":true}" >/dev/null
|
||||
|
||||
log "seed: grant explicit doc.read for the cockpit fixture owner"
|
||||
cmd rdm.perm.set "{\"projectId\":\"$PID_MAIN\",\"member\":\"$OWNER\",\"action\":\"doc.read\",\"allow\":true}" >/dev/null
|
||||
cmd rdm.perm.set "{\"projectId\":\"$PID_ISO\",\"member\":\"$OWNER\",\"action\":\"doc.read\",\"allow\":true}" >/dev/null
|
||||
|
||||
log "seed: conversation source in $HOST_MAIN (formal project commands)"
|
||||
seed_source "$HOST_MAIN"
|
||||
log "seed: import requirement ledger into $PID_MAIN"
|
||||
fcmd rdm.reqs.import "{\"projectId\":\"$PID_MAIN\",\"items\":$(
|
||||
cmd rdm.reqs.import "{\"projectId\":\"$PID_MAIN\",\"items\":$(
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
rows = [
|
||||
@@ -294,35 +228,33 @@ SEED_MD='# 用户需求与系统需求
|
||||
审计工作区按项目隔离读取;管理员可跨项目目录进入。事件按操作归组,
|
||||
历史模式按 seq 还原,缺失事实明确标注不可恢复。'
|
||||
log "seed: ingest corpus into $PID_MAIN"
|
||||
fcmd rdm.ingest "{\"projectId\":\"$PID_MAIN\",\"source\":\"01-用户需求与系统需求.md\",\"stage\":\"BD\",\"text\":$(python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))' <<<"$SEED_MD")}" >/dev/null
|
||||
cmd rdm.ingest "{\"projectId\":\"$PID_MAIN\",\"source\":\"01-用户需求与系统需求.md\",\"stage\":\"BD\",\"text\":$(python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))' <<<"$SEED_MD")}" >/dev/null
|
||||
log "seed done"
|
||||
|
||||
# ── 驾驶舱 I4 种子:章节探针提案 + 非成员账号(正文经结构 YAML 装载) ──
|
||||
# Fixture owner already holds doc.write via owner membership defaults; seed
|
||||
# draft.propose runs as SUPER_ADMIN (project creator) and needs no perm.set.
|
||||
cmd rdm.perm.set "{\"projectId\":\"$PID_MAIN\",\"member\":\"$OWNER\",\"action\":\"doc.write\",\"allow\":true}" >/dev/null
|
||||
log "seed: cockpit pending proposal probe (non-danger; scenario 4)"
|
||||
COCKPIT_OV=$(cmd rdm.cockpit.overview "{\"projectId\":\"$PID_MAIN\"}")
|
||||
DOC_ID=$(printf '%s' "$COCKPIT_OV" | python3 -c 'import json,sys; d=json.load(sys.stdin); print([i["ref"]["id"] for i in d["documents"] if i["title"]=="验证主体报告"][0])')
|
||||
SEC_JSON=$(cmd rdm.cockpit.tree "{\"projectId\":\"$PID_MAIN\",\"parent\":\"$DOC_ID\"}")
|
||||
SEC_DESIGN=$(printf '%s' "$SEC_JSON" | python3 -c 'import json,sys; d=json.load(sys.stdin); print([i["ref"]["id"] for i in d["items"] if i["title"]=="设计说明"][0])')
|
||||
# 场景 4 驱动用:留一个未采纳提案(浏览器内经 API 采纳后观察投影一致)。
|
||||
fcmd rdm.draft.propose "{\"projectId\":\"$PID_MAIN\",\"sectionId\":\"$SEC_DESIGN\",\"content\":\"一致性探针内容。\"}" >/dev/null
|
||||
cmd rdm.draft.propose "{\"projectId\":\"$PID_MAIN\",\"sectionId\":\"$SEC_DESIGN\",\"content\":\"一致性探针内容。\"}" >/dev/null
|
||||
# 场景 2 驱动:验证主体报告设文档级三权(职责判据与正文版本作者无关;
|
||||
# 结构装载作者为 structure,owner 经文档职责获得正文可读)。
|
||||
log "seed: duty accounts + doc-level duties (scenario 2)"
|
||||
DOC_MAIN=$(printf '%s' "$COCKPIT_OV" | python3 -c 'import json,sys; d=json.load(sys.stdin); print([i["ref"]["id"] for i in d["documents"] if i["title"]=="验证主体报告"][0])')
|
||||
admin_create_user e2e-rev 'E2eRev#2026' e2e-rev
|
||||
admin_create_user e2e-app 'E2eApp#2026' e2e-app
|
||||
"$OUT/agent-system" user create --data "$DATA" --owner e2e-rev --out-file "$OUT/e2e-rev.bootstrap.key" >/dev/null || die "rev create failed"
|
||||
"$OUT/agent-system" user create --data "$DATA" --owner e2e-app --out-file "$OUT/e2e-app.bootstrap.key" >/dev/null || die "app create failed"
|
||||
cmd rdm.project.member.add "{\"projectId\":\"$PID_MAIN\",\"member\":\"e2e-rev\",\"role\":\"member\"}" >/dev/null
|
||||
cmd rdm.project.member.add "{\"projectId\":\"$PID_MAIN\",\"member\":\"e2e-app\",\"role\":\"member\"}" >/dev/null
|
||||
fcmd rdm.review.assign.doc "{\"projectId\":\"$PID_MAIN\",\"docId\":\"$DOC_MAIN\",\"author\":\"$OWNER\",\"reviewers\":[\"e2e-rev\"],\"approver\":\"e2e-app\"}" >/dev/null
|
||||
cmd rdm.review.assign.doc "{\"projectId\":\"$PID_MAIN\",\"docId\":\"$DOC_MAIN\",\"author\":\"$OWNER\",\"reviewers\":[\"e2e-rev\"],\"approver\":\"e2e-app\"}" >/dev/null
|
||||
log "seed: second account (non-member negative case)"
|
||||
# cockpit 场景 6 直接以 E2E_READER_PASSWORD 登录(无改密门);种子代完 must-change,
|
||||
# 使最终密码与 Playwright 缺省 E2eReader#2026 一致。
|
||||
READER=${E2E_READER:-e2e-reader}
|
||||
READER_PASSWORD=${E2E_READER_PASSWORD:-E2eReader#2026}
|
||||
admin_create_user "$READER" "$READER_PASSWORD" "$READER"
|
||||
complete_must_change "$READER" "$READER_PASSWORD" "$READER_PASSWORD"
|
||||
"$OUT/agent-system" user create --data "$DATA" --owner e2e-reader --out-file "$OUT/e2e-reader.bootstrap.key" >/dev/null || die "reader create failed"
|
||||
K2=$(cat "$OUT/e2e-reader.bootstrap.key")
|
||||
JAR2="$OUT/reader.jar"
|
||||
curl -sf -c "$JAR2" -X POST "$API_BASE/api/auth/login-key/redeem" -H 'Content-Type: application/json' -d "{\"key\":\"$K2\",\"owner\":\"e2e-reader\"}" >/dev/null || die "reader redeem failed"
|
||||
curl -sf -b "$JAR2" -c "$JAR2" -X POST "$API_BASE/api/auth/password" -H 'Content-Type: application/json' -d "{\"next\":\"E2eReader#2026\"}" >/dev/null || die "reader password setup failed"
|
||||
|
||||
# ── 3. 验收 ─────────────────────────────────────────────
|
||||
if [ "$SEED_ONLY" = 1 ]; then
|
||||
@@ -352,12 +284,11 @@ log "playwright (install chromium if missing)"
|
||||
log "run specs"
|
||||
cd "$DEV_ROOT/modules/frontend"
|
||||
export PLAYWRIGHT_BASE_URL="http://127.0.0.1:$UI_PORT" E2E_OWNER="$OWNER" \
|
||||
E2E_PASSWORD="$PASSWORD" E2E_PASSWORD2="$PASSWORD2" \
|
||||
E2E_READER="$READER" E2E_READER_PASSWORD="$READER_PASSWORD" \
|
||||
E2E_PASSWORD="${E2E_PASSWORD:-E2eAudit#2026}" E2E_PASSWORD2="$PASSWORD2" \
|
||||
E2E_PROJECT_MAIN="$PROJ_MAIN" E2E_PROJECT_ISOLATED="$PROJ_ISO"
|
||||
set +e
|
||||
# 本脚本的种子只覆盖审计工作区。u7 现场验收用例依赖另一套入口,不在这里跑。
|
||||
# admin-create 场景复用本种子的基座超管会话(SUPER_ADMIN_*)。
|
||||
# admin-create 场景复用本种子的基座管理员账号(bootstrap-admin)。
|
||||
npx playwright test e2e/rdm-audit.playwright.ts e2e/rdm-cockpit.playwright.ts e2e/admin-user-create.playwright.ts --reporter=list >"$OUT/playwright.log" 2>&1
|
||||
PW_EXIT=$?
|
||||
set -e
|
||||
|
||||
Reference in New Issue
Block a user