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.
3.1 KiB
XMPP layer
src/xmpp/ wraps libstrophe and exposes higher-level operations to the
command, event, and UI layers.
Connection lifecycle
src/xmpp/connection.c owns the connection state machine. Public surface in
connection.h:
jabber_conn_status_t connection_get_status(void);jabber_conn_status_t connection_connect(const char* fulljid, const char* passwd, ...);jabber_conn_status_t connection_register(...);void connection_disconnect(void);
jabber_conn_status_t values:
| Value | Meaning |
|---|---|
JABBER_DISCONNECTED |
Not connected. |
JABBER_CONNECTING |
Connect in progress. |
JABBER_CONNECTED |
Live session. |
JABBER_DISCONNECTING |
Tearing down. |
Most code paths gate on JABBER_CONNECTED. A canonical command-handler
guard:
if (connection_get_status() != JABBER_CONNECTED) {
cons_show("You are not currently connected.");
return TRUE;
}
In tests, will_return(connection_get_status, JABBER_CONNECTED) (or
JABBER_DISCONNECTED) before the call. See gotchas.md.
Stanza building
src/xmpp/stanza.c is the assembler. Helpers like
stanza_create_message(...), stanza_create_presence(...), plus low-level
xmpp_stanza_* from libstrophe.
Outgoing flow:
cmd_funcs.corclient_events.c→xmpp/message.c(orpresence.c,iq.c) →stanza.cto build → libstrophe to send.
Incoming flow:
- libstrophe handler →
xmpp/message.c(or sibling) parses →event/server_events.cfans out →ui/,chatlog.c, plugin callbacks.
JIDs
src/xmpp/jid.h defines Jid and the auto_jid cleanup macro. Use
auto_jid rather than manual jid_destroy() whenever practical:
auto_jid Jid* parsed = jid_create(input);
if (!parsed || !parsed->barejid) {
return FALSE;
}
Jid exposes barejid, fulljid, localpart, domainpart, resourcepart.
Sessions, MUC, presence, roster
| File | Responsibility |
|---|---|
session.c |
Logical XMPP session: account, fulljid, presence, settings. |
muc.c |
Multi-user chat rooms (joins, occupants, configuration). |
presence.c |
Presence stanzas, subscription requests. |
roster.c / roster_list.c |
Roster fetch, push, contact lookup. |
chat_session.c |
Per-conversation state (carbons, OTR channel, etc.). |
chat_state.c |
Composing / paused / inactive notifications (XEP-0085). |
bookmark.c |
Bookmarked rooms (XEP-0048). |
blocking.c |
Block list (XEP-0191). |
vcard.c / vcard_funcs.h |
vCard fetch / publish. |
avatar.c |
Avatar publish / fetch (XEP-0084). |
iq.c |
Generic IQ handling and pending-IQ map. |
capabilities.c |
Entity capabilities cache (XEP-0115). |
Encryption bridges
src/xmpp/omemo.c and src/xmpp/ox.c are bridges into the encryption
modules — they live alongside same-named files in src/omemo/ and
src/pgp/. Be precise about which path you mean.
Testing
When unit-testing code that calls into xmpp/, expect to:
- Mock
connection_get_statuswithwill_return(...). - Stub session getters (
session_get_account_name) and roster lookups. - Use stubs in
tests/unittests/xmpp/stub_*.c. Seetesting/stubs.md.