feat(platform): close AI expense value loop

Add tenant-safe value, telemetry, connector, commercial, and production-readiness foundations.
This commit is contained in:
caoxiaozhu
2026-07-17 14:14:08 +08:00
parent 242d68c36f
commit 787bc3a481
507 changed files with 82072 additions and 6344 deletions

View File

@@ -0,0 +1,204 @@
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import test from 'node:test'
import { fileURLToPath } from 'node:url'
import {
labelAgentAssetReleaseObservation,
normalizeAgentAssetReleaseReviewLabel,
normalizeAgentAssetReleaseReviewQueue
} from '../src/services/agentAssets.js'
import {
buildReleaseMonitorMetricCards,
buildReleaseReviewDocumentRoute
} from '../src/views/scripts/useAuditReleaseMonitor.js'
function source(path) {
return readFileSync(fileURLToPath(new URL(path, import.meta.url)), 'utf8')
}
const panel = source('../src/components/audit/AuditReleaseMonitorPanel.vue')
const detail = source('../src/components/audit/AuditJsonRiskRuleDetail.vue')
const view = source('../src/views/AuditView.vue')
const service = source('../src/services/agentAssets.js')
const composable = source('../src/views/scripts/useAuditReleaseMonitor.js')
test('盲审面板正负样本混排且不读取或暗示模型预测', () => {
assert.match(panel, /正负样本随机混排/u)
assert.match(panel, /候选与基线结论对复核人隐藏/u)
assert.match(panel, /模型结论已隐藏/u)
assert.match(panel, /存在真实风险/u)
assert.match(panel, /确认无该风险/u)
assert.doesNotMatch(panel, /candidate_hit|baseline_hit/u)
assert.doesNotMatch(service, /candidate_hit|baseline_hit/u)
assert.doesNotMatch(panel, /'confirmed'|'false_positive'/u)
assert.match(panel, /'risk_present'/u)
assert.match(panel, /'risk_absent'/u)
assert.doesNotMatch(panel, /确认命中|标记误报|待复核正例/u)
assert.match(panel, /class="review-decision"[\s\S]*class="review-decision"/u)
assert.match(panel, /:key="item\.sample_id \|\| item\.observation_id"/u)
assert.match(panel, /target="_blank"/u)
assert.match(panel, /rel="noopener noreferrer"/u)
})
test('复核队列只保留盲审字段并可从 source_document_id 打开单据', () => {
const queue = normalizeAgentAssetReleaseReviewQueue({
asset_id: 'asset-1',
release_id: 'release-1',
stage: 'shadow',
version: 'v2',
pending_total: 1,
telemetry_status: 'collecting',
items: [{
sample_id: 'sample-1',
observation_id: 'observation-1',
source_document_id: 'claim-1',
rule_code: 'RISK-001',
business_stage: 'reimbursement',
prediction_blinded: true,
reviewer_count: 1,
required_reviewers: 2,
conflicted: false,
created_at: '2026-07-17T00:00:00Z',
candidate_hit: true,
baseline_hit: false
}]
})
assert.deepEqual(Object.keys(queue.items[0]).sort(), [
'business_stage', 'conflicted', 'created_at', 'observation_id', 'prediction_blinded',
'required_reviewers', 'reviewer_count', 'rule_code', 'sample_id', 'source_document_id'
])
assert.equal(queue.items[0].prediction_blinded, true)
assert.deepEqual(buildReleaseReviewDocumentRoute(queue.items[0]), {
name: 'app-document-detail',
params: { requestId: 'claim-1' }
})
assert.equal(buildReleaseReviewDocumentRoute({ source_document_id: '' }), null)
})
test('负样本证据未就绪时召回和实际漏检不可用null 不伪装为 0', () => {
const queue = normalizeAgentAssetReleaseReviewQueue({
pending_total: 4,
metrics: {
observed_count: 20,
runtime_failure_count: 1,
runtime_failure_rate: 0.05,
negative_sample_count: 8,
negative_labeled_count: 3,
negative_pending_label_count: 5,
false_negative_count: null,
estimated_false_negative_count: null,
false_negative_upper_bound: null,
random_negative_population_count: 12,
random_negative_sample_count: 4,
random_negative_labeled_count: 1,
recall: null,
recall_lower_bound: null,
recall_confidence_level: 0.95,
recall_method: 'stratified_random_audit_wilson_upper_bound',
negative_ground_truth_status: 'insufficient_random_negative_reviews'
}
})
const cards = cardsByLabel(buildReleaseMonitorMetricCards(queue))
assert.equal(queue.metrics.false_negative_count, null)
assert.equal(cards['实际漏检'].value, '不可用')
assert.match(cards['实际漏检'].hint, /不按 0 展示/u)
assert.equal(cards['估计漏检'].value, '不可用')
assert.equal(cards['召回率'].value, '不可用')
assert.equal(cards['召回率'].hint, '随机负样本复核不足')
assert.equal(cards['负样本积压'].value, '5')
assert.equal(cards['负样本标注进度'].value, '37.5%')
assert.equal(cards['随机负样本抽检'].value, '25.0%')
})
test('真实负样本证据显示召回点估计、保守下界和漏检上界', () => {
const cards = cardsByLabel(buildReleaseMonitorMetricCards({
pending_total: 2,
metrics: {
observed_count: 100,
runtime_failure_count: 0,
runtime_failure_rate: 0,
negative_sample_count: 20,
negative_labeled_count: 18,
negative_pending_label_count: 2,
false_negative_count: 2,
estimated_false_negative_count: 2.5,
false_negative_upper_bound: 4.75,
random_negative_population_count: 40,
random_negative_sample_count: 10,
random_negative_labeled_count: 10,
recall: 0.8,
recall_lower_bound: 0.64,
recall_confidence_level: 0.95,
recall_method: 'stratified_random_audit_wilson_upper_bound',
negative_ground_truth_status: 'available_stratified_random_audit'
}
}))
assert.equal(cards['实际漏检'].value, '2')
assert.equal(cards['估计漏检'].value, '2.5')
assert.equal(cards['估计漏检'].hint, '保守上界 4.75')
assert.equal(cards['负样本标注进度'].value, '90.0%')
assert.equal(cards['负样本积压'].value, '2')
assert.equal(cards['召回率'].value, '80.0%')
assert.match(cards['召回率'].hint, /保守下界 64\.0% · 95% 置信度/u)
assert.match(cards['召回率'].hint, /分层随机盲审 Wilson 保守上界/u)
})
test('发布复核使用独立租户鉴权 API、幂等请求号和中性结果文案', () => {
assert.match(service, /\/release\/review-queue/u)
assert.match(service, /\/release\/review-queue\/\$\{observationId\}\/labels/u)
assert.match(service, /normalizeAgentAssetReleaseReviewQueue\(payload\)/u)
assert.match(composable, /requestId:\s*requestId\(assetId, observationId, label\)/u)
assert.match(composable, /Promise\.all\(\[/u)
assert.match(composable, /fetchAgentAssetReleaseState/u)
assert.match(composable, /fetchAgentAssetReleaseReviewQueue/u)
assert.match(composable, /已提交“存在真实风险”/u)
assert.match(composable, /已提交“确认无该风险”/u)
assert.equal(normalizeAgentAssetReleaseReviewLabel('risk_present'), 'risk_present')
assert.equal(normalizeAgentAssetReleaseReviewLabel('risk_absent'), 'risk_absent')
assert.throws(() => normalizeAgentAssetReleaseReviewLabel('confirmed'), /risk_present/u)
assert.throws(() => normalizeAgentAssetReleaseReviewLabel('false_positive'), /risk_absent/u)
})
test('复核服务只发送 risk_present 或 risk_absent 新语义', async () => {
const originalFetch = globalThis.fetch
const bodies = []
globalThis.fetch = async (_url, options) => {
bodies.push(JSON.parse(options.body))
return new Response(JSON.stringify({ label: options.body.includes('risk_present') ? 'risk_present' : 'risk_absent' }), {
status: 200,
headers: { 'content-type': 'application/json' }
})
}
try {
await labelAgentAssetReleaseObservation('asset-1', 'observation-1', 'risk_present', {
actor: 'auditor', requestId: 'blind-review-present'
})
await labelAgentAssetReleaseObservation('asset-1', 'observation-2', 'risk_absent', {
actor: 'auditor', requestId: 'blind-review-absent'
})
assert.throws(
() => labelAgentAssetReleaseObservation('asset-1', 'observation-3', 'confirmed'),
/risk_present/u
)
} finally {
globalThis.fetch = originalFetch
}
assert.deepEqual(bodies, [{ label: 'risk_present' }, { label: 'risk_absent' }])
})
test('规则详情和审计页复用独立发布监控组件', () => {
assert.match(detail, /<AuditReleaseMonitorPanel/u)
assert.match(detail, /@label="\(observationId, label\) => emit\('label-release'/u)
assert.match(view, /:release-queue="releaseQueue"/u)
assert.match(view, /@label-release="submitReleaseLabel"/u)
})
function cardsByLabel(cards) {
return Object.fromEntries(cards.map((card) => [card.label, card]))
}