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,209 @@
1
+ """Deterministic, cross-discipline section routing for research-plan writing."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from copy import deepcopy
6
+ from typing import Any, Mapping
7
+
8
+
9
+ AUTHOR_TEMPLATE_FAMILIES = (
10
+ "computational_digital",
11
+ "mathematics_theory",
12
+ "materials_chemical",
13
+ "engineering_energy",
14
+ "earth_environment_agro",
15
+ "life_veterinary",
16
+ "clinical_health",
17
+ )
18
+
19
+ _DISCIPLINE_TEMPLATE = {
20
+ "17": "computational_digital",
21
+ "26": "mathematics_theory",
22
+ "15": "materials_chemical",
23
+ "16": "materials_chemical",
24
+ "25": "materials_chemical",
25
+ "21": "engineering_energy",
26
+ "22": "engineering_energy",
27
+ "11": "earth_environment_agro",
28
+ "19": "earth_environment_agro",
29
+ "23": "earth_environment_agro",
30
+ "13": "life_veterinary",
31
+ "24": "life_veterinary",
32
+ "28": "life_veterinary",
33
+ "30": "life_veterinary",
34
+ "34": "life_veterinary",
35
+ "27": "clinical_health",
36
+ "29": "clinical_health",
37
+ "35": "clinical_health",
38
+ "36": "clinical_health",
39
+ }
40
+
41
+ _COMMON_ROUTES = (
42
+ ("abstract", "Abstract", "abstract", ("planned_contribution", "expected_outcome")),
43
+ ("introduction", "Introduction", "sections", ("background", "research_gap", "planned_contribution", "design_assumption")),
44
+ ("survey_and_research_gap", "Background, Survey, and Research Gap", "sections", ("background", "survey_evidence", "research_gap")),
45
+ ("research_questions_and_contributions", "Research Questions and Planned Contributions", "sections", ("research_question", "planned_contribution", "design_assumption")),
46
+ ("idea_origin_and_selection", "Idea Source Checkpoints and Direction Selection Audit", "sections", ("idea_provenance", "design_assumption")),
47
+ ("formal_problem_and_hypotheses", "Problem Definition, Assumptions, and Hypotheses", "sections", ("formal_definition", "formal_proposition", "hypothesis", "design_assumption")),
48
+ ("study_design_and_methods", "Study Design and Methods", "sections", ("planned_method", "design_assumption", "needs_human_input")),
49
+ ("expected_outcomes", "Expected Outcome Branches and Conditional Conclusions", "sections", ("expected_outcome", "conditional_conclusion")),
50
+ ("risk_limitations_and_review", "Risks, Limitations, and Human Review Requirements", "sections", ("limitation", "needs_human_input", "review_requirement")),
51
+ ("references", "References", "sections", ("citation_inventory",)),
52
+ ("appendix_idea_evolution", "Idea Source Checkpoints and Direction Selection Audit", "appendices", ("idea_provenance",)),
53
+ ("appendix_variables_and_definitions", "Variables, Symbols, and Operational Definitions", "appendices", ("formal_definition", "planned_method", "design_assumption", "needs_human_input")),
54
+ ("appendix_evidence_and_review", "Evidence Coverage, Unknown Items, and Review Checklist", "appendices", ("survey_evidence", "limitation", "review_requirement", "needs_human_input")),
55
+ )
56
+
57
+ _TEMPLATE_ROUTES = {
58
+ "computational_digital": (
59
+ ("computational_evaluation_protocol", "Data, Baselines, Ablations, and Robustness", ("planned_method", "design_assumption", "needs_human_input")),
60
+ ),
61
+ "mathematics_theory": (
62
+ ("definitions_and_propositions", "Definitions, Propositions, and Proof Obligations", ("formal_definition", "formal_proposition", "proof_obligation")),
63
+ ("forward_derivation_and_counterexamples", "Forward Derivation and Counterexample Search Plan", ("forward_derivation", "counterexample_plan", "limitation")),
64
+ ),
65
+ "materials_chemical": (
66
+ ("materials_and_characterization", "Material System, Characterization, and DOE Plan", ("planned_method", "design_assumption", "needs_human_input")),
67
+ ),
68
+ "engineering_energy": (
69
+ ("system_boundary_and_validation", "System Boundary, Constraints, and Layered Validation", ("planned_method", "design_assumption", "needs_human_input")),
70
+ ),
71
+ "earth_environment_agro": (
72
+ ("spatiotemporal_design", "Spatiotemporal Units, Sampling Frame, and Environmental Covariates", ("planned_method", "design_assumption", "needs_human_input")),
73
+ ),
74
+ "life_veterinary": (
75
+ ("model_controls_and_repeats", "Model System, Controls, Assays, and Replicates", ("planned_method", "design_assumption", "needs_human_input", "review_requirement")),
76
+ ),
77
+ "clinical_health": (
78
+ ("pico_endpoints_and_governance", "PICO, Endpoints, Bias Control, and Governance", ("planned_method", "design_assumption", "needs_human_input", "review_requirement")),
79
+ ),
80
+ }
81
+
82
+ _MATHEMATICS_THEORY_ROUTE_ROLES = {
83
+ "formal_problem_and_hypotheses": "candidate_theorem_entry",
84
+ "definitions_and_propositions": "theory_control_panel",
85
+ "forward_derivation_and_counterexamples": "derivation_and_falsification",
86
+ "expected_outcomes": "preregistered_decision_protocol",
87
+ "risk_limitations_and_review": "release_and_review_protocol",
88
+ "appendix_variables_and_definitions": "energy_condition_boundary_defense",
89
+ }
90
+
91
+
92
+ def _mapping(value: object) -> dict[str, Any]:
93
+ return dict(value) if isinstance(value, Mapping) else {}
94
+
95
+
96
+ def _text(value: object) -> str:
97
+ return str(value or "").strip()
98
+
99
+
100
+ def resolve_author_template(author_input: Mapping[str, Any]) -> str:
101
+ """Resolve one author template from upstream routing, then declared disciplines."""
102
+
103
+ provenance = _mapping(author_input.get("provenance"))
104
+ configured = _text(provenance.get("template_id"))
105
+ if configured in AUTHOR_TEMPLATE_FAMILIES:
106
+ return configured
107
+ composition = _mapping(author_input.get("template_composition"))
108
+ configured = _text(composition.get("template_id"))
109
+ if configured in AUTHOR_TEMPLATE_FAMILIES:
110
+ return configured
111
+ disciplines = provenance.get("discipline_ids") if isinstance(provenance.get("discipline_ids"), list) else []
112
+ if "31" in {_text(item) for item in disciplines}:
113
+ selected = _mapping(author_input.get("selected_direction"))
114
+ context = " ".join(
115
+ _text(value).casefold()
116
+ for value in (
117
+ selected.get("title"),
118
+ selected.get("central_hypothesis"),
119
+ selected.get("mechanism_or_relation"),
120
+ )
121
+ )
122
+ return "mathematics_theory" if any(term in context for term in ("theorem", "proof", "derivation", "counterexample", "formal")) else "engineering_energy"
123
+ for discipline_id in disciplines:
124
+ resolved = _DISCIPLINE_TEMPLATE.get(_text(discipline_id))
125
+ if resolved:
126
+ return resolved
127
+ return "computational_digital"
128
+
129
+
130
+ def route_author_sections(author_input: Mapping[str, Any]) -> dict[str, Any]:
131
+ """Return a fixed route that the LLM may fill but never expand or reorder."""
132
+
133
+ template_family = resolve_author_template(author_input)
134
+ template_routes = _TEMPLATE_ROUTES[template_family]
135
+ routes: list[dict[str, Any]] = []
136
+ for section_id, title, target, claim_kinds in _COMMON_ROUTES:
137
+ if section_id == "references":
138
+ for extra_id, extra_title, extra_claim_kinds in template_routes:
139
+ template_route = {
140
+ "section_id": extra_id,
141
+ "title": extra_title,
142
+ "target": "sections",
143
+ "applicability": "required",
144
+ "allowed_claim_kinds": list(extra_claim_kinds),
145
+ }
146
+ theory_role = _MATHEMATICS_THEORY_ROUTE_ROLES.get(extra_id) if template_family == "mathematics_theory" else ""
147
+ if theory_role:
148
+ template_route["theory_role"] = theory_role
149
+ routes.append(template_route)
150
+ route = {
151
+ "section_id": section_id,
152
+ "title": title,
153
+ "target": target,
154
+ "applicability": "required" if section_id != "appendix_idea_evolution" else "optional",
155
+ "allowed_claim_kinds": list(claim_kinds),
156
+ }
157
+ theory_role = (
158
+ _MATHEMATICS_THEORY_ROUTE_ROLES.get(section_id)
159
+ if template_family == "mathematics_theory"
160
+ else ""
161
+ )
162
+ if theory_role:
163
+ route["theory_role"] = theory_role
164
+ routes.append(route)
165
+ if template_family == "mathematics_theory":
166
+ for route in routes:
167
+ if route.get("section_id") == "appendix_variables_and_definitions":
168
+ route["title"] = "Energy-Condition Taxonomy, Symbols, and Boundary Defense"
169
+ appendix_order = {
170
+ "appendix_variables_and_definitions": 0,
171
+ "appendix_idea_evolution": 1,
172
+ "appendix_evidence_and_review": 2,
173
+ }
174
+ routes = sorted(
175
+ enumerate(routes),
176
+ key=lambda item: (
177
+ 1 if item[1].get("target") == "appendices" else 0,
178
+ appendix_order.get(_text(item[1].get("section_id")), 99),
179
+ item[0],
180
+ ),
181
+ )
182
+ routes = [route for _index, route in routes]
183
+ return {
184
+ "schema_version": "research_plan_author_section_routing_v1",
185
+ "template_family": template_family,
186
+ "routes": routes,
187
+ "theory_sampling_power_status": "not_applicable" if template_family == "mathematics_theory" else "route_specific",
188
+ }
189
+
190
+
191
+ def required_route_ids(routing: Mapping[str, Any]) -> list[str]:
192
+ return [
193
+ _text(route.get("section_id"))
194
+ for route in routing.get("routes") or []
195
+ if isinstance(route, Mapping) and _text(route.get("applicability")) == "required"
196
+ ]
197
+
198
+
199
+ def route_copy(routing: Mapping[str, Any]) -> dict[str, Any]:
200
+ return deepcopy(dict(routing))
201
+
202
+
203
+ __all__ = [
204
+ "AUTHOR_TEMPLATE_FAMILIES",
205
+ "required_route_ids",
206
+ "resolve_author_template",
207
+ "route_author_sections",
208
+ "route_copy",
209
+ ]
@@ -0,0 +1,254 @@
1
+ """Cross-section semantic validation for a proposal-only Research Plan document."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from collections.abc import Mapping
7
+ from typing import Any
8
+
9
+ from .contracts import (
10
+ AUTHORING_LANGUAGE,
11
+ validate_research_plan_document,
12
+ )
13
+ from .latex_safety import (
14
+ contains_observed_result_language,
15
+ )
16
+ from .section_router import required_route_ids
17
+ from .theory_spine import theory_spine_internal_ids_in_text
18
+
19
+ def _mapping(value: object) -> dict[str, Any]:
20
+ return dict(value) if isinstance(value, Mapping) else {}
21
+
22
+
23
+ def _text(value: object) -> str:
24
+ return str(value or "").strip()
25
+
26
+
27
+ def _canonical(value: object) -> str:
28
+ return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False)
29
+
30
+
31
+ def validate_composed_research_plan(
32
+ document: object,
33
+ *,
34
+ preparation: Mapping[str, Any],
35
+ routing: Mapping[str, Any],
36
+ source_registry: Mapping[str, Any],
37
+ ) -> list[str]:
38
+ """Reject forged identifiers and scientific-status upgrades only.
39
+
40
+ Writing quality, route recommendations, evidence-card wording, and
41
+ cross-section repetition are deliberately handled as non-blocking quality
42
+ concerns. This final pass protects the proposal boundary rather than
43
+ restricting legitimate synthesis of upstream artifacts.
44
+ """
45
+
46
+ errors = validate_research_plan_document(document)
47
+ if not isinstance(document, Mapping):
48
+ return errors
49
+ payload = dict(document)
50
+ if payload.get("document_status") != "PROPOSAL_NO_OBSERVED_RESULTS":
51
+ errors.append("composed document must remain PROPOSAL_NO_OBSERVED_RESULTS")
52
+ if payload.get("language") != AUTHORING_LANGUAGE:
53
+ errors.append("composed document language must be English")
54
+ metadata = _mapping(payload.get("document_metadata"))
55
+ for text_field in (metadata.get("title"), payload.get("abstract", {}).get("text") if isinstance(payload.get("abstract"), Mapping) else ""):
56
+ if contains_observed_result_language(text_field):
57
+ errors.append("composed document presents an observed result in visible prose")
58
+ all_sections = [
59
+ section
60
+ for section in [*(payload.get("sections") or []), *(payload.get("appendices") or [])]
61
+ if isinstance(section, Mapping)
62
+ ]
63
+ document_block_kinds = {
64
+ f"{_text(section.get('section_id'))}:{_text(block.get('block_id'))}": _text(block.get("kind"))
65
+ for section in all_sections
66
+ if _text(section.get("section_id"))
67
+ for block in section.get("blocks") or []
68
+ if isinstance(block, Mapping) and _text(block.get("block_id"))
69
+ }
70
+ section_ids = {_text(section.get("section_id")) for section in all_sections}
71
+ theory_unit_ids: set[str] = set()
72
+ theory_spine = _mapping(preparation.get("theory_spine"))
73
+ for collection_name, identifier_field in (
74
+ ("lemma_units", "lemma_id"),
75
+ ("proof_obligations", "proof_obligation_id"),
76
+ ("falsifiers", "falsifier_id"),
77
+ ("decision_branches", "branch_id"),
78
+ ):
79
+ theory_unit_ids.update(
80
+ _text(record.get(identifier_field))
81
+ for record in theory_spine.get(collection_name) or []
82
+ if isinstance(record, Mapping) and _text(record.get(identifier_field))
83
+ )
84
+ blueprint_sections = {
85
+ _text(section.get("section_id")): _mapping(section)
86
+ for section in _mapping(payload.get("authoring_blueprint")).get("sections") or []
87
+ if isinstance(section, Mapping) and _text(section.get("section_id"))
88
+ }
89
+ required_ids = set(required_route_ids(routing))
90
+ if "abstract" in required_ids:
91
+ abstract = _mapping(payload.get("abstract"))
92
+ if not _text(abstract.get("text")):
93
+ errors.append("composed document omits required abstract content")
94
+ elif not {_text(claim_id) for claim_id in abstract.get("claim_ids") or [] if _text(claim_id)}:
95
+ errors.append("composed document abstract must reference at least one claim ID")
96
+ required_ids.remove("abstract")
97
+ missing = required_ids - section_ids
98
+ if missing:
99
+ errors.append(f"composed document omits required routed sections: {sorted(missing)}")
100
+ for visible_label, text_value in (
101
+ ("document title", metadata.get("title")),
102
+ ("abstract", _mapping(payload.get("abstract")).get("text")),
103
+ *(("keyword", keyword) for keyword in payload.get("keywords") or []),
104
+ ):
105
+ private_ids = theory_spine_internal_ids_in_text(text_value)
106
+ if private_ids:
107
+ errors.append(f"{visible_label} exposes private theory identifiers: {private_ids}")
108
+ claims = [claim for claim in payload.get("claim_provenance") or [] if isinstance(claim, Mapping)]
109
+ claim_ids = [_text(claim.get("claim_id")) for claim in claims]
110
+ if len(claim_ids) != len(set(claim_ids)):
111
+ errors.append("document contains duplicate claim_id values")
112
+ claim_id_set = set(claim_ids)
113
+ for section in all_sections:
114
+ section_id = _text(section.get("section_id"))
115
+ allowed_theory_units = {
116
+ _text(unit_id)
117
+ for field_name in ("lemma_ids", "proof_obligation_ids", "falsifier_ids", "decision_branch_ids")
118
+ for unit_id in _mapping(blueprint_sections.get(section_id)).get("theory_unit_references", {}).get(field_name, [])
119
+ if _text(unit_id)
120
+ }
121
+ private_ids = theory_spine_internal_ids_in_text(section.get("title"))
122
+ if private_ids:
123
+ errors.append(f"section {section_id} title exposes private theory identifiers: {private_ids}")
124
+ blocks = [block for block in section.get("blocks") or [] if isinstance(block, Mapping)]
125
+ block_kinds = {
126
+ _text(block.get("block_id")): _text(block.get("kind")) for block in blocks
127
+ }
128
+ for block in blocks:
129
+ block_id = _text(block.get("block_id")) or "unnamed"
130
+ block_text = _text(block.get("text"))
131
+ for field_name in ("heading", "text"):
132
+ private_ids = theory_spine_internal_ids_in_text(block.get(field_name))
133
+ if private_ids:
134
+ errors.append(
135
+ f"section block {block_id} exposes private theory identifiers in {field_name}: {private_ids}"
136
+ )
137
+ if not (section_id == "references" and block_id == "bibliography") and contains_observed_result_language(block_text):
138
+ errors.append(f"section block {block_id} presents an observed result")
139
+ block_claim_ids = {_text(claim_id) for claim_id in block.get("claim_ids") or [] if _text(claim_id)}
140
+ if block_text and not block_claim_ids:
141
+ errors.append(f"section block {block_id} must reference at least one claim ID")
142
+ unknown_claims = block_claim_ids - claim_id_set
143
+ if unknown_claims:
144
+ errors.append(f"section block {block.get('block_id')} references unknown claims")
145
+ reference_ids = {
146
+ _text(reference_id)
147
+ for reference_id in block.get("reference_block_ids") or []
148
+ if _text(reference_id)
149
+ }
150
+ local_references = {reference_id for reference_id in reference_ids if ":" not in reference_id}
151
+ scoped_references = reference_ids - local_references
152
+ if (local_references - set(block_kinds)) or (scoped_references - set(document_block_kinds)):
153
+ errors.append(f"section block {block_id} references an unknown equation block")
154
+ if any(
155
+ (reference_id in block_kinds and block_kinds.get(reference_id) != "equation")
156
+ or (
157
+ reference_id in document_block_kinds
158
+ and document_block_kinds.get(reference_id) != "equation"
159
+ )
160
+ for reference_id in reference_ids
161
+ ):
162
+ errors.append(f"section block {block_id} cross-references a non-equation block")
163
+ unknown_theory_units = {
164
+ _text(unit_id)
165
+ for unit_id in block.get("theory_unit_ids") or []
166
+ if _text(unit_id)
167
+ } - theory_unit_ids
168
+ if unknown_theory_units:
169
+ errors.append(f"section block {block_id} references an unknown theory unit")
170
+ nonlocal_theory_units = {
171
+ _text(unit_id)
172
+ for unit_id in block.get("theory_unit_ids") or []
173
+ if _text(unit_id)
174
+ } & theory_unit_ids - allowed_theory_units
175
+ if nonlocal_theory_units:
176
+ errors.append(f"section block {block_id} references a theory unit outside its section slice")
177
+ allowed_sources = set(source_registry.get("allowed_source_ids") or [])
178
+ allowed_anchors = set(source_registry.get("allowed_survey_anchor_ids") or [])
179
+ cards = _mapping(source_registry.get("evidence_cards_by_id"))
180
+ allowed_card_ids = set(cards)
181
+ citation_keys = {
182
+ _text(record.get("citation_key"))
183
+ for record in payload.get("citation_registry") or []
184
+ if isinstance(record, Mapping)
185
+ }
186
+ formal_ids: set[str] = set()
187
+ frozen = _mapping(_mapping(preparation.get("source_bundle")).get("author_context"))
188
+ plan = _mapping(frozen.get("formal_reasoning"))
189
+ for collection, field in (("definitions", "definition_id"), ("assumptions", "assumption_id"), ("propositions", "proposition_id"), ("proof_obligations", "obligation_id")):
190
+ formal_ids.update(_text(item.get(field)) for item in plan.get(collection) or [] if isinstance(item, Mapping))
191
+ formal_ids.update(_text(item.get("step_id")) for item in _mapping(plan.get("forward_derivation")).get("steps") or [] if isinstance(item, Mapping))
192
+ branch_ids = {
193
+ _text(branch.get("branch_id"))
194
+ for branch in frozen.get("outcome_branches") or []
195
+ if isinstance(branch, Mapping)
196
+ }
197
+ for claim in claims:
198
+ claim_id = _text(claim.get("claim_id"))
199
+ claim_kind = _text(claim.get("claim_kind"))
200
+ qualification = _text(claim.get("qualification"))
201
+ statement = _text(claim.get("statement"))
202
+ if claim_kind == "observed_result" or contains_observed_result_language(statement):
203
+ errors.append(f"claim {claim_id} presents an observed result")
204
+ if set(claim.get("source_ids") or []) - allowed_sources:
205
+ errors.append(f"claim {claim_id} has an unregistered source")
206
+ if set(claim.get("survey_anchor_ids") or []) - allowed_anchors:
207
+ errors.append(f"claim {claim_id} has an unregistered survey anchor")
208
+ if set(claim.get("evidence_card_ids") or []) - allowed_card_ids:
209
+ errors.append(f"claim {claim_id} has an unregistered evidence card")
210
+ if set(claim.get("formal_reference_ids") or []) - formal_ids:
211
+ errors.append(f"claim {claim_id} has an unregistered formal reference")
212
+ if set(claim.get("citation_keys") or []) - citation_keys:
213
+ errors.append(f"claim {claim_id} has an invented citation key")
214
+ if claim_kind == "expected_outcome":
215
+ if qualification != "expected_not_observed" or not set(claim.get("outcome_branch_ids") or []):
216
+ errors.append(f"expected outcome claim {claim_id} is not a conditional branch")
217
+ if set(claim.get("outcome_branch_ids") or []) - branch_ids:
218
+ errors.append(f"expected outcome claim {claim_id} references an unknown outcome branch")
219
+ final_unknowns = payload.get("open_items") if isinstance(payload.get("open_items"), list) else []
220
+ final_reviews = payload.get("review_items") if isinstance(payload.get("review_items"), list) else []
221
+ expected_unknown_ids = {str(item.get("source_item_id") or "") for item in source_registry.get("unknown_items") or [] if isinstance(item, Mapping)}
222
+ expected_review_ids = {str(item.get("source_item_id") or "") for item in source_registry.get("review_items") or [] if isinstance(item, Mapping)}
223
+ final_unknown_id_list = [str(item.get("source_item_id") or "") for item in final_unknowns if isinstance(item, Mapping)]
224
+ final_review_id_list = [str(item.get("source_item_id") or "") for item in final_reviews if isinstance(item, Mapping)]
225
+ final_unknown_ids = set(final_unknown_id_list)
226
+ final_review_ids = set(final_review_id_list)
227
+ if final_unknown_ids != expected_unknown_ids:
228
+ errors.append("composed document dropped or invented an upstream unknown item")
229
+ if final_review_ids != expected_review_ids:
230
+ errors.append("composed document dropped or invented an upstream human-review item")
231
+ if len(final_unknown_id_list) != len(final_unknown_ids) or len(final_review_id_list) != len(final_review_ids):
232
+ errors.append("composed document repeats an upstream unknown or human-review item")
233
+ for item in final_unknowns:
234
+ if isinstance(item, Mapping) and item.get("status") != "needs_human_input":
235
+ errors.append("composed document open_items must use status=needs_human_input")
236
+ for item in final_reviews:
237
+ if isinstance(item, Mapping) and item.get("status") != "review_required":
238
+ errors.append("composed document review_items must use status=review_required")
239
+ if routing.get("template_family") == "mathematics_theory":
240
+ if _mapping(payload.get("source_manifest")).get("theory_sampling_power_status") != "not_applicable":
241
+ errors.append("mathematics/theory sampling and power must be recorded as not_applicable")
242
+ methods_text = " ".join(
243
+ _text(block.get("text"))
244
+ for section in all_sections
245
+ if _text(section.get("section_id")) == "study_design_and_methods"
246
+ for block in section.get("blocks") or []
247
+ if isinstance(block, Mapping)
248
+ ).casefold()
249
+ if ("sample size" in methods_text or "statistical power" in methods_text) and "not applicable" not in methods_text:
250
+ errors.append("mathematics/theory sampling and power must remain not_applicable")
251
+ return sorted(set(errors))
252
+
253
+
254
+ __all__ = ["validate_composed_research_plan"]
@@ -0,0 +1,46 @@
1
+ """Build the bounded, traceable source bundle consumed by later Author stages."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from copy import deepcopy
6
+ from typing import Any, Mapping
7
+
8
+ from .contracts import AUTHORING_LANGUAGE, AUTHOR_SOURCE_BUNDLE_SCHEMA, AUTHOR_SOURCE_BUNDLE_SCHEMA_VERSION
9
+
10
+
11
+ def _mapping(value: object) -> dict[str, Any]:
12
+ return dict(value) if isinstance(value, Mapping) else {}
13
+
14
+
15
+ def _text(value: object) -> str:
16
+ return str(value or "").strip()
17
+
18
+
19
+ def build_author_source_bundle(
20
+ author_input: Mapping[str, Any],
21
+ *,
22
+ author_input_path: str,
23
+ author_input_identity: Mapping[str, Any],
24
+ survey_sources: Mapping[str, Any],
25
+ survey_binding: Mapping[str, Any],
26
+ idea_evolution: Mapping[str, Any],
27
+ ) -> dict[str, Any]:
28
+ """Create a source-addressable bundle without parsing human-readable Markdown."""
29
+
30
+ provenance = _mapping(author_input.get("provenance"))
31
+ bundle = {
32
+ "schema_version": AUTHOR_SOURCE_BUNDLE_SCHEMA_VERSION,
33
+ "language": AUTHORING_LANGUAGE,
34
+ "source_design_id": _text(author_input.get("source_design_id")),
35
+ "selected_direction_id": _text(provenance.get("selected_direction_id")),
36
+ "author_input_path": _text(author_input_path),
37
+ "author_input_identity": deepcopy(dict(author_input_identity)),
38
+ "author_context": deepcopy(dict(author_input)),
39
+ "survey_sources": deepcopy(dict(survey_sources)),
40
+ "survey_binding": deepcopy(dict(survey_binding)),
41
+ "idea_evolution": deepcopy(dict(idea_evolution)),
42
+ }
43
+ return bundle
44
+
45
+
46
+ __all__ = ["AUTHOR_SOURCE_BUNDLE_SCHEMA", "build_author_source_bundle"]