Captures the verified current behavior (author-keyed DeletionIndex, no
wrap→rumor cascade, accidental seal-id blocking) and the agreed design:
recipient special case in hasBeenDeleted, recipient field on HostStub,
and the reverse-lookup live cascade in LocalCache.
https://claude.ai/code/session_01B39MQmrT3dz137nfpXABvo
Catalogs every Nostr kind the RUNSTR app publishes/consumes, the exact
1301 tag dialect, the Supabase-migration caveats, and a phased plan for
Quartz event classes and Amethyst fitness screens.
https://claude.ai/code/session_01Kpx53UEeJqqR7CASzMu6GB
Append a 'Final implementation state' section to the CLINK plan capturing
what shipped across Phases 0-3 + the receive side + CLI, the audit findings
and their fixes, the three-level verification matrix, and the critical
spec-vs-SDK gotchas (offer 'latest' at GFY code 3 and ndebit k1 at TLV-3 are
spec-defined and must not be removed). Flip the doc status to implemented.
https://claude.ai/code/session_01NM2TyJtosLdY5ycjyabSRS
Plan to implement CLINK (Offers 21001 / Debits 21002 / Manage 21003) on
Quartz (client + server) and Amethyst (consume-only), reusing NIP-44,
bech32/TLV, the NWC encrypted-event pattern, and ZapPaymentHandler.
Pointers parsed by a dedicated ClinkPointerParser (separate from NIP-19).
Two correctness bugs in `RemoteSignerManager` (NIP-46) and its NIP-55
sibling `IntentRequestManager`:
1. **Double-resume crash** — `awaitingRequests.get(id)?.resume(value)`
was non-atomic. Multi-relay delivery, bunker echo/retry, and
late-after-timeout responses could call `resume` twice for the same
continuation, throwing `IllegalStateException: Already resumed` on a
`Dispatchers.Default` worker.
2. **Retry id-reuse → wrong data** (NIP-46 only) —
`launchWaitAndParse` built the request and event once, then re-used
the same `request.id` across retry attempts. A late response from
attempt N could resume attempt N+1's continuation with stale data.
Replace the cached-`Continuation` map with the in-house Channel-per-request
correlation pattern already used in `quartz/.../accessories/NostrClientPublishExt.kt`
(`LargeCache<id, Channel<Response>(capacity=1)>` + atomic `remove` +
`trySend` + `withTimeoutOrNull { receive() }`). Each retry attempt now
builds a fresh request with a new id; the builder is still called only
once. `finally`-block cleanup removes the cache entry on every path,
incidentally fixing a slow leak on the success path.
Adds three regression tests:
- duplicate responses → no crash + single resume (fails on \`main\`
with \`IllegalStateException\`)
- late response after timeout → silently discarded
- late attempt-1 response does not corrupt attempt-2 result (fails on
\`main\`: the two attempts share an id)
Design + review notes: \`quartz/plans/2026-06-03-fix-nip46-bunker-double-resume-plan.md\`
Reframe from a forward-looking plan diff to the current architecture, and fix
the onAuthenticated signature to (event): Boolean (pubKey was dropped). All
structural elements already matched the merged code.
nostr-protocol/nips#2332 adds optional ["block", …] and ["proof", …] tags
on kind:8333 that ship the SPV proof inline. The data-model side is already
shipped in Quartz (BlockTag, ProofTag, OnchainZapEvent.block()/.proof() and
the TagArray helpers), but no production code path produces or consumes
either tag yet.
amethyst/plans/2026-05-14-onchain-zaps.md — onchain zaps plan:
- Update the "Chain backend" decision bullet to flag the spec change and
the two production gaps (send-side emit, receive-side consume).
- Add a dedicated "Inline SPV proofs" section covering: spec status and
the merkle-proof encoding ambiguity flagged back to the PR; per-layer
status matrix (shipped vs gap, with file locations); send-side
two-publish design (Design B — keep instant receipt, add post-confirm
republish with block+proof; dedupe by (txid, target)); receive-side
fast-path with fall-through on proof failure (never hard-reject);
phased delivery G.1–G.7 with effort estimates (~3–4 d after S1 ships
and spec encoding lands).
- Add the two new pending items to the existing "What's still pending"
list to keep that section authoritative.
quartz/plans/2026-05-08-local-headers-explorer.md — headers-explorer plan:
- Rewrite §19 (follow-up onchain-zap verification) to reflect the spec
change. Original section assumed we'd need BIP-37 merkleblock or
full-block fetch over P2P; with the proof inline none of that
infrastructure is required. Estimate collapses from 10–15 d to ~3–4 d.
- Point §19 at the full implementation plan in the onchain-zaps file,
keeping S1 focused on OTS while the follow-up details live with the
rest of the NIP-BC work.
Every consensus-relevant layer of the planned headers explorer (BlockHeader80
parser, DifficultyTarget compact↔target, CalculateNextWorkRequired retarget,
MedianTimePast, header validator end-to-end, P2P wire codecs, reorg/chain
selection, OTS proofs) is pinned to upstream test vectors committed under
quartz/src/commonTest/resources/bitcoin/, matching the existing
nip44.vectors.json / bip39.vectors.json / mls/*.json pattern.
The single highest-value test is a nightly differential check asserting
LocalHeadersBitcoinExplorer.blockHash(h) == OkHttpBitcoinExplorer.blockHash(h)
for every height in [checkpoint, tip] — any consensus drift surfaces as a
disagreeing height.
Maps cleanly onto the existing Phase 1/3/4/5/7/9 work, adding ~5–7
engineer-days total to the plan budget. No new top-level phase needed.
Lock the design choices from the 2026-05-19 review against the intervening
2026-05-14 onchain-zaps work:
- Move the module from quartz/.../nip03Timestamp/bitcoin/ to a sibling
quartz/.../bitcoin/ package so the headers explorer, header validator,
peer pool and store can be reused by the future onchain-zap merkle-proof
work without an inverted import path.
- Use androidx.sqlite + BundledSQLiteDriver for HeaderStore, matching the
existing SQLiteEventStore. Schema lives in commonMain via IModule. Drops
the hand-rolled flat-file + sidecar height index.
- Drop the bundled headers blob. Ship a single hardcoded PinnedCheckpoint
constant; first-run sync starts from the checkpoint and pulls forward
over P2P. APK growth: 0 bytes.
- Pre-checkpoint OTS heights fall through to OkHttpBitcoinExplorer via
BitcoinExplorerEndpoint (shared with the onchain-zap EsploraBackend).
Strict-mode users get an explicit error instead of a network call.
- Mark trustless NIP-BC onchain-zap verification as out of scope and
capture it as a follow-up plan (BIP-37 merkleblock or full-block fetch
on top of this stack).
Resolves open questions Q1, Q2 and Q4 from the original plan; Q3 (Quartz
public API vs internal) left open for Phase 0.
Comprehensive design doc for a headers-only Bitcoin P2P client that would
let NIP-03 OTS attestations be verified locally against the proof-of-work
chain instead of a trusted block explorer. Parked pending direction on
NIP-BC onchain-zaps verification, which has overlapping requirements.