12.2 Atlas Infrastructure Migration Implementation Plan¶
Implementation record: This plan was executed task by task; completed steps use checked boxes.
Status: Completed
Goal: Replace the legacy vendor/genai-vanilla JupyterHub consumption seam with a pinned Atlas infra/ submodule, make each active notebook's Atlas runtime contract machine-readable, and document local VS Code-to-Atlas-JupyterLab as the primary notebook workflow.
Architecture: ml-eng-lab owns a root atlas.consumer.yml, a narrow JupyterHub workspace-mount overlay, local lifecycle wrappers, notebook runtime metadata, and its documentation. Atlas owns the immutable infra/ implementation and local runtime state. The default workflow keeps notebooks in the local checkout and connects VS Code to a running Atlas Jupyter server; a writable mounted checkout at /home/jovyan/work/ml-eng-lab is the explicit fallback for sibling-module imports and host-visible artifacts.
Tech Stack: Git submodule; Atlas 61c7c5103660e2226bf107c115dae42bf46f8374; Docker Compose through Atlas; Bash with ShellCheck; Python 3.11; PyYAML; pytest; MkDocs/site/wiki documentation pipeline; GitHub Actions.
12.2.1 Global constraints¶
- Pin
infra/to the detached Atlas SHA61c7c5103660e2226bf107c115dae42bf46f8374..gitmodulescontains only the Atlas URL andinfrapath—never a movingbranchentry. - Treat
infra/as read-only implementation owned by Atlas. Do not add consumer symlinks under it, alter its compose files, patch its Dockerfiles, or write parent-specific scripts inside it. - The consumer manifest is the committed source of infrastructure intent. It uses
profile: dev,BASE_PORT: auto,JUPYTERHUB_SOURCE: container, one parent-owned compose overlay, and notrack:key. Only the start wrapper selects--track ml-eng. - Pin
LLM_PROVIDER_SOURCE: ollama-localhostin the committed manifest. Do not useautobecause it can resolve toollama-container-cpu; this consumer must never launch containerized Ollama. A normalatlas-upmust fail fast if the operator-owned daemon is unavailable at127.0.0.1:${OLLAMA_LOCALHOST_PORT:-11434}and must not attempt to start it or fall back to a container. - Keep ComfyUI disabled for the current notebook scope. A future task may explicitly opt into only
COMFYUI_SOURCE=localhost(or the documented native managed-MPS mode), nevercontainer-cpuorcontainer-gpu. - JupyterHub is the only service currently authorized by notebook contracts. Other
ml-engtrack services may run by default, but notebooks must not depend on them until a task contract explicitly admits them. - Treat
atlas.env.userandinfra/.envas required local runtime inputs, not optional conveniences. On a fresh clone the wrappers/CI must create them from secret-free templates without overwriting an existing local file. Neither file nor a Jupyter token may be committed. - Do not hard-code a Jupyter or future service port in source.
atlas-connectreads the current Jupyter port/token from Atlas-managed local state and prints it only interactively; it must not use the stable endpoint-export contract, write a token-bearing file, orsource infra/.env. - Notebook metadata must be driven by the 21 active tasks listed in
scripts/verify_repo_config.yaml, ordered bydocs/manifest.yaml, rather than filesystem glob order. It is not a replacement for existing task content metadata. - Preserve all three documentation surfaces: edit canonical docs and the manifest only; let existing generators produce
generated/site,generated/wiki, andmkdocs.yml. Never hand-edit generated outputs. - Do not call the migration complete, remove the legacy gitlink, or change the manual-only quantization status before the static contract, live Atlas package probe, remote VS Code connection, and mounted NumPy import gates have succeeded.
12.2.2 Migration phases¶
- Build and test the parent-owned Atlas contract while the old gitlink remains only as an unmodified rollback reference.
- Validate the real Atlas runtime at the reviewed pin. Resolve the documented package-compatibility boundary from evidence, not image-version assumptions.
- In one final replacement change, retarget all verifier/docs/CI seams and remove the legacy submodule, override, launcher, and active instructions.
12.2.3 Task 1: Add the reusable notebook-infrastructure contract parser and renderer¶
Files:
- Create:
scripts/docs/notebook_infrastructure.py - Create:
tests/test_notebook_infrastructure.py - Modify:
scripts/docs/check_docs.py - Modify:
tests/test_check_docs.py - Modify:
scripts/verify_repo.py - Modify:
tests/test_verify_repo.py
Interfaces to establish:
@dataclass(frozen=True)
class AtlasTaskContract:
task: str
title: str
tier: str
executor: str
default_mode: str
required_services: tuple[str, ...]
workspace_access: str
artifact_policy: str
constraints: tuple[str, ...]
class NotebookInfrastructureError(ValueError): ...
def load_atlas_task_contracts(repo_root: Path, manifest: Manifest) -> list[AtlasTaskContract]: ...
def render_atlas_task_table(contracts: Sequence[AtlasTaskContract]) -> str: ...
def verify_atlas_task_table(doc_path: Path, expected_table: str) -> list[str]: ...
def write_atlas_task_table(doc_path: Path, expected_table: str) -> None: ...
- [x] Add tests first. Use minimal temporary manifests/specs plus the real repository fixture to prove that loading follows
manifest.notebooksorder and that the manifest task set exactly equalsactive_task_dirsinscripts/verify_repo_config.yaml. - [x] Add failing tests for each owned
atlasfield: a mapping is required;executor == "jupyterhub";default_modeisvscode-remoteormounted-workspaceand pairs respectively withworkspace_access: remoteormounted-required;required_servicesis a non-empty, unique service-ID list containingjupyterhub;artifact_policyisatlas-jupyter-volumeortask-local-ignored-paths; andconstraintsis a list of non-empty strings. - [x] Keep future service IDs forward-compatible: validate their syntax and uniqueness, not a closed set of today’s services. Require
jupyterhubonly because the current executor is JupyterHub. - [x] Implement the module under
scripts/docs/, using the existingscripts.docs.manifest.Manifestand PyYAML already available to both runtime and docs requirements. Do not put task-spec parsing intoscripts/docs/manifest.py; that module continues to own only the documentation manifest. - [x] Make the renderer produce exactly one deterministic Markdown table with columns
Task | Tier | Default mode | Workspace access | Required Atlas services | Artifact policy | Constraints, use—for no constraints, and join multiple constraints with<br>. - [x] Add the canonical marker protocol
<!-- atlas-task-contracts:start -->/<!-- atlas-task-contracts:end -->. Make missing, duplicated, reversed, or drifted markers/table content an error.--writeis an explicit maintainer action; ordinary docs builds and CI use--checkand never rewrite canonical Markdown. - [x] Add a thin
check_notebook_infrastructure(manifest, repo_root)adapter inscripts/docs/check_docs.py, and invoke it fromcheck()before generated-surface validation. Add a no-duplication adapter inscripts/verify_repo.py::check_docs; it may no-op only for existing synthetic fixtures that do not containdocs/manifest.yaml. - [x] Cover the adapters with tests that surface schema/table drift as normal docs/verifier findings rather than tracebacks.
Run:
uv run pytest tests/test_notebook_infrastructure.py tests/test_check_docs.py tests/test_verify_repo.py -q
uv run ruff check scripts/docs/notebook_infrastructure.py scripts/docs/check_docs.py scripts/verify_repo.py
Expected: the new contract tests pass, invalid fixtures identify the precise field or marker defect, and existing verifier fixtures remain valid.
- [x] Commit the coherent unit-test and implementation slice.
git add scripts/docs/notebook_infrastructure.py scripts/docs/check_docs.py scripts/verify_repo.py tests/test_notebook_infrastructure.py tests/test_check_docs.py tests/test_verify_repo.py
git commit -m "feat: validate notebook Atlas runtime contracts"
12.2.4 Task 2: Declare every active task’s Atlas contract and publish the canonical table¶
Files:
- Modify: all
notebooks/*/docs/spec.yamlpaths listed indocs/manifest.yaml - Create:
docs/notebook-infrastructure.md - Modify:
docs/manifest.yaml - Modify:
scripts/docs/build_docs.py - Modify:
tests/test_build_docs.py - Modify:
tests/test_transforms.py - Modify:
tests/test_wiki.py - Modify:
scripts/verify_repo.py -
Modify:
Makefile -
[x] Add a failing real-repository test that calls
load_atlas_task_contracts()and asserts 21 validated contracts in documentation-manifest order. - [x] Add the following exact block to every active task spec, preserving existing task content:
atlas:
executor: jupyterhub
default_mode: vscode-remote
required_services: [jupyterhub]
workspace_access: remote
artifact_policy: atlas-jupyter-volume
constraints: []
- [x] Replace that default only for
notebooks/image_classification-mnist-ffnn-numpy/docs/spec.yaml:
atlas:
executor: jupyterhub
default_mode: mounted-workspace
required_services: [jupyterhub]
workspace_access: mounted-required
artifact_policy: task-local-ignored-paths
constraints:
- Browser JupyterLab or VS Code attached to the JupyterHub container is required from /home/jovyan/work/ml-eng-lab because sibling Python modules need the mounted checkout.
- [x] Replace the default only for
notebooks/quantization-mnist-ffnn-pytorch/docs/spec.yaml:
atlas:
executor: jupyterhub
default_mode: vscode-remote
required_services: [jupyterhub]
workspace_access: remote
artifact_policy: atlas-jupyter-volume
constraints:
- Manual-only until Atlas Jupyter package validation passes.
- [x] Create
docs/notebook-infrastructure.mdwith H1# 4.3 Notebook infrastructure, an explanation of the default remote-kernel and mounted-workspace modes, artifact locations, future-service activation rules, and the required generated marker block. Generate the table with the new--writecommand and commit the rendered table. - [x] Expose an explicit Make target such as
docs-sync-notebook-infrastructurethat runspython -m scripts.docs.notebook_infrastructure --write; add the matching check todocs-check/the verifier, never an implicit canonical-doc rewrite. - [x] Register existing runtime docs and the new page under the existing Environment section in
docs/manifest.yaml, without renumbering the current8.xnotebook pages:
- id: environment
number: "4"
title: Environment & runtimes
source: docs/env-setup.md
children:
- id: jupyterhub-integration
number: "4.1"
title: JupyterHub integration
source: docs/jupyterhub-integration.md
- id: vscode-remote-access
number: "4.2"
title: VS Code remote access
source: docs/vscode-remote-access.md
- id: notebook-infrastructure
number: "4.3"
title: Notebook infrastructure
source: docs/notebook-infrastructure.md
- [x] Fix
scripts/docs/build_docs.py::_nav_lines()so a manifest section with bothsourceandchildrenrenders a nested navigation mapping: the section’s source becomes the first leaf and each child remains visible. Do not use the currentif source / elif childrenshape that hides children. - [x] Confirm site source maps, wiki output, and sidebar output contain both the parent Environment page and its three children. Add unit tests for the nav map, transformed paths, and wiki sidebar.
- [x] Add
docs/notebook-infrastructure.mdtoscripts/verify_repo.py::_iter_numbered_doc_filesso its baked H1/H2 numbering is checked.
Run:
python -m scripts.docs.notebook_infrastructure --write
python -m scripts.docs.notebook_infrastructure --check
uv run pytest tests/test_notebook_infrastructure.py tests/test_build_docs.py tests/test_transforms.py tests/test_wiki.py tests/test_check_docs.py -q
make docs-check
Expected: exactly 21 rows, two documented exceptions, visible nested navigation on site/wiki, and no generated-output changes staged.
- [x] Commit the metadata/table/navigation slice.
git add notebooks docs/notebook-infrastructure.md docs/manifest.yaml scripts/docs/build_docs.py scripts/verify_repo.py Makefile tests
git commit -m "docs: declare notebook Atlas runtime contracts"
12.2.5 Task 3: Add the pinned Atlas consumer seam and its static configuration contract¶
Files:
- Modify:
.gitmodules - Add gitlink:
infra/at61c7c5103660e2226bf107c115dae42bf46f8374 - Create:
atlas.consumer.yml - Create:
atlas.env.user.example - Create:
compose/ml-eng-lab-atlas.yml - Modify:
.gitignore - Create:
tests/test_atlas_consumer_contract.py -
Modify:
pyproject.toml -
[x] Start with tests that parse the new manifest/overlay and reject a moving branch, a
track:manifest key, a non-autobase port, non-container JupyterHub source, a missing/non-ollama-localhostLLM source, any containerized/autoOllama source, a containerized ComfyUI source, any SSH mount, a relative workspace path, or an overlay that mounts over/home/jovyan/workitself. - [x] Add the Atlas submodule without deleting
vendor/genai-vanillayet; it remains a rollback reference only until Task 6’s live acceptance gate. Use the exact upstream and detached revision:
git submodule add https://github.com/thekaveh/atlas.git infra
git -C infra checkout --detach 61c7c5103660e2226bf107c115dae42bf46f8374
git submodule status -- infra
- [x] Make the final
.gitmodulesentry structurally equivalent to this and verify it contains nobranch =line:
[submodule "infra"]
path = infra
url = https://github.com/thekaveh/atlas.git
- [x] Add this committed consumer contract exactly; Atlas’s
ml-engselection belongs to the wrapper command, not this YAML:
name: ml-eng-lab
project_name: ml-eng-lab
profile: dev
brand:
name: ML Eng Lab
env:
file: ./atlas.env.user
values:
BASE_PORT: auto
JUPYTERHUB_SOURCE: container
LLM_PROVIDER_SOURCE: ollama-localhost
compose_overlays:
- ./compose/ml-eng-lab-atlas.yml
- [x] Add the local-only template and the sole parent overlay:
# Copy/create this as atlas.env.user; it is ignored and machine-local.
ML_ENG_LAB_REPO_PATH=/absolute/path/to/ml-eng-lab
# Optional: only when the native Ollama daemon uses a non-default port.
# OLLAMA_LOCALHOST_PORT=11434
services:
jupyterhub:
volumes:
- ${ML_ENG_LAB_REPO_PATH}:/home/jovyan/work/ml-eng-lab
- [x] Ignore
atlas.env.userand only Atlas-generated parent-local connection/probe artifacts if implementation introduces them. Keep the already-correct exception that allows revieweddocs/superpowers/specs/*.mdanddocs/superpowers/plans/*.mdthrough the broad planning ignore rule. - [x] Add
infra/beside the existingvendor/pytest/ruff exclusions inpyproject.tomlso the transitional checkout cannot recurse into either submodule. Task 8 removes the now-obsoletevendor/exclusions after the legacy gitlink is gone. - [x] Implement the tests with a temporary copy of the manifest/overlay, then run them against the actual files. They must demonstrate Atlas input correctness without starting Docker.
Run:
git submodule status --recursive
uv run pytest tests/test_atlas_consumer_contract.py -q
git -C infra status --short
Expected: the new gitlink prints the exact detached SHA, static contract tests pass, and infra/ is clean.
- [x] Commit the new consumer seam and configuration only. Do not delete the legacy gitlink in this commit.
git add .gitmodules .gitignore atlas.consumer.yml atlas.env.user.example compose/ml-eng-lab-atlas.yml infra pyproject.toml tests/test_atlas_consumer_contract.py
git commit -m "feat: add pinned Atlas consumer configuration"
12.2.6 Task 4: Implement safe Atlas lifecycle wrappers and the default VS Code connection helper¶
Files:
- Create:
scripts/atlas-up.sh - Create:
scripts/atlas-down.sh - Create:
scripts/atlas-connect.sh - Modify:
Makefile - Create:
tests/test_atlas_lifecycle.py -
Modify:
tests/test_makefile_contract.py -
[x] Write dry-run tests before the scripts. Require
set -euo pipefail, absolute root/manifest resolution, actionable uninitialized-submodule errors, and noevalor secret-bearing artifact writes. Add normal-start tests that require the materialized source to be exactlyollama-localhost, probe only127.0.0.1:<validated-port>/api/version, fail clearly when it is unavailable, and never execute that probe in--prepare,--validate, or--dry-runmode. - [x] Add
make atlas-setup,make atlas-up,make atlas-down,make atlas-connect, andmake atlas-contracthelp/.PHONYentries.atlas-setupmust initialize the exact submodule and then invokeatlas-up.sh --prepare; ordinaryatlas-upalso performs preparation idempotently so a fresh clone cannot reach a confusing missing-env validation failure.
atlas-setup:
git submodule update --init --recursive infra
./scripts/atlas-up.sh --prepare
atlas-up:
./scripts/atlas-up.sh
atlas-down:
./scripts/atlas-down.sh $(if $(COLD),--cold,)
atlas-connect:
./scripts/atlas-connect.sh
atlas-contract:
./scripts/atlas-up.sh --validate
- [x] In
atlas-up.sh, accept only--prepare,--validate, and--dry-run. ResolveREPO_ROOT,INFRA, and an absoluteMANIFEST. When absent, copyinfra/.env.exampletoinfra/.envand createatlas.env.userfrom the template with the resolved absolute root; never overwrite either existing file. Validate the resultingML_ENG_LAB_REPO_PATHis an absolute path matching the checkout. This is mandatory becauseenv backfillis additive and does not create an absent.env, while Atlas requiresenv.filefor non-live validation. - [x] For a normal start, execute and dry-run-print this exact ordered sequence from
infra/:
./start.sh env backfill
./start.sh --consumer "$MANIFEST" compose validate
./start.sh --consumer "$MANIFEST" doctor --format json
./start.sh --consumer "$MANIFEST" --track ml-eng --no-tui --detach
--validate first calls the same idempotent preparation routine, then runs the first three commands and exits without starting services; --prepare creates/verifies only local state. After the doctor succeeds during a normal start, read the materialized .env using the shared non-evaluating dotenv parser: reject any LLM_PROVIDER_SOURCE other than ollama-localhost, validate OLLAMA_LOCALHOST_PORT (default 11434), and require curl --fail --silent --show-error --max-time 2 http://127.0.0.1:<port>/api/version to succeed before detach. On failure, tell the operator to start native Ollama; do not run ollama serve, pass a source flag, or fallback to a container. After a normal final command, fail clearly if git -C "$INFRA" status --porcelain reports a non-ignored change. Do not add a start subcommand, endpoints export, a Docker command, or a service assertion to this wrapper.
- [x] In atlas-down.sh, permit only --cold and --dry-run, construct an argument array, and run (cd "$INFRA" && ./stop.sh "${stop_args[@]}"). Default shutdown must preserve volumes; --cold is opt-in and its help text says it destroys persisted volumes.
- [x] In atlas-connect.sh, provide an interactive-only read-only adapter for the Atlas pin: parse only needed dotenv values from infra/.env without sourcing it, use JUPYTERHUB_PORT and PROJECT_NAME, prefer a configured JUPYTERHUB_TOKEN if present, otherwise obtain the one-time token from the running ${PROJECT_NAME}-jupyterhub container log. Validate every parsed value, avoid shell evaluation, never write a URL, and print the VS Code command-palette steps plus the current http://localhost:<resolved-port>/?token=<resolved-token> connection URL to the terminal.
- [x] Test the precise dry-run command order; that --prepare and --validate do not start services or probe host Ollama; that a normal start rejects a non-localhost resolved source and an unavailable/malformed host port before detach; that --cold never appears unless requested; that a missing local env produces a preparation path rather than validation; and that the connection helper neither relies on ATLAS_*JUPYTER*ENDPOINT nor writes token files.
Run:
uv run pytest tests/test_atlas_lifecycle.py tests/test_makefile_contract.py -q
bash -n scripts/atlas-up.sh scripts/atlas-down.sh scripts/atlas-connect.sh
make -n atlas-setup atlas-up atlas-down atlas-connect
Expected: all static wrapper tests pass; no command starts Docker during dry-run; Make exposes the four documented entry points.
- [x] Commit lifecycle behavior separately from live-runtime evidence.
git add Makefile scripts/atlas-up.sh scripts/atlas-down.sh scripts/atlas-connect.sh tests/test_atlas_lifecycle.py tests/test_makefile_contract.py
git commit -m "feat: add Atlas notebook lifecycle wrappers"
12.2.7 Task 5: Retarget repository verification and add a non-live Atlas CI contract¶
Files:
- Modify:
scripts/verify_repo.py - Modify:
tests/test_verify_repo.py - Create:
.github/workflows/atlas-contract.yml - Modify:
.github/workflows/docs.yml -
Modify:
Makefile -
[x] Add failing verifier tests first for a missing/malformed
atlas.consumer.yml, illegaltrack, missing overlay/template/lifecycle script, an Ollama source other thanollama-localhost, containerized ComfyUI, invalid active-task metadata, hard-coded executablelocalhost:<port>or127.0.0.1:<port>Atlas service URLs, and a dirtyinfraworktree. - [x] Retarget
_required_submodule_paths()fromvendor/genai-vanillatoinfra, preserving existing E6 clean-gitlink/worktree behavior. Retarget the three legacy D10 dependency-ledger fixtures and git index lookup togit ls-files --stage -- infra; retain the stableD10.dependency_ledger_submodule_shafinding identity. - [x] Remove Atlas implementation files from
_required_shellcheck_targets(): the parent owns only its local wrappers. Add explicit required/executable coverage forscripts/atlas-up.sh,scripts/atlas-down.sh, andscripts/atlas-connect.shso their absence cannot be hidden by glob discovery. - [x] Add focused
E15.atlas_manifest,E16.atlas_task_metadata, andE17.atlas_hardcoded_endpointfindings. Reuse the shared notebook-infrastructure parser rather than copying its schema. Exclude documentation, tests, and historical records from the endpoint literal scan; scope it to executable integration code and notebook code cells. - [x] Add
make atlas-contractas the local deterministic wrapper check. Keep the existingverify-repojob’s recursive checkout in.github/workflows/ci.yml. The dedicated GitHub workflow deliberately uses the raw Atlas preflight below as its single command source, so CI tests can assert it never starts services. - [x] Create
.github/workflows/atlas-contract.ymlwith recursive checkout and path filters for.gitmodules,infra,atlas.consumer.yml,atlas.env.user.example,compose/ml-eng-lab-atlas.yml,scripts/atlas-*.sh,scripts/docs/notebook_infrastructure.py,docs/notebook-infrastructure.md,docs/atlas-pin-bump-runbook.md,notebooks/**/docs/spec.yaml, verifier files, and workflow files. - [x] In that job, provision only disposable non-secret state, then run the exact non-live preflight. It must not start containers, detach services, call
endpoints assert, or inspect a live endpoint:
cp infra/.env.example infra/.env
printf 'ML_ENG_LAB_REPO_PATH=%s\n' "$GITHUB_WORKSPACE" > atlas.env.user
(
cd infra
./start.sh env backfill
./start.sh --consumer ../atlas.consumer.yml compose validate
./start.sh --consumer ../atlas.consumer.yml doctor --format json
)
End with git -C infra status --porcelain --untracked-files=all --ignored=no and fail on non-ignored changes.
- [x] Extend .github/workflows/docs.yml path filters and explicit pytest command to include the new parser/tests, docs/manifest.yaml, and task specs so metadata table drift cannot bypass docs CI.
Run:
uv run pytest tests/test_verify_repo.py tests/test_atlas_consumer_contract.py tests/test_atlas_lifecycle.py -q
make atlas-contract
git -C infra status --short
Expected: the verifier is now Atlas-aware, static contract CI is provably non-live, and all submodule checks target only the parent-owned infra seam.
- [x] Commit verifier and CI migration once the static commands are green.
git add scripts/verify_repo.py tests/test_verify_repo.py Makefile .github/workflows/atlas-contract.yml .github/workflows/docs.yml
git commit -m "ci: validate Atlas consumer contract"
12.2.8 Task 6: Capture Atlas runtime compatibility evidence before changing dependency claims¶
Files:
- Create:
scripts/atlas_runtime_probe.py - Create:
tests/test_atlas_runtime_probe.py - Modify:
docs/dependency-contracts.md -
Modify as evidence requires:
requirements.txt,torch-core-requirements.txt,torch-requirements.txt,Dockerfile,.devcontainer/devcontainer.json,Makefile, and their tests/docs -
[x] Write pure unit tests for a JSON probe result evaluator before implementing the probe. It must distinguish a missing module/asset from a version mismatch and must never serialize connection tokens, environment dumps, home paths, or credentials.
- [x] Implement an in-container probe that reports Python, distribution/version, and import evidence for
thekaveh-nnx[lm],nnx, Torch, TorchVision, TorchAudio, TorchAO, PyTorch Geometric,python-louvain, spaCyen_core_web_sm, and NLTK VADER. Include a deterministic check of the direct imports used by active notebook code. - [x] Start the real pin locally with
make atlas-setup,make atlas-up, andmake atlas-connect. Use the printed URL in local VS Code’s Jupyter: Specify Jupyter Server for Connections command and execute a cheap remote-mode notebook while the.ipynbremains in the host checkout. - [x] In the mounted workspace mode, open a Jupyter terminal in the running JupyterLab (or use a verified
docker execcommand for the running Jupyter container), then run the probe and verify every NumPy MNIST sibling module is importable from/home/jovyan/work/ml-eng-lab/notebooks/image_classification-mnist-ffnn-numpy:
cd /home/jovyan/work/ml-eng-lab
python scripts/atlas_runtime_probe.py --json /tmp/ml-eng-lab-atlas-probe.json
cd notebooks/image_classification-mnist-ffnn-numpy
python -c "import consts, feed_fwd_nn, funcs, iteration_data_point, linear_layer, relu_layer, softmax_cross_entropy_layer, utils"
- [x] Record the observed package matrix in
docs/dependency-contracts.md. The expected Atlas image lineage at the reviewed pin includes Torch 2.11.0 / TorchVision 0.26.0 / TorchAudio 2.11.0 / PyG 2.6.1, but treat those as a hypothesis until the probe proves the built image. Do not retain a statement thattorch==2.4.1is required for genai-vanilla image parity. - [x] Reconcile each local dependency manifest deliberately. If its independent venv/Docker/Codespaces stack is retained at another version, label it as a separately tested local contract rather than Atlas parity. If it is moved to the observed Atlas stack, update Torch/TorchVision/TorchAudio/PyG pins together and rerun the matching CPU/Linux tests. Do not install packages at Jupyter session time.
- [x] Keep quantization manual-only unless an explicit Atlas Jupyter quantization smoke imports TorchAO and completes the notebook’s relevant surface. A newer Torch version alone is insufficient evidence.
- [x] If the probe fails a Tier-A import, stop before legacy removal; retain the evidence, correct the parent dependency/documentation contract or obtain a reviewed Atlas pin, then repeat this task. Do not patch
infra/to make the test pass.
Run:
uv run pytest tests/test_atlas_runtime_probe.py -q
make test-nnx-surface
make test
make atlas-down
git -C infra status --short
Expected: package evidence is captured without secrets, the default remote connection and mounted NumPy fallback work, normal shutdown preserves volumes, and infra/ remains clean.
- [x] Commit the evidence-driven dependency reconciliation and probe only after the live gate passes.
git add scripts/atlas_runtime_probe.py tests/test_atlas_runtime_probe.py docs/dependency-contracts.md requirements.txt torch-core-requirements.txt torch-requirements.txt Dockerfile .devcontainer/devcontainer.json Makefile
git commit -m "test: establish Atlas Jupyter runtime compatibility"
12.2.9 Task 7: Rewrite the user-facing documentation, architecture, and Atlas pin-bump runbook¶
Files:
- Modify:
README.md - Modify:
CONTRIBUTING.md - Modify:
docs/env-setup.md - Modify:
docs/jupyterhub-integration.md - Modify:
docs/vscode-remote-access.md - Modify:
docs/architecture.md - Modify:
docs/diagrams/ml-eng-lab-system.html - Modify:
docs/diagrams/ml-eng-lab-runtime-flow.html - Modify:
docs/dependency-contracts.md - Create:
docs/atlas-pin-bump-runbook.md - Modify:
docs/manifest.yaml -
Modify:
CHANGELOG.md -
[x] Register
docs/atlas-pin-bump-runbook.mdas child6.1of the existing Dependency contracts manifest section, preserving current notebook numbers. Update the doc’s H1/H2 numbering and add it to the numbered-doc verifier list. - [x] Rewrite the README quick start and layout to make Atlas local VS Code remote-kernel mode the recommended path. Show
git submodule update --init --recursive,make atlas-setup,make atlas-up,make atlas-connect, and the VS Code server-selection step. Explain the mounted fallback for NumPy MNIST and host-visibledata//runs/; retain Docker, venv, and Codespaces as supported non-Atlas modes. - [x] Make
docs/jupyterhub-integration.mdthe authoritative lifecycle guide: parent/Atlas ownership boundary, prepare/backfill/validate/doctor/start ordering,BASE_PORT: auto, required native Ollama (LLM_PROVIDER_SOURCE=ollama-localhost) and its fail-fast preflight, no-container guarantee, local state, normal versusCOLD=1stop, token safety, troubleshooting, persistence semantics, and theinfraclean-worktree check. - [x] Make
docs/vscode-remote-access.mdlead with remote VS Code to running JupyterLab. Include the exact visual workflow, a warning that notebook-relative writes in this mode land in the Atlas Jupyter volume, and the mounted-workspace fallback for sibling imports/host artifacts. Do not document an invented exported Jupyter endpoint or a fixed port. - [x] Update
CONTRIBUTING.mdwith the notebookatlas:metadata requirement, generator/check command, the future-service activation sequence (spec first, central enablement, injected in-network variable, targeted runtime smoke, docs), and the rule against changes insideinfra/. - [x] State in the future-service guide that an injected variable alone is not availability evidence: for example,
SPARK_REMOTEmay have a default value while Spark remains disabled. A task may rely on a future service only after its manifest source is explicitly enabled, doctor confirms the consumer configuration, and its targeted runtime smoke succeeds. For future image generation, the only permissible sources are hostlocalhostor native managed-MPS; containerized ComfyUI is prohibited for this consumer. - [x] Update environment/dependency docs to distinguish Atlas’s observed Jupyter package contract from separate local installs, describe the manual-only quantization evidence, and remove all instructions to invoke
vendor/genai-vanillaorscripts/start-jupyterhub.sh. - [x] Update the system and runtime-flow diagram source to show: local VS Code → Atlas Jupyter kernel as default; browser/container-attached mode → mounted checkout as fallback; parent manifest/overlay/wrappers/specs around a pinned
infragitlink; future services disabled until a task declares them. Regenerate PNG/SVG only through the existing diagram tooling. - [x] Write the pin-bump runbook with the immutable procedure: choose/review target SHA; update only the gitlink; provision local state; run backfill/compose validate/doctor; execute static suite; run
make atlas-up, package probe, remote connection, mounted NumPy smoke, normal stop, andinfraclean check; then update ledger/docs/changelog and stage only the reviewed gitlink and parent-owned changes. Explain that Atlas automatically adds--buildafter a committed Atlas SHA change through.atlas-build-state; an ordinary pin bump does not require--cold. Require an explicit rebuild only for documented uncommitted Dockerfile/context changes, and reserve--coldfor the separate destructive volume-reset path. - [x] Add a Changelog entry that identifies Atlas as the direct successor to the former genai-vanilla seam and states the exact pin.
Run:
make docs-build
make docs-check
rg -n -i "genai-vanilla|vendor/genai-vanilla|start-jupyterhub" README.md CONTRIBUTING.md docs Makefile scripts .github pyproject.toml
Expected: all active guidance points to Atlas, documentation surfaces include all runtime pages, and remaining legacy matches are only explicitly historical records awaiting Task 8 removal/annotation.
- [x] Commit the documentation and diagram migration.
git add README.md CONTRIBUTING.md CHANGELOG.md docs Makefile scripts/verify_repo.py
git commit -m "docs: make Atlas the primary notebook runtime"
12.2.10 Task 8: Complete the direct replacement and remove the legacy consumer seam¶
Files:
- Remove gitlink:
vendor/genai-vanilla/ - Remove:
deploy/genai-vanilla-jupyterhub.override.yml - Remove:
scripts/start-jupyterhub.sh - Replace:
docs/FINDINGS-VENDOR.mdwithdocs/FINDINGS-ATLAS.md -
Modify:
.gitmodules,.gitignore,pyproject.toml,scripts/verify_repo.py, tests, docs, workflows, and all active references identified by the final search -
[x] Re-run the Task 6 live acceptance evidence immediately before deletion. Do not remove the legacy path if the normal Atlas start, VS Code connection, mounted NumPy import, or dependency probe regressed.
- [x] Retire the old gitlink precisely, then verify no submodule config remains for it:
git submodule deinit -f -- vendor/genai-vanilla
git rm -f vendor/genai-vanilla
git add .gitmodules
Do not recursively delete arbitrary .git/modules state; Git’s retained local metadata is harmless and recoverable.
- [x] Delete the legacy parent compose override and launcher. Ensure no target, verifier, workflow, README, or active environment document references their old paths.
- [x] Replace the old vendor findings ledger with docs/FINDINGS-ATLAS.md. It must state that Atlas findings are reported upstream without modifying the pinned submodule, link to the Atlas dependency-contract ledger, and contain only current observations rather than copied historical genai-vanilla comments.
- [x] Finish the pyproject.toml migration so infra/ is excluded from pytest/ruff traversal and vendor/ is no longer treated as a consumed repository path.
- [x] Use a scoped search to eliminate active legacy instructions. Preserve dated maintenance records only when they plainly describe historical state; do not rewrite audit history to pretend Atlas existed then.
Run:
git submodule status --recursive
test ! -e vendor/genai-vanilla
test ! -e deploy/genai-vanilla-jupyterhub.override.yml
test ! -e scripts/start-jupyterhub.sh
rg -n -i "vendor/genai-vanilla|scripts/start-jupyterhub\.sh|genai-vanilla" README.md CONTRIBUTING.md docs Makefile scripts .github pyproject.toml
git -C infra status --short
Expected: infra/ is the sole infrastructure gitlink, legacy launch/config files are gone, active docs are clean, and deliberately historical matches are clearly dated.
- [x] Commit the irreversible-in-practice replacement only after the gate above is green.
git add -A .gitmodules pyproject.toml docs scripts Makefile .github tests infra vendor deploy
git commit -m "refactor: replace genai-vanilla submodule with Atlas"
12.2.11 Task 9: Run the complete acceptance suite and record release evidence¶
Files:
- Modify if required by verified results only:
CHANGELOG.md,docs/dependency-contracts.md,docs/atlas-pin-bump-runbook.md -
No generated files should be committed.
-
[x] Start from a clean clone or a fresh worktree. Initialize recursive submodules and verify the target gitlink is the reviewed detached SHA.
- [x] Run all static gates after the legacy deletion:
git submodule update --init --recursive
make atlas-setup
make atlas-contract
make verify
make test
make test-nnx-surface
make lint
make docs-check
git diff --check
- [x] Run the manual live release smoke in a Docker-capable environment with a running native Ollama daemon:
make atlas-up; assertdocker compose pshas neitherollamanorollama-pullfor theml-eng-labproject;make atlas-connect; attach local VS Code to the returned Jupyter server; execute a representative remote-mode notebook; open a running-Jupyter terminal for the mounted-mode NumPy sibling-import command and runtime probe; runmake atlas-down; verifygit -C infra status --shortis empty. - [x] Verify
COLD=1 make atlas-downis documented but is not exercised in routine validation because it removes persistent volumes. If it must be tested, use disposable state and record that scope in the runbook evidence. - [x] Confirm the GitHub static Atlas job starts no services by reviewing its logged command sequence, and schedule/dispatch the opt-in live smoke only after the static workflow is green. The live smoke must cover Jupyter health, package probe, connection guidance, mounted NumPy import, and clean
infrastate without becoming a default PR job. - [x] Update the ledger/runbook/changelog only with facts proven by these commands. Confirm no token URL, local absolute path,
atlas.env.user,infra/.env,.atlas-build-state, data, runs, or generated docs entered Git.
Run final audit:
git status --short
git diff --cached --check
git submodule status --recursive
git -C infra status --short
rg -n "JUPYTERHUB_TOKEN|token=" README.md CONTRIBUTING.md CHANGELOG.md docs Makefile scripts .github atlas.consumer.yml atlas.env.user.example compose --glob '!docs/maintenance/**' --glob '!docs/superpowers/**'
Expected: only intentional parent-owned changes are staged, the Atlas gitlink is clean and pinned, all documented workflows have evidence, and no secret-bearing runtime artifact is tracked.
- [x] Create the final implementation commit(s) and open review with the static and live evidence attached. Do not advance the Atlas SHA as part of review cleanup; pin bumps follow the new runbook.
12.2.12 Task 10: Enforce the native-host AI service policy¶
Files:
- Modify:
atlas.consumer.yml - Modify:
atlas.env.user.example - Modify:
scripts/atlas-up.sh - Modify:
scripts/lib/atlas-dotenv.shonly if the existing parser lacks a safe last-value lookup - Modify:
scripts/verify_repo.py - Modify:
tests/test_atlas_consumer_contract.py - Modify:
tests/test_atlas_lifecycle.py - Modify:
tests/test_verify_repo.py
Interfaces:
- The manifest must materialize
LLM_PROVIDER_SOURCE=ollama-localhostbefore every Atlas start. scripts/atlas-up.shmay call a single internal host preflight only for an ordinary start. It clears inheritedLLM_PROVIDER_SOURCE,COMFYUI_SOURCE, andOLLAMA_LOCALHOST_PORTvalues, rejects an explicitly declaredatlas.env.userComfyUI source unless it is host-native (or disabled), then probeshttp://127.0.0.1:<OLLAMA_LOCALHOST_PORT>/api/versionwith proxy and curlrc configuration disabled;<OLLAMA_LOCALHOST_PORT>defaults to11434and must be an integer from1through65535.-
--prepare,--validate, and--dry-runremain non-live and must not require, start, or contact a host Ollama daemon. -
[x] Add failing manifest/verification tests that reject an omitted or non-
ollama-localhostLLM_PROVIDER_SOURCE, includingauto,ollama-container-cpu, andollama-container-gpu. RejectCOMFYUI_SOURCE=container-cpuandCOMFYUI_SOURCE=container-gpu; do not require a ComfyUI source while the ml-eng track keeps it disabled. - [x] Update the exact committed manifest contract:
env:
file: ./atlas.env.user
values:
BASE_PORT: auto
JUPYTERHUB_SOURCE: container
LLM_PROVIDER_SOURCE: ollama-localhost
Keep COMFYUI_SOURCE absent. Add only a commented OLLAMA_LOCALHOST_PORT=11434 example to atlas.env.user.example, explaining that an operator sets it only for a non-default native-daemon port.
- [x] Add lifecycle tests with fake start.sh and curl executables. The ordinary-start test must record the ordered Atlas calls, show that compose validate materializes LLM_PROVIDER_SOURCE=ollama-localhost, and require the preflight before the detach call. Add failures for a changed source, a malformed/out-of-range port, missing curl, and a failed /api/version response. Exercise atlas.env.user values that attempt COMFYUI_SOURCE=auto, container-cpu, or container-gpu, and conflicting parent-shell exports. Assert that the diagnostics tell the operator to start native Ollama and that none invokes ollama serve, docker, or a container-source flag.
- [x] Implement the smallest non-evaluating helper needed to read the final materialized .env values and any explicit consumer-local ComfyUI override. In atlas-up.sh, clear inherited policy variables and run the host check only after env backfill, consumer compose validation, and doctor pass, and only in ordinary start mode. When atlas.env.user explicitly declares COMFYUI_SOURCE, permit only disabled, localhost, or managed-localhost-mps; reject auto and every containerized source. When it is absent, leave the pinned default for the final ml-eng track to disable. Do not add a source flag to Atlas’s command line. Use a loopback URL plus curl --disable --noproxy '*' for the host-side check; Atlas itself routes its containers through host.docker.internal.
- [x] Extend repository verification with a stable Atlas-manifest finding that enforces the same source policy without requiring Docker, curl, a host Ollama installation, or local runtime state.
Run:
uv run pytest tests/test_atlas_consumer_contract.py tests/test_atlas_lifecycle.py tests/test_verify_repo.py -q
bash -n scripts/atlas-up.sh scripts/lib/atlas-dotenv.sh
make atlas-contract
git diff --check
Expected: static CI remains non-live; a normal local start cannot reach detach unless the manifest resolves to native host Ollama and the daemon answers on loopback; no consumer source can select a containerized Ollama or ComfyUI.
- [x] Commit the policy enforcement slice.
git add atlas.consumer.yml atlas.env.user.example scripts/atlas-up.sh scripts/lib/atlas-dotenv.sh scripts/verify_repo.py tests/test_atlas_consumer_contract.py tests/test_atlas_lifecycle.py tests/test_verify_repo.py
git commit -m "feat: require native Ollama for Atlas"