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