# Python
__pycache__/
*.pyc
*.pyo

# Packaging
*.egg-info/
dist/
build/
*.egg

# OS
.DS_Store

# Secrets
.env
.env.local
*.token

# Claude Code local settings
.claude/settings.local.json
.claude/skills/seven-advisors/

# Superpowers brainstorm sessions (local dev artifacts)
.superpowers/

# Git worktrees (isolated feature workspaces)
.worktrees/

# spec_sync.py run records (spec-delta.txt, name-lock.txt, gate.txt)
.spec-sync/

# Generated HTML visualizations
*pipeline-visual*.html
assessment-report*.html
assessment-report*.pdf

# Dev-only docs (design prompts, plans, parked items, reports, team templates, branch archives)
docs/prompts/
docs/superpowers/
docs/demo/
docs/references/
docs/later/
docs/plans/
docs/reports/
docs/team-prompts/
docs/archive/
docs/arch/
# Historical SDK object-model reference (kept locally, out of git and the shipped bundle)
docs/reference/archive/
docs/webex-api-feedback.html
docs/webex-api-feedback-for-cisco-collab-bu.md
# Internal audit deliverable and working docs (local-only, not part of the shipped playbook)
docs/audit/
docs/ARCHITECTURE_AUDIT.md
notebooklm-sources/
mcp-vs-cli-comparison.md
presentation-transcript-5min.md

# Tests (dev-only, except the actively-maintained migration/org-health suites
# and the artifact guards below)
tests/*
!tests/migration/
!tests/migration/**
!tests/org_health/
!tests/org_health/**
# Artifact guards: these assert on files that ship (settings.bundled.json,
# field_overrides.yaml, README.md, ci.yml). They caught real drift while CI
# could not see them, so they are tracked and run on every PR. They import only
# stdlib/pytest/yaml plus in-repo modules — no network, no live API, and no
# dependency on the untracked tests/conftest.py.
!tests/test_assemble.py
!tests/test_field_overrides.py
!tests/test_readme_distribution.py
!tests/test_release_integrity.py
!tests/test_drift_check_untracked.py
!tests/test_drift_check_columns.py
!tests/test_drift_check_naming.py
!tests/test_drift_check_inert.py
!tests/test_drift_check_paging.py
!tests/test_drift_check_doc_shape.py
!tests/test_drift_check_name_lock.py
!tests/test_spec_sync.py
!tests/test_sync_guard.py
!tests/test_sync_classify.py
!tests/test_sync_version.py
!tests/test_spec_sync_liveness.py
# Checks 19/20. This one also carries the three real 2026-08-03 spec changes
# that reached the CLI while the gate said PASS — inlined from the spec diff,
# not read out of git, so a shallow CI checkout still proves the gate sees them.
!tests/test_drift_check_semantics.py
# Guards the gate's ability to report that it DID NOT RUN. Both halves of that
# (exit 2 in drift_check.py, and CI treating 2 as distinct + asserting the run
# reached the end) regressed silently once already and cost 11 days of a gate
# that verified nothing while looking like an ordinary red build.
!tests/test_drift_check_exit_codes.py
!tests/test_errors_actionability.py
!tests/test_suggest_and_paging.py
!tests/test_pagination_walkers.py
!tests/test_command_naming_residue.py
# Same contract: these assert on behaviour that ships (the --calling-data
# interlock on people.py, and --verify across 328 generated update commands).
# Both guard SCOPING — a check that reaches the wrong commands warns about
# flags they do not have — which only a tree-wide assertion can catch.
!tests/test_field_expansion.py
!tests/test_verify_flag.py
!tests/test_errors_id_kind.py
# Same contract again, and the sharpest case for it: this one guards the
# PreToolUse gate that stops the main session mutating a live org. The gate
# script ships tracked; its shell decision table ships tracked; but the
# tree-wide "no list-*/show-* command writes" invariant lived only here, where
# CI could not see it — and so nobody noticed it had been inspecting 86 of 1961
# commands. Stdlib + pytest only, no conftest, no network: verified green in a
# `git archive HEAD` checkout.
!tests/test_wxcli_gate.py
# The Codex-side counterpart to test_wxcli_gate.py above: unit coverage for
# codex_gate.py (the `wxcli codex-gate` subcommand the Codex PreToolUse hook
# calls). Same contract — an untracked test on a safety gate has no way to
# tell anyone when it goes red. Stdlib + pytest only, no network.
!tests/test_codex_gate.py
# The shared runtime's retry contract — the only executable proof of it. Every
# HTTP call from ~1,887 generated commands goes through `WebexSession._request`,
# and `auth.py`'s policy was deliberately widened on 2026-07-24 (`bcb1330`, no
# test) to add the 500/502/503/504 statuses, the jitter and the `Retry-After`
# guard. This file went red on 2026-07-28 — a lazy-import refactor invalidated
# ten patch targets — and stayed red for eight days, because an untracked test
# has no way to tell anyone. It is repaired, and the two cases that were at zero
# coverage even with every test on this disk (`_request`'s `Retry-After` cap and
# HTTP-date fallback; `follow_pagination`, the `--all` walker behind 173 list
# commands) are now covered. Stdlib + pytest + httpx, no network, no live API,
# no dependency on the untracked tests/conftest.py.
!tests/test_auth.py
# Shared-runtime unit tests. `config.py`, `output.py` and `update_check.py` had
# ZERO tracked importers, which is why the CI statement coverage of
# src/wxcli/*.py is 50% while the same suite on a developer's disk is 79%
# (07-testability.md §3.3). These four files are that 29-point gap. Stdlib +
# pytest only, no CliRunner, no network.
!tests/test_common.py
!tests/test_config.py
!tests/test_config_org.py
!tests/test_output.py
!tests/test_output_errors.py
!tests/test_org_id_injection.py
# CLI-surface tests. These drive real commands through Typer's CliRunner, so
# they need tests/conftest.py below — both for its fixtures and for the
# `WXCLI_NO_UPDATE_CHECK=1` it sets at import time, without which the top-level
# callback fires a PyPI lookup on every single invoke.
# test_cli_smoke.py is the slow one (~46s for 122 tests); it is also the only
# thing that walks the whole command surface, so the minute is the point.
!tests/test_cli_smoke.py
!tests/test_cleanup.py
!tests/test_init_playbook.py
!tests/test_update.py
# The startup update-notify path, plus three assertions on the shipped bundle
# (settings.bundled.json, codex/config.toml, .claude/settings.json) that the
# git-pull updater stays retired. Red at HEAD when Phase A walked it — one
# assertion outlived the Codex hook design `e35d8a1` deliberately retracted,
# and being untracked is why nobody heard about it for the eight days between.
!tests/test_update_check.py
# Packaging + release metadata. Same artifact-guard contract as the block
# above: they assert on files that ship, and read nothing but the repo.
!tests/test_packaging_metadata.py
!tests/test_release_workflow.py
# The OpenAPI parser, whose output every one of the ~1,887 generated commands
# is derived from. Two files, same basename, different packages — which is why
# the two empty __init__.py markers ship with them: without the packages,
# pytest collects two `test_openapi_parser` modules and dies on the basename
# collision instead of running either. tests/tools/ is re-included and then
# re-emptied so only these two files come along, same shape as the
# tests/fixtures/ block below (git cannot re-include a file whose parent
# directory is excluded).
!tests/__init__.py
!tests/test_openapi_parser.py
!tests/tools/
tests/tools/*
!tests/tools/__init__.py
!tests/tools/test_openapi_parser.py
# tools/update-specs.py's exit code. Fetch errors were counted and printed but
# never reached it, so a 6-of-7-failed run read as success and the next step
# regenerated against mixed-vintage specs. Stdlib + pytest only, no network.
!tests/test_update_specs.py
# Shared fixtures for everything above. 23 lines, no network, no live API. It
# is tracked for its import-time side effect as much as its two fixtures: it
# sets WXCLI_NO_UPDATE_CHECK=1 so the suite cannot reach PyPI. Every guard
# tracked before this line was written to work WITHOUT it, so adding it can
# only make CI more hermetic, never less.
!tests/conftest.py
# The generator's own tests. Same contract as every guard above, and the
# sharpest case for it yet: `tools/command_renderer.py` is the file whose
# defects multiply by the whole generated surface, and all four of these ran
# on nobody's PR. Audit Phase 4 proved the cost by mutation — deleting every
# `_render_destructive_gate` call site regenerates cleanly, drops all 24
# confirmation gates, and reports drift-gate PASS with 415/415 tracked tests
# green. Stdlib + pytest only; imports `tools.*` (resolved by pyproject's
# `pythonpath = ["."]`), never `wxcli`; no network, no live API, no dependency
# on the untracked tests/conftest.py.
!tests/test_command_renderer.py
!tests/test_command_renderer_dispatch.py
!tests/test_generate_commands.py
!tests/test_generator_regression.py
# Check 21. Asserts every operation classify_real_semantics flags destructive
# has a typer.confirm in its rendered body — the assertion 02-drift.md F3
# found nothing was making.
!tests/test_drift_check_confirms.py
# The three files above read these two fixtures. A tracked test with an
# untracked fixture is a red CI job on a fresh clone, so they ship together.
# The directory is re-included and then re-excluded so tests/fixtures/
# axl-responses/ (gitignored, referenced by nothing — 06-machinery.md) stays
# out: git cannot re-include a file whose parent directory is excluded.
!tests/fixtures/
tests/fixtures/*
!tests/fixtures/mini-openapi.json
!tests/fixtures/expected_output.py
tests/migration/**/__pycache__/
tests/org_health/**/__pycache__/

# Live CUCM testbed scripts (contain lab host/credentials, never commit)
tests/migration/cucm/build-testbed.md
tests/migration/cucm/provision_testbed.py
tests/migration/cucm/provision_testbed_phase9.py
tests/migration/cucm/provision_testbed_phase10.py
tests/migration/cucm/teardown_testbed.py
tests/migration/cucm/testbed-manifest.json
tests/migration/cucm/validate_live_cucm.py

# CI (no value without tests) — except release.yml, which must be tracked to run
.github/*
!.github/workflows/
.github/workflows/*
!.github/workflows/release.yml
!.github/workflows/ci.yml
!.github/workflows/spec-sync-liveness.yml

# Coverage
.coverage
.lab/
.lab.bak.*/
run.log

# Local folder (not part of repo)
Webex Calling/

# Local one-off tools (not part of the CLI)
tools/build_oncall_deck.py
tools/reassign_dids_to_cc.py

# README backup
README.md.bak
src/wxcli/_version.py

# Org-health scan output (contains live org data — person IDs, numbers, devices)
org-health-output/

# Remotion video production (local build artifact)
remotion-video/

# Flow Store CLI (dev-only, not production)
specs/webex-flow-store.json
src/wxcli/commands/fs_*.py

# General skills (not part of the Webex toolset)
.claude/skills/seven-advisors/
.claude/skills/researcher/

# Prototypes are local-only scratch work — demo shells and SDK spikes, not part
# of the CLI or the shipped playbook. This also covers the node_modules trees the
# untracked prototypes carry — pos-demo alone was 2,330 files one `git add .` from landing.
prototypes/*
