refactor: rename internal Fai* design system + fai_ helpers to chain
Some checks failed
Security / Security check (push) Failing after 2s

The Studio design system, widgets and helpers carried a Fai* / fai_
prefix (FaiSpace, FaiColors, FaiTheme, FaiLog, 17 fai_*.dart files, the
faiBinary* l10n keys). Studio is the Ch∆In product, so rename them to
Chain* / chain_ — carefully preserving English fail/failure/failed.
Also fix stale references: the 'fai' binary in l10n strings -> 'chain',
FAI_* env vars (FAI_BIN/DATA_DIR/MODULES_DIR/TODAY/BOOTSTRAP_TOKEN) ->
CHAIN_*, fai_platform -> fai_chain, fai_hub -> chain_hub. Vendor
security-hook tooling (FAI_BANNED_TERMS_FILE) + the .fai bundle ext left.
flutter analyze + test: clean (20 passed).

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-06-16 17:53:17 +02:00
parent 68d23ab7dd
commit 891acd2ba2
52 changed files with 1225 additions and 1225 deletions

View file

@ -26,10 +26,10 @@ import 'dart:io';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
class FaiLog {
FaiLog._();
class ChainLog {
ChainLog._();
static final FaiLog instance = FaiLog._();
static final ChainLog instance = ChainLog._();
// Serialise concurrent writes Future-based mutex so a burst
// of errors (rare but happens during failed install retries)

View file

@ -16,9 +16,9 @@
import 'package:flutter/material.dart';
import '../widgets/fai_error_box.dart';
import '../widgets/chain_error_box.dart';
import '../theme/tokens.dart';
import 'fai_log.dart';
import 'chain_log.dart';
/// Show [error] as a SnackBar with a copy affordance.
///
@ -41,7 +41,7 @@ void showFaiErrorSnack(
}) {
// Fire-and-forget log write. If the disk's full or the dir
// is read-only the UI still surfaces the error.
FaiLog.instance.error(source, error, context: title);
ChainLog.instance.error(source, error, context: title);
final messenger = ScaffoldMessenger.maybeOf(context);
if (messenger == null) {
// No Scaffold above the caller is likely showing the
@ -60,8 +60,8 @@ void showFaiErrorSnack(
padding: EdgeInsets.zero,
content: Padding(
padding: const EdgeInsets.symmetric(
horizontal: FaiSpace.sm,
vertical: FaiSpace.xs,
horizontal: ChainSpace.sm,
vertical: ChainSpace.xs,
),
child: Column(
mainAxisSize: MainAxisSize.min,
@ -75,9 +75,9 @@ void showFaiErrorSnack(
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: FaiSpace.xs),
const SizedBox(height: ChainSpace.xs),
],
FaiErrorBox(error: error, isError: true),
ChainErrorBox(error: error, isError: true),
],
),
),
@ -94,14 +94,14 @@ Future<void> showFaiErrorDialog(
Object error, {
String? title,
}) async {
FaiLog.instance.error(source, error);
ChainLog.instance.error(source, error);
return showDialog<void>(
context: context,
builder: (ctx) => AlertDialog(
title: title == null ? null : Text(title),
content: SizedBox(
width: 480,
child: FaiErrorBox(error: error, isError: true, maxHeight: 240),
child: ChainErrorBox(error: error, isError: true, maxHeight: 240),
),
actions: [
TextButton(

View file

@ -161,7 +161,7 @@ class StudioFlowRunDriver implements editor.FlowRunDriver {
/// (text / json / bytes only). File outputs degrade to
/// JSON containing the URI string the editor's run-tab
/// renderer is read-only so the operator can still see
/// where the file went; Studio's richer FaiFlowOutput
/// where the file went; Studio's richer ChainFlowOutput
/// widget keeps file-open affordances available elsewhere.
editor.FlowOutputValue _convertOutput(FlowOutput out) {
return switch (out) {

View file

@ -1,4 +1,4 @@
// HubService singleton wrapper around fai_dart_sdk's HubClient.
// HubService singleton wrapper around chain_dart_sdk's HubClient.
//
// Centralises the gRPC connection so each page just imports
// `HubService.instance` instead of constructing its own client.
@ -1282,7 +1282,7 @@ class SatelliteEnrollment {
return 'federation:\n'
' upstream: https://<this-primary-host>:<federation-port>\n'
' hub_name: $name\n'
' bootstrap_token_env: FAI_BOOTSTRAP_TOKEN$ca';
' bootstrap_token_env: CHAIN_BOOTSTRAP_TOKEN$ca';
}
}
@ -1553,7 +1553,7 @@ class HardwareSnapshot {
}
/// One curated model with editorial metadata. Wire-faithful
/// with `crates/fai_hub/system-ai/models.yaml`.
/// with `crates/chain_hub/system-ai/models.yaml`.
class CuratedModelInfo {
final String id;
final String family;

View file

@ -4,7 +4,7 @@ import 'package:path/path.dart' as p;
/// Operator-managed registry auth token, kept at
/// `~/.chain/registry-token` (mode 0600 on Unix). The hub reads
/// this file at install time when `CHAIN_REGISTRY_TOKEN` is unset
/// see `download_to_temp` in `crates/fai_hub/src/lib.rs`.
/// see `download_to_temp` in `crates/chain_hub/src/lib.rs`.
///
/// Studio writes the file directly so a fresh install never
/// requires the operator to fiddle with shell env vars.

View file

@ -22,7 +22,7 @@ import 'package:shared_preferences/shared_preferences.dart';
/// Sentinel returned in `_runFai(...).stderr` when no `fai`
/// binary could be located. UI layers should not display this
/// verbatim they check [SystemActions.faiBinaryExists] first
/// verbatim they check [SystemActions.chainBinaryExists] first
/// and render a localized, actionable message instead.
const String kFaiBinaryNotFound = 'fai-binary-not-found';
@ -37,7 +37,7 @@ class SystemActions {
/// SharedPreferences key for an operator-chosen `fai` binary
/// path (set via the file picker when auto-detection fails).
static const String _kFaiBinaryPrefKey = 'system.fai_binary_path';
static const String _kFaiBinaryPrefKey = 'system.chain_binary_path';
/// In-memory cache of the operator override, loaded once at
/// startup by [loadFaiBinaryOverride]. Null = no override.
@ -71,7 +71,7 @@ class SystemActions {
/// the canonical install dir). UI uses this to decide between
/// the normal daemon-control affordances and the "locate the
/// binary / read the install guide" recovery path.
static bool faiBinaryExists() => _faiExecutable() != null;
static bool chainBinaryExists() => _faiExecutable() != null;
/// Ask the OS to open [path] in the default handler. On macOS
/// this opens text files in TextEdit, configs in the registered
@ -137,7 +137,7 @@ class SystemActions {
/// Run a `chain daemon ...` subcommand and surface the captured
/// output. Used by Doctor's "Restart daemon" button.
static Future<({bool ok, String stdout, String stderr})> faiDaemon(
static Future<({bool ok, String stdout, String stderr})> chainDaemon(
List<String> args,
) async {
return _runFai(['daemon', ...args]);
@ -145,7 +145,7 @@ class SystemActions {
/// Run `chain update apply --channel <c>`. Long-running on a slow
/// network caller should show a spinner.
static Future<({bool ok, String stdout, String stderr})> faiUpdateApply(
static Future<({bool ok, String stdout, String stderr})> chainUpdateApply(
String channel,
) async {
return _runFai(['update', 'apply', '--channel', channel]);
@ -154,7 +154,7 @@ class SystemActions {
/// Switch the active channel pointer at `~/.chain/current-channel`.
/// The CLI also restarts the daemon for the new channel, so the
/// caller does not need a follow-up restart.
static Future<({bool ok, String stdout, String stderr})> faiChannelSwitch(
static Future<({bool ok, String stdout, String stderr})> chainChannelSwitch(
String channel,
) async {
return _runFai(['channel', 'switch', channel]);
@ -164,14 +164,14 @@ class SystemActions {
/// (launchd plist on macOS, systemd-user unit on Linux). On
/// Windows the platform CLI returns a "not supported" exit
/// status that the caller surfaces as an error message.
static Future<({bool ok, String stdout, String stderr})> faiDaemonEnable(
static Future<({bool ok, String stdout, String stderr})> chainDaemonEnable(
String channel,
) async {
return _runFai(['daemon', 'enable', '--channel', channel]);
}
/// Remove the autostart unit installed by [faiDaemonEnable].
static Future<({bool ok, String stdout, String stderr})> faiDaemonDisable(
/// Remove the autostart unit installed by [chainDaemonEnable].
static Future<({bool ok, String stdout, String stderr})> chainDaemonDisable(
String channel,
) async {
return _runFai(['daemon', 'disable', '--channel', channel]);
@ -186,7 +186,7 @@ class SystemActions {
///
/// Studio's gRPC channel goes down for ~1s while the daemon
/// restarts caller should follow up with a reconnect.
static Future<({bool ok, String stdout, String stderr})> faiReset({
static Future<({bool ok, String stdout, String stderr})> chainReset({
bool keepModules = false,
bool keepData = false,
}) async {
@ -202,9 +202,9 @@ class SystemActions {
final exe = _faiExecutable();
if (exe == null) {
// Sentinel, not a user-facing string. Callers detect this
// via `faiBinaryExists()` and render a localized,
// via `chainBinaryExists()` and render a localized,
// actionable recovery message (locate binary / install
// guide) instead of CLI jargon like "set FAI_BIN".
// guide) instead of CLI jargon like "set CHAIN_BIN".
return (ok: false, stdout: '', stderr: kFaiBinaryNotFound);
}
try {
@ -226,7 +226,7 @@ class SystemActions {
}
/// Locate the `fai` binary. Order: operator override (set via
/// the file picker), $FAI_BIN, PATH, fallback to the canonical
/// the file picker), $CHAIN_BIN, PATH, fallback to the canonical
/// install location under the user's home dir.
static String? _faiExecutable() {
final override = _faiBinaryOverride;
@ -236,7 +236,7 @@ class SystemActions {
return override;
}
final fromEnv = Platform.environment['FAI_BIN'];
final fromEnv = Platform.environment['CHAIN_BIN'];
if (fromEnv != null && fromEnv.isNotEmpty && File(fromEnv).existsSync()) {
return fromEnv;
}

View file

@ -16,7 +16,7 @@ import 'hub.dart';
/// SharedPreferences key for the operator's preferred theme
/// plugin. `null` (or absent) means "use Studio's built-in
/// default" (FaiTheme.light / .dark).
/// default" (ChainTheme.light / .dark).
const _kThemePluginKey = 'theme_plugin_capability';
/// One ColorScheme pair as built from a theme-plugin's
@ -96,14 +96,14 @@ Future<ThemePluginSchemes> loadThemePluginSchemes(String capability) async {
}
/// Build a `ThemeData` from a plugin-supplied `ColorScheme`.
/// Delegates to [FaiTheme.fromColorScheme] so plugin-themed
/// Delegates to [ChainTheme.fromColorScheme] so plugin-themed
/// builds and built-in themes share one structural shape same
/// textTheme cascade, same component themes, same `inherit`
/// values on every TextStyle. Without that, Flutter's
/// AnimatedDefaultTextStyle lerp blows up when swapping between
/// the two paths.
ThemeData themeDataFromScheme(ColorScheme scheme) =>
FaiTheme.fromColorScheme(scheme);
ChainTheme.fromColorScheme(scheme);
/// Translate the plugin's 14 ARGB tokens into a `ColorScheme`.
/// Order matches the plugin contract: