# AGENTS.md — working method

This file is the **working method** for a developer or AI agent picking up VoiceCat. Companion
files:

- [`CLAUDE.md`](CLAUDE.md) — the hub: build/test commands, architecture at a glance, doc map.
- [`PROGRESS.md`](PROGRESS.md) — living tracker: what's done, what's next. **Update it as you work.**
- [`docs/`](docs/) — the **source of truth** for all design.

Read those, then use the method below.

## What this repo is right now

A complete **design** ([`docs/`](docs/)) plus a working implementation through M5: real TLS
control plane, encrypted UDP voice (Opus), multi-stream, TOFU identity pinning, channel tree,
permissions, moderation, disconnect/keepalive/reaper. The Windows WinForms C# client is
shipped (M4). The macOS/iOS Swift client is next. The `skeleton` preset still links a
no-deps stub path (`VC_ERR_NOT_IMPLEMENTED`) for smoke-check builds.

## The working method (important)

**A clean compile is the floor, not the goal.** Do not treat "make the compiler errors go
away" as done. Each milestone in [`docs/roadmap.md`](docs/roadmap.md) has an **exit
criterion stated as observable behavior** — that is what "done" means. Examples:

- M1 done = *two `vccli` instances actually chat through a real server over TLS*, not "it builds".
- M2 done = *you can talk between two clients in a channel and hear loss concealment work*.

So the loop is:

1. Pick the current milestone in `docs/roadmap.md`. Read the relevant design doc section.
2. Write the smallest test (CTest, or a `vccli` interaction) that encodes the exit behavior.
3. Implement the subsystem until that test passes — not just until it compiles.
4. Keep the build green and the existing tests passing on every commit.

Every commit must compile and pass `ctest`. Behavior tests are how you know you're actually
making progress.

## Build

Default development preset (real deps via vcpkg — works on Windows/Linux/macOS):

```bash
export VCPKG_ROOT=/path/to/vcpkg     # bootstrap vcpkg first; cross-platform
cmake --preset dev
cmake --build --preset dev
ctest --preset dev
```

Skeleton (no third-party deps — works immediately, no vcpkg needed):

```bash
cmake --preset skeleton
cmake --build --preset skeleton
ctest --preset skeleton
```

> **Windows gotcha — always run `ctest` and built binaries via PowerShell, not Git Bash.**
> MinGW-built executables fail in Git Bash with exit code `0xc0000139`
> (STATUS_ENTRYPOINT_NOT_FOUND) even though the file exists and is marked executable.
> PowerShell runs them correctly. Use the PowerShell tool (not Bash) for any `ctest`,
> `voicecat-server.exe`, or `vccli.exe` invocation on Windows.

Other presets: `release` (optimized + tests), `server-release` (optimized + stripped,
deployment-shaped), `windows-client` (DLL for C# app), `apple-dev`/`apple-ios`/
`apple-ios-sim` (Apple platform scaffolding). See [`docs/building.md`](docs/building.md)
for the full matrix.

`vcpkg.json` pins all deps to a fixed vcpkg baseline — `cmake --preset dev` resolves them
automatically on first configure. The vcpkg triplet is auto-resolved from the host platform
by [`cmake/voicecat-toolchain.cmake`](cmake/voicecat-toolchain.cmake).

## Where each subsystem lives (and its doc)

| Path | Subsystem | Design |
|------|-----------|--------|
| `core/include/voicecat.h` | The C ABI every client/server calls | docs/architecture.md §4 |
| `core/proto/voicecat.proto` | Control-plane wire format | docs/protocol.md |
| `core/src/net/` | Asio TCP/UDP transport, framing | docs/architecture.md, docs/protocol.md §1 |
| `core/src/crypto/` | TLS 1.3 (mbedTLS), media AEAD (libsodium), anti-replay | docs/security.md |
| `core/src/codec/` | Opus encode/decode, FEC/DTX | docs/voice.md §3–4 |
| `core/src/protocol/` | Envelope (de)serialize, state machine, routing | docs/protocol.md |
| `core/src/session/` | Channels, users, streams, permissions, text | docs/protocol.md §5 |
| `core/src/audio/` | Capture/playback (miniaudio), APM DSP, jitter buffer, mixer | docs/voice.md §8–11 |
| `server/` | Connection mgr, session registry, SFU relay, SQLite | docs/architecture.md §5 |
| `tools/vccli/` | Headless client to drive/verify the protocol | — |

## Suggested first steps (M1 spine)

1. **Wire protobuf + framing** (`net/` + `protocol/`): build, then generate C++ from
   `voicecat.proto`, implement the `[u32 length][Envelope]` framing over a plain TCP socket
   (TLS can come right after). Test: round-trip an `Envelope` through the framer.
2. **TLS 1.3 via mbedTLS** (`crypto/`): wrap the TCP channel. Test: `vccli` completes a TLS
   handshake against `voicecat-server` and exchanges a `ClientHello`/`ServerHello`.
3. **Auth + state** (`session/`): guest + admin-provisioned accounts (Argon2id/SQLite),
   channel tree snapshot/deltas, ephemeral text relay. Test: two `vccli` chat.

Then proceed to M2 (UDP media) per the roadmap.

## House rules

- **No GPL/LGPL dependencies, ever** (closed-source redistribution is a goal). See
  docs/tech-stack.md §5. CI should fail on a copyleft transitive dep.
- **Encryption is mandatory** — never add a plaintext transport path. docs/security.md.
- **Real-time audio threads** never allocate, lock, or block. docs/architecture.md §3.
- Keep `docs/` and code in sync. If you change a wire format or the C ABI, update the doc in
  the same commit.
- The C ABI is the contract for the Swift/C# clients — treat changes to `voicecat.h` and
  `voicecat.proto` as deliberate, versioned events (docs/protocol.md §8).
