Utkarsh Bahuguna, reliability engineer and adversarial tester, Bengaluru
Use the left and right arrow keys to move through this carousel, or the previous and next buttons below it. You can also drag it sideways.
Utkarsh Bahuguna, Bengaluru, India

A computer science undergraduate at BITS Pilani working on systems that have to be right rather than merely finished. Order books, kernels, CRDTs, inference engines. In every case the interesting half of the work is the machinery built to prove the first half wrong.

- reliability engineer
- adversarial tester
- open source contributor

Upcoming Next
Live work, not
shipped work. Open
in front of me now.
tip!Click on the image to explore
DivergenceIn progressReasoning-model behaviour · ICLR 2027One prompt, one set of weights, sampled traces that reach incompatible conclusions.
Build, Break Prove
I build the system first, then the thing whose only job is to prove it wrong. The harness is not scaffolding around the deliverable, it is the deliverable: an engine nobody has tried to falsify is not one anybody should trust. The claim is worth exactly what the adversary failed to break.
Merged contributions
Contribution indexMicrosoftNVIDIAHugging FaceCNCFGCCResearch
Published work, and what is currently open in front of me.
The standard way to make a language model more reliable is to sample several reasoning traces and take the most common answer. On hard science questions, that makes it worse more often than it helps. Across 198 GPQA Diamond problems, majority voting reduced accuracy on 56.6% of problems for one model and 65.7% for another. The obvious response is to detect the bad cases and route around them, so I tested three cheap confidence signals that could do that. All three fail, each for a different reason, and one of those failures I still cannot explain. Every hypothesis was registered and git-tagged before the confirmatory data was touched. Version two revised the mechanism claim in my own accepted paper rather than defending it.
The follow-up
In progress
The unexplained failure above is what I am working on now. The question is whether agreement between samples measures evidence at all, or just measures how strongly the model already believed the answer before it reasoned. To test it I needed reasoning-model data that the published study could not afford to buy, so I generated it myself: 12,672 samples across 198 problems, 82.7 million tokens, twenty-three hours on a consumer laptop GPU. The hypotheses and kill conditions are written down and tagged before anything is run, so the result is whatever it is. No conclusion yet, and possibly no paper. That is the arrangement.
Same seed, same crash



A bug that only appears sometimes has not been found; it has been noticed. Every system here is built so that a failure carries a seed, and the seed replays the failure on any machine, in any order, as many times as you want.
That is the whole discipline: make the machine deterministic enough that its bugs can be handed to somebody else. contribution index.
What broke
tip!Hover, focus or swipe to read
The bug that only existed in production
A sync loop used its timer handle as its stopped flag. A stop left the handle holding a fired timer’s id, so the resume check never fired and any backgrounded tab died permanently. The local test passed because it never backgrounded the tab.
A delete that matched more than it was given
Removing seeds by harm category matched substrings of the stored JSON rather than whole elements, so a category name that happened to appear inside an unrelated entry took that entry with it. The default was already the exact mode, which is precisely when a caller expects neither.
A trace that rendered as nothing
A span link was encoded as a causal reference, then read back as a parent. A root linking to its own descendant became a two-span cycle. The UI rendered a fully chromed page with no spans, no error, no spinner, and a silent console.
A crash three layers below where it crashed
let x = ::;segfaulted in type checking. The cause was in the parser: it returned an error sentinel with no diagnostic, and the sentinel was a zero-segment path indistinguishable from a real one, so it flowed silently through name resolution.
Open source
Merged!
68 merged · 12 repositories · 11 organisations
Ordered by the name
you would recognise,
not by the date.
tip!Expand an organisation for its pull requests
- Upstream GCCThe gccrs fix for types used as generic arguments was sent to gcc-patches as part of a 77 patch sync and committed to GCC master, with authorship preserved. It is in the compiler.
- Bugs I foundThirty-eight of these fix crashes and defects I found and filed myself rather than picking up an assigned ticket: thirty-two in PyRIT, five in gccrs, one in Jaeger. One of them was a bug in my own already merged code.
PR #1960issue I openedBuilt the CodeAttack jailbreak converter, encoding an objective into a code-completion template across five language variants.
The CodeAttack technique from Ren et al., across five language variants. Two and a half months and 43 review comments, with the tests growing from 31 to 88. I argued for a separate attack class; the maintainer decided otherwise, so it landed as a converter.
Open PR #1960 on Microsoft PyRITPR #2721issue I openedAdded the code_attack_framed technique, a system-framed variant of the CodeAttack converter, leaving the paper-aligned original untouched.
The paper defines no system prompt, so this framing is a PyRIT-specific condition rather than part of the method: opt-in catalog only, default technique set untouched. The generic mechanism the issue asked about already existed, so no new abstraction was added.
Open PR #2721 on Microsoft PyRITPR #2822issue I openedFixed TAP and PAIR skipping their first real turn whenever a conversation had been prepended.
Prepended messages counted towards the turn count, so the first real turn was treated as already taken: the adversarial system prompt was never set and a required message was dropped. The node now tracks how many it persisted. Five end-to-end cases fail on main.
Open PR #2822 on Microsoft PyRITPR #2816issue I openedStopped MultiPromptSendingAttack mutating the caller’s own messages, and carried harm categories through as the base class already did.
The attack sent the caller’s message objects rather than copies, so reusing them across runs, or broadcasting through AttackExecutor, modified the caller’s own data and failed on a unique constraint. It now sends a duplicate. Three tests, all failing on main.
Open PR #2816 on Microsoft PyRITPR #2811issue I openedMade seed removal list filters match whole elements instead of JSON substrings, which had been deleting more than was asked.
Under the default exact mode the list filters matched substrings of the stored JSON, so a value could match inside an unrelated element and take it too. They now use the whole-element helper already used elsewhere, on both SQLite and Azure SQL.
Open PR #2811 on Microsoft PyRITPR #2810issue I openedFixed the JBB-Behaviors loader seeding every run with a short label instead of the actual request.
The loader read Behavior, a short label, where it should have read Goal, the request itself, so every seed was a stub. The test mocks did not match the real schema and were hiding it. Checked against the live dataset: 100 full requests.
Open PR #2810 on Microsoft PyRITPR #2814issue I openedStopped the HTTP targets storing the printed form of a bytes object, and taught the JSON key parser about digits and hyphens.
Both targets stored the printed form of the raw bytes, so a saved response was a bytes repr and any non-ASCII body came back mangled. They now store decoded text. The JSON key parser also rejected digits and hyphens, leaving output2 and generated-text unaddressable.
Open PR #2814 on Microsoft PyRITPR #2812issue I openedMade the scale scorers retry an out-of-range judge score through the existing JSON retry instead of crashing on it.
A judge answering outside the scale, or with something non-numeric, took the scorer down. An out-of-range value now raises the same exception the existing JSON retry already handles. Scorer identifiers are untouched, so existing evaluation hashes still match.
Open PR #2812 on Microsoft PyRITPR #2687Consolidated two copies of the async image download path behind one shared helper, with no public API change.
Two image converters each carried their own copy of the same download. It moved behind a shared helper while the protected hook stayed on both classes, so subclasses that override or patch it keep working. Error handling and cancellation were preserved rather than rewritten.
Open PR #2687 on Microsoft PyRITPR #2818Kept the raw HarmBench behaviour in metadata, and gave the context separator a name instead of a bare literal.
While this was open the main fix landed in a maintainer’s own pull request, so what remained was two review points: the separator became a named constant, and every row keeps its raw behaviour in metadata, which is now the only place that text survives.
Open PR #2818 on Microsoft PyRITPR #2820issue I openedMoved the scenario success calculation into one place, so the SDK, the backend and the reports stop deriving it three ways.
The same statistic was computed independently in three layers, which is how they came to disagree. Plan lookup, execution-unit identity, latest-attempt selection, denominators and rounding now live in one module and everything else presents its result, with errors and retries reported separately from the effective counts.
Open PR #2820 on Microsoft PyRITPR #2897issue I openedMade the general self-ask scorers keep the configured category rather than failing when the judge returned one as well.
With their default handlers both scorers failed outright when the configuration and the judge response each carried a category. The configured one now wins, and the judge’s is used only when none was configured. That deliberately replaces the documented response-first contract, so the conflict behaviour is a named policy rather than a quiet default.
Open PR #2897 on Microsoft PyRITPR #2895issue I openedStopped an inverted or combined score carrying a float that described a verdict it no longer had.
The inverter kept the wrapped threshold float, which describes the uninverted verdict, so a normalised score could contradict the verdict printed beside it. The float is dropped when a score is inverted or when several are combined, and kept for a single score where it still matches.
Open PR #2895 on Microsoft PyRITPR #3017issue I openedDeduplicated three dataset loaders that were returning the same prompt many times over.
Each loader now keeps one seed per prompt and merges the harm categories from every row carrying it, so a filter still only admits the categories of rows that pass. On the real data BeaverTails falls from 166,382 seeds to 14,402, PKU-SafeRLHF from 73,907 to 38,641 and Aegis from 19,093 to 13,246.
Open PR #3017 on Microsoft PyRITPR #3019issue I openedStripped the instruction template out of ALERT prompts so the seed is the prompt, and carried the attack type into metadata.
The loader shipped each row with its Instruction and Response scaffolding attached, so every seed carried a template the target was never meant to see. Rows without the template are left alone, and the attack type now reaches metadata when the row has one.
Open PR #3019 on Microsoft PyRITPR #3021issue I openedStopped two scenarios silently dropping the technique converters a caller had asked for.
Doctor and AdversarialBenchmark never passed technique_converters to the matrix builder, so they applied nothing and said nothing. They pass them now, and the scenarios that genuinely cannot apply them declare it instead of ignoring the argument.
Open PR #3021 on Microsoft PyRITPR #3080issue I openedKept Responses API web search calls replayable, instead of storing only enough of one to break the next turn.
Parsing kept a call’s type and id and discarded its status and action, so replaying the conversation sent back an item the API would not accept. The whole item is stored now, and rows written before the fix still replay.
Open PR #3080 on Microsoft PyRITPR #3082issue I openedMade the runner reject dataset limits that the chosen scenario would have quietly ignored.
Exploitation scenarios run a fixed dataset, so a dataset name, filter or size limit passed alongside one was accepted and then discarded. Configuration resolution now checks what the scenario takes and says plainly that the dataset is fixed.
Open PR #3082 on Microsoft PyRITPR #3084issue I openedCorrected the Multilingual run size estimate, which ignored the language axis and came out three and a half times low.
The scenario multiplies each seed group across languages, and the estimate used the base formula, which counts none of that. It now mirrors what the scenario builds, so the number shown before a run matches the run.
Open PR #3084 on Microsoft PyRITPR #3086issue I openedMade a Psychosocial dataset subset narrow the run, rather than leaving sub-harms whose data had not been selected.
Picking a subset of datasets still ran every sub-harm, including the ones whose dataset was absent. A single selector now gates validation, seed resolution, the size estimate and the attack build, so the four cannot disagree.
Open PR #3086 on Microsoft PyRITPR #3090issue I openedMade the UTCDateTime column store aware datetimes as UTC, so filtering by time stopped depending on the caller’s zone.
Naive values were read as UTC and aware ones stored as written, so a timestamp from any other zone was compared against UTC rows and matched the wrong ones. Conversion happens on the way in now, and the schema is unchanged.
Open PR #3090 on Microsoft PyRITPR #3092issue I openedIncluded the extra body parameters in chat target identifiers, so two differently configured targets stop sharing one identity.
The Responses target already did this. On the chat and LiteLLM targets the extra body was left out, and since the audio configuration is merged into it, two different voices were recorded as the same target.
Open PR #3092 on Microsoft PyRITPR #3094issue I openedGave adaptive technique selection the run id on a fresh run, not only on a resumed one.
The id existed only once a result had been stored, so on a first run the selector had nothing to key its history to. The context now carries the id the result will take, chosen before the attacks are built.
Open PR #3094 on Microsoft PyRITPR #3097issue I openedStamped the attack identity on error results, which until then came back anonymous.
The error handler is a separate object with no view of the strategy, so a failed attack produced a result that could not be traced back to what produced it. The context now carries a small builder the handler stamps from.
Open PR #3097 on Microsoft PyRITPR #3100issue I openedMade the Prompt Shield scorer read the converted prompt, as every other scorer does, rather than the original.
One line, with a large consequence: any attack carrying a converter was scored on text the target never saw. Unconverted prompts give the same value either way, which is why this went unnoticed.
Open PR #3100 on Microsoft PyRITPR #3102issue I openedKept the original float value readable at the top level of a fallback score, where callers look for it.
The composite scorer wrote the selected child’s value only under a primary or fallback prefix, so anything reading the standard key off the result got nothing. The prefixed copies stay, so nothing already working changed.
Open PR #3102 on Microsoft PyRITPR #3104issue I openedMade TAP branch on the objective score rather than on whichever auxiliary scorer answered first.
The node took the first score it found, so adding any second scorer steered the tree search by the wrong signal. It now matches on the objective scorer’s identity, and reports the score as unavailable when there is none.
Open PR #3104 on Microsoft PyRITPR #3107issue I openedHandled grayscale and palette images in the rotation and saturation converters, which assumed every input was RGB.
The fill colour on a rotation is RGBA and saturation works in RGB, so a palette PNG or a grayscale photograph raised instead of converting. Inputs are promoted first now, to RGBA where they carry transparency and RGB otherwise.
Open PR #3107 on Microsoft PyRITPR #3109issue I openedKept int32 and uint8 WAV input intact through the audio frequency converter.
The converter assumed signed 16-bit samples, so other integer formats came out as noise. It shifts around 128 for unsigned input, keeps the input dtype and clips integer output to its range, the approach an earlier fix took for volume and echo.
Open PR #3109 on Microsoft PyRITPR #3111issue I openedCarried the memory labels onto the sequential attack result, which was the one attack dropping them.
Every other attack passes the context labels through, and so does this attack’s own error path. The completed result did not, so a successful sequential run could not be filtered by the labels it was launched with.
Open PR #3111 on Microsoft PyRITPR #3136issue I openedMade the PDF converter apply the font colour it was given, having accepted and discarded it until then.
Generated PDFs were always black. The colour defaults to unset now and the generator fills with it when there is one, so anyone who never passed a colour sees exactly what they saw before.
Open PR #3136 on Microsoft PyRITPR #3169issue I openedRecorded an unscored attempt as undetermined rather than as a failure.
With an objective scorer configured, a response in hand and no score returned, the attack was filed as a failure, which is a claim the run cannot support. The outcome now says the scorer returned no score.
Open PR #3169 on Microsoft PyRITPR #3170issue I openedMade the analytics count an attack with no converters as having none, instead of as missing data.
Identifiers omit an empty converter list, so a real run with no converters had no list, no edges and a null array, which the query read as unknown. The source falls back to an empty list now and those runs are counted.
Open PR #3170 on Microsoft PyRITPR #3200issue I openedGave the regex, package hallucination and aggregator scorers identities that include the configuration deciding their results.
Several scorer identities left out the configuration, so two differently configured scorers hashed alike and could pick up each other’s metrics. A regex scorer now folds in a digest of its patterns when they differ from the class default.
Open PR #3200 on Microsoft PyRITPR #3078issue I openedStopped the Copilot and A2A targets silently losing conversation history between turns.
Copilot opened a fresh session for a conversation that already had turns and sent only the last message. A2A dropped its context whenever the agent returned none. Both now carry their own id or fail loudly, and repeat-send checks that a target can replay before copying a conversation.
Open PR #3078 on Microsoft PyRITPR #3171issue I openedGave targets with no model name their own analytics key, instead of collapsing every one of them into a single unlabelled group.
Analytics keyed objective targets by model name, temperature and top_p, so the HTTP and Gandalf targets, which have no model name, all hashed alike. They fall back to a content hash with a readable label now, and a migration reruns the backfill for databases written under the old keys.
Open PR #3171 on Microsoft PyRIT
PR #1308Stopped the benchmark runner handing child processes the parent’s own script path, which broke every way of starting it but one.
The task runner re-invoked the entry point by the path it had been given, so starting tritonbench by absolute path, as a relative path, or from a wrapper script made every child benchmark process fail. Only the bare invocation worked.
Open PR #1308 on Meta PyTorch tritonbench
PR #1842Added a generic suppressed_params mechanism to the Bedrock generator, fixing scans that Claude 4.x rejected outright.
BedrockGenerator sent both temperature and topP, which Claude 4.x rejects, breaking scans on those models. The maintainer invited a generic mechanism rather than the narrow fix, so it became a parameter map with suppression checks. A competing narrower pull request was closed for this one.
Open PR #1842 on NVIDIA garak
PR #742Replaced string matching with real URL parsing in the local-address check, closing an SSRF hole.
The check decided whether a target was local by matching substrings in the URL, which is not a decision string matching can make. It now parses the URL and uses Python’s ipaddress module, with 15 tests covering what the old check got wrong.
Open PR #742 on Hugging Face OpenEnv
PR #4053Classified GenAI tool spans against the OpenTelemetry semantic conventions, and stopped a bare call id counting as one.
This started as a thousand-line GenAI Observability Mode for CNCF LFX. The maintainer rejected it as too large to review and it stalled. I rewrote it as a three-file, plus-76 minus-4 change, and that is what merged.
Open PR #4053 on CNCF jaeger-uiPR #4271issue I openedFixed the trace view re-deriving GenAI detection by hand instead of calling the shared detector, silently bypassing it.
A bug in my own merged code. The trace page scanned raw attributes itself instead of calling the canonical detector, so improvements to that detector were skipped on the auto-activation path. Four-line fix, merged about two and a half hours after I reported it.
Open PR #4271 on CNCF jaeger-uiPR #4313Added image and audio previews to the GenAI view, so a multimodal prompt can be inspected without copying its URL into another tab.
Markdown and pretty-printed JSON had already landed; rendering referenced media had not, so a prompt whose content was an image link showed as link text. A remote link is never fetched until the reader asks, and that choice is never persisted.
Open PR #4313 on CNCF jaeger-uiPR #4421Corrected five wire-format claims in RFC 0002 against a live v2.19.0 server, including a field name the document had wrong.
Found by probing a running instance and diffing its responses against the document rather than by reading the code: four claims that do not match what the server returns, plus one behaviour it never documented. The operations endpoint returns spanKind, not span_kind.
Open PR #4421 on CNCF jaeger-ui
PR #4731Marked types used only as generic arguments as live, fixing a dead-code lint that discarded them.
The dead-code pass never marked a type live when it appeared only as a generic argument. Three existing tests asserted that wrong behaviour, so I corrected the tests. This is the one that reached upstream GCC, committed to master with authorship preserved.
Open PR #4731 on GCC gccrsPR #4728Emitted E0259 and E0260 for duplicate extern crate names, matching rustc’s diagnostics.
The most involved review here. My first design stored extern-crate status on the resolver rib; the reviewer asked for a mapping keyed on node id instead. Rebuilding it surfaced an ordering difference: the duplicate check runs inside the insert, so status has to be recorded before it.
Open PR #4728 on GCC gccrsPR #4799issue I openedReported an error on an empty path expression instead of segfaulting the compiler.
A crash I found myself: `let x = ::;` segfaulted in type checking, three layers below the parser that returned an error sentinel with no diagnostic. The sentinel was a zero-segment path, indistinguishable from a legitimate empty one the whole way down.
Open PR #4799 on GCC gccrsPR #4929Stopped an internal compiler error on Fn, FnMut and FnOnce bounds, which produce a path segment the type parameter builder did not handle.
Fn, FnMut and FnOnce bounds produce a segment the type parameter builder treated as impossible, so the compiler aborted rather than reporting anything at all. Verified by hand across six spellings, with the full suite at 11,627 passes.
Open PR #4929 on GCC gccrsPR #4930Made constant evaluation diagnose unsigned arithmetic overflow, which the existing check was structurally unable to see.
GCC only sets its overflow flag for signed operations, because unsigned wraparound is defined behaviour in C, so the evaluator was reading a flag that would never be set and unsigned overflow in a constant compiled silently. The check now runs before the operands are folded.
Open PR #4930 on GCC gccrsPR #4959issue I openedImplemented match arm guards, which were parsed and then silently ignored, so a guarded arm matched on its pattern alone.
Guards were never type checked or compiled, so a guarded arm was taken whenever its pattern matched, whatever the condition said. A guard is now checked as a bool and falls through when false, and the unsafe and const checkers see guards too, so one cannot call an unsafe function from safe code.
Open PR #4959 on GCC gccrsPR #4958issue I openedMade call arguments evaluate left to right on x86, where the gimplifier had been following the target push order.
Arguments were evaluated right to left because the gimplifier follows the order the target pushes them, which is not the order Rust specifies. The callee and the earlier arguments are now saved in order before the call, so side effects happen in the order the source wrote them.
Open PR #4958 on GCC gccrsPR #4953Caught type parameter defaults naming a later parameter, which the existing check let through.
A default can only refer to parameters declared before it, but only a default naming its own parameter was caught, so a struct whose first default named a later one was accepted. It reports E0128 for those too now, leaving a trait’s implicit Self alone because that is always in scope.
Open PR #4953 on GCC gccrsPR #4974issue I openedFixed an internal compiler error on patterns nested inside a constructor with several fields.
The match checker popped a constructor’s sub-patterns onto the back of the row while specialisation put their types at the front of the columns. With more than one field the two orders disagreed and the compiler crashed.
Open PR #4974 on GCC gccrsPR #4979issue I openedFixed an internal compiler error on a rest pattern inside an enum tuple variant.
The rest pattern code could only reach the fields of a struct, so a pattern like E::A(x, ..) tripped an assert in the backend. It reads the variant’s fields through the payload union now, as the same pattern without the rest already did, and a test marked as a known crash compiles.
Open PR #4979 on GCC gccrsPR #4998Made an inline const block parse at the start of a statement, the way an unsafe block already does.
The first of three gaps in inline const support that I filed. Const blocks parsed where an expression was expected but not in statement position. The other two, compile-time evaluation and locals leaking into scope, are open.
Open PR #4998 on GCC gccrs
PR #2777Modernised the type hints across the utils module, part of the project-wide migration off legacy typing constructs.
Part of the tracking issue migrating legacy typing constructs to built-in generics across the model-compression toolkit. A small diff, and a net-negative line count, which is the shape maintainers like.
Open PR #2777 on vLLM llm-compressorPR #2779Modernised the type hints across the modeling module, same migration.
The companion to the utils change, under the same tracking issue. Also net-negative.
Open PR #2779 on vLLM llm-compressor
PR #23276Stopped the Inspector crashing the moment a model output was not a tensor, on both the printed table and the plot.
The metric helpers return None for a non-tensor output, and the print loop then formatted it, so comparing results died on a TypeError rather than reporting what it could. None now prints as not applicable and plots as zero, so the bar chart still renders, and the CLI no longer calls the comparison at all when there is no reference output to compare against.
Open PR #23276 on PyTorch executorchPR #23400Fixed the Inspector plot crashing on a non-finite metric, which is exactly what a perfect match produces.
A follow-up to the earlier Inspector fix. Signal-to-noise is infinite when the output matches the reference exactly, and matplotlib refuses an axis limit that is not finite, so the plot failed precisely in the best case. Non-finite values now plot as zero while the label still shows the real value.
Open PR #23400 on PyTorch executorchPR #4965Split the run-tags environment variable before handing it to wandb, which had been reading it one character at a time.
The variable went into wandb.init as a plain string, and wandb calls tuple() on it, so setting it to exp1,baseline produced a tag per character: e, x, p, 1, comma, b, and so on. It is now split on commas with empty entries dropped, and unset still means no tags. The new test stubs wandb and fails on main.
Open PR #4965 on PyTorch torchtitanPR #5042Added range checks to the learning rate scheduler config, which accepted values that quietly did the wrong thing.
A negative minimum factor drove the learning rate below zero near the end of decay, measured at about minus a third of the base over ten steps, and a negative decay ratio simply switched decay off. Both are now rejected at construction, following the pattern of the checks that landed before it.
Open PR #5042 on PyTorch torchtitanPR #5041Fixed a rollout filter that recorded everything when it was asked to record nothing.
The top end was sliced with a negative index, and at zero that is the whole list rather than none of it, so turning recording down turned it all the way up. It is sliced by position now, and a negative setting is rejected instead of silently duplicating rollouts.
Open PR #5041 on PyTorch torchtitanPR #5040Fixed asset download matching, which lowercased the pattern but not the filename, so any uppercase pattern matched nothing.
The script’s own help text offers README.md as the example, and that downloaded nothing, as did LICENSE. The basename is lowercased before the comparison now. Files are still written under their real names; only the matching changed.
Open PR #5040 on PyTorch torchtitanPR #5288Made the comparison scripts resolve commits before checking anything out, so a relative reference still means what it meant at the start.
Both scripts checked out the baseline before reading the test commit, so anything relative to the current checkout, a bare dot or HEAD~1, resolved against the baseline instead and the run silently compared the wrong pair.
Open PR #5288 on PyTorch torchtitanPR #5289Gave each child of a concatenated dataset its own seed, so repeating a dataset stopped drawing identical samples from every copy.
The mixing config already offsets each child’s seed by its index, deliberately. Concatenation built every child with the same iteration policy and therefore the same seed, which is exactly wrong for the repeat-a-dataset case.
Open PR #5289 on PyTorch torchtitan
PR #1016Made a sandbox manager test repeatable, and stopped a real claim failure surfacing as a nil pointer panic.
The test panicked whenever it ran more than once: a fixed sandbox UID leaked a resource version expectation into the next run, and retry.OnError then turned the resulting deadline error into nil, so the assertion passed and the test dereferenced a nil sandbox.
Open PR #1016 on OpenKruise agents
PR #200Made the forward-node-ip setting a per-gateway annotation instead of one flag for the whole cluster.
A roadmap item for configuring this per node pool. The tunnel engine already decided it per gateway, so an annotation on the Gateway overrides the global flag and anything unrecognised falls back to it. Every agent reads the same annotation, so both ends of a tunnel agree on whether that gateway’s node IPs are routed.
Open PR #200 on OpenYurt raven
PR #53Added the Ways to Get Involved section to the community page.
Content and structure work on the AI Village site, the DEF CON AI security community. Web content rather than tooling, and worth listing as such.
Open PR #53 on AI Village aiv_websitePR #54Added sponsorship details to the sponsors page.
Companion to the community page change, on the same site.
Open PR #54 on AI Village aiv_website








