Adds vcpkg as a submodule at vcpkg/, pinned to the exact commit vcpkg.json already declares as builtin-baseline, so the bundled checkout and the manifest's resolved port versions can never drift apart. cmake/voicecat-toolchain.cmake, scripts/common.sh, and clients/apple/scripts/build-xcframework.sh now resolve vcpkg as: VCPKG_ROOT env var (external checkout) > bundled submodule. Docs updated to describe the new one-time setup. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
116 lines
5.8 KiB
Markdown
116 lines
5.8 KiB
Markdown
# 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). vcpkg is
|
||
bundled as a git submodule at `vcpkg/`, pinned to `vcpkg.json`'s `builtin-baseline`:
|
||
|
||
```bash
|
||
git submodule update --init vcpkg # one-time, after cloning
|
||
./vcpkg/bootstrap-vcpkg.sh # .bat on Windows
|
||
cmake --preset dev
|
||
cmake --build --preset dev
|
||
ctest --preset dev
|
||
```
|
||
|
||
To use an external vcpkg checkout instead, `export VCPKG_ROOT=/path/to/vcpkg` — it always
|
||
takes priority over the bundled submodule.
|
||
|
||
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), which also resolves
|
||
`VCPKG_ROOT` (env var override, else the bundled `vcpkg/` submodule).
|
||
|
||
## 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).
|