# Apra Fleet - Claude Code Context

<!-- SYNC-SOURCE-ONLY:START -->
> This file is the source of truth for AGENTS.md and AGY.md, generated by `node scripts/sync-agent-docs.mjs` (each gets its own title plus a small tool-specific appendix from `scripts/agent-doc-partials/`). Edit this file, then rerun the script -- do not hand-edit the shared sections of AGENTS.md/AGY.md directly. Text between SYNC-SOURCE-ONLY markers is stripped from the generated copies.
<!-- SYNC-SOURCE-ONLY:END -->

> Beads: run `bd prime --no-memories` first. DB name (`.beads/metadata.json`) is local/gitignored and can differ per clone -- not a sync requirement. If `bd bootstrap` errors "database exists" on a clean clone, retry with `--database <other-name>`.

Read `README.md` in this repo for the full tool reference, installation, member registration, multi-provider setup, git authentication, PM skill commands, and troubleshooting.

## Dev commands

```bash
npm install && npm run build   # Build from source
npm test                       # Unit tests (vitest + apra-fleet-se), wall-clock bounded
npm run build:binary           # Build single-executable binary
node dist/index.js install     # Dev-mode install
```

Run tests only through `npm test` (`scripts/run-all-tests.mjs`) or the
apra-fleet-se workspace's own `npm test` (`packages/apra-fleet-se/scripts/run-tests.mjs`)
-- both are wall-clock bounded (default 20 minutes per suite, override with
`APRA_TEST_TIMEOUT_MS`) and kill the whole child process tree (not just the
immediate child) on timeout, so a hung suite can never hold a dispatch open
indefinitely. Do not invoke `vitest run` or `node --test` directly for a
tracked task's verification step. `test:slow` in `packages/apra-fleet-se`
is a deliberate exception: it is a manual/regression-playbook lane invoked
directly, not part of the `npm test` chain, so it is intentionally left
unbounded by this rule.

## Conventions

- Branch naming: `feat/<topic>`, `fix/<topic>`, `chore/<topic>`
- Commit style: `<type>(<scope>): <description>` - e.g. `fix(ssh): handle key rotation timeout`
- Never push to `main` directly; open a PR
- See [Architecture](docs/architecture.md) for internal structure
- ASCII only: never write non-ASCII characters to any file. Use `-` for dashes, `->` for arrows, `[OK]` for checkmarks, etc.
- Permission blocks must be surfaced, not routed around: if a tool or git invocation is blocked by the permission layer, stop and report the block to the user/orchestrator. Do not author a wrapper script, alternate binary, or other workaround whose purpose is to bypass the block, even if the underlying operation is judged safe.
- `packages/apra-fleet-client` must always be updated to catch up with any changes to the fleet MCP tools (`src/tools/*` schemas/behavior) in the same change -- it is the thin client wrapper other packages (fleet-sprint, apra-pm, workflows) use to call those tools, and a drifted client silently gives callers a stale or inconsistent view of what the server actually accepts/does. This is not optional cleanup; treat it as part of the tool change itself.
- Any change to the memory subsystem (its tools, schemas, or bindings) must land together with the corresponding `memory-contract/v1` spec, schema, and conformance updates in the same change -- not as a separate follow-up cleanup -- because a drifted contract silently misrepresents what the server actually accepts and does.
- Never rely on shell-level variable expansion in a member-bound command string ($VAR/path, ~/, backticks) -- the target member's shell may be PowerShell, not POSIX. Resolve paths in JavaScript before building the command using `probeCommandFor(targetOs, shell)` (src/services/member-home.ts) or branching on the member's OS/shell via `isPosixShell(agentOs, shell)` (src/providers/claude.ts). Wrap PowerShell commands explicitly (powershell -EncodedCommand, per src/os/windows.ts) rather than assuming the member's shell. A POSIX-only feature must hard-fail on Windows or gate with a surfaced error -- an advisory warning that never blocks is a false success.
- Never cite a bead id (apra-fleet-XXXX) in any LLM-facing text: prompts, playbooks, schema descriptions, or strings a script prints/writes at runtime. Bead ids are fine only in code comments and docs/.
- The fleet-sprint engine (`packages/apra-fleet-se/fleet-sprint/**` plus the role prompts in `packages/apra-fleet-se/apra-pm/agents/**`) is a GENERIC product that runs sprints for any target repo; apra-fleet building itself with it is the build method, not the product scope. LLM-facing text there (prompt strings, role-prompt markdown) must never assume the target is apra-fleet -- its build commands, env vars, ports, repo layout, bead ids, or deploy.md/playbook sections beyond the documented contract. Target-specific content belongs in the target's own deploy.md/playbooks/CLAUDE.md. Enforced by `packages/apra-fleet-se/scripts/check-generic-boundary.mjs` (part of `npm test`); rule and exception mechanism in docs/generic-engine-boundary.md.

## Fix the product, not the environment

Learn from every failure and misbehaviour by improving the PRODUCT, never by
patching the environment it runs in. We are not building a cradle for a baby;
we are maturing the baby into a strong adult. Thousands of people are meant to
run this software on machines we will never see.

- A manual intervention repeated is a product requirement that was not
  escalated. Its second occurrence stops being a workaround and becomes scoped
  product work, ranked against current work rather than deferred behind it.
- When reporting a failure, the deliverable is the generic fix, not the local
  recovery you performed to keep things moving.
- No fix may depend on a line in this file, an agent's memory, or operator
  tribal knowledge. If a user without those would hit the same trap, it is not
  fixed -- writing the workaround down protects one operator and leaves every
  other user in the trap.
- `human` is an acceptable fallback only where a human genuinely must decide.
  Everywhere else it is an unshipped feature.
- Watch for the recurring shape: implicit environment decides behaviour and
  failure is silent. The answer is explicit configuration plus loud failure,
  in the engine.

## DeepWiki

Always use DeepWiki (MCP server `https://mcp.deepwiki.com/mcp`) while exploring this codebase -- prefer it over cold file reads for architecture/unfamiliar-component questions:
- `mcp__deepwiki__read_wiki_structure(repo)` -- architecture map; call first when starting on an unfamiliar area
- `mcp__deepwiki__read_wiki_contents(repo, topic)` -- a specific doc topic
- `mcp__deepwiki__ask_question(repo, question)` -- faster than local grep for understanding a component

`repo` format: `owner/repo`. Use `Apra-Labs/apra-fleet` for this repo; also useful for related repos this project depends on: `Apra-Labs/apra-pm`, `gastownhall/beads`, `Apra-Labs/fleet-e2e-toy`. To claim what a *specific script does*, read the script -- DeepWiki is for architecture/orientation, not a substitute for reading code you're about to modify.

<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:970c3bf2 -->
## Beads Issue Tracker

This project uses **bd (beads)** for issue tracking. Run `bd prime --no-memories` to see full workflow context and commands.

### Quick Reference

```bash
bd ready                # Find available work
bd show <id>            # View issue details
bd update <id> --claim  # Claim work
bd close <id>           # Complete work
bd prime --no-memories  # Refresh Beads context
```

### Rules

- Use `bd` for ALL task tracking - do NOT use TodoWrite, TaskCreate, or markdown TODO lists
- Run `bd prime --no-memories` for detailed command reference and session close protocol
- Use `bd remember` for persistent knowledge - do NOT use MEMORY.md files
- Operational memories are role-scoped: see "Role-scoped operational memories" below this block.

**Architecture in one line:** issues live in a local Dolt DB; sync uses `refs/dolt/data` on your git remote; `.beads/issues.jsonl` is a passive export. See https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md for details and anti-patterns.

### Persistent Memory - Which System

Three memory systems exist; when asked to "remember" something, route by content:

- **User/assistant preferences** (user's role, standing feedback on how the assistant collaborates, anything not about this repo's code) -> Claude's own auto-memory (`~/.claude/projects/.../memory/`). Not managed by this repo; named here only so it is not confused with the two below.
- **Operational rules** (short, actionable directives for any dispatched agent during this project's beads-tracked work - test-harness gotchas, required flags, launch conventions) -> `bd remember`. Keep entries terse: the actionable rule only, no PR/bead/commit-ref padding. Keys are role-scoped: see "Role-scoped operational memories" below this block.
- **Technical facts about the codebase** (architecture decisions, gotchas, "why is it built this way" - tied to specific files/symbols, worth confidence-grading and contradiction-checking, shareable via `kb_export` to `.fleet/kb-canonical.json`) -> KB (`kb_capture`).

When a rule is both operational and technical: prefer KB if it anchors to specific files/symbols and benefits from confidence-grading over time; prefer `bd remember` if it is a procedural directive with no file/symbol anchor.

KB is opt-in per repo. If `kb_capture`/`kb_query` errors because `kb_setup` has not run here, do not treat it as a hard failure or drop the memory - fall back to `bd remember` (or tell the user) so the request still lands.

## Agent Context Profiles

The managed Beads block is task-tracking guidance, not permission to override repository, user, or orchestrator instructions.

- **Conservative (default)**: Use `bd` for task tracking. Do not run git commits, git pushes, or Dolt remote sync unless explicitly asked. At handoff, report changed files, validation, and suggested next commands.
- **Minimal**: Keep tool instruction files as pointers to `bd prime --no-memories`; use the same conservative git policy unless active instructions say otherwise.
- **Team-maintainer**: Only when the repository explicitly opts in, agents may close beads, run quality gates, commit, and push as part of session close. A current "do not commit" or "do not push" instruction still wins.

## Session Completion

This protocol applies when ending a Beads implementation workflow. It is subordinate to explicit user, repository, and orchestrator instructions.

1. **File issues for remaining work** - Create beads for anything that needs follow-up
2. **Run quality gates** (if code changed) - Tests, linters, builds
3. **Update issue status** - Close finished work, update in-progress items
4. **Handle git/sync by active profile**:
   ```bash
   # Conservative/minimal/default: report status and proposed commands; wait for approval.
   git status

   # Team-maintainer opt-in only, unless current instructions forbid it:
   git pull --rebase
   bd dolt push
   git push
   git status
   ```
5. **Hand off** - Summarize changes, validation, issue status, and any blocked sync/commit/push step

**Critical rules:**
- Explicit user or orchestrator instructions override this Beads block.
- Do not commit or push without clear authority from the active profile or the current user request.
- If a required sync or push is blocked, stop and report the exact command and error.
<!-- END BEADS INTEGRATION -->

## Role-scoped operational memories

Kept outside the bd-managed block above so `bd setup` cannot drop it. Every `bd remember` key is role-scoped -- wrap each role token in `+` on both sides, then `:<slug>`:

- universal (every role): `+all+:<slug>`, e.g. `bd remember --key "+all+:multi-llm-providers" "..."`
- one role: `+<role>+:<slug>`, e.g. `+orchestrator+:sprint-launch-via-supervisor-api`
- several roles: `+<role1>+<role2>+:<slug>`, e.g. `+doer+reviewer+:secret-placeholder-syntax`
- roles: `planner`, `plan-reviewer`, `doer`, `reviewer`, `deployer`, `integ-test-runner`, `regression-test-runner`, `harvester`, `ci-watcher`, `groomer`, `orchestrator`.
- Never write an unscoped key or a one-sided prefix (`reviewer:`). `node packages/apra-fleet-se/scripts/rekey-beads-memories.mjs` re-keys older `role:all:`/`<role>:` keys.

Readers: `bd prime --no-memories` injects no memories. Dispatched roles run `bd memories --json +all+` plus `bd memories --json +<role>+` from their role prompt and apply only entries whose key carries their token (`bd memories` is a case-insensitive substring search over keys and values; the `+` on both sides keeps `+reviewer+` from matching `+plan-reviewer+`; text output truncates long values, `--json` returns them in full). Interactive/orchestrator Claude Code sessions get `+all+` and `+orchestrator+` in full from the SessionStart/PreCompact hook `node scripts/beads-session-memories.mjs +all+ +orchestrator+` in `.claude/settings.json`; an interactive session in a tool without that hook runs the same command itself at session start.

<!-- gitnexus:start -->
# GitNexus -- Code Intelligence

This project is indexed by GitNexus as **apra-fleet** (12888 symbols, 30673 relationships, 300 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.

> Index stale? Run `node .gitnexus/run.cjs analyze` from the project root -- it auto-selects an available runner. No `.gitnexus/run.cjs` yet? `npx gitnexus analyze` (npm 11 crash -> `npm i -g gitnexus`; #1939).

## Always Do

- **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user.
- **MUST run `detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows. For regression review, compare against the default branch: `detect_changes({scope: "compare", base_ref: "main"})`.
- **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
- When exploring unfamiliar code, use `query({search_query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
- When you need full context on a specific symbol -- callers, callees, which execution flows it participates in -- use `context({name: "symbolName"})`.
- For security review, `explain({target: "fileOrSymbol"})` lists taint findings (source->sink flows; needs `analyze --pdg`).

## Never Do

- NEVER edit a function, class, or method without first running `impact` on it.
- NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
- NEVER rename symbols with find-and-replace -- use `rename` which understands the call graph.
- NEVER commit changes without running `detect_changes()` to check affected scope.

## Resources

| Resource | Use for |
|----------|---------|
| `gitnexus://repo/apra-fleet/context` | Codebase overview, check index freshness |
| `gitnexus://repo/apra-fleet/clusters` | All functional areas |
| `gitnexus://repo/apra-fleet/processes` | All execution flows |
| `gitnexus://repo/apra-fleet/process/{name}` | Step-by-step execution trace |

## CLI

| Task | Read this skill file |
|------|---------------------|
| Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` |
| Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` |
| Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` |
| Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` |
| Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` |
| Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` |

<!-- gitnexus:end -->
