§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
@@ -144,13 +144,13 @@ pub struct PromptContext {
/// stdio / generic-ACP).
#[serde(default)]
pub is_non_interactive: bool,
/// Identity in the primary grok-build system prompt (`You are <label>…`).
/// Identity in the primary kigi system prompt (`You are <label>…`).
/// Not the UI picker name. Defaults to [`DEFAULT_SYSTEM_PROMPT_LABEL`].
#[serde(default = "default_system_prompt_label")]
pub system_prompt_label: String,
}
/// Default identity on trim-tool-descriptions (`You are Grok released by xAI`).
pub const DEFAULT_SYSTEM_PROMPT_LABEL: &str = "Grok";
/// Default identity on trim-tool-descriptions (`You are Kigi released by xAI`).
pub const DEFAULT_SYSTEM_PROMPT_LABEL: &str = "Kigi";
fn default_system_prompt_label() -> String {
DEFAULT_SYSTEM_PROMPT_LABEL.to_string()
}
@@ -427,9 +427,9 @@ mod tests {
#[test]
fn test_placeholders_system_prompt_label_override() {
let mut ctx = test_context();
ctx.system_prompt_label = "Grok Internal".into();
ctx.system_prompt_label = "Kigi Internal".into();
let p = ctx.placeholders();
assert_eq!(p["system_prompt_label"], "Grok Internal");
assert_eq!(p["system_prompt_label"], "Kigi Internal");
}
#[test]
fn test_missing_system_prompt_label_deserializes_to_default() {
@@ -1229,7 +1229,7 @@ mod tests {
("plan", plan),
] {
assert!(
!prompt.contains("You are a Grok Build agent"),
!prompt.contains("You are a Kigi agent"),
"{name} prompt should not duplicate base template identity"
);
}
File diff suppressed because one or more lines are too long
+27 -27
View File
@@ -832,12 +832,12 @@ mod tests {
fn find_skill_paths_flat_layout() {
// Traditional flat layout: skills/<name>/SKILL.md
let tmp = tempfile::tempdir().unwrap();
let grok_dir = tmp.path().join(".kigi");
let kigi_dir = tmp.path().join(".kigi");
write_skill_md(&grok_dir.join("skills").join("alpha"), "alpha");
write_skill_md(&grok_dir.join("skills").join("beta"), "beta");
write_skill_md(&kigi_dir.join("skills").join("alpha"), "alpha");
write_skill_md(&kigi_dir.join("skills").join("beta"), "beta");
let paths = find_skill_paths(&grok_dir);
let paths = find_skill_paths(&kigi_dir);
assert_eq!(paths.len(), 2);
assert!(paths.iter().all(|p| p.file_name().unwrap() == "SKILL.md"));
}
@@ -846,13 +846,13 @@ mod tests {
fn find_skill_paths_nested_layout() {
// Nested: skills/team/infra/SKILL.md, skills/team/training/SKILL.md
let tmp = tempfile::tempdir().unwrap();
let grok_dir = tmp.path().join(".kigi");
let skills = grok_dir.join("skills");
let kigi_dir = tmp.path().join(".kigi");
let skills = kigi_dir.join("skills");
write_skill_md(&skills.join("team").join("infra"), "infra");
write_skill_md(&skills.join("team").join("training"), "training");
let paths = find_skill_paths(&grok_dir);
let paths = find_skill_paths(&kigi_dir);
assert_eq!(paths.len(), 2);
let path_strs: Vec<String> = paths.iter().map(|p| p.display().to_string()).collect();
@@ -864,8 +864,8 @@ mod tests {
fn find_skill_paths_mixed_flat_and_nested() {
// Mix of flat and nested skills
let tmp = tempfile::tempdir().unwrap();
let grok_dir = tmp.path().join(".kigi");
let skills = grok_dir.join("skills");
let kigi_dir = tmp.path().join(".kigi");
let skills = kigi_dir.join("skills");
// Flat
write_skill_md(&skills.join("top-level"), "top-level");
@@ -874,7 +874,7 @@ mod tests {
// Nested 2 levels
write_skill_md(&skills.join("org").join("team").join("deep"), "deep");
let paths = find_skill_paths(&grok_dir);
let paths = find_skill_paths(&kigi_dir);
assert_eq!(paths.len(), 3);
}
@@ -882,8 +882,8 @@ mod tests {
fn find_skill_paths_dir_without_skill_md_is_skipped() {
// A subdirectory exists but has no SKILL.md — should not appear
let tmp = tempfile::tempdir().unwrap();
let grok_dir = tmp.path().join(".kigi");
let skills = grok_dir.join("skills");
let kigi_dir = tmp.path().join(".kigi");
let skills = kigi_dir.join("skills");
write_skill_md(&skills.join("valid"), "valid");
// Create a dir with no SKILL.md
@@ -893,7 +893,7 @@ mod tests {
fs::create_dir_all(&other).unwrap();
fs::write(other.join("README.md"), "not a skill").unwrap();
let paths = find_skill_paths(&grok_dir);
let paths = find_skill_paths(&kigi_dir);
assert_eq!(paths.len(), 1);
assert!(paths[0].display().to_string().contains("valid"));
}
@@ -902,10 +902,10 @@ mod tests {
fn find_skill_paths_no_skills_dir() {
// .kigi exists but no skills/ subdirectory
let tmp = tempfile::tempdir().unwrap();
let grok_dir = tmp.path().join(".kigi");
fs::create_dir_all(&grok_dir).unwrap();
let kigi_dir = tmp.path().join(".kigi");
fs::create_dir_all(&kigi_dir).unwrap();
let paths = find_skill_paths(&grok_dir);
let paths = find_skill_paths(&kigi_dir);
assert!(paths.is_empty());
}
@@ -944,15 +944,15 @@ mod tests {
fn find_skill_paths_parent_and_child_both_have_skill_md() {
// A directory has SKILL.md and also has subdirectories with SKILL.md
let tmp = tempfile::tempdir().unwrap();
let grok_dir = tmp.path().join(".kigi");
let skills = grok_dir.join("skills");
let kigi_dir = tmp.path().join(".kigi");
let skills = kigi_dir.join("skills");
// Parent skill
write_skill_md(&skills.join("parent"), "parent-skill");
// Child skill inside parent
write_skill_md(&skills.join("parent").join("child"), "child-skill");
let paths = find_skill_paths(&grok_dir);
let paths = find_skill_paths(&kigi_dir);
assert_eq!(paths.len(), 2);
let path_strs: Vec<String> = paths.iter().map(|p| p.display().to_string()).collect();
@@ -1108,9 +1108,9 @@ mod tests {
#[test]
fn parse_model_and_effort() {
let content = "---\nname: my-skill\ndescription: test\nmodel: grok-3\neffort: high\n---\n";
let content = "---\nname: my-skill\ndescription: test\nmodel: kigi-3\neffort: high\n---\n";
let parsed = parse_skill_frontmatter(content, None).unwrap();
assert_eq!(parsed.model.as_deref(), Some("grok-3"));
assert_eq!(parsed.model.as_deref(), Some("kigi-3"));
assert_eq!(parsed.effort.as_deref(), Some("high"));
}
@@ -1251,7 +1251,7 @@ mod tests {
#[test]
fn parse_full_spec_plus_extensions() {
// Mixed agentskills.io spec fields + our extensions — all must parse.
let content = "---\nname: my-skill\ndescription: A full skill\nlicense: MIT\ncompatibility: Python 3.12+\nmetadata:\n author: test-org\n version: \"2.0\"\nallowed-tools:\n - bash\n - read_file\nargument-hint: file path\nmodel: grok-3\neffort: high\nuser-invocable: true\ndisable-model-invocation: false\n---\nBody content.\n";
let content = "---\nname: my-skill\ndescription: A full skill\nlicense: MIT\ncompatibility: Python 3.12+\nmetadata:\n author: test-org\n version: \"2.0\"\nallowed-tools:\n - bash\n - read_file\nargument-hint: file path\nmodel: kigi-3\neffort: high\nuser-invocable: true\ndisable-model-invocation: false\n---\nBody content.\n";
let parsed = parse_skill_frontmatter(content, None).unwrap();
assert_eq!(parsed.name, "my-skill");
assert_eq!(parsed.description, "A full skill");
@@ -1263,7 +1263,7 @@ mod tests {
Some(["bash".to_string(), "read_file".to_string()].as_slice())
);
assert_eq!(parsed.argument_hint.as_deref(), Some("file path"));
assert_eq!(parsed.model.as_deref(), Some("grok-3"));
assert_eq!(parsed.model.as_deref(), Some("kigi-3"));
assert_eq!(parsed.effort.as_deref(), Some("high"));
assert!(parsed.user_invocable);
assert!(!parsed.disable_model_invocation);
@@ -1575,7 +1575,7 @@ mod tests {
root: root.clone(),
canonical_root: root.clone(),
scope: PluginScope::User,
origin: crate::plugins::PluginOrigin::UserGrok,
origin: crate::plugins::PluginOrigin::UserKigi,
trusted: true,
enabled: true,
version: Some("1.0.0".to_string()),
@@ -1653,7 +1653,7 @@ mod tests {
root: root.to_path_buf(),
canonical_root: root.to_path_buf(),
scope: PluginScope::User,
origin: crate::plugins::PluginOrigin::UserGrok,
origin: crate::plugins::PluginOrigin::UserKigi,
trusted: true,
skill_dirs,
command_dirs: vec![],
@@ -2323,7 +2323,7 @@ mod tests {
root: root.clone(),
canonical_root: root,
scope: PluginScope::Project,
origin: crate::plugins::PluginOrigin::ProjectGrok,
origin: crate::plugins::PluginOrigin::ProjectKigi,
trusted: true,
enabled: true,
version: Some("1.0.0".to_string()),
@@ -2458,7 +2458,7 @@ mod tests {
"cursor must be gated off: {dirs:?}"
);
assert!(ends_with(&dirs, ".claude"), "claude must remain: {dirs:?}");
assert!(ends_with(&dirs, ".kigi"), "grok must remain: {dirs:?}");
assert!(ends_with(&dirs, ".kigi"), "kigi must remain: {dirs:?}");
}
// ── Same-scope frontmatter-name collisions (copied skill dirs) ──────
@@ -32,7 +32,7 @@ pub(crate) fn base_template() -> Zeroizing<String> {
decrypt(BASE_PROMPT_ENC, PROMPT_SEEDS[0])
}
/// The base prompt template source, exposed for `grok prompt --section template`.
/// The base prompt template source, exposed for `kigi prompt --section template`.
pub fn base_template_source() -> Zeroizing<String> {
base_template()
}
@@ -41,7 +41,7 @@ pub(crate) fn apply_patch_template() -> Zeroizing<String> {
decrypt(CODEX_PROMPT_ENC, PROMPT_SEEDS[1])
}
/// Apply-patch prompt template source, exposed for `grok prompt --section apply-patch-template`.
/// Apply-patch prompt template source, exposed for `kigi prompt --section apply-patch-template`.
pub fn apply_patch_template_source() -> Zeroizing<String> {
apply_patch_template()
}
@@ -93,7 +93,7 @@ mod tests {
);
}
/// Build a TemplateRenderer with the standard grok-build tool kinds.
/// Build a TemplateRenderer with the standard kigi tool kinds.
fn default_renderer() -> TemplateRenderer {
let tools: HashMap<ToolKind, String> = [
(ToolKind::Read, "read_file"),
@@ -5,7 +5,7 @@
//! workspace overview, optional rules / skills / MCP listings).
//!
//! `UserMessageTemplate` selects the rendering strategy:
//! - `Default` -- the legacy Grok Build prefix (built by the shell layer).
//! - `Default` -- the legacy Kigi prefix (built by the shell layer).
//! - `Custom` -- caller-supplied template string (MiniJinja, same delimiters
//! as the system prompt templates).
//!
@@ -63,7 +63,7 @@ fn normalize_git_status(status: &str) -> Option<String> {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum UserMessageTemplate {
/// Legacy Grok Build prefix: `<user_info>` + optional `<git_status>`.
/// Legacy Kigi prefix: `<user_info>` + optional `<git_status>`.
/// Built directly by the shell layer; this
/// renderer returns `None` for `Default` and the caller falls back to
/// its own legacy path.