# Offline Windows Installer Implementation Plan > **Status:** Abandoned at the user's request on 2026-05-13 before implementation began. This file is retained as historical planning context only. Do not execute this plan unless the user explicitly reopens offline installer work. > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Build an offline Windows installer that installs the existing `pdf2md` CLI/UI runtime on another Windows x64 PC without internet access. **Architecture:** Build a large installer payload on an internet-connected build PC, then create the target PC `.venv` locally from bundled wheels during installation. Keep conversion behavior unchanged and keep the UI as a launcher over the installed project-owned `pdf2md` CLI. **Tech Stack:** Python 3.12, uv, pip wheelhouse/download workflow, PyInstaller, PowerShell, Inno Setup, MinerU 3.1.0, CUDA PyTorch `2.6.0+cu126`, optional Node.js/MathJax. --- ## File Structure - `docs/Sprints/SPRINT17CONTRACT.md`: sprint contract, scope, acceptance criteria, and hard failure criteria. - `packaging/offline/build-offline-payload.ps1`: connected build-PC script that stages all offline files under `dist/offline-installer/`. - `packaging/offline/verify-offline-payload.ps1`: build-PC and target-PC script that validates `payload-manifest.json` and hashes. - `packaging/offline/install-runtime.ps1`: target-PC installer script that hash-verifies the payload, creates `.venv`, installs from local wheels, configures local models, and runs doctor. - `packaging/offline/repair-runtime.ps1`: target-PC repair script that recreates `.venv` from the retained wheelhouse. - `packaging/offline/run-doctor.ps1`: shortcut target for post-install diagnostics. - `packaging/offline/Pdf2MdOffline.iss`: Inno Setup installer script. - `packaging/offline/requirements-runtime-cu126.txt`: pinned offline runtime requirement set for Windows x64 CUDA 12.6 wheels. - `packaging/offline/README.md`: build and install instructions. - `packaging/offline/THIRD_PARTY_NOTICES.md`: redistribution notes and license links for bundled payload families. - `src/pdf2md/packaging_manifest.py`: optional small helper for deterministic manifest/hash generation. - `src/pdf2md_ui/runner.py`: installed runtime command resolution and child environment updates. - `src/pdf2md_ui/app.py`: installed runtime project-root default only if needed. - `tests/test_offline_packaging.py`: fast tests for manifest, script safety, and installer script contents with fake payloads. - `tests/test_ui_runner.py`: fast tests for installed `.venv` and bundled `uv --offline` command resolution. - `.gitignore`: ignore generated payload, wheelhouse, models, and installer outputs. - `README.md` and `docs/V1RELEASECHECKLIST.md`: user-facing build/release documentation. - `PLAN.md`, `PROGRESS.md`, `docs/WORKARCHIVE.md`: coordination and handoff. ## Task 1: Packaging Manifest And Ignore Policy **Files:** - Create: `tests/test_offline_packaging.py` - Create: `src/pdf2md/packaging_manifest.py` - Modify: `.gitignore` - [ ] **Step 1: Write the failing manifest tests** ```python from pathlib import Path from pdf2md.packaging_manifest import build_payload_manifest def test_build_payload_manifest_records_hash_size_and_source(tmp_path: Path) -> None: payload = tmp_path / "payload" payload.mkdir() wheel = payload / "wheelhouse" / "example-1.0-py3-none-any.whl" wheel.parent.mkdir() wheel.write_bytes(b"wheel-bytes") manifest = build_payload_manifest( payload, sources={"wheelhouse/example-1.0-py3-none-any.whl": "local test wheel"}, ) assert manifest["files"] == [ { "path": "wheelhouse/example-1.0-py3-none-any.whl", "size": 11, "sha256": "9ceb18f15662bb87e54af2f5953c0484d2ef76f5444d87913360b9ef87d7296d", "source": "local test wheel", } ] def test_build_payload_manifest_uses_forward_slash_relative_paths(tmp_path: Path) -> None: payload = tmp_path / "payload" nested = payload / "models" / "mineru" / "model.bin" nested.parent.mkdir(parents=True) nested.write_bytes(b"model") manifest = build_payload_manifest(payload, sources={}) assert manifest["files"][0]["path"] == "models/mineru/model.bin" ``` - [ ] **Step 2: Run the manifest tests to verify failure** Run: ```powershell uv run pytest tests/test_offline_packaging.py -q ``` Expected: FAIL because `pdf2md.packaging_manifest` does not exist. - [ ] **Step 3: Implement the minimal manifest helper** ```python """Offline installer payload manifest helpers.""" from __future__ import annotations import hashlib from pathlib import Path from typing import Mapping, TypedDict class ManifestFile(TypedDict): path: str size: int sha256: str source: str class PayloadManifest(TypedDict): files: list[ManifestFile] def build_payload_manifest(payload_root: str | Path, *, sources: Mapping[str, str]) -> PayloadManifest: root = Path(payload_root) files: list[ManifestFile] = [] for path in sorted(candidate for candidate in root.rglob("*") if candidate.is_file()): relative = path.relative_to(root).as_posix() files.append( { "path": relative, "size": path.stat().st_size, "sha256": _sha256(path), "source": sources.get(relative, "unknown"), } ) return {"files": files} def _sha256(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as handle: for chunk in iter(lambda: handle.read(1024 * 1024), b""): digest.update(chunk) return digest.hexdigest() ``` - [ ] **Step 4: Add generated payload ignores** Append to `.gitignore`: ```gitignore dist/ packaging/offline/_payload/ packaging/offline/_wheelhouse/ packaging/offline/_models/ *.issig *.exe.tmp ``` If `dist/` is already ignored implicitly by an existing entry, keep one clear `dist/` entry and avoid duplicates. - [ ] **Step 5: Run tests** Run: ```powershell uv run pytest tests/test_offline_packaging.py -q git diff --check ``` Expected: tests PASS; diff check has no whitespace errors. - [ ] **Step 6: Commit** ```powershell git add .gitignore src\pdf2md\packaging_manifest.py tests\test_offline_packaging.py git commit -m "feat: add offline payload manifest helper" ``` ## Task 2: Offline Payload Builder **Files:** - Create: `packaging/offline/build-offline-payload.ps1` - Create: `packaging/offline/verify-offline-payload.ps1` - Create: `packaging/offline/requirements-runtime-cu126.txt` - Create: `packaging/offline/README.md` - Modify: `tests/test_offline_packaging.py` - [ ] **Step 1: Write tests for builder safety** ```python from pathlib import Path def test_payload_builder_excludes_development_and_sample_paths() -> None: script = Path("packaging/offline/build-offline-payload.ps1").read_text(encoding="utf-8") assert ".git" in script assert ".venv" in script assert "samples" in script assert "outputs" in script assert "Copy-Item -Recurse -Force" in script def test_runtime_requirements_pin_core_gpu_stack() -> None: requirements = Path("packaging/offline/requirements-runtime-cu126.txt").read_text(encoding="utf-8") assert "torch==2.6.0" in requirements assert "torchvision==0.21.0" in requirements assert "mineru[core]==3.1.0" in requirements assert "pypdf" in requirements ``` - [ ] **Step 2: Run tests to verify failure** Run: ```powershell uv run pytest tests/test_offline_packaging.py -q ``` Expected: FAIL because the packaging files do not exist. - [ ] **Step 3: Create the pinned requirements file** ```text convert-pdf-to-md==0.1.0 pypdf>=6.10.2,<7 torch==2.6.0 torchvision==0.21.0 mineru[core]==3.1.0 ``` - [ ] **Step 4: Create the payload builder skeleton** The script must accept explicit input paths and fail when required payload pieces are missing: ```powershell param( [string]$Configuration = "Release", [string]$PythonInstaller, [string]$UvExe, [string]$MinerUModelSource, [string]$NodeRoot = "", [string]$OutputRoot = "dist\offline-installer" ) $ErrorActionPreference = "Stop" $RepoRoot = Resolve-Path (Join-Path $PSScriptRoot "..\..") $StageRoot = Join-Path $RepoRoot $OutputRoot $AppRoot = Join-Path $StageRoot "app" $RuntimeRoot = Join-Path $StageRoot "runtime" $PayloadRoot = Join-Path $StageRoot "payload" if (-not (Test-Path $PythonInstaller)) { throw "Missing Python installer: $PythonInstaller" } if (-not (Test-Path $UvExe)) { throw "Missing uv.exe: $UvExe" } if (-not (Test-Path $MinerUModelSource)) { throw "Missing MinerU model source: $MinerUModelSource" } if (-not (Test-Path (Join-Path $RepoRoot "dist\pdf2md-ui.exe"))) { throw "Missing UI exe. Build dist\pdf2md-ui.exe first." } Remove-Item -LiteralPath $StageRoot -Recurse -Force -ErrorAction SilentlyContinue New-Item -ItemType Directory -Path $AppRoot,$RuntimeRoot,$PayloadRoot | Out-Null $Excluded = @(".git", ".venv", "samples", "outputs", "dist", "build", "node_modules", ".pytest_cache", "__pycache__") Copy-Item -Recurse -Force (Join-Path $RepoRoot "src") (Join-Path $RuntimeRoot "src") Copy-Item -Force (Join-Path $RepoRoot "pyproject.toml") (Join-Path $RuntimeRoot "pyproject.toml") Copy-Item -Force (Join-Path $RepoRoot "uv.lock") (Join-Path $RuntimeRoot "uv.lock") Copy-Item -Force (Join-Path $RepoRoot "README.md") (Join-Path $RuntimeRoot "README.md") Copy-Item -Force (Join-Path $RepoRoot "dist\pdf2md-ui.exe") (Join-Path $AppRoot "pdf2md-ui.exe") New-Item -ItemType Directory -Path (Join-Path $PayloadRoot "python"),(Join-Path $PayloadRoot "uv") | Out-Null Copy-Item -Force $PythonInstaller (Join-Path $PayloadRoot "python\python-3.12-amd64.exe") Copy-Item -Force $UvExe (Join-Path $PayloadRoot "uv\uv.exe") Copy-Item -Recurse -Force $MinerUModelSource (Join-Path $PayloadRoot "models") if ($NodeRoot -and (Test-Path $NodeRoot)) { Copy-Item -Recurse -Force $NodeRoot (Join-Path $PayloadRoot "node") } Write-Host "Offline installer stage created at $StageRoot" Write-Host "Use pip download on the connected build PC to fill payload\wheelhouse before compiling the installer." ``` - [ ] **Step 5: Document the connected wheelhouse build command** Add to `packaging/offline/README.md`: ```powershell uv build --wheel Copy-Item dist\convert_pdf_to_md-0.1.0-py3-none-any.whl dist\offline-installer\payload\wheelhouse\ py -3.12 -m pip download -d dist\offline-installer\payload\wheelhouse -r packaging\offline\requirements-runtime-cu126.txt --find-links dist\offline-installer\payload\wheelhouse --extra-index-url https://download.pytorch.org/whl/cu126 ``` - [ ] **Step 6: Add the payload verifier** `verify-offline-payload.ps1` must read `payload\payload-manifest.json`, recompute SHA-256 for each listed file, and fail when a file is missing or changed. - [ ] **Step 7: Run tests** Run: ```powershell uv run pytest tests/test_offline_packaging.py -q git diff --check ``` Expected: PASS. - [ ] **Step 8: Commit** ```powershell git add packaging\offline\build-offline-payload.ps1 packaging\offline\verify-offline-payload.ps1 packaging\offline\requirements-runtime-cu126.txt packaging\offline\README.md tests\test_offline_packaging.py git commit -m "feat: plan offline payload builder" ``` ## Task 3: Target Runtime Install And Repair Scripts **Files:** - Create: `packaging/offline/install-runtime.ps1` - Create: `packaging/offline/repair-runtime.ps1` - Create: `packaging/offline/run-doctor.ps1` - Modify: `tests/test_offline_packaging.py` - [ ] **Step 1: Write script safety tests** ```python from pathlib import Path def test_install_runtime_uses_only_local_package_sources() -> None: script = Path("packaging/offline/install-runtime.ps1").read_text(encoding="utf-8") assert "--no-index" in script assert "--find-links" in script assert "UV_OFFLINE" in script assert "https://" not in script assert "http://" not in script def test_install_runtime_does_not_silently_overwrite_mineru_config() -> None: script = Path("packaging/offline/install-runtime.ps1").read_text(encoding="utf-8") assert "mineru.json" in script assert "Backup" in script assert "Silent" in script assert "throw" in script ``` - [ ] **Step 2: Run tests to verify failure** Run: ```powershell uv run pytest tests/test_offline_packaging.py -q ``` Expected: FAIL because scripts do not exist. - [ ] **Step 3: Implement `install-runtime.ps1`** The script must: ```powershell param( [string]$InstallRoot = "$env:LOCALAPPDATA\Programs\ConvertPDFToMD", [switch]$Silent ) $ErrorActionPreference = "Stop" $PayloadRoot = Join-Path $InstallRoot "payload" $RuntimeRoot = Join-Path $InstallRoot "runtime" $VenvPython = Join-Path $RuntimeRoot ".venv\Scripts\python.exe" $VenvPdf2Md = Join-Path $RuntimeRoot ".venv\Scripts\pdf2md.exe" $UvExe = Join-Path $PayloadRoot "uv\uv.exe" $Wheelhouse = Join-Path $PayloadRoot "wheelhouse" $Requirements = Join-Path $PayloadRoot "requirements-runtime-cu126.txt" $LogRoot = Join-Path $InstallRoot "logs" New-Item -ItemType Directory -Path $LogRoot -Force | Out-Null $env:UV_OFFLINE = "1" $env:MINERU_MODEL_SOURCE = "local" if (-not (Test-Path $UvExe)) { throw "Missing bundled uv.exe: $UvExe" } if (-not (Test-Path $Wheelhouse)) { throw "Missing wheelhouse: $Wheelhouse" } if (-not (Test-Path $Requirements)) { throw "Missing requirements: $Requirements" } & $UvExe venv (Join-Path $RuntimeRoot ".venv") --python 3.12 if ($LASTEXITCODE -ne 0) { throw "uv venv failed with exit code $LASTEXITCODE" } & $UvExe pip install --python $VenvPython --no-index --find-links $Wheelhouse -r $Requirements if ($LASTEXITCODE -ne 0) { throw "offline package install failed with exit code $LASTEXITCODE" } & $UvExe pip check --python $VenvPython if ($LASTEXITCODE -ne 0) { throw "uv pip check failed with exit code $LASTEXITCODE" } $MinerUConfig = Join-Path $env:USERPROFILE "mineru.json" if (Test-Path $MinerUConfig) { if ($Silent) { throw "Existing mineru.json requires interactive confirmation: $MinerUConfig" } $Backup = "$MinerUConfig.pdf2md-backup-$(Get-Date -Format yyyyMMddHHmmss)" Copy-Item -Force $MinerUConfig $Backup } & $VenvPdf2Md doctor *> (Join-Path $LogRoot "doctor-after-install.txt") if ($LASTEXITCODE -ne 0) { throw "pdf2md doctor failed with exit code $LASTEXITCODE" } ``` - [ ] **Step 4: Implement repair and doctor scripts** `repair-runtime.ps1` reruns `install-runtime.ps1` for an existing install root. `run-doctor.ps1` runs the installed `.venv\Scripts\pdf2md.exe doctor` and writes `logs\doctor-latest.txt`. - [ ] **Step 5: Run tests** Run: ```powershell uv run pytest tests/test_offline_packaging.py -q git diff --check ``` Expected: PASS. - [ ] **Step 6: Commit** ```powershell git add packaging\offline\install-runtime.ps1 packaging\offline\repair-runtime.ps1 packaging\offline\run-doctor.ps1 tests\test_offline_packaging.py git commit -m "feat: add offline runtime install scripts" ``` ## Task 4: UI Installed Runtime Resolution **Files:** - Modify: `src/pdf2md_ui/runner.py` - Modify: `src/pdf2md_ui/app.py` only if needed - Modify: `tests/test_ui_runner.py` - [ ] **Step 1: Add failing runner tests** ```python from pathlib import Path from pdf2md_ui.runner import resolve_cli_command def test_resolve_prefers_project_venv_pdf2md(tmp_path: Path) -> None: root = tmp_path / "runtime" scripts = root / ".venv" / "Scripts" scripts.mkdir(parents=True) (root / "pyproject.toml").write_text("[project]\nname='x'\n", encoding="utf-8") pdf2md = scripts / "pdf2md.exe" pdf2md.write_text("", encoding="utf-8") resolved = resolve_cli_command(project_root=root, which=lambda name: None) assert resolved.args_prefix == (str(pdf2md),) assert resolved.cwd is None assert resolved.source == "venv" def test_resolve_uses_bundled_uv_offline_when_no_venv_command(tmp_path: Path) -> None: root = tmp_path / "runtime" root.mkdir() (root / "pyproject.toml").write_text("[project]\nname='x'\n", encoding="utf-8") uv = tmp_path / "payload" / "uv" / "uv.exe" uv.parent.mkdir(parents=True) uv.write_text("", encoding="utf-8") resolved = resolve_cli_command(project_root=root, bundled_uv=uv, which=lambda name: None) assert resolved.args_prefix == (str(uv), "run", "--offline", "pdf2md") assert resolved.cwd == root assert resolved.source == "bundled-uv" ``` - [ ] **Step 2: Run tests to verify failure** Run: ```powershell uv run pytest tests/test_ui_runner.py -q ``` Expected: FAIL because the runner does not yet support installed `.venv` or bundled uv resolution. - [ ] **Step 3: Implement minimal runner changes** Add `bundled_uv` as an optional keyword to `resolve_cli_command`, check `\.venv\Scripts\pdf2md.exe` after configured command and before PATH, and use bundled `uv run --offline pdf2md` before system `uv`. - [ ] **Step 4: Add child environment tests** Add a test that `build_child_environment(project_root=runtime_root)` prepends `.venv\Scripts` and `payload\node` when those folders exist, while preserving `MINERU_MODEL_SOURCE=custom` if the user already set it. - [ ] **Step 5: Run tests** Run: ```powershell uv run pytest tests/test_ui_runner.py -q ``` Expected: PASS. - [ ] **Step 6: Commit** ```powershell git add src\pdf2md_ui\runner.py src\pdf2md_ui\app.py tests\test_ui_runner.py git commit -m "feat: resolve installed offline runtime from UI" ``` ## Task 5: Inno Setup Script **Files:** - Create: `packaging/offline/Pdf2MdOffline.iss` - Modify: `tests/test_offline_packaging.py` - [ ] **Step 1: Add Inno script tests** ```python from pathlib import Path def test_inno_script_installs_payload_and_shortcuts() -> None: script = Path("packaging/offline/Pdf2MdOffline.iss").read_text(encoding="utf-8") assert "DefaultDirName={localappdata}\\Programs\\ConvertPDFToMD" in script assert "payload\\*" in script assert "app\\*" in script assert "runtime\\*" in script assert "pdf2md-ui.exe" in script assert "install-runtime.ps1" in script assert "PDF2MD Doctor" in script assert "Repair PDF2MD Runtime" in script def test_inno_script_excludes_development_artifacts() -> None: script = Path("packaging/offline/Pdf2MdOffline.iss").read_text(encoding="utf-8") assert "samples" not in script assert "outputs" not in script assert ".venv" not in script ``` - [ ] **Step 2: Run tests to verify failure** Run: ```powershell uv run pytest tests/test_offline_packaging.py -q ``` Expected: FAIL because the Inno script does not exist. - [ ] **Step 3: Create the Inno script** ```ini [Setup] AppId={{PDF2MD-OFFLINE-INSTALLER}} AppName=ConvertPDFToMD AppVersion=0.1.0 DefaultDirName={localappdata}\Programs\ConvertPDFToMD DefaultGroupName=ConvertPDFToMD OutputDir=..\..\dist OutputBaseFilename=Pdf2MdOfflineSetup-0.1.0 Compression=lzma2 SolidCompression=yes PrivilegesRequired=lowest [Files] Source: "..\..\dist\offline-installer\payload\*"; DestDir: "{app}\payload"; Flags: recursesubdirs createallsubdirs Source: "..\..\dist\offline-installer\app\*"; DestDir: "{app}\app"; Flags: recursesubdirs createallsubdirs Source: "..\..\dist\offline-installer\runtime\*"; DestDir: "{app}\runtime"; Flags: recursesubdirs createallsubdirs Source: "install-runtime.ps1"; DestDir: "{app}\scripts" Source: "repair-runtime.ps1"; DestDir: "{app}\scripts" Source: "run-doctor.ps1"; DestDir: "{app}\scripts" [Icons] Name: "{group}\ConvertPDFToMD"; Filename: "{app}\app\pdf2md-ui.exe"; WorkingDir: "{app}\runtime" Name: "{group}\PDF2MD Doctor"; Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\scripts\run-doctor.ps1"""; WorkingDir: "{app}" Name: "{group}\Repair PDF2MD Runtime"; Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\scripts\repair-runtime.ps1"""; WorkingDir: "{app}" [Run] Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\scripts\install-runtime.ps1"" -InstallRoot ""{app}"""; StatusMsg: "Installing offline pdf2md runtime..."; Flags: runhidden ``` - [ ] **Step 4: Run tests** Run: ```powershell uv run pytest tests/test_offline_packaging.py -q git diff --check ``` Expected: PASS. - [ ] **Step 5: Compile with Inno Setup on a build PC** Run: ```powershell ISCC.exe packaging\offline\Pdf2MdOffline.iss ``` Expected: exit code 0 and `dist\Pdf2MdOfflineSetup-0.1.0.exe` exists. Do not commit the generated exe. - [ ] **Step 6: Commit** ```powershell git add packaging\offline\Pdf2MdOffline.iss tests\test_offline_packaging.py git commit -m "feat: add offline installer script" ``` ## Task 6: Documentation, Verification, And Handoff **Files:** - Modify: `README.md` - Modify: `docs/V1RELEASECHECKLIST.md` - Modify: `docs/Sprints/SPRINT17CONTRACT.md` - Modify: `PLAN.md` - Modify: `PROGRESS.md` - Modify: `docs/WORKARCHIVE.md` - [ ] **Step 1: Document build and install flow** Add a README section with: ```markdown ## Offline Windows Installer The offline installer is built on an internet-connected Windows x64 build PC, then copied to a target Windows x64 PC with networking disabled. The target installer creates a fresh `.venv` from bundled wheels; it does not copy the development `.venv`. ``` - [ ] **Step 2: Document verification gates** Add to `docs/V1RELEASECHECKLIST.md`: ```markdown ### Offline Installer Gate - Build `dist\pdf2md-ui.exe`. - Stage the offline payload. - Verify payload hashes. - Compile the Inno Setup installer. - Install on a clean Windows x64 VM with networking disabled. - Run `pdf2md doctor` from the installed `.venv`. - Run one optional local conversion only when a local test PDF is available and generated outputs remain ignored. ``` - [ ] **Step 3: Run final fast tests** Run: ```powershell uv run pytest tests/test_offline_packaging.py tests/test_ui_runner.py uv run pytest git diff --check ``` Expected: PASS, except pre-existing documented optional skips. - [ ] **Step 4: Run packaging smoke on build PC** Run: ```powershell uv run --group ui-build pyinstaller --clean --onefile --windowed --name pdf2md-ui src\pdf2md_ui\app.py $pythonInstaller = "C:\BuildCache\python-3.12-amd64.exe" $uvExe = "C:\BuildCache\uv.exe" $mineruModels = "C:\BuildCache\mineru-models" powershell -ExecutionPolicy Bypass -File packaging\offline\build-offline-payload.ps1 -Configuration Release -PythonInstaller $pythonInstaller -UvExe $uvExe -MinerUModelSource $mineruModels ISCC.exe packaging\offline\Pdf2MdOffline.iss ``` Expected: installer exe exists under `dist\`; generated files remain untracked. - [ ] **Step 5: Update coordination docs** Record changed files, verification output, generated installer path, payload size, and residual risks in `PROGRESS.md`. Move final implementation evidence and offline VM smoke results to `docs/WORKARCHIVE.md`. - [ ] **Step 6: Commit final docs** ```powershell git add README.md docs\V1RELEASECHECKLIST.md docs\Sprints\SPRINT17CONTRACT.md PLAN.md PROGRESS.md docs\WORKARCHIVE.md git commit -m "docs: record offline installer release gate" ``` ## Execution Notes - Do not commit payload contents, wheels, model files, Python installers, Node binaries, generated installer exe files, `samples/`, or `outputs/`. - Keep runtime conversion strict-local. Setup-time payload creation may use internet only on the build PC. - Treat license/model redistribution review as a release gate before sharing the installer outside the current personal environment.