From 98c6fa4bfa897ff0b8f9c95ea698d4d065b5e9f3 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Tue, 18 Nov 2025 16:50:02 +0000 Subject: docs: switch focus onto grasp implementation --- ...25-11-05-grasp01-event-reference-test-design.md | 987 +++++++++++++++++++++ 1 file changed, 987 insertions(+) create mode 100644 docs/archive/2025-11-05-grasp01-event-reference-test-design.md (limited to 'docs/archive/2025-11-05-grasp01-event-reference-test-design.md') diff --git a/docs/archive/2025-11-05-grasp01-event-reference-test-design.md b/docs/archive/2025-11-05-grasp01-event-reference-test-design.md new file mode 100644 index 0000000..dd805b8 --- /dev/null +++ b/docs/archive/2025-11-05-grasp01-event-reference-test-design.md @@ -0,0 +1,987 @@ +# GRASP-01 Event Reference Validation Test Design + +**Version:** 1.0 +**Date:** 2025-11-05 +**Status:** Design Phase - Ready for Review + +## Executive Summary + +This document provides a comprehensive test design for GRASP-01 lines 7-9 compliance, covering event reference validation. The design reshapes existing test stubs to implement proper event relationship testing across all NIP-34 event types (issues, patches, PRs, comments, status updates, and text notes). + +## 1. Analysis Section + +### 1.1 NIP-34 Event Structures + +From `/persistent/dcdev/clones/nips/34.md`, we have these git-related event types: + +#### Repository Announcements (kind 30617) +```json +{ + "kind": 30617, + "tags": [ + ["d", ""], + ["a", "30617::"], + ["clone", "", ...], + ["relays", "", ...], + ["maintainers", "", ...] + ] +} +``` + +#### Patches (kind 1617) +```json +{ + "kind": 1617, + "tags": [ + ["a", "30617::"], + ["e", "", "", "reply"], // NIP-10 threading + ["p", ""], + ["r", ""] + ] +} +``` + +#### Pull Requests (kind 1618) +```json +{ + "kind": 1618, + "tags": [ + ["a", "30617::"], + ["e", ""], // Optional revision reference + ["p", ""], + ["c", ""] + ] +} +``` + +#### Issues (kind 1621) +```json +{ + "kind": 1621, + "tags": [ + ["a", "30617::"], + ["p", ""] + ] +} +``` + +#### Comments (kind 1111 - NIP-22) +```json +{ + "kind": 1111, + "tags": [ + ["E", ""], // Root scope (uppercase) + ["K", ""], + ["P", ""], + ["e", ""], // Parent (lowercase) + ["k", ""], + ["p", ""] + ] +} +``` + +### 1.2 GRASP-01 Lines 7-9 Requirements + +Based on test stub comments in [`grasp01_nostr_relay.rs:29-36`](grasp-audit/src/specs/grasp01_nostr_relay.rs:29-36): + +**Line 7-9 (inferred):** Events that **tag** OR **are tagged by** accepted repository announcements SHOULD be stored. + +This breaks down into three scenarios: + +1. **Events NOT referenced** by or referencing other events → SHOULD NOT be stored (orphans) +2. **Events referenced BY** an existing stored event → SHOULD be stored (forward reference) +3. **Events referencing** an existing stored event → SHOULD be stored (backward reference) + +### 1.3 Reference Tag Types and Semantics + +#### Standard Nostr Reference Tags + +| Tag | Purpose | Format | NIP | +|-----|---------|--------|-----| +| `e` | Event ID reference | `["e", "", "", "", ""]` | NIP-10 | +| `a` | Addressable event reference | `["a", "::", ""]` | NIP-01 | +| `p` | Pubkey reference | `["p", "", ""]` | NIP-01 | +| `q` | Quote reference | `["q", "", "", ""]` | NIP-10 | + +#### NIP-22 Comment Tags (Uppercase = Root, Lowercase = Parent) + +| Tag | Purpose | Format | +|-----|---------|--------| +| `E` | Root event ID | `["E", "", "", ""]` | +| `A` | Root addressable event | `["A", "::", ""]` | +| `K` | Root event kind | `["K", ""]` | +| `P` | Root author pubkey | `["P", "", ""]` | +| `e` | Parent event ID | `["e", "", "", ""]` | +| `k` | Parent event kind | `["k", ""]` | +| `p` | Parent author pubkey | `["p", "", ""]` | + +#### NIP-10 Threading Tags + +| Marker | Purpose | +|--------|---------| +| `root` | First event in thread | +| `reply` | Direct reply to parent | + +### 1.4 Event Type Coverage Requirements + +Tests must cover: + +- ✅ **Issues** (kind 1621) - referencing repos via `a` tag +- ✅ **Patches** (kind 1617) - referencing repos via `a` tag, threading via `e` tags +- ✅ **Pull Requests** (kind 1618) - referencing repos via `a` tag +- ✅ **Comments** (kind 1111) - replying via NIP-22 structure +- ✅ **Status updates** (kinds 1630-1633) - referencing issues/PRs via `e` tag (may also use `E` tag for root references) +- ✅ **Text notes** (kind 1) - may reference announcements/issues/patches/comments OR be referenced by them + +## 2. Test Architecture Design + +### 2.1 Overall Test Suite Structure + +To manage the growing number of tests, we'll organize them into separate test module files: + +``` +grasp-audit/src/specs/ +├── mod.rs (module declarations) +├── grasp01_nostr_relay.rs (main entry point, existing tests) +└── grasp01/ + ├── mod.rs (test suite registration) + ├── helpers.rs (shared helper functions) + ├── issues.rs (issue reference tests) + ├── patches.rs (patch reference tests) + ├── pull_requests.rs (PR reference tests) + ├── comments.rs (NIP-22 comment tests) + ├── status_updates.rs (status change tests) + └── text_notes.rs (kind 1 reference tests) +``` + +**Benefits:** +- Better code organization and navigation +- Isolated test contexts +- Easier to maintain and extend +- Clear separation of concerns + +### 2.2 Test Organization Strategy + +**Group by relationship type:** + +1. **Forward References** - Event A exists, send Event B that references A +2. **Backward References** - Send Event A that references B, then send B +3. **Bidirectional** - Events that both reference each other +4. **Orphans** - Events with no references (should be rejected) +5. **Transitive** - Multi-hop references (A → B → C) + +**Group by event type:** + +1. Issues referencing repos +2. Patches referencing repos (with threading) +3. PRs referencing repos +4. Comments replying to issues/patches/PRs +5. Status updates for issues/PRs +6. Text notes being tagged by repos + +## 3. Helper Function Specifications + +### 3.1 Core Event Creation Helpers + +```rust +/// Create a NIP-34 issue event +async fn create_issue( + client: &AuditClient, + repo_announcement: &Event, + subject: &str, + content: &str, +) -> Result +``` + +**Purpose:** Create properly formatted issue (kind 1621) with `a` tag to repo +**Returns:** Signed event ready to send +**Usage:** +```rust +let issue = create_issue(&client, &repo_event, "Bug: Test", "Description").await?; +``` + +--- + +```rust +/// Create a NIP-34 patch event +async fn create_patch( + client: &AuditClient, + repo_announcement: &Event, + parent_patch: Option<&Event>, + patch_content: &str, +) -> Result +``` + +**Purpose:** Create patch (kind 1617) with optional NIP-10 threading +**Returns:** Signed event with proper `a` tag and optional `e` reply tag +**Usage:** +```rust +// First patch in series +let patch1 = create_patch(&client, &repo, None, "diff...").await?; + +// Reply patch +let patch2 = create_patch(&client, &repo, Some(&patch1), "diff...").await?; +``` + +--- + +```rust +/// Create a NIP-34 pull request event +async fn create_pull_request( + client: &AuditClient, + repo_announcement: &Event, + branch_name: &str, + commit_id: &str, +) -> Result +``` + +**Purpose:** Create PR (kind 1618) with proper repo reference +**Returns:** Signed event with `a` tag +**Usage:** +```rust +let pr = create_pull_request(&client, &repo, "feature-x", "abc123").await?; +``` + +--- + +```rust +/// Create a NIP-22 comment event +async fn create_comment( + client: &AuditClient, + root_event: &Event, // The root (issue, patch, or PR) + parent_event: Option<&Event>, // None for top-level, Some for replies + content: &str, +) -> Result +``` + +**Purpose:** Create comment (kind 1111) with proper NIP-22 tags +**Returns:** Signed event with E/K/P (root) and e/k/p (parent) tags +**Usage:** +```rust +// Top-level comment +let comment1 = create_comment(&client, &issue, None, "Great idea!").await?; + +// Reply to comment +let comment2 = create_comment(&client, &issue, Some(&comment1), "Thanks!").await?; +``` + +--- + +```rust +/// Create a status event +async fn create_status( + client: &AuditClient, + target_event: &Event, // Issue, patch, or PR + status_kind: Kind, // 1630 (Open), 1631 (Resolved), 1632 (Closed), 1633 (Draft) + reason: &str, +) -> Result +``` + +**Purpose:** Create status change event +**Returns:** Signed event with `e` tag to target +**Usage:** +```rust +let status = create_status(&client, &issue, Kind::Custom(1631), "Fixed in v1.0").await?; +``` + +### 3.2 Test Orchestration Helpers + +```rust +/// Send event and verify acceptance by querying back +async fn send_and_verify_stored( + client: &AuditClient, + event: Event, +) -> Result<()> +``` + +**Purpose:** Send event, wait for propagation, query to confirm storage +**Reduces:** Duplication of send → wait → query → verify pattern +**Usage:** +```rust +send_and_verify_stored(&client, issue_event).await?; +``` + +--- + +```rust +/// Send event and verify it was NOT stored (rejection test) +async fn send_and_verify_rejected( + client: &AuditClient, + event: Event, +) -> Result<()> +``` + +**Purpose:** Send event, verify it's not in relay storage +**Reduces:** Duplication in negative tests +**Usage:** +```rust +send_and_verify_rejected(&client, orphan_event).await?; +``` + +--- + +```rust +/// Extract repo identifier from announcement event +fn extract_repo_id(repo_announcement: &Event) -> Result +``` + +**Purpose:** Get `d` tag value from repo announcement +**Reduces:** Tag parsing duplication +**Usage:** +```rust +let repo_id = extract_repo_id(&repo_event)?; +``` + +--- + +```rust +/// Build addressable event tag (a tag) for repo +fn build_repo_atag(repo_announcement: &Event) -> Result +``` + +**Purpose:** Create properly formatted `a` tag for repo reference +**Reduces:** Tag construction errors +**Usage:** +```rust +let a_tag = build_repo_atag(&repo_announcement)?; +``` + +## 4. Test Case Specifications + +### 4.1 Issues Referencing Repositories + +#### Test: `test_accept_issue_for_repo` +**Validates:** GRASP-01 lines 8-9 - Accept issues referencing accepted repos +**Reference Tags:** `a` tag (repo) +**Expected:** Issue event SHOULD be stored + +**Setup:** +1. Create and send kind 30617 repo announcement +2. Verify repo is stored +3. Create kind 1621 issue with: + - `["a", "30617:{pubkey}:{d-tag}"]` + - `["subject", "Bug: Something broken"]` +4. Send issue event + +**Verification:** +- Query for kind 1621 with author filter +- Verify issue event was stored +- Verify `a` tag correctly references repo + +--- + +#### Test: `test_reject_issue_for_nonexistent_repo` +**Validates:** GRASP-01 line 7 - Reject orphaned issues +**Reference Tags:** `a` tag (nonexistent repo) +**Expected:** Issue event SHOULD NOT be stored + +**Setup:** +1. Create kind 1621 issue with `a` tag referencing non-existent repo +2. Send issue event + +**Verification:** +- Query for issue event +- Verify it was NOT stored (empty result) + +### 4.2 Patches Referencing Repositories + +#### Test: `test_accept_patch_for_repo` +**Validates:** GRASP-01 lines 8-9 - Accept patches for accepted repos +**Reference Tags:** `a` tag (repo), `p` tag, `r` tag +**Expected:** Patch event SHOULD be stored + +**Setup:** +1. Create and send repo announcement +2. Create kind 1617 patch with: + - `["a", "30617:{pubkey}:{d-tag}"]` + - `["p", "{repo-owner}"]` + - `["r", "{commit-id}"]` + - `["t", "root"]` (first patch marker) +3. Send patch + +**Verification:** +- Query for kind 1617 +- Verify patch stored +-Verify proper repo reference + +--- + +#### Test: `test_accept_patch_series_threading` +**Validates:** NIP-10 threading in patches +**Reference Tags:** `e` reply tag for threading +**Expected:** All patches in series SHOULD be stored + +**Setup:** +1. Send repo announcement +2. Create and send patch 1 with `["t", "root"]` +3. Create patch 2 with `["e", "{patch1-id}", "", "reply"]` +4. Create patch 3 with `["e", "{patch2-id}", "", "reply"]` +5. Send patches 2 and 3 + +**Verification:** +- Query all 3 patches +- Verify threading structure via `e` tags +- Verify all stored + +### 4.3 Pull Requests Referencing Repositories + +#### Test: `test_accept_pull_request_for_repo` +**Validates:** GRASP-01 lines 8-9 - Accept PRs for accepted repos +**Reference Tags:** `a` tag, `c` tag (commit) +**Expected:** PR event SHOULD be stored + +**Setup:** +1. Send repo announcement +2. Create kind 1618 PR with: + - `["a", "30617:{pubkey}:{d-tag}"]` + - `["c", "{commit-id}"]` + - `["subject", "Add feature X"]` +3. Send PR + +**Verification:** +- Query kind 1618 +- Verify PR stored with correct repo reference + +--- + +#### Test: `test_accept_pr_update` +**Validates:** PR updates (kind 1619) reference original PR +**Reference Tags:** `E` tag (NIP-22 root), `P` tag +**Expected:** PR update SHOULD be stored + +**Setup:** +1. Create and send repo + original PR +2. Create kind 1619 update with: + - `["E", "{pr-event-id}"]` + - `["P", "{pr-author}"]` + - `["c", "{new-commit-id}"]` +3. Send update + +**Verification:** +- Query kind 1619 +- Verify update references original PR + +### 4.4 Comments (NIP-22) + +#### Test: `test_accept_reply_to_issue` +**Validates:** Comments on issues using NIP-22 +**Reference Tags:** `E`, `K`, `P` (root), `e`, `k`, `p` (parent) +**Expected:** Comment SHOULD be stored + +**Setup:** +1. Send repo + issue +2. Create kind 1111 comment with: + - `["E", "{issue-id}"]` (root) + - `["K", "1621"]` (issue kind) + - `["P", "{issue-author}"]` + - `["e", "{issue-id}"]` (parent, same as root for top-level) + - `["k", "1621"]` + - `["p", "{issue-author}"]` +3. Send comment + +**Verification:** +- Query kind 1111 +- Verify proper NIP-22 tag structure + +--- + +#### Test: `test_accept_nested_comment_thread` +**Validates:** Multi-level comment threading +**Reference Tags:** E/K/P (constant root), e/k/p (changing parent) +**Expected:** All comments SHOULD be stored + +**Setup:** +1. Send repo + issue +2. Send comment 1 (to issue) +3. Send comment 2 (reply to comment 1): + - Root tags point to issue + - Parent tags point to comment 1 +4. Send comment 3 (reply to comment 2): + - Root tags still point to issue + - Parent tags point to comment 2 + +**Verification:** +- Query all 3 comments +- Verify root tags always reference issue +- Verify parent tags form chain + +--- + +#### Test: `test_accept_comment_on_patch` +**Validates:** Comments work on patches +**Reference Tags:** NIP-22 tags for kind 1617 +**Expected:** Comment on patch SHOULD be stored + +**Setup:** +1. Send repo + patch +2. Send kind 1111 comment referencing patch +3. Verify stored + +--- + +#### Test: `test_accept_comment_on_pr` +**Validates:** Comments work on PRs +**Reference Tags:** NIP-22 tags for kind 1618 +**Expected:** Comment on PR SHOULD be stored + +### 4.5 Status Updates + +#### Test: `test_accept_status_for_issue` +**Validates:** Status changes for issues +**Reference Tags:** `e` tag, `p` tag +**Expected:** Status event SHOULD be stored + +**Setup:** +1. Send repo + issue +2. Create kind 1631 (Resolved) status with: + - `["e", "{issue-id}", "", "root"]` + - `["p", "{issue-author}"]` + - `["a", "30617:{pubkey}:{repo-id}"]` (optional) +3. Send status + +**Verification:** +- Query kind 1631 +- Verify references issue + +### 4.6 Text Notes and Cross-References + +#### Test: `test_accept_kind1_quoted_by_issue` +**Validates:** Kind 1 text notes referenced by issues using `q` tag +**Reference Tags:** Issue's `q` tag pointing to kind 1 note +**Expected:** Kind 1 note SHOULD be accepted when issue quotes it + +**Setup:** +1. Create kind 1 text note about project +2. Send text note (may initially be rejected) +3. Send repo announcement +4. Create kind 1621 issue with: + - `["a", "30617:{pubkey}:{d-tag}"]` (repo reference) + - `["q", "{note-id}"]` (quote reference to kind 1) + - `["subject", "Discussion: Feature Request"]` +5. Send issue +6. Re-query for text note + +**Verification:** +- Text note should now be stored +- Verifies kind 1 being referenced by issue scenario + +## 5. Implementation Phases + +### Phase 1: Module Structure Setup (Priority: HIGH) +**Goal:** Create new test suite file structure +**Duration:** 0.5 days + +**Tasks:** +1. Create `grasp-audit/src/specs/grasp01/` directory +2. Set up module files: + - `mod.rs` (test registration) + - `helpers.rs` (shared functions) + - `issues.rs` + - `patches.rs` + - `pull_requests.rs` + - `comments.rs` + - `status_updates.rs` + - `text_notes.rs` +3. Update `grasp-audit/src/specs/mod.rs` to include new module + +**Acceptance Criteria:** +- Module structure compiles +- Tests can be run from new location +- No duplicate code + +### Phase 2: Helper Functions (Priority: HIGH) +**Goal:** Core helper functions in `helpers.rs` +**Duration:** 1 day + +**Tasks:** +1. Implement core event creation helpers: + - `create_issue()` + - `create_patch()` + - `create_pull_request()` + - `create_comment()` + - `create_status()` + +2. Implement test orchestration helpers: + - `send_and_verify_stored()` + - `send_and_verify_rejected()` + - `extract_repo_id()` + - `build_repo_atag()` + +**Acceptance Criteria:** +- All helper functions documented +- Unit tests for helpers +- Functions follow nostr-sdk 0.43 API + +### Phase 3: Core Event Type Tests (Priority: HIGH) +**Goal:** Implement tests for issues, patches, PRs +**Duration:** 1.5 days + +**Tasks:** +1. Implement in `issues.rs`: + - `test_accept_issue_for_repo` + - `test_reject_issue_for_nonexistent_repo` + +2. Implement in `patches.rs`: + - `test_accept_patch_for_repo` + - `test_accept_patch_series_threading` + +3. Implement in `pull_requests.rs`: + - `test_accept_pull_request_for_repo` + - `test_accept_pr_update` + +**Acceptance Criteria:** +- All tests pass against ngit-relay +- Proper event tagging +- Clear test documentation + +### Phase 4: Comment Threading (Priority: HIGH) +**Goal:** NIP-22 comment support in `comments.rs` +**Duration:** 1 day + +**Tasks:** +1. Implement comment tests: + - `test_accept_reply_to_issue` + - `test_accept_nested_comment_thread` + - `test_accept_comment_on_patch` + - `test_accept_comment_on_pr` + +**Acceptance Criteria:** +- Multi-level threading works +- Uppercase/lowercase tag handling correct +- All comment tests pass + +### Phase 5: Status Updates and Text Notes (Priority: MEDIUM) +**Goal:** Complete remaining event types +**Duration:** 1 day + +**Tasks:** +1. Implement in `status_updates.rs`: + - `test_accept_status_for_issue` + +2. Implement in `text_notes.rs`: + - `test_accept_kind1_quoted_by_issue` + +**Acceptance Criteria:** +- Status updates work correctly +- Kind 1 quote references validated +- All tests documented + +### Phase 6: Documentation and Finalization (Priority: HIGH) +**Goal:** Complete documentation and code review +**Duration:** 0.5 days + +**Tasks:** +1. Add comprehensive doc comments to all modules +2. Create migration guide from old structure +3. Update main README with new structure +4. Code review and refactoring +5. Run full test suite verification + +**Acceptance Criteria:** +- All modules documented +- Clear organization +- No compiler warnings +- All tests pass + +## 6. Edge Cases and Considerations + +### 6.1 Potential Edge Cases + +1. **Event Arrival Order:** + - Issue arrives before repo announcement + - Comment arrives before target event + - **Mitigation:** Test both orders, document relay behavior + +2. **Reference Ambiguity:** + - Multiple `a` tags to different repos + - Conflicting `e` tags + - **Mitigation:** Document which reference takes precedence + +3. **Deleted Events:** + - Event references something that gets deleted + - **Mitigation:** Test and document behavior + +4. **Malformed Tags:** + - Invalid `a` tag format + - Missing required tag components + - **Mitigation:** Test rejection with clear errors + +5. **Threading Depth:** + - Very deep reply chains (100+ levels) + - **Mitigation:** Set reasonable limits, test performance + +6. **Circular References:** + - A references B, B references A + - **Mitigation:** Prevent infinite loops, document handling + +### 6.2 Performance Considerations + +1. **Query Efficiency:** + - Use specific filters (kind + author) + - Avoid full relay scans + - Timeout after 5 seconds + +2. **Event Batching:** + - Send multiple events efficiently + - Wait between sends (100ms) for propagation + +3. **Cleanup:** + - All events have audit tags for cleanup + - Use `run_id` for isolation + +### 6.3 Test Isolation Requirements + +1. **Unique Identifiers:** + - Use UUIDs for repo IDs + - Avoid collisions between test runs + +2. **Audit Tags:** + - Automatic via `AuditClient::event_builder()` + - Enable production cleanup + +3. **Relay State:** + - Assume shared relay (ngit-relay) + - Don't depend on empty state + +## 7. Implementation Guidelines + +### 7.1 Code Style + +Follow existing patterns in [`grasp01_nostr_relay.rs`](grasp-audit/src/specs/grasp01_nostr_relay.rs): + +```rust +/// Test: +/// +/// Spec: Line X of ../grasp/01.md +/// Requirement: +async fn test_name(client: &AuditClient) -> TestResult { + TestResult::new( + "test_name", + "GRASP-01:nostr-relay:X", + "Human-readable requirement description", + ) + .run(|| async { + // Test implementation + Ok(()) + }) + .await +} +``` + +### 7.2 nostr-sdk 0.43 API Usage + +**Field Access (NOT method calls):** +```rust +event.id // ✅ Correct +event.tags // ✅ Correct +event.tags.iter() // ✅ Correct + +event.id() // ❌ Wrong (0.35 API) +``` + +**Tag Construction:** +```rust +Tag::custom(TagKind::custom("a"), vec!["30617:pubkey:repo-id"]) // ✅ +Tag::identifier("repo-id") // ✅ +Tag::from_standardized(TagStandard::PublicKey { ... }) // ✅ +``` + +**Event Building:** +```rust +client.event_builder(kind, content) + .tag(tag1) + .tag(tag2) + .build(client.keys())? +``` + +### 7.3 Test Naming Convention + +Pattern: `test_{action}_{subject}_{condition}` + +Examples: +- `test_accept_issue_for_repo` (positive) +- `test_reject_orphan_issue` (negative) +- `test_accept_nested_comment_thread` (complex) + +### 7.4 Error Handling + +```rust +.run(|| async { + // Create events + let repo = client.create_repo_announcement("test").await + .map_err(|e| format!("Failed to create repo: {}", e))?; + + // Send events + client.send_event(repo.clone()).await + .map_err(|e| format!("Failed to send to relay: {}", e))?; + + // Verify results + let events = client.query(filter).await + .map_err(|e| format!("Failed to query: {}", e))?; + + if events.is_empty() { + return Err("Event not stored".to_string()); + } + + Ok(()) +}) +``` + +## 8. Test Data Patterns + +### 8.1 Sample Event IDs +Use realistic hex event IDs: +```rust +"abc123def456789012345678901234567890abcd" // 40 hex characters +``` + +### 8.2 Sample Pubkeys +Use proper npub format: +```rust +client.public_key().to_bech32()? // Real key from client +``` + +### 8.3 Sample Repo IDs +Use test name + UUID: +```rust +format!("test-{}-{}", test_name, Timestamp::now().as_u64()) +``` + +## 9. Acceptance Criteria + +### 9.1 Code Quality + +- ✅ All functions have doc comments +- ✅ No compiler warnings +- ✅ Follows existing code patterns +- ✅ Uses nostr-sdk 0.43 API correctly +- ✅ Proper error messages + +### 9.2 Test Coverage + +- ✅ All 7 test stubs implemented +- ✅ All NIP-34 event types covered +- ✅ All reference tag types tested +- ✅ Both positive and negative cases +- ✅ Edge cases documented + +### 9.3 Passing Tests + +- ✅ All tests pass against ngit-relay +- ✅ Tests properly isolated +- ✅ No flaky tests +- ✅ Clear failure messages + +## 10. References + +- **NIP-34:** `/persistent/dcdev/clones/nips/34.md` (Git Stuff) +- **NIP-10:** `/persistent/dcdev/clones/nips/10.md` (Threading) +- **NIP-22:** `/persistent/dcdev/clones/nips/22.md` (Comments) +- **Current Implementation:** [`grasp01_nostr_relay.rs:29-36`](grasp-audit/src/specs/grasp01_nostr_relay.rs:29-36) +- **Client Helpers:** [`client.rs:193-235`](grasp-audit/src/client.rs:193-235) +- **AGENTS.md:** Code patterns and testing guidelines + +## 11. Next Steps + +1. **Review this design document with user** +2. **Get approval or iterate on design** +3. **Switch to Code mode for implementation** +4. **Implement Phase 1 (Foundation)** +5. **Test against ngit-relay** +6. **Iterate through remaining phases** + +## Appendix A: Test Flow Diagram + +``` +Event Reference Testing Flow +============================ + +┌─────────────────────────────────────────────────┐ +│ Setup: Create Repo Announcement │ +│ - Send kind 30617 with clone/relays tags │ +│ - Verify acceptance and storage │ +└────────────────┬────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────┐ +│ Test 1: Issues (kind 1621) │ +│ ┌─────────────────────────────────────────────┐│ +│ │ → Create issue with 'a' tag to repo ││ +│ │ → Send to relay ││ +│ │ → Query back ││ +│ │ → Verify stored ││ +│ └─────────────────────────────────────────────┘│ +└────────────────┬────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────┐ +│ Test 2: Patches (kind 1617) │ +│ ┌─────────────────────────────────────────────┐│ +│ │ → Create patch with 'a' tag to repo ││ +│ │ → Optionally thread with 'e' tag ││ +│ │ → Send and verify ││ +│ └─────────────────────────────────────────────┘│ +└────────────────┬────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────┐ +│ Test 3: Pull Requests (kind 1618) │ +│ ┌─────────────────────────────────────────────┐│ +│ │ → Create PR with 'a' tag and 'c' commit ││ +│ │ → Send and verify ││ +│ └─────────────────────────────────────────────┘│ +└────────────────┬────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────┐ +│ Test 4: Comments (kind 1111 - NIP-22) │ +│ ┌─────────────────────────────────────────────┐│ +│ │ Top-level: ││ +│ │ E/K/P → Issue ││ +│ │ e/k/p → Issue (same as root) ││ +│ │ Nested: ││ +│ │ E/K/P → Issue (unchanged) ││ +│ │ e/k/p → Parent Comment ││ +│ └─────────────────────────────────────────────┘│ +└────────────────┬────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────┐ +│ Test 5: Status Updates (kinds 1630-1633) │ +│ ┌─────────────────────────────────────────────┐│ +│ │ → Create status with 'e' tag to issue/PR ││ +│ │ → Test state transitions ││ +│ └─────────────────────────────────────────────┘│ +└────────────────┬────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────┐ +│ Test 6: Negative Cases │ +│ ┌─────────────────────────────────────────────┐│ +│ │ → Orphan events (no references) ││ +│ │ → Invalid references ││ +│ │ → Verify rejection ││ +│ └──────────────────────────── ────────────────┘│ +└─────────────────────────────────────────────────┘ +``` + +## Appendix B: Helper Function Dependency Graph + +``` +Helper Functions +================ + +create_repo_announcement() (exists in AuditClient) + │ + ├─→ extract_repo_id() + └─→ build_repo_atag() + │ + ├─→ create_issue() + ├─→ create_patch() + ├─→ create_pull_request() + ├─→ create_comment() + └─→ create_status() + │ + ├─→ send_and_verify_stored() + └─→ send_and_verify_rejected() +``` -- cgit v1.2.3