data/
__pycache__/
*.py[cod]
.venv/
venv/
*.db
*.db-wal
*.db-shm
.pytest_cache/
*.egg-info/
build/
dist/

# Host-specific IDE / willow-mcp wiring — materialized by
# `willow-mcp project sync nestor` from the fleet registry, not source.
# Cursor hooks stay local until there is a template worth committing.
.mcp.json
.cursor/
.willow/
.claude/settings.local.json

# build/test artifacts
.pytest_cache/
*.egg-info/
*.egg
build/
dist/

# Agent worktrees are transient scratch, never repo content.
.claude/worktrees/

# Bench runs land here by default; the tracked bench/results/*.json is the
# PUBLISHED record, written only with NESTOR_BENCH_PUBLISH=1. Running a
# bench must not dirty the tree — that blocked the first independent
# reproduction of a result from a clean clone.
bench/results/local/

# Dogfood stores under docs/dogfood/ are the PUBLISHED record of a session's own
# decisions, the same distinction bench/results/ already makes above: a store a
# run happens to write is an artifact, a store committed here is evidence. The
# blanket *.db rule is what these two lines exist to except, deliberately and
# visibly, rather than reaching around it with `git add -f`.
!docs/dogfood/**/*.db
!docs/dogfood/**/ledger.jsonl

# scratch review desk — the path hooks/before_write.py tells you to use
.review/

# Keyrings hold verifier keys — runtime trust material, not source (like *.db
# above). A local seal keyring must never be committed.
keyring.json

# The same rule, stated by shape rather than by filename. A seal key generated
# by hand lands wherever the operator ran the command — usually the repo root —
# and `keyring.json` above only catches the one name we happened to think of.
# Private key material is never source in this repository.
*.pem
*.key

# Session-local seal ledger for the joke store (audit chain, runtime like *.db).
# Targeted so the docs/dogfood/**/ledger.jsonl exception above is untouched.
demo/llm-only-joke/ledger.jsonl

# Coverage data — rewritten by every local test run; a tracked binary here is a
# permanent phantom diff and an unresolvable merge conflict waiting.
.coverage
.coverage.*

# Editor lock files. LibreOffice writes `.~lock.<name>#` beside any file it has
# open, and a `git add -A` while a document is open commits it — which happened:
# `.~lock.IDEAS.md#` rode into #189 and merged. It names a host and a PID, so it
# is meaningless to anyone else and conflicts with itself between machines.
.~lock.*#

# The reviewer's own copy of the dogfood store. Sealing must NOT happen in
# `docs/dogfood/nestor.db` — that file is derived from the decision files and
# `dogfood_store.py --verify` fails on a sealed row in it, however it got there
# (agent-log §6.123). So a human reviewing the queue takes a copy:
#
#     python -c "import sqlite3; sqlite3.connect('docs/dogfood/nestor.db').execute(\"VACUUM INTO 'review.db'\")"
#     nestor --db review.db ui --verifier <you>
#
# `VACUUM INTO` rather than `cp`, because a plain copy of a live WAL store takes
# a stale file. The glob covers the ledger nestor writes alongside it
# (`review.db.ledger.jsonl`) and SQLite's own `-wal` / `-shm` companions.
review.db*
