Open to senior AI engineering roles

Howard PantonSenior Lead Engineer, FrontendM2A Media, March 2018 to nowCV (PDF)

Eight years building a cloud broadcast console. This year I changed how it gets built.

I manage two frontend developers and lead frontend on a production Angular platform, with a remit for code quality and automation. Most of my own work now ships through Claude Code agents, and I want to do that for a team full time: designing the agent workflows, skills and guardrails that let engineers ship faster without lowering the bar.

skills and subagents in the team's shared agent library, started June 2026
34 + 9
pull requests from a three-day unattended agent run, all merged after human review
10 of 10
merges made by an agent. People merge; hooks block the rest
0
to prepare a CI build, down from 4 to 7 minutes
6 s
statement coverage, up from 74% over summer 2026. Team result, my direction
97%

Angular 8 → 22, since 2019Nx monorepo, 27 micro-frontendsTypeScript · RxJS · Signals · TailwindJest · Cypress · Storybook · Jenkins · AWS

The company

M2A Media is an AWS-native cloud broadcast platform. It orchestrates live video contribution, transformation and distribution for broadcasters, sports rights owners and streaming platforms. The console is the multi-tenant web app operators use to schedule live events and to route, monitor, package and clip streams across AWS media services.

01Agentic delivery

From writing the code to running the system that writes it

Since May 2026 most of my delivery has run through Claude Code. In June the team started a shared agent library in the repository: a CLAUDE.md of non-negotiables, 34 skills that each own one area of the codebase, and 9 subagents. I made its first commit and set its direction; a developer on my team built the per-ticket pipeline and most of the skills, and 49 of the library's 160 commits are mine. I wrote the layer that lets agents work unattended: sprint runs, the bug-board sweep, browser QA, test planning, session handovers and ticket writing.

The bug-board sweep, one ticket per run

  1. Opt inThe team labels a bug for AI work. Nothing else is picked up.
  2. AssessIs it still relevant? Does it have an outcome, a repro and acceptance criteria?
  3. BuildPlan, develop, test and review run in their own git worktree.
  4. ProveBrowser check against a local build, plus the E2E domains the change can touch.
  5. ReportPull request with test and coverage evidence, and a Slack update to the team.
  6. MergeA person reviews and merges. Agents never do.
If unclearThe agent parks the ticket with a specific question, returns it to the backlog and tells the team in Slack.
  • 10 of 10An unattended sprint. Agents worked a sprint's pipeline tickets for three days while I was away and left a review pack of 10 pull requests across three repositories, tests re-run. I walked through them on my first day back: nine merged that day, the tenth after team review. Nothing merged or deployed without a person.
  • 7 of 7The bug-board sweep took seven labelled bugs from backlog to pull request in its first three days. All seven merged into the release train that week after review. One fix cut a page's background polling from 26 requests to 4.
  • 5 in 2.5 hFrom proposal to code. An agent run on phase one of my code-quality proposal had five pull requests open and verified in about two and a half hours. All five merged.
  • 273 of 275A new repository, built with agents. I started the release-orchestration engine in June 2026 and wrote 273 of its 275 commits, about half co-written with Claude, with contract tests guarding its release rules.

What went wrong, and what changed

In September an agent hand-typed a submodule commit hash during a release-branch merge, one hex digit wrong. Git accepted it; five builds in a row failed at checkout with an error that looked like a git fault. The fix went into the skill library (hashes are captured from git commands and checked against the remote before any commit) and a hook now blocks any commit that stages a submodule pointer unless the message says the bump is deliberate.

How I keep agent work trustworthy

  • Evidence before "done"Every pull request carries test output with coverage, lint results, and a screenshot for anything a user can see.
  • Hooks, not intentionsHooks block pushes to protected branches, the gate bypass, and edits to env files, lockfiles and bot-managed config. People merge.
  • Gates outside the agentThe pre-push gate and CI gates are git hooks and Jenkins stages, so they hold whichever tool or model wrote the change.
  • Tests that can failNew contract assertions are mutation-tested, so a passing test proves something.
  • Predictions before measurementsPerformance experiments commit the expected result before the first run.
  • Lessons go back inEach run's surprises are written into the skill that owns that area.
02The console

The product's frontend, from first commit to 27 modules

I built M2A's first dashboard console in 2018 and started the current cloud console from an empty repository in October 2019. It is now an Nx monorepo of 27 micro-frontends on Angular 22, used to schedule live events and to route, monitor, package and clip streams.

  • ScheduleThe busiest screen: a timeline of live events across up to 1,000 sources. A quarter of the module's commits are mine, including the 2025 rendering pass (debounced overlap checks, change-detection tuning, leaner polling), polling that restarts after a dropped connection, and the main-data-visible mark the lab baseline measures.
  • RoutesA diagram of connections between sources, selections and destinations. Over winter 2025–26 I rebuilt its line renderer as canvas and SVG variants with coalesced layout scheduling, debounced resize and scroll handling and collapsible destination groups, so layout work is batched rather than redrawn on every change.
  1. 2018

    Joined M2A Media. Built the first dashboard console from its first commit: 1,816 of its 1,865 commits, in Angular 6 with Angular Material, D3 and Chart.js.

  2. Oct 2019

    Started the cloud console: Angular 8, a component library with Storybook and Jest in the first week, Cypress and an Nx monorepo by December.

  3. 2021–23

    Angular 11 to 15, including the Material migration. TSLint to ESLint, a mock API server for UI and E2E tests, Tailwind, Sentry, Auth0 login and semantic-release versioning.

  4. 2024–25

    Led the micro-frontend architecture from 13 modules at the end of 2023 to 25 by the end of 2025 (27 today). Stepped Angular 16, 17 and 18 in one day, one version per commit, then 19 and 20.

  5. 2026

    Agentic delivery, the release engine, the quality gates and the performance baseline. A developer on my team ran the Angular 21 and 22 upgrades.

03Release pipeline

Builds people trust and releases that don't need babysitting

I own the console's Jenkins pipeline and the release engine behind it: 213 of the pipeline's 255 commits since January 2026 are mine. I set its roadmap of 25 tickets in six phases, from "a red build means a real failure" to every E2E domain in CI and the release gate.

  • 6 sBuild environment prep, down from 4 to 7 minutes. Builds pull a prebuilt CI image keyed on a hash of its inputs and rebuild it only when those change.
  • 21 → 15 minUnit tests, from three sequential stages to parallel buckets. Consistent across the last ten builds.
  • By impactE2E tests on a merge run only the domains the change can affect; anything unmapped runs the full suite, and a daily run sweeps everything.
  • Same bytesDeploy by composition. Every environment runs a recorded set of module artifacts with checksums, so what passed on staging is exactly what reaches production. Promotion, drift reports and alerts are built on it.
  • Approved planRollback runs from a plan the release owner approves, naming the versions it moves from and to; the engine refuses any plan whose hash doesn't match. A promotion reaches its approval prompt in 17 minutes, against the 20-minute criterion I set.
04Quality gates

Catching breakage before review, not after release

In November 2025 I rebuilt the pre-push gate every change, human or agent, must pass: ESLint on changed files, a spec beside every changed component or service, and 80% Jest coverage thresholds per push.

Unit-test coverage across the console's modules and shared libraries, summer 2026Team result: I directed the campaign and delegated it to a developer on my team, who ran it through Claude agents. The gate keeps the gains.
Show as a table
  • Blast radiusPR quality signals. Our two most recent escaped regressions broke shared contracts, each used by more than a dozen repositories, and coverage alone would have passed them. I proposed per-PR signals to catch that class: a blast-radius report of every repository calling a changed shared API, a complexity limit of 20 enforced on push, and a changed-line scorecard. Phase one is merged.
  • 7 to 1Dependency health. I replaced seven stale automated security pull requests with one tested upgrade; the automated ones pinned old framework versions and could never merge as raised.
05Measurement

Performance and analytics as numbers on every release

Performance used to be judged by feel. With a developer on my team I set up a lab baseline for the console's data-heavy pages, then turned it into a Jenkins job that measures each release under fixed conditions (production build, lab mocks, throttled network, cold cache, 5 to 10 runs per cell) and flags regressions. I also designed the console's GA4 event tracking, with a documented event catalogue.

Schedule50 · 500 · 1,000 sources
Sources50 · 500 sources
Source detail50 sources
Routes50 sources
Encoder50 sources
Multiviewer50 sources
  • Main data visibleA metric that matches the user. I added a mark for the moment operators can see their data, measured alongside LCP and INP across three production releases.
  • 5% and 100 msA clear regression rule. p75 main-data-visible and LCP both worse by at least 5% and 100 ms marks the build unstable and posts to the release channel.
  • Found and fixedA silent analytics failure. After a configuration split, production analytics had recorded nothing for weeks: the page asked Google's tag library for a destination ID rather than a tag ID and got a 404. I fixed the tag set-up and the code.
  • 3,000 to 10Clean data. The same fix stopped development traffic leaking into production analytics; stray events fell from about 3,000 a week to 10.
06Toolkit

What I work with

AI engineering

  • Claude Code
  • Skills
  • Subagents
  • Hooks
  • MCP servers
  • Scheduled routines
  • Session handovers
  • Claude Design

Frontend

  • Angular 8 → 22
  • TypeScript
  • RxJS
  • Signals
  • Nx
  • Micro-frontends
  • Tailwind
  • Storybook
  • Accessibility

Quality and performance

  • Jest
  • Cypress
  • Mutation testing
  • Puppeteer
  • Core Web Vitals
  • Sentry
  • GA4

Delivery

  • Jenkins / Groovy
  • Docker
  • semantic-release
  • AWS: S3, ECR, IAM, CloudFront
  • AWS media services
  • Bitbucket
  • Jira / Confluence