Skip to content

feat(e2e): relay-backed add_reaction so a headless click publishes a real kind-7 - #146

Merged
oscarlehuu merged 6 commits into
mainfrom
devin/issue-133-relay-add-reaction
Aug 12, 2026
Merged

feat(e2e): relay-backed add_reaction so a headless click publishes a real kind-7#146
oscarlehuu merged 6 commits into
mainfrom
devin/issue-133-relay-add-reaction

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Aug 11, 2026

Copy link
Copy Markdown

Summary

The desktop e2e bridge's add_reaction was mock-only, so relay mode could not make a headless click publish anything: handleAddReaction looked the target up in the mock store and synthesized a kind-7. Only the transports (plugin:websocket|*) branched on relay mode. That is why #121's owner Accept/Reject had to be proven in two halves (desktop click on the mock bridge, kind-7 on the relay via the buzz CLI) with no single run covering click → relay.

Mutating handlers now follow the convention the message/channel handlers already use — branch on getIdentity(config) (non-null only in relay mode), publish via submitSignedEvent, and skip mock-store bookkeeping because the real WebSocket subscription supplies the echo:

// handleAddReaction
const tags = [["e", args.eventId], ...(args.emojiUrl ? [["emoji", shortcode, args.emojiUrl]] : [])];
if (identity) return submitSignedEvent(config, { kind: KIND_REACTION, content: emoji, tags });
// …existing mock path unchanged

Each relay branch mirrors its Rust command exactly — add_reaction → kind 7 with only the target e tag (events.rs::build_reaction), remove_reaction → relay-query the caller's own kind-7 then kind 5 on the reaction id (build_remove_reaction), delete_message → kind 5 with h+e (build_delete_compat), set_canvas → kind 40100 with h (build_set_canvas). No reaction semantics, kinds, or evidence tags change — D-036 stands.

The audit is the real payload. docs/crew/verification/0011-e2e-bridge-relay-mutation-audit.md classifies every mutating bridge command: (a) already relay-aware, (b) mock-only in relay mode — the trap, where a spec passes while never reaching the relay, (c) legitimately local-only. The four cheap (b) cases above are fixed here; the four that need real design (send_managed_agent_channel_message needs an agent signing identity, send_channel_user_input_answer, update_persona_and_publish, archive_identity/unarchive_identity) are filed as #144 with evidence. Class-(c) rows inferred only from the bridge side (workflows, save subscriptions/archive_events) are marked unconfirmed from the Rust side rather than asserted, and #144 tracks confirming them.

New decision D-042 (slot assigned by the orchestrator; D-028…D-039 are taken by in-flight PRs) records the rule: a mutating bridge command with a real Nostr event behind it publishes in relay mode, and one that cannot must be listed in 0011 with its reason.

Basing: branched off devin/1786360062-evidence-thread-log (PR #128, issue #121) because the evidence cards and verification record 0010 live there and are not on main yet. Targets main, so this diff carries #128's commits until #128 lands.

Related issue

Closes #133. Depends on #128 (#121). Files #144 for the remaining mock-only mutations. Verification record for the gap this closes: docs/crew/verification/0010-evidence-on-thread-log-probes.md (its split-probe limitation now points at the closing evidence).

Testing

New headless spec desktop/tests/e2e/evidence-reactions-relay.spec.ts (integration project — the relay-backed lane; smoke has no relay). In one run it publishes an evidence-tagged kind-9 to a real local relay, clicks evidence-accept, then polls POST /query for the resulting event and asserts kind 7 / owner pubkey / content / e tag on the evidence id — then the same for evidence-reject with , plus the reply composer still opening.

Running 1 test using 1 worker
  ✓  1 [integration] › tests/e2e/evidence-reactions-relay.spec.ts:88:1 › owner Accept and Reject publish real relay reactions (1.8s)
  1 passed (3.2s)

Mock-path regression set (evidence-reactions, evidence-cards, reaction-order, reaction-names, inbox-reactions, custom-emoji, empty-edit-delete, --project=smoke): 28 passed, 1 failedinbox-reactions.spec.ts:36 ("Toggle ❤️ reaction" not visible). Verified preexisting: it fails identically in a clean worktree at the base commit df2a9995e, output in record 0011. pnpm --filter buzz check and typecheck clean.

Known limit, stated in 0011 rather than papered over: the agent-ownership metadata for the card is still injected via bridge config (mock.searchProfiles) — publishing an owner-authenticated kind-0 for the test identities needs plumbing the headless harness lacks. The evidence message and the entire reaction path are real relay state, so the claim supported is "a headless click publishes a real kind-7 to a real relay", not agent-profile provenance.

No computer-use anywhere in the verification path (per #121).

Where this evidence stops — no CI lane, deliberately: the integration project (all 17 relay-backed specs, of which this is the only Crew-specific one) runs only in the inherited ci.yml, which Crew disabled on purpose as part of the CI minimisation (docs/crew/CI.md: "Upstream Sync does not run the inherited integration or cross-platform matrices"). The lane is upstream-owned (block/buzz a1c28f487d, still active upstream) and costs 2 ubuntu-latest shards at ~6m45s/~6m17s (run 30533242569) needing Postgres + Redis + MinIO, a built buzz-relay, schema + community seed, setup-desktop-test-data.sh and a Playwright install. The active workflow's Project Relay job provisions its own stack inside its script and jobs don't share services, so a Crew lane means duplicating all of that — not a small addition, so it stays with #147 (which also owns the required-vs-advisory call; D-032's posture argues advisory). Record 0011 carries the numbers and exact local-run commands so the spec is runnable without rediscovering any of it.

remove_reaction's relay branch throws could not find your reaction event for this emoji on no match, matching the Rust command rather than diverging silently; the mock path's preexisting silent no-op is untouched.

Desktop Smoke E2E shards 1/3 red: six of the failures reproduce on clean-main (run 31362178966, shard 1), inbox-reactions.spec.ts:36 reproduces on the base commit, and channels.spec.ts:1951 / :2108 reproduce on PR #128's parent df2a9995e — inherited from the base branch, not from this diff. Per-test baseline with job URLs is in 0011. The required NuncioCrew Gate is green.

Link to Devin session: https://app.devin.ai/sessions/bae615c82bdc4b5bb116dcf221f47d4c
Requested by: @oscarlehuu

@oscarlehuu oscarlehuu self-assigned this Aug 11, 2026
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

devin-ai-integration Bot and others added 6 commits August 11, 2026 15:05
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…an main

Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/issue-133-relay-add-reaction branch from 306f7ca to b13eb59 Compare August 11, 2026 15:05
@oscarlehuu
oscarlehuu merged commit f53e4ad into main Aug 12, 2026
9 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

e2e bridge: relay-backed add_reaction so a headless click can be proven end to end

1 participant