Skip to content

Contributing

Deepratna Awale edited this page Oct 6, 2026 · 5 revisions

Contributing

A summary of CONTRIBUTING.md: where code goes, the rules, tests, and commits. Read Architecture first. Each rule exists because breaking it once hid a real bug.

Building

See Building and running: Xcode 26.3+, scheme OpenWallpaperEngine, Debug and Release sign with Apple Development (don't commit your own team), no tools to install, no WE assets in the repo.

Where code goes

You are adding… Put it in…
A new WE file format or field Scene/Format/: plain Decodable models, no side effects
Anything that reads a value that can be user-, script- or animation-bound Resolve it through Scene/Values; never read the raw JSON
Shader translation, reflection, caching Scene/Shaders/
Metal drawing, render passes, render targets Scene/Rendering/
A SceneScript API member Scene/Scripting/ (JS in a bundled .js resource, not a Swift string)
A settings control or Scene Editor (Live) UI Settings/ or Scene/UI/; the view model next to its view
Anything used by several features (logging, settings, asset paths) Core/

One type per file unless the types are tiny and private. A file over about 600 lines, or a function over about 80, needs a reason; split along a real seam.

The rules

  1. Implement WE's behaviour, not a look-alike. No native approximations of WE effects, invented parameter names or remapped ranges. No special cases keyed on a layer, effect, file or property name ("cloud", "clock", "snow"…). If a wallpaper renders wrong, find the missing general feature. See WE-fidelity principles.
  2. Fail loudly. No try? on file IO, decoding, shader translation or pipeline creation: do/catch and log once, with the wallpaper, layer, effect and reason. try? is fine for genuinely optional lookups, with a comment. Decode collections element by element.
  3. No new global state. No new static let shared, no AppDelegate.shared from engine code, no UserDefaults.standard. Use UserDefaults.app and AppStorageLocation.current. Pass dependencies in; state belongs to a wallpaper instance.
  4. Typed keys. No new "_owe_…" string keys.
  5. Logging through OWELog: .debug per frame, .info lifecycle, .error failures. No print or raw NSLog; nothing every frame at .info or above.
  6. Caches are versioned. Keyed on inputs and a revision constant bumped when the producing code changes: ShaderVariantTranslator.revision (ShaderVariantCacheTests enforces it).
  7. Concurrency. UI types are @MainActor. Shared mutable state has an owner (an actor, or one documented lock). No nonisolated(unsafe) without a comment saying why it's safe.
  8. Keep dead code out. Delete it; don't comment it out or keep an unused alternate path.
  9. UI text goes through Localizable.xcstrings, translated into all 15 languages with the glossary's terms. See UI, localization and settings storage.

Tests

  • Tests go in OpenWallpaperEngineTests; fixtures in Tests/Fixtures/. Every fix or feature comes with a test. Known gaps use strict XCTExpectFailure.
  • Tests never touch the user's state or assets (OWE_ASSETS only).
  • Launch dev copies isolated with OWE_ISOLATED_STATE.
  • Before merging, a PR passes Scripts/ci-local.sh (the local gate), run with OWE_ASSETS and OWE_SLOW_TESTS=1.

Details: Testing.

Commits and PRs

  • Conventional Commits: fix:, feat:, perf:, refactor:, build:, docs:, test: (with a scope, e.g. fix(particles): …).
  • Small, single-purpose commits. File moves and renames go in their own commit with no logic changes and must build, so review and git log --follow stay useful. Asset or vendor drops never share a commit with code.
  • The PR description says what changed, why, and how it was verified.

The project file

  • The project uses folder-synced groups, so putting a new file in the right folder is enough.
  • Never add Wallpaper Engine files to the repository, the app or Tests/Fixtures.

User guide: Legal and credits

Clone this wiki locally