wokhei 0.3.0

Agent-first CLI for creating and publishing Decentralized List events on Nostr
# Protocol

This document defines the protocol baseline for Wokhei and explains how the implementation follows it.

## Standards in Scope

1. **NIP-01 (Basic protocol flow)**
   - Source: https://raw.githubusercontent.com/nostr-protocol/nips/master/01.md
2. **Decentralized Lists custom NIP** (the NostrHub reference provided in this repo context)
   - NostrHub naddr: https://nostrhub.io/naddr1qvzqqqrcvypzpef89h53f0fsza2ugwdc3e54nfpun5nxfqclpy79r6w8nxsk5yp0qy2hwumn8ghj7un9d3shjtnyd968gmewwp6kyqqnv3jkxetww3exzmrf0fjkgttvd9ehgucxgd7rv
   - Source mirror used by this project: https://raw.githubusercontent.com/wds4/brainstorm-knowledge-graph/main/docs/nips/decentralizedLists.md

---

## 1) NIP-01 Requirements Used by Wokhei

Wokhei relies on NIP-01 foundations:

- **Event model**: events have `id`, `pubkey`, `created_at`, `kind`, `tags`, `content`, `sig`.
- **Cryptographic signing**: event signing follows the Nostr event model through `nostr-sdk`.
- **Kind semantics**:
  - Regular events: used here for `9998` (header) and `9999` (item)
  - Addressable events: used here for `39998` (header) and `39999` (item), keyed by `(kind, pubkey, d-tag)`
- **Relay protocol**: WebSocket publish/query behavior is handled through `nostr-sdk` client operations (`send_event_builder`, `fetch_events`) which map to NIP-01 EVENT/REQ flows.
- **Tag conventions**: Wokhei uses NIP-01-compatible tag arrays and coordinate forms (notably `a`-style coordinate format in `z` for addressable parents: `39998:<pubkey>:<d-tag>`).

---

## 2) Decentralized Lists Requirements Used by Wokhei

From the Decentralized Lists spec:

- **Header declarations** use kind `9998` or `39998`.
- **Item declarations** use kind `9999` or `39999`.
- Header must include `names` (singular + plural).
- Addressable header (`39998`) must include `d`.
- Items must include `z` pointing to the parent list:
  - `z=<header-event-id>` for regular header (`9998`)
  - `z=39998:<pubkey>:<d-tag>` for addressable header (`39998`)
- Addressable items (`39999`) must include `d`.

---

## 3) How Wokhei Implements These Standards

### Header creation

`wokhei create-header` maps directly to list-header declarations:

- Chooses kind `9998` or `39998` via `--addressable`
- Requires `--d-tag` when addressable
- Emits protocol tags including `names`, optional `titles`, `description`, `required`, `recommended`, topic tags (`t`), `alt`, and `client`
- Returns `coordinate` for addressable headers so follow-up item commands can use stable parent addressing

Implementation references:
- `src/header.rs`
- `src/main.rs` (`create-header` command surface)

### Item creation

`wokhei add-item` maps directly to list-item declarations:

- Chooses kind `9999` or `39999` via `--addressable`
- Requires `--d-tag` when item is addressable (`39999`)
- Always derives and emits `z` parent pointer automatically
- Supports parent resolution by either:
  - `--header=<event-id>`
  - `--header-coordinate=39998:<pubkey>:<d-tag>`
- Emits `r` resource tag and optional custom field tags (`key=value` -> custom tag)

Implementation references:
- `src/item.rs`
- `src/main.rs` (`add-item` command surface)

### Coordinate and parent-pointer correctness

Wokhei normalizes and validates coordinates to prevent malformed parent references:

- Validates `kind:pubkey:d-tag` format
- Enforces `39998` for coordinate mode
- Canonicalizes coordinate output to `39998:<normalized-pubkey>:<d-tag>`
- Uses the resolved parent reference as the `z` tag value for item retrieval and linking

Implementation references:
- `src/item.rs` (`parse_coordinate_str`, `resolve_header_ref`)
- `src/query.rs` (`normalize_coordinate_ref`, `z_ref_for_header_event`)

### Query behavior for list membership

`wokhei list-items` follows the spec by fetching item events through `z` linkage:

- Queries only kinds `9999` and `39999`
- Filters by `#z=<parent-ref>` so membership is derived from the protocol-defined parent pointer

Implementation reference:
- `src/query.rs` (`fetch_items_by_z`)

### Raw protocol publishing

`wokhei publish` supports direct raw event publishing from JSON while still using signed relay publication flow.

Implementation reference:
- `src/publish.rs`

---

## 4) Mermaid Diagrams

### A. Decentralized Lists data model and lifecycle

```mermaid
flowchart LR
    A[List author] --> B[Create header\nkind 9998 or 39998]
    B --> C{Addressable?}
    C -->|No| D[z uses header event_id]
    C -->|Yes| E[Header has d-tag\ncoordinate 39998:pubkey:d]

    F[Contributor] --> G[Create item\nkind 9999 or 39999]
    G --> H[Item has z tag]
    H --> D
    H --> E

    I[Relay stores events] --> J[Consumers query #z]
    J --> K[List membership emerges from z linkage]
```

### B. How Wokhei executes protocol flow

```mermaid
sequenceDiagram
    participant U as User
    participant W as wokhei CLI
    participant R as Relay

    U->>W: create-header [--addressable --d-tag?]
    W->>W: Build NIP-compatible tags
    W->>R: EVENT(header 9998/39998)
    R-->>W: OK + event id

    U->>W: add-item --header or --header-coordinate
    W->>W: Resolve parent z ref
    W->>R: EVENT(item 9999/39999 with z)
    R-->>W: OK + event id

    U->>W: list-items <header> or --header-coordinate
    W->>R: REQ kinds[9999,39999] + #z[parent-ref]
    R-->>W: EVENT stream + EOSE
    W-->>U: JSON result + next_actions
```

---

## 5) Practical Protocol Contract for Wokhei Users

When using Wokhei, treat these as hard rules:

1. Use `39998/39999` + `d-tag` when you need updatable identity.
2. Use `9998/9999` for immutable event-id-based records.
3. For all item events, `z` is the parent link of record.
4. Prefer coordinate parents (`39998:<pubkey>:<d-tag>`) when cross-relay or long-lived references matter.
5. Keep downstream tooling keyed by the same protocol primitives (`kind`, `pubkey`, `d`, `z`).