Skip to content

Release Process and Hygiene

M T edited this page Oct 4, 2026 · 1 revision

Release Process and Hygiene

Halo Vision is published as a curated public source tree plus, from 1.0.3 on, separately authorised GitHub Release assets (a source ZIP, a visual-assets ZIP and a Complete bundle). Because the project works with privately owned game files, product registration values, Apple signing material and device identifiers, the release process is built around privacy controls: an exact per-file SOURCE_MANIFEST.json, a path and content hygiene auditor that never prints what it finds, a narrowly scoped Gitleaks configuration, an extensive .gitignore, and documented validation boundaries that keep "compiled", "signed", "installed", "launched" and "played" as separate claims. This page documents the release procedure, the version history, the release assets, the manifests, and every hygiene rule.

Source files

File Role
docs/RELEASING.md Release procedure for source updates and Complete release assets.
docs/COMPLETE_RELEASE.md User guide for the Complete bundle and its verification.
docs/VALIDATION.md What was actually validated for each release, and what was not.
CHANGELOG.md, VERSION Version history; current version 1.0.3.
SOURCE_MANIFEST.json SHA-256 manifest of every source file except itself.
tools/check_repository_hygiene.py, tools/test_repository_hygiene.py Path/content audit and its regressions.
.gitleaks.toml Gitleaks configuration (default rules plus one narrow allowlist).
.gitignore Keeps owned data, build products and signing material out of Git.
.github/workflows/source-checks.yml CI (strict hygiene plus portable suite).
.github/ISSUE_TEMPLATE/bug_report.yml, config.yml Privacy-aware issue intake.
AGENTS.md, CONTRIBUTING.md Ground rules for agents and contributors.
docs/ASSET_NOTICES.md, docs/assets/README.md Third-party asset notices and header-art provenance.

Release artefacts

Artefact Contents Where
Git repository mitchaiet/master-chef Curated source and documentation, the reviewed header PNG, public manifests (mods/*.json, SOURCE_MANIFEST.json). No game data, generated engine code, binaries or private history. GitHub
MasterChef-v1.0.3-source.zip (+ .sha256) The source snapshot for the tag; "no Git history". Release v1.0.3
MasterChef-v1.0.3-visual-assets.zip (+ .sha256) TextureMods.hvt, ShaderMods.hvs, CEnshineSources.zip. Pinned by mods/visual-assets.json (963,216,022 bytes). Downloaded and verified by setup. Release v1.0.3
MasterChef-v1.0.3-Complete.zip (+ .sha256) The source tree; a fresh generic unsigned Release/HaloVision.app; the static game content needed by the runtime (41 files per FEATURES.md: 32 map/shared-data files, the executable, strings, two shader binaries, configuration and four movies); the exact Build91 visual packs; Release/Notices/ with the retail EULA and readme; RELEASE_MANIFEST.json. Excludes registry values, saves, profiles, tracking/pose data and Apple signing. Release v1.0.3

The issue-template config.yml links to releases/latest as "App, game content, visual packs, source, and checksums". FEATURES.md notes that main also carries later documentation and standalone shader-adapter tooling that "do not change the packaged runtime".

Release procedure

flowchart TD
    A["Changes on the curated public tree"] --> B["run_source_checks.py on Apple Silicon (+ --sanitize where relevant)"]
    B --> C["Verify build route with locally owned game files (outputs stay local)"]
    C --> D["Bump VERSION, app marketing/build versions, CHANGELOG, VALIDATION"]
    D --> E["Export source only (no Git history)"]
    E --> F["Compare ZIP entries + digests to SOURCE_MANIFEST.json; reject extras and symlinks"]
    F --> G["check_repository_hygiene.py --strict --root EXPORT_DIR"]
    G --> H["Secret scan of export, archive and outgoing Git history (Gitleaks)"]
    H --> I{"Complete release authorised?"}
    I -->|no| K["Verify remote, push, tag"]
    I -->|yes| J["Fresh generic unsigned app from public source; select static assets; packs + notices; RELEASE_MANIFEST.json; privacy scan of binary, nested archives, game assets"]
    J --> K
    K --> L["Anonymously download release ZIPs; compare checksums and per-file manifests"]
Loading

RELEASING.md in detail:

  1. Licenses. Preserve the MIT license for original project code and every third-party notice.
  2. Checks. Run python3 tools/run_source_checks.py on an Apple Silicon Mac and the relevant sanitizer runs. "The CI subset runs on macOS because some host fixtures require Mach APIs and Apple's linker. Report hosted CI separately." See Testing and Source Checks.
  3. Build route. Verify with locally owned game files; keep generated sources, reports, signing inputs and packages local.
  4. Versions. Update VERSION, app marketing/build versions, CHANGELOG.md and VALIDATION.md. "The source release's app build number and the owner's private development build number are separate series. Identify both when comparing results."
  5. Export. Export source only. Compare the ZIP entry list and each file digest against SOURCE_MANIFEST.json; reject unexpected entries and symbolic links. Audit the clean export with python3 tools/check_repository_hygiene.py --strict --root <export>, and scan the export/archive and outgoing Git history for secrets.
  6. Header art. Permitted only at its reviewed path and SHA-256 in the hygiene checker; updating the artwork means updating that digest after review. "never add a general binary or image exception."
  7. Complete release (1.0.3+), only when explicitly authorised. Keep large files out of Git. Select static game assets explicitly; exclude registry values, profiles, saves, logs, machine paths, device identifiers, provisioning and signing keys. Build a fresh generic unsigned app from public source; "never distribute the owner's signed bundle." Include exact packs, provenance/notices and shader source/license; record resource hashes and runtime defaults. Verify direct-build and Xcode resource inclusion; test checksum rejection, safe extraction, existing-file preservation and offline bundle setup. RELEASE_MANIFEST.json must describe every Complete archive entry except itself, including the source manifest. Scan the binary, nested source archives and selected game assets for private values without printing them. Recheck the public download against the local ZIP and per-file manifest after uploading.
  8. After publishing. Verify the remote commit/tag, anonymously download the release ZIP and compare its checksum. "Keep signed device installs, launch, startup telemetry, gameplay acceptance and source publication as distinct validation steps."

AGENTS.md adds that agents must verify the remote is https://github.com/mitchaiet/master-chef before any explicitly authorised publication, and that Complete release assets "require explicit authorization, an exact file manifest and privacy review; never upload a raw installation directory or the owner's signed app."

Version bump checklist

File Field
VERSION 1.0.3
native/EngineVision/project.yml MARKETING_VERSION, CURRENT_PROJECT_VERSION (1.0.3, 103)
tools/build_engine_vision.py CFBundleShortVersionString, CFBundleVersion in the direct-build Info.plist
mods/visual-assets.json version, and archive.url/bytes/sha256 when the packs or tag change
mods/runtime-settings.json version
SOURCE_MANIFEST.json version, fileCount, totalBytes, files[] (regenerate after all other edits)
CHANGELOG.md, docs/VALIDATION.md new section
docs/COMPLETE_RELEASE.md, docs/FEATURES.md release asset names
.github/ISSUE_TEMPLATE/bug_report.yml placeholder example v1.0.3 / build 103

SOURCE_MANIFEST.json

Top-level structure:

Key Value at this commit
version 1.0.3
formatVersion 1
license "MIT for original project code; third-party and asset notices retained"
scope "Source, documentation, reviewed header and public asset/configuration manifests. Game and runtime packs are separate release assets."
fileCount 377
totalBytes 7804993
files[] {"path", "bytes", "sha256"}, sorted by path

At this commit the manifest matches the Git tree exactly: all 378 tracked files except SOURCE_MANIFEST.json itself are listed, with matching sizes and SHA-256 digests, and totalBytes equals the sum of the listed sizes. The repository does not contain the script that generates the manifest; RELEASING.md describes it as part of the export step, and nothing in run_source_checks.py or CI verifies it. A maintainer can check it with a few lines of Python, for example:

import hashlib, json, subprocess
m = json.load(open('SOURCE_MANIFEST.json'))
tracked = set(subprocess.check_output(['git', 'ls-files'], text=True).split()) - {'SOURCE_MANIFEST.json'}
assert {r['path'] for r in m['files']} == tracked
assert all(hashlib.sha256(open(r['path'], 'rb').read()).hexdigest() == r['sha256'] for r in m['files'])
assert m['fileCount'] == len(m['files']) and m['totalBytes'] == sum(r['bytes'] for r in m['files'])

(git ls-files splitting on whitespace is sufficient here because no tracked path contains spaces.)

RELEASE_MANIFEST.json exists only inside the Complete archive; it lists every Complete entry except itself, including SOURCE_MANIFEST.json. mods/visual-assets.json pins the visual packs and their archive (Visual Mods Pipeline). The .sha256 file beside each ZIP covers the whole archive; users verify with shasum -a 256 -c MasterChef-v1.0.3-Complete.zip.sha256.

Version history

From CHANGELOG.md and VALIDATION.md. Public builds are numbered 100-103; the owner's private series (for example Build91) is separate.

Version (build) Changes Validation recorded
1.0.0 (100) First curated public snapshot under MIT: Metal renderer, panorama scheduler, controller and audio integration, ARM texture CRC path, bounded geometry reuse; source-only C/ObjC/Metal/Swift/Python checks; decoder/lifter moved to third_party/xwa; device and signing inputs parameterised; generic emulated player; build/controls/architecture/limitations docs; historical Git data, prototypes, reports, generated code, game assets, signing data and binaries excluded. Full suite (59 C targets plus others); portable subset with ASan/UBSan; save-preservation; fresh generation of 8,336 functions in 32 units with no unresolved function frontier; unsigned Release compile (59 native units, 24 Swift, SDK 26.5, deployment 26.0); Xcode generation; missing signing inputs rejected; hygiene; Gitleaks 8.30.1 with no unreviewed findings; source ZIP checked against its manifest. Generator records 15 undecodable entries and 47,843 trap annotations. Not signed, installed or played.
1.0.1 (101) setup.sh guided setup (ISO install, existing imports, private registry conversion, dependency setup, generation, Xcode handoff); payload bundled into the Xcode project with automatic signing; readiness reports, disk checks, resumable setup, setup regressions; agent guide; Windows fallback. 24 setup regressions; portable suite; a real owned ISO checked with --stage check --json; XcodeGen with a synthetic payload. Not run: fresh Wine install/key-entry/update session, full ISO-to-headset path, Windows export on Windows.
1.0.2 (102) Independent U/V and mirrored texture addressing; bounded sampler and depth/stencil caches that reuse under pressure; audio activation/queue retry every two seconds respecting backgrounding and interruptions; real-Metal pixel and cache-pressure regressions; audio lifecycle failure tests; generated header and documentation-art exception; CI moved to macOS; probe freshness includes implementation includes. Shared with owner Build91. Full suite (59 C) and portable with sanitizers (32 C); 768 sampler requests and 192 depth/stencil states beyond cache capacity; 450 exact GPU pixel checks for 25 U/V combinations; audio coordinator failure injection; desktop entry probes on a30 and d40 (2,400 frames each, median 29.78 and 29.86 FPS, explicitly not a firefight or headset measurement). Owner Build91 installed and startup-verified on a headset (engine frame 1,226, 2,708 GPU frames, zero GPU failures, audio queue running).
1.0.3 (103) Publishes the full Build91 visual selection (1,068 textures, 13 shaders, CEnshine source/license); fixes both build routes omitting the packs; setup fetches checksum-pinned packs or reuses Complete-bundle copies; preserves original configuration and movie files on import; archive integrity, safe extraction, offline bundle, tamper and preservation regressions; fresh unsigned build 103 and release manifests; corrected header lettering. Runtime gameplay code unchanged from 1.0.2. Fresh generation (8,336 functions, 32 chunks); unsigned Release build (59 native units, 24 Swift, SDK 26.5); pack hashes match Build91; Xcode resources include every pack; 9 visual-asset/content tests, 24 setup regressions, portable suite. Follow-up: import_censhine_pack.py with 4 regressions; source comparison of 271 native files (260 identical, 11 reviewed differences). Build103 is package-verified and unsigned, not a new campaign qualification.

Repository hygiene audit

tools/check_repository_hygiene.py is a "layered guard, not a guarantee". It walks a tree, and reports path:line: kind for every finding without printing the matched text, then PASS|FAIL: N source files checked; M findings. Exit status is 1 when anything was found.

python3 tools/check_repository_hygiene.py                 # working tree, skipping local artefact directories
python3 tools/check_repository_hygiene.py --strict        # include normally ignored directories
python3 tools/check_repository_hygiene.py --strict --root /path/to/export

Traversal

audit() (check_repository_hygiene.py:33-57):

  • .git is always skipped.
  • Without --strict, any path with a component in SKIP = .git, .build, .setup, __pycache__, .venv, game, build, logs, dist, DerivedData is skipped (line 14). With --strict (used by CI and for distribution trees) they are audited, so any local artefact present is a finding.
  • Any symbolic link is a finding (symbolic-link).

Path rules (non-source-artifact)

A file is a non-source-artifact if any of the following hold (lines 20-22, 42-45):

Rule Values
Suffix .exe .dll .map .iso .ipa .p12 .p8 .pfx .pem .key .mobileprovision .provisionprofile .o .a .dylib .so .pyc .zip .tpf .hvt .hvs .bgra .mov .mp4 .jsonl .log .reg
File name .DS_Store, .env, halo-vision-registry.txt
Path component ends with .app, .xcarchive, .dSYM
Path component equals assessment, local-agent-inputs, .context, .claude, .setup

Documentation-art exception

Exactly one binary is allowed: docs/assets/master-chef-header.png with SHA-256 e15bc1102ca36f40e357c39d48149445f94115971a9469406f7e67c9f442a386 (lines 15-19). At that path the file must start with the PNG signature and match the digest, otherwise unreviewed-documentation-art. "Explicitly reviewed generated documentation art, never a general binary allowlist." Any other file that is not valid UTF-8 is a binary-file finding.

Content rules

Every UTF-8 file is scanned line by line (lines 23-31):

Kind What it detects
home-directory /Users/<name> or /home/<name> paths
private-key PEM BEGIN ... PRIVATE KEY headers (RSA, EC, OPENSSH, DSA or generic)
github-token ghp_/gho_/ghu_/ghs_/ghr_ tokens and github_pat_ tokens
cloud-key AKIA/ASIA access key IDs
service-token sk-/sk-proj- style API keys and Slack xox* tokens
private-network 192.168.x.x and 10.x.x.x addresses
apple-device-id the 8 hex - 16 hex device identifier shape

These rules are why documentation in the repository avoids personal paths and device identifiers, and why logs, captures and registry exports are blocked by suffix.

Regressions

tools/test_repository_hygiene.py ("Ensure the documentation artwork exception cannot admit arbitrary binaries"): the exact reviewed art passes in strict mode; appended bytes give unreviewed-documentation-art; the same bytes under another name give binary-file; text written under the art's name gives unreviewed-documentation-art.

Gitleaks

.gitleaks.toml extends the default ruleset (useDefault = true) with a single allowlist: rule generic-api-key, condition AND, matching on the line, restricted to the path native/EngineHost/third_party/xxhash/xxhash.h and to the exact expressions __m512i const data_key_(lo|hi) = _mm512_srli_epi64 (data_key, 32);. The comment explains these are "Two unmodified xxHash vector shifts [that] look like key assignments to the generic detector. Match the exact expressions and file, not the whole vendor tree." VALIDATION.md records Gitleaks 8.30.1 with decoding and no unreviewed findings for 1.0.0. Gitleaks is not run by CI or run_source_checks.py; it is part of the manual release scan.

.gitignore

.gitignore groups:

Group Entries
Owned data and setup state /.setup/, /game/, /Release/, *.reg, halo-vision-registry.txt, .context/
Environment .env, .env.* (except .env.example), .venv/, __pycache__/, *.pyc
Generated code and builds /build/, /dist/, /native/build/, /native/logs/, /native/EngineHost/halo-host, /native/EngineVision/.build/, /native/EngineVision/*.xcodeproj/, /native/EngineVision/build-receipt.json, *.xcuserstate, xcuserdata/, *.o, *.a, *.dylib, *.so
App packages *.app/, *.xcarchive/, *.dSYM/, *.ipa
Game files *.exe, *.dll, *.map, *.iso
Signing *.p12, *.p8, *.pfx, *.pem, *.key, *.mobileprovision, *.provisionprofile
Visual packs *.hvt, *.hvs, *.tpf
macOS .DS_Store

Privacy rules

Collected from AGENTS.md, AGENT_SETUP.md, SETUP.md, BUILDING.md, CONTRIBUTING.md and the issue template:

  • Never publish game/, .setup/, .venv/, registry exports or halo-vision-registry.txt, private setup logs, generated engine source, signed apps, provisioning profiles, signing identities, device identifiers, saves/profiles, raw diagnostic captures, or an installation directory.
  • Product keys are entered only in the original installer window, never in chat, command-line flags or files. Agents must never ask for a key, print or attach raw product values, or invent PID/DigitalProductID values. Setup tooling never echoes registry values in errors (see Setup Wizard).
  • Signing inputs are always supplied explicitly by the user; the tools contain no personal defaults (Device Preparation and Signing).
  • Logs and reports can contain local paths and device information; review them and share short redacted excerpts only.
  • Before an authorised publication, inspect git diff --cached and run the hygiene scanner against a clean source export, not a private game installation.
  • Build products use -ffile-prefix-map=<repo>=. on the direct route so the checkout path is not embedded in object files (Build System).
  • The Complete bundle never includes anyone's registration or signing; "Do not fabricate registration values to make a public package launch without them."

Issue intake

The bug report form (title prefix [Bug]: ) warns: "Never attach product keys, registry exports, saves, signing files, device identifiers, or unreviewed diagnostic archives." It asks for an area (installation/build, graphics or panorama seams, performance, audio, controller/haptics, crash/level loading, other), the release tag and app build number rather than a device identifier, the environment without serial numbers or personal paths, reproduction steps including mission/checkpoint and whether the issue occurs when still, turning with the controller, or moving the head, and a required checkbox confirming the reporter reviewed attachments for private information. Blank issues are enabled; contact links point to SETUP.md, AGENT_SETUP.md and the latest release.

Asset notices and header art

  • ASSET_NOTICES.md: the project is unofficial and unaffiliated with Microsoft, Bungie or Gearbox. MIT covers original project code only. Original game content keeps its rights and requires a valid license; the HD texture inputs are credited to Delta117; the 13 adapted shaders come from CEnshine 1.0.0 by Sledmine and contributors under GPL-3.0 (upstream commit ce22b5456ed29ae0c53cf19711085b4b9ee93d6a), shipped with source in CEnshineSources.zip. Build91 and this release use identical pack bytes.
  • docs/assets/README.md: master-chef-header.png (2172 x 724) is generated documentation art, not extracted from the game; the original and correction prompts are recorded; the original version remains in the v1.0.2 tag.
  • Third-party code notices are retained (THIRD_PARTY.md, native/EngineVision/Resources/ThirdPartyNotices.txt, bundled into the app).

Related pages

Clone this wiki locally