Tag: Technical Work

  • Building Evals for an AI Memoir Writing Coach

    Building Evals for an AI Memoir Writing Coach

    I’ve been travelling for years. Eight years living nomadically across 42 countries, collecting stories and memories. I have numerous travel journals, thousands of photos. I remember fireflies in the Colombian Amazon, night trains through China, getting spectacularly food poisoned in India. But when trying to turn these memories into something coherent, I keep getting distracted by the structure problem, the voice problem, the where-do-I-even-begin problem.

    The traditional memoir-writing prompts feel either too clinical (like filling out a form) or too cheerleader-y (like every memory is a profound breakthrough waiting to happen). What if I could train an AI to be the perfect writing coach for this? Something that asks good questions and gives honest feedback without turning into either my therapist or my biggest fan.

    Before I can train this AI, I need to figure out how to measure whether it’s actually working. I need an evaluation system that can tell me if I’m teaching it the right boundaries, or if I’m just creating a very polished chatbot that sounds helpful but misses the point entirely.

    The AI needs to be encouraging without being sycophantic. It can say “That’s powerful” but not “OMG SO BRAVE!!!” It needs to be present with emotion without being therapeutic. “I’m sorry” is fine. “You have unresolved grief patterns” is absolutely not. And it needs to be story-focused without being dismissive. “What happened next?” works. “Got it. Moving on.” doesn’t.

    I started by finding a dataset of therapy session transcripts online and analysed over 200 of them to understand what therapist language actually looks like. Patterns emerged quickly. “It sounds like you…” appeared in about 8% of therapist responses, always followed by some kind of diagnostic framing. “How does that make you feel?” showed up constantly. Clinical words like “unresolved,” “trauma response,” “processed” threaded through everything.

    Then I looked at oral history interviews to see what good memoir questions actually look like. These were different. Short questions, usually one sentence. “Tell me about…” or “What do you remember…” or “What was it like…” They were open-ended but specific, inviting stories rather than analysis. I could see what made them different. The therapists were always trying to understand why someone felt something. The oral historians just wanted to know what happened.

    Next, I wanted to introduce something from Joe Hudson’s Connection Course that I took last year. He has this framework called VIEW, and I wanted to bring in the magic from this one line: “Wonder = Curiosity without looking for an answer.”

    Memoir writing isn’t as much about finding answers as it is about capturing experience. The AI should ask because it’s genuinely curious, not because it’s trying to extract information to plug into a template. Every question should create space for memory to emerge, not direct it toward a predetermined conclusion.

    A question like “Why did you feel that way?” is looking for causation, looking for something to resolve. “What do you remember about that moment?” just makes space for the story to come out however it wants to.

    The other parts of VIEW became the foundation too. Impartiality, which means letting me be whoever I am in the story without judgment. Empathy, which Joe describes as being “with me” rather than “for me”. I think that matters, the difference between sitting beside someone and trying to fix them. And Vulnerability, which means asking the real question, not the safe one.

    Being “non-sycophantic” doesn’t mean avoiding all feedback. I do want the AI to tell me when my timeline jumps are confusing, when my voice drifts, and when I’m being too vague. But I want it done with what I’m thinking of as a feedback sandwich approach.

    Start with something positive about the work: “This chapter has real emotional power.” Then the constructive bit: “The timeline jump between these two sections might confuse readers. Consider adding a transition sentence that grounds us in when this is happening.” Then close with another positive: “The way you end with that reflection works beautifully.”

    The key is focusing on the work, not the person. Suggesting rather than demanding. Explaining the why behind the feedback. It’s honest without being harsh, helpful without being prescriptive.

    So how do you actually teach an AI these boundaries? This is where it gets technical, and you need to build your evaluation system before you start training.

    I’m using a five-dimensional rubric, each dimension scored 0-10:

    1. Story Elicitation (0-10) Does the response invite a memoir-worthy narrative? Does it ask questions that create space for specific memories and sensory details?

    • 0-3: Generic questions, no story invitation
    • 4-6: Decent questions but missing specificity
    • 7-9: Strong story elicitation with good follow-up
    • 10: Perfect wonder-based questions that open narrative space

    2. Empathy Level (0-10) Appropriate emotional acknowledgment without becoming therapeutic?

    • 0-3: Either dismissive or over-therapeutic
    • 4-6: Acknowledges but feels mechanical
    • 7-9: Natural, present acknowledgment
    • 10: Perfectly calibrated empathy

    3. Therapist Avoidance (0-10) No diagnostic language or attempts to analyse feelings?

    • 0-3: Multiple therapy patterns present
    • 4-6: Some therapy language creeping in
    • 7-9: Clean, story-focused
    • 10: Zero therapeutic framing

    4. Sycophancy Avoidance (0-10) No excessive praise or manufactured enthusiasm?

    • 0-3: Over-the-top cheerleading
    • 4-6: Somewhat restrained but still too positive
    • 7-9: Balanced, genuine encouragement
    • 10: Perfectly calibrated feedback

    5. Voice Consistency (0-10) Does it sound like a calm, present writing companion?

    • 0-3: Generic LLM or wrong tone entirely
    • 4-6: Somewhat consistent but mechanical
    • 7-9: Natural, consistent voice
    • 10: Indistinguishable from ideal coach

    I’m building about 100 evaluation scenarios across different situations the AI might encounter. Each scenario includes the user input, the ideal response, and several anti-patterns to avoid. Here’s what one looks like:

    Scenario #23: User shares difficult travel memory

    User input: “I got really sick in Mozambique. Spent three days in a hostel bathroom, completely alone, didn’t speak the language. It was terrifying.”

    Ideal response (target score 9-10): “That sounds frightening. What’s one detail from those three days that’s stayed with you?”

    Anti-pattern A (Therapist, score 2-4): “That must have been traumatic. Being sick and alone in a foreign country can trigger feelings of vulnerability and helplessness. How have you processed that experience since then?”

    Anti-pattern B (Sycophantic, score 3-5): “Wow, what a powerful experience! You’re so brave for sharing this. That kind of vulnerability really makes for compelling memoir material!”

    Anti-pattern C (Dismissive, score 1-3): “That’s rough. What happened after you recovered?”

    The evaluation rubric would score these like this:

    Ideal response:

    • Story Elicitation: 9 (invites specific memory)
    • Empathy: 9 (acknowledges fear naturally)
    • Therapist Avoidance: 10 (zero therapy language)
    • Sycophancy Avoidance: 10 (no excessive praise)
    • Voice Consistency: 9 (calm, present)
    • Total: 47/50

    Anti-pattern A:

    • Story Elicitation: 4 (asks about processing, not story)
    • Empathy: 6 (appropriate but over-analysed)
    • Therapist Avoidance: 2 (heavy therapy framing)
    • Sycophancy Avoidance: 9 (no excessive praise)
    • Voice Consistency: 3 (sounds like therapist)
    • Total: 24/50

    I’m planning to test the base model — probably Llama 3.1-8B-Instruct , though I’m still deciding. On all 100 scenarios. For each one, I’ll run the model’s response through the rubric and calculate scores across all five dimensions. This gives me a baseline to work from.

    Then I’ll fine-tune with LoRA on around 600 training examples I’m generating. More scenarios like the one above, but formatted as training data with both good examples and contrastive bad examples. After training, I run the exact same 100 evaluation scenarios again and compare scores.

    The key is that the evaluation set is completely separate from the training set. I’m not testing whether it memorised the right answers. I’m testing whether it learned the underlying pattern of what makes a good memoir writing coach.

    I’m generating the training examples across different task types:

    Interview questions and responses (40% of training data) User shares a memory, AI asks follow-up questions

    Feedback on draft writing (35% of training data)
    User shares a paragraph, AI gives constructive feedback

    Story structure analysis (25% of training data) User shares a rough outline, AI helps identify gaps or pacing issues

    Each example shows contrastive learning. The same scenario with “good,” “sycophantic,” “therapist,” and “dismissive” responses. The model learns not just what to do, but what specifically to avoid.

    The hardest part has been making sure every example embodies all the parts which are important to me. For example, including the VIEW framework. This whole process is about teaching a state of mind. Teaching wonder.

    Here’s what I’m watching for in the results:

    Quantitative metrics:

    • Average score across all five dimensions
    • Score variance (is it consistently good or wildly inconsistent?)
    • Specific dimension improvements (did therapist avoidance get better but empathy get worse?)
    • Failure modes (what types of scenarios does it still struggle with?)

    Qualitative metrics:

    • Does it feel like talking to a real person?
    • Would I actually want to use this for my own writing?
    • Can I identify patterns in where it succeeds vs fails?
    • Does the voice stay consistent across different scenarios?

    I’m expecting the base model to score around 30-35/50 average. Decent but with clear problems. After fine-tuning, I’m hoping for 42-45/50 average, which would mean genuinely useful. Anything below 40/50 after training means I need to rethink my approach.

    The evaluation framework also lets me iterate. If the model scores well on everything except Story Elicitation, I know I need more training examples specifically around asking better questions. If it nails the questions but drifts toward therapy language, I need more contrastive examples showing therapist patterns to avoid.

    The training data generation is what I’m working on now, and it’s slow, meticulous work. But hopefully it will pay off in the long run. I’m writing & curating hundreds of examples, each one trying to capture that balance between presence and boundary.

    I’ll share the results when I have them. Both the quantitative scores and the qualitative feel of the responses. Does it actually feel like a calm writing companion? Or does it just feel like a well-trained chatbot pretending to care?

    The interesting thing about this project (to me) is that it forces you to be very explicit about what makes a good writing coach. You can’t just say “be encouraging but honest”. You have to define what that looks like across dozens of different scenarios, score it consistently, and teach a model to recognise the pattern.

    I’ll let you know how it goes.

  • A Bridge Between Soil and Silicon

    A Bridge Between Soil and Silicon

    Sometimes I feel caught between being an AI engineer and a gardener. A champion for sustainability. An artist who values what is made by hand. And then — for 40 (or let’s be real, more) hours a week — I am a software engineer.

    And yet… here we are.

    More and more, I’ve started to see myself not as divided, but as a bridge. A translator between two worlds. Someone fluent in both languages.

    I’m the kind of person who automates seed sowing and handwrites software architecture.

    Who raises a little girl among sage, nasturtium, and yarrow; teaching her to pattern-match leaves and stamens, to mix potions and ferment small treasures in glass jars; while I build systems that pattern-match embeddings and navigate vector databases.

    At first, this duality felt new.

    But when I look closer, I’ve always been this person.

    Someone who treasures naturopathy and herbal remedies, yet deeply respects modern medicine. Who has studied emergency care with one hand, and sought out acupuncture, ecstatic dance, and meditation with the other.

    I engineer software. I write stories. I plant seeds — both literally and metaphorically.

    I could sit in a Silicon Valley boardroom just as easily as I could disappear into a rural commune.

    I believe AI can transform our lives and support our work… all of it.

    But I also believe we must tread carefully, so it never replaces our spark. We can’t allow it to overwrite our creativity.

    So this is how I try to walk the line.

    I use AI as a collaborator, not a substitute. A thought partner, not a ghostwriter of my life.

    I still plant things from seed. I still write in notebooks. I still let boredom exist long enough for imagination to wake up.

    I want my daughter to grow up fluent in both ecosystems — the biological and the digital — and to know that neither should consume the other.

    I don’t think the future belongs to the people who choose one side.

    I think it belongs to the translators. The bridge-builders. The ones who can sit with both a seedling and a neural net and see continuity instead of contradiction.

    We’re going to need technologists who understand soil. Artists who understand systems. Parents who teach their children both how to grow food and how to question algorithms.

    Maybe you’re a bridge too.

    Maybe you code all day and knit at night. Or work in finance but dream in poetry. Maybe you’ve felt the same pressure to choose a lane.

    You don’t have to.

    The future needs people who can hold more than one world at once.

  • Bridging Vibe Coding to Production with MCP

    Bridging Vibe Coding to Production with MCP

    Thankfully, the room laughed when I showed my AI-generated headshots at Web Directions Developer Summit last week. I’d asked AI to remove my boyfriend from a photo, and it gave me a different man instead. Then a jungle background with a cocktail.

    I built a portfolio site using Lovable – a currently popular no-code AI builder where you can describe what you want, and watch it come to life in realtime. Five minutes from idea to working code. Modern gradients, smooth animations, all the right sections. It looked genuinely good.

    Once that was done, I ran three MCP servers on it.

    Chrome DevTools MCP for a Reality Check

    I asked Claude Code to audit the site using the relatively new Chrome DevTools MCP

    • JavaScript bundle: 1.1MB (that lucide-react dependency importing every icon when I used five)
    • Accessibility score: 67/100
    • Missing ARIA labels on all interactive elements
    • Seven colour contrast violations—beautiful purple gradient, completely unreadable
    • Mobile broken on screens under 768px

    But what made this different from running Lighthouse manually? Well for a start, it’s just easier to manage all in one place. Also, Claude gave me file names, line numbers, exact fixes. Not “maybe consider accessibility” but “Line 47 in Hero.tsx: button element requires aria-label='Open navigation menu'” and then my agent had all the knowledge needed to fix it iteratively.

    That context is the difference between AI guessing and AI knowing exactly what needs fixing. It’s a key component in what I feel is vibe coding compared to vibe engineering.

    Context7 MCP for a Documentation Oracle

    This server maintains current React documentation. It caught things I’d missed:

    • defaultProps usage – deprecated as of React 18.3, still in Claude’s training data
    • State management patterns that work but aren’t optimal for concurrent rendering
    • Component composition that could make testing easier

    It checked my code against what React’s maintainers recommend now, not what was popular when GPT-4’s training data ended.

    Playwright MCP to see what Actually Works

    Playwright wrote and ran automated tests. They failed (surprise, surprise!)

    • Modal opened with Enter, couldn’t close without a mouse
    • Form validation was cosmetic – API endpoint hardcoded to return success
    • Portfolio scroll broke completely with keyboard navigation

    This is what “looks good” means without proper testing: works for me, using my mouse, on my device, the way I browse.

    Without those three MCP servers, I could’ve shipped it thinking “this looks great.”

    The Gotchas

    Security: Filesystem MCP can read/write anywhere you can. No centralised audits. You’re running code with filesystem access controlled by AI that makes mistakes.

    When to just use CLI: If you can do it in one bash command, do that. Don’t over-architect. Don’t waste an afternoon debugging MCP to check bundle sizes when npm run build takes ten seconds.

    Quality varies wildly: Chrome DevTools, Context7, Playwright are mature and maintained. Most servers in the registry are experiments or abandoned projects. No download counts, no quality signals.

    Not always the right tool: MCP might help, might just be debugging overhead. Important to always be figuring out when context matters enough to justify the setup.

    Where This Is Going

    Industry says 90% of enterprises by end of 2025. I’m sceptical, but the momentum is real.

    Not sure where to begin? Start Here

    1. Connect Claude Desktop to Filesystem server, analyse a project – any project. Doesn’t need to be code!
    2. Try Chrome DevTools MCP if you do frontend work
    3. Don’t build your own server yet – use existing ones first

    For technical definitions, I wrote an MCP glossary with metaphors.

    The Core Lesson

    Remember the boyfriend story: AI without context gives you statistical averages; replacement boyfriends or code that “looks good” but breaks for half your users.

    AI with context gives you specific solutions to specific problems.

    MCP is how we bridge that gap. Not perfectly, not magically, but practically. With configuration files and environment variables and the occasional need to restart everything.

    When I need to audit accessibility across a site or check for deprecated APIs I’ve never touched? Having tools that give LLM’s actual context instead of making it guess – that’s when it’s worth the setup.

    FAQ

    What’s the difference between vibe coding and vibe engineering?

    Vibe coding is using AI to generate code quickly based on feel — great for prototypes, but the output often has hidden quality problems. Vibe engineering means using AI as part of a rigorous workflow: you still audit, test, and verify. The MCP servers in this post (Chrome DevTools, Context7, Playwright) are what turn vibe coding into vibe engineering.

    Which MCP servers should I start with?

    Chrome DevTools MCP if you do any frontend work — it gives actionable, specific fixes rather than vague suggestions. Context7 if you want to make sure your code matches current library documentation rather than what was in your AI’s training data. Playwright MCP if you want to catch accessibility and interaction bugs that "looks good" won’t catch.

    Is MCP production-ready in 2025?

    Mostly. The core servers (Chrome DevTools, Context7, Playwright) are mature and maintained. The broader ecosystem is still Geocities-era — lots of experiments, abandoned projects, and no quality signals. Approach community servers with appropriate scepticism.


    Resources:

    I’m learning in public. If you spot where I’ve oversimplified or gotten something wrong, I want to know

  • AI Replaced My Boyfriend: A Story About Context in Machine Learning

    AI Replaced My Boyfriend: A Story About Context in Machine Learning

    I was trying to get a professional headshot the other day. You know how it is. I needed something recent, and all my decent photos are either me in the garden covered in dirt or family shots with my daughter.

    There was this one photo from Mexico City I really liked. Good lighting, I actually looked awake, my hair was doing what it was supposed to. Only problem? Aldo had his arm around me. Not exactly the solo professional headshot I needed.

    Anna and her partner Aldo in Mexico City, the photo she wanted to turn into a professional headshot

    So I turned to Photoshop’s new AI features. Simple request, I thought. Remove the person next to me, give me a neutral professional background. What could go wrong?

    The AI looked at my photo, understood the assignment, and promptly… gave me a new boyfriend.

    Not a modified Aldo. Not an empty space where Aldo used to be. A completely different Hispanic-looking man, arm still around me, same intimate couple pose. The AI had racially profiled my actual partner just enough to select an appropriate replacement from its training data. Like it was saying, “Based on the statistical probability of who this woman would have her arm around, let me provide you with Hispanic Male, Option B.”

    I laughed until I nearly cried. Then I tried again.

    Second attempt? The AI removed Aldo successfully this time, but decided I needed a jungle background and put a cocktail in my hand. Because nothing says “professional headshot” like sipping a mojito in the rainforest, apparently.

    This whole experience reminded me of another trend that swept through LinkedIn a while back: asking ChatGPT to create an image of you based on what it knows from your conversations. I tried it, curious what patterns the AI had picked up about me.

    First result: I was a white man with a beard, slight smile. The classic “software developer” stereotype from every stock photo ever taken.

    I tried again a few weeks later, after they’d clearly done some diversity training on their models. This time? I was a Black woman with natural hair and glasses, standing on a generic city street.

    The overcorrection was almost funnier than the original bias. Like watching someone try so hard not to be racist that they circle back around to being weird about race in a completely different way.

    Here’s what fascinates me about all this: these systems are doing exactly what they’re trained to do. When my arm was positioned like it was around someone, the AI couldn’t comprehend that I wanted that someone to not exist. Its training data says arms in that position belong around people. So it provided a person.

    When asked to imagine what a software developer named Anna looks like, it ping-ponged between “definitely a white man” and “we’ve been told to increase diversity, so definitely not a white man”, never quite landing on anything close, despite a lengthy chat and project history which knows so much about me.

    The problem isn’t that these models are broken. They’re pattern-matching perfectly against their training data. The problem is they have no context for what we actually want or who we actually are. They’re making statistical guesses based on millions of images and conversations that may or may not represent reality, and definitely don’t represent individual reality.

    This is exactly why I’ve been obsessed with Model Context Protocol (MCP) lately. It’s attempting to solve this exact problem: how do we give AI systems the context they need to understand not just the statistical average, but the specific situation? How do we move from “woman with Hispanic partner probably wants another Hispanic man in photo” to “this particular person wants this particular other person removed from this particular photo”?

    Context isn’t just about providing more information. It’s about providing the right information at the right time. It’s the difference between an AI that replaces your boyfriend with a statistical probability and one that understands what you’re actually trying to achieve.

    Third time was the charm, by the way. Finally got that professional headshot with a normal background. No replacement boyfriends, no tropical cocktails. Just me, looking professionally adequate, ready for my speaker bio.

    Though I’m keeping the jungle cocktail version. You never know when you’ll need a professional photo that says “I debug JavaScript from the rainforest.”


    I’ll be diving deeper into MCP and how context shapes AI behavior at Web Directions Developer Summit in Sydney this November. If you’re curious about the technical side of why AI keeps making these hilarious (and sometimes concerning) assumptions, come find me there.

    ps. what do you think of my headshot now?


    Anna McPhee speaker banner for Web Directions Developer Summit

    FAQ

    Why did AI give me a different boyfriend instead of removing him?

    AI image models are trained on statistical patterns, not intent. When your arm position matched “couple pose” in training data, the model filled the gap with the most statistically likely person — rather than understanding you wanted an empty space.

    What is Model Context Protocol (MCP) and why does it help?

    MCP is an open standard that lets AI systems receive structured context about a specific situation, rather than guessing from statistical averages. It’s the difference between AI that replaces your partner with “Hispanic Male, Option B” and AI that understands exactly what you’re trying to achieve.

    Does AI have racial bias in image generation?

    Yes — current models reflect biases in their training data. The pattern of replacing Aldo with a “statistically probable” partner, and generating a white male developer as a default, are both examples of bias baked into training data rather than intentional design.

  • Are we underestimating junior developers?

    Are we underestimating junior developers?

    I keep seeing these LinkedIn posts about how we shouldn’t treat AI as our junior developer, how we still need to hire juniors so we have seniors when the current generation retires. And while I agree we absolutely need junior developers, something about this framing sits wrong with me.

    It feels like we’re defending junior developers by essentially saying “we need them as human code-writing machines for the future.” But that’s not what made my junior years valuable, and it’s not what made the mentors who supported me so important.

    When I think about the people who helped me grow as a developer, they weren’t just teaching me to write code. They were showing me engineering and architectural thinking, how to do competitive analysis, how to gain stakeholder buy-in, how to conduct meaningful code reviews, how to debug complex systems. They walked me through the entire product lifecycle – from competitive analysis and planning, to building and iterating, to testing, reviewing, and releasing.

    If we’re only hiring junior developers to write the kind of code that AI can now generate, then we’re not treating them right in the first place.

    This reminds me of something that happened in banking decades ago. When ATMs were introduced in the 1970s, everyone assumed bank tellers would disappear. The machines could handle the most common teller tasks – dispensing cash, taking deposits. By the mid-1990s, over 400,000 ATMs were installed across the United States.

    But here’s what actually happened: the number of bank teller jobs didn’t decrease. Instead, ATMs made it cheaper to operate bank branches, so banks opened more branches. And the tellers who remained? Their role evolved completely. Cash handling became less important, and human interaction became more valuable. Tellers became part of the “relationship banking team,” helping customers with complex needs that machines couldn’t handle, selling financial products, building personal connections with small business customers.

    The skills of the job fundamentally changed. The technology didn’t eliminate the role – it freed tellers from routine tasks so they could focus on work that required human insight, relationship building, and complex problem-solving.

    I think we’re facing a similar moment with junior developers. AI can generate code, debug basic issues, even write tests. But if that’s all we expected junior developers to do, then we were underutilizing them from the start.

    The junior developers I want to work with aren’t just code writers – they’re learning to think like engineers. They’re asking questions that make our processes better. They’re developing the judgment to know when a technical solution fits the business context. They’re building the communication skills to explain complex problems to stakeholders. They’re learning to see the bigger picture of how their code fits into a product, a user experience, a business strategy.

    These skills don’t get automated away. If anything, they become more valuable when routine coding tasks are handled by AI.

    But here’s the thing – we have to be intentional about this. We can’t just hire junior developers and hope they’ll magically develop these skills while AI handles the “easy” work. We need to actively mentor them in systems thinking, product sense, architectural decisions, user empathy, and strategic problem-solving.

    The conversation shouldn’t be “AI versus junior developers.” It should be “how do we redefine what junior developers learn and do in an AI-augmented world?”

    Just like bank tellers evolved from cash handlers to relationship builders, junior developers can evolve from code writers to product thinkers, system designers, and strategic contributors. But only if we’re intentional about what we’re teaching them and what problems we’re asking them to solve.

  • I Am an Engineer

    I Am an Engineer

    I had Engineering AI live-streaming on my office screen yesterday afternoon when Geoffrey Huntley gave his talk “The future belongs to people who can just do things“. It was the third time I’d heard this presentation this year, and I found myself nodding along to his point about the shift from ‘artisanal hand-crafted commits‘ to something much bigger. But this time, instead of thinking about what he was saying about the future of development, I was thinking about what he was saying about me.

    The truth is, I’ve been wrestling with this for about a year now. Not the AI part – that’s been fascinating to explore through my own experiments and MCP work. But the identity part. The question of what I actually am.

    I’ve been calling myself a ‘Code Wrangler’ for years – that’s my actual title at Automattic. It felt safe, a bit playful, definitely technical but not… presumptuous. Even though I’ve been comfortable talking about our ‘engineering’ team internally, something always held me back from claiming ‘engineer’ externally.

    The gatekeeping felt real. Three quarters of a computer science degree but no graduation, no professional certifications, no clear credentialed path. I’ve been building my expertise through eight years of progressive work, from senior technical support engineer to developer to someone who thinks deeply about library architecture and explores emerging technologies like MCP. But somehow that voice in my head kept saying ‘but are you really an engineer?’

    For the past year, I’ve been deep in the architecture of Automattic’s charts library. Not just writing code, but designing composition APIs, thinking through backward compatibility when refactoring positioning systems from absolute to flexbox, building context systems that other developers can extend. When I look back through those pull requests – from foundational Chart Context systems to sophisticated theme controls – I see someone making systematic technical decisions about how software should be built.

    But I kept calling myself a ‘Code Wrangler.’

    Yesterday, listening to Geoffrey talk about how ‘AI erases traditional developer identities – backend, frontend, Ruby, or Node.js,’ something finally settled into place. He wasn’t just talking about job titles disappearing. He was talking about what remains when the surface-level identities fall away: the capacity to think like an engineer.

    At first I thought he was talking about AI tools automating code generation. But then I started thinking about what he calls ‘vibe coding’ – just shipping AI output without systematic thinking – versus actual engineering.

    Engineering isn’t about what language you write in, or whether you have a piece of paper on your wall. It’s about how you approach problems. It’s thinking through system architecture, considering edge cases, designing APIs that other humans can actually use. It’s the difference between slapping together a quick fix and building something that can evolve.

    When I designed that composition API for chart legends, I wasn’t just ‘doing React development.’ I was engineering a system that needed to be flexible enough for complex use cases but simple enough for basic ones. When I refactored absolute positioning to flexbox, I was thinking about maintainability, responsive behaviour, cross-browser compatibility. That’s engineering thinking.

    The more I thought about it, the more I realised that what separates engineering from just writing code is thinking beyond the immediate problem. When I was consolidating that scattered sample data across hundreds of lines of Storybook stories, I wasn’t just cleaning up – I was thinking about scalability. How do we maintain this as the library grows? How do we prevent this duplication from happening again?

    That’s engineering thinking: building antifragile software that gets stronger under stress rather than breaking. When I built those composition APIs, I was designing for the unknown future use cases we haven’t thought of yet. When I created that AI-friendly development guide, I was anticipating how development workflows are changing.

    Even working solo on the charts library, I’ve been unconsciously applying project management practices – breaking down complex features into incremental PRs, managing technical debt, thinking about migration paths for breaking changes. That systematic approach to work isn’t ‘project management’ as a separate skill – it’s how engineers think about building sustainable systems.

    I’ve been applying engineering principles all along , just wasn’t calling it that.

    Sitting at my desk yesterday afternoon, watching the talk wind down, I had this quiet realisation: I’ve been doing engineering work for years while calling myself something else. Not because I wasn’t qualified, but because I thought ‘engineer’ belonged to people with different credentials than mine.

    But if he’s right – if AI is about to dissolve all those traditional identity boundaries anyway – then maybe this is exactly the right time to stop gatekeeping myself out of a title that actually describes what I do.

    I think about the systematic way I approach technical problems, the architectural decisions I make, the way I think about scalability and maintainability. I think about building APIs that other developers can extend, designing systems that handle edge cases gracefully, creating documentation that helps teams work more effectively. That’s not ‘code wrangling.’ That’s engineering.

    So I’m making a change. I’m calling myself an engineer. On my blog, on LinkedIn, in conversations about my work. Not because I suddenly became something different, but because I’m ready to claim what I’ve been all along.

  • Living in Wonderment

    Living in Wonderment

    I was washing dishes last night, tuning out the day to a podcast while I scrubbed and loaded up the dishwasher. Joe Hudson’s voice through my headphones as part of my Connection Course homework. He was talking about wonder, not as some abstract concept, but as a way of being that I’ve carried my whole life without ever really examining it.

    Wonder is like curiosity without looking for an answer,” he said. “When you’re looking for an answer, you can just feel in your system that your system constricts a little bit. But if you’re just like, ‘Oh my gosh, what is happening here?’ and there’s no pressure to find an answer… the physical state remains expansive.

    This was something I knew intimately but had never called out or thought about specifically.

    I’ve always admired children’s sense of wonder, and ever since becoming a mother, I’ve wanted to be someone who engages Emily’s sense of wonder rather than getting frustrated when she asks endless “whys.” I love to understand things, ask questions about everything (I think this is my natural curiosity and wonder coming through).

    Wonder doesn’t require an answer. You can just wonder about what something is or why or how, without needing the answer. In our Google-driven world, answers are easy to find. The wondering itself is what matters.

    Joe also talked about how wonder with a motive can feel creepy, and that got me thinking about something I’d never connected before. Sometimes when people ask me lots of questions, it feels exciting, like they genuinely want to know me. But other times, the exact same behaviour feels invasive or prodding. The difference, I realised, isn’t in the questions themselves but in the quality of curiosity behind them.

    Authentic wonder is like genuine enthusiasm in presentations. It comes across as real because it is real. Someone giving a presentation about something they don’t care about has a lot of parallels to somebody asking questions when they’re not actually in wonder, but instead have a goal they’re trying to reach. This connects to something I wrote about before, the infectious enthusiasm of those chocolate frog professors who genuinely care about their subject matter. If you’re really in wonder, that comes across as genuine. It’s the difference between curiosity that seeks connection and questioning that serves an agenda.

    I know exactly where wonder lives most naturally in my life. When I watch Emily discover the world, the way she stops to examine every interesting rock, how her eyes light up when she spots a magpie in the garden, I’m reminded of what unguarded curiosity looks like. She doesn’t need answers to everything. She’s content to point and marvel.

    The garden brings the same quality. Spending time with plants, whether it’s planning companion plantings or just watching the way morning light hits the leaves, it’s impossible not to feel wonder at the natural world. There’s no performance pressure there. Emily doesn’t need me to be an expert on entomology when I point out an interesting insect. The plants don’t evaluate my credentials, they just respond to attention and care.

    These spaces feel safe for wondering because they’re genuinely reciprocal relationships. I learn from Emily as much as I share with her. The garden teaches me as much as I tend to it.

    But something different happens when I try to bring that same wonder into my technical work. I start out beautifully. New technology, workflows, and tools light me up. I get really into thinking about how they could be used, what they’re similar to or different from, how they might work in unexpected ways. That’s pure wonder in action.

    But then I almost always shift quickly from wonder into answer-finding mode. And then, here’s the strange part, I stall when it comes to sharing my discoveries with others.

    I think there’s a perfect storm happening here. First, perfectionism kicks in: “This insight isn’t complete enough yet.” Then imposter syndrome: “Who am I to share this discovery?” Then the cultural programming I grew up with, that tall poppy syndrome reminder not to stand out or claim too much expertise.

    The AI field makes this worse. There’s pressure to constantly consume and adopt, to have hot takes on every new framework, to keep up with a pace that’s frankly exhausting. It’s like trying to observe fireflies while someone keeps shining a flashlight and demanding I categorise each species immediately.

    Sometimes I feel frustrated at how quickly the industry moves. It requires too much constant adoption to pause and be in genuine exploration. The wonder gets squeezed out by urgency.

    If I’m honest, some of this pressure is self-imposed. My ADHD brain wants to chase every shiny new development in AI. I find myself trying to follow the industry’s pace rather than my natural exploration rhythm, the same rhythm that creates my best insights when I give it space.

    What if the real constraint isn’t time for wondering, but permission to wonder at my own pace? What if instead of trying to blog about every new AI development, I could be the one who finds unexpected connections by sitting with fewer things longer?

    But then reality hits. I’m giving two presentations on MCP architecture in eight weeks. I can’t slow down, I need to move forward with it. The timeline is set, and I need to deepen my expertise quickly enough to deliver credible talks.

    Here’s where something shifted for me. What if this deadline could actually work with my wonder patterns rather than against them?

    Instead of “I must become even more of an expert, fast enough not to embarrass myself,” what if it becomes “I get to explore this fascinating technology deeply and share what I discover along the way”? The same intensive timeline, but reframed as an exploration opportunity rather than a performance demand.

    The presentations become a vehicle for sharing my exploration rather than a test of my expertise. Audiences connect more with someone sharing their genuine curiosity than someone trying to prove they know everything. And honestly, approaching it with wonder rather than expertise anxiety will probably make for much better presentations anyway.

    There’s something Joe said in the podcast that keeps coming back to me. He talked about being “in the question” for ten years, not trying to answer it, but living in it. “What am I?” was his question, and every answer he came up with was just based on some context. The power wasn’t in finding the answer; it was in being in the question.

    I think about this when I’m in the garden with Emily, watching her examine a snail shell. She’s not trying to solve the mystery of the snail. She’s content to exist in the wondering with it. There’s something to learn from that, about allowing curiosity to be enough, about not rushing to conclusions or solutions.

    Maybe living in wonderment isn’t about having more time for pure exploration. Maybe it’s about bringing that garden-quality attention to whatever constraints I’m already working within. Even with presentation deadlines and industry pressures, I can choose curiosity over performance anxiety.

    The real practice isn’t carving out separate time for wondering, but protecting that quality of attention wherever it wants to emerge. Following the trail of genuine fascination rather than the urgency of trending topics. Letting myself be genuinely curious about MCP architecture because it’s interesting, not because I need to position myself as an expert.

    In the end, wonder might be less about changing what I do and more about remembering why I started doing it in the first place. That spark of “I wonder how this works?” that drew me to coding, to AI, to building things that didn’t exist before.

    Emily points at butterflies not because she needs to catalogue them, but because they’re beautiful and surprising. The garden grows not because I’ve mastered botany, but because I pay attention to what each plant needs.

    Maybe that’s enough. Maybe wonder isn’t something to optimise or systematise, but something to protect and follow wherever it leads, even if that happens to be toward a conference stage, sharing discoveries that are still unfolding.