SelfImprovement/SourceTreeService.cscsharp

Documentation

Lilith self-improvement (Version 7+)

Lilith can extend herself only by creating tools in three categories:

| Category | Location | Examples | |----------|----------|----------| | Core | Agent-Core | Memory, time (rare; system-level) | | Addon | Agent-Addons | Weather, C# projects, apps | | Self | Lilith | Workspace files, self-improvement |

Layout

  • ShippedSource/ — copy of src/Version7 next to the built app (MSBuild CopyShippedSource)
  • {workspace}/output/self-improvement/live — current editable source
  • {workspace}/output/self-improvement/sandbox — clone for edits and builds
  • {workspace}/output/self-improvement/backups/{timestamp} — backups before promote

Tools

1. self_improve_get_source_layout 2. self_improve_generate_tool 3. self_improve_backup_live 4. self_improve_create_sandbox 5. self_improve_build_sandbox 6. self_improve_verify_sandbox_tool 7. self_improve_promote_sandbox — copies sandbox → live, builds, restarts

Set GENESIS_REPO_ROOT to the repo root when developing from source instead of ShippedSource.

using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;namespace Lilith.Agent.SelfImprovement;internal static class SourceTreeService{    private static readonly HashSet<string> ExcludedDirectoryNames = new(StringComparer.OrdinalIgnoreCase)    {        "bin", "obj", ".vs", "Builds",    };    public static void EnsureDirectory(string path) => Directory.CreateDirectory(path);    public static string CopyTree(string sourceRoot, string destinationRoot, bool overwriteDestination = true)    {        if (!Directory.Exists(sourceRoot))            throw new DirectoryNotFoundException($"Source tree not found: {sourceRoot}");        if (overwriteDestination && Directory.Exists(destinationRoot))            Directory.Delete(destinationRoot, recursive: true);        Directory.CreateDirectory(destinationRoot);        CopyDirectory(sourceRoot, destinationRoot);        return destinationRoot;    }    public static string CreateBackup(SelfImprovementPaths paths)    {        EnsureDirectory(paths.Backups);        string stamp = DateTime.UtcNow.ToString("yyyyMMdd-HHmmss");        string backupDir = Path.Combine(paths.Backups, stamp);        CopyTree(paths.Live, backupDir, overwriteDestination: false);        return backupDir;    }    public static void SeedLiveIfEmpty(SelfImprovementPaths paths)    {        EnsureDirectory(paths.Root);        if (Directory.Exists(paths.Live) && Directory.EnumerateFileSystemEntries(paths.Live).Any())            return;        string seed = Directory.Exists(paths.ShippedSource) && Directory.EnumerateFileSystemEntries(paths.ShippedSource).Any()            ? paths.ShippedSource            : paths.RepoVersionRoot;        if (!Directory.Exists(seed))            throw new DirectoryNotFoundException(                "No live source tree and no ShippedSource or repo Version8 folder was found.");        CopyTree(seed, paths.Live, overwriteDestination: true);    }    public static string DescribeLayout(SelfImprovementPaths paths)    {        var sb = new StringBuilder();        sb.AppendLine("Self-improvement source layout:");        sb.AppendLine($"  ShippedSource: {paths.ShippedSource} ({DirState(paths.ShippedSource)})");        sb.AppendLine($"  Repo Version8: {paths.RepoVersionRoot} ({DirState(paths.RepoVersionRoot)})");        sb.AppendLine($"  Live:   {paths.Live} ({DirState(paths.Live)})");        sb.AppendLine($"  Sandbox:{paths.Sandbox} ({DirState(paths.Sandbox)})");        sb.AppendLine($"  Backups:{paths.Backups} ({DirState(paths.Backups)})");        sb.AppendLine();        sb.AppendLine("Tool categories when generating tools:");        sb.AppendLine("  core  — Agent-Core system tools (memory, time, etc.)");        sb.AppendLine("  addon — Agent-Addons optional tools");        sb.AppendLine("  self  — Lilith-only tools (workspace, self-improvement)");        sb.AppendLine();        sb.AppendLine("Workflow: backup_live → create_sandbox → generate_tool → build_sandbox → verify_sandbox_tool → promote_sandbox");        return sb.ToString().TrimEnd();    }    private static string DirState(string path) =>        !Directory.Exists(path) ? "missing" : $"{Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).Count()} files";    private static void CopyDirectory(string sourceDir, string destDir)    {        Directory.CreateDirectory(destDir);        foreach (string file in Directory.GetFiles(sourceDir))        {            string destFile = Path.Combine(destDir, Path.GetFileName(file));            File.Copy(file, destFile, overwrite: true);        }        foreach (string subDir in Directory.GetDirectories(sourceDir))        {            string name = Path.GetFileName(subDir);            if (ExcludedDirectoryNames.Contains(name))                continue;            CopyDirectory(subDir, Path.Combine(destDir, name));        }    }}