merge: 集成V2.6 性能增强与小宝后台化

# Conflicts:
#	apps/server/prisma/schema.prisma
#	apps/server/src/app.module.ts
#	apps/web/components/layout/Sidebar.tsx
#	docs/architecture.md
#	docs/decisions.md
#	docs/roadmap.md
This commit is contained in:
2026-07-08 18:04:39 +08:00
60 changed files with 4933 additions and 46 deletions

View File

@@ -157,6 +157,27 @@ V2.5 控制面新增三类横切能力:
- V2.6 在关系表主源稳定后做大数据性能增强和小宝预警后台化;性能基础不后置,增强项包括压测、慢查询治理、缓存/摘要、后台任务、幂等和失败重试。
- V2.7 面向企业级协作与管理治理V2.8 面向生产硬化与运维闭环生产部署基线已经存在V2.8 重点是备份恢复演练、发布 smoke test、监控告警、日志检索、迁移回滚和运维手册。
## Background Job Runtime Layer (V2.6)
V2.6 introduces a database-backed background job runtime for server-side refresh work that must not depend on a user opening a page.
- Storage: `background_jobs` stores `type`, `payload`, `dedupe_key`, `status`, `attempts`, `max_attempts`, `available_at`, `locked_by`, `locked_until`, and `last_error`.
- Dedupe: active jobs (`queued` / `running`) are unique by `(type, dedupe_key)` when `dedupe_key` is present. Services still check first and recover from unique conflicts to stay idempotent under concurrent enqueue.
- Lease: `JobLockService.claimNext()` uses `FOR UPDATE SKIP LOCKED` and treats expired `running` rows as claimable, so a crashed worker can be recovered by a later worker.
- Retry: failed handlers are requeued while `attempts < max_attempts`; terminal failures keep `last_error` and move to `failed`.
- Worker boundary: `BackgroundJobWorker` is a small handler registry and single-job runner. Domain modules register typed handlers and only write through their own services.
This runtime is intentionally DB-backed first. Redis is already available in deployment, but V2.6 jobs need transactional dedupe with domain writes more than high-throughput queue semantics.
## Runtime Ops Dashboard (V2.6)
V2.6 adds an Ops runtime surface for local operators and future production admins:
- Backend: `OpsModule` exposes `GET /api/v1/ops/runtime`, reading recent in-memory slow API request events, recent in-memory slow Prisma query events, `background_jobs` queue rows, and dirty `xiaobao_risk_summaries` count.
- Capture: `ApiTimingInterceptor` and `PrismaService` still log slow events, and also append redacted bounded previews into the Ops runtime buffer. SQL query parameters are not exposed; request query strings and key-like values are stripped or redacted.
- Jobs: the dashboard summarizes queued/running/succeeded/failed jobs by type and shows recent terminal failures with redacted `lastError`.
- Permissions: the frontend route is guarded by `ops:view`. Backend RBAC is represented by `OpsPermissionAdapter` until the V2.5 RBAC contract lands, so the replacement point is explicit instead of hard-coupled to temporary role data.
## 生产部署层2026-07-01
当前仓库已补齐云服务器生产部署基线:
@@ -260,7 +281,16 @@ The rule surface stays in pure frontend engines:
Managers with `xiaobao.warning:manage` can see all unfinished versions. Non-managers with `xiaobao.warning:view` can only see unfinished versions where the current user is in `version.members`.
AI explains rule results only. It writes interpretation cache to `xiaobao-risk-insights` and never mutates Version, Requirement, DevTask, TestCase, Bug, or Member data. Risk snapshots are saved to `xiaobao-risk-snapshots` when the page is opened. The first version uses page-triggered analysis rather than a background scheduled Agent.
AI explains rule results only. It writes interpretation cache to `xiaobao-risk-insights` and never mutates Version, Requirement, DevTask, TestCase, Bug, or Member data. Risk snapshots are saved to `xiaobao-risk-snapshots` when the page is opened.
V2.6 moves the current risk summary refresh to the server:
- `XiaobaoRiskService.refreshSummary(versionId)` recomputes deterministic rule output from Version, DevTask, TestCase, Bug, WorkActivity, and TaskWorklog relation rows, then upserts `xiaobao_risk_summaries` with `dirty=false`.
- `XiaobaoRiskWorker` registers the `xiaobao.summary.refresh` background job handler, so dirty summaries can be refreshed without opening `/xiaobao-warning`.
- Domain writes that produce work activity already mark the affected version dirty; V2.6 also enqueues a deduped refresh job. Plain update/delete paths for version plans, dev tasks, test cases, and bugs explicitly mark the version dirty as well.
- `XiaobaoAiService` evaluates the refreshed summary and enqueues `xiaobao.ai.interpret` when policy allows. The worker reloads the latest summary, skips stale signatures, calls the existing `AiService.interpretRisk()` prompt path, and writes only `xiaobao_risk_insights`.
- AI interpretation cache uses the summary `riskSignature`, exact cache reuse, a six-hour cooldown, and risk-level escalation bypass. Until the server has full daily trend snapshots, `attention` summaries trigger server-side AI only when release is within one day and unfinished work remains.
- Frontend `/xiaobao-warning` still consumes V2.2 summary reads first and only falls back to AppData calculation when summaries are empty or unavailable.
Per-user warning read state is saved to `xiaobao-warning-views`. The read marker stores `userId + versionId + risk signature`, so the sidebar can turn the Xiaobao badge blue when any visible risk has a completed unread update, then return to the red risk-count badge after the user opens every updated warning. AI interpretation that is still generating only shows the "updating" notice and must not produce the blue update badge yet.
## V2.2 Partitioned Domain Data Layer (2026-07-03)

View File

@@ -623,3 +623,60 @@
- Xiaobao risk snapshots/insights 的 AppData key 进入 `read_only_archive`,关系表写入和后台化归 V2.6`xiaobao-warning-views` 读状态 API 归 V2.7。
**理由**:冻结写入能立即切断新的双主源风险,同时保留旧 JSON 的审计和回滚价值。把权限和审计合并到领域 mutation 装饰器,可以确保后续新增写接口默认带服务端 guard 和 audit event。审计覆盖对历史数据只告警避免为了“补齐历史审计”伪造事件。auth header adapter 给 V2.5 一个可测试的服务端权限边界,但不把它包装成最终安全方案,后续 JWT/企业 RBAC 可以替换 adapter 而不改领域 controller 合同。
## 48. V2.6 后台任务先采用 PostgreSQL Lease 队列
**问题**小宝风险摘要、AI 解读和后续通知都需要在用户不打开页面时后台刷新。直接把这些逻辑放在页面 effect 中会导致无人访问时数据不更新;直接引入 Redis queue 又会增加一套可靠性、幂等和迁移运维面。
**决策**
- 新增 `background_jobs` 表和 `JobsModule`,作为 V2.6 后台任务运行时。
- Job 行包含 `type``payload``dedupe_key``status``attempts``max_attempts``available_at``locked_by``locked_until``last_error`
- 同一 `type + dedupe_key``queued/running` 状态下唯一;服务层先查 active job遇到并发唯一冲突再回读保证 enqueue 幂等。
- Worker claim 使用数据库事务、`FOR UPDATE SKIP LOCKED` 和 lease 时间;`running``locked_until` 过期的 job 可以被新 worker 回收。
- Handler 失败时按 `attempts < max_attempts` 重回 `queued` 并设置下一次 `available_at`;达到上限后进入 `failed`,只记录错误,不修改业务实体。
- `BackgroundJobWorker` 只负责 handler 注册和单次执行,业务副作用仍放在各领域 service 内,避免队列层知道小宝、通知或审计细节。
**理由**PostgreSQL 队列足够支撑 V2.6 的低频后台刷新,同时能和领域写入共享事务边界、唯一约束和迁移流程。等 V2.7 通知或更高吞吐任务落地后,如确实需要 Redis/专用队列,再通过同一 `JobsService` 接口替换底层实现,而不是现在提前引入第二套事实源。
## 49. V2.6 小宝风险摘要改为服务端后台刷新
**问题**:小宝预警最初由页面加载完整前端 store 后计算并保存快照/缓存。这样会导致没人打开页面时 `xiaobao_risk_summaries` 不刷新,侧边栏和 V2.2 快读只能看到旧风险。
**决策**
- 新增 `XiaobaoModule`,包含 `XiaobaoRiskService``XiaobaoRiskWorker` 和最小 controller。
- 服务端先移植确定性规则的核心口径:剩余开发/测试/Bug 工作量、关键缺陷、阻塞项、失败用例、预测延期、置信度和 risk signature。
- `XiaobaoRiskService.markDirtyAndEnqueue(versionId)` 负责 upsert dirty summary 并排入 `xiaobao.summary.refresh`dedupe key 使用 `versionId`
- `XiaobaoRiskWorker` 通过 V2.6 `BackgroundJobWorker` 注册 handler执行时只刷新 `xiaobao_risk_summaries`,不修改 Version、Requirement、DevTask、TestCase、Bug 或 Member。
- 领域写入侧继续通过 `WorkActivityService.markXiaobaoSummaryDirty()` 收口;普通 update/delete 没有 activity 证据时显式标脏,避免风险摘要漏刷新。
**理由**:把 deterministic summary 放到服务端后,读路径不再依赖页面打开,且所有前端仍可沿用 V2.2 summary API。AI 解读仍是后续独立队列,只消费 summary/signature 并写 insight cache本决策不让 AI 或后台 worker 直接改业务实体。
## 50. V2.6 小宝 AI 解读改为服务端队列,只写 insight cache
**问题**:小宝 AI 解读原先由 `/xiaobao-warning` 页面触发。即使 V2.6 已经把 deterministic summary 刷新移到服务端,如果 AI 解读仍依赖页面打开,高风险版本在无人访问时仍不会产生新的解释缓存,也不利于后续 V2.7 通知使用同一解读结果。
**决策**
- 新增 `XiaobaoAiModule`,通过 `XiaobaoAiService``XiaobaoAiWorker` 注册 `xiaobao.ai.interpret` job。
- `XiaobaoRiskService.refreshSummary()` upsert summary 后调用 `XiaobaoAiService.evaluateSummary()`,按 policy 判断是否排入 AI 解读 job。
- AI 触发策略复用页面规则的核心边界:`at_risk``likely_delayed``blocked` 可触发;精确 `riskSignature` 命中时复用缓存;同版本最近 6 小时内已有解读时 cooldown风险等级升级可绕过 cooldown。
- 服务端当前没有完整前端趋势快照上下文,因此 `attention` 只在“距离预期发版日小于等于 1 天且仍有未完成工作”时触发。趋势、置信度下降和明细信号变化的完整 attention 策略等待服务端趋势快照补齐后再扩展。
- Worker 执行时重新读取 `xiaobao_risk_summaries`,若 job payload 的 `riskSignature` 已过期则跳过,避免为旧风险写新解释。
- AI 调用只走现有 `AiService.interpretRisk()` 和 risk prompt/provider 抽象,不新增 SDK 调用、不绕过 AI 配置。
- AI 成功后只写 `xiaobao_risk_insights`,缓存保存时间使用服务端 `now`,不信任模型返回的 `generatedAt` 作为缓存新鲜度;失败抛错交给 background job retry。
- Worker 不修改 Version、Requirement、DevTask、TestCase、Bug、Member 等业务实体也不写通知。V2.7 通知如需消费结果,应通过 insight cache 或 adapter 读取。
**理由**AI 解读是对确定性规则结果的解释层,不是业务事实源。把它做成 summary 后置队列,能让无人打开页面时也生成解释,同时通过 signature/cooldown/escalation 控制成本和重复调用。只写 cache 能保持 AI 与业务实体解耦,后续通知和审计可以复用缓存,而不是让 AI worker 直接参与业务状态流转。
## 51. V2.6 运维看板先做轻量运行时快照RBAC 通过 adapter 衔接
**问题**V2.6 增加了性能 harness、后台 job runtime、小宝 summary refresh 和 AI 解读队列。如果没有一个运行时入口慢请求、慢查询、job 堆积和 dirty summary 数只能从日志或数据库手工排查。与此同时V2.5 后端 RBAC/audit 合同尚未落地,不能为了看板临时硬编码一套后端权限结构。
**决策**
- 新增 `OpsModule`,提供 `GET /api/v1/ops/runtime`,返回慢请求、慢 Prisma 查询、后台任务队列、失败任务和 dirty summary 数。
- 慢请求继续由 `ApiTimingInterceptor` 识别;慢查询继续由 `PrismaService` query event 识别。二者额外写入进程内 ring buffer作为轻量 dashboard 数据源。
- 看板只保留最近事件,不做长期审计。长期审计和多实例聚合等待 V2.5 audit 或后续 observability 方案。
- 请求 URL 去掉 query stringSQL 只展示截断后的 query preview`sk-*`、token、secret、password、authorization 等 key-like 文本统一 redacted不展示 AI provider apiKey、请求参数或环境变量。
- Job 队列从 `background_jobs` 最近 200 行聚合,按 type 展示 queued/running/succeeded/failed并展示最近 failed job 的脱敏 `lastError`
- 前端 `/admin/ops` 使用 `RouteGuard permission="ops:view"`;权限字典新增 `ops:view`,但不默认授给非管理员 preset。后端通过 `OpsPermissionAdapter` 保留 `ops:view` 校验入口,待 V2.5 RBAC guard 落地后替换。
**理由**:当前目标是让 V2.6 的性能和后台化能力可观察,而不是建设完整监控平台。进程内 ring buffer 成本低、对生产数据无额外写放大;结合脱敏规则可避免把 secrets 带进管理端。权限 adapter 明确了未来替换点,避免 Ops 看板和未定型 RBAC/audit 合同互相绑死。

View File

@@ -0,0 +1,79 @@
# V2.6 Hot Query Budget And Index Audit
This document records the V2.6 query budget for the large-data harness and the index contracts that keep hot APIs on partition keys.
## Commands
Offline contract audit:
```bash
node scripts/explain-hot-queries.mjs --dry-run
```
Database explain audit:
```bash
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ftb_pm pnpm perf:explain
```
Strict plan mode is available for seeded medium/large databases:
```bash
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ftb_pm pnpm perf:explain -- --strict-plan
```
`--strict-plan` fails on sequential scans. It is useful after the medium fixture is seeded and analyzed, but not required for empty or tiny local databases where PostgreSQL may choose a sequential scan correctly.
## Budgets
| Area | Query Shape | Budget |
| --- | --- | --- |
| `health/version` | no database query | HTTP p95 <= 500ms |
| Requirement pool | `requirements.product_id` + optional filters/search, cursor, `created_at` sort | HTTP p95 <= 1000ms |
| Version detail | root version plus child rows by `version_id` | HTTP p95 <= 1500ms |
| Workspace | owner/assignee unfinished rows | HTTP p95 <= 1200ms |
| Xiaobao warnings | non-`on_track` summaries by score | HTTP p95 <= 1000ms |
| Xiaobao dirty queue | `dirty=true` summaries ordered by `updated_at` | background batch <= 100 rows |
| Audit search adapter | V2.5 audit table pending; `ai_logs` is the current AI audit surface | explain-only contract |
## Required Index Contracts
V2.6 keeps the existing partition prefixes:
- Requirement pool queries must include `productId`; `requirements` is hash-partitioned by `product_id`.
- Version detail child queries must include `versionId`; `dev_tasks`, `test_cases`, and `bugs` are hash-partitioned by `version_id`.
- Append evidence tables stay range-partitioned by `created_at`; background workers must still filter by `version_id`, `user_id`, or date before scanning.
Added in migration `20260708030000_v26_hot_query_indexes`:
| Index | Purpose |
| --- | --- |
| `projects_product_created_at_idx` | product-scoped project list |
| `versions_product_created_at_idx` | product-scoped version list |
| `versions_product_project_created_at_idx` | project-scoped version list |
| `version_plans_owner_open_due_idx` | workspace plan queue |
| `dev_tasks_assignee_open_priority_idx` | workspace dev task queue |
| `test_cases_assignee_open_priority_idx` | workspace test case queue |
| `bugs_version_status_priority_updated_at_idx` | version detail bug ordering |
| `bugs_assignee_open_priority_idx` | workspace bug queue |
| `test_cases_version_round_status_updated_at_desc_idx` | version detail test case ordering |
| `xiaobao_risk_summaries_warning_score_idx` | manager Xiaobao warning list |
| `xiaobao_risk_summaries_dirty_updated_at_idx` | background Xiaobao dirty summary queue |
| `work_activities_version_occurred_at_idx` | Xiaobao evidence recompute |
Existing V2.2 indexes remain part of the contract, including requirement pool indexes, version child indexes, workspace partial indexes, task worklog date indexes, Xiaobao snapshot/insight indexes, and `ai_logs` operation/status indexes.
## Audit Adapter Note
The V2.5 RBAC/audit contract is not present in this branch. V2.6 therefore documents `audit.searchAdapter` as an adapter target instead of inventing a temporary audit table. When audit lands, the expected query shape should be:
```sql
SELECT *
FROM audit_events
WHERE product_id = $1
AND created_at >= $2
ORDER BY created_at DESC
LIMIT 100;
```
Expected future index: `(product_id, created_at DESC)` plus actor/resource indexes required by the audit module. Until then, `ai_logs_operation_created_at_idx` and `ai_logs_status_created_at_idx` cover AI operation audit searches only.

104
docs/performance.md Normal file
View File

@@ -0,0 +1,104 @@
# V2.6 Performance Harness
V2.6 adds a deterministic large-data fixture and a small HTTP performance harness for the current hot paths. The goal is to make performance regressions visible before adding more background jobs and Xiaobao automation.
## Fixture Sizes
The fixture script creates only `perf-*` rows and can be rerun safely. It covers:
- products
- projects
- versions
- requirements
- version plans
- dev tasks
- test cases
- bugs
- work activities
- Xiaobao risk summaries
Preset sizes:
| Size | Purpose |
| --- | --- |
| `small` | Local smoke fixture. Fast dry-run and minimal database seed. |
| `medium` | Default performance gate for V2.6 hot APIs. |
| `large` | Stress fixture for query/index audit work. |
Stable anchors used by the harness:
```text
productId=perf-product-001
versionId=perf-version-001-001-001
userId=perf-user-dev-01
```
## Commands
Dry-run without database access:
```bash
node scripts/seed-large-dataset.mjs --size small --dry-run
node scripts/perf-check.mjs --base-url http://localhost:3001/api/v1 --dry-run
```
Seed a database:
```bash
pnpm perf:seed -- --size small
```
Run the hot-path harness against a running NestJS API:
```bash
pnpm perf:check -- --base-url http://localhost:3001/api/v1
```
Audit SQL plans and hot-path indexes:
```bash
pnpm perf:explain -- --dry-run
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ftb_pm pnpm perf:explain
```
## Hot Probes
`perf-check` measures p50 and p95 latency, records HTTP status code counts, and exits non-zero when a request fails or p95 exceeds the current query budget.
| Probe | Endpoint | p95 Budget |
| --- | --- | ---: |
| Runtime version | `/health/version` | 500ms |
| Requirement pool | `/v2.2/requirements?productId=perf-product-001&q=REQ&limit=50` | 1000ms |
| Version detail | `/v2.2/versions/perf-version-001-001-001/detail-data` | 1500ms |
| Workspace | `/v2.2/workspace?userId=perf-user-dev-01` | 1200ms |
| Xiaobao warning | `/v2.2/xiaobao-warning?manager=true` | 1000ms |
The medium fixture is the V2.6 acceptance target. Large fixture runs are for index audit and explain-plan work, not for every local commit.
See `docs/performance-hot-queries.md` for query budgets, partition-key contracts, and required indexes.
## Runtime Ops Dashboard
`/admin/ops` provides the V2.6 runtime view for checking whether the hot paths and background workers stay healthy after fixture/perf runs.
It reads `GET /api/v1/ops/runtime` and shows:
- recent slow API requests captured by `ApiTimingInterceptor`
- recent slow Prisma query previews captured by `PrismaService`
- `background_jobs` totals and per-type queued/running/succeeded/failed counts
- recent failed jobs with redacted `lastError`
- dirty `xiaobao_risk_summaries` count
Access is guarded in the frontend by `ops:view`. Backend RBAC is currently an explicit `OpsPermissionAdapter` placeholder until the V2.5 RBAC contract lands.
Secret handling:
- request query strings are stripped before display
- SQL is shown only as a bounded query preview, without Prisma parameters
- key-like text such as `sk-*`, token, secret, password, and authorization is redacted
## Notes
- `seed-large-dataset` uses deterministic IDs and dates so repeated runs are comparable.
- Non-dry-run seeding deletes and recreates only `perf-*` rows.
- The harness intentionally depends on public API endpoints instead of calling Prisma directly; it measures the same path the frontend uses.

View File

@@ -1,12 +1,14 @@
# 开发路线图
## 当前阶段V2.5 已完成 — 下一阶段 V2.6 大数据性能增强 + 小宝预警后台化
## 当前阶段V2.6 已完成 — 下一阶段 V2.7 企业协作 + V2.8 运维闭环集成
V2.4 已将高增长和核心业务领域从“AppData 主写 + 关系表同步副本”推进到“领域 CRUD 主写关系表 + AppData 兼容/迁移兜底”。V2.2 快读 API 和 V2.3 AppData 写后同步继续保留,但它们现在是兼容基础设施,不再是已迁移领域的数据新鲜度主链路。
V2.5 的目标是正式收口后端权限、审计、AppData 禁写和一致性核对。AppData 不能直接删除,必须按“禁写 → 双读核对 → 移除 fallback → 只读归档/导出 → 后续删表”的顺序推进。
### V2.5 完成范围
V2.6 的目标是在关系表主源稳定后完成大数据性能增强、小宝风险后台化、AI 解读队列和运行时 Ops 看板,让高增长热路径、后台任务和风险摘要不再依赖页面打开。
### V2.5-V2.6 完成范围
1. **RBAC 收口**:领域 mutation API 已接入服务端权限校验、资源作用域和当前用户上下文。
2. **审计事件**:领域 mutation 通过 `audit_events` 写 append-only audit event支持后台查询和敏感字段脱敏。
@@ -14,6 +16,10 @@ V2.5 的目标是正式收口后端权限、审计、AppData 禁写和一致性
4. **导出归档**:已提供 AppData archive export/verify 脚本,包含 checksum、key list 和应用版本元数据。
5. **一致性校验**:已提供 counts、partition key、orphan refs、audit coverage 的本地脚本和后台页面。
6. **管理端可视化**:已补 `/admin/audit``/admin/consistency`,并由 `audit:view` / `consistency:view` 控制。
7. **性能压测与热查询治理**:已补 deterministic fixture、`perf:check``perf:explain`、热查询索引审计和性能预算文档。
8. **后台任务运行时**:已补 PostgreSQL-backed `background_jobs`、dedupe、lease、retry、失败记录和单步 worker。
9. **小宝后台化**:已补服务端 summary refresh、dirty/enqueue 桥接和 `xiaobao.ai.interpret` AI 解读队列。
10. **Ops 看板**:已补 `/admin/ops``GET /api/v1/ops/runtime`展示慢请求、慢查询、job 队列和 dirty summary 数。
## V2 分阶段交付链路
@@ -42,10 +48,22 @@ V2.5 的目标是正式收口后端权限、审计、AppData 禁写和一致性
- 需求池已切到服务端分页、搜索、筛选、排序,不再要求加载全量 AppData 文档。
- `packages/shared` 状态契约已统一为当前业务状态机。
- V2.6/V2.7 协调边界Xiaobao risk snapshots/insights 关系表写入和后台化归 V2.6warning read-state API、部门/角色/密码规则/加班原因配置表归 V2.7。
- V2.6.1 已新增 deterministic large-data fixture、HTTP performance harness 和性能预算文档。
- V2.6.2 已新增 hot query explain/index audit 脚本、热查询索引迁移和 `docs/performance-hot-queries.md`
- V2.6.3 已新增 PostgreSQL-backed `background_jobs` 运行时、去重/lease/retry 语义和 jobs 单元测试。
- V2.6.4 已新增服务端小宝风险 summary refresh、后台 job handler以及领域写入 dirty/enqueue 桥接。
- V2.6.5 已新增服务端小宝 AI 解读队列summary 刷新后按 signature/cooldown/escalation policy 入队,只写 `xiaobao_risk_insights` 缓存。
- V2.6.6 已新增 `/admin/ops` 运行时看板和 `GET /api/v1/ops/runtime`展示慢请求、慢查询、job 队列和 dirty summary 数。
### 已完成(按时间倒序)
**2026-07-08**
- V2.6.6 added the Ops runtime dashboard with `ops:view`, redacted slow request/query buffers, background job queue summary, failed job list, and dirty Xiaobao summary count.
- V2.6.5 moved Xiaobao AI interpretation behind the background job runtime, reusing `AiService.interpretRisk()` and writing only insight cache rows.
- V2.6.4 moved deterministic Xiaobao risk summary refresh into the server, registered the `xiaobao.summary.refresh` background job handler, and enqueue refresh jobs from dirty domain writes.
- V2.6.3 added DB-backed background jobs with active dedupe keys, lease-based claiming, expired lock recovery, retry/terminal-failure handling, and a small handler worker.
- V2.6.2 added `perf:explain`, hot query explain targets, index audit documentation, and V2.6 hot-path indexes for workspace, Xiaobao warning/dirty queues, project/version lists, and evidence scans.
- V2.6.1 added deterministic small/medium/large fixture generation, `perf:check`, and `docs/performance.md` for hot API p50/p95 budgets.
- V2.5.0 added server auth context, current-user decorator, permission decorator/guard/service, wildcard super admin support, project/version-member scope checks, and guard/service tests.
- V2.5.1 added append-only `audit_events`, audit service/controller/query DTO, sensitive-field redaction, `audit:view`, and audit service/controller tests.
- V2.5.2 protected V2.4 domain mutation APIs with server-side permission metadata and audit writes through `@ProtectedMutation()`.

View File

@@ -339,9 +339,9 @@ Implementation convention:
- `xiaobao.warning:manage`:查看所有未结束版本的预警。
- `xiaobao.warning:view`:仅查看当前用户在 `version.members` 中的未结束版本。
页面打开时会聚合版本下的计划、开发任务、测试用例、Bug、日报和工作活动,计算当前风险并保存当天快照。页面使用 `buildXiaobaoWorkItems`版本级聚合,不使用个人工作台的 `aggregateWorkItems(userName, ...)` 过滤。快照按同版本同日节流保存:重大变化立即保存,普通变化 10 分钟内不重复写入
V2.6 后小宝当前 summary 由服务端后台刷新:领域写入标记 `xiaobao_risk_summaries.dirty=true` 并排入 `xiaobao.summary.refresh`worker 从版本下的计划、开发任务、测试用例、Bug、日报和工作活动重新计算风险。页面仍可用前端 `buildXiaobaoWorkItems`兼容聚合和快照保存,但默认优先读取 V2.2 summary
AI 解读不由人工按钮触发。`at_risk``likely_delayed``blocked` 自动触发;`attention` 在风险分明显上升、趋势连续上升、关键 Bug 增加、测试失败、阻塞增加、静默风险增加、置信度下降或预测发版日延后时触发。缓存命中时复用解读;同版本最近 6 小时内已有解读时进入 cooldown不重复请求风险等级升级时可绕过缓存保存时间使用客户端时间,不信任模型返回的 `generatedAt` 作为缓存新鲜度。
AI 解读不由人工按钮触发。服务端 summary 刷新后按 policy 排入 `xiaobao.ai.interpret``at_risk``likely_delayed``blocked` 自动触发;`attention` 当前服务端只在临近发版且仍有未完成工作时触发,页面完整趋势策略仍保留作为兼容。缓存命中时复用解读;同版本最近 6 小时内已有解读时进入 cooldown不重复请求风险等级升级时可绕过缓存保存时间使用服务端写入时间,不信任模型返回的 `generatedAt` 作为缓存新鲜度。
静默风险包括长期无更新、无日报、无活动、进行中事项无人处理等信号。日报和工作活动是风险解释的重要证据,必须进入 AI 解读输入。