feat(welcome): New project flow + per-repo account roadblock (T-488)

The UI half of the new-project flow (story T-486). A "New project…" welcome
action opens a dialog (location + name) that dispatches project.new (T-487),
opens the result, and announces it on projectCreatedChannel. The Claude
extension consumes that and shows the account roadblock — the embedded
per-workspace picker + accounts list, so a fresh project gets bound to an
account (or Default) right at birth.

The two halves stay decoupled: the welcome builtin only publishes the event
(no claude import); the claude builtin owns the account dialog. Only freshly-
created projects announce, so existing opens are never prompted.

Closes T-488. The non-repo "initialize as a project" path (T-489) is next.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 08:35:30 +02:00
co-authored by Claude Opus 4.8
parent adaf8966dc
commit 25430686cc
11 changed files with 439 additions and 0 deletions
+7
View File
@@ -15,6 +15,13 @@ import '../ipc/envelope.dart';
import '../ipc/schema_v1.dart';
import 'dispatcher.dart';
/// MessageBus channel announcing a freshly-created project (path in `dir`). The
/// welcome new-project dialog publishes it after create + open; the Claude
/// extension consumes it to show the per-repo account roadblock (T-488) — only
/// NEW projects prompt, existing opens never do. Lives here in the neutral
/// daemon layer so both builtins name one literal without coupling to each other.
const projectCreatedChannel = 'project.created';
/// Runs `git init` in [dir]. Injected so this stays Flutter-free + testable;
/// main.dart wires it to the real toolchain.
typedef ProjectGitInit = Future<void> Function(String dir);