Skip to content

feat(tui): make configure gate a forced setup - #78

Merged
quickbeard merged 2 commits into
mainfrom
force-configure-gate
Jul 14, 2026
Merged

quickbeard merged 2 commits into
mainfrom
force-configure-gate

Conversation

@quickbeard

Copy link
Copy Markdown
Owner

Summary

The first-run Configure CoDev Code gate can no longer be escaped into an unconfigured chat. Previously Option 2 (Custom provider) and Option 3 (Connect provider) each dropped the user into chat if they hit Esc — the code comments literally said "escaping here lands in an unconfigured chat." This closes that.

Approach

Instead of freezing Esc per-step (which for Option 3 would mean invasive edits across upstream's multi-step dialog-provider.tsx, and would also kill Esc inside OAuth and remove in-flow back-navigation), the gate now re-asserts itself. The one-shot open-on-startup effect in app.tsx becomes a stateless invariant:

createEffect(() => {
  if (sync.status !== "complete") return
  if (connected()) return
  if (dialog.stack.length > 0) return
  dialog.replace(() => <DialogConfigure />)
})

While unconfigured with no dialog open, the gate (re)opens. Consequences, all desired (confirmed with the requester):

  • Esc at any depth of Option 2 or Option 3 → stack empties → gate reopens ("back to the gate"). Works for upstream's Connect-provider dialog with zero upstream edits.
  • Credential-only save (Option 2, empty base URL) → provider isn't usable, connected() stays false → gate reopens ("block it").
  • Errors / cancels → gate reopens. Only a real provider or double-Ctrl+C (quit) leaves the gate.
  • A configured user is never trapped — connected() is true, so /connect, /models, and /configure stay dismissable to chat.

Scope note: an unconfigured user who opens /connect or /models manually and escapes also bounces to the gate — a natural consequence of "force configuration," and the same mechanism that makes Option 3 work without touching upstream.

Changes

  • packages/tui/src/app.tsx: transition-only gate effect → the invariant; dropped the now-unused on import.
  • packages/tui/src/component/dialog-configure.tsx: refreshed the two stale Option 2/3 comments.
  • DIVERGENCES.md: updated the existing app.tsx row.

Test plan

  • packages/tui: typecheck green; 220 pass / 1 fail — the pre-existing app-lifecycle epilogue flake, identical on clean main.
  • End-to-end in tmux (mock /v1/models, isolated XDG dirs), all confirmed:
    • Option 2, Esc at the API-key step → back to gate.
    • Option 2, empty base URL → credential saved (toast) → back to gate.
    • Option 3 → Anthropic → Esc at the depth-2 API-key step → back to gate.
    • Full success (mockgw + models) → lands in chat, gate does not reopen.
    • Configured user: /connect then Esc → returns to chat (not trapped).

🤖 Generated with Claude Code

quickbeard and others added 2 commits July 14, 2026 15:38
The first-run gate is now inescapable into an unconfigured chat. Replace
the one-shot open-on-startup effect with a stateless invariant: while
sync is complete, no provider is connected, and the dialog stack is
empty, (re)open DialogConfigure.

Escaping any gate-launched flow — Custom provider or upstream's Connect
provider dialog, at any depth — a credential-only save, or any error
empties the stack and bounces back to the gate instead of chat. Only a
real provider (connected() true) or quitting (double Ctrl+C) leaves it.
This needs no per-step escape handling and leaves upstream's connect
dialog untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Unit-test the gate open-condition (extracted as shouldOpenConfigureGate)
across all four branches. E2e-test the wiring: the gate opens on an
unconfigured startup, escaping the Connect-provider dialog bounces back
to it, and a configured provider keeps it closed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@quickbeard
quickbeard merged commit 56b5a47 into main Jul 14, 2026
5 checks passed
@quickbeard
quickbeard deleted the force-configure-gate branch July 14, 2026 08:49
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