gazeaudit 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.
- gazeaudit-0.1.0/.github/workflows/distribution.yml +84 -0
- gazeaudit-0.1.0/.github/workflows/interop.yml +45 -0
- gazeaudit-0.1.0/.github/workflows/korthals-scientific-execution.yml +160 -0
- gazeaudit-0.1.0/.github/workflows/korthals-source-freeze.yml +139 -0
- gazeaudit-0.1.0/.github/workflows/pedrotti-scientific-execution.yml +159 -0
- gazeaudit-0.1.0/.github/workflows/pedrotti-source-freeze.yml +150 -0
- gazeaudit-0.1.0/.github/workflows/release-candidate.yml +104 -0
- gazeaudit-0.1.0/.github/workflows/tests.yml +56 -0
- gazeaudit-0.1.0/.gitignore +13 -0
- gazeaudit-0.1.0/CHANGELOG.md +58 -0
- gazeaudit-0.1.0/CITATION.cff +19 -0
- gazeaudit-0.1.0/LICENSE +21 -0
- gazeaudit-0.1.0/PKG-INFO +309 -0
- gazeaudit-0.1.0/README.md +246 -0
- gazeaudit-0.1.0/docs/CITATION_AND_REUSE.md +102 -0
- gazeaudit-0.1.0/docs/PUBLICATION_SUMMARY.md +105 -0
- gazeaudit-0.1.0/docs/RELEASE.md +107 -0
- gazeaudit-0.1.0/docs/REPRODUCIBILITY_INDEX.json +116 -0
- gazeaudit-0.1.0/docs/SCIENTIFIC_METHODS.md +153 -0
- gazeaudit-0.1.0/docs/VALIDATION_MATRIX.md +124 -0
- gazeaudit-0.1.0/docs/case_studies/GAZEBASE_MULTIDETECTOR_PROTOCOL.md +260 -0
- gazeaudit-0.1.0/docs/case_studies/gazebase_multidetector_protocol.json +127 -0
- gazeaudit-0.1.0/docs/case_studies/gazebase_real_data_execution.md +93 -0
- gazeaudit-0.1.0/docs/protocols/PEDROTTI2023_SAMPLING_MISSINGNESS_V1.md +86 -0
- gazeaudit-0.1.0/docs/protocols/korthals2026_target_tracking_aoi_v1.json +116 -0
- gazeaudit-0.1.0/docs/protocols/korthals2026_target_tracking_aoi_v2.json +125 -0
- gazeaudit-0.1.0/docs/protocols/pedrotti2023_sampling_missingness_v1.json +144 -0
- gazeaudit-0.1.0/docs/results/korthals2026_target_tracking_aoi_v2.json +129 -0
- gazeaudit-0.1.0/docs/results/korthals2026_target_tracking_aoi_v2.md +91 -0
- gazeaudit-0.1.0/docs/results/pedrotti_sampling_missingness_v1.md +141 -0
- gazeaudit-0.1.0/docs/validation/korthals_memory_bounded_intake_v2.md +58 -0
- gazeaudit-0.1.0/docs/validation/korthals_osf_download_resilience_v2.md +82 -0
- gazeaudit-0.1.0/docs/validation/korthals_scientific_execution_v2.md +76 -0
- gazeaudit-0.1.0/docs/validation/korthals_source_lock_v2.md +77 -0
- gazeaudit-0.1.0/docs/validation/korthals_tutorial_scope_v1.md +11 -0
- gazeaudit-0.1.0/docs/validation/korthals_zero_finite_cell_amendment_v2.md +36 -0
- gazeaudit-0.1.0/docs/validation/pedrotti_source_freeze_v1.md +149 -0
- gazeaudit-0.1.0/pyproject.toml +95 -0
- gazeaudit-0.1.0/src/gazeaudit/__init__.py +309 -0
- gazeaudit-0.1.0/src/gazeaudit/adapters.py +84 -0
- gazeaudit-0.1.0/src/gazeaudit/aoi.py +69 -0
- gazeaudit-0.1.0/src/gazeaudit/aoi_artifacts.py +295 -0
- gazeaudit-0.1.0/src/gazeaudit/aoi_audit.py +154 -0
- gazeaudit-0.1.0/src/gazeaudit/aoi_propagation.py +267 -0
- gazeaudit-0.1.0/src/gazeaudit/aoi_protocol.py +165 -0
- gazeaudit-0.1.0/src/gazeaudit/benchmark.py +154 -0
- gazeaudit-0.1.0/src/gazeaudit/bids_adapter.py +386 -0
- gazeaudit-0.1.0/src/gazeaudit/conclusion.py +448 -0
- gazeaudit-0.1.0/src/gazeaudit/data/__init__.py +1 -0
- gazeaudit-0.1.0/src/gazeaudit/data/gazebase_multidetector_protocol.json +127 -0
- gazeaudit-0.1.0/src/gazeaudit/data/korthals2026_source_lock_v2.json +89 -0
- gazeaudit-0.1.0/src/gazeaudit/data/korthals2026_target_tracking_aoi_v1.json +116 -0
- gazeaudit-0.1.0/src/gazeaudit/data/korthals2026_target_tracking_aoi_v2.json +125 -0
- gazeaudit-0.1.0/src/gazeaudit/data/pedrotti2023_sampling_missingness_v1.json +144 -0
- gazeaudit-0.1.0/src/gazeaudit/data/pedrotti2023_source_lock_v1.json +95 -0
- gazeaudit-0.1.0/src/gazeaudit/endpoints.py +47 -0
- gazeaudit-0.1.0/src/gazeaudit/gazebase_artifacts.py +281 -0
- gazeaudit-0.1.0/src/gazeaudit/gazebase_cli.py +112 -0
- gazeaudit-0.1.0/src/gazeaudit/gazebase_execution.py +571 -0
- gazeaudit-0.1.0/src/gazeaudit/gazebase_failure.py +164 -0
- gazeaudit-0.1.0/src/gazeaudit/gazebase_partitioned.py +458 -0
- gazeaudit-0.1.0/src/gazeaudit/gazebase_pymovements.py +164 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_execution.py +882 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_execution_archive_v2.py +122 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_execution_v2.py +510 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_execution_v2_cli.py +86 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_freeze.py +318 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_freeze_cli.py +86 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_freeze_v2.py +263 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_freeze_v2_cli.py +84 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_osf.py +248 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_reveal_v2_cli.py +28 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_source.py +697 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_source_cli.py +64 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_source_lock.py +165 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_source_v2_cli.py +57 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_streaming.py +277 -0
- gazeaudit-0.1.0/src/gazeaudit/korthals_v2.py +667 -0
- gazeaudit-0.1.0/src/gazeaudit/missingness.py +161 -0
- gazeaudit-0.1.0/src/gazeaudit/multiverse.py +104 -0
- gazeaudit-0.1.0/src/gazeaudit/pedrotti_execution.py +1234 -0
- gazeaudit-0.1.0/src/gazeaudit/pedrotti_execution_cli.py +54 -0
- gazeaudit-0.1.0/src/gazeaudit/pedrotti_fetch.py +410 -0
- gazeaudit-0.1.0/src/gazeaudit/pedrotti_freeze.py +336 -0
- gazeaudit-0.1.0/src/gazeaudit/pedrotti_freeze_cli.py +87 -0
- gazeaudit-0.1.0/src/gazeaudit/pedrotti_prefetch.py +186 -0
- gazeaudit-0.1.0/src/gazeaudit/pedrotti_reveal_cli.py +36 -0
- gazeaudit-0.1.0/src/gazeaudit/pedrotti_source.py +587 -0
- gazeaudit-0.1.0/src/gazeaudit/pedrotti_source_cli.py +52 -0
- gazeaudit-0.1.0/src/gazeaudit/pedrotti_source_lock.py +213 -0
- gazeaudit-0.1.0/src/gazeaudit/peyes_adapter.py +223 -0
- gazeaudit-0.1.0/src/gazeaudit/provenance.py +129 -0
- gazeaudit-0.1.0/src/gazeaudit/publication.py +473 -0
- gazeaudit-0.1.0/src/gazeaudit/pymovements_adapter.py +285 -0
- gazeaudit-0.1.0/src/gazeaudit/report.py +108 -0
- gazeaudit-0.1.0/src/gazeaudit/robustness.py +184 -0
- gazeaudit-0.1.0/src/gazeaudit/sampling.py +100 -0
- gazeaudit-0.1.0/src/gazeaudit/scientific_benchmark.py +180 -0
- gazeaudit-0.1.0/src/gazeaudit/sensitivity.py +130 -0
- gazeaudit-0.1.0/src/gazeaudit/sensitivity_protocol.py +242 -0
- gazeaudit-0.1.0/src/gazeaudit/study.py +109 -0
- gazeaudit-0.1.0/src/gazeaudit/task_contrast.py +452 -0
- gazeaudit-0.1.0/src/gazeaudit/uncertainty.py +404 -0
- gazeaudit-0.1.0/tests/test_aoi_propagation.py +212 -0
- gazeaudit-0.1.0/tests/test_aoi_protocol_artifacts.py +249 -0
- gazeaudit-0.1.0/tests/test_aoi_uncertainty.py +297 -0
- gazeaudit-0.1.0/tests/test_bids_adapter.py +306 -0
- gazeaudit-0.1.0/tests/test_conclusion_recovery.py +223 -0
- gazeaudit-0.1.0/tests/test_core.py +128 -0
- gazeaudit-0.1.0/tests/test_gazebase_artifacts.py +212 -0
- gazeaudit-0.1.0/tests/test_gazebase_execution.py +400 -0
- gazeaudit-0.1.0/tests/test_gazebase_failure.py +219 -0
- gazeaudit-0.1.0/tests/test_gazebase_partitioned.py +253 -0
- gazeaudit-0.1.0/tests/test_gazebase_protocol.py +89 -0
- gazeaudit-0.1.0/tests/test_gazebase_pymovements_contract.py +150 -0
- gazeaudit-0.1.0/tests/test_grouped_uncertainty.py +220 -0
- gazeaudit-0.1.0/tests/test_interoperability.py +325 -0
- gazeaudit-0.1.0/tests/test_korthals_aoi_protocol.py +94 -0
- gazeaudit-0.1.0/tests/test_korthals_execution.py +252 -0
- gazeaudit-0.1.0/tests/test_korthals_execution_v2.py +177 -0
- gazeaudit-0.1.0/tests/test_korthals_freeze.py +223 -0
- gazeaudit-0.1.0/tests/test_korthals_osf.py +171 -0
- gazeaudit-0.1.0/tests/test_korthals_participant_identity.py +192 -0
- gazeaudit-0.1.0/tests/test_korthals_source.py +257 -0
- gazeaudit-0.1.0/tests/test_korthals_source_lock.py +105 -0
- gazeaudit-0.1.0/tests/test_korthals_streaming.py +258 -0
- gazeaudit-0.1.0/tests/test_korthals_tutorial_scope.py +107 -0
- gazeaudit-0.1.0/tests/test_korthals_v2.py +271 -0
- gazeaudit-0.1.0/tests/test_missingness_provenance.py +147 -0
- gazeaudit-0.1.0/tests/test_optional_interop.py +99 -0
- gazeaudit-0.1.0/tests/test_pedrotti_execution.py +415 -0
- gazeaudit-0.1.0/tests/test_pedrotti_fetch.py +61 -0
- gazeaudit-0.1.0/tests/test_pedrotti_fetch_fallback.py +234 -0
- gazeaudit-0.1.0/tests/test_pedrotti_prefetch.py +154 -0
- gazeaudit-0.1.0/tests/test_pedrotti_scientific_workflow.py +46 -0
- gazeaudit-0.1.0/tests/test_pedrotti_source_freeze.py +245 -0
- gazeaudit-0.1.0/tests/test_pedrotti_source_gate_runtime.py +258 -0
- gazeaudit-0.1.0/tests/test_pedrotti_source_lock.py +140 -0
- gazeaudit-0.1.0/tests/test_publication_bundle.py +214 -0
- gazeaudit-0.1.0/tests/test_publication_index.py +127 -0
- gazeaudit-0.1.0/tests/test_release_gate.py +125 -0
- gazeaudit-0.1.0/tests/test_release_metadata.py +60 -0
- gazeaudit-0.1.0/tests/test_report_interactions.py +17 -0
- gazeaudit-0.1.0/tests/test_scientific_benchmark_sampling.py +179 -0
- gazeaudit-0.1.0/tests/test_sensitivity_protocol.py +167 -0
- gazeaudit-0.1.0/tests/test_task_contrast.py +285 -0
- gazeaudit-0.1.0/tools/release_gate.py +86 -0
- gazeaudit-0.1.0/tools/verify_distribution.py +171 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
name: distribution
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build-and-verify:
|
|
14
|
+
runs-on: ubuntu-24.04
|
|
15
|
+
timeout-minutes: 20
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout
|
|
18
|
+
uses: actions/checkout@v7
|
|
19
|
+
|
|
20
|
+
- name: Set up Python 3.12.14
|
|
21
|
+
uses: actions/setup-python@v7
|
|
22
|
+
with:
|
|
23
|
+
python-version: '3.12.14'
|
|
24
|
+
cache: pip
|
|
25
|
+
|
|
26
|
+
- name: Install build validators
|
|
27
|
+
shell: bash
|
|
28
|
+
run: |
|
|
29
|
+
set -euo pipefail
|
|
30
|
+
python -m pip install --upgrade pip
|
|
31
|
+
python -m pip install build twine
|
|
32
|
+
|
|
33
|
+
- name: Build clean sdist and wheel
|
|
34
|
+
shell: bash
|
|
35
|
+
run: |
|
|
36
|
+
set -euo pipefail
|
|
37
|
+
rm -rf build dist
|
|
38
|
+
python -m build
|
|
39
|
+
test "$(find dist -maxdepth 1 -type f | wc -l)" -eq 2
|
|
40
|
+
|
|
41
|
+
- name: Validate package metadata
|
|
42
|
+
shell: bash
|
|
43
|
+
run: |
|
|
44
|
+
set -euo pipefail
|
|
45
|
+
python -m twine check dist/*
|
|
46
|
+
python tools/verify_distribution.py dist
|
|
47
|
+
|
|
48
|
+
- name: Install wheel in fresh environment
|
|
49
|
+
shell: bash
|
|
50
|
+
run: |
|
|
51
|
+
set -euo pipefail
|
|
52
|
+
wheel="$(find dist -maxdepth 1 -name '*.whl' -print -quit)"
|
|
53
|
+
test -n "$wheel"
|
|
54
|
+
python -m venv .wheel-smoke
|
|
55
|
+
.wheel-smoke/bin/python -m pip install --upgrade pip
|
|
56
|
+
.wheel-smoke/bin/python -m pip install "$wheel"
|
|
57
|
+
.wheel-smoke/bin/python - <<'PY'
|
|
58
|
+
import tomllib
|
|
59
|
+
from importlib import metadata, resources
|
|
60
|
+
from pathlib import Path
|
|
61
|
+
|
|
62
|
+
import gazeaudit
|
|
63
|
+
|
|
64
|
+
project = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))
|
|
65
|
+
expected = project["project"]["version"]
|
|
66
|
+
if metadata.version("gazeaudit") != expected:
|
|
67
|
+
raise SystemExit("installed wheel version differs from pyproject.toml")
|
|
68
|
+
if not hasattr(gazeaudit, "GazeStudy"):
|
|
69
|
+
raise SystemExit("installed wheel does not expose GazeStudy")
|
|
70
|
+
resource = resources.files("gazeaudit.data").joinpath(
|
|
71
|
+
"pedrotti2023_sampling_missingness_v1.json"
|
|
72
|
+
)
|
|
73
|
+
if not resource.is_file():
|
|
74
|
+
raise SystemExit("installed wheel is missing frozen scientific package data")
|
|
75
|
+
PY
|
|
76
|
+
|
|
77
|
+
- name: Archive qualified distributions
|
|
78
|
+
uses: actions/upload-artifact@v7
|
|
79
|
+
with:
|
|
80
|
+
name: gazeaudit-distribution-${{ github.sha }}
|
|
81
|
+
path: dist/
|
|
82
|
+
if-no-files-found: error
|
|
83
|
+
retention-days: 30
|
|
84
|
+
compression-level: 0
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: interoperability
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, "dev/**"]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref_name }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
live-contracts:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- name: Checkout
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Set up Python
|
|
25
|
+
uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.12"
|
|
28
|
+
cache: pip
|
|
29
|
+
|
|
30
|
+
- name: Install interoperability dependencies
|
|
31
|
+
run: |
|
|
32
|
+
python -m pip install --upgrade pip
|
|
33
|
+
python -m pip install -e ".[test,interop]"
|
|
34
|
+
|
|
35
|
+
- name: Verify upstream versions
|
|
36
|
+
run: |
|
|
37
|
+
python - <<'PY'
|
|
38
|
+
import peyes
|
|
39
|
+
import pymovements
|
|
40
|
+
print("pEYES", peyes.__version__)
|
|
41
|
+
print("pymovements", pymovements.__version__)
|
|
42
|
+
PY
|
|
43
|
+
|
|
44
|
+
- name: Run live interoperability contract tests
|
|
45
|
+
run: pytest -q tests/test_optional_interop.py
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
name: korthals-scientific-execution
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: korthals-scientific-execution-v2
|
|
11
|
+
cancel-in-progress: false
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
scientific-execution:
|
|
15
|
+
if: github.ref == 'refs/heads/main'
|
|
16
|
+
runs-on: ubuntu-24.04
|
|
17
|
+
timeout-minutes: 180
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout exact GazeAudit commit
|
|
20
|
+
uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Set up exact Python 3.12.14
|
|
23
|
+
uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: '3.12.14'
|
|
26
|
+
cache: pip
|
|
27
|
+
|
|
28
|
+
- name: Verify exact main execution identity
|
|
29
|
+
shell: bash
|
|
30
|
+
run: |
|
|
31
|
+
set -euo pipefail
|
|
32
|
+
test "$GITHUB_REF" = "refs/heads/main"
|
|
33
|
+
test "$(git rev-parse HEAD)" = "$GITHUB_SHA"
|
|
34
|
+
|
|
35
|
+
- name: Checkout frozen companion implementation
|
|
36
|
+
shell: bash
|
|
37
|
+
run: |
|
|
38
|
+
set -euo pipefail
|
|
39
|
+
git clone https://github.com/lukekorthals/pursuing-smooth-pursuits-data companion
|
|
40
|
+
git -C companion checkout 1d7ebec23e3fe20f6db952eefda1a0dd58ae09da
|
|
41
|
+
test "$(git -C companion rev-parse HEAD)" = \
|
|
42
|
+
"1d7ebec23e3fe20f6db952eefda1a0dd58ae09da"
|
|
43
|
+
|
|
44
|
+
- name: Install source-freeze-matched critical execution stack
|
|
45
|
+
shell: bash
|
|
46
|
+
run: |
|
|
47
|
+
set -euo pipefail
|
|
48
|
+
python -m pip install --upgrade pip
|
|
49
|
+
python -m pip install \
|
|
50
|
+
"numpy==2.5.3" \
|
|
51
|
+
"pandas==2.3.3" \
|
|
52
|
+
"scipy==1.18.1"
|
|
53
|
+
python -m pip install -e .
|
|
54
|
+
python -m pip install ./companion
|
|
55
|
+
python - <<'PY'
|
|
56
|
+
import platform
|
|
57
|
+
import numpy as np
|
|
58
|
+
import pandas as pd
|
|
59
|
+
import scipy
|
|
60
|
+
|
|
61
|
+
expected = {
|
|
62
|
+
"python": "3.12.14",
|
|
63
|
+
"numpy": "2.5.3",
|
|
64
|
+
"pandas": "2.3.3",
|
|
65
|
+
"scipy": "1.18.1",
|
|
66
|
+
}
|
|
67
|
+
observed = {
|
|
68
|
+
"python": platform.python_version(),
|
|
69
|
+
"numpy": np.__version__,
|
|
70
|
+
"pandas": pd.__version__,
|
|
71
|
+
"scipy": scipy.__version__,
|
|
72
|
+
}
|
|
73
|
+
if observed != expected:
|
|
74
|
+
raise SystemExit(f"execution environment differs from source freeze: {observed}")
|
|
75
|
+
PY
|
|
76
|
+
|
|
77
|
+
- name: Download complete published OSF source
|
|
78
|
+
shell: bash
|
|
79
|
+
run: |
|
|
80
|
+
set -euo pipefail
|
|
81
|
+
python - <<'PY'
|
|
82
|
+
from gazeaudit.korthals_osf import fetch_korthals_osf_resumable
|
|
83
|
+
|
|
84
|
+
summary = fetch_korthals_osf_resumable(
|
|
85
|
+
max_attempts=6,
|
|
86
|
+
initial_backoff_seconds=15.0,
|
|
87
|
+
)
|
|
88
|
+
print(
|
|
89
|
+
"verified endpoint-blind OSF transfer: "
|
|
90
|
+
f"files={summary['file_count']} attempts={summary['attempts']} "
|
|
91
|
+
f"retained={summary['retained_verified_files']} "
|
|
92
|
+
f"removed_partials={summary['removed_partial_files']}"
|
|
93
|
+
)
|
|
94
|
+
PY
|
|
95
|
+
|
|
96
|
+
- name: Verify locked public-source bytes before preprocessing
|
|
97
|
+
shell: bash
|
|
98
|
+
run: |
|
|
99
|
+
set -euo pipefail
|
|
100
|
+
python - <<'PY'
|
|
101
|
+
from gazeaudit.korthals_source_lock import verify_korthals_locked_source_manifest
|
|
102
|
+
from gazeaudit.korthals_v2 import build_korthals_source_manifest_v2
|
|
103
|
+
|
|
104
|
+
manifest = build_korthals_source_manifest_v2("data")
|
|
105
|
+
verify_korthals_locked_source_manifest(manifest)
|
|
106
|
+
PY
|
|
107
|
+
|
|
108
|
+
- name: Capture exact dependency environment before scientific execution
|
|
109
|
+
shell: bash
|
|
110
|
+
run: |
|
|
111
|
+
set -euo pipefail
|
|
112
|
+
python -m pip freeze | LC_ALL=C sort > pip-freeze.txt
|
|
113
|
+
test -s pip-freeze.txt
|
|
114
|
+
grep -Fx 'numpy==2.5.3' pip-freeze.txt
|
|
115
|
+
grep -Fx 'pandas==2.3.3' pip-freeze.txt
|
|
116
|
+
grep -Fx 'scipy==1.18.1' pip-freeze.txt
|
|
117
|
+
|
|
118
|
+
- name: Execute locked protocol v2 without revealing scientific results
|
|
119
|
+
shell: bash
|
|
120
|
+
run: |
|
|
121
|
+
set -euo pipefail
|
|
122
|
+
python -m gazeaudit.korthals_execution_v2_cli \
|
|
123
|
+
--data-root data \
|
|
124
|
+
--output-dir korthals-scientific-execution \
|
|
125
|
+
--environment-file pip-freeze.txt \
|
|
126
|
+
--execution-commit "$GITHUB_SHA" \
|
|
127
|
+
--run-id "$GITHUB_RUN_ID" \
|
|
128
|
+
--runner-os "$RUNNER_OS" \
|
|
129
|
+
--runner-arch "$RUNNER_ARCH"
|
|
130
|
+
|
|
131
|
+
- name: Verify locked scientific archive before upload
|
|
132
|
+
shell: bash
|
|
133
|
+
run: |
|
|
134
|
+
set -euo pipefail
|
|
135
|
+
python - <<'PY'
|
|
136
|
+
from gazeaudit.korthals_execution_archive_v2 import (
|
|
137
|
+
verify_korthals_locked_execution_artifacts_v2,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
if not verify_korthals_locked_execution_artifacts_v2(
|
|
141
|
+
"korthals-scientific-execution"
|
|
142
|
+
):
|
|
143
|
+
raise SystemExit("locked Korthals protocol-v2 archive verification failed")
|
|
144
|
+
PY
|
|
145
|
+
|
|
146
|
+
- name: Archive scientific execution before reveal
|
|
147
|
+
uses: actions/upload-artifact@v4
|
|
148
|
+
with:
|
|
149
|
+
name: korthals-scientific-v2-${{ github.sha }}
|
|
150
|
+
path: korthals-scientific-execution/
|
|
151
|
+
if-no-files-found: error
|
|
152
|
+
retention-days: 90
|
|
153
|
+
compression-level: 0
|
|
154
|
+
|
|
155
|
+
- name: Reveal archived scientific result
|
|
156
|
+
shell: bash
|
|
157
|
+
run: |
|
|
158
|
+
set -euo pipefail
|
|
159
|
+
python -m gazeaudit.korthals_reveal_v2_cli \
|
|
160
|
+
--artifact-dir korthals-scientific-execution
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
name: korthals-source-freeze
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: korthals-source-freeze-v2
|
|
11
|
+
cancel-in-progress: false
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
source-freeze:
|
|
15
|
+
if: github.ref == 'refs/heads/main'
|
|
16
|
+
runs-on: ubuntu-24.04
|
|
17
|
+
timeout-minutes: 180
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout exact GazeAudit commit
|
|
20
|
+
uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Set up Python 3.12
|
|
23
|
+
uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: '3.12'
|
|
26
|
+
cache: pip
|
|
27
|
+
|
|
28
|
+
- name: Verify exact main execution identity
|
|
29
|
+
shell: bash
|
|
30
|
+
run: |
|
|
31
|
+
set -euo pipefail
|
|
32
|
+
test "$GITHUB_REF" = "refs/heads/main"
|
|
33
|
+
test "$(git rev-parse HEAD)" = "$GITHUB_SHA"
|
|
34
|
+
printf '%s\n' "$GITHUB_SHA" > execution-commit.txt
|
|
35
|
+
|
|
36
|
+
- name: Checkout frozen companion implementation
|
|
37
|
+
shell: bash
|
|
38
|
+
run: |
|
|
39
|
+
set -euo pipefail
|
|
40
|
+
git clone https://github.com/lukekorthals/pursuing-smooth-pursuits-data companion
|
|
41
|
+
git -C companion checkout 1d7ebec23e3fe20f6db952eefda1a0dd58ae09da
|
|
42
|
+
test "$(git -C companion rev-parse HEAD)" = "1d7ebec23e3fe20f6db952eefda1a0dd58ae09da"
|
|
43
|
+
|
|
44
|
+
- name: Install exact execution stack
|
|
45
|
+
shell: bash
|
|
46
|
+
run: |
|
|
47
|
+
set -euo pipefail
|
|
48
|
+
python -m pip install --upgrade pip
|
|
49
|
+
# The frozen companion relies on pandas 2.x DataFrameGroupBy.apply retaining
|
|
50
|
+
# the grouping column. pandas 3.x drops it by default, which removes
|
|
51
|
+
# trial_number before the companion's blink-masking step.
|
|
52
|
+
python -m pip install "pandas==2.3.3"
|
|
53
|
+
python -m pip install -e .
|
|
54
|
+
python -m pip install ./companion
|
|
55
|
+
python - <<'PY'
|
|
56
|
+
import pandas as pd
|
|
57
|
+
|
|
58
|
+
if pd.__version__ != "2.3.3":
|
|
59
|
+
raise SystemExit(f"unexpected pandas version: {pd.__version__}")
|
|
60
|
+
PY
|
|
61
|
+
|
|
62
|
+
- name: Download complete published OSF source
|
|
63
|
+
shell: bash
|
|
64
|
+
run: |
|
|
65
|
+
set -euo pipefail
|
|
66
|
+
# Frozen companion selection remains exactly:
|
|
67
|
+
# raw_clean="both", train_test="both", participants="all", overwrite=False.
|
|
68
|
+
python - <<'PY'
|
|
69
|
+
from gazeaudit.korthals_osf import fetch_korthals_osf_resumable
|
|
70
|
+
|
|
71
|
+
summary = fetch_korthals_osf_resumable(
|
|
72
|
+
max_attempts=6,
|
|
73
|
+
initial_backoff_seconds=15.0,
|
|
74
|
+
)
|
|
75
|
+
print(
|
|
76
|
+
"verified endpoint-blind OSF transfer: "
|
|
77
|
+
f"files={summary['file_count']} attempts={summary['attempts']} "
|
|
78
|
+
f"retained={summary['retained_verified_files']} "
|
|
79
|
+
f"removed_partials={summary['removed_partial_files']}"
|
|
80
|
+
)
|
|
81
|
+
PY
|
|
82
|
+
|
|
83
|
+
- name: Build endpoint-blind protocol-v2 source intake
|
|
84
|
+
shell: bash
|
|
85
|
+
run: |
|
|
86
|
+
set -euo pipefail
|
|
87
|
+
gazeaudit-korthals-source-intake-v2 \
|
|
88
|
+
--data-root data \
|
|
89
|
+
--output-dir source-intake \
|
|
90
|
+
> source-intake-status.txt
|
|
91
|
+
|
|
92
|
+
- name: Capture dependency environment
|
|
93
|
+
shell: bash
|
|
94
|
+
run: |
|
|
95
|
+
set -euo pipefail
|
|
96
|
+
python -m pip freeze | LC_ALL=C sort > pip-freeze.txt
|
|
97
|
+
test -s pip-freeze.txt
|
|
98
|
+
|
|
99
|
+
- name: Build protocol-v2 source-freeze envelope
|
|
100
|
+
shell: bash
|
|
101
|
+
run: |
|
|
102
|
+
set -euo pipefail
|
|
103
|
+
gazeaudit-korthals-source-freeze-v2 \
|
|
104
|
+
--intake-dir source-intake \
|
|
105
|
+
--output-dir korthals-source-freeze \
|
|
106
|
+
--environment-file pip-freeze.txt \
|
|
107
|
+
--execution-commit "$GITHUB_SHA" \
|
|
108
|
+
--run-id "$GITHUB_RUN_ID" \
|
|
109
|
+
--runner-os "$RUNNER_OS" \
|
|
110
|
+
--runner-arch "$RUNNER_ARCH" \
|
|
111
|
+
> source-freeze-status.json
|
|
112
|
+
|
|
113
|
+
- name: Verify protocol-v2 frozen source envelope before archive
|
|
114
|
+
shell: bash
|
|
115
|
+
run: |
|
|
116
|
+
set -euo pipefail
|
|
117
|
+
python - <<'PY'
|
|
118
|
+
from gazeaudit.korthals_freeze_v2 import (
|
|
119
|
+
verify_korthals_source_freeze_artifacts_v2,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
if not verify_korthals_source_freeze_artifacts_v2("korthals-source-freeze"):
|
|
123
|
+
raise SystemExit("Korthals protocol-v2 source-freeze verification failed")
|
|
124
|
+
PY
|
|
125
|
+
|
|
126
|
+
- name: Archive source freeze before reveal
|
|
127
|
+
uses: actions/upload-artifact@v4
|
|
128
|
+
with:
|
|
129
|
+
name: korthals-source-freeze-v2-${{ github.sha }}
|
|
130
|
+
path: korthals-source-freeze/
|
|
131
|
+
if-no-files-found: error
|
|
132
|
+
retention-days: 90
|
|
133
|
+
compression-level: 0
|
|
134
|
+
|
|
135
|
+
- name: Reveal archived source identity
|
|
136
|
+
shell: bash
|
|
137
|
+
run: |
|
|
138
|
+
set -euo pipefail
|
|
139
|
+
cat source-freeze-status.json
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
name: pedrotti-scientific-execution
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: pedrotti-scientific-execution-v1
|
|
11
|
+
cancel-in-progress: false
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
scientific-execution:
|
|
15
|
+
if: github.ref == 'refs/heads/main'
|
|
16
|
+
runs-on: ubuntu-24.04
|
|
17
|
+
timeout-minutes: 180
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout exact GazeAudit commit
|
|
20
|
+
uses: actions/checkout@v7
|
|
21
|
+
|
|
22
|
+
- name: Set up Python 3.12.14
|
|
23
|
+
uses: actions/setup-python@v7
|
|
24
|
+
with:
|
|
25
|
+
python-version: '3.12.14'
|
|
26
|
+
cache: pip
|
|
27
|
+
|
|
28
|
+
- name: Verify exact main execution identity
|
|
29
|
+
shell: bash
|
|
30
|
+
run: |
|
|
31
|
+
set -euo pipefail
|
|
32
|
+
test "$GITHUB_REF" = "refs/heads/main"
|
|
33
|
+
test "$(git rev-parse HEAD)" = "$GITHUB_SHA"
|
|
34
|
+
|
|
35
|
+
- name: Install frozen scientific stack
|
|
36
|
+
shell: bash
|
|
37
|
+
run: |
|
|
38
|
+
set -euo pipefail
|
|
39
|
+
python -m pip install --upgrade pip
|
|
40
|
+
python -m pip install "numpy==2.5.3" "pandas==2.3.3"
|
|
41
|
+
python -m pip install -e .
|
|
42
|
+
python - <<'PY'
|
|
43
|
+
import platform
|
|
44
|
+
import numpy as np
|
|
45
|
+
import pandas as pd
|
|
46
|
+
|
|
47
|
+
if platform.python_version() != "3.12.14":
|
|
48
|
+
raise SystemExit(f"unexpected Python version: {platform.python_version()}")
|
|
49
|
+
if np.__version__ != "2.5.3":
|
|
50
|
+
raise SystemExit(f"unexpected NumPy version: {np.__version__}")
|
|
51
|
+
if pd.__version__ != "2.3.3":
|
|
52
|
+
raise SystemExit(f"unexpected pandas version: {pd.__version__}")
|
|
53
|
+
PY
|
|
54
|
+
|
|
55
|
+
- name: Download exact checksum-locked Zenodo source
|
|
56
|
+
shell: bash
|
|
57
|
+
run: |
|
|
58
|
+
set -euo pipefail
|
|
59
|
+
python - <<'PY'
|
|
60
|
+
from gazeaudit.pedrotti_fetch import fetch_pedrotti_zenodo_source
|
|
61
|
+
from gazeaudit.pedrotti_prefetch import prefetch_pedrotti_source_bytes
|
|
62
|
+
|
|
63
|
+
prefetch = prefetch_pedrotti_source_bytes(
|
|
64
|
+
"pedrotti-source",
|
|
65
|
+
max_attempts=6,
|
|
66
|
+
initial_backoff_seconds=15.0,
|
|
67
|
+
timeout_seconds=180.0,
|
|
68
|
+
)
|
|
69
|
+
print(
|
|
70
|
+
"checksum-locked redundant byte prefetch: "
|
|
71
|
+
f"files={prefetch['file_count']} "
|
|
72
|
+
f"request_attempts={prefetch['request_attempts']} "
|
|
73
|
+
f"retained={prefetch['retained_verified_files']} "
|
|
74
|
+
f"removed_mismatches={prefetch['removed_mismatched_files']}"
|
|
75
|
+
)
|
|
76
|
+
summary = fetch_pedrotti_zenodo_source(
|
|
77
|
+
"pedrotti-source",
|
|
78
|
+
max_attempts=6,
|
|
79
|
+
initial_backoff_seconds=15.0,
|
|
80
|
+
timeout_seconds=180.0,
|
|
81
|
+
metadata_max_attempts=2,
|
|
82
|
+
metadata_timeout_seconds=30.0,
|
|
83
|
+
)
|
|
84
|
+
print(
|
|
85
|
+
"verified endpoint-blind Zenodo transfer: "
|
|
86
|
+
f"files={summary['file_count']} "
|
|
87
|
+
f"metadata_source={summary['metadata_source']} "
|
|
88
|
+
f"retained={summary['retained_verified_files']} "
|
|
89
|
+
f"removed_mismatches={summary['removed_mismatched_files']}"
|
|
90
|
+
)
|
|
91
|
+
PY
|
|
92
|
+
|
|
93
|
+
- name: Verify locked endpoint-blind intake before scientific execution
|
|
94
|
+
shell: bash
|
|
95
|
+
run: |
|
|
96
|
+
set -euo pipefail
|
|
97
|
+
python - <<'PY'
|
|
98
|
+
from gazeaudit.pedrotti_source import inspect_pedrotti_source
|
|
99
|
+
from gazeaudit.pedrotti_source_lock import (
|
|
100
|
+
verify_pedrotti_locked_intake,
|
|
101
|
+
verify_pedrotti_source_lock,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
verify_pedrotti_source_lock()
|
|
105
|
+
intake = inspect_pedrotti_source("pedrotti-source")
|
|
106
|
+
verify_pedrotti_locked_intake(intake)
|
|
107
|
+
print("Pedrotti endpoint-blind source lock: verified")
|
|
108
|
+
PY
|
|
109
|
+
|
|
110
|
+
- name: Capture frozen dependency environment
|
|
111
|
+
shell: bash
|
|
112
|
+
run: |
|
|
113
|
+
set -euo pipefail
|
|
114
|
+
python -m pip freeze | LC_ALL=C sort > pip-freeze.txt
|
|
115
|
+
test -s pip-freeze.txt
|
|
116
|
+
|
|
117
|
+
- name: Execute frozen protocol and build hidden scientific archive
|
|
118
|
+
shell: bash
|
|
119
|
+
run: |
|
|
120
|
+
set -euo pipefail
|
|
121
|
+
python -m gazeaudit.pedrotti_execution_cli \
|
|
122
|
+
--source-dir pedrotti-source \
|
|
123
|
+
--output-dir pedrotti-scientific-archive \
|
|
124
|
+
--environment-file pip-freeze.txt \
|
|
125
|
+
--execution-commit "$GITHUB_SHA" \
|
|
126
|
+
--run-id "$GITHUB_RUN_ID" \
|
|
127
|
+
--runner-os "$RUNNER_OS" \
|
|
128
|
+
--runner-arch "$RUNNER_ARCH"
|
|
129
|
+
|
|
130
|
+
- name: Verify scientific archive before upload
|
|
131
|
+
shell: bash
|
|
132
|
+
run: |
|
|
133
|
+
set -euo pipefail
|
|
134
|
+
python - <<'PY'
|
|
135
|
+
from gazeaudit.pedrotti_execution import (
|
|
136
|
+
verify_pedrotti_locked_execution_artifacts,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
if not verify_pedrotti_locked_execution_artifacts(
|
|
140
|
+
"pedrotti-scientific-archive"
|
|
141
|
+
):
|
|
142
|
+
raise SystemExit("Pedrotti scientific archive verification failed")
|
|
143
|
+
PY
|
|
144
|
+
|
|
145
|
+
- name: Archive scientific result before reveal
|
|
146
|
+
uses: actions/upload-artifact@v7
|
|
147
|
+
with:
|
|
148
|
+
name: pedrotti-scientific-execution-v1-${{ github.sha }}
|
|
149
|
+
path: pedrotti-scientific-archive/
|
|
150
|
+
if-no-files-found: error
|
|
151
|
+
retention-days: 90
|
|
152
|
+
compression-level: 0
|
|
153
|
+
|
|
154
|
+
- name: Reveal archived scientific result
|
|
155
|
+
shell: bash
|
|
156
|
+
run: |
|
|
157
|
+
set -euo pipefail
|
|
158
|
+
python -m gazeaudit.pedrotti_reveal_cli \
|
|
159
|
+
--archive-dir pedrotti-scientific-archive
|