diag3d 0.2.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.
- diag3d-0.2.0/.github/dependabot.yml +6 -0
- diag3d-0.2.0/.github/workflows/ci.yml +86 -0
- diag3d-0.2.0/.github/workflows/prepare-release.yml +83 -0
- diag3d-0.2.0/.github/workflows/release.yml +146 -0
- diag3d-0.2.0/.gitignore +32 -0
- diag3d-0.2.0/ARCHITECTURE.md +70 -0
- diag3d-0.2.0/BEFORE_AFTER.md +29 -0
- diag3d-0.2.0/BENCHMARK_RESULTS.md +72 -0
- diag3d-0.2.0/CHANGELOG.md +98 -0
- diag3d-0.2.0/CONTRIBUTING.md +5 -0
- diag3d-0.2.0/FLAGSHIP_DEMO.md +18 -0
- diag3d-0.2.0/IMPLEMENTATION_STATUS.md +54 -0
- diag3d-0.2.0/INDEPENDENT_BOOTSTRAP_RESULTS.md +22 -0
- diag3d-0.2.0/LICENSE +21 -0
- diag3d-0.2.0/MODEL_SPACE_ARCHITECTURE.md +74 -0
- diag3d-0.2.0/NESTED_REPAIR_RESULTS.md +36 -0
- diag3d-0.2.0/NULL_CALIBRATION_RESULTS.md +45 -0
- diag3d-0.2.0/PKG-INFO +327 -0
- diag3d-0.2.0/README.md +266 -0
- diag3d-0.2.0/SECURITY.md +3 -0
- diag3d-0.2.0/SOURCE_AUDIT.md +36 -0
- diag3d-0.2.0/THIRD_PARTY_NOTICES.md +38 -0
- diag3d-0.2.0/UX_SPEC.md +50 -0
- diag3d-0.2.0/VALIDATION_RESULTS.md +73 -0
- diag3d-0.2.0/VISUAL_EVIDENCE_REPORT.md +32 -0
- diag3d-0.2.0/docs/architecture.md +60 -0
- diag3d-0.2.0/docs/benchmarks.md +30 -0
- diag3d-0.2.0/docs/consolidation.md +38 -0
- diag3d-0.2.0/docs/dependencies.md +21 -0
- diag3d-0.2.0/docs/figures/concept.svg +284 -0
- diag3d-0.2.0/docs/glb_export.md +147 -0
- diag3d-0.2.0/docs/history/IMPLEMENTATION_STATUS-null-validation.md +39 -0
- diag3d-0.2.0/docs/history/README-null-validation.md +120 -0
- diag3d-0.2.0/docs/legacy/METHODS-v0.1.md +122 -0
- diag3d-0.2.0/docs/legacy/README-v0.1.md +281 -0
- diag3d-0.2.0/docs/legacy/VALIDATION-v0.1.md +74 -0
- diag3d-0.2.0/docs/lifecycle.md +333 -0
- diag3d-0.2.0/docs/lifecycle_audit.md +64 -0
- diag3d-0.2.0/docs/lifecycle_plan.md +92 -0
- diag3d-0.2.0/docs/limitations.md +14 -0
- diag3d-0.2.0/docs/model-space/00-research-explorer-before.png +0 -0
- diag3d-0.2.0/docs/model-space/01-data.png +0 -0
- diag3d-0.2.0/docs/model-space/05-failure.png +0 -0
- diag3d-0.2.0/docs/model-space/07-repair-after.png +0 -0
- diag3d-0.2.0/docs/model-space/08-classification.png +0 -0
- diag3d-0.2.0/docs/model-space/10-wine-pre-run.png +0 -0
- diag3d-0.2.0/docs/packaging-validation.md +37 -0
- diag3d-0.2.0/docs/prior_art_and_novelty_questions.md +39 -0
- diag3d-0.2.0/docs/public_api.md +57 -0
- diag3d-0.2.0/docs/releasing.md +87 -0
- diag3d-0.2.0/docs/research_method.md +150 -0
- diag3d-0.2.0/docs/v01_inventory.json +171 -0
- diag3d-0.2.0/docs/validation/benchmark_results.json +1800 -0
- diag3d-0.2.0/docs/validation/initial_core_only_results.json +1800 -0
- diag3d-0.2.0/docs/validation/model_space_browser.json +60 -0
- diag3d-0.2.0/docs/validation/model_space_handoff.json +19 -0
- diag3d-0.2.0/docs/validation/model_space_performance.json +17 -0
- diag3d-0.2.0/docs/validation/model_space_primary.json +342 -0
- diag3d-0.2.0/docs/validation/null_validation_calibration_sensitivity.json +25 -0
- diag3d-0.2.0/docs/validation/null_validation_experiment_summary.json +459 -0
- diag3d-0.2.0/docs/validation/null_validation_plugin_null_summary.json +7 -0
- diag3d-0.2.0/docs/validation/null_validation_search_precision.json +13 -0
- diag3d-0.2.0/docs/validation/performance_results.json +12 -0
- diag3d-0.2.0/docs/validation/sensitivity_results.json +450 -0
- diag3d-0.2.0/examples/DATASETS.md +32 -0
- diag3d-0.2.0/examples/MODEL_SPACE_DATASETS.md +15 -0
- diag3d-0.2.0/examples/export_glb.py +52 -0
- diag3d-0.2.0/examples/export_previews.py +61 -0
- diag3d-0.2.0/examples/fetch_industry_data.py +156 -0
- diag3d-0.2.0/examples/generate_data.py +55 -0
- diag3d-0.2.0/examples/generate_gallery.py +84 -0
- diag3d-0.2.0/examples/generate_industry_gallery.py +143 -0
- diag3d-0.2.0/examples/industry_catalog.py +99 -0
- diag3d-0.2.0/examples/lifecycle_1_preflight.py +59 -0
- diag3d-0.2.0/examples/lifecycle_2_training.py +125 -0
- diag3d-0.2.0/examples/lifecycle_3_posthoc.py +104 -0
- diag3d-0.2.0/examples/model_space_demos.py +147 -0
- diag3d-0.2.0/examples/python_api.py +31 -0
- diag3d-0.2.0/examples/static_previews.py +153 -0
- diag3d-0.2.0/experiments/calibration_sensitivity.py +139 -0
- diag3d-0.2.0/experiments/make_evidence_report.py +273 -0
- diag3d-0.2.0/experiments/make_figures.py +12 -0
- diag3d-0.2.0/experiments/null_validation.py +419 -0
- diag3d-0.2.0/experiments/performance.py +50 -0
- diag3d-0.2.0/experiments/plot_acceptance.py +80 -0
- diag3d-0.2.0/experiments/plugin_null_pilot.py +81 -0
- diag3d-0.2.0/experiments/refresh_refit.py +59 -0
- diag3d-0.2.0/experiments/run_benchmarks.py +60 -0
- diag3d-0.2.0/experiments/search_precision.py +103 -0
- diag3d-0.2.0/experiments/sensitivity.py +65 -0
- diag3d-0.2.0/pyproject.toml +72 -0
- diag3d-0.2.0/src/diag3d/__init__.py +67 -0
- diag3d-0.2.0/src/diag3d/__main__.py +3 -0
- diag3d-0.2.0/src/diag3d/_version.py +1 -0
- diag3d-0.2.0/src/diag3d/baselines.py +246 -0
- diag3d-0.2.0/src/diag3d/cli.py +849 -0
- diag3d-0.2.0/src/diag3d/config.py +27 -0
- diag3d-0.2.0/src/diag3d/dataset.py +160 -0
- diag3d-0.2.0/src/diag3d/diagnostics.py +283 -0
- diag3d-0.2.0/src/diag3d/lifecycle/__init__.py +39 -0
- diag3d-0.2.0/src/diag3d/lifecycle/figures.py +103 -0
- diag3d-0.2.0/src/diag3d/lifecycle/findings.py +128 -0
- diag3d-0.2.0/src/diag3d/lifecycle/investigate.py +347 -0
- diag3d-0.2.0/src/diag3d/lifecycle/monitor.py +720 -0
- diag3d-0.2.0/src/diag3d/lifecycle/posthoc.py +984 -0
- diag3d-0.2.0/src/diag3d/lifecycle/predictions.py +529 -0
- diag3d-0.2.0/src/diag3d/lifecycle/preflight.py +783 -0
- diag3d-0.2.0/src/diag3d/lifecycle/report.py +199 -0
- diag3d-0.2.0/src/diag3d/lifecycle/run.py +694 -0
- diag3d-0.2.0/src/diag3d/lifecycle/splits.py +289 -0
- diag3d-0.2.0/src/diag3d/lifecycle/workflow.py +121 -0
- diag3d-0.2.0/src/diag3d/model_space/__init__.py +6 -0
- diag3d-0.2.0/src/diag3d/model_space/adapters.py +138 -0
- diag3d-0.2.0/src/diag3d/model_space/assets/explorer.css +10 -0
- diag3d-0.2.0/src/diag3d/model_space/assets/explorer.html +29 -0
- diag3d-0.2.0/src/diag3d/model_space/assets/explorer.js +298 -0
- diag3d-0.2.0/src/diag3d/model_space/diagnostics.py +143 -0
- diag3d-0.2.0/src/diag3d/model_space/glb.py +605 -0
- diag3d-0.2.0/src/diag3d/model_space/session.py +498 -0
- diag3d-0.2.0/src/diag3d/modeling.py +265 -0
- diag3d-0.2.0/src/diag3d/profiling.py +137 -0
- diag3d-0.2.0/src/diag3d/relationships.py +166 -0
- diag3d-0.2.0/src/diag3d/reporting.py +566 -0
- diag3d-0.2.0/src/diag3d/research/__init__.py +19 -0
- diag3d-0.2.0/src/diag3d/research/analyzer.py +287 -0
- diag3d-0.2.0/src/diag3d/research/benchmarks.py +196 -0
- diag3d-0.2.0/src/diag3d/research/calibration.py +298 -0
- diag3d-0.2.0/src/diag3d/research/config.py +94 -0
- diag3d-0.2.0/src/diag3d/research/diagnostics.py +158 -0
- diag3d-0.2.0/src/diag3d/research/discovery.py +155 -0
- diag3d-0.2.0/src/diag3d/research/explorer.py +523 -0
- diag3d-0.2.0/src/diag3d/research/fields.py +115 -0
- diag3d-0.2.0/src/diag3d/research/figures.py +1098 -0
- diag3d-0.2.0/src/diag3d/research/nested.py +457 -0
- diag3d-0.2.0/src/diag3d/research/nulls.py +73 -0
- diag3d-0.2.0/src/diag3d/research/oof.py +197 -0
- diag3d-0.2.0/src/diag3d/research/refit.py +220 -0
- diag3d-0.2.0/src/diag3d/research/repairs.py +205 -0
- diag3d-0.2.0/src/diag3d/research/stability.py +135 -0
- diag3d-0.2.0/src/diag3d/research/types.py +360 -0
- diag3d-0.2.0/src/diag3d/spatial.py +86 -0
- diag3d-0.2.0/src/diag3d/surfaces.py +94 -0
- diag3d-0.2.0/src/diag3d/utils.py +71 -0
- diag3d-0.2.0/src/diag3d/visualization.py +423 -0
- diag3d-0.2.0/tests/conftest.py +34 -0
- diag3d-0.2.0/tests/industry_runtime.mjs +45 -0
- diag3d-0.2.0/tests/lifecycle_data.py +51 -0
- diag3d-0.2.0/tests/model_space_runtime.cjs +91 -0
- diag3d-0.2.0/tests/report_runtime.mjs +60 -0
- diag3d-0.2.0/tests/research_runtime.mjs +21 -0
- diag3d-0.2.0/tests/test_baselines.py +118 -0
- diag3d-0.2.0/tests/test_dataset.py +100 -0
- diag3d-0.2.0/tests/test_diagnostics.py +62 -0
- diag3d-0.2.0/tests/test_edge_cases.py +61 -0
- diag3d-0.2.0/tests/test_glb.py +287 -0
- diag3d-0.2.0/tests/test_industry_gallery.py +99 -0
- diag3d-0.2.0/tests/test_lifecycle_audit.py +765 -0
- diag3d-0.2.0/tests/test_lifecycle_e2e.py +249 -0
- diag3d-0.2.0/tests/test_lifecycle_examples.py +47 -0
- diag3d-0.2.0/tests/test_lifecycle_membership.py +192 -0
- diag3d-0.2.0/tests/test_lifecycle_monitor.py +299 -0
- diag3d-0.2.0/tests/test_lifecycle_portability.py +84 -0
- diag3d-0.2.0/tests/test_lifecycle_posthoc.py +283 -0
- diag3d-0.2.0/tests/test_lifecycle_predictions.py +168 -0
- diag3d-0.2.0/tests/test_lifecycle_preflight.py +189 -0
- diag3d-0.2.0/tests/test_lifecycle_regressions.py +28 -0
- diag3d-0.2.0/tests/test_lifecycle_run.py +124 -0
- diag3d-0.2.0/tests/test_model_space.py +326 -0
- diag3d-0.2.0/tests/test_modeling.py +77 -0
- diag3d-0.2.0/tests/test_null_validation.py +337 -0
- diag3d-0.2.0/tests/test_public_api.py +71 -0
- diag3d-0.2.0/tests/test_release_gates.py +145 -0
- diag3d-0.2.0/tests/test_reporting_cli.py +128 -0
- diag3d-0.2.0/tests/test_research_engine.py +478 -0
- diag3d-0.2.0/tests/test_research_packaging.py +29 -0
- diag3d-0.2.0/tests/test_scientific_figures.py +60 -0
- diag3d-0.2.0/tests/test_visualizations.py +64 -0
- diag3d-0.2.0/tools/check_distribution.py +156 -0
- diag3d-0.2.0/tools/index_release.py +117 -0
- diag3d-0.2.0/tools/lifecycle_mutations.py +117 -0
- diag3d-0.2.0/tools/package_smoke.py +135 -0
- diag3d-0.2.0/tools/release.py +25 -0
- diag3d-0.2.0/tools/security_scan.py +95 -0
- diag3d-0.2.0/tools/test_distribution.py +41 -0
- diag3d-0.2.0/tools/validate_evidence.py +98 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
name: Scientific tests and package
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
pull_request:
|
|
5
|
+
workflow_call:
|
|
6
|
+
inputs:
|
|
7
|
+
expected_tag:
|
|
8
|
+
type: string
|
|
9
|
+
default: ''
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
env:
|
|
13
|
+
OMP_NUM_THREADS: '1'
|
|
14
|
+
OPENBLAS_NUM_THREADS: '1'
|
|
15
|
+
POLARS_MAX_THREADS: '2'
|
|
16
|
+
PYTHONUTF8: '1'
|
|
17
|
+
jobs:
|
|
18
|
+
test:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
matrix:
|
|
23
|
+
python: ['3.11', '3.12', '3.13']
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
|
+
with:
|
|
27
|
+
persist-credentials: false
|
|
28
|
+
fetch-depth: 0
|
|
29
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
30
|
+
with:
|
|
31
|
+
python-version: ${{ matrix.python }}
|
|
32
|
+
- run: python -m pip install '.[dev,gallery]'
|
|
33
|
+
- run: python -m compileall -q src
|
|
34
|
+
- run: python -m ruff check src tests experiments tools
|
|
35
|
+
- run: python -m pytest -q
|
|
36
|
+
- run: python tools/security_scan.py --history
|
|
37
|
+
- name: Installed wheel and sdist smoke test on this Python
|
|
38
|
+
run: |
|
|
39
|
+
python -m build --outdir "$RUNNER_TEMP/dist"
|
|
40
|
+
python tools/test_distribution.py "$RUNNER_TEMP"/dist/*
|
|
41
|
+
windows:
|
|
42
|
+
runs-on: windows-latest
|
|
43
|
+
env:
|
|
44
|
+
PYTHONUTF8: '0' # the default code page, so encoding regressions surface here
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
47
|
+
with:
|
|
48
|
+
persist-credentials: false
|
|
49
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
50
|
+
with:
|
|
51
|
+
python-version: '3.12'
|
|
52
|
+
- run: python -m pip install ".[dev,gallery]"
|
|
53
|
+
- run: python -m pytest -q
|
|
54
|
+
build:
|
|
55
|
+
needs: [test, windows]
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
59
|
+
with:
|
|
60
|
+
persist-credentials: false
|
|
61
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
62
|
+
with:
|
|
63
|
+
python-version: '3.12'
|
|
64
|
+
- run: python -m pip install 'build>=1.2,<2' 'twine>=6,<8'
|
|
65
|
+
- name: Build wheel from sdist with a reproducible timestamp
|
|
66
|
+
run: |
|
|
67
|
+
export SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)
|
|
68
|
+
python -m build
|
|
69
|
+
- run: python -m twine check --strict dist/*
|
|
70
|
+
- name: Validate distribution contents and version
|
|
71
|
+
env:
|
|
72
|
+
EXPECTED_TAG: ${{ inputs.expected_tag }}
|
|
73
|
+
run: |
|
|
74
|
+
if [ -n "$EXPECTED_TAG" ]; then
|
|
75
|
+
python tools/check_distribution.py --tag "$EXPECTED_TAG"
|
|
76
|
+
else
|
|
77
|
+
python tools/check_distribution.py
|
|
78
|
+
fi
|
|
79
|
+
- name: Analyze using clean wheel and sdist installations
|
|
80
|
+
run: python tools/test_distribution.py dist/*
|
|
81
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
82
|
+
with:
|
|
83
|
+
name: python-dist
|
|
84
|
+
path: dist/
|
|
85
|
+
if-no-files-found: error
|
|
86
|
+
retention-days: 30
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
name: Prepare release
|
|
2
|
+
# Creates the version tag and a DRAFT GitHub Release with notes taken from CHANGELOG.md.
|
|
3
|
+
# Nothing is published: publishing the draft (a deliberate human action) fires the
|
|
4
|
+
# Release workflow, which stages on TestPyPI, publishes to PyPI through trusted
|
|
5
|
+
# publishing and attaches the verified artifacts.
|
|
6
|
+
on:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
version:
|
|
10
|
+
description: 'Stable version to release, e.g. 0.2.0 (must equal src/diag3d/_version.py on main)'
|
|
11
|
+
type: string
|
|
12
|
+
required: true
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
env:
|
|
16
|
+
OMP_NUM_THREADS: '1'
|
|
17
|
+
OPENBLAS_NUM_THREADS: '1'
|
|
18
|
+
POLARS_MAX_THREADS: '2'
|
|
19
|
+
PYTHONUTF8: '1'
|
|
20
|
+
jobs:
|
|
21
|
+
prepare:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
permissions:
|
|
24
|
+
contents: write
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
27
|
+
with:
|
|
28
|
+
persist-credentials: false
|
|
29
|
+
fetch-depth: 0
|
|
30
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
31
|
+
with:
|
|
32
|
+
python-version: '3.12'
|
|
33
|
+
- name: Require main, a stable version, a matching _version.py and a changelog entry
|
|
34
|
+
env:
|
|
35
|
+
VERSION: ${{ inputs.version }}
|
|
36
|
+
run: |
|
|
37
|
+
test "$GITHUB_REF" = "refs/heads/main"
|
|
38
|
+
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]
|
|
39
|
+
grep -qx "__version__ = \"$VERSION\"" src/diag3d/_version.py
|
|
40
|
+
grep -q "^## $VERSION " CHANGELOG.md
|
|
41
|
+
if git rev-parse -q --verify "refs/tags/v$VERSION" >/dev/null; then
|
|
42
|
+
echo "Tag v$VERSION already exists"; exit 1
|
|
43
|
+
fi
|
|
44
|
+
- run: python -m pip install ".[dev,gallery]"
|
|
45
|
+
- run: python -m compileall -q src
|
|
46
|
+
- run: python -m ruff check src tests experiments tools
|
|
47
|
+
- run: python -m pytest -q
|
|
48
|
+
- run: python tools/security_scan.py --history
|
|
49
|
+
- name: Build and audit the distributions
|
|
50
|
+
run: |
|
|
51
|
+
export SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)
|
|
52
|
+
python -m build
|
|
53
|
+
python -m twine check --strict dist/*
|
|
54
|
+
python tools/check_distribution.py --tag "v${{ inputs.version }}"
|
|
55
|
+
- name: Extract release notes from CHANGELOG.md
|
|
56
|
+
env:
|
|
57
|
+
VERSION: ${{ inputs.version }}
|
|
58
|
+
run: |
|
|
59
|
+
python - <<'EOF'
|
|
60
|
+
import os, re, pathlib
|
|
61
|
+
version = os.environ["VERSION"]
|
|
62
|
+
text = pathlib.Path("CHANGELOG.md").read_text(encoding="utf-8")
|
|
63
|
+
match = re.search(rf"^## {re.escape(version)}[^\n]*\n(.*?)(?=^## |\Z)", text, re.S | re.M)
|
|
64
|
+
body = match.group(1).strip() if match else ""
|
|
65
|
+
if not body:
|
|
66
|
+
raise SystemExit("No changelog section for this version")
|
|
67
|
+
notes = (f"{body}\n\n## Installation\n\n```bash\npip install diag3d=={version}\n"
|
|
68
|
+
"```\n\nmacOS: `brew tap falhezaimi/tap && brew install diag3d`\n\n"
|
|
69
|
+
"Wheel, sdist and SHA256SUMS are attached after PyPI publication is verified.\n")
|
|
70
|
+
pathlib.Path("release_notes.md").write_text(notes, encoding="utf-8")
|
|
71
|
+
EOF
|
|
72
|
+
- name: Create the annotated tag and a draft release
|
|
73
|
+
env:
|
|
74
|
+
GH_TOKEN: ${{ github.token }}
|
|
75
|
+
VERSION: ${{ inputs.version }}
|
|
76
|
+
run: |
|
|
77
|
+
git config user.name "github-actions[bot]"
|
|
78
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
79
|
+
git tag -a "v$VERSION" -m "Diag3D $VERSION"
|
|
80
|
+
git push "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "refs/tags/v$VERSION"
|
|
81
|
+
gh release create "v$VERSION" --draft --verify-tag --title "Diag3D $VERSION" \
|
|
82
|
+
--notes-file release_notes.md
|
|
83
|
+
echo "Draft release v$VERSION created; stage it with the Release workflow, then publish the draft."
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
on:
|
|
3
|
+
workflow_dispatch:
|
|
4
|
+
inputs:
|
|
5
|
+
tag:
|
|
6
|
+
description: 'Approved stable tag to stage on TestPyPI, e.g. v0.2.0; select the same tag as ref'
|
|
7
|
+
type: string
|
|
8
|
+
required: true
|
|
9
|
+
release:
|
|
10
|
+
types: [published]
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
concurrency:
|
|
14
|
+
group: release-${{ github.event.release.tag_name || inputs.tag }}
|
|
15
|
+
cancel-in-progress: false
|
|
16
|
+
env:
|
|
17
|
+
OMP_NUM_THREADS: '1'
|
|
18
|
+
OPENBLAS_NUM_THREADS: '1'
|
|
19
|
+
POLARS_MAX_THREADS: '2'
|
|
20
|
+
jobs:
|
|
21
|
+
gate:
|
|
22
|
+
if: github.event_name == 'workflow_dispatch' || (!github.event.release.prerelease && !github.event.release.draft)
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- name: Require an explicit stable version tag and matching ref
|
|
26
|
+
env:
|
|
27
|
+
TAG: ${{ github.event.release.tag_name || inputs.tag }}
|
|
28
|
+
run: |
|
|
29
|
+
[[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]
|
|
30
|
+
test "$GITHUB_REF" = "refs/tags/$TAG"
|
|
31
|
+
validate:
|
|
32
|
+
needs: gate
|
|
33
|
+
uses: ./.github/workflows/ci.yml
|
|
34
|
+
with:
|
|
35
|
+
expected_tag: ${{ github.event.release.tag_name || inputs.tag }}
|
|
36
|
+
staging-status:
|
|
37
|
+
needs: validate
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
outputs:
|
|
40
|
+
already_staged: ${{ steps.status.outputs.already_staged }}
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
43
|
+
with:
|
|
44
|
+
persist-credentials: false
|
|
45
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
46
|
+
with:
|
|
47
|
+
python-version: '3.12'
|
|
48
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
49
|
+
with:
|
|
50
|
+
name: python-dist
|
|
51
|
+
path: dist/
|
|
52
|
+
- id: status
|
|
53
|
+
run: python tools/index_release.py stage-check --index testpypi
|
|
54
|
+
- name: Reject an existing production version
|
|
55
|
+
if: github.event_name == 'release'
|
|
56
|
+
run: python tools/index_release.py unused --index pypi
|
|
57
|
+
testpypi:
|
|
58
|
+
needs: staging-status
|
|
59
|
+
# Explicit opt-in: nothing is uploaded unless the repository enables staging.
|
|
60
|
+
if: needs.staging-status.outputs.already_staged != 'true' && vars.TESTPYPI_RELEASE_ENABLED == 'true'
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
environment:
|
|
63
|
+
name: testpypi
|
|
64
|
+
url: https://test.pypi.org/p/diag3d
|
|
65
|
+
permissions:
|
|
66
|
+
id-token: write
|
|
67
|
+
steps:
|
|
68
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
69
|
+
with:
|
|
70
|
+
name: python-dist
|
|
71
|
+
path: dist/
|
|
72
|
+
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
|
73
|
+
with:
|
|
74
|
+
repository-url: https://test.pypi.org/legacy/
|
|
75
|
+
skip-existing: false
|
|
76
|
+
print-hash: true
|
|
77
|
+
attestations: true
|
|
78
|
+
verify-testpypi:
|
|
79
|
+
needs: [staging-status, testpypi]
|
|
80
|
+
if: ${{ !cancelled() && vars.TESTPYPI_RELEASE_ENABLED == 'true' && needs.staging-status.result == 'success' && (needs.testpypi.result == 'success' || needs.testpypi.result == 'skipped') }}
|
|
81
|
+
runs-on: ubuntu-latest
|
|
82
|
+
steps:
|
|
83
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
84
|
+
with:
|
|
85
|
+
persist-credentials: false
|
|
86
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
87
|
+
with:
|
|
88
|
+
python-version: '3.12'
|
|
89
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
90
|
+
with:
|
|
91
|
+
name: python-dist
|
|
92
|
+
path: dist/
|
|
93
|
+
- run: python tools/index_release.py verify --index testpypi
|
|
94
|
+
pypi:
|
|
95
|
+
needs: verify-testpypi
|
|
96
|
+
if: ${{ !cancelled() && needs.verify-testpypi.result == 'success' && github.event_name == 'release' && vars.PYPI_RELEASE_ENABLED == 'true' }}
|
|
97
|
+
runs-on: ubuntu-latest
|
|
98
|
+
environment:
|
|
99
|
+
name: pypi
|
|
100
|
+
url: https://pypi.org/p/diag3d
|
|
101
|
+
permissions:
|
|
102
|
+
id-token: write
|
|
103
|
+
steps:
|
|
104
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
105
|
+
with:
|
|
106
|
+
name: python-dist
|
|
107
|
+
path: dist/
|
|
108
|
+
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
|
109
|
+
with:
|
|
110
|
+
skip-existing: false
|
|
111
|
+
print-hash: true
|
|
112
|
+
attestations: true
|
|
113
|
+
verify-production:
|
|
114
|
+
needs: pypi
|
|
115
|
+
runs-on: ubuntu-latest
|
|
116
|
+
steps:
|
|
117
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
118
|
+
with:
|
|
119
|
+
persist-credentials: false
|
|
120
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
121
|
+
with:
|
|
122
|
+
python-version: '3.12'
|
|
123
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
124
|
+
with:
|
|
125
|
+
name: python-dist
|
|
126
|
+
path: dist/
|
|
127
|
+
- run: python tools/index_release.py verify --index pypi
|
|
128
|
+
release-assets:
|
|
129
|
+
needs: verify-production
|
|
130
|
+
runs-on: ubuntu-latest
|
|
131
|
+
permissions:
|
|
132
|
+
contents: write
|
|
133
|
+
steps:
|
|
134
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
135
|
+
with:
|
|
136
|
+
name: python-dist
|
|
137
|
+
path: dist/
|
|
138
|
+
- name: Attach the verified distributions and checksums
|
|
139
|
+
env:
|
|
140
|
+
GH_TOKEN: ${{ github.token }}
|
|
141
|
+
GH_REPO: ${{ github.repository }}
|
|
142
|
+
TAG: ${{ github.event.release.tag_name }}
|
|
143
|
+
run: |
|
|
144
|
+
cd dist
|
|
145
|
+
sha256sum *.whl *.tar.gz > SHA256SUMS
|
|
146
|
+
gh release upload "$TAG" *.whl *.tar.gz SHA256SUMS
|
diag3d-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
.pytest_cache/
|
|
5
|
+
.ruff_cache/
|
|
6
|
+
.venv/
|
|
7
|
+
venv/
|
|
8
|
+
build/
|
|
9
|
+
dist/
|
|
10
|
+
wheelhouse/
|
|
11
|
+
.env
|
|
12
|
+
.env.*
|
|
13
|
+
*.pem
|
|
14
|
+
*.key
|
|
15
|
+
*.p12
|
|
16
|
+
*.pfx
|
|
17
|
+
.DS_Store
|
|
18
|
+
gallery/
|
|
19
|
+
/validation/
|
|
20
|
+
benchmark_outputs/
|
|
21
|
+
results/
|
|
22
|
+
.industry_cache/
|
|
23
|
+
examples/industry_data/
|
|
24
|
+
*.log
|
|
25
|
+
|
|
26
|
+
/Diag3D-v0.2-research-evidence.html
|
|
27
|
+
|
|
28
|
+
lifecycle_output/
|
|
29
|
+
.pypirc
|
|
30
|
+
.venv*/
|
|
31
|
+
*.whl
|
|
32
|
+
*.tar.gz
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
The authoritative 0.2.0.dev0 development tree is created from the supplied v0.1 implementation. Legacy modules remain; research modules are additive and import the established Plotly/report shell.
|
|
4
|
+
|
|
5
|
+
| Module | Responsibility and principal interfaces |
|
|
6
|
+
|---|---|
|
|
7
|
+
| `research/types.py` | Typed `PredictionRecord`, columnar `PredictionBatch`, `FoldPlan`, `OOFResult`, `ErrorField`, `FailureRegion`, `RegionMetrics`, `PersistenceResult`, `StabilityResult`, `CrossModelRegionAnalysis`, `SupportDiagnostics`, `FailureCharacterization`, `EvidenceScore`, `RepairExperimentResult`, `AnalysisResult` |
|
|
8
|
+
| `research/config.py` | Validated analysis limits, score weights, characterization thresholds |
|
|
9
|
+
| `research/oof.py` | Input validation, immutable reused fold plan, seeded cloned estimators, train-fold transforms, OOF predictions, train-relative support |
|
|
10
|
+
| `research/fields.py` | Uniform/quantile 1D/2D binning, weighted empirical loss aggregation, support mask; `ErrorFieldEstimator` protocol |
|
|
11
|
+
| `research/discovery.py` | Connected components, threshold lineages, core/extent geometry, Jaccard deduplication; `DiscoveryStrategy` protocol |
|
|
12
|
+
| `research/stability.py` | Conditional row/group bootstrap and held-out fold rediscovery |
|
|
13
|
+
| `research/diagnostics.py` | Cross-model disagreement, support interpretation, explicit taxonomy, exposed weighted ranking |
|
|
14
|
+
| `research/analyzer.py` | `FailureAnalyzer.fit_analyze`, default model factories, bounded orchestration, reproducibility metadata |
|
|
15
|
+
| `research/repairs.py` | Nested training-only selection; weighting, interaction, alternative estimator and resampling experiments |
|
|
16
|
+
| `research/explorer.py` | Offline 1D/3D evidence figures, exact exposed cell boundaries, model/overlay controls, report sections and region inspection |
|
|
17
|
+
| `research/benchmarks.py` | Six deterministic mechanisms, planted masks/bounds, localization evaluation |
|
|
18
|
+
| `experiments/` | Reproducible full suite, seed/grid sensitivity and null audit |
|
|
19
|
+
| `cli.py` | Seven commands; new `analyze` delegates to `FailureAnalyzer` |
|
|
20
|
+
|
|
21
|
+
`AnalysisResult` retains numeric fields, OOF batches and typed regional evidence. `.visualize()` returns a Plotly figure; `.report(path)` writes standalone HTML; `.save(directory)` also writes strict JSON and observation-level OOF CSV. JSON export has no pickled estimators or executable payloads.
|
|
22
|
+
|
|
23
|
+
## Preserved v0.1 architecture
|
|
24
|
+
|
|
25
|
+
- `dataset.py`: strict CSV loading, Polars frames, deterministic row caps and original Dataset API.
|
|
26
|
+
- `profiling.py`, `diagnostics.py`, `relationships.py`: column profiling, diagnostic flags, VIF, dependence and exploratory pair screening.
|
|
27
|
+
- `modeling.py`: original single-held-out baseline result and metrics.
|
|
28
|
+
- `visualization.py`, `surfaces.py`, `spatial.py`: relationship clouds, residual/disagreement landscapes, support-masked response surfaces and coordinate views.
|
|
29
|
+
- `reporting.py`: offline Plotly bundling, responsive report shell, lazy rendering and camera controls.
|
|
30
|
+
- `utils.py`, `config.py`: shared formatting, errors, limits and centralized version.
|
|
31
|
+
|
|
32
|
+
The original 2,713 source lines were inspected. Machine-readable public class/function inventory is in `docs/v01_inventory.json`. The original archive's 79 tests passed before changes. Generated legacy industry galleries and downloaded datasets are excluded from source; their 12 asset checks remain optional and skip when the assets are absent. The other 67 baseline tests remain active.
|
|
33
|
+
|
|
34
|
+
## Source provenance
|
|
35
|
+
|
|
36
|
+
| Input | Role | SHA-256 |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `Diag3D-v0.1.0(1).zip` | Implementation foundation | `d2cb469745008c968cf7a2917e232b6dd15ee298a9a392c238ffe0a5c89ce6a6` |
|
|
39
|
+
| `Diag3D-packaging-candidate.zip` | Reference for dynamic versioning, artifact exclusions, metadata and release separation | `21eb9c15ce47fff942ffc23ff71ba7088229083069ee96e13158d82d212065e2` |
|
|
40
|
+
|
|
41
|
+
No recovered research-reset source was substituted. Packaging reference science modules were not copied over v0.1. Public samples are recreated from generators or fetched with documented attribution; research data, caches, model binaries and generated galleries are not committed.
|
|
42
|
+
|
|
43
|
+
## Performance and extension boundaries
|
|
44
|
+
|
|
45
|
+
Fold indices, observation-level OOF losses and support transforms are computed once and reused. Uniform/quantile field aggregation uses bincount and bounded grids. Nearest-neighbor queries avoid materializing n×n distance matrices, although high-dimensional nearest-neighbor search can still be expensive. Estimator `n_jobs` is configurable; folds run sequentially to bound memory and BLAS thread pools are capped. Feature count, pair count, grid resolution, candidate count and bootstrap replicates are bounded.
|
|
46
|
+
|
|
47
|
+
Bootstrap currently recalculates grids per candidate/replicate, preserving simple auditable logic at additional cost. It does not cache results to disk. The field/discovery protocols allow compatible grid strategies; custom geometry would also require changing matching, membership and visualization contracts. Categorical discovery, classification, arbitrary-dimensional regions, persistent homology and full model-refit bootstrap are not implemented.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
## Null-validation modules
|
|
51
|
+
|
|
52
|
+
The existing v0.2 tree is extended by `calibration.py`, `nulls.py`, `refit.py`, `nested.py`, and optional `figures.py`. Public methods are `FailureAnalyzer.calibrate`, `refit_bootstrap`, and `validate_repairs`. Null maxima repeat the complete configured search; duplicate bootstrap identities never cross folds; strategy selection accepts outer-training data only. Typed results retain replicate maxima, p calculations, refit geometries and outer-fold predictions. See [detailed architecture](docs/architecture.md).
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
## Lifecycle layer (`src/diag3d/lifecycle/`)
|
|
56
|
+
|
|
57
|
+
| Module | Responsibility |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `findings.py` | `Finding` (observation vs hypothesis, rule/version, evidence, counts, threshold, status incl. `not_evaluable`) |
|
|
60
|
+
| `predictions.py` | `PredictionTable` keyed by `(sample_id, model, repeat, fold, seed, role, checkpoint)`; loaders; alignment |
|
|
61
|
+
| `run.py` | `Run` directory: manifest, events, split, predictions, findings, artifacts; atomic writes; lock |
|
|
62
|
+
| `preflight.py` | Data-quality and split-design checks; no model fitting |
|
|
63
|
+
| `monitor.py` | `TrainingMonitor` events, checkpoint checks, LightGBM callback |
|
|
64
|
+
| `investigate.py` | Bounded advisory follow-up checks with audit records |
|
|
65
|
+
| `posthoc.py` | Frozen-prediction diagnostics; `oof_from_predictions` bridge to `FailureAnalyzer.analyze_oof` |
|
|
66
|
+
| `splits.py` | `SplitManifest`: explicit or verified per-fold membership |
|
|
67
|
+
| `report.py`, `figures.py` | Redacted outputs, `export_error_glb` (via the canonical `model_space/glb.py` exporter), optional Matplotlib figures |
|
|
68
|
+
| `workflow.py` | `preflight_run`, `posthoc_run`, `reproduce_posthoc` |
|
|
69
|
+
|
|
70
|
+
`research/oof.assemble_oof` is shared by fitted and imported predictions. See [docs/lifecycle.md](docs/lifecycle.md).
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Before / after explorer comparison
|
|
2
|
+
|
|
3
|
+
| Aspect | Existing v0.2 research explorer | New model-space explorer |
|
|
4
|
+
|---|---|---|
|
|
5
|
+
| Entry | Static research report with embedded local-error scenes | Immediate shared 3D environment |
|
|
6
|
+
| Primary identity | Failure-region evidence | Pre-run and post-run spatial model exploration, with research evidence integrated |
|
|
7
|
+
| Navigation | Report sections | DATA → MODEL → PREDICTION → ERROR → FAILURE → REPAIR |
|
|
8
|
+
| Data before training | Separate legacy diagnostic report | Same viewport, missingness/support/target/correlation/shift inspection |
|
|
9
|
+
| Supplied y/y_pred | Residual visualization command | Full CSV model-space workflow, no model file |
|
|
10
|
+
| Camera and selection | Separate scenes and controls | One stateful camera and persistent row/region identity |
|
|
11
|
+
| Failure evidence | Existing model/overlay/region controls | Same evidence in a compact inspector, exact union outlines and explicit source model |
|
|
12
|
+
| Repair | Reported numerical experiments | Actual outer-prediction endpoint replay and guardrail table |
|
|
13
|
+
| Classification | No calibrated discovery engine | Class/probability/confidence/error exploration; inference limitation explicit |
|
|
14
|
+
| Fitted models | Existing research estimator API | Optional adapter for model queries and selected linear/tree explanations |
|
|
15
|
+
| Browser validation | Prior pixel rendering unverified | Chromium/WebGL tested, including mobile sizing and zero external requests |
|
|
16
|
+
|
|
17
|
+
The original evidence report remains separately available. Its only code change is renaming a colliding browser observer variable; numerical evidence and discovery logic are unchanged.
|
|
18
|
+
|
|
19
|
+
## Existing research scene
|
|
20
|
+
|
|
21
|
+

|
|
22
|
+
|
|
23
|
+
## Unified failure space
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
|
|
27
|
+
## Validated repair endpoint
|
|
28
|
+
|
|
29
|
+

|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Actual synthetic benchmark results
|
|
2
|
+
|
|
3
|
+
Executed locally with version 0.2.0.dev0, seed 42, 2,400 observations per case, five validation folds, 20 conditional bootstrap replicates, ten grid bins, minimum cell support 4 and region support 20. All values below come from actual runs. No ground-truth masks are supplied to the detector.
|
|
4
|
+
|
|
5
|
+
## Localization and stability
|
|
6
|
+
|
|
7
|
+
| Case | Best IoU | Precision | Recall | Samples | Error lift | Persistence | Bootstrap | Eligible-fold recurrence | Diagnostic candidate |
|
|
8
|
+
|---|---:|---:|---:|---:|---:|---:|---:|---:|---|
|
|
9
|
+
| A | 0.9955 | 1.0000 | 0.9955 | 220 | 4.490× | 100% | 100% | 100% (5/5 eligible) | SHARED_STRUCTURAL_FAILURE |
|
|
10
|
+
| B | 1.0000 | 1.0000 | 1.0000 | 68 | 17.556× | 100% | 100% | 100% (5/5 eligible) | DATA_SPARSE_FAILURE |
|
|
11
|
+
| C | 1.0000 | 1.0000 | 1.0000 | 384 | 5.099× | 100% | 100% | 100% (5/5 eligible) | SHARED_STRUCTURAL_FAILURE |
|
|
12
|
+
| D | 1.0000 | 1.0000 | 1.0000 | 449 | 3.778× | 100% | 65% | 100% (1/5 eligible) | EXTRAPOLATION_FAILURE |
|
|
13
|
+
| F | 0.9955 | 1.0000 | 0.9955 | 220 | 4.487× | 100% | 100% | 100% (5/5 eligible) | MODEL_SPECIFIC_FAILURE |
|
|
14
|
+
|
|
15
|
+
IoU is observation-membership Jaccard. Benchmark scoring chooses the best-IoU candidate; the detector never sees ground truth. In D, the broader extent is F-02; the top-ranked severe core covers approximately half the true region. The 1/1 eligible-fold result in D must not be described as recurrence across all five folds.
|
|
16
|
+
|
|
17
|
+
## Primary acceptance: A
|
|
18
|
+
|
|
19
|
+
- Planted rectangle: 0.2 < x1 < 0.8 and 0.2 < x2 < 0.8; 221 true observations.
|
|
20
|
+
- Detected F-01: exact union of nine adjacent cells, with enclosing bounds x1 [0.200173, 0.799691], x2 [0.199706, 0.799040]; 220 observations.
|
|
21
|
+
- Source-model MAE 3.8363, global MAE 0.8543, lift 4.4904×; local relative density 1.0652 and training-neighbor distance ratio 0.9629.
|
|
22
|
+
- Threshold lineage spans all six thresholds from 1.25× to 4×, with 20/20 bootstrap detections and 5/5 eligible fold detections.
|
|
23
|
+
- Shared-error candidate among two deliberately restricted Ridge baselines. These are two estimators from one family, not two independent model families.
|
|
24
|
+
- Report includes the computed surface, support/disagreement/persistence overlays, exact cell edges and region inspection. A static figure is generated by `experiments/plot_acceptance.py`.
|
|
25
|
+
|
|
26
|
+
## Distinct secondary signatures
|
|
27
|
+
|
|
28
|
+
- B: relative density 0.0634, training-neighbor distance ratio 3.476; sparse support is the primary category.
|
|
29
|
+
- D: range-exceedance fraction 100%, training-neighbor distance ratio 4.012; extrapolation is primary.
|
|
30
|
+
- F: regional Ridge MAE 4.5995 versus HGB 0.1995; affected model is Ridge.
|
|
31
|
+
- C: high irreducible noise is detected as shared dense error. The taxonomy cannot causally distinguish noise from structural misspecification; this is a known limitation.
|
|
32
|
+
|
|
33
|
+
## Grouped leakage: E
|
|
34
|
+
|
|
35
|
+
| Validation | MAE | RMSE | R² |
|
|
36
|
+
|---|---:|---:|---:|
|
|
37
|
+
| Random KFold | 0.110541 | 0.138239 | 0.999261 |
|
|
38
|
+
| GroupKFold | 6.044717 | 7.660880 | -1.269610 |
|
|
39
|
+
|
|
40
|
+
Group-aware MAE is 54.68 times random-CV MAE. There is no unique planted geometric region in E, so localization precision/recall/IoU are not reported.
|
|
41
|
+
|
|
42
|
+
## Nested repair experiments on A
|
|
43
|
+
|
|
44
|
+
Geometry is rediscovered in each outer training fold through inner OOF prediction. Outer test outcomes do not select that geometry. Metrics pool fold-specific regimes. The second Ridge estimator is the predeclared alternative in this benchmark.
|
|
45
|
+
|
|
46
|
+
| Strategy | Global MAE before → after | Regional MAE before → after | Outside MAE before → after | Success criteria met |
|
|
47
|
+
|---|---:|---:|---:|---|
|
|
48
|
+
| targeted_weighting | 0.8557 → 1.3664 | 3.8321 → 2.2773 | 0.5553 → 1.2745 | False |
|
|
49
|
+
| interaction_augmentation | 0.8557 → 0.0994 | 3.8321 → 0.0928 | 0.5553 → 0.1001 | True |
|
|
50
|
+
| alternative_estimator | 0.8557 → 0.8543 | 3.8321 → 3.8363 | 0.5553 → 0.5534 | False |
|
|
51
|
+
| support_rebalancing | 0.8557 → 1.3659 | 3.8321 → 2.2793 | 0.5553 → 1.2737 | False |
|
|
52
|
+
|
|
53
|
+
Weighting and rebalancing improve the selected regime while degrading the rest of the model, and are therefore rejected. Interaction augmentation improves all three metrics. This validates this synthetic procedure only, not general remediation effectiveness.
|
|
54
|
+
|
|
55
|
+
## Failed attempts and remaining weaknesses
|
|
56
|
+
|
|
57
|
+
- The first implementation chose only the severity-support core: D IoU was 0.5011. A broader excess-error representative improved D to 1.0 but degraded A and F to 0.4944. The final method retains both materially distinct representatives; core and extent remain correlated candidates. This development used the same benchmark suite, so it is not an independent methodological comparison.
|
|
58
|
+
- F has 4 candidates with IoU <0.1 to the planted mask, out of 11 candidates. These include boundary effects and spurious candidates; they are not discarded to improve the report.
|
|
59
|
+
- A grid/seed sensitivity check (seeds 17,43,101; grids 8,10,13; 1,600 rows) gives best-IoU range 0.704–1.000. Axis alignment matters.
|
|
60
|
+
- Null-data audit uses five homoscedastic linear datasets (no planted localized failure). Results below demonstrate that recurrence does not establish significance.
|
|
61
|
+
|
|
62
|
+
| Null seed | Candidate count | Highest priority score | Candidates with bootstrap and fold recurrence ≥0.6 |
|
|
63
|
+
|---|---:|---:|---:|
|
|
64
|
+
| 0 | 1 | 47.76 | 1 |
|
|
65
|
+
| 1 | 1 | 21.83 | 0 |
|
|
66
|
+
| 2 | 4 | 45.42 | 2 |
|
|
67
|
+
| 3 | 1 | 19.69 | 0 |
|
|
68
|
+
| 4 | 2 | 32.21 | 0 |
|
|
69
|
+
|
|
70
|
+
**Next research priority:** independent discovery/confirmation evaluation with null-calibrated thresholds and explicit false-discovery/power assessment.
|
|
71
|
+
|
|
72
|
+
Raw measured summaries: `docs/validation/benchmark_results.json` and `docs/validation/sensitivity_results.json`. Regenerate full reports and prediction records with the experiments runner.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0 — first public release (2026-09-24)
|
|
4
|
+
|
|
5
|
+
First release on PyPI as `diag3d` (`pip install diag3d`).
|
|
6
|
+
|
|
7
|
+
Fixed: the training monitor recorded prediction part paths as OS-native strings and
|
|
8
|
+
consolidated them by looking for a forward-slash prefix, so on Windows no part was ever
|
|
9
|
+
registered and analysing a run failed with `KeyError: 'final'`. Parts are now recorded
|
|
10
|
+
as POSIX paths and matched by file name; a regression test and a Windows CI job cover it.
|
|
11
|
+
The killed-writer recovery test now uses a portable process kill.
|
|
12
|
+
|
|
13
|
+
Fixed on Windows: run manifests, findings and explorer assets are read as UTF-8 regardless
|
|
14
|
+
of the platform code page (they were always written as UTF-8), research outputs are written
|
|
15
|
+
as UTF-8, and the `diag3d` CLI and the lifecycle examples no longer crash when the console or
|
|
16
|
+
a redirected pipe cannot encode a character such as `→` or `ρ`: the echo degrades to `?`
|
|
17
|
+
while every file stays UTF-8. The Windows CI job runs under the default code page.
|
|
18
|
+
|
|
19
|
+
Added `diag3d.baselines`: reference baselines (`linear`, `rf`, `hgb`, and `xgb`, `lgbm`,
|
|
20
|
+
`mlp` when their optional packages are installed) fitted on every partition of one
|
|
21
|
+
explicit split manifest with shared preprocessing, documented default parameters,
|
|
22
|
+
deterministic seeds, fit/predict wall-clock timings and environment metadata, returning
|
|
23
|
+
a validated `PredictionTable`. Added `diag3d.lifecycle.partitions` (training rows versus
|
|
24
|
+
evaluation rows of a manifest on a caller's row order) and widened the documented public
|
|
25
|
+
surface of `diag3d.lifecycle` (`docs/public_api.md`).
|
|
26
|
+
|
|
27
|
+
Release engineering: a "Prepare release" workflow creates the version tag and a draft
|
|
28
|
+
GitHub Release with notes from this changelog; the release workflow stages on TestPyPI
|
|
29
|
+
and publishes to PyPI through trusted publishing with attestations, verifies the
|
|
30
|
+
published files and attaches them to the release; the build backend is pinned exactly so
|
|
31
|
+
a rebuild of the tagged commit reproduces the validated bytes; a Homebrew tap
|
|
32
|
+
(`falhezaimi/homebrew-tap`) is maintained separately.
|
|
33
|
+
|
|
34
|
+
## Unreleased — consolidation into main
|
|
35
|
+
|
|
36
|
+
Merged the model-space explorer (PR #1), GLB export (PR #4) and release readiness
|
|
37
|
+
(PR #2), with safeguards ported from PR #3. One GLB exporter (the explorer's) replaces
|
|
38
|
+
the lifecycle point-cloud exporter, which mirrored scenes and mis-encoded colours.
|
|
39
|
+
The training monitor records observed fold membership and stores it as the run's split
|
|
40
|
+
manifest. Run schema 2.1 records conventions for nested CV (outer loop only), multiple
|
|
41
|
+
evaluation datasets (one linked dataset per table) and checkpoint units (declared).
|
|
42
|
+
|
|
43
|
+
## Unreleased — lifecycle foundation audit
|
|
44
|
+
|
|
45
|
+
Training membership is no longer inferred from fold labels unless a complement design
|
|
46
|
+
(K-fold, repeated/group K-fold, leave-one-group-out) is declared and verified; other
|
|
47
|
+
designs need an explicit `SplitManifest`, otherwise dependent checks are `not_evaluable`.
|
|
48
|
+
Run schema 2.0 (split manifest, part-based prediction tables with dataset links, model
|
|
49
|
+
registry, per-diagnostic Diag3D version, writer ids on events; 1.x readable read-only).
|
|
50
|
+
Fixed: future/buffer rows counted as training data; complement taken across repeats;
|
|
51
|
+
missing inputs reported as `pass` (small subgroups, single-role splits, missing times);
|
|
52
|
+
test-set samples accepted under non-test roles during training; investigator reference
|
|
53
|
+
defaulting to all samples; row-order-dependent results; int64 fingerprint collisions;
|
|
54
|
+
duplicate CSV headers accepted; ECE bin edges off at exact boundaries; `status()` ignoring
|
|
55
|
+
session order and Ctrl-C; resumed writers corrupting a torn event line and overwriting a
|
|
56
|
+
crashed session's prediction parts; ~1 GB memory spike when finishing long runs.
|
|
57
|
+
Added `r2_mean_over_repeats`, `tools/lifecycle_mutations.py` (20/20 mutations caught), 44 adversarial tests.
|
|
58
|
+
|
|
59
|
+
## Unreleased — lifecycle diagnostics (version string remains 0.2.0.dev0)
|
|
60
|
+
|
|
61
|
+
Added `diag3d.lifecycle`: shared `Finding` records; validated long-format `PredictionTable`
|
|
62
|
+
with composite keys, explicit column mapping and CSV/Parquet/NPZ/structured-NPY loading
|
|
63
|
+
(pickle/joblib only with `trusted=True`); directory `Run` store with versioned manifest,
|
|
64
|
+
append-only events, atomic writes, fingerprints and a single-writer lock; `preflight`;
|
|
65
|
+
`TrainingMonitor` with a LightGBM callback, test-label guard and bounded memory; bounded
|
|
66
|
+
`Investigator`; `analyze_predictions` for frozen predictions; redacted Markdown/JSON/CSV
|
|
67
|
+
outputs; `.glb` export with a companion manifest; optional Matplotlib figures. New CLI
|
|
68
|
+
commands `preflight`, `posthoc`, `run-show`. `FailureAnalyzer.analyze_oof` runs region
|
|
69
|
+
discovery on imported OOF predictions without fitting.
|
|
70
|
+
|
|
71
|
+
Fixed: `python -m diag3d.cli analyze` failed with "No such command" (the `__main__` guard
|
|
72
|
+
preceded the command). `r2_of_mean_prediction` is now `None` for a constant target instead
|
|
73
|
+
of scikit-learn's 1.0/0.0.
|
|
74
|
+
|
|
75
|
+
## Unreleased — release preparation
|
|
76
|
+
|
|
77
|
+
- Preserve the unapproved `0.2.0.dev0` research version and single version source.
|
|
78
|
+
- Validate both distributions, clean installations and installed OOF analysis.
|
|
79
|
+
- Add stable-tag OIDC release automation with exact TestPyPI artifact verification,
|
|
80
|
+
duplicate-version rejection and an explicit production enable gate.
|
|
81
|
+
- Extend source/history inspection and document Trusted Publishing, dependency
|
|
82
|
+
groups and the complete maintainer release procedure.
|
|
83
|
+
|
|
84
|
+
## 0.2.0.dev0
|
|
85
|
+
|
|
86
|
+
Implemented the research reset from v0.1: typed OOF failure-region engine, supported empirical error grids, threshold persistence, bootstrap/fold recurrence, cross-model/support diagnostics, transparent characterization and ranking, nested repair experiments, synthetic benchmarks, evidence explorer, research CLI/report, and development packaging. Preserved the legacy CSV API/commands and report infrastructure. Production publication remains disabled.
|
|
87
|
+
|
|
88
|
+
## 0.2.0.dev0 — null-validation development snapshot
|
|
89
|
+
|
|
90
|
+
Adds search-wide empirical calibration, six negative controls, model-refit bootstrap, training-only nested strategy selection, explicit repair guardrails, statistical explorer overlays, publication figures and measured false-positive/detection experiments. Retains the prior implementation and its regression coverage. Production publication remains disabled.
|
|
91
|
+
|
|
92
|
+
## Model-space development snapshot — 2026-09-21
|
|
93
|
+
|
|
94
|
+
- Added a unified Data/Model/Prediction/Error/Failure/Repair explorer and offline session contract.
|
|
95
|
+
- Added CSV supplied-output reports, pre-run diagnostics, optional fitted-model adapters and evidence-backed repair replay.
|
|
96
|
+
- Preserved the existing numerical research engine and original reporting APIs.
|
|
97
|
+
- Fixed a duplicate observer declaration in the research HTML.
|
|
98
|
+
- Added three redistributable demos, browser screenshots, source audit, architecture/UX specifications and 25 Python tests.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Install `python -m pip install -e '.[dev]'`. Run `python -m pytest -q`, `python -m ruff check src tests experiments tools`, `python -m compileall -q src`, and the synthetic benchmark runner. Add tests for scientific invariants, leakage boundaries, stability and meaningful failure modes. Preserve failed benchmarks. Explain changes to estimands, fold design, overlap definitions or ranking formulas in `docs/research_method.md`.
|
|
4
|
+
|
|
5
|
+
Do not commit datasets, generated reports, model artifacts, credentials, caches or environments. Production publishing and stable tags are disabled during the research reset. Discuss methodological claims with evidence and relevant prior art; do not infer causation from regional error alone.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Flagship walkthrough — 28 seconds
|
|
2
|
+
|
|
3
|
+
Open `gallery/model-space/regression.html` in a WebGL-capable desktop browser. Press **28s walkthrough**. A 1600×1000 recording provides readable axes and evidence; 1920×1080 is also suitable. The controls keep the same camera and selection as the layers change.
|
|
4
|
+
|
|
5
|
+
| Time | Visual | Suggested narration |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| 0–4 s | Raw benchmark points in feature space | “Start with an ordinary machine-learning results table.” |
|
|
8
|
+
| 4–8 s | Prediction field and residual lines appear | “Enter the relationship between observations and predictions.” |
|
|
9
|
+
| 8–12 s | Prediction geometry | “See the response your model produces where data provide support.” |
|
|
10
|
+
| 12–16 s | Error height and color | “Turn error into a spatial structure.” |
|
|
11
|
+
| 16–18 s | Exact failure outlines | “Locate a recurring failure region.” |
|
|
12
|
+
| 18–22 s | Region selected; calibration/refit inspector | “Inspect its support, recurrence and statistical assumptions.” |
|
|
13
|
+
| 22–25.5 s | Original outer-test predictions | “A repair is chosen using training-side validation.” |
|
|
14
|
+
| 25.5–28 s | Selected repair predictions and smaller residuals | “Then inspect the change on untouched outer-test observations.” |
|
|
15
|
+
|
|
16
|
+
The exported MP4 is assembled from actual rendered browser captures of these states, with discrete cuts; it is not a continuous screen recording. The HTML button runs the interactive sequence for a fresh recording. No interpolated intermediate predictions are represented as a trained model.
|
|
17
|
+
|
|
18
|
+
For a public caption, retain “synthetic interaction benchmark” and “research development version.” Do not generalize its 220/221 localization, 50/50 refit recurrence or large repair gain to real datasets. Keep the unresolved null-calibration caveat available in the linked evidence.
|