namespace IdleSpectator;
///
/// Single source of truth: would the orange dossier show this EventLed Label?
/// Selection must equal presentation - unpresentable beats must not win Watching.
///
public static class EventPresentability
{
///
/// True when the candidate may own Layer A camera.
/// Empty Label is only allowed for CharacterLed fill (task chip, no orange reason).
///
public static bool WouldShow(InterestCandidate scene)
{
if (scene == null)
{
return false;
}
if (string.IsNullOrEmpty(scene.Label))
{
return scene.LeadKind == InterestLeadKind.CharacterLed;
}
return !string.IsNullOrEmpty(UnitDossier.EvaluateSceneLabel(scene, recordDrops: false));
}
///
/// Shown orange reason, or empty when blanked by identity / ownership rules.
///
public static string ShownReason(InterestCandidate scene, bool recordDrops = true)
{
return UnitDossier.EvaluateSceneLabel(scene, recordDrops);
}
///
/// Harness synthetic tips ("HoldAction") must be subject-led EventReason shape
/// so the presentability gate matches production dossier rules.
///
public static string EnsureSubjectLedLabel(Actor subject, string label)
{
if (string.IsNullOrEmpty(label))
{
return label ?? "";
}
string name = EventFeedUtil.SafeName(subject);
if (string.IsNullOrEmpty(name))
{
return label;
}
if (label.StartsWith(name, System.StringComparison.OrdinalIgnoreCase))
{
return label;
}
// "Name is in scene: HoldAction" → EventSentence + subject-led first token.
return name + " is in scene: " + label;
}
}