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,25 @@
1
+ # debug
2
+
3
+ Diagnose and fix bugs systematically.
4
+
5
+ ## When to use
6
+
7
+ Use when the user reports a bug, error, or unexpected behavior.
8
+
9
+ ## Workflow
10
+
11
+ 1. Reproduce: understand the exact steps that trigger the issue
12
+ 2. Read the error: stack traces, log messages, error codes
13
+ 3. Locate: use Grep/Read to find the relevant code path
14
+ 4. Hypothesize: form a theory about the root cause
15
+ 5. Verify: add logging or read surrounding code to confirm
16
+ 6. Fix: make the minimal change that addresses the root cause
17
+ 7. Test: verify the fix works and doesn't break other things
18
+
19
+ ## Rules
20
+
21
+ - Read the error message carefully before searching code
22
+ - Don't guess — verify your hypothesis before changing code
23
+ - Fix the root cause, not the symptom
24
+ - Don't retry the same approach if it failed — investigate why
25
+ - If stuck after 3 attempts, explain what you've tried and ask for help
@@ -0,0 +1,35 @@
1
+ # diagnose
2
+
3
+ Diagnose why an agent run failed, regressed, or produced unexpected output — using structured evidence instead of intuition.
4
+
5
+ ## When to use
6
+
7
+ Use when the user asks:
8
+ - "Why did this run fail?"
9
+ - "What changed between this run and the last one?"
10
+ - "The output looks wrong — what happened?"
11
+ - "Why is this run worse than before?"
12
+
13
+ ## Workflow
14
+
15
+ 1. **Locate the run artifacts** — check `artifacts/runs/<run_id>/` or the latest run directory for:
16
+ - `manifest.json` — run metadata, task type, input hash, timestamps
17
+ - `execution_trace.jsonl` — the full tool-call chain, one event per line
18
+ - `verification_report.json` — what was verified and whether it passed
19
+ - `failure_signature.json` — which stage failed and why (if present)
20
+ 2. **Read the failure signature first** — if it exists, it already localizes the failure to a specific stage (routing, execution, verification, or governance)
21
+ 3. **Trace the execution chain** — walk `execution_trace.jsonl` forward to find where output diverged from expectation
22
+ 4. **Compare with a passing run** — if a previous run succeeded, diff the two manifests and traces to identify what changed
23
+ 5. **Identify the failure layer**:
24
+ - **Routing**: wrong task type or profile selected
25
+ - **Execution**: tool call error, permission block, or unexpected result
26
+ - **Verification**: output produced but did not match expected artifact
27
+ - **Governance**: run was halted by a safety or boundary check
28
+ 6. **Report with evidence** — cite specific file paths, line numbers in the trace, or field values from the manifest; never summarize without pointing to the source
29
+
30
+ ## Rules
31
+
32
+ - Evidence before intuition: always read the trace before forming a hypothesis
33
+ - Localize before explaining: identify which stage failed before describing why
34
+ - Compare, don't guess: if a previous run succeeded, diff it — don't speculate about what changed
35
+ - If no artifacts exist, say so clearly and ask the user to re-run with archive mode enabled
@@ -0,0 +1,39 @@
1
+ # plan
2
+
3
+ Design an implementation plan before coding.
4
+
5
+ ## When to use
6
+
7
+ Use when the user asks to plan, design, or architect a feature before implementing it.
8
+
9
+ ## Workflow
10
+
11
+ 1. Understand the requirement:
12
+ - What problem does this solve?
13
+ - What are the constraints?
14
+ - What's the expected outcome?
15
+ 2. Explore the codebase to find:
16
+ - Existing functions/utilities that can be reused
17
+ - Patterns used elsewhere in the project
18
+ - Files that will need modification
19
+ 3. Design the approach:
20
+ - Break into discrete steps
21
+ - Identify dependencies between steps
22
+ - Consider edge cases and error handling
23
+ 4. Present the plan:
24
+ - Start with a Context section (why this change)
25
+ - List concrete steps with file paths
26
+ - Include a verification section (how to test)
27
+
28
+ For this repository, follow the root `AGENTS.md` lightweight strategy: plan by related
29
+ functional batches, match detail and verification to risk, and do not create
30
+ micro-task review or full-test gates unless the change is a milestone or high risk.
31
+
32
+ ## Rules
33
+
34
+ - Read before suggesting — never propose changes to code you haven't read
35
+ - Prefer editing existing files over creating new ones
36
+ - Reuse existing patterns and utilities
37
+ - Include file paths and line numbers when referencing code
38
+ - Don't over-plan: match complexity to the task
39
+ - Treat verification as a risk-based minimum, not a blocking template step.
@@ -0,0 +1,33 @@
1
+ # review
2
+
3
+ Review code for bugs, security issues, and quality.
4
+
5
+ ## When to use
6
+
7
+ Use when the user asks to review code, a PR, or a diff.
8
+
9
+ ## Workflow
10
+
11
+ 1. Read the changed files or diff thoroughly
12
+ 2. Check for:
13
+ - **Bugs**: logic errors, off-by-one, null/undefined access, race conditions
14
+ - **Security**: injection, XSS, hardcoded secrets, path traversal
15
+ - **Performance**: N+1 queries, unnecessary allocations, missing indexes
16
+ - **Tests**: are new code paths covered? Are edge cases tested?
17
+ - **Style**: naming consistency, dead code, unnecessary complexity
18
+ 3. Provide concrete, actionable feedback with file:line references
19
+ 4. Prioritize findings by severity (critical > major > minor > nit)
20
+
21
+ For this repository, follow the root `AGENTS.md` lightweight strategy: perform review
22
+ as an implementation self-check for ordinary local changes. Start an independent
23
+ review only for high-risk architecture/API/security/persistence changes, cross-module
24
+ changes with unclear local impact, repeated unresolved fixes, a milestone, or final
25
+ delivery. Batch related changes into one review instead of reviewing every subtask.
26
+
27
+ ## Rules
28
+
29
+ - Be specific: "line 42 may throw if `user` is null" not "check for null"
30
+ - Suggest fixes, don't just point out problems
31
+ - Acknowledge good patterns too
32
+ - Don't nitpick formatting if there's a linter
33
+ - Do not make review a subtask-level blocking gate when no material risk is present.
@@ -0,0 +1,26 @@
1
+ # simplify
2
+
3
+ Refactor code to be simpler and more maintainable.
4
+
5
+ ## When to use
6
+
7
+ Use when the user asks to simplify, clean up, or refactor code.
8
+
9
+ ## Workflow
10
+
11
+ 1. Read the target code completely
12
+ 2. Identify complexity sources:
13
+ - Unnecessary abstractions or indirection
14
+ - Duplicated logic that should be consolidated
15
+ - Over-engineered patterns (factories, builders, strategies for simple cases)
16
+ - Dead code paths or unused variables
17
+ 3. Propose changes that reduce line count while preserving behavior
18
+ 4. Verify the refactored code passes existing tests
19
+
20
+ ## Rules
21
+
22
+ - Don't add features or change behavior — simplification only
23
+ - Prefer deleting code over refactoring it
24
+ - Three similar lines are better than a premature abstraction
25
+ - Remove backwards-compatibility shims for removed features
26
+ - Don't add comments to explain simple code
@@ -0,0 +1,175 @@
1
+ ---
2
+ name: skill-creator
3
+ description: >
4
+ Create, improve, and verify OpenHarness skills. Use this whenever the user
5
+ asks to create a new skill, convert a workflow into a skill, update an
6
+ existing SKILL.md, add skills for oh/ohmo, design skill trigger behavior,
7
+ or test whether a skill loads and works correctly.
8
+ ---
9
+
10
+ # skill-creator
11
+
12
+ Create or improve OpenHarness skills in the directory-based `SKILL.md` format.
13
+
14
+ ## When to use
15
+
16
+ Use this skill when the user wants to:
17
+
18
+ - create a new skill from a workflow, repeated task, domain guide, or tool process
19
+ - convert existing notes, prompts, or instructions into a reusable skill
20
+ - modify or harden an existing skill
21
+ - make a skill available to `oh`, `ohmo`, or a plugin
22
+ - debug why the `skill` tool cannot find or load a skill
23
+ - test trigger wording, skill metadata, or skill behavior
24
+
25
+ ## OpenHarness skill locations
26
+
27
+ Choose the target deliberately:
28
+
29
+ - Built-in OpenHarness skills live in `src/openharness/skills/bundled/content/*.md`.
30
+ - User skills for `oh` live in `~/.openharness/skills/<skill-dir>/SKILL.md`.
31
+ - Private `ohmo` skills live in `~/.ohmo/skills/<skill-dir>/SKILL.md`.
32
+ - Plugin skills live in `<plugin-root>/skills/<skill-dir>/SKILL.md`.
33
+
34
+ OpenHarness user and plugin skills use a directory layout. Do not create flat
35
+ `*.md` user skills under `skills/`; they will not be loaded by the normal loader.
36
+
37
+ ## Skill anatomy
38
+
39
+ Use this structure for user, ohmo, and plugin skills:
40
+
41
+ ```text
42
+ my-skill/
43
+ ├── SKILL.md
44
+ ├── scripts/ # optional deterministic helpers
45
+ ├── references/ # optional long docs loaded only when relevant
46
+ └── assets/ # optional templates or static files
47
+ ```
48
+
49
+ Use this structure inside `SKILL.md`:
50
+
51
+ ```markdown
52
+ ---
53
+ name: my-skill
54
+ description: >
55
+ What the skill does and exactly when to use it.
56
+ ---
57
+
58
+ # my-skill
59
+
60
+ Short purpose statement.
61
+
62
+ ## When to use
63
+
64
+ Trigger contexts in plain language.
65
+
66
+ ## Workflow
67
+
68
+ Concrete steps the agent should follow.
69
+
70
+ ## Rules
71
+
72
+ Important boundaries, verification, and failure handling.
73
+ ```
74
+
75
+ ## Workflow
76
+
77
+ 1. Capture intent before writing.
78
+ Ask or infer what the skill should help with, when it should trigger, what
79
+ output it should produce, and what success looks like. If the conversation
80
+ already contains the workflow, extract the sequence from history before
81
+ asking more questions.
82
+
83
+ 2. Inspect existing examples.
84
+ Read nearby skills and loader behavior before choosing a layout. For
85
+ OpenHarness, confirm whether the target is bundled, user, ohmo-private, or
86
+ plugin-provided.
87
+
88
+ 3. Write the metadata first.
89
+ The `description` is the primary trigger hint shown in the available skills
90
+ list. Make it specific and slightly assertive: include both what the skill
91
+ does and the phrases or situations that should trigger it. Avoid vague
92
+ descriptions like "Helpful notes for X".
93
+
94
+ 4. Keep the body procedural.
95
+ Use concise imperative steps. Explain why non-obvious constraints matter.
96
+ Prefer general principles over overfitted examples. If a skill is getting
97
+ long, move details into `references/` and point to the relevant file.
98
+
99
+ 5. Add deterministic resources only when they pay for themselves.
100
+ If the skill repeatedly needs the same script, template, schema, or checklist,
101
+ place it under `scripts/`, `assets/`, or `references/` rather than making the
102
+ model regenerate it every time.
103
+
104
+ 6. Verify loading.
105
+ Run a local loader check for the chosen target. For bundled skills, use:
106
+
107
+ ```bash
108
+ PYTHONPATH=src python - <<'PY'
109
+ from openharness.skills import load_skill_registry
110
+ for skill in load_skill_registry().list_skills():
111
+ print(skill.name, skill.source, skill.path)
112
+ PY
113
+ ```
114
+
115
+ For ohmo-private skills, include the extra skill directory:
116
+
117
+ ```bash
118
+ PYTHONPATH=src python - <<'PY'
119
+ from openharness.skills import load_skill_registry
120
+ from ohmo.workspace import get_skills_dir
121
+ for skill in load_skill_registry(extra_skill_dirs=[get_skills_dir()]).list_skills():
122
+ print(skill.name, skill.source, skill.path)
123
+ PY
124
+ ```
125
+
126
+ 7. Test behavior.
127
+ Create two or three realistic prompts that should use the skill. If the skill
128
+ changes code or files, add regression tests around loading or command
129
+ behavior. Run targeted tests first, then broader tests if the loader or
130
+ runtime path changed.
131
+
132
+ 8. Iterate from evidence.
133
+ If a skill under-triggers, improve the frontmatter description. If it
134
+ triggers but produces poor work, improve the body workflow. If agents repeat
135
+ deterministic work, add a helper script or reference file.
136
+
137
+ ## Writing rules
138
+
139
+ - Preserve the skill name when updating an existing skill unless the user
140
+ explicitly asks to rename it.
141
+ - Do not overwrite user-created skills without reading the existing `SKILL.md`.
142
+ - Keep `SKILL.md` under roughly 500 lines; use `references/` for long material.
143
+ - Keep trigger guidance in frontmatter `description`, not buried only in the
144
+ body.
145
+ - Make skills safe and unsurprising. Do not create skills that hide behavior,
146
+ bypass permissions, exfiltrate data, or encourage unauthorized access.
147
+ - Prefer directory names that are lowercase kebab-case, even if the displayed
148
+ skill `name` is more human-readable.
149
+ - Mention exact install or verification paths in the final response.
150
+
151
+ ## Test prompts
152
+
153
+ After drafting a skill, propose a small eval set:
154
+
155
+ ```json
156
+ {
157
+ "skill_name": "my-skill",
158
+ "evals": [
159
+ {
160
+ "id": "happy-path",
161
+ "prompt": "A realistic user request that should trigger the skill.",
162
+ "expected_output": "What good behavior looks like."
163
+ },
164
+ {
165
+ "id": "near-miss",
166
+ "prompt": "A similar request that should not trigger this skill.",
167
+ "expected_output": "The agent should choose a different path."
168
+ }
169
+ ]
170
+ }
171
+ ```
172
+
173
+ For objective skills, add assertions or tests. For subjective skills, collect
174
+ human feedback and revise the workflow from concrete complaints rather than
175
+ adding rigid rules.
@@ -0,0 +1,38 @@
1
+ # test
2
+
3
+ Write and run tests for code.
4
+
5
+ ## When to use
6
+
7
+ Use when the user asks to write tests, verify behavior, or improve test coverage.
8
+
9
+ ## Workflow
10
+
11
+ 1. Understand what needs testing:
12
+ - New feature? Write unit tests for the happy path and edge cases
13
+ - Bug fix? Write a regression test that would have caught the bug
14
+ - Refactor? Ensure existing tests still pass
15
+ 2. Follow the project's testing patterns:
16
+ - Check existing tests for framework (pytest, jest, go test, etc.)
17
+ - Match naming conventions and file organization
18
+ - Use the same fixtures and helpers
19
+ 3. Write tests that are:
20
+ - Independent: each test can run alone
21
+ - Deterministic: same result every time
22
+ - Fast: mock external services, use in-memory databases
23
+ 4. Run the tests and verify they pass
24
+
25
+ For this repository, follow the root `AGENTS.md` lightweight strategy: run the
26
+ smallest affected test set during development. Reserve full test suites, complete
27
+ builds, full lint, and E2E for milestones or final delivery, and skip a command that
28
+ already passed on the same unchanged code unless it covers a newly introduced risk.
29
+
30
+ ## Rules
31
+
32
+ - Test behavior, not implementation details
33
+ - One assertion per test when possible
34
+ - Use descriptive test names that explain the scenario
35
+ - Don't test framework or library code
36
+ - Mock at system boundaries (external APIs, filesystem, network)
37
+ - Do not require a full-suite run after every small fix; record why broader checks
38
+ are unnecessary when local validation is sufficient.
@@ -0,0 +1,229 @@
1
+ """Skill loading from bundled, user, compatibility, and project directories."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ from pathlib import Path
7
+ from typing import Iterable
8
+
9
+ from openharness.config.paths import get_config_dir
10
+ from openharness.config.settings import load_settings
11
+ from openharness.skills._frontmatter import (
12
+ optional_frontmatter_str,
13
+ parse_bool_frontmatter,
14
+ parse_skill_frontmatter,
15
+ parse_skill_metadata,
16
+ )
17
+ from openharness.skills.bundled import get_bundled_skills
18
+ from openharness.skills.registry import SkillRegistry
19
+ from openharness.skills.types import SkillDefinition
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+ _USER_COMPAT_SKILL_DIRS = (
24
+ (".claude", "skills"),
25
+ (".agents", "skills"),
26
+ )
27
+ _DEFAULT_PROJECT_SKILL_DIRS = (".openharness/skills", ".agents/skills", ".claude/skills")
28
+
29
+
30
+ def get_user_skills_dir() -> Path:
31
+ """Return the OpenHarness user skills directory."""
32
+ path = get_config_dir() / "skills"
33
+ path.mkdir(parents=True, exist_ok=True)
34
+ return path
35
+
36
+
37
+ def get_user_skill_dirs() -> list[Path]:
38
+ """Return user-level skill directories loaded by default."""
39
+ return [get_user_skills_dir(), *(Path.home().joinpath(*parts) for parts in _USER_COMPAT_SKILL_DIRS)]
40
+
41
+
42
+ def load_skill_registry(
43
+ cwd: str | Path | None = None,
44
+ *,
45
+ extra_skill_dirs: Iterable[str | Path] | None = None,
46
+ extra_plugin_roots: Iterable[str | Path] | None = None,
47
+ settings=None,
48
+ ) -> SkillRegistry:
49
+ """Load bundled, user-defined, project, and plugin skills."""
50
+ registry = SkillRegistry()
51
+ for skill in get_bundled_skills():
52
+ registry.register(skill)
53
+ for skill in load_user_skills():
54
+ registry.register(skill)
55
+ for skill in load_skills_from_dirs(extra_skill_dirs, source="user"):
56
+ registry.register(skill)
57
+
58
+ resolved_settings = settings or load_settings()
59
+ if cwd is not None and getattr(resolved_settings, "allow_project_skills", True):
60
+ project_dirs = discover_project_skill_dirs(
61
+ cwd,
62
+ getattr(resolved_settings, "project_skill_dirs", list(_DEFAULT_PROJECT_SKILL_DIRS)),
63
+ )
64
+ for skill in load_skills_from_dirs(project_dirs, source="project", create_missing=False):
65
+ registry.register(skill)
66
+
67
+ if cwd is not None:
68
+ from openharness.plugins.loader import load_plugins
69
+
70
+ for plugin in load_plugins(resolved_settings, cwd, extra_roots=extra_plugin_roots):
71
+ if not plugin.enabled:
72
+ continue
73
+ for skill in plugin.skills:
74
+ registry.register(skill)
75
+ return registry
76
+
77
+
78
+ def load_user_skills() -> list[SkillDefinition]:
79
+ """Load markdown skills from user-level OpenHarness and compatibility directories."""
80
+ return load_skills_from_dirs(get_user_skill_dirs(), source="user")
81
+
82
+
83
+ def discover_project_skill_dirs(
84
+ cwd: str | Path,
85
+ project_skill_dirs: Iterable[str] | None = None,
86
+ ) -> list[Path]:
87
+ """Return existing project skill directories from cwd up to the git root.
88
+
89
+ Directories are ordered from least-specific to most-specific so later registry
90
+ entries can override broader project or user skills deterministically.
91
+ """
92
+ start = Path(cwd).expanduser().resolve()
93
+ if not start.exists():
94
+ start = start.parent
95
+ if start.is_file():
96
+ start = start.parent
97
+
98
+ relative_dirs = _valid_project_skill_dirs(project_skill_dirs or _DEFAULT_PROJECT_SKILL_DIRS)
99
+ git_root = _find_git_root(start)
100
+ home = Path.home().resolve()
101
+ current = start
102
+ levels: list[Path] = []
103
+ while True:
104
+ levels.append(current)
105
+ if git_root is not None and current == git_root:
106
+ break
107
+ if git_root is None and current == home:
108
+ break
109
+ parent = current.parent
110
+ if parent == current:
111
+ break
112
+ current = parent
113
+
114
+ roots: list[Path] = []
115
+ seen: set[Path] = set()
116
+ for base in reversed(levels):
117
+ for rel in relative_dirs:
118
+ candidate = (base / rel).resolve()
119
+ if candidate in seen or not candidate.is_dir():
120
+ continue
121
+ seen.add(candidate)
122
+ roots.append(candidate)
123
+ return roots
124
+
125
+
126
+ def _valid_project_skill_dirs(project_skill_dirs: Iterable[str]) -> list[Path]:
127
+ """Return safe relative project skill paths."""
128
+ paths: list[Path] = []
129
+ for raw in project_skill_dirs:
130
+ value = str(raw).strip()
131
+ if not value:
132
+ continue
133
+ rel = Path(value)
134
+ if rel.is_absolute() or ".." in rel.parts:
135
+ logger.warning("Ignoring unsafe project skill dir: %s", raw)
136
+ continue
137
+ paths.append(rel)
138
+ return paths
139
+
140
+
141
+ def _find_git_root(start: Path) -> Path | None:
142
+ """Find the nearest git root containing start, if any."""
143
+ current = start
144
+ while True:
145
+ if (current / ".git").exists():
146
+ return current
147
+ parent = current.parent
148
+ if parent == current:
149
+ return None
150
+ current = parent
151
+
152
+
153
+ def load_skills_from_dirs(
154
+ directories: Iterable[str | Path] | None,
155
+ *,
156
+ source: str = "user",
157
+ create_missing: bool = True,
158
+ ) -> list[SkillDefinition]:
159
+ """Load markdown skills from one or more directories.
160
+
161
+ Supported layout:
162
+ - ``<root>/<skill-dir>/SKILL.md``
163
+ """
164
+ skills: list[SkillDefinition] = []
165
+ if not directories:
166
+ return skills
167
+ seen: set[Path] = set()
168
+ for directory in directories:
169
+ root = Path(directory).expanduser().resolve()
170
+ if create_missing:
171
+ root.mkdir(parents=True, exist_ok=True)
172
+ elif not root.is_dir():
173
+ continue
174
+ candidates: list[Path] = []
175
+ for child in sorted(root.iterdir()):
176
+ if child.is_dir():
177
+ skill_path = child / "SKILL.md"
178
+ if skill_path.exists():
179
+ candidates.append(skill_path)
180
+ for path in candidates:
181
+ if path in seen:
182
+ continue
183
+ seen.add(path)
184
+ content = path.read_text(encoding="utf-8")
185
+ default_name = path.parent.name
186
+ metadata = _parse_skill_metadata(default_name, content)
187
+ name = metadata["name"]
188
+ description = metadata["description"]
189
+ display_name = name if name != default_name else None
190
+ skills.append(
191
+ SkillDefinition(
192
+ name=name,
193
+ description=description,
194
+ content=content,
195
+ source=source,
196
+ path=str(path),
197
+ base_dir=str(path.parent),
198
+ command_name=default_name,
199
+ display_name=display_name,
200
+ user_invocable=metadata["user_invocable"],
201
+ disable_model_invocation=metadata["disable_model_invocation"],
202
+ model=metadata["model"],
203
+ argument_hint=metadata["argument_hint"],
204
+ )
205
+ )
206
+ return skills
207
+
208
+
209
+ def _parse_skill_markdown(default_name: str, content: str) -> tuple[str, str]:
210
+ """Parse name and description from a skill markdown file with YAML frontmatter support."""
211
+ return parse_skill_frontmatter(default_name, content, fallback_template="Skill: {name}")
212
+
213
+
214
+ def _parse_skill_metadata(default_name: str, content: str) -> dict:
215
+ parsed = parse_skill_metadata(default_name, content, fallback_template="Skill: {name}")
216
+ frontmatter = parsed.get("frontmatter")
217
+ if not isinstance(frontmatter, dict):
218
+ frontmatter = {}
219
+ return {
220
+ "name": str(parsed["name"]),
221
+ "description": str(parsed["description"]),
222
+ "user_invocable": parse_bool_frontmatter(frontmatter.get("user-invocable"), default=True),
223
+ "disable_model_invocation": parse_bool_frontmatter(
224
+ frontmatter.get("disable-model-invocation"),
225
+ default=False,
226
+ ),
227
+ "model": optional_frontmatter_str(frontmatter.get("model")),
228
+ "argument_hint": optional_frontmatter_str(frontmatter.get("argument-hint")),
229
+ }
@@ -0,0 +1,29 @@
1
+ """Skill registry."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from openharness.skills.types import SkillDefinition
6
+
7
+
8
+ class SkillRegistry:
9
+ """Store loaded skills by name."""
10
+
11
+ def __init__(self) -> None:
12
+ self._skills: dict[str, SkillDefinition] = {}
13
+
14
+ def register(self, skill: SkillDefinition) -> None:
15
+ """Register one skill."""
16
+ for key in (skill.name, skill.command_name, skill.display_name, *skill.aliases):
17
+ if key:
18
+ self._skills[key] = skill
19
+
20
+ def get(self, name: str) -> SkillDefinition | None:
21
+ """Return a skill by name."""
22
+ return self._skills.get(name)
23
+
24
+ def list_skills(self) -> list[SkillDefinition]:
25
+ """Return all skills sorted by name."""
26
+ unique: dict[tuple[str, str | None], SkillDefinition] = {}
27
+ for skill in self._skills.values():
28
+ unique[(skill.source, skill.path or skill.name)] = skill
29
+ return sorted(unique.values(), key=lambda skill: skill.command_name or skill.name)
@@ -0,0 +1,24 @@
1
+ """Skill data models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+
7
+
8
+ @dataclass(frozen=True)
9
+ class SkillDefinition:
10
+ """A loaded skill."""
11
+
12
+ name: str
13
+ description: str
14
+ content: str
15
+ source: str
16
+ path: str | None = None
17
+ base_dir: str | None = None
18
+ command_name: str | None = None
19
+ display_name: str | None = None
20
+ aliases: tuple[str, ...] = ()
21
+ user_invocable: bool = True
22
+ disable_model_invocation: bool = False
23
+ model: str | None = None
24
+ argument_hint: str | None = None
@@ -0,0 +1,6 @@
1
+ """State exports."""
2
+
3
+ from openharness.state.app_state import AppState
4
+ from openharness.state.store import AppStateStore
5
+
6
+ __all__ = ["AppState", "AppStateStore"]