diff --git a/Launcher.Next.App/App.xaml.cs b/Launcher.Next.App/App.xaml.cs index 5b1086d..20cf786 100644 --- a/Launcher.Next.App/App.xaml.cs +++ b/Launcher.Next.App/App.xaml.cs @@ -9,6 +9,11 @@ public partial class App : System.Windows.Application Shutdown(await LegacyConfigurationProbeCli.RunAsync(e.Args.Skip(1).ToArray())); return; } + if (e.Args.FirstOrDefault()?.Equals("package-lifecycle-pilot", StringComparison.OrdinalIgnoreCase) == true) + { + Shutdown(await PackageLifecyclePilotCli.RunAsync(e.Args.Skip(1).ToArray())); + return; + } if (e.Args.FirstOrDefault()?.Equals("pilot", StringComparison.OrdinalIgnoreCase) == true) { Shutdown(await PilotCli.RunAsync(e.Args.Skip(1).ToArray())); return; } new MainWindow().Show(); } diff --git a/Launcher.Next.App/PackageLifecyclePilotCli.cs b/Launcher.Next.App/PackageLifecyclePilotCli.cs new file mode 100644 index 0000000..7a309a7 --- /dev/null +++ b/Launcher.Next.App/PackageLifecyclePilotCli.cs @@ -0,0 +1,27 @@ +using System.Security.Cryptography; +using System.Text.Json; +using Launcher.Next.Core; +using Launcher.Next.Infrastructure; + +namespace Launcher.Next.App; + +internal static class PackageLifecyclePilotCli +{ + public static async Task RunAsync(string[] args) + { + if (args.Length != 4 || args[0] != "--mode" || args[1] != "PackageLifecyclePilot" || args[2] != "--root" || !Path.IsPathFullyQualified(args[3]) || args[3].StartsWith(@"\\")) return 2; + var root=Path.GetFullPath(args[3]); var id=Guid.NewGuid().ToString("N"); var evidenceDir=Path.Combine(root,"evidence",id); Directory.CreateDirectory(evidenceDir); + try + { + var catalog=Path.Combine(root,"catalog"); Directory.CreateDirectory(catalog); var store=new LocalPackageStore(root,new Sha256FileHasher()); + async Task<(ImmutableLocalPackage,PackageManifest)> Materialize(string version,byte seed) + { var a=new[]{seed,(byte)(seed+1)}; var b=new[]{(byte)(seed+2)}; await File.WriteAllBytesAsync(Path.Combine(catalog,"entry.dll"),a); await File.WriteAllBytesAsync(Path.Combine(catalog,"payload.dat"),b); var manifest=new PackageManifest(1,"Pilot.Package",version,"Plant3D",2026,"x64","entry.dll",[new("entry.dll",a.Length,Convert.ToHexString(SHA256.HashData(a))),new("payload.dat",b.Length,Convert.ToHexString(SHA256.HashData(b)))],new("none",""),RolloutChannel:"pilot"); return (await store.MaterializeAsync(manifest,catalog,CancellationToken.None),manifest); } + PackageRequirement Req(string v)=>new("Pilot.Package","Plant3D",2026,"x64","pilot",v,"pilot-roster",true); + var (a,ma)=await Materialize("1.0.0",1); var pointersAfterA=await store.GetCurrentVersionAsync("Pilot.Package",CancellationToken.None); var aa=await store.ActivateImmutableAsync(a,Req("1.0.0"),CancellationToken.None); var repeat=await store.ActivateImmutableAsync(a,Req("1.0.0"),CancellationToken.None); + var (b,mb)=await Materialize("2.0.0",4); var beforeB=await store.GetCurrentVersionAsync("Pilot.Package",CancellationToken.None); var ab=await store.ActivateImmutableAsync(b,Req("2.0.0"),CancellationToken.None); var rollback=await store.RollbackAsync(ab.Receipt!,CancellationToken.None); var current=await store.GetCurrentVersionAsync("Pilot.Package",CancellationToken.None); + var evidence=new { schemaVersion=1,mode="PackageLifecyclePilot",operationId=id,terminalState=current=="1.0.0"?"Succeeded":"Blocked",sourceClassification="SyntheticLocal",rootFingerprint=Convert.ToHexString(SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(id+root))),packages=new[]{new{version=ma.Version,manifestSha256=Convert.ToHexString(SHA256.HashData(JsonSerializer.SerializeToUtf8Bytes(ma)))},new{version=mb.Version,manifestSha256=Convert.ToHexString(SHA256.HashData(JsonSerializer.SerializeToUtf8Bytes(mb)))}},pointers=new{afterMaterializeA=pointersAfterA,afterActivateA=aa.Outcome,repeatedA=repeat.Outcome,beforeActivateB=beforeB,afterActivateB=ab.Outcome,afterRollback=rollback.Outcome,current},sideEffects=new{corporateDfsUsed=false,corporateDfsWriteAttempted=false,autoCadLaunchAttempted=false,processLaunchAttempted=false,productionPointerMutationAttempted=false,productionProjectAccessed=false}}; + var final=Path.Combine(evidenceDir,"package-lifecycle-pilot.json"); var temp=final+".tmp"; await File.WriteAllTextAsync(temp,JsonSerializer.Serialize(evidence)); File.Move(temp,final,true); return current=="1.0.0"?0:2; + } + catch { return 10; } + } +}