# Build outputs
*.exe
*.build/
*.dist/
*.onefile-build/
nuitka_cache/
__pycache__/
*.pyc
*.pyo

# Auto-installed Arena SDK tarballs / installers (downloaded during build)
vendor/
arena_runtime/

# Temporary files
*.tmp
*.temp
debug.txt
processing_debug.log

# Build scripts (keep source, ignore outputs)
enhanced_nuitka_command.txt
nuitka-crash-report.xml
onefile_*/

# Generated processing output
output/

# Rust/Tauri build artifacts
src-tauri/target/
# NOTE: src-tauri/Cargo.lock is deliberately NOT ignored. It sat here
# under 'build artifacts', which is the usual misconception -- for a
# BINARY crate (src-tauri has no [workspace] and builds an exe) the
# lockfile is a reproducibility record, and Rust's own guidance is to
# commit it. Without it every CI run and every fresh AWS build
# re-resolved 539 dependencies, so a semver-compatible upstream
# release could change what got built between two runs of the SAME
# commit -- and `cargo test --locked` could not be used at all.
#
# NOTE: src-tauri/gen/schemas/ is deliberately NOT ignored either, and the
# rule that used to sit here was dead anyway -- those four files have been
# TRACKED since before it was written, and .gitignore does not apply to a
# tracked file. Its only effect was to advertise that nobody needed to
# commit them, which is how they went stale while every worktree showed
# them permanently modified. They are the app's ACL: acl-manifests.json is
# what decides whether the webview may invoke `plugin:process|exit`, so a
# dependency bump that widens a permission SET has to show up in a diff
# (round-4 review R4-1).
#
# The reason given here previously -- that backend.rs's permission-resolver
# guard include_str!s the manifest and "must not depend on build.rs having
# run first on a clean checkout" -- was wrong: cargo runs build.rs before
# compiling the crate, so the macro always reads a freshly generated file.
# The diff-visibility argument above is the real one and stands on its own.
#
# Regenerate with any `cargo build`, and COMMIT the result in the same
# change. Leaving them uncommitted is what made every worktree show three
# permanently-modified files (round-5 review R5-15): the output is
# deterministic for a given Cargo.lock, so a stale commit means every
# build dirties the tree until someone commits the regenerated files.

# Node modules and build artifacts
node_modules/
node-compile-cache/
dist/
# build/ contains electron-builder resources, but also setuptools temporary files
# We ignore the directory but specifically allow the installer script
build/
!build/installer.nsh
.cache/
chloros-electron-app/dist2/
electron-packager/
temp-*/
*.spec

# TypeScript build artifacts
*.js.map
*.d.ts.map
*.d.ts

# Compiled UI build artifacts (generated from ui/ts/ by `npm run build-ts` +
# `npm run build-webpack`). The per-component ui/js/*.js, the webpack
# components-bundle.js, and its LICENSE sidecar are all build output — they
# only ever showed up in git as bundle drift. Source of truth is ui/ts/.
# Hand-authored JS that also lives in ui/js/ (the i18n catalogs, the Tauri
# adapter, the SSE client, the test script) stays tracked via the negations.
ui/js/*.js
ui/js/components-bundle.js.LICENSE.txt
!ui/js/i18n.js
!ui/js/i18n-extended.js
!ui/js/i18n-asian.js
!ui/js/i18n-additional.js
!ui/js/tauri-adapter.js
!ui/js/sse-client.js
!ui/js/test-script.js

# IDE and editor files
.vscode/
.idea/
*.swp
*.swo
*~

# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Python virtual environments
venv/
.venv/
env/
.env

# Logs
*.log
chloros-backend-cloud.zip

# Python package build artifacts
*.egg-info/
dist/
build/*
!build/installer.nsh
.eggs/
*.egg
wheels/
*.whl

# ML model weights (large files - both plain and encrypted)
models/*.pth
models/*.pth.enc
models/*.onnx
models/*.trt
NAFNet-SIDD-width32.pth

# Claude Code: ignore local/private state, but SHARE skills, hooks, and project settings
.claude/*
!.claude/skills/
!.claude/hooks/
!.claude/settings.json
nul

# Compiled backend artifacts (Nuitka build output - large binaries).
# resources/backend/ is a build-time deployment tree; nothing here is tracked.
# The desktop UI ships via Tauri frontendDist=../ui; the Nuitka backend build
# does not bundle resources/backend/ui (browser mode, which served UI from there,
# is removed), so nothing under resources/backend/ belongs in git.
resources/backend/*/
resources/backend/*.py
resources/backend/*.pyd
resources/backend/*.dll
resources/backend/*.config

# MAPIR calibration master secret — never committed to source
.mapir_cal_secret
lattice_sdk/_built_in_secret.py
# DAQ fleet secret — derives every DAQ-E's control token and OTA password
# (daq/device_credentials.py). Committing it would put the whole fleet's
# credentials in git history. keys/ otherwise holds only PUBLIC keys, so this
# one file is the exception.
#
# Globbed, not an exact path: rotation leaves suffixed copies behind
# (daq_fleet_secret.replaced is what the last rotation displaced), and those
# are the SAME live credential material -- a superseded fleet secret still
# derives every token minted under it. An exact-path rule ignored the one
# canonical name and left every copy of it stageable by `git add -A`.
keys/daq_fleet_secret*
# ...and the copy scripts/embed_daq_fleet_secret.py bakes into a production
# build so a provisioned unit stays updatable in the field. Generated before
# Nuitka, scrubbed after, never committed.
daq/_fleet_secret_builtin.py

# Production build marker — written by build scripts before Nuitka, scrubbed
# after. Source tree always treats absence-of-file as dev mode so
# `npm run tauri:dev` keeps the env-var bypasses available.
_chloros_build_marker.py

# AWS build pipeline -- downloaded artifacts only.
# config.json IS tracked: AMI/subnet/SG IDs aren't credentials, every
# worktree should get it automatically.
dist-aws/

# M3M product-page HTML -- generated per-filter Shopify pages (copy-paste output).
# The templates at repo root ARE tracked; the generated L87/L41 folders are not.
/M3M Product Page HTML/

# Unadopted vendor firmware images must NOT sit in firmware/<prefix>/.
# find_firmware_file() flashes the HIGHEST version present in that dir,
# so an unvalidated .fwa dropped there auto-flashes every camera that
# arrives below MIN_FIRMWARE_VERSION. TRI032S 1.172 was declined
# 2026-08-04 (its only fix is TRI050S-specific). Archived out of tree.
firmware/TRI032S/TRI032S_1.172.0.0.fwa
firmware/TRI032S/TRI032S_1.172.0.0.fwa.sig
firmware/**/_staging_*/

# Generated experiment output (synthetic_unmix_groundtruth.py) - hundreds of MB of CSV
scripts/out/

# Shadowband Langley analysis output -- scripts/shadowband_langley.py writes
# this to CWD on every run, including failed ones (results: {}).
shadowband_langley.json

# Arena SDK per-camera state (StreamSelector etc). Rewritten by the SDK
# on every run that touches cameras, so tracking it just churns the diff.
persist.json
