§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:
1 parent
86e3724310
commit
6f31415ed6
1056 files changed
+8410
-18307
No files matched your search
@@ -67,7 +67,7 @@ fn prompt_request_meta_omits_screen_mode_when_unset() {
|
||||
assert_eq!(meta, serde_json::json!({ "promptId" : "p-2" }));
|
||||
}
|
||||
/// Text-only interjections must omit the `content` key entirely — the
|
||||
/// legacy `x.ai/interject` wire shape stays byte-identical.
|
||||
/// legacy `kigi/interject` wire shape stays byte-identical.
|
||||
#[test]
|
||||
fn interject_params_omit_content_when_no_blocks() {
|
||||
let sid = acp::SessionId::new("s1");
|
||||
@@ -83,7 +83,7 @@ fn interject_params_omit_content_when_no_blocks() {
|
||||
fn picker_keeps_conversation_with_empty_cwd_and_missing_updated_at() {
|
||||
let payload = serde_json::json!(
|
||||
{ "sessions" : [{ "sessionId" : "conv_abc", "cwd" : "", "summary" :
|
||||
"Compare GPU vendors", "source" : "conversation", "_meta" : { "x.ai/session" : {
|
||||
"Compare GPU vendors", "source" : "conversation", "_meta" : { "kigi/session" : {
|
||||
"kind" : "chat" } } }] }
|
||||
);
|
||||
let entries = parse_session_picker_entries(&payload);
|
||||
@@ -97,7 +97,7 @@ fn picker_keeps_old_conversation_past_cutoff() {
|
||||
let payload = serde_json::json!(
|
||||
{ "sessions" : [{ "sessionId" : "conv_old", "cwd" : "", "summary" :
|
||||
"Ancient chat", "source" : "conversation", "updatedAt" : "2020-01-01T00:00:00Z",
|
||||
"_meta" : { "x.ai/session" : { "kind" : "chat" } } }] }
|
||||
"_meta" : { "kigi/session" : { "kind" : "chat" } } }] }
|
||||
);
|
||||
let entries = parse_session_picker_entries(&payload);
|
||||
assert_eq!(entries.len(), 1, "old conversation must still render");
|
||||
@@ -112,13 +112,13 @@ fn picker_drops_local_with_missing_updated_at() {
|
||||
let entries = parse_session_picker_entries(&payload);
|
||||
assert!(entries.is_empty(), "local rows still require a parseable updatedAt");
|
||||
}
|
||||
/// Untitled grok.com chats must stay listed, rendered as "Untitled".
|
||||
/// Untitled kimi.com chats must stay listed, rendered as "Untitled".
|
||||
#[test]
|
||||
fn picker_keeps_untitled_conversation_as_untitled() {
|
||||
let payload = serde_json::json!(
|
||||
{ "sessions" : [{ "sessionId" : "conv_untitled", "cwd" : "", "summary" : "",
|
||||
"source" : "conversation", "updatedAt" : "2026-07-01T00:00:00Z", "_meta" : {
|
||||
"x.ai/session" : { "kind" : "chat" } } }] }
|
||||
"kigi/session" : { "kind" : "chat" } } }] }
|
||||
);
|
||||
let entries = parse_session_picker_entries(&payload);
|
||||
assert_eq!(entries.len(), 1, "untitled conversation must not vanish");
|
||||
@@ -277,7 +277,7 @@ fn interject_params_carry_content_when_blocks_present() {
|
||||
assert_eq!(content.len(), 1);
|
||||
assert_eq!(content[0] ["text"], "look at [Image #1]");
|
||||
}
|
||||
/// `x.ai/billing` ext result (a serialized shell `UsageResponse`) parses
|
||||
/// `kigi/billing` ext result (a serialized shell `UsageResponse`) parses
|
||||
/// into typed rows; unknown labels/reset hints survive the round trip.
|
||||
#[test]
|
||||
fn parse_usage_response_reads_rows_from_fixture() {
|
||||
@@ -473,7 +473,7 @@ async fn persist_setting_type_mismatch_errors_simple_mode() {
|
||||
}
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
/// Spawn a fake ACP agent that counts `x.ai/yolo_mode_changed`
|
||||
/// Spawn a fake ACP agent that counts `kigi/yolo_mode_changed`
|
||||
/// notifications. Exits when the channel closes.
|
||||
fn spawn_fake_acp_agent(
|
||||
mut rx: tokio::sync::mpsc::UnboundedReceiver<kigi_acp_lib::AcpAgentMessage>,
|
||||
@@ -483,7 +483,7 @@ fn spawn_fake_acp_agent(
|
||||
tokio::spawn(async move {
|
||||
while let Some(msg) = rx.recv().await {
|
||||
if let kigi_acp_lib::AcpAgentMessage::ExtNotification(args) = msg {
|
||||
if args.request.method.as_ref() == "x.ai/yolo_mode_changed" {
|
||||
if args.request.method.as_ref() == "kigi/yolo_mode_changed" {
|
||||
counter_clone.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
let _ = args.response_tx.send(Ok(()));
|
||||
@@ -590,7 +590,7 @@ async fn persist_permission_mode_acp_notification_fires_once_on_best_effort() {
|
||||
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
|
||||
assert_eq!(
|
||||
counter.load(Ordering::SeqCst), 1,
|
||||
"ACP `x.ai/yolo_mode_changed` notification must fire exactly once \
|
||||
"ACP `kigi/yolo_mode_changed` notification must fire exactly once \
|
||||
on BestEffort path (regardless of disk outcome)",
|
||||
);
|
||||
assert!(
|
||||
@@ -972,7 +972,7 @@ async fn fetch_session_list_pushes_query_and_echoes_seq() {
|
||||
tokio::spawn(async move {
|
||||
while let Some(msg) = rx.recv().await {
|
||||
if let AcpAgentMessage::ExtMethod(args) = msg {
|
||||
assert_eq!(args.request.method.as_ref(), "x.ai/session/list");
|
||||
assert_eq!(args.request.method.as_ref(), "kigi/session/list");
|
||||
let params: serde_json::Value = serde_json::from_str(
|
||||
args.request.params.get(),
|
||||
)
|
||||
@@ -1094,7 +1094,7 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
ask_user: false,
|
||||
..Default::default()
|
||||
},
|
||||
"grok-build-plan",
|
||||
"kigi-plan",
|
||||
),
|
||||
(
|
||||
SessionFlags {
|
||||
@@ -1103,7 +1103,7 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
ask_user: false,
|
||||
..Default::default()
|
||||
},
|
||||
"grok-build-plan-no-subagents",
|
||||
"kigi-plan-no-subagents",
|
||||
),
|
||||
(
|
||||
SessionFlags {
|
||||
@@ -1112,7 +1112,7 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
ask_user: true,
|
||||
..Default::default()
|
||||
},
|
||||
"grok-build-plan",
|
||||
"kigi-plan",
|
||||
),
|
||||
(
|
||||
SessionFlags {
|
||||
@@ -1121,7 +1121,7 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
ask_user: true,
|
||||
..Default::default()
|
||||
},
|
||||
"grok-build-plan-no-subagents",
|
||||
"kigi-plan-no-subagents",
|
||||
),
|
||||
(
|
||||
SessionFlags {
|
||||
@@ -1130,7 +1130,7 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
ask_user: true,
|
||||
..Default::default()
|
||||
},
|
||||
"grok-build-ask-user",
|
||||
"kigi-ask-user",
|
||||
),
|
||||
(
|
||||
SessionFlags {
|
||||
@@ -1139,7 +1139,7 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
ask_user: true,
|
||||
..Default::default()
|
||||
},
|
||||
"grok-build-ask-user",
|
||||
"kigi-ask-user",
|
||||
),
|
||||
];
|
||||
for (flags, expected_name) in test_cases {
|
||||
@@ -1156,13 +1156,13 @@ fn agent_profile_names_are_valid_builtins() {
|
||||
);
|
||||
}
|
||||
}
|
||||
/// Default flags produce no agent profile (uses grok-build default).
|
||||
/// Default flags produce no agent profile (uses kigi default).
|
||||
#[test]
|
||||
fn default_flags_produce_no_profile() {
|
||||
let flags = SessionFlags::default();
|
||||
assert_eq!(flags.agent_profile(), None);
|
||||
}
|
||||
/// --subagents alone produces no profile (grok-build already has TaskTool).
|
||||
/// --subagents alone produces no profile (kigi already has TaskTool).
|
||||
#[test]
|
||||
fn subagents_without_plan_produces_no_profile() {
|
||||
let flags = SessionFlags {
|
||||
@@ -1178,7 +1178,7 @@ fn subagents_without_plan_produces_no_profile() {
|
||||
/// escape hatch and drops `agentProfile` — the tests would then assert the
|
||||
/// wrong branch. Empty string counts as unset (`!s.trim().is_empty()`).
|
||||
/// Callers must be `#[serial_test::serial(KIGI_AGENT)]` (process-global env).
|
||||
fn without_grok_agent() -> crate::test_util::EnvVarGuard {
|
||||
fn without_kigi_agent() -> crate::test_util::EnvVarGuard {
|
||||
crate::test_util::EnvVarGuard::set("KIGI_AGENT", "")
|
||||
}
|
||||
/// At the runtime defaults (every `--no-*` flag false → every
|
||||
@@ -1187,7 +1187,7 @@ fn without_grok_agent() -> crate::test_util::EnvVarGuard {
|
||||
#[serial_test::serial(KIGI_AGENT)]
|
||||
#[test]
|
||||
fn runtime_default_flags_produce_plan_meta() {
|
||||
let _env = without_grok_agent();
|
||||
let _env = without_kigi_agent();
|
||||
let flags = SessionFlags {
|
||||
plan_mode: true,
|
||||
subagents: true,
|
||||
@@ -1195,7 +1195,7 @@ fn runtime_default_flags_produce_plan_meta() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().unwrap();
|
||||
assert_eq!(meta["agentProfile"], "grok-build-plan");
|
||||
assert_eq!(meta["agentProfile"], "kigi-plan");
|
||||
assert!(meta.get("askUserQuestion").is_none());
|
||||
assert_eq!(meta["yoloMode"], false);
|
||||
}
|
||||
@@ -1204,7 +1204,7 @@ fn runtime_default_flags_produce_plan_meta() {
|
||||
#[serial_test::serial(KIGI_AGENT)]
|
||||
#[test]
|
||||
fn plan_only_meta() {
|
||||
let _env = without_grok_agent();
|
||||
let _env = without_kigi_agent();
|
||||
let flags = SessionFlags {
|
||||
plan_mode: true,
|
||||
subagents: false,
|
||||
@@ -1212,7 +1212,7 @@ fn plan_only_meta() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().unwrap();
|
||||
assert_eq!(meta["agentProfile"], "grok-build-plan-no-subagents");
|
||||
assert_eq!(meta["agentProfile"], "kigi-plan-no-subagents");
|
||||
assert_eq!(meta["askUserQuestion"], false);
|
||||
assert_eq!(meta["yoloMode"], false);
|
||||
}
|
||||
@@ -1220,7 +1220,7 @@ fn plan_only_meta() {
|
||||
#[serial_test::serial(KIGI_AGENT)]
|
||||
#[test]
|
||||
fn plan_with_subagents_meta() {
|
||||
let _env = without_grok_agent();
|
||||
let _env = without_kigi_agent();
|
||||
let flags = SessionFlags {
|
||||
plan_mode: true,
|
||||
subagents: true,
|
||||
@@ -1228,15 +1228,15 @@ fn plan_with_subagents_meta() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().unwrap();
|
||||
assert_eq!(meta["agentProfile"], "grok-build-plan");
|
||||
assert_eq!(meta["agentProfile"], "kigi-plan");
|
||||
assert_eq!(meta["askUserQuestion"], false);
|
||||
assert_eq!(meta["yoloMode"], false);
|
||||
}
|
||||
/// --ask-user alone selects the grok-build-ask-user profile.
|
||||
/// --ask-user alone selects the kigi-ask-user profile.
|
||||
#[serial_test::serial(KIGI_AGENT)]
|
||||
#[test]
|
||||
fn ask_user_alone_meta() {
|
||||
let _env = without_grok_agent();
|
||||
let _env = without_kigi_agent();
|
||||
let flags = SessionFlags {
|
||||
plan_mode: false,
|
||||
subagents: false,
|
||||
@@ -1244,7 +1244,7 @@ fn ask_user_alone_meta() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().unwrap();
|
||||
assert_eq!(meta["agentProfile"], "grok-build-ask-user");
|
||||
assert_eq!(meta["agentProfile"], "kigi-ask-user");
|
||||
assert!(meta.get("askUserQuestion").is_none());
|
||||
assert_eq!(meta["yoloMode"], false);
|
||||
}
|
||||
@@ -1252,7 +1252,7 @@ fn ask_user_alone_meta() {
|
||||
#[serial_test::serial(KIGI_AGENT)]
|
||||
#[test]
|
||||
fn plan_with_ask_user_uses_plan_profile() {
|
||||
let _env = without_grok_agent();
|
||||
let _env = without_kigi_agent();
|
||||
let flags = SessionFlags {
|
||||
plan_mode: true,
|
||||
subagents: false,
|
||||
@@ -1260,14 +1260,14 @@ fn plan_with_ask_user_uses_plan_profile() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().unwrap();
|
||||
assert_eq!(meta["agentProfile"], "grok-build-plan-no-subagents");
|
||||
assert_eq!(meta["agentProfile"], "kigi-plan-no-subagents");
|
||||
assert!(meta.get("askUserQuestion").is_none());
|
||||
assert_eq!(meta["yoloMode"], false);
|
||||
}
|
||||
/// --no-plan --no-subagents --no-ask-user picks the default profile but
|
||||
/// must still emit `askUserQuestion: false` so the shell can strip the
|
||||
/// tool at the builder. Mirrors the runtime: `subagents` toggle alone
|
||||
/// does not need an `agentProfile` (default `grok-build` already has it).
|
||||
/// does not need an `agentProfile` (default `kigi` already has it).
|
||||
#[test]
|
||||
fn subagents_alone_emits_only_ask_user_question_disable() {
|
||||
let flags = SessionFlags {
|
||||
@@ -1280,12 +1280,12 @@ fn subagents_alone_emits_only_ask_user_question_disable() {
|
||||
assert!(meta.get("agentProfile").is_none());
|
||||
assert_eq!(meta["askUserQuestion"], false);
|
||||
}
|
||||
/// All three flags on at the runtime default produce grok-build-plan
|
||||
/// All three flags on at the runtime default produce kigi-plan
|
||||
/// and no `askUserQuestion` field.
|
||||
#[serial_test::serial(KIGI_AGENT)]
|
||||
#[test]
|
||||
fn all_flags_meta() {
|
||||
let _env = without_grok_agent();
|
||||
let _env = without_kigi_agent();
|
||||
let flags = SessionFlags {
|
||||
plan_mode: true,
|
||||
subagents: true,
|
||||
@@ -1293,7 +1293,7 @@ fn all_flags_meta() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().unwrap();
|
||||
assert_eq!(meta["agentProfile"], "grok-build-plan");
|
||||
assert_eq!(meta["agentProfile"], "kigi-plan");
|
||||
assert!(meta.get("askUserQuestion").is_none());
|
||||
assert_eq!(meta["yoloMode"], false);
|
||||
}
|
||||
@@ -1388,7 +1388,7 @@ fn to_meta_chat_mode_stamps_kind_and_omits_agent_profile() {
|
||||
..Default::default()
|
||||
};
|
||||
let meta = flags.to_meta().expect("chat_mode must emit meta");
|
||||
assert_eq!(meta["x.ai/session"] ["kind"], "chat");
|
||||
assert_eq!(meta["kigi/session"] ["kind"], "chat");
|
||||
assert!(
|
||||
meta.get("agentProfile").is_none(), "K12: chat mode must omit Build agentProfile"
|
||||
);
|
||||
@@ -1414,7 +1414,7 @@ fn load_meta_chat_kind_alone_stamps_kind_and_strips_profile() {
|
||||
scrub_chat_workspace_bind_meta(&mut meta);
|
||||
}
|
||||
let meta = meta.expect("chat_kind must produce meta");
|
||||
assert_eq!(meta["x.ai/session"] ["kind"], "chat");
|
||||
assert_eq!(meta["kigi/session"] ["kind"], "chat");
|
||||
assert!(
|
||||
meta.get("agentProfile").is_none(),
|
||||
"entry chat_kind must strip Build agentProfile"
|
||||
@@ -1444,7 +1444,7 @@ fn chat_create_meta_never_includes_workspace_bind_keys_when_cloud_fields_set() {
|
||||
apply_chat_kind_meta(&mut meta);
|
||||
scrub_chat_workspace_bind_meta(&mut meta);
|
||||
let meta = meta.expect("chat create must emit meta");
|
||||
assert_eq!(meta["x.ai/session"] ["kind"], "chat");
|
||||
assert_eq!(meta["kigi/session"] ["kind"], "chat");
|
||||
assert_chat_meta_has_no_workspace_bind_keys(
|
||||
&serde_json::Value::Object(meta.clone()),
|
||||
);
|
||||
@@ -1457,15 +1457,15 @@ fn chat_load_meta_never_includes_workspace_bind_keys() {
|
||||
{
|
||||
let obj = meta.get_or_insert_with(acp::Meta::new);
|
||||
obj.insert("envId".into(), serde_json::json!("env-poison"));
|
||||
obj.insert("x.ai/cloud_server_id".into(), serde_json::json!("srv-poison"));
|
||||
obj.insert("kigi/cloud_server_id".into(), serde_json::json!("srv-poison"));
|
||||
obj.insert(
|
||||
"x.ai/cloud_existing_workspace".into(),
|
||||
"kigi/cloud_existing_workspace".into(),
|
||||
serde_json::json!({ "server_id" : "srv-poison", "cwd" : "/ws", }),
|
||||
);
|
||||
}
|
||||
scrub_chat_workspace_bind_meta(&mut meta);
|
||||
let meta = meta.expect("chat load must emit meta");
|
||||
assert_eq!(meta["x.ai/session"] ["kind"], "chat");
|
||||
assert_eq!(meta["kigi/session"] ["kind"], "chat");
|
||||
assert_chat_meta_has_no_workspace_bind_keys(
|
||||
&serde_json::Value::Object(meta.clone()),
|
||||
);
|
||||
@@ -1491,9 +1491,9 @@ fn agent_profile_definitions_have_correct_names() {
|
||||
use std::str::FromStr;
|
||||
use kigi_agent::config::BuiltinAgentName;
|
||||
for name in [
|
||||
"grok-build-plan",
|
||||
"grok-build-plan-no-subagents",
|
||||
"grok-build-ask-user",
|
||||
"kigi-plan",
|
||||
"kigi-plan-no-subagents",
|
||||
"kigi-ask-user",
|
||||
] {
|
||||
let builtin = BuiltinAgentName::from_str(name).unwrap();
|
||||
let def = builtin.definition();
|
||||
@@ -1542,23 +1542,23 @@ fn format_session_info_shows_conversation_id_when_present() {
|
||||
}
|
||||
#[test]
|
||||
fn format_session_info_shows_resolved_when_enabled_and_different() {
|
||||
let info = make_session_info("grok-4.5", Some("grok-4.3"), 1000, 10000);
|
||||
let info = make_session_info("kigi-4.5", Some("kigi-4.3"), 1000, 10000);
|
||||
let text = format_session_info(&info, None, true);
|
||||
assert!(text.contains("Model: grok-4.5 (grok-4.3)"));
|
||||
assert!(text.contains("Model: kigi-4.5 (kigi-4.3)"));
|
||||
}
|
||||
#[test]
|
||||
fn format_session_info_hides_resolved_when_disabled() {
|
||||
let info = make_session_info("grok-4.5", Some("grok-4.3"), 1000, 10000);
|
||||
let info = make_session_info("kigi-4.5", Some("kigi-4.3"), 1000, 10000);
|
||||
let text = format_session_info(&info, None, false);
|
||||
assert!(text.contains("Model: grok-4.5"));
|
||||
assert!(! text.contains("grok-4.3"));
|
||||
assert!(text.contains("Model: kigi-4.5"));
|
||||
assert!(! text.contains("kigi-4.3"));
|
||||
}
|
||||
#[test]
|
||||
fn format_session_info_no_parens_when_resolved_matches_requested() {
|
||||
let info = make_session_info("grok-4.5", Some("grok-4.5"), 1000, 10000);
|
||||
let info = make_session_info("kigi-4.5", Some("kigi-4.5"), 1000, 10000);
|
||||
let text = format_session_info(&info, None, true);
|
||||
assert!(text.contains("Model: grok-4.5"));
|
||||
assert!(! text.contains("(grok-4.5)"));
|
||||
assert!(text.contains("Model: kigi-4.5"));
|
||||
assert!(! text.contains("(kigi-4.5)"));
|
||||
}
|
||||
#[test]
|
||||
fn format_session_info_shows_model_hash_when_catalog_flag_set() {
|
||||
@@ -1647,7 +1647,7 @@ fn session_picker_entry_maps_to_dormant_roster_row() {
|
||||
cwd: "/repo/app".to_string(),
|
||||
hostname: Some("box".to_string()),
|
||||
source: "local".to_string(),
|
||||
model_id: Some("grok-4".to_string()),
|
||||
model_id: Some("kigi-4".to_string()),
|
||||
num_messages: 3,
|
||||
last_active_at: Some(updated),
|
||||
branch: None,
|
||||
@@ -1660,7 +1660,7 @@ fn session_picker_entry_maps_to_dormant_roster_row() {
|
||||
assert_eq!(roster.title.as_deref(), Some("Wire up dashboard"));
|
||||
assert_eq!(roster.cwd, "/repo/app");
|
||||
assert!(roster.is_worktree, "worktree_label present → is_worktree");
|
||||
assert_eq!(roster.model_id.as_deref(), Some("grok-4"));
|
||||
assert_eq!(roster.model_id.as_deref(), Some("kigi-4"));
|
||||
assert_eq!(roster.activity, RosterActivity::Dormant);
|
||||
assert!(! roster.resident);
|
||||
assert_eq!(roster.last_change_unix_ms, updated.timestamp_millis());
|
||||
|
||||
Reference in new issue
Block a user