审计范围:
E:\workspace\Saas-voc前端与E:\workspace\server\saas-voc-server后端。 审计对象:反馈收件箱、AI VOC 洞察、行动创建面板、SaasPlatformService、后端AnalysisRun/Action路由与本地仓储。 审计时间:2026-08-06
当前系统已经形成一条可运行的 VOC 工作流:
真实评价
-> 证据准备与筛选
-> AI 结构化洞察 / deterministic 规则摘要
-> 用户查看原始证据并提交行动表单
-> ActionItem 进入行动中心
其中,证据回跳、证据 ID 校验、needs_validation 标记、AnalysisRun 持久化状态和 Action 创建审计已经具备。当前的“人工确认”由用户查看洞察后主动打开并提交“创建行动项”面板来体现,但还不是一个可查询、可审计、可阻断后续动作的独立业务状态。
因此当前实现适合表达“生成结果并由人决定是否转行动”,还不适合表达完整的“洞察发布、行动执行、效果验证、结果回流”闭环。
ai-voc-insight 通过 AiVocInsightService.prepare(...) 对数据集中的有效评价进行准备:
feedback-inbox 提供同一类评价的队列和详情视图。详情页保留原始评价正文、主题判断、同类样本量、来源类型、置信表达和处理建议;证据链接通过 reviewId 回到收件箱详情。
点击生成后,前端先调用:
POST /workspaces/:workspaceId/analyses
请求类型为 analysisType: voc_insight,目标为当前 workspace,并把筛选条件、输入证据 ID、主题统计、样本数和来源/情感统计写入 input。后端创建记录时状态为 pending,接口返回 202。
随后前端用:
PATCH /workspaces/:workspaceId/analyses/:id
把运行推进到 processing,生成结束后再写入 result、evidenceCount、终态和时间戳。后端上下文能力明确声明 analysisExecution: false,所以当前 AnalysisRun 是生成过程的持久化记录,实际 AI 执行仍由前端调用 AI 网关完成。
AI 输入携带 evidenceId,提示约束要求每条洞察引用输入中的真实 ID,并输出:
evidenceIds、evidenceCount 和验证指标;AI 返回结果会再次解析和归一化:未知证据 ID 会被过滤,没有有效证据引用的洞察会被丢弃;如果没有可验证洞察、请求超时或网关异常,则从同一输入生成 deterministic 规则摘要并明确标记为待验证。前端展示引用数量和每个证据 ID,并可跳回 feedback-inbox 查看原始评价。
当前 UI 的人工决策路径是:
action-create-panel;用户提交表单后调用:
POST /workspaces/:workspaceId/actions
后端要求 action:write 权限,校验负责人是 workspace 内的 active 成员,创建 ActionItem,初始状态默认为 open,并记录 action.created 审计事件。
feedback-inbox 也能从单条反馈直接创建行动草稿,并把原始反馈和主题上下文带入面板。前端用本地 createdActionIds 防止当前页面重复点击,但该集合不是后端关联关系。
需要特别区分:页面文案中的“已确认”与正式确认状态不是同一件事。当前没有 confirmedBy、confirmedAt、确认意见或洞察决策接口;用户提交 ActionItem 可以视作一次显式的人为转行动决定,但这次决定没有作为独立记录保存。
后端 AnalysisRun 的状态转移和字段约束如下:
| 状态 | 语义 | 当前进入方式 | 关键约束 |
|---|---|---|---|
pending |
请求已创建,等待生成开始 | POST /analyses 创建后的初始状态 |
没有结果,未开始处理 |
processing |
生成正在进行 | 前端 PATCH 状态;若未提供 startedAt,后端自动补时间 |
只能从 pending 进入;前端负责实际生成 |
completed |
AI 结果完整完成 | AI 结果成功解析并写入 | 必须有 result;终态不可再次 PATCH |
partial |
有结果但需要人工复核,当前主要用于 deterministic fallback | 规则摘要写入结果 | 必须有 result;终态不可再次 PATCH |
failed |
本次生成没有可用结果 | AI 请求、解析或持久化流程报告失败 | 必须有非空 errorSummary;终态不可再次 PATCH |
cancelled |
运行被取消 | 后端允许从 pending 或 processing 取消 |
当前没有前端取消控件;终态不可再次 PATCH |
允许的状态转移是:
pending -> processing | cancelled | failed
processing -> completed | partial | failed | cancelled
completed -> terminal
partial -> terminal
failed -> terminal
cancelled -> terminal
后端还会自动补齐:进入 processing 时的 startedAt,以及进入任意终态时的 completedAt。GET 列表支持按状态筛选和游标分页;前端只恢复 voc_insight、当前 workspace 且状态为 completed 或 partial 并且有结果的运行。
当前 local-platform.repository 使用进程内数组保存 AnalysisRun 和 ActionItem,服务重启后记录会丢失;Parse REST / Postgres 仓储具备持久化实现。该差异必须在本地演示和验收环境中明确标注。
AiVocInsightService.generate(...) 调用 AiAnalysisService.streamAnalysis(...);mode 为 ai,前端将 AnalysisRun 写成 completed;supported、partially_supported、needs_validation 或 not_supported,但最终仍需人工判断;当 AI 网关未配置,或 AI 请求、解析发生异常时,系统按固定主题规则聚合当前证据:
needs_validation;mode 为 deterministic,前端将 AnalysisRun 写成 partial,并提示人工复核后再转行动。deterministic fallback 是可解释的可用性降级,属于规则层信号;主题命中仍需人工复核,尚不足以表达总体问题率或已确认机会。
以下三条不变量是当前链路必须保持的业务契约。现状中的“已实现”与“仍需补强”分别列出,避免把 UI 行为误当成后端保证。
规则: 每条洞察的 evidenceIds 必须是本次分析上下文 evidence[].id 的子集;每个引用都能回到反馈收件箱的原始评价;evidenceCount 和覆盖率只能基于实际引用 ID 计算。
现状: AI 提示词要求真实 ID,结果归一化会过滤未知 ID,并丢弃没有有效引用的洞察;规则摘要也保留真实 ID。前端提供引用链接和证据回跳。
缺口: ActionItem 没有 analysisId、insightId 或 evidenceIds 字段。AI 创建行动时证据 ID 会进入描述文本,收件箱直接创建行动时主要带入原始反馈文本,因此数据库层还没有强引用约束。
needs_validation 与已确认机会保持区分规则: 样本不足、规则降级、主题边界不确定或证据覆盖不足的洞察必须保持 needs_validation;此状态只触发补证、人工复核或带验证指标的草稿,正式发布前需要显式确认。
现状: deterministic 结果统一使用 needs_validation;AI 缺失或非法机会状态时归一化默认使用 needs_validation;结果页展示“待验证”标签和验证指标。
缺口: 当前 openAction(...) 没有根据 opportunityStatus 阻断操作,用户仍可以直接为 needs_validation 洞察创建 ActionItem;后端也没有对结果内容或样本阈值做服务端校验。
规则: 只有用户查看了证据并明确确认洞察成立、确认验证目标和行动责任后,才允许创建可执行行动;确认人、时间、决策和意见必须可查询,并写入审计。
现状: 创建行动前必须经过用户点击和表单提交;后端用 action:write 权限保护创建接口,并记录 action.created。这能阻止纯展示状态自动创建行动。
缺口: 当前没有独立的确认 API 或确认字段,尚未区分“确认”“驳回”“需要补充证据”;也缺少用户完成证据审阅的可验证记录。行动创建本身是隐式确认,且对 needs_validation 没有统一阻断。
当前 ActionItem 只有执行状态、负责人、优先级、截止时间和完成时间,没有以下对象或字段:
analysisRunId、insightId、evidenceIds;所以当前链路止于“行动已创建/执行状态变化”,还没有“行动是否解决了用户问题”的证据闭环。
AnalysisRun 的 completed / partial 是计算运行状态,不是洞察的业务发布状态。当前不存在独立 Insight 实体或版本对象,也没有:
draft -> confirmed -> published -> archived
所需的发布人、发布时间、版本号、确认意见、归档原因、回滚关系和跨页面可见性策略。当前历史列表只能恢复有结果的 AnalysisRun,尚未表达某条洞察是否已被正式发布给产品、运营或管理层。
洞察与证据强关联
voc_insight AnalysisRun,When 结果保存,Then 每条洞察只能引用该运行输入中的证据 ID,服务端拒绝未知 ID、空引用和跨运行引用。analysisRunId、insightId 和去重后的 evidenceIds,页面仍可从行动跳回原始评价。人工确认成为显式门槛
needs_validation 或 deterministic fallback,When 用户未提交确认,Then创建行动请求被 UI 和 API 双重阻断。confirmed、rejected 或 needs_more_evidence 决策,并保存 confirmedBy、confirmedAt、确认说明及审计事件。AnalysisRun 执行契约稳定
completed 且 result 可恢复;Given deterministic fallback,Then状态为 partial 且结果中明确 mode: deterministic 和 needs_validation。failed 且有可读 errorSummary;终态之后的 PATCH 必须被拒绝。行动效果可回流
独立洞察发布生命周期
published;已发布版本不可被原地覆盖,修改必须生成新版本。历史、行动和效果一体化视图
质量与回归评估
needs_validation 识别率、人工确认通过率、行动完成率和效果回流完整率建立可重复测试;src/modules/feedback-inbox/feedback-inbox.component.ts、feedback-inbox.component.html;src/modules/ai-voc-insight/ai-voc-insight.component.ts、ai-voc-insight.component.html、ai-voc-insight.service.ts、ai-voc-insight.models.ts;src/modules/shared/components/action-create-panel/action-create-panel.component.ts、action-create-panel.component.html;src/app/core/services/saas-platform.service.ts;src/modules/saas-platform/domain.ts、routes.ts、local-platform.repository.ts;src/modules/saas-platform/parse-rest-voc.repository.ts、postgres-platform.repository.ts 中 AnalysisRun / Action 的持久化实现。