about
A little context behind the work.
I like software that is easy to use, hard to break, and still understandable after the first rush of shipping is over.
story
I study computer engineering, but most of my learning has come from projects that stopped being simple the moment someone else had to depend on them. I like that turn: when a neat idea becomes a tired student trying to find the right paper, a protocol mismatch that needs a replayable fixture, or a small kernel fix that has to survive people who know the subsystem better than I do.
The work I care about has to be clear at the surface and honest underneath. A tool should feel direct to the person using it, but the internals should leave a trail too: named failure modes, careful boundaries, and decisions that still make sense after the first rush of shipping is gone.
That is why upstream work matters to me. It removes some of the private mythology around a patch: the reasoning either survives public review, or it shows me exactly where it has to get sharper.
- work I choose Product software, protocol tooling, and verification-heavy systems where correctness changes the result.
- working style Start with the real use case, name the failure modes, and keep the implementation small enough to inspect.
- looking for Developer infrastructure, product systems, and correctness-heavy software with real users and real constraints.
principles
- Name the failure mode before decorating the solution.
- If a system asks for trust, make the boundary inspectable.
- Prefer small, reviewable changes over clever machinery.
- Choose work that teaches judgment, not just speed.
What I want to work on
- Systems where the engineering has to be solid because people actually rely on it.
- Tools that get out of the way and make a hard workflow feel simple.
- Environments that force me to understand the layers beneath the code I write.
recognition
Recognition belongs here only when it points back to the work: a real problem, a constrained build, and enough public evidence to inspect what happened.
PromptWars × AbhiyantriX / 2026
Top-ranked coding-round submission among 332 participants; advanced to the pitching round.
I built Orvio, a smart event management platform, for PromptWars × AbhiyantriX. My submission scored 96.98 and ranked 1st among 332 participants in the coding round, earning advancement to the pitching round. Evaluation covered code quality, security, efficiency, testing, accessibility, and alignment with the problem statement.
- View coding-round leaderboard screenshot ↗ August 29, 2026
- Official PromptWars × AbhiyantriX event page August 29, 2026
- Orvio source repository August 2026
- result 1st of 332, coding round
- score 96.98
- next round Advanced to the pitching round
- project Orvio — smart event management platform
OrchidHackX / 2026
1st place in the Cybersecurity Track with ShallowFake.
As team Secure Bytes, we built ShallowFake, a pre-publication privacy layer that adds imperceptible adversarial noise to face photos so they remain visually unchanged to people while disrupting deepfake pipelines. The prototype combines a FastAPI protection service with a React workflow, quality reporting, metadata stripping, rate limiting, and a no-retention policy for original images.
- Official OrchidHackX Cybersecurity Track winner announcement July 14, 2026
- ShallowFake submission on Devpost July 2026
- OrchidHackX 2026 event page July 10-12, 2026
- result 1st place, Cybersecurity Track
- project ShallowFake
- team Secure Bytes
- scope Pre-publication face-photo protection against deepfake pipelines
HackForUHC / 2026
1st place at HackForUHC 2026. Continued as NIYAM and presented at an AeHIN international webinar.
As team CLAIM∅, we won 1st place at HackForUHC 2026 (June 18-19). We were invited to present at the 10th anniversary openIMIS Community Meeting in Kathmandu (June 23-25), and after that the project kept going at the Health Informatics Lab at KU under Prof. Rabindra Bista. It turned into NIYAM: a claim validation layer that sits in front of openIMIS and catches bad claims before they reach a reviewer. On August 27, the team — Aman Karn, Laxman Acharya, and I — presented the system architecture and a live demo at the AeHIN Hour webinar.
- Certificate June 18-19, 2026
- HackForUHC 2026 event listing June 18-19, 2026
- Health Informatics Lab event announcement June 2026
- openIMIS Community Meeting 2026 participation certificate June 23-25, 2026
- AeHIN Hour webinar: NIYAM — Claim Integrity Layer for openIMIS August 27, 2026
- result 1st place, overall hackathon
- team CLAIM∅
- continued as NIYAM — claim validation layer for openIMIS
- presented AeHIN Hour webinar, August 27, 2026
JunctionX Kathmandu / 2026
JunctionX Kathmandu 2026 with Team Pikachu.
As team Pikachu, we worked on a constrained build around a local energy problem at JunctionX Kathmandu 2026. The result opened the next round of work in Finland, but what belongs here just as much is the support around it: the mentors, organizers, teammates, and KU community who made the work possible.
- JunctionX Kathmandu event page May 29-31, 2026
- Overall winner certificate Issued June 1, 2026
- Hydropower track winner certificate Issued June 1, 2026
- result Overall Winner + Hydropower & Sustainable Energy Track Winner
- team Pikachu
- next Golden Ticket to the global Junction stage in Finland
Google TMT Hackathon / 2026
1st place in the File Translation Tool Track with SANAD.
As team SPAN, a two-person team, we built SANAD for the Google TMT Hackathon 2026 under KU ILPRL's Google-supported Trilingual Machine Translation project. The product turns public-service documents into a reviewable translation workflow with protected-entity checks, scoped memory, risk flags, human review, and export-ready output.
- Official Google TMT Hackathon 2026 results May 8, 2026
- SANAD source repository May 2026
- Google TMT project context KU ILPRL
- result Winner, File Translation Tool Track
- team SPAN, two-person team
- scope English / Nepali / Tamang public-service document translation
upstream
The contributions below are small on purpose: concrete enough to inspect, strict enough to review, and real enough to affect behavior that other people depend on.
Linux / Kernel / 2026
Linux kernel contributions across Bluetooth memory safety, DRM/PCI controller fixes, KUnit, and core library paths.
The work spans 14 commits verified in mainline Linux: Bluetooth memory-safety work, an OpenVPN keepalive peer-lifetime fix, AMD XDNA debug BO sync, PowerVR userspace array stride handling, PCI/DWC/Meson teardown and error-path fixes, KUnit tooling fixes, cmdline next_arg() coverage, printf IPv6 tests, seq_buf export/KUnit coverage, and IIO DMA and PowerVR fixes tagged for stable. Related accepted upstream work includes a FUSE/io-uring request-lifetime race report.
- fix Bluetooth SSP passkey-handler UAF later tracked as CVE-2026-46056 April 13, 2026
- add Meson PCIe remove callback for host-bridge deinit and PHY power-off June 9, 2026
- guard DesignWare RAS DES debugfs teardown when state was not allocated June 9, 2026
- propagate devm_add_action_or_reset() failure in Meson PCIe clock setup June 9, 2026
- use caller client for AMD XDNA debug BO sync, later tracked as CVE-2026-72090 June 16, 2026
- fix PowerVR userspace array stride handling in pvr_set_uobj_array(), tagged for stable, later tracked as CVE-2026-68262 July 2, 2026
- reported FUSE/io-uring commit_fetch error-path race fixed in mainline June 15, 2026
- ovpn: hold peer before scheduling keepalive work July 20, 2026
- copy caller args in run_kernel to prevent mutation February 26, 2026
- skip stty when stdin is not a tty February 27, 2026
- add IPv6 address format tests for printf coverage April 2026
- extend cmdline KUnit with next_arg() regression tests March 2026
- export seq_buf_putmem_hex() April 8, 2026
- add seq_buf KUnit coverage May 22, 2026
- zero-initialize NXP SAR ADC DMA config, tagged for stable consideration May 15, 2026
- scope Bluetooth memory safety / AMD XDNA debug BO sync / PowerVR userspace array stride handling / PCI controller teardown and error paths / OpenVPN peer lifetime / FUSE io_uring request lifetime / KUnit tooling / cmdline and seq_buf tests / printf IPv6 coverage / IIO DMA fix
- through Maintainer-reviewed upstream workflow
LLVM / AArch64 backend / 2026
Fixed-point SCVTF/UCVTF scale operand validation in LLVM.
Merged in llvm/llvm-project#213490, this gives the fixed-point SCVTF/UCVTF scale operands the ParserMatchClass that fixedpoint_i32/i64 already carried. Without it, a symbolic scale could reach the encoder and hit its MO.isImm() assertion, and an out-of-range scale could alias a valid encoding instead of being rejected. The operands now use Imm1_32Operand and Imm1_64Operand, and the MC diagnostics test covers both integer source widths and the symbolic-scale case.
- pull request #213490: validate fixed-point SCVTF/UCVTF scale operands August 10, 2026
- merged commit in llvm/llvm-project main August 10, 2026
- issue #185358: assembler crash on symbolic scvtf/ucvtf immediates scvtf/ucvtf half addressed
- status Merged into llvm/llvm-project, approved by two AArch64 backend reviewers
- scope TableGen operand definitions / AArch64 assembly parsing / MC layer diagnostics
- evidence Diagnostics coverage for both integer source widths and symbolic scales
ROOT / CERN scientific computing / 2026
TFormula Hessian result sizing in ROOT.
Merged in root-project/root#22877, this fix makes TFormula::HessianPar() validate storage against the full fNpar × fNpar Hessian size instead of accepting a buffer large enough for only fNpar entries. The existing ResultUpsize regression now covers the two-parameter case that exposed the mismatch.
- pull request #22877: fix TFormula Hessian result sizing July 28, 2026
- merged commit in root-project/root July 28, 2026
- status Merged into root-project/root
- scope C++ / TFormula / automatic differentiation / Hessian storage
- evidence Targeted regression coverage plus maintainer approval
Indico / CERN event platform / 2026
Webpack manifest thread-safety fix in Indico.
Merged in indico/indico#7675, this fix stops a half-initialized manifest from being published to the thread-shared cache. Under uWSGI with more than one thread and a customization directory configured, a second request could read the manifest after __custom.css was added but before __custom.js, and fail until the worker warmed up. The manifest is now cached only once it is fully populated, and the regression test pins the interleaving across two threads so the race reproduces deterministically instead of by chance.
- pull request #7675: cache the manifest only after custom assets are added August 4, 2026
- merged commit in indico/indico master August 4, 2026
- issue #7530: intermittent ManifestKeyNotFoundError under concurrent requests Reported May 19, 2026
- status Merged into indico/indico, credited in the release changelog
- scope Python / shared cache thread safety / webpack manifest loading
- evidence Deterministic two-thread regression test plus maintainer review
- credit Fix implemented and tested from a maintainer-triaged report
Cilium Tetragon / eBPF / 2026
Kprobe return-path validation and schema clarification in Tetragon.
Merged in cilium/tetragon#4601, this series rejects unsupported returnArgAction values on kprobe return paths, adds regression coverage, and carries the clarified semantics through CRDs, docs, vendored schema copies, and examples. An earlier Helm template cleanup also merged in #4631.
- pull request #4601: returnArgAction validation, docs, and CRD sync April 29, 2026
- pull request #4631: Helm template extension cleanup February 24, 2026
- status 2 merged pull requests in cilium/tetragon
- scope Kprobe return-path validation / tracing-policy docs and CRDs / Helm packaging cleanup
- evidence Regression coverage plus maintainer-reviewed upstream workflow
Linnix / Linux observability / Rust / 2026
Process-event lifetime and deployment handling in Linnix.
Merged in linnix-os/linnix#43, this fixes exit-event pruning that compared timestamps from two different clocks. It now uses the queue timestamp with saturating subtraction and includes a regression test. The same PR made install paths configurable and added an uninstaller that preserves the data directory.
- pull request #43: fix process-event pruning and deployment lifecycle August 9, 2026
- merged commit in linnix-os/linnix August 9, 2026
- status Merged into linnix-os/linnix
- scope Rust / process-event pruning / install and uninstall lifecycle
- evidence Regression coverage plus maintainer review
Pyrefly / Type checker / 2026
Stub descriptor semantics in Pyrefly.
Merged in facebook/pyrefly#3151, this fix makes stub and interface declarations use descriptor protocol lookup instead of exposing raw descriptor types. It closes #3045, adds regression coverage for inherited .pyi descriptors, and the mypy_primer run reported fewer real-world false positives.
- merged fix for stub/interface descriptor semantics April 28, 2026
- pull request #3151 with maintainer approval and mypy_primer signal April 28, 2026
- status Merged into facebook/pyrefly
- scope Descriptor protocol / .pyi stubs / type inference
- evidence Regression test plus mypy_primer signal across real projects
Bitcoin Core / PSBT and descriptors / 2026
Two authored fixes merged into Bitcoin Core: the PSBT combiner and the descriptor parser.
Both merged on August 24, 2026. In bitcoin/bitcoin#36025, PSBTInput::m_tap_scripts maps a leaf script to a set of control blocks but is serialized one record per control block, keyed by the control block, while PSBTInput::Merge unioned it by the map key. Two PSBTs mapping one control block to different leaf scripts merged into an input serializing the PSBT_IN_TAP_LEAF_SCRIPT key twice, so combinepsbt returned a PSBT that decodepsbt then rejected as invalid, a defect present since v24.0. Merging per record rather than per map entry also stops the union from dropping control blocks that do not conflict. I found it by adding a "combining must round-trip" assertion to the PSBT fuzz target and reported it with a minimal pair on #35665, where another contributor reproduced it. In bitcoin/bitcoin#34697, the miniscript duplicate-key check compared two key expressions by deriving each at index 0 against an empty signing provider, so any expression with a hardened step came back empty and compared equal to any other such expression: a musig() descriptor reusing the same participants in one tapleaf was rejected as "contains duplicate public keys" as soon as one participant was a private key on a hardened path, while the all-xpub spelling of it imported fine. The check now derives against the signing provider populated during parsing and only compares expression strings when neither side resolves. A reviewer found a second bug on the same branch: OriginPubkeyProvider::GetPubKey() prefixed its origin onto whichever entry was already in the output provider, so a participant expanded by a second expression had m/86h/1h/0h come out as m/86h/1h/0h/86h/1h/0h in the input and output taproot BIP32 derivation maps of a PSBT, sending a signer that follows them to the wrong key. Both are fixed here.
- pull request #36025: avoid duplicate taproot leaf script keys when merging August 24, 2026
- merged commit 1cb4163: merge the leaf script records by control block, with a functional regression test August 24, 2026
- the original report and minimal reproduction, on pull request #35665 August 12, 2026
- pull request #34697: fix musig() duplicate key checks and doubled PSBT origin paths August 24, 2026
- merged commit 7b15e2c: compare key expressions against the signing provider filled during parsing August 24, 2026
- merged commit b42f7fa: stop prepending a participant key origin twice August 24, 2026
- issue #34273, reported by another contributor: musig descriptor rejected as duplicate keys January 13, 2026
- status Both pull requests written by me and merged into bitcoin/bitcoin on August 24, 2026; #34697 is milestoned for the 32.0 release
- scope PSBT combiner / BIP 371 taproot leaf script records / descriptor and miniscript key comparison / musig() participant key origins in PSBTs
- evidence Three ACKs on each pull request, in both cases including the maintainer who merged it; regression tests added in rpc_psbt.py, descriptor_tests.cpp, and wallet_musig.py
Bitcoin Core / LLVM compiler-rt / 2026
TSAN and glibc fortify investigation for a Bitcoin Core timeout.
Investigated an intermittent Bitcoin Core TSAN timeout and traced the failing path to glibc fortify emitting __read_chk for TokenPipeEnd::TokenRead(), which did not go through TSAN's normal intercepted read path. The public issue thread records the diagnosis; a Bitcoin maintainer later linked the issue to an LLVM compiler-rt fix for fortified read/pread interceptors.
- status Public upstream investigation; not counted as a merged LLVM code contribution
- scope Bitcoin Core functional test timeout / glibc _FORTIFY_SOURCE / TSAN signal handling / compiler-rt interceptors
- evidence Issue-thread diagnosis, maintainer follow-up, and merged LLVM PR addressing the same missing fortified read/pread interceptor path
Bitcoin Core / RPC and wallet / 2026
A review finding and a co-authored commit in Bitcoin Core.
Reviewing bitcoin/bitcoin#35946, I found that the generated OpenRPC schema described type_str arguments as number | string while all four RPCs behind that override parse the numeric form as an integer, so 0.5 validated against the published schema and was then rejected at runtime with "JSON integer out of range". A maintainer agreed with the tightening, and the pull request author made the one-line change and attributed the commit to me. On bitcoin/bitcoin#35955 I worked with the author on the commit finishing a legacy wallet cleanup and am credited with a Co-authored-by trailer: LegacyScriptPubKeyMan had been deleted earlier, but an orphaned forward declaration in wallet/rpc/util.h, the SetupLegacyScriptPubKeyMan() name, several comments, and an inactive-HD-chain log message still referred to the removed class.
- review finding on pull request #35946: schema advertised fractional values the RPCs reject August 13, 2026
- commit e07d826 that addressed it, attributed to me by the pull request author August 18, 2026
- co-authored commit 02de12b: remove remaining LegacyScriptPubKeyMan references August 18, 2026
- pull request #35955: remove orphaned GetAffectedKeys and LegacyScriptPubKeyMan declarations August 18, 2026
- status Both pull requests merged August 18, 2026; the code was written by their authors
- scope OpenRPC schema generation / RPC argument parsing / legacy wallet declaration cleanup
- evidence Review finding endorsed in-thread by a maintainer and addressed in the merged branch; Co-authored-by credit recorded on the wallet commit
Dify / Agentic workflow platform / 2026
OpenTelemetry decorator typing cleanup in Dify.
Merged in langgenius/dify#32163, this refactor tightens OpenTelemetry decorator typing in the API service while preserving runtime behavior. A separate prompt-template typing cleanup remains open and is not counted here.
- pull request #32163: tighten OTel decorator typing February 9, 2026
- merged commit in langgenius/dify main February 9, 2026
- status 1 merged pull request in langgenius/dify
- scope Python typing / OpenTelemetry decorator ergonomics
- evidence Merge commit verified reachable from langgenius/dify main