using System;using System.Diagnostics;using System.IO;using System.Text;namespace Lilith.Agent.SelfImprovement;internal static class SandboxBuildService{ public static string BuildSandboxConsole(SelfImprovementPaths paths, TimeSpan? timeout = null) { string project = paths.LilithConsoleProject; if (!File.Exists(project)) throw new FileNotFoundException($"Sandbox console project not found: {project}"); return BuildProject(project, paths.Sandbox, timeout); } public static string BuildProject(string projectPath, string workingDirectory, TimeSpan? timeout = null) => RunDotnet($"build \"{projectPath}\" -c Release", workingDirectory, timeout ?? TimeSpan.FromMinutes(5)); public static string RunDesignTests(SelfImprovementPaths paths, string? filter, TimeSpan? timeout = null) { string project = paths.DesignTestsProject; if (!File.Exists(project)) return "Skipped: DesignTests project not present in sandbox."; string filterArg = string.IsNullOrWhiteSpace(filter) ? "" : $" --filter \"{filter}\""; return RunDotnet($"test \"{project}\" -c Release{filterArg}", paths.Sandbox, timeout ?? TimeSpan.FromMinutes(5)); } private static string RunDotnet(string arguments, string workingDirectory, TimeSpan timeout) { var psi = new ProcessStartInfo { FileName = "dotnet", Arguments = arguments, WorkingDirectory = workingDirectory, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true, }; using var process = Process.Start(psi) ?? throw new InvalidOperationException("Failed to start dotnet process."); var stdout = new StringBuilder(); var stderr = new StringBuilder(); process.OutputDataReceived += (_, e) => { if (e.Data is not null) stdout.AppendLine(e.Data); }; process.ErrorDataReceived += (_, e) => { if (e.Data is not null) stderr.AppendLine(e.Data); }; process.BeginOutputReadLine(); process.BeginErrorReadLine(); if (!process.WaitForExit((int)timeout.TotalMilliseconds)) { try { process.Kill(entireProcessTree: true); } catch { /* best effort */ } throw new TimeoutException($"dotnet timed out after {timeout.TotalSeconds:F0}s."); } process.WaitForExit(); var sb = new StringBuilder(); sb.AppendLine($"Exit code: {process.ExitCode}"); if (stdout.Length > 0) sb.AppendLine(stdout.ToString().TrimEnd()); if (stderr.Length > 0) sb.AppendLine(stderr.ToString().TrimEnd()); return sb.ToString().TrimEnd(); }}
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 ofsrc/Version7next to the built app (MSBuildCopyShippedSource){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.