Files
ngit-grasp/AGENTS.md
T

7.8 KiB

AGENTS.md

This file provides guidance to agents when working with code in this repository.

Project Structure

Workspace with Two Rust Projects:

  • Root: ngit-grasp (main GRASP relay implementation)
  • grasp-audit/: Separate subproject with own Cargo.toml and flake.nix

Cannot build grasp-audit from root - must cd grasp-audit first.

Build & Test

Nix Flakes (Non-Standard)

CRITICAL: Use nix develop, NOT nix-shell (we use flake.nix, not shell.nix)

# ✅ Correct
cd grasp-audit
nix develop -c cargo build
nix develop -c cargo test

# ❌ Wrong
nix-shell
nix-shell --run "cargo build"

Running Tests

Integration tests require relay running:

# Start ngit-relay first (use any available port to avoid conflicts)
docker run --rm -p 18081:8081 ghcr.io/danconwaydev/ngit-relay:latest

# From grasp-audit directory, set RELAY_URL to match your port
# Run all ignored tests (includes GRASP-01 and other relay-dependent tests)
RELAY_URL="ws://localhost:18081" nix develop -c cargo test --lib -- --ignored --nocapture

# Or run a specific test
RELAY_URL="ws://localhost:18081" nix develop -c cargo test --lib test_grasp01_nostr_relay_against_relay -- --ignored --nocapture

Tests marked #[ignore] need relay - unit tests don't.

Note: Always use a random available port for the relay to avoid conflicts with existing services.

Use test-ngit-relay.sh for automated relay management:

This script handles all relay lifecycle management automatically:

  • Starts ngit-relay in isolated Docker container
  • Uses random port to avoid conflicts
  • Creates isolated temporary directories
  • Ensures cleanup on exit (success or failure)
  • Supports both audit and test modes

Basic Usage:

# Run cargo test suite (recommended for GRASP-01 development)
cd grasp-audit && nix develop -c bash test-ngit-relay.sh --mode test

# Run audit CLI tool (for quick validation)
cd grasp-audit && nix develop -c bash test-ngit-relay.sh

# Get help
cd grasp-audit && ./test-ngit-relay.sh --help

Benefits:

  • No manual relay startup required
  • Automatic cleanup prevents leftover containers
  • Random port selection avoids conflicts
  • Consistent environment across all runs
  • Proper test isolation

Note: Manual relay setup is still available but test-ngit-relay.sh is recommended for development workflows.

Running Single Test

# From grasp-audit/
nix develop -c cargo test --lib specific_test_name -- --nocapture

Quick Test Verification

To verify GRASP-01 compliance tests are working correctly:

# Run all ignored library tests (includes GRASP-01)
cd grasp-audit && RELAY_URL="ws://localhost:18081" nix develop -c cargo test --lib -- --ignored --nocapture 2>&1 | tail -60

# Or run specific GRASP-01 test
cd grasp-audit && RELAY_URL="ws://localhost:18081" nix develop -c cargo test --lib test_grasp01_nostr_relay_against_relay -- --ignored --nocapture 2>&1 | tail -60

Expected Output:

  • 2-3 tests passing
  • 15+ tests showing "Not implemented yet"

Troubleshooting

Buffer Size Errors: If you see mpsc channel buffer size panics on first test run, this is usually transient. Simply run the tests again.

Verify Relay is Running: Check if relay is accessible before running tests:

nak req -l 1 ws://localhost:18081  # Replace port with your chosen port

Port Conflicts: Always use a random available port to avoid conflicts with existing services. If a port is busy, choose a different one for docker.

Code Patterns

nostr-sdk 0.43 Breaking Changes (vs 0.35)

Field access, not method calls:

// ❌ WRONG (0.35 API)
event.id()
event.tags()
for tag in &event.tags { }

// ✅ CORRECT (0.43 API)
event.id          // Direct field access
event.tags        // Direct field access
event.tags.iter() // Iterator method

Tag API changed:

// ❌ WRONG (0.35)
Tag::Generic(TagKind::Custom("clone".into()), vec![...])

// ✅ CORRECT (0.43)
Tag::custom(TagKind::custom("clone"), vec![...])

EventBuilder signature changed:

// ❌ WRONG (0.35)
EventBuilder::new(kind, content, &[tags])

// ✅ CORRECT (0.43)
EventBuilder::new(kind, content).tags(tags)

See docs/archive/2025-11-04-nostr-sdk-upgrade.md for full migration.

Audit Event Tagging (grasp-audit)

All audit events automatically include cleanup tags:

The grasp-audit system automatically adds three tags to every event for production cleanup and test isolation. These tags are added transparently via AuditEventBuilder::build() with 100% coverage through AuditClient::event_builder().

Automatic Tags (no manual intervention needed):

// These tags are automatically added to EVERY audit event:
["t", "grasp-audit-test-event"]              // Identifies all audit test events
["t", "audit-{run_id}"]                      // Unique ID for this audit run (correlates events)
["t", "audit-cleanup-after-{unix_timestamp}"] // Unix timestamp for cleanup scheduling

Tag Format Details:

  • Uses standard NIP-01 "t" (hashtag) tags for maximum compatibility
  • Unix timestamps (not ISO 8601) for easier database queries
  • All tags added automatically when calling client.event_builder().build()
  • No manual tag management required

Verifying Tags in Tests:

// Test that verifies automatic tag addition:
// See: grasp-audit/src/client.rs:273-302
#[test]
fn test_audit_tags_automatically_added() {
    // Creates event and verifies all three tags are present
}

Testing Implications:

  • All audit events are tagged for easy cleanup
  • Use run_id tag to correlate events from same audit run
  • Tags enable production relay cleanup scripts
  • No special handling needed in test code - tags are automatic

Documentation

Diátaxis Framework Used:

  • docs/tutorials/ - Learning-oriented
  • docs/how-to/ - Task-oriented
  • docs/reference/ - Information-oriented
  • docs/explanation/ - Understanding-oriented

Session files go in work/ (gitignored except README.md)

  • Archive valuable content to docs/archive/YYYY-MM-DD-*.md at session end
  • Delete temporary files
  • Keep root clean (only README.md, AGENTS.md)

Critical Gotchas

  1. Workspace compilation: Can't cargo build from root for grasp-audit
  2. Nix environment: Must use nix develop, not nix-shell
  3. nostr-sdk API: Fields not methods in 0.43
  4. Test isolation: Integration tests need relay, marked with #[ignore]
  5. Work directory: All session docs go in work/, NOT root
  6. Archive naming: Use YYYY-MM-DD-description.md format
  7. Use test-ngit-relay.sh: Always use the test script for GRASP-01 tests - it handles cleanup and port management automatically

File Restrictions by Mode

Code mode can only edit files matching specific patterns (enforced by system):

  • Example: Architect mode restricted to \.md$ files only
  • Attempting to edit restricted files causes FileRestrictionError
  • Check mode configuration if edit attempts fail unexpectedly

Quick Reference

# Recommended: Use test-ngit-relay.sh for all testing
cd grasp-audit && nix develop -c bash test-ngit-relay.sh --mode test

# Build grasp-audit
cd grasp-audit && nix develop -c cargo build

# Manual relay testing (if needed)
# 1. Start relay: docker run --rm -p 18081:8081 ghcr.io/danconwaydev/ngit-relay:latest
# 2. Run all ignored tests: RELAY_URL="ws://localhost:18081" nix develop -c cargo test --lib -- --ignored --nocapture
# 3. Or specific test: RELAY_URL="ws://localhost:18081" nix develop -c cargo test --lib test_grasp01_nostr_relay_against_relay -- --ignored --nocapture

# Run single test
cd grasp-audit && nix develop -c cargo test --lib test_name -- --nocapture

# Check session files
ls work/  # Should only have README.md when clean