Skip to content

init: --no-history, for checkouts that never read the past - #94

Merged
jschatz1 merged 1 commit into
mainfrom
feat/init-no-history
Sep 8, 2026
Merged

init: --no-history, for checkouts that never read the past#94
jschatz1 merged 1 commit into
mainfrom
feat/init-no-history

Conversation

@jschatz1

@jschatz1 jschatz1 commented Sep 8, 2026

Copy link
Copy Markdown
Member

Chasing why a PR review takes ~16 minutes. On kai-server#195 the run was 979s, and 875s of it was one line: kai init in the review pod.

Almost none of that is the semantic graph. kai init replays up to 50 commits as snapshots (runGitImport, capped at importMaxCommits) before it captures the working tree.

Measured on a fresh clone of kai-server at ba7e4c2 with KAI_CAPTURE_TIMING=1:

kai init (git history + graph) 83.7s
kai init with no .git present (graph only) 4.1s
…of which the whole Analyze pass 2.7s (parse+symbols 2.25s, imports+tests 155ms, calls 131ms)

So ~95% of init is history the caller may never touch. That's a fine trade for a person — it's what makes kai log, blame and bisect worth having — and a pure tax on a container that is deleted at the end of one review: the reviewer's blast walk uses the freshly-captured single-snapshot graph (BlastFor(..., headHex "")), and base...head comes from git.

--no-history skips the import. Default behavior is unchanged.

Two tests: --no-history leaves exactly one snapshot (the working-tree capture, which the review does read), and the default still imports more than one.

The consumer is kaicontext/kai-server#198, which probes for the flag rather than hardcoding it — the pinned kai-ci image predates it, so nothing changes until the pin moves to an image built from this.

🤖 Generated with Claude Code

`kai init` replays up to 50 commits as snapshots, and on any real repo
that import is nearly all of its wall clock: measured on kai-server at
ba7e4c2, 83.7s with the import and 4.1s without — the semantic graph
itself is 2.7s of that.

The review pod pays it every run and reads none of it. The blast walk
uses the freshly-captured single-snapshot graph, and base...head comes
from git; the imported snapshots exist for `kai log`, blame and bisect,
which nothing in a container that is deleted at the end of one review
will ever run.

Default behavior is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jschatz1 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: ea4bd2a0-053b-4a73-a167-33e4d98cd2fe


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kaicontext kaicontext Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kai review

Kai Summary

Read through this one. One thing worth your eyes before it merges. 👇

Review: kai init --no-history

Scope: kai-engine, commit 3e49fd6. I read the production change in cmd/kai/main.go (the init flow, runGitImport, and the already-initialized short-circuit), the new test file, and the existing init_test.go for comparison. Nothing outside this repo is implicated.

What it does: Adds a --no-history flag (wired to the initNoHistory global) that, when set, skips the runGitImport call inside runInit. Default behavior is untouched — the import still runs whenever the flag is absent. Two tests cover both branches by counting KindSnapshot nodes after init.

Overall take: This is a clean, narrowly-scoped change with a genuine fix-test. The guard is correctly placed inside the isGitRepo block, the default path is byte-for-byte preserved (the old code is just nested one level deeper under if !initNoHistory), and the no-history test would actually fail on the pre-change code. I have no defects to report.

A few things I specifically verified:

  • The test is not a no-op. TestInitNoHistorySkipsTheImport sets initNoHistory = true and asserts exactly one snapshot. On the pre-change code, initNoHistory is never read, so runGitImport would run unconditionally for the 3-commit repo and produce 3 history snapshots plus the working-tree capture, failing the got != 1 assertion. With the fix, only the Step-4 runCapture snapshot exists, so got == 1 passes. This is a real regression guard, not a mechanism-asserts-config shape.
  • The default test guards the right invariant. TestInitImportsHistoryByDefault asserts \> 1 snapshots, which requires the import to have actually run — so a future regression that accidentally gates the import too broadly (e.g., inverting the flag) is caught here too.
  • Global mutation is safe under the test runner. runInitInRepo saves/restores four package globals via t.Cleanup. These tests don't call t.Parallel(), so they run sequentially within the package; no data race on the globals. snapshotCount reads kaiDir while it's still .kai (cleanup is LIFO, runs after the count), and uses an absolute dir join, so it's correct regardless of cwd.
  • No downstream breakage from skipping the import. runGitImport's side effects beyond snapshot creation are writing graph_refs pins and the kaiDir/message file; with --no-history those simply aren't produced, which is consistent with a one-shot checkout that never runs kai log/blame/bisect. The capture that follows is independent and still runs, so the head graph the review actually reads is present.
  • The pre-existing git rev-list/runGitImport shell-outs have no deadline. That's unchanged by this diff — the change only adds a gate in front of them — so it's not a new defect, though a timeout on those subprocesses would be a worthwhile follow-up for the non-no-history path.

One non-defect worth flagging as a decision: --no-history is a new user-facing flag that, when passed, silently removes the data backing kai log, blame, and bisect for that workspace. It's opt-in, default-preserving, and clearly documented in the flag help text, so it's low-stakes. The decision a human owns is how broadly it gets wired into automation templates — a CI config that defaults every kai init to --no-history would quietly strip history from every workspace that uses it. The flag itself is fine; the policy of where it's applied is the thing to keep an eye on.

Merge readiness: This is ready to merge — no defects, and the only decision (where --no-history gets baked into automation) lives outside this diff.

Important files changed
File Change
cmd/kai/init_no_history_test.go modified · +99 −0
cmd/kai/main.go modified · +20 −5

Decisions

Correct as written, but somebody should say yes to these:

  • --no-history is a new opt-in flag that strips kai log/blame/bisect data from a workspace; the flag is fine, but wherever it gets defaulted into automation templates is a policy decision about how broadly history is suppressed, affecting anyone whose init runs through that template.

+119 −5 · 2 files · reaches 0 · the full analysis
💬 Reply to any of my comments and I'll answer, or say @kaicontext anywhere on this PR — a question, or "take another look at the retry logic".

@jschatz1
jschatz1 merged commit f04cdbe into main Sep 8, 2026
8 checks passed
@jschatz1
jschatz1 deleted the feat/init-no-history branch September 8, 2026 11:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant