Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/adr/0004-capability-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ been live-qualified.
or host-side behavior that ordinary CI has not established.
- The matrix gives reviewers one place to distinguish a deliberate product gate from a missing implementation, keeping
package release claims honest as SDK evidence changes.
- Capability evidence exposes the stable `EffectiveReasonCode` of the gate that supplied its display reason. Consumers
use that code with the gate's independently observed state rather than parsing text or reproducing the Client's
priority order; it does not promote an unknown, faulted, malformed, or unqualified capability to `Available`.

## Current template boundary

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ CheatEngine.Client.Runtime.ClientCapabilityEvidence.ClientCapabilityEvidence() -
CheatEngine.Client.Runtime.ClientCapabilityEvidence.ClientCapabilityEvidence(CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate implementation, CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate package, CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate host, CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate liveQualification, CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate policy, CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate lifetime) -> void
CheatEngine.Client.Runtime.ClientCapabilityEvidence.AvailabilityState.get -> CheatEngine.Client.Runtime.ClientCapabilityAvailabilityState
CheatEngine.Client.Runtime.ClientCapabilityEvidence.EffectiveReason.get -> string!
CheatEngine.Client.Runtime.ClientCapabilityEvidence.EffectiveReasonCode.get -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode
CheatEngine.Client.Runtime.ClientCapabilityEvidence.Host.get -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate
CheatEngine.Client.Runtime.ClientCapabilityEvidence.Implementation.get -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate
CheatEngine.Client.Runtime.ClientCapabilityEvidence.IsExecutable.get -> bool
Expand All @@ -52,6 +53,13 @@ CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate.IsSatisfied.get -> bool
CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate.Reason.get -> string!
CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate.State.get -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceState
CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate.Equals(CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate other) -> bool
CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode
CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode.Host = 2 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode
CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode.Implementation = 0 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode
CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode.Lifetime = 5 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode
CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode.LiveQualification = 3 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode
CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode.Package = 1 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode
CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode.Policy = 4 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode
CheatEngine.Client.Runtime.ClientCapabilityEvidenceState
CheatEngine.Client.Runtime.ClientCapabilityEvidenceState.Faulted = 3 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceState
CheatEngine.Client.Runtime.ClientCapabilityEvidenceState.Malformed = 4 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceState
Expand Down
4 changes: 4 additions & 0 deletions libs/CheatEngine.Client.Abstractions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ host observation, live qualification, policy, and activation lifetime are distin
missing, faulted, and malformed host observations remain distinguishable instead of being collapsed into a generic
unavailable result.

`Evidence.EffectiveReasonCode` is the stable, typed identity of the gate supplying `Evidence.EffectiveReason`; use it
with that gate's public state instead of parsing the human-readable reason text or duplicating the Client's deterministic
priority. The reason text remains available for display and diagnostics.

In particular, the value-scan contract and state model are published, but the Core implementation
does **not** currently create a live `MemScan`/`FoundList` session. The next SDK line now contains a
production owner factory with parent rollback and child-before-parent teardown, but Client
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,100 +86,121 @@ public ClientCapabilityAvailabilityState AvailabilityState
public bool IsExecutable => AllSatisfied;

/// <summary>Gets the reason for the highest-priority missing, faulted, malformed, or unknown prerequisite.</summary>
public string EffectiveReason => GetEffectiveGate().Reason;
public string EffectiveReason => GetGate(EffectiveReasonCode).Reason;

/// <summary>
/// Gets the stable code for the evidence gate that supplies <see cref="EffectiveReason"/>. Its state remains
/// available through the corresponding evidence-gate property.
/// </summary>
public ClientCapabilityEvidenceReasonCode EffectiveReasonCode => GetEffectiveReasonCode();

private bool AllSatisfied =>
Implementation.IsSatisfied && Package.IsSatisfied && Host.IsSatisfied && LiveQualification.IsSatisfied &&
Policy.IsSatisfied && Lifetime.IsSatisfied;

private ClientCapabilityEvidenceGate GetEffectiveGate()
private ClientCapabilityEvidenceReasonCode GetEffectiveReasonCode()
{
if (Lifetime.State == ClientCapabilityEvidenceState.Missing)
{
return Lifetime;
return ClientCapabilityEvidenceReasonCode.Lifetime;
}

if (Policy.State == ClientCapabilityEvidenceState.Missing)
{
return Policy;
return ClientCapabilityEvidenceReasonCode.Policy;
}

if (Implementation.State == ClientCapabilityEvidenceState.Missing)
{
return Implementation;
return ClientCapabilityEvidenceReasonCode.Implementation;
}

if (Package.State == ClientCapabilityEvidenceState.Missing)
{
return Package;
return ClientCapabilityEvidenceReasonCode.Package;
}

if (Host.State == ClientCapabilityEvidenceState.Missing)
{
return Host;
return ClientCapabilityEvidenceReasonCode.Host;
}

if (LiveQualification.State == ClientCapabilityEvidenceState.Missing)
{
return LiveQualification;
return ClientCapabilityEvidenceReasonCode.LiveQualification;
}

if (Host.State is ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed)
{
return Host;
return ClientCapabilityEvidenceReasonCode.Host;
}

if (Package.State is ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed)
{
return Package;
return ClientCapabilityEvidenceReasonCode.Package;
}

if (LiveQualification.State is ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed)
{
return LiveQualification;
return ClientCapabilityEvidenceReasonCode.LiveQualification;
}

if (Implementation.State is ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed)
{
return Implementation;
return ClientCapabilityEvidenceReasonCode.Implementation;
}

if (Policy.State is ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed)
{
return Policy;
return ClientCapabilityEvidenceReasonCode.Policy;
}

if (Lifetime.State is ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed)
{
return Lifetime;
return ClientCapabilityEvidenceReasonCode.Lifetime;
}

if (Host.State == ClientCapabilityEvidenceState.Unknown)
{
return Host;
return ClientCapabilityEvidenceReasonCode.Host;
}

if (Package.State == ClientCapabilityEvidenceState.Unknown)
{
return Package;
return ClientCapabilityEvidenceReasonCode.Package;
}

if (LiveQualification.State == ClientCapabilityEvidenceState.Unknown)
{
return LiveQualification;
return ClientCapabilityEvidenceReasonCode.LiveQualification;
}

if (Implementation.State == ClientCapabilityEvidenceState.Unknown)
{
return Implementation;
return ClientCapabilityEvidenceReasonCode.Implementation;
}

if (Policy.State == ClientCapabilityEvidenceState.Unknown)
{
return Policy;
return ClientCapabilityEvidenceReasonCode.Policy;
}

return Lifetime;
return ClientCapabilityEvidenceReasonCode.Lifetime;
}

private ClientCapabilityEvidenceGate GetGate(ClientCapabilityEvidenceReasonCode reasonCode)
{
return reasonCode switch
{
ClientCapabilityEvidenceReasonCode.Implementation => Implementation,
ClientCapabilityEvidenceReasonCode.Package => Package,
ClientCapabilityEvidenceReasonCode.Host => Host,
ClientCapabilityEvidenceReasonCode.LiveQualification => LiveQualification,
ClientCapabilityEvidenceReasonCode.Policy => Policy,
ClientCapabilityEvidenceReasonCode.Lifetime => Lifetime,
_ => throw new ArgumentOutOfRangeException(nameof(reasonCode), reasonCode,
"The Client capability evidence reason code is not defined.")
};
}

private bool HasState(ClientCapabilityEvidenceState state)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace CheatEngine.Client.Runtime;

/// <summary>Identifies the evidence gate that supplies <see cref="ClientCapabilityEvidence.EffectiveReason"/>.</summary>
public enum ClientCapabilityEvidenceReasonCode : byte
{
/// <summary>The operational Client adapter gate supplies the effective reason.</summary>
Implementation = 0,

/// <summary>The consumed package artifact gate supplies the effective reason.</summary>
Package = 1,

/// <summary>The Cheat Engine host observation gate supplies the effective reason.</summary>
Host = 2,

/// <summary>The live host-qualification gate supplies the effective reason.</summary>
LiveQualification = 3,

/// <summary>The Client policy gate supplies the effective reason.</summary>
Policy = 4,

/// <summary>The activation-lifetime gate supplies the effective reason.</summary>
Lifetime = 5
}
Loading