docs: split context into layered, agent-oriented files

Replace the single file-structure.md with a stratified layout designed
for AI/agent skill consumption: tables and concrete identifiers over
prose, files loaded on demand, content separated by churn rate.

Layers:
- architecture/  stable structural reference (overview, source-map,
                 test-map, data-flow)
- patterns/      memory, commands, autocomplete, events, xmpp,
                 encryption, ui, plugins
- testing/       unit-tests, stubs, functional-tests, bench
- build/         local, docker, ci
- playbooks/     add-command, add-test, add-autocomplete,
                 add-event-handler, add-encryption
- gotchas.md     append-only dated entries (seven seed entries)
- wip/           branch-specific notes; deleted on merge to master

Stable layers describe cproof on master only. In-flight feature
branches (currently feat/ai) get a single file under wip/.

INDEX.md is the entry map with churn labels; SKILL.md is the
always-loaded skill hint pointing to it.
This commit is contained in:
2026-04-30 20:52:06 +03:00
parent bea6ab6df5
commit 22977846a3
30 changed files with 2351 additions and 112 deletions

76
architecture/data-flow.md Normal file
View File

@@ -0,0 +1,76 @@
# Data flow
High-level paths through the codebase. Use this when reasoning about where a
change should land or where a bug originates.
## User input → action
```
keypress
→ src/ui/inputwin.c (line editor, key dispatch)
→ src/command/cmd_ac.c (autocomplete on Tab)
→ src/command/cmd_defs.c (parse / lookup)
→ src/command/cmd_funcs.c (handler: cmd_<name>)
→ side effects: src/xmpp/, src/config/, src/ui/, src/event/
```
- Tab triggers autocomplete via `cmd_ac.c` lookup in `ac_funcs` hash table
(key: `/cmd`, value: per-command `_<cmd>_autocomplete` function).
- Enter parses input via `parse_args()` (`src/tools/parser.c`), looks up the
`Command*` via `cmd_get()` (`src/command/cmd_defs.c`), invokes the handler
declared with `CMD_MAINFUNC` or one of the `CMD_SUBFUNCS`.
## Outgoing chat message
```
cmd_msg / typing-into-chatwin
→ src/xmpp/message.c (build message stanza)
→ src/xmpp/stanza.c (assemble XML)
→ libstrophe (send)
→ src/chatlog.c (persist locally)
→ src/ui/chatwin.c (echo into window)
```
Encryption injects between message build and send:
- OMEMO via `src/xmpp/omemo.c``src/omemo/omemo.c` (libsignal-protocol).
- OTR via `src/otr/otr.c` (libotr).
- PGP / OX via `src/pgp/gpg.c` / `src/pgp/ox.c``src/xmpp/ox.c`.
## Incoming stanza
```
libstrophe callback
→ src/xmpp/{message,presence,iq,muc,roster}.c (parse, validate)
→ src/event/server_events.c (sv_ev_*)
→ src/ui/{chatwin,mucwin,console,...}.c (render)
→ src/chatlog.c (persist)
```
`server_events.c` is the chokepoint — every inbound XMPP event flows through a
`sv_ev_*` function. UI updates and persistence fan out from there.
## Client-initiated events
`src/event/client_events.c` mirrors `server_events.c` for events that
originate locally (UI actions, command-driven state changes) but need the
same downstream fan-out.
## Connection state
- `src/xmpp/connection.c` owns the `jabber_conn_status_t` (declared in
`connection.h`).
- `connection_get_status()` returns the current state. Many code paths gate
on `JABBER_CONNECTED` — see `patterns/xmpp.md`.
- Tests must `will_return(connection_get_status, JABBER_CONNECTED)` (or the
desired state) before exercising any code path that consults it. See
`gotchas.md`.
## Plugin hook points
Plugin callbacks (`src/plugins/callbacks.c`) sit on:
- Pre/post message send and receive (around `src/xmpp/message.c` flow).
- Connection lifecycle (around `src/xmpp/session.c`).
- Window-switch events (around `src/ui/window_list.c`).
See `patterns/plugins.md`.

59
architecture/overview.md Normal file
View File

@@ -0,0 +1,59 @@
# Overview
## What cproof is
- Terminal-based XMPP (chat) client written in C.
- Fork of [Profanity](https://github.com/profanity-im/profanity); rename to
cproof is **work in progress** — many internal symbols, copyright headers,
and identifiers still say "Profanity".
- Heavy GLib usage (strings, lists, hash tables, key files).
- Optional integrations: OMEMO (libsignal-protocol), OTR (libotr), PGP/OX
(gpgme), Python plugins, libnotify, libgcrypt, libreadline, ncurses.
## Build system
- Autotools: `configure.ac` + a top-level `Makefile.am`. No CMake.
- `autogen.sh` regenerates the configure script.
- `configure-debug` is a thin helper that invokes `./configure` with
debug-friendly flags.
- Canonical build environment: Docker (`Dockerfile.debian` at repo root).
See `build/docker.md`.
## Test framework
- **Unit tests:** cmocka, run via `make check`. Live in `tests/unittests/`.
- **Functional tests:** custom runner in `tests/functionaltests/` against a
real running cproof instance.
- **Benches:** custom runners in `tests/bench/<runner>/` for database /
flatfile / long-message workloads.
- See `architecture/test-map.md` and the `testing/` directory for detail.
## High-level module split
Source lives under `src/` in module directories — see
`architecture/source-map.md` for the full table. Major chunks:
- **Command layer** (`src/command/`) — `/foo`-style commands the user types.
- **XMPP layer** (`src/xmpp/`) — protocol, sessions, stanza building.
- **UI layer** (`src/ui/`) — windows, buffers, status bar, input.
- **Event layer** (`src/event/`) — bridges between XMPP and UI / commands.
- **Encryption** (`src/omemo/`, `src/otr/`, `src/pgp/`) — three independent
encryption stacks.
- **Plugins** (`src/plugins/`) — C and Python plugin APIs.
- **Tools** (`src/tools/`) — generic utilities (parser, autocomplete, HTTP,
clipboard, editor).
Active feature branches (e.g. `feat/ai`, which adds `src/ai/`) are not
described in the stable architecture files. See `wip/` for branch-specific
notes.
## Entry points
| File | Role |
|---|---|
| `src/main.c` | Process entry. |
| `src/profanity.c` | Application init/shutdown lifecycle. |
| `src/common.h` | Project-wide macros (`auto_*`, `FREE_SET_NULL`, `ARRAY_SIZE`). |
| `src/database.c` / `src/database.h` | Database (SQLite + flatfile) abstraction. |
| `src/chatlog.c` | Chat history persistence. |
| `src/log.c` | Application log. |

View File

@@ -0,0 +1,38 @@
# Source map
## `src/` module directories
| Path | Purpose | Key files |
|---|---|---|
| `src/command/` | `/command` definition, dispatch, autocompletion. | `cmd_defs.c/h`, `cmd_funcs.c/h`, `cmd_ac.c/h` |
| `src/config/` | Persistent configuration: accounts, prefs, themes, colors, CA file, scripts. | `accounts.c/h`, `preferences.c/h`, `theme.c/h`, `color.c/h`, `cafile.c/h`, `scripts.c/h`, `tlscerts.c/h`, `conflists.c/h`, `files.c/h`, `account.c/h` |
| `src/event/` | Mediates between XMPP layer and UI/commands. | `client_events.c/h`, `server_events.c/h`, `common.c/h` |
| `src/omemo/` | OMEMO encryption (libsignal-protocol). | `omemo.c/h`, `crypto.c/h`, `store.c/h` |
| `src/otr/` | OTR encryption (libotr v4). | `otr.c/h`, `otrlib.h`, `otrlibv4.c` |
| `src/pgp/` | OpenPGP / OX (gpgme). | `gpg.c/h`, `ox.c/h` |
| `src/plugins/` | C and Python plugin support. | `plugins.c/h`, `c_plugins.c/h`, `python_plugins.c/h`, `c_api.c/h`, `python_api.c/h`, `api.c/h`, `profapi.c/h`, `callbacks.c/h`, `autocompleters.c/h`, `disco.c/h`, `settings.c/h`, `themes.c/h` |
| `src/tools/` | Generic utilities. | `parser.c/h`, `autocomplete.c/h`, `clipboard.c/h`, `editor.c/h`, `http_*.c/h`, `aesgcm_download.c/h`, `bookmark_ignore.c/h`, `plugin_download.c/h` |
| `src/ui/` | Windows, buffers, status bar, input. | `window.c/h`, `window_list.c/h`, `chatwin.c`, `mucwin.c`, `console.c`, `confwin.c`, `privwin.c`, `xmlwin.c`, `vcardwin.c`, `rosterwin.c`, `occupantswin.c`, `inputwin.c/h`, `statusbar.c/h`, `titlebar.c/h`, `tray.c/h`, `screen.c/h`, `notifier.c`, `core.c`, `buffer.c/h`, `ui.h`, `win_types.h` |
| `src/xmpp/` | XMPP protocol layer. | `connection.c/h`, `session.c/h`, `roster.c/h`, `roster_list.c/h`, `muc.c/h`, `presence.c/h`, `message.c/h`, `iq.c/h`, `stanza.c/h`, `vcard.c/h`, `vcard_funcs.h`, `jid.c/h`, `capabilities.c/h`, `omemo.c/h`, `ox.c/h`, `blocking.c/h`, `bookmark.c/h`, `chat_session.c/h`, `chat_state.c/h`, `avatar.c/h`, `contact.c/h`, `form.c/h`, `resource.c/h` |
## Top-level files in `src/`
| File | Role |
|---|---|
| `main.c` | Process entry. |
| `profanity.c` / `profanity.h` | Application init/shutdown. |
| `common.h` / `common.c` | Project-wide macros and small helpers. |
| `database.c` / `database.h` | Database facade (SQLite + flatfile). |
| `chatlog.c` / `chatlog.h` | Chat log writer/reader. |
| `log.c` / `log.h` | Application log. |
| `config.h.in` | autoconf-generated config header (do not edit `config.h`). |
| `gitversion.h.in` | Generated `gitversion.h` carrying build-time SHA. |
## Naming notes
- The fork-rename (Profanity → cproof) is incomplete. Many symbols, file
paths, and headers still carry "Profanity" / "prof_" prefixes. Treat them as
current and authoritative; do not rename opportunistically.
- Encryption modules under `src/omemo/`, `src/otr/`, `src/pgp/` use module-
internal helpers; the XMPP-side bridges live in `src/xmpp/omemo.c` and
`src/xmpp/ox.c` (separate files with the same names — be precise about path).

69
architecture/test-map.md Normal file
View File

@@ -0,0 +1,69 @@
# Test map
## Top-level test directories
| Path | Runner | Purpose |
|---|---|---|
| `tests/unittests/` | cmocka via `make check` | Unit tests with stubbed dependencies. |
| `tests/functionaltests/` | custom binary, runs against a real cproof | End-to-end behaviour tests. |
| `tests/bench/` | custom benches, one binary per runner | Database / flatfile / long-message benchmarks. |
| `tests/prof_cmocka.h` | — | Thin cmocka wrapper used by all unit tests. |
## `tests/unittests/` layout
- `unittests.c` — single test runner. Registers every test via
`cmocka_unit_test()` / `cmocka_unit_test_setup_teardown()`.
- `helpers.c` / `helpers.h` — shared test utilities.
- `test_<topic>.c` + `test_<topic>.h` — paired test files. The header
declares each test function; the runner includes the header to register it.
- Per-module subdirectories carry **stubs** for that module's public symbols:
| Stub directory | Stubs for |
|---|---|
| `tests/unittests/chatlog/` | `src/chatlog.c` |
| `tests/unittests/command/` | `src/command/` |
| `tests/unittests/config/` | `src/config/` (accounts, cafile, etc.) |
| `tests/unittests/database/` | `src/database.c` |
| `tests/unittests/event/` | `src/event/` |
| `tests/unittests/log/` | `src/log.c` |
| `tests/unittests/omemo/` | `src/omemo/` |
| `tests/unittests/otr/` | `src/otr/` |
| `tests/unittests/pgp/` | `src/pgp/` |
| `tests/unittests/plugins/` | `src/plugins/` |
| `tests/unittests/tools/` | `src/tools/` |
| `tests/unittests/ui/` | `src/ui/` |
| `tests/unittests/xmpp/` | `src/xmpp/` |
| `tests/unittests/unittests/` | top-level utility stubs |
Branch-specific stubs (e.g. `tests/unittests/ai/` on `feat/ai`) are not
listed here — see `wip/` for branch notes.
Each stub file is named `stub_<module>.c`. See `testing/stubs.md` for when
to add or extend a stub.
## `tests/functionaltests/` layout
- `functionaltests.c` — runner.
- `proftest.c` / `proftest.h` — fixture: spawns cproof under PTY, talks XMPP.
- `test_<feature>.c` — feature suites: connect, disconnect, message, presence,
carbons, roster, history, ping, autoping, lastactivity, software, disco,
receipts, rooms, muc, chat_session, export_import.
Functional tests require:
- A test XMPP server reachable from the test harness.
- A pre-baked `.profrc` (see recent perf work).
- See `testing/functional-tests.md` for prerequisites and runner flags.
## `tests/bench/` layout
Each runner is a separate directory + binary:
| Runner | Measures |
|---|---|
| `bench_runner` | Combined runner for general bench scenarios. |
| `bench_export_import` | Database export/import throughput. |
| `bench_failure_modes` | Flatfile parser failure / recovery paths. |
| `bench_long_messages` | Flatfile parser with very long messages. |
| `gen_history` | Generates synthetic chat history for benches. |
See `testing/bench.md` for invocation and interpretation.