qwen-sci 0.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (549) hide show
  1. qwen_sci-0.2.2.dist-info/METADATA +492 -0
  2. qwen_sci-0.2.2.dist-info/RECORD +549 -0
  3. qwen_sci-0.2.2.dist-info/WHEEL +4 -0
  4. qwen_sci-0.2.2.dist-info/entry_points.txt +6 -0
  5. qwen_sci-0.2.2.dist-info/licenses/LICENSE +21 -0
  6. src/1.txt +1 -0
  7. src/__init__.py +1 -0
  8. src/__main__.py +5 -0
  9. src/agents/__init__.py +1 -0
  10. src/agents/experiment_design_agent/__init__.py +268 -0
  11. src/agents/experiment_design_agent/artifacts.py +747 -0
  12. src/agents/experiment_design_agent/cache.py +319 -0
  13. src/agents/experiment_design_agent/completeness.py +130 -0
  14. src/agents/experiment_design_agent/contracts.py +771 -0
  15. src/agents/experiment_design_agent/counterexample_analyzer.py +187 -0
  16. src/agents/experiment_design_agent/design_evidence_paper_screener.py +470 -0
  17. src/agents/experiment_design_agent/discipline_catalog.py +178 -0
  18. src/agents/experiment_design_agent/evidence_cards.py +338 -0
  19. src/agents/experiment_design_agent/evidence_planner.py +452 -0
  20. src/agents/experiment_design_agent/formal_reasoning_planner.py +884 -0
  21. src/agents/experiment_design_agent/fulltext_acquisition.py +863 -0
  22. src/agents/experiment_design_agent/idea_adapter.py +100 -0
  23. src/agents/experiment_design_agent/idea_intake.py +87 -0
  24. src/agents/experiment_design_agent/llm_json.py +328 -0
  25. src/agents/experiment_design_agent/orchestrator.py +1220 -0
  26. src/agents/experiment_design_agent/reasoning_context.py +183 -0
  27. src/agents/experiment_design_agent/reasoning_validation.py +546 -0
  28. src/agents/experiment_design_agent/run.py +481 -0
  29. src/agents/experiment_design_agent/run_logging.py +292 -0
  30. src/agents/experiment_design_agent/scope_gate.py +198 -0
  31. src/agents/experiment_design_agent/study_type_composer.py +1360 -0
  32. src/agents/experiment_design_agent/survey_evidence.py +1381 -0
  33. src/agents/experiment_design_agent/template_router.py +195 -0
  34. src/agents/experiment_design_agent/variable_claim_extractor.py +93 -0
  35. src/agents/idea_agent/__init__.py +1 -0
  36. src/agents/idea_agent/agent/__init__.py +6 -0
  37. src/agents/idea_agent/agent/artifacts.py +308 -0
  38. src/agents/idea_agent/agent/base.py +122 -0
  39. src/agents/idea_agent/agent/ligagent.py +488 -0
  40. src/agents/idea_agent/agent/mcts.py +2060 -0
  41. src/agents/idea_agent/agent/prompts/__init__.py +48 -0
  42. src/agents/idea_agent/agent/prompts/advanced_analysis.py +235 -0
  43. src/agents/idea_agent/agent/prompts/algorithm_alignment.py +55 -0
  44. src/agents/idea_agent/agent/prompts/algorithm_structuring.py +48 -0
  45. src/agents/idea_agent/agent/prompts/component_extraction.py +62 -0
  46. src/agents/idea_agent/agent/prompts/component_novelty_evaluation.py +54 -0
  47. src/agents/idea_agent/agent/prompts/experiment_findings_extraction.py +39 -0
  48. src/agents/idea_agent/agent/prompts/idea_fusion.py +295 -0
  49. src/agents/idea_agent/agent/prompts/idea_introduction.py +30 -0
  50. src/agents/idea_agent/agent/prompts/idea_result_alignment.py +39 -0
  51. src/agents/idea_agent/agent/prompts/input_interpreter.py +52 -0
  52. src/agents/idea_agent/agent/prompts/keynote_ops.py +78 -0
  53. src/agents/idea_agent/agent/prompts/mcts_evaluation.py +235 -0
  54. src/agents/idea_agent/agent/prompts/mcts_generation.py +140 -0
  55. src/agents/idea_agent/agent/prompts/mechanism_commit_query.py +99 -0
  56. src/agents/idea_agent/agent/prompts/memory_selection.py +0 -0
  57. src/agents/idea_agent/agent/prompts/prompt_modes.py +16 -0
  58. src/agents/idea_agent/agent/prompts/rag_query.py +34 -0
  59. src/agents/idea_agent/agent/prompts/re_analysis_replan.py +48 -0
  60. src/agents/idea_agent/agent/prompts/reference_grounding.py +34 -0
  61. src/agents/idea_agent/agent/prompts/root_domain_classification.py +32 -0
  62. src/agents/idea_agent/agent/prompts/scientific_debate.py +88 -0
  63. src/agents/idea_agent/agent/prompts/scientific_materialization.py +45 -0
  64. src/agents/idea_agent/agent/prompts/skill_instantiation.py +193 -0
  65. src/agents/idea_agent/agent/prompts/theory_transfer_query.py +93 -0
  66. src/agents/idea_agent/agent/prompts/topic_background.py +15 -0
  67. src/agents/idea_agent/agent/skills/DEFAULT_SKILL_TEMPLATES.json +263 -0
  68. src/agents/idea_agent/agent/skills/edit_operator_skills/alternative-path-contrast/SKILL.md +40 -0
  69. src/agents/idea_agent/agent/skills/edit_operator_skills/alternative-path-contrast/references/contrast_patterns.md +22 -0
  70. src/agents/idea_agent/agent/skills/edit_operator_skills/feedback-closed-loop/SKILL.md +40 -0
  71. src/agents/idea_agent/agent/skills/edit_operator_skills/feedback-closed-loop/references/mechanism_cards.md +24 -0
  72. src/agents/idea_agent/agent/skills/edit_operator_skills/hierarchical-decomposition/SKILL.md +39 -0
  73. src/agents/idea_agent/agent/skills/edit_operator_skills/hierarchical-decomposition/references/hierarchy_patterns.md +22 -0
  74. src/agents/idea_agent/agent/skills/edit_operator_skills/mechanism-commit-innovation/SKILL.md +39 -0
  75. src/agents/idea_agent/agent/skills/edit_operator_skills/mechanism-commit-innovation/references/mechanism_commit_patterns.md +24 -0
  76. src/agents/idea_agent/agent/skills/edit_operator_skills/multi-scale-coordinator/SKILL.md +39 -0
  77. src/agents/idea_agent/agent/skills/edit_operator_skills/multi-scale-coordinator/references/coordination_patterns.md +22 -0
  78. src/agents/idea_agent/agent/skills/edit_operator_skills/speculative-execution-with-repair/SKILL.md +41 -0
  79. src/agents/idea_agent/agent/skills/edit_operator_skills/speculative-execution-with-repair/references/speculation_patterns.md +22 -0
  80. src/agents/idea_agent/agent/skills/edit_operator_skills/surgical-modularity/SKILL.md +39 -0
  81. src/agents/idea_agent/agent/skills/edit_operator_skills/surgical-modularity/references/modularity_patterns.md +22 -0
  82. src/agents/idea_agent/agent/skills/edit_operator_skills/theory-transfer-injection/SKILL.md +40 -0
  83. src/agents/idea_agent/agent/skills/edit_operator_skills/theory-transfer-injection/references/transfer_patterns.md +24 -0
  84. src/agents/idea_agent/example/idea_result.json +900 -0
  85. src/agents/idea_agent/run.py +276 -0
  86. src/agents/idea_agent/tests/test_advanced_analysis_contract.py +90 -0
  87. src/agents/idea_agent/tests/test_gap_hypothesis_bridge.py +166 -0
  88. src/agents/idea_agent/tests/test_idea_debate.py +480 -0
  89. src/agents/idea_agent/tests/test_idea_result_v5.py +99 -0
  90. src/agents/idea_agent/tests/test_idea_synthesis.py +92 -0
  91. src/agents/idea_agent/tests/test_mature_idea_sources.py +27 -0
  92. src/agents/idea_agent/tests/test_multimodal_idea_integration.py +386 -0
  93. src/agents/idea_agent/tests/test_profile_materialization_and_scoring.py +219 -0
  94. src/agents/idea_agent/tests/test_profile_native_skill_rendering.py +122 -0
  95. src/agents/idea_agent/tests/test_result_persistence.py +183 -0
  96. src/agents/idea_agent/tests/test_scientific_intervention_profiles.py +241 -0
  97. src/agents/idea_agent/tests/test_scientific_rubric_and_prompts.py +559 -0
  98. src/agents/idea_agent/tests/test_strict_json_object_responses.py +48 -0
  99. src/agents/idea_agent/utils/core/__init__.py +1 -0
  100. src/agents/idea_agent/utils/core/ablation_inputs.py +60 -0
  101. src/agents/idea_agent/utils/core/chat_errors.py +95 -0
  102. src/agents/idea_agent/utils/core/chat_router.py +130 -0
  103. src/agents/idea_agent/utils/core/chat_transport.py +188 -0
  104. src/agents/idea_agent/utils/core/config_loader.py +166 -0
  105. src/agents/idea_agent/utils/core/json_utils.py +28 -0
  106. src/agents/idea_agent/utils/core/logger.py +287 -0
  107. src/agents/idea_agent/utils/core/progress.py +58 -0
  108. src/agents/idea_agent/utils/core/response_parsing.py +57 -0
  109. src/agents/idea_agent/utils/core/run_inputs.py +198 -0
  110. src/agents/idea_agent/utils/mcts/__init__.py +1 -0
  111. src/agents/idea_agent/utils/mcts/component_novelty.py +342 -0
  112. src/agents/idea_agent/utils/mcts/defect_registry.py +302 -0
  113. src/agents/idea_agent/utils/mcts/idea_routes.py +61 -0
  114. src/agents/idea_agent/utils/mcts/idea_taste_presets.py +312 -0
  115. src/agents/idea_agent/utils/mcts/mcts_helpers.py +738 -0
  116. src/agents/idea_agent/utils/mcts/mcts_runtime.py +3000 -0
  117. src/agents/idea_agent/utils/mcts/scientific_intervention_ontology.py +1561 -0
  118. src/agents/idea_agent/utils/mcts/scientific_rubric.py +211 -0
  119. src/agents/idea_agent/utils/mcts/skill_parsing.py +92 -0
  120. src/agents/idea_agent/utils/papers/__init__.py +1 -0
  121. src/agents/idea_agent/utils/papers/paper_graph_vector_store.py +499 -0
  122. src/agents/idea_agent/utils/papers/paper_repository.py +372 -0
  123. src/agents/idea_agent/utils/prompting/__init__.py +1 -0
  124. src/agents/idea_agent/utils/prompting/prompt_views.py +637 -0
  125. src/agents/idea_agent/utils/workflow/__init__.py +1 -0
  126. src/agents/idea_agent/utils/workflow/advanced_analysis_contract.py +244 -0
  127. src/agents/idea_agent/utils/workflow/gap_hypothesis_bridge.py +461 -0
  128. src/agents/idea_agent/utils/workflow/idea_contract.py +426 -0
  129. src/agents/idea_agent/utils/workflow/idea_debate.py +1238 -0
  130. src/agents/idea_agent/utils/workflow/idea_diversity.py +163 -0
  131. src/agents/idea_agent/utils/workflow/idea_fusion.py +889 -0
  132. src/agents/idea_agent/utils/workflow/idea_helpers.py +478 -0
  133. src/agents/idea_agent/utils/workflow/idea_portfolio.py +422 -0
  134. src/agents/idea_agent/utils/workflow/idea_synthesis.py +482 -0
  135. src/agents/idea_agent/utils/workflow/ligagent_flow.py +581 -0
  136. src/agents/idea_agent/utils/workflow/ligagent_handlers.py +1836 -0
  137. src/agents/idea_agent/utils/workflow/ligagent_helpers.py +1331 -0
  138. src/agents/idea_agent/utils/workflow/ligagent_utils.py +322 -0
  139. src/agents/idea_agent/utils/workflow/mature_idea_sources.py +648 -0
  140. src/agents/idea_agent/utils/workflow/multimodal_data_anchoring.py +578 -0
  141. src/agents/idea_agent/utils/workflow/result_persistence.py +774 -0
  142. src/agents/idea_agent/utils/workflow/stage_contract.py +76 -0
  143. src/agents/idea_agent/utils/workflow/workflow_runtime.py +288 -0
  144. src/agents/research_plan_author/__init__.py +50 -0
  145. src/agents/research_plan_author/artifacts.py +270 -0
  146. src/agents/research_plan_author/authoring_blueprint.py +1246 -0
  147. src/agents/research_plan_author/bibtex_renderer.py +252 -0
  148. src/agents/research_plan_author/contract_repair.py +131 -0
  149. src/agents/research_plan_author/contracts.py +745 -0
  150. src/agents/research_plan_author/cross_section_editor.py +232 -0
  151. src/agents/research_plan_author/document_quality.py +987 -0
  152. src/agents/research_plan_author/idea_evolution.py +223 -0
  153. src/agents/research_plan_author/input_loader.py +76 -0
  154. src/agents/research_plan_author/latex_compiler.py +260 -0
  155. src/agents/research_plan_author/latex_safety.py +159 -0
  156. src/agents/research_plan_author/llm_json.py +74 -0
  157. src/agents/research_plan_author/markdown_renderer.py +275 -0
  158. src/agents/research_plan_author/pdf_validator.py +149 -0
  159. src/agents/research_plan_author/render.py +166 -0
  160. src/agents/research_plan_author/render_artifacts.py +187 -0
  161. src/agents/research_plan_author/run.py +765 -0
  162. src/agents/research_plan_author/run_logging.py +209 -0
  163. src/agents/research_plan_author/section_cache.py +184 -0
  164. src/agents/research_plan_author/section_composer.py +1764 -0
  165. src/agents/research_plan_author/section_router.py +209 -0
  166. src/agents/research_plan_author/semantic_validator.py +254 -0
  167. src/agents/research_plan_author/source_bundle.py +46 -0
  168. src/agents/research_plan_author/source_registry.py +208 -0
  169. src/agents/research_plan_author/survey_source_loader.py +137 -0
  170. src/agents/research_plan_author/template_adapter.py +173 -0
  171. src/agents/research_plan_author/template_profile.py +204 -0
  172. src/agents/research_plan_author/tex_renderer.py +496 -0
  173. src/agents/research_plan_author/theory_presentation.py +134 -0
  174. src/agents/research_plan_author/theory_spine.py +703 -0
  175. src/agents/survey_agent/Dockerfile +54 -0
  176. src/agents/survey_agent/README.md +350 -0
  177. src/agents/survey_agent/config/deep_survey.yaml +217 -0
  178. src/agents/survey_agent/config/deep_survey_batch.yaml +176 -0
  179. src/agents/survey_agent/config/deep_survey_fast.yaml +183 -0
  180. src/agents/survey_agent/config/evaluate_baseline.yaml +197 -0
  181. src/agents/survey_agent/config/outcomeRAG.yaml +159 -0
  182. src/agents/survey_agent/env_report.md +348 -0
  183. src/agents/survey_agent/modules/__init__.py +0 -0
  184. src/agents/survey_agent/modules/code_collector.py +2194 -0
  185. src/agents/survey_agent/modules/code_report_generator.py +1282 -0
  186. src/agents/survey_agent/modules/data_manager.py +1713 -0
  187. src/agents/survey_agent/modules/database.py +167 -0
  188. src/agents/survey_agent/modules/fulltext_download_cache.py +462 -0
  189. src/agents/survey_agent/modules/fulltext_http.py +134 -0
  190. src/agents/survey_agent/modules/fulltext_resolution.py +749 -0
  191. src/agents/survey_agent/modules/judge.py +434 -0
  192. src/agents/survey_agent/modules/outcome_RAG.py +236 -0
  193. src/agents/survey_agent/modules/paper_graph_retriever.py +1075 -0
  194. src/agents/survey_agent/modules/pe.py +1729 -0
  195. src/agents/survey_agent/modules/pseudo_creator.py +782 -0
  196. src/agents/survey_agent/modules/pseudo_reviser.py +537 -0
  197. src/agents/survey_agent/modules/refine_agent.py +1952 -0
  198. src/agents/survey_agent/modules/survey_generator.py +5691 -0
  199. src/agents/survey_agent/modules/survey_visualizer.py +1817 -0
  200. src/agents/survey_agent/modules/visual_prompts.py +327 -0
  201. src/agents/survey_agent/modules/work_analyzer.py +2750 -0
  202. src/agents/survey_agent/modules/work_collector.py +5649 -0
  203. src/agents/survey_agent/scripts/baseline_evaluation.py +411 -0
  204. src/agents/survey_agent/scripts/run_deep_survey.py +224 -0
  205. src/agents/survey_agent/scripts/run_deep_survey_adapter.py +407 -0
  206. src/agents/survey_agent/scripts/run_deep_survey_adapter_with_input.py +409 -0
  207. src/agents/survey_agent/scripts/run_deep_survey_batch.py +228 -0
  208. src/agents/survey_agent/scripts/run_deep_survey_batch_arg.py +243 -0
  209. src/agents/survey_agent/scripts/run_deep_survey_batch_settings.py +218 -0
  210. src/agents/survey_agent/scripts/run_keynotes_gen.py +128 -0
  211. src/agents/survey_agent/scripts/run_work_clusters.py +140 -0
  212. src/agents/survey_agent/utils/__init__.py +0 -0
  213. src/agents/survey_agent/utils/ablation_utils.py +317 -0
  214. src/agents/survey_agent/utils/api_call.py +2518 -0
  215. src/agents/survey_agent/utils/chat_utils.py +82 -0
  216. src/agents/survey_agent/utils/config_utils.py +70 -0
  217. src/agents/survey_agent/utils/convert_to_md.py +29 -0
  218. src/agents/survey_agent/utils/err_info.py +24 -0
  219. src/agents/survey_agent/utils/file_utils.py +176 -0
  220. src/agents/survey_agent/utils/gpu_utils.py +145 -0
  221. src/agents/survey_agent/utils/graph_visualizer.py +279 -0
  222. src/agents/survey_agent/utils/html_utils.py +181 -0
  223. src/agents/survey_agent/utils/latex_generator_intra_cluster.py +529 -0
  224. src/agents/survey_agent/utils/latex_generator_relation_table.py +193 -0
  225. src/agents/survey_agent/utils/mineru_section_packer.py +334 -0
  226. src/agents/survey_agent/utils/mineru_utils.py +396 -0
  227. src/agents/survey_agent/utils/paper.py +144 -0
  228. src/agents/survey_agent/utils/read_yaml.py +15 -0
  229. src/agents/survey_agent/utils/repo_utils.py +167 -0
  230. src/agents/survey_agent/utils/rich_logger.py +77 -0
  231. src/agents/survey_agent/utils/step2v2.py +874 -0
  232. src/agents/survey_agent/utils/step2v2_extractor.py +856 -0
  233. src/agents/survey_agent/utils/topic_survey_storage.py +309 -0
  234. src/agents/survey_agent/utils/utils.py +118 -0
  235. src/agents/survey_agent/utils/work.py +2 -0
  236. src/cli.py +1611 -0
  237. src/config/__init__.py +213 -0
  238. src/config/default.yaml +1122 -0
  239. src/harness/LICENSE +21 -0
  240. src/harness/VENDORED.md +14 -0
  241. src/harness/src/__init__.py +0 -0
  242. src/harness/src/openharness/__init__.py +0 -0
  243. src/harness/src/openharness/__main__.py +6 -0
  244. src/harness/src/openharness/api/__init__.py +21 -0
  245. src/harness/src/openharness/api/client.py +281 -0
  246. src/harness/src/openharness/api/codex_client.py +407 -0
  247. src/harness/src/openharness/api/copilot_auth.py +240 -0
  248. src/harness/src/openharness/api/copilot_client.py +134 -0
  249. src/harness/src/openharness/api/errors.py +19 -0
  250. src/harness/src/openharness/api/openai_client.py +577 -0
  251. src/harness/src/openharness/api/provider.py +186 -0
  252. src/harness/src/openharness/api/registry.py +437 -0
  253. src/harness/src/openharness/api/usage.py +17 -0
  254. src/harness/src/openharness/auth/__init__.py +29 -0
  255. src/harness/src/openharness/auth/external.py +610 -0
  256. src/harness/src/openharness/auth/flows.py +189 -0
  257. src/harness/src/openharness/auth/manager.py +482 -0
  258. src/harness/src/openharness/auth/storage.py +269 -0
  259. src/harness/src/openharness/autopilot/__init__.py +23 -0
  260. src/harness/src/openharness/autopilot/service.py +2239 -0
  261. src/harness/src/openharness/autopilot/types.py +91 -0
  262. src/harness/src/openharness/bridge/__init__.py +20 -0
  263. src/harness/src/openharness/bridge/manager.py +106 -0
  264. src/harness/src/openharness/bridge/session_runner.py +46 -0
  265. src/harness/src/openharness/bridge/types.py +37 -0
  266. src/harness/src/openharness/bridge/work_secret.py +41 -0
  267. src/harness/src/openharness/channels/UPSTREAM +6 -0
  268. src/harness/src/openharness/channels/__init__.py +22 -0
  269. src/harness/src/openharness/channels/adapter.py +131 -0
  270. src/harness/src/openharness/channels/bus/__init__.py +6 -0
  271. src/harness/src/openharness/channels/bus/events.py +38 -0
  272. src/harness/src/openharness/channels/bus/queue.py +44 -0
  273. src/harness/src/openharness/channels/impl/__init__.py +6 -0
  274. src/harness/src/openharness/channels/impl/base.py +141 -0
  275. src/harness/src/openharness/channels/impl/dingtalk.py +445 -0
  276. src/harness/src/openharness/channels/impl/discord.py +311 -0
  277. src/harness/src/openharness/channels/impl/email.py +410 -0
  278. src/harness/src/openharness/channels/impl/feishu.py +1342 -0
  279. src/harness/src/openharness/channels/impl/manager.py +257 -0
  280. src/harness/src/openharness/channels/impl/matrix.py +700 -0
  281. src/harness/src/openharness/channels/impl/mochat.py +897 -0
  282. src/harness/src/openharness/channels/impl/qq.py +141 -0
  283. src/harness/src/openharness/channels/impl/slack.py +284 -0
  284. src/harness/src/openharness/channels/impl/telegram.py +525 -0
  285. src/harness/src/openharness/channels/impl/whatsapp.py +159 -0
  286. src/harness/src/openharness/cli.py +2551 -0
  287. src/harness/src/openharness/commands/__init__.py +21 -0
  288. src/harness/src/openharness/commands/registry.py +2783 -0
  289. src/harness/src/openharness/config/__init__.py +34 -0
  290. src/harness/src/openharness/config/paths.py +160 -0
  291. src/harness/src/openharness/config/schema.py +119 -0
  292. src/harness/src/openharness/config/settings.py +1104 -0
  293. src/harness/src/openharness/coordinator/__init__.py +12 -0
  294. src/harness/src/openharness/coordinator/agent_definitions.py +975 -0
  295. src/harness/src/openharness/coordinator/coordinator_mode.py +520 -0
  296. src/harness/src/openharness/engine/__init__.py +80 -0
  297. src/harness/src/openharness/engine/cost_tracker.py +24 -0
  298. src/harness/src/openharness/engine/messages.py +222 -0
  299. src/harness/src/openharness/engine/query.py +1188 -0
  300. src/harness/src/openharness/engine/query_engine.py +313 -0
  301. src/harness/src/openharness/engine/stream_events.py +90 -0
  302. src/harness/src/openharness/hooks/__init__.py +50 -0
  303. src/harness/src/openharness/hooks/events.py +20 -0
  304. src/harness/src/openharness/hooks/executor.py +242 -0
  305. src/harness/src/openharness/hooks/hot_reload.py +31 -0
  306. src/harness/src/openharness/hooks/loader.py +68 -0
  307. src/harness/src/openharness/hooks/schemas.py +66 -0
  308. src/harness/src/openharness/hooks/types.py +38 -0
  309. src/harness/src/openharness/keybindings/__init__.py +14 -0
  310. src/harness/src/openharness/keybindings/default_bindings.py +11 -0
  311. src/harness/src/openharness/keybindings/loader.py +22 -0
  312. src/harness/src/openharness/keybindings/parser.py +18 -0
  313. src/harness/src/openharness/keybindings/resolver.py +13 -0
  314. src/harness/src/openharness/mcp/__init__.py +79 -0
  315. src/harness/src/openharness/mcp/client.py +298 -0
  316. src/harness/src/openharness/mcp/config.py +16 -0
  317. src/harness/src/openharness/mcp/types.py +76 -0
  318. src/harness/src/openharness/memory/__init__.py +25 -0
  319. src/harness/src/openharness/memory/agent.py +91 -0
  320. src/harness/src/openharness/memory/manager.py +183 -0
  321. src/harness/src/openharness/memory/memdir.py +52 -0
  322. src/harness/src/openharness/memory/migrate.py +137 -0
  323. src/harness/src/openharness/memory/paths.py +22 -0
  324. src/harness/src/openharness/memory/relevance.py +145 -0
  325. src/harness/src/openharness/memory/scan.py +116 -0
  326. src/harness/src/openharness/memory/schema.py +443 -0
  327. src/harness/src/openharness/memory/search.py +71 -0
  328. src/harness/src/openharness/memory/team.py +90 -0
  329. src/harness/src/openharness/memory/types.py +33 -0
  330. src/harness/src/openharness/memory/usage.py +153 -0
  331. src/harness/src/openharness/output_styles/__init__.py +5 -0
  332. src/harness/src/openharness/output_styles/loader.py +42 -0
  333. src/harness/src/openharness/permissions/__init__.py +26 -0
  334. src/harness/src/openharness/permissions/checker.py +200 -0
  335. src/harness/src/openharness/permissions/modes.py +13 -0
  336. src/harness/src/openharness/personalization/__init__.py +6 -0
  337. src/harness/src/openharness/personalization/extractor.py +138 -0
  338. src/harness/src/openharness/personalization/rules.py +64 -0
  339. src/harness/src/openharness/personalization/session_hook.py +65 -0
  340. src/harness/src/openharness/platforms.py +86 -0
  341. src/harness/src/openharness/plugins/__init__.py +53 -0
  342. src/harness/src/openharness/plugins/bundled/__init__.py +0 -0
  343. src/harness/src/openharness/plugins/installer.py +39 -0
  344. src/harness/src/openharness/plugins/loader.py +730 -0
  345. src/harness/src/openharness/plugins/schemas.py +24 -0
  346. src/harness/src/openharness/plugins/types.py +59 -0
  347. src/harness/src/openharness/prompts/__init__.py +14 -0
  348. src/harness/src/openharness/prompts/claudemd.py +48 -0
  349. src/harness/src/openharness/prompts/context.py +187 -0
  350. src/harness/src/openharness/prompts/environment.py +135 -0
  351. src/harness/src/openharness/prompts/system_prompt.py +109 -0
  352. src/harness/src/openharness/sandbox/Dockerfile +6 -0
  353. src/harness/src/openharness/sandbox/__init__.py +33 -0
  354. src/harness/src/openharness/sandbox/adapter.py +148 -0
  355. src/harness/src/openharness/sandbox/docker_backend.py +232 -0
  356. src/harness/src/openharness/sandbox/docker_image.py +103 -0
  357. src/harness/src/openharness/sandbox/path_validator.py +37 -0
  358. src/harness/src/openharness/sandbox/session.py +63 -0
  359. src/harness/src/openharness/services/__init__.py +30 -0
  360. src/harness/src/openharness/services/autodream/__init__.py +34 -0
  361. src/harness/src/openharness/services/autodream/backup.py +104 -0
  362. src/harness/src/openharness/services/autodream/lock.py +138 -0
  363. src/harness/src/openharness/services/autodream/prompt.py +128 -0
  364. src/harness/src/openharness/services/autodream/service.py +313 -0
  365. src/harness/src/openharness/services/compact/__init__.py +1725 -0
  366. src/harness/src/openharness/services/cron.py +137 -0
  367. src/harness/src/openharness/services/cron_scheduler.py +595 -0
  368. src/harness/src/openharness/services/lsp/__init__.py +216 -0
  369. src/harness/src/openharness/services/memory_extract/__init__.py +261 -0
  370. src/harness/src/openharness/services/oauth/__init__.py +0 -0
  371. src/harness/src/openharness/services/session_backend.py +97 -0
  372. src/harness/src/openharness/services/session_memory/__init__.py +139 -0
  373. src/harness/src/openharness/services/session_storage.py +230 -0
  374. src/harness/src/openharness/services/token_estimation.py +15 -0
  375. src/harness/src/openharness/services/tool_outputs.py +55 -0
  376. src/harness/src/openharness/skills/__init__.py +44 -0
  377. src/harness/src/openharness/skills/_frontmatter.py +97 -0
  378. src/harness/src/openharness/skills/bundled/__init__.py +75 -0
  379. src/harness/src/openharness/skills/bundled/content/commit.md +25 -0
  380. src/harness/src/openharness/skills/bundled/content/debug.md +25 -0
  381. src/harness/src/openharness/skills/bundled/content/diagnose.md +35 -0
  382. src/harness/src/openharness/skills/bundled/content/plan.md +39 -0
  383. src/harness/src/openharness/skills/bundled/content/review.md +33 -0
  384. src/harness/src/openharness/skills/bundled/content/simplify.md +26 -0
  385. src/harness/src/openharness/skills/bundled/content/skill-creator.md +175 -0
  386. src/harness/src/openharness/skills/bundled/content/test.md +38 -0
  387. src/harness/src/openharness/skills/loader.py +229 -0
  388. src/harness/src/openharness/skills/registry.py +29 -0
  389. src/harness/src/openharness/skills/types.py +24 -0
  390. src/harness/src/openharness/state/__init__.py +6 -0
  391. src/harness/src/openharness/state/app_state.py +30 -0
  392. src/harness/src/openharness/state/store.py +40 -0
  393. src/harness/src/openharness/swarm/__init__.py +70 -0
  394. src/harness/src/openharness/swarm/in_process.py +693 -0
  395. src/harness/src/openharness/swarm/lockfile.py +24 -0
  396. src/harness/src/openharness/swarm/mailbox.py +522 -0
  397. src/harness/src/openharness/swarm/permission_sync.py +1168 -0
  398. src/harness/src/openharness/swarm/registry.py +410 -0
  399. src/harness/src/openharness/swarm/spawn_utils.py +229 -0
  400. src/harness/src/openharness/swarm/subprocess_backend.py +171 -0
  401. src/harness/src/openharness/swarm/team_lifecycle.py +910 -0
  402. src/harness/src/openharness/swarm/types.py +398 -0
  403. src/harness/src/openharness/swarm/worktree.py +315 -0
  404. src/harness/src/openharness/tasks/__init__.py +18 -0
  405. src/harness/src/openharness/tasks/local_agent_task.py +28 -0
  406. src/harness/src/openharness/tasks/local_shell_task.py +17 -0
  407. src/harness/src/openharness/tasks/manager.py +475 -0
  408. src/harness/src/openharness/tasks/stop_task.py +11 -0
  409. src/harness/src/openharness/tasks/types.py +32 -0
  410. src/harness/src/openharness/themes/__init__.py +21 -0
  411. src/harness/src/openharness/themes/builtin.py +89 -0
  412. src/harness/src/openharness/themes/loader.py +55 -0
  413. src/harness/src/openharness/themes/schema.py +54 -0
  414. src/harness/src/openharness/tools/__init__.py +107 -0
  415. src/harness/src/openharness/tools/agent_tool.py +141 -0
  416. src/harness/src/openharness/tools/ask_user_question_tool.py +46 -0
  417. src/harness/src/openharness/tools/base.py +80 -0
  418. src/harness/src/openharness/tools/bash_tool.py +259 -0
  419. src/harness/src/openharness/tools/brief_tool.py +33 -0
  420. src/harness/src/openharness/tools/config_tool.py +54 -0
  421. src/harness/src/openharness/tools/cron_create_tool.py +105 -0
  422. src/harness/src/openharness/tools/cron_delete_tool.py +32 -0
  423. src/harness/src/openharness/tools/cron_list_tool.py +69 -0
  424. src/harness/src/openharness/tools/cron_toggle_tool.py +37 -0
  425. src/harness/src/openharness/tools/enter_plan_mode_tool.py +28 -0
  426. src/harness/src/openharness/tools/enter_worktree_tool.py +80 -0
  427. src/harness/src/openharness/tools/exit_plan_mode_tool.py +28 -0
  428. src/harness/src/openharness/tools/exit_worktree_tool.py +42 -0
  429. src/harness/src/openharness/tools/file_edit_tool.py +95 -0
  430. src/harness/src/openharness/tools/file_read_tool.py +72 -0
  431. src/harness/src/openharness/tools/file_write_tool.py +87 -0
  432. src/harness/src/openharness/tools/glob_tool.py +175 -0
  433. src/harness/src/openharness/tools/grep_tool.py +374 -0
  434. src/harness/src/openharness/tools/image_generation_tool.py +447 -0
  435. src/harness/src/openharness/tools/image_to_text_tool.py +237 -0
  436. src/harness/src/openharness/tools/list_mcp_resources_tool.py +36 -0
  437. src/harness/src/openharness/tools/lsp_tool.py +154 -0
  438. src/harness/src/openharness/tools/mcp_auth_tool.py +71 -0
  439. src/harness/src/openharness/tools/mcp_tool.py +72 -0
  440. src/harness/src/openharness/tools/notebook_edit_tool.py +97 -0
  441. src/harness/src/openharness/tools/read_mcp_resource_tool.py +38 -0
  442. src/harness/src/openharness/tools/remote_trigger_tool.py +74 -0
  443. src/harness/src/openharness/tools/send_message_tool.py +58 -0
  444. src/harness/src/openharness/tools/skill_tool.py +43 -0
  445. src/harness/src/openharness/tools/sleep_tool.py +32 -0
  446. src/harness/src/openharness/tools/task_create_tool.py +56 -0
  447. src/harness/src/openharness/tools/task_get_tool.py +33 -0
  448. src/harness/src/openharness/tools/task_list_tool.py +35 -0
  449. src/harness/src/openharness/tools/task_output_tool.py +35 -0
  450. src/harness/src/openharness/tools/task_stop_tool.py +30 -0
  451. src/harness/src/openharness/tools/task_update_tool.py +50 -0
  452. src/harness/src/openharness/tools/team_create_tool.py +31 -0
  453. src/harness/src/openharness/tools/team_delete_tool.py +30 -0
  454. src/harness/src/openharness/tools/todo_write_tool.py +46 -0
  455. src/harness/src/openharness/tools/tool_search_tool.py +38 -0
  456. src/harness/src/openharness/tools/web_fetch_tool.py +117 -0
  457. src/harness/src/openharness/tools/web_search_tool.py +119 -0
  458. src/harness/src/openharness/ui/__init__.py +5 -0
  459. src/harness/src/openharness/ui/app.py +320 -0
  460. src/harness/src/openharness/ui/backend_host.py +941 -0
  461. src/harness/src/openharness/ui/coordinator_drain.py +198 -0
  462. src/harness/src/openharness/ui/input.py +32 -0
  463. src/harness/src/openharness/ui/output.py +265 -0
  464. src/harness/src/openharness/ui/permission_dialog.py +14 -0
  465. src/harness/src/openharness/ui/protocol.py +247 -0
  466. src/harness/src/openharness/ui/react_launcher.py +179 -0
  467. src/harness/src/openharness/ui/runtime.py +799 -0
  468. src/harness/src/openharness/ui/textual_app.py +495 -0
  469. src/harness/src/openharness/utils/__init__.py +0 -0
  470. src/harness/src/openharness/utils/file_lock.py +86 -0
  471. src/harness/src/openharness/utils/fs.py +98 -0
  472. src/harness/src/openharness/utils/helpers.py +77 -0
  473. src/harness/src/openharness/utils/network_guard.py +340 -0
  474. src/harness/src/openharness/utils/shell.py +147 -0
  475. src/harness/src/openharness/vim/__init__.py +5 -0
  476. src/harness/src/openharness/vim/transitions.py +8 -0
  477. src/harness/src/openharness/voice/__init__.py +7 -0
  478. src/harness/src/openharness/voice/keyterms.py +10 -0
  479. src/harness/src/openharness/voice/stream_stt.py +8 -0
  480. src/harness/src/openharness/voice/voice_mode.py +44 -0
  481. src/llm/__init__.py +29 -0
  482. src/llm/image_generation.py +402 -0
  483. src/llm/provider_registry.py +419 -0
  484. src/llm/runtime_env.py +64 -0
  485. src/llm/structured_output.py +131 -0
  486. src/llm/vision.py +198 -0
  487. src/memory/__init__.py +2 -0
  488. src/memory/api/__init__.py +1 -0
  489. src/memory/api/base_memory_system_api.py +98 -0
  490. src/memory/api/base_symbolic_memory_system_api.py +190 -0
  491. src/memory/api/base_vector_memory_system_api.py +116 -0
  492. src/memory/api/faiss_memory_system_api.py +228 -0
  493. src/memory/api/slot_process_api.py +827 -0
  494. src/memory/api/symbolic_memory_system_api.py +572 -0
  495. src/memory/memory_system/__init__.py +48 -0
  496. src/memory/memory_system/component_taxonomy.py +430 -0
  497. src/memory/memory_system/llm.py +437 -0
  498. src/memory/memory_system/models.py +168 -0
  499. src/memory/memory_system/user_prompt.py +418 -0
  500. src/memory/memory_system/utils.py +282 -0
  501. src/memory/memory_system/vectorstore.py +311 -0
  502. src/memory/memory_system/working_slot.py +99 -0
  503. src/pipeline/__init__.py +129 -0
  504. src/pipeline/contracts.py +531 -0
  505. src/pipeline/discipline_taxonomy.py +916 -0
  506. src/pipeline/evidence_coverage_ledger.py +1150 -0
  507. src/pipeline/evidence_refinement.py +620 -0
  508. src/pipeline/experiment_to_symbolic.py +137 -0
  509. src/pipeline/multimodal_evidence/__init__.py +28 -0
  510. src/pipeline/multimodal_evidence/capabilities.py +107 -0
  511. src/pipeline/multimodal_evidence/claims.py +135 -0
  512. src/pipeline/multimodal_evidence/contract.py +291 -0
  513. src/pipeline/multimodal_evidence/data_sh_compiler.py +505 -0
  514. src/pipeline/multimodal_evidence/handoff_binding.py +135 -0
  515. src/pipeline/multimodal_evidence/manifest.py +254 -0
  516. src/pipeline/multimodal_evidence/native_analysis.py +479 -0
  517. src/pipeline/multimodal_evidence/perception.py +277 -0
  518. src/pipeline/multimodal_evidence/query_binding.py +65 -0
  519. src/pipeline/multimodal_evidence/rendering.py +120 -0
  520. src/pipeline/multimodal_evidence/safety.py +42 -0
  521. src/pipeline/multimodal_evidence/sampling.py +69 -0
  522. src/pipeline/multimodal_evidence/service.py +148 -0
  523. src/pipeline/multimodal_evidence/survey_integration.py +460 -0
  524. src/pipeline/paper_identity.py +52 -0
  525. src/pipeline/research_design_inventory.py +338 -0
  526. src/pipeline/research_domain_resolution.py +669 -0
  527. src/pipeline/research_identity.py +548 -0
  528. src/pipeline/research_question_contract.py +646 -0
  529. src/pipeline/retrieval_lanes.py +889 -0
  530. src/pipeline/run_loop.py +862 -0
  531. src/pipeline/science_events.py +30 -0
  532. src/pipeline/science_manifests.py +602 -0
  533. src/pipeline/science_run.py +918 -0
  534. src/pipeline/science_stages.py +709 -0
  535. src/pipeline/science_workflow.py +807 -0
  536. src/pipeline/sh_cluster_projection.py +306 -0
  537. src/pipeline/sh_graph_provenance.py +648 -0
  538. src/pipeline/subhypothesis_decomposition.py +392 -0
  539. src/pipeline/subhypothesis_evidence.py +856 -0
  540. src/pipeline/survey_evidence_plan.py +858 -0
  541. src/pipeline/survey_gap_adjudication.py +647 -0
  542. src/pipeline/survey_gap_candidates.py +840 -0
  543. src/pipeline/survey_gap_ledger.py +683 -0
  544. src/pipeline/survey_gap_triage.py +401 -0
  545. src/pipeline/survey_handoff_persistence.py +481 -0
  546. src/pipeline/survey_handoff_projection.py +457 -0
  547. src/pipeline/survey_idea_handoff.py +1112 -0
  548. src/pipeline/survey_idea_loader.py +289 -0
  549. src/research_run_ids.py +11 -0
@@ -0,0 +1,342 @@
1
+ """Component novelty scoring utilities backed by embedding similarity."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from collections import Counter, defaultdict
7
+ from pathlib import Path
8
+ from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple
9
+ from sentence_transformers import SentenceTransformer
10
+
11
+ from src.agents.idea_agent.agent.prompts.component_novelty_evaluation import (
12
+ COMPONENT_NOVELTY_EVALUATION_PROMPT,
13
+ )
14
+ from src.agents.idea_agent.utils.core.json_utils import pretty_json
15
+ from src.agents.idea_agent.utils.core.response_parsing import parse_json_response
16
+ from src.agents.idea_agent.utils.papers.paper_graph_vector_store import (
17
+ PaperGraphComponentVectorStore,
18
+ )
19
+
20
+
21
+ def _clamp_novelty_score(value: Any) -> float:
22
+ score = float(value)
23
+ if math.isnan(score) or math.isinf(score):
24
+ raise ValueError(f"Invalid novelty score: {value!r}")
25
+ return max(0.0, min(5.0, score))
26
+
27
+
28
+ def _clip_text(value: Any, limit: int = 6000) -> str:
29
+ text = "" if value is None else str(value).strip()
30
+ if limit <= 0 or len(text) <= limit:
31
+ return text
32
+ return text[: max(1, limit - 3)] + "..."
33
+
34
+
35
+ from src.agents.idea_agent.utils.mcts.scientific_rubric import PROFILE_NOVELTY_AXES
36
+
37
+
38
+ class ComponentNoveltyScorer:
39
+ """Retrieve nearby paper-graph nodes from component explanations and ask an LLM for novelty."""
40
+
41
+ def __init__(
42
+ self,
43
+ model_name_or_path: str = "all-MiniLM-L6-v2",
44
+ *,
45
+ index_dir: Optional[str] = None,
46
+ retrieval_top_k: int = 50,
47
+ evidence_node_top_k: int = 5,
48
+ evaluation_model: str = "gpt-5.2",
49
+ evaluation_temperature: float = 0.001,
50
+ evaluation_max_tokens: int = 2048,
51
+ chat_fn: Optional[Callable[..., str]] = None,
52
+ logger: Optional[Any] = None,
53
+ log_sink: Optional[Callable[[str, str], None]] = None,
54
+ vector_store: Optional[PaperGraphComponentVectorStore] = None,
55
+ ) -> None:
56
+ self.model_name_or_path = model_name_or_path
57
+ self.index_dir = index_dir
58
+ self.retrieval_top_k = max(1, int(retrieval_top_k))
59
+ self.evidence_node_top_k = max(1, int(evidence_node_top_k))
60
+ self.evaluation_model = evaluation_model
61
+ self.evaluation_temperature = float(evaluation_temperature)
62
+ self.evaluation_max_tokens = max(256, int(evaluation_max_tokens))
63
+ self.chat_fn = chat_fn
64
+ self.logger = logger
65
+ self.log_sink = log_sink
66
+
67
+ self._model: Optional[Any] = None
68
+ self._vector_store: Optional[PaperGraphComponentVectorStore] = vector_store
69
+ self._disabled_error: Optional[str] = None
70
+ self.last_novelty_axes: Dict[str, float] = {}
71
+
72
+ def _log(self, level: str, message: str, *args: Any) -> None:
73
+ rendered = message % args if args else message
74
+ if self.logger is not None:
75
+ log_method = getattr(self.logger, level, None)
76
+ if callable(log_method):
77
+ log_method(rendered)
78
+ if self.log_sink is not None:
79
+ try:
80
+ self.log_sink(level, rendered)
81
+ except Exception:
82
+ pass
83
+
84
+ def _resolve_model_source(self) -> str:
85
+ candidate = Path(str(self.model_name_or_path)).expanduser()
86
+ if candidate.exists():
87
+ return str(candidate.resolve())
88
+ local_path = Path(__file__).resolve().parents[5] / "models" / str(self.model_name_or_path)
89
+ return str(local_path) if local_path.exists() else str(self.model_name_or_path)
90
+
91
+ def _get_model(self) -> Any:
92
+ if self._model is not None:
93
+ return self._model
94
+ if self._vector_store is not None:
95
+ self._model = self._vector_store.get_model()
96
+ return self._model
97
+ self._model = SentenceTransformer(self._resolve_model_source())
98
+ return self._model
99
+
100
+ def _get_vector_store(self) -> PaperGraphComponentVectorStore:
101
+ if self._vector_store is None:
102
+ self._vector_store = PaperGraphComponentVectorStore(
103
+ model_name_or_path=self.model_name_or_path,
104
+ index_dir=self.index_dir,
105
+ model=self._model,
106
+ )
107
+ if self._vector_store.size <= 0:
108
+ self._vector_store.load(allow_stale_graph=True)
109
+ return self._vector_store
110
+
111
+ def _extract_components(
112
+ self,
113
+ state: Any,
114
+ ) -> Tuple[List[Dict[str, str]], Dict[str, Any]]:
115
+ if hasattr(state, "component_inventory") and callable(state.component_inventory):
116
+ components_with_explanations = state.component_inventory()
117
+ payload = state.to_payload() if hasattr(state, "to_payload") and callable(state.to_payload) else {}
118
+ return components_with_explanations, payload
119
+
120
+ if isinstance(state, dict):
121
+ components = state.get("components_with_explanations")
122
+ if isinstance(components, list):
123
+ return components, dict(state)
124
+
125
+ if isinstance(state, list):
126
+ return state, {}
127
+
128
+ raise ValueError("Unsupported state payload for component novelty scoring")
129
+
130
+ def _prepare_component_queries(
131
+ self,
132
+ components_with_explanations: Sequence[Dict[str, str]],
133
+ idea_payload: Optional[Dict[str, Any]] = None,
134
+ ) -> List[Dict[str, str]]:
135
+ queries: List[Dict[str, str]] = []
136
+ for item in components_with_explanations:
137
+ if not isinstance(item, dict):
138
+ continue
139
+ component = str(item.get("component", "")).strip()
140
+ explanation = str(item.get("explanation", "")).strip()
141
+ query_text = explanation
142
+ if not query_text:
143
+ continue
144
+ queries.append(
145
+ {
146
+ "component": component or f"component_{len(queries)}",
147
+ "explanation": explanation,
148
+ "query_text": query_text,
149
+ }
150
+ )
151
+ idea_payload = idea_payload if isinstance(idea_payload, dict) else {}
152
+ for label, value in (
153
+ ("central_hypothesis", idea_payload.get("core_contribution")),
154
+ ("mechanism_or_relation", idea_payload.get("method")),
155
+ ):
156
+ text = str(value or "").strip()
157
+ if text:
158
+ queries.append(
159
+ {
160
+ "component": label,
161
+ "explanation": text,
162
+ "query_text": text,
163
+ }
164
+ )
165
+ return queries
166
+
167
+ def _embed_queries(self, query_payloads: Sequence[Dict[str, str]]) -> Any:
168
+ model = self._get_model()
169
+ return model.encode(
170
+ [item["query_text"] for item in query_payloads],
171
+ convert_to_numpy=True,
172
+ normalize_embeddings=True,
173
+ show_progress_bar=False,
174
+ )
175
+
176
+ def _collect_evidence_nodes(
177
+ self,
178
+ store: PaperGraphComponentVectorStore,
179
+ query_payloads: Sequence[Dict[str, str]],
180
+ component_hits: Sequence[Sequence[Dict[str, Any]]],
181
+ ) -> List[Dict[str, Any]]:
182
+ node_counts: Counter[str] = Counter()
183
+ node_best_scores: Dict[str, float] = {}
184
+ node_support: Dict[str, List[Dict[str, Any]]] = defaultdict(list)
185
+
186
+ for query_index, hits in enumerate(component_hits):
187
+ query_info = query_payloads[query_index] if query_index < len(query_payloads) else {}
188
+ for hit in hits:
189
+ node_id = str(hit.get("node_id") or "")
190
+ if not node_id:
191
+ continue
192
+ score = float(hit.get("score") or 0.0)
193
+ node_counts[node_id] += 1
194
+ prev = node_best_scores.get(node_id)
195
+ if prev is None or score > prev:
196
+ node_best_scores[node_id] = score
197
+ if len(node_support[node_id]) < 3:
198
+ node_support[node_id].append(
199
+ {
200
+ "query_component": query_info.get("component", ""),
201
+ "query_text": _clip_text(query_info.get("query_text", "")),
202
+ "matched_component": hit.get("component_name"),
203
+ "score": score,
204
+ }
205
+ )
206
+
207
+ if not node_counts:
208
+ return []
209
+
210
+ ranked_node_ids = sorted(
211
+ node_counts.keys(),
212
+ key=lambda node_id: (
213
+ -node_counts[node_id],
214
+ -node_best_scores.get(node_id, 0.0),
215
+ str(store.get_core_node(node_id).get("paper_title") or node_id).lower(),
216
+ ),
217
+ )
218
+
219
+ evidence_nodes: List[Dict[str, Any]] = []
220
+ for node_id in ranked_node_ids[: self.evidence_node_top_k]:
221
+ core_node = store.get_core_node(node_id)
222
+ evidence_nodes.append(
223
+ {
224
+ "node_id": node_id,
225
+ "label": core_node.get("full_name") or core_node.get("label") or node_id,
226
+ "paper_title": core_node.get("paper_title") or "",
227
+ "match_count": int(node_counts[node_id]),
228
+ "best_score": float(node_best_scores.get(node_id, 0.0)),
229
+ "summary": _clip_text(core_node.get("summary") or ""),
230
+ "insight": _clip_text(core_node.get("insight") or ""),
231
+ "support": node_support.get(node_id, []),
232
+ }
233
+ )
234
+ return evidence_nodes
235
+
236
+ def _evaluate_with_llm(
237
+ self,
238
+ *,
239
+ topic: str,
240
+ idea_payload: Dict[str, Any],
241
+ components_with_explanations: Sequence[Dict[str, str]],
242
+ evidence_nodes: Sequence[Dict[str, Any]],
243
+ ) -> float:
244
+ if self.chat_fn is None:
245
+ raise RuntimeError("chat_fn is unavailable for component novelty scoring")
246
+
247
+ self.last_novelty_axes = {}
248
+ intervention = idea_payload.get("scientific_intervention")
249
+ intervention = intervention if isinstance(intervention, dict) else {}
250
+ profile_id = str(intervention.get("profile_id") or "generic_scientific").strip().lower()
251
+ novelty_axes = PROFILE_NOVELTY_AXES.get(profile_id, PROFILE_NOVELTY_AXES["generic_scientific"])
252
+ prompt = COMPONENT_NOVELTY_EVALUATION_PROMPT.format(
253
+ topic=topic or "Unknown topic",
254
+ profile_id=profile_id,
255
+ novelty_axes=", ".join(novelty_axes),
256
+ idea_state=pretty_json(idea_payload),
257
+ components_with_explanations=pretty_json(list(components_with_explanations)),
258
+ retrieval_top_k=self.retrieval_top_k,
259
+ retrieved_nodes=pretty_json(list(evidence_nodes)),
260
+ )
261
+ response = self.chat_fn(
262
+ prompt,
263
+ model=self.evaluation_model,
264
+ temperature=self.evaluation_temperature,
265
+ max_output_tokens=self.evaluation_max_tokens,
266
+ stage="component_novelty_evaluation",
267
+ )
268
+ payload = parse_json_response(response)
269
+ if isinstance(payload, list):
270
+ payload = payload[0] if payload else {}
271
+ if not isinstance(payload, dict):
272
+ payload = {}
273
+ raw_axes = payload.get("novelty_axes") if isinstance(payload, dict) else None
274
+ if isinstance(raw_axes, dict):
275
+ self.last_novelty_axes = {
276
+ str(key): _clamp_novelty_score(value)
277
+ for key, value in raw_axes.items()
278
+ if str(key).strip() in novelty_axes
279
+ }
280
+ score = payload.get("rubric_score")
281
+ if score is None:
282
+ score = payload.get("scientific_novelty")
283
+ if score is None:
284
+ score = payload.get("perceived_novelty", payload.get("novelty"))
285
+ if score is None and isinstance(payload.get("novelty_axes"), dict):
286
+ axis_scores = []
287
+ for axis_name in novelty_axes:
288
+ axis = payload["novelty_axes"].get(axis_name)
289
+ if axis is None:
290
+ continue
291
+ try:
292
+ axis_scores.append(_clamp_novelty_score(axis))
293
+ except (TypeError, ValueError):
294
+ continue
295
+ if axis_scores:
296
+ score = sum(axis_scores) / len(axis_scores)
297
+ if score is None:
298
+ raise ValueError(f"Novelty evaluator missing rubric_score: {payload}")
299
+ return _clamp_novelty_score(score)
300
+
301
+ def score(self, state: Any, topic: str = "") -> float:
302
+ if self._disabled_error:
303
+ raise RuntimeError(self._disabled_error)
304
+
305
+ components_with_explanations, idea_payload = self._extract_components(state)
306
+ query_payloads = self._prepare_component_queries(
307
+ components_with_explanations,
308
+ idea_payload,
309
+ )
310
+ if not query_payloads:
311
+ raise ValueError("No component explanations were provided for novelty scoring")
312
+
313
+ try:
314
+ embeddings = self._embed_queries(query_payloads)
315
+ store = self._get_vector_store()
316
+ except Exception as exc:
317
+ self._disabled_error = str(exc)
318
+ raise
319
+
320
+ component_hits = store.search_component_hits_by_vectors(
321
+ query_embeddings=embeddings,
322
+ top_k=self.retrieval_top_k,
323
+ )
324
+ evidence_nodes = self._collect_evidence_nodes(store, query_payloads, component_hits)
325
+ if not evidence_nodes:
326
+ raise ValueError("Component novelty retrieval returned no evidence nodes")
327
+
328
+ self._log(
329
+ "info",
330
+ "[ComponentNovelty] Retrieved top evidence nodes: %s",
331
+ ", ".join(
332
+ f"{item['label']}#{item['match_count']}"
333
+ for item in evidence_nodes
334
+ ),
335
+ )
336
+
337
+ return self._evaluate_with_llm(
338
+ topic=topic,
339
+ idea_payload=idea_payload,
340
+ components_with_explanations=query_payloads,
341
+ evidence_nodes=evidence_nodes,
342
+ )
@@ -0,0 +1,302 @@
1
+ """Canonical defect registry shared by MCTS evaluation and skill selection."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Dict, Optional, Set
6
+
7
+
8
+ DEFECT_REGISTRY: Dict[str, str] = {
9
+ # mechanism-first innovation
10
+ "stagnant_novelty": (
11
+ "The idea lacks a genuinely new mechanism; contributions feel incremental "
12
+ "or re-package known techniques without a clear novel insight."
13
+ ),
14
+ "unclear_mechanism": (
15
+ "The core mechanism is vaguely described or under-specified, making it "
16
+ "hard to reproduce, reason about, or evaluate the contribution."
17
+ ),
18
+ "validation_gap": (
19
+ "The validation plan is missing key ablations, stress tests, or fair "
20
+ "comparisons needed to support the claims."
21
+ ),
22
+ # domain-neutral scientific reasoning and evidence defects
23
+ "unsupported_causal_link": (
24
+ "The proposal claims a causal or mechanistic link that is not supported "
25
+ "by the stated intervention, observation, proof, or evidence."
26
+ ),
27
+ "unresolved_alternative_explanation": (
28
+ "A competing explanation remains plausible and the proposed evidence does "
29
+ "not distinguish it from the preferred mechanism."
30
+ ),
31
+ "missing_comparator": (
32
+ "No adequate control, counterfactual, reference case, or competing condition "
33
+ "is specified for interpreting the claimed effect."
34
+ ),
35
+ "measurement_construct_mismatch": (
36
+ "The observable, assay, endpoint, or characterization does not validly "
37
+ "represent the construct or mechanism being claimed."
38
+ ),
39
+ "missing_boundary_condition": (
40
+ "The proposal does not state the regime, population, scale, assumptions, "
41
+ "or operating conditions where the claim holds or fails."
42
+ ),
43
+ "nonidentifiable_mechanism": (
44
+ "The proposed mechanism cannot be distinguished from plausible alternatives "
45
+ "with the stated data, experiment, observation, or proof."
46
+ ),
47
+ "confounding_or_selection_bias": (
48
+ "Confounding, selection, sampling, or allocation bias can explain the "
49
+ "observed relation and is not adequately controlled."
50
+ ),
51
+ "invalid_generalization": (
52
+ "The conclusion is extended beyond the supported object, sample, regime, "
53
+ "scale, domain, or formal validity conditions."
54
+ ),
55
+ "claim_overreach": (
56
+ "The wording claims more causal, universal, predictive, or mechanistic "
57
+ "strength than the evidence and validation can justify."
58
+ ),
59
+ "insufficient_reproducibility": (
60
+ "The intervention, measurement, derivation, protocol, or conditions are "
61
+ "not specified well enough for an independent reproduction."
62
+ ),
63
+ "missing_assumption": (
64
+ "A formal or scientific assumption required for the stated relation is "
65
+ "implicit, incomplete, or inconsistent."
66
+ ),
67
+ "missing_counterexample": (
68
+ "The proposal lacks a counterexample, limiting case, or failure probe that "
69
+ "could expose the boundary of the claim."
70
+ ),
71
+ "proof_gap": (
72
+ "A required proof, derivation, construction, or verification step is "
73
+ "missing or does not establish the stated conclusion."
74
+ ),
75
+ # alternative-path-contrast
76
+ "brittle_single_path": (
77
+ "The method assumes one dominant operating regime and lacks a structured "
78
+ "fallback or contrastive treatment for rare regimes, failures, or recovery."
79
+ ),
80
+ "rare_regime_failure": (
81
+ "Behavior under boundary conditions, overload, adversarial inputs, or "
82
+ "other rare regimes is weak or unexamined."
83
+ ),
84
+ "weak_fallback_behavior": (
85
+ "Fallback, recovery, or degraded-mode behavior is missing, underspecified, "
86
+ "or ineffective when the primary path breaks down."
87
+ ),
88
+ # modular architecture
89
+ "feature_dumping": (
90
+ "Multiple components or features are added simultaneously without "
91
+ "individual justification, making ablation or attribution impossible."
92
+ ),
93
+ "monolithic_design": (
94
+ "Core responsibilities are trapped inside a single tightly coupled block, "
95
+ "resisting modular analysis, replacement, or incremental improvement."
96
+ ),
97
+ "harder_to_ablate": (
98
+ "Design choices make it difficult to isolate the effect of any single "
99
+ "component through controlled ablation studies."
100
+ ),
101
+ # coordination across scales or layers
102
+ "scale_mismatch": (
103
+ "The solution operates at one scale, layer, or tier while the problem "
104
+ "requires coordination across multiple scales or granularities."
105
+ ),
106
+ "coordination_failure": (
107
+ "Multiple subsystems, branches, or layers fail to maintain a coherent "
108
+ "decision rule, causing conflicts, redundancy, or information loss."
109
+ ),
110
+ "latency_bottleneck": (
111
+ "A component, synchronization point, or coordination rule introduces "
112
+ "unacceptable latency or throughput collapse."
113
+ ),
114
+ # hierarchical decomposition
115
+ "responsibility_entanglement": (
116
+ "Planning, control, execution, or analysis responsibilities are tangled "
117
+ "together instead of being separated into explicit layers or roles."
118
+ ),
119
+ # feedback and adaptation
120
+ "silent_failure": (
121
+ "The system produces wrong or degraded outputs without exposing enough "
122
+ "signal for downstream detection or correction."
123
+ ),
124
+ "drift": (
125
+ "Performance degrades over time or across regimes as workloads, data, or "
126
+ "operating conditions shift away from the design assumptions."
127
+ ),
128
+ "open_loop_fragility": (
129
+ "The system acts in an open-loop manner and cannot adapt when outcomes, "
130
+ "errors, or environment conditions change."
131
+ ),
132
+ # theory-guided reformulation
133
+ "theory_gap": (
134
+ "The approach lacks grounding in a transferable principle, invariant, or "
135
+ "formal lens that could justify the mechanism design."
136
+ ),
137
+ "weak_generalization": (
138
+ "Evidence that the approach transfers across domains, workloads, "
139
+ "distributions, or operating regimes is insufficient or absent."
140
+ ),
141
+ # speculative execution
142
+ "over_conservative_execution": (
143
+ "The system pays full serialization, synchronization, or safety cost on "
144
+ "every path because it lacks a principled optimistic fast path."
145
+ ),
146
+ "rollback_blindspot": (
147
+ "The design lacks explicit detection, rollback, or repair when optimistic "
148
+ "actions misfire or speculative assumptions are violated."
149
+ ),
150
+ # default fallback used when no context-specific defect is identified
151
+ "unexplored_gap": (
152
+ "No specific defect has been identified yet; the idea space is still "
153
+ "being explored and requires targeted analysis."
154
+ ),
155
+ }
156
+
157
+
158
+ DEFECT_PROFILE_PRIORITIES: Dict[str, tuple[str, ...]] = {
159
+ "computational_algorithmic": (
160
+ "feature_dumping",
161
+ "latency_bottleneck",
162
+ "weak_fallback_behavior",
163
+ "monolithic_design",
164
+ "stagnant_novelty",
165
+ ),
166
+ "physical_materials_chemical": (
167
+ "measurement_construct_mismatch",
168
+ "unsupported_causal_link",
169
+ "missing_boundary_condition",
170
+ "insufficient_reproducibility",
171
+ ),
172
+ "life_molecular_mechanistic": (
173
+ "unsupported_causal_link",
174
+ "missing_comparator",
175
+ "measurement_construct_mismatch",
176
+ "missing_boundary_condition",
177
+ "confounding_or_selection_bias",
178
+ ),
179
+ "clinical_health": (
180
+ "missing_comparator",
181
+ "confounding_or_selection_bias",
182
+ "invalid_generalization",
183
+ "claim_overreach",
184
+ "measurement_construct_mismatch",
185
+ "missing_boundary_condition",
186
+ ),
187
+ "earth_environment_agro": (
188
+ "unsupported_causal_link",
189
+ "missing_boundary_condition",
190
+ "measurement_construct_mismatch",
191
+ "invalid_generalization",
192
+ ),
193
+ "energy_engineering_systems": (
194
+ "unsupported_causal_link",
195
+ "missing_boundary_condition",
196
+ "insufficient_reproducibility",
197
+ "invalid_generalization",
198
+ ),
199
+ "formal_theoretical": (
200
+ "missing_assumption",
201
+ "proof_gap",
202
+ "missing_counterexample",
203
+ "nonidentifiable_mechanism",
204
+ "invalid_generalization",
205
+ ),
206
+ "generic_scientific": (
207
+ "unsupported_causal_link",
208
+ "unresolved_alternative_explanation",
209
+ "missing_comparator",
210
+ "missing_boundary_condition",
211
+ "claim_overreach",
212
+ ),
213
+ }
214
+
215
+
216
+ # Profile-native defects are mapped onto the existing skill vocabulary so
217
+ # legacy skill files remain readable while profile-aware selection can still
218
+ # reward the right intervention family.
219
+ PROFILE_DEFECT_SKILL_MATCHES: Dict[str, Dict[str, tuple[str, ...]]] = {
220
+ "computational_algorithmic": {},
221
+ "physical_materials_chemical": {
222
+ "measurement_construct_mismatch": ("mechanism-commit-innovation", "feedback-closed-loop"),
223
+ "unsupported_causal_link": ("mechanism-commit-innovation", "alternative-path-contrast"),
224
+ "missing_boundary_condition": ("alternative-path-contrast", "feedback-closed-loop"),
225
+ "insufficient_reproducibility": ("mechanism-commit-innovation", "feedback-closed-loop"),
226
+ },
227
+ "life_molecular_mechanistic": {
228
+ "unsupported_causal_link": ("mechanism-commit-innovation", "alternative-path-contrast"),
229
+ "missing_comparator": ("alternative-path-contrast",),
230
+ "measurement_construct_mismatch": ("mechanism-commit-innovation", "feedback-closed-loop"),
231
+ "missing_boundary_condition": ("alternative-path-contrast", "feedback-closed-loop"),
232
+ "confounding_or_selection_bias": ("alternative-path-contrast",),
233
+ },
234
+ "clinical_health": {
235
+ "missing_comparator": ("alternative-path-contrast",),
236
+ "confounding_or_selection_bias": ("alternative-path-contrast",),
237
+ "invalid_generalization": ("alternative-path-contrast", "theory-transfer-injection"),
238
+ "claim_overreach": ("alternative-path-contrast",),
239
+ "measurement_construct_mismatch": ("mechanism-commit-innovation", "feedback-closed-loop"),
240
+ "missing_boundary_condition": ("alternative-path-contrast", "feedback-closed-loop"),
241
+ },
242
+ "earth_environment_agro": {
243
+ "unsupported_causal_link": ("mechanism-commit-innovation", "alternative-path-contrast"),
244
+ "missing_boundary_condition": ("alternative-path-contrast", "feedback-closed-loop"),
245
+ "measurement_construct_mismatch": ("mechanism-commit-innovation", "feedback-closed-loop"),
246
+ "invalid_generalization": ("alternative-path-contrast", "theory-transfer-injection"),
247
+ },
248
+ "energy_engineering_systems": {
249
+ "unsupported_causal_link": ("mechanism-commit-innovation", "alternative-path-contrast"),
250
+ "missing_boundary_condition": ("alternative-path-contrast", "feedback-closed-loop"),
251
+ "insufficient_reproducibility": ("mechanism-commit-innovation", "feedback-closed-loop"),
252
+ "invalid_generalization": ("alternative-path-contrast", "theory-transfer-injection"),
253
+ },
254
+ "formal_theoretical": {
255
+ "missing_assumption": ("mechanism-commit-innovation", "theory-transfer-injection"),
256
+ "proof_gap": ("theory-transfer-injection",),
257
+ "missing_counterexample": ("alternative-path-contrast",),
258
+ "nonidentifiable_mechanism": ("alternative-path-contrast", "theory-transfer-injection"),
259
+ "invalid_generalization": ("alternative-path-contrast", "theory-transfer-injection"),
260
+ },
261
+ "generic_scientific": {
262
+ "unsupported_causal_link": ("mechanism-commit-innovation", "alternative-path-contrast"),
263
+ "unresolved_alternative_explanation": ("alternative-path-contrast", "theory-transfer-injection"),
264
+ "missing_comparator": ("alternative-path-contrast",),
265
+ "missing_boundary_condition": ("alternative-path-contrast", "feedback-closed-loop"),
266
+ "claim_overreach": ("alternative-path-contrast",),
267
+ },
268
+ }
269
+
270
+
271
+ def profile_skill_defect_tags(profile_id: Optional[str], skill_name: str) -> Set[str]:
272
+ """Return profile-native defects that a legacy skill can remediate."""
273
+
274
+ profile_key = str(profile_id or "generic_scientific").strip().lower()
275
+ profile_matches = PROFILE_DEFECT_SKILL_MATCHES.get(profile_key, {})
276
+ priority_tags = set(DEFECT_PROFILE_PRIORITIES.get(profile_key, ()))
277
+ if priority_tags:
278
+ profile_matches = {
279
+ defect: skill_names
280
+ for defect, skill_names in profile_matches.items()
281
+ if defect in priority_tags
282
+ }
283
+ skill_key = str(skill_name or "").strip()
284
+ return {
285
+ defect
286
+ for defect, skill_names in profile_matches.items()
287
+ if skill_key in skill_names
288
+ }
289
+
290
+
291
+ def format_defect_registry(profile_id: Optional[str] = None) -> str:
292
+ """Return a prompt-friendly listing of canonical defect tags."""
293
+ profile_key = str(profile_id or "").strip()
294
+ priority_tags = set(DEFECT_PROFILE_PRIORITIES.get(profile_key, ()))
295
+ header = "Canonical defect tag registry (use ONLY these tags in detected_defects):"
296
+ if profile_key:
297
+ header += f"\nProfile priority: {profile_key}"
298
+ lines = [header]
299
+ for tag, desc in DEFECT_REGISTRY.items():
300
+ priority = " [profile-priority]" if tag in priority_tags else ""
301
+ lines.append(f" - {tag}{priority}: {desc}")
302
+ return "\n".join(lines)