Release v9.3.0 report updates without committing local API keys.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
喻长发
2026-09-04 16:57:04 +08:00
co-authored by Cursor
parent 19410caf76
commit 8c33d08537
29 changed files with 1111 additions and 131 deletions
+15 -11
View File
@@ -47,11 +47,13 @@ class EvidenceOnlyReportTest(unittest.TestCase):
'meta': {},
}
def test_empty_model_result_does_not_generate_fallback_report(self):
def test_empty_model_result_still_generates_reviewable_report(self):
result = ensure_experience_solution(self.analysis)
self.assertFalse(result['meta']['fallbackReport'])
self.assertFalse(result['meta']['reportReady'])
self.assertIn('不输出兜底报告', result['meta']['reportBlockedReason'])
self.assertTrue(result['meta']['reportReady'])
self.assertFalse(result['meta']['reportAuditPassed'])
self.assertEqual('needs_review', result['meta']['reportQuality'])
self.assertIn('审核未通过', result['meta']['reportNotice'])
self.assertEqual('', result['facts']['product']['title'])
self.assertEqual(['面料支数', '床单面料材质', '适用床尺寸'], [x['name'] for x in result['facts']['attributes']])
self.assertEqual(2, result['baseline']['reviewCount'])
@@ -61,18 +63,20 @@ class EvidenceOnlyReportTest(unittest.TestCase):
self.assertEqual('下一款明确卖点', cards[0]['label'])
self.assertIn('ATTR_0003', cards[0]['evidenceIds'])
self.assertEqual([], result['experienceSolution']['productExperience']['gates'])
with self.assertRaisesRegex(ValueError, '不输出兜底报告'):
render(result, 'fixture')
html = render(result, 'fixture')
self.assertIn('审核未通过', html)
def test_analysis_runs_without_model_channel(self):
def test_analysis_runs_without_model_channel_uses_evidence_fallback(self):
raw = dict(self.analysis['facts'])
raw['_model_available'] = False
result = analyze(raw)
self.assertFalse(result['meta']['modelUsed'])
self.assertEqual('9.2.5', result['meta']['engineVersion'])
self.assertEqual('9.3.0', result['meta']['engineVersion'])
self.assertEqual('home_textile', result['meta']['industryTemplate'])
self.assertFalse(result['meta']['fallbackReport'])
self.assertFalse(result['meta']['reportReady'])
self.assertTrue(result['meta']['reportReady'])
self.assertTrue(result['experienceSolution']['reportSummary']['title'])
self.assertEqual(7, len(result['roleOutputs']))
def test_historical_fallback_json_is_rejected(self):
result = ensure_experience_solution({
@@ -198,9 +202,9 @@ class EvidenceOnlyReportTest(unittest.TestCase):
self.assertNotIn('决定成交', output)
self.assertNotIn('爆款', output)
doc = render(result, 'evidence-only')
self.assertIn('老板速览', doc)
self.assertIn('下一款先做什么', doc)
self.assertIn('V9.2.5', doc)
self.assertIn('window.REPORT_DATA=', doc)
self.assertIn('Sansong Product Intelligence V9.3.0', doc)
self.assertIn('<script src="/report.js"></script>', doc)
self.assertNotIn('项目负责人', doc)
def test_incomplete_final_editor_output_is_repaired_from_real_evidence(self):
+3 -2
View File
@@ -21,8 +21,9 @@ class V910RegressionTest(unittest.TestCase):
def test_missing_sku_not_rendered_as_zero(self):
doc=render(self.base_result(),'test')
self.assertNotIn('SKU 0',doc)
self.assertIn('结构化SKU 未完整采集',doc)
self.assertIn('SKU图片数量不等于SKU数量',doc)
self.assertNotIn('结构化SKU 未完整采集',doc)
self.assertNotIn('SKU图片数量不等于SKU数量',doc)
self.assertIn('window.REPORT_DATA=',doc)
def test_renderer_prefers_local_image_and_keeps_remote_fallback(self):
entry={'value':'https://img.example.com/a.jpg','meta':{'localUrl':'/reports/assets/test/main/IMG_MAIN_0001.jpg','sourceUrl':'https://img.example.com/a.jpg'}}
+9 -9
View File
@@ -33,13 +33,12 @@ class V920ImageDrivenReportTest(unittest.TestCase):
def test_renderer_is_image_driven_and_professional(self):
doc=render(self.fixture(),'v920')
for text in ('老板速览','下一款先做什么','主图到底在卖什么','详情页证明了什么','先解决适配,再解决审美','消费者真正感受到什么'):
self.assertIn(text,doc)
self.assertIn('v92-main-grid',doc)
self.assertIn('v925-detail-list',doc)
self.assertIn('v92-sku-mosaic',doc)
self.assertIn('v92-buyer-grid',doc)
self.assertIn('v925-plan-grid',doc)
self.assertIn('window.REPORT_DATA=',doc)
self.assertIn('<script src="/report.js"></script>',doc)
self.assertIn('IMG_MAIN_0001',doc)
self.assertIn('IMG_DETAIL_0001',doc)
self.assertNotIn('v92-main-grid',doc)
self.assertNotIn('v925-detail-list',doc)
self.assertNotIn('[数据事实]',doc)
self.assertNotIn('[分析判断]',doc)
self.assertNotIn('[设计建议]',doc)
@@ -48,8 +47,9 @@ class V920ImageDrivenReportTest(unittest.TestCase):
def test_cover_has_no_card_border_wrapper(self):
doc=render(self.fixture(),'v920')
self.assertIn('class="v92-cover"',doc)
self.assertIn('cover-ratio',doc)
self.assertIn('"coverImageId":"IMG_MAIN_0001"',doc)
self.assertNotIn('class="v92-cover"',doc)
self.assertNotIn('cover-ratio',doc)
self.assertNotIn('hero-shot',doc)
def test_launch_fallback_never_empty_with_real_evidence(self):
+25
View File
@@ -0,0 +1,25 @@
import json, sys, unittest
from pathlib import Path
ROOT=Path(__file__).resolve().parents[1]
sys.path.insert(0,str(ROOT/'server'))
from audit_report import audit, has_content
class V930ReportAuditTest(unittest.TestCase):
def test_zero_and_false_are_real_content(self):
self.assertTrue(has_content(0))
self.assertTrue(has_content(False))
self.assertFalse(has_content('未采集'))
self.assertFalse(has_content({}))
def test_current_reference_report_has_complete_roles_and_evidence(self):
source=ROOT/'server/reports/tmall_1068693788227_20260903_181040_ac150.json'
if not source.exists():
self.skipTest('reference report is not distributed')
result=audit(json.loads(source.read_text('utf-8')))
self.assertTrue(result['ok'],result['failures'])
self.assertEqual(7,result['roles']['present'])
self.assertFalse(result['evidence']['unresolved'])
self.assertGreaterEqual(result['sourceCoverage'],12)
if __name__=='__main__':unittest.main()
+1 -1
View File
@@ -2,7 +2,7 @@ import json, re
from pathlib import Path
ROOT=Path(__file__).resolve().parents[1]
EXPECTED='9.2.5'
EXPECTED='9.3.0'
def test_version_consistency():
assert (ROOT/'VERSION.txt').read_text().strip()==EXPECTED