diff options
| author | Paul Buetow <paul@buetow.org> | 2026-07-12 17:20:15 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-07-12 17:20:15 +0300 |
| commit | 1770b12d5d95476310c27ccf39a91b5ba4a3f119 (patch) | |
| tree | c81bf1d97b5f71140acc73e970abf406f9f64fe7 /AGENTS.md | |
| parent | f2b8ed6d2ea0744cfd1a36a6fbd1763926b873bb (diff) | |
bootstrap: meson build, test harness, CI, conventions, README/AGENTS (et0)
Phase 0 (task et0): lays the build/test/CI/convention groundwork before any
feature code.
- meson.build: project ggaze C11 -Wall -Wextra; deps gtk4/glib/gio/libadwaita;
feature options gegl/jxl/avif/heif (auto); generated ggaze-config.h with
app id, version, GGAZE_HAVE_* feature flags.
- tests: GLib g_test harness with separate unit/integration suites
(--suite unit / --suite integration); test_bootstrap sanity test proves
the harness compiles and the config header is reachable; -Db_coverage=true
coverage target wired.
- CI: .woodpecker/ci.yml three lanes (minimal, gegl, asan) with xvfb for the
integration track and a coverage lane that warns until M10.
- conventions: .clang-format (3-space, 80-col, K&R, *-on-var, return type on
its own line) + .editorconfig matching docs/coding-conventions.md; CI
clang-format --dry-run -Werror gate.
- top-level README.md (humans) and AGENTS.md (agents) pointing into docs/.
- LICENSE (GPL-3.0-or-later), .gitignore, dir placeholders.
Acceptance: meson setup build && ninja -C build && meson test -C build green;
clang-format --dry-run --Werror clean.
Diffstat (limited to 'AGENTS.md')
| -rw-r--r-- | AGENTS.md | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..f56a48a --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,126 @@ +# AGENTS.md — guide for coding agents working on ggaze + +ggaze is a small, fast, native GTK4 image viewer in C for Fedora/GNOME. This +file is the entry point for a fresh-context agent: read it first, then the +linked `docs/`. Humans should read `README.md`. + +## Load these skills as instructions (not as shell commands) + +- `agent-task-management` — task workflow (use `~/go/bin/ask` subcommands only) +- `c-best-practices` — C style, authoritative for all C here +- `solid-principles` — OO/design review +- `beyond-solid-principles` — architecture review +- `find-code-bugs` — defect hunting (at audit milestones) + +## Build / test / coverage + +```sh +meson setup build +ninja -C build +meson test -C build +meson test -C build --suite unit +meson test -C build --suite integration + +# coverage (>=80% on plain-C modules; gate warns until M10, then fails) +meson setup -Db_coverage=true build-cov && ninja -C build-cov +meson test -C build-cov && ninja -C build-cov coverage + +# leak check (run after every major feature — see "Memory" below) +meson setup build-asan -Db_sanitize=address,undefined +ASAN_OPTIONS=detect_leaks=1:abort_on_error=1 G_DEBUG=gc-friendly \ + meson test -C build-asan +``` + +## Two test tracks (both mandatory) + +| Track | Where | What | Gate | +|-------|------|------|------| +| unit | `tests/test_<module>.c` | plain-C modules, no display | >=80% line coverage (gcov) | +| integration | `tests/integration/test_<flow>.c` | cross-module flows, real temp dirs, offscreen GTK | must be green, no coverage gate | + +Shared helpers go in `tests/helpers/`; fixtures in `tests/fixtures/` (grow per +milestone). Integration suites land with the milestone that first makes a flow +possible — see `docs/IMPLEMENTATION.md` "Planned integration suites". + +## Conventions (enforced) + +- `docs/coding-conventions.md` summarizes; the `c-best-practices` skill wins. +- 3-space indent, 80 cols, K&R braces, `*` on the variable (`Token *p_token`), + parenthesized returns (`return (x);`), return type on its own line. +- One module per `foo.h` + `foo.c`; every concrete type gets `type_new` / + `type_delete` (pair them); plain-C modules own no GtkWidget and are + unit-testable without a display. +- `clang-format --dry-run --Werror` must be clean on every `*.c`/`*.h` + (`.clang-format` matches the conventions). CI fails on a dirty tree. The + config targets LLVM clang-format >=16 (Fedora 40 ships 18); it uses the + cross-version key spellings (`UseTab`, `AlwaysBreakAfterReturnType`) so + both the Fedora-40 CI toolchain and newer local builds accept it. +- Header guards uppercase from filename (`NAVIGATOR_H`). `.c` includes: own + header first, blank line, system `<...>`, then project `"..."`. + +## Optional features are OFF in the minimal CI lane + +`gegl`, `jxl`, `avif`, `heif` are meson `feature`s (default `auto`). The +**minimal** CI lane forces all disabled and must stay green; the **gegl** lane +forces `gegl=enabled`. Never break the minimal build when adding an optional +backend — gate code with `GGAZE_HAVE_*` from `ggaze-config.h` and toast +"GEGL not built in" gracefully. + +## Architecture invariants (do not violate) + +- Only the main thread touches GTK widgets. Decode runs in `GTask` threads. +- **One active load per window.** Issuing a new load cancels the previous + `GCancellable` and drops its result. The viewer only ever shows a texture + whose path == `navigator.current` (**last-write-wins**). +- Bounded `GdkTexture` LRU (cap 4) to bound memory. +- Plain-C modules (`navigator`, `loader`, `detect`, `thumbnail`, `trash`, + `mover`, `opener`, `runner`, `enhancer`, `info`, `texturecache`, + `clipboard`) own no GtkWidget and are unit-tested standalone. + +## Memory (C has no GC) + +After **every major feature milestone**, run a `+leakcheck` pass before +starting the next feature: ASan build + `G_DEBUG=gc-friendly`, full test suite +(unit + integration), and a scripted elevator-pitch session; any leak blocks +the next milestone. See `docs/IMPLEMENTATION.md` "Memory-leak profiling". + +## Module map + +``` +src/main.c entry, CLI, GtkApplication +src/app.{c,h} GApplication, actions, single-instance +src/window.{c,h} GgazeWindow : GtkApplicationWindow (grid/large stack) +src/viewer.{c,h} GgazeViewer : GtkWidget (large canvas, zoom/pan) +src/gridview.{c,h} GgazeGrid (thumbnail overview) +src/shortcuts.{c,h} keybinding -> GAction map +src/navigator.{c,h} dir listing, sort/filter, marks, GFileMonitor +src/trash.{c,h} ./Trash bin + permanent delete + undo +src/mover.{c,h} configurable move destinations +src/opener.{c,h} configurable external programs +src/runner.{c,h} configurable shell scripts (async /bin/sh -c) +src/enhancer.{c,h} optional GEGL quick-enhance + export copy +src/clipboard.{c,h} copy image/URIs to GdkClipboard +src/thumbnail.{c,h} freedesktop TMS cache +src/settings.{c,h} GSettings wrapper (org.buetow.ggaze) +src/info.{c,h} EXIF/dimensions gather (libexif) +src/texturecache.{c,h} bounded LRU of decoded GdkTextures +src/loader/loader.{c,h} async load API +src/loader/detect.{c,h} content-sniff format detection +src/loader/backends/ pixbuf.c jxl.c avif.c heif.c (jpeg.c M6) +``` + +## Design docs (read before touching a milestone) + +`docs/PLAN.md` (tracker + decisions log), `docs/IMPLEMENTATION.md` (execution +plan + test-track tables + leak-check rules), `docs/architecture.md`, +`docs/ui-and-interactions.md`, `docs/tech-stack.md`, `docs/gegl.md`, +`docs/roadmap.md`, `docs/open-questions.md`. When docs disagree, the detail +docs are authoritative and `PLAN.md` gets updated. + +## Task workflow + +Tasks are scoped to this git project via `~/go/bin/ask`. Use only its +subcommands (`list`, `ready`, `add`, `info`, `start`, `done`, `annotate`, +`modify`, `dep`, ...). When a task passes tests + sub-agent review, commit and +push to `origin main`, then mark `ask done <id>` and progress to the next ready +task.
\ No newline at end of file |
