Files
cproof-context/gotchas.md
jabber.developer2 22977846a3 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.
2026-04-30 20:52:06 +03:00

3.5 KiB

Gotchas

Append-only log of known pitfalls. One entry per pitfall. Format:

## YYYY-MM-DD — <short title>

<body — what bites, why, what to do instead>

Scan this file before finishing any non-trivial task.


2026-04-30 — g_strsplit result must use g_strfreev

g_strsplit (and g_strdupv) return a gchar** whose elements are individually GLib-allocated. Free with g_strfreev, not g_free. The latter compiles fine and silently leaks the inner strings.

The cleanup macro is auto_gcharv (declared in src/common.h):

auto_gcharv gchar** parts = g_strsplit(line, " ", -1);

Mixing g_free on a gchar** is the most common allocator-mismatch bug in this codebase.


2026-04-30 — JABBER_CONNECTED must be queued in unit tests

Most XMPP-touching code paths gate on connection_get_status(). The unit- test stub returns mock(), so every test reaching that gate must:

will_return(connection_get_status, JABBER_CONNECTED);
// or
will_return(connection_get_status, JABBER_DISCONNECTED);

Forgetting this aborts cmocka with a "missing mock value" error. If you see that error, it's almost always connection_get_status you forgot.


2026-04-30 — Autocomplete callbacks must be stateless

Some older callbacks keep "last match" state in a file-static _last_*_match variable. Do not copy that pattern. A clean canonical example is roster_contact_autocomplete (src/xmpp/roster_list.c) — it delegates straight to autocomplete_complete against a roster-owned Autocomplete object and keeps no callback-local state.

Stateful callbacks misbehave under shift-tab cycling and break when two completers run concurrently in a layered command (e.g. /foo set bar <tab> followed by /foo set baz <tab>).


2026-04-30 — CWE-134 format-string discipline

Never pass user-controlled or arbitrary strings as the format argument to printf-family or GLib formatted-print functions. A recent compiler- hardening pass (cf. cproof commit 9ec01fa8c) audited and tightened these sites; do not regress.

Right:

cons_show("%s", user_text);

Wrong:

cons_show(user_text);

The compiler does not always warn, especially across helper layers. Enable and respect -Wformat -Wformat-security warnings in any build you trust.


2026-04-30 — Build inside Docker, not on the host

Library version drift between a developer host and Dockerfile.debian (GLib, OpenSSL, libstrophe in particular) can mask or invent failures. CI is the source of truth; CI builds inside the Debian image. See build/docker.md.

If you absolutely must build on the host, mirror the package set in Dockerfile.debian exactly and pin versions — you will spend more time chasing version drift than the Docker build would have cost.


2026-04-30 — Beware of "Profanity" vs "cproof" naming

The fork-rename is incomplete. Many files, symbols, copyright headers, and config keys still say Profanity / prof_ / profanity. These are authoritative as-is; do not rename them opportunistically alongside unrelated changes. Rename work, when it happens, will be a dedicated PR.


2026-04-30 — Encryption disable builds must compile

Each encryption stack (HAVE_OMEMO, HAVE_LIBOTR, HAVE_LIBGPGME) can be turned off at configure time. New code that calls into these modules must wrap calls in the matching #ifdef and provide a graceful fallback in the #else. CI does not always test every disable combination — verify locally with at least the off-build for each stack you touched.