Skip to content

fix(wizard): init wizard fixes for 0.10.1 (#537, #538, #540)#559

Merged
Aaronontheweb merged 4 commits into
devfrom
claude-wt-init-wizard-fixes-10.1
Apr 8, 2026
Merged

fix(wizard): init wizard fixes for 0.10.1 (#537, #538, #540)#559
Aaronontheweb merged 4 commits into
devfrom
claude-wt-init-wizard-fixes-10.1

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Collaborator

Summary

Three init wizard fixes for the 0.10.1 milestone:

Closes #537, closes #538, closes #540

Test plan

  • dotnet build passes
  • All 37 ExposureModeStepViewModelTests pass (5 new)
  • All 38 WizardOrchestratorTests + SecurityPostureStepViewModelTests + WizardConfigBuilderTests pass
  • E2E: netclaw init with Tailscale Funnel → daemon starts successfully (devices.json + DeviceToken written)
  • E2E: netclaw init with Local mode → no devices.json, no DeviceToken in secrets

…air local device (#537, #538, #540)

Three init wizard fixes for the 0.10.1 milestone:

- #537: Security posture step now asks "Who will interact with this
  Netclaw instance?" instead of asking about access method. Stripped
  parenthetical transport hints from Team/Public option labels.

- #538: Moved exposure mode step from position 3 to second-to-last
  (before health check). Natural inside-out order: who trusts it →
  where it talks → what it does → how to reach it.

- #540: Auto-register the local machine as a paired device during
  init when a non-Local exposure mode is selected. Generates a
  bootstrap device token, writes the hash to devices.json and the
  raw token to secrets.json. This satisfies ExposureModeValidationService's
  requirement of at least one paired device, fixing the chicken-and-egg
  problem where the daemon crashed on first boot because the pairing
  flow requires a running daemon.
…vice

The orchestrator already calls EnsureDirectoriesExist() before
WriteBootstrapDevice is invoked, so the config directory is guaranteed
to exist.
Two root causes prevented Up/Down arrows and A/D keys from working
on the Channels step:

1. Stale IFocusable components (SelectionListNode, TextInputNode) from
   prior wizard steps remained on Termina's focus stack, consuming keys
   before they reached the Channels view's custom handler. Fixed by
   overriding HandlePageInput to intercept Channels keys at the capture
   phase, before the focus manager routes them.

2. The DynamicLayoutNode rebuild callback called ClearFocusState() on
   every content invalidation, resetting _addMode and _cursorIndex.
   This meant pressing 'A' would enter add mode but immediately reset
   it when InvalidateAndRedraw triggered a layout rebuild. Fixed by
   skipping ClearFocusState for the Channels step, which manages its
   own state across invalidations.

Also promotes Ctrl+Q to the capture phase so it always triggers shutdown
even when a TextInputNode has focus.

Adds headless TUI tests using VirtualInputSource that exercise the full
Termina rendering and input-routing pipeline for the Channels step.
@Aaronontheweb Aaronontheweb force-pushed the claude-wt-init-wizard-fixes-10.1 branch from 6a46904 to 5c8fa9a Compare April 8, 2026 02:57
@Aaronontheweb Aaronontheweb force-pushed the claude-wt-init-wizard-fixes-10.1 branch from 194de73 to 6445fc0 Compare April 8, 2026 21:38
@Aaronontheweb Aaronontheweb marked this pull request as ready for review April 8, 2026 21:39
@Aaronontheweb Aaronontheweb enabled auto-merge (squash) April 8, 2026 21:39
@Aaronontheweb Aaronontheweb merged commit 84c6dc6 into dev Apr 8, 2026
3 checks passed
@Aaronontheweb Aaronontheweb deleted the claude-wt-init-wizard-fixes-10.1 branch April 8, 2026 21:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant