From 1a8a4012a6297ec3ab8000699751c434486d6ad8 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Jul 2026 21:44:26 +0000 Subject: [PATCH] docs(cli): audit graperank docs against code; simplify the --help block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audited every graperank verb/flag in the code against the three doc surfaces and fixed the drift: - Main.kt `--help`: rewrote the GrapeRank block to match the terse house style (one line per command, key flags on continuation lines) — it had grown to ~68 lines of prose. Now ~33 lines, reordered into pipeline order (crawl -> score -> publish, then rank/status/refresh, then the provider/operator discovery group), with the per-verb timeout-semantics prose dropped (it lives in the KDoc). Verbs and primary flags verified against the dispatch and each function's arg reads. - README: added the missing `graperank crawl` and `graperank score` rows (stage 1 and 2 of the pipeline — crawl had no table row at all, score was only mentioned inline) and labelled the three pipeline stages. No stale references remain (no `graperank sync`, no removed publish/ bench flags, `operator providers`/`update` only as documented aliases). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_013WSzVX9RoUxyV3nT3dfc56 --- cli/README.md | 6 +- .../com/vitorpamplona/amethyst/cli/Main.kt | 98 ++++++------------- 2 files changed, 36 insertions(+), 68 deletions(-) diff --git a/cli/README.md b/cli/README.md index 1350cd478b..925c456afc 100644 --- a/cli/README.md +++ b/cli/README.md @@ -389,8 +389,10 @@ HTTP endpoint. Reuses quartz's `Nip86Client` and the shared `Nip86Retriever` | `amy profile show [USER]` | Print kind:0 metadata. USER accepts npub/nprofile/hex/NIP-05; defaults to self. | | `amy profile edit --name … --about … --picture URL …` | Patch and re-publish your kind:0. | | `amy follow USER` / `amy unfollow USER` | Add/remove USER from your kind:3 contact list (fetches the freshest list first). | -| `amy graperank [OBSERVER] [--offline] [--min-rank N]` | Compute GrapeRank web-of-trust scores (0..1) over the follow/mute/report graph. Exhaustively crawls each user's kind:10002 outbox for their latest kind:3/10000/1984 until every discovered user is checked (no user cap), dropping reports the author retracted via NIP-09. **Every score run persists its result locally**: the ranks (cutoff `--min-rank`, default 2) are reconciled into the shared store as NIP-85 kind:30382 cards signed by a per-observer **service key** — changed ranks re-signed, unchanged skipped (no event-id churn), dropped targets retracted (kind:5). `graperank score` is the local-only variant (same as `--offline`). | -| `amy graperank publish [OBSERVER] [--relay URL[,URL…]]` | Transport only: make the operator relay(s) converge to the locally persisted card set — one NIP-77 up-only reconcile per relay over the service key's kind:30382 + kind:5 (nothing is re-scored or re-signed; a relay that can't reconcile gets the full set published instead). Also refreshes the observer's kind:10040 pointer when we hold their key. | +| `amy graperank [OBSERVER] [--offline] [--min-rank N]` | Crawl + score: compute GrapeRank web-of-trust scores (0..1) over the follow/mute/report graph, then persist the result. Exhaustively crawls each user's kind:10002 outbox for their latest kind:3/10000/1984 until every discovered user is checked (no user cap), dropping reports the author retracted via NIP-09. **Every score run persists its result locally**: the ranks (cutoff `--min-rank`, default 2) are reconciled into the shared store as NIP-85 kind:30382 cards signed by a per-observer **service key** — changed ranks re-signed, unchanged skipped (no event-id churn), dropped targets retracted (kind:5). `--offline` skips the crawl. | +| `amy graperank crawl [OBSERVER] [--max-hops N] [--no-preconnect]` | Pipeline stage 1 — network only: crawl the follow/mute/report graph (kind 3/10000/1984/10002) into the local store, no scoring. Idempotent and cumulative: run it a few times to load everything, then `score`. | +| `amy graperank score [OBSERVER]` | Pipeline stage 2 — local only: score from the store and persist the cards (identical to bare `--offline`; same scoring flags). No network, so re-run with different `--rigor`/`--attenuation`/`--min-rank` without re-crawling. | +| `amy graperank publish [OBSERVER] [--relay URL[,URL…]]` | Pipeline stage 3 — transport only: make the operator relay(s) converge to the locally persisted card set — one NIP-77 up-only reconcile per relay over the service key's kind:30382 + kind:5 (nothing is re-scored or re-signed; a relay that can't reconcile gets the full set published instead). Also refreshes the observer's kind:10040 pointer when we hold their key. | | `amy graperank rank USER [--provider PUBKEY] [--refresh]` | The consumer side: read the kind:30382 cards about USER — one rank per provider, newest card each. Local store first; `--refresh` (or a miss) drains the operator relays, the relays your kind:10040 declares, and the bootstrap set. | | `amy graperank refresh [--down] [--up]` | Refresh every locally-known author's WoT record kinds (0/3/10002/1984) from their own outbox: one NIP-77 negentropy reconcile per write relay scoped to its authors, so the next `score` runs on current data without a full re-crawl. (`update` is the pre-rename alias.) | | `amy graperank status` | Read-only local inventory, no network, no signing: WoT record counts in the store (the "do I need to crawl again?" answer), reachability-cache size + age, operator/service-key state, and the persisted card + retraction counts per observer. | diff --git a/cli/src/main/kotlin/com/vitorpamplona/amethyst/cli/Main.kt b/cli/src/main/kotlin/com/vitorpamplona/amethyst/cli/Main.kt index cf5f6d2e4e..a3bfeb8f28 100644 --- a/cli/src/main/kotlin/com/vitorpamplona/amethyst/cli/Main.kt +++ b/cli/src/main/kotlin/com/vitorpamplona/amethyst/cli/Main.kt @@ -612,72 +612,38 @@ private fun printUsage() { | (USER: npub|nprofile|hex|name@domain) | |Web of Trust (GrapeRank): - | graperank [OBSERVER] compute subjective trust scores (0..1) for every - | [--limit N] [--min-score X] user reachable in the follow/mute/report graph. - | [--rigor X] [--attenuation X] Exhaustively crawls each user's kind:10002 outbox - | [--max-rounds N] [--max-hops N] for their latest kind:3/10000/1984 until every - | [--offline] [--timeout SECS] discovered user has been checked (no user cap; - | [--diagnose] [--min-rank N] --timeout: per-REQ drain, default 10s; - | --max-hops bounds follow distance, e.g. 8; - | --diagnose dumps per-relay telemetry: outcome - | mix, yield, latency, and a LIVE/DEAD + limits - | classification table of every relay contacted). - | OBSERVER: npub|nprofile|hex|name@domain (default: - | active account). --offline scores from the local - | store only. EVERY score run persists its result - | locally as NIP-85 kind:30382 cards signed by a - | per-observer service key (ranks >= --min-rank, - | default 2): changed ranks re-signed, unchanged - | skipped, dropped targets retracted (kind:5). - | `graperank publish` pushes that set to relays. - | graperank score [OBSERVER] local only: build the graph from the store and - | score (same as bare --offline; same flags). Fast - | and param-tunable without re-crawling. - | graperank publish [OBSERVER] transport only: make the operator relay(s) match - | [--relay URL[,URL…]] [--timeout SECS] the local card set via one NIP-77 up-only - | [--relay-concurrency N] reconcile per relay (nothing re-scored or - | re-signed; full-set publish fallback when a relay - | can't reconcile). Also refreshes the observer's - | kind:10040 pointer when we hold their key. - | --timeout: idle watchdog per relay, default 30s. - | graperank rank USER [--provider PUBKEY] read the kind:30382 cards about USER — one rank - | [--refresh] [--timeout SECS] per provider, local store first, --refresh drains - | the operator/declared/bootstrap relays - | (--timeout: drain, default 8s). - | graperank status read-only local inventory, no network: WoT record - | counts (do I need to crawl again?), reachability - | cache size + age, operator state, and the - | persisted card set per observer. - | graperank crawl [OBSERVER] network only: crawl the WoT graph (kind 3/10000/ - | [--max-hops N] [--preconnect-cap N] 1984/10002) into the local store without scoring. - | [--no-preconnect] Pre-connects every known-live relay in one parallel - | storm (seeded from the reachability cache). - | graperank probe alias for `relay probe` (the census moved there — - | it feeds the shared NIP-66 reachability cache). - | graperank refresh [--down] [--up] refresh every locally-known author's WoT record kinds - | [--no-sync-deletions] [--timeout SECS] (0/3/10002/1984) from their own outbox: reads all - | [--relay-concurrency N] [--author-chunk N] kind:10002 in the store, groups authors by write - | [--min-authors N] [--report-limit N] relay, and runs one NIP-77 negentropy reconcile per - | relay scoped to its authors. Bidirectional by default; - | the deletion settle downloads the relay's kind:5 when - | an uploaded record was rejected (author retracted it). - | Falls back to a full paged download when a relay - | can't reconcile via negentropy. (`update` is the - | pre-rename alias; --timeout: idle watchdog per - | relay, default 30s.) - | graperank operator [status|relay … manage the machine's operator keys (~/.amy/operator/, - | |keys] independent of accounts): relay sets where cards + - | retractions publish; status shows master + relays; - | keys lists observer -> service-pubkey. - | graperank register [PROVIDER] declare a NIP-85 provider in your kind:10040 so - | [--service KIND:TAG] [--relay URL] clients can discover it (default: self as the - | [--private] 30382:rank provider at your first outbox relay). - | graperank unregister PROVIDER remove matching provider entries (public + private) - | [--service KIND:TAG] [--relay URL] from your kind:10040 and re-publish it; --service/ - | --relay narrow the match, else every entry for - | that provider key is dropped. - | graperank providers [USER] [--refresh] list a user's declared NIP-85 trusted providers - | [--timeout SECS] (default: active account). + | graperank [OBSERVER] crawl + score: subjective trust (0..1) over the + | [--min-rank N] [--offline] follow/mute/report graph, then persist the result + | [--limit N] [--min-score X] as local NIP-85 kind:30382 cards (ranks >= + | [--rigor X] [--attenuation X] --min-rank, default 2). --offline skips the crawl. + | [--max-hops N] [--diagnose] OBSERVER: npub|nprofile|hex|name@domain (self). + | graperank crawl [OBSERVER] network only: crawl the graph (kind 3/10000/1984/ + | [--max-hops N] [--max-rounds N] 10002) into the local store, no scoring. + | [--no-preconnect] [--preconnect-cap N] Idempotent — run a few times to load everything. + | graperank score [OBSERVER] local only: score from the store + persist cards + | (= bare --offline; same flags). No network. + | graperank publish [OBSERVER] push local cards to the operator relay(s) via a + | [--relay URL[,URL…]] [--timeout SECS] NIP-77 up-sync (nothing re-scored), and refresh + | [--relay-concurrency N] the observer's kind:10040 when we hold their key. + | graperank rank USER [--provider PUBKEY] read the kind:30382 cards about USER, one rank per + | [--refresh] [--timeout SECS] provider; --refresh drains relays on a miss. + | graperank status read-only local inventory: record counts, cache + | freshness, operator state, cards per observer. + | graperank refresh [--down] [--up] re-sync known authors' records (kind 0/3/10002/ + | [--relay-concurrency N] [--author-chunk N] 1984) from their outboxes via NIP-77, so score + | [--min-authors N] [--report-limit N] runs on current data. (`update` is the alias.) + | [--no-sync-deletions] [--timeout SECS] + | graperank register [PROVIDER] declare a NIP-85 provider in your kind:10040 + | [--service KIND:TAG] [--relay URL] (default: self as 30382:rank at your 1st outbox). + | [--private] + | graperank unregister PROVIDER remove matching entries from your kind:10040; + | [--service KIND:TAG] [--relay URL] --service/--relay narrow, else all for that key. + | graperank providers [USER] [--refresh] list a user's declared NIP-85 providers. + | [--timeout SECS] + | graperank operator operator keys (~/.amy/operator/): `relay URL…` + | [status | relay URL… | keys] sets the publish target; `keys` maps observer + | -> service-key. (default: status) + | graperank probe alias for `relay probe` (the relay census). | |Zaps (NIP-57): | zap user USER SATS build a profile zap-request, fetch a BOLT11