fix: make p-rec-update initialization load-safe
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
/link/
|
||||
/link
|
||||
|
||||
# Generated build output is never source or package input.
|
||||
**/bin/
|
||||
**/obj/
|
||||
|
||||
# DocumentAutomation generated files and local source data
|
||||
DocumentAutomation/**/bin/
|
||||
DocumentAutomation/**/obj/
|
||||
|
||||
@@ -9,8 +9,18 @@ public sealed class EntryPoint : IExtensionApplication
|
||||
{
|
||||
public void Initialize()
|
||||
{
|
||||
RuntimeMarker.Write("AssemblyInitializeStarted");
|
||||
RuntimeMarker.Write("AssemblyInitializeCompleted");
|
||||
// Keep the load boundary free of Plant/DataLinks access. Any exception
|
||||
// here must remain observable independently of a project fixture.
|
||||
RuntimeMarker.Write("InitializeEntered");
|
||||
try
|
||||
{
|
||||
RuntimeMarker.Write("AssemblyInitializeCompleted");
|
||||
}
|
||||
catch (System.Exception exception)
|
||||
{
|
||||
RuntimeMarker.Write("AssemblyInitializeFailed", exception.GetType().Name + ":" + exception.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void Terminate() => RuntimeMarker.Write("AssemblyTerminateCompleted");
|
||||
@@ -37,8 +47,27 @@ public sealed class EntryPoint : IExtensionApplication
|
||||
},
|
||||
UpdateExecutionMode.DryRun,
|
||||
ControlledFixturePermit: false));
|
||||
var status = new
|
||||
{
|
||||
schemaVersion = 1,
|
||||
operationId = Environment.GetEnvironmentVariable("P_REC_UPDATE_OPERATION_ID") ?? "unknown",
|
||||
processId = Environment.ProcessId,
|
||||
command,
|
||||
assemblyVersion = typeof(EntryPoint).Assembly.GetName().Version?.ToString(),
|
||||
assemblySha256 = RuntimeMarker.AssemblySha256(),
|
||||
product = "Plant3D",
|
||||
productYear = 2026,
|
||||
activeDocumentPresent = document is not null,
|
||||
activePlantProjectPresent = HasPlantProject(),
|
||||
dryRunInfrastructure = "Available",
|
||||
domainApply = "BlockedByExactFixture",
|
||||
diagnostics = plan.Diagnostics
|
||||
};
|
||||
document?.Editor.WriteMessage($"\nP_Rec_Update {command}: {(plan.Accepted ? "DryRun planned; no project data changed." : string.Join(", ", plan.Diagnostics))}");
|
||||
RuntimeMarker.Write(plan.Accepted ? "CommandRegistrationVerified" : "CommandPreflightRejected");
|
||||
// STATUS proves registration and reports preflight state; it must not
|
||||
// be classified as a failed command merely because no controlled Plant
|
||||
// project fixture is open.
|
||||
RuntimeMarker.Write(command == "P-R-UPD-STATUS" || plan.Accepted ? "CommandRegistrationVerified" : "CommandPreflightRejected", System.Text.Json.JsonSerializer.Serialize(status));
|
||||
}
|
||||
|
||||
private static bool HasPlantProject()
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace PRecUpdate.Plant3D2026;
|
||||
|
||||
internal static class RuntimeMarker
|
||||
{
|
||||
internal static void Write(string state)
|
||||
internal static void Write(string state, string? detail = null)
|
||||
{
|
||||
var root = Environment.GetEnvironmentVariable("P_REC_UPDATE_MARKER_ROOT");
|
||||
if (string.IsNullOrWhiteSpace(root)) return;
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(root);
|
||||
var payload = $"{DateTimeOffset.UtcNow:O}|{state}|{typeof(EntryPoint).Assembly.GetName().Name}";
|
||||
File.WriteAllText(Path.Combine(root, state + ".marker"), payload, new UTF8Encoding(false));
|
||||
var payload = JsonSerializer.Serialize(new
|
||||
{
|
||||
schemaVersion = 1,
|
||||
operationId = Environment.GetEnvironmentVariable("P_REC_UPDATE_OPERATION_ID") ?? "unknown",
|
||||
processId = Environment.ProcessId,
|
||||
timestampUtc = DateTimeOffset.UtcNow,
|
||||
state,
|
||||
detail,
|
||||
assembly = typeof(EntryPoint).Assembly.GetName().Name,
|
||||
assemblySha256 = AssemblySha256()
|
||||
});
|
||||
File.WriteAllText(Path.Combine(root, state + ".marker.json"), payload, new UTF8Encoding(false));
|
||||
}
|
||||
catch { /* Evidence cannot make Plant initialization fail. */ }
|
||||
}
|
||||
|
||||
@@ -46,4 +46,17 @@ public sealed class UpdatePlanBuilderTests
|
||||
Assert.True(plan.MayWriteDrawing);
|
||||
Assert.True(plan.MayWriteProjectData);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Status_probe_preflight_is_deterministic_and_never_write_capable()
|
||||
{
|
||||
var request = new UpdateRequest(true, false, false, new HashSet<UpdateOperation>(), UpdateExecutionMode.DryRun, false);
|
||||
var first = builder.Build(request);
|
||||
var second = builder.Build(request);
|
||||
Assert.False(first.Accepted);
|
||||
Assert.Equal(first.Diagnostics, second.Diagnostics);
|
||||
Assert.False(first.MayWriteDrawing);
|
||||
Assert.False(first.MayWriteProjectData);
|
||||
Assert.Contains("PLANT_PROJECT_REQUIRED", first.Diagnostics);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user