researchforge 0.2.0__tar.gz → 0.4.0__tar.gz

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 (429) hide show
  1. researchforge-0.4.0/.claude-plugin/marketplace.json +18 -0
  2. {researchforge-0.2.0 → researchforge-0.4.0}/.gitignore +4 -0
  3. researchforge-0.4.0/CHANGELOG.md +487 -0
  4. researchforge-0.4.0/PKG-INFO +377 -0
  5. researchforge-0.4.0/README.md +338 -0
  6. researchforge-0.4.0/assets/demo-thumbnail.png +0 -0
  7. researchforge-0.4.0/assets/graph.png +0 -0
  8. researchforge-0.4.0/assets/yolov5-graph.svg +56 -0
  9. researchforge-0.4.0/claude-plugin/README.md +29 -0
  10. researchforge-0.4.0/docs/architecture.md +223 -0
  11. researchforge-0.4.0/docs/demo.md +377 -0
  12. researchforge-0.4.0/docs/experiment-mode.md +290 -0
  13. researchforge-0.4.0/docs/research-mode.md +275 -0
  14. {researchforge-0.2.0 → researchforge-0.4.0}/examples/docker-python/README.md +1 -1
  15. researchforge-0.4.0/examples/yolov5-detection/.gitignore +10 -0
  16. researchforge-0.4.0/examples/yolov5-detection/Dockerfile +31 -0
  17. researchforge-0.4.0/examples/yolov5-detection/README.md +188 -0
  18. researchforge-0.4.0/examples/yolov5-detection/benchmarks/evaluate.py +104 -0
  19. researchforge-0.4.0/examples/yolov5-detection/requirements.txt +4 -0
  20. researchforge-0.4.0/examples/yolov5-detection/researchforge.example.yaml +66 -0
  21. researchforge-0.4.0/examples/yolov5-detection/src/config.py +23 -0
  22. {researchforge-0.2.0 → researchforge-0.4.0}/pyproject.toml +17 -0
  23. researchforge-0.4.0/scripts/check_doc_links.py +61 -0
  24. researchforge-0.4.0/scripts/export_readme_charts.py +105 -0
  25. researchforge-0.4.0/scripts/sync_skills.sh +162 -0
  26. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/__init__.py +1 -1
  27. researchforge-0.4.0/src/researchforge/ai/__init__.py +15 -0
  28. researchforge-0.4.0/src/researchforge/ai/dockerfile_gen.py +184 -0
  29. researchforge-0.4.0/src/researchforge/ai/eval_gen.py +148 -0
  30. researchforge-0.4.0/src/researchforge/ai/file_diff.py +86 -0
  31. researchforge-0.4.0/src/researchforge/ai/merge_gen.py +144 -0
  32. researchforge-0.4.0/src/researchforge/ai/observation_gen.py +107 -0
  33. researchforge-0.4.0/src/researchforge/ai/plan_gen.py +367 -0
  34. researchforge-0.4.0/src/researchforge/ai/policy_gen.py +271 -0
  35. researchforge-0.4.0/src/researchforge/ai/providers.py +401 -0
  36. researchforge-0.4.0/src/researchforge/ai/query_gen.py +102 -0
  37. researchforge-0.4.0/src/researchforge/ai/service.py +225 -0
  38. researchforge-0.4.0/src/researchforge/ai/synthesis.py +227 -0
  39. researchforge-0.4.0/src/researchforge/ai/usage.py +149 -0
  40. researchforge-0.4.0/src/researchforge/audit/__init__.py +1 -0
  41. researchforge-0.4.0/src/researchforge/audit/cli.py +89 -0
  42. researchforge-0.4.0/src/researchforge/audit/service.py +75 -0
  43. researchforge-0.4.0/src/researchforge/audit/trail.py +337 -0
  44. researchforge-0.4.0/src/researchforge/autorun/cli.py +486 -0
  45. researchforge-0.4.0/src/researchforge/autorun/engine.py +1563 -0
  46. researchforge-0.4.0/src/researchforge/autorun/frontier.py +133 -0
  47. researchforge-0.4.0/src/researchforge/autorun/kaggle_mode.py +162 -0
  48. researchforge-0.4.0/src/researchforge/autorun/merges.py +50 -0
  49. researchforge-0.4.0/src/researchforge/autorun/state.py +122 -0
  50. researchforge-0.4.0/src/researchforge/autorun/unattended.py +972 -0
  51. researchforge-0.4.0/src/researchforge/autorun/unattended_cli.py +240 -0
  52. researchforge-0.4.0/src/researchforge/claude/.claude-plugin/icon.png +0 -0
  53. researchforge-0.4.0/src/researchforge/claude/.claude-plugin/plugin.json +27 -0
  54. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/installer.py +31 -0
  55. researchforge-0.4.0/src/researchforge/claude/skills/overnight/SKILL.md +536 -0
  56. researchforge-0.4.0/src/researchforge/claude/skills/overnight/overnight.prompt +60 -0
  57. researchforge-0.4.0/src/researchforge/claude/skills/researchforge-autorun/SKILL.md +125 -0
  58. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/skills/researchforge-start/SKILL.md +4 -0
  59. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cli.py +129 -27
  60. researchforge-0.4.0/src/researchforge/compliance/__init__.py +1 -0
  61. researchforge-0.4.0/src/researchforge/compliance/cli.py +272 -0
  62. researchforge-0.4.0/src/researchforge/compliance/engine.py +117 -0
  63. researchforge-0.4.0/src/researchforge/compliance/gate_impls/human_approval.py +53 -0
  64. researchforge-0.4.0/src/researchforge/compliance/gate_impls/protected_assets.py +82 -0
  65. researchforge-0.4.0/src/researchforge/compliance/gate_impls/provider_policy.py +88 -0
  66. researchforge-0.4.0/src/researchforge/compliance/gates.py +179 -0
  67. researchforge-0.4.0/src/researchforge/compliance/policy.py +156 -0
  68. researchforge-0.4.0/src/researchforge/compliance/ship_eligibility.py +108 -0
  69. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/config/paths.py +12 -0
  70. researchforge-0.4.0/src/researchforge/config/settings.py +87 -0
  71. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/contract/cli.py +8 -1
  72. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/contract/render.py +13 -2
  73. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/contract/service.py +9 -2
  74. researchforge-0.4.0/src/researchforge/contract/wizard.py +171 -0
  75. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/installer.py +70 -0
  76. researchforge-0.4.0/src/researchforge/cursor/rules/researchforge-autorun.mdc +114 -0
  77. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/domain/baseline.py +25 -0
  78. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/domain/contract.py +32 -0
  79. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/domain/experiment.py +95 -5
  80. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/domain/hypothesis.py +28 -1
  81. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/baseline.py +127 -23
  82. researchforge-0.4.0/src/researchforge/execution/cli.py +449 -0
  83. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/evaluation.py +22 -1
  84. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/experiments.py +229 -40
  85. researchforge-0.4.0/src/researchforge/execution/guard.py +78 -0
  86. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/ranking.py +2 -12
  87. researchforge-0.4.0/src/researchforge/execution/regression.py +164 -0
  88. researchforge-0.4.0/src/researchforge/execution/setup_recovery.py +395 -0
  89. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/validation.py +33 -6
  90. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/worktrees.py +29 -0
  91. researchforge-0.4.0/src/researchforge/experiments/cli.py +1233 -0
  92. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/experiments/context_export.py +139 -9
  93. researchforge-0.4.0/src/researchforge/experiments/graph.py +50 -0
  94. researchforge-0.4.0/src/researchforge/experiments/handshake_usage.py +70 -0
  95. researchforge-0.4.0/src/researchforge/experiments/importers.py +535 -0
  96. researchforge-0.4.0/src/researchforge/experiments/measurements.py +46 -0
  97. researchforge-0.4.0/src/researchforge/experiments/repo_context.py +229 -0
  98. researchforge-0.4.0/src/researchforge/experiments/selection.py +149 -0
  99. researchforge-0.4.0/src/researchforge/generate/__init__.py +542 -0
  100. researchforge-0.4.0/src/researchforge/hypotheses/cli.py +352 -0
  101. researchforge-0.4.0/src/researchforge/intelligence/__init__.py +1 -0
  102. researchforge-0.4.0/src/researchforge/intelligence/scanner.py +402 -0
  103. researchforge-0.4.0/src/researchforge/kaggle/__init__.py +55 -0
  104. researchforge-0.4.0/src/researchforge/kaggle/api.py +412 -0
  105. researchforge-0.4.0/src/researchforge/kaggle/auto_run.py +1017 -0
  106. researchforge-0.4.0/src/researchforge/kaggle/auto_run_child.py +15 -0
  107. researchforge-0.4.0/src/researchforge/kaggle/benchmark_runner.py +725 -0
  108. researchforge-0.4.0/src/researchforge/kaggle/cli.py +3778 -0
  109. researchforge-0.4.0/src/researchforge/kaggle/cloud_gpu_config.py +597 -0
  110. researchforge-0.4.0/src/researchforge/kaggle/colab.py +616 -0
  111. researchforge-0.4.0/src/researchforge/kaggle/competition_reader.py +513 -0
  112. researchforge-0.4.0/src/researchforge/kaggle/compute_policy.py +340 -0
  113. researchforge-0.4.0/src/researchforge/kaggle/compute_router.py +781 -0
  114. researchforge-0.4.0/src/researchforge/kaggle/contract_generator.py +89 -0
  115. researchforge-0.4.0/src/researchforge/kaggle/control.py +676 -0
  116. researchforge-0.4.0/src/researchforge/kaggle/control_cli.py +1313 -0
  117. researchforge-0.4.0/src/researchforge/kaggle/credentials.py +225 -0
  118. researchforge-0.4.0/src/researchforge/kaggle/dashboard.py +1117 -0
  119. researchforge-0.4.0/src/researchforge/kaggle/dashboard_app.html +1675 -0
  120. researchforge-0.4.0/src/researchforge/kaggle/dashboard_state.py +2074 -0
  121. researchforge-0.4.0/src/researchforge/kaggle/experiment_loop.py +597 -0
  122. researchforge-0.4.0/src/researchforge/kaggle/facts_gatherer.py +537 -0
  123. researchforge-0.4.0/src/researchforge/kaggle/gpu_detector.py +196 -0
  124. researchforge-0.4.0/src/researchforge/kaggle/history_import.py +221 -0
  125. researchforge-0.4.0/src/researchforge/kaggle/human_questions.py +335 -0
  126. researchforge-0.4.0/src/researchforge/kaggle/hypothesis_pool.py +255 -0
  127. researchforge-0.4.0/src/researchforge/kaggle/idea_sources.py +358 -0
  128. researchforge-0.4.0/src/researchforge/kaggle/ideation.py +363 -0
  129. researchforge-0.4.0/src/researchforge/kaggle/kernel_board.py +188 -0
  130. researchforge-0.4.0/src/researchforge/kaggle/kernel_claims.py +89 -0
  131. researchforge-0.4.0/src/researchforge/kaggle/kernel_port.py +159 -0
  132. researchforge-0.4.0/src/researchforge/kaggle/kernel_watcher.py +698 -0
  133. researchforge-0.4.0/src/researchforge/kaggle/keys.py +417 -0
  134. researchforge-0.4.0/src/researchforge/kaggle/keys_cli.py +136 -0
  135. researchforge-0.4.0/src/researchforge/kaggle/late_rounds.py +106 -0
  136. researchforge-0.4.0/src/researchforge/kaggle/new_project.py +235 -0
  137. researchforge-0.4.0/src/researchforge/kaggle/notebook_baseline.py +264 -0
  138. researchforge-0.4.0/src/researchforge/kaggle/orchestrator.py +794 -0
  139. researchforge-0.4.0/src/researchforge/kaggle/patch_proposer.py +308 -0
  140. researchforge-0.4.0/src/researchforge/kaggle/round_target.py +82 -0
  141. researchforge-0.4.0/src/researchforge/kaggle/run_config.py +456 -0
  142. researchforge-0.4.0/src/researchforge/kaggle/scheduler.py +363 -0
  143. researchforge-0.4.0/src/researchforge/kaggle/sensors.py +211 -0
  144. researchforge-0.4.0/src/researchforge/kaggle/service_install.py +129 -0
  145. researchforge-0.4.0/src/researchforge/kaggle/ssh_config.py +99 -0
  146. researchforge-0.4.0/src/researchforge/kaggle/steering.py +157 -0
  147. researchforge-0.4.0/src/researchforge/kaggle/submission.py +371 -0
  148. researchforge-0.4.0/src/researchforge/kaggle/token_log.py +77 -0
  149. researchforge-0.4.0/src/researchforge/kaggle/workspace.py +405 -0
  150. researchforge-0.4.0/src/researchforge/notifications/__init__.py +6 -0
  151. researchforge-0.4.0/src/researchforge/notifications/cli.py +153 -0
  152. researchforge-0.4.0/src/researchforge/notifications/service.py +402 -0
  153. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/reporting/dashboard.py +194 -11
  154. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/reporting/dashboard_cli.py +42 -1
  155. researchforge-0.4.0/src/researchforge/reporting/economics.py +418 -0
  156. researchforge-0.4.0/src/researchforge/reporting/graph_layout.py +500 -0
  157. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/reporting/svg_charts.py +285 -84
  158. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/research/arxiv_client.py +27 -2
  159. researchforge-0.4.0/src/researchforge/research/cli.py +596 -0
  160. researchforge-0.4.0/src/researchforge/research/hypothesis_dedup.py +90 -0
  161. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/research/importers.py +102 -12
  162. researchforge-0.4.0/src/researchforge/research/research_log.py +233 -0
  163. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/research/search_service.py +5 -0
  164. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/server/data.py +4 -0
  165. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/server/hub.py +56 -0
  166. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/server/pages.py +174 -13
  167. researchforge-0.4.0/src/researchforge/shipping/__init__.py +0 -0
  168. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/shipping/branch.py +97 -14
  169. researchforge-0.4.0/src/researchforge/shipping/cli.py +467 -0
  170. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/shipping/gh.py +49 -27
  171. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/shipping/pr_body.py +3 -0
  172. researchforge-0.4.0/src/researchforge/shipping/push.py +146 -0
  173. researchforge-0.4.0/src/researchforge/storage/__init__.py +0 -0
  174. researchforge-0.4.0/src/researchforge/storage/ai_call_repository.py +93 -0
  175. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/storage/baseline_repository.py +33 -0
  176. researchforge-0.4.0/src/researchforge/storage/compliance_repository.py +174 -0
  177. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/storage/db.py +92 -2
  178. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/storage/experiment_repository.py +30 -0
  179. researchforge-0.4.0/src/researchforge/storage/hypothesis_repository.py +132 -0
  180. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/storage/synthesis_repository.py +12 -0
  181. researchforge-0.4.0/src/researchforge/utils/__init__.py +0 -0
  182. researchforge-0.4.0/src/researchforge/utils/progress.py +120 -0
  183. {researchforge-0.2.0 → researchforge-0.4.0}/tests/conftest.py +21 -2
  184. researchforge-0.4.0/tests/integration/test_autorun_example.py +305 -0
  185. researchforge-0.4.0/tests/integration/test_autorun_loop.py +660 -0
  186. researchforge-0.4.0/tests/integration/test_repo_auto_run.py +305 -0
  187. researchforge-0.4.0/tests/unit/test_ai_usage.py +162 -0
  188. researchforge-0.4.0/tests/unit/test_answer_actions.py +216 -0
  189. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_arxiv_client.py +41 -0
  190. researchforge-0.4.0/tests/unit/test_audit_trail.py +529 -0
  191. researchforge-0.4.0/tests/unit/test_auto_run.py +505 -0
  192. researchforge-0.4.0/tests/unit/test_autorun.py +255 -0
  193. researchforge-0.4.0/tests/unit/test_autorun_kaggle_mode.py +114 -0
  194. researchforge-0.4.0/tests/unit/test_baseline_repeats.py +221 -0
  195. researchforge-0.4.0/tests/unit/test_claude_plugin.py +55 -0
  196. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_claude_skills.py +82 -1
  197. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_cli.py +23 -0
  198. researchforge-0.4.0/tests/unit/test_cloud_gpu_providers.py +84 -0
  199. researchforge-0.4.0/tests/unit/test_colab.py +218 -0
  200. researchforge-0.4.0/tests/unit/test_colab_rounds.py +358 -0
  201. researchforge-0.4.0/tests/unit/test_compliance_phase1.py +378 -0
  202. researchforge-0.4.0/tests/unit/test_compute_choice.py +127 -0
  203. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_contract_wizard.py +35 -6
  204. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_dashboard.py +76 -16
  205. researchforge-0.4.0/tests/unit/test_dashboard_setup.py +435 -0
  206. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_doctor.py +2 -2
  207. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_domain_experiment.py +16 -6
  208. researchforge-0.4.0/tests/unit/test_economics.py +344 -0
  209. researchforge-0.4.0/tests/unit/test_experiment_graph.py +630 -0
  210. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_experiment_planning.py +109 -0
  211. researchforge-0.4.0/tests/unit/test_frontier.py +127 -0
  212. researchforge-0.4.0/tests/unit/test_graph.py +65 -0
  213. researchforge-0.4.0/tests/unit/test_graph_chart.py +278 -0
  214. researchforge-0.4.0/tests/unit/test_graph_layout.py +285 -0
  215. researchforge-0.4.0/tests/unit/test_handshake_usage.py +75 -0
  216. researchforge-0.4.0/tests/unit/test_hypothesis_dedup.py +124 -0
  217. researchforge-0.4.0/tests/unit/test_hypothesis_pool.py +224 -0
  218. researchforge-0.4.0/tests/unit/test_hypothesis_review.py +384 -0
  219. researchforge-0.4.0/tests/unit/test_init.py +149 -0
  220. researchforge-0.4.0/tests/unit/test_kaggle_control.py +261 -0
  221. researchforge-0.4.0/tests/unit/test_kaggle_dashboard.py +706 -0
  222. researchforge-0.4.0/tests/unit/test_kaggle_service_install.py +83 -0
  223. researchforge-0.4.0/tests/unit/test_merge_gen.py +120 -0
  224. researchforge-0.4.0/tests/unit/test_metric_direction.py +233 -0
  225. researchforge-0.4.0/tests/unit/test_observation_gen.py +178 -0
  226. researchforge-0.4.0/tests/unit/test_ollama_provider.py +135 -0
  227. researchforge-0.4.0/tests/unit/test_one_history.py +155 -0
  228. researchforge-0.4.0/tests/unit/test_papers_transfer.py +244 -0
  229. researchforge-0.4.0/tests/unit/test_plan_gen.py +331 -0
  230. researchforge-0.4.0/tests/unit/test_questions.py +232 -0
  231. researchforge-0.4.0/tests/unit/test_repo_auto_run_unit.py +200 -0
  232. researchforge-0.4.0/tests/unit/test_repo_context.py +180 -0
  233. researchforge-0.4.0/tests/unit/test_research_log.py +214 -0
  234. researchforge-0.4.0/tests/unit/test_resynthesis.py +369 -0
  235. researchforge-0.4.0/tests/unit/test_run_control.py +292 -0
  236. researchforge-0.4.0/tests/unit/test_selection.py +192 -0
  237. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_server.py +72 -1
  238. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_ship_pr.py +121 -24
  239. researchforge-0.4.0/tests/unit/test_ship_push.py +172 -0
  240. researchforge-0.4.0/tests/unit/test_submission.py +340 -0
  241. researchforge-0.4.0/tests/unit/test_unscored_and_notebooks.py +404 -0
  242. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_validation.py +122 -0
  243. researchforge-0.2.0/CHANGELOG.md +0 -27
  244. researchforge-0.2.0/PKG-INFO +0 -390
  245. researchforge-0.2.0/README.md +0 -354
  246. researchforge-0.2.0/assets/ResearchForgeDemoResearch.mp4 +0 -0
  247. researchforge-0.2.0/assets/ResearchForgeIntro.mp4 +0 -0
  248. researchforge-0.2.0/assets/ResearchForgeRepoDemoRepo.mp4 +0 -0
  249. researchforge-0.2.0/claude-plugin/README.md +0 -15
  250. researchforge-0.2.0/docs/RESEARCHFORGE_PHASED_BUILD_SPEC.md +0 -2204
  251. researchforge-0.2.0/docs/architecture.md +0 -122
  252. researchforge-0.2.0/docs/claude-mode.md +0 -117
  253. researchforge-0.2.0/docs/demo.md +0 -113
  254. researchforge-0.2.0/docs/experiment-mode.md +0 -98
  255. researchforge-0.2.0/docs/research-mode.md +0 -148
  256. researchforge-0.2.0/docs/security.md +0 -84
  257. researchforge-0.2.0/src/researchforge/config/settings.py +0 -37
  258. researchforge-0.2.0/src/researchforge/contract/wizard.py +0 -95
  259. researchforge-0.2.0/src/researchforge/execution/cli.py +0 -122
  260. researchforge-0.2.0/src/researchforge/experiments/cli.py +0 -595
  261. researchforge-0.2.0/src/researchforge/experiments/importers.py +0 -427
  262. researchforge-0.2.0/src/researchforge/hypotheses/cli.py +0 -108
  263. researchforge-0.2.0/src/researchforge/research/cli.py +0 -261
  264. researchforge-0.2.0/src/researchforge/shipping/cli.py +0 -264
  265. researchforge-0.2.0/src/researchforge/storage/hypothesis_repository.py +0 -45
  266. researchforge-0.2.0/tests/unit/test_experiment_tree.py +0 -223
  267. researchforge-0.2.0/tests/unit/test_init.py +0 -59
  268. {researchforge-0.2.0 → researchforge-0.4.0}/.github/ISSUE_TEMPLATE/beta_feedback.yml +0 -0
  269. {researchforge-0.2.0 → researchforge-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  270. {researchforge-0.2.0 → researchforge-0.4.0}/.github/ISSUE_TEMPLATE/setup_failure.yml +0 -0
  271. {researchforge-0.2.0 → researchforge-0.4.0}/.github/workflows/ci.yml +0 -0
  272. {researchforge-0.2.0 → researchforge-0.4.0}/.github/workflows/release.yml +0 -0
  273. {researchforge-0.2.0 → researchforge-0.4.0}/LICENSE +0 -0
  274. {researchforge-0.2.0 → researchforge-0.4.0}/assets/logo.jpeg +0 -0
  275. {researchforge-0.2.0 → researchforge-0.4.0}/assets/logo.png +0 -0
  276. {researchforge-0.2.0 → researchforge-0.4.0}/examples/docker-python/Dockerfile +0 -0
  277. {researchforge-0.2.0 → researchforge-0.4.0}/examples/docker-python/benchmarks/evaluate.py +0 -0
  278. {researchforge-0.2.0 → researchforge-0.4.0}/examples/docker-python/requirements.txt +0 -0
  279. {researchforge-0.2.0 → researchforge-0.4.0}/examples/docker-python/researchforge.example.yaml +0 -0
  280. {researchforge-0.2.0 → researchforge-0.4.0}/examples/docker-python/src/__init__.py +0 -0
  281. {researchforge-0.2.0 → researchforge-0.4.0}/examples/docker-python/src/classifier.py +0 -0
  282. {researchforge-0.2.0 → researchforge-0.4.0}/examples/docker-python/src/config.py +0 -0
  283. {researchforge-0.2.0 → researchforge-0.4.0}/examples/simple-python/README.md +0 -0
  284. {researchforge-0.2.0 → researchforge-0.4.0}/examples/simple-python/benchmarks/evaluate.py +0 -0
  285. {researchforge-0.2.0 → researchforge-0.4.0}/examples/simple-python/requirements.txt +0 -0
  286. {researchforge-0.2.0 → researchforge-0.4.0}/examples/simple-python/researchforge.example.yaml +0 -0
  287. {researchforge-0.2.0 → researchforge-0.4.0}/examples/simple-python/src/__init__.py +0 -0
  288. {researchforge-0.2.0 → researchforge-0.4.0}/examples/simple-python/src/classifier.py +0 -0
  289. {researchforge-0.2.0 → researchforge-0.4.0}/examples/simple-python/src/config.py +0 -0
  290. {researchforge-0.2.0/src/researchforge/config → researchforge-0.4.0/examples/yolov5-detection/src}/__init__.py +0 -0
  291. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/__main__.py +0 -0
  292. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/analytics/__init__.py +0 -0
  293. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/analytics/cli.py +0 -0
  294. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/analytics/service.py +0 -0
  295. {researchforge-0.2.0/src/researchforge/contract → researchforge-0.4.0/src/researchforge/autorun}/__init__.py +0 -0
  296. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/__init__.py +0 -0
  297. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/cli.py +0 -0
  298. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/skills/researchforge-baseline/SKILL.md +0 -0
  299. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/skills/researchforge-doctor/SKILL.md +0 -0
  300. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/skills/researchforge-hypotheses/SKILL.md +0 -0
  301. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/skills/researchforge-landscape/SKILL.md +0 -0
  302. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/skills/researchforge-paper/SKILL.md +0 -0
  303. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/skills/researchforge-papers/SKILL.md +0 -0
  304. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/skills/researchforge-plan/SKILL.md +0 -0
  305. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/skills/researchforge-results/SKILL.md +0 -0
  306. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/skills/researchforge-run/SKILL.md +0 -0
  307. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/skills/researchforge-ship/SKILL.md +0 -0
  308. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/claude/skills/researchforge-validate/SKILL.md +0 -0
  309. {researchforge-0.2.0/src/researchforge/execution → researchforge-0.4.0/src/researchforge/compliance/gate_impls}/__init__.py +0 -0
  310. {researchforge-0.2.0/src/researchforge/experiments → researchforge-0.4.0/src/researchforge/config}/__init__.py +0 -0
  311. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/config/paths_cli.py +0 -0
  312. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/config/registry.py +0 -0
  313. {researchforge-0.2.0/src/researchforge/hypotheses → researchforge-0.4.0/src/researchforge/contract}/__init__.py +0 -0
  314. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/contract/validate.py +0 -0
  315. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/__init__.py +0 -0
  316. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/cli.py +0 -0
  317. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/__init__.py +0 -0
  318. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/researchforge-baseline.mdc +0 -0
  319. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/researchforge-doctor.mdc +0 -0
  320. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/researchforge-hypotheses.mdc +0 -0
  321. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/researchforge-landscape.mdc +0 -0
  322. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/researchforge-paper.mdc +0 -0
  323. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/researchforge-papers.mdc +0 -0
  324. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/researchforge-plan.mdc +0 -0
  325. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/researchforge-results.mdc +0 -0
  326. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/researchforge-run.mdc +0 -0
  327. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/researchforge-ship.mdc +0 -0
  328. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/researchforge-start.mdc +0 -0
  329. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/cursor/rules/researchforge-validate.mdc +0 -0
  330. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/domain/__init__.py +0 -0
  331. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/domain/deliverable.py +0 -0
  332. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/domain/environment.py +0 -0
  333. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/domain/evidence.py +0 -0
  334. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/domain/landscape.py +0 -0
  335. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/domain/paper.py +0 -0
  336. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/domain/project.py +0 -0
  337. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/domain/repo_scan.py +0 -0
  338. {researchforge-0.2.0/src/researchforge/project → researchforge-0.4.0/src/researchforge/execution}/__init__.py +0 -0
  339. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/constraints.py +0 -0
  340. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/docker_exec.py +0 -0
  341. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/environment.py +0 -0
  342. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/metrics.py +0 -0
  343. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/path_guard.py +0 -0
  344. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/runner.py +0 -0
  345. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/execution/venv_exec.py +0 -0
  346. {researchforge-0.2.0/src/researchforge/reporting → researchforge-0.4.0/src/researchforge/experiments}/__init__.py +0 -0
  347. {researchforge-0.2.0/src/researchforge/repository → researchforge-0.4.0/src/researchforge/hypotheses}/__init__.py +0 -0
  348. {researchforge-0.2.0/src/researchforge/research → researchforge-0.4.0/src/researchforge/project}/__init__.py +0 -0
  349. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/project/cli.py +0 -0
  350. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/project/service.py +0 -0
  351. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/py.typed +0 -0
  352. {researchforge-0.2.0/src/researchforge/shipping → researchforge-0.4.0/src/researchforge/reporting}/__init__.py +0 -0
  353. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/reporting/cli.py +0 -0
  354. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/reporting/engineering_report.py +0 -0
  355. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/reporting/paper_cli.py +0 -0
  356. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/reporting/research_package.py +0 -0
  357. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/reporting/research_report.py +0 -0
  358. {researchforge-0.2.0/src/researchforge/storage → researchforge-0.4.0/src/researchforge/repository}/__init__.py +0 -0
  359. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/repository/cli.py +0 -0
  360. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/repository/scanner.py +0 -0
  361. {researchforge-0.2.0/src/researchforge/utils → researchforge-0.4.0/src/researchforge/research}/__init__.py +0 -0
  362. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/research/context_export.py +0 -0
  363. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/research/dedup.py +0 -0
  364. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/research/queries.py +0 -0
  365. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/research/ranking.py +0 -0
  366. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/research/text.py +0 -0
  367. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/server/__init__.py +0 -0
  368. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/server/app.py +0 -0
  369. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/server/cli.py +0 -0
  370. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/server/monitor.py +0 -0
  371. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/storage/contract_repository.py +0 -0
  372. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/storage/deliverable_repository.py +0 -0
  373. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/storage/paper_repository.py +0 -0
  374. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/storage/project_repository.py +0 -0
  375. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/storage/scan_repository.py +0 -0
  376. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/utils/artifact_io.py +0 -0
  377. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/utils/console.py +0 -0
  378. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/utils/output.py +0 -0
  379. {researchforge-0.2.0 → researchforge-0.4.0}/src/researchforge/utils/system_checks.py +0 -0
  380. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/README.md +0 -0
  381. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/artifacts/hypotheses_missing_claim.yaml +0 -0
  382. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/artifacts/hypotheses_overlap.yaml +0 -0
  383. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/artifacts/hypotheses_valid.yaml +0 -0
  384. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/artifacts/landscape_bad_paper_ref.yaml +0 -0
  385. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/artifacts/landscape_valid.yaml +0 -0
  386. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/arxiv/malformed.xml +0 -0
  387. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/arxiv/search_empty.xml +0 -0
  388. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/arxiv/search_overlapping.xml +0 -0
  389. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/arxiv/search_page1.xml +0 -0
  390. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/arxiv/search_page2.xml +0 -0
  391. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/contracts/example_full.yaml +0 -0
  392. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/eval_scripts/failing.py +0 -0
  393. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/eval_scripts/good.py +0 -0
  394. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/eval_scripts/knobs.py +0 -0
  395. {researchforge-0.2.0 → researchforge-0.4.0}/tests/fixtures/eval_scripts/wrong_metric.py +0 -0
  396. {researchforge-0.2.0 → researchforge-0.4.0}/tests/integration/test_examples.py +0 -0
  397. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_analytics.py +0 -0
  398. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_baseline_docker_args.py +0 -0
  399. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_baseline_venv.py +0 -0
  400. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_constraints.py +0 -0
  401. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_context_export.py +0 -0
  402. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_contract_cli.py +0 -0
  403. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_contract_validate.py +0 -0
  404. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_domain_contract.py +0 -0
  405. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_domain_project.py +0 -0
  406. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_domain_research.py +0 -0
  407. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_engineering_report.py +0 -0
  408. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_environment_resolver.py +0 -0
  409. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_experiment_run.py +0 -0
  410. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_experiment_storage.py +0 -0
  411. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_hub.py +0 -0
  412. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_importers.py +0 -0
  413. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_metrics_parser.py +0 -0
  414. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_path_guard.py +0 -0
  415. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_project_cli.py +0 -0
  416. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_ranking.py +0 -0
  417. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_repo_scanner.py +0 -0
  418. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_report.py +0 -0
  419. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_research_pure.py +0 -0
  420. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_run_lifecycle.py +0 -0
  421. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_runner.py +0 -0
  422. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_search_service.py +0 -0
  423. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_settings.py +0 -0
  424. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_ship_branch.py +0 -0
  425. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_status.py +0 -0
  426. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_storage.py +0 -0
  427. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_storage_migration.py +0 -0
  428. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_worktree_patch_ops.py +0 -0
  429. {researchforge-0.2.0 → researchforge-0.4.0}/tests/unit/test_worktrees.py +0 -0
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/claude-code-marketplace.json",
3
+ "name": "researchforge",
4
+ "description": "ResearchForge plugins for Claude Code.",
5
+ "owner": {
6
+ "name": "Forger Labs HQ",
7
+ "url": "https://www.researchforgehq.com"
8
+ },
9
+ "plugins": [
10
+ {
11
+ "name": "researchforge",
12
+ "source": "./src/researchforge/claude",
13
+ "description": "Kaggle Overnight and an evidence-first research loop: frozen baselines, isolated experiments, repeated validation. Needs the CLI: pip install researchforge.",
14
+ "category": "data-science",
15
+ "homepage": "https://www.researchforgehq.com"
16
+ }
17
+ ]
18
+ }
@@ -61,3 +61,7 @@ todo.md
61
61
 
62
62
  # Compressed upload copies (temp)
63
63
  assets/*_small.mp4
64
+ # The README's demo video: only the small voiced copy is published
65
+ assets/ResearchForgeDemo_60s.mp4
66
+ assets/ResearchForgeDemo_60s_voice.mp4
67
+ !assets/ResearchForgeDemo_60s_voice_small.mp4
@@ -0,0 +1,487 @@
1
+ # Changelog
2
+
3
+ ## 0.4.0 — Kaggle overnight, background sensors and a live dashboard (2026-11-15)
4
+
5
+ 0.3.0 was never published to PyPI; this is the first release that carries it.
6
+
7
+ ### Answering from the dashboard
8
+
9
+ - **An answer can change a setting.** A question may tie an answer to Run configs changes
10
+ (`kaggle ask … --action "<answer> => compute:kaggle, max_experiments:40"`). Picking that answer
11
+ applies them through the same setters as Run configs, logged as "answer to q-…"; a refused
12
+ value keeps the question open with the reason. Only the person can pick such an answer: an
13
+ unattended run is refused. Before this, "switch compute to kaggle" only recorded the words, so
14
+ auto-run found compute unchanged and asked again. Auto-run and `/overnight` now attach the
15
+ change to such answers instead of asking the person to edit Run configs by hand.
16
+ - **The 🔔 groups questions by competition**, one collapsible section each with its count of
17
+ questions and submission offers; the sections you open are remembered.
18
+ - **Submissions left today** shows on every submission offer and each competition's section:
19
+ Kaggle's reply to today's last submission, else the competition's daily limit (read once from
20
+ Kaggle's API) minus today's submissions. A used-up day is refused before calling Kaggle.
21
+
22
+ ### Kaggle overnight
23
+
24
+ - **`/overnight <competition-url>`** skill and **`researchforge kaggle overnight`**: reads the
25
+ competition, finds starter kernels, asks five setup questions, then runs a propose → run →
26
+ measure → keep loop on the compute you pick — Kaggle GPU, this machine, Colab, an SSH server
27
+ (`kaggle ssh-setup`) or a RunPod / Lambda Labs GPU (`kaggle cloud-gpu-setup`). Competition data
28
+ never downloads locally when the compute policy forbids it.
29
+ - **Claude drives the DAG**: `kaggle prepare-round` (DAG state, merge opportunity, ranked
30
+ hypothesis pool, next batch ready), `kaggle execute-round`, `kaggle run-parallel`,
31
+ `kaggle resynthesize` every five rounds, `kaggle propose-hypothesis`, `kaggle finish`.
32
+ Proposals name the hypothesis they test, and that hypothesis is marked tested with the round
33
+ and its outcome.
34
+ - **Human-gated submissions**: `experiment submission-candidates` ranks candidates by evidence;
35
+ `experiment submit <id>` asks for confirmation and records the public LB back into the DAG.
36
+
37
+ ### Background sensors
38
+
39
+ - **`researchforge kaggle monitor`** runs every sensor in one cycle: new public kernels → ideas,
40
+ submission status, hypothesis-pool growth, hung-experiment heartbeat, arXiv scan and a morning
41
+ briefing. Each sensor's last result is recorded in `monitor_state.json`.
42
+ - **`researchforge kaggle sensors <slug>`** turns sensors on/off and adds custom sensors (any shell
43
+ command; exit 0 = healthy), stored in `scheduler_config.json`.
44
+ - **`kaggle scheduler-install`** runs the monitor under launchd with the base interpreter and logs
45
+ under `~/.local/share/researchforge/logs/`, so macOS privacy controls on `~/Desktop` no longer
46
+ stop it (exit 78).
47
+
48
+ ### Live dashboard
49
+
50
+ - **`researchforge dashboard`** (or `kaggle dashboard --open/--daemon/--stop`) serves one live page
51
+ for every competition and repository project on this machine — nested repos, worktrees and
52
+ backups included. Home, Automation, Runs, DAG, Hypotheses, Submissions, Timeline and Insights
53
+ read one versioned state payload, polled with ETags; refreshes keep your view.
54
+ - DAG edges come from recorded parents; nodes show their patch, rationale and linked hypothesis;
55
+ merge candidates are drawn dashed using the engines' own merge rules.
56
+ - Projects show running / waiting for you / stalled / watching / idle, deadline countdowns, a
57
+ run gantt, launchd state with the real error line, and token usage per model, purpose and round.
58
+ - The old static report is `researchforge dashboard --legacy`.
59
+
60
+ ### Set up, sign in and steer from the dashboard
61
+
62
+ - **+ New competition**: paste a Kaggle URL; the dashboard gathers the facts and asks the
63
+ `/overnight` questions as a form, then runs the same setup commands, showing each step's output.
64
+ The answers are a draft (`setup_draft.json`, `kaggle draft <slug>`) that `/overnight` in Claude
65
+ Code or Cursor picks up, and a chat can hand to the page (`kaggle draft <slug> --start`).
66
+ - **Keys & accounts**: one page and `kaggle keys status|open|wait|set|test|remove` for Kaggle,
67
+ Anthropic/Gemini/OpenAI, the Claude Code and Cursor tokens, Colab, RunPod, Lambda, vast.ai and
68
+ AWS. A value is saved once and never shown again. `/overnight` asks which accounts you want and
69
+ opens the page for the missing ones instead of asking for a key in the chat. Cloud GPU rounds
70
+ read their provider key from the same file, so a background monitor can use it.
71
+ - **Steer**: directions for the next round or every round (`kaggle steer`), handed to the
72
+ proposer by `prepare-round` (`directions`) and auto-run's prompt, and answered on the page.
73
+ Pause, resume, re-synthesize and add an idea from the same page.
74
+
75
+ ### Colab rounds, the round time limit and phone alerts
76
+
77
+ - **Colab rounds survive a dropped connection.** `colab run` held one connection whose access
78
+ token expires after about 30 minutes, so every longer round died with "Connection was lost".
79
+ A round now starts in the background on the VM (`colab new`, `upload`), is checked every
80
+ minute with short `colab exec` calls that renew the token, and its output and submission
81
+ file are downloaded before the VM is released (`colab stop`, always). The kept file makes
82
+ the round eligible for a submission offer.
83
+ - **Colab only means Colab.** `prepare-round` gives the proposer `compute`: where the round
84
+ runs, its time limit and its rules. On Colab, `execute-round` and `run-parallel` refuse a
85
+ round that pushes a Kaggle notebook.
86
+ - **Round time limit** (Run configs → Budget, `round_time_limit_minutes`): how long one round's
87
+ full run may take, 30 minutes by default, instead of a fixed 30 minutes.
88
+ - **Alerts reach your topic.** Questions, approvals and submission offers ignored the
89
+ machine-wide topic (`researchforge notify setup`) and a topic given as a setup answer, so
90
+ they were never sent. Now: `NTFY_TOPIC`, then the competition's topic (`kaggle settings
91
+ <slug> --ntfy-topic`), then the machine-wide one. With no topic, nothing is sent: the shared
92
+ `researchforge-overnight` fallback, readable by anyone, is gone.
93
+ - **Run configs → Notifications**: where alerts go, how to subscribe, what each level sends,
94
+ **New topic** and **Send test alert**; the machine-wide topic is editable there too.
95
+ - Tests no longer send real alerts or add projects to your dashboard.
96
+ - `kaggle ask --options` keeps commas inside brackets or quotes in one answer (or separate
97
+ with `|`); an answer like "Switch to local (…, which …)" was split in two.
98
+ - A failed run shows no score on the Runs page instead of 0.0000.
99
+
100
+ ### Unattended auto-run for repository projects
101
+
102
+ - **`researchforge auto-run`** runs a repository project's loop with no terminal open. A
103
+ background monitor (`auto-run service`: launchd, systemd timer or Task Scheduler) runs a
104
+ cycle every 15 minutes and starts a launch when its checks pass. A launch runs the plans you
105
+ approved, then rounds of the real `autorun` engine.
106
+ - **Drivers:** Claude Code, Cursor (through their CLIs, every tool off) or an API key, chosen
107
+ per project. Keys come from the same `auto_run.env` as competitions.
108
+ - **Approval:** each plan waits for **Approve plan** and sends a phone alert; or the person types a
109
+ standing approval (`auto-run approval standing`), the consent `autorun` already asks for.
110
+ Unattended runs cannot give it.
111
+ - **Kaggle-side controls carried over:** pause and resume, rounds per launch and per day,
112
+ launch time limit, waiting out a driver's usage limit, alerts to the project's own ntfy topic,
113
+ a daily summary, and a daily scan for new arXiv papers.
114
+ - **Dashboard:** the Automation page's repo card has the service switch, driver, settings,
115
+ Start now / Stop, Pause, approval mode, topic and each check's status.
116
+ - `autorun`'s engine gains `ask_every_plan`, and `resolve_provider` a scoped override, so the
117
+ engine plans with the project's driver.
118
+
119
+ ### Unscored notebook rounds, real submission questions and the notebook board
120
+
121
+ - **A round with no local score but a submission is kept and offered.** A public notebook for
122
+ a hidden test set prints no score, so these rounds were marked failed and dropped their
123
+ output; Enveda's 0.480–0.500 notebook rounds (R7, R8, R21, R22) were never offered. They are
124
+ now recorded *unscored* (purple in Runs and the DAG), keep their notebook or file, and get a
125
+ submission question: Kaggle's score is the only measure of them.
126
+ - **"Submit R21's output?" asked by an agent is now that round's submission question**, so your
127
+ yes submits it. Before, it was a plain question: two yeses on Enveda submitted nothing. A
128
+ submit question about a round with nothing to submit is refused. Agents use
129
+ `researchforge kaggle offer-submission <slug> <round> --note "…"`.
130
+ - **Kaggle's daily submission limit is checked before submitting.** Kaggle's reply to each
131
+ submission says how many are left today; with 0 left, an approval is refused with the reset
132
+ time (00:00 UTC) and the question stays open. Before, R7, R8 and R21 on Enveda went to Kaggle
133
+ and came back as an unreadable "400 Bad Request". The allowance shows on each approval and
134
+ the Submissions page, and the "outdated kaggle" warning is no longer shown as the error.
135
+ - **A round is never submitted twice, and one competition sends one submission at a time.**
136
+ Enveda's R26 was sent twice at 14:51 and 14:52, spending a submission.
137
+ - **Improvements count without a baseline score.** A round the loop marked improved is shown as
138
+ improved when it beat every earlier round; the cards said "0 improved" on every project.
139
+ - **Public notebooks are checked every hour** (`monitor --kernel-minutes`, default 60), not every
140
+ 6 hours, including notebooks *re-run* since they were last seen. Each check rebuilds
141
+ `kernel_board.json`: every notebook with its claimed LB, Kaggle's best-score order, when it
142
+ last ran and our rounds that ran it, ranked by claimed LB. The dashboard's Hypotheses page
143
+ shows it per project, and `prepare-round` gives the proposer `public_notebooks_ahead`.
144
+ - **"Better notebook" alerts compare with our best leaderboard score.** They compared with the
145
+ setup baseline, which no project had, so none was ever sent.
146
+ - **The idea pool ranks notebooks claiming more than our best LB first**, highest claim first,
147
+ ahead of local measurability and relevance. A local benchmark can miss the leaderboard
148
+ entirely (Enveda: local 0.915, LB 0.21, public notebooks 0.49+). The Hypotheses page sorts by
149
+ claim by default.
150
+
151
+ ### Loop and notifications
152
+
153
+ - `autorun --no-metric-gate` records every result instead of auto-rejecting (for when the local
154
+ metric is not the real score); `experiment plan --merge a,b` combines two independent winners.
155
+ - `researchforge notify setup --topic <topic>` persists ntfy settings for every process; every
156
+ experiment result, merge opportunity and briefing is pushed, and logged to
157
+ `~/.config/researchforge/notification_log.jsonl`.
158
+ - Producers write to one resolved `.overnight_<slug>` directory per competition instead of
159
+ whichever folder a command ran from, and JSON state is written atomically.
160
+
161
+ ### Steer a running loop without stopping it
162
+
163
+ - **`kaggle status | pause | resume | respond | compute | add-hypothesis | settings`**, and the
164
+ same verbs as `/overnight status`, `/overnight pause`, … in the skill. A pause stops
165
+ `prepare-round`, `execute-round` and `run-parallel` from starting new rounds; a round already
166
+ running finishes and sensors keep going.
167
+ - **Questions never block the loop.** Mid-loop questions and submission offers are recorded in
168
+ `pending_interaction.json`; the loop keeps working on anything they do not block, and
169
+ `kaggle respond` answers them (domain answers flow into the next proposals).
170
+ - **Notification level** (`verbose` / `balanced` / `minimal`) and **submission policy**
171
+ (`aggressive` / `balanced` / `conservative`) per competition. Nothing is ever submitted
172
+ automatically — a submission offer records your decision only.
173
+ - **Daily Kaggle GPU cap** (`kaggle settings --kaggle-gpu-daily-cap N`): `execute-round` refuses
174
+ on Kaggle compute once today's cap is reached.
175
+ - **Kernel-watcher ideas are tagged by relevance** — builds on the best path, repeats a failure,
176
+ or a new direction — and `prepare-round` ranks them that way, with your own ideas first.
177
+ - **`autorun --kaggle`** records every result, tags how far each local metric can be trusted, marks
178
+ what is worth Kaggle GPU time, and lists submission candidates at the end. **`autorun
179
+ --judgment`** asks per experiment instead (a prompt, or a queued question answered with
180
+ `experiment judge <id> yes|no|skip`). Evidence goes to `.researchforge/kaggle_evidence.json`.
181
+ - **More compute:** vast.ai (`VAST_API_KEY`) and AWS EC2 (through the `aws` CLI) alongside RunPod and
182
+ Lambda; `scheduler-install` now also installs a systemd user timer on Linux and a Task Scheduler
183
+ task on Windows.
184
+ - Fixed: "no improvement" round notifications were never sent (an invalid format string raised
185
+ inside the notifier and was swallowed).
186
+
187
+ ### Auto-run, questions and run configs
188
+
189
+ - **Auto-run** (`kaggle auto-run <slug> --on`, off by default): `auto_run_sensor` starts rounds on
190
+ untested ideas with no chat open, driven by headless Claude Code (`claude -p`, allowed only
191
+ `researchforge kaggle …` commands and edits inside the project), the Cursor agent
192
+ (`cursor-agent -p`) or your API key (`kaggle run --rounds N`). A launch starts only when setup is
193
+ done, the loop isn't paused, no question holds it, no round is running, and the daily limit and
194
+ Kaggle GPU cap allow it; `--max-minutes` stops a long launch. It never submits.
195
+ With no flag it shows its status; also `--dry-run`, `--now` and `--stop`.
196
+ - **One driver per project, switchable any time** (`kaggle driver <slug> <driver>`). The driver also
197
+ does the sensors' AI work through one-shot, tool-less calls (`--no-sensors` keeps them on a
198
+ key), and every round records which driver ran it. `kaggle driver-login <claude|cursor|byok|colab>`
199
+ signs a driver in from your own terminal; tokens and keys go to
200
+ `~/.config/researchforge/auto_run.env` (mode 600). `kaggle auto-run-key <NAME>` stores one value.
201
+ - **Questions come to you**: `kaggle ask <slug> "…" --options a,b --blocks "<idea>" [--hold]` pushes
202
+ to your phone and the dashboard's 🔔 and Home; only the ideas it names wait.
203
+ `kaggle respond <slug> <id> --dismiss` closes one unanswered and its ideas run again. A
204
+ standalone repository project's plans waiting for approval are listed too: **Approve plan** asks
205
+ you to type `approve`, as `researchforge experiment approve` does; unattended runs never approve
206
+ plans. A repo project beside a competition gets no plan approvals.
207
+ - **Run configs** in the dashboard: every setting for a competition, editable on the fly through the
208
+ same setters as the CLI, with a change log.
209
+ - **Metric direction is measured**: read from the leaderboard's order, with its source recorded and a
210
+ guess flagged; lower-is-better is handled everywhere. `kaggle settings --metric-direction` fixes it.
211
+ - **Every compute option is offered at setup**; `--gpu` accepts local, kaggle, colab, ssh, cloud and
212
+ competition, and an unknown or unconfigured target stops setup.
213
+ - **Colab without clicking Run all**, through Google's Colab CLI: each round rents a fresh VM with
214
+ the GPU your plan allows (T4, L4, G4, A100, H100, optional high-RAM), downloads the data there
215
+ with your Kaggle key, runs and releases the VM. `kaggle colab-setup <slug> --plan pro --gpu L4`
216
+ and `kaggle driver-login colab`; without a sign-in, rounds wait. Used on a real Colab account
217
+ (a T4 VM up in about 15 s, Titanic data downloaded on the VM, score read back, VM released);
218
+ Colab Enterprise is not supported yet.
219
+ - **One history per competition**: the Kaggle loop is a competition's only engine, and auto-run
220
+ always continues it. A repo project beside it is folded in (`kaggle merge-history`, also run by
221
+ the monitor each cycle): its finished experiments appear in the same graph, dotted and marked
222
+ imported, and never count as best or as a parent; its untested hypotheses join the pool. With
223
+ no baseline, a round must beat the best earlier round to count as improved or be offered for
224
+ submission.
225
+ - **Notebook score claims**: notebook ideas carry the LB score their author claims and its gap to
226
+ your best public score, ranked by it but never treated as a measurement.
227
+ - **`kaggle archive <slug> R7`** (reversible) and **`kaggle delete-round`** (confirmed, not
228
+ available to unattended runs); **`kaggle pull-kernel <slug> <owner/notebook>`** downloads a
229
+ public notebook into `reference_kernels/`.
230
+ - Fixed: a round whose process died left a lock that blocked every later round — the lock is now
231
+ released and the round recorded as interrupted; the monitor runs a cycle missed while the Mac
232
+ slept within a minute of waking.
233
+ - Fixed: running `/overnight` again on a set-up project redid setup — it now resumes (`--refresh`
234
+ starts over).
235
+
236
+ ### Install and models
237
+
238
+ - **Claude Code plugin.** The repository is a plugin marketplace:
239
+ `/plugin marketplace add forger-labs-hq/researchforge`, then
240
+ `/plugin install researchforge@researchforge`. It ships the same skills as
241
+ `researchforge claude install`, namespaced as `/researchforge:overnight` and so on.
242
+ - **Local models through Ollama.** `RESEARCHFORGE_LLM=ollama/<model>` (server at `OLLAMA_HOST`,
243
+ default `http://localhost:11434`) uses Ollama's native API: no key and no SDK. Calls are recorded
244
+ as `ollama/<model>`, and their tokens are priced at zero. Kaggle Overnight runs headless on it
245
+ (`ai_provider_mode: ollama`), and background services now pass on `RESEARCHFORGE_LLM` and
246
+ `OLLAMA_HOST`. They also pass on `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID`; before this,
247
+ Telegram alerts stopped under the scheduler. The previously documented `http://localhost:11434/api` URL now reaches Ollama;
248
+ it used to be sent to an OpenAI client that cannot talk to that endpoint.
249
+ - **`researchforge --version`.**
250
+ - Fixed: setup claimed API-key mode lets "the laptop be off". The loop always runs on the
251
+ machine where it starts. A key or a local model removes the need for the editor, not for the
252
+ machine.
253
+
254
+ ## 0.3.0 — What it costs, and running it from your editor (2026-09-01)
255
+
256
+ Two gaps 0.2.0 left open: the loop needed an API key even when you were already
257
+ paying for one inside your editor, and nothing anywhere said what a run cost.
258
+
259
+ ### The loop without an API key
260
+
261
+ - **`autorun --dry-run`** answers "where would you go next?" — which node the
262
+ frontier would expand and which hypotheses it ranked there — without planning,
263
+ running, or calling a provider. An agent driving the loop by hand gets
264
+ ResearchForge's search instead of re-deriving one by eye from a results table.
265
+ `--json` for programmatic use.
266
+ - **`experiment plan --parent exp-NNN`** compounds onto a measured winner from
267
+ the handshake path: the exported repository files are the ones that experiment
268
+ leaves behind, so the change is written against what it already won. Unknown
269
+ ids fail before any AI call or file write.
270
+ - **Provider resolution is lazy** in `plan_all_hypotheses`. A round with nothing
271
+ to plan no longer demands a key it was never going to use, which is what
272
+ blocked keyless execution-only rounds.
273
+ - **`researchforge-autorun`** skill and Cursor rule drive the loop from the
274
+ editor: dry-run for the next move, plan and import it, run it, repeat.
275
+ - **`init --cursor` installs the workflow rules**, not only the gateway —
276
+ matching what `--claude` has always done.
277
+
278
+ ### What a run costs
279
+
280
+ - **Time economics** on the dashboard: compute split by stage and *by how each
281
+ experiment ended*, so what the failures cost is visible rather than only what
282
+ the winner gained; how many full benchmarks never ran because screening or the
283
+ stall rule stopped them first; and which changes a hard limit caught.
284
+ - **Work avoided is shown as its arithmetic** — skipped runs times this
285
+ project's own measured average full benchmark, with both halves on screen. A
286
+ project with no completed benchmark to average reports no figure rather than
287
+ zero.
288
+ - **No counterfactual claims.** There is deliberately no "this would have taken
289
+ a human N hours": that number cannot be checked, and one unfalsifiable claim
290
+ discredits the measured ones next to it. A test fails the build if the phrase
291
+ reappears in the dashboard.
292
+ - **The hub shows compute and token spend per project**, so you can see which
293
+ project has been running rather than only thinking; the monitor's overview tab
294
+ carries the same summary, and the full breakdown stays on its dashboard tab.
295
+
296
+ ### Token accounting
297
+
298
+ - **Every provider now reports usage.** Anthropic, Gemini and OpenAI all
299
+ returned token counts that were being discarded on the line that extracted the
300
+ text. Providers file them into a context-local ledger rather than changing
301
+ `generate()`'s signature, so callers that want the numbers opt in and the rest
302
+ are unaffected. Usage is recorded even when a call raises — a request that
303
+ failed after the prompt was read still cost money.
304
+ - **Calls are attributed to what asked for them** — planning, synthesis,
305
+ observation, evaluation, merge, queries, dockerfile — and stored per project.
306
+ - **Prices live in `.researchforge/config.json`** under `model_prices`, dollars
307
+ per million tokens matched by longest model-name prefix, so `gpt-4o-mini` is
308
+ not billed at `gpt-4o`'s rate and a dated release is priced by its family.
309
+ Defaults ship for common models and are overridable for negotiated rates.
310
+ - **A model with no rate is named, not billed at zero.** The dashboard says the
311
+ dollar figure is a floor and lists the unpriced models; the hub omits the
312
+ dollar pill entirely. A zero meaning "unknown" reads as "free".
313
+ - **Benchmark compute converts to dollars only if you say what an hour costs**
314
+ (`local_compute_usd_per_hour`), since an owned laptop has no marginal hourly
315
+ cost and a rented GPU has an invoice.
316
+ - **IDE-driven planning is sized, not metered.** When Claude Code or Cursor
317
+ makes the call, ResearchForge never sees the response — so it records the size
318
+ of the exchange it *can* see: context handed over, plan and patches returned.
319
+ These are stored flagged as estimates, kept out of the metered total, never
320
+ priced, and rendered with a tilde everywhere they appear.
321
+
322
+ **Compatibility:** schema 8 adds `ai_calls` and its `estimated` column;
323
+ migration is automatic on the first write. Projects that have not been written
324
+ to since upgrading report no model calls, which is accurate — usage is captured
325
+ as calls happen and cannot be reconstructed for runs that already finished.
326
+
327
+ ## 0.2.0 — Phase 2: standalone AI and the autonomous loop (2026-08-30)
328
+
329
+ 0.1.0 needed a human at every step and Claude Code to think. This release
330
+ removes both: ResearchForge runs from a plain API key, and `autorun` searches
331
+ for hours unattended without giving up the gates, constraints, or records that
332
+ make a result worth trusting.
333
+
334
+ ### Standalone — no IDE required
335
+
336
+ - **Built-in AI providers**: Anthropic, Google Gemini and OpenAI ship as core
337
+ dependencies with auto-detection from whichever key is set, `--provider` to
338
+ choose explicitly, `RESEARCHFORGE_LLM` to override the model, and Ollama for
339
+ local inference. Every step that previously required an IDE now has a CLI
340
+ path; the Claude Code and Cursor integrations remain, as one option of three.
341
+ - **`research synthesize` / `hypotheses generate`**: landscape and hypotheses
342
+ generated directly from retrieved papers, validated against the same schemas
343
+ as the IDE path before import.
344
+ - **`generate eval-script`**: writes `benchmarks/evaluate.py` and a tunable
345
+ `src/config.py` for a repo that has no benchmark, and commits them — an
346
+ uncommitted eval script is invisible to the worktrees experiments run in.
347
+ `--existing` adopts a script you already have.
348
+ - **`generate dockerfile`**: heuristic by default (no key needed), AI-tailored
349
+ with `--provider`.
350
+ - **`experiment plan --synthesize`**: plan and patches authored in one command.
351
+
352
+ ### `researchforge autorun` — the loop
353
+
354
+ - **Unattended rounds**: plan, run, record, re-synthesize from measured results,
355
+ repeat. Stopping conditions are per-plan `--stall`, loop-wide
356
+ `--global-stall`, `--max-rounds`, `--max-hours` and `--target`; `--resume`
357
+ continues an interrupted loop with the same counters and budget.
358
+ - **Human gates survive autonomy**: the contract and the first batch are still
359
+ typed by a human. `--yes` skips only the per-round confirmations after that,
360
+ and hard constraints are enforced at 3am exactly as they are by hand.
361
+ - **Experiments became a DAG**: `parent_experiment_ids` replaces the single
362
+ parent, so a round can build on any earlier winner and two independent
363
+ winners can be merged into one experiment to test whether their gains add.
364
+ Parent patches compose in topological order; conflicts are caught at import.
365
+ - **Graph search, not a queue drain**: the unit of work is a *(hypothesis,
366
+ node)* pair — the same idea on a different ancestor is a different
367
+ measurement — bounded by trying each pair once and never applying a
368
+ hypothesis on top of itself. Re-synthesis fires on exhaustion rather than
369
+ round number, so a second `autorun` on an explored graph starts working
370
+ instead of exiting.
371
+ - **Node selection is UCB1** (`--explore`): 0 always expands the current best,
372
+ higher values revisit under-explored branches so a stalled leader cannot trap
373
+ the loop.
374
+ - **`--observe`**: the AI reads each run's own `stdout.log` and writes a short
375
+ observation, so a failure that failed for an interesting reason leaves
376
+ something readable rather than only a status code.
377
+ - **Results-grounded re-synthesis**: new hypotheses account for what improved,
378
+ what violated a constraint and what failed. They are added rather than
379
+ replacing the set, and near-duplicates of tested ideas are dropped.
380
+
381
+ ### Patches are written from the source
382
+
383
+ - The contract's `editable_paths` are exported **in full** — real contents read
384
+ from git, prioritized by the hypothesis's wording when the budget cannot fit
385
+ everything, with the remainder listed by name.
386
+ - The AI returns the **complete new content** of each file it changes and
387
+ ResearchForge computes the diff with git, which cannot produce a diff that
388
+ fails to apply to the state it came from. This replaced a long tail of
389
+ `corrupt patch` and `No such file or directory` plan rejections.
390
+ - A compounding plan sees its **parent's** files, not the baseline's: the
391
+ lineage is replayed in a scratch worktree and the prompt names which
392
+ experiments are already baked into what the model is reading.
393
+
394
+ ### Honesty and legibility
395
+
396
+ - **`NO CHANGE` badge**: every percentage is measured against the frozen
397
+ baseline, which is what makes two cards comparable — but it means a child that
398
+ changed nothing still wears its parent's gain. A node measuring exactly what
399
+ its ancestors measured is now badged, with a tooltip saying the number is
400
+ inherited.
401
+ - **Derived audit trail**: `audit log` / `audit export` reconstruct project
402
+ history from the records the workflow already writes, and report *gate
403
+ findings* — plans that executed without a recorded approval. There is
404
+ deliberately no separate audit log file; a second write path can drift from
405
+ what it describes.
406
+ - **Readable experiment graph**: sibling edges share a trunk, parents are
407
+ centred on their children, and layers too tall to stack wrap into sub-columns
408
+ with edges routed over a rail, so wide runs grow sideways rather than downward.
409
+ - **Nothing runs silently**: planning shows its phase and a clock and then
410
+ states the plan's shape; execution reports worktree setup, patch application,
411
+ screening and the full benchmark, and every finished experiment leaves a
412
+ permanent one-line verdict. Rounds narrate which node they are expanding and
413
+ why.
414
+
415
+ ### Shipping
416
+
417
+ - **`ship pr` asks where the pull request should go** and pins that repository
418
+ for every `gh` call instead of relying on `gh`'s base-repo inference, which
419
+ can silently prefer `upstream` over your own fork. `--remote` and `--repo-url`
420
+ choose non-interactively.
421
+ - **Replay by default**: the winning change is replayed as a single commit on
422
+ the target's base branch, so the PR carries the change rather than the
423
+ baseline history it was measured on. `--as-measured` pushes the shipped commit
424
+ instead, and diverging files are reported before anything is pushed.
425
+ - **Opening a PR on a repository you cannot push to always requires a typed
426
+ confirmation**, which `--yes` cannot bypass.
427
+
428
+ ### Setup that recovers itself
429
+
430
+ - `baseline run` diagnoses setup failures instead of reporting them: it reads
431
+ stderr and retries against a rule set covering flat-layout `pyproject.toml`,
432
+ stale pip, missing compilers, CUDA mismatches, resolver conflicts, network and
433
+ disk failures, and a benchmark script missing from git.
434
+ - When every venv fix fails and Docker is available, it can generate a
435
+ Dockerfile, switch the contract to Docker mode, re-approve, and retry there.
436
+
437
+ ### Also
438
+
439
+ - **`baseline run --n-runs N`** freezes the *mean* of N runs and records the
440
+ spread, so a noisy benchmark's improvements are not measured against one lucky
441
+ run. **`baseline reset`** refuses without `--force` once experiments have been
442
+ measured against the baseline, and never rewrites their records.
443
+ - **`validate --n` / `--stdev-max`** refuse a finalist whose repeats spread too
444
+ wide, however good the average.
445
+ - **`hypotheses review/approve/reject`** as an optional gate — rejection is the
446
+ half with teeth, and the refusal names the command that undoes it.
447
+ - **`papers export` / `import`** move a literature set between projects without
448
+ re-querying arXiv; **`research search --since`** filters inside the query so
449
+ the candidate budget is not spent on papers that get discarded.
450
+ - **`env_overrides`** in a plan change configuration without a patch file. Note
451
+ the asymmetry, which silently breaks compounding if you don't know it: patches
452
+ compose down a lineage, `env_overrides` do not.
453
+ - **`researchforge run <plan.yaml>`** and **`baseline status`** aliases;
454
+ `--help` groups commands into named panels.
455
+ - **`examples/yolov5-detection`**: a real ML target — YOLOv5su on COCO128, mAP as
456
+ the objective, per-image latency as a hard constraint — rather than a
457
+ deterministic toy.
458
+
459
+ **Compatibility:** existing single-parent experiment records migrate
460
+ automatically. Contracts from 0.1.0 remain valid; `stall`, `mode: auto` and
461
+ `target_value` are optional additions.
462
+
463
+ ## 0.1.0 — Phase 1 open-source beta (2026-07-24)
464
+
465
+ The complete local pipeline, Claude-first.
466
+
467
+ - **Research intelligence**: arXiv discovery (dedup + deterministic
468
+ ranking), the Claude↔CLI synthesis handshake (landscape + hypotheses with
469
+ graded evidence), citation-backed research report.
470
+ - **Experiment contract**: `researchforge.yaml` wizard, 14 semantic
471
+ validation rules, typed approval into immutable versions with drift
472
+ detection.
473
+ - **Isolated execution**: detached git worktrees per attempt, Docker
474
+ (locked-down defaults) and `.venv` runners, path guard with run-time
475
+ re-check, process-group timeouts, secrets redaction.
476
+ - **Experiment funnel**: Claude-authored patch variants through screening →
477
+ full benchmark → repeated validation; hard constraints; Pareto ranking
478
+ with honesty caveats; rejected/failed experiments preserved.
479
+ - **Shipping**: clean branch reconstructed from the frozen baseline
480
+ (pre-ship re-validation, post-conditions asserted), opt-in draft PR via
481
+ gh, engineering report, research package (BibTeX, outline,
482
+ reproducibility bundle).
483
+ - **Claude Code experience**: 12 installable project skills
484
+ (`researchforge init --claude`), manifest-based installer that never
485
+ clobbers user edits.
486
+ - **Beta tooling**: tested launch-demo examples, opt-in local-only
487
+ analytics, security notes.