Back to "StyloBot-utsläppsserien"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

Architecture ASP.NET Bot Detection StyloBot Testing

StyloBot-utsläppsserien

Monday, 01 June 2026

Hur testar man en detektor vars svar ska ändras när den lär sig?

StyloBot

StyloBot-utsläppsserien

  1. Behavior, Inte Identitet: varför StyloBot modellerar klienter beteendemässigt
  2. Behavior-Är medveten ASP.NET UI: servern - skickade ut ytan över det upptäcktsresultatet
  3. Att hitta och lösa gränslös tillväxt i långtids-, -- och / eller körande- -.-nätverk: den tillförlitlighetsdisciplin som gör motorn tråkig i produktionen
  4. Behavior-Akvis typscript-UI: Express , Fastify, och webbladerkomponenter
  5. Sidecar-arkitekturen: hur detektoren kopplas till icke--.NET-skivor
  6. Att lära sig bli snabbare: adaptiv inlärningssystem, ,, fyra, M SK2, övningsminnet, ,, och bedömningsキャッシュen
  7. Att testa det som inte stannar kvar: kontrolldisciplinen : en BDF-fielddriver regression M SK2 belastning , och kalibrering
  8. StyloExtract - en lokal lärande HTML omvandlare till Markdown: HTML, →, Markdown-lagret som paras med detektorn, ,, walkersbug lucidVIEW som fångade, M SK3, och den hundföda-loopan som gjorde det ärligt

Tillförlitlighetsdisciplinen finns i Att hitta och fixa gränslös tillväxt; adaptiv inlärningssystem i Att lära sig bli snabbare; källa på github.com/scottgalM SK2stylobot.


Hur testar man något som lär sig?

Det är den obehagliga frågan bakom StyloBot, och det är inte retoriskt.

En konventionell testpinner en funktion på plats: input X ger utgång Y . Det fungerar när objektet under testet är stabilt. StyloBot är avsiktligt inte stabilt på den nivånM SK3 Den samlar upp beteendemässiga bevisMska4 en enda begäran Mska5 dess bedömande beror på begäran självt M Ska6 fingeravtrycket Mske7 driften från dess lärda archetyp- ankar, Mska8 sammankomstbeteendet, M Ska9 och huruvida systemet redan sett tillräckligt för att hoppa rakt till den snabba vägen, . Varje fingeravslag börjar att pinnas till den närmaste archetypen, Mske11, dess tidigare, );, när nya observationer landar, rör det sig,Mska13, och rörelsen är själva signalen. Att lära sig bli snabbare.)

Bedömelsen för begäran 20, då , är inte en funktion av begäran

Det förutsätter Assert.Equal. Frågan som en test kan ställa är inte längre | " | kräver X återvänder slutsats Y | ?" | blir det | МSK3 | med tanke på den här beteendeklassen |, | förvandlas systemet till rätt svar |, | av rätt anledningar |M, | inom ett begränsat antal steg |МSK7 | Det är frågan som BDF existerar för att besvara |

De närmaste .NET-analogerna är Verifiera och FsCheck, men BDF är inget av dem . Bevestig bekräftar en artefakt, misslyckas sedan med att bygga på någon exakt diffM SK3 FsCheck säkerställer egenskaper över slumpmässigt skapade inmatningarMska4 BDF sitter mellan demM Ska5 det apstiprināta artefaktet är en beteendemässig definitionM ska6 men passförståndet är sannolikhetsmässigt M Ska7 Inte Mska8 var utgången matchad med detta ögonblicksbild? Mska9 men Mska10? var denna fördelning konvergent till den förväntade sidan av gränsen? M Ska11? med rätt signaler närvarande?

En beteendemässig definition , tre kontrollsystem

Tricket som gör det här tillgodliga, att skapa en BDF-Datei är inte ett testfall. utförbar beteendemässig kontrakt, en definition av hur en klass av klient beter sig

  1. Återuppspelat genom integreringsrigg, en utmaning i taget mot den riktiga orkestern , att fånga signalen - strömregressioner som enheten inte kan se
  2. Re-samplade under k6, många samtida virtuella användare drar ny tid från samma definition , för att generera en realistisk dragning
  3. Den undersökta mot signalerna en riktig sträckning faktiskt mätt , för att fånga kalibreringsdriften.
flowchart TD
    classDef def fill:none,stroke:#3b82f6,stroke-width:2px
    classDef rig fill:none,stroke:#a855f7,stroke-width:2px
    classDef out fill:none,stroke:#22c55e,stroke-width:2px

    BDF["BDF behavioural definition<br/>clientProfile · timingProfile<br/>requests · evidence · labels"]:::def

    Replay["Integration replay<br/>slim form · real orchestrator<br/>cache disabled · identity reset"]:::rig
    K6["k6 load harness<br/>full form · re-sampled per VU<br/>burst + jitter"]:::rig
    Calibration["Calibration audit<br/>claimed evidence<br/>vs measured signals"]:::rig

    Signals["Signal-flow regressions caught<br/>merged ev.Signals reaches<br/>dashboard · persistence · threat report"]:::out
    Metrics["Load envelope verified<br/>latency · detection_rate<br/>burst_detected"]:::out
    Drift["Calibration drift surfaced<br/>stale claims · aged signatures<br/>moved detection surface"]:::out

    BDF --> Replay --> Signals
    BDF --> K6 --> Metrics
    BDF --> Calibration --> Drift

Regressionen, ,, belastning och kalibrering är vanligtvis tre provsystem med tre källor till sanning som driftar bort från varandra.

Varför missar enhetens tester felklassen

Den första versionen av det här arbetet hade hundratals tester per detektorenhet med modellkontexter och kapsylkoppor. De var snabba, deterministiska och blinda för misslyckandet som jag brydde mig om.

Orchestern kombinerar bidrag till en enda ev.Signals ordbok som nedströmsförbrukarna använder. (dashboard, ,, uthållighet, ,, historiebyggare, M SK3, hotstudien, MST4, läsa från, MSV5, en faktor som minskar primary_signature från den sammankopplade ytan misslyckas ingen per- detektorenhetstest: detektorn körde fortfarande, bidraget förde fortfarande signalen, det slutade nå vem som behövde det. brädanaren' fingeravtryckbordet är tom. uthållighet hoppar över rymden. enhetens färgsättning är grön eftersom inget av det går nära sammankopplingen.

Detta är inte en hypotetisk signal-kontraktdokument mäter exakt den här regressen.:, en förändring som slutade sammanfoga signalerna. " överlevde sex dagar i produktion trots att 1957 passerade enhetstest. evidence.Signals."

Integrationstestet vid BdfReplayTests.Integration.cs är direkt om varför det existerar

Den här riggen existerar eftersom fallklassen den fångar ( nedströmsförbrukare av ev.Signals nedbryter tyst när orkestern slutar att kombinera signaler

Orchesteraren är inte en funktion; det är en pipeline vars värde är vad som helst som kommer ut ur fuzningen efter att varje bidragande har kört den. Det enda sättet att hävda detta är att köra en riktig begäran genom en riktig orchesterare och undersöka fuzandets yta . Att flytta på fuzeringen misslyckas med testetM SK3

BDF: en beteendemässig definition , inte ett skriptat test

Ett BDF (Behavioural Definition Format )-fail beskriver hur klass av klientbeteendet.,, inte ett fixerat återspelning av ett... De intressanta delarna i schemat är statistiska. :, ett klientprofil som fångar fördelningsidentiteten. M SK3, ett tidsprofil som definierar en chock. -, med -, en stämlingsregel istället för fixera fördröjningar. MSC6, en uppsättning bevis av viktade förutsägelser över beteendesignaler.bot-signatures/python-requests-bdf.json):

{
  "scenarioName": "python-requests-bdf",
  "scenario": "A bot/scraper using python-requests/2.31.0 with specific behavior patterns.",
  "confidence": 0.85,

  "clientProfile": {
    "userAgent": "python-requests/2.31.0",
    "cookieMode": "none",
    "headerCompleteness": "minimal",
    "clientHintsPresent": false,
    "robotsConsulted": false
  },

  "timingProfile": {
    "burstRequests": 10,
    "delayAfterMs":      { "min":   20, "max":   150 },
    "pauseAfterBurstMs": { "min":  500, "max":  2000 }
  },

  "requests": [
    { "method": "GET",  "path": "/",                "expectedStatusAny": [200,301,302], "expectedOutcome": "indexing", "successCondition": "any 2xx" },
    { "method": "HEAD", "path": "/admin",           "expectedStatusAny": [200,403],     "expectedOutcome": "indexing", "successCondition": "any 2xx" },
    { "method": "GET",  "path": "/api/data?page=1", "expectedStatusAny": [200,403],     "expectedOutcome": "indexing", "successCondition": "any 2xx" },
    { "method": "GET",  "path": "/api/data?page=2", "expectedStatusAny": [200,403],     "expectedOutcome": "indexing", "successCondition": "any 2xx" },
    { "method": "GET",  "path": "/api/data?page=3", "expectedStatusAny": [403,404],     "expectedOutcome": "indexing", "successCondition": "any 4xx" }
  ],

  "labels": ["Scraper", "RobotsIgnore"],

  "evidence": [
    { "signal": "interval_ms_p95", "op": "<", "value": 200,           "weight": 0.35 },
    { "signal": "requestInterval", "op": "<", "value": "burst <150ms", "weight": 0.70 }
  ],

  "patterns":  { "requestInterval": "burst <150ms" },
  "reasoning": "The bot/scraper uses python-requests/2.31.0 to access various endpoints, including the root path and admin pages, while also enumerating API paths and testing different HTTP methods."
}

Den största delen av ytan är statistisk, och det mesta är vad som gör BDF till en definition snarare än ett testskript. docs/bdf-v2-schema.json.)

confidence är en tidigare ",", inte ett påstående . 0.85 säger " det här borde landa högt - självförtroende robot när systemet är friskt M SK3 riggen kontrollerar inte att den mogna poängen är lika МSK4 den kontrollerar dom som dömer landar på robotens sida av gränsen, . det föregående är bandet som är kännetecken, ' författaren, ♫ ( LLM eller människan, M SK8 tror att systemet borde nå . Driften här är en kalibreringshistoria,

clientProfile är en kategori från klienten. cookieMode: none är en kategori av beteendet ( inga cookieburkar , varje begäran börjar färska M SK2 inte en specifik nagłówk . headerCompleteness: minimal säger: " en begäran från den här klienten bär endast den kurl som biblioteken i klass - set, ", en fakta om populationen av begäran som den här clienten skickar ut, ,, inte en fixerad nagłówkist, . Konvertern kM SK5 materialiserar dessa till nagłówknycklar när den körs. likhet av klienten.

timingProfile är en sampningsregel. burstRequests: 10 plus delayAfterMs: {min: 20, max: 150} plus pauseAfterBurstMs: {min: 500, max: 2000} definierar en generator: tio applikationer med en likvärdig sträcka i 20 till | 150 ms , sen en liknighetsmässig stopp i ♫- en tänksam paus mellan ♫ 500 och ♪ 2000 ms\ , repetera |. samma BDF som spelats upp två gånger producerar två olika strömmar med samma statistisk fördelning

evidence är en viktad förutsägelse över signaler. Varje insats är ett krav på formen signal OP value, weight w. {signal: "interval_ms_p95", op: "<", value: 200, weight: 0.35} säger " att pM SK1 inter--inställningsintervalet för detta scenario borde vara under 200ms, och det är värt ♫ 0.35 av bedömningen ♫". BDF hävdar på statistiska nivåer ♫

labels är taxonomi. [Scraper, RobotsIgnore] är klassen som scenariot skapades för . Label drivscenariot-selection i lasthållaren, bara (run Scraper scenarios , utesluta RobotsIgnore) utan att någon skriver en regex över scenerna

requests beskrev vad klienten gör, inte vad som skulle hända nästa gång . expectedStatusAny: [200, 403] toleraerar antingen en framgångsrik fetch eller ett rakt block, eftersom båda är korrekta produktioner av en fiend banasond. expectedOutcome: indexing är kunds intention, ' (beräkning av API-sidor successCondition: "any 4xx"/api/data?page=3 är klienten' s heuristik för " gjorde det här arbeten ": en skräpmaskin som får ♫ 4xx på den tredje sidan lyckas med sitt uträkningsjobb | ( | det har upptäckt klippan |). | BDF fångar asymmetryn mellan vad klienten försöker göra och vad systemet ska göra åt det

Ett BDF och en centroid : samma idé, omvänd

Ordet definition är Last, -, bärande, ,, och den kopplar BDF till konceptet i mitten av StyloBots detektor, M SK2, och .. Motorn klassificerar trafiken mot beteendemässiga centroider: referenspunkter i den dimensionella utrymmet från Behavior, Inte Identitet, var och en lärt ankar för en klass av klient som rör sig på samma sätt

Ett BDF beskriver samma sak: ( en klass av klienter ) med rollen omvänd M SK2 Den centroida är utmärkande: frågar " ser den här utmaningen ut som en klass generator: svarar ♫ " ♫ Producera en begäranström från den klassen ♫

Motorn SignatureToBdfMapper bridges the two: den tar ett beteendesignat fångat från riktig trafik och skriver ut det som en BDF du kan läsa och spela upp igen . En LLM gör samma sak från andra änden M SK2 omvandlar en attackers beskrywing till en ny . Det ger en lus

bot-signatures/ corpus är inte bara ett testfixture; det är en bibliotek av beteendedefinitioner , en file per klass av klient StyloBot anledningar till. Signaturerna där skapades av en modell M SK3ministral-3:3b, per directory 's README) ge kommandor som beskriver en klientfamilj som träffar en uppsättning ändepunkterM SK3 och samma yta är öppen för en mänsklig författareMSC4 skriva en BDF för en ny scraperfamilj och du har en beteendedefinitionMska5 ett regressionsscenarioMske6 och en belastningM Ska7 tester-inskrywing i en enda file

Ett smalt "-"-replay-form lever under test-suites/{bots,humans,adversarial}/*.bdf.json bara för att requests[].method/path/headers/delayAfter plus en mjuk expectedDetection. Det där subset är det som integreringsriggen placerar till återspelningsgränsen , som inte har något sätt att syntetisera fördelningsbeteende från en enda återspelning | ( | inga samtida VUs | , | bara loopback |, | så TLS | МSK5 | TCP fingeravtrycksdimensioner bryts ner på grund av konstruktionen

Slutpunkten för återspelning körs genom den riktiga orkestern

Integrationsriggen placerar varje scenario för att POST /bot-detection/bdf-replay/replay, en ändepunkt som finns i produkten (BdfReplayEndpoints.cs), inte i testprojektet IDetectionOrchestrator från DI och kör genom vilken orkestrare som än är aktuell registrerad DetectionPolicy.Default. Förra versionen hårdkoderade en specifik orkestrator och maskerade regressioner i alternativet (Ephemeral

Eftersom slutpunkten lever i produkten, ,, så är den angrippad som en produktytan. BdfReplay är avstängd standardmässigt; när det är aktiverat X-BdfReplay-Api-Key header och passera en per, -, IP-hastighetsgränsen., så att återuppspelningsväg inte är en upptäcktsbipass som ligger omkring.

flowchart LR
    classDef test fill:none,stroke:#3b82f6,stroke-width:2px
    classDef proc fill:none,stroke:#a855f7,stroke-width:2px
    classDef out fill:none,stroke:#22c55e,stroke-width:2px

    Test["BDF replay rig<br/>authenticated with API key"]:::test --> Endpoint["Product replay endpoint<br/>identity reset · cache disabled"]:::proc
    Endpoint --> Orch["Current DI-registered<br/>orchestrator"]:::proc
    Orch --> Signals["Merged ev.Signals"]:::proc
    Signals --> Assert["Contract assertions<br/>verdict · signal probes<br/>convergence bound"]:::out

Ett medvetet beslut att överrida per- -den signerats- -avsiktskälla för återspelning.

var replayPolicy = Policies.DetectionPolicy.Default with
{
    SignatureCache = Policies.DetectionPolicy.Default.SignatureCache with { Enabled = false }
};

The cache's Skip path bypasses the matcher completely once a primary signature has a confident cached verdict Att lära sig bli snabbare); för en rig som mäter avkänningsgenrikthet och signalflödet, gömmer den per request-beteende som rigen försöker sätta på

Scenarier är också isolerade från varandra. Varje scenario får ett unikt syntetiskt IP som kommer från en deterministisk xxHash med dess namn (a 192.0.x.y address from the RFC 5737 TEST - Net range), so subnetM SK3 reputation never bleeds between scenarios POST /bot-detection/bdf-replay/reset-identity innan varje scen för att skära ner fingeravtrycksbutiken, utan det, ; scenario N ärfår upp fingeravslagsscenariorna, 1..,N,-1, skapade och per-scenario-stabilitetsbehauptningarna blir ordande.

Behauptande på en icke-deterministisk yta

Riggen gör tre påståenden om varje scenario.

Förberedda bedömningar , inte per-ansökt bedömning. Botscenarier hävdar last.Actual.IsBot är sant; mänskliga scenarior hävdar majoritet av krav som är klassificerade som mänskliga. Att bevisa på varje individuellt krav skulle couplera testet med driftsträngningen bort från archetypankaren

// Some heuristics legitimately escalate on outlier rates; assert majority human, not all.
var humanCount = response.Results.Count(r => r.Actual is { IsBot: false });
var botCount = response.Results.Count - humanCount;
Assert.True(humanCount >= botCount,
    $"{response.ScenarioName}: {botCount}/{response.Results.Count} requests classified as bot, " +
    $"expected majority human. Last verdict: {last.Actual!.RiskBand} prob={last.Actual.BotProbability:F2}");

Namerade signalsonder, inte mäter signalen Signalflödet undersöks per nyckeln.,, inte som ett total... Ett sammanräkningsbehauptande är brittiskt. :. En ny detektör som utsätter en ny signal maskerar förlusten av ett kritiskt redan existerande.

Assert.True(probes.TryGetValue(SignalKeys.PrimarySignature, out var hasSig) && hasSig,
    $"{scenarioName}: {SignalKeys.PrimarySignature} missing from ev.Signals — " +
    "RequestPersistenceService skips persistence, dashboard fingerprint table goes blank");

Misslyckandets meddelande är testet' specifikationen . Tre månader senare behöver du inte komma ihåg varför signalen spelade roll

Begränsad konvergenss , inte exakt jämlikhet. Den metastabla fingeravtrycksmatcharen löser en högljudd vektor till en stabil identitet. Vektorkompositionen inkluderar sessionsdimensioner ( bana-entropiM SK2 sessionsålderMska3 som driftar per applikationMske4 så att matchet mellan de två Mska5passen kan ibland falla ut ur dess locka band och fördelasM Ska6 Att på en enda fingeravslagsidentifikation över alla applikationer skulle vara felaktigt ; att påstå mska8 inga hålMka9 och konvergensen till inte mer än ceil(N/2) avseparerade fingeravtryck " är det faktiska kontraktet

var distinctFps = withFingerprints
    .Select(r => r.Actual!.IdentityFingerprintId!)
    .Distinct(StringComparer.OrdinalIgnoreCase)
    .Count();
var allowed = Math.Max(1, (int)Math.Ceiling(response.Results.Count / 2.0));
Assert.True(distinctFps <= allowed,
    $"{scenarioName}: {distinctFps} distinct fingerprints across {response.Results.Count} requests " +
    $"(allowed {allowed}). The matcher isn't converging — every request is allocating new, suggesting " +
    "vector composition is unstable or LooseThreshold is unreachable.");

ceil(N/2) är inte magiskt. Det koder en policy : den första utmaningen allocaterar alltid ; efterföljande utmaningar ska mestadels matchas via LM SK3 bekräfta eller Släng 2. Iblandaloktionen under hög vägsvarians är möjlig varenda dag begäran är en regression. gränsen är tillräckligt lös för att absorbera oljudet matcharen är konstruerad att absorberar, tillräckligt tät för att fånga misslyckande modet där den slutar förbinda sig överhuvudtaget

Alla tre mönster delar en egenskap, :, de påstår i kontraktet att beteendet är tänkt att tillfredsställa ,, inte på de specifika siffrorna som den nuvarande implementeringen orsakar att producera ., när implementeringen ändrar sig ,, så håller testet kvar om kontrakten fortfarande håller ., det är vad som gör ett icke-deterministiskt test stabilt

Lade samma korpus under tryck

En BDF-Datei är bara JSON. Integrationsriggen tar upp den smala formen . Lastbehållaren tar upp hela den statistiska formen scripts/convert-bdf-to-k6-v2.csx läser ett signerskatalog och utsätter en k6 skrip som re-samples varje undertecknande's fördelning per VU per iteration.

Re-samples gör verkligt arbete i den där meningen . k6 skriptet återspelar inte ett fångat spår clientProfile och timingProfile som en live generator. Varje VU-iteration väljer en signature, bygger opskrifte från dess headerCompleteness och clientHintsPresent flags, fäster en kakaburk som matchar dess cookieMode, får tag robots.txt om robotsConsulted är sant, och drar sedan fram fria per-delayer från delayAfterMs.min..max och en ny paus från pauseAfterBurstMs.min..max. Två VU med samma signering skickar ut två olika begäranströmmar med samma statistisk fördelning , vilket är precis vad det detekteringskedjan ska känna igen som ett likhet av klienten.

// Main test function - each VU picks random scenario and replays with burst/jitter.
// Multiple VUs running concurrently provide natural request interleaving.
export default function() {
    const sig = signatures[Math.floor(Math.random() * signatures.length)];
    // ... robots.txt, cookie jar, header bundle built from sig.clientProfile ...

    for (let i = 0; i < sig.requests.length; i++) {
        const req = sig.requests[i];
        const url = `${TARGET_URL}${req.path}`;
        const headers = buildHeaders(req.headers || {}, sig.clientProfile);
        const res = http.request(req.method, url, null, params);

        if (sig.timingProfile) {
            if (requestCount < sig.timingProfile.burstRequests) {
                sleep(randomBetween(
                    sig.timingProfile.delayAfterMs.min / 1000,
                    sig.timingProfile.delayAfterMs.max / 1000));
            } else {
                sleep(randomBetween(
                    sig.timingProfile.pauseAfterBurstMs.min / 1000,
                    sig.timingProfile.pauseAfterBurstMs.max / 1000));
                requestCount = 0;
                burstRate.add(1);
            }
        }
    }
}

Den rubrikens egenskap: det korpus du testar för korrekthet är det korpus som du betonar för prestation. Det finns inga ♫ " ♫ integreringstest som går, men produktionstrafiken ser inte ut som integreringstester ♫ är trafikgeneratorn. När en klient rapporterar en misslyckad robotfamilj, lägger du till ett BDF och den går samman med både regresspaketet och lasttestetM SK2 Ingen översättning , ingen andra källa till sanning

k6 mätvärdena talar samma språk som BDF-ytan

kM SK1 mätbart Vad det mäter
bot_scenarios / human_scenarios Beräkningar per scenarioklass
detection_rate Fraktion av Bot-scenarier i klass -, markerade vid kanten
interval_ms Inter
sensitive_path_rate Fraktion av träffade begäran /admin, /api, punktfiler
burst_detected De sprängningsgränsen som kommer från tidensprofilet
http_req_duration Standardlatenshistogram för p95/pM SK2 tröskel

tröskeln på dessa blir en utförbar specifikation för lastbeläggningen:

thresholds: {
    http_req_duration: ['p(95)<1000'],
    http_req_failed: ['rate<0.1'],
    'detection_rate': ['rate>0.3'],
},

En reaktor som återspeglar detektionsgenomfattning under last (det bedömande kassvakt som hoppar över begäran att den skan'tM SK2 resa detection_rate. En reaktor som introducerar en lång väg under motsättningsresor http_req_duration p95. Samma källdata , två regressioner fångade

Kalibrering : tredje användning av samma file

Vid det här laget har BDF redan gjort två jobb, den har kontrollerat orkesterns signalkontrakt under repetition, , och skapat en realistisk belastning under k. Den tredje tillämpningen är den som jag tycker är mest intressant, själv.

Varje bevisinsats är en påstående från formen signal OP value, weight w. När ett signerat har spelats upp igen (under loopback eller kM SK2 så har systemet skapat en mätd fördelning för samma signaler interval_ms_p95 < 200 krävande kan kontrolleras mot den mätta p95. cookie_count >= 2 är kontrollbar mot cookie-räkningen som begäran faktiskt skickades till. header_count >= 8 kan kontrolleras mot opskrifte som landade evidence är upplisterade i BDF v2 schema: interval_ms_p95, interval_ms_p50, sensitive_path_rate, error_rate, burst_detected, header_count, cookie_count.)

När mätt skiljer sig från påståendet, har kännetecken driftat ut ur kalibreringen . Antingen var den överspecifikerad för systemet det skrevs emot, eller systemet har flyttats under detM SK3 Båda är användbaraMSC4 den första säger att reMska5 generera känneteken från observationenM Ska6 den andra säger att en reafaktor flyttade det detekterande ytan på ett sätt som ingen funktionell test skulle fånga

Den python-requests-bdf.json som visades tidigare är ett litet exempel på varför auditen är nödvändig value ("burst <150ms") där schemat kräver ett tal requestInterval signal som den namnges inte finns i beviset överhuvudtaget. En modell skrev att raden , och ingen enhetstest avfärdar den M SK2 Bara ett mätt utdrag som jämför påstående bevis mot observerade signaler visar på en påstående som aldrig var kontrollbar från första början

Detta gör att BDF omvandlas från en regressartefakt till en kalibrering artefakt. bot-signatures/ var LLM-genererad mot en tidigare version av detektorleitungen ; deras bevis på att koda vad att version thought distinguished each client family

Sex regler för att testa icke-deterministiska system

De icke-deterministiska systemen kräver inte byggt ena. De mönster som fungerar för StyloBot generaliserar

  1. Definiera ingången som en fördelning A timingProfile med min/ Max hål är en generator ; ett fångat begäranspår är en dragning från det M SK2 Testa mot spåret och du testar dragningen , inte distributionen Mska4 Samma logik för klientprofilet Mske5cookie-läger och opskriftefullhet beskriver en population M Ske6 inte en fixerad opskriftelista M ske7
  2. Välj contractet som viktade företeelser. Den evidence array är det närmaste som systemet har till en enhetinterval_ms_p95 < 200), inte punktvärdena . Beräkningar med vikter komponerarM SK2 jämlikhetsbehauptningar don'tMSC4
  3. Behaupta på målet, inte vägen. För system vars tillstånd är ett fingeravtryck som sträcker sig från en archetyp innan
  4. Probe den sammanlagda ytan , inte komponenterna. Förlustklassens prover kan inte fånga är den där komponenterna är individuellt korrekta men sammansättningen faller något.
  5. Förbinda konvergensen. En matchare som löser ljudlig inmatning till en stabil identitet kommer ibland att allocera. Behauptelsen är M SK1 stannar under gränsen ", som valdes från policyn
  6. dela inmatningsformatet över rigg, belastning , och kalibrering När scenariot är ett utförbart beteendemässigt kontrakt snarare än ett skript, så driver samma dokument en regressrigg, ,, en perf utrustning och en kalibreringsaudit.

Där det passar in i releasserien

Att hitta och fixa gränslös tillväxt begränsade minnet; Att lära sig bli snabbare gjort repetition av detektorn billigt. Det här är den tredje sträckan : som kontrollerar ett system vars utgång kommer att bli bättre ' inte stanna kvar

Metoden är ett korpus. Samma BDF-signaturer driver regression, load, kalibrering och kalibrering, så att testers underhåll förvandlas till korpusvård.

Så det här är svaret på " hur kan man testa något som StyloBot? ?" Du fryser inte det, . Du definierar en klass av trafik, ,, kör det riktiga systemet mot det,,, och ser till att tre saker är klart: :, att dom slutsatserna fortfarande är sammanhängande.,, att signalerna som dess konsumenter är beroende av, fortfarande kommer fram. ,, och att bevisen som definitionen säger matchar vad den mäter.


BDF återspelar rigen lever vid BdfReplayTests.Integration.cs. Slima återspelningsscenarior är under test-suites/{bots,humans,adversarial}/*.bdf.json; fulla statistiska undertecknande ( med clientProfile, timingProfile, evidence) är under bot-signatures/*.json. Konverrenaren kM SK1 är scripts/convert-bdf-to-k6-v2.csx. Slutpunkten för återspelning som båda riggar använder är BdfReplayEndpoints.cs. Signalkontraktet som dessa tester försvarar är dokumenterat i docs/architecture/signal-contracts.md. All källa på github.com/scottgalM SK2stylobot. Livmotorn , brädan, , och kommersiella kontrollen stylobot.net.

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.