From 96dfce0e48b2239c29a96dbf5a7c7d985aa2d0bd Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 16:18:34 +0000 Subject: [PATCH 1/4] chore: open auto-fix batch claude/friendly-maxwell-uPyR3 From d19de75b25ea036ab8f367274b6031136b23336b Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 16:24:30 +0000 Subject: [PATCH 2/4] fix(network): replace mem.rs neighbor catch-all with exhaustive variants GossipEvent grow new variant later: catch-all `_ =>` silently forward, self-id filter shape only cover NeighborUp/NeighborDown. explicit variant arm force compile error on future additions. iroh.rs already exhaustive at api::Event match (line 150-181), no change need. Refs #258 --- crates/network/src/mem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/network/src/mem.rs b/crates/network/src/mem.rs index ec7e29df..2c10a23f 100644 --- a/crates/network/src/mem.rs +++ b/crates/network/src/mem.rs @@ -277,7 +277,7 @@ impl TopicEvents for MemTopicEvents { // Filter out events about ourselves match &event { GossipEvent::NeighborUp(id) | GossipEvent::NeighborDown(id) if *id == self.id => continue, - _ => return Some(Ok(event)), + GossipEvent::Received(_) | GossipEvent::NeighborUp(_) | GossipEvent::NeighborDown(_) => return Some(Ok(event)), } } Err(broadcast::error::RecvError::Closed) => return None, From dad976572381ca6125f46f921d4e92da9b98c16f Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 16:28:39 +0000 Subject: [PATCH 3/4] docs(plans): add STATUS.md mapping UI plans to state-layer prereqs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit audit ARCH-07 flag spec/code drift: phase-2e plan reserve SearchScope::ThisLetter + ::AllLetters but no Letter EventKind in crates/state/src/event.rs. visibility fix only — single STATUS.md tabulate UI-phase plan + EventKind prereq + landed-state. snapshot, not live tracker; manual patch when plan ship. Refs #337 --- docs/plans/STATUS.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 docs/plans/STATUS.md diff --git a/docs/plans/STATUS.md b/docs/plans/STATUS.md new file mode 100644 index 00000000..f0a82f1e --- /dev/null +++ b/docs/plans/STATUS.md @@ -0,0 +1,33 @@ +# Phase-plan status + +At a glance, for each UI-design phase plan in `docs/plans/`, which state-layer prerequisites are already in `crates/state/src/event.rs` and which still need to land. + +**Rationale.** Per `docs/specs/2026-04-19-ui-design/README.md`, "Feature disparity between spec and client is expected and acceptable." This file makes that disparity legible without grepping across crates. It exists to answer one question quickly: when a plan reserves a wire type or `EventKind` variant that has not shipped, can a reader spot the gap before tracing it through the spec? The audit that prompted this file (issue #337, ARCH-07) flagged exactly that pattern: phase-2e reserves `SearchScope::ThisLetter` / `SearchScope::AllLetters` while the DAG has no `Letter` `EventKind`. + +**Maintenance.** This is a snapshot in time, not a live tracker. Updated by hand when plans land or new state primitives ship. If the table drifts from `crates/state/src/event.rs`, treat the source as canonical and patch the table. + +## Status table + +| Plan | UI scope | State-layer prereq | Landed? | Notes | +|------|----------|--------------------|---------|-------| +| [`2026-04-19-ui-phase-0-foundation.md`](2026-04-19-ui-phase-0-foundation.md) | Design tokens (palette, typography, motion) reskin | none — view layer only | yes | Pure CSS / token plumbing; no Rust state changes. | +| [`2026-04-20-ui-phase-1a-desktop-shell.md`](2026-04-20-ui-phase-1a-desktop-shell.md) | Desktop three-pane shell, grove rail, channel sidebar, right rail | none new — consumes existing `CreateChannel`, `ChannelKind`, members | yes | Plan explicitly defers ephemeral / archive / muted / per-grove-accent flags to later phases (covered by 2d / 1f). | +| [`2026-04-20-ui-phase-1b-mobile-shell.md`](2026-04-20-ui-phase-1b-mobile-shell.md) | Mobile shell — tab bar, top bar, grove drawer, bottom sheets | none — view layer only | yes | No new events; mounts on existing channel / member views. | +| [`2026-04-20-ui-phase-1c-palette-a11y.md`](2026-04-20-ui-phase-1c-palette-a11y.md) | Command palette, ARIA landmarks, keyboard close-stack | none — view layer only | yes | Local-search handoff is surface only; index ships in 2e. | +| [`2026-04-20-ui-phase-1d-trust-verification.md`](2026-04-20-ui-phase-1d-trust-verification.md) | SAS fingerprints, trust badges, compare-friend flow | none new — local-only per-device belief | yes | Plan §Architecture: "no new `EventKind`. Trust is local per-device." Shared-trust event explicitly out of scope. | +| [`2026-04-20-ui-phase-1e-presence.md`](2026-04-20-ui-phase-1e-presence.md) | 7-state presence, status dot, presence menu | none new — derived from network reachability + local override | yes | Plan §Architecture: "Presence is derived, not event-sourced in 1e." `PresenceHeartbeat` `EventKind` flagged as future work. | +| [`2026-04-20-ui-phase-1f-notifications.md`](2026-04-20-ui-phase-1f-notifications.md) | Toast stack, unread badges, OS push contract, per-surface mute | `MuteChannel` + `MuteGrove` `EventKind` | yes | Both variants present in `event.rs` (lines ~355, ~361). VAPID wire format + relay-side dispatch are out of scope. | +| [`2026-04-20-ui-phase-2a-message-row.md`](2026-04-20-ui-phase-2a-message-row.md) | Message row anatomy, mentions, code, day separators, jump-to-latest | uses existing `Message`, `EditMessage`, `DeleteMessage`, `PinMessage` | partial | Plan gates a `WhisperStart` placeholder behind always-false flag — `WhisperStart` `EventKind` is not in `event.rs`; whisper body styling deferred to `whisper-mode.md` (no plan yet). Quote-reply uses existing `Message.reply_to`. | +| [`2026-04-21-ui-phase-2b-sync-queue.md`](2026-04-21-ui-phase-2b-sync-queue.md) | Offline strip, queue pills, sync-queue screen, reconnection toast | none new — `ServerState` unchanged; `MessageStore::delivery_state` + relay status are local | partial | Plan §Architecture: "No new `EventKind`. Queue state is purely local / per-device." Peer-identity tombstone signal flagged as out of scope (deferred to `letters-dms.md`); inbound queue heartbeat extension is an open dep. | +| [`2026-04-21-ui-phase-2c-profile-card.md`](2026-04-21-ui-phase-2c-profile-card.md) | Profile popover / sheet, 17 fields, crest banner, nickname editor | `EventKind::UpdateProfile(Box)` + extended `Profile` fields (pronouns, bio, tagline, crest, pinned, elsewhere, since) | yes | `UpdateProfile` present (line ~322). Nickname store is local-only per spec — no event needed. | +| [`2026-04-21-ui-phase-2e-local-search.md`](2026-04-21-ui-phase-2e-local-search.md) | On-device search index, scope ladder, results surface, palette bridge | no new `EventKind`; `SearchScope::ThisLetter` + `SearchScope::AllLetters` reserved on the client side | partial | The two letter scopes have no backing `EventKind` — there is no `Letter` / DM variant in `event.rs`. Plan flags this with `TODO(letters-dms.md)` on letter-scope filter branches. The audit that prompted this status file (issue #337) called out exactly this drift. | +| [`2026-04-25-ui-phase-2d-ephemeral-channels.md`](2026-04-25-ui-phase-2d-ephemeral-channels.md) | Auto-archive on inactivity, archives surface, kind chip, revive | `CreateChannel.ephemeral: Option` + `EventKind::ChannelRevive { channel_id }` + `Channel.last_activity_hlc` | yes | Both present (lines ~250, ~263). Replaces the `_ephemeral-` name-prefix heuristic from 1a. | + +## Aggregate + +- **12 plans tabulated.** +- **9 yes** (state-layer prereqs all landed or none required). +- **3 partial** — 2a (whisper placeholder gate, no `WhisperStart`), 2b (peer tombstone + inbound heartbeat deferred), 2e (letter scopes reserved with no `Letter` `EventKind`). +- **0 no** — every plan has at least started landing in `crates/state/src/event.rs` or is intentionally view-layer-only. + +The recurring blocker across the partial rows is the absence of a `Letter` / DM family of `EventKind` variants. `letters-dms.md` is a spec but has no implementation plan yet; until one lands, plans 2a / 2b / 2e all carry forward-references that are correct but unbacked. From 0647319d952e7af79f53f295b1bb8c4a67d88afb Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 16:30:02 +0000 Subject: [PATCH 4/4] docs(skill): Monitor wait pattern + coordinator-files-rot escape hatch stop hook fire while implementer mid-cargo-gates: coordinator no commit (skill rule), need wait without poll. Monitor + until-loop on git head advance = one notification when commit land. coordinator do GH-API metadata work in mean time (file follow-up, draft PR body), no touch implementer file scope. implementer surface pre-existing rot it not fix in scope (e.g. unrelated wasm break under --all-features): coordinator file follow-up via mcp__github__issue_write. metadata work, allow under coordinator-never- codes rule. cite discovery context (which dispatch, which gate step) so next run have provenance. example this run: #258 implementer surface mem.rs --all-features wasm break, coordinator file as #502. Refs #337, #258 --- .claude/skills/resolving-issues/SKILL.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.claude/skills/resolving-issues/SKILL.md b/.claude/skills/resolving-issues/SKILL.md index a6d16629..11072f53 100644 --- a/.claude/skills/resolving-issues/SKILL.md +++ b/.claude/skills/resolving-issues/SKILL.md @@ -149,6 +149,19 @@ Never defer skill edits to a follow-up — they ship with the run that surfaced - Research subagents *inside* an implementer may run in parallel. - Cap = 10 issues per run. +### Waiting for implementer commits without polling +- Implementer agent runs in the background. Coordinator gets a notification when the agent's tool call completes — but the agent's *commit* may land seconds before that, and the harness's stop hook fires on uncommitted changes during cargo gates. +- **Don't sleep, don't poll, don't read the agent's output file.** The system explicitly blocks long sleeps and warns against reading sub-agent transcripts (context overflow). +- **Use `Monitor` with an `until` loop watching for HEAD to advance** past the prior known SHA. One notification fires when the loop exits; the coordinator stays idle in between. Pattern: + ```bash + cd /home/user/willow && until [ "$(git log -1 --format='%H')" != "" ]; do sleep 5; done; echo "agent committed: $(git log -1 --oneline)" + ``` + Set `timeout_ms` to ~5–10 minutes for typical implementer runs (longer for cross-crate gates). The coordinator can do GitHub-API metadata work (filing follow-up issues, drafting PR body) while waiting; just don't touch files in the implementer's scope. + +### Implementer-flagged out-of-scope rot +- When the implementer surfaces pre-existing rot it intentionally doesn't fix (e.g. unrelated wasm break under `--all-features`, dead-code warnings in untouched files), the coordinator files a follow-up GH issue using `mcp__github__issue_write` (metadata work, allowed under the Coordinator-never-codes rule). Cite the discovery context (which dispatch surfaced it, which commit + gate step) so the next run has full provenance. +- This is the same shape as the "implementer files follow-up" rule — coordinator just does the filing because the implementer is single-task and exits after commit. + ### Fresh agent per issue - New implementer each issue. No state leak. - Each implementer gets only its issue + master branch ref.