docs: Campaign LA — pinned launch-contract schema COMMITTED into plan LA1

The LA3 Opus review process note was right: the contract both sides
implement lived only in orchestrator prompts, which is exactly the drift
mode the pin exists to prevent (and it produced the paths-key CRITICAL).
The schema, field rules, probe-mode discriminator, and status vocabulary
are now a binding plan section; amendments change this text first,
implementations second. Ledger: LA3 fix round dispatched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-14 16:04:32 +02:00
parent 0bcc7ba3a3
commit db9ad53c1c
38 changed files with 2397 additions and 40 deletions

View file

@ -82,7 +82,11 @@ internal sealed record SessionPlayerDependencies(
CombatAttackOperationsSlot CombatAttackOperations,
CombatFeedbackSlot CombatFeedback,
TransferableResourceSlot<PortalTunnelPresentation> PortalTunnelFallback,
Action<string> Log)
Action<string> Log,
/// <summary>Campaign LA slice LA1: the shared per-session status-event
/// writer, no-op when <see cref="RuntimeOptions.StatusFilePath"/> was
/// not configured.</summary>
SessionStatusWriter StatusWriter)
{
public RuntimeActionState Actions => Runtime.ActionOwner;
@ -1124,7 +1128,9 @@ internal sealed class SessionPlayerCompositionPhase
acceptedPositionDrive,
remotePlacementDrive),
liveSessionCommands,
d.Log);
d.Log,
d.StatusWriter,
d.Options.SessionId ?? "app");
LiveSessionHost sessionHost = sessionRuntimeFactory.Create(
liveSession,
new LiveSessionConnectOptions(
@ -1132,7 +1138,8 @@ internal sealed class SessionPlayerCompositionPhase
d.Options.LiveHost,
d.Options.LivePort,
d.Options.LiveUser ?? string.Empty,
d.Options.LivePass ?? string.Empty));
d.Options.LivePass ?? string.Empty,
d.Options.LiveCharacterSelector));
Fault(SessionPlayerCompositionPoint.SessionHostCreated);
// The ImGui developer-tools debug toast sink was removed at Campaign V

View file

@ -1,9 +1,14 @@
using AcDream.Runtime;
using AcDream.Runtime.Session;
namespace AcDream.App.Composition;
internal sealed record SessionStartDependencies(
Action<string> Log);
Action<string> Log,
/// <summary>Campaign LA slice LA1: no-op when no statusFile was
/// configured.</summary>
SessionStatusWriter StatusWriter,
string SessionId);
/// <summary>
/// Terminal startup phase. Every callback, command target, and frame root is
@ -21,6 +26,9 @@ internal sealed class SessionStartCompositionPhase
public void Start(FrameRootResult frame)
{
ArgumentNullException.ThrowIfNull(frame);
// Campaign LA slice LA1: "started" = session host start — the
// earliest point the graphical host actually attempts to connect.
_dependencies.StatusWriter.Started(_dependencies.SessionId);
RuntimeSessionStartResult result =
frame.GameRuntime.Session.Start(frame.GameRuntime.Generation);
Report(result, _dependencies.Log);