test(e2e): full-system browser multi-user acceptance

This commit is contained in:
weichen
2026-09-26 03:48:34 +00:00
parent 4873c5e8b9
commit 466426a58f
19 changed files with 437 additions and 190 deletions
@@ -24,65 +24,25 @@ remote_sync: not_requested
## 用户目标与授权
- **目标**:对已清库(wipe)的 local `dev`(`BASE_URL=http://127.0.0.1:8080`)做完整、深入的**真实 Chromium / Playwright** 多人协作验收,并按测试报告规范落盘。
- **硬边界**:禁止用 API 创建项目/发消息/审批文档;仅允许登录探测、health、查控制台/落盘证据用的只读辅助。业务动作一律浏览器点击/输入。
- **交付终点**:`web/e2e/full-system-browser-e2e.spec.ts` + assets 证据 + `.doc/test-reports/2026-09-26-full-system-browser-e2e-test-report.md` + agentctl 租约内 commit。
- **保留**:测完保留测试账号与内容(前缀 `e2e26_` / 项目 `E2E全量-20260926-`)。
- **目标**:wipe 后 local `dev` 真实 Chromium / Playwright 多人协作验收 + 规范报告。
- **硬边界**:业务动作仅浏览器;禁止 API 冒充立项/发消息/审批。
- **交付终点**:spec + assets + test-report + agentctl commit。
## 前置(已完成)
## 本轮结果(2026-09-26T03:32Z Docker,EXIT:1)
- Wipe 收据:[.doc/test-reports/assets/2026-09-26-full-system-browser-e2e/wipe-receipt.md](../../test-reports/assets/2026-09-26-full-system-browser-e2e/wipe-receipt.md)
- 清库后:schema 75;用户含 `admin` + goose `seed-*`;10 种子项目;`DISABLE_DEV_SEED_USERS=true`(runtime demo 用户未创建)
## 证据路径
| 产物 | 路径 |
|---|---|
| Playwright log | `.doc/test-reports/assets/2026-09-26-full-system-browser-e2e/playwright.log` |
| 结果账本 | `…/ui-results.json` |
| 截图 | `…/screenshots/` |
| console 落盘 | `…/console-*.jsonl` |
| 测试报告 | `.doc/test-reports/2026-09-26-full-system-browser-e2e-test-report.md` |
## 用例 ID(优先级)
| 优先级 | ID 前缀 | 覆盖 |
|---|---|---|
| P0 | FS-IAM / FS-PROJ / FS-CHAT | 建用户角色、建项目加成员分权、基础对话 |
| P0 | FS-SQUAD-WF / FS-DOC-REV / FS-NONAUTH | 工作流文档生成→审签→退回→再送→批准;non-author 编辑 vs 送审门禁 |
| P1 | FS-ASSIST / FS-SQUAD-FREE / FS-UPLOAD / FS-KB / FS-CTX | 助手任务、自由任务、上传解析、KB 只读核验、上下文观察 |
| P2 | FS-CONSOLE / 冲突 | console 汇总、双人编辑冲突(时间不够则 SKIP+理由) |
- PASS **5** / FAIL **1** / SKIP(did not run)**15**
- 已修:create-modal 角色 + `promoteToProjectMember`(LeftRail title +「完成并关闭」)
- **FAIL**:FS-SQUAD-WF-01 真实 PI 任务 `data-chat-status=pending` 挂起至测试超时 15m(server-id 243)
- 保留用户:`e2e26_{author,reviewer,approver,member,guest}_muhu39da`;项目 `E2E全量-20260926-muhu39da`
- 报告:`.doc/test-reports/2026-09-26-full-system-browser-e2e-test-report.md`
## 计划与进展
1. [x] Wipe 完成(sibling wipe task)
2. [x] 编写 Playwright full-system spec + 任务记录 + Docker 运行脚本
3. [x] 实跑 Docker Playwright(`DISPLAY` empty / headless;`DOCKER_E2E_EXIT:1`)
4. [x] 落盘规范测试报告(FAIL 收口;见 test-reports)
5. [ ] 修复 FS-PROJ-01 `editor` option 契约后全量重跑
6. [x] `agentctl with` commit(本轮证据 + 报告)
## 本轮结果(2026-09-26T03:25Z Docker)
- PASS **2** / FAIL **1** / SKIP(did not run)**18**
- 严重缺陷:FS-PROJ-01 `selectOption('editor')` vs UI 仅 `author|reviewer|approver|viewer`
- 保留用户:`e2e26_{author,reviewer,approver,member,guest}_muhtu9gc`(无密码)
- 报告:`.doc/test-reports/2026-09-26-full-system-browser-e2e-test-report.md`
## 已知阻塞与处置
| 问题 | 处置 |
|---|---|
| 宿主 `npx playwright` 缺 `libatk-1.0.so.0` | 已改标准 Docker Playwright 通道;本轮 Chromium 正常启动 |
| FS-PROJ-01 角色 option 不匹配 | 修正 spec 角色值后重跑;当前 FAIL 阻断 PI/审签 |
1. [x] Wipe / spec / Docker 脚本
2. [x] 修角色与 promote 选择器并重跑
3. [x] 落盘 FAIL 收口报告 + agentctl commit
4. [ ] 排查 PI pending 挂起后全量重跑至绿
## 验证契约
- 层级:产品 UI 真实浏览器验收(验证契约「产品 PI 基线」相关);禁止 stub/SKIP 冒充 PASS。
- 未跑项必须 `SKIP` + 理由。
- 工程规范变更附带 e2e;本任务以 UI 证据为主。
## 状态与交接
- Docker 实跑 + 报告已落盘;全量验收未完成(FS-PROJ-01 FAIL)。
- 不 push;不合入除非另授权。下一步:修 option 契约后重跑。
- 产品 UI + 真实 PI;未跑项 SKIP;不得 stub 冒充 PASS。
@@ -2,42 +2,36 @@
## 一、测试背景 (Background)
对 wipe 后的 local `dev`(`BASE_URL=http://127.0.0.1:8080`,schema 75)做完整、深入的真实 Chromium / Playwright 多人协作验收。宿主直接跑 Playwright 会因缺 `libatk-1.0.so.0` 失败;本轮按仓库标准改走 **Docker Playwright**(`mcr.microsoft.com/playwright:v1.63.0-noble`,`--network host`)。
对 wipe 后的 local `dev`(`BASE_URL=http://127.0.0.1:8080`)做完整 Playwright 多人协作验收。宿主缺 `libatk-1.0.so.0`,按仓库标准走 **Docker Playwright**(`mcr.microsoft.com/playwright:v1.63.0-noble --network host`)。上一轮 FS-PROJ-01 因 create-modal 误用 `editor` / promote 误点私密库「保存」失败;本轮已修正选择器后全量重跑。
## 二、测试目标 (Test Objectives)
- 实跑 `web/e2e/full-system-browser-e2e.spec.ts`(21 条 serial)真实 UI
- 覆盖 IAM → 立项加成员 → 工作流审签 → 自由任务 / 上传 / KB / console 等链路
- 落盘 assets + 本规范报告;`agentctl with` 租约内提交
- 实跑 `web/e2e/full-system-browser-e2e.spec.ts`(21 条 serial)真实 UI + 真实 PI
- 覆盖 IAM → 立项/成员晋升 → 工作流 → 闲聊 → 编队生成 intake → 审签链路等
- 落盘 assets + 本规范报告;`agentctl with` 租约提交
## 三、测试方案与环境 (Test Plan & Environment)
| 项 | 值 |
|---|---|
| OS | linux 7.0.0-31-generic |
| 通道 | **headless Docker Playwright**(非宿主 Chromium) |
| 通道 | **headless Docker Playwright** |
| 镜像 | `mcr.microsoft.com/playwright:v1.63.0-noble` |
| 网络 | `--network host` → `http://127.0.0.1:8080` |
| DISPLAY | **empty / unset**(`DISPLAY=<unset>`;`run-meta.json` → `"display": ""`, `"headedHint": false`) |
| 环境变量 | `CI=1`,`DISABLE_DEV_SEED_USERS=true`,`RUN_UI_ACCEPTANCE=1` |
| 入口脚本 | `web/scripts/run-full-system-browser-e2e.sh` |
| 测试层级 | 产品 UI 真实浏览器验收(验证契约「产品 PI 基线」相关);禁止 stub 冒充 PASS |
启动证据(终端):
| BASE_URL | `http://127.0.0.1:8080`(`--network host`) |
| DISPLAY | **empty**(`DISPLAY=<unset>`;`run-meta.json` → `"display":""`, `"headedHint":false`) |
| 入口 | `web/scripts/run-full-system-browser-e2e.sh` |
| 开始时间 | `2026-09-26T03:32:25.804Z` |
| 层级 | 产品 UI 真实浏览器验收(含真实 PI);禁止 stub 冒充 PASS |
```text
/usr/bin/docker
DOCKER_OK
2026-09-26T03:32:24+00:00
DISPLAY=<unset>
2026-09-26T03:25:24+00:00
IMAGE=mcr.microsoft.com/playwright:v1.63.0-noble BASE_URL=http://127.0.0.1:8080 ASSETS=.../2026-09-26-full-system-browser-e2e WT=.../full-system-browser-e2e-2026-09-26
IMAGE=mcr.microsoft.com/playwright:v1.63.0-noble BASE_URL=http://127.0.0.1:8080 …
```
## 四、预期结果 (Expected Results)
- 21 条用例按 serial 顺序执行;IAM/立项成功后进入真实 PI 等待(预计 1–2h)
- 每条在 `ui-results.json` 记 PASS / FAIL / SKIP(SKIP 须附理由)
- P0 失败则后续未跑项记 SKIP(不得记 PASS)
- 21 条按 serial 执行;编队用例允许长达数十分钟~2h 等待真实 PI
- `ui-results.json` 记录 PASS/FAIL/SKIP;P0 FAIL 后后续 did not run 记 SKIP(不得记 PASS)
## 五、实际测试结果与判定 (Actual Results & Evaluation)
@@ -45,111 +39,93 @@ IMAGE=mcr.microsoft.com/playwright:v1.63.0-noble BASE_URL=http://127.0.0.1:8080
| Verdict | Count | IDs |
|---|---:|---|
| PASS | **2** | FS-IAM-01, FS-IAM-02 |
| FAIL | **1** | FS-PROJ-01 |
| SKIP | **0**(账本未写入 SKIP 行) | — |
| PASS | **5** | FS-IAM-01, FS-IAM-02, FS-PROJ-01, FS-PROJ-02, FS-CHAT-01 |
| FAIL | **1** | FS-SQUAD-WF-01 |
| SKIP | **0**(账本未写 SKIP 行) | — |
### 5.2 Playwright 套件计数(`playwright.log`)
| 指标 | 值 |
|---|---|
| passed | **2** |
| passed | **5** |
| failed | **1** |
| did not run(报告口径记为 SKIP) | **18** |
| duration | 35.2s |
| `DOCKER_E2E_EXIT` | **1** |
`playwright.log` 摘要:
| did not run(报告口径 SKIP) | **15** |
| duration | 15.1m |
| `EXIT` | **1** |
```text
Running 21 tests using 1 worker
✓ 1 … FS-IAM-01 admin creates multi-role users via UI (2.0s)
✓ 2 … FS-IAM-02 first-login password change for all e2e users (2.0s)
✘ 3 … FS-PROJ-01 create project + add members with roles (30.5s)
- 4 … FS-PROJ-02 …
…(至 21 均为 did not run)
✓ 1 … FS-IAM-01 … (2.1s)
✓ 2 … FS-IAM-02 … (2.1s)
✓ 3 … FS-PROJ-01 … (793ms)
✓ 4 … FS-PROJ-02 … (632ms)
✓ 5 … FS-CHAT-01 … (347ms)
✘ 6 … FS-SQUAD-WF-01 generate workflow intake document (real PI) (15.0m)
- 7 … FS-DOC-REV-01 …
…(至 21 did not run)
1 failed
18 did not run
2 passed (35.2s)
15 did not run
5 passed (15.1m)
EXIT:1
```
### 5.3 逐条记录
### 5.3 逐条(账本)
#### FS-IAM-01 — PASS(2008ms)
| ID | Verdict | Duration | 实际摘要 |
|---|---|---:|---|
| FS-IAM-01 | PASS | 2052ms | 五账号 `e2e26_*_muhu39da` 开通 |
| FS-IAM-02 | PASS | 2064ms | 5/5 首次改密 |
| FS-PROJ-01 | PASS | 790ms | 立项成功;guestListed=true;**member promoted** |
| FS-PROJ-02 | PASS | 628ms | workflow activated |
| FS-CHAT-01 | PASS | 344ms | assistant bubble non-empty |
| FS-SQUAD-WF-01 | FAIL | 900102ms | 真实 PI:`data-chat-status` 始终 `"pending"`,测试超时 900000ms |
- **输入**:admin 控制台 →「开通受控员工账号」×5
- **实际输出**:`e2e26_author_muhtu9gc,e2e26_reviewer_muhtu9gc,e2e26_approver_muhtu9gc,e2e26_member_muhtu9gc,e2e26_guest_muhtu9gc`
- **判定**:PASS
- **截图**:`screenshots/FS-IAM-01-admin-users.png`, `FS-IAM-01-done.png`
#### FS-IAM-02 — PASS(1998ms)
- **输入**:五个 `e2e26_*` 账号首次登录改密
- **实际输出**:`5/5 password changes OK`
- **判定**:PASS
- **截图**:`screenshots/FS-IAM-02-done.png`
#### FS-PROJ-01 — FAIL(30515ms)
- **输入**:author 登录 →「新建立项会话」→ 填项目名/描述 → 勾选成员并设角色(含 `selectOption('editor')`)
- **实际输出**(`playwright.log`):
#### FS-SQUAD-WF-01 FAIL 终端片段
```text
TimeoutError: locator.selectOption: Timeout 30000ms exceeded.
Call log:
- waiting for … getByText('E2E成员-muhtu9gc' …).locator('select')
- locator resolved to <select>…</select>
- attempting select option action
… did not find some options …
Test timeout of 900000ms exceeded.
Error: expect(locator).toHaveAttribute(expected) failed
Locator: …[@data-chat-role="assistant"]
Expected pattern: /^(completed|pending_author_confirmation|failed|cancelled|quality_failed|blocked_pending_governance)$/
Received string: "pending"
… 540 × … data-chat-status="pending" id="chat-anchor-ast-1790393552123"
… 1252 × … data-server-id="243" data-category="task" data-chat-status="pending"
```
- **判定**:FAIL
- **根因(已核对 UI)**:`CreateProjectModal.tsx` 成员角色 `<select>` 仅有 `author|reviewer|approver|viewer`;spec 对成员传入不存在的 `editor`,导致 `selectOption` 永久匹配失败。
- **截图**:`screenshots/FS-PROJ-01-FAIL.png`
- **Error context**:`playwright-output-main/.../error-context.md`
#### SKIP / did not run(15)
#### FS-PROJ-02 … FS-CONSOLE-01(18 条)— SKIP / did not run
- **输入**:未执行(serial worker 在 FS-PROJ-01 失败后中止)
- **实际输出**:Playwright 标记 `-` / `18 did not run`
- **判定**:SKIP(理由:上游 P0 FS-PROJ-01 FAIL,禁止冒充 PASS;账本未逐条写 SKIP 行)
- **未跑 ID**:FS-PROJ-02, FS-CHAT-01, FS-SQUAD-WF-01, FS-DOC-REV-01…07, FS-NONAUTH-01/02, FS-ASSIST-01, FS-SQUAD-FREE-01, FS-UPLOAD-01, FS-KB-01, FS-CTX-01, FS-CONSOLE-01
FS-DOC-REV-01…07, FS-NONAUTH-01/02, FS-ASSIST-01, FS-SQUAD-FREE-01, FS-UPLOAD-01, FS-KB-01, FS-CTX-01, FS-CONSOLE-01 — 理由:上游 P0 FS-SQUAD-WF-01 FAIL,serial 中止。
### 5.4 严重缺陷
1. **P0 阻塞**:立项成员角色 option 契约漂移 — 测试用 `editor`,UI 无此 value(仅 `author|reviewer|approver|viewer`)。阻断后续全部工作流 / PI / 审签用例。
2. **次要噪声**:IAM/立项阶段 console 出现多条 `404` / `403` 资源加载失败(见 `console-*.jsonl`);未单独判为套件 FAIL,但需后续收敛。
1. **P0 产品/运行态**:工作流编队任务「请编制用户初始需求收集表」在 UI 上挂起为 `data-chat-status="pending"` 超过 15 分钟未达终态(completed / failed / pending_author_confirmation 等)。阻断后续全部审签与 P1 用例。
2. (已修复,本轮验证)create-modal 角色仅 `author|reviewer|approver|viewer`;成员经立项后「项目成员」弹窗晋升;收口按钮为「完成并关闭」,不得匹配私密库「保存」。
## 六、自动化测试套件汇总 (Test Suite Execution)
| 套件 | 命令 / 入口 | 结果 |
| 套件 | 入口 | 结果 |
|---|---|---|
| Docker Playwright E2E | `bash web/scripts/run-full-system-browser-e2e.sh` | **FAIL**(exit 1;2 passed / 1 failed / 18 did not run) |
| 产品 PI 全链路 | (依赖 FS-PROJ 及之后用例) | **未运行**(不得记 PASS) |
| 工程 unittest | 本任务不适用产品 UI 例外之外的强制全量 | NOT REQUIRED(本轮以 UI 证据为主) |
| Docker Playwright E2E | `run-full-system-browser-e2e.sh` | **FAIL**(5 passed / 1 failed / 15 did not run) |
| 真实 PI 编队 | FS-SQUAD-WF-01 | **FAIL**(pending 挂起) |
| 产品审签全链路 | FS-DOC-REV-* 等 | **未运行** |
通过率(按 Playwright 已调度 21):2/21 ≈ 9.5%;按账本已记录 3:2 PASS / 1 FAIL。
通过率(21 调度):5/21 ≈ 23.8%。账本已记 6 条:5 PASS / 1 FAIL。
## 七、测试结论与后续优化建议 (Conclusion & Next Steps)
- **结论**:Docker 通道可用;headless(DISPLAY empty)下 Chromium 正常启动。全量多人协作验收 **未完成**,以 **FAIL** 收口。禁止将 2 条 IAM PASS 写成全套 PASS。
- **保留账号**(无密码):见下节与 `retained-accounts.json`。
- **下一步**:
1. 修正 `toggleCreateProjectMember` / FS-PROJ-01 角色值,与 `CreateProjectModal` option 对齐(成员宜用 `author`/`viewer`/`approver`/`reviewer`,勿用 `editor`)
2. 全量重跑 Docker 脚本(含真实 PI 等待)
3. 更新本报告与 `ui-results.json` 后再提交
- **结论**:Docker headless 通道可用;立项/成员晋升/工作流激活/闲聊已通。全量验收 **未完成**,以 **FAIL** 收口。禁止将 5 PASS 写成全套 PASS。
- **下一步**:排查 task `data-server-id=243` 为何长期 pending(调度器、PI runner、模型/配额、前端状态映射);修复后仅从 FS-SQUAD-WF-01 起或全量重跑。
- **保留账号**见下;项目 `E2E全量-20260926-muhu39da` 已创建。
## 保留账号(无密码)
| 角色 | username |
|---|---|
| author | `e2e26_author_muhtu9gc` |
| reviewer | `e2e26_reviewer_muhtu9gc` |
| approver | `e2e26_approver_muhtu9gc` |
| member | `e2e26_member_muhtu9gc` |
| guest | `e2e26_guest_muhtu9gc` |
| author | `e2e26_author_muhu39da` |
| reviewer | `e2e26_reviewer_muhu39da` |
| approver | `e2e26_approver_muhu39da` |
| member | `e2e26_member_muhu39da` |
| guest | `e2e26_guest_muhu39da` |
- 项目名意图:`E2E全量-20260926-muhtu9gc`(立项未成功创建,仅保留账号)
- Assets:`.doc/test-reports/assets/2026-09-26-full-system-browser-e2e/`
@@ -18,3 +18,23 @@
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:25:26.433Z"}
{"kind":"console","level":"warning","text":"Failed to load date stats: Error: fetchChatDates failed: HTTP 404\n at C_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7112)","ts":"2026-09-26T03:25:26.433Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:25:26.433Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:06.250Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:06.250Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:06.253Z"}
{"kind":"console","level":"warning","text":"[useChatWindow] fetch window failed, falling back to local cache/fallback Error: fetchChatWindow failed: HTTP 404\n at Jx (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:6112)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:436:2697","ts":"2026-09-26T03:30:06.253Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:06.253Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:06.257Z"}
{"kind":"console","level":"warning","text":"Failed to load date stats: Error: fetchChatDates failed: HTTP 404\n at C_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7112)","ts":"2026-09-26T03:30:06.257Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:06.257Z"}
{"kind":"console","level":"warning","text":"Failed to load category stats: Error: fetchChatCategories failed: HTTP 404\n at T_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7452)","ts":"2026-09-26T03:30:06.257Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:06.257Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:26.134Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:26.135Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:26.137Z"}
{"kind":"console","level":"warning","text":"[useChatWindow] fetch window failed, falling back to local cache/fallback Error: fetchChatWindow failed: HTTP 404\n at Jx (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:6112)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:436:2697","ts":"2026-09-26T03:32:26.138Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:26.138Z"}
{"kind":"console","level":"warning","text":"Failed to load category stats: Error: fetchChatCategories failed: HTTP 404\n at T_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7452)","ts":"2026-09-26T03:32:26.138Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:26.138Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:26.139Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:26.139Z"}
{"kind":"console","level":"warning","text":"Failed to load date stats: Error: fetchChatDates failed: HTTP 404\n at C_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7112)","ts":"2026-09-26T03:32:26.139Z"}
@@ -0,0 +1,13 @@
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:31.678Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:31.679Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:31.679Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:31.682Z"}
{"kind":"console","level":"warning","text":"Failed to load category stats: Error: fetchChatCategories failed: HTTP 404\n at T_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7452)","ts":"2026-09-26T03:32:31.683Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:31.683Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:31.683Z"}
{"kind":"console","level":"warning","text":"[useChatWindow] fetch window failed, falling back to local cache/fallback Error: fetchChatWindow failed: HTTP 404\n at Jx (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:6112)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:436:2697","ts":"2026-09-26T03:32:31.683Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:31.683Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:31.683Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:31.683Z"}
{"kind":"console","level":"warning","text":"Failed to load date stats: Error: fetchChatDates failed: HTTP 404\n at C_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7112)","ts":"2026-09-26T03:32:31.683Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:31.683Z"}
@@ -114,3 +114,119 @@
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:25:30.077Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:25:30.079Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:25:30.079Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.219Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.219Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.219Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:08.221Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.221Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:30:08.222Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:08.223Z"}
{"kind":"console","level":"warning","text":"Failed to load date stats: Error: fetchChatDates failed: HTTP 404\n at C_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7112)","ts":"2026-09-26T03:30:08.223Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:08.223Z"}
{"kind":"console","level":"warning","text":"[useChatWindow] fetch window failed, falling back to local cache/fallback Error: fetchChatWindow failed: HTTP 404\n at Jx (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:6112)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:436:2697","ts":"2026-09-26T03:30:08.223Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.223Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:08.223Z"}
{"kind":"console","level":"warning","text":"Failed to load category stats: Error: fetchChatCategories failed: HTTP 404\n at T_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7452)","ts":"2026-09-26T03:30:08.223Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.367Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.367Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.367Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.369Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:30:08.369Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.611Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.612Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.612Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.612Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:30:08.613Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.768Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.769Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.769Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.771Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:30:08.771Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.989Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.989Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.992Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:08.992Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:30:08.992Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.146Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.147Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.148Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.155Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:30:09.155Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.374Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.375Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.376Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.376Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:30:09.376Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.542Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.542Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.542Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.542Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:30:09.542Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.722Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.723Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.723Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.726Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:30:09.726Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.884Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.884Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.886Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:09.887Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:30:09.887Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.177Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.178Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.179Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.181Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:28.182Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:28.182Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:28.182Z"}
{"kind":"console","level":"warning","text":"Failed to load category stats: Error: fetchChatCategories failed: HTTP 404\n at T_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7452)","ts":"2026-09-26T03:32:28.182Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:28.182Z"}
{"kind":"console","level":"warning","text":"[useChatWindow] fetch window failed, falling back to local cache/fallback Error: fetchChatWindow failed: HTTP 404\n at Jx (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:6112)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:436:2697","ts":"2026-09-26T03:32:28.182Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.182Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:28.182Z"}
{"kind":"console","level":"warning","text":"Failed to load date stats: Error: fetchChatDates failed: HTTP 404\n at C_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7112)","ts":"2026-09-26T03:32:28.182Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.330Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.331Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.331Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.331Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:28.332Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.565Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.565Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.567Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.567Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:28.568Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.724Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.724Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.724Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.725Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:28.725Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.954Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.954Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.954Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:28.956Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:28.956Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.108Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.110Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.110Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.112Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:29.112Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.337Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.338Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.338Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.338Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:29.338Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.498Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.498Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.498Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.499Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:29.500Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.716Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.716Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.717Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.717Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:29.717Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.875Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.876Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.876Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:29.876Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:29.876Z"}
@@ -38,3 +38,29 @@
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:25:55.478Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:26:00.476Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:26:00.477Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:10.369Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:10.369Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:10.369Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:10.371Z"}
{"kind":"console","level":"warning","text":"[useChatWindow] fetch window failed, falling back to local cache/fallback Error: fetchChatWindow failed: HTTP 404\n at Jx (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:6112)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:436:2697","ts":"2026-09-26T03:30:10.371Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:10.371Z"}
{"kind":"console","level":"warning","text":"Failed to load category stats: Error: fetchChatCategories failed: HTTP 404\n at T_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7452)","ts":"2026-09-26T03:30:10.372Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:10.372Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:10.372Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:30:10.372Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:30:10.373Z"}
{"kind":"console","level":"warning","text":"Failed to load date stats: Error: fetchChatDates failed: HTTP 404\n at C_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7112)","ts":"2026-09-26T03:30:10.373Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:30:10.374Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:30.260Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:30.261Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:30.261Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:30.264Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:30.264Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:30.264Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:30.264Z"}
{"kind":"console","level":"warning","text":"[useChatWindow] fetch window failed, falling back to local cache/fallback Error: fetchChatWindow failed: HTTP 404\n at Jx (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:6112)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:436:2697","ts":"2026-09-26T03:32:30.264Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:30.264Z"}
{"kind":"console","level":"warning","text":"Failed to load category stats: Error: fetchChatCategories failed: HTTP 404\n at T_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7452)","ts":"2026-09-26T03:32:30.264Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:30.265Z"}
{"kind":"console","level":"warning","text":"Failed to load date stats: Error: fetchChatDates failed: HTTP 404\n at C_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7112)","ts":"2026-09-26T03:32:30.266Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:30.266Z"}
@@ -0,0 +1,13 @@
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:31.045Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:31.045Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:31.045Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:31.046Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:31.046Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:31.049Z"}
{"kind":"console","level":"warning","text":"Failed to load date stats: Error: fetchChatDates failed: HTTP 404\n at C_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7112)","ts":"2026-09-26T03:32:31.050Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:31.050Z"}
{"kind":"console","level":"warning","text":"[useChatWindow] fetch window failed, falling back to local cache/fallback Error: fetchChatWindow failed: HTTP 404\n at Jx (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:6112)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:436:2697","ts":"2026-09-26T03:32:31.050Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:31.050Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:31.050Z"}
{"kind":"console","level":"warning","text":"Failed to load category stats: Error: fetchChatCategories failed: HTTP 404\n at T_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7452)","ts":"2026-09-26T03:32:31.050Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:31.050Z"}
@@ -0,0 +1,13 @@
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:32.029Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:32.029Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:32.032Z"}
{"kind":"console","level":"warning","text":"[useChatWindow] fetch window failed, falling back to local cache/fallback Error: fetchChatWindow failed: HTTP 404\n at Jx (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:6112)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:436:2697","ts":"2026-09-26T03:32:32.032Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:32.032Z"}
{"kind":"console","level":"warning","text":"[deliverables] 工作流受控文档同步失败: Error: list project workflow documents failed: 403\n at sm (http://127.0.0.1:8080/assets/index-I90hqfds.js:55:88607)\n at async http://127.0.0.1:8080/assets/index-I90hqfds.js:463:3951","ts":"2026-09-26T03:32:32.032Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:32.032Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:32.032Z"}
{"kind":"console","level":"warning","text":"Failed to load category stats: Error: fetchChatCategories failed: HTTP 404\n at T_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7452)","ts":"2026-09-26T03:32:32.033Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:32.033Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 403 (Forbidden)","ts":"2026-09-26T03:32:32.033Z"}
{"kind":"console","level":"error","text":"Failed to load resource: the server responded with a status of 404 (Not Found)","ts":"2026-09-26T03:32:32.033Z"}
{"kind":"console","level":"warning","text":"Failed to load date stats: Error: fetchChatDates failed: HTTP 404\n at C_ (http://127.0.0.1:8080/assets/index-I90hqfds.js:54:7112)","ts":"2026-09-26T03:32:32.033Z"}
@@ -1,18 +1,18 @@
{
"note": "Passwords intentionally omitted. Accounts retained after E2E by design.",
"projectName": "E2E全量-20260926-muhtu9gc",
"projectName": "E2E全量-20260926-muhu39da",
"usernames": [
"e2e26_author_muhtu9gc",
"e2e26_reviewer_muhtu9gc",
"e2e26_approver_muhtu9gc",
"e2e26_member_muhtu9gc",
"e2e26_guest_muhtu9gc"
"e2e26_author_muhu39da",
"e2e26_reviewer_muhu39da",
"e2e26_approver_muhu39da",
"e2e26_member_muhu39da",
"e2e26_guest_muhu39da"
],
"roles": {
"author": "e2e26_author_muhtu9gc",
"reviewer": "e2e26_reviewer_muhtu9gc",
"approver": "e2e26_approver_muhtu9gc",
"member": "e2e26_member_muhtu9gc",
"guest": "e2e26_guest_muhtu9gc"
"author": "e2e26_author_muhu39da",
"reviewer": "e2e26_reviewer_muhu39da",
"approver": "e2e26_approver_muhu39da",
"member": "e2e26_member_muhu39da",
"guest": "e2e26_guest_muhu39da"
}
}
@@ -1,29 +1,29 @@
{
"startedAt": "2026-09-26T03:25:26.016Z",
"startedAt": "2026-09-26T03:32:25.804Z",
"baseURL": "http://127.0.0.1:8080",
"display": "",
"headedHint": false,
"projectName": "E2E全量-20260926-muhtu9gc",
"projectName": "E2E全量-20260926-muhu39da",
"users": {
"author": {
"username": "e2e26_author_muhtu9gc",
"display": "E2E编制-muhtu9gc"
"username": "e2e26_author_muhu39da",
"display": "E2E编制-muhu39da"
},
"reviewer": {
"username": "e2e26_reviewer_muhtu9gc",
"display": "E2E审核-muhtu9gc"
"username": "e2e26_reviewer_muhu39da",
"display": "E2E审核-muhu39da"
},
"approver": {
"username": "e2e26_approver_muhtu9gc",
"display": "E2E批准-muhtu9gc"
"username": "e2e26_approver_muhu39da",
"display": "E2E批准-muhu39da"
},
"member": {
"username": "e2e26_member_muhtu9gc",
"display": "E2E成员-muhtu9gc"
"username": "e2e26_member_muhu39da",
"display": "E2E成员-muhu39da"
},
"guest": {
"username": "e2e26_guest_muhtu9gc",
"display": "E2E访客-muhtu9gc"
"username": "e2e26_guest_muhu39da",
"display": "E2E访客-muhu39da"
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

@@ -5,17 +5,17 @@
"priority": "P0",
"input": "admin console → 开通受控员工账号 ×5",
"expected": "author/reviewer/approver/member/guest created",
"actual": "e2e26_author_muhtu9gc,e2e26_reviewer_muhtu9gc,e2e26_approver_muhtu9gc,e2e26_member_muhtu9gc,e2e26_guest_muhtu9gc",
"actual": "e2e26_author_muhu39da,e2e26_reviewer_muhu39da,e2e26_approver_muhu39da,e2e26_member_muhu39da,e2e26_guest_muhu39da",
"verdict": "PASS",
"durationMs": 2008,
"durationMs": 2052,
"console_errors": [
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)"
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)"
]
},
"FS-IAM-02": {
@@ -26,17 +26,17 @@
"expected": "all reach workbench after reset",
"actual": "5/5 password changes OK",
"verdict": "PASS",
"durationMs": 1998,
"durationMs": 2064,
"console_errors": [
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
@@ -79,11 +79,32 @@
"id": "FS-PROJ-01",
"name": "create project + members",
"priority": "P0",
"input": "create project",
"expected": "project created",
"actual": "TimeoutError: locator.selectOption: Timeout 30000ms exceeded.\nCall log:\n\u001b[2m - waiting for getByText('发起医疗器械新项目立项', { exact: true }).locator('xpath=ancestor::div[contains(@style,\"position: fixed\")][1]').getByText('E2E成员-muhtu9gc', { exact: true }).first().locator('xpath=ancestor::div[contains(@style,\"justify-content: space-between\")][1]').locator('select')\u001b[22m\n\u001b[2m - locator resolved to <select>…</select>\u001b[22m\n\u001b[2m - attempting select option action\u001b[22m\n\u001b[2m 2 × waiting for element to be visible and enabled\u001b[22m\n\u001b[2m - did not find some options\u001b[22m\n\u001b[2m - retrying select option action\u001b[22m\n\u001b[2m - waiting 20ms\u001b[22m\n\u001b[2m 2 × waiting for element to be visible and enabled\u001b[22m\n\u001b[2m - did not find some options\u001b[22m\n\u001b[2m - retrying select option action\u001b[22m\n\u001b[2m - waiting 100ms\u001b[22m\n\u001b[2m 60 × waiting for element to be visible and enabled\u001b[22m\n\u001b[2m - did not find some options\u001b[22m\n\u001b[2m - retrying select option action\u001b[22m\n\u001b[2m - waiting 500ms\u001b[22m\n",
"verdict": "FAIL",
"durationMs": 30515,
"input": "project=E2E全量-20260926-muhu39da; reviewer/approver duties + member promote(+guest)",
"expected": "banner shows project; member is project_role=member",
"actual": "created; guestListed=true; member promoted",
"verdict": "PASS",
"durationMs": 790,
"console_errors": [
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)"
]
},
"FS-PROJ-02": {
"id": "FS-PROJ-02",
"name": "activate workflow duties",
"priority": "P0",
"input": "配置工作流 → 纳入审批 → 三权指派 → 确认激活",
"expected": "运行中",
"actual": "workflow activated",
"verdict": "PASS",
"durationMs": 628,
"console_errors": [
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
@@ -93,14 +114,50 @@
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)"
]
},
"FS-CHAT-01": {
"id": "FS-CHAT-01",
"name": "casual dialogue",
"priority": "P0",
"input": "E2E闲聊:请用一句话确认项目通道可用,不要生成受控文档。",
"expected": "assistant reply visible",
"actual": "assistant bubble non-empty",
"verdict": "PASS",
"durationMs": 344,
"console_errors": [
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)"
]
},
"FS-SQUAD-WF-01": {
"id": "FS-SQUAD-WF-01",
"name": "squad workflow doc generation",
"priority": "P0",
"input": "请编制用户初始需求收集表",
"expected": "PI squad completes",
"actual": "Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoHaveAttribute\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m failed\n\nLocator: locator('[data-chat-role=\"user\"]').filter({ hasText: '请编制用户初始需求收集表' }).last().locator('xpath=ancestor::*[@data-index][1]/following-sibling::*[@data-index][1]//*[@data-chat-role=\"assistant\"]')\nExpected pattern: \u001b[32m/^(completed|pending_author_confirmation|failed|cancelled|quality_failed|blocked_pending_governance)$/\u001b[39m\nReceived string: \u001b[31m\"pending\"\u001b[39m\n\nCall log:\n\u001b[2m - Expect \"toHaveAttribute\" locator('[data-chat-role=\"user\"]').filter({ hasText: '请编制用户初始需求收集表' }).last().locator('xpath=ancestor::*[@data-index][1]/following-sibling::*[@data-index][1]//*[@data-chat-role=\"assistant\"]') with timeout 1200000ms\u001b[22m\n\u001b[2m - waiting for locator('[data-chat-role=\"user\"]').filter({ hasText: '请编制用户初始需求收集表' }).last().locator('xpath=ancestor::*[@data-index][1]/following-sibling::*[@data-index][1]//*[@data-chat-role=\"assistant\"]')\u001b[22m\n\u001b[2m 540 × locator resolved to <div data-chat-role=\"assistant\" data-chat-status=\"pending\" id=\"chat-anchor-ast-1790393552123\">…</div>\u001b[22m\n\u001b[2m - unexpected value \"pending\"\u001b[22m\n\u001b[2m 1252 × locator resolved to <div id=\"chat-anchor-243\" data-server-id=\"243\" data-category=\"task\" data-chat-role=\"assistant\" data-chat-status=\"pending\">…</div>\u001b[22m\n\u001b[2m - unexpected value \"pending\"\u001b[22m\n\u001b[2m - Test ended.\u001b[22m\n",
"verdict": "FAIL",
"durationMs": 900102,
"console_errors": [
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 403 (Forbidden)",
"[error] Failed to load resource: the server responded with a status of 404 (Not Found)"
],
"notes": "真实 PI 超时/失败记 FAIL,不伪装 PASS"
}
}
+60 -7
View File
@@ -250,7 +250,8 @@ async function adminCreateUser(
async function toggleCreateProjectMember(
projectModal: ReturnType<Page['locator']>,
displayName: string,
role?: 'reviewer' | 'viewer' | 'editor',
/** CreateProjectModal options: author|reviewer|approver|viewer (no editor). */
role?: 'author' | 'reviewer' | 'approver' | 'viewer',
) {
const memberName = projectModal.getByText(displayName, { exact: true }).first();
await expect(memberName).toBeVisible({ timeout: 15_000 });
@@ -264,6 +265,41 @@ async function toggleCreateProjectMember(
await memberRole.selectOption(role);
}
/** After create, promote a create-modal viewer to project_role=member (editable, no doc duty). */
async function promoteToProjectMember(page: Page, displayName: string) {
// LeftRail: title="管理当前项目成员与职责分配" (avoid matching vault "保存" buttons).
const openBtn = page.locator('button[title="管理当前项目成员与职责分配"]').first();
await expect(openBtn).toBeVisible({ timeout: 15_000 });
await openBtn.click();
const heading = page.getByText('项目成员与职责权限管理', { exact: true });
await expect(heading).toBeVisible({ timeout: 20_000 });
const modal = heading.locator('xpath=ancestor::div[contains(@style,"position: fixed")][1]');
// Row is flex space-between with the display name + a role <select>.
const nameEl = modal.getByText(displayName, { exact: true }).first();
await expect(nameEl).toBeVisible({ timeout: 15_000 });
const row = nameEl.locator(
'xpath=ancestor::div[contains(@style,"justify-content: space-between")][1]',
);
const roleSelect = row.locator('select').first();
await expect(roleSelect).toBeVisible({ timeout: 15_000 });
const opts = await roleSelect.locator('option').evaluateAll((nodes) =>
nodes.map((n) => ({
value: (n as HTMLOptionElement).value,
text: (n.textContent || '').trim(),
})),
);
const memberOpt = opts.find((o) => o.value === 'member' || /^项目成员/.test(o.text));
if (!memberOpt) {
fail(`promoteToProjectMember: no member option in ${JSON.stringify(opts)}`);
}
// onChange persists immediately — no separate save; do NOT match vault「保存」.
await roleSelect.selectOption(memberOpt.value);
await expect(roleSelect).toHaveValue('member');
await expect(row.getByText('项目成员 (Member)', { exact: true })).toBeVisible({ timeout: 15_000 });
await modal.getByRole('button', { name: '完成并关闭' }).click();
await expect(heading).toBeHidden({ timeout: 15_000 });
}
async function goToWorkflowDutyStep(page: Page) {
const approval = page.locator('label', { hasText: '纳入人工审批' }).first();
const selectHint = page.getByText('选择要激活的已发布工作流版本');
@@ -617,9 +653,9 @@ test.describe.serial('full-system browser multi-user E2E', () => {
if ((await desc.count()) === 0) fail('project form missing description');
await desc.fill('全系统浏览器 E2E:骨科超声吸引止血,覆盖多人协作与审签链路。');
await toggleCreateProjectMember(modal, USERS.reviewer.display, 'reviewer');
await toggleCreateProjectMember(modal, USERS.approver.display, 'viewer');
await toggleCreateProjectMember(modal, USERS.member.display, 'editor');
// guest optional — if listed, add as viewer
await toggleCreateProjectMember(modal, USERS.approver.display, 'approver');
// Plain collaborator: create-modal has no "member" option — select (defaults viewer) then promote.
await toggleCreateProjectMember(modal, USERS.member.display);
const guestVisible = await modal.getByText(USERS.guest.display, { exact: true }).count();
if (guestVisible > 0) {
await toggleCreateProjectMember(modal, USERS.guest.display, 'viewer');
@@ -628,14 +664,31 @@ test.describe.serial('full-system browser multi-user E2E', () => {
await modal.getByRole('button', { name: /确认立项/ }).click();
await expect(heading).toBeHidden({ timeout: 15_000 });
await expect(currentProjectBannerName(page, PROJECT_NAME)).toBeVisible({ timeout: 30_000 });
try {
await promoteToProjectMember(page, USERS.member.display);
} catch (promoteErr) {
record({
id: 'FS-PROJ-01b',
name: 'promote member role',
priority: 'P0',
input: `promote ${USERS.member.display} to project member`,
expected: 'project_role=member',
actual: String(promoteErr),
verdict: 'FAIL',
durationMs: Date.now() - t0,
console_errors: consoleErrorsFor(label),
notes: 'create-modal 仅有 author/reviewer/approver/viewer;成员级可编辑需立项后改派',
});
throw promoteErr;
}
await shot(page, 'FS-PROJ-01-created');
record({
id: 'FS-PROJ-01',
name: 'create project + members',
priority: 'P0',
input: `project=${PROJECT_NAME}; members reviewer/approver/member(+guest)`,
expected: 'banner shows project; members selected',
actual: `created; guestListed=${guestVisible > 0}`,
input: `project=${PROJECT_NAME}; reviewer/approver duties + member promote(+guest)`,
expected: 'banner shows project; member is project_role=member',
actual: `created; guestListed=${guestVisible > 0}; member promoted`,
verdict: 'PASS',
durationMs: Date.now() - t0,
console_errors: consoleErrorsFor(label),