AGENTS.md (4072B)
1 # ppad-auditor 2 3 Haskell tool for static analysis of GHC aarch64 assembly with a focus 4 on constant-time memory access auditing. 5 6 ## Project Structure 7 8 - `lib/` - library source (parser, CFG, analysis) 9 - `app/` - CLI entrypoint 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-auditor.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) when helpful. 34 Current dependencies: aeson, bytestring, containers, megaparsec, text, 35 optparse-applicative. 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 - Current project deps: aeson, bytestring, containers, megaparsec, 45 optparse-applicative, text 46 - ppad-* libraries 47 - Test dependencies (tasty, QuickCheck, etc. for test-suite only) 48 - Benchmark dependencies (criterion, weigh for benchmark only) 49 50 ## Code Style 51 52 ### Performance 53 54 - Prefer strict data structures where it simplifies analysis 55 - Avoid unnecessary allocations in hot paths (parsing, dataflow) 56 57 ### Type safety 58 59 - Encode invariants into the type system 60 - Use newtypes liberally (e.g., Reg, Sym, Label) 61 - Use ADTs to make illegal states unrepresentable 62 - Prefer smart constructors that validate inputs 63 64 ### Safety 65 66 - Never use partial Prelude functions (head, tail, !!, etc.) 67 - Avoid brittle partials in tests too (e.g., unchecked indexing). Prefer 68 bounds checks or total helpers even in test code. 69 - Avoid non-exhaustive pattern matches and unsafe behavior; use total 70 helpers and make all constructors explicit. 71 - Use Maybe/Either for fallible operations 72 - Validate all inputs at system boundaries 73 74 ### Formatting 75 76 - Keep lines under 80 characters 77 - Use Haskell2010 78 - Module header with copyright, license, maintainer 79 - OPTIONS_HADDOCK prune for public modules 80 - Haddock examples for exported functions 81 82 ## Testing 83 84 Use tasty to wrap all tests: 85 - tasty-hunit for unit tests with known vectors 86 - tasty-quickcheck for property-based tests 87 - Source fixtures from real GHC aarch64 dumps and hand-crafted samples 88 89 Property tests should enforce invariants that can't be encoded in types. 90 91 ## Benchmarking 92 93 Always maintain benchmark suites: 94 - `bench/Main.hs` - criterion for wall-time benchmarks 95 - `bench/Weight.hs` - weigh for allocation tracking 96 97 Define NFData instances for types that need benchmarking. 98 99 ## Git Workflow 100 101 - Feature branches for development; commit freely there 102 - Logical, atomic commits on feature branches 103 - Master should be mostly merge commits 104 - Merge to master with `--no-ff` after validation 105 - Always build and test before creating a merge commit 106 - Write detailed merge commit messages summarising changes 107 108 ### Worktree flow (for planned work) 109 110 When starting work on an implementation plan: 111 112 ``` 113 git worktree add ./impl-<desc> -b impl/<desc> master 114 # work in that worktree 115 # merge to master when complete 116 git worktree remove ./impl-<desc> 117 ``` 118 119 ### Commits 120 121 - Higher-level descriptions in merge commits 122 - Never update git config 123 - Never use destructive git commands (push --force, hard reset) without 124 explicit request 125 - Never skip hooks unless explicitly requested 126 127 ## Planning 128 129 When planning work: 130 - Highlight which steps can be done independently 131 - Consider forking subagents for concurrent work on independent steps 132 - Write implementation plans to `plans/IMPL<n>.md` if the project uses 133 this convention 134 135 ## Flake Structure 136 137 The flake.nix follows ppad conventions: 138 - Uses ppad-nixpkgs as base 139 - Follows references to avoid duplication 140 - Supports LLVM backend via cabal flag 141 - Provides devShell with ghc, cabal, cc, llvm