Selected work

Manual processes, turned into systems.

A selection of projects from 20 years of production work at XBOX and Microsoft, a TPM role at an early-stage AI startup, and what I'm building for myself. Focused on approach and outcomes.

3 languages
became
30 languages

Localization Pipeline Enhancements

XBOX localization was fragmented across surfaces, each with its own CMS and its own rules. My tooling generated localized content per surface from its own source and cut production turnaround from 30 minutes to 3.

The XBOX app for PC Store tab: featured sale banners, a Game Pass promotion, and rows of game tiles
The XBOX app for PC. Every campaign placement shipped in 30 languages and 122 locale variants through this pipeline.
Problem, approach, result

The problem

XBOX localization was fragmented across surfaces and systems. One surface in the XBOX app covered just 3 languages with no fallback; another already ran 30 with fallbacks, but on a different CMS. On the console there were fewer languages and variants, but strict character-width limits. Every surface had its own rules and leaned on manual copy-and-paste, and complex multi-market sales (different messaging per market) made all of it harder.

The approach

Pulling it together took several tools, refined over time. They generated localized content for each surface from its own source, added worldwide templates and fallbacks where a surface lacked them, and respected each surface's limits, whether that was language coverage or character width. Rather than start from scratch, I wrapped existing but unadopted tools in a UI and kept iterating until the whole process took minutes.

The result

The tools turned a fragmented, multi-CMS process into a consistent, largely automated one and cut manual effort on every surface. The most limited surface jumped from 3 languages to 30 and gained fallbacks it never had; the hardest multi-market sale updates dropped from 30 minutes to 3. And because content was generated from each surface's source of truth, an AI review step could verify the output against the origin (not a downstream copy) before it published.

reactive QA
became
caught at source

Copilot Localization Review Agent

Localization errors were surfacing after publish. A custom M365 Copilot agent moved that review upstream, checking localized content against the source at import, before anything went live.

Problem, approach, result

The problem

Localization errors (incorrect context, the wrong language shipped to a market, off-brand terminology) were being caught late in the production cycle, sometimes after content had already published to multiple surfaces. Each catch meant updates across several markets and a manual review sweep.

The approach

The agent I set up in M365 Copilot reviewed localized content against the source at the point of import, before it entered production. It applied rules for grammar, style, sales terms, and brand terminology, then flagged issues with enough context for the producer to fix them on the spot or route them to the localization team. For the first time, producers could catch errors in languages they couldn't read, and the loc team got feedback it had never had.

The result

Manual spot-checking gave way to an automated review step. Errors that used to spread across several markets got fixed before they left the producer's hands.

siloed
became
shared practice

AI Explorers: A Cross-Team Community of Practice

AI experiments were happening in isolation across teams. I designed and ran a weekly cross-team session where practitioners taught each other and shared best practices.

Problem, approach, result

The problem

AI tools were being adopted unevenly across the team. Enthusiasts had built sophisticated workflows while others weren't sure where to start, and there was no shared vocabulary or place to write down what worked. The gap between the people using AI well and everyone else kept growing.

The approach

I started small with a few people already experimenting with AI and grew it into a weekly cross-team session where anyone could bring a question. It wasn't top-down training. The people doing the work taught each other, while I set the agenda, picked topics (Copilot agents, Power Automate, Copilot Studio, homegrown tooling), and facilitated.

The result

It became the place our AI practice spread, person to person. A few people reached out afterward to thank me for setting it up and accelerating their learning. One of the best learnings for me personally was personal knowledge management: I'd just set up my own second brain at home, and hearing how others implemented theirs into their Microsoft work changed how I work.

manual checks
became
alerts in Teams

Real-Time Microsoft Teams Alerts from ADO Changes

Time-sensitive campaign changes landed as a tag on a work item requiring an impossible level of attention to queries and email. I moved the alerts into Teams, sent only when action was still needed.

Problem, approach, result

The problem

A time-sensitive campaign change would land as a tag on an Azure DevOps work item and be dropped into email. As ADO notifications were easy to miss, and changes accumulated quickly in email, producers and PMs frequently checked both their inbox and a saved ADO query several times a day. Some changes needed action within the hour, which made a missed check on a busy day a real risk.

The approach

In Power Automate, I set up a flow from ADO tag to Teams message, with M365 Copilot helping me troubleshoot and refine it. When the target tag appeared on a work item, the flow checked an Excel tracker to confirm the work wasn't already handled, then sent a direct Teams alert to the responsible producers and PMs, but only when action was still needed. That meant fewer misses and less stress for everyone.

The result

The team stopped relying on memory, repeated query checks, and a cluttered inbox to catch time-sensitive work. Alerts showed up where people were already working, and only when something needed doing.

a stale doc
became
a self-updating plan

A Self-Updating Project Plan in Copilot Cowork

My editorial calendar was a color-coded Excel sheet: nice-looking, but hard to use as a plan. A Copilot Cowork agent turned it into a real project plan and kept it current on its own.

Problem, approach, result

The problem

My editorial calendar lived in Excel: color-coded and formatted as a calendar for people to read at a glance. Useful for sharing, but difficult for production planning. Turning it into an actual project plan meant reading it by hand, and it kept changing, so the plan was always in flux. I also wanted something a non-developer could run to create a plan: an alternative to VS Code and Copilot for teammates who don't live in a code editor.

The approach

When Copilot Cowork came out, I went straight to it for non-dev work. The agent connected to SharePoint, ran on a schedule, and transformed the colorful editorial calendar into a structured Excel project plan, then watched for changes and folded them back in on its own. Each morning it sent me a Teams ping listing what the day needed. It required no code editor, so I shared it with the AI Explorers team as something any PM could pick up.

The result

An ongoing manual chore became something that ran on a schedule, though, like a lot of AI tools, not perfectly. It became one of my favorite uses of agentic AI outside of coding, practical and easy to set up, even as I kept refining the prompts and waiting for the product to catch up.

a reboot per language
became
all on one page

XBOX Ad Preview Tool

Seeing a localized console ad meant changing the console's language and rebooting, one language at a time. Starting from nothing but an idea, I made a custom HTML tool that showed every language on one page and highlighted any copy over its character limit.

Problem, approach, result

The problem

The only way to see how localized ad copy would actually render on the XBOX console was to go into console settings, change the language, and reboot, then do it all again for the next one. Spot-checking one or two languages that way was fine, but covering 20 or so took far too long. So copy that looked fine in English could run past its character limit in German or Greek, and those catches often came too late.

The approach

The tool started with a question I asked myself. How could I preview all of our localized content, know exactly how it would render, and see it on one page I could save if needed? There was no complete spec, so working with Copilot, I created a custom HTML page from real ad placements, comparing it against the console and refining the layout until it matched almost pixel for pixel. The page rendered every supported language side by side at real display dimensions and highlighted anything that exceeded its character count.

The result

A settings change and a reboot per language became one page with every language on it and the overruns already highlighted. Reviewing 20 or so languages took a single scroll, the page could be saved whenever a record was useful, and what we approved on screen was what every market got.

no search
became
one-command reports

A Command-Line Toolkit for a CMS with Limited Search

The XBOX Support CMS couldn't scrub its own content well. Roughly twenty command-line tools later, anyone on the team could audit content without Visual Studio.

Problem, approach, result

The problem

The XBOX Support CMS couldn't search across the full, global content areas. You could export XML, but answering a broad question (where does something appear, what's broken, what changed) meant manual investigation or one-off work in Visual Studio. Visibility across multiple content areas was poor, making routine audits surprisingly difficult.

The approach

With AI's help, I started with PowerShell scripts that parsed the CMS XML exports and grew them into roughly twenty C# command-line apps covering automated exports, regex and flexible search, and CSV and Excel reporting. Packaged as simple .exe files, they needed no Visual Studio or scripting knowledge, so teammates could run global content dashboards, broken-link audits, and configuration reports on their own.

The result

Work that had needed an expert and a lot of manual digging became something anyone on the team could run from the command line. The team could finally see across its content, and recurring audits became standard reports people ran themselves.

vague summaries
became
actionable recaps

Meeting Recap Pipeline for Microsoft Teams

At an early-stage AI startup, only some of the team had access to Copilot meeting summaries in Microsoft Teams, and the default summary rarely said what was decided or who owned the next step. A custom recap format and a Power Automate flow gave everyone the same actionable record, and cut several minutes of manual recap work to about one.

Problem, approach, result

The problem

As a TPM at an early-stage AI startup, I was in meetings several times a week with a team that relied on the meeting summary Copilot generates in Microsoft Teams. Its default format read as a general narrative that didn't separate decisions from discussion or say who owned what next. And not everyone on the team had access to those Copilot summaries, so for some people a shared recap was the only record they got. I'd been writing, naming, filing, and announcing those recaps by hand, and with no set place or naming for them, a decision made on Monday was hard to find by Thursday.

The approach

I started with the format, a custom Markdown layout for the Teams Copilot summary that organized each recap around decisions, priorities, and tasks. Tasks came out as a table with a title, description, assignee, priority, and due date for each one. Then I set up a manually triggered Power Automate flow. After a meeting I ran it, typed a title, and pasted in the notes, and the flow created a predictably named .md file in the right SharePoint library and posted a link in the team's Teams chat.

The result

What had taken several minutes of manual work after each meeting took about a minute. Every meeting ended with the same kind of recap, in the same place, under a name you could guess, and the whole team heard about it right away, including the people without Copilot in Teams. Because the recaps were consistent, decisions and action items were easy to follow from one meeting to the next, and when a task belonged in Microsoft Planner, I copied it over straight from the table. Markdown also meant a recap could go straight into a notes system or an AI tool without conversion.

tab triage
became
one ranked list

Personal Job Board

Personal build · Python · local LLM · 2026

A serious job search means watching six sources daily and reading fifty postings to find three that match my interests. Now a pipeline collects, dedupes, and scores every posting with a local LLM against eight weighted axes.

Problem, approach, result

The problem

I'm trying to simplify how I look for jobs by creating a tool just for myself. I want to watch six-plus sources (government portals, company boards on Greenhouse, USAJobs, aggregators) every day. The same posting appears on three of them under slightly different titles. And "is this worth applying to?" is a judgment call across many dimensions at once: how central each of my skills is to the role, where it sits, whether it quietly wants a hands-on engineer instead of an orchestrator. Reading fifty postings to find three good ones is exactly the kind of manual process suited to an LLM and for what I need.

The approach

So I built the tool I wanted: a Python pipeline that collects from all six sources, dedupes across them (same company + title + city, keeping the richest record), then scores every posting with a local LLM against eight weighted "centrality" axes, plus a location gate and disqualifier factors that encode what I'm not (hands-on IC engineering ×0.35, visual design ×0.5). One axis is Automation Opportunity: a role drowning in manual process scores high, because that's a primary interest of mine. Scores are cached, so a morning run only evaluates what's new. I designed the pipeline and the scoring model; AI wrote most of the implementation under my direction, which is rather the point. Probably obvious, but this is one of my favorite uses of AI: make your own tools! A companion tool compares any posting against my résumé and reports the gaps.

The result

One command each morning produces a ranked, self-contained dashboard: per-axis score meters, sort by any axis, location and source filters. I read the top of a ranked list instead of triaging browser tabs. My fit judgment lives in a config file instead of my head, so tuning it is an edit, not a habit. And because the scoring model runs on a local LLM, the whole thing costs nothing per run and no job data leaves my machine.

The job board dashboard: a ranked list of job cards, each with a fit score, per-axis score meters, salary, and location, under a header showing 516 listings from five sources with min-fit, sort, and filter controls
One morning's run: 516 listings collected, deduped, and ranked; per-axis meters, min-fit slider, sort by any axis. Runs locally, just for me; not a product.

Open to work

Got a manual process worth automating?