Associate Professor · Carnegie Mellon University · Institute for Software Research
My broad goal in research is to help software engineers build complex systems in the real world, and to do so responsibly. My group and I work in three main areas: engineering AI-powered software systems, software supply-chain security, and scaling software variability and reuse. Methodologically, I lean on empirical methods and pragmatic tool building, often in interdisciplinary collaborations spanning AI, human-computer interaction, security, and the social sciences.
Software systems increasingly rely on AI components for core functionality, opening up capabilities that were previously out of reach, but also breaking traditional assumptions about specifications, testing, and modularity. AI components are fundamentally unreliable, yet the engineering needed to build dependable systems around them is rarely taken seriously in practice. Much of my research and teaching focuses on how to responsibly build software with AI components, sometimes called AI engineering: improving collaboration between software engineers and data scientists, grounding testing in requirements engineering, and designing for safety, risk, and production operation. More recently, AI coding agents are disrupting how software itself is built, raising the urgency further.
Nearly all modern software is built on open source, the critical infrastructure maintained largely by volunteers with no formal obligation to the many projects that depend on them. This makes the software supply chain a growing security concern: malicious package updates, compromised dependencies, and fake or abandoned projects can ripple across the ecosystem, while the trust signals developers have long relied on are eroding. My research studies these threats empirically and builds interventions that help: lightweight sandboxes for risky dependencies, tools that flag suspicious updates, and notifications for abandoned dependencies. This work sits within a broader interest in how open-source communities collaborate, sustain themselves, and cope with change. This work is supported by the NSF Frontier Secure Software Supply Chain Center (S3C2).
Variability and reuse are how complex modern software scales: a single configurable codebase like the Linux kernel or a modern web framework can serve millions of distinct use cases. But that leverage comes at a cost when thousands of interacting options create combinatorial spaces that resist traditional testing, leaving defects that hide in specific configurations. My earlier research championed pragmatic, disciplined variability management with tooling rather than new language constructs, and showed how to scale analyses across exponential configuration spaces—such as type-checking all 214k compile-time configurations of the Linux kernel using SAT solvers. The tools we built, like CIDE and TypeChef, were adopted widely in the research community.