§9 acceptance: grep-zero sweep — every internal x.ai/grok identifier renamed

The PRD's first acceptance gate now holds: grep -RinE '\bx\.ai\b|grok'
crates/ --include='*.rs' → 0 matches (exempt: NOTICE and third-party
license archives, README provenance, and the required 'Based on Grok
Build Open Source' attribution, now sourced from version_attribution.txt).

Wire-visible renames (both sides in this repo, changed in lockstep):
- Auth method id 'grok.com' → 'kimi-code' (AuthMethodKind::KimiCode).
- Every x.ai/* and _x.ai/* ACP ext method and meta key → kigi/* /
  _kigi/* (~200 names; grokShell → kigiShell). Session-file replay keeps
  a read-side alias for the legacy '_x.ai/session/update' method so
  existing updates.jsonl histories load; writes emit only the new name
  (both directions test-pinned).
- Agent types grok-build* → kigi* with a documented legacy-prefix alias
  at resolution time so persisted sessions keep resolving.
- ToolNamespace/BuiltinAgentName GrokBuild* → Kigi* (wire snake_case
  kigi/kigi_concise/kigi_hashline; schema regenerated); grok_build
  implementation dirs renamed to kigi*.
- x-grok-* headers → x-kigi-*, __GROK_* sentinels → __KIGI_*, themes
  grokday/groknight → kigiday/kiginight (old persisted values fall back
  to the default theme), web_fetch allowlist xAI hosts → kimi.com +
  moonshot platforms, changelog CDN → this repo, grok-build changelog
  archives deleted.
- BYOK default endpoint removed: [endpoints] api_base_url is now truly
  optional with NO default — consumers fail fast with the flag name when
  unset (no silent x.ai egress). Mock harnesses inject it explicitly.
- System-prompt identity fixed: 'released by xAI' → 'an unofficial
  community CLI for Kimi' (template + regenerated encrypted form).

Also repaired pre-existing grok-era test debt found by the sweep: the
stale trace_classify default-model pin, the grok-pager UA label test,
pty-harness stale-binary reuse and non-hermetic moonshot routing (a PTY
test could previously reach the real api.moonshot.cn), and the outdated
oauth fixture scope key.

Gates: §9 grep 0; fmt clean; workspace check/clippy 0/0 (-D warnings);
FULL cargo test --workspace: 234 suites, 21,961 passed, 0 failed;
deny advisories ok.
This commit is contained in:
2026-07-18 02:48:46 -04:00
parent 86e3724310
commit 6f31415ed6
1056 changed files with 8410 additions and 18307 deletions
@@ -1,6 +1,6 @@
//! Stable per-install agent identifier.
//!
//! Stamped on requests (`x-grok-agent-id` / `x_grok_agent_id`) so the backend
//! Stamped on requests (`x-kigi-agent-id` / `x_kigi_agent_id`) so the backend
//! can bucket by install. Cached in `$KIGI_SHARE_DIR/agent_id` so every process on
//! this install (and restarts) agree; the in-memory `OnceLock` makes repeat
//! calls free.
@@ -12,7 +12,7 @@ static AGENT_ID: OnceLock<String> = OnceLock::new();
/// Cached agent instance ID — per-process lifetime.
static AGENT_INSTANCE_ID: OnceLock<String> = OnceLock::new();
/// Returns the per-install agent ID, backed by a file cache under the grok
/// Returns the per-install agent ID, backed by a file cache under the kigi
/// home so it is stable across process restarts.
pub fn agent_id() -> String {
AGENT_ID.get_or_init(load_or_compute_agent_id).clone()
@@ -74,7 +74,7 @@ fn dismiss_campaign_ids_at(
let _guard = DISMISS_LOCK.lock().unwrap_or_else(|p| p.into_inner());
let path = campaigns_state_path(home);
// Cross-process advisory lock over the read-modify-write: in leader mode
// several grok processes share `$KIGI_SHARE_DIR`; the in-process mutex alone would
// several kigi processes share `$KIGI_SHARE_DIR`; the in-process mutex alone would
// let them lose-update the set. Best-effort; a lock failure still proceeds.
let lock = std::fs::OpenOptions::new()
.create(true)
@@ -142,7 +142,7 @@ mod tests {
fn test_models_default_parsing() {
let toml_str = r#"
[models]
default = "grok-code-fast-1"
default = "kigi-code-fast-1"
"#;
let root: TomlValue = toml::from_str(toml_str).unwrap();
if let TomlValue::Table(table) = root
@@ -152,7 +152,7 @@ default = "grok-code-fast-1"
.get("default")
.and_then(|v| v.as_str())
.map(|s| s.to_string());
assert_eq!(default.as_deref(), Some("grok-code-fast-1"));
assert_eq!(default.as_deref(), Some("kigi-code-fast-1"));
} else {
panic!("Expected models table");
}
@@ -198,7 +198,7 @@ secret = "my-secret-token"
fn test_remote_secret_no_section() {
let toml_str = r#"
[models]
default = "grok-code-fast-1"
default = "kigi-code-fast-1"
"#;
let root: TomlValue = toml::from_str(toml_str).unwrap();
if let TomlValue::Table(table) = root {
@@ -1329,7 +1329,7 @@ auto_update = true
// Test with no cli section at all
let toml_str = r#"
[models]
default = "grok-code-fast-1"
default = "kigi-code-fast-1"
"#;
let root: TomlValue = toml::from_str(toml_str).unwrap();
if let TomlValue::Table(ref table) = root {
@@ -1374,7 +1374,7 @@ auto_update = true
fn test_use_leader_opt_returns_none_when_no_cli_section() {
let toml_str = r#"
[models]
default = "grok-code-fast-1"
default = "kigi-code-fast-1"
"#;
let root: TomlValue = toml::from_str(toml_str).unwrap();
assert_eq!(use_leader_from_toml_opt(&root), None);
@@ -1702,10 +1702,10 @@ expose_image_base64 = true
#[test]
fn mcp_json_all_toml_names_includes_disabled() {
let tmp = tempfile::tempdir().unwrap();
let grok_dir = tmp.path().join(".kigi");
std::fs::create_dir_all(&grok_dir).unwrap();
let kigi_dir = tmp.path().join(".kigi");
std::fs::create_dir_all(&kigi_dir).unwrap();
std::fs::write(
grok_dir.join("config.toml"),
kigi_dir.join("config.toml"),
r#"
[mcp_servers.enabled_one]
url = "https://example.com"
@@ -344,7 +344,7 @@ mod tests {
#[test]
fn permission_mode_from_ui_if_set_none_when_no_keys() {
let theme: TomlValue = toml::from_str("[ui]\ntheme = \"groknight\"\n").unwrap();
let theme: TomlValue = toml::from_str("[ui]\ntheme = \"kiginight\"\n").unwrap();
assert_eq!(
permission_mode_from_ui_if_set(theme.get("ui").unwrap()),
None,
@@ -459,7 +459,7 @@ mod tests {
"ask",
),
// No permission keys → Ask.
("[ui]\ntheme = \"groknight\"\n", PermissionMode::Ask, "ask"),
("[ui]\ntheme = \"kiginight\"\n", PermissionMode::Ask, "ask"),
];
for (toml_str, expected_mode, expected_canonical) in cases {
let root: TomlValue = toml::from_str(toml_str).unwrap();
@@ -423,7 +423,7 @@ mod tests {
ui.insert("show_timestamps".into(), TomlValue::Boolean(true));
ui.insert(
"auto_light_theme".into(),
TomlValue::String("grokday".into()),
TomlValue::String("kigiday".into()),
);
table.insert("ui".into(), TomlValue::Table(ui));
@@ -446,7 +446,7 @@ mod tests {
);
assert_eq!(
ui.get("auto_light_theme").and_then(|v| v.as_str()),
Some("grokday"),
Some("kigiday"),
"pre-existing field not in serialized output should be preserved"
);
}
@@ -619,7 +619,7 @@ mod tests {
yolo = true
show_timestamps = false
auto_dark_theme = "tokyonight"
auto_light_theme = "grokday"
auto_light_theme = "kigiday"
"#;
let root: TomlValue = toml::from_str(toml_str).unwrap();
let cfg = load_config_from_toml(&root);
@@ -627,7 +627,7 @@ auto_light_theme = "grokday"
assert!(cfg.ui.yolo);
assert_eq!(cfg.ui.show_timestamps, Some(false));
assert_eq!(cfg.ui.auto_dark_theme.as_deref(), Some("tokyonight"));
assert_eq!(cfg.ui.auto_light_theme.as_deref(), Some("grokday"));
assert_eq!(cfg.ui.auto_light_theme.as_deref(), Some("kigiday"));
// Simulate save_config: serialize back through merge_section
let mut table = root.as_table().unwrap().clone();
@@ -644,7 +644,7 @@ auto_light_theme = "grokday"
);
assert_eq!(
ui.get("auto_light_theme").and_then(|v| v.as_str()),
Some("grokday")
Some("kigiday")
);
assert_eq!(ui.get("yolo").and_then(|v| v.as_bool()), Some(true));
}
@@ -730,10 +730,10 @@ auto_light_theme = "grokday"
[ui]
show_timestamps = true
auto_dark_theme = "tokyonight"
auto_light_theme = "grokday"
auto_light_theme = "kigiday"
[models]
default = "grok-3"
default = "kigi-3"
[cli]
auto_update = true
@@ -742,7 +742,7 @@ auto_update = true
let mut cfg = load_config_from_toml(&root);
// User changes default model (unrelated to UI)
cfg.models.default = Some("grok-4".to_string());
cfg.models.default = Some("kigi-4".to_string());
// Simulate save_config
let mut table = root.as_table().unwrap().clone();
@@ -763,14 +763,14 @@ auto_update = true
);
assert_eq!(
ui.get("auto_light_theme").and_then(|v| v.as_str()),
Some("grokday")
Some("kigiday")
);
// Verify the model change went through
let models = table.get("models").unwrap().as_table().unwrap();
assert_eq!(
models.get("default").and_then(|v| v.as_str()),
Some("grok-4")
Some("kigi-4")
);
}
@@ -823,7 +823,7 @@ auto_update = true
#[test]
fn models_config_serializes_only_some_fields() {
let m = crate::agent::config::ModelsConfig {
default: Some("grok-3".to_string()),
default: Some("kigi-3".to_string()),
..Default::default()
};
let v = TomlValue::try_from(&m).expect("serialize ModelsConfig");
@@ -836,7 +836,7 @@ auto_update = true
assert!(!t.contains_key("disabled_models"));
assert!(!t.contains_key("allowed_models"));
assert!(!t.contains_key("agent_type"));
assert_eq!(t.get("default").and_then(|x| x.as_str()), Some("grok-3"));
assert_eq!(t.get("default").and_then(|x| x.as_str()), Some("kigi-3"));
} else {
panic!("expected table from serialization");
}
@@ -941,12 +941,12 @@ auto_update = true
models.insert("unmodeled_foo".into(), TomlValue::String("keep-me".into()));
table.insert("models".into(), TomlValue::Table(models));
let cfg = crate::agent::config::ModelsConfig {
default: Some("grok-new".to_string()),
default: Some("kigi-new".to_string()),
..Default::default()
};
merge_section(&mut table, "models", &cfg);
let m = table.get("models").unwrap().as_table().unwrap();
assert_eq!(m.get("default").and_then(|v| v.as_str()), Some("grok-new"));
assert_eq!(m.get("default").and_then(|v| v.as_str()), Some("kigi-new"));
assert_eq!(
m.get("session_summary").and_then(|v| v.as_str()),
Some("old-title")
@@ -960,10 +960,10 @@ auto_update = true
#[test]
fn persist_preferred_model_flow_roundtrips_via_load_and_new_from_toml_cfg() {
let original = "[models]\ndefault = \"grok-old\"\n";
let original = "[models]\ndefault = \"kigi-old\"\n";
let root: TomlValue = toml::from_str(original).unwrap();
let mut cfg = load_config_from_toml(&root);
cfg.models.default = Some("grok-persisted".to_string());
cfg.models.default = Some("kigi-persisted".to_string());
let mut table = if let TomlValue::Table(t) = root {
t
} else {
@@ -972,10 +972,10 @@ auto_update = true
merge_section(&mut table, "models", &cfg.models);
let reloaded_root = TomlValue::Table(table);
let reloaded = load_config_from_toml(&reloaded_root);
assert_eq!(reloaded.models.default.as_deref(), Some("grok-persisted"));
assert_eq!(reloaded.models.default.as_deref(), Some("kigi-persisted"));
let cfg2 = crate::agent::config::Config::new_from_toml_cfg(&reloaded_root)
.expect("new_from_toml_cfg");
assert_eq!(cfg2.models.default.as_deref(), Some("grok-persisted"));
assert_eq!(cfg2.models.default.as_deref(), Some("kigi-persisted"));
}
// ── merge_section pin tests for CLI/session setters ──────────────────
@@ -1116,8 +1116,8 @@ auto_update = true
use crate::agent::config::{Config, ConfigModelOverride, ModelInfo};
use std::sync::Mutex;
const TEST_MODEL: &str = "grok-4.5";
const OTHER_MODEL: &str = "grok-4.3";
const TEST_MODEL: &str = "kigi-4.5";
const OTHER_MODEL: &str = "kigi-4.3";
/// Serialize tests that mutate `KIGI_AUTO_COMPACT_THRESHOLD_PERCENT`.
static ENV_LOCK: Mutex<()> = Mutex::new(());
@@ -1453,8 +1453,8 @@ auto_update = true
// `cfg.ui.auto_{dark,light}_theme = Some(value)`.
let cfg = apply(|cfg| cfg.ui.auto_dark_theme = Some("tokyonight".to_string()));
assert_eq!(cfg.ui.auto_dark_theme, Some("tokyonight".to_string()));
let cfg = apply(|cfg| cfg.ui.auto_light_theme = Some("grokday".to_string()));
assert_eq!(cfg.ui.auto_light_theme, Some("grokday".to_string()));
let cfg = apply(|cfg| cfg.ui.auto_light_theme = Some("kigiday".to_string()));
assert_eq!(cfg.ui.auto_light_theme, Some("kigiday".to_string()));
// set_hunk_tracker_mode wraps `cfg.ui.hunk_tracker_mode = Some(value)`.
let cfg = apply(|cfg| cfg.ui.hunk_tracker_mode = Some("off".to_string()));
@@ -1475,7 +1475,7 @@ auto_update = true
let original = r#"
[ui]
compact_mode = true
theme = "groknight"
theme = "kiginight"
auto_dark_theme = "tokyonight"
custom_user_key = "preserve-me"
"#;
@@ -1516,8 +1516,8 @@ custom_user_key = "preserve-me"
let original = r#"
[ui]
theme = "auto"
auto_dark_theme = "groknight"
auto_light_theme = "grokday"
auto_dark_theme = "kiginight"
auto_light_theme = "kigiday"
custom_unknown_key = 42
"#;
let root: TomlValue = toml::from_str(original).unwrap();
@@ -19,11 +19,11 @@ pub(crate) const ENV_AUTO_COMPACT_THRESHOLD_PERCENT: &str = "KIGI_AUTO_COMPACT_T
/// 3. user TOML `[session].auto_compact_threshold_percent`
/// (read from `cfg.session.auto_compact_threshold_percent: Option<u8>`)
/// 4. remote settings per-model `ModelInfo.auto_compact_threshold_percent`
/// (populated from `grok_build_models[i].auto_compact_threshold_percent`;
/// (populated from `kigi_models[i].auto_compact_threshold_percent`;
/// intentionally NOT collapsed via `ConfigModelOverride::apply` so the
/// user-vs-GB per-model distinction is preserved)
/// 5. remote settings global `RemoteSettings.auto_compact_threshold_percent`
/// (populated from `grok_build_settings.auto_compact_threshold_percent`)
/// (populated from `kigi_settings.auto_compact_threshold_percent`)
/// 6. default `DEFAULT_AUTO_COMPACT_THRESHOLD_PERCENT` (85)
///
/// Values outside `0..=100` from the env var are ignored with a debug log and
@@ -163,7 +163,7 @@ pub const DEFAULT_MCP_STARTUP_TIMEOUT_SECS: u64 = 30;
/// Env override for the MCP startup timeout, in milliseconds (shared with
/// common third-party tooling, so an existing setting carries over).
const ENV_MCP_TIMEOUT_MS: &str = "MCP_TIMEOUT";
/// Env override for the MCP startup timeout, in seconds (grok-native).
/// Env override for the MCP startup timeout, in seconds (kigi-native).
const ENV_MCP_STARTUP_TIMEOUT_SECS: &str = "KIGI_MCP_STARTUP_TIMEOUT_SECS";
/// Cached remote settings `mcp_startup_timeout_secs` (`0` = unset). MCP servers start
@@ -300,7 +300,7 @@ fn max_mcp_output_bytes_from_toml(v: &toml::Value) -> Option<usize> {
/// Precedence (highest first):
/// 1. requirements.toml `[mcp] max_output_bytes`
/// 2. env `KIGI_MAX_MCP_OUTPUT_BYTES` / `MAX_MCP_OUTPUT_BYTES`
/// (Grok-native wins when both set)
/// (Kigi-native wins when both set)
/// 3. effective `config.toml [mcp] max_output_bytes`
/// 4. remote settings `RemoteSettings.max_mcp_output_bytes`
/// 5. [`DEFAULT_MAX_MCP_OUTPUT_BYTES`] (20_000)
@@ -4,7 +4,7 @@ pub const DEFAULT_SYSTEM_PROMPT_LABEL: &str = kigi_agent::DEFAULT_SYSTEM_PROMPT_
/// Resolve system-prompt identity label.
/// Precedence: env → config per-model → `[agent]` → GB per-model → GB global →
/// `"Grok"`. Empty/whitespace falls through.
/// `"Kigi"`. Empty/whitespace falls through.
///
/// Per-model TOML is looked up by session catalog id, then routing slug
/// (`ModelInfo.model`). Do not use CLI `-m` alone — it may outlive a mid-session
@@ -1,5 +1,5 @@
use crate::util::config::RemoteSettings;
use kigi_tools::implementations::grok_build::ask_user_question;
use kigi_tools::implementations::kigi::ask_user_question;
use toml::Value as TomlValue;
/// Resolve whether the bash-harness `find`→`bfs` / `grep`→`ugrep` shadows are
@@ -287,9 +287,7 @@ fn resolve_ask_user_question_timeout_secs_from_tiers(
.or(config)
.or(managed)
.or(remote)
.unwrap_or(
kigi_tools::implementations::grok_build::ask_user_question::RESPONSE_TIMEOUT.as_secs(),
)
.unwrap_or(kigi_tools::implementations::kigi::ask_user_question::RESPONSE_TIMEOUT.as_secs())
}
/// Resolve `[toolset.ask_user_question] timeout_secs` (positive seconds).
@@ -307,7 +305,7 @@ fn resolve_ask_user_question_timeout_secs(
) -> u64 {
resolve_ask_user_question_timeout_secs_from_tiers(
ask_user_question_timeout_secs_from_toml(requirements),
kigi_tools::implementations::grok_build::ask_user_question::response_timeout_env_secs(),
kigi_tools::implementations::kigi::ask_user_question::response_timeout_env_secs(),
ask_user_question_timeout_secs_from_toml(user),
ask_user_question_timeout_secs_from_toml(managed)
.or_else(|| ask_user_question_timeout_secs_from_toml(system_managed)),
@@ -326,7 +324,7 @@ fn resolve_ask_user_question_timeout_secs(
/// runs for consumers that skip this resolver.
pub(crate) fn resolve_ask_user_question_params_from_disk(
remote: Option<&RemoteSettings>,
) -> kigi_tools::implementations::grok_build::ask_user_question::AskUserQuestionParams {
) -> kigi_tools::implementations::kigi::ask_user_question::AskUserQuestionParams {
let requirements = crate::config::load_merged_requirements();
let layers = match crate::config::ConfigLayers::load() {
Ok(l) => Some(l),
@@ -338,7 +336,7 @@ pub(crate) fn resolve_ask_user_question_params_from_disk(
let user = layers.as_ref().map(|l| &l.user);
let managed = layers.as_ref().map(|l| &l.managed);
let system_managed = layers.as_ref().map(|l| &l.system_managed);
kigi_tools::implementations::grok_build::ask_user_question::AskUserQuestionParams {
kigi_tools::implementations::kigi::ask_user_question::AskUserQuestionParams {
timeout_enabled: Some(
resolve_ask_user_question_timeout_enabled(
requirements.as_ref(),
@@ -363,7 +361,7 @@ pub(crate) fn resolve_ask_user_question_params_from_disk(
mod ask_user_question_timeout_tests {
use super::*;
use crate::agent::config::ConfigSource;
use kigi_tools::implementations::grok_build::ask_user_question::RESPONSE_TIMEOUT_ENV;
use kigi_tools::implementations::kigi::ask_user_question::RESPONSE_TIMEOUT_ENV;
// Both env vars are process-global (a dev exports the secs var for TUI
// repro); serialize and force them unset so these tests can't go flaky.
@@ -439,8 +437,7 @@ mod ask_user_question_timeout_tests {
#[test]
fn timeout_secs_tier_precedence() {
let d =
kigi_tools::implementations::grok_build::ask_user_question::RESPONSE_TIMEOUT.as_secs();
let d = kigi_tools::implementations::kigi::ask_user_question::RESPONSE_TIMEOUT.as_secs();
let r = resolve_ask_user_question_timeout_secs_from_tiers;
assert_eq!(r(None, None, None, None, None), d);
assert_eq!(r(Some(1), Some(2), Some(3), Some(4), Some(5)), 1); // requirements highest
@@ -453,8 +450,7 @@ mod ask_user_question_timeout_tests {
#[test]
fn timeout_secs_rejects_non_positive_layers() {
let _g = guard();
let d =
kigi_tools::implementations::grok_build::ask_user_question::RESPONSE_TIMEOUT.as_secs();
let d = kigi_tools::implementations::kigi::ask_user_question::RESPONSE_TIMEOUT.as_secs();
// user 0 and managed negative are dropped; remote fills the gap.
let zero = toml_ask("timeout_secs = 0");
let negative = toml_ask("timeout_secs = -5");
@@ -61,7 +61,7 @@ pub async fn set_contextual_hint_word_select(value: bool) -> Result<()> {
}
/// Persist `[ui].theme` via `update_config`. Caller must pass the
/// canonical theme name (`groknight`, `tokyonight`, `auto`, etc.).
/// canonical theme name (`kiginight`, `tokyonight`, `auto`, etc.).
pub async fn set_theme(value: String) -> Result<()> {
update_config(|cfg| cfg.ui.theme = Some(value)).await
}
@@ -180,7 +180,7 @@ auto_update = true
fn test_worktree_type_no_cli_section() {
let toml_str = r#"
[models]
default = "grok-code-fast-1"
default = "kigi-code-fast-1"
"#;
let root: TomlValue = toml::from_str(toml_str).unwrap();
assert_eq!(worktree_type_from_toml(&root), WorktreeType::Linked);
@@ -232,7 +232,7 @@ worktree_type = "invalid"
#[test]
fn test_worktree_type_from_toml_opt_no_cli_section() {
let root: TomlValue = toml::from_str("[models]\ndefault = \"grok\"").unwrap();
let root: TomlValue = toml::from_str("[models]\ndefault = \"kigi\"").unwrap();
assert_eq!(worktree_type_from_toml_opt(&root), None);
}
@@ -319,7 +319,7 @@ worktree_type = "invalid"
#[test]
fn test_restore_code_from_toml_no_cli_section() {
let root: TomlValue = toml::from_str("[models]\ndefault = \"grok\"").unwrap();
let root: TomlValue = toml::from_str("[models]\ndefault = \"kigi\"").unwrap();
assert_eq!(restore_code_from_toml(&root), None);
}
+4 -4
View File
@@ -51,18 +51,18 @@ pub fn discover_hook_source_paths(
let home = dirs::home_dir();
// user_kigi_home() is None when no home resolves, so inspect lists the same
// sources a live session loads, instead of a cwd-relative .kigi.
let grok = kigi_config::user_kigi_home();
let kigi = kigi_config::user_kigi_home();
let mut global = Vec::new();
if !skip_claude && let Some(ref h) = home {
global.push(h.join(".claude").join("settings.json"));
global.push(h.join(".claude").join("settings.local.json"));
}
if let Some(ref grok) = grok {
global.push(grok.join("hooks"));
if let Some(ref kigi) = kigi {
global.push(kigi.join("hooks"));
}
let custom_paths: Vec<PathBuf> = grok
let custom_paths: Vec<PathBuf> = kigi
.as_ref()
.and_then(|g| std::fs::read_to_string(g.join("hooks-paths")).ok())
.map(|content| {
@@ -1,6 +1,6 @@
use reqwest::RequestBuilder;
use std::sync::Arc;
/// Credentials for authenticating with grok backend services.
/// Credentials for authenticating with kigi backend services.
///
/// Two construction modes:
/// - `with_auth_manager(am)` — live mode. `resolve_async()` drives