Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions .github/workflows/kumo-engine-weekly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ jobs:
matrix: ${{ steps.config.outputs.matrix }}
manifest_sha256: ${{ steps.config.outputs.manifest_sha256 }}
reference_sha256: ${{ steps.config.outputs.reference_sha256 }}
p1: ${{ steps.config.outputs.p1 }}
steps:
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
with:
Expand Down Expand Up @@ -70,8 +71,22 @@ jobs:
if not isinstance(path, str) or not PurePosixPath(path).is_absolute() or any(c in path for c in '\r\n'):
raise SystemExit('Bind absolute data paths and the shared host lock')
profiles.append(profile)
p1 = value.get('p1', {})
if os.environ['MODE'] == 'candidate':
runner = p1['runner']
if (not isinstance(runner, dict) or set(runner) != {'group', 'labels'}
or any(not isinstance(v, str) or not v for v in runner.values())):
raise SystemExit('Bind the existing P1 runner group and label')
for key in ('input_root', 'reference', 'host_lock', 'work_root'):
path = p1[key]
if not isinstance(path, str) or not PurePosixPath(path).is_absolute() or any(c in path for c in '\r\n'):
raise SystemExit('Bind absolute P1 input, reference, lock, and work paths')
for key in ('manifest_sha256', 'reference_sha256'):
if not re.fullmatch('[0-9a-f]{64}', p1.get(key, '')):
raise SystemExit('Bind the reviewed P1 manifest and reference checksums')
with open(os.environ['GITHUB_OUTPUT'], 'a') as output:
output.write('matrix=' + json.dumps(dict(include=profiles)) + '\n')
output.write('p1=' + json.dumps(p1) + '\n')
for key in ('manifest_sha256', 'reference_sha256'):
output.write(key + '=' + str(value.get(key, '')) + '\n')
PYCODE
Expand All @@ -89,6 +104,7 @@ jobs:
- run: python packages/kumo-engine/test/test_weekly_check.py
- run: python packages/kumo-engine/test/test_weekly_reference.py
- run: python packages/kumo-engine/test/test_weekly_workflow.py
- run: python packages/kumo-engine/test/test_weekly_p1.py

wheel:
if: github.event_name == 'workflow_dispatch' && inputs.mode == 'candidate'
Expand Down Expand Up @@ -317,6 +333,92 @@ jobs:
shutil.rmtree(temporary / 'weekly-wheel', ignore_errors=True)
PY

p1:
name: P1 CPU sampling
needs: [cpu, configure, gpu, wheel]
if: ${{ !cancelled() && github.event_name == 'workflow_dispatch' && inputs.mode == 'candidate' && needs.cpu.result == 'success' && needs.configure.result == 'success' && needs.wheel.result == 'success' }}
runs-on: ${{ fromJSON(needs.configure.outputs.p1).runner }}
timeout-minutes: 120
env:
P1_CONFIG: ${{ needs.configure.outputs.p1 }}
CUDA_VISIBLE_DEVICES: ''
KUMO_ACCELERATOR: cpu
OMP_NUM_THREADS: '8'
MKL_NUM_THREADS: '8'
OPENBLAS_NUM_THREADS: '8'
PYTHONDONTWRITEBYTECODE: '1'
PIP_CONFIG_FILE: /dev/null
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
with:
python-version: '3.12'
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: weekly-wheel-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/weekly-p1-wheel
- name: Prepare an isolated P1 environment
run: |
python - <<'PY'
import json, os, runpy, subprocess
from pathlib import Path
api = runpy.run_path('packages/kumo-engine/scripts/weekly_check.py')
config = json.loads(os.environ['P1_CONFIG'])
wheels = Path(os.environ['RUNNER_TEMP']) / 'weekly-p1-wheel'
[wheel] = wheels.glob('*.whl')
build = api['read'](wheels / 'build.json')
api['check_build'](build, build['version'], api['digest'](wheel))
root = Path(config['work_root']) / ('weekly-p1-' + os.environ['GITHUB_RUN_ID'] + '-' + os.environ['GITHUB_RUN_ATTEMPT'])
root.mkdir(exist_ok=False)
with open(os.environ['GITHUB_ENV'], 'a') as output:
output.write(f'WEEKLY_P1_ROOT={root}\n')
subprocess.run(['python', '-m', 'venv', str(root / 'venv')], check=True)
python = str(root / 'venv/bin/python')
subprocess.run([python, '-I', '-m', 'pip', '--isolated', 'install', '--index-url', 'https://pypi.org/simple', str(wheel)], check=True)
subprocess.run([python, '-I', '-m', 'pip', '--isolated', 'check'], check=True)
PY
- name: Run P1 against its approved reference
run: |
python - <<'PY'
import json, os, runpy, subprocess
from pathlib import Path
api = runpy.run_path('packages/kumo-engine/scripts/weekly_check.py')
config = json.loads(os.environ['P1_CONFIG'])
root = Path(os.environ['WEEKLY_P1_ROOT'])
wheels = Path(os.environ['RUNNER_TEMP']) / 'weekly-p1-wheel'
[wheel] = wheels.glob('*.whl')
build = api['read'](wheels / 'build.json')
api['check_build'](build, build['version'], api['digest'](wheel))
subprocess.run([str(root / 'venv/bin/python'), '-I', 'packages/kumo-engine/scripts/weekly_p1.py',
'--mode', 'candidate', '--input-root', config['input_root'], '--manifest-sha256', config['manifest_sha256'],
'--reference', config['reference'], '--reference-sha256', config['reference_sha256'],
'--host-lock', config['host_lock'], '--output', str(root / 'evidence'),
'--wheel', str(wheel), '--wheel-sha256', build['wheel_sha256']], check=True)
PY
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: always() && env.WEEKLY_P1_ROOT != ''
with:
name: weekly-p1-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ env.WEEKLY_P1_ROOT }}/evidence
if-no-files-found: error
retention-days: 7
- name: Remove this P1 job's temporary files
if: always() && env.WEEKLY_P1_ROOT != ''
run: |
python - <<'PY'
import json, os, shutil
from pathlib import Path
config = json.loads(os.environ['P1_CONFIG'])
root = Path(os.environ['WEEKLY_P1_ROOT']).resolve()
expected = 'weekly-p1-' + os.environ['GITHUB_RUN_ID'] + '-' + os.environ['GITHUB_RUN_ATTEMPT']
if root.parent != Path(config['work_root']).resolve() or root.name != expected:
raise SystemExit('Unexpected P1 cleanup directory')
shutil.rmtree(root)
shutil.rmtree(Path(os.environ['RUNNER_TEMP']) / 'weekly-p1-wheel', ignore_errors=True)
PY

collect:
needs: [configure, gpu]
if: ${{ !cancelled() && needs.configure.result == 'success' }}
Expand Down
5 changes: 3 additions & 2 deletions docs/development/engine-weekly-ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ restored weights with the saved checkpoint. Checkpoint-format failures, missing
rows, changed weights, and excess score drift fail the case. A candidate also reloads its own saved model.

P1 means five CPU sampling operations on commerce/100M. B9 means prediction with
the retained P2 model on one GPU and then two matching GPUs. They are separate
changes and do not run in this workflow.
the retained P2 model on one GPU and then two matching GPUs. The separate
[P1 job](engine-weekly-p1.md) follows the eleven cases during a manual candidate run.
B9 remains a separate change.

## Inputs and reference approval

Expand Down
231 changes: 231 additions & 0 deletions docs/development/engine-weekly-p1-calibration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
{
"format": "kumo-engine-weekly-p1-calibration-v1",
"approval": "PENDING_REVIEW",
"date_utc": "2026-11-02",
"physical_fits": 0,
"operations": 15,
"runtime": {
"version": "1.0.0",
"wheel_sha256": "1bc15ecb7696bce216b05aa883d6897d2b8ce4342c6c2f9d62b7cc28b314539e",
"dependencies": {
"cloudpickle": "3.1.2",
"mpmath": "1.3.0",
"nvidia-cuda-runtime-cu12": "12.9.79",
"optuna": "4.9.0",
"multidict": "7.1.0",
"psutil": "7.2.2",
"nvidia-nvjitlink": "13.4.92",
"certifi": "2026.10.19",
"torchmetrics": "1.8.1",
"nvidia-cusparse": "12.6.3.3",
"packaging": "26.3",
"cuda-pathfinder": "1.8.3",
"nvidia-cudnn-cu13": "9.24.0.43",
"nvidia-cusolver": "12.0.4.66",
"aiohappyeyeballs": "2.7.1",
"Werkzeug": "3.1.9",
"xxhash": "4.0.2",
"yarl": "1.25.1",
"tensorboard": "2.21.0",
"filelock": "4.2.4",
"nvidia-nvtx": "13.0.85",
"threadpoolctl": "3.7.0",
"absl-py": "2.5.1",
"fonttools": "4.67.0",
"antlr4-python3-runtime": "4.9.3",
"nvidia-cublas": "13.1.1.3",
"cycler": "0.12.1",
"pillow": "13.0.0",
"fsspec": "2026.9.0",
"nvidia-cufile": "1.15.1.6",
"frozenlist": "1.8.0",
"nvidia-curand-cu12": "10.3.10.19",
"typing-inspection": "0.4.4",
"aiohttp": "3.14.5",
"numpy": "2.5.4",
"propcache": "0.5.4",
"Markdown": "3.11.2",
"python-dateutil": "2.9.0.post0",
"matplotlib": "3.11.2",
"setuptools": "84.2.0",
"joblib": "1.6.0",
"tensorboard-data-server": "0.7.2",
"scikit-learn": "1.9.1",
"cuda-toolkit": "13.0.3.0",
"nvidia-cuda-runtime": "13.0.96",
"nvidia-cuda-nvrtc-cu12": "12.9.86",
"kiwisolver": "1.5.1",
"cuda-bindings": "13.4.4",
"pytorch-frame": "0.3.0",
"charset-normalizer": "3.5.2",
"nvidia-cuda-cupti": "13.0.85",
"tzdata": "2026.5",
"scipy": "1.18.1",
"tabulate": "0.8.10",
"nvidia-curand": "10.4.0.35",
"grpcio": "1.84.0",
"urllib3": "2.8.0",
"nvidia-cufft": "12.0.0.61",
"nvidia-nvshmem-cu13": "3.4.5",
"Mako": "1.4.3",
"aiosignal": "1.4.0",
"torch": "2.14.1",
"protobuf": "7.36.2",
"requests": "2.34.2",
"sympy": "1.14.0",
"pyparsing": "3.3.3",
"torch-geometric": "2.8.1",
"PyYAML": "6.0.3",
"tqdm": "4.70.1",
"pytz": "2026.5",
"narwhals": "2.27.1",
"MarkupSafe": "3.0.4",
"networkx": "3.7",
"pydantic": "2.14.1",
"nvidia-cusparselt-cu13": "0.8.1",
"nvidia-cuda-nvrtc": "13.0.88",
"nvidia-cublas-cu12": "12.9.2.10",
"pip": "24.0",
"nvidia-nccl-cu13": "2.30.7",
"attrs": "26.1.0",
"triton": "3.8.0",
"kumo-engine": "1.0.0",
"alembic": "1.20.0",
"six": "1.17.0",
"colorlog": "6.12.0",
"pytorch-lightning": "2.6.5",
"pyarrow": "24.0.0",
"SQLAlchemy": "2.1.5",
"typing_extensions": "4.16.0",
"pydantic_core": "2.50.1",
"idna": "3.20",
"faiss-gpu": "1.14.3",
"duckdb": "1.5.5",
"Jinja2": "3.1.6",
"annotated-types": "0.8.0",
"sqlglot": "30.17.0",
"lightning-utilities": "0.15.3",
"pandas": "2.3.3",
"contourpy": "1.4.0"
}
},
"workload": {
"n": 300000,
"unique_customers": 100000,
"offset": 0,
"hops": 3,
"batch": 256,
"procs": 2,
"threads": 8,
"plan": [
24,
8,
6
],
"cache": "no_drop_uncontrolled",
"features": true,
"expected_work": {
"batches": 1172,
"requested_seeds": 300000
},
"historical_sampled_work": {
"nodes": 173052351,
"edges": 196315170
}
},
"graph_row_counts": {
"merchants": 6848,
"purchases": 17144193,
"merchant_views": 63497928,
"searches": 20142246,
"favorites": 796998,
"reviews": 1959145,
"customers": 2960000
},
"identical_work_per_operation": {
"seeds": 300000,
"batches": 1172,
"nodes": 173052351,
"edges": 196315170,
"fetched_rows": 173052351,
"membership_sha256": "008c24bd53606f71928bc1fd8e7dd055680cb322de0246747951b481b0564f57"
},
"sampling_function_sha256": "5a1b7b26e48fa95c6eef3747fcf5d8cb65add55e0b7c1b8e4eaa3b47726fae70",
"measurement_manifest_sha256": "2656adba90834d2c89b91673bc092a5f9f6eb20a4d6e216c48e9a036ee511752",
"workload_sha256": "8dc9e7ad80efed943310140bfac8d9235dc13045cacd0d591dbf46f4e4f5f85a",
"observations": [
{
"block": 1,
"status": "PASS",
"physical_fits": 0,
"raw_result_sha256": "fe22afcc846424b3646ac28ff370e01e5ad28e6b8b85c17ddc71da59f86eeff7",
"runner_sha256": "1b0722762d12fa546222dbcc3e25c0dc2309457dfa727b6edcb8f98a54e83bae",
"python": "3.12.3",
"command_elapsed": "PT7M37.684S",
"operation_seconds": [
90.02141279296484,
88.75617220095592,
88.70439774199622,
91.41735572600737,
89.70340646797558
],
"median_seconds": 89.70340646797558
},
{
"block": 2,
"status": "PASS",
"physical_fits": 0,
"raw_result_sha256": "287c75361763cf00b5f4060eee901cc0703ed0b6e6dbd7eaa3cbac1699eeb1f0",
"runner_sha256": "1b0722762d12fa546222dbcc3e25c0dc2309457dfa727b6edcb8f98a54e83bae",
"python": "3.12.3",
"command_elapsed": "PT7M33.947S",
"operation_seconds": [
88.51640437496826,
90.26576620602282,
86.10522801801562,
89.66752364404965,
90.85604079504265
],
"median_seconds": 89.66752364404965
},
{
"block": 3,
"status": "PASS",
"physical_fits": 0,
"raw_result_sha256": "5a1b7ff7c2f707dc866f6b8ded63f3f7da43708ab1b1b3275e18fe11e52b81cb",
"runner_sha256": "e432e55964006acc55232f64f00aebb06ac6fa6a72400366eb6cebd6e7f00cf6",
"python": "3.12.3",
"command_elapsed": "PT7M34.122S",
"operation_seconds": [
90.26548215199728,
89.95532578800339,
85.50048555596732,
89.96577449498,
90.01619070599554
],
"median_seconds": 89.96577449498
}
],
"proposed_timing_policy": {
"atol_seconds": 5.0,
"rtol": 0.1,
"baseline_block": 1,
"baseline_median_seconds": 89.70340646797558,
"maximum_candidate_median_seconds": 103.67374711477315,
"observed_block_median_range_seconds": [
89.66752364404965,
89.96577449498
],
"rule": "candidate median <= reference median * 1.1 + 5 seconds",
"rationale": "The three observed medians differ by less than 0.4 percent. The proposed 10 percent plus 5 seconds is operational headroom, not a measured confidence interval."
},
"proposed_input_manifest_sha256": "a6f6abd0f27d874c460e3cede732020822f5c1cc814b41e0efddfded63d05fc4",
"proposed_reference_sha256": "4b08fee40490cff81f9b8bf465a22aa90aed7d21e7ad67bb435acfaed808e8db",
"limits": [
"The host provides 192 CPUs. P1 uses two processes with eight sampler threads each.",
"Cache state is uncontrolled. These three blocks do not establish a universal timing budget.",
"The installed published wheel is 1.0.0. No GitHub dispatch or candidate-wheel comparison ran.",
"Raw results and their original input manifest remain unchanged. A separate reference record binds the proposed timing policy to the same data and work.",
"A maintainer must review the reference and policy before configuring their checksums for future manual weekly runs."
]
}
Loading