From 8f1105d2e2875054cd4d9027196760582d53a51f Mon Sep 17 00:00:00 2001 From: Patrick Emami Date: Wed, 14 Oct 2026 11:57:56 -0500 Subject: [PATCH 1/4] Update repo name --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 992cfaa..ab11074 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,8 @@ No HPC allocation, DAOS container, or accelerator needed. > *Installation* instead. ```bash -git clone --recursive https://github.com/AI-ModCon/BaseMM_PRISM.git -cd BaseMM_PRISM +git clone --recursive https://github.com/AI-ModCon/PRISM.git +cd PRISM python -m venv .venv && source .venv/bin/activate pip install -r requirements/base.txt From 9dda92ce87c944040a2e2f6e46ab3e7fb53d4d1d Mon Sep 17 00:00:00 2001 From: Patrick Emami Date: Wed, 14 Oct 2026 12:06:18 -0500 Subject: [PATCH 2/4] Replacing BaseMM_PRISM in other places --- .env.aurora.example | 2 +- .env.template | 6 +++--- .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- .github/pull_request_template.md | 4 ++-- CHANGELOG.md | 2 +- CITATION.cff | 4 ++-- CONTRIBUTING.md | 4 ++-- README.md | 2 +- docs/getting-started.md | 4 ++-- docs/platforms/aurora_operations.md | 2 +- docs/platforms/running_on_polaris.md | 8 ++++---- pyproject.toml | 8 ++++---- src/conf/model/prism_olmo1b_linear_interleaved_ts.yaml | 2 +- .../prism_olmo3_7b_instruct_linear_interleaved_ts.yaml | 2 +- src/conf/model/prism_olmo7b_linear_interleaved_ts.yaml | 2 +- src/config.py | 6 +++--- 17 files changed, 31 insertions(+), 31 deletions(-) diff --git a/.env.aurora.example b/.env.aurora.example index 0578c6e..6da7307 100644 --- a/.env.aurora.example +++ b/.env.aurora.example @@ -38,7 +38,7 @@ PRISM_DATA_ROOT="/lus/flare/projects///prism_data" # Interleaved tokenizers. Two are committed under tokenizers/ in the repo; # there is no builder script. Referenced by the # prism_olmo*_ts presets in src/conf/model/. -PRISM_TOKENIZERS="/lus/flare/projects///BaseMM_PRISM/tokenizers" +PRISM_TOKENIZERS="/lus/flare/projects///PRISM/tokenizers" # Staged third-party generator assets, e.g. the pinned OmniGen2 checkout used # by src/conf/image_generation/*.json (which append "/OmniGen2"). diff --git a/.env.template b/.env.template index 368983c..53b69ef 100644 --- a/.env.template +++ b/.env.template @@ -17,7 +17,7 @@ HF_HOME="/flare//" # PRISM Project Root # Path to the base of the repository -PRISM_DIR="/flare///BaseMM_PRISM" +PRISM_DIR="/flare///PRISM" # Shared Hugging Face Hub (Optional but strongly recommended on Aurora) # A shared directory containing pre-downloaded models to avoid re-downloading. @@ -73,7 +73,7 @@ PRISM_DATA_ROOT="/flare///data" # Interleaved tokenizers (two are committed under tokenizers/), referenced by the # prism_olmo*_ts presets in src/conf/model/. -PRISM_TOKENIZERS="/flare///BaseMM_PRISM/tokenizers" +PRISM_TOKENIZERS="/flare///PRISM/tokenizers" # Staged third-party generator assets, e.g. the pinned OmniGen2 snapshot used # by the image-generation configs in src/conf/image_generation/. @@ -100,7 +100,7 @@ PRISM_OUTPUT_ROOT="/flare///outputs" # Custom OLMo tokenizer with interleaving tokens added, used as llm_tokenizer_id # by the prism-olmo-*-interleaved presets. Build with # the committed tokenizers/ directory, or point at your own path. -# PRISM_OLMO1B_INTERLEAVED_TOKENIZER="/flare///BaseMM_PRISM/tokenizers/prism-olmo-1b-interleaved" +# PRISM_OLMO1B_INTERLEAVED_TOKENIZER="/flare///PRISM/tokenizers/prism-olmo-1b-interleaved" # Shared HF hub snapshot of the walrus geometry encoder weights. When set and # the file exists, src/encoders/geometry.py loads it directly instead of diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d97b1cd..dff79a9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,4 @@ -# Code owners for BaseMM_PRISM. +# Code owners for PRISM. # # GitHub requests a review from the owning entry whenever a matching file # changes. Branch protection on `main` will require one approving review at the diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index be72cdd..ebb61e5 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -24,7 +24,7 @@ Other solutions or features you considered, and why they fall short. ## Compatibility Impact Would this change any of the following? See *Compatibility* in -[CONTRIBUTING.md](https://github.com/AI-ModCon/BaseMM_PRISM/blob/main/CONTRIBUTING.md). +[CONTRIBUTING.md](https://github.com/AI-ModCon/PRISM/blob/main/CONTRIBUTING.md). - [ ] `src.*` import paths - [ ] the `prism` CLI surface diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 83ad7d3..699e4ce 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -55,12 +55,12 @@ its license and provenance. Write "None" if there are none. - [ ] I have added tests that cover this change, or explained why none are needed - [ ] New and existing tests pass locally - [ ] No secrets, credentials, or absolute institutional paths are included - (see [SECURITY.md](https://github.com/AI-ModCon/BaseMM_PRISM/blob/main/SECURITY.md)) + (see [SECURITY.md](https://github.com/AI-ModCon/PRISM/blob/main/SECURITY.md)) ## AI/LLM Assistance See *Guidelines for AI/LLM-Assisted Contributions* in -[CONTRIBUTING.md](https://github.com/AI-ModCon/BaseMM_PRISM/blob/main/CONTRIBUTING.md). All PRs require a human reviewer who is +[CONTRIBUTING.md](https://github.com/AI-ModCon/PRISM/blob/main/CONTRIBUTING.md). All PRs require a human reviewer who is accountable for the review — a project norm, not yet enforced by branch protection. diff --git a/CHANGELOG.md b/CHANGELOG.md index 501539c..0e5b497 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,4 +68,4 @@ will make up v0.1.0. pretrained causal-LM backbone, with validated training paths on Aurora, Polaris, and Perlmutter. --> -[Unreleased]: https://github.com/AI-ModCon/BaseMM_PRISM/commits/main +[Unreleased]: https://github.com/AI-ModCon/PRISM/commits/main diff --git a/CITATION.cff b/CITATION.cff index 170d35a..2418201 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -42,8 +42,8 @@ abstract: >- type: software version: 0.1.0 license: Apache-2.0 -repository-code: "https://github.com/AI-ModCon/BaseMM_PRISM" -url: "https://github.com/AI-ModCon/BaseMM_PRISM" +repository-code: "https://github.com/AI-ModCon/PRISM" +url: "https://github.com/AI-ModCon/PRISM" keywords: - multimodal - machine learning diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a5fd0d0..6fcce00 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -128,8 +128,8 @@ Historical experiment IDs and their ordering are stable — see *Compatibility*. 1. Fork the repository, then clone your fork **with submodules**: ```bash - git clone --recursive https://github.com//BaseMM_PRISM.git - cd BaseMM_PRISM + git clone --recursive https://github.com//PRISM.git + cd PRISM ``` If you already cloned without `--recursive`: diff --git a/README.md b/README.md index ab11074..8d839a4 100644 --- a/README.md +++ b/README.md @@ -344,7 +344,7 @@ Full reference, including the export key-renaming and the serving flags: ## Project structure ``` -BaseMM_PRISM/ +PRISM/ ├── src/ │ ├── train.py # Hydra entry point │ ├── model.py # UnifiedTransformer diff --git a/docs/getting-started.md b/docs/getting-started.md index 6a225e8..7b2e133 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -12,8 +12,8 @@ PRISM vendors the Walrus geometry encoder as a git submodule, so clone recursively: ```bash -git clone --recursive https://github.com/AI-ModCon/BaseMM_PRISM.git -cd BaseMM_PRISM +git clone --recursive https://github.com/AI-ModCon/PRISM.git +cd PRISM ``` If you already cloned without `--recursive`: diff --git a/docs/platforms/aurora_operations.md b/docs/platforms/aurora_operations.md index e4f8c9a..d0f1726 100644 --- a/docs/platforms/aurora_operations.md +++ b/docs/platforms/aurora_operations.md @@ -45,7 +45,7 @@ cat $PBS_NODEFILE Open a new terminal on the UAN and run: ```bash -cd /lus/flare/projects/ModCon/ngetty/BaseMM_PRISM +cd /lus/flare/projects/ModCon/ngetty/PRISM # Quick test (5 steps, 1B model): python tools/launch_aurora_web.py \ diff --git a/docs/platforms/running_on_polaris.md b/docs/platforms/running_on_polaris.md index d44b4f0..8e1797f 100644 --- a/docs/platforms/running_on_polaris.md +++ b/docs/platforms/running_on_polaris.md @@ -22,8 +22,8 @@ counterpart to [Aurora operations](aurora_operations.md). ```bash ssh polaris cd /eagle/ModCon/ngetty/repos -git clone git@github.com:AI-ModCon/BaseMM_PRISM.git # or rsync from Aurora -cd BaseMM_PRISM +git clone git@github.com:AI-ModCon/PRISM.git # or rsync from Aurora +cd PRISM # Build the venv on top of the conda base module (uses uv if available) PRISM_VENV=/eagle/ModCon/ngetty/envs/.venv-polaris \ @@ -98,7 +98,7 @@ recommended layout: datasets//shards/*.tar models// # HF snapshot dirs envs/.venv-polaris/ # built by setup_polaris_env.sh - repos/BaseMM_PRISM/ # checkout + repos/PRISM/ # checkout logs// # PBS stdout/stderr ``` @@ -206,7 +206,7 @@ Training Zone A: 100%|██████| 30/30 [00:31<00:00, 1.02s/it, loss=8.9 `from src.X` imports resolve. Aurora launchers don't need this because their per-rank shell isn't `-l`. - **rsync `--exclude='data'` is too greedy.** It matches both the - intended repo-root `BaseMM_PRISM/data` AND `BaseMM_PRISM/src/data`. + intended repo-root `PRISM/data` AND `PRISM/src/data`. Use anchored excludes (`--exclude='/data'`) when staging the repo to Polaris. - **Outbound network is via proxy.** Set diff --git a/pyproject.toml b/pyproject.toml index 5b5faea..22c51cd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,10 +102,10 @@ data = [ ] [project.urls] -Homepage = "https://github.com/AI-ModCon/BaseMM_PRISM" -Repository = "https://github.com/AI-ModCon/BaseMM_PRISM" -Issues = "https://github.com/AI-ModCon/BaseMM_PRISM/issues" -Documentation = "https://github.com/AI-ModCon/BaseMM_PRISM/tree/main/docs" +Homepage = "https://github.com/AI-ModCon/PRISM" +Repository = "https://github.com/AI-ModCon/PRISM" +Issues = "https://github.com/AI-ModCon/PRISM/issues" +Documentation = "https://github.com/AI-ModCon/PRISM/tree/main/docs" [project.scripts] prism = "src.cli:app" diff --git a/src/conf/model/prism_olmo1b_linear_interleaved_ts.yaml b/src/conf/model/prism_olmo1b_linear_interleaved_ts.yaml index c82ac05..16653d3 100644 --- a/src/conf/model/prism_olmo1b_linear_interleaved_ts.yaml +++ b/src/conf/model/prism_olmo1b_linear_interleaved_ts.yaml @@ -2,7 +2,7 @@ backbone_id: allenai/OLMo-1B-0724-hf # Custom tokenizer with interleaving tokens added. # Placeholder path — set to wherever you've built/copied this tokenizer # (see PRISM_OLMO1B_INTERLEAVED_TOKENIZER default in src/config.py). -tokenizer_id: "/flare///BaseMM_PRISM/tokenizers/prism-olmo-1b-interleaved" +tokenizer_id: "/flare///PRISM/tokenizers/prism-olmo-1b-interleaved" modalities: [text,time_series] diff --git a/src/conf/model/prism_olmo3_7b_instruct_linear_interleaved_ts.yaml b/src/conf/model/prism_olmo3_7b_instruct_linear_interleaved_ts.yaml index 50298f4..43cc014 100644 --- a/src/conf/model/prism_olmo3_7b_instruct_linear_interleaved_ts.yaml +++ b/src/conf/model/prism_olmo3_7b_instruct_linear_interleaved_ts.yaml @@ -1,7 +1,7 @@ backbone_id: allenai/Olmo-3-7B-Instruct # Custom tokenizer with interleaving tokens added. # Placeholder path — set to wherever you've built/copied this tokenizer. -tokenizer_id: "/flare///BaseMM_PRISM/tokenizers/prism-olmo-3-7b-instruct-interleaved" +tokenizer_id: "/flare///PRISM/tokenizers/prism-olmo-3-7b-instruct-interleaved" modalities: [text,time_series] diff --git a/src/conf/model/prism_olmo7b_linear_interleaved_ts.yaml b/src/conf/model/prism_olmo7b_linear_interleaved_ts.yaml index 8166ec6..efa87f5 100644 --- a/src/conf/model/prism_olmo7b_linear_interleaved_ts.yaml +++ b/src/conf/model/prism_olmo7b_linear_interleaved_ts.yaml @@ -4,7 +4,7 @@ backbone_id: allenai/OLMo-7B-0724-hf # Custom tokenizer with interleaving tokens added. # Placeholder path — set to wherever you've built/copied this tokenizer # (see PRISM_OLMO1B_INTERLEAVED_TOKENIZER default in src/config.py). -tokenizer_id: "/flare///BaseMM_PRISM/tokenizers/prism-olmo-1b-interleaved" +tokenizer_id: "/flare///PRISM/tokenizers/prism-olmo-1b-interleaved" modalities: [text,time_series] diff --git a/src/config.py b/src/config.py index bbc8a6a..0e3bb4b 100644 --- a/src/config.py +++ b/src/config.py @@ -543,7 +543,7 @@ def from_preset(cls, preset_name: str): "PRISM_OLMO1B_INTERLEAVED_TOKENIZER", # Custom tokenizer with interleaving tokens added; build it with # the committed tokenizers/ directory, or point this at your own path. - "/flare///BaseMM_PRISM/tokenizers/prism-olmo-1b-interleaved", + "/flare///PRISM/tokenizers/prism-olmo-1b-interleaved", ), "modalities": ["text", "time_series"], "freeze_backbone": True, @@ -566,7 +566,7 @@ def from_preset(cls, preset_name: str): "PRISM_OLMO1B_INTERLEAVED_TOKENIZER", # Custom tokenizer with interleaving tokens added; build it with # the committed tokenizers/ directory, or point this at your own path. - "/flare///BaseMM_PRISM/tokenizers/prism-olmo-1b-interleaved", + "/flare///PRISM/tokenizers/prism-olmo-1b-interleaved", ), "modalities": ["text", "time_series"], "freeze_backbone": True, @@ -589,7 +589,7 @@ def from_preset(cls, preset_name: str): "PRISM_OLMO1B_INTERLEAVED_TOKENIZER", # Custom tokenizer with interleaving tokens added; build it with # the committed tokenizers/ directory, or point this at your own path. - "/flare///BaseMM_PRISM/tokenizers/prism-olmo-1b-interleaved", + "/flare///PRISM/tokenizers/prism-olmo-1b-interleaved", ), "modalities": ["text", "time_series"], "freeze_backbone": True, From 777d3313f24c1f25429ddf321eebfc50c4c9af82 Mon Sep 17 00:00:00 2001 From: jdwillard19 Date: Wed, 14 Oct 2026 13:32:06 -0500 Subject: [PATCH 3/4] Finish BaseMM_PRISM -> PRISM rename follow-ups - launch_aurora.py: default PRISM_DIR falls back to the launcher's own checkout (as launch_polaris.py does) instead of a hardcoded user path under BaseMM_PRISM. - aurora_operations.md: replace a real user's checkout path with a / placeholder. - test_scits_fix_static.py: docstring tokenizer path matches the renamed model configs. - launch_polaris.py: comment rename; running_on_polaris.md: realign the layout comment column. - Regenerate the site-path allowlist (two hardcoded paths removed). Co-Authored-By: Claude Opus 5.5 --- docs/platforms/aurora_operations.md | 2 +- docs/platforms/running_on_polaris.md | 2 +- tests/test_scits_fix_static.py | 2 +- tools/ci/site_path_allowlist.json | 4 ++-- tools/launch_aurora.py | 5 ++++- tools/launch_polaris.py | 2 +- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/docs/platforms/aurora_operations.md b/docs/platforms/aurora_operations.md index d0f1726..e969b3f 100644 --- a/docs/platforms/aurora_operations.md +++ b/docs/platforms/aurora_operations.md @@ -45,7 +45,7 @@ cat $PBS_NODEFILE Open a new terminal on the UAN and run: ```bash -cd /lus/flare/projects/ModCon/ngetty/PRISM +cd /lus/flare/projects///PRISM # Quick test (5 steps, 1B model): python tools/launch_aurora_web.py \ diff --git a/docs/platforms/running_on_polaris.md b/docs/platforms/running_on_polaris.md index 8e1797f..189c364 100644 --- a/docs/platforms/running_on_polaris.md +++ b/docs/platforms/running_on_polaris.md @@ -98,7 +98,7 @@ recommended layout: datasets//shards/*.tar models// # HF snapshot dirs envs/.venv-polaris/ # built by setup_polaris_env.sh - repos/PRISM/ # checkout + repos/PRISM/ # checkout logs// # PBS stdout/stderr ``` diff --git a/tests/test_scits_fix_static.py b/tests/test_scits_fix_static.py index 56867ab..8bbd480 100644 --- a/tests/test_scits_fix_static.py +++ b/tests/test_scits_fix_static.py @@ -455,7 +455,7 @@ def test_no_user_specific_hub_paths_in_model_configs(): Tokenizer paths under a project dir are still allowed: the interleaved TS configs legitimately point at custom tokenizers checked in under - /flare/ModCon//BaseMM_PRISM/tokenizers/. + /flare///PRISM/tokenizers/. """ offenders = [] for cfg in sorted((REPO_ROOT / "src" / "conf" / "model").glob("*.yaml")): diff --git a/tools/ci/site_path_allowlist.json b/tools/ci/site_path_allowlist.json index 35ee1f2..321c339 100644 --- a/tools/ci/site_path_allowlist.json +++ b/tools/ci/site_path_allowlist.json @@ -20,7 +20,7 @@ "docs/modalities/image_decoder/docci_data.md": 3, "docs/modalities/timeseries.md": 6, "docs/models/auroragpt_vlm.md": 1, - "docs/platforms/aurora_operations.md": 4, + "docs/platforms/aurora_operations.md": 3, "docs/platforms/daos_setup.md": 10, "docs/platforms/running_on_polaris.md": 8, "docs/results/patrick_tsqa_ab.md": 3, @@ -50,7 +50,7 @@ "tools/isoflop_collect.py": 1, "tools/isoflop_launch.py": 1, "tools/isoflop_plan.py": 4, - "tools/launch_aurora.py": 3, + "tools/launch_aurora.py": 2, "tools/launch_aurora_daos.py": 2, "tools/launch_aurora_web.py": 1, "tools/launch_baremetal.py": 2, diff --git a/tools/launch_aurora.py b/tools/launch_aurora.py index d1df0d3..d59c87b 100644 --- a/tools/launch_aurora.py +++ b/tools/launch_aurora.py @@ -56,7 +56,10 @@ def main(): env_config = load_dotenv() # Defaults from .env or hardcoded fallbacks - default_prism_dir = env_config.get("PRISM_DIR", "/flare/ModCon/ngetty/BaseMM_PRISM") + # Fall back to the checkout this launcher lives in, not a hardcoded user path. + default_prism_dir = env_config.get( + "PRISM_DIR", os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + ) default_hf_home = env_config.get("HF_HOME", "/flare/ModCon/sandeep") env_config.get("PROJECT_ALLOCATION", "ModCon") env_config.get("QUEUE_NAME", "debug") diff --git a/tools/launch_polaris.py b/tools/launch_polaris.py index 3f39005..676762b 100755 --- a/tools/launch_polaris.py +++ b/tools/launch_polaris.py @@ -239,7 +239,7 @@ def main() -> int: env_config = load_dotenv() # When --prism-dir isn't given, prefer the launcher's own location over - # cwd. That way `ssh polaris "cd /eagle/.../BaseMM_PRISM && \ + # cwd. That way `ssh polaris "cd /eagle/.../PRISM && \ # python tools/launch_polaris.py ..."` Just Works from a different host. if args.prism_dir: prism_dir = args.prism_dir From 9b92e7d3ca473710d9afbfcc077a607b9bc29529 Mon Sep 17 00:00:00 2001 From: Patrick Emami Date: Wed, 14 Oct 2026 15:22:16 -0500 Subject: [PATCH 4/4] Delete stale make_release_snapshot.sh --- tools/make_release_snapshot.sh | 322 --------------------------------- 1 file changed, 322 deletions(-) delete mode 100755 tools/make_release_snapshot.sh diff --git a/tools/make_release_snapshot.sh b/tools/make_release_snapshot.sh deleted file mode 100755 index 6c3fafa..0000000 --- a/tools/make_release_snapshot.sh +++ /dev/null @@ -1,322 +0,0 @@ -#!/bin/bash -# Build the AI-ModCon/PRISM release snapshot from this repository. -# -# PRISM is a published snapshot of BaseMM_PRISM, decided in #232: content is -# the current tree, with no development history. Changes flow one way -- -# BaseMM_PRISM -> PRISM, by force-push. Anything edited only in PRISM is lost -# the next time a snapshot is taken. -# -# Two such edits exist, and this script reapplies both. They are deliberately -# NOT upstreamed: BaseMM_PRISM's badges are correct for BaseMM_PRISM, and -# Dependabot should stay active here. -# -# 1. README badges. The CI and Codecov badges point at AI-ModCon/BaseMM_PRISM, -# which stays private. On a public PRISM the Codecov badge advertises -# coverage for a repository nobody can see and the CI badge 404s for any -# external reader. Replaced with static license/python badges that resolve -# inside the published repo. -# -# 2. Dependabot. Disabled in the snapshot via `open-pull-requests-limit: 0`. -# A Dependabot PR opened against PRISM cannot be merged usefully -- the -# next snapshot overwrites it -- and one (PRISM#1) was already opened and -# auto-closed that way. The config file is kept rather than deleted, -# because tests/platform/test_dependabot_scope.py reads it and that suite -# runs in PRISM's CI; deleting the file turns 8 tests into errors. -# -# Usage: -# bash tools/make_release_snapshot.sh # build only -# bash tools/make_release_snapshot.sh --push # build and push -# bash tools/make_release_snapshot.sh --remove-protection # unlock PRISM main -# bash tools/make_release_snapshot.sh --restore-protection -# -# Without --push it builds the snapshot and stops, so the result can be -# inspected. The two protection flags act on PRISM only and do not build -# anything; run them either side of a push: -# -# bash tools/make_release_snapshot.sh --remove-protection -# bash tools/make_release_snapshot.sh --push -# bash tools/make_release_snapshot.sh --restore-protection -# -# PRISM's main requires status checks and blocks force-pushes, so a snapshot -# cannot be pushed while protection is on. --remove-protection saves the live -# configuration to $PRISM_PROTECTION_FILE (default -# ~/backups/prism/PRISM-branch-protection.json) before deleting it, and -# --restore-protection puts that exact configuration back. Saving on the way -# out is what makes the restore faithful: it cannot drift from whatever -# BaseMM_PRISM happens to have today, and it does not depend on a file -# somebody remembered to create by hand. -# -# The GET and PUT schemas for branch protection differ, so a saved GET -# response is NOT a valid PUT body -- GitHub rejects it with -# `No subschema in "anyOf" matched`. --remove-protection writes the PUT form. -# -# Between the two calls PRISM's main is unprotected. Keep the window short, -# and if a push fails, still run --restore-protection. - -# No `set -u`: Lmod's init reads unset shell variables and dies under nounset. -set -eo pipefail - -REMOTE="${PRISM_REMOTE:-git@github.com:AI-ModCon/PRISM.git}" -WALRUS_PATH="src/libs/walrus" -# owner/repo for the gh API calls, derived from the remote so the two cannot -# disagree. -SLUG="$(printf '%s' "$REMOTE" | sed -E 's#\.git$##; s#^.*[:/]([^/]+/[^/]+)$#\1#')" -PROT_FILE="${PRISM_PROTECTION_FILE:-$HOME/backups/prism/PRISM-branch-protection.json}" - -PUSH=0 -ACTION="" -case "${1:-}" in - --push) PUSH=1 ;; - --remove-protection) ACTION=remove ;; - --restore-protection) ACTION=restore ;; - "") ;; - *) echo "unknown argument: $1" >&2 - sed -n '/^# Usage:/,/^# and if a push fails/p' "$0" >&2 - exit 2 ;; -esac - -# The system python3 on an Aurora login node is 3.6 -- no tomllib, and it -# cannot parse `from __future__ import annotations` in this repo's tooling. -# Find a 3.11+ interpreter rather than assuming `python3` is one. -find_python() { - local c - for c in "${PRISM_PYTHON:-}" python3.13 python3.12 python3.11 python3 \ - /opt/aurora/default/frameworks/aurora_frameworks-*/bin/python3; do - [ -n "$c" ] || continue - command -v "$c" >/dev/null 2>&1 || [ -x "$c" ] || continue - if "$c" -c 'import sys,tomllib; sys.exit(0 if sys.version_info>=(3,11) else 1)' \ - >/dev/null 2>&1; then - echo "$c"; return 0 - fi - done - return 1 -} -PY="$(find_python)" || { - echo "ERROR: no Python 3.11+ with tomllib found. Set PRISM_PYTHON, or" >&2 - echo " module load frameworks first." >&2 - exit 1 -} - -# ---- branch protection ----------------------------------------------------- -# These act on PRISM and build nothing. They exit when done. - -require_gh() { - command -v gh >/dev/null 2>&1 || { - echo "ERROR: gh is not on PATH; the protection flags need it." >&2; exit 1; } - # A stale GITHUB_TOKEN in the environment shadows gh's own credentials on - # this cluster, so every call here clears it. -} - -if [ "$ACTION" = "remove" ]; then - require_gh - echo "Saving current protection for $SLUG main -> $PROT_FILE" - mkdir -p "$(dirname "$PROT_FILE")" - if ! env -u GITHUB_TOKEN gh api "repos/$SLUG/branches/main/protection" \ - > "$PROT_FILE.get" 2>/dev/null; then - echo " branch is already unprotected -- nothing to save, nothing to do." - rm -f "$PROT_FILE.get" - exit 0 - fi - # The GET and PUT schemas differ. Convert, rather than saving the GET and - # discovering at restore time that GitHub rejects it with - # `No subschema in "anyOf" matched`. - "$PY" - "$PROT_FILE.get" "$PROT_FILE" <<'PYX' -import json, sys -g = json.load(open(sys.argv[1])) -rpr = g.get("required_pull_request_reviews") -put = { - "required_status_checks": { - "strict": g["required_status_checks"]["strict"], - "contexts": g["required_status_checks"]["contexts"], - } if g.get("required_status_checks") else None, - "enforce_admins": g["enforce_admins"]["enabled"], - "required_pull_request_reviews": { - "dismiss_stale_reviews": rpr["dismiss_stale_reviews"], - "require_code_owner_reviews": rpr["require_code_owner_reviews"], - "required_approving_review_count": rpr["required_approving_review_count"], - } if rpr else None, - # Restrictions are a user/team/app allowlist; this repo has none. Carrying - # one over would need re-expanding logins, so refuse rather than silently - # drop it. - "restrictions": None, - "required_linear_history": g["required_linear_history"]["enabled"], - "allow_force_pushes": g["allow_force_pushes"]["enabled"], - "allow_deletions": g["allow_deletions"]["enabled"], - "required_conversation_resolution": g["required_conversation_resolution"]["enabled"], -} -if g.get("restrictions"): - sys.exit("ERROR: branch has push restrictions; this script would drop them. " - "Save and restore protection by hand.") -json.dump(put, open(sys.argv[2], "w"), indent=2) -n = len(put["required_status_checks"]["contexts"]) if put["required_status_checks"] else 0 -print(f" saved: {n} required contexts, enforce_admins={put['enforce_admins']}") -PYX - rm -f "$PROT_FILE.get" - env -u GITHUB_TOKEN gh api -X DELETE "repos/$SLUG/branches/main/protection" --silent - echo "Protection REMOVED from $SLUG main. It is unprotected until you run:" - echo " bash tools/make_release_snapshot.sh --restore-protection" - exit 0 -fi - -if [ "$ACTION" = "restore" ]; then - require_gh - [ -f "$PROT_FILE" ] || { - echo "ERROR: no saved protection at $PROT_FILE" >&2 - echo " Run --remove-protection first, or point PRISM_PROTECTION_FILE" >&2 - echo " at a saved PUT payload." >&2 - exit 1; } - env -u GITHUB_TOKEN gh api -X PUT "repos/$SLUG/branches/main/protection" \ - --input "$PROT_FILE" --silent - # Read it back rather than trusting the exit code. - env -u GITHUB_TOKEN gh api "repos/$SLUG/branches/main/protection" --jq \ - '"Protection RESTORED: \(.required_status_checks.contexts|length) required contexts, enforce_admins=\(.enforce_admins.enabled), force_pushes=\(.allow_force_pushes.enabled)"' - exit 0 -fi - -REPO="$(git rev-parse --show-toplevel)" -cd "$REPO" - -SRC_SHA="$(git rev-parse --short HEAD)" -if ! git diff --quiet HEAD -- || ! git diff --cached --quiet; then - echo "ERROR: working tree is dirty. The snapshot is built from HEAD, so" >&2 - echo " uncommitted work would be silently omitted. Commit or stash." >&2 - exit 1 -fi - -WORK="$(mktemp -d)" -trap 'rm -rf "$WORK"' EXIT -OUT="$WORK/snapshot" -mkdir -p "$OUT" - -echo "[1/6] Exporting tree at $SRC_SHA" -# git archive, not cp: it emits exactly the tracked tree. A plain copy would -# pick up untracked local state, and `git add -A` in the new repo would then -# re-apply .gitignore -- which silently drops ~100 files that are tracked here -# despite matching ignore patterns (tools/_*.sh, scaling-study/, jobs/). -git archive --format=tar HEAD | tar -x -C "$OUT" - -echo "[2/6] Reapplying the README badge replacement" -"$PY" - "$OUT" <<'PY' -import pathlib, sys, re -readme = pathlib.Path(sys.argv[1]) / "README.md" -t = readme.read_text() -pat = re.compile( - r"\[!\[CI\]\(https://github\.com/AI-ModCon/BaseMM_PRISM[^\n]*\n" - r"\[!\[codecov\]\(https://codecov\.io/gh/AI-ModCon/BaseMM_PRISM[^\n]*\n" -) -new = ("[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)\n" - "[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](pyproject.toml)\n") -t2, n = pat.subn(new, t, count=1) -if n != 1: - # Loud, not silent: if the badge block was reworded upstream this script - # must be updated, or the snapshot ships badges pointing at a private repo. - raise SystemExit("ERROR: BaseMM badge block not found in README.md -- " - "it was probably reworded. Update this script.") -readme.write_text(t2) -print(" badges replaced") -PY - -echo "[3/6] Disabling Dependabot in the snapshot" -"$PY" - "$OUT" <<'PY' -import pathlib, sys -cfg = pathlib.Path(sys.argv[1]) / ".github" / "dependabot.yml" -if not cfg.exists(): - raise SystemExit("ERROR: .github/dependabot.yml missing -- update this script.") -t = cfg.read_text() -n = t.count("open-pull-requests-limit:") -if n == 0: - raise SystemExit("ERROR: no open-pull-requests-limit found -- update this script.") -import re -t = re.sub(r"open-pull-requests-limit: *\d+", "open-pull-requests-limit: 0", t) -banner = """# --------------------------------------------------------------------------- -# SNAPSHOT REPOSITORY: Dependabot is disabled here via -# `open-pull-requests-limit: 0`, applied by tools/make_release_snapshot.sh. -# Edit that script, not this file -- this copy is regenerated each snapshot. -# -# A Dependabot PR opened against the snapshot cannot be merged usefully: -# changes flow BaseMM_PRISM -> PRISM by force-push, so the next snapshot -# overwrites it. The file is kept rather than deleted because -# tests/platform/test_dependabot_scope.py reads it and runs in PRISM's CI. -# --------------------------------------------------------------------------- -version: 2""" -if "version: 2" not in t: - raise SystemExit("ERROR: `version: 2` not found in dependabot.yml.") -t = t.replace("version: 2", banner, 1) -cfg.write_text(t) -print(f" {n} PR limit(s) set to 0, banner added") -PY - -echo "[4/6] Building the root commit" -# .mailmap is tracked in this repository, so git archive already exported it. -# It used to live only in the snapshot, which is why an earlier version of -# this script copied it in; that copy is now redundant and the file must -# compare equal like any other tracked path. -cd "$OUT" -git init -q -b main -git config user.name "$(git -C "$REPO" config user.name)" -git config user.email "$(git -C "$REPO" config user.email)" -# --force: see the note in step 1. Without it, tracked-but-ignored files vanish. -git add --force -A - -# The submodule is a gitlink; git archive does not emit it, so restore the -# pointer explicitly or `git clone --recursive` silently populates nothing. -WALRUS_SHA="$(git -C "$REPO" ls-tree HEAD "$WALRUS_PATH" | awk '{print $3}')" -if [ -z "$WALRUS_SHA" ]; then - echo "ERROR: no gitlink for $WALRUS_PATH in the source tree." >&2 - exit 1 -fi -git update-index --add --cacheinfo "160000,$WALRUS_SHA,$WALRUS_PATH" - -AUTHORS="$("$PY" - "$REPO/pyproject.toml" <<'PY' -import sys, tomllib -d = tomllib.load(open(sys.argv[1], "rb")) -for a in d["project"]["authors"]: - print(f"Co-Authored-By: {a['name']} <{a['email']}>") -PY -)" - -git commit -q -F - < "$WORK/snap.txt" -git -C "$REPO" ls-tree -r HEAD | awk '{print $3, $4}' | sort > "$WORK/src.txt" -# README and dependabot.yml are expected to differ -- that is the point. -EXPECTED="README.md|.github/dependabot.yml" -if ! diff <(grep -vE " ($EXPECTED)$" "$WORK/src.txt") \ - <(grep -vE " ($EXPECTED)$" "$WORK/snap.txt") > "$WORK/diff.txt"; then - echo "ERROR: snapshot differs from the source tree beyond the two expected files:" >&2 - head -20 "$WORK/diff.txt" >&2 - exit 1 -fi -COMMITS="$(git rev-list --count HEAD)" -COAUTHORS="$(git log -1 --format=%B | grep -c '^Co-Authored-By:')" -echo " 1 root commit ($COMMITS total), $COAUTHORS co-authors, gitlink ${WALRUS_SHA:0:7}" -echo " every other path byte-identical to $SRC_SHA" - -echo "[6/6] Push" -if [ "$PUSH" -eq 1 ]; then - git push --force "$REMOTE" main:main - echo " pushed to $REMOTE" - echo - echo "NOW RESTORE BRANCH PROTECTION -- see the header of this script." -else - # The work dir is removed on exit, so offer a copy that outlives it. - KEEP="${PRISM_SNAPSHOT_OUT:-/tmp/prism-release-snapshot}" - rm -rf "$KEEP" && cp -a "$OUT" "$KEEP" - echo " not pushed (no --push). Snapshot kept at: $KEEP" - echo " inspect, then: git -C $KEEP push --force $REMOTE main:main" -fi