# Dependencies and Package Management
# No trailing slash: a worktree may SYMLINK node_modules to a sibling checkout to share
# deps, and `dir/` matches a directory but not a symlink of that name. Measured 2026-08-27
# by two sessions independently — `git add -A -- server` committed the symlink as mode 120000.
server/node_modules
.npm/
.yarn/
.pnp.*
yarn.lock

# Build Output and TypeScript
# server/dist/ is EXCLUDED - built fresh in CI/CD, distributed via GitHub Releases
server/dist/
build/
out/
*.tsbuildinfo
.tsbuildinfo

# Environment Variables
server/.env*
.env*

# Logs and Debug Files
#server/logs/
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Test Coverage and Reports
coverage/
nyc_output/
.coverage/
junit.xml
test-results/
*.lcov

# Editor and IDE Files
.vscode/
.cursor/
.history/
is/

# Operating System Files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
*:Zone.Identifier
*.Zone.Identifier

# Runtime Files
server/.npm-cache/
.npm-cache/
tmp/
temp/
pids/
*.pid
*.seed
*.pid.lock

# Gemini CLI runtime artifacts (if present in repo root)
.gemini/hook-cache.json
.gemini/hooks/debug.log
.gemini/tool-log.txt
.gemini/memory/session-*.jsonl

# MCP Server Specific
admin-ui/
server/cache/
# Version history sidecar files (now stored in SQLite)
**/.history.json

# Runtime State Files
# server/config/framework-state.json
# .framework-state.json

# Runtime State (generated during server execution)
runtime-state/
server/runtime-state/

# Root-level resources (stale if MCP_WORKSPACE pointed to repo root)
/resources/

# Crash Dumps and Diagnostics
*.dmp
report.*.json
*.diagraw
heapdump-*

# Claude-Code setup
plans/archive/
# Machine-written validation ledger, one line per validation command, appended by
# ~/.claude/hooks/validation/validation-flush.py beside the plan it belongs to.
#
# It lived inside the tracked `*-implementation-notes.md` until 2026-08-14 and had grown
# to 3,610 lines across this repo's plans — 596 in one file, ~40% of one active
# initiative's notes. Every validation command dirtied a tracked file, so the choice was
# commit noise or a permanently dirty tree, and a dirty notes file is exactly what the
# Stop gate asks about: the two fed each other.
#
# Ignored rather than deleted, and a SIDECAR rather than a temp dir, so it still sits
# next to its plan and `ls plans/` finds it. Authored content — deviations, findings,
# rulings — stays in the notes and stays tracked.
*.validation-log.md
CLAUDE.md
# No trailing slash: matches both a stray `.codex` file and a `.codex/` directory.
# A trailing slash matches directories ONLY, which let a zero-byte `.codex` file
# through into `git status` (observed 2026-07-29).
.codex
.clinerules

# Claude Code project config - track rules, ignore personal settings
#
# The blanket `.claude/` below used to sit here alone, which contradicted the line above it:
# project rules are shared context, not personal settings. It only looked correct because
# `.claude/rules/mcp-contracts.md` and `extension-alignment.md` were already tracked when it
# landed, and git does not retroactively ignore tracked files. Every rule written since was
# silently untrackable -- including one CLAUDE.md points at as auto-loaded.
.claude/settings.local.json
.claude/settings.json
server/.claude/
server/.opencode/
.claude/*
!.claude/rules/
.claude/rules/*
!.claude/rules/*.md

.agent/
# Temporary test files
test_*.js
test_*.ts

# Backup files
*.backup
*.bak

# Temporary directories
opencodetmp/

# Python cache
__pycache__/
*.pyc
*.pyo
.cache/
.pytest_cache/
.ruff_cache/

# Future planning
plans/future/

# Test prompts
server/prompts/general/test_*.md
node_modules
*.tgz
.osgrep

# Local backups (not committed)
plans/_backup-commands/

# Local dev scripts
scripts/dev-link.sh

# IDE workspace files
plans/claude-prompts.code-workspace

# Act event payloads (local CD testing)
.github/events/

# Claude Desktop Extension artifacts
*.mcpb
.mcpb-staging/
# Test environments
.test-gemini-home/
.history/

# Large assets (moodboards, design files)
assets/moodboard.png

# Mascot design studies. Working scratch for logo/mascot iteration: SVG explorations,
# raster comparison frames, and third-party artist reference images gathered for study.
# Deliberately not published — this is a public repository, so tracking them would put
# other artists' work in every clone, and the raster frames alone are ~1.5 MB of history
# that no consumer of an MCP server needs. Published artwork lives in assets/brand/;
# logo.png and icon-512.png remain compatibility aliases. Only iteration scratch is ignored.
assets/studies/

# CLI config files (user-specific)
opencode.json
state.db

# User-local gates and scripts (not bundled with releases)
# path-verification: experimental gate paired with private implementation_plan prompt.
# Pattern preserved for future reference — if a bundled workflow emerges that
# uses this gate, move the files back out of the ignore list.
server/resources/gates/path-verification/
server/scripts/verify-path-claims.mjs
server/tests/integration/gates/path-verification.test.ts

# CLI build output (built by server/esbuild.config.mjs into server/dist, and
# by `npm -w cli run build` into cli/dist for standalone dev)
cli/dist/

# Skills-sync export output — generated, never committed.
#
# `skills/` is the Agent Plugins project-scope output dir (skills-sync service.ts:380); the spec
# fixes it at the plugin root, which is why it lands here and not under a dot-dir. Every OTHER
# client's export dir is already ignored on the same principle — `.claude/skills` and
# `.codex/skills` are 0-tracked — so committing this one was the anomaly, not the rule.
#
# It is produced by `npm run skills:export` from the registrations in server/skills-sync.yaml,
# which is itself untracked (see below). Committing the output would mean a hand edit survives
# silently until someone re-exports, and it would make the repo carry one user's choice of
# exported resources as if it were the project's.
#
# Consequence for the distribution renderer: it GENERATES skills/ rather than drift-checking a
# committed tree. `scripts/render-targets.json` records the same under canonicalTree.
skills/

# Skills-sync registrations — per-installation, never committed.
#
# Which resources you export as native skills is a local choice. The file itself used to be
# tracked, and it carried four registrations while the note above claimed registrations "ship
# EMPTY by default" — so the documented default and the shipped one disagreed, and every
# developer's local edit showed up as a repo change they had to remember not to commit.
#
# `server/skills-sync.yaml` also states the principle for its own agent-plugins block: "Which
# resources the native package ships is a per-installation choice, not a project default. An
# entry here exports on every `skills:export`, so shipping one would make this repo's guess the
# default for everyone who installs it." That applies to every client, not just that one.
#
# `server/skills-sync.example.yaml` is the committed artifact. Both readers already handle the
# file being absent: `loadSkillsSyncExports` returns an empty set, and the export command prints
# `No skills-sync.yaml found. Copy the example to get started` (service.ts:549).
server/skills-sync.yaml

# t3.codes script-runner config. Local tooling choice, not a project default: it
# registers whichever preview/viewer commands a given developer happens to use,
# so committing one machine's set makes it everyone's. Same reasoning as
# `server/skills-sync.yaml` above.
t3.json
