loopmath 0.2.2__tar.gz → 0.2.3__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 (378) hide show
  1. {loopmath-0.2.2 → loopmath-0.2.3}/PKG-INFO +3 -1
  2. {loopmath-0.2.2 → loopmath-0.2.3}/README.md +2 -0
  3. {loopmath-0.2.2 → loopmath-0.2.3}/pyproject.toml +1 -1
  4. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/__init__.py +1 -1
  5. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/design.py +5 -3
  6. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/fit.py +5 -3
  7. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/priors.py +46 -7
  8. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/state.py +4 -1
  9. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/builder/context.py +18 -2
  10. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/cli_registry.py +6 -2
  11. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/onboard/commands.py +5 -0
  12. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/__init__.py +31 -8
  13. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/benchmarks.py +6 -1
  14. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/benchmarks.toml +7 -2
  15. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/build.py +84 -33
  16. loopmath-0.2.3/src/loopmath/priors/bundle/README.md +7 -0
  17. loopmath-0.2.3/src/loopmath/priors/bundle/e0.jsonl.gz +0 -0
  18. loopmath-0.2.3/src/loopmath/priors/bundle/lanes.jsonl.gz +0 -0
  19. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/bundle/manifest.json +133 -42
  20. loopmath-0.2.3/src/loopmath/priors/bundle/rq1.jsonl.gz +0 -0
  21. loopmath-0.2.3/src/loopmath/priors/bundle/sweep.jsonl.gz +0 -0
  22. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/commands.py +16 -10
  23. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/e0.py +8 -3
  24. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/lanes.py +15 -1
  25. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/ocpdoc.py +45 -0
  26. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/registry.py +3 -1
  27. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/rq1.py +13 -3
  28. loopmath-0.2.3/src/loopmath/priors/show.py +182 -0
  29. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/sweep.py +34 -7
  30. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/recommend/commands.py +18 -8
  31. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/recommend/engine.py +18 -8
  32. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/recommend/message.py +50 -4
  33. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/recommend/storeread.py +8 -0
  34. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/skill/skills/loopmath-import-runs/SKILL.md +2 -2
  35. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/skill/skills/loopmath-onboard/SKILL.md +3 -1
  36. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/skill/skills/loopmath-update-fit/SKILL.md +2 -2
  37. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/skill/skills/reference.md +3 -3
  38. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/config.py +5 -3
  39. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/types.py +9 -1
  40. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/builder.css +4 -0
  41. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/builder.js +52 -16
  42. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/plans.css +1 -0
  43. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/plans.js +10 -1
  44. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/results.js +12 -3
  45. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/posterior.py +14 -1
  46. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath.egg-info/PKG-INFO +3 -1
  47. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath.egg-info/SOURCES.txt +1 -0
  48. loopmath-0.2.3/tests/test_starting_prior.py +233 -0
  49. loopmath-0.2.2/src/loopmath/priors/bundle/README.md +0 -3
  50. loopmath-0.2.2/src/loopmath/priors/bundle/e0.jsonl.gz +0 -0
  51. loopmath-0.2.2/src/loopmath/priors/bundle/lanes.jsonl.gz +0 -0
  52. loopmath-0.2.2/src/loopmath/priors/bundle/rq1.jsonl.gz +0 -0
  53. loopmath-0.2.2/src/loopmath/priors/bundle/sweep.jsonl.gz +0 -0
  54. loopmath-0.2.2/src/loopmath/priors/show.py +0 -72
  55. {loopmath-0.2.2 → loopmath-0.2.3}/LICENSE +0 -0
  56. {loopmath-0.2.2 → loopmath-0.2.3}/setup.cfg +0 -0
  57. {loopmath-0.2.2 → loopmath-0.2.3}/spec/ocp-v0.2.schema.json +0 -0
  58. {loopmath-0.2.2 → loopmath-0.2.3}/spec/ocp-v0.schema.json +0 -0
  59. {loopmath-0.2.2 → loopmath-0.2.3}/spec/ocp_conformance.py +0 -0
  60. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/__main__.py +0 -0
  61. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapter_host.py +0 -0
  62. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/__init__.py +0 -0
  63. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/atrium.py +0 -0
  64. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/base.py +0 -0
  65. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/bb.py +0 -0
  66. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/bb_support.py +0 -0
  67. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/omp.py +0 -0
  68. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/omp_facts.py +0 -0
  69. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/omp_links.py +0 -0
  70. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/omp_parse.py +0 -0
  71. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/omp_types.py +0 -0
  72. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/opencode.py +0 -0
  73. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/opencode_store.py +0 -0
  74. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/orca.py +0 -0
  75. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/otel_genai.py +0 -0
  76. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/otel_genai_graph.py +0 -0
  77. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/otel_genai_parse.py +0 -0
  78. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/otel_genai_types.py +0 -0
  79. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/otel_genai_usage.py +0 -0
  80. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/paseo.py +0 -0
  81. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/pi.py +0 -0
  82. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/pi_support.py +0 -0
  83. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/adapters/registry.py +0 -0
  84. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/__init__.py +0 -0
  85. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/block.py +0 -0
  86. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/check_pymc.py +0 -0
  87. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/commands.py +0 -0
  88. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/compose.py +0 -0
  89. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/features.py +0 -0
  90. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/forest.py +0 -0
  91. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/gaussian.py +0 -0
  92. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/lookahead.py +0 -0
  93. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/outcome.py +0 -0
  94. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/belief/pricing.py +0 -0
  95. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/builder/__init__.py +0 -0
  96. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/builder/cli.py +0 -0
  97. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/builder/predict.py +0 -0
  98. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/builder/server.py +0 -0
  99. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/cli.py +0 -0
  100. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/cli_graph.py +0 -0
  101. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/cli_support.py +0 -0
  102. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/e0/__init__.py +0 -0
  103. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/e0/arms.py +0 -0
  104. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/e0/cli_e0.py +0 -0
  105. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/e0/estimate.py +0 -0
  106. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/e0/estimate_rework.py +0 -0
  107. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/e0/figures.py +0 -0
  108. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/e0/io.py +0 -0
  109. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/e0/verb.py +0 -0
  110. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/explain.py +0 -0
  111. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/fit.py +0 -0
  112. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/fit_assembly.py +0 -0
  113. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/fit_bayes.py +0 -0
  114. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/fit_masks.py +0 -0
  115. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/fit_predict.py +0 -0
  116. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/fit_pricing.py +0 -0
  117. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/fit_transfer.py +0 -0
  118. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/gaps.py +0 -0
  119. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/gitwalk.py +0 -0
  120. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/grade.py +0 -0
  121. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/grade_support.py +0 -0
  122. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/__init__.py +0 -0
  123. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/artifact_git.py +0 -0
  124. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/artifact_join.py +0 -0
  125. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/artifact_kinds.py +0 -0
  126. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/artifacts.py +0 -0
  127. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/bashparse.py +0 -0
  128. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/bashread_ops.py +0 -0
  129. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/bashwrite_ops.py +0 -0
  130. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/bashwrites.py +0 -0
  131. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/cache.py +0 -0
  132. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/codexio.py +0 -0
  133. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/codexio_parse.py +0 -0
  134. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/codexio_scan.py +0 -0
  135. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/dataset.py +0 -0
  136. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/dataset_build.py +0 -0
  137. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/dataset_core.py +0 -0
  138. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/dataset_edges.py +0 -0
  139. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/dataset_nodes.py +0 -0
  140. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/extract.py +0 -0
  141. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/html_common.py +0 -0
  142. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/html_costcurve.py +0 -0
  143. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/html_css.py +0 -0
  144. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/html_data.py +0 -0
  145. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/html_force.py +0 -0
  146. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/html_render.py +0 -0
  147. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/html_swimlanes.py +0 -0
  148. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler.py +0 -0
  149. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_cli.py +0 -0
  150. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_common.py +0 -0
  151. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_parse.py +0 -0
  152. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_pricing.py +0 -0
  153. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_prompt.py +0 -0
  154. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_prompt_build.py +0 -0
  155. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_prompt_dispatch.py +0 -0
  156. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_prompt_evidence.py +0 -0
  157. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_prompt_node.py +0 -0
  158. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_prompt_records.py +0 -0
  159. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_prompt_result.py +0 -0
  160. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_prompt_session.py +0 -0
  161. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_prompt_tools.py +0 -0
  162. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_prompt_validation.py +0 -0
  163. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_prompt_workflow.py +0 -0
  164. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_report.py +0 -0
  165. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labeler_score.py +0 -0
  166. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/labels.py +0 -0
  167. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/launch.py +0 -0
  168. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/launch_origin.py +0 -0
  169. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/ocp.py +0 -0
  170. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/ocp_emit.py +0 -0
  171. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/ocp_support.py +0 -0
  172. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/render.py +0 -0
  173. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/runfile.py +0 -0
  174. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/runfile_export.py +0 -0
  175. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/runfile_finish.py +0 -0
  176. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/scan.py +0 -0
  177. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/schema.py +0 -0
  178. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/graph/token_completeness.py +0 -0
  179. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ingest/__init__.py +0 -0
  180. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ingest/base.py +0 -0
  181. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ingest/claude_code.py +0 -0
  182. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ingest/claude_code_support.py +0 -0
  183. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ingest/codex.py +0 -0
  184. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ingest/codex_support.py +0 -0
  185. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ingest/ocp.py +0 -0
  186. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ingest/ocp_analysis.py +0 -0
  187. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ingest/ocp_artifact.py +0 -0
  188. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ingest/ocp_common.py +0 -0
  189. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ingest/ocp_convert.py +0 -0
  190. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ingest/ocp_projection.py +0 -0
  191. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/logmatch/__init__.py +0 -0
  192. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/logmatch/artifacts.py +0 -0
  193. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/logmatch/clip.py +0 -0
  194. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/logmatch/costs.py +0 -0
  195. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/logmatch/match.py +0 -0
  196. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/logmatch/settle.py +0 -0
  197. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/logmatch/tariff.py +0 -0
  198. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ocp/__init__.py +0 -0
  199. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ocp/canonical.py +0 -0
  200. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ocp/commands.py +0 -0
  201. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ocp/conformance.py +0 -0
  202. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ocp/contractv3.py +0 -0
  203. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ocp/emit.py +0 -0
  204. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ocp/migrate.py +0 -0
  205. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ocp/schema/ocp-v0.2.schema.json +0 -0
  206. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ocp/schema/ocp-v0.3.schema.json +0 -0
  207. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ocp/schema/ocp-v0.schema.json +0 -0
  208. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/ocp/version.py +0 -0
  209. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/onboard/__init__.py +0 -0
  210. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/onboard/history.py +0 -0
  211. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/onboard/label.py +0 -0
  212. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/onboard/usual.py +0 -0
  213. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/output.py +0 -0
  214. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/pool.py +0 -0
  215. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/price.py +0 -0
  216. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/price_validation.py +0 -0
  217. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/prices.toml +0 -0
  218. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/history.py +0 -0
  219. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/reduce.py +0 -0
  220. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/priors/validate.py +0 -0
  221. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/receipts.py +0 -0
  222. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/recommend/__init__.py +0 -0
  223. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/recommend/backlog.py +0 -0
  224. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/recommend/curve.py +0 -0
  225. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/recommend/gain.py +0 -0
  226. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/recommend/receipts.py +0 -0
  227. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/recommend/search.py +0 -0
  228. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/recommend/stats.py +0 -0
  229. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/report/__init__.py +0 -0
  230. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/report/html.py +0 -0
  231. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/report/terminal.py +0 -0
  232. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/report/terminal_exclusions.py +0 -0
  233. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/report/terminal_format.py +0 -0
  234. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/report/terminal_read.py +0 -0
  235. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/research_defaults.py +0 -0
  236. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/research_paths.py +0 -0
  237. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/scoring.py +0 -0
  238. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/scoring_comparisons.py +0 -0
  239. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/scoring_predictive.py +0 -0
  240. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/share/__init__.py +0 -0
  241. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/share/commands.py +0 -0
  242. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/share/export.py +0 -0
  243. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/share/import_.py +0 -0
  244. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/skill/__init__.py +0 -0
  245. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/skill/commands.py +0 -0
  246. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/skill/doctor.py +0 -0
  247. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/skill/install.py +0 -0
  248. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/skill/skills/loopmath/SKILL.md +0 -0
  249. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/skill/skills/loopmath-plan-task/SKILL.md +0 -0
  250. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/skill/skills/loopmath-record-run/SKILL.md +0 -0
  251. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/__init__.py +0 -0
  252. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/budget.py +0 -0
  253. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/commands.py +0 -0
  254. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/finish.py +0 -0
  255. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/fitjob.py +0 -0
  256. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/home.py +0 -0
  257. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/ids.py +0 -0
  258. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/lock.py +0 -0
  259. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/record.py +0 -0
  260. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/report.py +0 -0
  261. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/runs.py +0 -0
  262. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/store/status.py +0 -0
  263. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/surface.py +0 -0
  264. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/surface_bootstrap.py +0 -0
  265. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/surface_estimation.py +0 -0
  266. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/surface_frame.py +0 -0
  267. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/surface_presentation.py +0 -0
  268. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/surface_support.py +0 -0
  269. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/taskmodel.py +0 -0
  270. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/__init__.py +0 -0
  271. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/README.md +0 -0
  272. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/base.css +0 -0
  273. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/builder.html +0 -0
  274. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/common.js +0 -0
  275. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/estimates.css +0 -0
  276. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/estimates.js +0 -0
  277. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/graph.css +0 -0
  278. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/graph.js +0 -0
  279. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/results.css +0 -0
  280. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/runs.js +0 -0
  281. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/viz.css +0 -0
  282. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/assets/viz.js +0 -0
  283. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/common.py +0 -0
  284. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/plans.py +0 -0
  285. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/views/runs.py +0 -0
  286. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/__init__.py +0 -0
  287. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/candidates.py +0 -0
  288. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/catalog/best_of_n.toml +0 -0
  289. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/catalog/implement_review.toml +0 -0
  290. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/catalog/plan_implement.toml +0 -0
  291. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/catalog/plan_implement_review.toml +0 -0
  292. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/catalog/solo.toml +0 -0
  293. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/catalog/swarm.toml +0 -0
  294. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/commands.py +0 -0
  295. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/diff.py +0 -0
  296. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/format.py +0 -0
  297. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/graphview.py +0 -0
  298. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/ids.py +0 -0
  299. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/infer.py +0 -0
  300. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/models.py +0 -0
  301. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/ocp.py +0 -0
  302. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath/workflows/shapes.py +0 -0
  303. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath.egg-info/dependency_links.txt +0 -0
  304. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath.egg-info/entry_points.txt +0 -0
  305. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath.egg-info/requires.txt +0 -0
  306. {loopmath-0.2.2 → loopmath-0.2.3}/src/loopmath.egg-info/top_level.txt +0 -0
  307. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_adapter_atrium.py +0 -0
  308. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_adapter_bb.py +0 -0
  309. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_adapter_omp.py +0 -0
  310. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_adapter_opencode.py +0 -0
  311. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_adapter_opencode_output_tokens.py +0 -0
  312. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_adapter_orca.py +0 -0
  313. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_adapter_otel_genai.py +0 -0
  314. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_adapter_paseo.py +0 -0
  315. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_adapter_services.py +0 -0
  316. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_adapters.py +0 -0
  317. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_adapters_pi.py +0 -0
  318. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_arms.py +0 -0
  319. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_cli_graph.py +0 -0
  320. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_cli_help_lists.py +0 -0
  321. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_cli_labeler.py +0 -0
  322. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_cli_main_module.py +0 -0
  323. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_cli_plan_hidden.py +0 -0
  324. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_cli_prices.py +0 -0
  325. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_cli_startup.py +0 -0
  326. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_color_proof.py +0 -0
  327. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_duplicate_guards.py +0 -0
  328. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_estimate.py +0 -0
  329. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_explain.py +0 -0
  330. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_fit.py +0 -0
  331. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_gaps.py +0 -0
  332. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_gitwalk.py +0 -0
  333. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_grade.py +0 -0
  334. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_artifact_recording.py +0 -0
  335. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_artifacts.py +0 -0
  336. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_bashwrites.py +0 -0
  337. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_cache.py +0 -0
  338. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_codexio.py +0 -0
  339. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_dataset.py +0 -0
  340. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_extract.py +0 -0
  341. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_glue.py +0 -0
  342. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_html.py +0 -0
  343. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_labeler.py +0 -0
  344. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_labeler_evidence_matrix.py +0 -0
  345. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_launch.py +0 -0
  346. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_ocp.py +0 -0
  347. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_render.py +0 -0
  348. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_runfile.py +0 -0
  349. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_graph_schema.py +0 -0
  350. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_home_guard.py +0 -0
  351. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_html.py +0 -0
  352. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_ingest.py +0 -0
  353. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_ingest_claude_code.py +0 -0
  354. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_ingest_codex.py +0 -0
  355. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_ingest_ocp.py +0 -0
  356. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_io.py +0 -0
  357. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_not_run_summary.py +0 -0
  358. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_ocp_conformance.py +0 -0
  359. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_ocp_golden.py +0 -0
  360. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_ocp_open_enums.py +0 -0
  361. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_ocp_versioning.py +0 -0
  362. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_output_html_path.py +0 -0
  363. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_packaging_metadata.py +0 -0
  364. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_packaging_smoke.py +0 -0
  365. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_pool.py +0 -0
  366. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_preview_script.py +0 -0
  367. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_price.py +0 -0
  368. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_receipts.py +0 -0
  369. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_release_paths.py +0 -0
  370. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_runfile_privacy_n1b.py +0 -0
  371. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_scoring.py +0 -0
  372. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_split_rebindings.py +0 -0
  373. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_surface.py +0 -0
  374. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_taskmodel_features.py +0 -0
  375. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_terminal.py +0 -0
  376. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_types_control.py +0 -0
  377. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_types_piece_prediction.py +0 -0
  378. {loopmath-0.2.2 → loopmath-0.2.3}/tests/test_v01_scaffold.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: loopmath
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Plan agent workflows, record how they went, and learn from your own Claude Code and Codex logs
5
5
  Author: QKV Labs
6
6
  License-Expression: MIT
@@ -103,6 +103,8 @@ Reading the history uses up to 8 worker processes (one per CPU, at most 8). Set
103
103
 
104
104
  loopmath ships with a prior built from our own sweeps and experiments, so `recommend` gives an answer before you have any history. Your own runs then move it.
105
105
 
106
+ The prior ships inside the package: our runs, in the shared form (no titles, paths, commands or free text), and the published benchmark results. They are the same files we fit with, and each release updates them. `onboard` and the results page say in one line which prior they start from, and `loopmath prior show` lists it source by source.
107
+
106
108
  ## The loop
107
109
 
108
110
  The plan and record skills take an agent through the loop in three commands:
@@ -65,6 +65,8 @@ Reading the history uses up to 8 worker processes (one per CPU, at most 8). Set
65
65
 
66
66
  loopmath ships with a prior built from our own sweeps and experiments, so `recommend` gives an answer before you have any history. Your own runs then move it.
67
67
 
68
+ The prior ships inside the package: our runs, in the shared form (no titles, paths, commands or free text), and the published benchmark results. They are the same files we fit with, and each release updates them. `onboard` and the results page say in one line which prior they start from, and `loopmath prior show` lists it source by source.
69
+
68
70
  ## The loop
69
71
 
70
72
  The plan and record skills take an agent through the loop in three commands:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "loopmath"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  description = "Plan agent workflows, record how they went, and learn from your own Claude Code and Codex logs"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -5,4 +5,4 @@ The command line (`loopmath`, or its alias `loop`) is the interface; see the
5
5
  README and `loopmath --help`.
6
6
  """
7
7
 
8
- __version__ = "0.2.2"
8
+ __version__ = "0.2.3"
@@ -464,10 +464,12 @@ def source_label(doc: dict) -> str:
464
464
  ext = run.get("ext") or {}
465
465
  share = ext.get("dev.loopmath.share")
466
466
  if isinstance(share, dict):
467
- # the importer writes `source` and `task.org` as `shared:<org_hash>` already: never prefix twice
467
+ # the importer writes `source` and `task.org` as `shared:<org_hash>` already: never prefix twice. With no
468
+ # org at all the source is `shared`, the name `fit --without shared` takes (0.2.3, 22X review N1)
468
469
  org = (share.get("source") or share.get("org") or share.get("org_hash") or (run.get("task") or {}).get("org")
469
- or "shared")
470
- return "shared:" + str(org).removeprefix("shared:")
470
+ or "")
471
+ name = str(org).removeprefix("shared:")
472
+ return f"shared:{name}" if name and name != "shared" else "shared"
471
473
  src = (run.get("task") or {}).get("source")
472
474
  kind = src.get("kind") if isinstance(src, dict) else src
473
475
  kind = str(kind or "").strip().lower()
@@ -526,7 +526,8 @@ def fit(home: Path, *, no_prior: bool = False, without: tuple[str, ...] = (), fu
526
526
  with fit_lock(home, wait_s):
527
527
  remove_partials(home)
528
528
  config = _read_config(home)
529
- weight = float(config.get("benchmark_prior_weight", prior_data.BENCHMARK_PRIOR_WEIGHT))
529
+ raw_weight = config.get("benchmark_prior_weight") # unset: each benchmark's own weight (spec 04 section 5)
530
+ weight = None if raw_weight is None else float(raw_weight)
530
531
  try:
531
532
  features, features_error = FeatureSet.from_config(config.get("features")), None
532
533
  except FeatureConfigError as exc: # a hand-edited config.toml: fit with the built-ins, say why
@@ -550,9 +551,10 @@ def fit(home: Path, *, no_prior: bool = False, without: tuple[str, ...] = (), fu
550
551
  raise UnknownSource(unknown_source_message(unknown, known))
551
552
  if not any(hr.rows for hr in heads_rows.values()):
552
553
  raise NothingToFit(_nothing_to_fit(no_prior, without, dropped))
553
- specs = []
554
+ specs, bench_weights = [], {}
554
555
  if not no_prior and "benchmark" not in without:
555
556
  specs = prior_data.benchmark_factors(benchmarks, weight=weight)
557
+ bench_weights = prior_data.benchmark_weights(benchmarks, weight=weight)
556
558
  seed_key = input_key(heads_rows, specs, {"no_prior": no_prior, "without": sorted(without), "eb": eb,
557
559
  "benchmark_prior_weight": weight})
558
560
  forest = Forest()
@@ -604,7 +606,7 @@ def fit(home: Path, *, no_prior: bool = False, without: tuple[str, ...] = (), fu
604
606
  "seed_key": seed_key, "timebox_effort": design_rows.TIMEBOX_EFFORT_COST,
605
607
  "timebox_terms": list(design_rows.TIMEBOX_LEVELS),
606
608
  "options": {"no_prior": no_prior, "without": list(without), "full": full, "eb": eb,
607
- "benchmark_prior_weight": weight},
609
+ "benchmark_prior_weight": weight, "benchmark_weights": bench_weights},
608
610
  "runs_by_source": runs_by_source,
609
611
  "n_runs": {"prior": sum(v for k, v in runs_by_source.items() if k != "user"),
610
612
  "user": runs_by_source.get("user", 0)},
@@ -10,8 +10,11 @@
10
10
  version nodes: success head, the logit gap to the benchmark's reference model with variance
11
11
  `1 / (w p (1 - p))`; cost head, the log cost ratio with variance `1 / w`; tokens head
12
12
  (`kind = "tokens"`, published total tokens for the evaluation), the log token ratio
13
- with variance `1 / w`. `w` is config `benchmark_prior_weight` (default 5): one benchmark
14
- result counts like about 5 runs.
13
+ with variance `1 / w`. `w` is one model's share of the benchmark's weight `w_b` (0.2.3,
14
+ lane 23K): the `weight` of its `[[benchmark]]` table (default 5, about 5 runs), shared by
15
+ the model's k results on that benchmark, so each gets `w_b / k` and a model with five
16
+ efforts pulls as hard in total as a model with one. Config `benchmark_prior_weight`, when
17
+ set, is one `w_b` for every benchmark; 0 turns the factors off.
15
18
  """
16
19
 
17
20
  from __future__ import annotations
@@ -91,8 +94,30 @@ def _model_terms(model: str, effort: str | None, sign: float) -> list[tuple[str,
91
94
  return terms
92
95
 
93
96
 
94
- def benchmark_factors(path: Path | None = None, *, weight: float = BENCHMARK_PRIOR_WEIGHT) -> list[FactorSpec]:
95
- """Prior factors from `benchmarks.toml`. A missing file gives no factors."""
97
+ def benchmark_weights(path: Path | None = None, *, weight: float | None = None) -> dict[str, float]:
98
+ """Each benchmark's weight `w_b`: `weight` for every benchmark when it is given (config
99
+ `benchmark_prior_weight`), else the benchmark's own `weight` field, else 5. Empty for a missing file."""
100
+ path = path or benchmark_path()
101
+ if not path.is_file():
102
+ return {}
103
+ data = tomllib.loads(path.read_text(encoding="utf-8"))
104
+ return {str(b["id"]): _weight_of(b, weight) for b in data.get("benchmark") or [] if b.get("id")}
105
+
106
+
107
+ def _weight_of(bench: dict, weight: float | None) -> float:
108
+ if weight is not None:
109
+ return float(weight)
110
+ own = bench.get("weight")
111
+ return float(own) if isinstance(own, (int, float)) and not isinstance(own, bool) else BENCHMARK_PRIOR_WEIGHT
112
+
113
+
114
+ def benchmark_factors(path: Path | None = None, *, weight: float | None = None) -> list[FactorSpec]:
115
+ """Prior factors from `benchmarks.toml`. A missing file gives no factors.
116
+
117
+ `weight` (config `benchmark_prior_weight`) overrides every benchmark's own weight; None reads
118
+ each benchmark's `weight`. A model's k results on one benchmark share its weight: each factor
119
+ has weight `w_b / k` (B1). A benchmark with weight 0 or less gives no factors.
120
+ """
96
121
  path = path or benchmark_path()
97
122
  if not path.is_file():
98
123
  return []
@@ -103,11 +128,15 @@ def benchmark_factors(path: Path | None = None, *, weight: float = BENCHMARK_PRI
103
128
  for bid, bench in benches.items():
104
129
  kind = str(bench.get("kind") or "success")
105
130
  ref = canonical_model_id(str(bench.get("reference") or ""))
131
+ w_b = _weight_of(bench, weight)
132
+ if w_b <= 0:
133
+ continue
106
134
  rows = [r for r in results if r["benchmark"] == bid]
107
135
  ref_rows = [r for r in rows if canonical_model_id(str(r["model"])) == ref]
108
136
  if not ref_rows:
109
137
  continue
110
138
  ref_value = float(ref_rows[0]["value"])
139
+ by_model: dict[str, list[tuple[str, list, float, dict]]] = {} # model -> (head, terms, mean, row) per result
111
140
  for r in rows:
112
141
  model = canonical_model_id(str(r["model"]))
113
142
  if model == ref:
@@ -117,14 +146,24 @@ def benchmark_factors(path: Path | None = None, *, weight: float = BENCHMARK_PRI
117
146
  terms = _cancel(terms)
118
147
  if not terms:
119
148
  continue
120
- note = f"{bid}: {model} {value} against {ref} {ref_value} ({r.get('url', '')}, {r.get('date', '')})"
121
149
  if kind == "success":
122
150
  p = min(max(value, 0.01), 0.99)
123
151
  p_ref = min(max(ref_value, 0.01), 0.99)
124
152
  gap = math.log(p / (1 - p)) - math.log(p_ref / (1 - p_ref))
125
- out.append(FactorSpec("success", terms, gap, 1.0 / (weight * p * (1 - p)), note))
153
+ by_model.setdefault(model, []).append(("success", terms, gap, r))
126
154
  elif kind in ("cost", "tokens") and value > 0 and ref_value > 0: # Tokens feed the tokens head only
127
- out.append(FactorSpec(kind, terms, math.log(value / ref_value), 1.0 / weight, note))
155
+ by_model.setdefault(model, []).append((kind, terms, math.log(value / ref_value), r))
156
+ for model, items in by_model.items():
157
+ w = w_b / len(items) # one budget per model and benchmark (B1)
158
+ share = f"weight {w_b:g} over {len(items)}" if len(items) > 1 else f"weight {w_b:g}"
159
+ for head, terms, mean, r in items:
160
+ note = (f"{bid}: {model} {float(r['value'])} against {ref} {ref_value} ({share}; "
161
+ f"{r.get('url', '')}, {r.get('date', '')})")
162
+ if head == "success":
163
+ p = min(max(float(r["value"]), 0.01), 0.99)
164
+ out.append(FactorSpec("success", terms, mean, 1.0 / (w * p * (1 - p)), note))
165
+ else:
166
+ out.append(FactorSpec(head, terms, mean, 1.0 / w, note))
128
167
  return out
129
168
 
130
169
 
@@ -792,10 +792,13 @@ class FitState:
792
792
  gate_pass=res[hg] if hg is not None else None, rounds=res[hr],
793
793
  cost_per_round=Money(usd=res[hpr[0]], tokens=res[hpr[1]]) if hpr else None)
794
794
  for piece, (hu, ht, hg, hr, hpr) in handles.items()}
795
+ # The typical run (0.2.3): the median of the same simulated runs, one per draw, the 80% range is read from
796
+ run_usd = dataclasses.replace(res[h_run[1]], median=float(np.median(rd.sim_usd)))
797
+ run_tokens = dataclasses.replace(res[h_run[2]], median=float(np.median(rd.sim_tokens)))
795
798
  pred = Prediction(
796
799
  config=cfg.id,
797
800
  p_success=res[h_run[0]],
798
- cost=Money(usd=res[h_run[1]], tokens=res[h_run[2]]),
801
+ cost=Money(usd=run_usd, tokens=run_tokens),
799
802
  ell=Money(usd=res[h_run[3]], tokens=res[h_run[4]]),
800
803
  rounds=res[h_run[5]],
801
804
  per_piece=per_piece,
@@ -137,7 +137,7 @@ def build_session(args: argparse.Namespace) -> tuple[Session | None, int]:
137
137
  rec = engine.recommend(belief, asked, rule, usual=usual, usual_from=usual_from, configs=configs,
138
138
  settings=settings, diff=C.diff_fn(), keep=[*(u.id for u in user),
139
139
  *(r.id for r in recorded)],
140
- **offered_kw(offered))
140
+ own_runs=storeread.own_runs(home), **offered_kw(offered))
141
141
  rec.task = task
142
142
  start = None
143
143
  if getattr(args, "start", None):
@@ -305,6 +305,17 @@ def candidate_entry(rec: Recommendation, c: Any) -> dict[str, Any]:
305
305
  "origin": c.origin, **rec.search_fields(c.config.id)}
306
306
 
307
307
 
308
+ def rescue_entry(session: Session, cfg: Configuration) -> dict[str, Any]:
309
+ """The rescue workflow as a candidate when the search did not offer it (22W N1, 0.2.3): predicted as a
310
+ candidate is, under the recommendation's task, rule and rescue, with origin `rescue`."""
311
+ rec = session.rec
312
+ bands: dict[str, Any] = {}
313
+ preds, medians = engine.predict_with_medians(session.belief, session.task, [cfg], session.rule, rec.rescue, bands)
314
+ view = with_numbers(rec, medians=medians, bands=bands)
315
+ return {"config": cfg.to_dict(), "label": rec.label(cfg), "numbers": numbers_of(view, preds[0]),
316
+ "origin": "rescue", **rec.search_fields(cfg.id)}
317
+
318
+
308
319
  def context_payload(session: Session) -> dict[str, Any]:
309
320
  """`GET /api/context` (spec 02, `builder`), built once per session."""
310
321
  if session.context is not None:
@@ -329,6 +340,10 @@ def context_payload(session: Session) -> dict[str, Any]:
329
340
  wanted.add(rec.rescue_config.id)
330
341
  top += [c for c in offer[TOP_CANDIDATES:]
331
342
  if c.config.id not in ids and (c.origin in KEEP_ORIGINS or c.config.id in wanted)]
343
+ candidates = [candidate_entry(rec, c) for c in top]
344
+ fix = rec.rescue_config
345
+ if fix is not None and fix.id not in retired and rec.by_id(fix.id) is None:
346
+ candidates.append(rescue_entry(session, fix))
332
347
  session.context = {
333
348
  "schema": SCHEMA,
334
349
  "task": C.task_block(rec.task, session.belief),
@@ -339,9 +354,10 @@ def context_payload(session: Session) -> dict[str, Any]:
339
354
  "rescue": core["rescue"],
340
355
  "reference": reference,
341
356
  "choices": choices,
342
- "candidates": [candidate_entry(rec, c) for c in top],
357
+ "candidates": candidates,
343
358
  "catalog": catalog(session),
344
359
  "start": session.start.to_dict() if session.start is not None else None,
360
+ "own_runs": rec.own_runs, # 0.2.3: the user's recorded runs; 0 leads each run cost with the typical run
345
361
  }
346
362
  return session.context
347
363
 
@@ -274,7 +274,11 @@ def _add_recording(sub) -> None:
274
274
  q.add_argument("key", nargs="?", default=None, metavar="KEY")
275
275
  _common(q)
276
276
  q.set_defaults(func=_lazy("loopmath.store.commands:config_get"))
277
- q = cs.add_parser("set", help="set one key")
277
+ q = cs.add_parser("set", help="set one key",
278
+ description="Sets one key in config.toml. benchmark_prior_weight is unset by default: each "
279
+ "benchmark in the shipped benchmarks.toml has its own weight, in runs, shared by "
280
+ "a model's results on it; a number here is one weight for every benchmark, and 0 "
281
+ "turns benchmark priors off.")
278
282
  q.add_argument("key", metavar="KEY")
279
283
  q.add_argument("value", metavar="VALUE")
280
284
  _common(q)
@@ -335,7 +339,7 @@ def _add_learning(sub) -> None:
335
339
  ps = p.add_subparsers(dest="prior_command", required=True)
336
340
  q = ps.add_parser("build", help="rebuild the packaged prior bundle from the sweep, E0 and RQ1 inputs")
337
341
  q.add_argument("--out", default=None, metavar="DIR", help="where to write the bundle (default: the packaged bundle folder, which it replaces)")
338
- q.add_argument("--sweep-dir", default=None, metavar="PATH", help="sweep results (default: LOOPMATH_SWEEP_DIR)")
342
+ q.add_argument("--sweep-dir", action="append", default=None, metavar="PATH", help="sweep results, one folder per batch; repeatable (default: LOOPMATH_SWEEP_DIR, one folder)")
339
343
  q.add_argument("--e0-corpus", default=None, metavar="PATH", help="E0 corpus (default: LOOPMATH_E0_CORPUS)")
340
344
  q.add_argument("--rq1-dir", default=None, metavar="PATH", help="RQ1 OCP documents (default: LOOPMATH_PRIOR_RQ1)")
341
345
  q.add_argument("--lanes-dir", default=None, metavar="PATH", help="build lane rows (default: LOOPMATH_PRIOR_LANES)")
@@ -31,6 +31,7 @@ from typing import Any, Callable
31
31
  from .. import output
32
32
  from ..output import EXIT_NOT_FOUND, EXIT_OK, EXIT_USER, emit_json, fail
33
33
  from .. import taskmodel
34
+ from ..priors.show import starting_prior
34
35
  from ..store.ids import since_days as since_window
35
36
  from ..taskmodel import LABEL_VERSION
36
37
  from . import history as H
@@ -124,6 +125,9 @@ def onboard(args: argparse.Namespace) -> int:
124
125
  # The one line printed even when stderr is captured: the wait that follows can be long.
125
126
  print(f"onboard: reading Claude Code and Codex history, {_window_words(since)}; "
126
127
  "a large history can take several minutes", file=sys.stderr, flush=True)
128
+ # Then, also when captured, what the answers start from, once (the skill shows this line to the user).
129
+ prior = starting_prior()
130
+ print(prior["line"], file=sys.stderr, flush=True)
127
131
  hist = deps.load_history(since_days, logs=deps.logs, progress=_progress, stage=_stage)
128
132
  now = deps.now()
129
133
  groups, before_window = H.in_window(H.group_sessions(hist.graph, hist.by_id), since_days, now=now)
@@ -160,6 +164,7 @@ def onboard(args: argparse.Namespace) -> int:
160
164
 
161
165
  payload: dict[str, Any] = {
162
166
  "dry_run": dry_run,
167
+ "prior": prior,
163
168
  "since": since,
164
169
  "since_days": round(since_days, 3),
165
170
  "window": _window(groups),
@@ -8,7 +8,9 @@ The read API for the belief model (lane 5):
8
8
  - `bundle_entries()`: the same documents as `(source, document)` pairs, so the fit
9
9
  knows where each run came from whatever its label says (spec 04 section 1).
10
10
  - `shipped_overlap(run_ids)` and `overlap_note(counts)`: how many of the user's runs
11
- are also in a shipped source; `run import`, `fit` and `status` say it once.
11
+ are also in a shipped source; `run import`, `fit` and `status` say it once. A
12
+ stored run and its shipped copy are matched on `run_id_of`, the run id less a
13
+ start stamp (`stable_run_id`), since the shipped rq1 ids lose theirs (23B).
12
14
  - `manifest()`, `sources()`, `bundle_dir()`: what the bundle holds and where.
13
15
 
14
16
  Reading never touches the network or the store; the bundle is package data.
@@ -18,6 +20,7 @@ from __future__ import annotations
18
20
 
19
21
  import gzip
20
22
  import json
23
+ import re
21
24
  from collections import Counter
22
25
  from pathlib import Path
23
26
  from typing import Iterable, Iterator
@@ -71,15 +74,33 @@ def bundle_docs(without: Iterable[str] = (), sources: Iterable[str] | None = Non
71
74
  yield doc
72
75
 
73
76
 
77
+ _STAMP = re.compile(r"-\d{8}-\d{6}(?=-|$)") # lane 10's run start, YYYYMMDD-HHMMSS local time
78
+
79
+
80
+ def stable_run_id(run_id: str) -> str:
81
+ """A run id less its `-YYYYMMDD-HHMMSS` start stamp; an id without one is unchanged.
82
+
83
+ The shipped rq1 runs carry lane 10's ids without the stamp (a real date and time
84
+ does not ship, 23B) while an RQ1 store keeps it, so a stored run and its shipped
85
+ copy compare on this key. It is the id itself, not a hash: the stamp space is
86
+ small enough that a hash of the stamped id would give the time away.
87
+ """
88
+ return _STAMP.sub("", run_id)
89
+
90
+
74
91
  def run_id_of(doc: dict) -> str:
75
- """The run id the fit keys on (`belief.design.parse_run`), read without parsing the run."""
92
+ """The key a stored run and its shipped copy are matched on, read without parsing the run.
93
+
94
+ The run id the fit keys on (`belief.design.parse_run`), less a start stamp
95
+ (`stable_run_id`); the fit and `shipped_overlap` both compare on it.
96
+ """
76
97
  run = doc.get("run") or {}
77
98
  task = run.get("task") or {}
78
- return str(run.get("id") or task.get("id") or (run.get("labels") or {}).get("task") or "unknown")
99
+ return stable_run_id(str(run.get("id") or task.get("id") or (run.get("labels") or {}).get("task") or "unknown"))
79
100
 
80
101
 
81
102
  def shipped_ids(directory: Path | None = None) -> dict[str, str]:
82
- """Run id to its shipped source, for every bundled run."""
103
+ """Run id (`run_id_of`) to its shipped source, for every bundled run."""
83
104
  out: dict[str, str] = {}
84
105
  for name, doc in bundle_entries(directory=directory):
85
106
  out.setdefault(run_id_of(doc), name)
@@ -89,10 +110,12 @@ def shipped_ids(directory: Path | None = None) -> dict[str, str]:
89
110
  def shipped_overlap(run_ids: Iterable[str], directory: Path | None = None) -> dict[str, int]:
90
111
  """How many of `run_ids` (the user's runs) are also in each shipped source.
91
112
 
92
- A fit uses the store's copy of such a run and leaves the shipped copy out.
113
+ A fit uses the store's copy of such a run and leaves the shipped copy out. The
114
+ ids compare as `run_id_of` does, without a start stamp.
93
115
  """
94
116
  ids = shipped_ids(directory)
95
- return dict(Counter(ids[r] for r in set(run_ids) if r in ids))
117
+ keys = [stable_run_id(r) for r in set(run_ids)]
118
+ return dict(Counter(ids[k] for k in keys if k in ids))
96
119
 
97
120
 
98
121
  def overlap_note(counts: dict[str, int] | None) -> str | None:
@@ -106,8 +129,8 @@ def overlap_note(counts: dict[str, int] | None) -> str | None:
106
129
  else:
107
130
  where = "the shipped prior (" + ", ".join(f"{k} {v}" for k, v in sorted(overlap.items(), key=lambda kv: -kv[1])) + ")"
108
131
  if total == 1:
109
- return f"1 of your runs is also in {where} (same run id): fits use your copy"
110
- return f"{total} of your runs are also in {where} (same run ids): fits use your copies"
132
+ return f"1 of your runs is also in {where} (same run): fits use your copy"
133
+ return f"{total} of your runs are also in {where} (same runs): fits use your copies"
111
134
 
112
135
 
113
136
  iter_runs = bundle_docs
@@ -1,11 +1,13 @@
1
1
  """Published benchmark results (lane 11): `priors/benchmarks.toml`.
2
2
 
3
3
  The file has `[[benchmark]]` tables (`id`, `title`, `metric`, `kind` success,
4
- cost or tokens, `reference` model, `reference_effort`, `harness`, `url`, `note`) and
4
+ cost or tokens, `reference` model, `reference_effort`, `weight`, `harness`, `url`, `note`) and
5
5
  `[[result]]` tables (`benchmark`, `model`, `effort`, `value`, `harness`, `date`,
6
6
  `url`, `note`). Lane 5's `belief.priors.benchmark_factors` turns them into prior
7
7
  factors on version nodes (spec 04 section 5); it reads the first result of the
8
8
  reference model as the reference, so that row is the one at `reference_effort`.
9
+ `weight` is the benchmark's weight in runs (5 when absent), shared by each model's
10
+ results on it (0.2.3, lane 23K; spec 04 section 5).
9
11
 
10
12
  This module loads the file and checks it: every value is a published number
11
13
  with its own source line, success values are fractions, the reference
@@ -49,6 +51,9 @@ def check_benchmarks(data: dict) -> list[str]:
49
51
  problems += [f"{where}: no {k}" for k in _BENCH_KEYS if not b.get(k)]
50
52
  if b.get("kind") and b["kind"] not in KINDS:
51
53
  problems.append(f"{where}: kind {b['kind']!r} is not one of {', '.join(KINDS)}")
54
+ if "weight" in b and (isinstance(b["weight"], bool) or not isinstance(b["weight"], (int, float))
55
+ or b["weight"] < 0):
56
+ problems.append(f"{where}: weight is not a number of 0 or more")
52
57
  if b.get("id") in benches:
53
58
  problems.append(f"{where}: duplicate id")
54
59
  benches[str(b.get("id"))] = b
@@ -3,8 +3,9 @@
3
3
  # design/0.1/data/benchmarks/artificialanalysis-2026-09-23.json (Terminal-Bench 4.0) and
4
4
  # artificialanalysis-2026-09-25.json (Terminal-Bench 2.1). Values are copied as published;
5
5
  # a missing cell stays missing. Lane 5's belief.priors.benchmark_factors reads this file: success
6
- # results become logit gaps to the reference model with variance 1 / (w p (1 - p)), w =
7
- # benchmark_prior_weight (default 5). The first result for the reference model is the reference.
6
+ # results become logit gaps to the reference model with variance 1 / (w p (1 - p)), w = the
7
+ # benchmark's weight over the model's k results on it (config benchmark_prior_weight, when set,
8
+ # replaces every weight). The first result for the reference model is the reference.
8
9
 
9
10
  [[benchmark]]
10
11
  id = "aa-terminal-bench-4.0"
@@ -13,6 +14,7 @@ metric = "pass@1 averaged over three repeats of 66 tasks, as a fraction"
13
14
  kind = "success"
14
15
  reference = "claude-opus-5"
15
16
  reference_effort = "max"
17
+ weight = 5.0
16
18
  harness = "mini-swe-agent (Artificial Analysis)"
17
19
  url = "https://artificialanalysis.ai/evaluations/terminalbench-4-0"
18
20
  note = "One harness for every model, so the gaps compare models rather than scaffolds. Variants without reasoning are left out (loopmath does not run them). Haiku 4.5 is the reasoning variant, which names no effort. Values are k of 198 task runs."
@@ -24,6 +26,7 @@ metric = "total tokens for the whole evaluation (66 tasks x 3 repeats): input (w
24
26
  kind = "tokens"
25
27
  reference = "claude-opus-5"
26
28
  reference_effort = "max"
29
+ weight = 5.0
27
30
  harness = "mini-swe-agent (Artificial Analysis)"
28
31
  url = "https://artificialanalysis.ai/evaluations/terminalbench-4-0"
29
32
  note = "D54: a log-ratio factor on the tokens head only, never converted to dollars. The same three streams for every model, so the ratio is like for like."
@@ -35,6 +38,7 @@ metric = "pass@1 averaged over three repeats of 89 tasks, as a fraction"
35
38
  kind = "success"
36
39
  reference = "claude-opus-5"
37
40
  reference_effort = "max"
41
+ weight = 5.0
38
42
  harness = "Terminus 2 (Artificial Analysis)"
39
43
  url = "https://artificialanalysis.ai/evaluations/terminalbench-2-1"
40
44
  note = "One harness for every model (Terminus 2, as the page says), so the gaps compare models rather than scaffolds. Variants without reasoning are left out. Haiku 4.5 is the reasoning variant, which names no effort. Values are k of 267 task runs. Artificial Analysis publishes no Terminal-Bench 2.1 result for claude-opus-5-5, gpt-6-sol or gpt-6-luna, and only the max effort for claude-sonnet-5 and claude-fable-5; those cells stay missing. The official Terminal-Bench 2.1 board mixes six harnesses and is left out (lane 22K)."
@@ -46,6 +50,7 @@ metric = "total tokens for the whole evaluation (89 tasks x 3 repeats): input (w
46
50
  kind = "tokens"
47
51
  reference = "claude-opus-5"
48
52
  reference_effort = "max"
53
+ weight = 5.0
49
54
  harness = "Terminus 2 (Artificial Analysis)"
50
55
  url = "https://artificialanalysis.ai/evaluations/terminalbench-2-1"
51
56
  note = "D54: a log-ratio factor on the tokens head only, never converted to dollars. The same three streams for every model, so the ratio is like for like. Only the variants the evaluation pages show carry token counts."