Poindexter/CLAUDE.md

5 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Poindexter is a Go library providing:

  • Sorting utilities with custom comparators (ints, strings, floats, generic types)
  • KDTree for nearest-neighbor search with multiple distance metrics (Euclidean, Manhattan, Chebyshev, Cosine)
  • Helper functions for building normalized/weighted KD points (2D/3D/4D/ND)
  • DNS/RDAP tools for domain, IP, and ASN lookups
  • Analytics for tree operations and peer selection tracking

Build Commands

# Run all tests
make test

# Run tests with race detector
make race

# Run tests with coverage (writes coverage.out)
make cover

# Run a single test
go test -run TestFunctionName ./...

# Build all packages
make build

# Build with gonum optimized backend
go build -tags=gonum ./...

# Run tests with gonum backend
go test -tags=gonum ./...

# Build WebAssembly module
make wasm-build

# Run benchmarks (writes bench.txt)
make bench

# Run benchmarks for specific backend
make bench-linear     # Linear backend
make bench-gonum      # Gonum backend (requires -tags=gonum)

# Fuzz testing (default 10s)
make fuzz
make fuzz FUZZTIME=30s

# Lint and static analysis
make lint   # requires golangci-lint
make vuln   # requires govulncheck

# CI-parity local run
make ci

# Format code
make fmt

# Tidy modules
make tidy

Architecture

Core Components

kdtree.go - Main KDTree implementation:

  • KDTree[T] generic struct with payload type T
  • KDPoint[T] represents points with ID, Coords, and Value
  • Query methods: Nearest(), KNearest(), Radius()
  • Mutation methods: Insert(), DeleteByID()
  • Distance metrics implement DistanceMetric interface

Dual Backend System:

  • kdtree_gonum.go (build tag gonum) - Optimized median-split KD-tree with branch-and-bound pruning
  • kdtree_gonum_stub.go (default) - Stubs when gonum tag not set
  • Linear backend is always available; gonum backend is default when tag is enabled
  • Backend selected via WithBackend() option or defaults based on build tags

kdtree_helpers.go - Point construction utilities:

  • BuildND(), Build2D(), Build3D(), Build4D() - Build normalized/weighted KD points
  • ComputeNormStatsND() - Compute per-axis min/max for normalization
  • Supports axis inversion and per-axis weights

kdtree_analytics.go - Operational metrics:

  • TreeAnalytics - Query/insert/delete counts, timing stats
  • PeerAnalytics - Per-peer selection tracking for DHT/NAT routing
  • Distribution statistics and NAT routing metrics

sort.go - Sorting utilities:

  • Type-specific sorts: SortInts(), SortStrings(), SortFloat64s()
  • Generic sorts: SortBy(), SortByKey()
  • Binary search: BinarySearch(), BinarySearchStrings()

dns_tools.go - DNS and RDAP lookup utilities:

  • DNS record types and lookup functions
  • RDAP (modern WHOIS) for domains, IPs, ASNs
  • External tool link generators

Examples Directory

Runnable examples demonstrating KDTree usage patterns:

  • examples/dht_ping_1d/ - 1D DHT with ping latency
  • examples/kdtree_2d_ping_hop/ - 2D with ping + hop count
  • examples/kdtree_3d_ping_hop_geo/ - 3D with geographic distance
  • examples/kdtree_4d_ping_hop_geo_score/ - 4D with trust scores
  • examples/dht_helpers/ - Convenience wrappers for common DHT schemas
  • examples/wasm-browser-ts/ - TypeScript + Vite browser demo

WebAssembly

WASM module in wasm/main.go exposes KDTree functionality to JavaScript. Build outputs to dist/.

Key Patterns

KDTree Construction

pts := []poindexter.KDPoint[string]{
    {ID: "A", Coords: []float64{0, 0}, Value: "alpha"},
}
tree, err := poindexter.NewKDTree(pts,
    poindexter.WithMetric(poindexter.EuclideanDistance{}),
    poindexter.WithBackend(poindexter.BackendGonum))

Building Normalized Points

pts, err := poindexter.BuildND(items,
    func(p Peer) string { return p.ID },           // ID extractor
    []func(Peer) float64{getPing, getHops},        // Feature extractors
    []float64{1.0, 0.5},                           // Per-axis weights
    []bool{false, false})                          // Inversion flags

Distance Metrics

  • EuclideanDistance{} - L2 norm (default)
  • ManhattanDistance{} - L1 norm
  • ChebyshevDistance{} - L-infinity (max) norm
  • CosineDistance{} - 1 - cosine similarity
  • WeightedCosineDistance{Weights: []float64{...}} - Weighted cosine

Note: Cosine metrics use linear backend only; L2/L1/L-infinity work with gonum backend.

Testing

Tests are organized by component:

  • kdtree_test.go, kdtree_nd_test.go - Core KDTree tests
  • kdtree_gonum_test.go - Gonum backend specific tests
  • kdtree_backend_parity_test.go - Backend equivalence tests
  • fuzz_kdtree_test.go - Fuzz targets
  • bench_*.go - Benchmark suites

Coverage targets:

make cover           # Summary
make coverfunc       # Per-function breakdown
make cover-kdtree    # kdtree.go only
make coverhtml       # HTML report

License

EUPL-1.2 (European Union Public Licence v1.2)