mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-10 16:33:27 +00:00
Relays that advertise NIP-77 in NIP-11 but refuse it at runtime answer a
NEG-OPEN with a connection-level NOTICE (which carries no subId) instead of a
subId-addressed NEG-ERR:
- strfry with negentropy disabled: "ERROR: bad msg: negentropy disabled"
- purplepag.es (no NEG envelope): "failed to parse envelope: unknown envelope label"
reconcileStreaming only routed NegMsg/NegErr for its exact subId into the driver
channel, so the NOTICE was dropped and the driver blocked in receiveWithinIdle
with no terminating frame. Worse, the connection-level idle watchdog was bumped
by every relay message, so unrelated refusal chatter (a rejected keep-alive REQ
being re-CLOSED on re-sync) reset it forever and it never fired. Net effect:
negentropySync/negentropyReconcile hung against relay.primal.net and
purplepag.es, and negentropySyncOrFetch never reached its paging fallback.
Fix, in reconcileStreaming's connection listener:
- route a CLOSED for our NEG subId into the driver as a terminal failure;
- treat a negentropy-refusal NOTICE as terminal, bound to this session by
phase (before the first valid NEG frame) + wording (isNegentropyRejectionNotice),
so an unrelated NOTICE on a healthy relay mid-reconcile cannot abort a
progressing sync;
- stop bumping the idle clock on NOTICE/CLOSED so refusal chatter can no longer
keep a dead sync alive; it now advances only on real progress (this session's
NEG frames and the download REQs' events/EOSEs).
The refusal now surfaces as NegentropySyncException(UNAVAILABLE); negentropySync
throws promptly and negentropySyncOrFetch pages the same filter (both relays
answer ordinary REQs fine). Verified live: primal 0-event hang -> pages 11.7k
events in 6.4s; purplepag.es 0-event hang -> pages continuously.
Tests:
- NegentropyRejectionFallbackTest: offline, deterministic; a scripted fake
relay answers NEG-OPEN with each observed NOTICE and asserts the sync throws
UNAVAILABLE fast and negentropySyncOrFetch sets pagedFallback.
- NegentropyStallRepro: gated live repro against the three real relays.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B6ZVTixuc1ef8eGB6MQHRn
quartz plans
Audited 2026-06-30. 11 plans: 7 shipped (archived), 0 in-progress, 3 queued, 1 closed (negative result).
Queued
| Plan | Summary |
|---|---|
| 2026-05-08-local-headers-explorer.md | Headers-only Bitcoin P2P client to verify NIP-03 OTS attestations without a trusted block explorer. |
| 2026-06-12-giftwrap-deletion-requests.md | Let a recipient-authored kind-5 delete/block a gift wrap (kind 1059) addressed to them. |
| 2026-07-03-incremental-negentropy-storage.md | Always-current (created_at, id) index so cold NEG-OPENs stop paying a full scan + seal (~340 ms at 50k vs strfry's ~21 ms). |
| 2026-07-04-small-req-floor.md | Small-REQ dispatch floor: decomposed, inline fast path tried and reverted (no wire-level win); floor is transport-side. |
Archived (shipped)
| Plan | Summary |
|---|---|
| archive/2026-06-03-fix-nip46-bunker-double-resume-plan.md | Fix NIP-46 bunker double-resume crash and retry id-reuse races via Channel-per-request + fresh id per attempt. |
| archive/2026-06-04-auth-scope-vs-policy.md | Move relay-server authenticated-identity state from the policy into the engine-owned connection scope. |
| archive/2026-06-09-clink.md | Implement CLINK (Offers/Debits/Manage) Lightning-over-Nostr pointers, events, and client/server in Quartz. |
| archive/2026-06-11-runstr-interop.md | RUNSTR kind-1301 workout events and supporting fitness kinds in Quartz plus Amethyst fitness screens. |
| archive/2026-06-19-napplet-nip5a-resolver.md | Platform-agnostic NIP-5A static-site resolver verifying content-addressed Blossom blobs against signed manifests. |
| archive/2026-06-20-powr-interop.md | Parse and render the POWR/NIP-101e kind-1301 strength-workout dialect alongside the existing RUNSTR dialect. |
| archive/2026-06-28-git-smart-http-browser.md | Git smart-HTTP v2 client to browse NIP-34 repo file trees and render source from the clone URL. |