diff --git a/.doc/ops/CURRENT.md b/.doc/ops/CURRENT.md
index b4c327c6..0fdc5ac3 100644
--- a/.doc/ops/CURRENT.md
+++ b/.doc/ops/CURRENT.md
@@ -13,7 +13,7 @@
| owner | task | branch | worktree | mutex | status |
|-------|------|--------|----------|-------|--------|
-| Cursor | 2026-09-17-initial-load-perf-u2 | feature/initial-load-perf-u2 | - | web + static-delivery | in_progress |
+| Cursor | 2026-09-17-initial-load-perf-u2 | feature/initial-load-perf-u2 | - | web + static-delivery | done |
| Codex | 2026-09-17-initial-load-performance-plan | feature/initial-load-performance-plan | .worktrees/feature-initial-load-performance-plan | loading-performance-audit | done |
| Kimi | 2026-09-17-system-admin-console | feature/system-admin-console | - | web + sysadmin | done |
| Cursor-Auto | 2026-09-17-engineering-dashboard | feature/engineering-dashboard | .worktrees/feature-engineering-dashboard | engineering-dashboard | done |
@@ -125,7 +125,7 @@
| holder | phase | since | scope | queue |
|--------|-------|-------|-------|-------|
-| Cursor | merging | 2026-09-17T08:08:45Z | initial-load-perf-u2(字体/压缩/静态缓存) | - |
+| - | idle | - | - | - |
**phase**: `idle` | `merging` | `smoke` | `e2e`
diff --git a/.doc/ops/short-term/2026-09-17-initial-load-perf-u2.md b/.doc/ops/short-term/2026-09-17-initial-load-perf-u2.md
index 02b51e33..66c8188f 100644
--- a/.doc/ops/short-term/2026-09-17-initial-load-perf-u2.md
+++ b/.doc/ops/short-term/2026-09-17-initial-load-perf-u2.md
@@ -1,6 +1,6 @@
---
title: "首次加载 U2:字体自托管与静态资源交付"
-status: in_progress
+status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor
@@ -35,19 +35,19 @@ mutex: web + static-delivery
2. [x] 自托管字体 + 移除外链
3. [x] 预压缩脚本接入 build
4. [x] Go 静态交付修复
-5. [ ] 测试与 rebuild 验收
-6. [ ] 测试报告与文档同步
+5. [x] 测试与 rebuild 验收
+6. [x] 测试报告与文档同步
## 验收标准
-- [ ] 登录页无 `fonts.googleapis.com` / `fonts.gstatic.com` 请求
-- [ ] 主 JS 响应带 `Content-Encoding: br` 或 `gzip`,体积显著下降
-- [ ] `/assets/missing.js` → 404 且非 HTML
-- [ ] HTML `Cache-Control: no-cache`;哈希资源 `immutable`
-- [ ] SSE / API 缓存行为未回归
+- [x] 登录页无 `fonts.googleapis.com` / `fonts.gstatic.com` 请求
+- [x] 主 JS 响应带 `Content-Encoding: br` 或 `gzip`,体积显著下降
+- [x] `/assets/missing.js` → 404 且非 HTML
+- [x] HTML `Cache-Control: no-cache`;哈希资源 `immutable`
+- [x] SSE / API 缓存行为未回归
## 相关链接
- 方案: [../../remediation/2026-09-17-initial-load-performance-plan.md](../../remediation/2026-09-17-initial-load-performance-plan.md)
- 审计: [../../audit/2026-09-17-initial-load-performance-audit.md](../../audit/2026-09-17-initial-load-performance-audit.md)
-- Test report: (验收后补)
+- Test report: [../../test-reports/2026-09-17-initial-load-perf-u2-test-report.md](../../test-reports/2026-09-17-initial-load-perf-u2-test-report.md)
diff --git a/.doc/remediation/2026-09-17-initial-load-performance-plan.md b/.doc/remediation/2026-09-17-initial-load-performance-plan.md
index ef66f118..17175ccb 100644
--- a/.doc/remediation/2026-09-17-initial-load-performance-plan.md
+++ b/.doc/remediation/2026-09-17-initial-load-performance-plan.md
@@ -117,7 +117,7 @@ sequenceDiagram
**Verification:** 形成基线报告,能回答耗时在哪一阶段,并确认性能指标可重复。登录态测量缺失不得用未登录测试代替。
-### U2. 修复字体与静态资源交付(P0,约 0.5–1 天)
+### U2. 修复字体与静态资源交付(P0,约 0.5–1 天) — **done 2026-09-17**
**Dependencies:** U1 的未登录基线;**Requirements:** R1、R5、R6;**Files:** `web/index.html`、`web/src/styles/index.css`、`web/vite.config.ts`、`internal/server/server.go`、新增 `internal/server/static_assets_test.go`;必要时实际 Docker 构建文件。
@@ -127,6 +127,8 @@ sequenceDiagram
**Verification:** curl 与浏览器确认真正压缩响应,JS 传输量下降;HTML 不被长期缓存。此单元不宣称已达到拆包预算。
+**交付证据:** [U2 测试报告](../test-reports/2026-09-17-initial-load-perf-u2-test-report.md);`dev` merge `feature/initial-load-perf-u2`;8080 主 JS br 传输 623,898 B;登录冷缓存可见 ~205 ms。U1/U3–U7 仍未完成。
+
### U3. 登录壳与重功能按需加载(P0,约 1–2 天)
**Dependencies:** U1;可与 U2 分开开发,合入仍串行。**Requirements:** R1、R2、R5;**Files:** `web/src/main.tsx`、`web/src/App.tsx`、新增认证壳组件、`web/src/components/doc/preview/FilePreviewPanel.tsx`、`web/src/features/replyExport/download.ts`、`web/src/engine/docxRenderer.ts`、`web/src/components/doc/blocks/MermaidBlockView.tsx`、U1 浏览器用例。
diff --git a/.doc/status/FEATURE-MATRIX.md b/.doc/status/FEATURE-MATRIX.md
index c834496f..1a86d3a1 100644
--- a/.doc/status/FEATURE-MATRIX.md
+++ b/.doc/status/FEATURE-MATRIX.md
@@ -93,4 +93,4 @@
## 2026-09-17 首次加载性能专项
-首次加载与重启首访性能优化:**planned**(不改变现有功能done/发布门禁结论)。[审计](../audit/2026-09-17-initial-load-performance-audit.md) · [方案](../remediation/2026-09-17-initial-load-performance-plan.md) · [诊断测量](../test-reports/2026-09-17-initial-load-performance-baseline.md)。资源/字体瓶颈已测;用户三入口重启现场及登录态基线待U1/U7,未实现或验收优化。mutex `loading-performance-audit`。
+首次加载与重启首访性能优化:**partial**(U2 静态交付已验收;不改变现有功能 done/发布门禁结论)。[审计](../audit/2026-09-17-initial-load-performance-audit.md) · [方案](../remediation/2026-09-17-initial-load-performance-plan.md) · [U2 报告](../test-reports/2026-09-17-initial-load-perf-u2-test-report.md)。U2:自托管字体 + br/gzip + assets 404;主 JS 传输 2.82 MB → ~624 KB。U1/U3–U7 未完成。mutex `web + static-delivery`(U2 done)/ `loading-performance-audit`。
diff --git a/.doc/test-reports/2026-09-17-initial-load-perf-u2-test-report.md b/.doc/test-reports/2026-09-17-initial-load-perf-u2-test-report.md
new file mode 100644
index 00000000..e2465c9e
--- /dev/null
+++ b/.doc/test-reports/2026-09-17-initial-load-perf-u2-test-report.md
@@ -0,0 +1,113 @@
+# 首次加载 U2:字体自托管与静态资源交付 测试报告
+
+## 一、 测试背景 (Background)
+
+诊断确认 8080 登录页下载约 2.82 MB 未压缩 JS,且 Google Fonts 外链 CSS 可阻塞首屏;Go `serveSPA` 无压缩协商、无明确缓存头,且缺失 `/assets` 会回退 HTML。本轮实施 U2(自托管字体、构建期预压缩、静态交付协商与 404 修复),不包含 U3 拆包。
+
+## 二、 测试目标 (Test Objectives)
+
+- 登录页无 `fonts.googleapis.com` / `fonts.gstatic.com` 请求;阻断该域名仍可出现登录表单
+- 主 JS 响应带 `Content-Encoding: br` 或 `gzip`,传输体积显著下降
+- `/assets/missing.js` → 404 且 body 非 HTML
+- HTML `Cache-Control: no-cache`;`/assets`/`/fonts` `immutable`;API 无 public 长缓存
+- 单元测试与 `go test -short` / `npm test` 通过
+
+## 三、 测试方案与环境 (Test Plan & Environment)
+
+- OS:Linux;Go 1.27.1;dev 容器 `shuimu-agent-app-dev`(镜像 `agent-dev-app@sha256:2d74fe18…`)
+- 入口:`http://127.0.0.1:8080`(构建产物)
+- 层级:Go 单元测试(`static_assets_test.go`)、前端断言、curl 协商验收、Playwright Docker(`mcr.microsoft.com/playwright:v1.63.0-noble`)浏览器探针
+- 代码:`dev@bc01781`(merge `feature/initial-load-perf-u2`);无缓存重建后镜像含 `/fonts` 与 `.br/.gz`
+
+## 四、 预期结果 (Expected Results)
+
+| 场景 | 预期 |
+|------|------|
+| `Accept-Encoding: gzip, br` | `Content-Encoding: br`,主 JS ~624 KiB |
+| 仅 `gzip` | `Content-Encoding: gzip` |
+| identity / `gzip;q=0` | 无 `Content-Encoding`,原始体积 |
+| `/assets/missing-hash.js` | 404,非 HTML |
+| HTML / SPA fallback | `Cache-Control: no-cache` |
+| 字体域名阻断 | 登录输入框仍可见 |
+| API 未认证 | 401,无 `immutable` |
+
+## 五、 实际测试结果与判定 (Actual Results & Evaluation)
+
+### 5.1 单元测试
+
+- **Input**: `go test -short ./internal/server/ -run 'TestStaticAssets_|TestParseAcceptEncoding'`
+- **Actual**: `ok`
+- **Verdict**: PASS
+- **Duration**: ~0.66 s
+
+- **Input**: `npx tsx --test src/styles/noExternalFonts.test.ts`;`npm test`
+- **Actual**: 字体断言 2/2 PASS;前端套件 380 + vitest 32 PASS
+- **Verdict**: PASS
+
+### 5.2 curl 协商(8080,无缓存重建后)
+
+证据:`.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/after-curl-nocache.txt`
+
+| 检查项 | 实际 | 判定 |
+|--------|------|------|
+| HTML | `Cache-Control: no-cache`,`Vary: Accept-Encoding`,无 Google Fonts | PASS |
+| JS + `gzip, br` | `Content-Encoding: br`,下载 **623,898 B**(原 2,820,055 B,−77.9%) | PASS |
+| JS + `gzip` | `Content-Encoding: gzip`,`immutable` | PASS |
+| JS identity | 无 encoding,`Content-Length: 2820055`,仍有 `Vary` | PASS |
+| `/assets/missing-hash.js` | **404** `404 page not found` | PASS |
+| `/fonts/inter-v20-latin.woff2` | 200,`immutable`,48256 B,无 Content-Encoding | PASS |
+| `/sessions/demo` | 200 + index,`no-cache` | PASS |
+| `/api/v1/chat/sessions` | 401 JSON,无 immutable | PASS |
+
+### 5.3 浏览器探针
+
+证据:`assets/2026-09-17-initial-load-perf-u2/browser-u2.json`
+
+| 场景 | 登录可见 | transferBytes | 外链字体请求 | 判定 |
+|------|----------:|------------:|-------------:|------|
+| login-cold | **205 ms** | **681,964** | 0 | PASS |
+| login-font-domain-blocked | **213 ms** | 681,964 | 0 | PASS |
+
+对比诊断 before(同机冷缓存登录页):可见 ~662 ms,transferSize 2,857,761 B;主 JS 未压缩 2,820,055 B。本轮未登录首屏传输量下降约 **76%**。
+
+主 JS Resource Timing:`transferSize=624198`,`decodedBodySize=2820055`(确认浏览器实际收到 br 变体)。
+
+### 5.4 重启时间线(U7 起点证据,非 U7 完成)
+
+| 事件 | 时刻 (UTC) |
+|------|------------|
+| 容器 StartedAt | 2026-09-17T08:22:48.548Z |
+| goose no migrations / kb online | 08:22:48.660–.676 |
+| 日志「监听地址」 | ~08:22:48.7 |
+| health=200 | ≤08:22:50(重建后首次探测) |
+
+app restart → listen ≈ **150–200 ms**(DB 已就绪、无迁移)。**不能**据此宣称用户「整机重启十几秒」已解决。
+
+首次 `env-service.sh dev rebuild` 曾因并行 Agent 切走工作树导致镜像装入旧 `web/`;随后在 `dev` 上 `docker compose build --no-cache app` 后验收通过。证据见 `rebuild-nocache-log.txt`。
+
+### 5.5 SSE
+
+未认证 `GET /api/v1/chat/stream` 立即 401 JSON;静态压缩路径不触及 API/SSE。PASS(静态层无缓冲回归迹象)。
+
+## 六、 自动化测试套件汇总 (Test Suite Execution)
+
+```text
+go test -short ./internal/server/ -run 'TestStaticAssets_|TestParseAcceptEncoding' → ok
+npm test (web) → 380 + 32 PASS
+npm run build → precompress 49 .br / 49 .gz
+```
+
+未在本报告将 stub 输出当作交付证据;浏览器与 curl 均打真实 8080 容器。
+
+## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
+
+- **U2 达到合并/dev 验收标准**:字体去阻塞、压缩协商、缓存头、assets 404 均有真实证据。
+- **不宣称** Success Criteria 全表达标(U1 登录态套件未建;U3 拆包未做,首屏 JS 解码体仍约 2.8 MB)。
+- 后续:U3 懒加载;U1/U7 补齐重启与登录态预算;并行 Agent 占用主仓时,合入容器重建须 `--no-cache` 或锁定工作树以免 BuildKit 读到脏上下文。
+
+### 提交与环境
+
+- 分支:`feature/initial-load-perf-u2` → 已 `merge --no-ff` 入 `dev@bc01781`
+- 镜像:`agent-dev-app` sha256:2d74fe184585ec0d0d24a051cd6bbc0cfb5b2ef050a376a32027c8e442703cd1
+- 资源:`/assets/index-Bu0CqZB_.js` + `.br`
+- 未推送、未晋升 test/main
diff --git a/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/after-curl-nocache.txt b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/after-curl-nocache.txt
new file mode 100644
index 00000000..935c9d81
--- /dev/null
+++ b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/after-curl-nocache.txt
@@ -0,0 +1,115 @@
+=== AFTER nocache rebuild curl 2026-09-17T08:23:03Z ===
+--- HTML headers ---
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Cache-Control: no-cache
+Content-Length: 715
+Content-Type: text/html; charset=utf-8
+Last-Modified: Thu, 17 Sep 2026 08:21:43 GMT
+Vary: Accept-Encoding
+Date: Thu, 17 Sep 2026 08:23:03 GMT
+
+--- HTML body (identity) ---
+
+
+
+
+
+
+
+ 水木东方 · 医疗器械现代 AI 协同工作台
+
+
+
+
+
+
+JS=/assets/index-Bu0CqZB_.js
+--- JS Accept-Encoding: gzip, br ---
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Cache-Control: public, max-age=31536000, immutable
+Content-Encoding: br
+Content-Type: text/javascript; charset=utf-8
+Last-Modified: Thu, 17 Sep 2026 08:21:43 GMT
+Vary: Accept-Encoding
+Date: Thu, 17 Sep 2026 08:23:03 GMT
+
+--- JS gzip only ---
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Cache-Control: public, max-age=31536000, immutable
+Content-Encoding: gzip
+Content-Type: text/javascript; charset=utf-8
+Last-Modified: Thu, 17 Sep 2026 08:21:43 GMT
+Vary: Accept-Encoding
+Date: Thu, 17 Sep 2026 08:23:03 GMT
+
+--- JS identity ---
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Cache-Control: public, max-age=31536000, immutable
+Content-Length: 2820055
+Content-Type: text/javascript; charset=utf-8
+Last-Modified: Thu, 17 Sep 2026 08:21:43 GMT
+Vary: Accept-Encoding
+Date: Thu, 17 Sep 2026 08:23:03 GMT
+
+--- missing asset ---
+HTTP/1.1 404 Not Found
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Content-Type: text/plain; charset=utf-8
+X-Content-Type-Options: nosniff
+Date: Thu, 17 Sep 2026 08:23:03 GMT
+Content-Length: 19
+
+body: 404 page not found
+
+--- font ---
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Cache-Control: public, max-age=31536000, immutable
+Content-Length: 48256
+Content-Type: font/woff2
+Last-Modified: Thu, 17 Sep 2026 08:21:42 GMT
+Date: Thu, 17 Sep 2026 08:23:03 GMT
+
+--- spa ---
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Cache-Control: no-cache
+Content-Length: 715
+Content-Type: text/html; charset=utf-8
+Last-Modified: Thu, 17 Sep 2026 08:21:43 GMT
+Vary: Accept-Encoding
+Date: Thu, 17 Sep 2026 08:23:03 GMT
+
+--- api ---
+HTTP/1.1 401 Unauthorized
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Content-Type: application/json; charset=utf-8
+Date: Thu, 17 Sep 2026 08:23:03 GMT
+Content-Length: 62
+
+--- google fonts domain in html? ---
+NONE
diff --git a/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/after-curl.txt b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/after-curl.txt
new file mode 100644
index 00000000..196c475b
--- /dev/null
+++ b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/after-curl.txt
@@ -0,0 +1,119 @@
+=== AFTER rebuild curl ===
+--- HTML ---
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Content-Length: 892
+Content-Type: text/html; charset=utf-8
+Last-Modified: Thu, 17 Sep 2026 07:00:36 GMT
+Date: Thu, 17 Sep 2026 08:19:24 GMT
+
+--- HTML body head ---
+
+
+
+
+
+
+
+ 水木东方 · 医疗器械现代 AI 协同工作台
+
+
+
+
+
+
+
+
+
+
+JS=/assets/index-BLnmtk_3.js
+--- JS br ---
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Content-Length: 2820055
+Content-Type: text/javascript; charset=utf-8
+Last-Modified: Thu, 17 Sep 2026 07:00:36 GMT
+Date: Thu, 17 Sep 2026 08:19:24 GMT
+
+--- JS gzip only ---
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Content-Length: 2820055
+Content-Type: text/javascript; charset=utf-8
+Last-Modified: Thu, 17 Sep 2026 07:00:36 GMT
+Date: Thu, 17 Sep 2026 08:19:24 GMT
+
+--- JS identity ---
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Content-Length: 2820055
+Content-Type: text/javascript; charset=utf-8
+Last-Modified: Thu, 17 Sep 2026 07:00:36 GMT
+Date: Thu, 17 Sep 2026 08:19:24 GMT
+
+--- JS gzip;q=0 ---
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Content-Length: 2820055
+Content-Type: text/javascript; charset=utf-8
+Last-Modified: Thu, 17 Sep 2026 07:00:36 GMT
+Date: Thu, 17 Sep 2026 08:19:24 GMT
+
+--- missing asset ---
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Session-Token, X-Requested-With
+Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
+Content-Length: 892
+Content-Type: text/html; charset=utf-8
+Last-Modified: Thu, 17 Sep 2026 07:00:36 GMT
+Date: Thu, 17 Sep 2026 08:19:24 GMT
+
+--- missing body ---
+
+
+
+
+
+ {
+ const browser = await chromium.launch({ headless: true, args: ['--no-sandbox'] });
+ const rows = [];
+
+ async function measure(label, { blockGoogleFonts = false } = {}) {
+ const context = await browser.newContext();
+ const page = await context.newPage();
+ const externalFontHits = [];
+ page.on('request', (req) => {
+ const u = req.url();
+ if (/fonts\.(googleapis|gstatic)\.com/.test(u)) externalFontHits.push(u.split('?')[0]);
+ });
+ if (blockGoogleFonts) {
+ await page.route(/fonts\.(googleapis|gstatic)\.com/, (r) => r.abort());
+ }
+ const started = Date.now();
+ let error = null;
+ try {
+ await page.goto('http://127.0.0.1:8080/', { waitUntil: 'domcontentloaded', timeout: 45000 });
+ await page.locator('input').first().waitFor({ state: 'visible', timeout: 15000 });
+ } catch (e) {
+ error = String(e.message || e).slice(0, 200);
+ }
+ const visibleMs = Date.now() - started;
+ await page.waitForTimeout(800);
+ const perf = await page.evaluate(() => ({
+ paint: performance.getEntriesByType('paint').map((p) => ({ name: p.name, ms: p.startTime })),
+ resources: performance.getEntriesByType('resource').map((r) => ({
+ url: r.name.split('?')[0],
+ bytes: r.transferSize,
+ decoded: r.decodedBodySize,
+ ms: Math.round(r.duration),
+ })),
+ }));
+ const html = await page.content();
+ const row = {
+ label,
+ visibleMs,
+ error,
+ externalFontHits,
+ hasGoogleInDOM: /fonts\.googleapis\.com|fonts\.gstatic\.com/.test(html),
+ paint: perf.paint,
+ requests: perf.resources.length,
+ transferBytes: perf.resources.reduce((s, r) => s + (r.bytes || 0), 0),
+ jsAssets: perf.resources.filter((r) => r.url.includes('/assets/') && r.url.endsWith('.js')),
+ fontAssets: perf.resources.filter((r) => r.url.includes('/fonts/')),
+ };
+ rows.push(row);
+ console.log(JSON.stringify(row));
+ await context.close();
+ }
+
+ await measure('login-cold');
+ await measure('login-font-domain-blocked', { blockGoogleFonts: true });
+ fs.writeFileSync('/out/browser-u2.json', JSON.stringify(rows, null, 2));
+ await browser.close();
+})();
diff --git a/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/browser-u2.json b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/browser-u2.json
new file mode 100644
index 00000000..b4d5370e
--- /dev/null
+++ b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/browser-u2.json
@@ -0,0 +1,72 @@
+[
+ {
+ "label": "login-cold",
+ "visibleMs": 205,
+ "error": null,
+ "externalFontHits": [],
+ "hasGoogleInDOM": false,
+ "paint": [
+ {
+ "name": "first-paint",
+ "ms": 32
+ },
+ {
+ "name": "first-contentful-paint",
+ "ms": 204
+ }
+ ],
+ "requests": 4,
+ "transferBytes": 681964,
+ "jsAssets": [
+ {
+ "url": "http://127.0.0.1:8080/assets/index-Bu0CqZB_.js",
+ "bytes": 624198,
+ "decoded": 2820055,
+ "ms": 13
+ }
+ ],
+ "fontAssets": [
+ {
+ "url": "http://127.0.0.1:8080/fonts/inter-v20-latin.woff2",
+ "bytes": 48556,
+ "decoded": 48256,
+ "ms": 5
+ }
+ ]
+ },
+ {
+ "label": "login-font-domain-blocked",
+ "visibleMs": 213,
+ "error": null,
+ "externalFontHits": [],
+ "hasGoogleInDOM": false,
+ "paint": [
+ {
+ "name": "first-paint",
+ "ms": 32
+ },
+ {
+ "name": "first-contentful-paint",
+ "ms": 216
+ }
+ ],
+ "requests": 4,
+ "transferBytes": 681964,
+ "jsAssets": [
+ {
+ "url": "http://127.0.0.1:8080/assets/index-Bu0CqZB_.js",
+ "bytes": 624198,
+ "decoded": 2820055,
+ "ms": 14
+ }
+ ],
+ "fontAssets": [
+ {
+ "url": "http://127.0.0.1:8080/fonts/inter-v20-latin.woff2",
+ "bytes": 48556,
+ "decoded": 48256,
+ "ms": 3
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/rebuild-log.txt b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/rebuild-log.txt
new file mode 100644
index 00000000..9499651c
--- /dev/null
+++ b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/rebuild-log.txt
@@ -0,0 +1,478 @@
+==> [dev] 重建镜像并重建容器...
+ Image agent-dev-events Building
+ Image shuimu-pi-agent:dev Building
+ Image agent-dev-app Building
+#1 [internal] load local bake definitions
+#1 reading from stdin 1.44kB done
+#1 DONE 0.0s
+
+#2 [app internal] load build definition from Dockerfile
+#2 transferring dockerfile: 1.53kB done
+#2 DONE 0.0s
+
+#3 [pi-agent internal] load build definition from Dockerfile
+#3 transferring dockerfile: 1.58kB done
+#3 DONE 0.0s
+
+#4 [auth] library/node:pull token for docker.1ms.run
+#4 DONE 0.0s
+
+#5 [auth] library/golang:pull token for docker.1ms.run
+#5 DONE 0.0s
+
+#6 [events internal] load metadata for docker.io/library/debian:bookworm-slim
+#6 DONE 0.2s
+
+#7 [app internal] load metadata for docker.io/library/node:22-bookworm
+#7 ...
+
+#8 [pi-agent internal] load metadata for docker.io/library/node:22-bookworm-slim
+#8 DONE 0.3s
+
+#9 [pi-agent internal] load .dockerignore
+#9 transferring context: 234B done
+#9 DONE 0.0s
+
+#10 [pi-agent 1/11] FROM docker.io/library/node:22-bookworm-slim@sha256:83f487e0a63425e5b4d146fb5e5be574bcbe1b7b843d3ebafdd95eaf7767a7e5
+#10 resolve docker.io/library/node:22-bookworm-slim@sha256:83f487e0a63425e5b4d146fb5e5be574bcbe1b7b843d3ebafdd95eaf7767a7e5 done
+#10 DONE 0.0s
+
+#11 [pi-agent internal] load build context
+#11 transferring context: 31.86kB done
+#11 DONE 0.0s
+
+#12 [pi-agent 6/11] COPY deploy/pi-agent/extensions/ /app/extensions/
+#12 CACHED
+
+#13 [pi-agent 2/11] RUN set -eux; apt-get update; apt-get install -y --no-install-recommends ca-certificates curl git bash; rm -rf /var/lib/apt/lists/*
+#13 CACHED
+
+#14 [pi-agent 3/11] RUN npm install -g @earendil-works/pi-coding-agent@0.85.1 --omit=dev
+#14 CACHED
+
+#15 [pi-agent 4/11] RUN pi --version
+#15 CACHED
+
+#16 [pi-agent 7/11] COPY deploy/pi-agent/runner.mjs /app/runner.mjs
+#16 CACHED
+
+#17 [pi-agent 9/11] COPY deploy/pi-agent/settle-policy.mjs /app/settle-policy.mjs
+#17 CACHED
+
+#18 [pi-agent 10/11] COPY deploy/pi-agent/entrypoint.sh /app/entrypoint.sh
+#18 CACHED
+
+#19 [pi-agent 5/11] WORKDIR /app
+#19 CACHED
+
+#20 [pi-agent 8/11] COPY deploy/pi-agent/result-v1.mjs /app/result-v1.mjs
+#20 CACHED
+
+#21 [pi-agent 11/11] RUN chmod +x /app/entrypoint.sh /app/runner.mjs
+#21 CACHED
+
+#22 [pi-agent] exporting to image
+#22 exporting layers done
+#22 exporting manifest sha256:84554c4311e3d33663a2349a68614db0f2e6a0192c0b3abfed729f1ac76b8d13 done
+#22 exporting config sha256:14f5c203947655983caf00baf53d78ff49d250b4f21afda352e293cfd5f72ed0 done
+#22 exporting attestation manifest sha256:612907871e23ecbd43acd81e1be6fdce19d23acd16d7c1b659e0345a17497d4a done
+#22 exporting manifest list sha256:f6f48df4362784021b66f99a181a20e455087c5b9f016be85f6147426dcf520d done
+#22 naming to docker.io/library/shuimu-pi-agent:dev done
+#22 unpacking to docker.io/library/shuimu-pi-agent:dev done
+#22 DONE 0.0s
+
+#23 [pi-agent] resolving provenance for metadata file
+#23 DONE 0.0s
+
+#7 [events internal] load metadata for docker.io/library/node:22-bookworm
+#7 DONE 0.4s
+
+#24 [app internal] load metadata for docker.io/library/golang:1.23-bookworm
+#24 DONE 2.2s
+
+#9 [app internal] load .dockerignore
+#9 CACHED
+
+#25 [events stage-2 1/9] FROM docker.io/library/debian:bookworm-slim@sha256:88200866dfff7ea7f5cbcb6ec7c8a701889efe6fe859fe64d6990e4b07ea4171
+#25 resolve docker.io/library/debian:bookworm-slim@sha256:88200866dfff7ea7f5cbcb6ec7c8a701889efe6fe859fe64d6990e4b07ea4171 done
+#25 DONE 0.0s
+
+#26 [events go-builder 1/7] FROM docker.io/library/golang:1.23-bookworm@sha256:167053a2bb901972bf2c1611f8f52c44d5fe7e762e5cab213708d82c421614db
+#26 resolve docker.io/library/golang:1.23-bookworm@sha256:167053a2bb901972bf2c1611f8f52c44d5fe7e762e5cab213708d82c421614db done
+#26 DONE 0.0s
+
+#27 [app web-builder 1/6] FROM docker.io/library/node:22-bookworm@sha256:8a34c4ab3ea2c5cd194f07e317b2a8f09461d3c8b05c4e34c8ccd56d56024c4d
+#27 resolve docker.io/library/node:22-bookworm@sha256:8a34c4ab3ea2c5cd194f07e317b2a8f09461d3c8b05c4e34c8ccd56d56024c4d done
+#27 DONE 0.0s
+
+#28 [app internal] load build context
+#28 transferring context: 105.56MB 0.8s done
+#28 DONE 0.8s
+
+#29 [events go-builder 2/7] WORKDIR /src
+#29 CACHED
+
+#30 [events go-builder 3/7] COPY go.mod go.sum ./
+#30 CACHED
+
+#31 [app go-builder 4/7] RUN go mod download
+#31 CACHED
+
+#32 [app web-builder 2/6] WORKDIR /web
+#32 CACHED
+
+#33 [app web-builder 3/6] COPY web/package.json web/package-lock.json* ./
+#33 DONE 0.1s
+
+#34 [events web-builder 4/6] RUN npm ci
+#34 ...
+
+#35 [events go-builder 5/7] COPY . .
+#35 DONE 0.3s
+
+#36 [events go-builder 6/7] RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /server ./cmd/server
+#36 DONE 6.1s
+
+#37 [events go-builder 7/7] RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /events ./cmd/events
+#37 DONE 0.4s
+
+#34 [events web-builder 4/6] RUN npm ci
+#34 ...
+
+#38 [events stage-2 2/9] RUN set -eux; apt-get update; apt-get install -y --no-install-recommends ca-certificates curl; rm -rf /var/lib/apt/lists/*
+#38 CACHED
+
+#39 [events stage-2 3/9] WORKDIR /app
+#39 CACHED
+
+#38 [app stage-2 2/9] RUN set -eux; apt-get update; apt-get install -y --no-install-recommends ca-certificates curl; rm -rf /var/lib/apt/lists/*
+#38 CACHED
+
+#39 [app stage-2 3/9] WORKDIR /app
+#39 CACHED
+
+#40 [app stage-2 4/9] COPY --from=go-builder /server /app/server
+#40 DONE 0.0s
+
+#41 [app stage-2 5/9] COPY --from=go-builder /events /app/events
+#41 DONE 0.0s
+
+#34 [events web-builder 4/6] RUN npm ci
+#34 12.13
+#34 12.13 added 245 packages, and audited 246 packages in 12s
+#34 12.13
+#34 12.13 21 packages are looking for funding
+#34 12.13 run `npm fund` for details
+#34 12.13
+#34 12.13 1 high severity vulnerability
+#34 12.13
+#34 12.13 Some issues need review, and may require choosing
+#34 12.13 a different dependency.
+#34 12.13
+#34 12.13 Run `npm audit` for details.
+#34 12.13 npm notice
+#34 12.13 npm notice New major version of npm available! 10.9.8 -> 12.0.2
+#34 12.13 npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.0.2
+#34 12.13 npm notice To update run: npm install -g npm@12.0.2
+#34 12.13 npm notice
+#34 DONE 12.2s
+
+#42 [app web-builder 5/6] COPY web/ ./
+#42 DONE 0.1s
+
+#43 [events web-builder 6/6] RUN npm run build
+#43 0.178
+#43 0.178 > shuimu-workbench@1.0.0 build
+#43 0.178 > tsc && vite build && node scripts/precompress-dist.mjs
+#43 0.178
+#43 3.830 vite v7.3.6 building client environment for production...
+#43 3.861 transforming...
+#43 11.14 ✓ 4122 modules transformed.
+#43 11.70 rendering chunks...
+#43 12.12 computing gzip size...
+#43 12.17 dist/index.html 0.72 kB │ gzip: 0.45 kB
+#43 12.17 dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff 4.42 kB
+#43 12.17 dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 4.93 kB
+#43 12.17 dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 5.21 kB
+#43 12.17 dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 5.47 kB
+#43 12.17 dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff 5.98 kB
+#43 12.17 dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff 6.19 kB
+#43 12.17 dist/assets/KaTeX_Size1-Regular-C195tn64.woff 6.50 kB
+#43 12.17 dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 6.91 kB
+#43 12.17 dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 6.91 kB
+#43 12.17 dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf 7.59 kB
+#43 12.17 dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff 7.66 kB
+#43 12.17 dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff 7.72 kB
+#43 12.17 dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 9.64 kB
+#43 12.17 dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 10.34 kB
+#43 12.17 dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf 10.36 kB
+#43 12.17 dist/assets/KaTeX_Script-Regular-D5yQViql.woff 10.59 kB
+#43 12.17 dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 11.32 kB
+#43 12.17 dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 11.35 kB
+#43 12.17 dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf 11.51 kB
+#43 12.17 dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 12.03 kB
+#43 12.17 dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 12.22 kB
+#43 12.17 dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf 12.23 kB
+#43 12.17 dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff 12.32 kB
+#43 12.17 dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf 12.34 kB
+#43 12.17 dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf 12.37 kB
+#43 12.17 dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff 13.21 kB
+#43 12.17 dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff 13.30 kB
+#43 12.17 dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 13.57 kB
+#43 12.17 dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff 14.11 kB
+#43 12.17 dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff 14.41 kB
+#43 12.17 dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff 16.03 kB
+#43 12.17 dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 16.40 kB
+#43 12.17 dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 16.44 kB
+#43 12.17 dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf 16.65 kB
+#43 12.17 dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 16.78 kB
+#43 12.17 dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 16.99 kB
+#43 12.17 dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff 18.67 kB
+#43 12.17 dist/assets/KaTeX_Math-Italic-DA0__PXp.woff 18.75 kB
+#43 12.17 dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff 19.41 kB
+#43 12.17 dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf 19.44 kB
+#43 12.17 dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf 19.57 kB
+#43 12.17 dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf 19.58 kB
+#43 12.17 dist/assets/KaTeX_Main-Italic-BMLOBm91.woff 19.68 kB
+#43 12.17 dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf 22.36 kB
+#43 12.17 dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf 24.50 kB
+#43 12.17 dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 25.32 kB
+#43 12.17 dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 26.27 kB
+#43 12.17 dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf 27.56 kB
+#43 12.17 dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 28.08 kB
+#43 12.17 dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff 29.91 kB
+#43 12.17 dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff 30.77 kB
+#43 12.17 dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf 31.20 kB
+#43 12.17 dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf 31.31 kB
+#43 12.17 dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf 32.97 kB
+#43 12.17 dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff 33.52 kB
+#43 12.17 dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf 33.58 kB
+#43 12.17 dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf 51.34 kB
+#43 12.17 dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf 53.58 kB
+#43 12.17 dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf 63.63 kB
+#43 12.17 dist/assets/index-BYHTgAJJ.css 36.82 kB │ gzip: 10.03 kB
+#43 12.17 dist/assets/channel-DNIEng0q.js 0.11 kB │ gzip: 0.12 kB
+#43 12.17 dist/assets/init-Gi6I4Gst.js 0.15 kB │ gzip: 0.13 kB
+#43 12.17 dist/assets/chunk-2Q5K7J3B-BZMLpKO7.js 0.19 kB │ gzip: 0.16 kB
+#43 12.17 dist/assets/chunk-JWPE2WC7-3XwVDd7R.js 0.22 kB │ gzip: 0.17 kB
+#43 12.17 dist/assets/chunk-XXDRQBXY-OG-34K3d.js 0.22 kB │ gzip: 0.20 kB
+#43 12.17 dist/assets/chunk-5VM5RSS4-wf5e4flP.js 0.36 kB │ gzip: 0.27 kB
+#43 12.17 dist/assets/stateDiagram-v2-MP3YSRHH-BuYCCE5b.js 0.39 kB │ gzip: 0.29 kB
+#43 12.17 dist/assets/classDiagram-ZZMXUADV-CVdTQJSv.js 0.43 kB │ gzip: 0.30 kB
+#43 12.17 dist/assets/classDiagram-v2-VYDZK3BY-CVdTQJSv.js 0.43 kB │ gzip: 0.30 kB
+#43 12.17 dist/assets/chunk-POPQ4Y6H-CrVio1q7.js 0.50 kB │ gzip: 0.35 kB
+#43 12.17 dist/assets/swimlanesDiagram-VR7AAH4N-2vwyB05c.js 0.51 kB │ gzip: 0.35 kB
+#43 12.17 dist/assets/infoDiagram-27XIBGKW-BgI1KvQI.js 0.55 kB │ gzip: 0.38 kB
+#43 12.17 dist/assets/sizeCapture-INFHLROL-BimZQ6a6.js 0.90 kB │ gzip: 0.51 kB
+#43 12.17 dist/assets/ordinal-Cboi1Yqb.js 1.19 kB │ gzip: 0.57 kB
+#43 12.17 dist/assets/railroadDiagram-O6MQD6OU-ByBV9o8N.js 1.57 kB │ gzip: 0.74 kB
+#43 12.17 dist/assets/abnfDiagram-VCTEODGH-DNWwdfvR.js 1.77 kB │ gzip: 0.87 kB
+#43 12.17 dist/assets/chunk-F27PBJKO-B3la_lkX.js 1.88 kB │ gzip: 0.83 kB
+#43 12.17 dist/assets/pegDiagram-XKGWAZYB-BG_KoFQ6.js 1.92 kB │ gzip: 0.91 kB
+#43 12.17 dist/assets/ebnfDiagram-PWID7BFC-DWQineoQ.js 1.97 kB │ gzip: 0.86 kB
+#43 12.17 dist/assets/arc-CJvvPhq7.js 3.43 kB │ gzip: 1.48 kB
+#43 12.17 dist/assets/diagram-Z3DM3KII-RF1V7gzL.js 4.18 kB │ gzip: 1.82 kB
+#43 12.17 dist/assets/defaultLocale-DX6XiGOO.js 4.69 kB │ gzip: 2.18 kB
+#43 12.17 dist/assets/linear-BZ30uBwb.js 5.65 kB │ gzip: 2.30 kB
+#43 12.17 dist/assets/diagram-UQ7AKVKN-DZi9K3zn.js 6.04 kB │ gzip: 2.60 kB
+#43 12.17 dist/assets/pieDiagram-E7YTZNPT-In23DzJs.js 6.26 kB │ gzip: 2.61 kB
+#43 12.17 dist/assets/diagram-S7CK7UJ4-D3XxuaTU.js 8.18 kB │ gzip: 3.66 kB
+#43 12.17 dist/assets/cynefinDiagram-5FMLGOSQ-QrrhMhDL.js 10.06 kB │ gzip: 3.61 kB
+#43 12.17 dist/assets/stateDiagram-D77RDMKH-C8R2qgBn.js 10.33 kB │ gzip: 3.61 kB
+#43 12.17 dist/assets/dagre-GXQ25YYZ-CM6w0zzF.js 10.64 kB │ gzip: 4.01 kB
+#43 12.17 dist/assets/diagram-VSXAHHWV-DHbN8ibS.js 10.68 kB │ gzip: 4.11 kB
+#43 12.17 dist/assets/chunk-SVP7TREG-CI8Y-3D2.js 15.73 kB │ gzip: 4.41 kB
+#43 12.17 dist/assets/diagram-VX7I27RA-BvQOHXue.js 15.92 kB │ gzip: 5.68 kB
+#43 12.17 dist/assets/ishikawaDiagram-5VMMS53U-Czj8Qul3.js 17.43 kB │ gzip: 6.62 kB
+#43 12.17 dist/assets/kanban-definition-UXKFOSKX-BoJUFrcC.js 20.26 kB │ gzip: 7.18 kB
+#43 12.17 dist/assets/mindmap-definition-YA3MSWOX-DWqHssQa.js 23.14 kB │ gzip: 7.80 kB
+#43 12.17 dist/assets/sankeyDiagram-P5KCCOFB-DbuNAAw9.js 23.16 kB │ gzip: 8.54 kB
+#43 12.17 dist/assets/journeyDiagram-3NMN7TZE-BKcwxO6D.js 23.54 kB │ gzip: 8.33 kB
+#43 12.17 dist/assets/wardleyDiagram-VM6X3IG4-CX23Vy_T.js 25.47 kB │ gzip: 6.77 kB
+#43 12.17 dist/assets/gitGraphDiagram-WWUBYQGX-Dn_exaMU.js 29.38 kB │ gzip: 8.68 kB
+#43 12.17 dist/assets/erDiagram-RLTQ6QDP-B5NGgjOU.js 30.76 kB │ gzip: 10.57 kB
+#43 12.17 dist/assets/timeline-definition-24CTP7MA-WeBLss97.js 30.79 kB │ gzip: 10.13 kB
+#43 12.17 dist/assets/requirementDiagram-BXWQKSXE-CGDVit9U.js 30.97 kB │ gzip: 9.71 kB
+#43 12.17 dist/assets/quadrantDiagram-AXDQQJYC-DtIrN-kE.js 33.98 kB │ gzip: 9.96 kB
+#43 12.17 dist/assets/layout-CrY6-gw1.js 35.43 kB │ gzip: 12.74 kB
+#43 12.17 dist/assets/chunk-IMKFNOWR-DL2S1Ocn.js 38.07 kB │ gzip: 12.51 kB
+#43 12.17 dist/assets/blockDiagram-I7D4REHJ-4pQkRsYE.js 41.72 kB │ gzip: 13.56 kB
+#43 12.17 dist/assets/vennDiagram-4TSXK5OY-mjOdrwai.js 41.93 kB │ gzip: 15.67 kB
+#43 12.17 dist/assets/xychartDiagram-S5SC5T6Z-BHknuwFK.js 44.47 kB │ gzip: 12.58 kB
+#43 12.17 dist/assets/chunk-TICWLB2K-upuxjo4B.js 49.17 kB │ gzip: 15.74 kB
+#43 12.17 dist/assets/flowDiagram-HODETNUW-ChE8AD7S.js 61.84 kB │ gzip: 19.87 kB
+#43 12.17 dist/assets/c4Diagram-7LVT6UL2-AvTEBjbZ.js 65.44 kB │ gzip: 18.77 kB
+#43 12.17 dist/assets/ganttDiagram-EL5Y4UJY-CelQZFDx.js 69.66 kB │ gzip: 23.54 kB
+#43 12.17 dist/assets/cose-bilkent-JH36ORCC-C3HMHbNW.js 81.66 kB │ gzip: 22.46 kB
+#43 12.17 dist/assets/swimlanes-42K2YHIH-DfsRAiF7.js 115.76 kB │ gzip: 42.49 kB
+#43 12.17 dist/assets/sequenceDiagram-WJ2MYXX4-DjJuHVj7.js 116.93 kB │ gzip: 31.11 kB
+#43 12.17 dist/assets/architectureDiagram-5GKGNRK7-BgFHVZr9.js 151.79 kB │ gzip: 43.13 kB
+#43 12.17 dist/assets/katex-HP8lGamR.js 261.31 kB │ gzip: 77.57 kB
+#43 12.17 dist/assets/cytoscape.esm-BB4DxJjf.js 443.04 kB │ gzip: 141.98 kB
+#43 12.17 dist/assets/cynefin-OW5HDTMX-BO97kahj.js 687.91 kB │ gzip: 154.14 kB
+#43 12.17 dist/assets/index-Bu0CqZB_.js 2,820.06 kB │ gzip: 803.51 kB
+#43 12.17
+#43 12.17 (!) Some chunks are larger than 500 kB after minification. Consider:
+#43 12.17 - Using dynamic import() to code-split the application
+#43 12.17 - Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks
+#43 12.17 - Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.
+#43 12.17 ✓ built in 8.33s
+#43 12.29 precompress: 49 candidate(s) under /web/dist
+#43 12.31 br assets/abnfDiagram-VCTEODGH-DNWwdfvR.js 1774 → 802 (−54.8%)
+#43 12.31 gzip assets/abnfDiagram-VCTEODGH-DNWwdfvR.js 1774 → 874 (−50.7%)
+#43 12.31 br assets/arc-CJvvPhq7.js 3434 → 1284 (−62.6%)
+#43 12.31 gzip assets/arc-CJvvPhq7.js 3434 → 1475 (−57.0%)
+#43 12.45 br assets/architectureDiagram-5GKGNRK7-BgFHVZr9.js 151788 → 36874 (−75.7%)
+#43 12.45 gzip assets/architectureDiagram-5GKGNRK7-BgFHVZr9.js 151788 → 42956 (−71.7%)
+#43 12.48 br assets/blockDiagram-I7D4REHJ-4pQkRsYE.js 41722 → 11974 (−71.3%)
+#43 12.48 gzip assets/blockDiagram-I7D4REHJ-4pQkRsYE.js 41722 → 13491 (−67.7%)
+#43 12.53 br assets/c4Diagram-7LVT6UL2-AvTEBjbZ.js 65438 → 15134 (−76.9%)
+#43 12.53 gzip assets/c4Diagram-7LVT6UL2-AvTEBjbZ.js 65438 → 18726 (−71.4%)
+#43 12.53 br assets/chunk-F27PBJKO-B3la_lkX.js 1876 → 732 (−61.0%)
+#43 12.53 gzip assets/chunk-F27PBJKO-B3la_lkX.js 1876 → 827 (−55.9%)
+#43 12.56 br assets/chunk-IMKFNOWR-DL2S1Ocn.js 38069 → 10968 (−71.2%)
+#43 12.56 gzip assets/chunk-IMKFNOWR-DL2S1Ocn.js 38069 → 12492 (−67.2%)
+#43 12.57 br assets/chunk-SVP7TREG-CI8Y-3D2.js 15728 → 3961 (−74.8%)
+#43 12.57 gzip assets/chunk-SVP7TREG-CI8Y-3D2.js 15728 → 4409 (−72.0%)
+#43 12.60 br assets/chunk-TICWLB2K-upuxjo4B.js 49171 → 13030 (−73.5%)
+#43 12.60 gzip assets/chunk-TICWLB2K-upuxjo4B.js 49171 → 15733 (−68.0%)
+#43 12.66 br assets/cose-bilkent-JH36ORCC-C3HMHbNW.js 81662 → 19601 (−76.0%)
+#43 12.66 gzip assets/cose-bilkent-JH36ORCC-C3HMHbNW.js 81662 → 22363 (−72.6%)
+#43 13.31 br assets/cynefin-OW5HDTMX-BO97kahj.js 687914 → 124608 (−81.9%)
+#43 13.31 gzip assets/cynefin-OW5HDTMX-BO97kahj.js 687914 → 153500 (−77.7%)
+#43 13.31 br assets/cynefinDiagram-5FMLGOSQ-QrrhMhDL.js 10062 → 3227 (−67.9%)
+#43 13.31 gzip assets/cynefinDiagram-5FMLGOSQ-QrrhMhDL.js 10062 → 3612 (−64.1%)
+#43 13.79 br assets/cytoscape.esm-BB4DxJjf.js 443036 → 119602 (−73.0%)
+#43 13.79 gzip assets/cytoscape.esm-BB4DxJjf.js 443036 → 141625 (−68.0%)
+#43 13.80 br assets/dagre-GXQ25YYZ-CM6w0zzF.js 10641 → 3656 (−65.6%)
+#43 13.80 gzip assets/dagre-GXQ25YYZ-CM6w0zzF.js 10641 → 4008 (−62.3%)
+#43 13.80 br assets/defaultLocale-DX6XiGOO.js 4688 → 2012 (−57.1%)
+#43 13.80 gzip assets/defaultLocale-DX6XiGOO.js 4688 → 2182 (−53.5%)
+#43 13.80 br assets/diagram-S7CK7UJ4-D3XxuaTU.js 8182 → 3317 (−59.5%)
+#43 13.80 gzip assets/diagram-S7CK7UJ4-D3XxuaTU.js 8182 → 3657 (−55.3%)
+#43 13.81 br assets/diagram-UQ7AKVKN-DZi9K3zn.js 6044 → 2351 (−61.1%)
+#43 13.81 gzip assets/diagram-UQ7AKVKN-DZi9K3zn.js 6044 → 2603 (−56.9%)
+#43 13.82 br assets/diagram-VSXAHHWV-DHbN8ibS.js 10681 → 3768 (−64.7%)
+#43 13.82 gzip assets/diagram-VSXAHHWV-DHbN8ibS.js 10681 → 4113 (−61.5%)
+#43 13.83 br assets/diagram-VX7I27RA-BvQOHXue.js 15922 → 5149 (−67.7%)
+#43 13.83 gzip assets/diagram-VX7I27RA-BvQOHXue.js 15922 → 5679 (−64.3%)
+#43 13.83 br assets/diagram-Z3DM3KII-RF1V7gzL.js 4176 → 1631 (−60.9%)
+#43 13.83 gzip assets/diagram-Z3DM3KII-RF1V7gzL.js 4176 → 1816 (−56.5%)
+#43 13.83 br assets/ebnfDiagram-PWID7BFC-DWQineoQ.js 1970 → 767 (−61.1%)
+#43 13.83 gzip assets/ebnfDiagram-PWID7BFC-DWQineoQ.js 1970 → 861 (−56.3%)
+#43 13.85 br assets/erDiagram-RLTQ6QDP-B5NGgjOU.js 30755 → 9165 (−70.2%)
+#43 13.85 gzip assets/erDiagram-RLTQ6QDP-B5NGgjOU.js 30755 → 10569 (−65.6%)
+#43 13.90 br assets/flowDiagram-HODETNUW-ChE8AD7S.js 61840 → 16328 (−73.6%)
+#43 13.90 gzip assets/flowDiagram-HODETNUW-ChE8AD7S.js 61840 → 19857 (−67.9%)
+#43 13.95 br assets/ganttDiagram-EL5Y4UJY-CelQZFDx.js 69656 → 20680 (−70.3%)
+#43 13.95 gzip assets/ganttDiagram-EL5Y4UJY-CelQZFDx.js 69656 → 23513 (−66.2%)
+#43 13.97 br assets/gitGraphDiagram-WWUBYQGX-Dn_exaMU.js 29382 → 7774 (−73.5%)
+#43 13.97 gzip assets/gitGraphDiagram-WWUBYQGX-Dn_exaMU.js 29382 → 8662 (−70.5%)
+#43 14.00 br assets/index-BYHTgAJJ.css 36824 → 8557 (−76.8%)
+#43 14.00 gzip assets/index-BYHTgAJJ.css 36824 → 9920 (−73.1%)
+#43 16.82 br assets/index-Bu0CqZB_.js 2820055 → 623898 (−77.9%)
+#43 16.82 gzip assets/index-Bu0CqZB_.js 2820055 → 800721 (−71.6%)
+#43 16.83 br assets/ishikawaDiagram-5VMMS53U-Czj8Qul3.js 17434 → 5995 (−65.6%)
+#43 16.83 gzip assets/ishikawaDiagram-5VMMS53U-Czj8Qul3.js 17434 → 6613 (−62.1%)
+#43 16.85 br assets/journeyDiagram-3NMN7TZE-BKcwxO6D.js 23536 → 7490 (−68.2%)
+#43 16.85 gzip assets/journeyDiagram-3NMN7TZE-BKcwxO6D.js 23536 → 8316 (−64.7%)
+#43 16.86 br assets/kanban-definition-UXKFOSKX-BoJUFrcC.js 20256 → 6393 (−68.4%)
+#43 16.86 gzip assets/kanban-definition-UXKFOSKX-BoJUFrcC.js 20256 → 7169 (−64.6%)
+#43 17.11 br assets/katex-HP8lGamR.js 261313 → 63694 (−75.6%)
+#43 17.11 gzip assets/katex-HP8lGamR.js 261313 → 77166 (−70.5%)
+#43 17.13 br assets/layout-CrY6-gw1.js 35429 → 11568 (−67.3%)
+#43 17.13 gzip assets/layout-CrY6-gw1.js 35429 → 12719 (−64.1%)
+#43 17.14 br assets/linear-BZ30uBwb.js 5654 → 2114 (−62.6%)
+#43 17.14 gzip assets/linear-BZ30uBwb.js 5654 → 2304 (−59.3%)
+#43 17.15 br assets/mindmap-definition-YA3MSWOX-DWqHssQa.js 23140 → 6973 (−69.9%)
+#43 17.15 gzip assets/mindmap-definition-YA3MSWOX-DWqHssQa.js 23140 → 7789 (−66.3%)
+#43 17.15 br assets/ordinal-Cboi1Yqb.js 1189 → 497 (−58.2%)
+#43 17.15 gzip assets/ordinal-Cboi1Yqb.js 1189 → 573 (−51.8%)
+#43 17.15 br assets/pegDiagram-XKGWAZYB-BG_KoFQ6.js 1921 → 800 (−58.4%)
+#43 17.15 gzip assets/pegDiagram-XKGWAZYB-BG_KoFQ6.js 1921 → 905 (−52.9%)
+#43 17.16 br assets/pieDiagram-E7YTZNPT-In23DzJs.js 6259 → 2385 (−61.9%)
+#43 17.16 gzip assets/pieDiagram-E7YTZNPT-In23DzJs.js 6259 → 2605 (−58.4%)
+#43 17.18 br assets/quadrantDiagram-AXDQQJYC-DtIrN-kE.js 33975 → 8512 (−74.9%)
+#43 17.18 gzip assets/quadrantDiagram-AXDQQJYC-DtIrN-kE.js 33975 → 9922 (−70.8%)
+#43 17.18 br assets/railroadDiagram-O6MQD6OU-ByBV9o8N.js 1571 → 665 (−57.7%)
+#43 17.18 gzip assets/railroadDiagram-O6MQD6OU-ByBV9o8N.js 1571 → 735 (−53.2%)
+#43 17.21 br assets/requirementDiagram-BXWQKSXE-CGDVit9U.js 30965 → 8235 (−73.4%)
+#43 17.21 gzip assets/requirementDiagram-BXWQKSXE-CGDVit9U.js 30965 → 9698 (−68.7%)
+#43 17.22 br assets/sankeyDiagram-P5KCCOFB-DbuNAAw9.js 23163 → 7808 (−66.3%)
+#43 17.22 gzip assets/sankeyDiagram-P5KCCOFB-DbuNAAw9.js 23163 → 8534 (−63.2%)
+#43 17.31 br assets/sequenceDiagram-WJ2MYXX4-DjJuHVj7.js 116927 → 25728 (−78.0%)
+#43 17.31 gzip assets/sequenceDiagram-WJ2MYXX4-DjJuHVj7.js 116927 → 31047 (−73.4%)
+#43 17.32 br assets/stateDiagram-D77RDMKH-C8R2qgBn.js 10326 → 3308 (−68.0%)
+#43 17.32 gzip assets/stateDiagram-D77RDMKH-C8R2qgBn.js 10326 → 3602 (−65.1%)
+#43 17.42 br assets/swimlanes-42K2YHIH-DfsRAiF7.js 115756 → 36665 (−68.3%)
+#43 17.42 gzip assets/swimlanes-42K2YHIH-DfsRAiF7.js 115756 → 42418 (−63.4%)
+#43 17.44 br assets/timeline-definition-24CTP7MA-WeBLss97.js 30794 → 9104 (−70.4%)
+#43 17.44 gzip assets/timeline-definition-24CTP7MA-WeBLss97.js 30794 → 10117 (−67.1%)
+#43 17.47 br assets/vennDiagram-4TSXK5OY-mjOdrwai.js 41926 → 13976 (−66.7%)
+#43 17.47 gzip assets/vennDiagram-4TSXK5OY-mjOdrwai.js 41926 → 15661 (−62.6%)
+#43 17.49 br assets/wardleyDiagram-VM6X3IG4-CX23Vy_T.js 25467 → 6071 (−76.2%)
+#43 17.49 gzip assets/wardleyDiagram-VM6X3IG4-CX23Vy_T.js 25467 → 6742 (−73.5%)
+#43 17.52 br assets/xychartDiagram-S5SC5T6Z-BHknuwFK.js 44474 → 11037 (−75.2%)
+#43 17.52 gzip assets/xychartDiagram-S5SC5T6Z-BHknuwFK.js 44474 → 12554 (−71.8%)
+#43 17.52 br fonts/OFL.txt 4474 → 1437 (−67.9%)
+#43 17.52 gzip fonts/OFL.txt 4474 → 1993 (−55.5%)
+#43 17.52 precompress: wrote 49 .br and 49 .gz
+#43 DONE 17.6s
+
+#44 [app stage-2 6/9] COPY --from=web-builder /web/dist /app/web/dist
+#44 DONE 0.0s
+
+#45 [events stage-2 7/9] COPY deploy/postgres/goose /app/deploy/postgres/goose
+#45 DONE 0.0s
+
+#46 [app stage-2 8/9] COPY templates /app/templates
+#46 DONE 0.0s
+
+#47 [app stage-2 9/9] COPY configs /app/configs
+#47 DONE 0.0s
+
+#48 [app] exporting to image
+#48 exporting layers
+#48 exporting layers 0.5s done
+#48 exporting manifest sha256:478f45e6785a3a54663d52f8bfbfd737acf4ba1bc08e61cefb8f50fc7f0d108c done
+#48 exporting config sha256:012423a05ae9029c6359a62195ba9bfd94ae57195ff2c3c1d58c0813b4840805 done
+#48 exporting attestation manifest sha256:99a8432c74582132f33a3d13e8d7018ce6c0cb28b1774eac2500c844ac44a1a0 done
+#48 exporting manifest list sha256:7ffd2cd6a7980cac58cb8bb5bfbd60e31ec4a6d1bf772b806407144562a55e87 done
+#48 naming to docker.io/library/agent-dev-app:latest done
+#48 unpacking to docker.io/library/agent-dev-app:latest 0.1s done
+#48 DONE 0.7s
+
+#49 [events] exporting to image
+#49 exporting layers 0.5s done
+#49 exporting manifest sha256:750ee7a2b3410dd4950559f5ac5d650b51a4afe24df2affb2cba579e934ccb21 done
+#49 exporting config sha256:5472d5395c11a812621e1d9220c1b5ebd503abdf29a5d1e0f195821c939b9d94 done
+#49 exporting attestation manifest sha256:3af9ce869fe078e177121a2f9ad9b8e5796a44877f016eb96842174b1f96ec3a done
+#49 exporting manifest list sha256:6c279d3ef4b766c874134b52e1af280d1dc5a2e230f89a4bf7c913138b8cf3eb done
+#49 naming to docker.io/library/agent-dev-events:latest done
+#49 unpacking to docker.io/library/agent-dev-events:latest 0.1s done
+#49 DONE 0.7s
+
+#50 [app] resolving provenance for metadata file
+#50 DONE 0.0s
+
+#51 [events] resolving provenance for metadata file
+#51 DONE 0.0s
+ Image shuimu-pi-agent:dev Built
+ Image agent-dev-app Built
+ Image agent-dev-events Built
+ Container shuimu-context-pg-dev Running
+ Container shuimu-cursor-agent-dev Running
+ Container shuimu-pi-agent-dev Running
+ Container shuimu-agent-app-dev Recreate
+ Container shuimu-agent-events-dev Recreate
+ Container shuimu-agent-events-dev Recreated
+ Container shuimu-agent-app-dev Recreated
+ Container shuimu-context-pg-dev Waiting
+ Container shuimu-context-pg-dev Waiting
+ Container shuimu-context-pg-dev Healthy
+ Container shuimu-agent-app-dev Starting
+ Container shuimu-context-pg-dev Healthy
+ Container shuimu-agent-events-dev Starting
+ Container shuimu-agent-app-dev Started
+ Container shuimu-agent-events-dev Started
+==> [dev] 镜像与容器已更新
diff --git a/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/rebuild-nocache-log.txt b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/rebuild-nocache-log.txt
new file mode 100644
index 00000000..2d8d4a68
--- /dev/null
+++ b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/rebuild-nocache-log.txt
@@ -0,0 +1,515 @@
+ Image agent-dev-app Building
+#1 [internal] load local bake definitions
+#1 reading from stdin 549B done
+#1 DONE 0.0s
+
+#2 [internal] load build definition from Dockerfile
+#2 transferring dockerfile: 1.53kB done
+#2 DONE 0.0s
+
+#3 [internal] load metadata for docker.io/library/node:22-bookworm
+#3 DONE 0.1s
+
+#4 [internal] load metadata for docker.io/library/golang:1.23-bookworm
+#4 DONE 0.1s
+
+#5 [internal] load metadata for docker.io/library/debian:bookworm-slim
+#5 DONE 0.2s
+
+#6 [internal] load .dockerignore
+#6 transferring context: 234B done
+#6 DONE 0.0s
+
+#7 [stage-2 1/9] FROM docker.io/library/debian:bookworm-slim@sha256:88200866dfff7ea7f5cbcb6ec7c8a701889efe6fe859fe64d6990e4b07ea4171
+#7 resolve docker.io/library/debian:bookworm-slim@sha256:88200866dfff7ea7f5cbcb6ec7c8a701889efe6fe859fe64d6990e4b07ea4171 done
+#7 CACHED
+
+#8 [web-builder 1/6] FROM docker.io/library/node:22-bookworm@sha256:8a34c4ab3ea2c5cd194f07e317b2a8f09461d3c8b05c4e34c8ccd56d56024c4d
+#8 resolve docker.io/library/node:22-bookworm@sha256:8a34c4ab3ea2c5cd194f07e317b2a8f09461d3c8b05c4e34c8ccd56d56024c4d done
+#8 DONE 0.0s
+
+#9 [web-builder 2/6] WORKDIR /web
+#9 CACHED
+
+#10 [go-builder 1/7] FROM docker.io/library/golang:1.23-bookworm@sha256:167053a2bb901972bf2c1611f8f52c44d5fe7e762e5cab213708d82c421614db
+#10 resolve docker.io/library/golang:1.23-bookworm@sha256:167053a2bb901972bf2c1611f8f52c44d5fe7e762e5cab213708d82c421614db 0.0s done
+#10 DONE 0.0s
+
+#11 [go-builder 2/7] WORKDIR /src
+#11 CACHED
+
+#12 [internal] load build context
+#12 transferring context: 46.16MB 0.5s done
+#12 DONE 0.5s
+
+#13 [go-builder 3/7] COPY go.mod go.sum ./
+#13 DONE 0.0s
+
+#14 [web-builder 3/6] COPY web/package.json web/package-lock.json* ./
+#14 DONE 0.0s
+
+#15 [go-builder 4/7] RUN go mod download
+#15 0.132 go: downloading go1.27.1 (linux/amd64)
+#15 ...
+
+#16 [stage-2 2/9] RUN set -eux; apt-get update; apt-get install -y --no-install-recommends ca-certificates curl; rm -rf /var/lib/apt/lists/*
+#16 0.125 + apt-get update
+#16 0.476 Get:1 http://deb.debian.org/debian bookworm InRelease [151 kB]
+#16 1.038 Get:2 http://deb.debian.org/debian bookworm-updates InRelease [55.4 kB]
+#16 1.252 Get:3 http://deb.debian.org/debian-security bookworm-security InRelease [34.8 kB]
+#16 1.423 Get:4 http://deb.debian.org/debian bookworm/main amd64 Packages [8790 kB]
+#16 10.05 Get:5 http://deb.debian.org/debian bookworm-updates/main amd64 Packages [6924 B]
+#16 10.30 Get:6 http://deb.debian.org/debian-security bookworm-security/main amd64 Packages [339 kB]
+#16 ...
+
+#17 [web-builder 4/6] RUN npm ci
+#17 ...
+
+#16 [stage-2 2/9] RUN set -eux; apt-get update; apt-get install -y --no-install-recommends ca-certificates curl; rm -rf /var/lib/apt/lists/*
+#16 10.96 Fetched 9378 kB in 11s (868 kB/s)
+#16 10.96 Reading package lists...
+#16 11.24 + apt-get install -y --no-install-recommends ca-certificates curl
+#16 11.24 Reading package lists...
+#16 11.47 Building dependency tree...
+#16 11.53 Reading state information...
+#16 11.59 The following additional packages will be installed:
+#16 11.59 libbrotli1 libcurl4 libgssapi-krb5-2 libk5crypto3 libkeyutils1 libkrb5-3
+#16 11.59 libkrb5support0 libldap-2.5-0 libnghttp2-14 libpsl5 librtmp1 libsasl2-2
+#16 11.59 libsasl2-modules-db libssh2-1 libssl3 openssl
+#16 11.59 Suggested packages:
+#16 11.59 krb5-doc krb5-user
+#16 11.59 Recommended packages:
+#16 11.59 krb5-locales libldap-common publicsuffix libsasl2-modules
+#16 11.65 The following NEW packages will be installed:
+#16 11.65 ca-certificates curl libbrotli1 libcurl4 libgssapi-krb5-2 libk5crypto3
+#16 11.65 libkeyutils1 libkrb5-3 libkrb5support0 libldap-2.5-0 libnghttp2-14 libpsl5
+#16 11.65 librtmp1 libsasl2-2 libsasl2-modules-db libssh2-1 libssl3 openssl
+#16 12.04 0 upgraded, 18 newly installed, 0 to remove and 1 not upgraded.
+#16 12.04 Need to get 5840 kB of archives.
+#16 12.04 After this operation, 14.7 MB of additional disk space will be used.
+#16 12.04 Get:1 http://deb.debian.org/debian bookworm/main amd64 libssl3 amd64 3.0.20-1~deb12u2 [2036 kB]
+#16 13.44 Get:2 http://deb.debian.org/debian bookworm/main amd64 openssl amd64 3.0.20-1~deb12u2 [1439 kB]
+#16 14.44 Get:3 http://deb.debian.org/debian-security bookworm-security/main amd64 ca-certificates all 20250419~deb12u1 [162 kB]
+#16 14.52 Get:4 http://deb.debian.org/debian bookworm/main amd64 libbrotli1 amd64 1.0.9-2+b6 [275 kB]
+#16 14.69 Get:5 http://deb.debian.org/debian bookworm/main amd64 libkrb5support0 amd64 1.20.1-2+deb12u5 [33.2 kB]
+#16 14.74 Get:6 http://deb.debian.org/debian bookworm/main amd64 libk5crypto3 amd64 1.20.1-2+deb12u5 [79.7 kB]
+#16 14.75 Get:7 http://deb.debian.org/debian bookworm/main amd64 libkeyutils1 amd64 1.6.3-2 [8808 B]
+#16 14.76 Get:8 http://deb.debian.org/debian bookworm/main amd64 libkrb5-3 amd64 1.20.1-2+deb12u5 [332 kB]
+#16 14.98 Get:9 http://deb.debian.org/debian bookworm/main amd64 libgssapi-krb5-2 amd64 1.20.1-2+deb12u5 [135 kB]
+#16 15.12 Get:10 http://deb.debian.org/debian bookworm/main amd64 libsasl2-modules-db amd64 2.1.28+dfsg-10 [20.3 kB]
+#16 15.12 Get:11 http://deb.debian.org/debian bookworm/main amd64 libsasl2-2 amd64 2.1.28+dfsg-10 [59.7 kB]
+#16 15.13 Get:12 http://deb.debian.org/debian bookworm/main amd64 libldap-2.5-0 amd64 2.5.13+dfsg-5 [183 kB]
+#16 15.25 Get:13 http://deb.debian.org/debian bookworm/main amd64 libnghttp2-14 amd64 1.52.0-1+deb12u3 [72.4 kB]
+#16 15.33 Get:14 http://deb.debian.org/debian bookworm/main amd64 libpsl5 amd64 0.21.2-1 [58.7 kB]
+#16 15.35 Get:15 http://deb.debian.org/debian bookworm/main amd64 librtmp1 amd64 2.4+20151223.gitfa8646d.1-2+b2 [60.8 kB]
+#16 15.40 Get:16 http://deb.debian.org/debian-security bookworm-security/main amd64 libssh2-1 amd64 1.10.0-3+deb12u1 [176 kB]
+#16 15.53 Get:17 http://deb.debian.org/debian bookworm/main amd64 libcurl4 amd64 7.88.1-10+deb12u15 [392 kB]
+#16 15.90 Get:18 http://deb.debian.org/debian bookworm/main amd64 curl amd64 7.88.1-10+deb12u15 [316 kB]
+#16 16.20 debconf: delaying package configuration, since apt-utils is not installed
+#16 16.21 Fetched 5840 kB in 4s (1311 kB/s)
+#16 16.24 Selecting previously unselected package libssl3:amd64.
+#16 16.24 (Reading database ...
(Reading database ... 5%
(Reading database ... 10%
(Reading database ... 15%
(Reading database ... 20%
(Reading database ... 25%
(Reading database ... 30%
(Reading database ... 35%
(Reading database ... 40%
(Reading database ... 45%
(Reading database ... 50%
(Reading database ... 55%
(Reading database ... 60%
(Reading database ... 65%
(Reading database ... 70%
(Reading database ... 75%
(Reading database ... 80%
(Reading database ... 85%
(Reading database ... 90%
(Reading database ... 95%
(Reading database ... 100%
(Reading database ... 6096 files and directories currently installed.)
+#16 16.25 Preparing to unpack .../00-libssl3_3.0.20-1~deb12u2_amd64.deb ...
+#16 16.25 Unpacking libssl3:amd64 (3.0.20-1~deb12u2) ...
+#16 16.36 Selecting previously unselected package openssl.
+#16 16.36 Preparing to unpack .../01-openssl_3.0.20-1~deb12u2_amd64.deb ...
+#16 16.36 Unpacking openssl (3.0.20-1~deb12u2) ...
+#16 16.45 Selecting previously unselected package ca-certificates.
+#16 16.45 Preparing to unpack .../02-ca-certificates_20250419~deb12u1_all.deb ...
+#16 16.45 Unpacking ca-certificates (20250419~deb12u1) ...
+#16 16.47 Selecting previously unselected package libbrotli1:amd64.
+#16 16.47 Preparing to unpack .../03-libbrotli1_1.0.9-2+b6_amd64.deb ...
+#16 16.47 Unpacking libbrotli1:amd64 (1.0.9-2+b6) ...
+#16 16.49 Selecting previously unselected package libkrb5support0:amd64.
+#16 16.49 Preparing to unpack .../04-libkrb5support0_1.20.1-2+deb12u5_amd64.deb ...
+#16 16.50 Unpacking libkrb5support0:amd64 (1.20.1-2+deb12u5) ...
+#16 16.51 Selecting previously unselected package libk5crypto3:amd64.
+#16 16.51 Preparing to unpack .../05-libk5crypto3_1.20.1-2+deb12u5_amd64.deb ...
+#16 16.51 Unpacking libk5crypto3:amd64 (1.20.1-2+deb12u5) ...
+#16 16.52 Selecting previously unselected package libkeyutils1:amd64.
+#16 16.52 Preparing to unpack .../06-libkeyutils1_1.6.3-2_amd64.deb ...
+#16 16.52 Unpacking libkeyutils1:amd64 (1.6.3-2) ...
+#16 16.53 Selecting previously unselected package libkrb5-3:amd64.
+#16 16.53 Preparing to unpack .../07-libkrb5-3_1.20.1-2+deb12u5_amd64.deb ...
+#16 16.54 Unpacking libkrb5-3:amd64 (1.20.1-2+deb12u5) ...
+#16 16.56 Selecting previously unselected package libgssapi-krb5-2:amd64.
+#16 16.56 Preparing to unpack .../08-libgssapi-krb5-2_1.20.1-2+deb12u5_amd64.deb ...
+#16 16.57 Unpacking libgssapi-krb5-2:amd64 (1.20.1-2+deb12u5) ...
+#16 16.58 Selecting previously unselected package libsasl2-modules-db:amd64.
+#16 16.58 Preparing to unpack .../09-libsasl2-modules-db_2.1.28+dfsg-10_amd64.deb ...
+#16 16.58 Unpacking libsasl2-modules-db:amd64 (2.1.28+dfsg-10) ...
+#16 16.59 Selecting previously unselected package libsasl2-2:amd64.
+#16 16.59 Preparing to unpack .../10-libsasl2-2_2.1.28+dfsg-10_amd64.deb ...
+#16 16.59 Unpacking libsasl2-2:amd64 (2.1.28+dfsg-10) ...
+#16 16.61 Selecting previously unselected package libldap-2.5-0:amd64.
+#16 16.61 Preparing to unpack .../11-libldap-2.5-0_2.5.13+dfsg-5_amd64.deb ...
+#16 16.61 Unpacking libldap-2.5-0:amd64 (2.5.13+dfsg-5) ...
+#16 16.63 Selecting previously unselected package libnghttp2-14:amd64.
+#16 16.63 Preparing to unpack .../12-libnghttp2-14_1.52.0-1+deb12u3_amd64.deb ...
+#16 16.63 Unpacking libnghttp2-14:amd64 (1.52.0-1+deb12u3) ...
+#16 16.64 Selecting previously unselected package libpsl5:amd64.
+#16 16.64 Preparing to unpack .../13-libpsl5_0.21.2-1_amd64.deb ...
+#16 16.64 Unpacking libpsl5:amd64 (0.21.2-1) ...
+#16 16.66 Selecting previously unselected package librtmp1:amd64.
+#16 16.66 Preparing to unpack .../14-librtmp1_2.4+20151223.gitfa8646d.1-2+b2_amd64.deb ...
+#16 16.66 Unpacking librtmp1:amd64 (2.4+20151223.gitfa8646d.1-2+b2) ...
+#16 16.67 Selecting previously unselected package libssh2-1:amd64.
+#16 16.67 Preparing to unpack .../15-libssh2-1_1.10.0-3+deb12u1_amd64.deb ...
+#16 16.67 Unpacking libssh2-1:amd64 (1.10.0-3+deb12u1) ...
+#16 16.69 Selecting previously unselected package libcurl4:amd64.
+#16 16.69 Preparing to unpack .../16-libcurl4_7.88.1-10+deb12u15_amd64.deb ...
+#16 16.69 Unpacking libcurl4:amd64 (7.88.1-10+deb12u15) ...
+#16 16.72 Selecting previously unselected package curl.
+#16 16.72 Preparing to unpack .../17-curl_7.88.1-10+deb12u15_amd64.deb ...
+#16 16.72 Unpacking curl (7.88.1-10+deb12u15) ...
+#16 16.75 Setting up libkeyutils1:amd64 (1.6.3-2) ...
+#16 16.75 Setting up libpsl5:amd64 (0.21.2-1) ...
+#16 16.75 Setting up libbrotli1:amd64 (1.0.9-2+b6) ...
+#16 16.75 Setting up libssl3:amd64 (3.0.20-1~deb12u2) ...
+#16 16.76 Setting up libnghttp2-14:amd64 (1.52.0-1+deb12u3) ...
+#16 16.76 Setting up libkrb5support0:amd64 (1.20.1-2+deb12u5) ...
+#16 16.76 Setting up libsasl2-modules-db:amd64 (2.1.28+dfsg-10) ...
+#16 16.76 Setting up librtmp1:amd64 (2.4+20151223.gitfa8646d.1-2+b2) ...
+#16 16.76 Setting up libk5crypto3:amd64 (1.20.1-2+deb12u5) ...
+#16 16.77 Setting up libsasl2-2:amd64 (2.1.28+dfsg-10) ...
+#16 16.77 Setting up libssh2-1:amd64 (1.10.0-3+deb12u1) ...
+#16 16.77 Setting up libkrb5-3:amd64 (1.20.1-2+deb12u5) ...
+#16 16.77 Setting up openssl (3.0.20-1~deb12u2) ...
+#16 16.78 Setting up libldap-2.5-0:amd64 (2.5.13+dfsg-5) ...
+#16 16.78 Setting up ca-certificates (20250419~deb12u1) ...
+#16 16.83 debconf: unable to initialize frontend: Dialog
+#16 16.83 debconf: (TERM is not set, so the dialog frontend is not usable.)
+#16 16.83 debconf: falling back to frontend: Readline
+#16 16.83 debconf: unable to initialize frontend: Readline
+#16 16.83 debconf: (Can't locate Term/ReadLine.pm in @INC (you may need to install the Term::ReadLine module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.36.0 /usr/local/share/perl/5.36.0 /usr/lib/x86_64-linux-gnu/perl5/5.36 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl-base /usr/lib/x86_64-linux-gnu/perl/5.36 /usr/share/perl/5.36 /usr/local/lib/site_perl) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 7.)
+#16 16.83 debconf: falling back to frontend: Teletype
+#16 17.05 Updating certificates in /etc/ssl/certs...
+#16 17.37 150 added, 0 removed; done.
+#16 17.38 Setting up libgssapi-krb5-2:amd64 (1.20.1-2+deb12u5) ...
+#16 17.38 Setting up libcurl4:amd64 (7.88.1-10+deb12u15) ...
+#16 17.39 Setting up curl (7.88.1-10+deb12u15) ...
+#16 17.39 Processing triggers for libc-bin (2.36-9+deb12u14) ...
+#16 17.41 Processing triggers for ca-certificates (20250419~deb12u1) ...
+#16 17.41 Updating certificates in /etc/ssl/certs...
+#16 17.65 0 added, 0 removed; done.
+#16 17.65 Running hooks in /etc/ca-certificates/update.d...
+#16 17.65 done.
+#16 17.66 + rm -rf /var/lib/apt/lists/auxfiles /var/lib/apt/lists/deb.debian.org_debian-security_dists_bookworm-security_InRelease /var/lib/apt/lists/deb.debian.org_debian-security_dists_bookworm-security_main_binary-amd64_Packages.lz4 /var/lib/apt/lists/deb.debian.org_debian_dists_bookworm-updates_InRelease /var/lib/apt/lists/deb.debian.org_debian_dists_bookworm-updates_main_binary-amd64_Packages.lz4 /var/lib/apt/lists/deb.debian.org_debian_dists_bookworm_InRelease /var/lib/apt/lists/deb.debian.org_debian_dists_bookworm_main_binary-amd64_Packages.lz4 /var/lib/apt/lists/lock /var/lib/apt/lists/partial
+#16 DONE 17.8s
+
+#17 [web-builder 4/6] RUN npm ci
+#17 ...
+
+#18 [stage-2 3/9] WORKDIR /app
+#18 DONE 0.0s
+
+#17 [web-builder 4/6] RUN npm ci
+#17 24.72
+#17 24.72 added 245 packages, and audited 246 packages in 25s
+#17 24.73
+#17 24.73 21 packages are looking for funding
+#17 24.73 run `npm fund` for details
+#17 24.73
+#17 24.73 1 high severity vulnerability
+#17 24.73
+#17 24.73 Some issues need review, and may require choosing
+#17 24.73 a different dependency.
+#17 24.73
+#17 24.73 Run `npm audit` for details.
+#17 24.73 npm notice
+#17 24.73 npm notice New major version of npm available! 10.9.8 -> 12.0.2
+#17 24.73 npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.0.2
+#17 24.73 npm notice To update run: npm install -g npm@12.0.2
+#17 24.73 npm notice
+#17 DONE 24.8s
+
+#19 [web-builder 5/6] COPY web/ ./
+#19 DONE 0.1s
+
+#15 [go-builder 4/7] RUN go mod download
+#15 ...
+
+#20 [web-builder 6/6] RUN npm run build
+#20 0.181
+#20 0.181 > shuimu-workbench@1.0.0 build
+#20 0.181 > tsc && vite build && node scripts/precompress-dist.mjs
+#20 0.181
+#20 3.826 vite v7.3.6 building client environment for production...
+#20 3.858 transforming...
+#20 10.86 ✓ 4122 modules transformed.
+#20 11.42 rendering chunks...
+#20 11.84 computing gzip size...
+#20 11.89 dist/index.html 0.72 kB │ gzip: 0.45 kB
+#20 11.89 dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff 4.42 kB
+#20 11.89 dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 4.93 kB
+#20 11.89 dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 5.21 kB
+#20 11.89 dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 5.47 kB
+#20 11.89 dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff 5.98 kB
+#20 11.89 dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff 6.19 kB
+#20 11.89 dist/assets/KaTeX_Size1-Regular-C195tn64.woff 6.50 kB
+#20 11.89 dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 6.91 kB
+#20 11.89 dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 6.91 kB
+#20 11.89 dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf 7.59 kB
+#20 11.89 dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff 7.66 kB
+#20 11.89 dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff 7.72 kB
+#20 11.89 dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 9.64 kB
+#20 11.89 dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 10.34 kB
+#20 11.89 dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf 10.36 kB
+#20 11.89 dist/assets/KaTeX_Script-Regular-D5yQViql.woff 10.59 kB
+#20 11.89 dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 11.32 kB
+#20 11.89 dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 11.35 kB
+#20 11.89 dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf 11.51 kB
+#20 11.89 dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 12.03 kB
+#20 11.89 dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 12.22 kB
+#20 11.89 dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf 12.23 kB
+#20 11.89 dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff 12.32 kB
+#20 11.89 dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf 12.34 kB
+#20 11.89 dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf 12.37 kB
+#20 11.89 dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff 13.21 kB
+#20 11.89 dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff 13.30 kB
+#20 11.89 dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 13.57 kB
+#20 11.89 dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff 14.11 kB
+#20 11.89 dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff 14.41 kB
+#20 11.89 dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff 16.03 kB
+#20 11.89 dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 16.40 kB
+#20 11.89 dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 16.44 kB
+#20 11.89 dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf 16.65 kB
+#20 11.89 dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 16.78 kB
+#20 11.89 dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 16.99 kB
+#20 11.89 dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff 18.67 kB
+#20 11.89 dist/assets/KaTeX_Math-Italic-DA0__PXp.woff 18.75 kB
+#20 11.89 dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff 19.41 kB
+#20 11.89 dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf 19.44 kB
+#20 11.89 dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf 19.57 kB
+#20 11.89 dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf 19.58 kB
+#20 11.89 dist/assets/KaTeX_Main-Italic-BMLOBm91.woff 19.68 kB
+#20 11.89 dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf 22.36 kB
+#20 11.89 dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf 24.50 kB
+#20 11.89 dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 25.32 kB
+#20 11.89 dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 26.27 kB
+#20 11.89 dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf 27.56 kB
+#20 11.89 dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 28.08 kB
+#20 11.89 dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff 29.91 kB
+#20 11.89 dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff 30.77 kB
+#20 11.89 dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf 31.20 kB
+#20 11.89 dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf 31.31 kB
+#20 11.89 dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf 32.97 kB
+#20 11.89 dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff 33.52 kB
+#20 11.89 dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf 33.58 kB
+#20 11.89 dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf 51.34 kB
+#20 11.89 dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf 53.58 kB
+#20 11.89 dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf 63.63 kB
+#20 11.89 dist/assets/index-BYHTgAJJ.css 36.82 kB │ gzip: 10.03 kB
+#20 11.89 dist/assets/channel-DNIEng0q.js 0.11 kB │ gzip: 0.12 kB
+#20 11.89 dist/assets/init-Gi6I4Gst.js 0.15 kB │ gzip: 0.13 kB
+#20 11.89 dist/assets/chunk-2Q5K7J3B-BZMLpKO7.js 0.19 kB │ gzip: 0.16 kB
+#20 11.89 dist/assets/chunk-JWPE2WC7-3XwVDd7R.js 0.22 kB │ gzip: 0.17 kB
+#20 11.89 dist/assets/chunk-XXDRQBXY-OG-34K3d.js 0.22 kB │ gzip: 0.20 kB
+#20 11.89 dist/assets/chunk-5VM5RSS4-wf5e4flP.js 0.36 kB │ gzip: 0.27 kB
+#20 11.89 dist/assets/stateDiagram-v2-MP3YSRHH-BuYCCE5b.js 0.39 kB │ gzip: 0.29 kB
+#20 11.89 dist/assets/classDiagram-ZZMXUADV-CVdTQJSv.js 0.43 kB │ gzip: 0.30 kB
+#20 11.89 dist/assets/classDiagram-v2-VYDZK3BY-CVdTQJSv.js 0.43 kB │ gzip: 0.30 kB
+#20 11.89 dist/assets/chunk-POPQ4Y6H-CrVio1q7.js 0.50 kB │ gzip: 0.35 kB
+#20 11.89 dist/assets/swimlanesDiagram-VR7AAH4N-2vwyB05c.js 0.51 kB │ gzip: 0.35 kB
+#20 11.89 dist/assets/infoDiagram-27XIBGKW-BgI1KvQI.js 0.55 kB │ gzip: 0.38 kB
+#20 11.89 dist/assets/sizeCapture-INFHLROL-BimZQ6a6.js 0.90 kB │ gzip: 0.51 kB
+#20 11.89 dist/assets/ordinal-Cboi1Yqb.js 1.19 kB │ gzip: 0.57 kB
+#20 11.89 dist/assets/railroadDiagram-O6MQD6OU-ByBV9o8N.js 1.57 kB │ gzip: 0.74 kB
+#20 11.89 dist/assets/abnfDiagram-VCTEODGH-DNWwdfvR.js 1.77 kB │ gzip: 0.87 kB
+#20 11.89 dist/assets/chunk-F27PBJKO-B3la_lkX.js 1.88 kB │ gzip: 0.83 kB
+#20 11.89 dist/assets/pegDiagram-XKGWAZYB-BG_KoFQ6.js 1.92 kB │ gzip: 0.91 kB
+#20 11.89 dist/assets/ebnfDiagram-PWID7BFC-DWQineoQ.js 1.97 kB │ gzip: 0.86 kB
+#20 11.89 dist/assets/arc-CJvvPhq7.js 3.43 kB │ gzip: 1.48 kB
+#20 11.89 dist/assets/diagram-Z3DM3KII-RF1V7gzL.js 4.18 kB │ gzip: 1.82 kB
+#20 11.89 dist/assets/defaultLocale-DX6XiGOO.js 4.69 kB │ gzip: 2.18 kB
+#20 11.89 dist/assets/linear-BZ30uBwb.js 5.65 kB │ gzip: 2.30 kB
+#20 11.89 dist/assets/diagram-UQ7AKVKN-DZi9K3zn.js 6.04 kB │ gzip: 2.60 kB
+#20 11.89 dist/assets/pieDiagram-E7YTZNPT-In23DzJs.js 6.26 kB │ gzip: 2.61 kB
+#20 11.89 dist/assets/diagram-S7CK7UJ4-D3XxuaTU.js 8.18 kB │ gzip: 3.66 kB
+#20 11.89 dist/assets/cynefinDiagram-5FMLGOSQ-QrrhMhDL.js 10.06 kB │ gzip: 3.61 kB
+#20 11.89 dist/assets/stateDiagram-D77RDMKH-C8R2qgBn.js 10.33 kB │ gzip: 3.61 kB
+#20 11.89 dist/assets/dagre-GXQ25YYZ-CM6w0zzF.js 10.64 kB │ gzip: 4.01 kB
+#20 11.89 dist/assets/diagram-VSXAHHWV-DHbN8ibS.js 10.68 kB │ gzip: 4.11 kB
+#20 11.89 dist/assets/chunk-SVP7TREG-CI8Y-3D2.js 15.73 kB │ gzip: 4.41 kB
+#20 11.89 dist/assets/diagram-VX7I27RA-BvQOHXue.js 15.92 kB │ gzip: 5.68 kB
+#20 11.89 dist/assets/ishikawaDiagram-5VMMS53U-Czj8Qul3.js 17.43 kB │ gzip: 6.62 kB
+#20 11.89 dist/assets/kanban-definition-UXKFOSKX-BoJUFrcC.js 20.26 kB │ gzip: 7.18 kB
+#20 11.89 dist/assets/mindmap-definition-YA3MSWOX-DWqHssQa.js 23.14 kB │ gzip: 7.80 kB
+#20 11.89 dist/assets/sankeyDiagram-P5KCCOFB-DbuNAAw9.js 23.16 kB │ gzip: 8.54 kB
+#20 11.89 dist/assets/journeyDiagram-3NMN7TZE-BKcwxO6D.js 23.54 kB │ gzip: 8.33 kB
+#20 11.89 dist/assets/wardleyDiagram-VM6X3IG4-CX23Vy_T.js 25.47 kB │ gzip: 6.77 kB
+#20 11.89 dist/assets/gitGraphDiagram-WWUBYQGX-Dn_exaMU.js 29.38 kB │ gzip: 8.68 kB
+#20 11.89 dist/assets/erDiagram-RLTQ6QDP-B5NGgjOU.js 30.76 kB │ gzip: 10.57 kB
+#20 11.89 dist/assets/timeline-definition-24CTP7MA-WeBLss97.js 30.79 kB │ gzip: 10.13 kB
+#20 11.89 dist/assets/requirementDiagram-BXWQKSXE-CGDVit9U.js 30.97 kB │ gzip: 9.71 kB
+#20 11.89 dist/assets/quadrantDiagram-AXDQQJYC-DtIrN-kE.js 33.98 kB │ gzip: 9.96 kB
+#20 11.89 dist/assets/layout-CrY6-gw1.js 35.43 kB │ gzip: 12.74 kB
+#20 11.89 dist/assets/chunk-IMKFNOWR-DL2S1Ocn.js 38.07 kB │ gzip: 12.51 kB
+#20 11.89 dist/assets/blockDiagram-I7D4REHJ-4pQkRsYE.js 41.72 kB │ gzip: 13.56 kB
+#20 11.89 dist/assets/vennDiagram-4TSXK5OY-mjOdrwai.js 41.93 kB │ gzip: 15.67 kB
+#20 11.89 dist/assets/xychartDiagram-S5SC5T6Z-BHknuwFK.js 44.47 kB │ gzip: 12.58 kB
+#20 11.89 dist/assets/chunk-TICWLB2K-upuxjo4B.js 49.17 kB │ gzip: 15.74 kB
+#20 11.89 dist/assets/flowDiagram-HODETNUW-ChE8AD7S.js 61.84 kB │ gzip: 19.87 kB
+#20 11.89 dist/assets/c4Diagram-7LVT6UL2-AvTEBjbZ.js 65.44 kB │ gzip: 18.77 kB
+#20 11.89 dist/assets/ganttDiagram-EL5Y4UJY-CelQZFDx.js 69.66 kB │ gzip: 23.54 kB
+#20 11.89 dist/assets/cose-bilkent-JH36ORCC-C3HMHbNW.js 81.66 kB │ gzip: 22.46 kB
+#20 11.89 dist/assets/swimlanes-42K2YHIH-DfsRAiF7.js 115.76 kB │ gzip: 42.49 kB
+#20 11.89 dist/assets/sequenceDiagram-WJ2MYXX4-DjJuHVj7.js 116.93 kB │ gzip: 31.11 kB
+#20 11.89 dist/assets/architectureDiagram-5GKGNRK7-BgFHVZr9.js 151.79 kB │ gzip: 43.13 kB
+#20 11.89 dist/assets/katex-HP8lGamR.js 261.31 kB │ gzip: 77.57 kB
+#20 11.89 dist/assets/cytoscape.esm-BB4DxJjf.js 443.04 kB │ gzip: 141.98 kB
+#20 11.89 dist/assets/cynefin-OW5HDTMX-BO97kahj.js 687.91 kB │ gzip: 154.14 kB
+#20 11.89 dist/assets/index-Bu0CqZB_.js 2,820.06 kB │ gzip: 803.51 kB
+#20 11.89
+#20 11.89 (!) Some chunks are larger than 500 kB after minification. Consider:
+#20 11.89 - Using dynamic import() to code-split the application
+#20 11.89 - Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks
+#20 11.89 - Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.
+#20 11.89 ✓ built in 8.05s
+#20 11.99 precompress: 49 candidate(s) under /web/dist
+#20 11.99 br assets/abnfDiagram-VCTEODGH-DNWwdfvR.js 1774 → 802 (−54.8%)
+#20 11.99 gzip assets/abnfDiagram-VCTEODGH-DNWwdfvR.js 1774 → 874 (−50.7%)
+#20 11.99 br assets/arc-CJvvPhq7.js 3434 → 1284 (−62.6%)
+#20 11.99 gzip assets/arc-CJvvPhq7.js 3434 → 1475 (−57.0%)
+#20 12.12 br assets/architectureDiagram-5GKGNRK7-BgFHVZr9.js 151788 → 36874 (−75.7%)
+#20 12.12 gzip assets/architectureDiagram-5GKGNRK7-BgFHVZr9.js 151788 → 42956 (−71.7%)
+#20 12.15 br assets/blockDiagram-I7D4REHJ-4pQkRsYE.js 41722 → 11974 (−71.3%)
+#20 12.15 gzip assets/blockDiagram-I7D4REHJ-4pQkRsYE.js 41722 → 13491 (−67.7%)
+#20 12.20 br assets/c4Diagram-7LVT6UL2-AvTEBjbZ.js 65438 → 15134 (−76.9%)
+#20 12.20 gzip assets/c4Diagram-7LVT6UL2-AvTEBjbZ.js 65438 → 18726 (−71.4%)
+#20 12.20 br assets/chunk-F27PBJKO-B3la_lkX.js 1876 → 732 (−61.0%)
+#20 12.20 gzip assets/chunk-F27PBJKO-B3la_lkX.js 1876 → 827 (−55.9%)
+#20 12.23 br assets/chunk-IMKFNOWR-DL2S1Ocn.js 38069 → 10968 (−71.2%)
+#20 12.23 gzip assets/chunk-IMKFNOWR-DL2S1Ocn.js 38069 → 12492 (−67.2%)
+#20 12.24 br assets/chunk-SVP7TREG-CI8Y-3D2.js 15728 → 3961 (−74.8%)
+#20 12.24 gzip assets/chunk-SVP7TREG-CI8Y-3D2.js 15728 → 4409 (−72.0%)
+#20 12.27 br assets/chunk-TICWLB2K-upuxjo4B.js 49171 → 13030 (−73.5%)
+#20 12.27 gzip assets/chunk-TICWLB2K-upuxjo4B.js 49171 → 15733 (−68.0%)
+#20 12.33 br assets/cose-bilkent-JH36ORCC-C3HMHbNW.js 81662 → 19601 (−76.0%)
+#20 12.33 gzip assets/cose-bilkent-JH36ORCC-C3HMHbNW.js 81662 → 22363 (−72.6%)
+#20 12.97 br assets/cynefin-OW5HDTMX-BO97kahj.js 687914 → 124608 (−81.9%)
+#20 12.97 gzip assets/cynefin-OW5HDTMX-BO97kahj.js 687914 → 153500 (−77.7%)
+#20 12.98 br assets/cynefinDiagram-5FMLGOSQ-QrrhMhDL.js 10062 → 3227 (−67.9%)
+#20 12.98 gzip assets/cynefinDiagram-5FMLGOSQ-QrrhMhDL.js 10062 → 3612 (−64.1%)
+#20 13.45 br assets/cytoscape.esm-BB4DxJjf.js 443036 → 119602 (−73.0%)
+#20 13.45 gzip assets/cytoscape.esm-BB4DxJjf.js 443036 → 141625 (−68.0%)
+#20 13.46 br assets/dagre-GXQ25YYZ-CM6w0zzF.js 10641 → 3656 (−65.6%)
+#20 13.46 gzip assets/dagre-GXQ25YYZ-CM6w0zzF.js 10641 → 4008 (−62.3%)
+#20 13.46 br assets/defaultLocale-DX6XiGOO.js 4688 → 2012 (−57.1%)
+#20 13.46 gzip assets/defaultLocale-DX6XiGOO.js 4688 → 2182 (−53.5%)
+#20 13.47 br assets/diagram-S7CK7UJ4-D3XxuaTU.js 8182 → 3317 (−59.5%)
+#20 13.47 gzip assets/diagram-S7CK7UJ4-D3XxuaTU.js 8182 → 3657 (−55.3%)
+#20 13.47 br assets/diagram-UQ7AKVKN-DZi9K3zn.js 6044 → 2351 (−61.1%)
+#20 13.47 gzip assets/diagram-UQ7AKVKN-DZi9K3zn.js 6044 → 2603 (−56.9%)
+#20 13.48 br assets/diagram-VSXAHHWV-DHbN8ibS.js 10681 → 3768 (−64.7%)
+#20 13.48 gzip assets/diagram-VSXAHHWV-DHbN8ibS.js 10681 → 4113 (−61.5%)
+#20 13.49 br assets/diagram-VX7I27RA-BvQOHXue.js 15922 → 5149 (−67.7%)
+#20 13.49 gzip assets/diagram-VX7I27RA-BvQOHXue.js 15922 → 5679 (−64.3%)
+#20 13.49 br assets/diagram-Z3DM3KII-RF1V7gzL.js 4176 → 1631 (−60.9%)
+#20 13.49 gzip assets/diagram-Z3DM3KII-RF1V7gzL.js 4176 → 1816 (−56.5%)
+#20 13.50 br assets/ebnfDiagram-PWID7BFC-DWQineoQ.js 1970 → 767 (−61.1%)
+#20 13.50 gzip assets/ebnfDiagram-PWID7BFC-DWQineoQ.js 1970 → 861 (−56.3%)
+#20 13.52 br assets/erDiagram-RLTQ6QDP-B5NGgjOU.js 30755 → 9165 (−70.2%)
+#20 13.52 gzip assets/erDiagram-RLTQ6QDP-B5NGgjOU.js 30755 → 10569 (−65.6%)
+#20 13.56 br assets/flowDiagram-HODETNUW-ChE8AD7S.js 61840 → 16328 (−73.6%)
+#20 13.56 gzip assets/flowDiagram-HODETNUW-ChE8AD7S.js 61840 → 19857 (−67.9%)
+#20 13.62 br assets/ganttDiagram-EL5Y4UJY-CelQZFDx.js 69656 → 20680 (−70.3%)
+#20 13.62 gzip assets/ganttDiagram-EL5Y4UJY-CelQZFDx.js 69656 → 23513 (−66.2%)
+#20 13.63 br assets/gitGraphDiagram-WWUBYQGX-Dn_exaMU.js 29382 → 7774 (−73.5%)
+#20 13.63 gzip assets/gitGraphDiagram-WWUBYQGX-Dn_exaMU.js 29382 → 8662 (−70.5%)
+#20 13.66 br assets/index-BYHTgAJJ.css 36824 → 8557 (−76.8%)
+#20 13.66 gzip assets/index-BYHTgAJJ.css 36824 → 9920 (−73.1%)
+#20 16.47 br assets/index-Bu0CqZB_.js 2820055 → 623898 (−77.9%)
+#20 16.47 gzip assets/index-Bu0CqZB_.js 2820055 → 800721 (−71.6%)
+#20 16.48 br assets/ishikawaDiagram-5VMMS53U-Czj8Qul3.js 17434 → 5995 (−65.6%)
+#20 16.48 gzip assets/ishikawaDiagram-5VMMS53U-Czj8Qul3.js 17434 → 6613 (−62.1%)
+#20 16.49 br assets/journeyDiagram-3NMN7TZE-BKcwxO6D.js 23536 → 7490 (−68.2%)
+#20 16.49 gzip assets/journeyDiagram-3NMN7TZE-BKcwxO6D.js 23536 → 8316 (−64.7%)
+#20 16.51 br assets/kanban-definition-UXKFOSKX-BoJUFrcC.js 20256 → 6393 (−68.4%)
+#20 16.51 gzip assets/kanban-definition-UXKFOSKX-BoJUFrcC.js 20256 → 7169 (−64.6%)
+#20 16.75 br assets/katex-HP8lGamR.js 261313 → 63694 (−75.6%)
+#20 16.75 gzip assets/katex-HP8lGamR.js 261313 → 77166 (−70.5%)
+#20 16.77 br assets/layout-CrY6-gw1.js 35429 → 11568 (−67.3%)
+#20 16.77 gzip assets/layout-CrY6-gw1.js 35429 → 12719 (−64.1%)
+#20 16.78 br assets/linear-BZ30uBwb.js 5654 → 2114 (−62.6%)
+#20 16.78 gzip assets/linear-BZ30uBwb.js 5654 → 2304 (−59.3%)
+#20 16.79 br assets/mindmap-definition-YA3MSWOX-DWqHssQa.js 23140 → 6973 (−69.9%)
+#20 16.79 gzip assets/mindmap-definition-YA3MSWOX-DWqHssQa.js 23140 → 7789 (−66.3%)
+#20 16.79 br assets/ordinal-Cboi1Yqb.js 1189 → 497 (−58.2%)
+#20 16.79 gzip assets/ordinal-Cboi1Yqb.js 1189 → 573 (−51.8%)
+#20 16.79 br assets/pegDiagram-XKGWAZYB-BG_KoFQ6.js 1921 → 800 (−58.4%)
+#20 16.79 gzip assets/pegDiagram-XKGWAZYB-BG_KoFQ6.js 1921 → 905 (−52.9%)
+#20 16.80 br assets/pieDiagram-E7YTZNPT-In23DzJs.js 6259 → 2385 (−61.9%)
+#20 16.80 gzip assets/pieDiagram-E7YTZNPT-In23DzJs.js 6259 → 2605 (−58.4%)
+#20 16.82 br assets/quadrantDiagram-AXDQQJYC-DtIrN-kE.js 33975 → 8512 (−74.9%)
+#20 16.82 gzip assets/quadrantDiagram-AXDQQJYC-DtIrN-kE.js 33975 → 9922 (−70.8%)
+#20 16.82 br assets/railroadDiagram-O6MQD6OU-ByBV9o8N.js 1571 → 665 (−57.7%)
+#20 16.82 gzip assets/railroadDiagram-O6MQD6OU-ByBV9o8N.js 1571 → 735 (−53.2%)
+#20 16.84 br assets/requirementDiagram-BXWQKSXE-CGDVit9U.js 30965 → 8235 (−73.4%)
+#20 16.84 gzip assets/requirementDiagram-BXWQKSXE-CGDVit9U.js 30965 → 9698 (−68.7%)
+#20 16.86 br assets/sankeyDiagram-P5KCCOFB-DbuNAAw9.js 23163 → 7808 (−66.3%)
+#20 16.86 gzip assets/sankeyDiagram-P5KCCOFB-DbuNAAw9.js 23163 → 8534 (−63.2%)
+#20 16.95 br assets/sequenceDiagram-WJ2MYXX4-DjJuHVj7.js 116927 → 25728 (−78.0%)
+#20 16.95 gzip assets/sequenceDiagram-WJ2MYXX4-DjJuHVj7.js 116927 → 31047 (−73.4%)
+#20 16.96 br assets/stateDiagram-D77RDMKH-C8R2qgBn.js 10326 → 3308 (−68.0%)
+#20 16.96 gzip assets/stateDiagram-D77RDMKH-C8R2qgBn.js 10326 → 3602 (−65.1%)
+#20 17.05 br assets/swimlanes-42K2YHIH-DfsRAiF7.js 115756 → 36665 (−68.3%)
+#20 17.05 gzip assets/swimlanes-42K2YHIH-DfsRAiF7.js 115756 → 42418 (−63.4%)
+#20 17.07 br assets/timeline-definition-24CTP7MA-WeBLss97.js 30794 → 9104 (−70.4%)
+#20 17.07 gzip assets/timeline-definition-24CTP7MA-WeBLss97.js 30794 → 10117 (−67.1%)
+#20 17.10 br assets/vennDiagram-4TSXK5OY-mjOdrwai.js 41926 → 13976 (−66.7%)
+#20 17.10 gzip assets/vennDiagram-4TSXK5OY-mjOdrwai.js 41926 → 15661 (−62.6%)
+#20 17.12 br assets/wardleyDiagram-VM6X3IG4-CX23Vy_T.js 25467 → 6071 (−76.2%)
+#20 17.12 gzip assets/wardleyDiagram-VM6X3IG4-CX23Vy_T.js 25467 → 6742 (−73.5%)
+#20 17.15 br assets/xychartDiagram-S5SC5T6Z-BHknuwFK.js 44474 → 11037 (−75.2%)
+#20 17.15 gzip assets/xychartDiagram-S5SC5T6Z-BHknuwFK.js 44474 → 12554 (−71.8%)
+#20 17.15 br fonts/OFL.txt 4474 → 1437 (−67.9%)
+#20 17.15 gzip fonts/OFL.txt 4474 → 1993 (−55.5%)
+#20 17.15 precompress: wrote 49 .br and 49 .gz
+#20 DONE 17.2s
+
+#15 [go-builder 4/7] RUN go mod download
+#15 DONE 80.6s
+
+#21 [go-builder 5/7] COPY . .
+#21 DONE 0.5s
+
+#22 [go-builder 6/7] RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /server ./cmd/server
+#22 DONE 5.7s
+
+#23 [go-builder 7/7] RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /events ./cmd/events
+#23 DONE 0.4s
+
+#24 [stage-2 4/9] COPY --from=go-builder /server /app/server
+#24 DONE 0.0s
+
+#25 [stage-2 5/9] COPY --from=go-builder /events /app/events
+#25 DONE 0.0s
+
+#26 [stage-2 6/9] COPY --from=web-builder /web/dist /app/web/dist
+#26 DONE 0.0s
+
+#27 [stage-2 7/9] COPY deploy/postgres/goose /app/deploy/postgres/goose
+#27 DONE 0.0s
+
+#28 [stage-2 8/9] COPY templates /app/templates
+#28 DONE 0.0s
+
+#29 [stage-2 9/9] COPY configs /app/configs
+#29 DONE 0.0s
+
+#30 exporting to image
+#30 exporting layers
+#30 exporting layers 0.5s done
+#30 exporting manifest sha256:6ef5fa2036e4f1d6fdb7063202a61a3e4d391e7c3fdd3e40f70dc2d0b4f690b6 done
+#30 exporting config sha256:1e0ba100057ae00271522987f0f8c5561ed9c07d0a69a6e73dbf57c861bd8cd7 done
+#30 exporting attestation manifest sha256:e7f4f96b5f60af59fd926fd336d0feb2b0bf9f773eb481affba876c0c2a2866a done
+#30 exporting manifest list sha256:2d74fe184585ec0d0d24a051cd6bbc0cfb5b2ef050a376a32027c8e442703cd1 done
+#30 naming to docker.io/library/agent-dev-app:latest done
+#30 unpacking to docker.io/library/agent-dev-app:latest
+#30 unpacking to docker.io/library/agent-dev-app:latest 0.2s done
+#30 DONE 0.8s
+
+#31 resolving provenance for metadata file
+#31 DONE 0.0s
+ Image agent-dev-app Built
diff --git a/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/rebuild-start.txt b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/rebuild-start.txt
new file mode 100644
index 00000000..6cc58849
--- /dev/null
+++ b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/rebuild-start.txt
@@ -0,0 +1,2 @@
+2026-09-17T08:18:26.300033723Z
+/shuimu-agent-app-dev StartedAt=2026-09-17T07:00:38.127811581Z Status=running
diff --git a/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/restart-timeline-nocache.txt b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/restart-timeline-nocache.txt
new file mode 100644
index 00000000..81a004d8
--- /dev/null
+++ b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/restart-timeline-nocache.txt
@@ -0,0 +1,5 @@
+StartedAt=2026-09-17T08:22:48.548364949Z
+time=2026-09-17T08:22:48.660Z level=INFO msg="goose: no migrations to run. current version: 49"
+time=2026-09-17T08:22:48.676Z level=INFO msg="[kb] online=true dsn=postgres://regkb:***@shuimu-kb-shared:5432/regulations?sslmode=disable"
+监听地址: http://0.0.0.0:8080
+curl_ready_at=2026-09-17T08:23:03Z
diff --git a/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/restart-timeline.txt b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/restart-timeline.txt
new file mode 100644
index 00000000..03d33562
--- /dev/null
+++ b/.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/restart-timeline.txt
@@ -0,0 +1,33 @@
+=== timeline ===
+StartedAt=2026-09-17T08:19:20.17479594Z Status=running
+time=2026-09-17T08:19:20.287Z level=INFO msg="goose: no migrations to run. current version: 49"
+time=2026-09-17T08:19:20.321Z level=INFO msg="[kb] online=true dsn=postgres://regkb:***@shuimu-kb-shared:5432/regulations?sslmode=disable"
+==================================================================
+ 🤖 医疗器械商务与研发智能参谋系统 - HTTP / SSE API 守护服务
+==================================================================
+服务环境: dev | 智能体后端: pi-agent
+监听地址: http://0.0.0.0:8080
+核心服务路由:
+ • [GET] /api/v1/health - 服务健康检查与基础设施状态
+ • [GET] /api/v1/projects - 查询项目当前上下文与黑板事实
+ • [POST] /api/v1/chat - 标准阻塞式对话协同接口
+ • [POST] /api/v1/chat/stream - 核心 SSE 流式长连接对话协议 (分层按需)
+ • [GET] /api/v1/chat/stream - SSE 流式长连接对话调试接口 (EventSource)
+ • [POST] /api/v1/tasks/run/stream - 独立任务与阶段执行 SSE 监控流 (精简进度与拦截)
+ • [GET] /api/v1/context/user - 获取单用户私有上下文与习惯偏好画像
+ • [PUT] /api/v1/context/user/preference - 整理或更新用户个性化产出风格
+ • [GET] /api/v1/context/project - 获取项目多方协同黑板事实与里程碑决策流
+ • [GET] /api/v1/chat/sessions - 分页查询用户/项目历史会话列表
+ • [GET] /api/v1/chat/messages - 分页拉取指定会话多轮历史消息记录
+ • [GET] /api/v1/context/cases/recommend - 往期受控标杆案例与历史报价语义自推荐
+ • [GET] /api/v1/docgov/document - 查询受控文档治理状态看板
+ • [POST] /api/v1/docgov/claim - 查阅并认领受控文档 (正式稿方可认领)
+ • [POST] /api/v1/docgov/proposal/decide - 编制负责人拍板同意/拒绝变更提案
+ • [POST] /api/v1/docgov/submit-review - 编制完成提交审核 (文档正文锁定)
+ • [POST] /api/v1/docgov/review-decision - 审核通过或驳回 (驳回必填原因且解锁)
+ • [POST] /api/v1/docgov/approver-decision - 最终批准或驳回
+ • [GET/POST] /api/v1/docgov/comments - 批注与修改建议管理
+ • [GET] /api/v1/docgov/audit-logs - 全生命周期审计轨迹流
+==================================================================
+--- health ---
+2026-09-17T08:19:24.180176416Z health=200 ready=200