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.
- qwen_sci-0.2.2.dist-info/METADATA +492 -0
- qwen_sci-0.2.2.dist-info/RECORD +549 -0
- qwen_sci-0.2.2.dist-info/WHEEL +4 -0
- qwen_sci-0.2.2.dist-info/entry_points.txt +6 -0
- qwen_sci-0.2.2.dist-info/licenses/LICENSE +21 -0
- src/1.txt +1 -0
- src/__init__.py +1 -0
- src/__main__.py +5 -0
- src/agents/__init__.py +1 -0
- src/agents/experiment_design_agent/__init__.py +268 -0
- src/agents/experiment_design_agent/artifacts.py +747 -0
- src/agents/experiment_design_agent/cache.py +319 -0
- src/agents/experiment_design_agent/completeness.py +130 -0
- src/agents/experiment_design_agent/contracts.py +771 -0
- src/agents/experiment_design_agent/counterexample_analyzer.py +187 -0
- src/agents/experiment_design_agent/design_evidence_paper_screener.py +470 -0
- src/agents/experiment_design_agent/discipline_catalog.py +178 -0
- src/agents/experiment_design_agent/evidence_cards.py +338 -0
- src/agents/experiment_design_agent/evidence_planner.py +452 -0
- src/agents/experiment_design_agent/formal_reasoning_planner.py +884 -0
- src/agents/experiment_design_agent/fulltext_acquisition.py +863 -0
- src/agents/experiment_design_agent/idea_adapter.py +100 -0
- src/agents/experiment_design_agent/idea_intake.py +87 -0
- src/agents/experiment_design_agent/llm_json.py +328 -0
- src/agents/experiment_design_agent/orchestrator.py +1220 -0
- src/agents/experiment_design_agent/reasoning_context.py +183 -0
- src/agents/experiment_design_agent/reasoning_validation.py +546 -0
- src/agents/experiment_design_agent/run.py +481 -0
- src/agents/experiment_design_agent/run_logging.py +292 -0
- src/agents/experiment_design_agent/scope_gate.py +198 -0
- src/agents/experiment_design_agent/study_type_composer.py +1360 -0
- src/agents/experiment_design_agent/survey_evidence.py +1381 -0
- src/agents/experiment_design_agent/template_router.py +195 -0
- src/agents/experiment_design_agent/variable_claim_extractor.py +93 -0
- src/agents/idea_agent/__init__.py +1 -0
- src/agents/idea_agent/agent/__init__.py +6 -0
- src/agents/idea_agent/agent/artifacts.py +308 -0
- src/agents/idea_agent/agent/base.py +122 -0
- src/agents/idea_agent/agent/ligagent.py +488 -0
- src/agents/idea_agent/agent/mcts.py +2060 -0
- src/agents/idea_agent/agent/prompts/__init__.py +48 -0
- src/agents/idea_agent/agent/prompts/advanced_analysis.py +235 -0
- src/agents/idea_agent/agent/prompts/algorithm_alignment.py +55 -0
- src/agents/idea_agent/agent/prompts/algorithm_structuring.py +48 -0
- src/agents/idea_agent/agent/prompts/component_extraction.py +62 -0
- src/agents/idea_agent/agent/prompts/component_novelty_evaluation.py +54 -0
- src/agents/idea_agent/agent/prompts/experiment_findings_extraction.py +39 -0
- src/agents/idea_agent/agent/prompts/idea_fusion.py +295 -0
- src/agents/idea_agent/agent/prompts/idea_introduction.py +30 -0
- src/agents/idea_agent/agent/prompts/idea_result_alignment.py +39 -0
- src/agents/idea_agent/agent/prompts/input_interpreter.py +52 -0
- src/agents/idea_agent/agent/prompts/keynote_ops.py +78 -0
- src/agents/idea_agent/agent/prompts/mcts_evaluation.py +235 -0
- src/agents/idea_agent/agent/prompts/mcts_generation.py +140 -0
- src/agents/idea_agent/agent/prompts/mechanism_commit_query.py +99 -0
- src/agents/idea_agent/agent/prompts/memory_selection.py +0 -0
- src/agents/idea_agent/agent/prompts/prompt_modes.py +16 -0
- src/agents/idea_agent/agent/prompts/rag_query.py +34 -0
- src/agents/idea_agent/agent/prompts/re_analysis_replan.py +48 -0
- src/agents/idea_agent/agent/prompts/reference_grounding.py +34 -0
- src/agents/idea_agent/agent/prompts/root_domain_classification.py +32 -0
- src/agents/idea_agent/agent/prompts/scientific_debate.py +88 -0
- src/agents/idea_agent/agent/prompts/scientific_materialization.py +45 -0
- src/agents/idea_agent/agent/prompts/skill_instantiation.py +193 -0
- src/agents/idea_agent/agent/prompts/theory_transfer_query.py +93 -0
- src/agents/idea_agent/agent/prompts/topic_background.py +15 -0
- src/agents/idea_agent/agent/skills/DEFAULT_SKILL_TEMPLATES.json +263 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/alternative-path-contrast/SKILL.md +40 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/alternative-path-contrast/references/contrast_patterns.md +22 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/feedback-closed-loop/SKILL.md +40 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/feedback-closed-loop/references/mechanism_cards.md +24 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/hierarchical-decomposition/SKILL.md +39 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/hierarchical-decomposition/references/hierarchy_patterns.md +22 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/mechanism-commit-innovation/SKILL.md +39 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/mechanism-commit-innovation/references/mechanism_commit_patterns.md +24 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/multi-scale-coordinator/SKILL.md +39 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/multi-scale-coordinator/references/coordination_patterns.md +22 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/speculative-execution-with-repair/SKILL.md +41 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/speculative-execution-with-repair/references/speculation_patterns.md +22 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/surgical-modularity/SKILL.md +39 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/surgical-modularity/references/modularity_patterns.md +22 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/theory-transfer-injection/SKILL.md +40 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/theory-transfer-injection/references/transfer_patterns.md +24 -0
- src/agents/idea_agent/example/idea_result.json +900 -0
- src/agents/idea_agent/run.py +276 -0
- src/agents/idea_agent/tests/test_advanced_analysis_contract.py +90 -0
- src/agents/idea_agent/tests/test_gap_hypothesis_bridge.py +166 -0
- src/agents/idea_agent/tests/test_idea_debate.py +480 -0
- src/agents/idea_agent/tests/test_idea_result_v5.py +99 -0
- src/agents/idea_agent/tests/test_idea_synthesis.py +92 -0
- src/agents/idea_agent/tests/test_mature_idea_sources.py +27 -0
- src/agents/idea_agent/tests/test_multimodal_idea_integration.py +386 -0
- src/agents/idea_agent/tests/test_profile_materialization_and_scoring.py +219 -0
- src/agents/idea_agent/tests/test_profile_native_skill_rendering.py +122 -0
- src/agents/idea_agent/tests/test_result_persistence.py +183 -0
- src/agents/idea_agent/tests/test_scientific_intervention_profiles.py +241 -0
- src/agents/idea_agent/tests/test_scientific_rubric_and_prompts.py +559 -0
- src/agents/idea_agent/tests/test_strict_json_object_responses.py +48 -0
- src/agents/idea_agent/utils/core/__init__.py +1 -0
- src/agents/idea_agent/utils/core/ablation_inputs.py +60 -0
- src/agents/idea_agent/utils/core/chat_errors.py +95 -0
- src/agents/idea_agent/utils/core/chat_router.py +130 -0
- src/agents/idea_agent/utils/core/chat_transport.py +188 -0
- src/agents/idea_agent/utils/core/config_loader.py +166 -0
- src/agents/idea_agent/utils/core/json_utils.py +28 -0
- src/agents/idea_agent/utils/core/logger.py +287 -0
- src/agents/idea_agent/utils/core/progress.py +58 -0
- src/agents/idea_agent/utils/core/response_parsing.py +57 -0
- src/agents/idea_agent/utils/core/run_inputs.py +198 -0
- src/agents/idea_agent/utils/mcts/__init__.py +1 -0
- src/agents/idea_agent/utils/mcts/component_novelty.py +342 -0
- src/agents/idea_agent/utils/mcts/defect_registry.py +302 -0
- src/agents/idea_agent/utils/mcts/idea_routes.py +61 -0
- src/agents/idea_agent/utils/mcts/idea_taste_presets.py +312 -0
- src/agents/idea_agent/utils/mcts/mcts_helpers.py +738 -0
- src/agents/idea_agent/utils/mcts/mcts_runtime.py +3000 -0
- src/agents/idea_agent/utils/mcts/scientific_intervention_ontology.py +1561 -0
- src/agents/idea_agent/utils/mcts/scientific_rubric.py +211 -0
- src/agents/idea_agent/utils/mcts/skill_parsing.py +92 -0
- src/agents/idea_agent/utils/papers/__init__.py +1 -0
- src/agents/idea_agent/utils/papers/paper_graph_vector_store.py +499 -0
- src/agents/idea_agent/utils/papers/paper_repository.py +372 -0
- src/agents/idea_agent/utils/prompting/__init__.py +1 -0
- src/agents/idea_agent/utils/prompting/prompt_views.py +637 -0
- src/agents/idea_agent/utils/workflow/__init__.py +1 -0
- src/agents/idea_agent/utils/workflow/advanced_analysis_contract.py +244 -0
- src/agents/idea_agent/utils/workflow/gap_hypothesis_bridge.py +461 -0
- src/agents/idea_agent/utils/workflow/idea_contract.py +426 -0
- src/agents/idea_agent/utils/workflow/idea_debate.py +1238 -0
- src/agents/idea_agent/utils/workflow/idea_diversity.py +163 -0
- src/agents/idea_agent/utils/workflow/idea_fusion.py +889 -0
- src/agents/idea_agent/utils/workflow/idea_helpers.py +478 -0
- src/agents/idea_agent/utils/workflow/idea_portfolio.py +422 -0
- src/agents/idea_agent/utils/workflow/idea_synthesis.py +482 -0
- src/agents/idea_agent/utils/workflow/ligagent_flow.py +581 -0
- src/agents/idea_agent/utils/workflow/ligagent_handlers.py +1836 -0
- src/agents/idea_agent/utils/workflow/ligagent_helpers.py +1331 -0
- src/agents/idea_agent/utils/workflow/ligagent_utils.py +322 -0
- src/agents/idea_agent/utils/workflow/mature_idea_sources.py +648 -0
- src/agents/idea_agent/utils/workflow/multimodal_data_anchoring.py +578 -0
- src/agents/idea_agent/utils/workflow/result_persistence.py +774 -0
- src/agents/idea_agent/utils/workflow/stage_contract.py +76 -0
- src/agents/idea_agent/utils/workflow/workflow_runtime.py +288 -0
- src/agents/research_plan_author/__init__.py +50 -0
- src/agents/research_plan_author/artifacts.py +270 -0
- src/agents/research_plan_author/authoring_blueprint.py +1246 -0
- src/agents/research_plan_author/bibtex_renderer.py +252 -0
- src/agents/research_plan_author/contract_repair.py +131 -0
- src/agents/research_plan_author/contracts.py +745 -0
- src/agents/research_plan_author/cross_section_editor.py +232 -0
- src/agents/research_plan_author/document_quality.py +987 -0
- src/agents/research_plan_author/idea_evolution.py +223 -0
- src/agents/research_plan_author/input_loader.py +76 -0
- src/agents/research_plan_author/latex_compiler.py +260 -0
- src/agents/research_plan_author/latex_safety.py +159 -0
- src/agents/research_plan_author/llm_json.py +74 -0
- src/agents/research_plan_author/markdown_renderer.py +275 -0
- src/agents/research_plan_author/pdf_validator.py +149 -0
- src/agents/research_plan_author/render.py +166 -0
- src/agents/research_plan_author/render_artifacts.py +187 -0
- src/agents/research_plan_author/run.py +765 -0
- src/agents/research_plan_author/run_logging.py +209 -0
- src/agents/research_plan_author/section_cache.py +184 -0
- src/agents/research_plan_author/section_composer.py +1764 -0
- src/agents/research_plan_author/section_router.py +209 -0
- src/agents/research_plan_author/semantic_validator.py +254 -0
- src/agents/research_plan_author/source_bundle.py +46 -0
- src/agents/research_plan_author/source_registry.py +208 -0
- src/agents/research_plan_author/survey_source_loader.py +137 -0
- src/agents/research_plan_author/template_adapter.py +173 -0
- src/agents/research_plan_author/template_profile.py +204 -0
- src/agents/research_plan_author/tex_renderer.py +496 -0
- src/agents/research_plan_author/theory_presentation.py +134 -0
- src/agents/research_plan_author/theory_spine.py +703 -0
- src/agents/survey_agent/Dockerfile +54 -0
- src/agents/survey_agent/README.md +350 -0
- src/agents/survey_agent/config/deep_survey.yaml +217 -0
- src/agents/survey_agent/config/deep_survey_batch.yaml +176 -0
- src/agents/survey_agent/config/deep_survey_fast.yaml +183 -0
- src/agents/survey_agent/config/evaluate_baseline.yaml +197 -0
- src/agents/survey_agent/config/outcomeRAG.yaml +159 -0
- src/agents/survey_agent/env_report.md +348 -0
- src/agents/survey_agent/modules/__init__.py +0 -0
- src/agents/survey_agent/modules/code_collector.py +2194 -0
- src/agents/survey_agent/modules/code_report_generator.py +1282 -0
- src/agents/survey_agent/modules/data_manager.py +1713 -0
- src/agents/survey_agent/modules/database.py +167 -0
- src/agents/survey_agent/modules/fulltext_download_cache.py +462 -0
- src/agents/survey_agent/modules/fulltext_http.py +134 -0
- src/agents/survey_agent/modules/fulltext_resolution.py +749 -0
- src/agents/survey_agent/modules/judge.py +434 -0
- src/agents/survey_agent/modules/outcome_RAG.py +236 -0
- src/agents/survey_agent/modules/paper_graph_retriever.py +1075 -0
- src/agents/survey_agent/modules/pe.py +1729 -0
- src/agents/survey_agent/modules/pseudo_creator.py +782 -0
- src/agents/survey_agent/modules/pseudo_reviser.py +537 -0
- src/agents/survey_agent/modules/refine_agent.py +1952 -0
- src/agents/survey_agent/modules/survey_generator.py +5691 -0
- src/agents/survey_agent/modules/survey_visualizer.py +1817 -0
- src/agents/survey_agent/modules/visual_prompts.py +327 -0
- src/agents/survey_agent/modules/work_analyzer.py +2750 -0
- src/agents/survey_agent/modules/work_collector.py +5649 -0
- src/agents/survey_agent/scripts/baseline_evaluation.py +411 -0
- src/agents/survey_agent/scripts/run_deep_survey.py +224 -0
- src/agents/survey_agent/scripts/run_deep_survey_adapter.py +407 -0
- src/agents/survey_agent/scripts/run_deep_survey_adapter_with_input.py +409 -0
- src/agents/survey_agent/scripts/run_deep_survey_batch.py +228 -0
- src/agents/survey_agent/scripts/run_deep_survey_batch_arg.py +243 -0
- src/agents/survey_agent/scripts/run_deep_survey_batch_settings.py +218 -0
- src/agents/survey_agent/scripts/run_keynotes_gen.py +128 -0
- src/agents/survey_agent/scripts/run_work_clusters.py +140 -0
- src/agents/survey_agent/utils/__init__.py +0 -0
- src/agents/survey_agent/utils/ablation_utils.py +317 -0
- src/agents/survey_agent/utils/api_call.py +2518 -0
- src/agents/survey_agent/utils/chat_utils.py +82 -0
- src/agents/survey_agent/utils/config_utils.py +70 -0
- src/agents/survey_agent/utils/convert_to_md.py +29 -0
- src/agents/survey_agent/utils/err_info.py +24 -0
- src/agents/survey_agent/utils/file_utils.py +176 -0
- src/agents/survey_agent/utils/gpu_utils.py +145 -0
- src/agents/survey_agent/utils/graph_visualizer.py +279 -0
- src/agents/survey_agent/utils/html_utils.py +181 -0
- src/agents/survey_agent/utils/latex_generator_intra_cluster.py +529 -0
- src/agents/survey_agent/utils/latex_generator_relation_table.py +193 -0
- src/agents/survey_agent/utils/mineru_section_packer.py +334 -0
- src/agents/survey_agent/utils/mineru_utils.py +396 -0
- src/agents/survey_agent/utils/paper.py +144 -0
- src/agents/survey_agent/utils/read_yaml.py +15 -0
- src/agents/survey_agent/utils/repo_utils.py +167 -0
- src/agents/survey_agent/utils/rich_logger.py +77 -0
- src/agents/survey_agent/utils/step2v2.py +874 -0
- src/agents/survey_agent/utils/step2v2_extractor.py +856 -0
- src/agents/survey_agent/utils/topic_survey_storage.py +309 -0
- src/agents/survey_agent/utils/utils.py +118 -0
- src/agents/survey_agent/utils/work.py +2 -0
- src/cli.py +1611 -0
- src/config/__init__.py +213 -0
- src/config/default.yaml +1122 -0
- src/harness/LICENSE +21 -0
- src/harness/VENDORED.md +14 -0
- src/harness/src/__init__.py +0 -0
- src/harness/src/openharness/__init__.py +0 -0
- src/harness/src/openharness/__main__.py +6 -0
- src/harness/src/openharness/api/__init__.py +21 -0
- src/harness/src/openharness/api/client.py +281 -0
- src/harness/src/openharness/api/codex_client.py +407 -0
- src/harness/src/openharness/api/copilot_auth.py +240 -0
- src/harness/src/openharness/api/copilot_client.py +134 -0
- src/harness/src/openharness/api/errors.py +19 -0
- src/harness/src/openharness/api/openai_client.py +577 -0
- src/harness/src/openharness/api/provider.py +186 -0
- src/harness/src/openharness/api/registry.py +437 -0
- src/harness/src/openharness/api/usage.py +17 -0
- src/harness/src/openharness/auth/__init__.py +29 -0
- src/harness/src/openharness/auth/external.py +610 -0
- src/harness/src/openharness/auth/flows.py +189 -0
- src/harness/src/openharness/auth/manager.py +482 -0
- src/harness/src/openharness/auth/storage.py +269 -0
- src/harness/src/openharness/autopilot/__init__.py +23 -0
- src/harness/src/openharness/autopilot/service.py +2239 -0
- src/harness/src/openharness/autopilot/types.py +91 -0
- src/harness/src/openharness/bridge/__init__.py +20 -0
- src/harness/src/openharness/bridge/manager.py +106 -0
- src/harness/src/openharness/bridge/session_runner.py +46 -0
- src/harness/src/openharness/bridge/types.py +37 -0
- src/harness/src/openharness/bridge/work_secret.py +41 -0
- src/harness/src/openharness/channels/UPSTREAM +6 -0
- src/harness/src/openharness/channels/__init__.py +22 -0
- src/harness/src/openharness/channels/adapter.py +131 -0
- src/harness/src/openharness/channels/bus/__init__.py +6 -0
- src/harness/src/openharness/channels/bus/events.py +38 -0
- src/harness/src/openharness/channels/bus/queue.py +44 -0
- src/harness/src/openharness/channels/impl/__init__.py +6 -0
- src/harness/src/openharness/channels/impl/base.py +141 -0
- src/harness/src/openharness/channels/impl/dingtalk.py +445 -0
- src/harness/src/openharness/channels/impl/discord.py +311 -0
- src/harness/src/openharness/channels/impl/email.py +410 -0
- src/harness/src/openharness/channels/impl/feishu.py +1342 -0
- src/harness/src/openharness/channels/impl/manager.py +257 -0
- src/harness/src/openharness/channels/impl/matrix.py +700 -0
- src/harness/src/openharness/channels/impl/mochat.py +897 -0
- src/harness/src/openharness/channels/impl/qq.py +141 -0
- src/harness/src/openharness/channels/impl/slack.py +284 -0
- src/harness/src/openharness/channels/impl/telegram.py +525 -0
- src/harness/src/openharness/channels/impl/whatsapp.py +159 -0
- src/harness/src/openharness/cli.py +2551 -0
- src/harness/src/openharness/commands/__init__.py +21 -0
- src/harness/src/openharness/commands/registry.py +2783 -0
- src/harness/src/openharness/config/__init__.py +34 -0
- src/harness/src/openharness/config/paths.py +160 -0
- src/harness/src/openharness/config/schema.py +119 -0
- src/harness/src/openharness/config/settings.py +1104 -0
- src/harness/src/openharness/coordinator/__init__.py +12 -0
- src/harness/src/openharness/coordinator/agent_definitions.py +975 -0
- src/harness/src/openharness/coordinator/coordinator_mode.py +520 -0
- src/harness/src/openharness/engine/__init__.py +80 -0
- src/harness/src/openharness/engine/cost_tracker.py +24 -0
- src/harness/src/openharness/engine/messages.py +222 -0
- src/harness/src/openharness/engine/query.py +1188 -0
- src/harness/src/openharness/engine/query_engine.py +313 -0
- src/harness/src/openharness/engine/stream_events.py +90 -0
- src/harness/src/openharness/hooks/__init__.py +50 -0
- src/harness/src/openharness/hooks/events.py +20 -0
- src/harness/src/openharness/hooks/executor.py +242 -0
- src/harness/src/openharness/hooks/hot_reload.py +31 -0
- src/harness/src/openharness/hooks/loader.py +68 -0
- src/harness/src/openharness/hooks/schemas.py +66 -0
- src/harness/src/openharness/hooks/types.py +38 -0
- src/harness/src/openharness/keybindings/__init__.py +14 -0
- src/harness/src/openharness/keybindings/default_bindings.py +11 -0
- src/harness/src/openharness/keybindings/loader.py +22 -0
- src/harness/src/openharness/keybindings/parser.py +18 -0
- src/harness/src/openharness/keybindings/resolver.py +13 -0
- src/harness/src/openharness/mcp/__init__.py +79 -0
- src/harness/src/openharness/mcp/client.py +298 -0
- src/harness/src/openharness/mcp/config.py +16 -0
- src/harness/src/openharness/mcp/types.py +76 -0
- src/harness/src/openharness/memory/__init__.py +25 -0
- src/harness/src/openharness/memory/agent.py +91 -0
- src/harness/src/openharness/memory/manager.py +183 -0
- src/harness/src/openharness/memory/memdir.py +52 -0
- src/harness/src/openharness/memory/migrate.py +137 -0
- src/harness/src/openharness/memory/paths.py +22 -0
- src/harness/src/openharness/memory/relevance.py +145 -0
- src/harness/src/openharness/memory/scan.py +116 -0
- src/harness/src/openharness/memory/schema.py +443 -0
- src/harness/src/openharness/memory/search.py +71 -0
- src/harness/src/openharness/memory/team.py +90 -0
- src/harness/src/openharness/memory/types.py +33 -0
- src/harness/src/openharness/memory/usage.py +153 -0
- src/harness/src/openharness/output_styles/__init__.py +5 -0
- src/harness/src/openharness/output_styles/loader.py +42 -0
- src/harness/src/openharness/permissions/__init__.py +26 -0
- src/harness/src/openharness/permissions/checker.py +200 -0
- src/harness/src/openharness/permissions/modes.py +13 -0
- src/harness/src/openharness/personalization/__init__.py +6 -0
- src/harness/src/openharness/personalization/extractor.py +138 -0
- src/harness/src/openharness/personalization/rules.py +64 -0
- src/harness/src/openharness/personalization/session_hook.py +65 -0
- src/harness/src/openharness/platforms.py +86 -0
- src/harness/src/openharness/plugins/__init__.py +53 -0
- src/harness/src/openharness/plugins/bundled/__init__.py +0 -0
- src/harness/src/openharness/plugins/installer.py +39 -0
- src/harness/src/openharness/plugins/loader.py +730 -0
- src/harness/src/openharness/plugins/schemas.py +24 -0
- src/harness/src/openharness/plugins/types.py +59 -0
- src/harness/src/openharness/prompts/__init__.py +14 -0
- src/harness/src/openharness/prompts/claudemd.py +48 -0
- src/harness/src/openharness/prompts/context.py +187 -0
- src/harness/src/openharness/prompts/environment.py +135 -0
- src/harness/src/openharness/prompts/system_prompt.py +109 -0
- src/harness/src/openharness/sandbox/Dockerfile +6 -0
- src/harness/src/openharness/sandbox/__init__.py +33 -0
- src/harness/src/openharness/sandbox/adapter.py +148 -0
- src/harness/src/openharness/sandbox/docker_backend.py +232 -0
- src/harness/src/openharness/sandbox/docker_image.py +103 -0
- src/harness/src/openharness/sandbox/path_validator.py +37 -0
- src/harness/src/openharness/sandbox/session.py +63 -0
- src/harness/src/openharness/services/__init__.py +30 -0
- src/harness/src/openharness/services/autodream/__init__.py +34 -0
- src/harness/src/openharness/services/autodream/backup.py +104 -0
- src/harness/src/openharness/services/autodream/lock.py +138 -0
- src/harness/src/openharness/services/autodream/prompt.py +128 -0
- src/harness/src/openharness/services/autodream/service.py +313 -0
- src/harness/src/openharness/services/compact/__init__.py +1725 -0
- src/harness/src/openharness/services/cron.py +137 -0
- src/harness/src/openharness/services/cron_scheduler.py +595 -0
- src/harness/src/openharness/services/lsp/__init__.py +216 -0
- src/harness/src/openharness/services/memory_extract/__init__.py +261 -0
- src/harness/src/openharness/services/oauth/__init__.py +0 -0
- src/harness/src/openharness/services/session_backend.py +97 -0
- src/harness/src/openharness/services/session_memory/__init__.py +139 -0
- src/harness/src/openharness/services/session_storage.py +230 -0
- src/harness/src/openharness/services/token_estimation.py +15 -0
- src/harness/src/openharness/services/tool_outputs.py +55 -0
- src/harness/src/openharness/skills/__init__.py +44 -0
- src/harness/src/openharness/skills/_frontmatter.py +97 -0
- src/harness/src/openharness/skills/bundled/__init__.py +75 -0
- src/harness/src/openharness/skills/bundled/content/commit.md +25 -0
- src/harness/src/openharness/skills/bundled/content/debug.md +25 -0
- src/harness/src/openharness/skills/bundled/content/diagnose.md +35 -0
- src/harness/src/openharness/skills/bundled/content/plan.md +39 -0
- src/harness/src/openharness/skills/bundled/content/review.md +33 -0
- src/harness/src/openharness/skills/bundled/content/simplify.md +26 -0
- src/harness/src/openharness/skills/bundled/content/skill-creator.md +175 -0
- src/harness/src/openharness/skills/bundled/content/test.md +38 -0
- src/harness/src/openharness/skills/loader.py +229 -0
- src/harness/src/openharness/skills/registry.py +29 -0
- src/harness/src/openharness/skills/types.py +24 -0
- src/harness/src/openharness/state/__init__.py +6 -0
- src/harness/src/openharness/state/app_state.py +30 -0
- src/harness/src/openharness/state/store.py +40 -0
- src/harness/src/openharness/swarm/__init__.py +70 -0
- src/harness/src/openharness/swarm/in_process.py +693 -0
- src/harness/src/openharness/swarm/lockfile.py +24 -0
- src/harness/src/openharness/swarm/mailbox.py +522 -0
- src/harness/src/openharness/swarm/permission_sync.py +1168 -0
- src/harness/src/openharness/swarm/registry.py +410 -0
- src/harness/src/openharness/swarm/spawn_utils.py +229 -0
- src/harness/src/openharness/swarm/subprocess_backend.py +171 -0
- src/harness/src/openharness/swarm/team_lifecycle.py +910 -0
- src/harness/src/openharness/swarm/types.py +398 -0
- src/harness/src/openharness/swarm/worktree.py +315 -0
- src/harness/src/openharness/tasks/__init__.py +18 -0
- src/harness/src/openharness/tasks/local_agent_task.py +28 -0
- src/harness/src/openharness/tasks/local_shell_task.py +17 -0
- src/harness/src/openharness/tasks/manager.py +475 -0
- src/harness/src/openharness/tasks/stop_task.py +11 -0
- src/harness/src/openharness/tasks/types.py +32 -0
- src/harness/src/openharness/themes/__init__.py +21 -0
- src/harness/src/openharness/themes/builtin.py +89 -0
- src/harness/src/openharness/themes/loader.py +55 -0
- src/harness/src/openharness/themes/schema.py +54 -0
- src/harness/src/openharness/tools/__init__.py +107 -0
- src/harness/src/openharness/tools/agent_tool.py +141 -0
- src/harness/src/openharness/tools/ask_user_question_tool.py +46 -0
- src/harness/src/openharness/tools/base.py +80 -0
- src/harness/src/openharness/tools/bash_tool.py +259 -0
- src/harness/src/openharness/tools/brief_tool.py +33 -0
- src/harness/src/openharness/tools/config_tool.py +54 -0
- src/harness/src/openharness/tools/cron_create_tool.py +105 -0
- src/harness/src/openharness/tools/cron_delete_tool.py +32 -0
- src/harness/src/openharness/tools/cron_list_tool.py +69 -0
- src/harness/src/openharness/tools/cron_toggle_tool.py +37 -0
- src/harness/src/openharness/tools/enter_plan_mode_tool.py +28 -0
- src/harness/src/openharness/tools/enter_worktree_tool.py +80 -0
- src/harness/src/openharness/tools/exit_plan_mode_tool.py +28 -0
- src/harness/src/openharness/tools/exit_worktree_tool.py +42 -0
- src/harness/src/openharness/tools/file_edit_tool.py +95 -0
- src/harness/src/openharness/tools/file_read_tool.py +72 -0
- src/harness/src/openharness/tools/file_write_tool.py +87 -0
- src/harness/src/openharness/tools/glob_tool.py +175 -0
- src/harness/src/openharness/tools/grep_tool.py +374 -0
- src/harness/src/openharness/tools/image_generation_tool.py +447 -0
- src/harness/src/openharness/tools/image_to_text_tool.py +237 -0
- src/harness/src/openharness/tools/list_mcp_resources_tool.py +36 -0
- src/harness/src/openharness/tools/lsp_tool.py +154 -0
- src/harness/src/openharness/tools/mcp_auth_tool.py +71 -0
- src/harness/src/openharness/tools/mcp_tool.py +72 -0
- src/harness/src/openharness/tools/notebook_edit_tool.py +97 -0
- src/harness/src/openharness/tools/read_mcp_resource_tool.py +38 -0
- src/harness/src/openharness/tools/remote_trigger_tool.py +74 -0
- src/harness/src/openharness/tools/send_message_tool.py +58 -0
- src/harness/src/openharness/tools/skill_tool.py +43 -0
- src/harness/src/openharness/tools/sleep_tool.py +32 -0
- src/harness/src/openharness/tools/task_create_tool.py +56 -0
- src/harness/src/openharness/tools/task_get_tool.py +33 -0
- src/harness/src/openharness/tools/task_list_tool.py +35 -0
- src/harness/src/openharness/tools/task_output_tool.py +35 -0
- src/harness/src/openharness/tools/task_stop_tool.py +30 -0
- src/harness/src/openharness/tools/task_update_tool.py +50 -0
- src/harness/src/openharness/tools/team_create_tool.py +31 -0
- src/harness/src/openharness/tools/team_delete_tool.py +30 -0
- src/harness/src/openharness/tools/todo_write_tool.py +46 -0
- src/harness/src/openharness/tools/tool_search_tool.py +38 -0
- src/harness/src/openharness/tools/web_fetch_tool.py +117 -0
- src/harness/src/openharness/tools/web_search_tool.py +119 -0
- src/harness/src/openharness/ui/__init__.py +5 -0
- src/harness/src/openharness/ui/app.py +320 -0
- src/harness/src/openharness/ui/backend_host.py +941 -0
- src/harness/src/openharness/ui/coordinator_drain.py +198 -0
- src/harness/src/openharness/ui/input.py +32 -0
- src/harness/src/openharness/ui/output.py +265 -0
- src/harness/src/openharness/ui/permission_dialog.py +14 -0
- src/harness/src/openharness/ui/protocol.py +247 -0
- src/harness/src/openharness/ui/react_launcher.py +179 -0
- src/harness/src/openharness/ui/runtime.py +799 -0
- src/harness/src/openharness/ui/textual_app.py +495 -0
- src/harness/src/openharness/utils/__init__.py +0 -0
- src/harness/src/openharness/utils/file_lock.py +86 -0
- src/harness/src/openharness/utils/fs.py +98 -0
- src/harness/src/openharness/utils/helpers.py +77 -0
- src/harness/src/openharness/utils/network_guard.py +340 -0
- src/harness/src/openharness/utils/shell.py +147 -0
- src/harness/src/openharness/vim/__init__.py +5 -0
- src/harness/src/openharness/vim/transitions.py +8 -0
- src/harness/src/openharness/voice/__init__.py +7 -0
- src/harness/src/openharness/voice/keyterms.py +10 -0
- src/harness/src/openharness/voice/stream_stt.py +8 -0
- src/harness/src/openharness/voice/voice_mode.py +44 -0
- src/llm/__init__.py +29 -0
- src/llm/image_generation.py +402 -0
- src/llm/provider_registry.py +419 -0
- src/llm/runtime_env.py +64 -0
- src/llm/structured_output.py +131 -0
- src/llm/vision.py +198 -0
- src/memory/__init__.py +2 -0
- src/memory/api/__init__.py +1 -0
- src/memory/api/base_memory_system_api.py +98 -0
- src/memory/api/base_symbolic_memory_system_api.py +190 -0
- src/memory/api/base_vector_memory_system_api.py +116 -0
- src/memory/api/faiss_memory_system_api.py +228 -0
- src/memory/api/slot_process_api.py +827 -0
- src/memory/api/symbolic_memory_system_api.py +572 -0
- src/memory/memory_system/__init__.py +48 -0
- src/memory/memory_system/component_taxonomy.py +430 -0
- src/memory/memory_system/llm.py +437 -0
- src/memory/memory_system/models.py +168 -0
- src/memory/memory_system/user_prompt.py +418 -0
- src/memory/memory_system/utils.py +282 -0
- src/memory/memory_system/vectorstore.py +311 -0
- src/memory/memory_system/working_slot.py +99 -0
- src/pipeline/__init__.py +129 -0
- src/pipeline/contracts.py +531 -0
- src/pipeline/discipline_taxonomy.py +916 -0
- src/pipeline/evidence_coverage_ledger.py +1150 -0
- src/pipeline/evidence_refinement.py +620 -0
- src/pipeline/experiment_to_symbolic.py +137 -0
- src/pipeline/multimodal_evidence/__init__.py +28 -0
- src/pipeline/multimodal_evidence/capabilities.py +107 -0
- src/pipeline/multimodal_evidence/claims.py +135 -0
- src/pipeline/multimodal_evidence/contract.py +291 -0
- src/pipeline/multimodal_evidence/data_sh_compiler.py +505 -0
- src/pipeline/multimodal_evidence/handoff_binding.py +135 -0
- src/pipeline/multimodal_evidence/manifest.py +254 -0
- src/pipeline/multimodal_evidence/native_analysis.py +479 -0
- src/pipeline/multimodal_evidence/perception.py +277 -0
- src/pipeline/multimodal_evidence/query_binding.py +65 -0
- src/pipeline/multimodal_evidence/rendering.py +120 -0
- src/pipeline/multimodal_evidence/safety.py +42 -0
- src/pipeline/multimodal_evidence/sampling.py +69 -0
- src/pipeline/multimodal_evidence/service.py +148 -0
- src/pipeline/multimodal_evidence/survey_integration.py +460 -0
- src/pipeline/paper_identity.py +52 -0
- src/pipeline/research_design_inventory.py +338 -0
- src/pipeline/research_domain_resolution.py +669 -0
- src/pipeline/research_identity.py +548 -0
- src/pipeline/research_question_contract.py +646 -0
- src/pipeline/retrieval_lanes.py +889 -0
- src/pipeline/run_loop.py +862 -0
- src/pipeline/science_events.py +30 -0
- src/pipeline/science_manifests.py +602 -0
- src/pipeline/science_run.py +918 -0
- src/pipeline/science_stages.py +709 -0
- src/pipeline/science_workflow.py +807 -0
- src/pipeline/sh_cluster_projection.py +306 -0
- src/pipeline/sh_graph_provenance.py +648 -0
- src/pipeline/subhypothesis_decomposition.py +392 -0
- src/pipeline/subhypothesis_evidence.py +856 -0
- src/pipeline/survey_evidence_plan.py +858 -0
- src/pipeline/survey_gap_adjudication.py +647 -0
- src/pipeline/survey_gap_candidates.py +840 -0
- src/pipeline/survey_gap_ledger.py +683 -0
- src/pipeline/survey_gap_triage.py +401 -0
- src/pipeline/survey_handoff_persistence.py +481 -0
- src/pipeline/survey_handoff_projection.py +457 -0
- src/pipeline/survey_idea_handoff.py +1112 -0
- src/pipeline/survey_idea_loader.py +289 -0
- 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
|