From 78e8f5cd731b1c3816a1c5fa6ab2b9ee823d30fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=8Dan?= Date: Thu, 2 Apr 2026 02:58:10 -0600 Subject: [PATCH] docs: add CLAUDE.md with project conventions and architecture Codifies project structure, call flow, testing patterns, and key conventions (Simple::Accessor lowercase accessors, Dist::Zilla build system, example embedding) to help contributors ramp up quickly. Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..773831f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,68 @@ +# CLAUDE.md — Slack::WebHook + +## What is this + +A CPAN Perl module for sending Slack webhook notifications with preset colors and layouts. +~250 lines of Perl. Simple, focused, stable. + +## Project structure + +``` +lib/Slack/WebHook.pm — The module (all logic lives here) +t/hooks.t — Test suite (Test2-based, mocks HTTP::Tiny) +examples/ — Example scripts (embedded in POD via Dist::Zilla InsertExample) +dist.ini — Dist::Zilla config (drives build, release, Makefile.PL generation) +cpanfile — Dependencies (used by CI and cpanm) +Makefile.PL — Auto-generated by dist.ini, committed for CI convenience +.github/workflows/ — GitHub Actions CI +``` + +## Commands + +```bash +# Run tests locally +prove -Ilib -v t/hooks.t + +# Install test dependencies +cpanm --installdeps . +``` + +## Architecture + +Call flow: `post_*()` → `_notify()` → `notify_slack()` → `_http_post()` + +- **`post()`** — Raw message, bypasses attachment formatting +- **`post_ok/warning/error/info()`** — Colored attachment wrappers +- **`post_start/post_end()`** — Timer pair (elapsed time appended to message) +- **`_notify()`** — Normalizes args (string or key-value pairs) → `notify_slack()` +- **`notify_slack()`** — Builds attachment structure with color, title, text, mrkdwn_in +- **`_http_post()`** — UTF-8 auto-detect + JSON encode + HTTP::Tiny post + +## Key conventions + +- **OO via Simple::Accessor** — `new()` calls `$self->$key($val)` for each constructor arg. + Accessor names must be **lowercase** (e.g., `url`, not `URL`). +- **Build system**: Dist::Zilla. `Makefile.PL` and `README.md` are auto-generated. + Edit `dist.ini` for dependency or metadata changes, not Makefile.PL directly. +- **Examples**: Files in `examples/` are embedded in POD via `[InsertExample]`. + They must have `use Slack::WebHook ();` and be syntactically valid Perl. +- **Minimum Perl**: 5.010 (declared in dist.ini). Don't use features above 5.10. + +## Testing + +- Tests mock `HTTP::Tiny::post_form` to capture payloads — no real HTTP calls +- `http_post_was_called_with()` is the main assertion helper: decodes JSON payload and compares +- `Test2::Plugin::NoWarnings` is active — unexpected warnings fail tests +- When testing warning paths, use `local $SIG{__WARN__}` to capture and test explicitly +- Mock must return `{ success => 1 }` — `_http_post()` warns on failure responses + +## Dependencies + +Runtime: `Simple::Accessor`, `HTTP::Tiny` (>= 0.076), `JSON::XS`, `Encode` +Test: `Test2::Bundle::Extended`, `Test2::Tools::Explain`, `Test2::Plugin::NoWarnings`, `Test::MockModule` + +## Git workflow + +- Branch prefix: `koan.atoomic/*` +- Never commit to master directly +- PRs target master, always draft