loopmath 0.2.7__tar.gz → 0.3.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 (408) hide show
  1. {loopmath-0.2.7/src/loopmath.egg-info → loopmath-0.3.0}/PKG-INFO +41 -3
  2. {loopmath-0.2.7 → loopmath-0.3.0}/README.md +40 -2
  3. {loopmath-0.2.7 → loopmath-0.3.0}/pyproject.toml +1 -1
  4. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/__init__.py +1 -1
  5. loopmath-0.3.0/src/loopmath/adapters/harness2.py +867 -0
  6. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/compose.py +53 -11
  7. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/design.py +58 -14
  8. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/features.py +2 -0
  9. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/fit.py +65 -16
  10. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/forest.py +5 -1
  11. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/lookahead.py +1 -1
  12. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/pricing.py +22 -3
  13. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/state.py +159 -73
  14. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/cli.py +23 -4
  15. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/cli_registry.py +115 -3
  16. loopmath-0.3.0/src/loopmath/compare/__init__.py +1016 -0
  17. loopmath-0.3.0/src/loopmath/compare/_thresholds.py +424 -0
  18. loopmath-0.3.0/src/loopmath/compare/calibrate.py +541 -0
  19. loopmath-0.3.0/src/loopmath/compare/calibration.py +78 -0
  20. loopmath-0.3.0/src/loopmath/compare/checks.py +303 -0
  21. loopmath-0.3.0/src/loopmath/compare/commands.py +307 -0
  22. loopmath-0.3.0/src/loopmath/compare/model.py +502 -0
  23. loopmath-0.3.0/src/loopmath/gate/__init__.py +12 -0
  24. loopmath-0.3.0/src/loopmath/gate/commands.py +181 -0
  25. loopmath-0.3.0/src/loopmath/gate/core.py +525 -0
  26. loopmath-0.3.0/src/loopmath/gate/inputs.py +259 -0
  27. loopmath-0.3.0/src/loopmath/harness/__init__.py +150 -0
  28. loopmath-0.3.0/src/loopmath/harness/layouts.py +318 -0
  29. loopmath-0.3.0/src/loopmath/harness_runs/__init__.py +16 -0
  30. loopmath-0.3.0/src/loopmath/harness_runs/commands.py +215 -0
  31. loopmath-0.3.0/src/loopmath/harness_runs/costs.py +59 -0
  32. loopmath-0.3.0/src/loopmath/harness_runs/ocp.py +285 -0
  33. loopmath-0.3.0/src/loopmath/harness_runs/rows.py +327 -0
  34. loopmath-0.3.0/src/loopmath/harness_runs/streams.py +179 -0
  35. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ingest/base.py +1 -0
  36. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/prices.toml +12 -2
  37. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/benchmarks.py +4 -4
  38. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/recommend/commands.py +35 -11
  39. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/recommend/storeread.py +14 -0
  40. loopmath-0.3.0/src/loopmath/recommend/variants.py +155 -0
  41. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/skill/skills/loopmath-plan-task/SKILL.md +2 -2
  42. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/commands.py +364 -35
  43. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/config.py +4 -2
  44. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/finish.py +43 -2
  45. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/home.py +13 -0
  46. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/record.py +18 -6
  47. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/estimates.js +1 -1
  48. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/posterior.py +15 -1
  49. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/runs.py +9 -0
  50. {loopmath-0.2.7 → loopmath-0.3.0/src/loopmath.egg-info}/PKG-INFO +41 -3
  51. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath.egg-info/SOURCES.txt +24 -1
  52. loopmath-0.3.0/tests/test_adapter_harness2.py +750 -0
  53. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_price.py +5 -5
  54. loopmath-0.3.0/tests/test_v028_sol_6_1.py +80 -0
  55. {loopmath-0.2.7 → loopmath-0.3.0}/LICENSE +0 -0
  56. {loopmath-0.2.7 → loopmath-0.3.0}/setup.cfg +0 -0
  57. {loopmath-0.2.7 → loopmath-0.3.0}/spec/ocp-v0.2.schema.json +0 -0
  58. {loopmath-0.2.7 → loopmath-0.3.0}/spec/ocp-v0.schema.json +0 -0
  59. {loopmath-0.2.7 → loopmath-0.3.0}/spec/ocp_conformance.py +0 -0
  60. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/__main__.py +0 -0
  61. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapter_host.py +0 -0
  62. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/__init__.py +0 -0
  63. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/atrium.py +0 -0
  64. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/base.py +0 -0
  65. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/bb.py +0 -0
  66. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/bb_support.py +0 -0
  67. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/omp.py +0 -0
  68. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/omp_facts.py +0 -0
  69. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/omp_links.py +0 -0
  70. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/omp_parse.py +0 -0
  71. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/omp_types.py +0 -0
  72. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/opencode.py +0 -0
  73. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/opencode_store.py +0 -0
  74. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/orca.py +0 -0
  75. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/otel_genai.py +0 -0
  76. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/otel_genai_graph.py +0 -0
  77. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/otel_genai_parse.py +0 -0
  78. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/otel_genai_types.py +0 -0
  79. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/otel_genai_usage.py +0 -0
  80. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/paseo.py +0 -0
  81. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/pi.py +0 -0
  82. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/pi_support.py +0 -0
  83. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/adapters/registry.py +0 -0
  84. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/__init__.py +0 -0
  85. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/block.py +0 -0
  86. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/check_pymc.py +0 -0
  87. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/commands.py +0 -0
  88. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/gaussian.py +0 -0
  89. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/outcome.py +0 -0
  90. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/priors.py +0 -0
  91. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/belief/rules.py +0 -0
  92. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/builder/__init__.py +0 -0
  93. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/builder/cli.py +0 -0
  94. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/builder/context.py +0 -0
  95. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/builder/predict.py +0 -0
  96. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/builder/server.py +0 -0
  97. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/cli_graph.py +0 -0
  98. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/cli_support.py +0 -0
  99. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/e0/__init__.py +0 -0
  100. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/e0/arms.py +0 -0
  101. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/e0/cli_e0.py +0 -0
  102. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/e0/estimate.py +0 -0
  103. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/e0/estimate_rework.py +0 -0
  104. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/e0/figures.py +0 -0
  105. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/e0/io.py +0 -0
  106. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/e0/verb.py +0 -0
  107. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/explain.py +0 -0
  108. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/fit.py +0 -0
  109. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/fit_assembly.py +0 -0
  110. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/fit_bayes.py +0 -0
  111. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/fit_masks.py +0 -0
  112. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/fit_predict.py +0 -0
  113. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/fit_pricing.py +0 -0
  114. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/fit_transfer.py +0 -0
  115. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/gaps.py +0 -0
  116. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/gitwalk.py +0 -0
  117. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/grade.py +0 -0
  118. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/grade_support.py +0 -0
  119. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/__init__.py +0 -0
  120. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/artifact_git.py +0 -0
  121. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/artifact_join.py +0 -0
  122. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/artifact_kinds.py +0 -0
  123. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/artifacts.py +0 -0
  124. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/bashparse.py +0 -0
  125. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/bashread_ops.py +0 -0
  126. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/bashwrite_ops.py +0 -0
  127. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/bashwrites.py +0 -0
  128. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/cache.py +0 -0
  129. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/codexio.py +0 -0
  130. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/codexio_parse.py +0 -0
  131. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/codexio_scan.py +0 -0
  132. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/dataset.py +0 -0
  133. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/dataset_build.py +0 -0
  134. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/dataset_core.py +0 -0
  135. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/dataset_edges.py +0 -0
  136. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/dataset_nodes.py +0 -0
  137. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/extract.py +0 -0
  138. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/html_common.py +0 -0
  139. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/html_costcurve.py +0 -0
  140. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/html_css.py +0 -0
  141. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/html_data.py +0 -0
  142. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/html_force.py +0 -0
  143. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/html_render.py +0 -0
  144. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/html_swimlanes.py +0 -0
  145. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler.py +0 -0
  146. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_cli.py +0 -0
  147. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_common.py +0 -0
  148. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_parse.py +0 -0
  149. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_pricing.py +0 -0
  150. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_prompt.py +0 -0
  151. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_prompt_build.py +0 -0
  152. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_prompt_dispatch.py +0 -0
  153. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_prompt_evidence.py +0 -0
  154. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_prompt_node.py +0 -0
  155. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_prompt_records.py +0 -0
  156. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_prompt_result.py +0 -0
  157. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_prompt_session.py +0 -0
  158. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_prompt_tools.py +0 -0
  159. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_prompt_validation.py +0 -0
  160. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_prompt_workflow.py +0 -0
  161. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_report.py +0 -0
  162. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labeler_score.py +0 -0
  163. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/labels.py +0 -0
  164. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/launch.py +0 -0
  165. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/launch_origin.py +0 -0
  166. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/ocp.py +0 -0
  167. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/ocp_emit.py +0 -0
  168. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/ocp_support.py +0 -0
  169. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/render.py +0 -0
  170. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/runfile.py +0 -0
  171. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/runfile_export.py +0 -0
  172. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/runfile_finish.py +0 -0
  173. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/scan.py +0 -0
  174. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/schema.py +0 -0
  175. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/graph/token_completeness.py +0 -0
  176. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ingest/__init__.py +0 -0
  177. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ingest/claude_code.py +0 -0
  178. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ingest/claude_code_support.py +0 -0
  179. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ingest/codex.py +0 -0
  180. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ingest/codex_support.py +0 -0
  181. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ingest/ocp.py +0 -0
  182. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ingest/ocp_analysis.py +0 -0
  183. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ingest/ocp_artifact.py +0 -0
  184. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ingest/ocp_common.py +0 -0
  185. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ingest/ocp_convert.py +0 -0
  186. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ingest/ocp_projection.py +0 -0
  187. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/logmatch/__init__.py +0 -0
  188. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/logmatch/artifacts.py +0 -0
  189. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/logmatch/clip.py +0 -0
  190. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/logmatch/codex_window.py +0 -0
  191. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/logmatch/costs.py +0 -0
  192. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/logmatch/match.py +0 -0
  193. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/logmatch/settle.py +0 -0
  194. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/logmatch/tariff.py +0 -0
  195. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/__init__.py +0 -0
  196. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/canonical.py +0 -0
  197. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/commands.py +0 -0
  198. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/conformance.py +0 -0
  199. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/contractv3.py +0 -0
  200. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/emit.py +0 -0
  201. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/graph_contract.py +0 -0
  202. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/membership.py +0 -0
  203. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/migrate.py +0 -0
  204. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/schema/ocp-v0.2.schema.json +0 -0
  205. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/schema/ocp-v0.3.schema.json +0 -0
  206. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/schema/ocp-v0.schema.json +0 -0
  207. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/ocp/version.py +0 -0
  208. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/onboard/__init__.py +0 -0
  209. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/onboard/commands.py +0 -0
  210. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/onboard/history.py +0 -0
  211. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/onboard/label.py +0 -0
  212. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/onboard/usual.py +0 -0
  213. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/output.py +0 -0
  214. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/pool.py +0 -0
  215. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/price.py +0 -0
  216. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/price_validation.py +0 -0
  217. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/__init__.py +0 -0
  218. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/benchmarks.toml +0 -0
  219. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/build.py +0 -0
  220. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/bundle/README.md +0 -0
  221. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/bundle/e0.jsonl.gz +0 -0
  222. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/bundle/lanes.jsonl.gz +0 -0
  223. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/bundle/manifest.json +0 -0
  224. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/bundle/rq1.jsonl.gz +0 -0
  225. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/bundle/sweep.jsonl.gz +0 -0
  226. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/commands.py +0 -0
  227. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/e0.py +0 -0
  228. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/history.py +0 -0
  229. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/lanes.py +0 -0
  230. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/ocpdoc.py +0 -0
  231. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/reduce.py +0 -0
  232. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/registry.py +0 -0
  233. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/rq1.py +0 -0
  234. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/show.py +0 -0
  235. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/sweep.py +0 -0
  236. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/priors/validate.py +0 -0
  237. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/receipts.py +0 -0
  238. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/recommend/__init__.py +0 -0
  239. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/recommend/backlog.py +0 -0
  240. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/recommend/curve.py +0 -0
  241. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/recommend/engine.py +0 -0
  242. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/recommend/gain.py +0 -0
  243. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/recommend/message.py +0 -0
  244. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/recommend/receipts.py +0 -0
  245. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/recommend/search.py +0 -0
  246. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/recommend/stats.py +0 -0
  247. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/report/__init__.py +0 -0
  248. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/report/eligibility.py +0 -0
  249. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/report/html.py +0 -0
  250. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/report/terminal.py +0 -0
  251. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/report/terminal_exclusions.py +0 -0
  252. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/report/terminal_format.py +0 -0
  253. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/report/terminal_read.py +0 -0
  254. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/research_defaults.py +0 -0
  255. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/research_paths.py +0 -0
  256. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/scoring.py +0 -0
  257. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/scoring_comparisons.py +0 -0
  258. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/scoring_predictive.py +0 -0
  259. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/share/__init__.py +0 -0
  260. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/share/commands.py +0 -0
  261. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/share/export.py +0 -0
  262. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/share/import_.py +0 -0
  263. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/skill/__init__.py +0 -0
  264. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/skill/commands.py +0 -0
  265. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/skill/doctor.py +0 -0
  266. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/skill/install.py +0 -0
  267. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/skill/skills/loopmath/SKILL.md +0 -0
  268. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/skill/skills/loopmath-import-runs/SKILL.md +0 -0
  269. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/skill/skills/loopmath-onboard/SKILL.md +0 -0
  270. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/skill/skills/loopmath-record-run/SKILL.md +0 -0
  271. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/skill/skills/loopmath-update-fit/SKILL.md +0 -0
  272. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/skill/skills/reference.md +0 -0
  273. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/__init__.py +0 -0
  274. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/budget.py +0 -0
  275. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/fitjob.py +0 -0
  276. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/ids.py +0 -0
  277. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/lock.py +0 -0
  278. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/report.py +0 -0
  279. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/rule_change.py +0 -0
  280. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/run_names.py +0 -0
  281. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/runs.py +0 -0
  282. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/status.py +0 -0
  283. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/store/verify.py +0 -0
  284. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/surface.py +0 -0
  285. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/surface_bootstrap.py +0 -0
  286. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/surface_estimation.py +0 -0
  287. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/surface_frame.py +0 -0
  288. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/surface_presentation.py +0 -0
  289. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/surface_support.py +0 -0
  290. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/taskmodel.py +0 -0
  291. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/types.py +0 -0
  292. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/__init__.py +0 -0
  293. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/README.md +0 -0
  294. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/base.css +0 -0
  295. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/builder.css +0 -0
  296. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/builder.html +0 -0
  297. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/builder.js +0 -0
  298. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/common.js +0 -0
  299. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/estimates.css +0 -0
  300. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/graph.css +0 -0
  301. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/graph.js +0 -0
  302. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/plans.css +0 -0
  303. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/plans.js +0 -0
  304. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/results.css +0 -0
  305. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/results.js +0 -0
  306. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/runs.js +0 -0
  307. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/viz.css +0 -0
  308. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/assets/viz.js +0 -0
  309. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/common.py +0 -0
  310. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/views/plans.py +0 -0
  311. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/__init__.py +0 -0
  312. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/candidates.py +0 -0
  313. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/catalog/best_of_n.toml +0 -0
  314. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/catalog/implement_review.toml +0 -0
  315. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/catalog/plan_implement.toml +0 -0
  316. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/catalog/plan_implement_review.toml +0 -0
  317. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/catalog/solo.toml +0 -0
  318. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/catalog/swarm.toml +0 -0
  319. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/commands.py +0 -0
  320. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/diff.py +0 -0
  321. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/format.py +0 -0
  322. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/graphview.py +0 -0
  323. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/ids.py +0 -0
  324. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/infer.py +0 -0
  325. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/models.py +0 -0
  326. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/ocp.py +0 -0
  327. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath/workflows/shapes.py +0 -0
  328. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath.egg-info/dependency_links.txt +0 -0
  329. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath.egg-info/entry_points.txt +0 -0
  330. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath.egg-info/requires.txt +0 -0
  331. {loopmath-0.2.7 → loopmath-0.3.0}/src/loopmath.egg-info/top_level.txt +0 -0
  332. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_adapter_atrium.py +0 -0
  333. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_adapter_bb.py +0 -0
  334. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_adapter_omp.py +0 -0
  335. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_adapter_opencode.py +0 -0
  336. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_adapter_opencode_output_tokens.py +0 -0
  337. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_adapter_orca.py +0 -0
  338. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_adapter_otel_genai.py +0 -0
  339. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_adapter_paseo.py +0 -0
  340. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_adapter_services.py +0 -0
  341. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_adapters.py +0 -0
  342. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_adapters_pi.py +0 -0
  343. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_analyze_cli.py +0 -0
  344. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_arms.py +0 -0
  345. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_cli_graph.py +0 -0
  346. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_cli_help_lists.py +0 -0
  347. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_cli_labeler.py +0 -0
  348. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_cli_main_module.py +0 -0
  349. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_cli_plan_hidden.py +0 -0
  350. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_cli_prices.py +0 -0
  351. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_cli_startup.py +0 -0
  352. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_color_proof.py +0 -0
  353. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_duplicate_guards.py +0 -0
  354. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_estimate.py +0 -0
  355. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_explain.py +0 -0
  356. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_fit.py +0 -0
  357. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_gaps.py +0 -0
  358. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_gitwalk.py +0 -0
  359. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_grade.py +0 -0
  360. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_artifact_recording.py +0 -0
  361. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_artifacts.py +0 -0
  362. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_bashwrites.py +0 -0
  363. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_cache.py +0 -0
  364. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_codexio.py +0 -0
  365. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_dataset.py +0 -0
  366. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_extract.py +0 -0
  367. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_glue.py +0 -0
  368. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_html.py +0 -0
  369. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_labeler.py +0 -0
  370. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_labeler_evidence_matrix.py +0 -0
  371. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_launch.py +0 -0
  372. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_ocp.py +0 -0
  373. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_render.py +0 -0
  374. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_runfile.py +0 -0
  375. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_graph_schema.py +0 -0
  376. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_home_guard.py +0 -0
  377. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_html.py +0 -0
  378. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_ingest.py +0 -0
  379. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_ingest_claude_code.py +0 -0
  380. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_ingest_codex.py +0 -0
  381. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_ingest_ocp.py +0 -0
  382. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_io.py +0 -0
  383. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_not_run_summary.py +0 -0
  384. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_ocp_conformance.py +0 -0
  385. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_ocp_golden.py +0 -0
  386. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_ocp_open_enums.py +0 -0
  387. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_ocp_versioning.py +0 -0
  388. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_output_html_path.py +0 -0
  389. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_packaging_metadata.py +0 -0
  390. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_packaging_smoke.py +0 -0
  391. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_pool.py +0 -0
  392. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_preview_script.py +0 -0
  393. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_receipts.py +0 -0
  394. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_release_paths.py +0 -0
  395. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_report_eligibility.py +0 -0
  396. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_research_cli.py +0 -0
  397. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_runfile_privacy_n1b.py +0 -0
  398. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_scoring.py +0 -0
  399. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_split_rebindings.py +0 -0
  400. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_starting_prior.py +0 -0
  401. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_surface.py +0 -0
  402. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_taskmodel_features.py +0 -0
  403. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_terminal.py +0 -0
  404. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_types_control.py +0 -0
  405. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_types_piece_prediction.py +0 -0
  406. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_v01_scaffold.py +0 -0
  407. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_v027_p3.py +0 -0
  408. {loopmath-0.2.7 → loopmath-0.3.0}/tests/test_v027_small_fixes.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: loopmath
3
- Version: 0.2.7
3
+ Version: 0.3.0
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
@@ -62,6 +62,8 @@ python3 -m venv .venv
62
62
  .venv/bin/python -m pip install -e .
63
63
  ```
64
64
 
65
+ Installing needs the network: pip, pipx and uv download the build backend (setuptools 77 or newer) and the dependencies (jsonschema, numpy, pandas, scipy), from a clone too, so `pip install --no-index -e .` fails offline.
66
+
65
67
  ## First run
66
68
 
67
69
  ```sh
@@ -153,7 +155,7 @@ A pair runs the goal workflow and an exploration pick from the same base commit,
153
155
 
154
156
  A run counts as a success when it is accepted under your rule. By default that means the task's tests pass. A run that `onboard` brought in from your logs, or that `run import` stored, with no tests verdict but a review or accepted verdict, is judged by the review rule instead: a success when its latest review or accepted verdict is accept, approve or pass. `loopmath runs` lists other finished runs such a verdict could settle, with the command that moves them to the review rule, `loopmath outcome --rule review RUN...`. `loopmath outcome --undo-rule RUN...` undoes that, restoring each run's rule as it was; naming that rule (`tests` when it had none) does too, unless the run's own rule was also named review. A review verdict on a reviewer's last attempt then counts twice: as the review gate's pass, and as the run's success. A rule can also be a score target: `loopmath recommend ... --target 'heldout_perf>=2400'` or `--target 'runtime_s<=200'` gives the expected score and the chance of reaching the target. Set standing rules and other options with `loopmath config set KEY VALUE` (`loopmath config get` lists every key, set or not, `config set` refuses a key loopmath does not read, and `loopmath config unset KEY` returns a key to its default), and the spending cap with `loopmath budget --usd X --period month`. Spend counts your runs and onboard's labelling calls; runs onboard brought in from your logs are shown apart and not counted. A run you record with `--source habit` counts.
155
157
 
156
- Runs recorded by another tool that writes OCP v0.3, such as an experiment runner, come in with `loopmath run import DIR --finish`: several files or a directory, with one refit at the end (`--no-fit` skips it). It says how many runs were new and how many were already in the store; importing finished runs into a store with no fit starts a fit. Runs in your store always count as yours, whatever source their documents name. `loopmath fit --without SOURCE` leaves out one shipped prior source, and `loopmath status` names the options of the current fit.
158
+ Runs recorded by another tool that writes OCP v0.3, such as an experiment runner, come in with `loopmath run import DIR --finish`: several files or a directory, with one refit at the end (`--no-fit` skips it). It says how many runs were new, unchanged or replaced; importing finished runs into a store with no fit starts a fit. Importing the same documents again changes nothing and keeps the outcomes you added since, and with `--finish` it finishes the runs left open (without it, the runs are stored open and it says to import again with `--finish`). A document whose run id is already in the store with different content is refused by name, with the fields that differ; `--replace` takes it and keeps the outcomes added after the import, and refuses a copy that would overwrite one. Runs in your store always count as yours, whatever source their documents name. `loopmath fit --without SOURCE` leaves out one shipped prior source, and `loopmath status` names the options of the current fit.
157
159
 
158
160
  ## The three views
159
161
 
@@ -179,7 +181,7 @@ The workflow builder is the one page that is served: `loopmath builder --type bu
179
181
  | OCP | `ocp` (validate, migrate) |
180
182
  | Log analysis | `analyze`, `graph`, `adapt`, `prices`, `validate-prices`, `scan` |
181
183
 
182
- Each command prints a short summary by default. With `--json`, it prints exactly one JSON object instead. Exit codes: 0 ok, 1 user error, 2 not found, 3 not implemented, 4 store locked, 5 no fit yet. For flags, `loopmath <command> --help` is the source of truth. Commands, pages and the `runs` table show times in your local time with the zone; the store and `--json` keep UTC. A cost under a cent shows one significant digit (`$0.004`), and an exact zero is `$0`.
184
+ Each command prints a short summary by default. With `--json`, it prints exactly one JSON object instead. One exception: `loopmath adapt harness2` and `adapt harness-runs` without `--out` print the run documents on stdout, one per line, so their `--json` summary goes to stderr. Exit codes: 0 ok, 1 user error, 2 not found, 3 not implemented, 4 store locked, 5 no fit yet. For flags, `loopmath <command> --help` is the source of truth. Commands, pages and the `runs` table show times in your local time with the zone; the store and `--json` keep UTC. A cost under a cent shows one significant digit (`$0.004`), and an exact zero is `$0`.
183
185
 
184
186
  A workflow is a TOML file. `loopmath workflows list` shows the catalog and yours, which live in `~/.loopmath/workflows/`. It also lists the shapes loopmath composes from catalog pieces, such as `team`; `loopmath workflows show team` says what one is and that `recommend` does not offer it. This one implements, then sends a rejected change back once or twice:
185
187
 
@@ -233,6 +235,42 @@ effort = "high"
233
235
 
234
236
  Check it with `loopmath workflows validate FILE`, compare it with `loopmath workflows diff implement_review FILE`, and pass it to `recommend --workflow FILE` to have it considered, or to `run start --workflow FILE --source user_edit` to record a run with its settings (`--set PIECE=HARNESS:MODEL:EFFORT` overrides a piece).
235
237
 
238
+ ## Harness parts
239
+
240
+ A run can record the harness it ran with: the prompt files, skills, plugins, MCP servers, hooks, sub-agents and commands in its working tree. loopmath stores a digest of those files and a list of named parts (`skill:pdf`, `mcp:github`, `hook:PostToolUse:Edit|Write`, `prompt:3f2a9c1d`), never a path, a hook command or an environment value. The fit then learns each part's effect on cost and success, as a change from its harness label.
241
+
242
+ - `loopmath run finish --harness auto` (or `run record --harness auto`) records the git working tree the run's attempts ran in; `--harness PATH` names a tree; `--harness none` records nothing. The default is `none`; `loopmath config set harness.record auto` makes `auto` the default, and the flag wins.
243
+ - `loopmath run import` keeps a record another tool wrote.
244
+ - `loopmath posterior --json` lists each part under `factors`, and `--level harness` shows the labels and their parts:
245
+
246
+ ```json
247
+ {"factor": "skill:pdf", "harness": "claude-code", "kind": "skill", "name": "pdf",
248
+ "node": "hfactor:claude-code|skill:pdf", "runs": 12,
249
+ "cost": {"mean": 0.87, "lo": 0.74, "hi": 1.02, "level": 0.8, "lo95": 0.68, "hi95": 1.11},
250
+ "success": {"mean": 4.1, "lo": -1.0, "hi": 9.0, "level": 0.8, "lo95": -3.6, "hi95": 11.5,
251
+ "log_odds": {"mean": 0.18, "lo": -0.04, "hi": 0.41, "level": 0.8, "lo95": -0.16, "hi95": 0.52},
252
+ "calibrated": false}}
253
+ ```
254
+
255
+ `cost` is the multiplier on an attempt's dollars when the part is present; `success` is percentage points.
256
+ - `loopmath recommend --harness-variants` prices the trees your runs used most, and `--harness PATH` prices one more, against the bare harness label on the same draws.
257
+
258
+ An estimate is the change when a named part is present, pooled over its versions. It is not the effect of one edit, and a part on every run cannot be told apart from its harness. The cost ranges met their stated coverage in simulation. **The success ranges did not:** they pull effects toward 0, and their 80% ranges held 60% of nonzero effects. So they are marked `calibrated: false`, and so are the success-side numbers of a priced variant. With no record anywhere, every number is what it was before. The record, the digest, the factor map and the limits are in [`spec/harness.md`](spec/harness.md).
259
+
260
+ ## Testing a harness change
261
+
262
+ These commands are for changing the harness your agents run with and finding out whether the change paid off.
263
+
264
+ - **Harness parts and `--harness`.** Record the tree each run used (`run finish --harness auto` or `PATH`), and the fit learns each named part's effect, as in the section above. `recommend --harness-variants` prices the trees your runs used on the configurations those runs used, and on the recommendation's own when their harness has data on the parts; `--harness PATH` prices one more tree. Where a tree is not priced, `not_priced` in `--json` says why. The record, the factor map and the limits are in [`spec/harness.md`](spec/harness.md).
265
+ - **`adapt harness-runs` and `adapt harness2`.** These bring in runs another tool made. `loopmath adapt harness-runs FILE --out DIR` reads a `loopmath.harness-runs/0.1` file, one JSON line per rollout, as an auto-research loop, a plugin eval suite or a hand A/B writes it. `loopmath adapt harness2 RUNS --out DIR` reads a harness2 runs folder. Then `loopmath run import DIR --finish` stores the runs. The row format, outcomes, costs and worked examples are in [`spec/harness-runs.md`](spec/harness-runs.md).
266
+ - **`check-change`.** It decides whether a change beats what it replaces, on paired runs:
267
+ - `check-change start --base LABEL|PATH --cand LABEL|PATH --n N` plans the pairs and each pair's arm order;
268
+ - `check-change status` gives the comparison, the verdict once there is one (adopt or reject) and the next pair worth running;
269
+ - `check-change from-runs --base-label SEL --cand-label SEL` compares finished runs already in the store, picked by a run label, a configuration id, a harness digest (a prefix of one digest will do) or `arm:NAME`.
270
+
271
+ `--rule` names what counts as accepted, and `loopmath check-change --help` lists the rest. A run with no dollar cost leaves the decision to the outcomes alone, and the cost reads unknown; a budget or `--objective cpar` then refuses, naming the runs without one.
272
+ - **`gate`.** For a loop that adopts changes on its own, it answers: adopt the candidate, reject it and keep the base, or replicate N more pairs first. `loopmath gate --base SEL --cand SEL` reads the finished runs in the store, or `--runs FILE` reads `loopmath.harness-runs/0.1` rows; an arm is a harness digest (`sha256:<hex>` or `digest:sha256:<hex>`, a prefix of one digest will do), a configuration id, or `arm=NAME` or `arm:NAME`; `check-change from-runs` takes the same forms. `--rule` takes the built-in rules or a rule defined under `[rules.NAME]` in the store's config, which the gate reads as `check-change` does, also with `--runs`. The comparison of the paired runs is `check-change`'s, and the gate adds the loop's policy to it: no adoption before `--r-min` pairs, looks at 1, 2, 4 and so on pairs up to `--r-max`, a `--floor` (the smallest gain worth adopting, 0 or more; under an acceptance rule it applies to the cut in cost per accepted result, a fraction, or to the gain in the chance of acceptance when a cost is unknown), and the dollars, `--budget-usd` for both arms (0 buys no further pair) and `--max-cost-ratio`. With no evidence, an arm that matches no run or a rule that scores no pair, it exits 1 and names the arms or the rules that are there. Both dollar flags need every run's cost and refuse, naming the runs without one; with neither flag, a run with no recorded cost leaves the decision to the outcomes alone, and the cost reads unknown, never $0. When nothing resolves within the cap or the budget, it keeps the base and says where it stopped. In Python, `loopmath.gate.decide(base_runs, cand_runs, GatePolicy(...))` gives the same answer and writes nothing; `loopmath gate --help` lists the rest.
273
+
236
274
  ## The store and privacy
237
275
 
238
276
  The store is `~/.loopmath`. Set `LOOPMATH_HOME` or pass `--home` to put it elsewhere; the log parse cache moves with it, to `cache/` inside the store, unless you set `LOOPMATH_CACHE_DIR`. It holds:
@@ -24,6 +24,8 @@ python3 -m venv .venv
24
24
  .venv/bin/python -m pip install -e .
25
25
  ```
26
26
 
27
+ Installing needs the network: pip, pipx and uv download the build backend (setuptools 77 or newer) and the dependencies (jsonschema, numpy, pandas, scipy), from a clone too, so `pip install --no-index -e .` fails offline.
28
+
27
29
  ## First run
28
30
 
29
31
  ```sh
@@ -115,7 +117,7 @@ A pair runs the goal workflow and an exploration pick from the same base commit,
115
117
 
116
118
  A run counts as a success when it is accepted under your rule. By default that means the task's tests pass. A run that `onboard` brought in from your logs, or that `run import` stored, with no tests verdict but a review or accepted verdict, is judged by the review rule instead: a success when its latest review or accepted verdict is accept, approve or pass. `loopmath runs` lists other finished runs such a verdict could settle, with the command that moves them to the review rule, `loopmath outcome --rule review RUN...`. `loopmath outcome --undo-rule RUN...` undoes that, restoring each run's rule as it was; naming that rule (`tests` when it had none) does too, unless the run's own rule was also named review. A review verdict on a reviewer's last attempt then counts twice: as the review gate's pass, and as the run's success. A rule can also be a score target: `loopmath recommend ... --target 'heldout_perf>=2400'` or `--target 'runtime_s<=200'` gives the expected score and the chance of reaching the target. Set standing rules and other options with `loopmath config set KEY VALUE` (`loopmath config get` lists every key, set or not, `config set` refuses a key loopmath does not read, and `loopmath config unset KEY` returns a key to its default), and the spending cap with `loopmath budget --usd X --period month`. Spend counts your runs and onboard's labelling calls; runs onboard brought in from your logs are shown apart and not counted. A run you record with `--source habit` counts.
117
119
 
118
- Runs recorded by another tool that writes OCP v0.3, such as an experiment runner, come in with `loopmath run import DIR --finish`: several files or a directory, with one refit at the end (`--no-fit` skips it). It says how many runs were new and how many were already in the store; importing finished runs into a store with no fit starts a fit. Runs in your store always count as yours, whatever source their documents name. `loopmath fit --without SOURCE` leaves out one shipped prior source, and `loopmath status` names the options of the current fit.
120
+ Runs recorded by another tool that writes OCP v0.3, such as an experiment runner, come in with `loopmath run import DIR --finish`: several files or a directory, with one refit at the end (`--no-fit` skips it). It says how many runs were new, unchanged or replaced; importing finished runs into a store with no fit starts a fit. Importing the same documents again changes nothing and keeps the outcomes you added since, and with `--finish` it finishes the runs left open (without it, the runs are stored open and it says to import again with `--finish`). A document whose run id is already in the store with different content is refused by name, with the fields that differ; `--replace` takes it and keeps the outcomes added after the import, and refuses a copy that would overwrite one. Runs in your store always count as yours, whatever source their documents name. `loopmath fit --without SOURCE` leaves out one shipped prior source, and `loopmath status` names the options of the current fit.
119
121
 
120
122
  ## The three views
121
123
 
@@ -141,7 +143,7 @@ The workflow builder is the one page that is served: `loopmath builder --type bu
141
143
  | OCP | `ocp` (validate, migrate) |
142
144
  | Log analysis | `analyze`, `graph`, `adapt`, `prices`, `validate-prices`, `scan` |
143
145
 
144
- Each command prints a short summary by default. With `--json`, it prints exactly one JSON object instead. Exit codes: 0 ok, 1 user error, 2 not found, 3 not implemented, 4 store locked, 5 no fit yet. For flags, `loopmath <command> --help` is the source of truth. Commands, pages and the `runs` table show times in your local time with the zone; the store and `--json` keep UTC. A cost under a cent shows one significant digit (`$0.004`), and an exact zero is `$0`.
146
+ Each command prints a short summary by default. With `--json`, it prints exactly one JSON object instead. One exception: `loopmath adapt harness2` and `adapt harness-runs` without `--out` print the run documents on stdout, one per line, so their `--json` summary goes to stderr. Exit codes: 0 ok, 1 user error, 2 not found, 3 not implemented, 4 store locked, 5 no fit yet. For flags, `loopmath <command> --help` is the source of truth. Commands, pages and the `runs` table show times in your local time with the zone; the store and `--json` keep UTC. A cost under a cent shows one significant digit (`$0.004`), and an exact zero is `$0`.
145
147
 
146
148
  A workflow is a TOML file. `loopmath workflows list` shows the catalog and yours, which live in `~/.loopmath/workflows/`. It also lists the shapes loopmath composes from catalog pieces, such as `team`; `loopmath workflows show team` says what one is and that `recommend` does not offer it. This one implements, then sends a rejected change back once or twice:
147
149
 
@@ -195,6 +197,42 @@ effort = "high"
195
197
 
196
198
  Check it with `loopmath workflows validate FILE`, compare it with `loopmath workflows diff implement_review FILE`, and pass it to `recommend --workflow FILE` to have it considered, or to `run start --workflow FILE --source user_edit` to record a run with its settings (`--set PIECE=HARNESS:MODEL:EFFORT` overrides a piece).
197
199
 
200
+ ## Harness parts
201
+
202
+ A run can record the harness it ran with: the prompt files, skills, plugins, MCP servers, hooks, sub-agents and commands in its working tree. loopmath stores a digest of those files and a list of named parts (`skill:pdf`, `mcp:github`, `hook:PostToolUse:Edit|Write`, `prompt:3f2a9c1d`), never a path, a hook command or an environment value. The fit then learns each part's effect on cost and success, as a change from its harness label.
203
+
204
+ - `loopmath run finish --harness auto` (or `run record --harness auto`) records the git working tree the run's attempts ran in; `--harness PATH` names a tree; `--harness none` records nothing. The default is `none`; `loopmath config set harness.record auto` makes `auto` the default, and the flag wins.
205
+ - `loopmath run import` keeps a record another tool wrote.
206
+ - `loopmath posterior --json` lists each part under `factors`, and `--level harness` shows the labels and their parts:
207
+
208
+ ```json
209
+ {"factor": "skill:pdf", "harness": "claude-code", "kind": "skill", "name": "pdf",
210
+ "node": "hfactor:claude-code|skill:pdf", "runs": 12,
211
+ "cost": {"mean": 0.87, "lo": 0.74, "hi": 1.02, "level": 0.8, "lo95": 0.68, "hi95": 1.11},
212
+ "success": {"mean": 4.1, "lo": -1.0, "hi": 9.0, "level": 0.8, "lo95": -3.6, "hi95": 11.5,
213
+ "log_odds": {"mean": 0.18, "lo": -0.04, "hi": 0.41, "level": 0.8, "lo95": -0.16, "hi95": 0.52},
214
+ "calibrated": false}}
215
+ ```
216
+
217
+ `cost` is the multiplier on an attempt's dollars when the part is present; `success` is percentage points.
218
+ - `loopmath recommend --harness-variants` prices the trees your runs used most, and `--harness PATH` prices one more, against the bare harness label on the same draws.
219
+
220
+ An estimate is the change when a named part is present, pooled over its versions. It is not the effect of one edit, and a part on every run cannot be told apart from its harness. The cost ranges met their stated coverage in simulation. **The success ranges did not:** they pull effects toward 0, and their 80% ranges held 60% of nonzero effects. So they are marked `calibrated: false`, and so are the success-side numbers of a priced variant. With no record anywhere, every number is what it was before. The record, the digest, the factor map and the limits are in [`spec/harness.md`](spec/harness.md).
221
+
222
+ ## Testing a harness change
223
+
224
+ These commands are for changing the harness your agents run with and finding out whether the change paid off.
225
+
226
+ - **Harness parts and `--harness`.** Record the tree each run used (`run finish --harness auto` or `PATH`), and the fit learns each named part's effect, as in the section above. `recommend --harness-variants` prices the trees your runs used on the configurations those runs used, and on the recommendation's own when their harness has data on the parts; `--harness PATH` prices one more tree. Where a tree is not priced, `not_priced` in `--json` says why. The record, the factor map and the limits are in [`spec/harness.md`](spec/harness.md).
227
+ - **`adapt harness-runs` and `adapt harness2`.** These bring in runs another tool made. `loopmath adapt harness-runs FILE --out DIR` reads a `loopmath.harness-runs/0.1` file, one JSON line per rollout, as an auto-research loop, a plugin eval suite or a hand A/B writes it. `loopmath adapt harness2 RUNS --out DIR` reads a harness2 runs folder. Then `loopmath run import DIR --finish` stores the runs. The row format, outcomes, costs and worked examples are in [`spec/harness-runs.md`](spec/harness-runs.md).
228
+ - **`check-change`.** It decides whether a change beats what it replaces, on paired runs:
229
+ - `check-change start --base LABEL|PATH --cand LABEL|PATH --n N` plans the pairs and each pair's arm order;
230
+ - `check-change status` gives the comparison, the verdict once there is one (adopt or reject) and the next pair worth running;
231
+ - `check-change from-runs --base-label SEL --cand-label SEL` compares finished runs already in the store, picked by a run label, a configuration id, a harness digest (a prefix of one digest will do) or `arm:NAME`.
232
+
233
+ `--rule` names what counts as accepted, and `loopmath check-change --help` lists the rest. A run with no dollar cost leaves the decision to the outcomes alone, and the cost reads unknown; a budget or `--objective cpar` then refuses, naming the runs without one.
234
+ - **`gate`.** For a loop that adopts changes on its own, it answers: adopt the candidate, reject it and keep the base, or replicate N more pairs first. `loopmath gate --base SEL --cand SEL` reads the finished runs in the store, or `--runs FILE` reads `loopmath.harness-runs/0.1` rows; an arm is a harness digest (`sha256:<hex>` or `digest:sha256:<hex>`, a prefix of one digest will do), a configuration id, or `arm=NAME` or `arm:NAME`; `check-change from-runs` takes the same forms. `--rule` takes the built-in rules or a rule defined under `[rules.NAME]` in the store's config, which the gate reads as `check-change` does, also with `--runs`. The comparison of the paired runs is `check-change`'s, and the gate adds the loop's policy to it: no adoption before `--r-min` pairs, looks at 1, 2, 4 and so on pairs up to `--r-max`, a `--floor` (the smallest gain worth adopting, 0 or more; under an acceptance rule it applies to the cut in cost per accepted result, a fraction, or to the gain in the chance of acceptance when a cost is unknown), and the dollars, `--budget-usd` for both arms (0 buys no further pair) and `--max-cost-ratio`. With no evidence, an arm that matches no run or a rule that scores no pair, it exits 1 and names the arms or the rules that are there. Both dollar flags need every run's cost and refuse, naming the runs without one; with neither flag, a run with no recorded cost leaves the decision to the outcomes alone, and the cost reads unknown, never $0. When nothing resolves within the cap or the budget, it keeps the base and says where it stopped. In Python, `loopmath.gate.decide(base_runs, cand_runs, GatePolicy(...))` gives the same answer and writes nothing; `loopmath gate --help` lists the rest.
235
+
198
236
  ## The store and privacy
199
237
 
200
238
  The store is `~/.loopmath`. Set `LOOPMATH_HOME` or pass `--home` to put it elsewhere; the log parse cache moves with it, to `cache/` inside the store, unless you set `LOOPMATH_CACHE_DIR`. It holds:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "loopmath"
7
- version = "0.2.7"
7
+ version = "0.3.0"
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.7"
8
+ __version__ = "0.3.0"