AGENTS.md (4207B)
1 # ppad-bolt8 2 3 Haskell implementation of BOLT #8 (Lightning Network encrypted transport). 4 5 Specification: https://github.com/lightning/bolts/blob/master/08-transport.md 6 7 ## Project Structure 8 9 - `lib/` - library source (Lightning.Protocol.BOLT8) 10 - `test/` - tests (tasty + tasty-hunit) 11 - `bench/` - benchmarks (criterion for timing, weigh for allocations) 12 - `flake.nix` - nix flake for dependency and build management 13 - `ppad-bolt8.cabal` - cabal package definition 14 - `CLAUDE.md` / `AGENTS.md` - keep these in sync 15 16 ## Build and Test 17 18 Enter devshell and use cabal: 19 20 ``` 21 nix develop 22 cabal build 23 cabal test 24 cabal bench 25 ``` 26 27 Do not use stack. All dependency and build management via nix. 28 29 ## Dependencies 30 31 ### ppad libraries (use freely) 32 33 Use ppad libraries (github.com/ppad-tech, git.ppad.tech) liberally. 34 Current dependencies: ppad-aead, ppad-hkdf, ppad-secp256k1, ppad-sha256. 35 36 ### External libraries 37 38 Use only minimal external dependencies. Prefer GHC's core/boot libraries 39 (base, bytestring, primitive, etc.). 40 41 **Ask for explicit confirmation before adding any library outside of:** 42 - GHC boot/core libraries 43 - ppad-* libraries 44 - Test dependencies (tasty, QuickCheck, etc. for test-suite only) 45 - Benchmark dependencies (criterion, weigh for benchmark only) 46 47 ## Code Style 48 49 ### Performance 50 51 - Use strictness annotations (BangPatterns) liberally 52 - Prefer UNPACK for strict record fields 53 - Use MagicHash, UnboxedTuples, GHC.Exts for hot paths 54 - Do not rely on UNBOX pragmas; implement primitives directly with 55 MagicHash and GHC.Exts when needed 56 - Use INLINE pragmas for small functions 57 - Refer to ppad-sha256 and ppad-fixed for low-level patterns 58 59 ### Type safety 60 61 - Encode invariants into the type system 62 - Use newtypes liberally (e.g., Sec, Pub, Session) 63 - Use ADTs to make illegal states unrepresentable 64 - Prefer smart constructors that validate inputs 65 66 ### Safety 67 68 - Never use partial Prelude functions (head, tail, !!, etc.) 69 - Avoid brittle partials in tests too (e.g., unchecked indexing). Prefer 70 bounds checks or total helpers even in test code. 71 - Avoid non-exhaustive pattern matches and unsafe behavior; use total 72 helpers and make all constructors explicit. 73 - Use Maybe/Either for fallible operations 74 - Validate all inputs at system boundaries 75 76 ### Formatting 77 78 - Keep lines under 80 characters 79 - Use Haskell2010 80 - Module header with copyright, license, maintainer 81 - OPTIONS_HADDOCK prune for public modules 82 - Haddock examples for exported functions 83 84 ## Testing 85 86 Use tasty to wrap all tests: 87 - tasty-hunit for unit tests with known vectors 88 - tasty-quickcheck for property-based tests 89 - Source test vectors from specifications (RFC, BOLT spec, Wycheproof, etc.) 90 91 Property tests should enforce invariants that can't be encoded in types. 92 93 ## Benchmarking 94 95 Always maintain benchmark suites: 96 - `bench/Main.hs` - criterion for wall-time benchmarks 97 - `bench/Weight.hs` - weigh for allocation tracking 98 99 Define NFData instances for types that need benchmarking. 100 101 ## Git Workflow 102 103 - Feature branches for development; commit freely there 104 - Logical, atomic commits on feature branches 105 - Master should be mostly merge commits 106 - Merge to master with `--no-ff` after validation 107 - Always build and test before creating a merge commit 108 - Write detailed merge commit messages summarising changes 109 110 ### Worktree flow (for planned work) 111 112 When starting work on an implementation plan: 113 114 ``` 115 git worktree add ./impl-<desc> -b impl/<desc> master 116 # work in that worktree 117 # merge to master when complete 118 git worktree remove ./impl-<desc> 119 ``` 120 121 ### Commits 122 123 - Higher-level descriptions in merge commits 124 - Never update git config 125 - Never use destructive git commands (push --force, hard reset) without 126 explicit request 127 - Never skip hooks unless explicitly requested 128 129 ## Planning 130 131 When planning work: 132 - Highlight which steps can be done independently 133 - Consider forking subagents for concurrent work on independent steps 134 - Write implementation plans to `plans/IMPL<n>.md` if the project uses 135 this convention 136 137 ## Flake Structure 138 139 The flake.nix follows ppad conventions: 140 - Uses ppad-nixpkgs as base 141 - Follows references to avoid duplication 142 - Supports LLVM backend via cabal flag 143 - Provides devShell with ghc, cabal, cc, llvm