feat: expose legacy launcher configuration workflow

This commit is contained in:
codex
2026-08-06 10:18:22 +03:00
parent 8d32f8e7ae
commit 0879d716dd
5 changed files with 71 additions and 5 deletions
+1 -1
View File
@@ -1 +1 @@
<Window x:Class="Launcher.Next.App.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Launcher Next (Foundation)" Height="300" Width="540"><StackPanel Margin="20"><TextBlock FontSize="20" Text="Launcher Next — foundation"/><TextBlock Margin="0,12,0,0" Text="Plant 3D: discovery available in diagnostics"/><TextBlock Text="Mode: Legacy (default); NextPilot requires explicit configuration"/><TextBlock Text="Package: no production catalog connected"/><Button Margin="0,16,0,0" IsEnabled="False" Content="Launch (disabled: dry-run foundation)"/></StackPanel></Window>
<Window x:Class="Launcher.Next.App.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Launcher Next" Height="560" Width="780"><Grid Margin="20"><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition Height="*"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><TextBlock FontSize="22" FontWeight="SemiBold" Text="Launcher Next — Plant 3D 2026"/><Grid Grid.Row="1" Margin="0,18,0,10"><Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><GroupBox Header="Autodesk"><StackPanel Margin="8"><TextBlock x:Name="AutodeskStatus"/><TextBlock x:Name="ExecutableStatus" TextWrapping="Wrap"/><Button Margin="0,8,0,0" Content="Refresh" Click="Refresh_Click"/></StackPanel></GroupBox><GroupBox Grid.Column="1" Header="Configuration" Margin="12,0,0,0"><StackPanel Margin="8"><TextBlock x:Name="ConfigurationStatus" Text="Configuration not selected"/><Button Margin="0,8,0,0" Content="Open legacy Settings.xml" Click="OpenSettings_Click"/></StackPanel></GroupBox></Grid><Grid Grid.Row="2"><Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><GroupBox Header="Available configurations"><ListBox x:Name="Patterns" Margin="8" DisplayMemberPath="Name" SelectionChanged="Patterns_SelectionChanged"/></GroupBox><GroupBox Grid.Column="1" Header="Selected configuration" Margin="12,0,0,0"><StackPanel Margin="8"><TextBlock x:Name="PatternDetails" TextWrapping="Wrap"/><TextBlock Margin="0,12,0,0" Text="Packages" FontWeight="SemiBold"/><TextBlock x:Name="PackageStatus" Text="Package preparation required" TextWrapping="Wrap"/></StackPanel></GroupBox></Grid><StackPanel Grid.Row="3" Margin="0,14,0,0"><WrapPanel><Button x:Name="PrepareButton" Content="Prepare / Install / Update" IsEnabled="False" Margin="0,0,8,0"/><Button x:Name="LaunchButton" Content="Launch Plant 3D" IsEnabled="False"/><Button Content="Diagnostics" Margin="8,0,0,0" Click="Diagnostics_Click"/></WrapPanel><TextBlock x:Name="Status" Margin="0,10,0,0" TextWrapping="Wrap"/></StackPanel></Grid></Window>
+26 -1
View File
@@ -1 +1,26 @@
namespace Launcher.Next.App; public partial class MainWindow : System.Windows.Window { public MainWindow() => InitializeComponent(); }
using Launcher.Next.Application;
using Launcher.Next.Autodesk;
namespace Launcher.Next.App;
public partial class MainWindow : System.Windows.Window
{
private readonly LegacyConfigurationAdapter adapter=new();
public MainWindow() { InitializeComponent(); RefreshDiscovery(); Status.Text="Ready: choose a legacy Settings.xml to inspect approved configurations."; }
private void RefreshDiscovery()
{
var product=new PlantProductDiscovery(new WindowsRegistryReader()).DiscoverPlant3D(2026);
AutodeskStatus.Text=product is null?"Autodesk Plant 3D 2026: Not found":"Autodesk Plant 3D 2026: Found";
ExecutableStatus.Text=product is null?"Discovery diagnostic: ACAD-9117 Plant 3D registry entry or executable unavailable.":$"Executable: {product.ExecutablePath}";
}
private void Refresh_Click(object sender,System.Windows.RoutedEventArgs e)=>RefreshDiscovery();
private void OpenSettings_Click(object sender,System.Windows.RoutedEventArgs e)
{
var dialog=new Microsoft.Win32.OpenFileDialog { Filter="Settings.xml|Settings.xml|XML files|*.xml" };
if(dialog.ShowDialog()!=true)return;
try { var settings=adapter.ParseSettings(System.IO.File.ReadAllText(dialog.FileName)); Patterns.ItemsSource=settings.Patterns; ConfigurationStatus.Text=$"Loaded {settings.Patterns.Count} configuration(s) from {System.IO.Path.GetFileName(dialog.FileName)}"; Status.Text="Select a configuration. Exact package preparation remains blocked until an approved compatibility overlay and local verified catalog are supplied."; }
catch(System.Exception ex) { ConfigurationStatus.Text="Configuration invalid";Status.Text=$"Blocked: {ex.Message}";Patterns.ItemsSource=null; }
}
private void Patterns_SelectionChanged(object sender,System.Windows.Controls.SelectionChangedEventArgs e)
{ if(Patterns.SelectedItem is not LegacyProductPattern pattern)return;PatternDetails.Text=$"Filter: {pattern.Filter}\nRoster: {pattern.Roster}\nLegacy plugins: {pattern.Plugins.Count}";PackageStatus.Text="Exact package requirements are derived only after approved overlay + ordered download_list.xml join.";Status.Text="Configuration selected; provide approved local compatibility inputs to prepare packages."; }
private void Diagnostics_Click(object sender,System.Windows.RoutedEventArgs e)=>System.Windows.MessageBox.Show($"{AutodeskStatus.Text}\n{ConfigurationStatus.Text}\n{Status.Text}","Launcher Next diagnostics");
}
+6 -3
View File
@@ -7,9 +7,12 @@ public sealed class PlantProductDiscovery(IRegistryReader registry) : IProductDi
{
public ProductInstallation? DiscoverPlant3D(int year)
{
var install = registry.GetValue($@"SOFTWARE\Autodesk\AutoCAD\R25.1\ACAD-xxxx:409", "InstallDir") as string;
if (string.IsNullOrWhiteSpace(install)) return null; var exe = Path.Combine(install, "acad.exe");
return File.Exists(exe) ? new(exe, year.ToString(), "x64", []) : null;
if (year != 2026) return null;
const string plantInstall = @"SOFTWARE\Autodesk\AutoCAD\R25.1\ACAD-9117\Install";
var install = registry.GetValue(plantInstall, "InstallDir") as string;
var exe = string.IsNullOrWhiteSpace(install) ? null : Path.Combine(install, "acad.exe");
if (exe is null || !File.Exists(exe) || !Directory.Exists(Path.Combine(install!, "PLNT3D"))) return null;
return new(exe, "2026", "x64", []);
}
}
public sealed class StartupScriptBuilder : IStartupScriptBuilder
+20
View File
@@ -0,0 +1,20 @@
# Legacy launcher capability matrix
Source audit: `All_Serv_Install/Form1.cs`, `F1_Xml.cs`, `F2_Xml.cs`, `All_Serv_Load/Form1.cs`, `All_Serv_InstallUpdater/Form1.cs`, `Control_Sum_XML.cs`, `P_Serv_Starter/Program.cs`, `launcher_starter.lsp`, `Settings.xml`, and `download_list_plant.xml`.
| Legacy capability | User-visible behavior | Modern equivalent | Status |
| --- | --- | --- | --- |
| Settings startup validation | Shows configurations only after required XML fields validate | Strict `LegacyConfigurationAdapter.ParseSettings` and UI file selection | SOURCE_VERIFIED / IMPLEMENTED |
| Pattern selection | Lists pattern name, filter and roster, then enables project/plugin workflow | Launcher Next lists patterns and selected filter/roster | SOURCE_VERIFIED / IMPLEMENTED |
| Ordered download list | Resolves ordered plugin IDs, sources and renewal aliases | Adapter preserves ordered IDs; overlay join rejects missing/ambiguous IDs | SOURCE_VERIFIED / VERIFIED_BY_TESTS |
| Plugin copy/install | Recursively copies arbitrary catalog directories and optional install payloads | Verified manifest acquisition to immutable local package only | SOURCE_VERIFIED / UNSUPPORTED_BLOCKING |
| Update checks | Reconciles server tree using mutable MD5 `control_sums.xml` | No trust is assigned to legacy checksum XML; SHA-256 manifest validation is required | SOURCE_VERIFIED / IGNORED_NON_OPERATIONAL_WITH_REASON |
| Local active state | Deletes/replaces local catalogs before launch | Materialize, validate, immutable commit and explicit activation | IMPLEMENTED / CONTROLLED_RUNTIME_VERIFIED |
| Starter LSP | Stages loader, mutates SupportPath and loads DLL/DVB/LISP | Not reproduced: direct legacy payload execution and persistent SupportPath mutation are unsafe | SOURCE_VERIFIED / UNSUPPORTED_BLOCKING |
| Plant discovery | Legacy BAT starts Plant 3D fire-and-forget | Product-specific ACAD-9117 registry discovery and UI status | SOURCE_VERIFIED / IMPLEMENTED |
| Interactive launch | Starts BAT without PID/evidence or wait | Requires verified local active package, explicit safe launch plan, PID check and evidence | SOURCE_VERIFIED / UNSUPPORTED_BLOCKING |
| Error/status UX | WinForms message boxes and partial continuation | Explicit UI ready/block status and diagnostics | SOURCE_VERIFIED / IMPLEMENTED |
## Blocking external inputs
The checked-in legacy settings reference `N:`/`Q:` production sources and legacy binaries. No owner-approved 2026 compatibility overlay, local manifest-backed catalog, or exact package roster is present in this worktree. Therefore enabling Prepare or Launch would either guess mappings or execute unverified legacy payloads; both violate the Launcher invariants.
@@ -0,0 +1,18 @@
using Launcher.Next.Autodesk;
using Xunit;
namespace Launcher.Next.Tests;
public sealed class PlantDiscoveryTests
{
private sealed class Registry(string? install) : IRegistryReader
{ public object? GetValue(string path,string name)=>path.Contains("ACAD-9117",StringComparison.Ordinal)&&name=="InstallDir"?install:null; }
[Fact]
public void Plant2026DiscoveryUsesPlantSpecificRegistryKey()
{
var directory=Path.Combine(Path.GetTempPath(),Guid.NewGuid().ToString("N"));Directory.CreateDirectory(Path.Combine(directory,"PLNT3D"));File.WriteAllBytes(Path.Combine(directory,"acad.exe"),[]);
try { var product=new PlantProductDiscovery(new Registry(directory)).DiscoverPlant3D(2026);Assert.NotNull(product);Assert.Equal("2026",product!.ProductVersion);Assert.Equal(Path.Combine(directory,"acad.exe"),product.ExecutablePath); }
finally { Directory.Delete(directory,true); }
}
}