# Environment / credentials
.env
.env.*
**/*.pem
**/*.key
scripts/gmail_credentials.json
scripts/gmail_token.pickle
tmp/*storage-state*.json
tmp/*playwright-auth*.json
tmp/*synorb-v2-auth*.json

# Python caches
__pycache__/
*.py[cod]
*.pyo
*.egg-info/
dist/
build/
.eggs/
# Re-include the marketing site's Build pages (NOT Python build output)
!site/build/
!site/build/**

# IDE / editors
.vscode/
.idea/
*.swp
*.swo
*~

# OS files
.DS_Store
Thumbs.db

# Temp scripts and output files
tmp_*.sh
*.txt
!scripts/*.txt
!hangingcontext/robots.txt
!hangingcontext/llms.txt
# Section-level agent indexes are public site artifacts, not local scratch files.
!site/docs/llms.txt
!site/agents/llms.txt
!site/agents/personal-agent-onboarding.txt
# IndexNow site key (public by protocol — must be fetchable at the site root)
!hangingcontext/369e4a53892d228bd962847a2de22d5a.txt
/artifacts/
# Frontier Eval Harness 2.0 scorecards (run outputs from scripts/mcp/frontier_eval_2.py)
/eval-artifacts/
# Twen realtime-voice eval scorecards (timestamped run outputs from eval-harnesses/twen-voice/run_voice_eval.py)
/work-product/twen-voice-eval/

# Source configs (now tracked — rebuilt with crawler knowledge notes 2026-03-03)
# ingest/sources/

# Archives
*.tar.gz

# Logs
logs/

# Diagnostic scripts (one-off, not production — root only)
# NOTE: these patterns are ANCHORED to the repo root with a leading `/`
# so they only match top-level files like ./check_foo.py, NOT genuine
# production scripts under scripts/. The old unanchored pattern forced a
# `!scripts/...` whitelist every time someone added a check_*.py helper
# under scripts/ — most of which were then added with `git add -f`, and
# the whitelist fell out of sync with reality. Anchoring fixes the bug
# at the source.
/diag*.py
/fix_*.py
/provision_*.py
/verify_*.py
/rename_*.py
/cleanup_*.py
/run_migration_*.py
/check_*.py

# Misc
new_configs/
dashboard_index_updated.html

# Server-generated deploy/runtime artifacts
/.deploy_sha
/backups/

# Per-source runtime config-hash markers (change-detection cache, written by
# ingest/source_history.py:save_config_hash, read by get_last_known_config_hash).
# Box-local runtime state read only from the filesystem, never from git. Tracking
# them made the box mutate them at runtime, flooding the server-drift deploy PRs
# with _config_hash churn. Untracked + ignored so those PRs carry only the real
# Healer *_fix.md / *_escalation.md training artifacts. (Pattern matches ONLY the
# hash markers — *_fix.md, *_escalation.md, *_human_fix.md stay tracked.)
**/_config_hash
# /stream/ is fully generated: samples.json + the static-prerendered
# index.html both come from build_hc_samples.py (template lives in
# hangingcontext/_templates/stream-index.template.html, tracked).
hangingcontext/stream/*
hangingcontext/by-agents/*
!hangingcontext/by-agents/index.html
# Aggregator-owned rolling windows. The HCAggregator workflow rebuilds these
# every 6h on the worker box and rsyncs to the API box. Tracking them in git
# created a class of bug where deploy-time `git reset --hard` resurrected a
# stale 24h.json from the merged drift PR while the untracked 7d.json sibling
# was wiped by the surrounding deploy churn — leaving the homepage with a
# half-set of windows and a 404 for /data/windows/7d.json (2026-04-27).
hangingcontext/data/windows/*.json

# SEC company_tickers.json cache — runtime artifact (~1MB) refreshed daily by
# the sec_ticker_cache Hatchet cron (core/sec_ticker_cache.py). Not tracked; the
# build-time securities-enrichment hot path reads it locally. The dir itself is
# created at write time (write_cache mkdir -p).
data/sec/company_tickers.json
data/sec/company_tickers.json.tmp

# HC aggregator rolling outputs (rebuilt every 12h by HCAggregator on the
# worker box, rsynced to the API box). Tracking them in git produced a
# steady stream of auto-drift PRs (~19/week) capturing snapshots that the
# next aggregator run immediately superseded — pure noise. Same fix as
# windows/*.json above.
hangingcontext/data/index.json
hangingcontext/data/months/*.json
hangingcontext/data/manifests/

# HC questions surface (rebuilt twice daily by HCQuestions on the worker box,
# rsynced to the API box). Generated pages + JSON twins; the registry that
# defines them is scripts/hc_questions_registry.py (tracked).
hangingcontext/questions/
hangingcontext/data/questions/
hangingcontext/production/
hangingcontext/data/production.json
hangingcontext/feed.xml

# Temporal context snapshot pages — STATIC-PRERENDERED twice daily by
# scripts/build_hc_snapshot_static.py inside HCPages (AI crawlers run no JS;
# these used to be committed empty shells). Only the 20 live lens pages + the
# hub are generated; the redirect stubs in sibling dirs stay committed.
hangingcontext/context-for-agents/index.html
hangingcontext/context-for-agents/ai-companies/
hangingcontext/context-for-agents/bank-research/
hangingcontext/context-for-agents/business-podcasts/
hangingcontext/context-for-agents/central-banks/
hangingcontext/context-for-agents/compute-infrastructure/
hangingcontext/context-for-agents/engineering-blogs/
hangingcontext/context-for-agents/hedge-funds/
hangingcontext/context-for-agents/judiciary/
hangingcontext/context-for-agents/large-corporates/
hangingcontext/context-for-agents/nba-teams/
hangingcontext/context-for-agents/private-equity/
hangingcontext/context-for-agents/private-companies/
hangingcontext/context-for-agents/research-frontier/
hangingcontext/context-for-agents/semiconductor-industry/
hangingcontext/context-for-agents/state-executive/
hangingcontext/context-for-agents/state-legislatures/
hangingcontext/context-for-agents/think-tanks/
hangingcontext/context-for-agents/us-government/
hangingcontext/context-for-agents/us-legislature-executive/
hangingcontext/context-for-agents/venture-capital/

# Panel snapshot metadata sidecars (<name>.json.gz.meta). A pure derived cache
# written next to each compressed snapshot so the timeline index builds without
# gzip-decompressing every retained snapshot on each rebuild. Regenerated and
# self-healed on demand by scripts/hc_distribution_ops.py, so it must never
# enter git or a drift PR.
hangingcontext/data/panels/snapshots/**/*.json.gz.meta

# Claude Code worktrees. These get created inside the repo by Claude Code
# when isolated agent sessions run, and have been committed many times
# as gitlinks (mode 160000) without a corresponding .gitmodules entry.
# Every `actions/checkout` post-step then ran
# `git submodule foreach --recursive ...` against them and warned:
#   fatal: No url found for submodule path '<path>' in .gitmodules
#   ##[warning]The process '/usr/bin/git' failed with exit code 128
# Job conclusions stayed SUCCESS but the noise piled up across every PR
# rollup. PR #2288 cleaned the three orphans at `.claude/.claude/worktrees/`
# (and gitignored that path); this expanded rule + the bulk removal in the
# same commit cleans the 61 remaining orphans at `.claude/worktrees/agent-*`
# and `.claude/worktrees/<short-name>`. Both rules stay so future Claude
# Code worktrees at either location can't be staged accidentally.
#
# Follow-up (2026-06-02): PR #2288's gitlink cleanup missed 1,820 files that
# had been committed as full file trees (not mode-160000 gitlinks) under
# `.claude/.claude/` — two whole nested-worktree checkouts
# (infallible-goldwasser, practical-darwin) plus stray launch.json /
# settings.local.json. Those were removed from tracking and the rule below
# was broadened from `.claude/.claude/worktrees/` to all of `.claude/.claude/`
# so the bogus nested dir can never be re-staged.
.claude/.claude/
.claude/worktrees/

# Agent-First Briefs golden regression set — per-family <family>.jsonl content
# files written by scripts/build_brief_golden_set.py. They contain customer
# record content + brief bodies and must NEVER enter the repo; only the manifest
# (ids + SHA-256 hashes, no content) at tests/fixtures/brief_golden/manifest.json
# is committed. Gates re-materialize the content from the DB by record_id.
work-product/agent-first-briefs/golden/

# Outbound prospect lists and Mailgun campaign exports (2026-07-29).
#
# These directories hold CSV/JSON exports carrying ~903 unique third-party
# email addresses — real named individuals at real companies (blueflame.ai,
# xapien.com, grata.com, 9fin.com, exabel.com, …) gathered for outbound sales.
# They sat untracked in work-product/ for a month and were nearly swept into
# git during a "commit the orphaned notes so we don't lose them" cleanup.
#
# They must stay out of the repo. Git history is permanent and replicates to
# every clone, so committing personal contact data here is effectively
# irreversible — `git filter-repo` across 19k files and thousands of commits
# is not a realistic remedy. The work-product protocol is about written NOTES
# (markdown); prospect exports are operational data and belong wherever the
# outbound tooling keeps them, not in source control.
#
# Scoped deliberately narrowly: 0 files under these paths are tracked today,
# so these rules contradict nothing. A blanket `work-product/**/*.csv` or
# `*.json` rule was considered and rejected — 152 .json and 32 .csv files
# under work-product/ ARE legitimately tracked, and a rule that disagrees
# with tracked reality just teaches people to pass `-f`.
work-product/outbound-finance-rag-prospects-*/
work-product/mailgun-reports/
sdk-python/dist/

# Data files that must ship with the code they gate. The blanket *.txt
# rule above would drop this one silently: core/bot_signing.py fails OPEN
# on a missing list, so an uncommitted file means every measured-broken
# host gets the honest user-agent and breaks exactly as measured.
!core/bot_signing_excluded_domains.txt
