test: harden AI analysis path

This commit is contained in:
2026-07-06 01:03:11 -07:00
parent ae561a7d45
commit 0d5093ac6c
15 changed files with 1736 additions and 23 deletions

View File

@@ -394,6 +394,7 @@ ANTHROPIC_API_KEY=sk-ant-...
- `errorCategory` / `errorReason`: sanitized only for failed rows
- Failed rows must not store prompts, full resident context snapshots, API keys, or raw provider errors.
- Knowledge retrieval may return enabled platform knowledge and enabled active-organization knowledge only.
- Completed elder analysis `resultJson.citations` must be derived from citation IDs actually referenced by `keyFindings[].citationIds` and `recommendations[].citationIds`; do not append unused available citations.
### 4. Validation & Error Matrix
@@ -407,6 +408,7 @@ ANTHROPIC_API_KEY=sk-ant-...
- Missing `AI_API_KEY` -> save failed analysis with `missing_config`, return structured failure.
- Provider failure -> save failed analysis with `provider_error` or `timeout`.
- Invalid model output -> save failed analysis with `schema_validation_failed`.
- Unknown citation IDs in findings or recommendations -> save failed analysis with `schema_validation_failed`, return structured failure.
### 5. Good/Base/Bad Cases
@@ -420,6 +422,7 @@ ANTHROPIC_API_KEY=sk-ant-...
- Permission seeding assertions for `ai:*` and `knowledge:*` default role grants.
- Knowledge retrieval tests for platform shared, own organization, other organization, and disabled entry filtering.
- Analysis tests for missing config, schema validation failure, failed-history sanitization, and data-scope redaction.
- Analysis tests for unknown citation rejection and referenced-only citation persistence.
- Route tests for auth/permission failures and standard response shape.
### 7. Wrong vs Correct
@@ -435,10 +438,20 @@ await model.invoke(JSON.stringify(residentRows));
#### Correct
```typescript
// Keep model calls in modules/ai/server and build permission-aware context first.
// Keep model calls in modules/ai/server and persist only citations that findings/recommendations reference.
const result = await generateElderAiAnalysis(auth.context, elderId);
if (!result.success) {
return jsonFailure(result.reason, result.status);
}
return jsonSuccess("AI 分析已生成", { analysis: result.data.analysis }, 201);
```
```typescript
// Good evidence chain: every cited source ID is from the allowed resident/knowledge citations.
const finding = {
category: "跌倒风险",
severity: "warning",
evidence: "夜间徘徊后需要加强通道清理和巡视。",
citationIds: ["resident-1", "kb-1"],
};
```