BudgetLimited is now a resumable state: a budget trip demotes in-flight
nodes to Ready (a resource stop, not a verdict — no forever-Running node is
ever persisted) and '/graph resume --budget <tokens>' re-arms the graph with
fresh headroom (new budget = spent-so-far + extra). The tripped node's
partial burn is charged into tokens_spent_nodes at BOTH cascade sites before
the demotion clears current_node, so the top-up arithmetic never runs on an
under-counted ledger. Any input starting with 'resume' resolves to a resume
(case-insensitive; malformed top-ups surface the usage hint) and setup_graph
refuses to replace any non-Complete graph — a typo can no longer silently
destroy a resumable graph. An explicit --budget on a merely-paused graph is
rejected loudly instead of silently discarded; all trip-time messages now
advertise the top-up.
The pager gains a graph status chip: a new GraphUpdated wire variant
(extensions/notification.rs, old pagers degrade via #[serde(other)]) is
emitted from the single persist_graph_state chokepoint — every transition is
both a checkpoint and a badge tick — with a 'cleared' sentinel on /graph
clear and a one-shot re-emit after session restore (the replayed updates log
otherwise shows the pre-shutdown Active state that from_snapshot just
demoted in memory). TUI side: GraphDisplayState, session-notification arm,
and a goal-idiom chip with node progress, clamped current-node title, and
budget-aware spend. Pre-session command availability now advertises /graph
from the flags (it was fail-closed to the in-session path only, so the
welcome-screen slash menu never showed it).
Coverage: GraphUpdated wire round-trip + minimal-payload + unknown-tag
tests; PTY scenarios graph_slash_presession{,_disabled}.yaml (both run
green against the real pager binary); handle_prompt-level e2e for terminal
slash outcomes (/graph status|resume|pause, /goal refusals while the graph
owns the engine); budget top-up e2e driving a BudgetLimited diamond back to
Complete. Not shimmed: pre-G2 persisted snapshots with budget-Failed nodes
(the KIGI_GRAPH flag has never shipped enabled, so none exist).
kigi-shell 4927 and kigi-tui 6610 lib tests green; workspace clippy clean.
7.0 KiB
Kigi — agent/developer notes
Single source of truth for how this repository is organized and the constraints every change must respect. Update this file whenever the tech stack or product direction changes.
What this is
Kigi is an unofficial Kimi Code CLI community build: a hard fork of
xai-org/grok-build (Apache-2.0, Rust) re-targeted at the Kimi Code
subscription API and the Moonshot open platform. It coexists with the
official kimi CLI: binary kigi, config dir ~/.kigi
(KIGI_SHARE_DIR override), keyring service kigi, env prefix KIGI_*.
Never read or write ~/.kimi (except the explicit one-time read-only
import) or any KIMI_* env var.
Hard constraints
- Zero egress: outbound connections are limited to
auth.kimi.com,api.kimi.com,api.moonshot.cn,api.moonshot.ai, GitHub Releases domains, and user-configured MCP servers. No telemetry, no analytics, ever.crates/codegen/kigi-envis the single home of first-party endpoints. - Toolchain: Rust 1.97.0 (rust-toolchain.toml), edition 2024.
- Gates (all must stay green):
cargo check --workspace --all-targets,cargo clippy --workspace --all-targets(zero warnings),cargo fmt --all --check,cargo deny check advisories. - Observability is local:
kigi-log(unified session log,--debugfirehose, subsystem file logs, opt-in instrumentation) writes under~/.kigionly. Its zero-network property is a contract. - The root
Cargo.tomlis hand-maintained (upstream's generator is not in this repo). Members sorted; versions inherited fromworkspace.package.version(0.1.0).
Layout
crates/codegen/— the bulk of the application (62kigi-*crates). Key ones:kigi-bin(binarykigi),kigi-tui(full-screen TUI + headless-pmode +acp/mcpcommands),kigi-shell(agent runtime, leader-follower IPC, sessions),kigi-sampler(inference client; ChatCompletions/Responses/Messages backends),kigi-auth(credentials),kigi-config(config layering,~/.kigipaths),kigi-env(endpoints),kigi-tools(tool implementations incl. codex/opencode ports — see its THIRD_PARTY_NOTICES.md),kigi-workspace(FS/VCS/exec/permissions, checkpoint/worktree),kigi-log(local observability).crates/common/,crates/build/,prod/mc/— shared libs, proto build, proxy wire types (the latter to be redefined against Kimi in M1).third_party/— vendored Mermaid rendering stack (untouched policy).bin/protoc— dotslash launcher used by proto codegen.
Storage discipline
- Tests that touch the filesystem MUST use
tempfile::TempDir(drop cleans up) — never barestd::env::temp_dir()+create_dir_all, which leaks directories into the OS temp root forever. target/grows past 150GB across repeated full-workspace builds (incremental is already off); runcargo cleanwhen it exceeds ~50GB and at milestone boundaries.- Graph node worktrees are removed right after a successful merge-back; only FAILED nodes keep theirs for postmortem.
Test seams
Cross-crate test hooks are behind the test-support cargo feature
(kigi-workspace, kigi-pager-render, kigi-config, kigi-tui), enabled via
dependents' [dev-dependencies]. Don't expose new test seams as plain
#[cfg(test)] items across crate boundaries.
Graph mode (/graph, post-0.1.x — plan.md in the parent dir)
A deterministic DAG scheduler layered over the goal engine: /graph <objective> decomposes the objective into nodes (graph planner subagent
→ Agentproof-style static gate in graph_plan.rs), then executes each
node as one ordinary goal — the agentic loop lives INSIDE the node; the
edges stay deterministic Rust. The harness appends a terminal
gn-final verification node depending on every planner node.
- Feature flag
KIGI_GRAPH=1(default off); availability additionally requires the goal harness (BuiltinGate::Graph). - Key modules (kigi-shell):
session/graph_tracker.rs(pure state machine; reusesGoalStatus/GoalPhase/GoalPauseReason),session/graph_plan.rs(planner-JSON contract + validation + fnv id canonicalization),session/graph_planner.rs(planner runner, reuses the goal planner spawn plumbing),session/acp_session_impl/graph.rs(orchestration seam). - Seam points:
handle_promptintercepts GraphSet/GraphResume; the in-turn loop'sEndTurnarm callsrun_graph_round_end()to advance nodes within the same turn; goal auto-pauses cascade to the graph inauto_pause_goal_if_active_inner; node goals are armed with the REMAINING graph budget soenforce_goal_token_budgetcascades trips. - Persistence:
PersistenceMsg::GraphModeState(Option<..>)→<session_dir>/graph/state.json(Nonetombstones after clear); immutable per-version baselinesgraph/graph.baseline.v{N}.json; per-node goal artifacts archived tograph/<node_id>/. Restore demotesActive→UserPausedandRunning→Ready(re-run is safe: the verifier gates completion). /goaland/graphare mutually exclusive while the graph owns the engine; e2e suite:acp_session_tests/graph/graph_e2e_tests.rs.- Parallel fan-out (G1): with
KIGI_GRAPH_CONCURRENCY > 1(default 3, clamp [1,8]) and ≥2Readynodes,drive_graphruns batches viaacp_session_impl/graph_workers.rs— per node a bounded worker↔verifier subagent loop (KIGI_GRAPH_NODE_ROUNDS, default 3;general-purposechildren; worktree isolation on round 1, resume keeps context+worktree on later rounds;NODE_RESULT:/NODE_VERDICT:terminal contracts parsed fail-closed), then SEQUENTIAL merge-back viakigi_workspace::worktree::apply_worktree(ApplyMode::Merge); a conflict fails the node and blocks its dependents while other chains continue.gn-finalalways runs serially on the full goal engine. Concurrency=1 is byte-identical to the serial G0 path. Ceiling: a worker round exceeding the foreground subagent await budget (600s) is cancelled and retried via resume. - G2:
BudgetLimitedis resumable — a budget trip demotes in-flight nodes toReady(resource stop, not a verdict) and/graph resume --budget <tokens>re-arms with fresh headroom. The pager shows a graph status chip driven by theGraphUpdatedwire variant (extensions/notification.rs), emitted from the singlepersist_graph_statechokepoint (checkpoint ⇔ badge tick); old pagers degrade via#[serde(other)] Unknown. PTY scenarios:graph_slash_presession{,_disabled}.yaml.
Milestones (PRD §8.3)
- M0 (done): rename, deletions (voice/telemetry/announcements/marketplace/ relay-gateway), toolchain, gates.
- M1: Kimi device-flow auth (F1), Moonshot API-key channel (F2), inference
via ChatCompletions (F3), dynamic model sync (F4). The auth stack in
kigi-shell/src/auth+kigi-authgets rewritten here; transitional grok.com references live only there and inkigi-sampler/proxy types. - M2: server-side search/fetch (F5), command parity with kimi-cli 1.49.0
(F6), one-time
~/.kimi/config.tomlimport (F7), F9 smoke list, perf CI. - M3: GitHub Releases distribution, install scripts, self-update (F8).