Shell/Swift tooling for the dev loop, signed + notarized releases, Sparkle publishing, and model downloads. The root Makefile is the entry point for all of it (make dev, make v0, make release, make publish); these scripts are the implementations. Human-facing docs: docs/development.md and docs/releasing.md (both kept accurate to these scripts).
check-i18n.sh— static chrome i18n gate (make check-i18n); seeswift/AfterRayRecall/Sources/L10n/AGENTS.md.dev.sh— watch-mode rebuild loop; change fingerprint viastat+shasum(dev.sh:57).--uiwatches only Swift UI + mock data and runs the Visual Lab instead of the app. An explicitAFTERRAY_DATA_DIRis forwarded through LaunchServices on every relaunch.run-v0.sh— builds shim + Rust workspace (release) and the app (debug — mixed configs are deliberate), assembles and signs.afterray-dev/AfterRay.app. Dev vault data lives in.afterray/, dev bundle/socket in.afterray-dev/(both gitignored);--ephemeraluses a throwaway vault.open-dev.sh/stop-dev.sh— reopen/quit the dev bundle (bundle iddev.afterray.app).
build-release.sh— full pipeline: version checks, assembleAfterRay.appby hand (SwiftPM emits bare binaries), sign, notarize, staple, DMG + zip intodist/. Modes: default /--skip-notarization/--local.publish-release.sh— uploads zip + DMG to R2 bucketafterray-releasesunderartifacts/, then updates thereleases.jsonindex last (publish-release.sh:36-38) so a partial failure leaves installs on the previous release.tag-release.sh— after appcast verification, creates and pushes annotatedv<version>at the exact publishedorigin/maincommit.fetch-sparkle-tools.sh— Sparkle 2.9.5 tools (sign_update,generate_keys) into.afterray-dev/sparkle-tools/, tarball SHA-256 pinned (fetch-sparkle-tools.sh:10-13). Once per machine.
docs-gate/—make docs-sync, run bymake test; coverage and limits: decisions/README.md.- Decision anchors cover Rust, Swift, and site web sources; build output is skipped.
- Node ≥22.6 runs TypeScript directly: no dependencies,
package.json, ornode_modules; never put this runtime on a product path. - A red anchor hash means a decision was not re-read when its code changed. Re-read it, then
node scripts/docs-gate/main.ts --writeand commit the sidecar diff — the diff is the confirmation. Never hand-edit a sidecar.
- Sparkle compares only
CFBundleVersion=git rev-list --count HEAD(build-release.sh:117, overrideAFTERRAY_BUILD_NUMBER); stamped into the assembled bundle only — never hand-edit the source plist. Info.plistCFBundleShortVersionStringmust equal[workspace.package].versioninCargo.toml, and bundle id must bedev.afterray.app— the release dies otherwise (build-release.sh:122-136).- arm64-only (build-release.sh:96); every shipped binary is
lipo-verified. - Sign inside-out, never
--deep. Sign Sparkle'sAutoupdate/Updater.appseparately and prune unused XPCServices/Headers. Every bundle runs a pre-main dyld probe; only local ad-hoc hosts disable library validation. - The Sparkle update zip is built from the stapled bundle — the notarization ticket must be in the archive or offline first-launch fails Gatekeeper.
- A release tag is created only after the public appcast contains the matching version and build; tags never move.
- Dev builds need a stable signing identity or TCC resets. Permission-sensitive DMGs use unnotarized Developer ID signing plus an explicit reference app; never hand off an ad-hoc
-localDMG. - Script style:
set -Eeuo pipefail, exit 64 for usage errors, guard everyrm -rfwith a path-prefix check.
make check-i18n— static i18n gate; also runs frommake checkandmake testmake dev/make dev-ui/make v0/make v0-daemon/make open/make stopmake release-preflight(needs explicitAFTERRAY_CODESIGN_IDENTITY+AFTERRAY_NOTARY_PROFILE; checks remote release-index collisions before a costly build) /make release(runs that preflight) /make release-local(needs neither)make verify-release MANIFEST=dist/AfterRay-<version>-arm64.json/make publish-dry-run MANIFEST=…/make publish MANIFEST=…/make tag-release MANIFEST=…— production steps always use one explicit manifest; never select an artifact bydist/ordering. Tag only after publish and public appcast verification.make models→download-models/download.sh— pure wrapper overafterray download(builds the CLI first if missing); override pack withAFTERRAY_DOWNLOAD_ONLY, dir withAFTERRAY_MODEL_DIR.
download-models/afterray_model_worker.pyanddownload_huggingface_model.pyare legacy and unused — no Python anywhere in model download or inference. Don't resurrect them.bench-*.swift,bench-recall-pipeline.sh,verify-gop-e2e.sh,prove-av1-decode.swift,t2-eval.pyare manual diagnostics, not part ofmake test.make buildbuilds the capture shim first — the daemon needs its binary atapps/AfterRayCaptureShim/.build/release/(orAFTERRAY_CAPTURE_SHIM).