import unittest from src.meeting_lab.consolidation.consolidate_facts import ( ConsolidationValidationError, DEFAULT_NUM_PREDICT, build_consolidated_output, build_ollama_payload, parse_model_json, validate_consolidated_output, validate_model_groups, ) def canonicalized_fixture(): fact_one = { "item_id": "fact_0001", "category": "fact", "text": "The lead maintains the list.", "evidence": "lead maintains the list", "source_file": "chunk_01_extraction.json", "source_index": 0, "original_value": "The lead maintains the list. | evidence", "source_references": [ { "source_file": "chunk_01_extraction.json", "source_index": 0, "evidence": "lead maintains the list", "original_value": "The lead maintains the list. | evidence", } ], "duplicate_count": 1, } fact_two = { "item_id": "fact_0002", "category": "fact", "text": "The head maintains the project list.", "evidence": "head maintains the project list", "source_file": "chunk_02_extraction.json", "source_index": 0, "original_value": "The head maintains the project list. | evidence", "source_references": [ { "source_file": "chunk_02_extraction.json", "source_index": 0, "evidence": "head maintains the project list", "original_value": "The head maintains the project list. | evidence", } ], "duplicate_count": 1, } decision = { "item_id": "decision_0001", "category": "decision", "text": "Ship it.", "evidence": "Agreed.", "source_file": "chunk_01_extraction.json", "source_index": 0, "original_value": "Ship it. | Agreed.", "source_references": [], "duplicate_count": 1, } return { "schema_version": "1", "source_files": ["chunk_01_extraction.json", "chunk_02_extraction.json"], "items": [fact_one, fact_two, decision], } class ConsolidateFactsTests(unittest.TestCase): def test_payload_construction_disables_streaming_and_thinking_by_default(self): payload = build_ollama_payload( model="qwen3.5:9B", prompt="prompt", num_ctx=32768, num_predict=DEFAULT_NUM_PREDICT, think=False, ) self.assertEqual(payload["model"], "qwen3.5:9B") self.assertEqual(payload["prompt"], "prompt") self.assertIs(payload["stream"], False) self.assertIs(payload["think"], False) self.assertEqual(payload["format"], "json") self.assertEqual(payload["options"]["temperature"], 0.0) self.assertEqual(payload["options"]["num_ctx"], 32768) self.assertEqual(payload["options"]["num_predict"], DEFAULT_NUM_PREDICT) def test_payload_construction_can_enable_thinking_explicitly(self): payload = build_ollama_payload( model="qwen3.5:9B", prompt="prompt", num_ctx=16384, num_predict=1024, think=True, ) self.assertIs(payload["think"], True) self.assertEqual(payload["options"]["num_ctx"], 16384) self.assertEqual(payload["options"]["num_predict"], 1024) def test_grouping_validation_accepts_complete_singletons(self): groups = validate_model_groups( { "groups": [ { "canonical_text": "The lead maintains the list.", "source_item_ids": ["fact_0001"], "merge_reason": "Singleton.", }, { "canonical_text": "The head maintains the project list.", "source_item_ids": ["fact_0002"], "merge_reason": "Singleton.", }, ] }, {"fact_0001", "fact_0002"}, ) self.assertEqual(len(groups), 2) def test_no_missing_source_ids(self): with self.assertRaisesRegex(ConsolidationValidationError, "Missing"): validate_model_groups( { "groups": [ { "canonical_text": "Only one.", "source_item_ids": ["fact_0001"], "merge_reason": "Singleton.", } ] }, {"fact_0001", "fact_0002"}, ) def test_no_duplicate_source_ids(self): with self.assertRaisesRegex(ConsolidationValidationError, "multiple"): validate_model_groups( { "groups": [ { "canonical_text": "One.", "source_item_ids": ["fact_0001"], "merge_reason": "Singleton.", }, { "canonical_text": "Again.", "source_item_ids": ["fact_0001"], "merge_reason": "Singleton.", }, ] }, {"fact_0001"}, ) def test_merged_group_validation(self): groups = validate_model_groups( { "groups": [ { "canonical_text": "The lead maintains the project list.", "source_item_ids": ["fact_0001", "fact_0002"], "merge_reason": "Same proposition.", } ] }, {"fact_0001", "fact_0002"}, ) output = build_consolidated_output(canonicalized_fixture(), groups) validate_consolidated_output(canonicalized_fixture(), output) self.assertEqual(output["items"][0]["source_item_ids"], ["fact_0001", "fact_0002"]) def test_preservation_of_non_fact_categories(self): fixture = canonicalized_fixture() groups = validate_model_groups( { "groups": [ { "canonical_text": "The lead maintains the project list.", "source_item_ids": ["fact_0001", "fact_0002"], "merge_reason": "Same proposition.", } ] }, {"fact_0001", "fact_0002"}, ) output = build_consolidated_output(fixture, groups) self.assertEqual(output["items"][1:], fixture["items"][2:]) def test_invalid_model_json(self): with self.assertRaisesRegex(ConsolidationValidationError, "Invalid model JSON"): parse_model_json("{invalid") def test_unknown_source_item_ids(self): with self.assertRaisesRegex(ConsolidationValidationError, "unknown"): validate_model_groups( { "groups": [ { "canonical_text": "Unknown.", "source_item_ids": ["fact_9999"], "merge_reason": "Bad ID.", } ] }, {"fact_0001"}, ) if __name__ == "__main__": unittest.main()