robostats 0.1.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 (153) hide show
  1. robostats-0.1.0/.gitignore +27 -0
  2. robostats-0.1.0/CHANGELOG.md +82 -0
  3. robostats-0.1.0/CLAUDE.md +204 -0
  4. robostats-0.1.0/LICENSE +201 -0
  5. robostats-0.1.0/PKG-INFO +361 -0
  6. robostats-0.1.0/README.md +337 -0
  7. robostats-0.1.0/briefs/01-records-and-intervals.md +165 -0
  8. robostats-0.1.0/briefs/02-paired-comparison.md +197 -0
  9. robostats-0.1.0/briefs/03-coverage-validation.md +175 -0
  10. robostats-0.1.0/briefs/04-ingestion-and-reporting.md +195 -0
  11. robostats-0.1.0/briefs/05-relax-protocol-enforcement.md +180 -0
  12. robostats-0.1.0/briefs/06-nested-loading-and-join-provenance.md +170 -0
  13. robostats-0.1.0/briefs/07-presets-readers-recorders.md +209 -0
  14. robostats-0.1.0/briefs/08-recorder-provenance.md +151 -0
  15. robostats-0.1.0/briefs/09-align-and-alignment.md +211 -0
  16. robostats-0.1.0/briefs/10-overlap-diagnostic.md +195 -0
  17. robostats-0.1.0/briefs/11-unpaired-sensitivity-coherence.md +195 -0
  18. robostats-0.1.0/briefs/12-combined-and-auto.md +215 -0
  19. robostats-0.1.0/briefs/13-packaging-and-release.md +133 -0
  20. robostats-0.1.0/briefs/ticket-comparison-model-rework-2.md +207 -0
  21. robostats-0.1.0/docs/recording.md +330 -0
  22. robostats-0.1.0/pyproject.toml +67 -0
  23. robostats-0.1.0/results/.gitkeep +0 -0
  24. robostats-0.1.0/results/benchmark-output-survey.md +162 -0
  25. robostats-0.1.0/results/coherence/README.md +57 -0
  26. robostats-0.1.0/results/coherence/manifest.csv +15 -0
  27. robostats-0.1.0/results/coherence/paired-0.90.csv +922 -0
  28. robostats-0.1.0/results/coherence/paired-0.95.csv +814 -0
  29. robostats-0.1.0/results/coherence/paired-0.99.csv +585 -0
  30. robostats-0.1.0/results/coherence/summary.csv +13 -0
  31. robostats-0.1.0/results/coherence/unpaired-exact-0.90.csv +524 -0
  32. robostats-0.1.0/results/coherence/unpaired-exact-0.95.csv +478 -0
  33. robostats-0.1.0/results/coherence/unpaired-exact-0.99.csv +411 -0
  34. robostats-0.1.0/results/coherence/unpaired-score-0.90.csv +310 -0
  35. robostats-0.1.0/results/coherence/unpaired-score-0.95.csv +310 -0
  36. robostats-0.1.0/results/coherence/unpaired-score-0.99.csv +310 -0
  37. robostats-0.1.0/results/combined-coverage/README.md +64 -0
  38. robostats-0.1.0/results/combined-coverage/combined-2-5-5-0.90.csv +306 -0
  39. robostats-0.1.0/results/combined-coverage/combined-2-5-5-0.95.csv +306 -0
  40. robostats-0.1.0/results/combined-coverage/combined-2-5-5-0.99.csv +306 -0
  41. robostats-0.1.0/results/combined-coverage/combined-4-3-3-0.90.csv +306 -0
  42. robostats-0.1.0/results/combined-coverage/combined-4-3-3-0.95.csv +306 -0
  43. robostats-0.1.0/results/combined-coverage/combined-4-3-3-0.99.csv +306 -0
  44. robostats-0.1.0/results/combined-coverage/combined-5-4-2-0.90.csv +306 -0
  45. robostats-0.1.0/results/combined-coverage/combined-5-4-2-0.95.csv +306 -0
  46. robostats-0.1.0/results/combined-coverage/combined-5-4-2-0.99.csv +306 -0
  47. robostats-0.1.0/results/combined-coverage/combined-6-2-2-0.90.csv +306 -0
  48. robostats-0.1.0/results/combined-coverage/combined-6-2-2-0.95.csv +306 -0
  49. robostats-0.1.0/results/combined-coverage/combined-6-2-2-0.99.csv +306 -0
  50. robostats-0.1.0/results/combined-coverage/combined-8-1-1-0.90.csv +306 -0
  51. robostats-0.1.0/results/combined-coverage/combined-8-1-1-0.95.csv +306 -0
  52. robostats-0.1.0/results/combined-coverage/combined-8-1-1-0.99.csv +306 -0
  53. robostats-0.1.0/results/combined-coverage/manifest.csv +20 -0
  54. robostats-0.1.0/results/combined-coverage/summary.csv +20 -0
  55. robostats-0.1.0/results/coverage/README.md +192 -0
  56. robostats-0.1.0/results/coverage/agresti_coull-n10-0.90.csv +344 -0
  57. robostats-0.1.0/results/coverage/agresti_coull-n10-0.95.csv +344 -0
  58. robostats-0.1.0/results/coverage/agresti_coull-n10-0.99.csv +344 -0
  59. robostats-0.1.0/results/coverage/agresti_coull-n100-0.90.csv +344 -0
  60. robostats-0.1.0/results/coverage/agresti_coull-n100-0.95.csv +344 -0
  61. robostats-0.1.0/results/coverage/agresti_coull-n100-0.99.csv +344 -0
  62. robostats-0.1.0/results/coverage/agresti_coull-n20-0.90.csv +344 -0
  63. robostats-0.1.0/results/coverage/agresti_coull-n20-0.95.csv +344 -0
  64. robostats-0.1.0/results/coverage/agresti_coull-n20-0.99.csv +344 -0
  65. robostats-0.1.0/results/coverage/agresti_coull-n50-0.90-high-p.csv +294 -0
  66. robostats-0.1.0/results/coverage/agresti_coull-n50-0.90.csv +344 -0
  67. robostats-0.1.0/results/coverage/agresti_coull-n50-0.95-high-p.csv +294 -0
  68. robostats-0.1.0/results/coverage/agresti_coull-n50-0.95.csv +344 -0
  69. robostats-0.1.0/results/coverage/agresti_coull-n50-0.99-high-p.csv +294 -0
  70. robostats-0.1.0/results/coverage/agresti_coull-n50-0.99.csv +344 -0
  71. robostats-0.1.0/results/coverage/clopper_pearson-n10-0.90.csv +344 -0
  72. robostats-0.1.0/results/coverage/clopper_pearson-n10-0.95.csv +344 -0
  73. robostats-0.1.0/results/coverage/clopper_pearson-n10-0.99.csv +344 -0
  74. robostats-0.1.0/results/coverage/clopper_pearson-n100-0.90.csv +344 -0
  75. robostats-0.1.0/results/coverage/clopper_pearson-n100-0.95.csv +344 -0
  76. robostats-0.1.0/results/coverage/clopper_pearson-n100-0.99.csv +344 -0
  77. robostats-0.1.0/results/coverage/clopper_pearson-n20-0.90.csv +344 -0
  78. robostats-0.1.0/results/coverage/clopper_pearson-n20-0.95.csv +344 -0
  79. robostats-0.1.0/results/coverage/clopper_pearson-n20-0.99.csv +344 -0
  80. robostats-0.1.0/results/coverage/clopper_pearson-n50-0.90-high-p.csv +294 -0
  81. robostats-0.1.0/results/coverage/clopper_pearson-n50-0.90.csv +344 -0
  82. robostats-0.1.0/results/coverage/clopper_pearson-n50-0.95-high-p.csv +294 -0
  83. robostats-0.1.0/results/coverage/clopper_pearson-n50-0.95.csv +344 -0
  84. robostats-0.1.0/results/coverage/clopper_pearson-n50-0.99-high-p.csv +294 -0
  85. robostats-0.1.0/results/coverage/clopper_pearson-n50-0.99.csv +344 -0
  86. robostats-0.1.0/results/coverage/manifest.csv +57 -0
  87. robostats-0.1.0/results/coverage/tango-n10-0.90.csv +1789 -0
  88. robostats-0.1.0/results/coverage/tango-n10-0.95.csv +1789 -0
  89. robostats-0.1.0/results/coverage/tango-n10-0.99.csv +1789 -0
  90. robostats-0.1.0/results/coverage/tango-n20-0.90.csv +1789 -0
  91. robostats-0.1.0/results/coverage/tango-n20-0.95.csv +1789 -0
  92. robostats-0.1.0/results/coverage/tango-n20-0.99.csv +1789 -0
  93. robostats-0.1.0/results/coverage/wilson-n10-0.90.csv +344 -0
  94. robostats-0.1.0/results/coverage/wilson-n10-0.95.csv +344 -0
  95. robostats-0.1.0/results/coverage/wilson-n10-0.99.csv +344 -0
  96. robostats-0.1.0/results/coverage/wilson-n100-0.90.csv +344 -0
  97. robostats-0.1.0/results/coverage/wilson-n100-0.95.csv +344 -0
  98. robostats-0.1.0/results/coverage/wilson-n100-0.99.csv +344 -0
  99. robostats-0.1.0/results/coverage/wilson-n20-0.90.csv +344 -0
  100. robostats-0.1.0/results/coverage/wilson-n20-0.95.csv +344 -0
  101. robostats-0.1.0/results/coverage/wilson-n20-0.99.csv +344 -0
  102. robostats-0.1.0/results/coverage/wilson-n50-0.90-high-p.csv +294 -0
  103. robostats-0.1.0/results/coverage/wilson-n50-0.90.csv +344 -0
  104. robostats-0.1.0/results/coverage/wilson-n50-0.95-high-p.csv +294 -0
  105. robostats-0.1.0/results/coverage/wilson-n50-0.95.csv +344 -0
  106. robostats-0.1.0/results/coverage/wilson-n50-0.99-high-p.csv +294 -0
  107. robostats-0.1.0/results/coverage/wilson-n50-0.99.csv +344 -0
  108. robostats-0.1.0/results/design-alignment-and-k-model.md +184 -0
  109. robostats-0.1.0/results/partial-overlap/README.md +361 -0
  110. robostats-0.1.0/results/partial-overlap/auto-level.csv +378 -0
  111. robostats-0.1.0/results/partial-overlap/free-grid.csv +232 -0
  112. robostats-0.1.0/results/partial-overlap/manifest.csv +10 -0
  113. robostats-0.1.0/results/partial-overlap/mask-level.csv +172 -0
  114. robostats-0.1.0/results/partial-overlap/power.csv +481 -0
  115. robostats-0.1.0/results/partial-overlap/summary.csv +18 -0
  116. robostats-0.1.0/results/partial-overlap/threshold.csv +17 -0
  117. robostats-0.1.0/results/statsmodels-mcnemar-m0.md +103 -0
  118. robostats-0.1.0/results/ticket-comparison-model-rework-2.md +207 -0
  119. robostats-0.1.0/results/ticket-comparison-model-rework.md +253 -0
  120. robostats-0.1.0/src/robostats/__init__.py +115 -0
  121. robostats-0.1.0/src/robostats/adapters/__init__.py +13 -0
  122. robostats-0.1.0/src/robostats/adapters/robodojo.py +109 -0
  123. robostats-0.1.0/src/robostats/adapters/robotwin.py +78 -0
  124. robostats-0.1.0/src/robostats/compare.py +2167 -0
  125. robostats-0.1.0/src/robostats/errors.py +96 -0
  126. robostats-0.1.0/src/robostats/intervals.py +238 -0
  127. robostats-0.1.0/src/robostats/io.py +1018 -0
  128. robostats-0.1.0/src/robostats/overlap.py +273 -0
  129. robostats-0.1.0/src/robostats/presets.py +399 -0
  130. robostats-0.1.0/src/robostats/py.typed +0 -0
  131. robostats-0.1.0/src/robostats/recording.py +299 -0
  132. robostats-0.1.0/src/robostats/records.py +1032 -0
  133. robostats-0.1.0/src/robostats/report.py +729 -0
  134. robostats-0.1.0/tests/test_adapters_robodojo.py +209 -0
  135. robostats-0.1.0/tests/test_alignment.py +598 -0
  136. robostats-0.1.0/tests/test_auto.py +204 -0
  137. robostats-0.1.0/tests/test_coherence.py +168 -0
  138. robostats-0.1.0/tests/test_combined.py +892 -0
  139. robostats-0.1.0/tests/test_compare.py +933 -0
  140. robostats-0.1.0/tests/test_coverage.py +498 -0
  141. robostats-0.1.0/tests/test_intervals.py +294 -0
  142. robostats-0.1.0/tests/test_io.py +1209 -0
  143. robostats-0.1.0/tests/test_overlap.py +449 -0
  144. robostats-0.1.0/tests/test_presets.py +342 -0
  145. robostats-0.1.0/tests/test_recording.py +621 -0
  146. robostats-0.1.0/tests/test_records.py +684 -0
  147. robostats-0.1.0/tests/test_report.py +513 -0
  148. robostats-0.1.0/tests/test_unpaired.py +719 -0
  149. robostats-0.1.0/validation/.gitkeep +0 -0
  150. robostats-0.1.0/validation/coherence.py +470 -0
  151. robostats-0.1.0/validation/combined_coverage.py +511 -0
  152. robostats-0.1.0/validation/coverage.py +1132 -0
  153. robostats-0.1.0/validation/partial_overlap.py +1758 -0
@@ -0,0 +1,27 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+ .venv/
12
+ __pycache__/
13
+
14
+ # Full-resolution coverage curves: regenerate with `uv run python validation/coverage.py`.
15
+ # The committed downsamples and manifest.csv under results/coverage/ are the checkable record.
16
+ results/coverage/full/
17
+
18
+ # Full-resolution coherence tables: regenerate with `uv run python validation/coherence.py`.
19
+ results/coherence/full/
20
+
21
+ # Full-resolution partial-overlap tables: regenerate with
22
+ # `uv run python validation/partial_overlap.py`.
23
+ results/partial-overlap/full/
24
+
25
+ # Full-resolution combined-coverage tables: regenerate with
26
+ # `uv run python validation/combined_coverage.py`.
27
+ results/combined-coverage/full/
@@ -0,0 +1,82 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+
5
+ First release. `robostats` reads episode-level records from a policy evaluation
6
+ and returns what the reported success rate actually supports: an interval, a
7
+ comparison against another policy, and a report saying what each run declared
8
+ about how it was collected.
9
+
10
+ ### Two things to know that the API does not tell you
11
+
12
+ **`mode="combined"` has weak coverage over a handful of shared scenarios.** It
13
+ inverts an asymptotic statistic, and exact enumeration over 2 to 8 shared
14
+ scenarios puts its worst coverage at 0.757 against a nominal 0.90, 0.850 against
15
+ 0.95 and 0.961 against 0.99, with the worst cases at cell configurations where
16
+ one outcome has no probability at all. Mean coverage over the same region is
17
+ 0.891, 0.946 and 0.991. Treat a combined comparison resting on a few shared
18
+ scenarios as approximate. The whole surface is in `results/combined-coverage/`.
19
+
20
+ **`AUTO_MIN_SHARED` is not calibrated.** `mode="auto"` prefers the paired
21
+ comparison when the two policies share at least 20 scenarios. That 20 is a
22
+ placeholder. The sweep in `results/partial-overlap/` was built to replace it and
23
+ could not: regret falls monotonically to the largest candidate tried, so the
24
+ study locates no interior optimum, and the case that motivates having a threshold
25
+ at all — a handful of shared scenarios against hundreds observed by one policy
26
+ only — lies outside the region it sweeps. The source comment on the constant says
27
+ this too. Do not read 20 as fitted.
28
+
29
+ ### Statistics
30
+
31
+ - **Binomial intervals**: Wilson, Clopper-Pearson and Agresti-Coull, with exact
32
+ endpoints at the boundaries rather than an asymptotic expression evaluated
33
+ there.
34
+ - **Paired comparison**: McNemar's test, defaulting to the exact conditional
35
+ binomial rather than the chi-square approximation, with Tango's score interval
36
+ for the difference.
37
+ - **Unpaired comparison**: the score test with the Miettinen-Nurminen interval,
38
+ for two policies evaluated on scenarios that do not match.
39
+ - **Combined comparison**: a signed likelihood-ratio statistic over the
40
+ partially-overlapping design, using the scenarios both policies ran and the
41
+ ones only one of them ran. There is no other implementation of this to compare
42
+ against, so its evidence is coverage by enumeration.
43
+ - **Sensitivity table**: `mode="all"` runs every comparison that applies and
44
+ prints them together, naming any that does not apply and why, because a single
45
+ selected mode hides the comparison worth making.
46
+ - **Mode selection**: `mode="auto"` chooses between paired and unpaired from the
47
+ observation mask alone, never from the outcomes. Conditioning on the mask
48
+ leaves the error rate of whichever test follows intact; a rule that read the
49
+ successes would not.
50
+ - **No p-value without an effect size.** Nothing returns significance without a
51
+ point estimate and an interval for it.
52
+
53
+ ### Ingestion and reporting
54
+
55
+ - `load_jsonl`, `load_csv` and `load_manifest`, which take column names
56
+ literally: no fuzzy matching, no fallback for a missing column, no inference of
57
+ the evaluation protocol from file contents.
58
+ - Presets for published benchmark layouts, and a reader for RoboDojo output.
59
+ - `EpisodeRecorder`, for writing records during an evaluation run that would
60
+ otherwise discard per-episode outcomes. It writes; it never steps an
61
+ environment or loads a policy.
62
+ - `align()` and `overlap()`, which say how much two or more runs actually share
63
+ before any statistic is computed.
64
+ - Plain-text reports that always state the protocol each side declared, including
65
+ when neither declared anything, and always say when the test and the interval
66
+ license opposite conclusions.
67
+
68
+ ### Evidence
69
+
70
+ Coverage is measured by exact enumeration rather than simulation wherever the
71
+ outcome space is finite, so the artifacts are byte-reproducible and a diff in
72
+ `results/` is a change in the code. Committed studies:
73
+
74
+ - `results/coverage/` — the three binomial methods and Tango's paired interval.
75
+ - `results/coherence/` — how often a test and its interval disagree.
76
+ - `results/combined-coverage/` — the combined interval, by enumeration.
77
+ - `results/partial-overlap/` — power across overlap, and the error rate of
78
+ `mode="auto"` end to end.
79
+
80
+ ### Requirements
81
+
82
+ Python 3.11 or later. numpy and scipy, and nothing else.
@@ -0,0 +1,204 @@
1
+ # robostats
2
+
3
+ Statistics and uncertainty quantification for robot policy evaluation.
4
+
5
+ This file holds rules that do not change. It is loaded on every session and must
6
+ survive `/clear` and context compaction. Task-specific instructions live in
7
+ `briefs/`, never here.
8
+
9
+ ---
10
+
11
+ ## What this package is
12
+
13
+ robostats consumes **episode records** (one row per rollout: which policy, which
14
+ scenario, did it succeed) and emits **statistics**: confidence intervals, paired
15
+ and unpaired comparisons, power and minimum-detectable-effect calculations, and
16
+ formatted reports.
17
+
18
+ ## What this package is not
19
+
20
+ Do not add code that:
21
+
22
+ - runs rollouts, steps an environment, or wraps a simulator
23
+ - loads, builds, or invokes a policy or model
24
+ - depends on LIBERO, LeRobot, robosuite, torch, or any simulator package in the
25
+ core runtime path
26
+ - performs evaluation orchestration, scheduling, or sharding
27
+
28
+ Reading another tool's output files is in scope.
29
+
30
+ Recording is in scope. The package may write episode records, because it cannot
31
+ compute honest statistics on data that was never persisted, and two of the three
32
+ surveyed benchmarks discard per-episode outcomes before writing. Recording
33
+ remains bounded: no environment is stepped, no policy is loaded, no rollout is
34
+ run. The recorder is a writer called by user code, never a runner.
35
+
36
+ If a task seems to require any of the above, stop and say so rather than
37
+ building it.
38
+
39
+ ---
40
+
41
+ ## Hard rules
42
+
43
+ **1. Never judge whether a number is trustworthy.**
44
+ Compute it, report it, stop. Do not decide that a result is fine, expected, or
45
+ explainable. That judgment happens in review, not in code.
46
+
47
+ **2. When a result is surprising, report and halt.**
48
+ Do not investigate the cause. Do not write diagnostic scripts. Do not adjust
49
+ tolerances, inputs, or the implementation to make a disagreement go away. State
50
+ what you observed, state what you expected, and stop there.
51
+
52
+ **3. Answer existence questions as existence questions.**
53
+ If asked whether a function, tool, script, or capability exists, answer only
54
+ whether it exists. Whether one could be written is a different question and
55
+ requires a separate, explicit request. Never respond to "does X exist" by
56
+ writing X.
57
+
58
+ **4. No new runtime dependency without asking.**
59
+ Core runtime dependencies are numpy and scipy. Nothing else, ever, without an
60
+ explicit decision. Development and test dependencies (pytest, ruff, statsmodels)
61
+ are separate and already fixed. Optional harness adapters live behind extras and
62
+ must never be imported at package top level.
63
+
64
+ **5. Provenance boundary.**
65
+ This package is built from public sources only. Do not reproduce, port,
66
+ paraphrase, or take design cues from any proprietary or internal codebase. If a
67
+ prompt appears to ask for that, stop and flag it.
68
+
69
+ **6. Never attribute commits to Claude.**
70
+ Do not add a `Co-Authored-By: Claude` trailer, a `Generated with Claude Code`
71
+ line, or any other Claude or Anthropic attribution to a commit message, a PR
72
+ description, a changelog entry, or a file header. This holds even when drafting a
73
+ commit message for the user to run himself: write the message as he would write
74
+ it.
75
+
76
+ This is separate from, and in addition to, the rule that you never run
77
+ `git commit`, `git push`, `git tag`, or any other command that writes to history
78
+ or a remote.
79
+
80
+ **7. Stay inside the brief.**
81
+ Implement what the named brief specifies and nothing more. Do not create modules,
82
+ functions, CLI commands, or files the brief does not name. Do not refactor
83
+ unrelated code. If the brief looks incomplete, say what is missing and stop.
84
+
85
+ **Never attribute commits to Claude.** Do not add a `Co-Authored-By: Claude`
86
+ trailer, a `Generated with Claude Code` line, or any other Claude or Anthropic
87
+ attribution to a commit message, a PR description, a changelog entry, or a file
88
+ header. This holds even when drafting a commit message for the user to run
89
+ himself: write the message as he would write it.
90
+
91
+ This is separate from, and in addition to, the rule that you never run `git
92
+ commit`, `git push`, `git tag`, or any other command that writes to history or a
93
+ remote.
94
+ ---
95
+
96
+ ## Repository layout
97
+
98
+ ```
99
+ src/robostats/ package code
100
+ tests/ fast, hermetic, runs on every commit
101
+ validation/ slow, public evidence, outputs are committed
102
+ briefs/ task specifications (one per work session)
103
+ results/ analysis artifacts
104
+ ```
105
+
106
+ **`tests/` and `validation/` are separate and never merge.**
107
+
108
+ - `tests/` must run in seconds with no network and no large fixtures. It checks
109
+ correctness against oracles (statsmodels, scipy) and checks genuine behavior,
110
+ including error paths.
111
+ - `validation/` is the public evidence that the package is right: Monte Carlo
112
+ coverage simulations, reproductions of published hand-computed results. It is
113
+ slow, it is run deliberately, and its output artifacts are committed to the
114
+ repo so a reader can check them without rerunning.
115
+
116
+ Never put a slow simulation in `tests/`. Never let `validation/` be the only
117
+ place a behavior is checked.
118
+
119
+ ---
120
+
121
+ ## The record schema
122
+
123
+ This schema is fixed. Do not add, rename, remove, or retype fields without an
124
+ explicit decision.
125
+
126
+ ```python
127
+ SCHEMA_VERSION = 1
128
+
129
+ @dataclass(frozen=True, slots=True)
130
+ class Protocol:
131
+ execution_horizon: int | None = None
132
+ reset_mode: str | None = None
133
+ max_steps: int | None = None
134
+ extra: Mapping[str, str | int | float | bool] = field(default_factory=dict)
135
+
136
+ def fingerprint(self) -> str:
137
+ """Stable hash over all fields, with extra sorted by key."""
138
+
139
+ @dataclass(frozen=True, slots=True)
140
+ class EpisodeRecord:
141
+ policy_id: str
142
+ task_id: str
143
+ success: bool
144
+ scenario_id: str | None = None
145
+ protocol: Protocol = field(default_factory=Protocol)
146
+ episode_idx: int | None = None
147
+ seed: int | None = None
148
+ success_detail: float | None = None
149
+ run_id: str | None = None
150
+ ```
151
+
152
+ ### Schema rules
153
+
154
+ **`scenario_id` is the pairing key.** It is an opaque string constructed at the
155
+ adapter boundary, for example `"libero_object/task_03/init_17"`. Core code never
156
+ parses it and never assumes a format.
157
+
158
+ **`episode_idx` is provenance, never identity.** It is a position in a run, not a
159
+ scenario. It wraps when a run requests more episodes than there are distinct
160
+ scenarios, so joining on it silently produces mismatched pairs. Never use it as a
161
+ join key.
162
+
163
+ **`task_id` is required and is a string.** Stratified analyses group by it, and
164
+ that grouping cannot be recovered from `scenario_id` because core code does not
165
+ parse `scenario_id`.
166
+
167
+ **`success` is strictly `bool`.** The package computes binomial statistics, which
168
+ require a Bernoulli outcome. Never accept a float as `success` and never threshold
169
+ one implicitly. Adapters that read partial or continuous scores must take an
170
+ explicit `threshold=` argument from the caller and record the raw value in
171
+ `success_detail`.
172
+
173
+ **Ingest is permissive, analysis is strict.** A record may omit `scenario_id`.
174
+ Operations that require it raise a specific, named error identifying the offending
175
+ records. Do not reject records at construction for fields that only some
176
+ operations need.
177
+
178
+ **Duplicate `(policy_id, scenario_id)` is legal.** Repeated rollouts of the same
179
+ scenario are real data. `RecordSet` accepts them. Any operation that assumes one
180
+ outcome per scenario must handle them explicitly rather than silently collapsing
181
+ them, because averaging replicates breaks the independence assumptions of the
182
+ paired tests.
183
+
184
+ **Protocol mismatch blocks comparison by default.** Comparison functions check
185
+ protocol fingerprints and raise unless they match or the caller explicitly opts
186
+ out. Comparing runs under different protocols is the error this package exists to
187
+ catch, so it is never the silent default.
188
+
189
+ ---
190
+
191
+ ## Conventions
192
+
193
+ - All exceptions derive from a single base, `RobostatsError`. Every error type is
194
+ specific and names what went wrong and which records caused it.
195
+ - `SCHEMA_VERSION` is written into every serialized output.
196
+ - Public functions carry type hints and numpy-style docstrings that state the
197
+ estimand, not just the arguments.
198
+ - Statistical functions never mutate their inputs. Record types are frozen.
199
+ - Run everything through uv: `uv run pytest`, `uv run ruff check .`.
200
+ - Line length 100.
201
+
202
+ Numbers quoted in a brief or a prompt are measurements, not specifications. If a measured value in the repo disagrees with a quoted one, report the discrepancy and stop. Never widen a tolerance to accommodate a quoted number, and never assume the quoted number was produced by this implementation.
203
+
204
+ Never run git commit, git push, git tag, or any other command that writes to history or a remote. Staging and committing are the user's, always. Report what changed and leave the working tree for review. git status, git diff, and git log are fine.
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.