equiframe-benchmark 0.12.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- equiframe_benchmark/PROTOCOL_V2.md +172 -0
- equiframe_benchmark/__init__.py +284 -0
- equiframe_benchmark/__main__.py +3 -0
- equiframe_benchmark/_scale_workload.py +375 -0
- equiframe_benchmark/calibration_types.py +112 -0
- equiframe_benchmark/cli.py +196 -0
- equiframe_benchmark/commands.py +149 -0
- equiframe_benchmark/commands_scale.py +38 -0
- equiframe_benchmark/commands_step10.py +275 -0
- equiframe_benchmark/commands_v2.py +206 -0
- equiframe_benchmark/cost_table.py +62 -0
- equiframe_benchmark/costs.py +788 -0
- equiframe_benchmark/distribution.py +932 -0
- equiframe_benchmark/evaluation.py +614 -0
- equiframe_benchmark/evaluation_v2.py +428 -0
- equiframe_benchmark/fixtures.py +299 -0
- equiframe_benchmark/freeze.py +869 -0
- equiframe_benchmark/freeze_v2.py +412 -0
- equiframe_benchmark/integration.py +655 -0
- equiframe_benchmark/io.py +29 -0
- equiframe_benchmark/models.py +313 -0
- equiframe_benchmark/models_v2.py +13 -0
- equiframe_benchmark/mutations.py +34 -0
- equiframe_benchmark/oracle.py +264 -0
- equiframe_benchmark/pairwise.py +248 -0
- equiframe_benchmark/pilot.py +254 -0
- equiframe_benchmark/py.typed +0 -0
- equiframe_benchmark/reconciliation.py +294 -0
- equiframe_benchmark/reproduction.py +542 -0
- equiframe_benchmark/scale_io.py +19 -0
- equiframe_benchmark/scale_process.py +1077 -0
- equiframe_benchmark/scale_types.py +120 -0
- equiframe_benchmark/scaling.py +529 -0
- equiframe_benchmark/schemas/protocol-v2/CommonSupportV2-2.0.schema.json +327 -0
- equiframe_benchmark/schemas/protocol-v2/ContrastSpecV2-2.0.schema.json +37 -0
- equiframe_benchmark/schemas/protocol-v2/EvaluationConfigV2-2.0.schema.json +184 -0
- equiframe_benchmark/schemas/protocol-v2/EvaluationReportV2-2.0.schema.json +1237 -0
- equiframe_benchmark/schemas/protocol-v2/EvaluationStratumV2-2.0.schema.json +747 -0
- equiframe_benchmark/schemas/protocol-v2/FreezeDefinitionV2-2.0.schema.json +5951 -0
- equiframe_benchmark/schemas/protocol-v2/FreezeManifestV2-2.0.schema.json +6222 -0
- equiframe_benchmark/schemas/protocol-v2/PrincipalContrastV2-2.0.schema.json +578 -0
- equiframe_benchmark/schemas/protocol-v2/ProtocolReviewV2-2.0.schema.json +56 -0
- equiframe_benchmark/schemas/protocol-v2/SignedMetricV2-2.0.schema.json +51 -0
- equiframe_benchmark/schemas/protocol-v2/StudyCaseResultV2-2.0.schema.json +4881 -0
- equiframe_benchmark/schemas/protocol-v2/StudyResultV2-2.0.schema.json +8370 -0
- equiframe_benchmark/schemas/protocol-v2/TableExportV2-2.0.schema.json +75 -0
- equiframe_benchmark/selection.py +178 -0
- equiframe_benchmark/snapshot.py +24 -0
- equiframe_benchmark/splits.py +92 -0
- equiframe_benchmark/study.py +526 -0
- equiframe_benchmark/study_bundle.py +379 -0
- equiframe_benchmark/study_bundle_v2.py +388 -0
- equiframe_benchmark/study_v2.py +544 -0
- equiframe_benchmark/tables.py +347 -0
- equiframe_benchmark/tables_v2.py +340 -0
- equiframe_benchmark/training_types.py +52 -0
- equiframe_benchmark-0.12.4.dist-info/METADATA +343 -0
- equiframe_benchmark-0.12.4.dist-info/RECORD +62 -0
- equiframe_benchmark-0.12.4.dist-info/WHEEL +4 -0
- equiframe_benchmark-0.12.4.dist-info/entry_points.txt +3 -0
- equiframe_benchmark-0.12.4.dist-info/licenses/LICENSE +21 -0
- equiframe_benchmark-0.12.4.dist-info/licenses/THIRD_PARTY_NOTICES.md +8 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""Readiness and reproduction commands; JSON never chooses executable code."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import cast
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def register(app: typer.Typer) -> None:
|
|
12
|
+
"""Attach commands to the caller's app without an eager circular CLI import."""
|
|
13
|
+
from equiframe_benchmark.cli import _factory, _failure
|
|
14
|
+
|
|
15
|
+
@app.command("distribution-readiness")
|
|
16
|
+
def distribution_command(
|
|
17
|
+
package_directory: Path,
|
|
18
|
+
wheel: Path | None = typer.Option(None),
|
|
19
|
+
name_check: Path | None = typer.Option(None),
|
|
20
|
+
output: Path | None = typer.Option(None),
|
|
21
|
+
) -> None:
|
|
22
|
+
"""Inventory local metadata; no PyPI network requests or publication actions."""
|
|
23
|
+
from equiframe_benchmark.distribution import NameCheck, inspect_distribution
|
|
24
|
+
from equiframe_benchmark.io import load_document, save_document
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
observation = load_document(NameCheck, name_check) if name_check else None
|
|
28
|
+
result = inspect_distribution(package_directory, wheel, name_check=observation)
|
|
29
|
+
if output is not None:
|
|
30
|
+
save_document(result, output)
|
|
31
|
+
except Exception as error:
|
|
32
|
+
_failure(error)
|
|
33
|
+
return
|
|
34
|
+
typer.echo(result.model_dump_json())
|
|
35
|
+
|
|
36
|
+
@app.command("verify-bundle")
|
|
37
|
+
def verify_command(
|
|
38
|
+
directory: Path,
|
|
39
|
+
expected_sha256: str | None = typer.Option(None),
|
|
40
|
+
) -> None:
|
|
41
|
+
"""Verify closed bundle bytes and inventory without importing a regenerator."""
|
|
42
|
+
from equiframe_benchmark.reproduction import read_bundle
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
result = read_bundle(directory, expected_sha256=expected_sha256)
|
|
46
|
+
except Exception as error:
|
|
47
|
+
_failure(error, input_validation=False)
|
|
48
|
+
return
|
|
49
|
+
typer.echo(
|
|
50
|
+
json.dumps(
|
|
51
|
+
{
|
|
52
|
+
"bundle_id": result.bundle_id,
|
|
53
|
+
"evidence_verified": True,
|
|
54
|
+
"files": len(result.files),
|
|
55
|
+
"reproduction_record_available": result.record_path is not None,
|
|
56
|
+
"independent_person_reproduced": False,
|
|
57
|
+
},
|
|
58
|
+
sort_keys=True,
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
@app.command("reproduce-bundle")
|
|
63
|
+
def reproduce_command(
|
|
64
|
+
directory: Path,
|
|
65
|
+
regenerator: str = typer.Option(
|
|
66
|
+
..., help="Explicit trusted module:factory, never from JSON."
|
|
67
|
+
),
|
|
68
|
+
expected_sha256: str | None = typer.Option(None),
|
|
69
|
+
output: Path | None = typer.Option(None),
|
|
70
|
+
) -> None:
|
|
71
|
+
"""Run an explicitly supplied trusted callable; compare complete logical content."""
|
|
72
|
+
from equiframe_benchmark.io import save_document
|
|
73
|
+
from equiframe_benchmark.reproduction import (
|
|
74
|
+
ReproductionRecord,
|
|
75
|
+
read_bundle,
|
|
76
|
+
reproduce_bundle,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
# Check persisted evidence before executing even the explicit factory.
|
|
81
|
+
read_bundle(directory, expected_sha256=expected_sha256)
|
|
82
|
+
except Exception as error:
|
|
83
|
+
_failure(error, input_validation=False)
|
|
84
|
+
return
|
|
85
|
+
try:
|
|
86
|
+
supplied = _factory(regenerator)()
|
|
87
|
+
if not callable(supplied):
|
|
88
|
+
raise ValueError("regenerator factory must return a callable")
|
|
89
|
+
callback = cast(Callable[[ReproductionRecord], ReproductionRecord], supplied)
|
|
90
|
+
except Exception as error:
|
|
91
|
+
_failure(error)
|
|
92
|
+
return
|
|
93
|
+
try:
|
|
94
|
+
receipt = reproduce_bundle(
|
|
95
|
+
directory,
|
|
96
|
+
regenerator=callback,
|
|
97
|
+
expected_sha256=expected_sha256,
|
|
98
|
+
)
|
|
99
|
+
if output is not None:
|
|
100
|
+
save_document(receipt, output)
|
|
101
|
+
except Exception as error:
|
|
102
|
+
_failure(error, input_validation=False)
|
|
103
|
+
return
|
|
104
|
+
typer.echo(receipt.model_dump_json())
|
|
105
|
+
if receipt.status == "different":
|
|
106
|
+
raise typer.Exit(code=1)
|
|
107
|
+
|
|
108
|
+
@app.command("bundle-study")
|
|
109
|
+
def bundle_study_command(directory: Path, output: Path = typer.Option(...)) -> None:
|
|
110
|
+
"""Copy a verified study into a closed bundle without rewriting original evidence."""
|
|
111
|
+
from equiframe_benchmark.study_bundle import bundle_study
|
|
112
|
+
|
|
113
|
+
try:
|
|
114
|
+
result = bundle_study(directory, output=output)
|
|
115
|
+
except Exception as error:
|
|
116
|
+
_failure(error)
|
|
117
|
+
return
|
|
118
|
+
typer.echo(
|
|
119
|
+
json.dumps(
|
|
120
|
+
{
|
|
121
|
+
"bundle_id": result.bundle_id,
|
|
122
|
+
"files": len(result.files),
|
|
123
|
+
"independent_person_reproduced": False,
|
|
124
|
+
"etl_repeated": False,
|
|
125
|
+
},
|
|
126
|
+
sort_keys=True,
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
@app.command("reproduce-study")
|
|
131
|
+
def reproduce_study_command(
|
|
132
|
+
directory: Path,
|
|
133
|
+
expected_sha256: str | None = typer.Option(None),
|
|
134
|
+
output: Path | None = typer.Option(None),
|
|
135
|
+
) -> None:
|
|
136
|
+
"""Regenerate metrics/tables from captured study decisions; never rerun ETL."""
|
|
137
|
+
from equiframe_benchmark.io import save_document
|
|
138
|
+
from equiframe_benchmark.study_bundle import reproduce_study_bundle
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
result = reproduce_study_bundle(directory, expected_sha256=expected_sha256)
|
|
142
|
+
if output is not None:
|
|
143
|
+
save_document(result, output)
|
|
144
|
+
except Exception as error:
|
|
145
|
+
_failure(error, input_validation=False)
|
|
146
|
+
return
|
|
147
|
+
typer.echo(result.model_dump_json())
|
|
148
|
+
if result.status == "different":
|
|
149
|
+
raise typer.Exit(code=1)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Engineering scale commands do not change the scientific benchmark protocol."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from equiframe._cli_support import exit_with_failure
|
|
8
|
+
from equiframe.evidence import load_json
|
|
9
|
+
|
|
10
|
+
from equiframe_benchmark.scale_types import ScaleSpec
|
|
11
|
+
from equiframe_benchmark.scaling import measure_scale, read_scale, summarize_scale
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def register(app: typer.Typer) -> None:
|
|
15
|
+
@app.command("scale")
|
|
16
|
+
def scale_command(spec: Path, output: Path = typer.Option(...)) -> None:
|
|
17
|
+
"""Measure one bounded synthetic case with safe process completion checks."""
|
|
18
|
+
try:
|
|
19
|
+
result = measure_scale(load_json(ScaleSpec, spec), work_dir=output)
|
|
20
|
+
except Exception as error:
|
|
21
|
+
exit_with_failure(error, code="scale_operation_failed", exit_code=3)
|
|
22
|
+
typer.echo(json.dumps(summarize_scale(result), sort_keys=True))
|
|
23
|
+
raise typer.Exit(code=0 if result.complete else 3)
|
|
24
|
+
|
|
25
|
+
@app.command("verify-scale")
|
|
26
|
+
def verify_scale_command(directory: Path) -> None:
|
|
27
|
+
"""Verify all retained bytes and completion; never rerun a workload."""
|
|
28
|
+
try:
|
|
29
|
+
result = read_scale(directory)
|
|
30
|
+
except Exception as error:
|
|
31
|
+
exit_with_failure(
|
|
32
|
+
error,
|
|
33
|
+
code="scale_evidence_invalid_or_incomplete",
|
|
34
|
+
exit_code=3,
|
|
35
|
+
input_validation=False,
|
|
36
|
+
)
|
|
37
|
+
typer.echo(json.dumps(summarize_scale(result), sort_keys=True))
|
|
38
|
+
raise typer.Exit(code=0 if result.complete else 3)
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"""Explicit experimental commands; persisted JSON never selects executable code."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def register(app: typer.Typer) -> None:
|
|
10
|
+
from equiframe_benchmark.cli import _factory, _failure
|
|
11
|
+
|
|
12
|
+
@app.command("freeze")
|
|
13
|
+
def freeze_command(definition: Path, output: Path = typer.Option(...)) -> None:
|
|
14
|
+
"""Audit and seal a declared pilot/final protocol before test execution."""
|
|
15
|
+
from equiframe_benchmark.freeze import FreezeDefinition, audit_freeze, create_freeze
|
|
16
|
+
from equiframe_benchmark.io import load_document, save_document
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
configuration = load_document(FreezeDefinition, definition)
|
|
20
|
+
audit = audit_freeze(configuration)
|
|
21
|
+
if not audit.ready:
|
|
22
|
+
typer.echo(
|
|
23
|
+
json.dumps(
|
|
24
|
+
{
|
|
25
|
+
"mode": configuration.mode,
|
|
26
|
+
"technical_ready": audit.technical_ready,
|
|
27
|
+
"scientific_ready": audit.scientific_ready,
|
|
28
|
+
"blockers": audit.blockers,
|
|
29
|
+
"sealed": False,
|
|
30
|
+
},
|
|
31
|
+
sort_keys=True,
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
raise typer.Exit(code=2)
|
|
35
|
+
manifest = create_freeze(configuration)
|
|
36
|
+
save_document(manifest, output)
|
|
37
|
+
except typer.Exit:
|
|
38
|
+
raise
|
|
39
|
+
except Exception as error:
|
|
40
|
+
_failure(error)
|
|
41
|
+
return
|
|
42
|
+
typer.echo(
|
|
43
|
+
json.dumps(
|
|
44
|
+
{
|
|
45
|
+
"mode": manifest.definition.mode,
|
|
46
|
+
"technical_ready": manifest.audit.technical_ready,
|
|
47
|
+
"scientific_ready": manifest.audit.scientific_ready,
|
|
48
|
+
"blockers": manifest.audit.blockers,
|
|
49
|
+
"sealed": True,
|
|
50
|
+
},
|
|
51
|
+
sort_keys=True,
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
@app.command("verify-freeze")
|
|
56
|
+
def verify_freeze_command(path: Path) -> None:
|
|
57
|
+
from equiframe_benchmark.freeze import read_freeze
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
manifest = read_freeze(path)
|
|
61
|
+
except Exception as error:
|
|
62
|
+
_failure(error, input_validation=False)
|
|
63
|
+
return
|
|
64
|
+
typer.echo(
|
|
65
|
+
json.dumps(
|
|
66
|
+
{
|
|
67
|
+
"evidence_verified": True,
|
|
68
|
+
"mode": manifest.definition.mode,
|
|
69
|
+
"technical_ready": manifest.audit.technical_ready,
|
|
70
|
+
"scientific_ready": manifest.audit.scientific_ready,
|
|
71
|
+
"blockers": manifest.audit.blockers,
|
|
72
|
+
},
|
|
73
|
+
sort_keys=True,
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
@app.command("run-study")
|
|
78
|
+
def study_command(
|
|
79
|
+
freeze: Path,
|
|
80
|
+
registry: str = typer.Option(...),
|
|
81
|
+
output: Path = typer.Option(Path("equiframe-studies")),
|
|
82
|
+
) -> None:
|
|
83
|
+
"""Run sealed cases with an explicitly trusted registry, without fitting."""
|
|
84
|
+
import equiframe as ef
|
|
85
|
+
|
|
86
|
+
from equiframe_benchmark.freeze import read_freeze
|
|
87
|
+
from equiframe_benchmark.study import read_study, run_study
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
manifest = read_freeze(freeze)
|
|
91
|
+
except Exception as error:
|
|
92
|
+
_failure(error, input_validation=False)
|
|
93
|
+
return
|
|
94
|
+
try:
|
|
95
|
+
registered = _factory(registry)()
|
|
96
|
+
if not isinstance(registered, ef.TransformationRegistry):
|
|
97
|
+
raise ValueError("registry factory must return a TransformationRegistry")
|
|
98
|
+
result = run_study(manifest, registry=registered, work_dir=output)
|
|
99
|
+
if read_study(output.resolve() / result.study_id) != result:
|
|
100
|
+
raise ValueError("published study differs from its verified receipt")
|
|
101
|
+
except Exception as error:
|
|
102
|
+
_failure(error)
|
|
103
|
+
return
|
|
104
|
+
typer.echo(
|
|
105
|
+
json.dumps(
|
|
106
|
+
{
|
|
107
|
+
"study_id": result.study_id,
|
|
108
|
+
"scientific": result.scientific,
|
|
109
|
+
"complete": result.complete,
|
|
110
|
+
"cases": len(result.evaluation.records),
|
|
111
|
+
"evidence_verified": True,
|
|
112
|
+
},
|
|
113
|
+
sort_keys=True,
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
raise typer.Exit(code=result.exit_code)
|
|
117
|
+
|
|
118
|
+
@app.command("verify-study")
|
|
119
|
+
def verify_study_command(directory: Path) -> None:
|
|
120
|
+
from equiframe_benchmark.study import read_study
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
result = read_study(directory)
|
|
124
|
+
except Exception as error:
|
|
125
|
+
_failure(error, input_validation=False)
|
|
126
|
+
return
|
|
127
|
+
typer.echo(
|
|
128
|
+
json.dumps(
|
|
129
|
+
{
|
|
130
|
+
"study_id": result.study_id,
|
|
131
|
+
"scientific": result.scientific,
|
|
132
|
+
"complete": result.complete,
|
|
133
|
+
"cases": len(result.evaluation.records),
|
|
134
|
+
"evidence_verified": True,
|
|
135
|
+
},
|
|
136
|
+
sort_keys=True,
|
|
137
|
+
)
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
@app.command("evaluate")
|
|
141
|
+
def evaluate_command(study: Path, output: Path = typer.Option(...)) -> None:
|
|
142
|
+
"""Regenerate a verified study's report from its complete captured records."""
|
|
143
|
+
from equiframe_benchmark.evaluation import evaluate_records
|
|
144
|
+
from equiframe_benchmark.io import save_document
|
|
145
|
+
from equiframe_benchmark.study import read_study
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
captured = read_study(study).evaluation
|
|
149
|
+
except Exception as error:
|
|
150
|
+
_failure(error, input_validation=False)
|
|
151
|
+
return
|
|
152
|
+
try:
|
|
153
|
+
report = evaluate_records(captured.records, config=captured.config)
|
|
154
|
+
if report != captured:
|
|
155
|
+
raise ValueError("evaluation must reproduce the captured report")
|
|
156
|
+
save_document(report, output)
|
|
157
|
+
except Exception as error:
|
|
158
|
+
_failure(error)
|
|
159
|
+
return
|
|
160
|
+
typer.echo(json.dumps({"scientific": report.scientific, "regenerated": True}))
|
|
161
|
+
|
|
162
|
+
@app.command("tables")
|
|
163
|
+
def tables_command(study: Path, output: Path = typer.Option(...)) -> None:
|
|
164
|
+
from equiframe_benchmark.study import read_study
|
|
165
|
+
from equiframe_benchmark.tables import write_tables
|
|
166
|
+
|
|
167
|
+
try:
|
|
168
|
+
report = read_study(study).evaluation
|
|
169
|
+
except Exception as error:
|
|
170
|
+
_failure(error, input_validation=False)
|
|
171
|
+
return
|
|
172
|
+
try:
|
|
173
|
+
receipt = write_tables(report, output)
|
|
174
|
+
except Exception as error:
|
|
175
|
+
_failure(error)
|
|
176
|
+
return
|
|
177
|
+
typer.echo(json.dumps({"tables": len(receipt.tables), "scientific": report.scientific}))
|
|
178
|
+
|
|
179
|
+
@app.command("costs")
|
|
180
|
+
def costs_command(
|
|
181
|
+
spec: Path,
|
|
182
|
+
bundle: Path = typer.Option(...),
|
|
183
|
+
output: Path = typer.Option(Path("equiframe-costs")),
|
|
184
|
+
) -> None:
|
|
185
|
+
"""Measure profile+M and comparison on previously captured artifacts."""
|
|
186
|
+
import equiframe as ef
|
|
187
|
+
|
|
188
|
+
from equiframe_benchmark.costs import CostSpec, ProfileMCostResult, measure_costs
|
|
189
|
+
from equiframe_benchmark.io import load_document
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
configuration = load_document(CostSpec, spec)
|
|
193
|
+
detector = ef.read_detector_bundle(bundle)
|
|
194
|
+
if ef.detector_fingerprint(detector) != configuration.detector_bundle_sha256:
|
|
195
|
+
raise ValueError("costs require the declared frozen detector bundle")
|
|
196
|
+
|
|
197
|
+
def profile_m(
|
|
198
|
+
directory: Path, cancellation: ef.CancellationToken
|
|
199
|
+
) -> ProfileMCostResult:
|
|
200
|
+
profile = ef.profile_execution(
|
|
201
|
+
configuration.execution,
|
|
202
|
+
spec=configuration.profile,
|
|
203
|
+
options=configuration.profile_options,
|
|
204
|
+
work_dir=directory,
|
|
205
|
+
cancellation=cancellation,
|
|
206
|
+
)
|
|
207
|
+
detection = (
|
|
208
|
+
ef.detect_component(detector, (profile.vector,), method="isolation_forest")
|
|
209
|
+
if profile.complete
|
|
210
|
+
else None
|
|
211
|
+
)
|
|
212
|
+
return ProfileMCostResult(profile=profile, detection=detection)
|
|
213
|
+
|
|
214
|
+
def comparison(
|
|
215
|
+
directory: Path, cancellation: ef.CancellationToken
|
|
216
|
+
) -> ef.ComparisonResult:
|
|
217
|
+
return ef.compare(
|
|
218
|
+
configuration.execution,
|
|
219
|
+
configuration.reference,
|
|
220
|
+
contract=configuration.execution.plan.contract,
|
|
221
|
+
policy=configuration.comparison_policy,
|
|
222
|
+
reference=configuration.comparison_reference,
|
|
223
|
+
options=configuration.comparison_options,
|
|
224
|
+
work_dir=directory,
|
|
225
|
+
cancellation=cancellation,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
result = measure_costs(
|
|
229
|
+
configuration, profile_m=profile_m, comparison=comparison, work_dir=output
|
|
230
|
+
)
|
|
231
|
+
except Exception as error:
|
|
232
|
+
_failure(error)
|
|
233
|
+
return
|
|
234
|
+
typer.echo(
|
|
235
|
+
json.dumps(
|
|
236
|
+
{
|
|
237
|
+
"cost_id": result.cost_id,
|
|
238
|
+
"complete": result.complete,
|
|
239
|
+
"scientific_h3_confirmed": False,
|
|
240
|
+
},
|
|
241
|
+
sort_keys=True,
|
|
242
|
+
)
|
|
243
|
+
)
|
|
244
|
+
raise typer.Exit(code=0 if result.complete else 3)
|
|
245
|
+
|
|
246
|
+
@app.command("verify-costs")
|
|
247
|
+
def verify_costs_command(directory: Path) -> None:
|
|
248
|
+
from equiframe_benchmark.costs import read_costs
|
|
249
|
+
|
|
250
|
+
try:
|
|
251
|
+
result = read_costs(directory)
|
|
252
|
+
except Exception as error:
|
|
253
|
+
_failure(error, input_validation=False)
|
|
254
|
+
return
|
|
255
|
+
typer.echo(
|
|
256
|
+
json.dumps(
|
|
257
|
+
{
|
|
258
|
+
"cost_id": result.cost_id,
|
|
259
|
+
"complete": result.complete,
|
|
260
|
+
"evidence_verified": True,
|
|
261
|
+
},
|
|
262
|
+
sort_keys=True,
|
|
263
|
+
)
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
@app.command("cost-table")
|
|
267
|
+
def cost_table_command(directory: Path, output: Path = typer.Option(...)) -> None:
|
|
268
|
+
from equiframe_benchmark.cost_table import write_cost_table
|
|
269
|
+
|
|
270
|
+
try:
|
|
271
|
+
write_cost_table(directory, output=output)
|
|
272
|
+
except Exception as error:
|
|
273
|
+
_failure(error, input_validation=False)
|
|
274
|
+
return
|
|
275
|
+
typer.echo(json.dumps({"observations": 12, "scientific_h3_confirmed": False}))
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""Explicit experimental commands; persisted JSON never selects executable code."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def register_v2(app: typer.Typer) -> None:
|
|
10
|
+
from equiframe_benchmark.cli import _factory, _failure
|
|
11
|
+
|
|
12
|
+
@app.command("freeze-v2")
|
|
13
|
+
def freeze_command(definition: Path, output: Path = typer.Option(...)) -> None:
|
|
14
|
+
"""Audit and seal a declared pilot/final protocol before test execution."""
|
|
15
|
+
from equiframe_benchmark.freeze_v2 import (
|
|
16
|
+
FreezeDefinitionV2,
|
|
17
|
+
audit_freeze_v2,
|
|
18
|
+
create_freeze_v2,
|
|
19
|
+
)
|
|
20
|
+
from equiframe_benchmark.io import load_document, save_document
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
configuration = load_document(FreezeDefinitionV2, definition)
|
|
24
|
+
audit = audit_freeze_v2(configuration)
|
|
25
|
+
if not audit.ready:
|
|
26
|
+
typer.echo(
|
|
27
|
+
json.dumps(
|
|
28
|
+
{
|
|
29
|
+
"mode": configuration.mode,
|
|
30
|
+
"technical_ready": audit.technical_ready,
|
|
31
|
+
"scientific_ready": audit.scientific_ready,
|
|
32
|
+
"blockers": audit.blockers,
|
|
33
|
+
"sealed": False,
|
|
34
|
+
},
|
|
35
|
+
sort_keys=True,
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
raise typer.Exit(code=2)
|
|
39
|
+
manifest = create_freeze_v2(configuration)
|
|
40
|
+
save_document(manifest, output)
|
|
41
|
+
except typer.Exit:
|
|
42
|
+
raise
|
|
43
|
+
except Exception as error:
|
|
44
|
+
_failure(error)
|
|
45
|
+
return
|
|
46
|
+
typer.echo(
|
|
47
|
+
json.dumps(
|
|
48
|
+
{
|
|
49
|
+
"mode": manifest.definition.mode,
|
|
50
|
+
"technical_ready": manifest.audit.technical_ready,
|
|
51
|
+
"scientific_ready": manifest.audit.scientific_ready,
|
|
52
|
+
"blockers": manifest.audit.blockers,
|
|
53
|
+
"sealed": True,
|
|
54
|
+
},
|
|
55
|
+
sort_keys=True,
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
@app.command("verify-freeze-v2")
|
|
60
|
+
def verify_freeze_command(path: Path) -> None:
|
|
61
|
+
from equiframe_benchmark.freeze_v2 import read_freeze_v2
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
manifest = read_freeze_v2(path)
|
|
65
|
+
except Exception as error:
|
|
66
|
+
_failure(error, input_validation=False)
|
|
67
|
+
return
|
|
68
|
+
typer.echo(
|
|
69
|
+
json.dumps(
|
|
70
|
+
{
|
|
71
|
+
"evidence_verified": True,
|
|
72
|
+
"mode": manifest.definition.mode,
|
|
73
|
+
"technical_ready": manifest.audit.technical_ready,
|
|
74
|
+
"scientific_ready": manifest.audit.scientific_ready,
|
|
75
|
+
"blockers": manifest.audit.blockers,
|
|
76
|
+
},
|
|
77
|
+
sort_keys=True,
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
@app.command("run-study-v2")
|
|
82
|
+
def study_command(
|
|
83
|
+
freeze: Path,
|
|
84
|
+
registry: str = typer.Option(...),
|
|
85
|
+
output: Path = typer.Option(Path("equiframe-studies")),
|
|
86
|
+
) -> None:
|
|
87
|
+
"""Run sealed cases with an explicitly trusted registry, without fitting."""
|
|
88
|
+
import equiframe as ef
|
|
89
|
+
|
|
90
|
+
from equiframe_benchmark.freeze_v2 import read_freeze_v2
|
|
91
|
+
from equiframe_benchmark.study_v2 import read_study_v2, run_study_v2
|
|
92
|
+
|
|
93
|
+
try:
|
|
94
|
+
manifest = read_freeze_v2(freeze)
|
|
95
|
+
except Exception as error:
|
|
96
|
+
_failure(error, input_validation=False)
|
|
97
|
+
return
|
|
98
|
+
try:
|
|
99
|
+
registered = _factory(registry)()
|
|
100
|
+
if not isinstance(registered, ef.TransformationRegistry):
|
|
101
|
+
raise ValueError("registry factory must return a TransformationRegistry")
|
|
102
|
+
result = run_study_v2(manifest, registry=registered, work_dir=output)
|
|
103
|
+
if read_study_v2(output.resolve() / result.study_id) != result:
|
|
104
|
+
raise ValueError("published study differs from its verified receipt")
|
|
105
|
+
except Exception as error:
|
|
106
|
+
_failure(error)
|
|
107
|
+
return
|
|
108
|
+
typer.echo(
|
|
109
|
+
json.dumps(
|
|
110
|
+
{
|
|
111
|
+
"study_id": result.study_id,
|
|
112
|
+
"scientific": result.scientific,
|
|
113
|
+
"complete": result.complete,
|
|
114
|
+
"cases": len(result.evaluation.records),
|
|
115
|
+
"evidence_verified": True,
|
|
116
|
+
},
|
|
117
|
+
sort_keys=True,
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
raise typer.Exit(code=result.exit_code)
|
|
121
|
+
|
|
122
|
+
@app.command("verify-study-v2")
|
|
123
|
+
def verify_study_command(directory: Path) -> None:
|
|
124
|
+
from equiframe_benchmark.study_v2 import read_study_v2
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
result = read_study_v2(directory)
|
|
128
|
+
except Exception as error:
|
|
129
|
+
_failure(error, input_validation=False)
|
|
130
|
+
return
|
|
131
|
+
typer.echo(
|
|
132
|
+
json.dumps(
|
|
133
|
+
{
|
|
134
|
+
"study_id": result.study_id,
|
|
135
|
+
"scientific": result.scientific,
|
|
136
|
+
"complete": result.complete,
|
|
137
|
+
"cases": len(result.evaluation.records),
|
|
138
|
+
"evidence_verified": True,
|
|
139
|
+
},
|
|
140
|
+
sort_keys=True,
|
|
141
|
+
)
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
@app.command("evaluate-v2")
|
|
145
|
+
def evaluate_command(study: Path, output: Path = typer.Option(...)) -> None:
|
|
146
|
+
"""Regenerate a verified study's report from its complete captured records."""
|
|
147
|
+
from equiframe_benchmark.evaluation_v2 import evaluate_records_v2
|
|
148
|
+
from equiframe_benchmark.io import save_document
|
|
149
|
+
from equiframe_benchmark.study_v2 import read_study_v2
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
captured = read_study_v2(study).evaluation
|
|
153
|
+
except Exception as error:
|
|
154
|
+
_failure(error, input_validation=False)
|
|
155
|
+
return
|
|
156
|
+
try:
|
|
157
|
+
report = evaluate_records_v2(captured.records, config=captured.config)
|
|
158
|
+
if report != captured:
|
|
159
|
+
raise ValueError("evaluation must reproduce the captured report")
|
|
160
|
+
save_document(report, output)
|
|
161
|
+
except Exception as error:
|
|
162
|
+
_failure(error)
|
|
163
|
+
return
|
|
164
|
+
typer.echo(json.dumps({"scientific": report.scientific, "regenerated": True}))
|
|
165
|
+
|
|
166
|
+
@app.command("tables-v2")
|
|
167
|
+
def tables_command(study: Path, output: Path = typer.Option(...)) -> None:
|
|
168
|
+
from equiframe_benchmark.study_v2 import read_study_v2
|
|
169
|
+
from equiframe_benchmark.tables_v2 import write_tables_v2
|
|
170
|
+
|
|
171
|
+
try:
|
|
172
|
+
report = read_study_v2(study).evaluation
|
|
173
|
+
except Exception as error:
|
|
174
|
+
_failure(error, input_validation=False)
|
|
175
|
+
return
|
|
176
|
+
try:
|
|
177
|
+
receipt = write_tables_v2(report, output)
|
|
178
|
+
except Exception as error:
|
|
179
|
+
_failure(error)
|
|
180
|
+
return
|
|
181
|
+
typer.echo(json.dumps({"tables": len(receipt.tables), "scientific": report.scientific}))
|
|
182
|
+
|
|
183
|
+
@app.command("bundle-study-v2")
|
|
184
|
+
def bundle_command(study: Path, output: Path = typer.Option(...)) -> None:
|
|
185
|
+
"""Copy the V2 captured study and original sources without rewriting provenance."""
|
|
186
|
+
from equiframe_benchmark.study_bundle_v2 import bundle_study_v2
|
|
187
|
+
|
|
188
|
+
try:
|
|
189
|
+
result = bundle_study_v2(study, output=output)
|
|
190
|
+
except Exception as error:
|
|
191
|
+
_failure(error, input_validation=False)
|
|
192
|
+
return
|
|
193
|
+
typer.echo(json.dumps({"protocol_version": "2.0", "bundle_id": result.bundle_id}))
|
|
194
|
+
|
|
195
|
+
@app.command("reproduce-study-v2")
|
|
196
|
+
def reproduce_command(directory: Path) -> None:
|
|
197
|
+
"""Regenerate paired tables from captured decisions, without executing native ETL."""
|
|
198
|
+
from equiframe_benchmark.study_bundle_v2 import reproduce_study_bundle_v2
|
|
199
|
+
|
|
200
|
+
try:
|
|
201
|
+
result = reproduce_study_bundle_v2(directory)
|
|
202
|
+
except Exception as error:
|
|
203
|
+
_failure(error, input_validation=False)
|
|
204
|
+
return
|
|
205
|
+
typer.echo(json.dumps({"protocol_version": "2.0", "status": result.status}))
|
|
206
|
+
raise typer.Exit(code=0 if result.status == "reproduced" else 1)
|