← Back to list

LeGittingEdition

By Ethan G Appleby.

Ethan G Appleby · 2026-03-08 10:33 · 50 claps · 21.6 min read
#game-modding #shaders #github #voxel #game-launchers
Open on Medium ↗
Wiki topics: 🔓 · Open Source

LeGittingEdition

By Ethan G Appleby.

Obviously this is a Do Not Run!!! version due to no safety handling (missing) and also this is not to be confused with well… LCE it is clearly LeGittingEdition launching framework of the..

// ============================================================================
// LeGitingEdition (lge)
// A delta layer on top of Git for fork-driven software ecosystems.
//
// Adds: fork registry, usage telemetry, delta-compressed binary distribution,
// branch browsing, AI attribution tracking, and community metrics.
//
// Build: g++ -std=c++17 -O2 -o lge lge.cpp -lsqlite3 -lz -lssl -lcrypto
// ============================================================================

#include <algorithm>
#include <cassert>
#include <chrono>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <filesystem>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <string_view>
#include <unordered_map>
#include <variant>
#include <vector>

#include <sqlite3.h>
#include <zlib.h>
#include <openssl/sha.h>

namespace fs = std::filesystem;

// ============================================================================
// CONFIG & PATHS
// ============================================================================

namespace config {

inline fs::path home_dir()       { return fs::path(std::getenv("HOME")) / ".lge"; }
inline fs::path registry_db()    { return home_dir() / "registry.db"; }
inline fs::path telemetry_db()   { return home_dir() / "telemetry.db"; }
inline fs::path binary_cache()   { return home_dir() / "cache"; }
inline fs::path delta_store()    { return home_dir() / "deltas"; }
inline fs::path branches_dir()   { return home_dir() / "branches"; }
inline fs::path config_file()    { return home_dir() / "config.json"; }

constexpr size_t BLOCK_SIZE = 4096;
constexpr const char* VERSION = "0.1.0";

} // namespace config

// ============================================================================
// UTILITY HELPERS
// ============================================================================

namespace util {

std::string sha256_hex(const std::string& input) {
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256(reinterpret_cast<const unsigned char*>(input.data()),
           input.size(), hash);
    std::ostringstream oss;
    for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i)
        oss << std::hex << std::setfill('0') << std::setw(2)
            << static_cast<int>(hash[i]);
    return oss.str();
}

std::string sha256_bytes(const std::vector<uint8_t>& data) {
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256(data.data(), data.size(), hash);
    std::ostringstream oss;
    for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i)
        oss << std::hex << std::setfill('0') << std::setw(2)
            << static_cast<int>(hash[i]);
    return oss.str();
}

// FNV-1a fast block hash
std::string block_hash(const uint8_t* data, size_t len) {
    uint64_t h = 0xcbf29ce484222325ULL;
    for (size_t i = 0; i < len; ++i) {
        h ^= data[i];
        h *= 0x100000001b3ULL;
    }
    std::ostringstream oss;
    oss << std::hex << std::setfill('0') << std::setw(16) << h;
    return oss.str();
}

std::string random_hex(size_t bytes) {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dist(0, 255);
    std::ostringstream oss;
    for (size_t i = 0; i < bytes; ++i)
        oss << std::hex << std::setfill('0') << std::setw(2) << dist(gen);
    return oss.str();
}

std::string utc_now() {
    auto now = std::chrono::system_clock::now();
    auto t   = std::chrono::system_clock::to_time_t(now);
    std::tm tm{};
    gmtime_r(&t, &tm);
    char buf[32];
    std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tm);
    return buf;
}

std::time_t parse_iso(const std::string& iso) {
    std::tm tm{};
    strptime(iso.c_str(), "%Y-%m-%dT%H:%M:%S", &tm);
    return timegm(&tm);
}

struct ProcResult {
    int exit_code;
    std::string out;
    std::string err;
};

ProcResult run_cmd(const std::vector<std::string>& args) {
    std::string cmd;
    for (auto& a : args) cmd += "'" + a + "' ";
    cmd += "2>/tmp/lge_stderr";

    FILE* fp = popen(cmd.c_str(), "r");
    if (!fp) return {-1, "", ""};

    std::string output;
    char buf[4096];
    while (fgets(buf, sizeof(buf), fp)) output += buf;

    int status = pclose(fp);
    int code   = WEXITSTATUS(status);

    std::string errout;
    std::ifstream errf("/tmp/lge_stderr");
    if (errf) { std::ostringstream oss; oss << errf.rdbuf(); errout = oss.str(); }

    return {code, output, errout};
}

std::vector<uint8_t> read_file_bytes(const fs::path& path) {
    std::ifstream f(path, std::ios::binary);
    if (!f) return {};
    return {std::istreambuf_iterator<char>(f), {}};
}

void write_file_bytes(const fs::path& path, const std::vector<uint8_t>& data) {
    std::ofstream f(path, std::ios::binary);
    f.write(reinterpret_cast<const char*>(data.data()), data.size());
}

std::string read_file_text(const fs::path& path) {
    std::ifstream f(path);
    if (!f) return "";
    std::ostringstream oss; oss << f.rdbuf();
    return oss.str();
}

void write_file_text(const fs::path& path, const std::string& text) {
    std::ofstream f(path); f << text;
}

std::string trim(const std::string& s) {
    auto start = s.find_first_not_of(" \t\r\n");
    auto end   = s.find_last_not_of(" \t\r\n");
    if (start == std::string::npos) return "";
    return s.substr(start, end - start + 1);
}

std::vector<std::string> split(const std::string& s, char delim) {
    std::vector<std::string> parts;
    std::istringstream ss(s);
    std::string part;
    while (std::getline(ss, part, delim))
        if (!part.empty()) parts.push_back(part);
    return parts;
}

std::vector<uint8_t> zlib_compress(const std::vector<uint8_t>& data) {
    uLongf bound = compressBound(data.size());
    std::vector<uint8_t> out(bound);
    int rc = compress2(out.data(), &bound, data.data(), data.size(), 9);
    if (rc != Z_OK) return {};
    out.resize(bound);
    return out;
}

std::vector<uint8_t> zlib_decompress(const std::vector<uint8_t>& data) {
    size_t out_size = data.size() * 10;
    std::vector<uint8_t> out(out_size);
    uLongf actual = out_size;
    while (true) {
        int rc = uncompress(out.data(), &actual, data.data(), data.size());
        if (rc == Z_OK) { out.resize(actual); return out; }
        if (rc == Z_BUF_ERROR) {
            out_size *= 2; out.resize(out_size); actual = out_size;
        } else { return {}; }
    }
}

} // namespace util

// ============================================================================
// MINIMAL JSON
// ============================================================================

namespace json {

struct Value;
using Object = std::map<std::string, Value>;

struct Value {
    std::variant<std::string, double, bool, Object> data;

    Value() : data(std::string("")) {}
    Value(const std::string& s) : data(s) {}
    Value(const char* s) : data(std::string(s)) {}
    Value(double d) : data(d) {}
    Value(bool b) : data(b) {}
    Value(const Object& o) : data(o) {}

    bool is_string() const { return std::holds_alternative<std::string>(data); }
    bool is_number() const { return std::holds_alternative<double>(data); }
    bool is_bool()   const { return std::holds_alternative<bool>(data); }
    bool is_object() const { return std::holds_alternative<Object>(data); }

    const std::string& str() const { return std::get<std::string>(data); }
    double num()             const { return std::get<double>(data); }
    bool   boolean()         const { return std::get<bool>(data); }
    const Object& obj()      const { return std::get<Object>(data); }
    Object& obj_mut()              { return std::get<Object>(data); }
};

std::string serialize(const Value& v, int indent = 0) {
    std::string pad(indent, ' ');
    std::string pad2(indent + 2, ' ');

    if (v.is_bool())   return v.boolean() ? "true" : "false";
    if (v.is_number()) {
        std::ostringstream oss; oss << v.num(); return oss.str();
    }
    if (v.is_string()) return "\"" + v.str() + "\"";
    if (v.is_object()) {
        std::ostringstream oss;
        oss << "{\n";
        auto& obj = v.obj();
        size_t i = 0;
        for (auto& [k, val] : obj) {
            oss << pad2 << "\"" << k << "\": " << serialize(val, indent + 2);
            if (++i < obj.size()) oss << ",";
            oss << "\n";
        }
        oss << pad << "}";
        return oss.str();
    }
    return "null";
}

class Parser {
    std::string_view src;
    size_t pos = 0;

    void skip_ws() { while (pos < src.size() && std::isspace(src[pos])) ++pos; }
    char peek() { skip_ws(); return pos < src.size() ? src[pos] : 0; }
    char next() { skip_ws(); return pos < src.size() ? src[pos++] : 0; }

    std::string parse_string() {
        next();
        std::string result;
        while (pos < src.size() && src[pos] != '"') {
            if (src[pos] == '\\') { ++pos; result += src[pos++]; }
            else result += src[pos++];
        }
        if (pos < src.size()) ++pos;
        return result;
    }

    Value parse_value() {
        skip_ws();
        if (pos >= src.size()) return Value("");
        char c = src[pos];
        if (c == '"') return Value(parse_string());
        if (c == '{') return Value(parse_object());
        if (c == 't') { pos += 4; return Value(true); }
        if (c == 'f') { pos += 5; return Value(false); }
        if (c == 'n') { pos += 4; return Value(""); }
        size_t start = pos;
        if (src[pos] == '-') ++pos;
        while (pos < src.size() && (std::isdigit(src[pos]) || src[pos] == '.')) ++pos;
        return Value(std::stod(std::string(src.substr(start, pos - start))));
    }

    Object parse_object() {
        next();
        Object obj;
        while (peek() != '}' && pos < src.size()) {
            std::string key = parse_string();
            next();
            obj[key] = parse_value();
            if (peek() == ',') next();
        }
        if (pos < src.size()) ++pos;
        return obj;
    }

public:
    Value parse(const std::string& input) {
        src = input; pos = 0; return parse_value();
    }
};

Value parse(const std::string& input) { Parser p; return p.parse(input); }

} // namespace json

// ============================================================================
// SQLITE RAII WRAPPER
// ============================================================================

class Database {
    sqlite3* db_ = nullptr;

public:
    Database() = default;

    explicit Database(const fs::path& path) {
        if (sqlite3_open(path.c_str(), &db_) != SQLITE_OK) {
            std::cerr << "[db] Failed to open " << path << ": "
                      << sqlite3_errmsg(db_) << "\n";
            db_ = nullptr;
        }
    }

    ~Database() { if (db_) sqlite3_close(db_); }

    Database(Database&& o) noexcept : db_(o.db_) { o.db_ = nullptr; }
    Database& operator=(Database&& o) noexcept {
        if (db_) sqlite3_close(db_);
        db_ = o.db_; o.db_ = nullptr;
        return *this;
    }

    Database(const Database&) = delete;
    Database& operator=(const Database&) = delete;

    bool ok() const { return db_ != nullptr; }

    bool exec(const std::string& sql) {
        char* err = nullptr;
        int rc = sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &err);
        if (rc != SQLITE_OK) {
            std::cerr << "[db] Error: " << (err ? err : "unknown") << "\n";
            sqlite3_free(err);
            return false;
        }
        return true;
    }

    using Row = std::map<std::string, std::string>;

    std::vector<Row> query(const std::string& sql,
                           const std::vector<std::string>& params = {}) {
        sqlite3_stmt* stmt = nullptr;
        if (sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
            std::cerr << "[db] Prepare: " << sqlite3_errmsg(db_) << "\n";
            return {};
        }
        for (size_t i = 0; i < params.size(); ++i)
            sqlite3_bind_text(stmt, i + 1, params[i].c_str(), -1, SQLITE_TRANSIENT);

        std::vector<Row> rows;
        int cols = sqlite3_column_count(stmt);
        while (sqlite3_step(stmt) == SQLITE_ROW) {
            Row row;
            for (int c = 0; c < cols; ++c) {
                const char* name = sqlite3_column_name(stmt, c);
                const char* val  = reinterpret_cast<const char*>(
                    sqlite3_column_text(stmt, c));
                row[name] = val ? val : "";
            }
            rows.push_back(std::move(row));
        }
        sqlite3_finalize(stmt);
        return rows;
    }

    bool execute(const std::string& sql, const std::vector<std::string>& params) {
        sqlite3_stmt* stmt = nullptr;
        if (sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
            std::cerr << "[db] Prepare: " << sqlite3_errmsg(db_) << "\n";
            return false;
        }
        for (size_t i = 0; i < params.size(); ++i)
            sqlite3_bind_text(stmt, i + 1, params[i].c_str(), -1, SQLITE_TRANSIENT);
        int rc = sqlite3_step(stmt);
        sqlite3_finalize(stmt);
        return rc == SQLITE_DONE;
    }

    std::string scalar(const std::string& sql,
                       const std::vector<std::string>& params = {}) {
        auto rows = query(sql, params);
        if (rows.empty()) return "0";
        return rows[0].begin()->second;
    }
};

// ============================================================================
// SCHEMA INITIALIZATION
// ============================================================================

namespace schema {

void init_registry(Database& db) {
    db.exec(R"SQL(
        CREATE TABLE IF NOT EXISTS forks (
            id TEXT PRIMARY KEY,
            url TEXT NOT NULL,
            name TEXT NOT NULL,
            description TEXT DEFAULT '',
            parent_id TEXT,
            created_at TEXT DEFAULT CURRENT_TIMESTAMP,
            last_seen TEXT DEFAULT CURRENT_TIMESTAMP,
            stars INTEGER DEFAULT 0,
            fork_count INTEGER DEFAULT 0,
            open_issues INTEGER DEFAULT 0,
            FOREIGN KEY (parent_id) REFERENCES forks(id)
        );
        CREATE TABLE IF NOT EXISTS branches (
            id TEXT PRIMARY KEY,
            fork_id TEXT NOT NULL,
            name TEXT NOT NULL,
            head_commit TEXT,
            build_status TEXT DEFAULT 'unknown',
            last_updated TEXT DEFAULT CURRENT_TIMESTAMP,
            FOREIGN KEY (fork_id) REFERENCES forks(id)
        );
        CREATE TABLE IF NOT EXISTS commits (
            hash TEXT PRIMARY KEY,
            fork_id TEXT NOT NULL,
            branch_id TEXT,
            author TEXT,
            message TEXT,
            timestamp TEXT,
            ai_authored_lines INTEGER DEFAULT 0,
            human_authored_lines INTEGER DEFAULT 0,
            ai_ratio REAL DEFAULT 0.0,
            parent_hash TEXT,
            FOREIGN KEY (fork_id) REFERENCES forks(id)
        );
        CREATE TABLE IF NOT EXISTS builds (
            commit_hash TEXT PRIMARY KEY,
            binary_hash TEXT,
            binary_size INTEGER,
            delta_from TEXT,
            delta_size INTEGER,
            build_time_seconds REAL,
            platform TEXT DEFAULT 'native',
            cached_at TEXT DEFAULT CURRENT_TIMESTAMP,
            FOREIGN KEY (commit_hash) REFERENCES commits(hash)
        );
    )SQL");
}

void init_telemetry(Database& db) {
    db.exec(R"SQL(
        CREATE TABLE IF NOT EXISTS sessions (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_hash TEXT NOT NULL,
            fork_id TEXT NOT NULL,
            branch_id TEXT NOT NULL,
            commit_hash TEXT NOT NULL,
            start_time TEXT NOT NULL,
            duration_seconds INTEGER NOT NULL,
            platform TEXT DEFAULT 'native'
        );
        CREATE TABLE IF NOT EXISTS commit_metrics (
            commit_hash TEXT PRIMARY KEY,
            total_usage_hours REAL DEFAULT 0,
            unique_users INTEGER DEFAULT 0,
            avg_session_minutes REAL DEFAULT 0,
            median_session_minutes REAL DEFAULT 0,
            usage_trend REAL DEFAULT 0,
            first_used TEXT,
            last_used TEXT
        );
        CREATE TABLE IF NOT EXISTS ai_signal (
            commit_hash TEXT PRIMARY KEY,
            ai_ratio REAL NOT NULL,
            usage_delta_percent REAL,
            session_length_delta_percent REAL,
            retention_delta_percent REAL,
            signal_confidence REAL DEFAULT 0,
            sample_size INTEGER DEFAULT 0
        );
    )SQL");
}

} // namespace schema

// ============================================================================
// FORK REGISTRY
// ============================================================================

class ForkRegistry {
    Database& db_;

public:
    explicit ForkRegistry(Database& db) : db_(db) {}

    std::string register_fork(const std::string& url,
                              const std::string& name,
                              const std::string& desc = "",
                              const std::string& parent_id = "") {
        std::string id = util::sha256_hex(url).substr(0, 12);
        db_.execute(
            "INSERT OR REPLACE INTO forks (id, url, name, description, parent_id) "
            "VALUES (?, ?, ?, ?, ?)",
            {id, url, name, desc, parent_id}
        );
        std::cout << "[registry] Registered: " << name << " (" << id << ")\n";
        return id;
    }

    void index_fork(const std::string& fork_id) {
        auto rows = db_.query("SELECT * FROM forks WHERE id = ?", {fork_id});
        if (rows.empty()) {
            std::cout << "[registry] Fork " << fork_id << " not found\n";
            return;
        }

        auto& fork = rows[0];
        std::string url = fork.at("url");
        std::cout << "[registry] Indexing " << fork.at("name") << "...\n";

        auto result = util::run_cmd({"git", "ls-remote", "--heads", url});
        if (result.exit_code != 0) {
            std::cout << "[registry] Failed to reach " << url << "\n";
            return;
        }

        for (auto& line : util::split(result.out, '\n')) {
            auto trimmed = util::trim(line);
            if (trimmed.empty()) continue;

            auto tab = trimmed.find('\t');
            if (tab == std::string::npos) continue;

            std::string hash = trimmed.substr(0, tab);
            std::string ref  = trimmed.substr(tab + 1);

            const std::string prefix = "refs/heads/";
            if (ref.find(prefix) == 0) ref = ref.substr(prefix.size());

            std::string bid = fork_id + ":" + ref;
            db_.execute(
                "INSERT OR REPLACE INTO branches "
                "(id, fork_id, name, head_commit, last_updated) "
                "VALUES (?, ?, ?, ?, ?)",
                {bid, fork_id, ref, hash, util::utc_now()}
            );
        }
        std::cout << "[registry] Done indexing " << fork.at("name") << "\n";
    }

    std::vector<Database::Row> list_forks(const std::string& sort = "usage") {
        if (sort == "usage") {
            return db_.query(R"SQL(
                SELECT f.*,
                    COALESCE(SUM(cm.total_usage_hours), 0) as total_usage
                FROM forks f
                LEFT JOIN commits c ON c.fork_id = f.id
                LEFT JOIN commit_metrics cm ON cm.commit_hash = c.hash
                GROUP BY f.id
                ORDER BY total_usage DESC
            )SQL");
        }
        return db_.query(
            "SELECT *, '0' as total_usage FROM forks ORDER BY last_seen DESC");
    }

    std::vector<Database::Row> list_branches(const std::string& fork_id) {
        return db_.query(R"SQL(
            SELECT b.*,
                COALESCE(cm.total_usage_hours, 0) as usage_hours,
                COALESCE(cm.unique_users, 0) as unique_users
            FROM branches b
            LEFT JOIN commit_metrics cm ON cm.commit_hash = b.head_commit
            WHERE b.fork_id = ?
            ORDER BY usage_hours DESC
        )SQL", {fork_id});
    }

    std::vector<Database::Row> search(const std::string& q) {
        std::string like = "%" + q + "%";
        return db_.query(
            "SELECT * FROM forks WHERE name LIKE ? OR description LIKE ?",
            {like, like});
    }

    std::vector<Database::Row> get_tree() {
        return db_.query("SELECT * FROM forks ORDER BY parent_id");
    }
};

// ============================================================================
// DELTA ENGINE
// ============================================================================

class DeltaEngine {
    Database& db_;

    static constexpr uint8_t OP_COPY   = 0;
    static constexpr uint8_t OP_INSERT = 1;

public:
    explicit DeltaEngine(Database& db) : db_(db) {}

    std::vector<uint8_t> compute_delta(const std::vector<uint8_t>& base,
                                        const std::vector<uint8_t>& target) {
        std::unordered_map<std::string, uint32_t> base_blocks;
        for (size_t i = 0; i < base.size(); i += config::BLOCK_SIZE) {
            size_t len = std::min(config::BLOCK_SIZE, base.size() - i);
            base_blocks[util::block_hash(base.data() + i, len)] =
                static_cast<uint32_t>(i);
        }

        std::vector<uint8_t> raw;
        auto emit_u8  = [&](uint8_t v)  { raw.push_back(v); };
        auto emit_u32 = [&](uint32_t v) {
            raw.push_back(v & 0xFF);
            raw.push_back((v >> 8) & 0xFF);
            raw.push_back((v >> 16) & 0xFF);
            raw.push_back((v >> 24) & 0xFF);
        };

        size_t i = 0;
        while (i < target.size()) {
            size_t len = std::min(config::BLOCK_SIZE, target.size() - i);
            auto h = util::block_hash(target.data() + i, len);
            auto it = base_blocks.find(h);

            if (it != base_blocks.end()) {
                emit_u8(OP_COPY);
                emit_u32(it->second);
                emit_u32(static_cast<uint32_t>(len));
            } else {
                emit_u8(OP_INSERT);
                emit_u32(static_cast<uint32_t>(len));
                raw.insert(raw.end(), target.begin() + i, target.begin() + i + len);
            }
            i += config::BLOCK_SIZE;
        }

        return util::zlib_compress(raw);
    }

    std::vector<uint8_t> apply_delta(const std::vector<uint8_t>& base,
                                      const std::vector<uint8_t>& delta) {
        auto raw = util::zlib_decompress(delta);
        if (raw.empty()) return {};

        std::vector<uint8_t> result;
        auto read_u8  = [&](size_t& p) -> uint8_t  { return raw[p++]; };
        auto read_u32 = [&](size_t& p) -> uint32_t {
            uint32_t v = raw[p] | (raw[p+1]<<8) | (raw[p+2]<<16) | (raw[p+3]<<24);
            p += 4; return v;
        };

        size_t p = 0;
        while (p < raw.size()) {
            uint8_t op = read_u8(p);
            if (op == OP_COPY) {
                uint32_t off = read_u32(p), len = read_u32(p);
                if (off + len <= base.size())
                    result.insert(result.end(), base.begin()+off, base.begin()+off+len);
            } else if (op == OP_INSERT) {
                uint32_t len = read_u32(p);
                if (p + len <= raw.size()) {
                    result.insert(result.end(), raw.begin()+p, raw.begin()+p+len);
                    p += len;
                }
            }
        }
        return result;
    }

    void store_build(const std::string& commit,
                     const std::vector<uint8_t>& binary,
                     const std::string& parent = "") {
        auto hash = util::sha256_bytes(binary);
        auto path = config::binary_cache() / (commit + ".bin");

        std::string delta_from, delta_size_str;

        if (!parent.empty()) {
            auto ppath = config::binary_cache() / (parent + ".bin");
            if (fs::exists(ppath)) {
                auto pdata = util::read_file_bytes(ppath);
                auto delta = compute_delta(pdata, binary);
                auto dpath = config::delta_store() / (parent + "_" + commit + ".delta");
                util::write_file_bytes(dpath, delta);
                delta_from = parent;
                delta_size_str = std::to_string(delta.size());

                double ratio = 100.0 * delta.size() / binary.size();
                std::cout << "[delta] " << commit.substr(0,8)
                          << ": " << std::fixed << std::setprecision(1)
                          << ratio << "% of full (" << delta.size()
                          << " vs " << binary.size() << " bytes)\n";
            }
        }

        util::write_file_bytes(path, binary);
        db_.execute(
            "INSERT OR REPLACE INTO builds "
            "(commit_hash, binary_hash, binary_size, delta_from, "
            "delta_size, platform) VALUES (?, ?, ?, ?, ?, ?)",
            {commit, hash, std::to_string(binary.size()),
             delta_from, delta_size_str, "native"});
    }

    std::vector<uint8_t> get_build(const std::string& commit) {
        auto path = config::binary_cache() / (commit + ".bin");
        if (fs::exists(path)) return util::read_file_bytes(path);

        // Walk delta chain
        struct Link { std::string target; fs::path delta_path; };
        std::vector<Link> chain;
        std::string cur = commit;

        while (!cur.empty()) {
            auto rows = db_.query("SELECT * FROM builds WHERE commit_hash = ?", {cur});
            if (rows.empty()) break;
            std::string df = rows[0].at("delta_from");
            if (!df.empty()) {
                auto dp = config::delta_store() / (df + "_" + cur + ".delta");
                if (fs::exists(dp)) { chain.push_back({cur, dp}); cur = df; }
                else break;
            } else break;
        }

        auto base_path = config::binary_cache() / (cur + ".bin");
        if (!fs::exists(base_path)) {
            std::cerr << "[delta] Missing base: " << cur << "\n";
            return {};
        }

        auto data = util::read_file_bytes(base_path);
        for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
            auto d = util::read_file_bytes(it->delta_path);
            data = apply_delta(data, d);
            util::write_file_bytes(config::binary_cache() / (it->target + ".bin"), data);
        }
        return data;
    }

    struct Plan {
        std::string strategy;
        std::string reason;
        std::vector<std::string> chain;
        int64_t download_bytes = 0;
        int64_t full_bytes     = 0;
        double  savings        = 0;
    };

    Plan get_plan(const std::string& commit) {
        auto rows = db_.query("SELECT * FROM builds WHERE commit_hash = ?", {commit});
        if (rows.empty()) return {"compile", "no cached build"};

        if (fs::exists(config::binary_cache() / (commit + ".bin")))
            return {"local", ""};

        int64_t full = std::stoll(rows[0].at("binary_size"));
        int64_t cost = 0;
        std::vector<std::string> chain;
        std::string cur = commit;

        while (!cur.empty()) {
            auto b = db_.query("SELECT * FROM builds WHERE commit_hash = ?", {cur});
            if (b.empty()) break;
            std::string df = b[0].at("delta_from");
            if (df.empty()) break;

            std::string ds = b[0].at("delta_size");
            cost += ds.empty() ? 0 : std::stoll(ds);
            chain.push_back(cur);

            if (fs::exists(config::binary_cache() / (df + ".bin"))) {
                double sav = full > 0 ? (1.0 - (double)cost/full) * 100 : 0;
                return {"delta_chain", "", chain, cost, full, sav};
            }
            cur = df;
        }
        return {"full_download", "", {}, full, full, 0};
    }
};

// ============================================================================
// USAGE TELEMETRY
// ============================================================================

class UsageTracker {
    Database& db_;
    Database& reg_;
    json::Object cfg_;

    struct Session {
        std::string user_hash, fork_id, branch_id, commit_hash, start_time;
    };
    std::optional<Session> active_;

    void update_metrics(const std::string& commit) {
        auto rows = db_.query("SELECT * FROM sessions WHERE commit_hash = ?", {commit});
        if (rows.empty()) return;

        std::vector<int64_t> durs;
        std::set<std::string> users;
        std::string first, last;

        for (auto& s : rows) {
            durs.push_back(std::stoll(s.at("duration_seconds")));
            users.insert(s.at("user_hash"));
            auto& t = s.at("start_time");
            if (first.empty() || t < first) first = t;
            if (last.empty()  || t > last)  last  = t;
        }

        double hours = std::accumulate(durs.begin(), durs.end(), 0LL) / 3600.0;
        double avg   = (std::accumulate(durs.begin(), durs.end(), 0LL)
                       / (double)durs.size()) / 60.0;

        std::sort(durs.begin(), durs.end());
        size_t m = durs.size() / 2;
        double median = (durs.size() % 2 == 0)
            ? (durs[m-1] + durs[m]) / 2.0 / 60.0
            : durs[m] / 60.0;

        db_.execute(
            "INSERT OR REPLACE INTO commit_metrics "
            "(commit_hash, total_usage_hours, unique_users, "
            "avg_session_minutes, median_session_minutes, "
            "first_used, last_used) VALUES (?, ?, ?, ?, ?, ?, ?)",
            {commit, std::to_string(hours),
             std::to_string(static_cast<int>(users.size())),
             std::to_string(avg), std::to_string(median), first, last});
    }

public:
    UsageTracker(Database& db, Database& reg, const json::Object& cfg)
        : db_(db), reg_(reg), cfg_(cfg) {}

    void start_session(const std::string& fork_id,
                       const std::string& branch_id,
                       const std::string& commit) {
        auto it = cfg_.find("telemetry_opt_in");
        if (it != cfg_.end() && !it->second.boolean()) return;

        auto pid = cfg_.find("user_id");
        std::string uid = pid != cfg_.end() ? pid->second.str() : "";

        active_ = Session{
            util::sha256_hex(uid).substr(0, 16),
            fork_id, branch_id, commit, util::utc_now()
        };
        std::cout << "[telemetry] Session started: " << commit.substr(0,8) << "\n";
    }

    void end_session() {
        if (!active_) return;
        int dur = static_cast<int>(
            std::time(nullptr) - util::parse_iso(active_->start_time));

        db_.execute(
            "INSERT INTO sessions "
            "(user_hash, fork_id, branch_id, commit_hash, "
            "start_time, duration_seconds) VALUES (?, ?, ?, ?, ?, ?)",
            {active_->user_hash, active_->fork_id, active_->branch_id,
             active_->commit_hash, active_->start_time, std::to_string(dur)});

        update_metrics(active_->commit_hash);
        std::cout << "[telemetry] Session ended: " << dur << "s\n";
        active_.reset();
    }

    std::vector<Database::Row> get_trending(int days = 7) {
        auto cutoff_t = std::time(nullptr) - (days * 86400);
        std::tm tm{}; gmtime_r(&cutoff_t, &tm);
        char buf[32]; std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tm);

        return db_.query(R"SQL(
            SELECT branch_id, fork_id, commit_hash,
                SUM(duration_seconds) / 3600.0 as hours_used,
                COUNT(DISTINCT user_hash) as unique_users,
                AVG(duration_seconds) / 60.0 as avg_session_min
            FROM sessions WHERE start_time > ?
            GROUP BY branch_id ORDER BY hours_used DESC
        )SQL", {std::string(buf)});
    }

    std::optional<Database::Row> get_metrics(const std::string& commit) {
        auto rows = db_.query(
            "SELECT * FROM commit_metrics WHERE commit_hash = ?", {commit});
        return rows.empty() ? std::nullopt
                            : std::optional<Database::Row>(rows[0]);
    }

    std::optional<Database::Row> compute_ai_signal(const std::string& hash) {
        auto commits = reg_.query("SELECT * FROM commits WHERE hash = ?", {hash});
        if (commits.empty()) return std::nullopt;

        double ai_ratio = std::stod(commits[0].at("ai_ratio"));
        if (ai_ratio == 0) return std::nullopt;

        auto parent_m  = get_metrics(commits[0].at("parent_hash"));
        auto current_m = get_metrics(hash);
        if (!parent_m || !current_m) return std::nullopt;

        double ph = std::stod(parent_m->at("total_usage_hours"));
        double ch = std::stod(current_m->at("total_usage_hours"));
        double pa = std::stod(parent_m->at("avg_session_minutes"));
        double ca = std::stod(current_m->at("avg_session_minutes"));

        double usage_d   = ph > 0 ? (ch - ph) / ph * 100 : 0;
        double session_d = pa > 0 ? (ca - pa) / pa * 100 : 0;

        int sample = std::stoi(current_m->at("unique_users"));
        double conf = std::min(1.0, sample / 100.0);

        db_.execute(
            "INSERT OR REPLACE INTO ai_signal "
            "(commit_hash, ai_ratio, usage_delta_percent, "
            "session_length_delta_percent, signal_confidence, sample_size) "
            "VALUES (?, ?, ?, ?, ?, ?)",
            {hash, std::to_string(ai_ratio), std::to_string(usage_d),
             std::to_string(session_d), std::to_string(conf),
             std::to_string(sample)});

        Database::Row sig;
        sig["commit_hash"]                 = hash;
        sig["ai_ratio"]                    = std::to_string(ai_ratio);
        sig["usage_delta_percent"]         = std::to_string(usage_d);
        sig["session_length_delta_percent"]= std::to_string(session_d);
        sig["signal_confidence"]           = std::to_string(conf);
        sig["sample_size"]                 = std::to_string(sample);
        return sig;
    }
};

// ============================================================================
// BRANCH MANAGER
// ============================================================================

class BranchManager {
    Database& reg_;
    DeltaEngine delta_;
    UsageTracker& tracker_;

public:
    BranchManager(Database& reg, UsageTracker& tracker)
        : reg_(reg), delta_(reg), tracker_(tracker) {}

    fs::path checkout(const std::string& fork_id, const std::string& branch) {
        std::string bid  = fork_id + ":" + branch;
        std::string dname = fork_id + "_" + branch;
        fs::path dir = config::branches_dir() / dname;

        auto forks = reg_.query("SELECT * FROM forks WHERE id = ?", {fork_id});
        if (forks.empty()) {
            std::cerr << "[branch] Unknown fork: " << fork_id << "\n";
            return {};
        }

        auto branches = reg_.query("SELECT * FROM branches WHERE id = ?", {bid});
        std::string commit;
        if (!branches.empty()) commit = branches[0].at("head_commit");

        if (!commit.empty()) {
            auto plan = delta_.get_plan(commit);
            std::cout << "[branch] Strategy: " << plan.strategy << "\n";
            if (plan.strategy == "local") {
                std::cout << "[branch] Ready: " << commit.substr(0,8) << "\n";
                return dir;
            }
            if (plan.strategy == "delta_chain") {
                std::cout << "[branch] Delta: " << plan.download_bytes
                          << " bytes (saving " << std::fixed
                          << std::setprecision(1) << plan.savings << "%)\n";
            }
        }

        std::string url = forks[0].at("url");
        if (fs::exists(dir)) {
            std::cout << "[branch] Pulling " << branch << "...\n";
            util::run_cmd({"git", "-C", dir.string(), "pull", "--ff-only"});
        } else {
            std::cout << "[branch] Cloning " << forks[0].at("name")
                      << ":" << branch << "...\n";
            fs::create_directories(dir);
            util::run_cmd({"git", "clone", "--branch", branch,
                           "--single-branch", "--depth", "1",
                           url, dir.string()});
        }
        return dir;
    }

    void launch(const std::string& fork_id, const std::string& branch,
                const std::string& executable) {
        std::string bid  = fork_id + ":" + branch;
        std::string dname = fork_id + "_" + branch;
        fs::path dir = config::branches_dir() / dname;

        auto result = util::run_cmd(
            {"git", "-C", dir.string(), "rev-parse", "HEAD"});
        std::string commit = result.exit_code == 0
            ? util::trim(result.out) : "unknown";

        tracker_.start_session(fork_id, bid, commit);

        fs::path exe = dir / executable;
        if (!fs::exists(exe)) {
            // Search common build output paths
            std::vector<fs::path> search = {
                dir / "build" / "Debug" / executable,
                dir / "build" / "Release" / executable,
                dir / "target" / "release" / executable,
                dir / "target" / "debug" / executable,
                dir / "bin" / executable,
            };
            for (auto& p : search) {
                if (fs::exists(p)) { exe = p; break; }
            }
        }

        if (fs::exists(exe)) {
            std::cout << "[launch] Running: " << exe << "\n"
                      << "[launch] Commit:  " << commit.substr(0,8) << "\n"
                      << "[launch] Ctrl+C to stop and record session\n";

            std::string cmd = "cd '" + exe.parent_path().string() +
                              "' && '" + exe.string() + "'";
            (void)std::system(cmd.c_str());
        } else {
            std::cerr << "[launch] Executable not found: " << executable << "\n"
                      << "[launch] Build the project first, then:\n"
                      << "  lge launch " << fork_id << " " << branch
                      << " <executable>\n";
        }

        tracker_.end_session();
    }

    std::vector<Database::Row> list_local() {
        std::vector<Database::Row> out;
        if (!fs::exists(config::branches_dir())) return out;

        for (auto& e : fs::directory_iterator(config::branches_dir())) {
            if (!e.is_directory()) continue;
            std::string name = e.path().filename().string();
            auto sep = name.find('_');
            std::string bid = sep != std::string::npos
                ? name.substr(0,sep) + ":" + name.substr(sep+1) : name;

            auto r = util::run_cmd(
                {"git", "-C", e.path().string(), "rev-parse", "HEAD"});
            std::string commit = r.exit_code == 0
                ? util::trim(r.out).substr(0,8) : "?";

            Database::Row row;
            row["branch_id"] = bid;
            row["path"]      = e.path().string();
            row["commit"]    = commit;
            out.push_back(std::move(row));
        }
        return out;
    }
};

// ============================================================================
// AI ATTRIBUTION
// ============================================================================

class AIAttribution {
    Database& reg_;
    Database& tel_;

public:
    AIAttribution(Database& reg, Database& tel) : reg_(reg), tel_(tel) {}

    void tag_commit(const std::string& hash, int ai, int human) {
        int total    = ai + human;
        double ratio = total > 0 ? (double)ai / total : 0;
        reg_.execute(
            "UPDATE commits SET ai_authored_lines = ?, "
            "human_authored_lines = ?, ai_ratio = ? WHERE hash = ?",
            {std::to_string(ai), std::to_string(human),
             std::to_string(ratio), hash});
    }

    std::vector<Database::Row> leaderboard() {
        return tel_.query(R"SQL(
            SELECT commit_hash, ai_ratio, usage_delta_percent,
                session_length_delta_percent, signal_confidence, sample_size
            FROM ai_signal WHERE signal_confidence > 0.3
            ORDER BY usage_delta_percent DESC
        )SQL");
    }

    Database::Row ratio_report(const std::string& fork_id) {
        auto rows = reg_.query(R"SQL(
            SELECT
                COALESCE(SUM(ai_authored_lines), 0) as total_ai,
                COALESCE(SUM(human_authored_lines), 0) as total_human,
                COALESCE(AVG(ai_ratio), 0) as avg_ratio,
                COUNT(*) as total_commits,
                SUM(CASE WHEN ai_ratio > 0 THEN 1 ELSE 0 END) as ai_commits
            FROM commits WHERE fork_id = ?
        )SQL", {fork_id});
        return rows.empty() ? Database::Row{} : rows[0];
    }
};

// ============================================================================
// CLI
// ============================================================================

namespace cli {

struct Col { std::string key, name; int width; };

void table(const std::vector<Database::Row>& rows,
           const std::vector<Col>& cols) {
    if (rows.empty()) { std::cout << "  (no data)\n"; return; }

    auto sep = [&]() {
        for (auto& c : cols) {
            std::cout << "  ";
            for (int i = 0; i < c.width; ++i) std::cout << "\u2500";
        }
        std::cout << "\n";
    };

    sep();
    for (auto& c : cols)
        std::cout << "  " << std::left << std::setw(c.width) << c.name;
    std::cout << "\n"; sep();

    for (auto& row : rows) {
        for (auto& c : cols) {
            auto it = row.find(c.key);
            std::string v = it != row.end() ? it->second : "";
            try {
                if (v.find('.') != std::string::npos) {
                    std::ostringstream o;
                    o << std::fixed << std::setprecision(1) << std::stod(v);
                    v = o.str();
                }
            } catch (...) {}
            if ((int)v.size() > c.width - 1)
                v = v.substr(0, c.width - 2) + "~";
            std::cout << "  " << std::left << std::setw(c.width) << v;
        }
        std::cout << "\n";
    }
    sep();
}

} // namespace cli

// ============================================================================
// COMMANDS
// ============================================================================

namespace cmd {

void init(int, char**) {
    for (auto& d : {config::home_dir(), config::binary_cache(),
                    config::delta_store(), config::branches_dir()})
        fs::create_directories(d);

    if (!fs::exists(config::config_file())) {
        json::Object cfg;
        cfg["user_id"]            = json::Value(util::random_hex(16).substr(0,16));
        cfg["telemetry_opt_in"]   = json::Value(true);
        cfg["compile_local"]      = json::Value(false);
        cfg["sandbox_enabled"]    = json::Value(true);
        cfg["ai_attribution"]     = json::Value(true);
        util::write_file_text(config::config_file(),
                              json::serialize(json::Value(cfg)));
    }

    Database reg(config::registry_db()); schema::init_registry(reg);
    Database tel(config::telemetry_db()); schema::init_telemetry(tel);
    std::cout << "[lge] Initialized at " << config::home_dir() << "\n";
}

void register_fork(int argc, char** argv) {
    if (argc < 4) {
        std::cerr << "Usage: lge register <url> <name> [--desc TEXT] [--index]\n";
        return;
    }
    std::string url = argv[2], name = argv[3], desc;
    bool idx = false;
    for (int i = 4; i < argc; ++i) {
        std::string a = argv[i];
        if (a == "--desc" && i+1 < argc) desc = argv[++i];
        if (a == "--index") idx = true;
    }
    Database reg(config::registry_db());
    ForkRegistry r(reg);
    auto id = r.register_fork(url, name, desc);
    if (idx) r.index_fork(id);
}

void index_cmd(int argc, char** argv) {
    Database reg(config::registry_db());
    ForkRegistry r(reg);
    bool all = false; std::string fid;
    for (int i = 2; i < argc; ++i) {
        std::string a = argv[i];
        if (a == "--all") all = true; else fid = a;
    }
    if (all) { for (auto& f : r.list_forks("recent")) r.index_fork(f.at("id")); }
    else if (!fid.empty()) r.index_fork(fid);
    else std::cerr << "Usage: lge index <fork_id> | --all\n";
}

void forks_cmd(int argc, char** argv) {
    std::string sort = "usage";
    for (int i = 2; i < argc; ++i) {
        if (std::string(argv[i]) == "--sort" && i+1 < argc) sort = argv[++i];
    }
    Database reg(config::registry_db());
    ForkRegistry r(reg);
    std::cout << "\n  LeGitingEdition Fork Registry\n"
              << "  Sorted by: " << sort << "\n\n";
    cli::table(r.list_forks(sort), {
        {"id",          "ID",         14},
        {"name",        "NAME",       30},
        {"total_usage", "USAGE (h)",  12},
        {"fork_count",  "FORKS",      8},
        {"stars",       "STARS",      8},
    });
}

void branches_cmd(int argc, char** argv) {
    if (argc < 3) { std::cerr << "Usage: lge branches <fork_id>\n"; return; }
    Database reg(config::registry_db());
    ForkRegistry r(reg);
    std::cout << "\n  Branches: " << argv[2] << "\n\n";
    cli::table(r.list_branches(argv[2]), {
        {"name",         "BRANCH",     30},
        {"head_commit",  "HEAD",       12},
        {"usage_hours",  "USAGE (h)",  12},
        {"unique_users", "USERS",      10},
        {"build_status", "BUILD",      10},
    });
}

void checkout_cmd(int argc, char** argv) {
    if (argc < 4) { std::cerr << "Usage: lge checkout <fork_id> <branch>\n"; return; }
    auto cfg = json::parse(util::read_file_text(config::config_file())).obj();
    Database reg(config::registry_db()), tel(config::telemetry_db());
    UsageTracker tracker(tel, reg, cfg);
    BranchManager mgr(reg, tracker);
    mgr.checkout(argv[2], argv[3]);
}

void launch_cmd(int argc, char** argv) {
    if (argc < 5) {
        std::cerr << "Usage: lge launch <fork_id> <branch> <executable>\n";
        return;
    }
    auto cfg = json::parse(util::read_file_text(config::config_file())).obj();
    Database reg(config::registry_db()), tel(config::telemetry_db());
    UsageTracker tracker(tel, reg, cfg);
    BranchManager mgr(reg, tracker);
    mgr.launch(argv[2], argv[3], argv[4]);
}

void local_cmd(int, char**) {
    auto cfg = json::parse(util::read_file_text(config::config_file())).obj();
    Database reg(config::registry_db()), tel(config::telemetry_db());
    UsageTracker tracker(tel, reg, cfg);
    BranchManager mgr(reg, tracker);
    std::cout << "\n  Local Branches\n\n";
    cli::table(mgr.list_local(), {
        {"branch_id", "BRANCH", 40},
        {"commit",    "COMMIT", 12},
        {"path",      "PATH",   50},
    });
}

void trending_cmd(int argc, char** argv) {
    int days = 7;
    for (int i = 2; i < argc; ++i)
        if (std::string(argv[i]) == "--days" && i+1 < argc) days = std::atoi(argv[++i]);

    auto cfg = json::parse(util::read_file_text(config::config_file())).obj();
    Database reg(config::registry_db()), tel(config::telemetry_db());
    UsageTracker tracker(tel, reg, cfg);

    std::cout << "\n  Trending (last " << days << " days)\n\n";
    cli::table(tracker.get_trending(days), {
        {"branch_id",      "BRANCH",      40},
        {"hours_used",     "HOURS",       10},
        {"unique_users",   "USERS",       10},
        {"avg_session_min","AVG SESSION", 12},
    });
}

void ai_signal_cmd(int, char**) {
    Database reg(config::registry_db()), tel(config::telemetry_db());
    AIAttribution ai(reg, tel);
    std::cout << "\n  AI Contribution Signal (ranked by usage impact)\n\n";
    cli::table(ai.leaderboard(), {
        {"commit_hash",                 "COMMIT",     12},
        {"ai_ratio",                    "AI %",       8},
        {"usage_delta_percent",         "USAGE D%",   12},
        {"session_length_delta_percent","SESSION D%", 12},
        {"signal_confidence",           "CONFIDENCE", 12},
        {"sample_size",                 "USERS",      10},
    });
}

void plan_cmd(int argc, char** argv) {
    if (argc < 3) { std::cerr << "Usage: lge plan <commit>\n"; return; }
    Database reg(config::registry_db());
    DeltaEngine d(reg);
    auto plan = d.get_plan(argv[2]);
    std::cout << "\n  Download Plan: " << std::string(argv[2]).substr(0,8) << "\n\n"
              << "  strategy: " << plan.strategy << "\n";
    if (!plan.reason.empty())    std::cout << "  reason:   " << plan.reason << "\n";
    if (plan.download_bytes > 0) std::cout << "  download: " << plan.download_bytes << " bytes\n";
    if (plan.full_bytes > 0)     std::cout << "  full:     " << plan.full_bytes << " bytes\n";
    if (plan.savings > 0)        std::cout << "  savings:  " << std::fixed
                                           << std::setprecision(1) << plan.savings << "%\n";
    std::cout << "\n";
}

void status_cmd(int, char**) {
    std::cout << "\n"
        "  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
        "\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
        "\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
        "\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n"
        "  \u2551     LeGitingEdition v"
    << config::VERSION <<
        "          \u2551\n"
        "  \u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
        "\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
        "\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
        "\u2550\u2550\u2550\u2550\u2550\u2550\u255d\n\n";

    Database reg(config::registry_db());
    int nf = std::stoi(reg.scalar("SELECT COUNT(*) FROM forks"));
    int nb = std::stoi(reg.scalar("SELECT COUNT(*) FROM branches"));
    int nc = std::stoi(reg.scalar("SELECT COUNT(*) FROM builds"));

    Database tel(config::telemetry_db());
    int ns = std::stoi(tel.scalar("SELECT COUNT(*) FROM sessions"));
    double th = std::stod(tel.scalar(
        "SELECT COALESCE(SUM(duration_seconds),0)/3600.0 FROM sessions"));
    int na = std::stoi(tel.scalar("SELECT COUNT(*) FROM ai_signal"));

    auto cfg = json::parse(util::read_file_text(config::config_file())).obj();
    auto gs = [&](const std::string& k) -> std::string {
        auto it = cfg.find(k);
        return it != cfg.end() && it->second.is_string() ? it->second.str() : "";
    };
    auto gb = [&](const std::string& k) -> bool {
        auto it = cfg.find(k);
        return it != cfg.end() && it->second.is_bool() && it->second.boolean();
    };

    std::cout << "  User ID:        " << gs("user_id") << "\n"
              << "  Telemetry:      " << (gb("telemetry_opt_in") ? "ON" : "OFF") << "\n"
              << "  Sandbox:        " << (gb("sandbox_enabled") ? "ON" : "OFF") << "\n"
              << "  AI Attribution: " << (gb("ai_attribution") ? "ON" : "OFF") << "\n\n"
              << "  Registry:       " << nf << " forks, " << nb << " branches\n"
              << "  Cache:          " << nc << " builds\n"
              << "  Telemetry:      " << ns << " sessions, "
              << std::fixed << std::setprecision(1) << th << " hours\n"
              << "  AI Signals:     " << na << " commits tracked\n\n";
}

void schema_cmd(int, char**) {
    std::cout << R"(
  LeGitingEdition Telemetry Schema (v1)
  ══════════════════════════════════════

  sessions:
    user_hash          - SHA256 of local user ID (anonymous)
    fork_id            - which fork was used
    branch_id          - which branch was used
    commit_hash        - exact commit running
    start_time         - UTC session start
    duration_seconds   - session length
    platform           - OS / platform

  commit_metrics (aggregated):
    total_usage_hours       - cumulative session time
    unique_users            - distinct user hashes
    avg_session_minutes     - mean session length
    median_session_minutes  - median session length
    usage_trend             - rate of change

  ai_signal:
    ai_ratio                     - fraction of AI-authored lines
    usage_delta_percent          - change vs parent commit
    session_length_delta_percent - change in session length
    signal_confidence            - confidence from sample size
    sample_size                  - unique users measured

  NOT collected:
    - Real names, emails, or IP addresses
    - In-application behavior or actions
    - Communications of any kind
    - Hardware or system specifications
    - Any personally identifiable information

)";
}

void search_cmd(int argc, char** argv) {
    if (argc < 3) { std::cerr << "Usage: lge search <query>\n"; return; }
    Database reg(config::registry_db());
    ForkRegistry r(reg);
    std::cout << "\n  Search: " << argv[2] << "\n\n";
    cli::table(r.search(argv[2]), {
        {"id",          "ID",          14},
        {"name",        "NAME",        30},
        {"description", "DESCRIPTION", 40},
        {"url",         "URL",         40},
    });
}

void tree_cmd(int, char**) {
    Database reg(config::registry_db());
    ForkRegistry r(reg);
    auto forks = r.get_tree();

    std::cout << "\n  Fork Tree\n\n";

    std::map<std::string, std::vector<Database::Row>> children;
    std::vector<Database::Row> roots;

    for (auto& f : forks) {
        std::string pid = f.at("parent_id");
        if (pid.empty()) roots.push_back(f);
        else children[pid].push_back(f);
    }

    std::function<void(const Database::Row&, int)> print_node =
        [&](const Database::Row& node, int depth) {
        std::string prefix(depth * 2, ' ');
        std::string id = node.at("id");
        std::cout << "  " << prefix
                  << (depth > 0 ? "\u2514\u2500 " : "")
                  << node.at("name") << " [" << id << "]\n";
        if (children.count(id)) {
            for (auto& child : children[id])
                print_node(child, depth + 1);
        }
    };

    for (auto& root : roots) print_node(root, 0);
    std::cout << "\n";
}

void help_cmd(int, char**) {
    std::cout << R"(
LeGitingEdition (lge) v)" << config::VERSION << R"(
A delta layer on top of Git for fork-driven software ecosystems.

Usage: lge <command> [options]

Registry:
  init                                  Initialize lge
  register <url> <name> [opts]          Register a fork
    --desc TEXT                           Description
    --index                               Index branches now
  index <fork_id> | --all               Index fork branches
  forks [--sort usage|recent]           List registered forks
  branches <fork_id>                    List branches
  search <query>                        Search forks
  tree                                  Show fork tree

Workspace:
  checkout <fork_id> <branch>           Check out a branch
  launch <fork_id> <branch> <exe>       Run a build with telemetry
  local                                 List local branches

Analytics:
  trending [--days N]                   Branches ranked by usage
  ai-signal                             AI contribution impact
  plan <commit>                         Show download strategy

System:
  status                                Overview
  schema                                Audit telemetry schema
  help                                  This message

)";
}

} // namespace cmd

// ============================================================================
// MAIN
// ============================================================================

int main(int argc, char** argv) {
    if (argc < 2) { cmd::help_cmd(argc, argv); return 0; }

    std::string c = argv[1];

    if (c != "init" && !fs::exists(config::home_dir()))
        cmd::init(argc, argv);

    std::map<std::string, std::function<void(int,char**)>> commands = {
        {"init",     cmd::init},
        {"register", cmd::register_fork},
        {"index",    cmd::index_cmd},
        {"forks",    cmd::forks_cmd},
        {"branches", cmd::branches_cmd},
        {"checkout", cmd::checkout_cmd},
        {"launch",   cmd::launch_cmd},
        {"local",    cmd::local_cmd},
        {"trending", cmd::trending_cmd},
        {"ai-signal",cmd::ai_signal_cmd},
        {"plan",     cmd::plan_cmd},
        {"status",   cmd::status_cmd},
        {"schema",   cmd::schema_cmd},
        {"search",   cmd::search_cmd},
        {"tree",     cmd::tree_cmd},
        {"help",     cmd::help_cmd},
        {"--help",   cmd::help_cmd},
        {"-h",       cmd::help_cmd},
    };

    auto it = commands.find(c);
    if (it != commands.end()) it->second(argc, argv);
    else { std::cerr << "Unknown: " << c << "\n"; cmd::help_cmd(argc, argv); return 1; }

    return 0;
}

메타데이터
post_id
9ecb30fd4195
slug
legittingedition-9ecb30fd4195
url
https://medium.com/@appleby.ethan.ea/legittingedition-9ecb30fd4195
canonical_url
https://medium.com/@appleby.ethan.ea/legittingedition-9ecb30fd4195
author_url
https://medium.com/@appleby.ethan.ea
status
ok
fetched_at
2026-07-12 03:01:25