diff --git a/CLAUDE.md b/CLAUDE.md index 8c79025..134ab85 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,22 +1,64 @@ -# CLAUDE.md - Rules for AI agents working on this repo - -## Branch protection -- Never bypass branch protection or force merge failing checks -- Never use --no-verify or skip pre-commit hooks -- All changes to main must pass required status checks (sdk-integration, deploy-staging) -- If a check fails, fix the root cause before merging - -## Deployment -- Staging deploys automatically on push to main -- Argus tests staging before production promotion -- Never deploy directly to production without Argus passing - -## Security -- Never hardcode API keys, secrets, or tokens in source code -- Use environment variables or GitHub secrets for all credentials -- All GitHub Actions must be pinned to commit SHAs, not version tags - -## Code quality -- Run tests locally before pushing: pytest tests/ -v -- Do not use em dashes in any user-facing content -- All support/security emails go to support@vector.build +# Claude Code Rules + +## Who Does What + +**Claude Code** - writes code, opens PRs, merges when CI passes, deploys to staging and frontend sites +**Argus** - tests staging, promotes to production, cuts PyPI release tags, tests docs and blog accuracy + +## PR Process - Non-Negotiable + +Every change must go through a PR. No direct pushes to main under any circumstances. +PRs are the permanent audit trail of every change made to this codebase. +Claude Code opens PRs and merges them once CI passes. No human reviewer required. +CI must pass before merging - no exceptions. +Never bypass branch protection or force merge. +Never merge a failing CI check - fix the root cause first. + +## Complete Pipeline + +### cueapi (hosted API - private repo) +Claude Code: code change -> open PR -> sdk-integration + deploy-staging CI must pass -> merge -> Railway staging deploy +Argus: runs 246 staging tests -> all pass -> promotes to production + +### cueapi-core (open source) +Claude Code: code change -> open PR -> sdk-integration CI must pass -> merge +Argus: runs full pytest suite -> confirms green + +### cueapi-python +Claude Code: code change -> open PR -> sdk-integration CI must pass -> merge +Argus: runs SDK tests -> all pass -> cuts version tag -> PyPI auto-publishes + +### cueapi-cli +Claude Code: code change -> open PR -> test CI must pass -> merge +Argus: runs CLI tests -> all pass -> cuts version tag -> PyPI auto-publishes + +### Marketing site (cueapi.ai) +Claude Code: code change -> open PR -> CI passes -> merge -> Cloudflare Pages auto-deploys to production +Argus: not involved + +### Docs (docs.cueapi.ai) +Claude Code: code change -> open PR -> CI passes -> merge -> Cloudflare Pages auto-deploys +Argus: crawls after deploy -> tests all code examples against real API -> verifies all links -> flags inaccuracies + +### Blog (blog.cueapi.ai) +Claude Code: code change -> open PR -> CI passes -> merge -> Cloudflare Pages auto-deploys +Argus: crawls after deploy -> tests all code snippets -> verifies package versions -> flags inaccuracies + +## Required CI Checks +cueapi-core: sdk-integration, deploy-staging +cueapi-python: sdk-integration +cueapi-cli: test +No PR review required - CI and Argus are the gates + +## Security Rules +1. Never hardcode secrets, API keys, or tokens anywhere +2. Always use environment variables: os.environ.get("SECRET_NAME") +3. Never commit .env files +4. All GitHub Actions must be pinned to commit SHAs not tags +5. If you find a hardcoded secret, remove it and rotate it immediately + +## Style Rules +1. No em dashes anywhere in any content +2. No AI-sounding language or corporate speak +3. Short, direct sentences + diff --git a/app/routers/echo.py b/app/routers/echo.py index d941913..eb64bb7 100644 --- a/app/routers/echo.py +++ b/app/routers/echo.py @@ -46,6 +46,7 @@ async def echo_store(token: str, request: Request): data = json.dumps({ "payload": payload, + "headers": dict(request.headers), "received_at": datetime.now(timezone.utc).isoformat(), }) await redis.set(f"echo:{token}", data, ex=ECHO_TTL_SECONDS) @@ -69,5 +70,6 @@ async def echo_retrieve( return { "status": "delivered", "payload": parsed["payload"], + "headers": parsed.get("headers", {}), "received_at": parsed["received_at"], }