Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
1018 commits
Select commit Hold shift + click to select a range
c129c14
chore(deps): bump lodash from 4.17.23 to 4.18.1
dependabot[bot] Apr 7, 2026
45c7289
fix: refactor forms flow 3
exromany Apr 8, 2026
696f3a7
feat: refactor forms flow 4
exromany Apr 8, 2026
2650240
fix: improve csp
exromany Apr 9, 2026
33244c2
feat: refactor forms flow 5
exromany Apr 9, 2026
1c76169
feat: update claim-bond WIP
exromany Apr 9, 2026
01f34d6
fix: types in test
exromany Apr 10, 2026
e94cb96
Merge pull request #480 from lidofinance/dependabot/npm_and_yarn/loda…
exromany Apr 10, 2026
f052cd9
Merge pull request #477 from lidofinance/dependabot/npm_and_yarn/defu…
exromany Apr 10, 2026
8602c8a
Merge pull request #473 from lidofinance/dependabot/npm_and_yarn/pico…
exromany Apr 10, 2026
fc31fd6
Merge pull request #466 from lidofinance/dependabot/npm_and_yarn/sock…
exromany Apr 10, 2026
bcbd779
Merge pull request #467 from lidofinance/dependabot/npm_and_yarn/flat…
exromany Apr 10, 2026
30a4d23
Merge pull request #457 from lidofinance/dependabot/npm_and_yarn/svgo…
exromany Apr 10, 2026
203b86f
fix: remove tests from eslintignore
exromany Apr 10, 2026
85597b5
fix: refactor tx-modal retry
exromany Apr 11, 2026
821d492
fix: claim bond empty state
exromany Apr 13, 2026
c41531b
feat: key status triggered-ejection
exromany Apr 13, 2026
64dd9af
Merge pull request #482 from lidofinance/fix/improve-csp
Mimidze Apr 13, 2026
58b3aec
Merge pull request #485 from lidofinance/develop
Mimidze Apr 13, 2026
4fd42e3
fix: last rewards tx hash - hide if no hash
exromany Apr 13, 2026
6d8c228
Merge branch 'feat/cm-forms-flow' into feature/csm-plus-cm
exromany Apr 13, 2026
22e5e5c
chore: add devnet settings
exromany Apr 13, 2026
b03810e
chore(deps): bump follow-redirects from 1.15.9 to 1.16.0
dependabot[bot] Apr 14, 2026
ca542f9
fix: update sdk
exromany Apr 14, 2026
5ef8928
fix: fixes
exromany Apr 14, 2026
cbe463e
fix: role actions, loader errors, modal form
exromany Apr 15, 2026
59679ab
chore: update devnet
exromany Apr 15, 2026
a10d6e9
chore: update devnet
exromany Apr 15, 2026
7e8cc67
chore: more devnet
exromany Apr 15, 2026
3f35c9c
chore(deps): bump hono from 4.12.3 to 4.12.14
dependabot[bot] Apr 16, 2026
d0b0734
fix: update group text
exromany Apr 16, 2026
0e8e3d0
chore: cleanup devnet
exromany Apr 16, 2026
a221bf3
Merge remote-tracking branch 'origin/develop' into feature/csm-plus-cm
exromany Apr 16, 2026
12c36c2
fix: update sdk with changed invite type
exromany Apr 16, 2026
39bb33c
fix: packages audit fix
exromany Apr 16, 2026
9b002ed
Merge branch 'fix/test-types' into feature/csm-plus-cm
exromany Apr 16, 2026
9a0ba41
fix: capitalize
exromany Apr 17, 2026
6b506fc
fix: validation address-input
exromany Apr 17, 2026
95be213
fix: stake and keys component
exromany Apr 17, 2026
4597c9b
fix: group page
exromany Apr 18, 2026
61efab9
fix: create-curated-operator styles
exromany Apr 21, 2026
047e17b
fix: radio button
exromany Apr 21, 2026
9dccb5f
fix: claim bond flow
exromany Apr 22, 2026
6140391
fix: max amount
exromany Apr 22, 2026
9963753
fix: add bond wsteth rate
exromany Apr 22, 2026
3df7291
feat: accept invite on change-role form
exromany Apr 22, 2026
406a8a7
fix: submit no changes in splitters
exromany Apr 22, 2026
45db43f
fix: updated sdk
exromany Apr 22, 2026
22ff1a7
Merge remote-tracking branch 'origin/main' into feature/csm-plus-cm
exromany Apr 23, 2026
ab712d9
Merge branch 'feature/csm-plus-cm' into develop-cm
exromany Apr 23, 2026
da8f2e2
chore: update env exmape
exromany Apr 23, 2026
ce707b8
Merge remote-tracking branch 'origin/develop' into develop-cm
exromany Apr 23, 2026
2dd2929
Merge branch 'feature/csm-plus-cm' into develop-cm
exromany Apr 23, 2026
4493a2b
fix: table styles
exromany Apr 23, 2026
ec9a695
fix: after walkthrough call
exromany Apr 23, 2026
9ee5e61
Merge pull request #487 from lidofinance/dependabot/npm_and_yarn/hono…
exromany Apr 24, 2026
37a2dd2
Merge pull request #486 from lidofinance/dependabot/npm_and_yarn/foll…
exromany Apr 24, 2026
6608035
chore: build-push-harbor
exromany Apr 24, 2026
5212c42
fix: add api/ready
exromany Apr 24, 2026
9354e08
chore: log module
exromany Apr 24, 2026
42538a5
fix: normalize rpc url ended with slash
exromany Apr 24, 2026
1ddbc33
fix: update sdk for unknown module
exromany Apr 24, 2026
d717c8b
fix: build with version
exromany Apr 26, 2026
e36cccc
fix: splitter share placeholder
exromany Apr 26, 2026
a758aab
fix: navigation, gates, nav items
exromany Apr 27, 2026
66299c7
fix: show commit in version
exromany Apr 27, 2026
b34b8fb
feat: claim bond + splitters
exromany Apr 27, 2026
e064d97
Merge branch 'feature/csm-plus-cm' into develop-cm
exromany Apr 27, 2026
17983f3
fix: claim bond
exromany Apr 29, 2026
f8e7a64
fix: after call 2
exromany Apr 29, 2026
2793fdb
fix: claim bond options with splitters
exromany Apr 29, 2026
901fb1a
Merge branch 'feature/csm-plus-cm' into develop-cm
exromany Apr 29, 2026
be8bcf5
fix: texts
exromany Apr 30, 2026
4eab842
Merge branch 'feature/csm-plus-cm' into develop-cm
exromany Apr 30, 2026
21cee42
Merge branch 'develop' into feature/csm-plus-cm
exromany Apr 30, 2026
8fc303a
chore: remove ci changes
exromany Apr 30, 2026
326ba37
Merge pull request #490 from lidofinance/feature/csm-plus-cm
exromany Apr 30, 2026
df1501e
chore(deps): bump brace-expansion from 1.1.11 to 1.1.14
dependabot[bot] Apr 30, 2026
989d2da
fix: texts
exromany May 3, 2026
9cbc088
fix: claim options
exromany May 4, 2026
d4d1983
fix: update preview
exromany May 4, 2026
c4e6b84
fix: simple moduleMeta
exromany May 4, 2026
013976c
Merge remote-tracking branch 'origin/develop' into develop-cm
exromany May 4, 2026
bd29702
chore: build push harbor
exromany May 4, 2026
5725ef6
Merge pull request #491 from lidofinance/dependabot/npm_and_yarn/brac…
exromany May 4, 2026
65f345c
Merge pull request #453 from lidofinance/dependabot/github_actions/ac…
exromany May 4, 2026
3c4c1e3
fix: remove md
exromany May 5, 2026
00143ef
fix: cm other module banner text
exromany May 5, 2026
787bda6
feat: dvt form
exromany May 5, 2026
a29c1d9
Merge branch 'develop-cm' into fix/cm
exromany May 5, 2026
cf0dcac
fix: text
exromany May 5, 2026
a4aac44
Merge pull request #492 from lidofinance/chore/build-push-harbor
exromany May 5, 2026
58441a1
fix: redirect for keys-upload for RA only
exromany May 5, 2026
1661553
chore(deps): bump docker/build-push-action from 6 to 7
dependabot[bot] May 5, 2026
4add360
chore(deps): bump actions/checkout from 4 to 6
dependabot[bot] May 5, 2026
2c7caab
chore(deps): bump docker/login-action from 3 to 4
dependabot[bot] May 5, 2026
a6bd780
Merge branch 'develop-cm' into fix/cm
exromany May 5, 2026
07b1e20
fix: build manifest.json
exromany May 5, 2026
648f07a
Merge branch 'develop-cm' into fix/cm
exromany May 5, 2026
23d4ffb
fix: validation get/set nested errors
exromany May 6, 2026
0ad248b
fix: update dvt form status
exromany May 6, 2026
6a5dcbe
fix: dipositable keys without weight
exromany May 8, 2026
9ffd03c
fix: operator type EEO
exromany May 8, 2026
38a5f03
feat: validate member is in ICS list
exromany May 11, 2026
83ed441
feat: add FAQ for CM
exromany May 11, 2026
00a1048
fix: form titles size
exromany May 11, 2026
3d3cffe
fix: claim bond options
exromany May 11, 2026
f31191d
fix: skip share-limit waiting for CM add-keys
exromany May 11, 2026
ac36965
Merge branch 'develop-cm' into fix/cm
exromany May 11, 2026
1fd0de0
Merge pull request #493 from lidofinance/fix/cm
exromany May 12, 2026
eddb8d4
fix: infinite loop on create page
exromany May 12, 2026
9e67d63
fix: select file for FF
exromany May 12, 2026
e6bb5e9
fix: claim bond long option
exromany May 12, 2026
0a88c96
fix: claim bond modal
exromany May 12, 2026
113bfd5
feat: added data attr for elements
Vorobeyko May 13, 2026
f19533d
fix: address review feedback on data-testid PR
exromany May 13, 2026
4040c13
Merge pull request #506 from lidofinance/feat/data-testids
exromany May 13, 2026
2951c1c
fix: grammar tx modal
exromany May 13, 2026
50dc26c
feat: qa-config page to setup custom rpc and cl api
exromany May 14, 2026
9a75b5a
feat: env for ipfs gateways and surveys api
exromany May 14, 2026
86aa44b
fix: qa-config layout dummy
exromany May 14, 2026
8920d28
feat: update CM faq
exromany May 19, 2026
d7235c8
fix: key comment link
exromany May 19, 2026
63aca52
fix: update faq idvtc type
exromany May 19, 2026
5e2fc4a
feat: rename stealing to delayed-penalty
exromany May 21, 2026
798a03f
fix: link, date, events
exromany May 25, 2026
b41444a
fix: disabled submit button for incomplete form
exromany May 25, 2026
c1742c2
feat: show actual status/button for type cards
exromany May 25, 2026
d0f45b6
fix: update Node.js version to 24 and clean up workflow files (#509)
Vorobeyko May 26, 2026
6eb08f7
feat: unified siwe auth
exromany May 28, 2026
33d423e
Merge pull request #500 from lidofinance/feature/idvtc-apply-form
Mimidze May 28, 2026
222adbc
fix: update Playwright and related dependencies to latest versions (#…
Vorobeyko May 29, 2026
5932921
feat: keys-cache used internally in sdk
exromany May 21, 2026
c7db194
fix: test dulicated-keys
exromany May 21, 2026
9c42eee
fix: revert group names
exromany May 21, 2026
b9e875f
fix: dummy qa-config
exromany May 21, 2026
2903fe6
fix: downgrade sdk
exromany May 22, 2026
0035c78
fix: current-stake without external-stake
exromany May 28, 2026
4cb827e
feat: group name
exromany May 28, 2026
6fcb021
fix: adapt curated gates to gateName-based SDK API
exromany Jun 1, 2026
ace6ac4
feat: keep IDVTC operator type metadata
exromany Jun 1, 2026
f54cda3
chore: ci
exromany May 28, 2026
f8dc9ea
fix: update Node.js version to 24 and clean up workflow files (#509)
Vorobeyko May 26, 2026
af9f726
fix: update Playwright and related dependencies to latest versions (#…
Vorobeyko May 29, 2026
6e7c39e
chore(deps): bump reef-knot to 8.1.0
exromany Jun 1, 2026
1c7f2dd
chore(deps): patch dependabot security advisories via resolutions
exromany Jun 1, 2026
d8cf5f0
chore(deps): bump uuid to v14 to patch advisories
exromany Jun 1, 2026
d948b00
Merge remote-tracking branch 'origin/develop' into develop-cm
exromany Jun 1, 2026
f7dc3ec
chore: ci
exromany Jun 2, 2026
4c0ba68
feat: schedule ICS round 6 on June 8
exromany Jun 2, 2026
5576305
feat(ics): add SSV VO to Proof-of-Humanity and broaden High Signal
exromany Jun 2, 2026
912c3c2
Merge pull request #515 from lidofinance/chore/sync-develop-cm
exromany Jun 2, 2026
9acae05
feat: update inbox requests copy
exromany Jun 2, 2026
986af6f
Merge pull request #496 from lidofinance/dependabot/github_actions/do…
exromany Jun 3, 2026
880ff75
Merge pull request #497 from lidofinance/dependabot/github_actions/ac…
exromany Jun 3, 2026
f0bb0b2
feat: add helper text to operator name and description inputs
exromany Jun 2, 2026
1acb810
fix: wrap view-mode change-role info in form so Accept invite submits
exromany Jun 2, 2026
25c157a
Merge pull request #519 from lidofinance/chore/sync-develop-cm
exromany Jun 3, 2026
4a5aa37
Merge pull request #498 from lidofinance/dependabot/github_actions/do…
exromany Jun 3, 2026
51d879b
feat: add tooltip explaining Main address selection in IDVTC apply form
exromany Jun 3, 2026
93f7a05
fix: delayed-penalty on cm
exromany Jun 4, 2026
4806bdd
fix(ics): split High Signal link into Lido and SSV
exromany Jun 4, 2026
eeccc81
fix: stack label and address in change-role/claimer tx modals
exromany Jun 4, 2026
868cc09
fix: show simple message on wallet sign timeout error
exromany Jun 4, 2026
cf911ff
fix: enforce sentence-ending dot rule in UI copy
exromany Jun 5, 2026
482b7e0
Merge pull request #516 from lidofinance/feature/update-ics-round
Mimidze Jun 5, 2026
f5ce676
fix: harden address-validation file loader against IO errors
exromany Jun 6, 2026
93ec47f
fix: infinite load page without operatro
exromany Jun 6, 2026
aba22cc
tests: added tests for curated module (#474)
Vorobeyko Jun 9, 2026
1552e3e
fix: type config.module as MODULE_NAME enum
exromany Jun 13, 2026
31cff81
fix: align test types with sdk module rename & node service api
exromany Jun 13, 2026
cddbac0
fix: capitalize "Not set" labels and use config links in cm
exromany Jun 13, 2026
0998751
Merge develop-cm into develop
exromany Jun 15, 2026
778754c
Use SecGuardReporter to hide sensetive env in pw report (#520)
jake4take Jun 15, 2026
2b0fef8
test: update event name for detailed link in welcome page test
Mimidze Jun 16, 2026
694b6ac
Merge remote-tracking branch 'origin/develop' into develop-cm
exromany Jun 16, 2026
9248e33
Merge branch 'develop-cm' into chore/sync-develop-cm
exromany Jun 16, 2026
c757b90
Merge pull request #521 from lidofinance/chore/sync-develop-cm
exromany Jun 18, 2026
a371e49
Merge remote-tracking branch 'origin/develop' into fix/csm-e2e-tests
Mimidze Jun 19, 2026
217e93f
test: fix visibility checks for latest rewards distribution
Mimidze Jun 19, 2026
7d52705
test: remove skipped test 144 for "Stuck keys found" field
Mimidze Jun 19, 2026
ab69d25
feat: siwe nonce handshake for surveys api auth
exromany Jun 22, 2026
3740c2d
chore: replace Harbor registry endpoint
Ziars Jun 22, 2026
54486b4
Merge pull request #530 from lidofinance/fix/siwe-auth
Mimidze Jun 22, 2026
9dbeabf
test: fixes after review
Mimidze Jun 23, 2026
e395f9b
fix: migrate survey API to lido.tools domains
exromany Jun 23, 2026
b8b038d
Merge pull request #533 from lidofinance/fix/migrate-api
Mimidze Jun 23, 2026
6173287
test: removed duplicate test skips
Mimidze Jun 23, 2026
93de5e4
feat: add e2e test workflows and setup actions for CSM/CM modules (#529)
Vorobeyko Jun 23, 2026
a64087f
feat: siwe nonce handshake for surveys api auth
exromany Jun 22, 2026
7042572
fix: migrate survey API to lido.tools domains
exromany Jun 23, 2026
acfccf4
test: fix why modal test
Mimidze Jun 23, 2026
b3bea82
test: fixed expected days verification for rewards distribution
Mimidze Jun 23, 2026
d16227e
test: remove skipped test for delayed oracle report
Mimidze Jun 23, 2026
f839f9f
Merge pull request #531 from Ziars/chore/replace-harbor-registry-endp…
madlabman Jun 24, 2026
4711628
fix: update button names and improve test timeout handling (#535)
Vorobeyko Jun 24, 2026
3c934f8
Merge pull request #522 from lidofinance/fix/csm-e2e-tests
Mimidze Jun 24, 2026
ef2f88e
Merge pull request #534 from lidofinance/fix/survey-api-auth
Mimidze Jun 25, 2026
8e63c66
test: add data-testid and update expected text in tests (#538)
Mimidze Jun 26, 2026
5e8ec35
feat: surveys-sdk + IDVTC apply/claim flows (#518)
exromany Jul 1, 2026
c573f29
tests: add tests for idvtc (#537)
Vorobeyko Jul 2, 2026
ad1e1b5
chore(deps): bump docker/setup-buildx-action from 3.3.0 to 4.2.0
dependabot[bot] Jul 2, 2026
ca30735
fix(matomo): distinct page events for settings and type sub-pages, fi…
exromany Jul 6, 2026
1551313
fix: assorted claim-bond, add-keys, deposit-data & tx-modal fixes (#539)
exromany Jul 7, 2026
5e27252
Merge pull request #541 from lidofinance/dependabot/github_actions/do…
exromany Jul 8, 2026
d5acdfc
test: add address blacklist validation tests for operators: (#548)
Vorobeyko Jul 8, 2026
a37c99e
feat: show stub for CM module via MODULE env
exromany Jul 12, 2026
8a82845
Merge pull request #553 from lidofinance/feature/cm-stub
Mimidze Jul 13, 2026
5443db6
Tests/cm matomo (#551)
Vorobeyko Jul 15, 2026
db8f025
chore: merge origin/main into develop branch
exromany Jul 16, 2026
7edaf18
fix: update tests (#555)
Vorobeyko Jul 17, 2026
ce3bd6d
Merge pull request #557 from lidofinance/chore/merge-origin-main
exromany Jul 21, 2026
7cd9972
feat(errors): typed error handling — SDK codes, ApiError envelope, va…
exromany Jul 21, 2026
f1440dd
refactor(surveys): rename dvt feature to idvtc + migrate to generated…
exromany Jul 21, 2026
c69b101
feat(idvtc): DKG files page + upload in add-keys and create flows
exromany Jul 21, 2026
ee6d4b9
feat(idvtc): cluster members page + member rotation request flow
exromany Jul 21, 2026
fa0fcf4
chore: scoped CLAUDE.md conventions + bump csm-sdk to alpha.71
exromany Jul 21, 2026
a2d2b09
feat(idvtc): redesign DKG files list + auth and validation fixes
exromany Jul 21, 2026
3f19478
feat(idvtc): gate members init on connected address's bindable form
exromany Jul 21, 2026
f9ed0db
feat(idvtc): from-scratch member init foundations + simplify DKG upload
exromany Jul 21, 2026
653b583
refactor(idvtc): unify SIWE UI, share IDVTC page shell + file utils; …
exromany Jul 21, 2026
453eee6
feat(idvtc): not-initialized members state machine + from-scratch ini…
exromany Jul 21, 2026
aed9305
feat(idvtc): per-card member rotation cards on merge-patch rotation-r…
exromany Jul 21, 2026
4afcdf3
feat(idvtc): auto-init cluster members after create and claim
exromany Jul 21, 2026
be0505d
fix(idvtc): members UI polish — FormBlock wrap, ICS proof validation,…
exromany Jul 21, 2026
1e292d2
chore(deps): bump csm-sdk to 2.0.0-alpha.74
exromany Jul 22, 2026
b1eb785
feat(idvtc): move DVT nav below Claim, use file icon
exromany Jul 22, 2026
983b521
feat(errors): adopt csm-sdk alpha.72 wallet/tx error taxonomy
exromany Jul 12, 2026
73cd050
feat: add flag to skip deposit data signature validation (#559)
exromany Jul 22, 2026
5a03229
chore: bump matomo/analytics @lidofinance/* family and reef-knot
exromany Jul 22, 2026
5077a81
Merge remote-tracking branch 'origin/develop' into feat/idvtc-rebaseline
exromany Jul 22, 2026
206be95
Merge pull request #562 from lidofinance/chore/update-matomo-analytics
Mimidze Jul 23, 2026
624db12
chore: reorder chip export in shared components index
exromany Jul 23, 2026
c8a5cba
feat: add dedicated favicon for CM module
exromany Jul 23, 2026
b096bc4
fix: failed tests (#560)
Vorobeyko Jul 23, 2026
6b03056
Merge remote-tracking branch 'origin/develop' into feat/idvtc-rebaseline
exromany Jul 23, 2026
0577d3d
fix: compare key limit against deposited keys
exromany Jul 23, 2026
2565df7
fix: prevent group cards overflow between 1024-1240px
exromany Jul 23, 2026
9b678d7
feat: warn when operator metadata editing is restricted
exromany Jul 23, 2026
4c87daf
fix: hide surveys CTA outside active survey window
exromany Jul 23, 2026
89c663d
fix: grant node write access to regenerated public assets
exromany Jul 23, 2026
c9f55d1
feat: rename cancel-editing button to just Cancel
exromany Jul 23, 2026
76c4fc3
refactor: use WhenLoaded wrapper in DKG files page
exromany Jul 23, 2026
bbe098b
feat: set mainnet CM feedback form
exromany Jul 23, 2026
8a27418
Merge pull request #567 from lidofinance/fix/last-fixes
exromany Jul 24, 2026
0f5cd66
Merge remote-tracking branch 'origin/develop' into feat/idvtc-rebaseline
exromany Jul 24, 2026
4e65a92
feat: track IDVTC survey-API failures and sign-in denials in Matomo
exromany Jul 24, 2026
2486655
Merge pull request #561 from lidofinance/feat/idvtc-rebaseline
Vorobeyko Jul 24, 2026
0dce483
fix: update status URLs and improve test assertions (#575)
Vorobeyko Jul 24, 2026
ad05805
Merge pull request #573 from lidofinance/feat/idvtc-matomo-tracking
exromany Jul 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
15 changes: 15 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"presets": [
[
"next/babel",
{
"preset-env": {
"exclude": ["transform-exponentiation-operator"]
}
}
]
],
"plugins": [
"babel-plugin-styled-components"
]
}
2 changes: 2 additions & 0 deletions .claude/skills/visual-verify/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Auto-installed csm-dev-wallet + generated screenshots (not source)
.cache/
178 changes: 178 additions & 0 deletions .claude/skills/visual-verify/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
---
name: visual-verify
description: >-
Use when you need to SEE, screenshot, preview, or visually QA how a page of the running CSM or CM
widget looks — connected as a specific wallet address or node operator, or in the disconnected/welcome
state — which a plain headless browser can't reach (it has no wallet). Opens the running app (localhost
or a testnet URL), navigates any route, optionally in dark/light theme, a mobile/desktop viewport, or
cropped to one element, and captures a screenshot plus any console/network errors. E.g. "show the
dashboard as operator 4", "settings in dark mode", "the bond page on mobile", "screenshot the welcome
screen", or "open cm.testnet.fi as operator 5". NOT for: writing unit/e2e tests, debugging
connector/wallet code, building UI features, or comparing against Figma.
---

# Visual verification of the running app

This app is a Web3 dApp: every meaningful page requires a connected wallet. A vanilla automated
browser has no `window.ethereum`, so the connect modal has nothing to click and you only ever see
the welcome screen. This skill solves that with **csm-dev-wallet** — a dev wallet extension that
injects a provider and lets you connect as _any_ address or node operator without keys or signing
(the app runs on Hoodi testnet, where watch-only is enough to render every connected page).

## Prerequisites

- A target app must be reachable — the local dev server at `http://localhost:3000` (`yarn dev`), the
CM instance (e.g. `localhost:3001`), or a remote testnet (`--url https://csm.testnet.fi`). This skill
does **not** start anything — check first (`curl -sI <url>`), and ask the user to run `yarn dev` if local is down.
- Which **module** (CSM vs CM) and **chain** the target runs on are detected automatically from the app
itself, so the same command works against any instance — no need to know or pass them.
- `csm-dev-wallet` is auto-installed into `.claude/skills/visual-verify/.cache/` on first run (it's a
QA tool, deliberately kept out of the project's `package.json`). `playwright` is reused from the repo.

## Quickstart — screenshot any page in any state

```bash
# Dashboard, connected as node operator #4 (resolves the operator's manager address automatically)
node .claude/skills/visual-verify/scripts/verify.mjs --operator 4 --route /

# Settings, as operator #4's rewards address
node .claude/skills/visual-verify/scripts/verify.mjs --operator 4 --role rewards --route /settings

# Any route, connected as a raw address
node .claude/skills/visual-verify/scripts/verify.mjs --address 0xd8dA…96045 --route /keys

# A different instance — the CM-module app, or a remote testnet. Module + chain auto-detected from the URL.
node .claude/skills/visual-verify/scripts/verify.mjs --url http://localhost:3001 --operator 2
node .claude/skills/visual-verify/scripts/verify.mjs --url https://cm.testnet.fi --operator 5

# Dark mode, and a mobile-width layout (combine freely)
node .claude/skills/visual-verify/scripts/verify.mjs --operator 4 --theme dark
node .claude/skills/visual-verify/scripts/verify.mjs --operator 4 --viewport mobile --theme dark

# Just one element (cropped, scrolled into view) instead of the whole page
node .claude/skills/visual-verify/scripts/verify.mjs --operator 4 --selector '[data-testid="accountSectionHeader"]'

# The disconnected/welcome state — no wallet at all (operator/address not required)
node .claude/skills/visual-verify/scripts/verify.mjs --no-connect --route /

# Watch it happen live, and leave the browser open to poke around
node .claude/skills/visual-verify/scripts/verify.mjs --operator 12 --headed --keep-open
```

It prints the resulting `STATE` (url / connected / account / operator), confirms the requested operator
is the one actually shown, a **page-health** line (console errors, uncaught exceptions, failed + 4xx/5xx
requests), and a screenshot path — then **Read the PNG to actually look at it**. The health line is what
catches a page that _looks_ fine but is actually broken (e.g. a dev server serving 404 chunks). If a run
fails at any step, it still saves a `FAILED-*.png` of wherever it got stuck (and reports its path) — a
failure image usually shows the cause (a modal that never opened, a blank card, the wrong route).

**`--operator N` guarantees operator N is displayed.** Many operators share an address (e.g. one address
is the rewards address of operators 4, 36 and 318). Connecting only pins the _address_; the app then shows
a default operator (the first or last-cached), which may be a sibling, not N. So after connecting the
script switches the in-app operator selection to N and verifies it — if N isn't available for the resolved
address, it errors and lists what _is_ available. (`--address` has no specific operator, so no switch.)

Default output is `.cache/shots/<module>-<tag>.png` (prefixed with module + any theme/viewport variant
so they don't collide); override with `--out path.png` (relative paths resolve to cwd). Flags:
`--url <origin>` (default `$APP_ORIGIN` / `localhost:3000`) | `--operator N` | `--address 0x…` |
`--role manager|rewards|owner` (default `manager`) | `--route /path` | `--theme light|dark` |
`--viewport mobile|tablet|desktop|WxH` | `--selector <css>` (shoot one element) |
`--no-connect` (capture with no wallet; operator/address not required) | `--json` |
`--module csm|cm` | `--chain 560048` | `--headed` | `--keep-open` | `--full` (full-page) |
`--out file.png`. **`--module` and `--chain` are auto-detected from the target URL** — only pass them to override.

`--json` emits one structured object on **stdout** (progress logs go to stderr) with the connection
details, `state`, the screenshot path, and `health` + full `diagnostics` (the console/network errors).
Use it when an agent needs to act on the result — `health.total > 0` is the machine-readable "this page
has problems" signal even when the screenshot looks fine. On failure it prints `{ "ok": false, "error" }`
and exits non-zero.

`--theme` works via `prefers-color-scheme` (the app honours it), set before first paint and verified by
page-background luminance, with the header theme toggler as fallback — so it's reliable even at mobile
widths where the toggler hides in a menu. `--viewport` presets: mobile `390×844`, tablet `768×1024`,
desktop `1280×800` (or pass an explicit `WIDTHxHEIGHT`).

## Finding operators

To pick an operator — or find an address that controls several (needed to exercise the in-app
operator switcher, which changes operator _without_ a wallet change):

```bash
node .claude/skills/visual-verify/scripts/operators.mjs # summary + multi-operator addresses
node .claude/skills/visual-verify/scripts/operators.mjs --id 4 # full details for operator #4
```

## How it connects (the non-obvious bits)

These quirks are already handled in `scripts/lib.mjs`; understand them before writing custom flows:

- **Connection is seeded, not clicked (with a modal fallback).** Setting `eth_accounts` alone does NOT
auto-connect — wagmi/reef-knot only adopt a connection from persisted storage or an explicit connector
call. So `connectAs` writes the exact 4 `localStorage` keys a real connect leaves behind (terms-accepted
flag + `wagmi.recentConnectorId`/`reconnect-wallet-id` + the `wagmi.store` connection record) via
`addInitScript` **before load**, and the app reconnects the injected wallet on boot — no clicks. If that
reconnect doesn't take (e.g. wagmi bumps `wagmi.store`'s schema or the `reef-knot_accept-terms_n2`
version suffix drifts), it falls back to the **proven modal flow**: `connectBtn` → tick the Terms
checkbox (it gates the wallet buttons) → click the **"Browser"** option (the injected provider shows up
under the pinned `browserExtension` connector, not by the wallet's own name).
- **The header chip re-renders asynchronously** after any navigation, reload, or account change (wagmi
reconnects, balances fetch). Always wait for the header to settle into connected-or-disconnected
before reading state or screenshotting, or you capture a blank chip. `settle()` does this.
- **Wallet account vs active operator are two layers.** One address can manage many operators; the app's
switcher (`data-testid="nodeOperatorHeader"`) changes the active operator with no wallet event. The
in-app operator selection is connection-scoped — it resets to the default operator on reconnect/reload,
which is why `connectAs` re-asserts it (via `ensureOperator`) _after_ the final navigation, not before.

## Writing custom multi-step flows

For scenarios beyond a single screenshot (persistence checks, account switching, the operator switcher,
disconnect/reconnect), import the library instead of shelling out to the CLI:

```js
import { connectAs, ensureOperator, readState, settle, HOODI } from './lib.mjs';

const { context, wallet, page } = await connectAs({
operatorId: 318,
route: '/settings',
});
await wallet.switchAccount(page, '0xba99…26af'); // change wallet account → app reacts live
await settle(page);
await ensureOperator(page, 36); // switch in-app operator (no wallet change)
console.log(await readState(page)); // { url, connected, account, operator }
await page.screenshot({ path: 'after-switch.png' });
await context.close();
```

`connectAs(...)` returns Playwright's `context`/`page` plus the dev-wallet `wallet` controller, and (for
`operatorId`) guarantees that operator is active. Helpers: `ensureOperator(page, id)` (in-app switch +
verify), `currentOperatorId(page)`, `readState`, `settle`, `connectModal`. Key `wallet` methods:
`switchAccount(page, addr)`, `switchNetwork(page, chainId)`, `disconnect(page)`,
`selectOperator(page, id, role)`, `refreshOperators(page, chainId, module)`, `getOperator(page, id, …)`.
Full controller API, the underlying `wallet_test*` RPC primitives (for drivers that can't use the
helper), and a **dev-browser fallback** (for headed/persistent sessions) are in
[references/advanced.md](references/advanced.md).

## Key app facts

- Network: Hoodi testnet, `chainId 560048` (auto-detected per instance). The app's RPC proxy
(`<origin>/api/rpc`) is reused to resolve operators.
- **CSM vs CM**: the app serves one module per instance (`MODULE` env). They have _different_ operator
sets, so an id valid in CSM may not exist in CM. `operators.mjs --url <cm-origin>` lists the right set.
The connect flow, header testids, and switcher are shared across both modules.
- Header testids: `accountSectionHeader` (wallet chip), `nodeOperatorHeader` (active operator + switcher),
`connectBtn` (shown only when disconnected). Account modal: `disconnectBtn`, `connectedAddress`.
Operator switcher rows: `switchModalOperatorRow`, with a "Switch" button per non-current row.
- Routes are normal Next.js paths: `/`, `/keys`, `/settings` (redirects to a sub-tab like
`/settings/roles`), etc. Use whatever the app's nav exposes.
- `MODULE` (csm/cm) is set by the server env; pass `--module` to match if you've switched it.

## Troubleshooting

- **Welcome screen / never connects** → app likely on a different `MODULE` or chain than you passed,
or the connect modal changed. Re-run with `--headed` to watch, and check the testids above still exist.
- **`ECONNREFUSED` / blank page** → dev server isn't running; start `yarn dev`.
- **Slow first load** → the dev server cold-compiles on first hit; navigation auto-retries (commit +
app-shell wait, 3 attempts). If it still reports "never became ready", the server is stuck — restart `yarn dev`.
- **Operator resolve fails** → `/api/rpc` proxy unreachable or the id doesn't exist on this chain; try
`operators.mjs` to list valid ids.
- **Chromium missing** → run `yarn playwright install chromium` (the repo's documented setup step).
Loading