// Robb Doering's resume, typeset by RenderCV 2.8. Compile it with `typst compile <this file>`.
// Needs Typst 0.14 or newer. The first compile fetches @preview/rendercv:0.3.0 and its
// fontawesome dependency from Typst Universe, so it wants a network connection once.
// Set in Newsreader Text, Newsreader Display, and MonaspiceNe NF (Nerd Font), which it does not
// embed: without them Typst falls back to its default font and the page count can change.
// Import the rendercv function and all the refactored components
#import "@preview/rendercv:0.3.0": *

// doering.ai v5 "academic" palette: slate ink, one mineral-cyan accent, amber as a rare mark.
#let ink = rgb("#16202c")
#let ink-2 = rgb("#4c5a6a")
#let rule-1 = rgb("#dce2e9")
#let rule-2 = rgb("#c4cdd7")
#let paper = rgb("#f5f7f9")
#let accent-2 = rgb("#074b59")
#let amber-mark = rgb("#e8a01e")
#let mono = "MonaspiceNe NF"

// Small tracked mono label, as on the site's figures.
#let mono-label(body) = text(font: mono, size: 6.6pt, tracking: 0.08em, fill: accent-2, upper(body))

// Dates and locations: mono metadata in secondary ink.
#let meta-column(body) = {
  set text(font: mono, size: 7.4pt, fill: ink-2, tracking: 0.01em)
  body
}

// Skills as plates: one tinted cell per area, items set as a run separated by thin dots.
#let skills-plates(columns: 3, ..areas) = {
  set par(leading: 0.48em, spacing: 0pt, justify: false)
  grid(
    columns: (1fr,) * columns,
    column-gutter: 5pt,
    row-gutter: 5pt,
    fill: paper,
    stroke: 0.6pt + rule-2,
    inset: (x: 7pt, top: 6pt, bottom: 7pt),
    ..areas.pos().map(((label, items)) => {
      block(below: 5pt, text(font: mono, fill: amber-mark, size: 5.6pt, baseline: -0.5pt)[■] + h(0.45em) + mono-label(label))
      text(size: 0.93em, items.map(box).join([~#text(fill: ink-2, weight: 600)[·] ]))
    }),
  )
}

// Skills as a ledger: hairline rows, mono label at left, items at right.
#let skills-ledger(columns: 3, ..areas) = {
  set par(leading: 0.5em, spacing: 0pt, justify: false)
  let rows = areas.pos()
  grid(
    columns: (3.4cm, 1fr),
    column-gutter: 8pt,
    inset: (y: 4.2pt),
    stroke: (x, y) => (
      top: 0.5pt + rule-1,
      bottom: if y == rows.len() - 1 { 0.5pt + rule-1 },
    ),
    ..rows.map(((label, items)) => (pad(top: 1.2pt, mono-label(label)), items.join([, ]))).flatten(),
  )
}

#set strong(delta: 200)
#show raw: set text(font: mono, size: 0.92em)

// Apply the rendercv template with custom configuration
#show: rendercv.with(
  name: "Robb Doering",
  title: "Robb Doering - CV",
  footer: context { [#emph[Robb Doering -- #str(here().page())\/#str(counter(page).final().first())]] },
  top-note: [ #emph[Last updated in Oct 2026] ],
  locale-catalog-language: "en",
  text-direction: ltr,
  page-size: "us-letter",
  page-top-margin: 1.5cm,
  page-bottom-margin: 1.5cm,
  page-left-margin: 1.8cm,
  page-right-margin: 1.8cm,
  page-show-footer: true,
  page-show-top-note: false,
  colors-body: rgb(22, 32, 44),
  colors-name: rgb(22, 32, 44),
  colors-headline: rgb(76, 90, 106),
  colors-connections: rgb(76, 90, 106),
  colors-section-titles: rgb(196, 205, 215),
  colors-links: rgb(10, 108, 128),
  colors-footer: rgb(76, 90, 106),
  colors-top-note: rgb(76, 90, 106),
  typography-line-spacing: 0.58em,
  typography-alignment: "left",
  typography-date-and-location-column-alignment: right,
  typography-font-family-body: "Newsreader Text",
  typography-font-family-name: "Newsreader Display",
  typography-font-family-headline: "Newsreader Text",
  typography-font-family-connections: "MonaspiceNe NF",
  typography-font-family-section-titles: "Newsreader Text",
  typography-font-size-body: 10pt,
  typography-font-size-name: 28pt,
  typography-font-size-headline: 11.5pt,
  typography-font-size-connections: 7.4pt,
  typography-font-size-section-titles: 13pt,
  typography-small-caps-name: false,
  typography-small-caps-headline: false,
  typography-small-caps-connections: false,
  typography-small-caps-section-titles: false,
  typography-bold-name: false,
  typography-bold-headline: false,
  typography-bold-connections: false,
  typography-bold-section-titles: false,
  links-underline: false,
  links-show-external-link-icon: false,
  header-alignment: left,
  header-photo-width: 3.5cm,
  header-space-below-name: 0.24cm,
  header-space-below-headline: 0.3cm,
  header-space-below-connections: 0.2cm,
  header-connections-hyperlink: true,
  header-connections-show-icons: false,
  header-connections-display-urls-instead-of-usernames: true,
  header-connections-separator: "",
  header-connections-space-between-connections: 0.25cm,
  section-titles-type: "with_partial_line",
  section-titles-line-thickness: 0.5pt,
  section-titles-space-above: 0.42cm,
  section-titles-space-below: 0.24cm,
  sections-allow-page-break: true,
  sections-space-between-text-based-entries: 0.3em,
  sections-space-between-regular-entries: 0.75em,
  entries-date-and-location-width: 3.6cm,
  entries-side-space: 0cm,
  entries-space-between-columns: 0.1cm,
  entries-allow-page-break: false,
  entries-short-second-row: false,
  entries-degree-width: 1cm,
  entries-summary-space-left: 0cm,
  entries-summary-space-above: 0cm,
  entries-highlights-bullet: text(fill: rule-2.darken(18%), [•]),
  entries-highlights-nested-bullet: text(fill: rule-2.darken(18%), [•]),
  entries-highlights-space-left: 0.3cm,
  entries-highlights-space-above: 0.15cm,
  entries-highlights-space-between-items: 0.1cm,
  entries-highlights-space-between-bullet-and-text: 0.5em,
  date: datetime(
    year: 2026,
    month: 10,
    day: 13,
  ),
)

#grid(
  columns: (1fr, auto),
  column-gutter: 14pt,
  align: (left + bottom, left + bottom),
  [
    #block(below: 0.24cm, text(
      font: "Newsreader Display",
      size: 28pt,
      weight: 600,
      fill: ink,
    )[Robb Doering])
    #text(
      font: "Newsreader Text",
      size: 11.5pt,
      style: "italic",
      fill: ink-2,
    )[Senior Full Stack Engineer · Agentic Engineering]
  ],
  [
    #set text(font: mono, size: 7.4pt, fill: ink-2)
    #grid(
      columns: 2,
      column-gutter: 13pt,
      row-gutter: 4.6pt,
      [#link("mailto:robb@doering.ai", icon: false, if-underline: false, if-color: false)[robb\@doering.ai]],
      [#link("tel:+1-415-713-1766", icon: false, if-underline: false, if-color: false)[(415) 713-1766]],
      [#link("https://doering.ai/", icon: false, if-underline: false, if-color: false)[doering.ai]],
      [#link("https://linkedin.com/in/robbd", icon: false, if-underline: false, if-color: false)[linkedin.com\/in\/robbd]],
      [#link("https://gitlab.com/robbd", icon: false, if-underline: false, if-color: false)[gitlab.com\/robbd]],
      [#link("https://github.com/robbwdoering", icon: false, if-underline: false, if-color: false)[github.com\/robbwdoering]],
    )
  ],
)
#v(0.3cm)
#line(length: 100%, stroke: 0.5pt + rule-2)
#v(0.2cm)

== #text(fill: ink, weight: 600)[Summary]

Senior full stack engineer (TypeScript, React, Python) with 6+ years of professional experience, from Google AdSense to satellite command-and-control software. Three years of independent AI work became full-time agentic engineering: directing coding agents in isolated Git worktrees and building the MCP servers, code review, guardrails, and recovery tooling around them. I relish any opportunity to apply science or philosophy to engineering challenges.

== #text(fill: ink, weight: 600)[Skills]

#strong[Languages:] Python, TypeScript\/JavaScript, C++, Java, SQL, Bash


#strong[Frontend:] React, Redux, Next.js, Astro, HTML\/CSS, Tailwind CSS, Bun


#strong[Backend and data:] REST APIs, WebSockets, Node.js, Flask, PostgreSQL, embeddings, RAG


#strong[Agentic engineering:] Claude Code, Codex CLI, Gemini CLI, MCP servers, skills, hooks, Git worktrees


#strong[Models:] LiteLLM, vLLM, llama.cpp, Hugging Face Transformers, QLoRA fine-tuning, Marker OCR


#strong[Testing and operations:] pytest, Jest, A\/B testing, GitLab CI\/CD, Linux, Docker\/Podman, systemd services


== #text(fill: ink, weight: 600)[Experience]

#regular-entry(
  [
    #strong[Doering Thinking Machines] · #emph[Software Engineer (self-employed)]

  ],
  [
    #show: meta-column
    Aug 2023 – Sept 2026

  ],
  main-column-second-row: [
    #summary[AI prototyping and agent tooling in Python and TypeScript, published as \~30 open-source repositories.]

    - #strong[Agent orchestration.] Directed coding agents (Claude Code, Codex CLI, Gemini CLI) through scoped tasks in isolated Git worktrees, with automated code review as the gate to main: nearly 2,400 agent branches merged across 45 repositories in Q3 2026.

    - #strong[MCP integrations.] Built four FastMCP servers that replace fragile shell calls with structured tools: #link("https://gitlab.com/doering-ai/libs/tact")[inTact] (on PyPI) heals stale agent edits through seven increasingly permissive matches and refuses ambiguous ones; the others handle Git with commit-time secret scanning, Plane task tracking, and task routing.

    - #strong[Code review and guardrails.] Built #link("https://gitlab.com/doering-ai/apps/gate")[myGate], which reviews each GitLab merge request from an immutable Git snapshot, posts findings as discussions, and holds the merge until major findings are resolved: 1,500+ merges reviewed from mid-August through September 2026. Its hooks block costly nested agent launches.

    - #strong[Recovery.] Built tooling to resume interrupted agent runs: session analytics classify how each run ended (frozen on a tool call, aborted), and a resumer agent rebuilds the work from transcripts, task records, and repository state, then finishes only what remains.

    - #strong[Engineering standards.] Codified the workflow as 29 policy documents with citable rule IDs and 46 agent skills, which #link("https://gitlab.com/doering-ai/libs/fleet")[myFleet] projects from one canonical copy into eleven agent harnesses. Held the libraries to GitLab CI, deep type coverage, and Sphinx documentation, with \~9,900 pytest cases across four of them.

    - #strong[Models and retrieval.] Ran a self-hosted LiteLLM gateway with sealed credentials; built embedding search on PostgreSQL; served models with vLLM and llama.cpp; fine-tuned with QLoRA on an RTX 4090.

  ],
)

#regular-entry(
  [
    #strong[Google] · #emph[Software Engineer, AdSense]

  ],
  [
    #show: meta-column
    Feb 2022 – June 2023

  ],
  main-column-second-row: [
    #summary[Modernized the JavaScript ad tag of AdSense, a multi-billion-dollar-a-year product, and implemented new ad formats across browser (TypeScript) and backend (C++) code.]

    - Owned features from start to finish at Google scale, meeting strict performance requirements and shipping through Google's production deployment systems.

    - Set up, monitored, and analyzed A\/B experiments on billions of ad queries to verify the impact of my changes, using Python notebooks and internal tools.

    - Investigated and documented JavaScript behavior for scripts that run in over 2M browser environments.

  ],
)

#regular-entry(
  [
    #strong[Space Ground System Solutions] · #emph[Software Engineer]

  ],
  [
    #show: meta-column
    June 2019 – July 2021

  ],
  main-column-second-row: [
    #summary[Helped bring a command-and-control system for government satellites to the web, building features in React\/Redux, Java, and C++ on data-intensive APIs from NASA, DoD, and commercial partners.]

    - Delivered \~12 full stack features end to end, some from design documents and others where I led requirements gathering and UX design.

    - Chosen as acting project lead for six engineers during the lead's three-month leave; ran Agile ceremonies, met with stakeholders, and cleared blockers.

    - Introduced Jest unit tests to a lightly tested codebase and helped coordinate regular functional testing.

  ],
)

#regular-entry(
  [
    #strong[Fujitsu Network Communications] · #emph[Automation Tools Intern]

  ],
  [
    #show: meta-column
    May 2018 – Aug 2018

  ],
  main-column-second-row: [
    #summary[Built a Java\/Spring MVC and JavaScript web application that formalized a project-management procedure and collected its data for executive analysis.]

  ],
)

== #text(fill: ink, weight: 600)[Projects]

#regular-entry(
  [
    #strong[#link("https://epstein-index.org")[The Epstein Index]] · #emph[Public Document Explorer]

  ],
  [
    #show: meta-column
    Astro · React · OCR

  ],
  main-column-second-row: [
    - A public explorer for over 45,000 DOJ case-file documents, fed by an eight-stage Python pipeline (download, OCR, clean), with an interactive React timeline, maps, and a network graph.

  ],
)

#regular-entry(
  [
    #strong[#link("https://gitlab.com/doering-ai/apps/wiki-parse")[Wikiparse]] · #emph[Wikitext Translation Pipeline]

  ],
  [
    #show: meta-column
    Python data pipeline

  ],
  main-column-second-row: [
    - Extracted 45M citations from a full English Wikipedia dump on home hardware and published a #link("https://huggingface.co/datasets/robbd/wikiparse-2606")[Hugging Face dataset] of 5.1M articles; converts wikitext to Markdown with composed regular expressions.

  ],
)

#regular-entry(
  [
    #strong[#link("https://doering.ai")[doering.ai]] · #emph[Professional Portfolio Site]

  ],
  [
    #show: meta-column
    Astro · TypeScript

  ],
  main-column-second-row: [
    - An Astro and TypeScript site on Bun and Tailwind CSS, with accessibility and reproducibility checks.

  ],
)

#regular-entry(
  [
    #strong[#link("https://gitlab.com/doering-ai/libs/basis")[myBasis]] · #emph[Ergonomic Python Utilities]

  ],
  [
    #show: meta-column
    Python library

  ],
  main-column-second-row: [
    - A broad extension of the Python standard library, published on PyPI as #link("https://pypi.org/project/my-basis/")[my-basis], centered on runtime type coercion, text processing, and functional programming.

  ],
)

#regular-entry(
  [
    #strong[#link("https://gitlab.com/doering-ai-sublime")[Sublime Text tooling]] · #emph[Plugins, Language Servers, and Test Infrastructure]

  ],
  [
    #show: meta-column
    Python · Rust · LSP

  ],
  main-column-second-row: [
    - A mock editor API for headless pytest, a Rust-backed language server for `.sublime-syntax` grammars, and LSP-pyrefly for Meta's pyrefly type checker.

  ],
)

== #text(fill: ink, weight: 600)[Education]

#education-entry(
  [
    #strong[Vanderbilt University] · #emph[Computer Science]

    #summary[Minors in Philosophy and Spanish.]

  ],
  [
    #show: meta-column
    Nashville, TN

    Aug 2015 – May 2019

  ],
  degree-column: [
    #strong[B.S.]
  ],
  main-column-second-row: [
  ],
)

#education-entry(
  [
    #strong[Georgia Institute of Technology] · #emph[Computer Science, Interactive Intelligence]

    #summary[Completed 8 of 10 courses toward an M.S.; degree not completed.]

  ],
  [
    #show: meta-column
    Online

    Sept 2020 – June 2022

  ],
  degree-column: [

  ],
  main-column-second-row: [
    - Coursework included AI, Knowledge-Based AI, Human-Computer Interaction, Networks, Operating Systems, and Visual Analytics.

  ],
)
