parseAppConfigSections function
Parses the already-loaded yaml documents into AppFahSections.
Every section parse is isolated: a malformed section records a warning naming its file + section and falls back to the default, never poisoning the other sections (AC7). Throws nothing.
Implementation
AppFahSections parseAppConfigSections({
Object? userDoc,
Object? projectDoc,
Object? projectRulesDoc,
String userSource = '~/.fah/config.yaml',
String projectSource = '.fah/config.yaml',
String projectRulesSource = '.fah/rules.yaml',
String? envMode,
}) {
final warnings = <String>[];
final user = _coerceScopeDoc(userDoc, userSource, warnings);
final project = _coerceScopeDoc(projectDoc, projectSource, warnings);
final roles = _parseRolesSection(user, userSource, warnings);
// tools: — both scopes parse independently; the caller stacks them
// (global < project < runtime) in the live resolution.
final userTools = _parseTools(user?['tools'], userSource, warnings);
final projectTools = _parseTools(
project?['tools'],
projectSource,
warnings,
);
final ttsr = _parseTtsrSection(
user,
userSource,
projectRulesDoc,
projectRulesSource,
warnings,
);
final redact = _parseRedactSection(user, userSource, warnings);
final providerTimeouts = _parseTimeoutsSection(user, userSource, warnings);
final loadMode = _resolveLoadMode(envMode, user, userSource, warnings);
// Inventory #2 interim: `mcp:` stays CLI-only on mobile — say so instead
// of silently ignoring it.
final mcpConfigured = user?['mcp'] != null;
if (mcpConfigured) {
warnings.add(
'mcp section in $userSource is not consumed by the app yet '
'(MCP servers connect through the CLI harness)',
);
}
return AppFahSections(
roles: roles,
ttsr: ttsr,
userTools: userTools,
projectTools: projectTools,
redact: redact,
providerTimeouts: providerTimeouts,
loadMode: loadMode,
mcpConfigured: mcpConfigured,
warnings: warnings,
userDoc: userDoc,
);
}