Files
clide/app/lib/main.dart
T
jpmschweitzerandClaude e2b3f7cff1
test / unit + widget + golden + a11y (push) Successful in 4m34s
test / integration_test (xvfb) (push) Failing after 1m4s
test / bundle smoke (xvfb 5s) (push) Failing after 58s
test / daemon subprocess + web WASM smoke (push) Successful in 2m27s
update CLAUDE.md and reserve decision/ticket/claude-control slots
CLAUDE.md gains a "Decision discipline" guardrail pointing at
decisions/<domain>.md, rewrites every inline ADR link to the new
anchor-link style (ADR 0001 → D-001, etc.), collapses the bottom
"Open questions" section to a one-line pointer, and updates the
parent-project note to reference decisions/architecture.md instead
of the deleted docs/ADRs/.

Three extension slots are reserved with id-only stubs, registered
alongside the existing 21 built-ins in main.dart:
  - builtin.decisions — future sidebar for D/Q/R records
  - builtin.tickets — future sidebar + kanban workspace
  - builtin.claude-control — future .claude/ first-class surface
    (Settings / Skills / Agents / Hooks / MCP). Distinct from the
    existing builtin.claude PTY-pane stub.

`flutter analyze` clean; builtin + a11y test suites still pass.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 17:32:06 +02:00

126 lines
4.8 KiB
Dart

import 'package:clide_app/app.dart';
import 'package:clide_app/builtin/canvas/canvas.dart';
import 'package:clide_app/builtin/claude/claude.dart';
import 'package:clide_app/builtin/claude_control/claude_control.dart';
import 'package:clide_app/builtin/decisions/decisions.dart';
import 'package:clide_app/builtin/default_layout/default_layout.dart';
import 'package:clide_app/builtin/diff/diff.dart';
import 'package:clide_app/builtin/editor/editor.dart';
import 'package:clide_app/builtin/extensions_ui/extensions_ui.dart';
import 'package:clide_app/builtin/files/files.dart';
import 'package:clide_app/builtin/git/git.dart';
import 'package:clide_app/builtin/grammars_core/grammars_core.dart';
import 'package:clide_app/builtin/graph/graph.dart';
import 'package:clide_app/builtin/ipc_status/ipc_status.dart';
import 'package:clide_app/builtin/jira/jira.dart';
import 'package:clide_app/builtin/keybindings_ui/keybindings_ui.dart';
import 'package:clide_app/builtin/markdown/markdown.dart';
import 'package:clide_app/builtin/pql/pql.dart';
import 'package:clide_app/builtin/problems/problems.dart';
import 'package:clide_app/builtin/settings_ui/settings_ui.dart';
import 'package:clide_app/builtin/terminal/terminal.dart';
import 'package:clide_app/builtin/theme_picker/theme_picker.dart';
import 'package:clide_app/builtin/tickets/tickets.dart';
import 'package:clide_app/builtin/todos/todos.dart';
import 'package:clide_app/builtin/welcome/welcome.dart';
import 'dart:io' show Directory, Platform;
import 'package:clide_app/kernel/kernel.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:flutter/widgets.dart';
Future<void> main() async {
final binding = WidgetsFlutterBinding.ensureInitialized();
// Enable the semantics tree at boot so screen readers (Orca, VoiceOver,
// NVDA) + the headless-browser automation harness both work out of the
// box. Production release builds could gate this on a platform check,
// but a11y-first means always-on.
binding.ensureSemantics();
final appDir = await _resolveAppDir();
final themes = await _loadBundledThemes();
final services = await KernelServices.boot(
appDir: appDir,
bundledThemes: themes,
i18nLoader: AssetCatalogLoader(bundle: rootBundle),
preloadNamespaces: _tier0Namespaces,
// The local unix-socket daemon is desktop-only. On web the
// connection indicator stays `disconnected` — that's the honest
// state: the Flutter-web build can't reach a local socket.
autoStartDaemonClient: !kIsWeb,
socketPath: kIsWeb ? '/clide-web-no-socket' : null,
);
// Register every built-in. Tier 0 activates only the four that do
// real work; the rest compile in as stubs so the extensions-ui can
// list them when Tier 6 lands.
services.extensions
..register(DefaultLayoutExtension())
..register(WelcomeExtension())
..register(IpcStatusExtension())
..register(ThemePickerExtension())
..register(ClaudeExtension())
..register(TerminalExtension())
..register(FilesExtension())
..register(EditorExtension())
..register(GrammarsCoreExtension())
..register(MarkdownExtension())
..register(DiffExtension())
..register(GitExtension())
..register(PqlExtension())
..register(TodosExtension())
..register(ProblemsExtension())
..register(JiraExtension())
..register(CanvasExtension())
..register(GraphExtension())
..register(SettingsUiExtension())
..register(ExtensionsUiExtension())
..register(KeybindingsUiExtension())
..register(DecisionsExtension())
..register(TicketsExtension())
..register(ClaudeControlExtension());
await services.extensions.activateAll();
runApp(ClideApp(services: services));
}
/// Resolve the app-settings directory.
///
/// On web we don't touch the filesystem — hand back a sentinel dir so
/// `SettingsStore.load()` silently no-ops (its read-file helper returns
/// `{}` when the file doesn't exist).
Future<Directory> _resolveAppDir() async {
if (kIsWeb) return Directory('/clide-web-no-disk');
final home = Platform.environment['HOME'] ?? '/tmp';
final xdg = Platform.environment['XDG_CONFIG_HOME'] ?? '$home/.config';
final dir = Directory('$xdg/clide');
await dir.create(recursive: true);
return dir;
}
Future<List<ThemeDefinition>> _loadBundledThemes() async {
const loader = ThemeLoader();
const paths = [
'lib/kernel/src/theme/themes/summer-night.yaml',
];
final out = <ThemeDefinition>[];
for (final p in paths) {
out.add(await loader.fromAsset(rootBundle, p));
}
return out;
}
/// Every Tier-0 extension that ships an i18n catalog. Extensions
/// registered but not active (the 17 stubs) don't preload — their
/// catalogs load lazily on activate in later tiers.
const List<String> _tier0Namespaces = [
'builtin.default-layout',
'builtin.welcome',
'builtin.ipc-status',
'builtin.theme-picker',
];