diff --git a/CLAUDE.md b/CLAUDE.md index f20e294..9f4e57b 100644 Binary files a/CLAUDE.md and b/CLAUDE.md differ diff --git a/app/__init__.py b/app/__init__.py index ff67f54..8238631 100644 Binary files a/app/__init__.py and b/app/__init__.py differ diff --git a/app/routes/__init__.py b/app/routes/__init__.py index bfebf3f..9218ad1 100644 Binary files a/app/routes/__init__.py and b/app/routes/__init__.py differ diff --git a/app/routes/domain.py b/app/routes/domain.py index 0ced23d..e4d29a8 100644 Binary files a/app/routes/domain.py and b/app/routes/domain.py differ diff --git a/app/routes/guidance.py b/app/routes/guidance.py index 038769a..458ae00 100644 Binary files a/app/routes/guidance.py and b/app/routes/guidance.py differ diff --git a/app/routes/health.py b/app/routes/health.py index a1ad4d8..553b0ae 100644 Binary files a/app/routes/health.py and b/app/routes/health.py differ diff --git a/app/routes/rules.py b/app/routes/rules.py index 8223c16..d19ac5e 100644 Binary files a/app/routes/rules.py and b/app/routes/rules.py differ diff --git a/app/routes/schema.py b/app/routes/schema.py index 06b5979..55f57c2 100644 Binary files a/app/routes/schema.py and b/app/routes/schema.py differ diff --git a/app/rules/__init__.py b/app/rules/__init__.py index 04ae995..4129f3e 100644 Binary files a/app/rules/__init__.py and b/app/rules/__init__.py differ diff --git a/app/utils/__init__.py b/app/utils/__init__.py index 5984bf6..3cf01b4 100644 Binary files a/app/utils/__init__.py and b/app/utils/__init__.py differ diff --git a/app/utils/guidance_analysis.py b/app/utils/guidance_analysis.py index 0c92a49..1152305 100644 Binary files a/app/utils/guidance_analysis.py and b/app/utils/guidance_analysis.py differ diff --git a/app/utils/guidance_storage.py b/app/utils/guidance_storage.py index 15bc5e5..28e5624 100644 Binary files a/app/utils/guidance_storage.py and b/app/utils/guidance_storage.py differ diff --git a/app/utils/llm.py b/app/utils/llm.py index 4b9ffc2..6276621 100644 Binary files a/app/utils/llm.py and b/app/utils/llm.py differ diff --git a/app/utils/logger.py b/app/utils/logger.py index f8542b3..fcc912e 100644 Binary files a/app/utils/logger.py and b/app/utils/logger.py differ diff --git a/app/utils/note_scope.py b/app/utils/note_scope.py index 2e47e7c..08d009d 100644 Binary files a/app/utils/note_scope.py and b/app/utils/note_scope.py differ diff --git a/app/utils/parser.py b/app/utils/parser.py index 9a4a0c1..2fd0725 100644 Binary files a/app/utils/parser.py and b/app/utils/parser.py differ diff --git a/app/utils/response.py b/app/utils/response.py index 5974f62..8f5b2fc 100644 Binary files a/app/utils/response.py and b/app/utils/response.py differ diff --git a/app/utils/rule_generation.py b/app/utils/rule_generation.py index b66594c..431340c 100644 Binary files a/app/utils/rule_generation.py and b/app/utils/rule_generation.py differ diff --git a/app/utils/schema_storage.py b/app/utils/schema_storage.py index bea7265..503a848 100644 Binary files a/app/utils/schema_storage.py and b/app/utils/schema_storage.py differ diff --git a/app/utils/storage.py b/app/utils/storage.py index 1a4124d..a58d867 100644 Binary files a/app/utils/storage.py and b/app/utils/storage.py differ diff --git a/config/__init__.py b/config/__init__.py index d52ea2d..4b4806c 100644 Binary files a/config/__init__.py and b/config/__init__.py differ diff --git a/requirements.txt b/requirements.txt index 5cea7ce..48a7ace 100644 Binary files a/requirements.txt and b/requirements.txt differ diff --git a/run.py b/run.py index 25f5ed4..b252be6 100644 Binary files a/run.py and b/run.py differ diff --git a/skill/registry.json b/skill/registry.json index b1b1a8a..3eb9c8a 100644 Binary files a/skill/registry.json and b/skill/registry.json differ diff --git a/skill/yg-rules-output/CLAUDE.md b/skill/yg-rules-output/CLAUDE.md index 7e57a96..ef98ce9 100644 Binary files a/skill/yg-rules-output/CLAUDE.md and b/skill/yg-rules-output/CLAUDE.md differ diff --git a/skill/yg-rules-output/SKILL.md b/skill/yg-rules-output/SKILL.md index d6d8587..48fe22c 100644 Binary files a/skill/yg-rules-output/SKILL.md and b/skill/yg-rules-output/SKILL.md differ diff --git a/skill/yg-rules-output/agents/openai.yaml b/skill/yg-rules-output/agents/openai.yaml index 61b30cf..8d19226 100644 Binary files a/skill/yg-rules-output/agents/openai.yaml and b/skill/yg-rules-output/agents/openai.yaml differ diff --git a/skill/yg-rules-output/references/markdown-format.md b/skill/yg-rules-output/references/markdown-format.md index f5f872c..dd950e4 100644 Binary files a/skill/yg-rules-output/references/markdown-format.md and b/skill/yg-rules-output/references/markdown-format.md differ diff --git a/skill/yg-rules-output/references/output-contract.md b/skill/yg-rules-output/references/output-contract.md index 712f69e..4d4baa0 100644 Binary files a/skill/yg-rules-output/references/output-contract.md and b/skill/yg-rules-output/references/output-contract.md differ diff --git a/skill/yg-rules-output/scripts/validate_task_output.py b/skill/yg-rules-output/scripts/validate_task_output.py index 0810b3e..cff3415 100644 Binary files a/skill/yg-rules-output/scripts/validate_task_output.py and b/skill/yg-rules-output/scripts/validate_task_output.py differ diff --git a/skill/yg-rules-output/skill.json b/skill/yg-rules-output/skill.json index ab26958..3dc25cc 100644 Binary files a/skill/yg-rules-output/skill.json and b/skill/yg-rules-output/skill.json differ diff --git a/skill/yg-rules-pipeline/CLAUDE.md b/skill/yg-rules-pipeline/CLAUDE.md index 5d70a9f..0885691 100644 Binary files a/skill/yg-rules-pipeline/CLAUDE.md and b/skill/yg-rules-pipeline/CLAUDE.md differ diff --git a/skill/yg-rules-pipeline/SKILL.md b/skill/yg-rules-pipeline/SKILL.md index 41d3372..0222b1c 100644 Binary files a/skill/yg-rules-pipeline/SKILL.md and b/skill/yg-rules-pipeline/SKILL.md differ diff --git a/skill/yg-rules-pipeline/agents/openai.yaml b/skill/yg-rules-pipeline/agents/openai.yaml index 8bf99ff..af9405e 100644 Binary files a/skill/yg-rules-pipeline/agents/openai.yaml and b/skill/yg-rules-pipeline/agents/openai.yaml differ diff --git a/skill/yg-rules-pipeline/references/local-pipeline.md b/skill/yg-rules-pipeline/references/local-pipeline.md index ad45267..e18c3d6 100644 Binary files a/skill/yg-rules-pipeline/references/local-pipeline.md and b/skill/yg-rules-pipeline/references/local-pipeline.md differ diff --git a/skill/yg-rules-pipeline/scripts/run_pipeline.py b/skill/yg-rules-pipeline/scripts/run_pipeline.py index 07bf775..b8d1125 100644 Binary files a/skill/yg-rules-pipeline/scripts/run_pipeline.py and b/skill/yg-rules-pipeline/scripts/run_pipeline.py differ diff --git a/skill/yg-rules-pipeline/skill.json b/skill/yg-rules-pipeline/skill.json index 02e4199..6becb9b 100644 Binary files a/skill/yg-rules-pipeline/skill.json and b/skill/yg-rules-pipeline/skill.json differ diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index b83d201..0000000 Binary files a/tests/conftest.py and /dev/null differ diff --git a/tests/test_domain_routes.py b/tests/test_domain_routes.py index 576b3fe..92f97e3 100644 Binary files a/tests/test_domain_routes.py and b/tests/test_domain_routes.py differ diff --git a/tests/test_guidance_analysis.py b/tests/test_guidance_analysis.py index 0351950..d3f7078 100644 Binary files a/tests/test_guidance_analysis.py and b/tests/test_guidance_analysis.py differ diff --git a/tests/test_guidance_file_extraction.py b/tests/test_guidance_file_extraction.py new file mode 100644 index 0000000..a5b0cc0 --- /dev/null +++ b/tests/test_guidance_file_extraction.py @@ -0,0 +1,38 @@ +import io +import unittest +from unittest.mock import patch + +from app.utils.guidance_analysis import GuidanceAnalyzer + + +class GuidanceFileExtractionTest(unittest.TestCase): + def test_extracts_plain_text_and_markdown(self): + analyzer = GuidanceAnalyzer() + + txt = analyzer.extract_text("资产负债率预警。".encode("utf-8"), "guide.txt") + md = analyzer.extract_text("# 标题\n\n资产负债率预警。".encode("utf-8"), "guide.md") + + self.assertIn("资产负债率预警", txt["text"]) + self.assertIn("资产负债率预警", md["text"]) + self.assertEqual(txt["method"], "plain_text") + self.assertEqual(md["method"], "markdown") + + def test_extracts_docx_text(self): + from docx import Document + + document = Document() + document.add_paragraph("资产负债率预警。") + stream = io.BytesIO() + document.save(stream) + + result = GuidanceAnalyzer().extract_text(stream.getvalue(), "guide.docx") + + self.assertEqual(result["method"], "docx") + self.assertIn("资产负债率预警", result["text"]) + + def test_pdf_extractor_result_shape(self): + with patch.object(GuidanceAnalyzer, "_extract_pdf_text", return_value="资产负债率预警。"): + result = GuidanceAnalyzer().extract_text(b"%PDF", "guide.pdf") + + self.assertEqual(result["method"], "pdf") + self.assertIn("资产负债率预警", result["text"]) diff --git a/tests/test_guidance_routes.py b/tests/test_guidance_routes.py index 8da89c2..9ba59e2 100644 Binary files a/tests/test_guidance_routes.py and b/tests/test_guidance_routes.py differ diff --git a/tests/test_guidance_storage.py b/tests/test_guidance_storage.py index f352d69..e39fdff 100644 Binary files a/tests/test_guidance_storage.py and b/tests/test_guidance_storage.py differ diff --git a/tests/test_llm.py b/tests/test_llm.py index 980a0f9..aba3df2 100644 Binary files a/tests/test_llm.py and b/tests/test_llm.py differ diff --git a/tests/test_note_scope.py b/tests/test_note_scope.py deleted file mode 100644 index 93edf6c..0000000 Binary files a/tests/test_note_scope.py and /dev/null differ diff --git a/tests/test_response.py b/tests/test_response.py new file mode 100644 index 0000000..755fb60 --- /dev/null +++ b/tests/test_response.py @@ -0,0 +1,20 @@ +import unittest + +from flask import Flask + +from app.utils.response import success + + +class ResponseMessageTest(unittest.TestCase): + def test_success_message_defaults_to_chinese(self): + app = Flask(__name__) + + with app.app_context(): + response, status_code = success({"ok": True}) + + self.assertEqual(status_code, 200) + self.assertEqual(response.get_json()["message"], "操作成功") + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_route_messages.py b/tests/test_route_messages.py new file mode 100644 index 0000000..171af29 --- /dev/null +++ b/tests/test_route_messages.py @@ -0,0 +1,66 @@ +import unittest +from unittest.mock import patch + +from app import create_app + + +class RouteMessageTest(unittest.TestCase): + def setUp(self): + self.app = create_app("testing") + self.client = self.app.test_client() + + def test_success_messages_include_business_action(self): + response = self.client.get("/api/health") + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get_json()["message"], "健康检查成功") + + def test_failure_messages_include_business_action(self): + response = self.client.get("/api/rules/status") + + self.assertEqual(response.status_code, 400) + self.assertEqual(response.get_json()["message"], "查询失败:缺少 task_id") + + def test_clear_domains_message_is_delete_success(self): + with patch("app.routes.domain.DomainStorage") as domain_storage_cls: + with patch("app.routes.domain.SchemaStorage") as schema_storage_cls: + domain_storage_cls.return_value.clear_all.return_value = 3 + schema_storage_cls.return_value.delete_file.return_value = True + + response = self.client.post("/api/domains/clear") + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get_json()["message"], "删除成功") + self.assertEqual(response.get_json()["data"]["deleted_count"], 3) + + def test_generate_rules_returns_compact_async_task_info(self): + with patch("app.routes.rules.RuleGenerationService") as service_cls: + service_cls.return_value.start.return_value = { + "task_id": "task-1", + "status": "running", + "limit": 3, + "generated_count": 0, + "output_file": "/app/output/rules-task-1/rules-task-1.xlsx", + "markdown_file": "/app/output/rules-task-1/rules-task-1.md", + "files": { + "excel": "/app/output/rules-task-1/rules-task-1.xlsx", + "markdown": "/app/output/rules-task-1/rules-task-1.md", + }, + } + + response = self.client.post("/api/rules/generate", json={"limit": 3}) + + body = response.get_json() + self.assertEqual(response.status_code, 200) + self.assertEqual(body["message"], "规则生成任务创建成功") + self.assertEqual(body["data"], { + "task_id": "task-1", + "status": "running", + "async": True, + "limit": 3, + "status_url": "/api/rules/status?task_id=task-1", + }) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_rule_generation.py b/tests/test_rule_generation.py index e84b9bf..5521246 100644 Binary files a/tests/test_rule_generation.py and b/tests/test_rule_generation.py differ diff --git a/tests/test_schema_descriptions.py b/tests/test_schema_descriptions.py index c72cf8c..5dead55 100644 Binary files a/tests/test_schema_descriptions.py and b/tests/test_schema_descriptions.py differ diff --git a/tests/test_schema_routes.py b/tests/test_schema_routes.py new file mode 100644 index 0000000..a3cf73d --- /dev/null +++ b/tests/test_schema_routes.py @@ -0,0 +1,32 @@ +import unittest +from unittest.mock import patch + +from flask import Flask + +from app.routes.schema import schema_bp + + +class SchemaRouteTest(unittest.TestCase): + def setUp(self): + self.app = Flask(__name__) + self.app.register_blueprint(schema_bp) + self.client = self.app.test_client() + + def test_schema_status_returns_processing_summary(self): + with patch("app.routes.schema.SchemaStorage") as storage_cls: + storage_cls.return_value.status.return_value = { + "processing_status": "done", + "module_count": 2, + "uploaded_at": "2026-06-10 15:50:00", + } + + response = self.client.get("/api/schema/status") + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get_json()["message"], "查询成功") + self.assertEqual(response.get_json()["data"]["processing_status"], "done") + self.assertEqual(response.get_json()["data"]["module_count"], 2) + + +if __name__ == "__main__": + unittest.main()