feat: add Claude domain playbooks for agent reference

This commit is contained in:
Backtalk6858
2026-06-27 01:04:06 -05:00
parent c3944641d3
commit cb65e3d7cf
2 changed files with 273 additions and 0 deletions
+150
View File
@@ -0,0 +1,150 @@
---
name: playbook-background-agent-prompts
description: "REQUIRED before writing any background agent prompt: full template, 5 discipline rules, mandatory wrap-up block, and anti-patterns; read this before drafting any agent prompt"
metadata:
node_type: memory
type: project
originSessionId: 075715ba-4454-464c-ba39-dfbcdefc6590
---
## When to use background agents
Use a background agent when:
- The task is bounded (clear start, clear end, defined output)
- It does not require real-time decisions from the user
- It can run in parallel with other work without file/resource conflicts
- It fits within 15 tool calls
Do NOT use a background agent for:
- Open-ended research or design tasks (those belong in main session)
- Tasks that require human decisions mid-way
- Tasks that share files or DB rows with another running agent
---
## The 5 Prompt Discipline Rules
Every background agent prompt must satisfy all 5. A prompt missing any of these will loop, stall, or silently fail.
### Rule 1 — Hard turn limit
Always include `--max-turns 15` in the prompt (or in the claude -p invocation). Without this, a looping agent runs indefinitely and consumes unbounded SDK credits.
### Rule 2 — Loop detection instruction
Include this verbatim:
> "If you issue the same tool call or command twice with identical arguments, STOP immediately and output the mandatory wrap-up with status=partially_succeeded."
### Rule 3 — Credential map inline
Every credential the agent needs must be provided inline in the prompt — exact Vault path and field name. Never send an agent to search for auth at runtime. Use the infrastructure auth map (`secret/data/claude/infrastructure-auth-map` → yaml field) as the source.
Format:
```
## Credentials you will need
- sudo-bridge (primary): Vault path secret/data/sudo-bridge → api_key
- Gitea token: Vault path secret/data/gitea → admin_token
- AppRole bootstrap: role-id at /opt/appdata/docker/docker-compose/vault/approle/role-id
```
Always include the AppRole bootstrap pattern when Vault access is needed:
```bash
VAULT_IP=$(docker inspect vault-iwaulpoi5hwirdlogshmul40 --format '{{json .NetworkSettings.Networks}}' | python3 -c "import sys,json; nets=json.load(sys.stdin); print(list(nets.values())[0]['IPAddress'])")
ROLE_ID=$(cat /opt/appdata/docker/docker-compose/vault/approle/role-id | tr -d '[:space:]')
SECRET_ID=$(cat /opt/appdata/docker/docker-compose/vault/approle/secret-id | tr -d '[:space:]')
VAULT_TOKEN=$(curl -sf -X POST -H "Content-Type: application/json" \
-d "{\"role_id\":\"$ROLE_ID\",\"secret_id\":\"$SECRET_ID\"}" \
http://$VAULT_IP:8200/v1/auth/approle/login | python3 -c "import sys,json; print(json.load(sys.stdin)['auth']['client_token'])")
# Always revoke after use:
curl -sf -X POST -H "X-Vault-Token: $VAULT_TOKEN" http://$VAULT_IP:8200/v1/auth/token/revoke-self
```
### Rule 4 — Defined output format
Specify the exact output the agent must produce. Never say "report what you did" — always define the schema. Use the mandatory wrap-up block (Rule 5 below) as the minimum output requirement. Add task-specific fields as needed.
### Rule 5 — Mandatory wrap-up block (structural, not instructional)
Add this block verbatim to every prompt, immediately before the loop detection instruction. This is structural — the agent cannot satisfy the prompt without emitting it.
```
## MANDATORY WRAP-UP (required regardless of success or failure)
Before stopping for ANY reason — task complete, error, or approaching turn limit — output this JSON as your final message. Do not stop without it.
{
"status": "succeeded|partially_succeeded|failed",
"actions_taken": ["action 1 — outcome", "action 2 — outcome"],
"actions_failed": ["action — reason it failed"],
"notes": "anything relevant for the next session"
}
If you hit --max-turns before finishing, set status="partially_succeeded" and list what remains in actions_failed.
```
---
## Prompt template
```
You are [one sentence role description]. [One sentence scope — what you will and will not touch.]
## Task
[Clear, bounded description of what to accomplish.]
## Context / pre-fetched data
[Include inline any data the agent needs: DB rows, config values, file contents. Do not make the agent fetch things that can be included here.]
## Credentials you will need
[List exact Vault paths and field names for every secret needed. Include AppRole bootstrap if Vault access required.]
## Step-by-step
[Numbered steps if the task has a defined sequence.]
## MANDATORY WRAP-UP (required regardless of success or failure)
Before stopping for ANY reason — task complete, error, or approaching turn limit — output this JSON as your final message. Do not stop without it.
{
"status": "succeeded|partially_succeeded|failed",
"actions_taken": ["action 1 — outcome", "action 2 — outcome"],
"actions_failed": ["action — reason it failed"],
"notes": "anything relevant for the next session"
}
If you hit --max-turns before finishing, set status="partially_succeeded" and list what remains in actions_failed.
--max-turns 15
If you issue the same tool call or command twice with identical arguments, STOP immediately and output the mandatory wrap-up with status=partially_succeeded.
```
---
## Parallel agent rules
- **Max comfortable parallel:** 4-5 agents (primary server has 18GB available RAM, ~300MB per agent)
- **Max safe parallel:** 8 agents
- **Do not parallelize:** Tasks that write to the same file, the same DB row, or the same Gitea repo
- **Do parallelize:** Tasks that touch independent files, services, or repos
- Token cost is the same whether serial or parallel — parallelism saves wall-clock time only
---
## Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| "Report what you did when done" | Instructional — skipped under context pressure | Use mandatory wrap-up JSON block |
| Sending agent to find its own credentials | Agent loops searching for auth | Provide all Vault paths inline |
| Open-ended task ("investigate and fix anything wrong") | No defined completion state | Bound the task: specific file, specific check, specific output |
| No --max-turns | Looping agent runs forever | Always include --max-turns 15 |
| Sharing a file between two parallel agents | Race condition, one overwrites the other | Assign non-overlapping files/resources |
| Making design decisions in the agent | Agent guesses wrong, wasted run | Pre-decide everything in main session, send agent only to execute |
| `curl -sf ... \| python3 -c` for API calls | `-sf` suppresses body on error; inline python escaping breaks | Write a /tmp Python script using urllib instead |
| secrets-proxy /shell with target="server-01" | Only accepts target=sandbox or target=production — 400 error | Server-01 ops go through sudo-bridge-server01 at http://192.168.1.90:8082 directly |
| Pre-fetching everything before writing prompts | Burns context; most things agents can discover in 1 tool call | Pre-fetch only what's blocking — include discovery steps inside the agent prompt instead |
| Writing files on server-01 without allowlist entry | 403 — command not in allowlist | Add pattern to allowlist (tier 1 = auto, tier 2 = NTFY approval) first; use base64 python3 -c for file writes |
| Downgrading tier-2 wildcard to tier-1 to bypass NTFY | First-registered wildcard wins — adding tier-1 `python3 -c *` after a tier-2 `python3 -c *` has no effect | Use `docker exec <container> python3 -c` instead (different prefix, not matched by `python3 -c *`) |
| Pre-hashing keys in PROXY_CALLERS env var | secrets-proxy app.py expects raw keys in PROXY_CALLERS and hashes internally — pre-hashing causes double-hash, all auth returns 403 Invalid API key | Store raw keys: `PROXY_CALLERS=json.dumps(callers)` not `json.dumps({n: sha256(k) for n,k in callers.items()})` |
| Relying on NTFY approvals for unattended agents | NTFY notifications may be missed or time out, stalling the agent indefinitely | Design server-01 file writes to use `docker exec` pattern (tier-1) for unattended runs; reserve tier-2 for explicit interactive sessions |
---
## Evolution
Update when: new anti-patterns discovered; AppRole bootstrap pattern changes; parallel agent limits change based on server hardware; new credential types need standard inline format.
+123
View File
@@ -0,0 +1,123 @@
---
name: Git Commit Criteria (Universal)
description: Universal decision criteria for when Claude commits and pushes autonomously — applies to all repos; all repo-specific git playbooks extend this
metadata:
type: project
last_updated: 2026-06-04
---
# Git Commit Criteria — Universal
**Playbook update rule:** Per-session updates via the end-of-session checklist playbook review step (step 4). Cross-repo patterns get promoted to this playbook during claude-config audit sessions.
---
## The one authorized trigger
Claude commits (and pushes) autonomously **only when the end-of-session checklist is executing**. The checklist is the authorization. Outside of checklist execution, never commit unless the user explicitly asks — no exceptions.
---
## Commit and push are always coupled
When the checklist triggers a commit, push to `origin main` immediately after. Never hold a commit local.
Push rules:
- Fast-forward only — never `--force`
- Always push to `origin main` explicitly, never guess remote/branch
- If push fails (diverged, network error): stop, report to user, do not attempt to fix automatically
---
## Repo opt-out
All repos default into autonomous checklist commits. A repo can opt out by adding `commit: manual-only` to its repo-specific playbook. When set, Claude never commits autonomously in that repo — always asks first, even during checklist execution.
---
## Hard blocks — always apply, checklist does not override them
These conditions always block a file from being staged:
| Block | Condition | Action |
|-------|-----------|--------|
| **Untested containerized script** | `.py` file runs inside a Docker container and has not been verified in a live container | Hold file — do not stage; report to user what is held and why |
| **Credential exposure** | Filename contains `token`, `key`, `secret`, `password`, `pull`, `registry`, `approle`, or `credential` | Hold file — confirm with `head -1 <file> \| cut -c1-10`; add to `.gitignore` if plaintext |
**Claude-authored host scripts are exempt from the untested script block.** Hooks (`.claude/hooks/`), memory files, context files, and anything else Claude authors that runs on the host or in the harness commit freely as part of the checklist — no testing gate applies.
**Partial commit rule:** When a hard block is hit, commit everything that passes checks, skip only the blocked files, report clearly what committed and what was held and why, then continue the checklist. Never hold clean changes hostage to a blocked file.
---
## Pre-stage check registry (universal defaults)
Run before staging any matching file. If a check fails, fix before staging — do not stage a file that fails its pre-stage check.
| File pattern | Check command |
|-------------|---------------|
| `*.py` | `python3 -m py_compile <file> && echo "syntax ok"` |
| `docker-compose.yml` | `docker compose -f <path> config > /dev/null && echo "compose ok"` |
**Repo-specific additions:** Each repo-specific playbook may define additional pre-stage checks (e.g. `npm run lint` for Node projects). These extend the registry — they do not replace it.
---
## Health check before push (universal pattern)
Before pushing, run the repo-appropriate health check if one is defined in the repo-specific playbook. If no health check is defined, skip this step.
If the health check fails: stop, do not push, report to user.
**Future:** When GitLab CI/CD is live, evaluate whether the GitLab pipeline status replaces this manual health check step for CI-managed repos.
---
## Commit splitting (universal rule)
One logical reason to change = one commit. Never bundle unrelated changes into a single commit.
Each repo-specific playbook defines its split taxonomy. When no taxonomy is defined, apply this test: would a future reader need to revert these changes independently? If yes, split.
---
## Commit message format (universal)
Always use the heredoc form to avoid quoting issues:
```bash
git commit -m "$(cat <<'EOF'
scope: short description under 70 chars
- Bullet explaining what changed and why
- Another bullet if needed
Co-Authored-By: Claude <current-model-id> <noreply@anthropic.com>
EOF
)"
```
**Format rules:**
- Subject line: `scope: description` — under 70 characters
- Body: explain *why*, not *what* (the diff shows what)
- Co-author line: always present; model ID must reflect the actual model running this session (dynamic — never hardcode a version)
- Scope keyword taxonomy is repo-specific — defined in each repo's playbook
---
## Training data — log these events
Log commit decisions that required judgment:
- **Hard block hit:** file path, block type (untested containerized script / credential), what was held vs. committed
- **Pre-stage check catch:** check type, file path, what was found
- **Push failure:** error encountered, how resolved or that it was escalated to user
Routine clean commits with no blocks or check failures do not need logging.
---
## Evolution
- **Per-session:** end-of-session checklist step 4 (playbook review) — any new patterns, gotchas, or rules discovered this session get added to the relevant repo-specific playbook or promoted here
- **Cross-repo promotion:** when a pattern appears in two or more repo-specific playbooks, promote it to this universal criteria at the next claude-config audit session