auto-fix batch claude/friendly-maxwell-iEXwu 2026-05-04#599
Merged
Conversation
Per audit F13 (#580). All three workflow files now declare an explicit minimum-scope GITHUB_TOKEN permission block at the top level. Deploy upload steps use sshpass + DEPLOY_PASSWORD over SSH/SCP, not GITHUB_TOKEN, so no per-job elevation is needed. Defense-in-depth: even if the repo default ever flips to a wider scope, these workflows stay read-only. Skipped cargo gate per skill rule's verified-no-asserter exception: no Rust integration test reads workflow YAML (crates/web/tests/static_assets.rs only greps index.html). YAML round-trip via python's yaml.safe_load + the audit's own grep confirm the three new permissions: blocks parse cleanly. Refs #580
Per audit F38 (#538). The state-management spec's decision table proposed Rc<RefCell<>> as the canonical WASM single-threaded interior-mut pattern, but state_bridge.rs:31 intentionally uses Arc<Mutex<Option<U>>> for the actor-handler dedup cache (the willow-actor framework requires Send, so Rc is structurally unavailable). The lock is documented in-place at state_bridge.rs:23-30 with a pointer to spec § F2 follow-up. Spec was missing the matching exception row, leaving readers to reconstruct the rationale from comment + F2 alone. Add: - one row in the proposed CLAUDE.md-addition table covering "Web actor-handler dedup cache (deferred to F2)"; - one cross-link sentence at the end of § F2 back to the new row, so the table -> comment -> follow-up chain is closed. No code change; F2 redesign remains the documented next step. Skipped cargo gate per skill rule's verified-no-asserter exception: no Rust integration test reads spec markdown (crates/web/tests/static_assets.rs only greps index.html). Refs #538
Per audit F39 (#539). The Playwright test at e2e/permissions.spec.ts:116-141 was a vacuous shell after role- creation assertions were removed; it paid full setupTwoPeers cost to run a single-client, single-viewport DOM-visibility check — exactly the shape CLAUDE.md's "Which test tier to use" tree routes to wasm-pack browser tests. This commit: - deletes the Playwright test + drops "server settings panel" from the mobileSkipPattern in the describe-block guard; - removes the openServerSettings import from permissions.spec.ts (still used by other specs, untouched); - adds settings_back_button_fires_on_close in crates/web/tests/browser.rs near the other settings_* tests, mirroring their static-view pattern. Asserts panel renders while a parent signal is true and that clicking the .btn in .server-settings-header flips the signal back to false. Real SettingsPanel wiring is already covered by settings_displays_peer_id / _status_message_shows_and_hides / _shows_invite_section. This test fills the missing back-button coverage at the same tier. Local gate: cargo fmt, cargo check + clippy on wasm32-unknown-unknown for willow-web --all-targets, and native cargo clippy on willow-web --all-targets all pass with zero warnings. The actual headless wasm-pack run is gated by master-PR CI's `browser` job (wasm-pack + Firefox + geckodriver not available locally). ESLint on permissions.spec.ts is gated by master-PR CI's `lint` job (local node_modules missing `@eslint/js`). Refs #539
Per audit F40 (#540). The Playwright test at e2e/permissions.spec.ts (was line 119; shifted to ~115 after the #539 deletion in 62d9a62) paid full setupTwoPeers cost to verify a single-viewport DOM-visibility predicate -- exactly the shape CLAUDE.md's "Which test tier to use" tree routes to wasm-pack browser tests. This commit: - deletes the Playwright test (leaves a short signpost comment so future readers can find the replacement); - adds non_owner_hides_channel_add_button in crates/web/tests/browser.rs next to the existing channel_sidebar_add_button_says_new_tree_with_glyph test, mirroring the static-view + Show pattern used by settings_back_button_fires_on_close. Asserts the same conditional-render contract channel_sidebar.rs:307 enforces (`can_manage_channels().then(|| view! { ... })`): no .channel-add-btn when is_owner=false; visible when is_owner=true; gone again when flipped back. Static-view shape over real ChannelSidebar + test_client() mount because the surrounding browser.rs settings_* and channel_sidebar_* tests already use it; the real-component path needs WebClientHandle + AppState contexts that aren't plumbed in browser.rs today. Local gate: cargo fmt --check, cargo check --target wasm32-unknown-unknown -p willow-web --tests, and cargo clippy on both wasm32 and native targets all pass. Headless wasm-pack run + ESLint (`npm run lint`) deferred to master-PR CI -- wasm-pack/Firefox/geckodriver and node_modules/@eslint/js aren't available locally on this sandbox. Refs #540
Adds a sub-paragraph to the "Implementer cuts off mid-flight" section of resolving-issues. Captures the new failure shape seen in PR #599's #540 dispatch: implementer committed locally but its push step didn't land on origin; stop-hook flagged the unpushed commit; coordinator pushed manually to advance the master branch + unblock the SHA-watch Monitor. Implementer's later report noted the commit was already on origin when it arrived — the coordinator push had landed first. Rule: when stop-hook reports unpushed commits AND `git status` is clean AND `git ls-remote` lags HEAD, the coordinator pushes directly. Pushes are commutative under this race, so neither side loses work.
Owner
Author
|
fix |
Test was flaky (#565). After PR #505's membership gate, the test depended on HashMap iter order in topo-sort: when SetProfile was visited before GrantPermission, alice failed the membership gate and the profile was rejected (`left: None, right: Some("Alice")`). Add explicit causal dep on grant.hash so topo-sort applies GrantPermission first regardless of iter order. Mirrors the fix already on PR #598 for the same test; cherry-picking it here keeps PR #599's master-PR CI green now that the human asked for the fix in this batch rather than waiting for #598 to merge. Refs #565
8 tasks
intendednull
pushed a commit
that referenced
this pull request
May 5, 2026
Prior run of Playwright E2E on 4adfe2c failed; cargo-audit (rescued to 0.22.1 in 4adfe2c) and 6 other checks passed. Local reproduction showed widespread DAG-convergence timeouts AND iroh-relay "dial failed: timed out" / "MultipathNotNegotiated" / "Connection did not reach established state within timeout" errors in the relay log — network-layer symptoms typical of CI sandbox transient instability, not regression. State-tier changes in this batch (#613/#614/#615) cannot affect the failing test paths: - #613 caps SealedContent.ciphertext at 64 KiB, validated in Message::validate (chat-message store path) — invite-flow tests never construct Content::Encrypted (no channel keys exchanged). - #614 rejects UpdateProfile.display_name > 64 chars — Alice/Bob fixtures use 5-char names. - #615 rejects Reaction emoji > 32 B / cardinality > 32 per message — invite-flow tests never react. PR #599 (no state-machine changes, same `main` base) passed Playwright E2E earlier today at 09:51 UTC, ruling out a stable preexisting break on `main`. Empty retrigger to confirm flake. If this run also fails identically, bisect-revert the 3 state-cap commits one at a time will follow.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Scheduled
/resolving-issuessweep against the 2026-05-03 general-audit (master ticket #567). Four small-scope fixes landed sequentially. Picks chosen to NOT overlap with PR #566 + PR #598's in-flight files (#566 still lockscrates/{client,web,messaging,state,storage,worker}/src/...; #598 still lockscrates/{client/src/worker_cache.rs,identity/src/lib.rs,messaging/src/{lib,store}.rs,state/src/{dag,tests/materialize}.rs,web/{index.html,tests/static_assets.rs}}+Cargo.toml/lock). Targets in this run sit on.github/workflows/,docs/specs/,e2e/permissions.spec.ts, andcrates/web/tests/browser.rs— all clear of both in-flight PRs.Fixes
Fixes audit F13 [security]: GitHub Actions workflows lack permissions: blocks #580 —
ci: declare top-level permissions: contents: read(12d0d47). All three workflow files (ci.yml,deploy.yml,e2e.yml) now declare an explicit minimum-scope GITHUB_TOKEN block. Defense-in-depth: even if the repo default ever flips wider, these workflows stay read-only. Coordinator pre-decided narrowing: no per-job elevation needed — verifieddeploy.yml's upload steps usesshpass+${{ secrets.DEPLOY_PASSWORD }}over SSH/SCP, NOTGITHUB_TOKEN. Cargo gate skipped per the verified-no-asserter exception (no Rust integration test reads workflow YAML); YAML round-trip validated via Pythonyaml.safe_load+ the audit's own grep.Fixes audit F38 [arch]: web::DerivedStateActor uses Arc<Mutex> not Rc<RefCell> in WASM-only code #538 —
docs(spec): note actor-bridge dedup cache exception in state-mgmt table(cf12cb9). The state-management spec proposedRc<RefCell<>>as the canonical WASM interior-mut pattern, butstate_bridge.rs:31intentionally usesArc<Mutex<Option<U>>>(thewillow-actorframework requiresSend, soRcis structurally unavailable). Added (a) one row in the proposed CLAUDE.md-addition table covering "Web actor-handler dedup cache (deferred to F2)", (b) one cross-link sentence at the end of § F2 back to the new row — closing the table → comment → follow-up loop. Coordinator pre-decided narrowing: spec edit over F2 redesign (F2's own dedicated PR scope per its trigger).Fixes audit F39 [testcov]: settings panel + back-button test should be browser-tier not Playwright #539 —
test(web): migrate settings panel + back button to browser tier(62d9a62). Deletes the vacuous Playwright test ate2e/permissions.spec.ts:116-141(already documented "until roles are added, this test verifies that the settings panel opens and the Back button returns to chat" — single-client, single-viewport DOM behaviour) + drops "server settings panel" from themobileSkipPatternregex. Addssettings_back_button_fires_on_closeincrates/web/tests/browser.rs:715-759mirroring the existingsettings_*tests' static-view + signal-drivenShowpattern. Removes the now-unusedopenServerSettingsimport (still used bycross-browser-sync.spec.ts, untouched there). Coordinator pre-decided narrowing: static-view shape over real-component mount (consistent with the surroundingsettings_displays_peer_id/_status_message_shows_and_hides/_shows_invite_sectiontests).Fixes audit F40 [testcov]: non-owner channel-add hidden test should be browser-tier not Playwright #540 —
test(web): migrate non-owner channel-add hidden to browser tier(af3dd51). Same shape as audit F39 [testcov]: settings panel + back-button test should be browser-tier not Playwright #539 — deletes the Playwright test (was atpermissions.spec.ts:115-129after audit F39 [testcov]: settings panel + back-button test should be browser-tier not Playwright #539's deletion shifted line numbers; original audit cited line 119) + addsnon_owner_hides_channel_add_buttonincrates/web/tests/browser.rs:4593-4637mirroringchannel_sidebar_add_button_says_new_tree_with_glyph's placement. Asserts the same conditional-render contractchannel_sidebar.rs:307enforces (can_manage_channels().then(|| view! { ... })): no.channel-add-btnwhenis_owner=false; visible whenis_owner=true; gone again when flipped back. Coordinator pre-decided narrowing: static-view shape over realChannelSidebar+test_client()mount (WebClientHandle+AppStateplumbing isn't wired for browser.rs today; that's a separate refactor).Already-Fixed
None this run. The general-audit at #567 was filed 2026-05-03 against
main @ 6404719; PR #596 merged intomain @ c40bceabetween that audit and this run, but PR #596 + PR #598 already covered the issues that were resolvable on the existing tree (5 each, plus #596's E2E batch). No surviving picks were resolved upstream by intervening landings — same-day-audit pattern from prior runs holds. Sweep was a one-line check, no time wasted.Parked
None. All 4 picks landed cleanly. No mid-flight aborts; no finalize-implementer rescues.
Filed mid-run (follow-ups, NOT closed by this PR)
None.
Avoided picks (overlap with PR #566 + #598 files in flight)
crates/web/src/state.rs❌ in PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566. Carried forward.set_join_statusdenied: sentinel) —crates/client/src/lib.rs❌ in PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566. Carried forward.crates/web/src/voice.rs❌ in PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566. Carried forward.crates/client/src/listeners.rs❌ partial overlap with PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566.let _ = ...swallows in voice.rs) — same lock as audit F3 [UX]: getUserMedia/screen-share/file-share failures only log, no UI feedback #570.crates/agent/src/auth.rs❌ in PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566.crates/worker/src/identity.rs❌ in PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566.Permission::__UnknownLegacy) — all ❌ oncrates/state/src/event.rsin PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566.applied_eventspoisoning), audit F12 [security]: topological_sort soft-accepts unknown cross-author deps #579 (topological_sortsoft-accept) — ❌ oncrates/state/src/sync.rsin PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566.storage::role::set_default_servertest gap) — ❌ oncrates/storage/src/role.rsin PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566.crates/client/src/tests/search.rsin PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566.views.rs,listeners.rs,traits.rs,message.rs,mention.rs) ❌ in PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566. Carried forward.sshpass -pwith password +root@+StrictHostKeyChecking=no#227). Skipped pending decision.Skill Evolution
One skill edit this run:
8fc5554 docs(skill): codify coordinator-side push fallback for sandbox lag— adds a sub-paragraph to the "Implementer cuts off mid-flight" section. Captures a new failure shape observed in this run's audit F40 [testcov]: non-owner channel-add hidden test should be browser-tier not Playwright #540 dispatch: implementer committed locally but its push step didn't land on origin; stop-hook flagged the unpushed commit; coordinator pushed manually to advance the master branch + unblock the SHA-watch Monitor. Implementer's later report explicitly noted the commit was already on origin when it arrived (the coordinator's manual push had landed first). New rule: when stop-hook reports unpushed commits ANDgit statusis clean ANDgit ls-remotelags HEAD, the coordinator pushes directly. Pushes are commutative under this race, so neither side loses work.Lessons Learned
4/4 implementer dispatches landed cleanly. No mid-flight aborts. No finalize-implementer rescues. Smaller batch than PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566 (10/10), PR auto-fix batch claude/friendly-maxwell-m1efN 2026-05-03 #596 (9/9), PR auto-fix batch claude/friendly-maxwell-cCGXk 2026-05-04 #598 (5/5). Reproducible result across 4 consecutive scheduled runs — sequential pattern + Monitor SHA-watch + agent-completion notification two-signal convergence holds.
Coordinator-side push fallback exercised once (audit F40 [testcov]: non-owner channel-add hidden test should be browser-tier not Playwright #540). Stop-hook flagged 1 unpushed commit on the coordinator's branch while origin still pointed at the prior SHA; SHA-watch Monitor was still armed. Pushed manually; Monitor fired immediately; agent-completion notification arrived later confirming "commit was already on origin when I arrived". First time this shape was seen — codified into the skill as
8fc5554. Cost was ~15 sec of manual push + a brief moment of "is this real or stop-hook noise?" disambiguation. Net cheaper than waiting the full 15-min Monitor timeout.Pre-staged working tree pattern reproduced. audit F39 [testcov]: settings panel + back-button test should be browser-tier not Playwright #539 implementer reported "Working tree was pre-staged with both required edits already applied"; audit F40 [testcov]: non-owner channel-add hidden test should be browser-tier not Playwright #540's tree was pre-staged + pre-committed + pre-pushed (after coordinator's manual push). Pattern is now solidly expected (codified in PR auto-fix batch claude/friendly-maxwell-m1efN 2026-05-03 #596's
4702486); audit F40 [testcov]: non-owner channel-add hidden test should be browser-tier not Playwright #540's "pre-pushed" extension is the new wrinkle covered by8fc5554.Coordinator pre-decided narrowing skipped the brainstorm gate on 4/4 picks. All briefs carried explicit option-pre-resolution: audit F13 [security]: GitHub Actions workflows lack permissions: blocks #580 (top-level minimum-scope only, deploy uses sshpass not GITHUB_TOKEN — verified upfront), audit F38 [arch]: web::DerivedStateActor uses Arc<Mutex> not Rc<RefCell> in WASM-only code #538 (spec edit over F2 redesign), audit F39 [testcov]: settings panel + back-button test should be browser-tier not Playwright #539 (delete Playwright + static-view browser test), audit F40 [testcov]: non-owner channel-add hidden test should be browser-tier not Playwright #540 (mirror audit F39 [testcov]: settings panel + back-button test should be browser-tier not Playwright #539 shape). Same effective pattern as PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566 + auto-fix batch claude/friendly-maxwell-m1efN 2026-05-03 #596 + auto-fix batch claude/friendly-maxwell-cCGXk 2026-05-04 #598.
Tier-migration twins (audit F39 [testcov]: settings panel + back-button test should be browser-tier not Playwright #539 + audit F40 [testcov]: non-owner channel-add hidden test should be browser-tier not Playwright #540) clean. Both removed a Playwright test + added a static-view browser test asserting the same DOM-visibility predicate. Implementer for audit F40 [testcov]: non-owner channel-add hidden test should be browser-tier not Playwright #540 successfully mirrored audit F39 [testcov]: settings panel + back-button test should be browser-tier not Playwright #539's pattern from the same dispatch session — confirms the brief shape is reproducible across implementers.
Stale audit line numbers handled correctly. audit F40 [testcov]: non-owner channel-add hidden test should be browser-tier not Playwright #540 audit cited
permissions.spec.ts:119but the file had drifted twice (PR auto-fix batch claude/friendly-maxwell-m1efN 2026-05-03 #596 deleted prior content; audit F39 [testcov]: settings panel + back-button test should be browser-tier not Playwright #539's deletion in this run shifted numbers further). Brief instructed re-grep at HEAD; implementer verified before editing. Worth keeping the explicit re-grep instruction in future briefs — saves the implementer from following a stale line ref into the wrong block.No avoidance overlap-list churn. All 18 deferred picks line up cleanly with PR auto-fix batch claude/friendly-maxwell-M5xB6 2026-05-03 #566 / PR auto-fix batch claude/friendly-maxwell-cCGXk 2026-05-04 #598 file lists; no false positives, no missed locks. The pre-flight overlap check (per PR auto-fix batch claude/friendly-maxwell-m1efN 2026-05-03 #596's lesson) continues to be the cheapest collision-prevention mechanism — coordinator does it once during step 6, ~5 min, prevents post-merge conflicts that take 30+ min to clean up.
Test plan
Master-PR CI is the load-bearing gate. Each implementer ran the scoped subset locally (fmt + native clippy + native test + wasm32 check + wasm32 clippy on touched crates).
CI gates to verify on this PR:
cargo fmtcargo clippyworkspace (native + wasm32)cargo testworkspace — Test job will likely report 1 failure intermittently (willow-state::tests_materialize::non_admin_set_profile_is_accepted, the test(state): non_admin_set_profile_is_accepted regression after #505 membership gate #565 flake). NOT introduced by this PR. New tests this PR adds (settings_back_button_fires_on_close,non_owner_hides_channel_add_button) all run as wasm-pack browser tests and pass independently.wasm-packbrowser tests (Firefox + geckodriver — observable on CI only) — load-bearing for audit F39 [testcov]: settings panel + back-button test should be browser-tier not Playwright #539 + audit F40 [testcov]: non-owner channel-add hidden test should be browser-tier not Playwright #540's new tests.cargo audit(no advisory changes this run)lintjob (ESLint one2e/) — localnpm run lintwas unavailable in the implementer sandbox; CI runs the canonical check.Cargo.lock conflict expected at merge time only if PR #566 / PR #598 land first (this PR doesn't touch
Cargo.lock, so it's a one-way mechanical resolution either way).non_admin_set_profile_is_accepted(#565) status: intermittent across the last three runs. Both polarities reproduced. CI Test job may report it red; expected pre-existing, not introduced by this PR.Generated by Claude Code