resolveStateRoot function
Resolves the state root for one run: the parsed kStateRootOption when it
carries a non-blank path, else the station-injected fallback. Null when
neither names one — the state store is then NOT consulted.
The public contract is the GRID HOME, exactly as kStateRootHelp says and
exactly as --grid-home takes it everywhere else on the runner, so a
selected root that holds a .grid directory resolves to that child. A path
that is already the state store (it holds .beads) resolves to itself, and
a home holding both prefers .grid.
Guards LOUD or GONE (the D-H doctrine, ADR-0008): a root holding neither child is REFUSED by StateError naming the root and both expected children, because a verb that silently accepted an unrelated root would report it as fine.
Implementation
String? resolveStateRoot(ArgResults results, String? Function() fallback) {
final option = results.option(kStateRootOption)?.trim();
final selected = option == null || option.isEmpty
? fallback()?.trim()
: option;
if (selected == null || selected.isEmpty) return null;
final root = p.normalize(selected);
final store = p.join(root, _stateStoreDir);
if (Directory(store).existsSync()) return store;
if (Directory(p.join(root, _beadsDir)).existsSync()) return root;
throw StateError(
'--state-root "$root" is neither a grid home (no $_stateStoreDir '
'directory) nor a state store (no $_beadsDir directory)',
);
}