# CLAUDE.md Instructions for Claude Code agents in this repo. History and rationale for these rules live in `docs/internal/architecture/decisions/claude-md-history.log`; this file holds only the rules. ## Role and session log If PM assigns a role, read its briefing in `docs/briefing/` and use its log slug. If no role is assigned, you are a general agent (slug `code`); ask PM if the task needs a role. | Role | Briefing | Slug | |---|---|---| | Lead Developer | BRIEFING-ESSENTIAL-LEAD-DEV.md | lead-code | | Piper Alpha | BRIEFING-piper-alpha.md | pa-code | | Chief Architect | BRIEFING-ESSENTIAL-ARCHITECT.md | arch-code | | Chief of Staff | BRIEFING-ESSENTIAL-CHIEF-STAFF.md | exec-code | | CXO | BRIEFING-ESSENTIAL-CXO.md | cxo-code | | CIO | BRIEFING-ESSENTIAL-CIO.md | cio-code | | PPM | BRIEFING-ESSENTIAL-PPM.md | ppm-code | | HOST | BRIEFING-ESSENTIAL-HOST.md | host-code | | Comms | BRIEFING-ESSENTIAL-COMMS.md | comms-code | | Docs | BRIEFING-ESSENTIAL-DOCS.md | docs-code | | Coding Agent | BRIEFING-ESSENTIAL-AGENT.md | prog-code | | Web | BRIEFING-ESSENTIAL-WEB.md | web-code | | ETA (dormant) | BRIEFING-ESSENTIAL-ETA.md | test-code | Tiers and lanes: `docs/briefing/ROSTER.md`. Session log: `dev/YYYY/MM/DD/YYYY-MM-DD-HHMM-{slug}-log.md`. All dates, times and filenames are Pacific time: run `TZ=America/Los_Angeles date` and never guess a timestamp. It is the only durable log (a cycle log in `dev/active/` is optional scratch). One log per role per day; record the model in its header. Create it (skill `create-session-log`) before any other work, even for a greeting. After compaction, resume that log; it is how you recover your role. If you can't find it, stop and ask PM. State you don't remember creating (commits, a changed cron, file edits) is most likely your own work from before a context gap. Check your session log first; use `list_sessions` only if doubt remains. Near compaction, keep your rigor; the session log, mail and skills carry you across. ## Session start 1. Create or resume the session log. 2. Read `mailboxes/{role}/inbox/` (skill `check-mailbox`). 3. Read the "Now" section of `docs/briefing/BRIEFING-CURRENT-STATE.md` (not the history below it). 4. Read `docs/briefs/cross-pollination/current.md`. 5. Confirm you're in your worktree and on your branch, not `main` in the shared checkout. The SessionStart hook prints a short status (log, mail, briefing freshness, role). If it says `BRIEFING: STALE`, or the briefing is visibly behind recent logs and commits, refresh what you can attest with skill `update-current-state` before other work. A partial refresh is better than none. Before reading git or file state to answer a question or start work, `git fetch` and fast-forward if more than a few minutes have passed. A sync from earlier in the session is stale. ## Worktrees - Amber (cohort host): your stable worktree `~/Development/piper-morgan-worktrees/{role}` on `claude/{role}-cycle`, reused every session (Claude Code keys state to the path). Check `git rev-list --count HEAD..origin/main` is 0 before working. - Claude Desktop: the ephemeral worktree Desktop creates. - Never work in the shared checkout `~/Development/piper-morgan-product`. Lifecycle: `docs/internal/operations/amber-worktree-lifecycle.md`. ## Hard rules (data loss, exposure, irreversible changes) 1. The shared checkout `~/Development/piper-morgan-product` (on Amber and PM's Mac: `/Users/xian/Development/piper-morgan-product`) is PM's live workspace with uncommitted edits. Never run there: `git checkout -- ` or `.`, `git reset --hard`, `git stash`, `git clean`, or anything else that discards working-tree changes. If a merge or rebase there is blocked by unstaged changes, stop and push from your own worktree instead. 2. Before any `git checkout -- ` anywhere, run `git diff HEAD -- `. If it is non-empty you are about to discard uncommitted work; read it and decide which side is stale. Clear MANIFEST noise only by your own role's explicit path. 3. Never write a bearer credential (invite code, API key, token) in full in any committed file. This repo is public. Use the masked form `ABCD…WXYZ`. A credential that reached git history must be rotated. 4. Projects v2: never send `updateProjectV2Field` with a partial `singleSelectOptions` list; it replaces the whole list and wipes assignments. Use skill `assign-sprint-safely`. 5. A commit message that pairs close/fix/resolve with `#N` closes issue N, whatever the surrounding words. Write the number without `#`, or add the trailer `Auto-Close: intentional` when closing is intended. 6. Memory in `~/.claude-pm/` is shared and has no git history. Export it to a tracked file before any prune or delete. 7. For any action with no undo (volume delete, `rm -rf`, force-push, bulk update), first check whether the narrow reversible step still works, and whether an API call is additive or full-replace. 8. Never write an outside person's name, address, employer or words into this public repo: files, filenames, commits, mail, logs, rollups. Use a role label ("an alpha tester"). When the detail matters, write it in a private repo (designinproduct `docs/mail/`, `-private-` in the filename) and leave a name-free pointer here. Outside means anyone but xian and his agents; the one exception is xian's Piper Morgan advisor. Report old mentions to Exec; don't remove them (a history rewrite is xian's call). Rule page: designinproduct `docs/conventions/people-details-stay-private.md`. These are backed by guards where noted in `docs/internal/operations/github-and-tooling-gotchas.md`; guards are advisory and bypassable, so the rule still applies. Scope is not direction: a narrow path list does not make an overwrite safe. ## Git, push, sign-off - Commit from your worktree and push finished units to main as you go: `git push origin HEAD:main`. Work not on `origin/main` is invisible to other agents. - Commit the session-log entry for a unit with that unit. - At idle points, run `scripts/sync-pm-local.sh` to fast-forward PM's checkout (it never touches PM's prose edits). - After subagent work, run `git status` and stage or explain any modified files left in `services/`, `tests/`, `web/`. - Stage in one call, commit in the next: the mailbox hook reads the index before a compound `git add && git commit` runs. Sign-off (paste the output in your log): ```bash git status git fetch origin main git rev-parse --verify -q origin/main >/dev/null || echo "STOP: origin/main did not resolve; the check below did not run" git log --oneline origin/main..HEAD # must be empty ``` If it is not empty: `git fetch origin main && git merge origin/main && git push origin HEAD:main`, or leave a NOTICE memo saying why the work is held, or ask PM. Before going dark on purpose (migration, stand-down), park your row in `dev/active/duty-cycle-registry.tsv` with a checkable clearing condition. ## Mail - Write memo, cc copies and sent mirror under `mailboxes/`, then send with `scripts/mail-send.sh "mail({role}): {subject}" `. Don't `git add` or commit mailbox files yourself. Details: `docs/internal/operations/branch-worktree-mailbox-discipline.md`. - Routing: `mailboxes/DIRECTORY.md`. Every memo's frontmatter carries `reply-to: piper-morgan-product:mailboxes/{your-slug}/inbox/`; reply to the memo's `reply-to`. - Never cc PM and never address mail to PM (the `mailboxes/xian (ceo)/` box is retired). Anything that needs PM (a decision only PM can make, a relayed PM ruling, something PM would contradict) goes **to `exec`**, with which of the three in the subject. - Mail to an agent outside this repo (Janus, Pard, Dispatch, …) goes to that agent's home repo: look it up in `~/Development/dispatch/CLAUDE.md` §"Mail routing" and send it with `scripts/mail-send-external.sh`, never a hand commit. Steps: `mailboxes/DIRECTORY.md`. - Write `date: now` in a memo's front matter: `mail-send.sh` and `mail-send-external.sh` stamp the clock, refuse a stamp ahead of it, and add the session's attribution trailers. - Mail asks another agent to act; a GitHub comment records something about the work. ## Working rules - **STOP and ask PM** when: infrastructure doesn't match the plan; tests fail; the thing you're building already exists (complete it); you can't produce evidence; the issue is missing; an ADR conflicts; user data is at risk; you want to defer work; you catch yourself claiming done without proof; you find work about 75% complete (report it). PM decides what is critical. - **Done** means a user can use it, tests exist and pass, evidence is on the issue, and your log is updated. Passing tests alone is not done. - **Evidence.** Every completion claim (memo, issue closure, report) carries `Verified how:` with the method you ran this time, the layer it measured (a curl 200 is not a render test), and the denominator (what it covered out of what exists). Close issues with skill `close-issue-properly` (description first, then comment, then close). - **Don't guess facts.** Look up names, credentials, config, counts and history, and quote the output in the same turn; otherwise say "unverified". - **Investigate before extending.** Read the whole issue, memo or module before acting on part of it. GitHub is the source of truth for issue status. - **Discovered work**: file it immediately with `gh issue create`; list filed issues at wrap-up. - **Deferral** needs a named trigger (a fresh session or a compaction, with the reason). Rows in `dev/active/{role}-standing-items.md` carry a `Filed` column or a `**Filed**: YYYY-MM-DD` line so `scripts/aging-standing-items.sh` can read them. - **Duty-cycle fires** wake you to check for work. Drain all unblocked work in priority order; commit at each unit but don't stop there. Procedure: skill `duty-cycle-tick`. - **Honesty.** Give your actual assessment and call out mistakes, including PM's. - **Decisions** other agents will need: an ADR in `docs/internal/architecture/adrs/` or a PDR in `docs/internal/product/pdr/`, or a line in `docs/internal/architecture/decisions/decisions.log`. Session logs are not the cross-session record. ## Subagents - Brief with role, task, issue, acceptance criteria and expected evidence (skill `brief-coding-agent`). - Set the `model` parameter explicitly and record the tier in your log entry: Haiku for fully specified mechanical work, Sonnet for bounded implementation, Opus for hard reasoning inside the unit. - Quick search subagents report back; implementation subagents keep their own session log. ## Code conventions - API routes use `/api/v1/` (exceptions: `docs/internal/architecture/current/web-routes-conventions.md`). - New action handlers register a `WorkflowEntry(..., action_triggered=True)` in `services/intent_service/workflow_entries.py`; never add an `elif intent.action` branch. Lower `MAX_DISPATCH_SITES` when you migrate one. - A new failing phrasing gets a corpus row, not a new extraction regex (`TestExtractionPatternRatchet`). - Read `docs/internal/architecture/current/intent-routing-stack.md` before touching classification, dispatch or chat responses, and update it if your change makes it stale. - Read `knowledge/piper-morgan-glossary-v1.1.md` before writing about Plugin, MCPB, Connector, Extension, Skills, Cowork or Claude Desktop. ## Quick reference ```bash python main.py # server, port 8001 (entry point; not web/app.py) python -m pytest tests/unit/ -v docker compose up -d && alembic upgrade head # Postgres 5433 ./scripts/fix-newlines.sh # before committing ``` Ports: server 8001, Postgres 5433, Redis 6379, ChromaDB 8000. Domain models `services/domain/models.py`; enums `services/shared_types.py`; config `config/PIPER.md` (`config/PIPER.user.md` is an optional, often absent overlay). From a Claude Code shell, start the server with the inherited Anthropic vars stripped, or every LLM call fails: ```bash env -u ANTHROPIC_API_KEY -u ANTHROPIC_BASE_URL -u ANTHROPIC_AUTH_TOKEN -u ANTHROPIC_CUSTOM_HEADERS \ POSTGRES_PORT=5433 nohup venv/bin/python main.py > /tmp/piper-server.log 2>&1 & ``` A local server also needs `JWT_SECRET_KEY` set, or `main.py` refuses to start: `export JWT_SECRET_KEY=$(python -c 'import secrets; print(secrets.token_urlsafe(32))')`. Deploys come from `origin/main` (`origin/production` is stale; don't cite it); for what is live, check the running host's commit. Store app credentials with `KeychainService`, not the `security` CLI. Repository: `https://github.com/mediajunkie/piper-morgan-product`. ## More detail when you need it | Need | Read | |---|---| | Sprint position | `docs/briefing/BRIEFING-CURRENT-STATE.md` ("Now") | | Project overview | `docs/briefing/PROJECT.md` | | Debugging / E2E investigation | `docs/agent-protocols/debugging-protocol.md`, `e2e-investigation-protocol.md` | | Git workflow, completion discipline | `docs/agent-protocols/git-workflow.md`, `completion-discipline.md` | | Ops recipes, tooling gotchas | `docs/internal/operations/canonical-ops-recipes.md`, `github-and-tooling-gotchas.md` | | Hooks on Amber | `docs/internal/operations/amber-hooks-investigation-2026-07.md` | | Patterns, ADRs | `docs/internal/architecture/patterns/`, `adrs/` | | Skills | `.claude/skills/` |