Skip to content

feat(init,config): prototype-proven init + config TUI; remove validated-UI framework#1368

Draft
Aaronontheweb wants to merge 81 commits into
netclaw-dev:devfrom
Aaronontheweb:docs/netclaw-validated-ui-components
Draft

feat(init,config): prototype-proven init + config TUI; remove validated-UI framework#1368
Aaronontheweb wants to merge 81 commits into
netclaw-dev:devfrom
Aaronontheweb:docs/netclaw-validated-ui-components

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Collaborator

Supersedes #1275 (folds in the guided-config-surfaces work). Reconciles netclaw init and netclaw config against a terminal-faithful browser prototype (design/tui-prototype/), then implements the proven UX in Termina. Four OpenSpec changes, all archived.

simplify-netclaw-init

  • netclaw init reduced 11 → 5 steps: Provider → Identity → Security Posture → Enabled Features (Personal skips) → Health Check. Channels, Search, Browser Automation, and Skill Sources move to netclaw config.
  • Existing-install action menu (Redo identity / Open configuration editor / Start over / Cancel); double-confirmed reset (setup-only vs full); identity-redo writes only identity files; post-flight nudges to netclaw chat + netclaw config.

netclaw-validated-ui-components — removed

  • The universal validated-UI commit framework was over-opinionated (a single consumer, a generic mandatory pipeline, a never-built analyzer). Removed entirely (−1145 net lines); Skill Sources migrated onto the same inline-validation pattern the Search editor uses. Config pages are presentational (an inverted audit test enforces it); persistence stays section-preserving on the view models.

netclaw-config-command

  • Live status-summary dashboard (Search ✓ Brave, Security & Access Team · 4/6 enabled).
  • Channels resolve-before-add (probe the channel against the adapter before saving).
  • Telemetry & Alerting multi-webhook list editor over NotificationsConfig.Webhooks.
  • Unified full-width selection bar across config sub-pages.

section-editor-abstraction

  • Confirmed valid — ConfigEditorSession is now the single persistence seam the migrated editors write through.

Testing

  • Build clean; full CLI suite 1027/1027.
  • Native smoke harness green: 14 tapes + 9 scenarios (incl. rewritten init-wizard, new init-existing, and config tapes driving the new dashboard / multi-webhook / channels UX).
  • slopwatch clean; copyright headers verified.
  • Eval suite runs in CI (needs a capable eval provider).

Draft — pending hands-on interactive TUI testing + code review before merge.

@Aaronontheweb Aaronontheweb force-pushed the docs/netclaw-validated-ui-components branch 2 times, most recently from 908ece4 to 6ed2445 Compare June 9, 2026 16:26
Adds three sequential OpenSpec changes for the netclaw init/config UX
overhaul planned in /home/petabridge/.claude/plans/so-a-big-ux-mossy-newt.md:

1. section-editor-abstraction — introduces ISectionEditor, registry,
   merge-on-save, single-step orchestrator mode, and refactors
   Provider/Identity/Posture to be reentrant. Lays the contract every
   future editable section must honor. Closes netclaw-dev#455.

2. netclaw-config-command — new menu-driven `netclaw config` TUI
   command composing 10 section editors (Search, 3x chat channels,
   Exposure Mode, Security Posture, Audience Profiles, Outbound +
   Inbound Webhooks, External Skills, Skill Feeds, Browser Automation),
   plus a generic ListEditor<T> framework, 4 new doctor checks, 12
   smoke tapes + audit. Closes netclaw-dev#1150.

3. simplify-netclaw-init — trims `netclaw init` to provider + identity
   + posture, adds existing-config refusal + --force backup-and-reset
   paths, post-flight nudge pointing operators at `netclaw config`.

All three validated with `openspec validate <change> --type change`.
Sequential dependencies: A enables the abstraction, B introduces the
command and editors, C cuts the long wizard. PR review can sequence
the implementation accordingly.

No production code changes in this PR; planning artifacts only.
Self-review pass on the three init/config UX changes surfaced real
issues. Fixes:

UI mockups landed in the repo (were stuck in ~/.claude/plans/):
- docs/ui/TUI-002-netclaw-config-wireframes.md (dashboard + 12
  editors + 8 page templates + doctor results + nudge)
- docs/ui/TUI-003-simplified-init-wireframes.md (3 init steps +
  post-flight + refusal + force-reset confirm)
- Each change's design.md references its corresponding wireframe
  document as the authoritative visual contract

ISectionEditor vs menu split (Change A):
- ISectionEditor gains `bool ShowInMenu` flag (default true)
- MenuRegistryAuditTests waives tape-existence check for
  ShowInMenu == false editors (e.g. Provider, Identity covered by
  init-wizard.tape and the netclaw provider CLI)
- Round-trip test + RelevantDoctorChecks contract still applies to
  every registered editor regardless of ShowInMenu

Schema/SectionId mismatches:
- Identity is NOT a top-level schema key; added to exemption list
  with category "synthetic-spans-multiple-sections" and
  ShowInMenu = false in Change A's tasks
- Top-level Security, Daemon, Tools added to exemption list in
  Change B's tasks with category "covered by another editor's
  dotted-path SectionId" naming the covering editor
- Exemption-list spec scenarios cover both top-level and
  dotted-path coverage

netclaw config show|validate reserved (Change B):
- Reserved subcommands now print an explicit "not yet implemented;
  PRD-004" notice and exit non-zero, preserving the documented
  future surface (previously rejected as unknown)

Important items tightened across the changes:
- Change B section editors explicitly REFACTOR existing init step
  viewmodels (not create duplicates) where the section already has
  an init step
- Daemon-restart nudge now specifies the PID-file + TCP probe with
  a 250 ms bound; timeout suppresses the nudge (conservative)
- In-place rename for list items now specifies originalKey/newKey
  tracking, secrets-store rekey, and array-position preservation
- BrowserAutomation schema-migration scenarios cover both the
  editor opening over a pre-existing config and doctor --fix
  auto-insert
- --force non-TTY refusal scenario added in Change C
- .bak filename collision handled via -1/-2 suffix; timestamp moves
  from unix-seconds to unix-millis
- Multi-instance editing and Test Connection partial-failure shape
  documented in Change B's design Risks section

All three changes re-validated:
  openspec validate section-editor-abstraction --type change  ✓
  openspec validate netclaw-config-command --type change      ✓
  openspec validate simplify-netclaw-init --type change       ✓
Wire Search into netclaw config so we can validate preserved-state section editing, semantic config and secrets saves, and probe-gated warnings before expanding the dashboard.
Preserve the active text input across redraws so inline edits keep their cursor position. Trim duplicate feedback so provider setup reads more cleanly.
Keep search backend setup on an explicit path from provider selection through validation and save. Preserve inactive backend settings so switching providers does not silently wipe prior configuration.
Return Esc from the saved state to the Search backend list instead of exiting the editor. Clarify the provider markers so active and configured backends are visually distinct.
Brings design/tui-prototype/ (browser mockup of the netclaw init + config
TUI) and its FINDINGS.md onto this line as the design source of truth for
reconciling the init/config UX and reworking validated-ui-components.

Squash-imported from branch claude-wt-netclaw-config-tui-design (full
13-commit history preserved there). FINDINGS.md records the validated UX
decisions, per-area corrections, the lighter validation stance (nullable
dynamic check, no analyzer, no mandatory commit object, typed probe
result), the keep/rework/delete/cancel tally, and the agreed process.
Companion to design/tui-prototype/FINDINGS.md. Defines the goal and the
task-level route to take both netclaw init and netclaw config through the
full OpenSpec lifecycle (reconcile -> apply -> verify -> sync -> archive)
and land the prototype-proven UX in Termina.

Grounded in the real task tallies on this branch: simplify-netclaw-init
0/30, netclaw-validated-ui-components 19/63 (revise lighter),
netclaw-config-command 60/67, section-editor-abstraction 42/42 (confirm).
Sequenced init -> infra -> config UX -> section-editor with the C# files,
spec deltas, and verification gates per step.
…-install menu

Reduce `netclaw init` from 11 steps to a minimal bootstrap — Provider →
Identity → Security Posture → Enabled Features (Personal skips) → Health
Check. Channels, Search, Browser Automation, and Skill Sources move to
`netclaw config`.

On an existing install, init now opens an explicit action menu (Redo identity
setup / Open configuration editor / Start over from scratch / Cancel) instead
of silently re-walking setup. "Open configuration editor" hands off to a shared
config-editor host; "Start over" runs a double-confirmed reset (setup-only vs
full). Identity stays init-owned and is editable on its own via a single-step
redo that writes only identity files. The post-flight summary nudges toward
`netclaw chat` and `netclaw config`.

Implements the simplify-netclaw-init OpenSpec change (archived). Validated with
the full CLI unit suite and the init-wizard + new init-existing smoke tapes.
…Sources validation

The validated-UI commit framework (NetclawUiCommit, the commit pipeline, the
NetclawValidated* components, SkillSourcesCommitFactory, and the never-built
Roslyn analyzer) was over-opinionated: it had a single consumer (Skill Sources)
yet forced every mutation through a generic pipeline. The TUI prototype
confirmed inline validation — the pattern every other config page already uses —
is the target.

Migrate Skill Sources to the Search editor's pattern: a lightweight result
record, inline structural validation, inline reachability probes, and the
shared probe-warning dialog, persisting through the view model's existing
section-preserving writers. The page is now presentational — an inverted audit
test enforces it never writes config directly.

Removes ~1145 net lines (5 framework files + 4 framework test files). The
superseded netclaw-validated-ui-components OpenSpec change is archived without
syncing its framework spec delta, so the main specs carry no framework mandates.
Full CLI suite green; config-ops-surfaces smoke green.
Align `netclaw config` with the validated TUI prototype:
- Dashboard shows a live status-summary column (e.g. `Search  ✓ Brave`,
  `Security & Access  Team · 4/6 enabled`) read fresh from config, with the
  focused row's description as a dim help line.
- Channels resolve a typed channel against the adapter BEFORE adding it; a
  non-resolving channel is rejected, a resolved one is added at the
  deployment-posture default audience and focused for ←/→ tuning.
- Telemetry & Alerting exposes the full NotificationsConfig.Webhooks list via a
  multi-webhook editor (Name / URL / one auth header, Format auto-detected from
  hooks.slack.com), replacing the single-webhook form.
- A unified full-width teal selection bar replaces the ▶/> marker prefixes
  across Channels, Security & Access, Skill Sources, Inbound Webhooks, and
  Telemetry, matching the dashboard.

Completes the netclaw-config-command OpenSpec change (archived) and adds the
autosave-consistency and section-preserving-persistence invariants to the main
spec. Full CLI suite green (1027 tests); config smoke tapes green.
The section-editor abstraction (ConfigEditorSession + the single-step
orchestrator) is the persistence seam that Skill Sources now migrates onto and
that the config leaf editors write through, so removing the validated-UI
framework confirmed its centrality rather than undermining it. Its delta is
already reflected in the main netclaw-onboarding spec; archived --skip-specs.
- smoke: drop the deleted init-wizard-reverse-proxy tape from LIGHT_TAPES (the
  rebase union wrongly retained it, red-ing run-smoke.sh light)
- config dashboard: read Browser Automation enablement from the canonical
  browser MCP server entries instead of a non-existent Browser.Enabled flag
- config host: drop the redundant NetclawPaths DI registration
- specs: de-duplicate the leaked ADDED requirements in netclaw-onboarding;
  document the shipped config UX (status dashboard, channels resolve-before-add,
  multi-webhook list, unified selection bar) in netclaw-config-command
- tests: cover skill-server token rotation (new/blank/probe-latch), the
  IdentityRedo don't-clobber-config invariant + Esc routing, the ConfigAutosave
  exception path, setup-only reset deletion semantics, and generalize the
  presentational-write audit guard across all config pages

Note: the review also flagged the /config host omitting ConfigureNativeSelection.
Enabling raw input there breaks the vhs config-* smoke tapes (authored for the
cooked-input config host), so it is intentionally deferred — see the code comment.

Full CLI suite 1039 green; slopwatch + headers clean.
Fixes surfaced while driving `netclaw config` interactively against the
prototype-proven design (see design/tui-prototype/MANUAL_REVIEW_FINDINGS.md).

- Native selection: the `/config` Termina host now calls ConfigureNativeSelection
  like every other host (init/provider/model/chat/...). It was the lone
  cooked-input host, so it enabled mouse tracking and broke native terminal
  drag-select.

- Inbound Webhooks enable-first: `Webhooks.Enabled` is only the feature toggle
  (the runtime 404s every request when no routes exist, so it is inert and
  default-deny). Enabling with no routes now persists with an advisory instead
  of a hard block, and the doctor check downgrades enabled-but-no-routes from
  Error to Warning. Matches inbound-webhooks/spec.md.

- Telemetry webhook form placeholders: ConfigSelectionRow gains a two-tone
  CreateLabeled (bright label, dim-gray placeholder, bright real value) so
  `(optional)` / the example URL no longer read as entered values; the URL
  example is prefixed `e.g.`.

- Skill Sources probe-driven disclosure: remote-feed add now matches SearXNG --
  enter URL, probe with no auth, and reveal the bearer-token field only on a
  401/403, then re-probe. Removes the upfront "No auth required / Bearer token"
  choice screen and its handlers. Also fixes two latent defects that prevented
  force-adding an unreachable open feed: ContinueAddRemoteUrl cleared the
  save-anyway fingerprint on every Enter, and the page re-staged the input on
  every Enter (clearing the fingerprint via MarkDirty through the real input
  pipeline).

Tests updated/added across all four areas (VM, doctor, page-integration,
coverage audit) and the config-surfaces smoke tape.
…sub-VM flag

The Channels editor save validated and probed an adapter using the picker's
Step.IsAdapterEnabled, but BuildContribution gated persistence on the
per-adapter sub-VM's *Enabled flag. When those two enabled-states disagreed, a
save validated + probed the adapter as enabled, then wrote only
{Adapter}.Enabled=false (dropping AllowedChannelIds and audiences) while
session.Save() ran and the status still showed "saved" — a success-reporting
silent half-write that lost channel config and bot tokens on disk.

BuildContribution now reads the single source of truth (Step.IsAdapterEnabled,
the same source dynamic validation uses) and threads `enabled` into the
per-adapter contributions; the sub-VM *Enabled flags remain reload-sync targets
but no longer decide whether a section is written. A save can no longer report
success while half-writing an adapter the editor treats as enabled.

Adds an invariant regression test (Save()==true implies the enabled adapter's
section + secret reached disk; proven load-bearing) plus an end-to-end
navigation test that enables Slack by name and Discord by id, escapes, and
asserts both sections and bot tokens survive on disk.
…rves an existing Daemon

WizardConfigBuilder seeds the output from the existing config to preserve
sections the wizard doesn't touch. After rebasing onto dev's UpdateChannel
preservation (which deliberately leaves the typed Daemon null for a default
`stable` channel), that seed carried the stale `Daemon: { UpdateChannel:
"stable" }` straight through to disk.

When no typed Daemon is contributed, strip a default `stable` UpdateChannel
from the copied Daemon and drop the section only if nothing else remains; a
Daemon carrying real fields (exposure mode, host, proxies, port) stays
preserved, so the exposure editor's section-contribution merge is unaffected.
@Aaronontheweb Aaronontheweb force-pushed the docs/netclaw-validated-ui-components branch from 6ed2445 to 91422b4 Compare June 10, 2026 03:24
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.

1 participant