StyloBot Release Series: Testing the Thing That Won't Sit Still
Comment tester un détecteur dont la réponse devrait changer au fur et à mesure qu’il apprend?? Ce post est sur le BDF, le Format de définition comportementale qui rend StyloBot testable.
StyloBot Release Series
- Comportement, Non identité: pourquoi StyloBot modele les clients de façon comportementale
- Behaviour-Aware ASP.NET UI: le serveur - remet la surface sur ce résultat de détection
- Trouver et rétablir une croissance sans limites dans les services longs-Running .NET: la discipline de fiabilité qui maintient le moteur borne dans la production
- Behaviour-Aware TypeScript UI: ExpressM SK1 Fastify, et composants de navigateur
- L'architecture de la Sidecar: comment le moteur de détection se connecte aux piles NET non -.
- Apprentissage pour devenir plus rapide: le système d'apprentissage adaptatif , quatre- mémoire de niveauM SK3 et cache des verdicts
- Étudier ce qui ne va pas se tenir: la discipline de vérification : un fichier BDF conduit à la régressionM SK2 charge, et à l'étalonnage
- StyloExtract - un convertisseur HTML d'apprentissage local à Markdown: la couche de marquage HTML→ qui se joigne au détecteur , le bug lucidVIEW du fauteuil roulant qui a capté l’image
La discipline de la fiabilité est Trouver et régler une croissance sans limites; le système d’apprentissage adaptatif dans Apprentissage pour devenir plus rapide; source à github.comM SK1scottgal/stylobot.
Comment tester quelque chose qui apprend?
C’est la question incommode derrière StyloBot, et elle n’est pas rétorique.
Un test conventionnel attribue une fonction en place: l'entrée X retourne la sortie Y. Ce qui fonctionne lorsque l'objet soumis à l'essai est stable . le StyloBot n'est pas délibérément stable à ce niveau M SK3 Il accumule des preuves de comportement MSC4 une seule demande ' son verdict dépend de la demande elle-même Mska6 l’ empreinte digitale M Ska7 sa dérive de son ancrage archétypique appréhendé MSKA8 son comportement pendant la session Mka9 et si le système a déjà vu assez pour passer directement sur la voie rapide MKA10 Chaque empreinte commence par être attachée au type archétype le plus proche M KA11 son précédent Mkkaa12 à mesure que les nouvelles observations débarquent, il se déplace M Ka13 et le mouvement lui-même est le signal. Apprentissage pour devenir plus rapide.)
Le verdict de la requête 20, alorsM SK1 n'est pas une fonction de la demande 20. Il s'agit d'une fonction des requêtes 1 par M20. Par conséquent, l'objectif d'essai ne constitue aucune requêté. C'est le comportement du système sur une séquence de celles-ci
Cela exclut Assert.Equal. La question qu'un essai peut poser n'est plus " demande le verdict de retour X YM SK2 Il devient " étant donné cette classe de comportement, le système converge-t-il à la bonne réponseMNK5 pour les bonnes raisonsMRK6 dans un nombre limité d'étapes MNK7 C'est la question BDF existe pour répondreMMK8
Les analogies les plus proches .NET sont Vérifier et FsCheck, mais le BDF n’est ni l’un ni l'autreM SK1 Vérifier approuve un artefact , puis ne réussit pas à construire sur une diff exacte. FsCheck affirme les propriétés sur des intrants générés au hasardMSC4 Le BDF se situe entre euxMNK5 l’artefact approuvé est une définition comportementaleMBK6 mais la condition de passage est probabilisteMGK7 Non " la sortie correspond-elle à cette photo instantanéeMZK9 mais " cette distribution converge-t-elle avec le côté escompté de la limiteMMK11 avec les signaux appropriés présentsMDK12
Une définition comportementale, trois systèmes de vérification
Le truc qui fait de ce fichier BDF facile à traiter: n’est pas un cas d’essai. contrat de comportement exécutoire, une définition de la façon dont se comporte une classe de client . Une fois écrite, qu'un fichier est consommé en trois manièresM SK3
- Réjouis par l’intermédiaire de l’appareil d’intégration, une demande à la fois contre l’orchestre réel, pour capter le signal - régressions des flux que l’unité suite ne peut pas voirM SK3
- Re-sampled sous k6, de nombreux utilisateurs virtuels concurrents dessinant un nouveau moment à partir de la même définitionM SK1 pour produire une charge réaliste.
- Vérification contre les signaux, une courbe réelle effectivement mesurée, pour capturer la dérive d’étalonnageM SK1
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
Régression, charge , et l’étalonnage sont habituellement trois systèmes d’essai avec trois sources de vérité qui s’écartent.
Pourquoi les essais d'unité manquent la classe de défaillance
La première version de ce travail comportait des centaines d’essais par unité de détection, avec des contextes modèles et des titres en conserve.
L'orchestre fusionne les contributions en un seul ev.Signals le dictionnaire que les consommateurs en aval. primary_signature à partir de la surface fusionnée n’échoue pas par appareil d’essai d’unité de détection : le détecteur est encore en marche , la contribution transporte toujours le signal , il a tout simplement cessé d’atteindre quiconque l’avait besoin . Le tableau de bord ' la table des empreintes digitales est vide . la persévérance passe dans la ligne . La suite unitaire reste verte parce qu’aucun de ces éléments ne se trouve près de la fusion
Ce n’est pas une hypothèse. signal-document de contrats "a survécu pendant six jours en production malgré le passage des essais d’unité 1957, parce que les essais de l'unité ont été assermentés sur la probabilité et le nombre de contributions evidence.Signals."
Le test d'intégration à BdfReplayTests.Integration.cs est direct sur la raison pour laquelle il existe:
Ce réservoir existe parce que la classe de défaillance qu’il capture (consommateurs en aval des
ev.Signalsde dégradation silencieuse lorsque l'orchestre arrête la fusion des signaux) ne faillit pas à aucun essai d'unité
L’orchestre n’est pas une fonction; il s’agit d’une pipeline dont la valeur est quelle que soit celle qui découle de la fusion après que chaque coauteur a exécuté la mise en œuvre. La seule façon d’affirmer cela est de lancer une demande réelle par l’entremise d’un orchestrateur réel et d’étudier la surface fusionnée . Mocking the merge defeats the testM SK3
BDF: une définition comportementale , pas un test scripté
Un fichier BDF (Format de définition comportementale) décrit comment un classe Les parties intéressantes du schéma sont statistiques: un profil de client qui saisit l’identité répartitionnelle , un Profil de temps qui définit une ruptureM SK4 avec- la règle d’échantillonnage des éclats plutôt que des retards fixesMSC6 un ensemble de preuves de prédictions pondérées sur les signaux comportementauxMNK7 et une confiance antérieure MNK8 Voici une signature réelle MMK9bot-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."
}
La plus grande partie de la surface est statistique, et c’est ce qui rend le BDF un Définition plutôt qu'un script d'essai. (Le schéma de champ complet-parM SK3 est docs/bdf-v2-schema.json.)
confidence n’est pas une affirmation antérieure, 0.85 dit "ce devrait atteindre un niveau élevé- robot de confiance lorsque le système est sainM SK3 Le rig ne vérifie pas que la note mature équivaut à 0.85; il contrôle le verdict qui atterreint sur le côté du bot de la frontièreMSC5 La première est la bande signéeMska6 son auteur mska7LLM ou humainMske8 croit que le système doit atteindre les niveaux requisMka9 Le débordement ici est une histoire d’étalonnageM Ska10 non une unitéM ska11essai d’échecMSKA12
clientProfile est une catégorie de client. cookieMode: none est un Toutes les catégories de comportement (pas de bouillon de témoinsM SK1 chaque demande commence fraîchement), pas d'en-tête spécifiqueMSC3 headerCompleteness: minimal indique "une requête de ce client ne porte que le curl que les bibliothèques classées dans la classe -set ", un fait concernant la population des requêtes émises par ce client, , non une liste fixe d'en-têtes. de la nature de client.
timingProfile est une règle d’échantillonnage burstRequests: 10 plus delayAfterMs: {min: 20, max: 150} plus pauseAfterBurstMs: {min: 500, max: 2000} définit un générateur: dix demandes avec l'uniformité - des lacunes aléatoires entre 20 et 150msM SK4 puis une pause aléatoire uniformeMSC5 de \500 jusqu'à |2000ms~, répéterMSSK9 Le même BDF reproduit deux fois produit deux flux de demandes différentes avec la même distribution statistiqueMNK10 C'est le comportement réel du StyloBot MNK11 son détecteur de périodicité et sa sessionMRK12 le compacteur de vectore tentent de reconnaîtreMMK13 un vecteur de retard fixe essaierait complètement une distribution différenteMGK14
evidence est un prédit pondéré sur les signaux. Chaque entrée est une réclamation du formulaire signal OP value, weight w. {signal: "interval_ms_p95", op: "<", value: 200, weight: 0.35} Le BDF affirme au niveau statistique que : n’est pas "requête 7 retourne le bot=trueM SK11 mais que =="la population produite par ce client devrait produire une distribution d’intervalle dont pMSC13 est inférieure à == 200ms". Un scénario dont les éléments de preuve prétendent différer de ceux que mesure le système en cours constitue une signature qui a échappé à l’étalonnage ==
labels sont la taxonomie. [Scraper, RobotsIgnore] est la classe pour laquelle le scénario a été généré pour . Choix du scénario de démarrage des étiquettes dans l'engrenage de charge (run seulement Scraper scénarios, exclure RobotsIgnore) sans que personne n’ait écrit un regex sur les noms de scénarios.
requests décrire ce que le client fait, non ce qui devrait se produire prochainement. expectedStatusAny: [200, 403] toléra soit un téléchargement réussi, soit un bloc immédiat, parce que ces deux produits sont valides d'une sonde de chemin hostile. expectedOutcome: indexing est la l’intention du client' (enumérer les pages de l'APIM SK1 non le serveur successCondition: "any 4xx" sur /api/data?page=3 est le client's heuristic pour M SK1did this work": un scraper qui obtient 4xx sur la troisième page réussit à son travail d'énumération (it a découvert l'écluseMSC5 Le BDF capte l'asymétrie entre ce que le client essaie de faire et ce qu'il est censé faire du système à cet égard
Un BDF et un centroïde: ont la même idée , inversé
Le mot Définition est chargée-portant, et il relie le BDF au concept au centre du détecteur StyloBot ' de . Le moteur classe la circulation contre les comportements centroïdes: points de référence dans l'espace dimensionnel 130+ à partir Comportement, Non identité, chacun est un ancrage axé sur l'apprentissage pour une classe de clients qui se déplacent de la même façon
Un BDF décrit la même chose (une classe de client) avec le rôle inverséM SK2 Le centroid est Recommandation de la Commission: il demande " cette requête ressemble-t-elle à celle de la classe génératrice: il répond " produire un flux de demandes à partir de cette classe." Le même comportementM SK3 direction opposéeMSC4 qui est exactement ce qui rend un BDF replayable et un centroid non
Le moteur's SignatureToBdfMapper bridges the two: it takes a behavioural signature captured from real traffic and writes it back out as a BDF you can read and replay . An LLM does the same job from the other endM SK2 turning a description of an attacker into a new one. That gives a loopMska4 observed traffic becomes a signatureM Ska5 the signature becomes an BDFM ska6 and the BDF can replay the behavior that produced itMSKA7
Ainsi, le bot-signatures/ corpus n'est pas seulement une fixture d'essai; il s'agit d'une bibliothèque de définitions comportementales, un fichier par classe de client StyloBot raisons à proposM SK2 Les signatures y ont été générées par un modèle (ministral-3:3b, par le répertoireM SK1s README) données des prompts qui décrivent une famille de clients battant un ensemble de points finals , et que la même surface est ouverte à un auteur humainMNK4 Rédigez un BDF pour une nouvelle famille de scrapers et vous avez une définition comportementale MNK5 un scénario de régression MGK6 et un chargement MMK7 entrée d'essai dans un seul fichier
Une forme de reproduction réduite- descendue vit sous test-suites/{bots,humans,adversarial}/*.bdf.json de conserver seulement requests[].method/path/headers/delayAfter En plus d'un soft expectedDetection. Ce sous-ensemble est ce que le rig d'intégration affiche au point final du replay , qui n'a aucune façon de synthétiser les comportements distributifs à partir d'un seul replay.
Le point final du replay passe par l'orchestre réel
Le réservoir d'intégration affiche chaque scénario pour POST /bot-detection/bdf-replay/replay, un point final qui vit dans le produit (BdfReplayEndpoints.cs), ne figure pas dans le projet d'essaiM SK1 Le placement est chargé -portant IDetectionOrchestrator de l’ID et passe par qui que ce soit l’orchestre actuellement inscrit, sous DetectionPolicy.Default. La version précédente codificait un orchestrateur spécifique et masquait les régressions dans l’alternative (Ephemeral) pathM SK3 rewiring to honour DI fixed thatMSC4
Étant donné que le point final vit dans le produit, il est gaté comme une surface de produit. BdfReplay est désactivé par défaut; lorsque activé, les appels nécessitent une validité X-BdfReplay-Api-Key le capteur et passer un par-limite de vitesse IPM SK1 pour que la voie de replay ne soit pas une passerelle de détection laissée à l'écart de la route . L'appareil authentifie avec cette clé . Le point est d'exercer la voie réelleMSC4
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
Une politique délibérée surride: le cache de verdict des signatures par- est désactivé pour la reproduction
var replayPolicy = Policies.DetectionPolicy.Default with
{
SignatureCache = Policies.DetectionPolicy.Default.SignatureCache with { Enabled = false }
};
Le cache's Passer la voie bypasse complètement le matcheur une fois qu’une signature primaire a un verdict confidentiel cachéM SK1 Dans la production, c’est exactement ce que vous voulez (il s’agit de tout Apprentissage pour devenir plus rapide); pour un rig mesurant l’exactitude de détection et le flux des signaux, il cache le comportement d’une demande par rapport à la demande qu’il essaie d’admettre sur le rig.
Les scénarios sont également isolés les uns des autres. Chaque scénario reçoit une IP synthétique unique dérivée d’un xxHash déterministe de son nom (a 192.0.x.y Adresse de la RFC 5737 TEST - Région NéTéeM SK2 ainsi que la réputation du sous-nété- n'a jamais dâ€TMinfluence entre les systà ̈mes POST /bot-detection/bdf-replay/reset-identity avant chaque scénario de couplage du cachet des empreintes digitales ; sans que ce soit le cas , scénario N hérite les scénarios d'imprintage créés et les affirmations relatives à la stabilité pour chacune des étapes du scénario deviennent ordonnées
Affirmation sur une surface non déterministe-
Le rig fait trois affirmations sur chaque scénario. Chacune est un modèle pour tester des systèmes comme celui-ci.
Décision achevée, non parM SK1décision de demande. Les scénarios de Bot affirment last.Actual.IsBot est vrai; les scénarios humains affirment que majorité de demandes classées comme humaines. Assurer, sur chaque demande individuelle, que l’essai serait lié à la trajectoire de dérive loin de l’ancrage archétypique ; relaxing to "settled at the end
// 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}");
Sondes de signalisation désignées, ne comptent pas les signauxM SK1 Le flux de signaux est étudié par clé, non par total. L'affirmation du comptement est fragile : un nouveau détecteur qui émet un nouveau signal masque la perte d'un nombre critique existant MSC3 le comptement demeure le mêmeM SK4 manquantMNK5 l'identité des clés est invisibleMRK6 Une probe par clé(s) identifie le consommateur qui rompt le message de défaillance MNK8
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");
Le message de défaillance est le test's spec. Trois mois plus tard, vous n’avez pas à vous rappeler pourquoi le signal a eu une importance.
Convergence limitée, non égalité exacteM SK1 Le matcheur métastable des empreintes digitales résoudra un vecteur bruyant pour obtenir une identité stable. La composition du vector comprend les dimensions de session (entropie de cheminementM SK2âge de la session ) qui se déplacent par demandeMSC4 afin que le pairage entre deux passeportsMNK5 puisse parfois tomber à l'extérieur de sa bande libre et être attribuéMRK6 Affirmer qu'il y a un id d'une seule empreinte digitale sur toutes les demandes serait erronéMEK7 affirmer MNK8pas de trous MEK9 et convergence jusqu'à concurrence de ceil(N/2) les empreintes digitales distinctes" est le contrat réel
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) n’est pas magique. Il encode une politiqueM SK1 la première demande attribue toujours des allocations; les demandes subséquentes devraient surtout correspondre par l’entremise de L 1 confirmer ou Passer MSC4 L’allocation occasionnelle sous une grande variance du chemin est acceptable tous les demande est une régression. La limite est suffisamment étendue pour absorber le bruit que l'adaptateur est conçu pour absorber , suffisamment étroite pour capturer le mode de défaillance où il cesse de converger en tout
Tous les trois modèles ont une propriété commune: ils affirment sur le contrat que le comportement est censé satisfaire , non pas sur les chiffres spécifiques que la mise en oeuvre actuelle produite M SK2 Lorsqu'elle change , l'essai demeure valide si le contrat reste valide MSC4 C'est ce qui fait qu'un essai non-deterministe stable
Charger: le même corps sous pression
Un fichier BDF est simplement JSON. Le rig d’intégration consomme la forme slime. Le harnais de charge consomme le formulaire statistique completM SK2 scripts/convert-bdf-to-k6-v2.csx affiche un répertoire de signatures et émet un script k6 qui re-sampleurs chaque signature's distribution par VU par iterationM SK1
Re- les échantillons accomplissent un travail réel dans cette phrase . Le script kM SK2 ne reprend pas une trace captée ; il réalise le clientProfile et timingProfile comme un générateur vivant. Chaque iteration VU choisit une signature , construit des titres de son headerCompleteness et clientHintsPresent flags, attache un jar de biscuits correspondant à son cookieMode, fetches robots.txt Si robotsConsulted est vrai, puis déduit des retards nouveaux par M SK1request de delayAfterMs.min..max et une nouvelle pause d’interruption de pauseAfterBurstMs.min..max. Deux VU utilisant la même signature émettent deux flux de demandes différents avec la même distribution statistique , qui est exactement ce que le pipeline de détection devrait reconnaître comme un de la nature de client.
// 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);
}
}
}
}
La propriété du titre: Le corpus que vous vérifiez pour la correction est le corps que vous soustrayez pour le rendement.. Il n’y a pas de passage aux essais d’intégration, mais le trafic de production ne ressemble pas à ceux des tests d’intégration. sont le générateur de trafic. Lorsqu'un client signale une famille de bottes manquantes, vous ajoutez un BDF et il se joint à la suite de régression et au test de chargementM SK2 Aucune traduction , aucune seconde source de véritéMSC4 aucun débordementMNK5
Les métriques k6 parlent la même langue que la surface BDF
| kM SK1 métrique | Ce qu'il mesure |
|---|---|
bot_scenarios / human_scenarios |
Compteurs par classe de scénario |
detection_rate |
Fraction des scénarios de la classe - pour les robots signalés à l’extrémité |
interval_ms |
InterM SK1 Tendance de l’écart entre les demandes ; vérifie le profil du moment retenu sous la charge |
sensitive_path_rate |
Fraction de demandes frappées /admin, /api, fichiers ponctuels |
burst_detected |
Les coups à la limite de fracture dérivés du profil du moment |
http_req_duration |
Histogramme normal de latence pour les seuils pM SK1p99 |
Les seuils de ces valeurs deviennent un spec exécutable pour l'enveloppe de charge:
thresholds: {
http_req_duration: ['p(95)<1000'],
http_req_failed: ['rate<0.1'],
'detection_rate': ['rate>0.3'],
},
Un réacteur qui régresse l'exactitude de détection sous la charge (le vérificateur du cache des verdicts demande qu'il n'effectue pas les voyages detection_rate. Un réacteur qui introduit une voie lente dans les voyages de contestation http_req_duration p95. Données de la même source , deux régressions capturéesM SK2
Calibration: la troisième utilisation du même fichier
À ce stade, le BDF a déjà effectué deux tâches: il a vérifié l’orchestre ' son contrat de signalisation sous replay, et généré une charge réaliste sous kM SK3 La troisième utilisation est celle que je trouve la plus intéressanteMSC4 car ici le BFD est véricité contre elle-même.
Chaque entrée de preuve est une réclamation du formulaire signal OP value, weight w. Une fois qu'une signature a été répétée, ( sous l'effet de la boucle ou k M SK2 le système a produit une distribution mesurée pour les mêmes signaux interval_ms_p95 < 200 La demande est vérifiable par rapport à la p95. mesurée cookie_count >= 2 est vérifiable par rapport au nombre de témoins que la demande a effectivement été transportée. header_count >= 8 est vérifiable par rapport aux titres qui ont atterri. M SK1Les signaux qui peuvent apparaître dans evidence sont énumérés dans le BDF v2 schéma: interval_ms_p95, interval_ms_p50, sensitive_path_rate, error_rate, burst_detected, header_count, cookie_count.)
Lorsque les mesures diffèrent de celles que l’on a prétendues, la signature est dérivée de l’étalonnage . soit elle a été sur-établie pour le système contre lequel elle avait été élaboréeM SK2 soit le système s’est déplacé sous celle‐ci. Les deux sont utilesMSC4 la première dit reMNK5générer la signature à partir de l'observationMST6 la seconde dit un réfactor a déplacé la surface de détection d’une manière dont aucun essai fonctionnel ne pourrait y parvenirMSP7
L'article 5 de la Loi sur l'immigration et le statut des réfugiés python-requests-bdf.json Le tableau ci-dessus est un petit exemple en direct de la nécessité d’une vérification. value ("burst <150ms") où le schéma requiert un numéro requestInterval Un modèle a écrit que la ligne , n’est pas rejetée par aucun essai d’unité, et qu’une seule courbe mesurée comparant les preuves réclamées contre les signaux observés fait apparaître une allégation qui n’a jamais été vérifiable en premier lieu.
Cela fait passer le BDF d'un artefact de régression à un artefact d'étalonnage. Les signatures sous bot-signatures/ LLM- ont été générés contre une version antérieure du pipeline de détecteur ; leurs allégations de preuve encodent ce que version thought distinguished each client family. Re-la calibration en cours aujourd’hui vous indique quelles revendications demeurent valides et qui sont devenues vieillues , de la même façon qu’une ancrage archétypique à laquelle rien n’a dérivé près pendant des semaines cesse d’être un précédent utileM SK3 Le corps lui-mêmeMST4auditsM ST5
Six règles pour l'essai de systèmes non déterministes
Les systèmes non-deterministes n’exigent pas de tests non-déterministes1, mais d’essais déterministes2; ils exigent différemment. a été construite ones. Les modèles qui fonctionnent pour StyloBot généralisent
- Définir l'entrée comme une distribution, non comme une traceM SK1 A
timingProfileavec min/max lacunes est un générateur ; une trace de demande capturée est un tirage d'elleM SK2 Tester contre la trace et vous tester le tirage, non la distributionMSC4 La même logique pour le profil client MNK5 mode cookies et completité des titres décrivent une populationMRK6 pas une liste de titres fixes - Exprimez le contrat sous forme de prédénominations ponctuelles. L'article 5 de la Loi sur l'immigration et le statut des réfugiés
evidencel'arrée est la chose la plus proche que le système a d'une unité-test assertionM SK1 et les prédits sont sur des signaux de distribution (interval_ms_p95 < 200), ne sont pas des valeurs ponctuellesM SK1 Les prédictions avec pondérations composent les affirmations d'égalité; don - Insérer sur la destination, non sur le chemin. Pour les systèmes dont l’état est une empreinte digitale dérivée d’un archétype antérieur, parM SK1assertions de étape couple à la mise en oeuvre; mûreMSC3afirmations de état couple au contratMNK4
- Vérifier la surface fusionnée, non les composantsM SK1 Les modèles de la classe d’échec ne peuvent pas être retenus, c’est-à-dire ceux où les composants sont corrects individuellement mais la composition laisse quelque chose tomber.
- Bound the convergence, do not fix itM SK1 Un jumelage qui résout l’entrée sonore à une identité stable attribuera occasionnellement. L’affirmation est : M SK1 demeure sous la limite ", choisie de la politique, non des chiffres observésMSC4
- Partage du format d’entrée à travers le rig, chargement , et calibration. Lorsque le scénario est un contrat comportemental exécutoire plutôt qu’un script,, le même fichier conduit un réacteur de régression, une harness perfM SK2 et une vérification d’étalonnage . Le corpus ne se divise pas
Où s'inscrit-il dans la série de sorties?
Trouver et régler une croissance sans limites bounded the memory; Apprentissage pour devenir plus rapide a fait de la détection répétitive peu coûteuse. Il s’agit du troisième volet : qui vérifie un système dont les sorties seront satisfaisantes
La méthode est un corpus. Les mêmes signatures de BDF conduit à la régression , charge M SK2 et à l'étalonnage , ainsi que l'entretien d'essais s'effondre en maintenance du corps. Une nouvelle signature est quelque chose qu'un LLM peut aider à élaborer à partir d'une description d'un attaquant
L'article 5 de la Loi sur l'immigration et le statut des réfugiés La série StyloMail accepte les mêmes questions d’évaluation dans le courriel. Utilisation de Nimble du C# examine la comparaison des modèles de décision locaux sur un corpus de courrier partagé, incluant l’étalonnage, la disponibilité des réponses et les erreurs qu’une route stratifiée peut manquer avant l’escaladeM SK2
C'est donc la réponse à "comment peut-on tester quelque chose comme le StyloBot ?" Vous ne l'êtes pas gelé . Vous définissez une classe de trafic M SK3 vous faites contrer le système réel MSC4 et vérifiez trois choses MST5 que le verdict reste convergent MSV6 que les signaux dont dépendent ses consommateurs sont toujours arrivés M SV7 et que les éléments de preuve que la définition prétend toujours correspondent aux mesures du démarrage M Sv8 L'essai n'est pas un ruban M Sav9 Il s'agit d'une boucle M sav10
Le répétiteur BDF vit à BdfReplayTests.Integration.cs. Les scénarios de replay souples sont en cours test-suites/{bots,humans,adversarial}/*.bdf.json; les signatures statistiques complètes ( avec clientProfile, timingProfile, evidence) sont sous bot-signatures/*.json. Le convertisseur kM SK1 est scripts/convert-bdf-to-k6-v2.csx. Le point final de replay que les deux rigs utilisent est BdfReplayEndpoints.cs. Le contrat de signalisation de ces essais est documenté dans docs/architecture/signal-contracts.md. All source at github.comM SK1scottgal/stylobot. moteur en direct , tableaux de bord M SK2 et contrôles commerciaux à stylobot.net.