docs(ai): 设计业务分析Agent

新增 Business Analysis Agent 设计稿,明确 Semantic Layer、Metric Catalog、Analysis Strategy、Analysis Plan Processor、Metric Engine、统一 ChartSpec、Insight/Report/Evidence/Follow-up 和 Apple Vision 图表规范。

同步记录关键架构决策,约束 AI 只提出分析计划建议,系统校验规范化后执行,且不得绕过权限或直接生成 SQL。

Co-Authored-By: GPT-5 Codex <codex@openai.com>
This commit is contained in:
2026-07-08 19:59:53 +08:00
parent 32aaf53b26
commit 5933b84bf6
2 changed files with 765 additions and 0 deletions

View File

@@ -694,3 +694,25 @@
- 治理字典使用软删除或使用中禁止硬删,变更必须写审计。 - 治理字典使用软删除或使用中禁止硬删,变更必须写审计。
**理由**:适配器把协作治理模块的权限和审计接入点收束在一层,既能复用 V2.5 的服务端控制面,也给后续 JWT/NextAuth 和企业级角色体系留下替换点。稳定事件名和多态评论引用能避免后续模块继续扩散 ad-hoc 字段。 **理由**:适配器把协作治理模块的权限和审计接入点收束在一层,既能复用 V2.5 的服务端控制面,也给后续 JWT/NextAuth 和企业级角色体系留下替换点。稳定事件名和多态评论引用能避免后续模块继续扩散 ad-hoc 字段。
## 53. Business Analysis Agent 采用语义层、指标目录和受控分析计划
**问题**:下一阶段需要让用户用自然语言围绕产品、项目、版本、需求、部门和用户多维度提问,并自动生成图表与分析报告。如果只做“问题 -> 固定模板 -> 查询”,后续会被模板数量卡住;如果让 AI 直接决定查询或生成 ECharts option则会带来权限绕过、口径不一致、不可复现和难以维护的问题。
**决策**
- 新增独立 Business Analysis Agent只读业务数据不修改任何业务实体、不创建草案、不触发状态流转。
- 自然语言先进入 Semantic Layer把“忙 / 压力 / 风险 / 延期 / 效率 / 质量 / 需求完成”等业务说法映射到受控 `metricId``dimensionId``analysisType``timeIntent``scopeIntent`
- Semantic Layer 输出内部 `semanticConfidence`;前端只展示高/中/低置信,不展示伪精确百分比。数据充分性另用 `dataConfidence` 表达。
- 建立 Metric Catalog记录 metric `version`、公式、owner、支持维度、支持分析类型、默认图表、默认维度和默认时间口径。只要公式或计算口径变更就提升 metric version纯展示变化不升版本。
- 分析策略分三层Template Strategy 优先命中高频模板Rule Composition Strategy 是确定性系统规则组合AI Planning Strategy 只在前两者无法覆盖时生成 `AnalysisPlan` 建议。
- AI 生成的 `AnalysisPlan` 必须只使用 Semantic Layer / Metric Catalog 暴露的指标、维度、筛选和聚合能力,并经过 Analysis Plan Processor 校验与规范化后才能执行。
- Analysis Plan Processor 不只校验,也负责 Normalize将模板、规则组合和 AI proposal 统一成标准 `AnalysisPlan`Metric Engine 只消费统一格式。
- Metric Engine 输出统一 `MetricResult`。ChartSpec Builder、Insight Engine、Report Builder 和 Follow-up Builder 并行消费同一份 MetricResult避免图表和报告互相耦合。
- ChartSpec 是平台统一契约,不是 ECharts option。前端第一版用 ECharts Renderer 渲染,未来可替换为其他图表引擎。
- Evidence 不是纯 chips而是可点击数据证据包含 label、value、sourceDomain 和 drilldown filters。
- Report 固定为 Summary / Key Findings / Evidence / Suggestions / Data Scope避免不同分析回答格式漂移。
- Follow-up 分为 question、drilldown、export。第一版只允许只读追问、明细跳转和导出不允许创建会议、分配负责人等写操作。
- 没有数据时走 No Data Strategy说明请求、范围、缺少的数据和可替代分析不让 AI 编造解释。
- 权限红线Analysis Agent 只能查询当前用户已有权限的数据,自然语言不能扩大范围;无权限时拒绝或返回授权范围内的空结果。
**理由**Semantic Layer 和 Metric Catalog 能把自然语言、业务口径和数据库字段解耦metric version 和 result snapshot 能支撑历史分析复现Analysis Plan Processor 保证 AI proposal 不直接变成系统执行;统一 ChartSpec 和 MetricResult 让 ECharts 只是当前 renderer而不是长期数据契约。这样第一版可以靠固定模板稳定交付后续又能通过确定性组合和受控 AI Planning 扩展能力。

View File

@@ -0,0 +1,743 @@
# Business Analysis Agent Design
## Goal
Build a read-only Business Analysis Agent that lets users ask FTB business data questions in natural language and receive an Insight Card, a chart, an analysis report, explainable evidence, and safe follow-up options.
The first product surface is the AI Assistant business-data conversation. The same analysis engine will also be embedded in product, project, and version detail pages with the current page context pre-filled.
## Approved Direction
- Use a dedicated Business Analysis Agent instead of extending Prototype Decompose Agent or Risk Watch Agent.
- Use ECharts as the first chart renderer, but do not expose raw ECharts options as the platform contract.
- Define a platform Unified ChartSpec and render it through a frontend Chart Renderer.
- Use Apple Vision style visual rules: large whitespace, large radius, light shadow, translucent material, clear hierarchy, natural motion, and content-first charts.
- Default to the last 30 days only for time-window analysis when the user did not specify a time range. Current status, risk, and lifecycle questions must use their natural business scope instead of forcing last 30 days.
- Every answer must include a structured report, not only a chart.
- The Agent must not mutate business data, create drafts, change workflow state, or bypass permissions.
## Non-Goals
- No AI-generated SQL.
- No direct AI database access.
- No arbitrary dashboard builder in the first implementation.
- No automatic business actions such as creating meetings, assigning owners, or changing due dates.
- No colorful BI big-screen style, 3D effects, dense dashboards, or raw table dumps as the primary answer.
- No new AppData key as a source of truth.
## Core Architecture
```text
User question + optional page context
Analysis Planner
Semantic Layer
Permission Scope Resolver
Analysis Strategy
1. Template Strategy
2. Rule Composition Strategy (Deterministic)
3. AI Planning Strategy
Analysis Plan Processor
- Validate: permission, metric, dimension, aggregation, time range, data scope
- Normalize: produce one standard AnalysisPlan shape
Metric Engine
Metric Result
├─ ChartSpec Builder
├─ Insight Engine
├─ Report Builder
└─ Follow-up Builder
UI Composition
Insight Card + Chart + Report + Evidence + Follow-ups
```
### Responsibility Boundaries
- **Analysis Planner** reads the question and current page context, then produces an initial intent.
- **Semantic Layer** maps business words such as "busy", "pressure", "risk", "delay", "efficiency", and "quality" to system-owned metrics and dimensions.
- **Permission Scope Resolver** converts the current user and page context into a queryable scope. It must never widen the user's existing data access.
- **Analysis Strategy** chooses how to build the analysis plan.
- **Analysis Plan Processor** validates and normalizes all plans, including AI-generated ones.
- **Metric Engine** executes deterministic relation-table queries and aggregations.
- **ChartSpec Builder**, **Insight Engine**, **Report Builder**, and **Follow-up Builder** consume the same Metric Result in parallel.
- **UI Composition** assembles the final response for chat and context-page surfaces.
## Analysis Strategy
### 1. Template Strategy
Use fixed high-frequency templates for stable MVP analyses such as requirement completion, version risk, member workload, department workload, and Bug distribution.
Template Strategy should be preferred whenever the user question cleanly matches a known template.
### 2. Rule Composition Strategy (Deterministic)
When no complete template matches, deterministic system rules may compose known semantic concepts, metrics, dimensions, and time policies.
Example:
```text
"最近两个月延期原因变化"
→ trend + delay_reason + month + project/version scope
```
This composition is not done by AI. It is a rule engine over the Semantic Layer and Metric Catalog.
### 3. AI Planning Strategy
When neither template nor deterministic rule composition covers the question, AI may generate an Analysis Plan proposal.
AI Planning constraints:
- AI only proposes an Analysis Plan.
- The plan may only use metrics, dimensions, filters, aggregations, and time policies exposed by the Semantic Layer and Metric Catalog.
- The plan must pass Analysis Plan Processor validation and normalization before execution.
- If the plan references an unsupported metric, dimension, aggregation, filter, or scope, the system rejects it and returns a clarification or unsupported-analysis response.
Enterprise principle: AI does not directly decide what the system executes. AI proposes; the system validates, normalizes, and executes.
## Semantic Layer
The Semantic Layer is the business vocabulary boundary between natural language and system metrics.
### First Semantic Concepts
| User wording | Semantic concept | Default interpretation |
|---|---|---|
| 忙 / 负载高 | `workload` | Open item count plus estimated or actual effort, with overtime as supporting evidence |
| 压力大 | `work_pressure` | Usually workload plus overdue and overtime; lower semantic confidence than "忙" |
| 风险高 | `release_risk` | Xiaobao summary, blockers, bugs, test completion, remaining time |
| 延期 | `delay` | Past planned end or expected release, or forecast release later than target |
| 效率 | `delivery_efficiency` | Completion volume per effort; fall back to completion trend if effort data is insufficient |
| 质量差 | `quality_risk` | Open bugs, critical bugs, failed cases, blocked cases, repeated test rounds |
| 需求完成 | `requirement_completion` | Requirement status plus version delivery progress |
### Semantic Confidence
Semantic parsing must produce an internal `semanticConfidence`.
- High confidence: direct wording maps clearly to one concept, such as "延期率" → `delay_rate`.
- Medium confidence: wording is common but may carry multiple business meanings, such as "压力最大" → `work_pressure`.
- Low confidence: wording is vague or could map to unrelated metrics.
UI display should use levels, not pseudo-precise numbers:
- `high`: proceed directly.
- `medium`: proceed but show the assumed interpretation in Data Scope.
- `low`: ask a clarification or show selectable interpretations.
Do not display "AI confidence 96%" as a primary user-facing claim. Internal scores may be kept for ranking candidate interpretations.
## Metric Catalog
Metric Catalog is the stable source of truth for what the Business Analysis Agent can measure.
```ts
type MetricId = string;
type DimensionId =
| 'product'
| 'project'
| 'version'
| 'requirement_status'
| 'requirement_type'
| 'requirement_source'
| 'department'
| 'member'
| 'role'
| 'month'
| 'week'
| 'day'
| 'bug_severity'
| 'bug_status'
| 'test_status'
| 'delay_reason';
type AnalysisType =
| 'ranking'
| 'trend'
| 'comparison'
| 'distribution'
| 'composition'
| 'correlation'
| 'breakdown'
| 'summary';
type TimePolicy =
| 'current_state'
| 'last_30_days'
| 'lifecycle'
| 'user_required'
| 'explicit_range';
type ChartKind =
| 'number_card'
| 'line_area'
| 'horizontal_bar'
| 'stacked_horizontal_bar'
| 'donut'
| 'table_preview';
type MetricDefinition = {
metricId: MetricId;
version: number;
name: string;
description: string;
formula: string;
owner: string;
supportedDimensions: DimensionId[];
supportedAnalysisTypes: AnalysisType[];
defaultChart: ChartKind;
defaultDimension?: DimensionId;
defaultTimePolicy: TimePolicy;
status: 'active' | 'deprecated';
};
```
Metric versioning is required. If the formula or business calculation changes, increment `version`. Do not increment the metric version for pure chart styling, copy, or layout changes.
Metric Result and analysis reports must record:
```ts
type MetricRef = {
metricId: string;
version: number;
};
```
Historical reproducibility needs both:
- `metricRef`: which metric algorithm was used.
- `analysisSnapshot` or `resultSnapshot`: the aggregated result at the time, because live business rows may change later.
## Analysis Plan Processor
The Analysis Plan Processor replaces a narrow "validator" with a stronger validate-and-normalize boundary.
Normalized plan shape:
```ts
type DataScope =
| { type: 'self'; userId: string }
| { type: 'managed_projects'; projectIds: string[] }
| { type: 'product'; productId: string }
| { type: 'project'; projectId: string }
| { type: 'version'; versionId: string }
| { type: 'system'; reason: 'admin' | 'management_permission' };
type AnalysisPlan = {
metricRef: MetricRef;
analysisType: AnalysisType;
dimensions: DimensionId[];
timeRange?: {
start: string;
end: string;
policy: TimePolicy;
};
filters: Record<string, string | number | boolean | string[] | number[]>;
scope: DataScope;
limit?: number;
sort?: Array<{ field: string; direction: 'asc' | 'desc' }>;
};
```
### Validate
It must check:
- Current user is allowed to access the requested scope.
- Metric exists and is active.
- Metric version exists or can resolve to current active version.
- Dimensions are supported by the metric.
- Analysis type is supported by the metric.
- Aggregation is legal for the metric and dimension.
- Time range is valid and within supported business bounds.
- Filters are known, typed, and compatible with the scope.
- Requested Top N is within system limits.
### Normalize
It converts all strategy outputs into the same `AnalysisPlan` shape.
Example:
```ts
// AI or user wording
{
time: '最近半年',
metric: '延期率'
}
// normalized
{
metricRef: { metricId: 'delay_rate', version: 1 },
analysisType: 'trend',
dimensions: ['month'],
timeRange: {
start: '2026-01-01',
end: '2026-06-30'
},
filters: {},
scope: { type: 'user_accessible' },
limit: 12
}
```
The Metric Engine only accepts normalized `AnalysisPlan`.
## Time Range Rules
1. If the user specifies a time range, use that exact range.
2. If the question asks current state or risk, use current state data instead of last 30 days.
3. If the question asks trend, throughput, efficiency, effort, or change and does not specify time, use last 30 days.
4. If the question asks comparison and does not specify a baseline, use last 30 days versus the previous 30 days.
5. If the question asks lifecycle totals, use the object lifecycle.
6. Every response must show the applied time scope, data cutoff time, permission scope, and whether the analysis is current-state, time-window, comparison, or lifecycle.
## Permissions
The Business Analysis Agent can only query data the current user can already access.
First implementation scope:
- AI Assistant global analysis is available to logged-in users.
- Normal users see only data related to themselves or contexts they can access.
- Users with `management:view`, system admin permissions, or project Owner/Admin governance can analyze their managed scope.
- Product, project, and version detail analysis follows the page's existing access rules and must not widen scope.
Natural language cannot bypass permission boundaries. If a user asks for a forbidden scope, return a no-permission response or an empty authorized result with clear Data Scope.
## MVP Analysis Templates
The MVP starts with fixed templates while preserving the three-layer Analysis Strategy for future flexibility.
| Group | Template | Default chart | Time policy | Default limit |
|---|---|---|---|---|
| Risk and progress | Version risk ranking | Horizontal bar + numeric card | Current state | Top 10 |
| Risk and progress | Project or version completion trend | Smooth line area | Last 30 days if unspecified | 30 points |
| Risk and progress | Overdue item distribution | Horizontal bar | Current state | Top 10 |
| Product and requirements | Product requirement status distribution | Donut + numeric card | Current state or explicit range | All statuses |
| Product and requirements | Requirement completion trend | Smooth line area | Last 30 days if unspecified | 30 points |
| Product and requirements | Requirement source/type composition | Donut | Last 30 days if unspecified | Top 8 + other |
| People and departments | Department workload ranking | Horizontal bar | Current state | Top 10 |
| People and departments | Member pending-work ranking | Horizontal bar | Current state | Top 10 |
| People and departments | Member effort ranking | Horizontal bar + numeric card | Last 30 days if unspecified | Top 10 |
| Quality | Bug severity distribution | Stacked horizontal bar | Current state | Top 10 |
| Quality | Test pass-rate trend | Smooth line area | Last 30 days if unspecified | 30 points |
| Effort | Overtime reason composition and ranking | Donut + horizontal bar | Last 30 days if unspecified | Top 8 |
Top N must be explicit in every ranking plan. Default is Top 10. The first implementation should cap user-requested limits to a safe maximum, such as Top 20.
## Metric Result
Metric Result is the reusable output of the Metric Engine. Chart, report, insight, export, and future dashboard cards consume this result in parallel.
```ts
type MetricResult = {
metricRef: MetricRef;
analysisType: AnalysisType;
columns: Array<{ id: string; label: string; type: 'string' | 'number' | 'date' | 'percent' }>;
rows: Array<Record<string, string | number | null>>;
totals?: Record<string, string | number>;
comparison?: {
baselineLabel: string;
currentLabel: string;
deltaValue?: number;
deltaPercent?: number;
};
evidence: EvidenceItem[];
dataScope: DataScope;
generatedAt: string;
};
```
## Evidence
Evidence is clickable data proof, not only visual chips.
```ts
type EvidenceItem = {
label: string;
value: string | number;
unit?: string;
sourceDomain:
| 'product'
| 'project'
| 'version'
| 'requirement'
| 'version_plan'
| 'dev_task'
| 'test_case'
| 'bug'
| 'work_activity'
| 'task_worklog'
| 'overtime'
| 'xiaobao';
sourceLabel?: string;
drilldown?: {
type: 'list' | 'detail';
target: string;
filters: Record<string, unknown>;
};
};
```
Examples:
- `未关闭 Bug / 18 / Bug Domain / click → Bug list filtered by open statuses`
- `阻塞任务 / 6 / DevTask Domain / click → DevTask list filtered by blocked`
- `测试通过率 / 62% / TestCase Domain / click → test case detail list`
## Unified ChartSpec
ChartSpec is platform-owned and renderer-agnostic. It is not an ECharts option object.
```ts
type UnifiedChartSpec = {
kind: ChartKind;
title: string;
subtitle?: string;
dataset: {
source: Array<Record<string, string | number | null>>;
x?: string;
y?: string;
series?: string;
value?: string;
label?: string;
};
encoding: {
x?: { field: string; label: string };
y?: { field: string; label: string };
value?: { field: string; label: string; unit?: string };
color?: { mode: 'single' | 'risk' | 'semantic'; field?: string };
};
annotations?: Array<{
type: 'outlier' | 'peak' | 'target' | 'threshold';
label: string;
value?: string | number;
field?: string;
}>;
stylePreset: 'apple_vision_light' | 'apple_vision_dark';
};
```
Frontend `ChartRenderer` converts Unified ChartSpec into ECharts options. This keeps the contract stable if the renderer changes later.
## Apple Vision Chart Design System
### Overall
- White or deep neutral background.
- Large whitespace and clear hierarchy.
- Large rounded cards, light borders, soft shadows, and translucent material.
- Content first; numbers and conclusions lead the page.
- No blue gradient dashboard, no dense big-screen layout, no rainbow metrics, no 3D shine.
### Number Cards
The number is the hero.
Structure:
```text
238
已完成需求
↑ 12%
较上周期
```
Rules:
- Big number, small label.
- Comparison line is secondary.
- Risk or negative trend may use orange/red; normal values use a restrained single accent color.
### Line Charts
Use Apple Stocks-like style:
- Smooth curve.
- Subtle area gradient.
- Minimal axes and grid.
- Highlight peaks, drops, or anomaly points automatically.
- Do not draw heavy traditional grid lines.
### Bar Charts
Use horizontal bars for ranking:
```text
研发 ████████
产品 ██████
测试 ████
```
Rules:
- Single color by default.
- Rounded bar caps.
- Soft entrance animation.
- Values aligned for scanning.
- Use Top N; do not render 100 members in one chart.
### Donut and Composition Charts
- Use only when part-to-whole composition matters.
- Limit slices to Top 8 plus "其他".
- Use restrained semantic colors. Avoid five-color decoration unless categories need separation.
### Motion
- Entrance animation is soft and short.
- Tooltip follows pointer naturally.
- Hover reveals detail without moving layout.
- No dramatic loading animation or distracting particle effects.
## Insight, Report, and Follow-Ups
### Insight Card
Insight Card comes before the chart. It is one concise conclusion, such as:
```text
产品部延期事项最多,占当前延期事项的 49%。
```
It should include:
- Main conclusion.
- Main metric value.
- Trend or comparison if available.
- Confidence level if semantic or data confidence is not high.
```ts
type InsightCard = {
summary: string;
primaryValue?: {
label: string;
value: string | number;
unit?: string;
};
comparison?: {
label: string;
direction: 'up' | 'down' | 'flat';
value: string | number;
tone: 'positive' | 'negative' | 'neutral';
};
semanticConfidence: 'high' | 'medium' | 'low';
dataConfidence: 'sufficient' | 'partial' | 'insufficient';
};
```
### Report Structure
Reports use a fixed structure:
1. Summary
2. Key Findings
3. Evidence
4. Suggestions
5. Data Scope
AI may write the prose, but it must only use Metric Result data, Evidence, and Data Scope.
```ts
type AnalysisReport = {
summary: string;
keyFindings: string[];
evidence: EvidenceItem[];
suggestions: string[];
dataScope: {
timeDescription: string;
permissionDescription: string;
metricFormulaDescription: string;
generatedAt: string;
};
};
```
### Follow-Up Types
```ts
type FollowUp =
| {
type: 'question';
label: string;
prompt: string;
}
| {
type: 'drilldown';
label: string;
target: string;
filters: Record<string, unknown>;
}
| {
type: 'export';
label: string;
format: 'png' | 'pdf' | 'csv';
};
```
First version follow-ups are read-only:
- Follow-up question: "为什么延期?"
- Drilldown: "查看负责人", "查看 Bug 明细", "切到版本维度"
- Export: "导出分析报告"
Business-mutating follow-ups such as creating meetings, assigning owners, or changing plans are excluded from the MVP. They require explicit user confirmation and domain API design in a later phase.
## Data Confidence
Data confidence is separate from semantic confidence.
Display levels:
- `sufficient`: enough rows, current data, reliable plan dates or status facts.
- `partial`: some missing dates, sparse records, or incomplete evidence.
- `insufficient`: no usable rows or too few rows for the requested comparison.
Examples that lower data confidence:
- No planned end dates.
- Missing work activities.
- No historical baseline for comparison.
- Small sample size.
- Current user only has partial scope.
## No Data Strategy
If there is no data, do not let AI invent an explanation.
Return a structured no-data result:
- State what was requested.
- State why no result can be computed.
- Show the applied scope and time range.
- Suggest valid alternatives.
Example:
```text
没有找到 2025 年测试通过率数据。
可以改看 2026 年、当前版本测试完成情况,或按项目查看已有测试用例。
```
## API Shape
Initial endpoint:
```text
POST /api/v1/ai/analysis
```
Request:
```ts
type AnalysisRequest = {
question: string;
context?: {
surface: 'ai_assistant' | 'product_detail' | 'project_detail' | 'version_detail';
productId?: string;
projectId?: string;
versionId?: string;
};
};
```
Response:
```ts
type AnalysisResponse =
| {
ok: true;
plan: AnalysisPlan;
metricResult: MetricResult;
insight: InsightCard;
chart: UnifiedChartSpec;
report: AnalysisReport;
followUps: FollowUp[];
}
| {
ok: false;
code:
| 'NO_PERMISSION'
| 'UNSUPPORTED_ANALYSIS'
| 'AMBIGUOUS_INTENT'
| 'NO_DATA'
| 'AI_UNAVAILABLE'
| 'INVALID_PLAN';
message: string;
clarificationOptions?: Array<{ label: string; prompt: string }>;
dataScope?: DataScope;
};
```
## Error Handling
- `NO_PERMISSION`: user asked for a scope outside authorized data.
- `UNSUPPORTED_ANALYSIS`: metric or dimension is not in the catalog.
- `AMBIGUOUS_INTENT`: semantic confidence is too low and multiple interpretations are plausible.
- `NO_DATA`: plan is valid but no rows exist in scope.
- `AI_UNAVAILABLE`: AI Planning or AI report generation failed; templates and deterministic reports can still work when possible.
- `INVALID_PLAN`: AI proposed or user requested an invalid plan after validation.
Fallback order:
1. Template or deterministic strategy with deterministic report.
2. AI report over Metric Result when provider is available.
3. Deterministic report summary if AI is unavailable.
4. Structured error/no-data response.
## Testing Strategy
### Unit Tests
- Semantic Layer maps known phrases to expected concepts and confidence levels.
- Metric Catalog rejects unknown metrics, unsupported dimensions, unsupported analysis types, and deprecated metrics.
- Analysis Strategy chooses Template before Rule Composition before AI Planning.
- Rule Composition produces deterministic plans for examples such as delay reason trend.
- Analysis Plan Processor validates and normalizes time ranges, scope, Top N, dimensions, and metric versions.
- No Data Strategy returns structured no-data responses.
- ChartSpec Builder emits renderer-agnostic ChartSpec, not raw ECharts options.
- Evidence items include source domain and drilldown filters when available.
### Service Tests
- Normal member cannot query all-company management scope.
- Project Owner/Admin can query managed project scope.
- Version detail context restricts analysis to current version.
- Current-state risk queries do not use last 30 days by default.
- Trend/effort/throughput queries use last 30 days when no range is specified.
- Comparison queries use last 30 days versus previous 30 days when no baseline is specified.
### Frontend Tests
- AI Assistant renders Insight Card, chart, report, evidence, and follow-ups.
- Product/project/version context passes correct IDs to the analysis endpoint.
- ChartRenderer converts Unified ChartSpec to ECharts options through a single renderer boundary.
- Long labels and Top N bars do not overflow on desktop or mobile.
- No-data and no-permission states render as clear non-chart answers.
### Visual QA
- Verify Apple Vision rules on light and dark backgrounds.
- Verify line charts have smooth curves, area gradient, minimal axes, and anomaly markers.
- Verify horizontal bars are single-color, rounded, and animated softly.
- Verify number cards make the number the primary visual element.
## Documentation Updates
This design affects:
- `docs/architecture.md`: add Business Analysis Agent layer.
- `docs/decisions.md`: add decision for Semantic Layer, Analysis Strategy, Metric Catalog, and unified ChartSpec.
- `docs/workflow.md`: add business analysis workflow.
- `docs/roadmap.md`: add V3 Business Analysis Agent stage.
- `docs/agent-spec.md`: add Business Analysis Agent contract summary.