M0: compilable skeleton — Kigi 0.1.0 fork surgery

Hard fork of xai-org/grok-build (Apache-2.0) re-targeted as Kigi, an
unofficial Kimi Code CLI community build.

Rename & identity
- 72 xai-*/xai-grok-* crates -> kigi-* (explicit: xai-grok-pager-bin ->
  kigi-bin [binary `kigi`], xai-grok-pager -> kigi-tui; rest mechanical);
  ptyctl, ptyctl-cli, third_party/ unchanged; proto package
  xai.grok.tools.v1 -> kigi.tools.v1
- Config home ~/.kigi (KIGI_SHARE_DIR override), env prefix GROK_* ->
  KIGI_*, `kigi --version` carries the unofficial-community-build notice
- clap identity, help text, startup banner, prompt templates rebranded
  (templates re-encrypted)

Deletions (PRD removal list #5/#6/#7/#9/#10)
- voice input (xai-grok-voice) and all TUI wiring
- telemetry: Mixpanel client, external OTel stream, Sentry, OTLP layers,
  trace/GCS/S3 upload queues (kigi-file-utils halved), workspace upload
  module & dc_log, heap-profile uploader, auth-diagnostics uploader,
  session-analytics halves of feedback; local zero-egress observability
  preserved in new kigi-log crate (unified log, --debug firehose,
  subsystem file logs, opt-in instrumentation)
- announcements (crate, remote-settings fields, TUI surfaces)
- plugin marketplace (crate, sources/browse/CTA/extensions-modal tab);
  direct plugin install/uninstall/update via kigi-agent git_install kept
- relay/gateway/assets endpoints and features (agent relay, headless
  relay transport, gateway bridge, LeaderEnvUrls); leader IPC socket now
  ~/.kigi/leader.sock + KIGI_LEADER_SOCKET, no ws-url derivation
- functional types rehomed instead of deleted: PermissionMode ->
  kigi-config-types, McpInitStrategy -> kigi-mcp, PrCreationSource ->
  session signals, TerminalDiagnostics -> kigi-pager-render, agent_id ->
  shell util

Endpoints
- kigi-env rewritten: single production KigiEndpoints {coding_api_base_url
  https://api.kimi.com/coding/v1 (KIGI_CODE_BASE_URL), oauth_host
  https://auth.kimi.com (KIGI_OAUTH_HOST), update_base_url (GitHub
  Releases API), upgrade_page_url}; GrokBuildEnvironment enum deleted

Toolchain & workspace hygiene
- Rust 1.97.0 pinned; edition 2024; full cargo update; git2 hoisted to
  workspace at 0.21 (Option->Result API migration), quick-xml 0.41
- Root Cargo.toml hand-maintained (PRD §8.1): version 0.1.0 inherited by
  all members, members sorted, unused deps pruned
- cargo-deny advisories gate (deny.toml with documented transitive
  exceptions); CI workflow (check/clippy/fmt/deny/test, macOS+Linux)
- cross-crate test seams re-gated behind `test-support` cargo feature;
  insta snapshot baselines renamed to the kigi_tui prefix
- clippy --workspace --all-targets: zero warnings; fmt clean

Fixes surfaced by the port
- updater probe/installer divergence (bin/kigi vs bin/grok symlink set)
- idle model-metadata refresh dead under KIGI_CODE_BASE_URL override
  (new is_effective_coding_endpoint_url, loopback+override aware)
- macOS symlinked-TMPDIR fixture canonicalization (foreign_sessions,
  fast-worktree); RSS measurement tests serialized via serial_test

Docs & legal (Apache §4)
- NOTICE added (upstream attribution + change statement); THIRD-PARTY
  notices sustained; kigi-tools ported-code notices extended; README,
  CONTRIBUTING, SECURITY, AGENTS.md rewritten

Out of scope for M0 (tracked): Kimi auth/inference (M1), search/fetch,
command parity, config import (M2), Computer Hub excision & final
brand-token sweep (M2), distribution & self-update rewrite (M3).
This commit is contained in:
2026-07-17 05:31:01 -04:00
commit d6c20fc13f
2612 changed files with 1353757 additions and 0 deletions
@@ -0,0 +1,222 @@
//! Unit tests for the `grok wrap` spawn planning in [`super`] (`wrap_cmd`),
//! split out via `#[path]` to keep the module itself small.
//!
//! Everything is pure — `derive_spawn` takes the PATH lookup result and the
//! shell as inputs — except the final test, which round-trips the rejoined
//! command line through a real `/bin/sh -c` to prove the quoting contract end
//! to end.
use super::*;
use pretty_assertions::assert_eq;
fn cmd(words: &[&str]) -> Vec<String> {
words.iter().map(|w| w.to_string()).collect()
}
#[test]
fn single_arg_with_whitespace_always_routes_via_shell() {
// Wins over PATH resolution: the arg is a command line, not a program.
let plan = derive_spawn(
&cmd(&["mycli ssh host-01"]),
"/bin/zsh",
true,
ShellMode::Interactive,
);
assert_eq!(plan.program, "/bin/zsh");
assert_eq!(plan.args, cmd(&["-i", "-c", "mycli ssh host-01"]));
// Wins over the explicit-path rule too: a single program path with
// spaces word-splits in the shell (quote it for the shell instead).
let plan = derive_spawn(
&cmd(&["/path/with space/prog"]),
"/bin/zsh",
false,
ShellMode::Interactive,
);
assert_eq!(plan.args, cmd(&["-i", "-c", "/path/with space/prog"]));
// Any whitespace counts, not just spaces: tabs/newlines also mark the
// arg as a command line to hand to the shell verbatim.
let plan = derive_spawn(
&cmd(&["x\tssh\nhost"]),
"/bin/sh",
false,
ShellMode::Interactive,
);
assert_eq!(plan.program, "/bin/sh");
assert_eq!(plan.args, cmd(&["-i", "-c", "x\tssh\nhost"]));
}
#[test]
fn resolvable_program_spawns_directly() {
let plan = derive_spawn(
&cmd(&["explorer", "ssh", "host"]),
"/bin/zsh",
true,
ShellMode::Interactive,
);
assert_eq!(plan.program, "explorer");
assert_eq!(plan.args, cmd(&["ssh", "host"]));
// A single resolvable word is a plain program run, not an alias.
let plan = derive_spawn(&cmd(&["ls"]), "/bin/zsh", true, ShellMode::Interactive);
assert_eq!(plan.program, "ls");
assert_eq!(plan.args, Vec::<String>::new());
// Explicit paths never route through the shell, resolvable or not —
// relative or absolute.
let plan = derive_spawn(
&cmd(&["./run.sh", "arg"]),
"/bin/zsh",
false,
ShellMode::Interactive,
);
assert_eq!(plan.program, "./run.sh");
let plan = derive_spawn(
&cmd(&["/abs/prog", "arg"]),
"/bin/zsh",
false,
ShellMode::Interactive,
);
assert_eq!(plan.program, "/abs/prog");
// A multi-arg first word with whitespace is never an alias: keep the
// direct spawn and its precise not-found error.
let plan = derive_spawn(
&cmd(&["my prog", "arg"]),
"/bin/zsh",
false,
ShellMode::Interactive,
);
assert_eq!(plan.program, "my prog");
assert_eq!(plan.args, cmd(&["arg"]));
// Same for an empty first word (unset `$PROG`): fail fast on the
// direct spawn rather than shell-executing the tail.
let plan = derive_spawn(
&cmd(&["", "rm", "-rf", "x"]),
"/bin/zsh",
false,
ShellMode::Interactive,
);
assert_eq!(plan.program, "");
}
#[test]
fn direct_route_passes_args_verbatim_without_quoting() {
// Quoting exists only on the shell route's rejoined line; a resolvable
// program must receive its argv elements byte-for-byte.
let plan = derive_spawn(
&cmd(&["rsync", "a b", "don't"]),
"/bin/zsh",
true,
ShellMode::Interactive,
);
assert_eq!(plan.program, "rsync");
assert_eq!(plan.args, cmd(&["a b", "don't"]));
}
#[test]
fn alias_route_keeps_first_word_bare_and_quotes_the_tail() {
// First word stays unquoted (aliases only expand on bare words); every
// tail word is quoted — zsh expands a bare `=word`, so no safe set.
let plan = derive_spawn(
&cmd(&["x", "ssh", "=host", "don't"]),
"/bin/zsh",
false,
ShellMode::Interactive,
);
assert_eq!(plan.program, "/bin/zsh");
assert_eq!(plan.args, cmd(&["-i", "-c", "x 'ssh' '=host' 'don'\\''t'"]));
// Bare alias with no args: the most common invocation.
let plan = derive_spawn(&cmd(&["x"]), "/bin/zsh", false, ShellMode::Interactive);
assert_eq!(plan.args, cmd(&["-i", "-c", "x"]));
}
#[test]
fn plain_shell_mode_drops_dash_i() {
let plan = derive_spawn(
&cmd(&["mycli ssh host"]),
"/bin/sh",
false,
ShellMode::Plain,
);
assert_eq!(plan.program, "/bin/sh");
assert_eq!(plan.args, cmd(&["-c", "mycli ssh host"]));
}
#[test]
fn quote_word_edge_cases() {
assert_eq!(quote_word("don't"), "'don'\\''t'");
assert_eq!(quote_word(""), "''");
// A lone quote is the worst case for the close-escape-reopen idiom.
assert_eq!(quote_word("'"), "''\\'''");
}
#[test]
fn quote_word_neutralizes_shell_metacharacters() {
// Expansion/control characters must come out single-quoted inert.
for meta in ["$HOME", "`id`", "*", "!!", ";", "&&", "|", "a\nb"] {
assert_eq!(quote_word(meta), format!("'{meta}'"));
}
}
#[test]
fn join_command_line_shapes() {
// Zero tail words: just the bare first word, no trailing space.
assert_eq!(join_command_line(&cmd(&["x"])), "x");
// An empty tail word survives as an explicit empty argument.
assert_eq!(join_command_line(&cmd(&["x", ""])), "x ''");
}
#[test]
fn resolve_shell_falls_back_to_bin_sh() {
assert_eq!(resolve_shell(None), "/bin/sh");
assert_eq!(resolve_shell(Some("")), "/bin/sh");
assert_eq!(resolve_shell(Some("/nonexistent/shell-xyz")), "/bin/sh");
}
#[test]
fn resolve_shell_uses_existing_file() {
let file = tempfile::NamedTempFile::new().expect("tempfile");
let path = file.path().to_str().expect("utf8 path").to_string();
assert_eq!(resolve_shell(Some(&path)), path);
}
/// Feed the rejoined command line through a real `/bin/sh -c` and assert the
/// child receives exactly the original words — the quoting contract proven
/// against an actual shell, not just against expected strings.
#[test]
fn joined_line_roundtrips_words_through_real_sh() {
let words = [
"a b",
"don't",
"=x",
"new\nline",
"$HOME",
"`id`",
"*",
";",
"&&",
"|",
"",
];
// `printf` repeats the format per argument, so each word renders as `[w]`.
let mut command = vec!["printf".to_string(), "[%s]".to_string()];
command.extend(words.iter().map(|w| w.to_string()));
let out = std::process::Command::new("/bin/sh")
.arg("-c")
.arg(join_command_line(&command))
.output()
.expect("run /bin/sh");
assert!(
out.status.success(),
"sh rejected the joined line: {}",
String::from_utf8_lossy(&out.stderr)
);
let expected: String = words.iter().map(|w| format!("[{w}]")).collect();
assert_eq!(String::from_utf8_lossy(&out.stdout), expected);
}