This document describes the system architecture, communication protocols, data structures, and implementation details of Akatsuki Git.
┌─────────────────────────────────────────────────────────────────┐
│ VS Code Extension (TypeScript) │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Protocol │ Status Bar │ Dashboard │ Git Watcher │ Messages│ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────┬───────────────────────────────────┘
│ JSON-RPC 2.0 (line-delimited)
│ stdin → RPC requests
│ stdout → RPC responses
│ stderr → logging
┌─────────────────────────────┴───────────────────────────────────┐
│ akatsuki-backend (Rust) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ RPC Handler │ Git Analyzer │ Storage │ Rank Calculator │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────┬───────────────────────┬────────────────────────────┘
│ │
│ │
┌─────────────┴─────┐ ┌──────────┴──────────────────┐
│ SQLite Database │ │ Git Analysis (git2-rs + CLI) │
│ ┌───────────────┐ │ │ ┌────────────────────────┐ │
│ │ Profile │ │ │ │ Commit DAG Walking │ │
│ │ Repos │ │ │ │ SHA Caching │ │
│ │ Events │ │ │ │ Commit Counting │ │
│ │ Key-Value │ │ │ │ Branch Tracking │ │
│ └───────────────┘ │ │ └────────────────────────┘ │
└────────────────────┘ └──────────────────────────────┘
The extension and backend communicate via line-delimited JSON-RPC 2.0 over standard input/output.
- Spawn: Extension activates → spawns
akatsuki-backendbinary - Handshake: Extension sends
handshakerequest with protocol version - Watchdog: Extension sends
pingevery 15 seconds; missing response → respawn backend - Shutdown: Extension deactivates → kills backend process
Health check used by watchdog.
Request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "ping",
"params": {}
}Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {}
}Version negotiation to ensure protocol compatibility.
Request:
{
"jsonrpc": "2.0",
"id": 2,
"method": "handshake",
"params": {
"version": 1
}
}Response:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"version": 1,
"ok": true
}
}If ok is false, the extension logs a version mismatch error and deactivates.
Create or update the singleton user profile (idempotent).
Request:
{
"jsonrpc": "2.0",
"id": 3,
"method": "init_profile",
"params": {
"name": "Naruto Uzumaki",
"path": "itachi"
}
}Response:
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"id": 1,
"name": "Naruto Uzumaki",
"path": "itachi",
"created_at": 1704067200000
}
}Retrieve the current user profile.
Request:
{
"jsonrpc": "2.0",
"id": 4,
"method": "get_profile",
"params": {}
}Response:
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"id": 1,
"name": "Naruto Uzumaki",
"path": "itachi",
"created_at": 1704067200000
}
}Returns null if no profile exists.
Update the character path for the existing profile.
Request:
{
"jsonrpc": "2.0",
"id": 5,
"method": "set_path",
"params": {
"path": "madara"
}
}Response:
{
"jsonrpc": "2.0",
"id": 5,
"result": {
"id": 1,
"name": "Naruto Uzumaki",
"path": "madara",
"created_at": 1704067200000
}
}Analyze a Git repository to count commits and track state.
Request:
{
"jsonrpc": "2.0",
"id": 6,
"method": "analyze_repo",
"params": {
"path": "/path/to/repo"
}
}Response:
{
"jsonrpc": "2.0",
"id": 6,
"result": {
"total_commits": 47,
"current_branch": "main",
"last_seen_sha": "a1b2c3d4e5f6..."
}
}Calculate rank information based on total commit count.
Request:
{
"jsonrpc": "2.0",
"id": 7,
"method": "get_rank",
"params": {
"total_commits": 150
}
}Response:
{
"jsonrpc": "2.0",
"id": 7,
"result": {
"rank": "Chunin",
"rank_key": "chunin",
"current": 150,
"next_threshold": 500,
"progress": 0.125
}
}For maximum rank (Akatsuki Member), next_threshold is null and progress is 1.0.
Log a Git operation event.
Request:
{
"jsonrpc": "2.0",
"id": 8,
"method": "record_event",
"params": {
"repo_path": "/path/to/repo",
"op": "commit",
"sha": "a1b2c3d4..."
}
}Response:
{
"jsonrpc": "2.0",
"id": 8,
"result": {}
}Valid operations: commit, push, pull, merge, merge_conflict.
Retrieve themed messages for Git operations based on selected path.
Request:
{
"jsonrpc": "2.0",
"id": 9,
"method": "get_message_templates",
"params": {
"path": "itachi"
}
}Response:
{
"jsonrpc": "2.0",
"id": 9,
"result": {
"commit": {
"in_flight": "Sealing knowledge into a forbidden scroll…",
"completion": "Mission Report Recorded\n\nEvery growth requires sacrifice."
},
"push": {
"in_flight": "Transmitting intelligence to Akatsuki Headquarters…",
"completion": "Mission report delivered. Leader has acknowledged your efforts.\n\nEvery growth requires sacrifice."
},
"pull": {
"in_flight": "Receiving intelligence from allied spies…",
"completion": "New information acquired.\n\nEvery growth requires sacrifice."
},
"merge": {
"in_flight": "Combining parallel timelines…",
"completion": "Reality stabilized.\n\nEvery growth requires sacrifice."
},
"merge_conflict": {
"in_flight": "⚔ Shinobi Battle Detected",
"completion": "Two powerful jutsu have collided. Resolve the conflict to continue."
}
}
}The backend sends unsolicited notifications for state changes:
Emitted after successful handshake, indicating the backend is ready.
{
"jsonrpc": "2.0",
"method": "initialized",
"params": {}
}Emitted when a repository's total commits cross a rank threshold.
{
"jsonrpc": "2.0",
"method": "rank_changed",
"params": {
"repo_path": "/path/to/repo",
"old": {
"rank": "Genin",
"rank_key": "genin"
},
"new": {
"rank": "Chunin",
"rank_key": "chunin"
}
}
}SQLite database file is stored at:
- macOS:
~/Library/Application Support/akatsuki-git/state.db - Linux:
~/.local/share/akatsuki-git/state.db - Windows:
%APPDATA%\akatsuki-git\state.db
- Single SQLite connection behind a
Mutexfor thread-safe access - WAL mode enabled for concurrent reads
busy_timeout=5000(5 seconds) to handle contention- All database operations use retry logic
PRAGMA journal_mode=WAL;
PRAGMA busy_timeout=5000;
CREATE TABLE IF NOT EXISTS profile (
id INTEGER PRIMARY KEY CHECK (id = 1),
name TEXT NOT NULL,
path TEXT NOT NULL CHECK (path IN ('itachi','pain','obito','madara')),
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS repos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
path TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
total_commits INTEGER NOT NULL DEFAULT 0,
last_seen_sha TEXT,
first_seen_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
repo_id INTEGER NOT NULL REFERENCES repos(id),
op TEXT NOT NULL CHECK (op IN ('commit','push','pull','merge','merge_conflict')),
sha TEXT,
ts INTEGER NOT NULL,
payload TEXT
);
CREATE INDEX IF NOT EXISTS idx_events_repo_time ON events(repo_id, ts);
CREATE TABLE IF NOT EXISTS kv (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);profile: Singleton user profile (id=1 enforced) for shinobi name and character pathrepos: Tracked Git repositories with commit counts and last seen SHAevents: Log of Git operations for future analyticskv: Key-value storage for configuration and cache
| Rank | rank_key | Total Commits Range |
|---|---|---|
| Academy Student | academy_student |
0–24 |
| Genin | genin |
25–99 |
| Chunin | chunin |
100–499 |
| Jonin | jonin |
500–1499 |
| Anbu | anbu |
1500–4999 |
| Akatsuki Member | akatsuki_member |
5000+ |
Progress within current rank is calculated as:
floor = minimum commits for current rank
next_floor = minimum commits for next rank (or null if max rank)
progress = (current_commits - floor) / (next_floor - floor)
Result is clamped to [0, 1]. For maximum rank, progress = 1.0 and next_threshold = null.
| Path | Description |
|---|---|
itachi |
The path of sacrifice and duty |
pain |
The path through suffering to peace |
obito |
The path of reality correction |
madara |
The path of ambition and power |
Default: itachi (selected if user skips onboarding).
All paths share the same in-flight messages but have unique completion suffixes.
| Operation | In-Flight Message |
|---|---|
| Commit | "Sealing knowledge into a forbidden scroll…" |
| Push | "Transmitting intelligence to Akatsuki Headquarters…" |
| Pull | "Receiving intelligence from allied spies…" |
| Merge | "Combining parallel timelines…" |
| Merge Conflict | "⚔ Shinobi Battle Detected" |
| Operation | Completion Message |
|---|---|
| Commit | "Mission Report Recorded" |
| Push | "Mission report delivered. Leader has acknowledged your efforts." |
| Pull | "New information acquired." |
| Merge | "Reality stabilized." |
| Merge Conflict | "Two powerful jutsu have collided. Resolve the conflict to continue." |
The following suffixes are appended to completion messages for all operations except merge_conflict:
- Itachi: "Every growth requires sacrifice."
- Pain: "Through pain comes progress."
- Obito: "Reality has been corrected."
- Madara: "Your ambition grows stronger."
Merge conflict messages remain unchanged regardless of path.
Akatsuki Git uses a hybrid, three-layer approach to detect Git events:
Uses the built-in vscode.git extension API:
const gitApi = vscode.extensions.getExtension('vscode.git')?.exports.getAPI(1);
gitApi.onDidChangeState(e => handleGitStateChange(e));This provides repository state changes with high accuracy within VS Code.
Watches .git/HEAD for immediate, reliable detection:
const watcher = vscode.workspace.createFileSystemWatcher('**/.git/HEAD');
watcher.onDidChange(e => handleHeadChange(e));This catches external Git operations that may not immediately reflect in VS Code's API.
Queries the backend every 5 minutes to poll for changes:
setInterval(() => backend.analyzeRepo(activeRepo.path), 5 * 60 * 1000);This ensures no events are missed even if both primary layers fail.
- Check cache: Query database for
last_seen_shaandtotal_commits - Walk DAG: Use
git2-rsto walk fromHEADtolast_seen_sha(exclusive) - Incremental count: Count only new commits since cached SHA
- Update cache: Store new
total_commitsand current HEAD SHA
If git2-rs fails (e.g., shallow clone, worktree edge cases), shell out to:
git rev-list --count HEADThis provides a reliable fallback at the cost of performance for large repositories.
- Database: Single
Mutex<Connection>ensures serialized access - WAL mode: Allows concurrent reads during writes
- Busy timeout: 5-second retry window for contention
- All Rust logging → stderr only
- stdout reserved strictly for JSON-RPC frames
- Extension forwards backend stderr to "Akatsuki Git" output channel
- This prevents stdio deadlock from mixed output
- Extension sends
pingevery 15 seconds - No response within 15 seconds → kill and respawn backend
- New backend instance restarts from handshake
PROTOCOL_VERSIONconstant on both sides (currently1)- Handshake failure on version mismatch → extension deactivates
- Protocol changes require version bump and mirroring to TypeScript
Format: ☁ Akatsuki | Rank: <Rank> | Missions: <N>
Where:
<Rank>= current shinobi rank (e.g., "Chunin")<N>= total commit count across all tracked repositories
The status bar updates on:
- Rank change
- New repository analyzed
- Commit count change
The shared crate (akatsuki-protocol) is the single source of truth for types:
- Rust: Define types in
shared/src/lib.rs - Mirror: Manually update
shared/ts/protocol.ts - Version: Bump
PROTOCOL_VERSIONconstant - Copy: Run
npm run copy-protocolin extension directory
Build step copies shared/ts/protocol.ts → extension/src/protocol.ts.
Future enhancement: Replace with ts-rs codegen for automatic synchronization.