<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mika Flowers</title>
    <description>The latest articles on DEV Community by Mika Flowers (@mikachu).</description>
    <link>https://dev.to/mikachu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4120886%2F5d1b9ce7-6321-409e-98bd-d4ad78e2a965.png</url>
      <title>DEV Community: Mika Flowers</title>
      <link>https://dev.to/mikachu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mikachu"/>
    <language>en</language>
    <item>
      <title>I Applied to 59 Tech Jobs in 14 Days. Here's What Actually Happened</title>
      <dc:creator>Mika Flowers</dc:creator>
      <pubDate>Thu, 01 Oct 2026 11:07:11 +0000</pubDate>
      <link>https://dev.to/mikachu/i-applied-to-59-tech-jobs-in-14-days-heres-what-actually-happened-46lp</link>
      <guid>https://dev.to/mikachu/i-applied-to-59-tech-jobs-in-14-days-heres-what-actually-happened-46lp</guid>
      <description>&lt;p&gt;A little over two weeks ago, I started seriously looking for a job in tech again.&lt;/p&gt;

&lt;p&gt;Not bookmarking jobs.&lt;/p&gt;

&lt;p&gt;Not tweaking my LinkedIn headline for the fifteenth time.&lt;/p&gt;

&lt;p&gt;Actually applying.&lt;/p&gt;

&lt;p&gt;Software engineer. Technical writer. Support engineer. Implementation engineer. Developer relations. Full stack. Frontend. Python. Anything that seemed reasonably connected to the strange collection of skills I've built over the last few years.&lt;/p&gt;

&lt;p&gt;After enough applications, something started happening to my perception of the search.&lt;/p&gt;

&lt;p&gt;I would apply to five jobs and feel like I'd applied to fifty.&lt;/p&gt;

&lt;p&gt;A rejection would show up and somehow feel more important than the ten applications still sitting unanswered.&lt;/p&gt;

&lt;p&gt;A few quiet days would turn into:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nobody is going to give me a chance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I decided to stop judging the job search by how it felt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc5fb78utnoemyv0r23ir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc5fb78utnoemyv0r23ir.png" alt="Late-night desk with a laptop showing a color-coded spreadsheet and a notebook filled with tally marks" width="775" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I went through my emails, LinkedIn notifications, ZipRecruiter messages, and applications that had gone to another email account.&lt;/p&gt;

&lt;p&gt;Then I started counting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7phzt615f0qrjcxnl30l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7phzt615f0qrjcxnl30l.png" alt="Timeline chart of job applications submitted each day from September 17 to September 30" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Applications submitted during the first two weeks: 58 of the 59 have a verified submission date (Sept 17-30).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  59 applications in 14 days
&lt;/h2&gt;

&lt;p&gt;My current job hunt really started on September 17.&lt;/p&gt;

&lt;p&gt;Between September 17 and September 30, I can verify &lt;strong&gt;59 separate job applications&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I deduplicated them. If LinkedIn sent me an application confirmation and the company's ATS sent another one five minutes later, that's still one application.&lt;/p&gt;

&lt;p&gt;As of October 1, the traditional application funnel looks like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Outcome&lt;/th&gt;
&lt;th&gt;Count&lt;/th&gt;
&lt;th&gt;Share&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Applications&lt;/td&gt;
&lt;td&gt;59&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Confirmed rejections&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;~10%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Technical screenings&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;~2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interviews&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;~2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No substantive response yet&lt;/td&gt;
&lt;td&gt;51&lt;/td&gt;
&lt;td&gt;~86%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn93pm9ngrgu2jfizd4pl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn93pm9ngrgu2jfizd4pl.png" alt="Chart of the application funnel: 59 applications, 6 rejections, 1 screening, 1 interview, 51 with no substantive response" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is another important number:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1 paid technical writing gig with Sinch.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm not counting Sinch as an application, interview, or offer in those 59.&lt;/p&gt;

&lt;p&gt;It came through a different path.&lt;/p&gt;

&lt;p&gt;Honestly, that might be the most interesting part of this entire experiment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Most applications have done absolutely nothing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd9wc4sf44uptbdugx7o9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd9wc4sf44uptbdugx7o9.png" alt="Chart of the 51 unanswered applications grouped by how long they have been waiting" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you look only at the traditional application funnel, the biggest category isn't rejection.&lt;/p&gt;

&lt;p&gt;It's silence.&lt;/p&gt;

&lt;p&gt;As of October 1, &lt;strong&gt;51 of my 59 applications had not produced a substantive response&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's about 86%.&lt;/p&gt;

&lt;p&gt;But that number needs context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;23 applications were submitted on September 29 or September 30&lt;/strong&gt;, right at the end of this two-week window.&lt;/p&gt;

&lt;p&gt;All 23 were still waiting for a substantive response when I took this snapshot.&lt;/p&gt;

&lt;p&gt;Calling those applications "ghosted" would make for a more dramatic article, but it wouldn't be accurate.&lt;/p&gt;

&lt;p&gt;Some of them were barely 24 hours old.&lt;/p&gt;

&lt;p&gt;The more interesting number is on the other end of the timeline.&lt;/p&gt;

&lt;p&gt;Of the 51 applications still waiting for a real response, &lt;strong&gt;20 had already been sitting for at least a week&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So both things are true.&lt;/p&gt;

&lt;p&gt;A large chunk of the silence is simply too fresh to judge.&lt;/p&gt;

&lt;p&gt;But a meaningful chunk isn't.&lt;/p&gt;

&lt;p&gt;That's one of the first things the data corrected for me.&lt;/p&gt;

&lt;p&gt;When you're applying every day, all unanswered applications start feeling the same.&lt;/p&gt;

&lt;p&gt;They aren't.&lt;/p&gt;

&lt;p&gt;An application from yesterday and an application from twelve days ago may both say "pending," but emotionally and statistically they're very different things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six applications ended in rejection
&lt;/h2&gt;

&lt;p&gt;So far, I've received six confirmed rejections.&lt;/p&gt;

&lt;p&gt;One was for a Developer Relations position.&lt;/p&gt;

&lt;p&gt;Some companies responded remarkably quickly. One rejected me the same day I applied. Another viewed my application first and rejected me several days later.&lt;/p&gt;

&lt;p&gt;A few applications also generated "your application was viewed" notifications without progressing any further.&lt;/p&gt;

&lt;p&gt;And weirdly, I don't mind the rejections nearly as much as I expected.&lt;/p&gt;

&lt;p&gt;A rejection contains information.&lt;/p&gt;

&lt;p&gt;They received the application.&lt;/p&gt;

&lt;p&gt;Something happened.&lt;/p&gt;

&lt;p&gt;The answer was no.&lt;/p&gt;

&lt;p&gt;That sucks, but at least the loop closes.&lt;/p&gt;

&lt;p&gt;The silence is stranger.&lt;/p&gt;

&lt;h2&gt;
  
  
  One application turned into an interview
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsjpnrqqxbve8k3m8lt6f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsjpnrqqxbve8k3m8lt6f.png" alt="Chart of applications by role type" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On September 24, I applied for a Technical Writer position.&lt;/p&gt;

&lt;p&gt;A few hours later, I received an email asking me to schedule an interview.&lt;/p&gt;

&lt;p&gt;Four days later, I interviewed.&lt;/p&gt;

&lt;p&gt;That was my first actual interview from this batch, and it came from one of the smaller categories in my search.&lt;/p&gt;

&lt;p&gt;Most of my applications haven't been for technical writing.&lt;/p&gt;

&lt;p&gt;They've been for software engineering.&lt;/p&gt;

&lt;p&gt;Out of the 59:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role type&lt;/th&gt;
&lt;th&gt;Applications&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Software engineering/development&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Technical writing/content&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Support, implementation, or solutions&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Other adjacent roles&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So more than 70% of my applications have been for software-development jobs.&lt;/p&gt;

&lt;p&gt;My first interview came from one of the eight writing-oriented applications.&lt;/p&gt;

&lt;p&gt;I'm not ready to turn that into a career conclusion.&lt;/p&gt;

&lt;p&gt;Eight applications and one interview make for an absurdly small sample size.&lt;/p&gt;

&lt;p&gt;But it is a signal I'm going to keep watching.&lt;/p&gt;

&lt;h2&gt;
  
  
  One application produced a technical screening
&lt;/h2&gt;

&lt;p&gt;One company sent me a technical screening for a Python/JavaScript full-stack position.&lt;/p&gt;

&lt;p&gt;I don't count that as an interview, but I do count it as movement.&lt;/p&gt;

&lt;p&gt;This distinction matters because I'm trying to understand &lt;strong&gt;where the funnel actually breaks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If nobody opens my applications, that's one problem.&lt;/p&gt;

&lt;p&gt;If employers open them but don't move me forward, that's another.&lt;/p&gt;

&lt;p&gt;If I reach interviews and fail there, that's a completely different problem.&lt;/p&gt;

&lt;p&gt;"Nobody will hire me" isn't actionable.&lt;/p&gt;

&lt;p&gt;"Very few applications are reaching human conversations" is.&lt;/p&gt;

&lt;p&gt;That is something I can investigate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then there's Sinch
&lt;/h2&gt;

&lt;p&gt;This is where the spreadsheet gets more interesting.&lt;/p&gt;

&lt;p&gt;During the same period that I was sending dozens of traditional applications into hiring systems, I also landed &lt;strong&gt;paid technical writing work with Sinch&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That opportunity doesn't belong in the 59-application funnel, so I'm not going to manipulate the numbers and call it a job offer.&lt;/p&gt;

&lt;p&gt;But leaving it out of the story would also be dishonest.&lt;/p&gt;

&lt;p&gt;Because while one part of my career strategy looked like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Apply → ATS → wait → maybe hear back&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;another part looked very different:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build things → write about things → show people what I know → get paid to write technical content&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And one of those paths has already produced paid work.&lt;/p&gt;

&lt;p&gt;Again, I'm not claiming I've discovered the secret to getting hired.&lt;/p&gt;

&lt;p&gt;I haven't.&lt;/p&gt;

&lt;p&gt;But this is exactly why I wanted to start tracking the search instead of just counting the resumes I sent.&lt;/p&gt;

&lt;p&gt;The goal isn't applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal is opportunities.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My job search is actually two experiments
&lt;/h2&gt;

&lt;p&gt;I didn't realize this when I started, but I'm running two career experiments at the same time.&lt;/p&gt;

&lt;p&gt;The first is the traditional one.&lt;/p&gt;

&lt;p&gt;Can I take my experience, projects, freelance development work, open-source work, and self-taught background and turn it into a full-time software or technical-writing job through normal applications?&lt;/p&gt;

&lt;p&gt;That's the 59-application experiment.&lt;/p&gt;

&lt;p&gt;The second is different.&lt;/p&gt;

&lt;p&gt;Can building things publicly and writing about what I learn create enough evidence of what I can do that opportunities start finding me another way?&lt;/p&gt;

&lt;p&gt;Sinch belongs to that experiment.&lt;/p&gt;

&lt;p&gt;So does my technical writing.&lt;/p&gt;

&lt;p&gt;So do my open-source projects.&lt;/p&gt;

&lt;p&gt;So does every article where I explain something I actually built instead of trying to convince somebody I'm passionate about technology in a cover letter.&lt;/p&gt;

&lt;p&gt;I don't know which path ultimately gets me where I'm trying to go.&lt;/p&gt;

&lt;p&gt;Maybe both will.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hardest part has been separating data from emotion
&lt;/h2&gt;

&lt;p&gt;I'm self-taught.&lt;/p&gt;

&lt;p&gt;I don't have a computer science degree.&lt;/p&gt;

&lt;p&gt;My career history isn't clean.&lt;/p&gt;

&lt;p&gt;I worked retail for years. I became a manager. I became a caregiver. I stepped away from a traditional career path. I taught myself development. I started building open-source software. I started writing.&lt;/p&gt;

&lt;p&gt;There is no obvious checkbox for that person.&lt;/p&gt;

&lt;p&gt;So when rejection emails start arriving, it's incredibly easy to interpret them as answers to much bigger questions.&lt;/p&gt;

&lt;p&gt;Maybe employers don't take self-taught developers seriously anymore.&lt;/p&gt;

&lt;p&gt;Maybe I'm too late.&lt;/p&gt;

&lt;p&gt;Maybe my projects aren't good enough.&lt;/p&gt;

&lt;p&gt;Maybe I don't belong here.&lt;/p&gt;

&lt;p&gt;But that's not what the data says.&lt;/p&gt;

&lt;p&gt;The data says:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I submitted 59 applications.&lt;/li&gt;
&lt;li&gt;Six rejected me.&lt;/li&gt;
&lt;li&gt;One sent me a technical screening.&lt;/li&gt;
&lt;li&gt;One interviewed me.&lt;/li&gt;
&lt;li&gt;51 haven't given me a substantive answer yet.&lt;/li&gt;
&lt;li&gt;20 of those unanswered applications had already been waiting at least a week.&lt;/li&gt;
&lt;li&gt;Outside that funnel, I landed paid technical writing work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's all I actually know.&lt;/p&gt;

&lt;p&gt;Everything else is interpretation.&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm changing how I think about the next two weeks
&lt;/h2&gt;

&lt;p&gt;I don't want the next checkpoint to simply say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I applied to 150 jobs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Volume matters, especially when response rates are low.&lt;/p&gt;

&lt;p&gt;But I want to get smarter about the volume.&lt;/p&gt;

&lt;p&gt;I want to see whether technical-writing roles continue producing stronger responses.&lt;/p&gt;

&lt;p&gt;I want to look at whether locally relevant roles behave differently from huge remote applicant pools.&lt;/p&gt;

&lt;p&gt;I want to track where employers actually view my application.&lt;/p&gt;

&lt;p&gt;I want to keep improving the software-engineering side instead of abandoning it because one technical-writing application happened to convert.&lt;/p&gt;

&lt;p&gt;And I want to keep building and publishing things.&lt;/p&gt;

&lt;p&gt;Because one of the clearest signals from the first two weeks isn't coming from the application spreadsheet at all.&lt;/p&gt;

&lt;p&gt;It's that showing my work can create opportunities too.&lt;/p&gt;

&lt;h2&gt;
  
  
  This isn't the 30-day conclusion
&lt;/h2&gt;

&lt;p&gt;It's Day 14.&lt;/p&gt;

&lt;p&gt;There are 51 applications whose stories haven't finished yet.&lt;/p&gt;

&lt;p&gt;Some will probably disappear forever.&lt;/p&gt;

&lt;p&gt;Some will reject me next week.&lt;/p&gt;

&lt;p&gt;Maybe a couple will turn into interviews.&lt;/p&gt;

&lt;p&gt;And I'll keep applying while all of that happens.&lt;/p&gt;

&lt;p&gt;On Day 30, I'm going back through the entire dataset.&lt;/p&gt;

&lt;p&gt;Same applications.&lt;/p&gt;

&lt;p&gt;Same methodology.&lt;/p&gt;

&lt;p&gt;Then we'll see what the funnel actually looks like once it's had enough time to breathe.&lt;/p&gt;

&lt;p&gt;For now:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;59 applications.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6 rejections.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1 screening.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1 interview.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1 paid writing opportunity outside the application funnel.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And I'm still going.&lt;/p&gt;




&lt;p&gt;If you've been through a job search, what did your funnel look like? I'd like to compare notes before Day 30.&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>devjournal</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The Version of Me Who Looks Better on Paper Doesn't Exist</title>
      <dc:creator>Mika Flowers</dc:creator>
      <pubDate>Wed, 30 Sep 2026 11:09:16 +0000</pubDate>
      <link>https://dev.to/mikachu/im-not-asking-you-to-pretend-im-qualified-3bg5</link>
      <guid>https://dev.to/mikachu/im-not-asking-you-to-pretend-im-qualified-3bg5</guid>
      <description>&lt;p&gt;When I think about what it means to be unconventional, to learn to figure things out on your own, I see a version of myself staring right back at me.&lt;/p&gt;

&lt;p&gt;I did not graduate high school and later earned my GED. I did not graduate with a computer science degree, walk across a stage, land an internship, and slide neatly into a junior developer position. I spent years working retail. I became a manager. I took care of someone I loved. I stepped away from a traditional career path. I went through a software development training program and did not finish it.&lt;/p&gt;

&lt;p&gt;I taught myself anyway. I built things anyway. Somewhere in the middle of all that, I became the kind of person who could sit in front of a blank IDE and try to build something.&lt;/p&gt;

&lt;p&gt;I know there is a version of me that looks better on paper. Sometimes I think about her.&lt;/p&gt;

&lt;p&gt;She went to college at 18. She picked computer science immediately. She had internships every summer. She graduated at 22 with a GitHub full of class projects and a professor willing to write her recommendations.&lt;/p&gt;

&lt;p&gt;Her resume does not need explanations. There is no career break. There are no weird transitions. No unfinished training program. No years spent in retail and managing a grocery store. No caregiving. No awkward answer when someone asks why she didn't just take the normal route.&lt;/p&gt;

&lt;p&gt;In my honest opinion, she probably gets taken seriously a little faster.&lt;/p&gt;

&lt;p&gt;But she also doesn't exist.&lt;/p&gt;

&lt;p&gt;I do.&lt;/p&gt;

&lt;p&gt;And I am tired of feeling like I'm supposed to apologize for that. Like I have to show up ten times harder just to be seen on the same level.&lt;/p&gt;

&lt;h2&gt;
  
  
  I learned software development in pieces
&lt;/h2&gt;

&lt;p&gt;My education in technology has been scattered across years.&lt;/p&gt;

&lt;p&gt;Some of it came from formal training. A lot of it came from late-night YouTube tutorials. Some came from breaking things. Some came from staring at an error message until I finally understood what the computer was actually trying to tell me.&lt;/p&gt;

&lt;p&gt;Some came from building things nobody asked me to build. Some came from realizing halfway through a project that my architecture was terrible and rebuilding it.&lt;/p&gt;

&lt;p&gt;Some came from GitHub issues, code reviews, Stack Overflow threads, documentation, AI tools, other developers, and pure stubbornness.&lt;/p&gt;

&lt;p&gt;That education doesn't fit nicely inside a degree section, and I'm aware of that. It's not the prettiest.&lt;/p&gt;

&lt;p&gt;But it is real.&lt;/p&gt;

&lt;p&gt;I have worked with APIs, databases, React, Python, GTK, deployment infrastructure, CMS platforms, 3D environments, automation, and all the wonderfully annoying glue that holds software together.&lt;/p&gt;

&lt;p&gt;I have shipped software that other people use.&lt;/p&gt;

&lt;h2&gt;
  
  
  The suspicion of the self-taught
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnbspz5e24tx372oljpr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnbspz5e24tx372oljpr9.png" alt="learningnotebook" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My "Open Learning" Notebook where I document everything that I learn&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Being self-taught means constantly proving that you're not pretending. That you're not an imposter. That you earned the right to call yourself a dev as much as any four-year graduate. We just got there differently.&lt;/p&gt;

&lt;p&gt;There is a strange suspicion attached to being self-taught. A suspicion of yourself.&lt;/p&gt;

&lt;p&gt;People hear it and sometimes translate it into beginner. Or hobbyist. Or someone who copies tutorials.&lt;/p&gt;

&lt;p&gt;And when your path is unconventional enough, people start inspecting every part of you for evidence that you're not a "real" developer.&lt;/p&gt;

&lt;p&gt;Did you use AI? Did you finish the bootcamp? Where is your degree? How many years of professional experience do you have? Was that a personal project or a real project? Was your freelance work really freelance work? How many users? How many stars? How much revenue? How many commits? How many interviews?&lt;/p&gt;

&lt;p&gt;How many times do I have to prove I know how to build something before the conversation changes from:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Can she actually code?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"What could she build here?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are very different questions.&lt;/p&gt;

&lt;p&gt;I wish more people asked the second one.&lt;/p&gt;

&lt;h2&gt;
  
  
  And then there's my identity
&lt;/h2&gt;

&lt;p&gt;There is another part of this story that is harder to write about.&lt;/p&gt;

&lt;p&gt;I am a transgender woman.&lt;/p&gt;

&lt;p&gt;That should be one of the least interesting things about my ability to write software. It is not a programming language. It is not a framework. It doesn't change whether my code compiles.&lt;/p&gt;

&lt;p&gt;But it changes the room sometimes. Awkwardly, most of the time. I'm used to people tiptoeing around me.&lt;/p&gt;

&lt;p&gt;I have watched conversations change. Faces sink. I have felt people take me less seriously. I have been rejected in ways where I couldn't always prove exactly what happened, and in other situations where the message felt much less ambiguous. Many times, there was just silence. Nothing at all.&lt;/p&gt;

&lt;p&gt;That uncertainty does something to you.&lt;/p&gt;

&lt;p&gt;Because after enough rejection, you start asking questions you can't answer.&lt;/p&gt;

&lt;p&gt;Was my resume not good enough? Was my experience too unconventional? Was I too nervous? Was someone else simply better? Was it because I'm trans?&lt;/p&gt;

&lt;p&gt;You rarely get to know.&lt;/p&gt;

&lt;p&gt;You just get another email that says:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We decided to move forward with other candidates.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And somehow you're expected to smile, improve your resume, practice another LeetCode problem, rewrite another portfolio page, and apply again.&lt;/p&gt;

&lt;p&gt;Sometimes I can do that.&lt;/p&gt;

&lt;p&gt;Sometimes it fucking hurts.&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm tired of pretending rejection is always motivational
&lt;/h2&gt;

&lt;p&gt;There is an entire industry built around making rejection sound beautiful.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Every no gets you closer to a yes."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Keep grinding."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Your time will come."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I understand why people say those things. But sometimes rejection doesn't make you stronger. Sometimes it makes you sit on the edge of your bed and wonder whether you misunderstood your own potential. Sometimes it makes you open your GitHub, stare at months of work, and wonder why none of it seems to count.&lt;/p&gt;

&lt;p&gt;That feeling is especially brutal when you've already spent years rebuilding your life. My career break wasn't optional, yet I'm expected to make it pretty. To tell the recruiter how it was all for my own development and how much I overcame.&lt;/p&gt;

&lt;h2&gt;
  
  
  I lost time
&lt;/h2&gt;

&lt;p&gt;That is the part I struggle with the most.&lt;/p&gt;

&lt;p&gt;I feel behind. I know comparison is useless and careers aren't races. I still feel it. I look at people my age with six or seven years of engineering experience, senior titles, teams, and conference talks, and I'm sitting here trying to convince someone to give me the first real shot.&lt;/p&gt;

&lt;p&gt;There is grief in that. I don't think we talk about it enough. The grief of realizing how different your life might have looked if you'd known who you were sooner, or if circumstances had been different, or if somebody had opened the door a few years earlier.&lt;/p&gt;

&lt;p&gt;But I can't build a career out of the life I could have had.&lt;/p&gt;

&lt;p&gt;I only get this one.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I started building the proof myself
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftyodg61chhht2svy08t6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftyodg61chhht2svy08t6.jpg" alt="mochi" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At some point, waiting for permission stopped making sense. So I built things:&lt;/p&gt;

&lt;p&gt;I wrote about what I learned. People started reading. Then more people. People commented. People shared things.&lt;/p&gt;

&lt;p&gt;A community I had spent years being afraid I wasn't qualified to join started treating me like I belonged there.&lt;/p&gt;

&lt;p&gt;That mattered more than I expected.&lt;/p&gt;

&lt;p&gt;I still don't feel established. I'm still applying, still learning, still filling gaps in my knowledge, and I still read job descriptions and think, &lt;em&gt;maybe they mean someone else.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The difference now is that I have evidence. When the voice in my head says &lt;em&gt;you are not a real developer,&lt;/em&gt; I don't have to argue with feelings anymore. I can point at the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  My path is messy because my life was messy
&lt;/h2&gt;

&lt;p&gt;That doesn't make it worthless.&lt;/p&gt;

&lt;p&gt;Retail taught me how to communicate with people. Management taught me responsibility. Caregiving taught me patience in ways I never wanted to learn. Starting over taught me humility. Teaching myself software development taught me how to learn when nobody is standing beside me with a curriculum.&lt;/p&gt;

&lt;p&gt;Being transgender taught me something else entirely: sometimes you have to build a life before other people understand it.&lt;/p&gt;

&lt;p&gt;Maybe that's why software feels so natural to me. You start with something that doesn't exist. You imagine what it could become. Then you build it piece by piece, even when other people don't understand what you're making yet. Sometimes you barely understand it yourself.&lt;/p&gt;

&lt;p&gt;You keep going anyway.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcq6umd2778cftizog8e9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcq6umd2778cftizog8e9.png" alt="buildingagain" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  I do belong here
&lt;/h2&gt;

&lt;p&gt;I still hesitate when I write that. That probably tells you how deeply the opposite message can sink in.&lt;/p&gt;

&lt;p&gt;But I'm trying to stop asking permission. I don't need a perfectly linear career to be a developer. I don't need a computer science degree to care deeply about computer science. And I definitely don't need someone else's comfort with my identity to determine how seriously I take my own work.&lt;/p&gt;

&lt;p&gt;I have a lot left to learn.&lt;/p&gt;

&lt;p&gt;Good. That means I'm still growing.&lt;/p&gt;

&lt;p&gt;I'm not asking anyone to lower the bar. I'm asking for the chance to show what I can do.&lt;/p&gt;

&lt;p&gt;And if that chance takes longer to arrive than it should?&lt;/p&gt;

&lt;p&gt;Fine.&lt;/p&gt;

&lt;p&gt;I'll keep building while I wait.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;This took me a long time to write and even longer to publish. If it landed with you, thank you. If you're commenting, I'd appreciate kindness.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>beginners</category>
      <category>career</category>
      <category>learning</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Tech can feel weirdly isolating sometimes

If you’re around, come say hi. Tell me what you’re working on, what you’re learning, or literally just say hi.🫶🏽</title>
      <dc:creator>Mika Flowers</dc:creator>
      <pubDate>Wed, 30 Sep 2026 00:04:05 +0000</pubDate>
      <link>https://dev.to/mikachu/feeling-a-little-isolated-tonight-so-i-figured-id-throw-this-into-the-void-if-youre-around-293c</link>
      <guid>https://dev.to/mikachu/feeling-a-little-isolated-tonight-so-i-figured-id-throw-this-into-the-void-if-youre-around-293c</guid>
      <description></description>
      <category>community</category>
      <category>discuss</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>AI Is Making Me Faster. I Don’t Want It to Make Me Worse.</title>
      <dc:creator>Mika Flowers</dc:creator>
      <pubDate>Tue, 29 Sep 2026 15:50:08 +0000</pubDate>
      <link>https://dev.to/mikachu/ai-is-making-me-faster-i-dont-want-it-to-make-me-worse-3lc3</link>
      <guid>https://dev.to/mikachu/ai-is-making-me-faster-i-dont-want-it-to-make-me-worse-3lc3</guid>
      <description>&lt;p&gt;I use AI constantly when I code and when I write. I use it to research ideas, plan code, debug, explore unfamiliar APIs, review architecture, generate tests, explain weird behavior, and write chunks of code faster than I could manually.&lt;/p&gt;

&lt;p&gt;I also think it can make you worse at programming. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Those two statements are not contradictory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The problem isn't that AI writes code. The problem is that AI can remove the exact parts of programming that force us to remember, reason, struggle, and form mental models. If we outsource those parts often enough, our skills get rusty.&lt;/p&gt;

&lt;p&gt;So I've been thinking a lot about a question that feels much more useful than arguing about whether developers &lt;em&gt;should&lt;/em&gt; use AI:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do we use AI heavily without letting our own abilities decay?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I don't think the answer is using less AI. The best approach is to use AI &lt;strong&gt;deliberately&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Dangerous Part Isn't Generated Code
&lt;/h2&gt;

&lt;p&gt;Developers have always used abstractions and tools. One could argue that libraries degraded our ability to write everything from scratch without boilerplate. But we regularly use autocomplete, documentation, Stack Overflow, linters, frameworks, debuggers, IDEs, and code review built by people smarter than us.&lt;/p&gt;

&lt;p&gt;Nobody expects a web developer to manually implement TCP before they're allowed to use &lt;code&gt;fetch()&lt;/code&gt;. AI is just another abstraction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But there's one critical difference:&lt;/strong&gt; Most traditional tools remove &lt;em&gt;mechanical work&lt;/em&gt;. AI can remove &lt;em&gt;thinking&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Consider the difference between these two interactions:&lt;/p&gt;

&lt;h3&gt;
  
  
  Version A (Manual Debugging)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;You encounter a bug and read the error.&lt;/li&gt;
&lt;li&gt;You inspect the relevant code and form a hypothesis.&lt;/li&gt;
&lt;li&gt;You test it—and you're wrong.&lt;/li&gt;
&lt;li&gt;You inspect the state again.&lt;/li&gt;
&lt;li&gt;You eventually discover that an asynchronous callback inside a &lt;code&gt;forEach()&lt;/code&gt; loop isn't being awaited.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That process might take 20 minutes. But by the end of it, you've built a durable mental model of how asynchronous execution works in JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Version B (Delegated Debugging)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;You paste the function into an AI model: &lt;em&gt;"Fix this."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Five seconds later:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;It works. You move on. You didn't spend time digging through three-year-old Stack Overflow posts trying to figure out why your code was failing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In &lt;strong&gt;Version B&lt;/strong&gt;, productivity increased dramatically—but learning may have approached zero. I've been guilty of this myself, getting far too comfortable with &lt;code&gt;Ctrl+C&lt;/code&gt; &amp;amp; &lt;code&gt;Ctrl+V&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Tradeoff:&lt;/strong&gt; Friction wasn't always wasted time. Some of the annoying parts of programming were secretly forcing your brain to retrieve and manipulate information.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  10 Deliberate Strategies to Stay Sharp
&lt;/h2&gt;

&lt;p&gt;If convenience and learning aren't always aligned, the solution isn't to make programming artificially miserable again. It's deciding &lt;strong&gt;which friction is valuable&lt;/strong&gt; and actively preserving it.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Make a Prediction Before Asking AI
&lt;/h3&gt;

&lt;p&gt;This is the simplest habit to build. Before sending a bug or stack trace to an AI model, stop for 30 seconds and ask yourself: &lt;em&gt;What do I think is happening?&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; &lt;em&gt;"I think this state update is re-triggering the effect because the dependency array changes reference on every render."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now when you prompt the AI, you aren't passively receiving an answer—you're testing a mental model against evidence. Recognition is much easier than recall; without a prediction, it's easy to read a confident explanation, think &lt;em&gt;"Yeah, that makes sense,"&lt;/em&gt; and immediately forget it.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Ask for Explanations Before Solutions
&lt;/h3&gt;

&lt;p&gt;Instead of prompting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;❌ &lt;em&gt;"Fix this code."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Try prompting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;em&gt;"Explain what is causing this bug. Don't fix it yet."&lt;/em&gt;&lt;br&gt;
💡 &lt;em&gt;"Give me three likely causes and tell me what evidence would distinguish them."&lt;/em&gt;&lt;br&gt;
💡 &lt;em&gt;"Walk me through how you would debug this without changing the code."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This transforms the AI from a code vending machine into a debugging partner. &lt;/p&gt;

&lt;h3&gt;
  
  
  3. Don't Immediately Copy Generated Code
&lt;/h3&gt;

&lt;p&gt;Copying is fast, but when a concept is important, read the generated solution, &lt;strong&gt;close the AI tab&lt;/strong&gt;, and then implement the idea yourself.&lt;/p&gt;

&lt;p&gt;If the AI suggests introducing a state machine, extracting a service, or adding a memoization layer, reimplementing it forces you to translate the core concept into your own mental model. That’s harder than copy-pasting—which is exactly why it works.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Use AI as a Reviewer, Not an Author
&lt;/h3&gt;

&lt;p&gt;One of the most effective workflows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You write the implementation.&lt;/li&gt;
&lt;li&gt;AI reviews it.&lt;/li&gt;
&lt;li&gt;You decide which feedback matters.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Review this function for correctness, readability, edge cases, and unnecessary complexity. 
Don't rewrite it unless necessary.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps you responsible for generating the solution while using the AI as an automated second pair of eyes.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Make Yourself Explain the Generated Code
&lt;/h3&gt;

&lt;p&gt;Take a piece of AI-generated code and ask yourself: &lt;strong&gt;"Could I explain every line of this in a peer code review?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the answer is no, you are taking on technical debt you don't understand. Ask follow-up questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Why is this specific dependency needed?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;What invariant does this check protect?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;What happens if two network requests execute simultaneously?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep going until the implementation stops feeling like magic.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Keep Some Tasks AI-Free
&lt;/h3&gt;

&lt;p&gt;You don't need to quit AI cold turkey for a month. But short, unassisted intervals are revealing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write a utility function without autocomplete.&lt;/li&gt;
&lt;li&gt;Debug a minor issue yourself using &lt;code&gt;console.log&lt;/code&gt; or a breakpoint debugger.&lt;/li&gt;
&lt;li&gt;Sketch an architecture on paper before asking a model what it thinks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it like testing a backup. You don't want the first time you discover you can't code without AI to be during a live interview, an outage, or a critical system failure.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Ask AI for Exercises Based on Your Weaknesses
&lt;/h3&gt;

&lt;p&gt;When you notice yourself repeatedly asking the AI about the same topics—like &lt;code&gt;async/await&lt;/code&gt;, SQL joins, React lifecycles, or Git rebasing—use that data to train yourself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"I've needed help with async JavaScript state several times. Give me three increasingly difficult exercises that test whether I actually understand it. Don't give me the answers unless I ask."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now your assistant becomes a personalized tutor rather than a crutch.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Separate "I Can Understand This" From "I Can Produce This"
&lt;/h3&gt;

&lt;p&gt;There are multiple levels of mastery:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Recognizing a correct solution.&lt;/li&gt;
&lt;li&gt;Understanding a solution when it's explained.&lt;/li&gt;
&lt;li&gt;Modifying an existing solution.&lt;/li&gt;
&lt;li&gt;Producing a solution with documentation.&lt;/li&gt;
&lt;li&gt;Producing a solution from memory.&lt;/li&gt;
&lt;li&gt;Teaching the concept to someone else.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;AI makes levels 1 and 2 effortless, creating an illusion that we've reached levels 4 or 5. Realizing where your actual capability boundary lies prevents overconfidence.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Don't Outsource Architecture Too Early
&lt;/h3&gt;

&lt;p&gt;If the first thing you do when starting a feature is prompt &lt;em&gt;"How should I architect this?"&lt;/em&gt;, you skip the critical initial design phase. Answer these questions first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;What owns this state?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;What boundaries need to exist?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;What's the simplest implementation that works?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have a draft, bring AI into the loop: &lt;em&gt;"Here is the architecture I'm considering. What edge cases or structural flaws am I missing?"&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Keep Responsibility on Your Side of the Keyboard
&lt;/h3&gt;

&lt;p&gt;If you ship AI-generated code, &lt;strong&gt;it is still your code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The model doesn't get paged when production breaks at 2 AM. It doesn't defend the architecture to stakeholders. It doesn't maintain the repository six months down the line. You do.&lt;/p&gt;

&lt;p&gt;When you hold yourself accountable for everything you ship, generated code stops being an absolute answer and becomes a proposal to be critically evaluated.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The future doesn't belong to developers who refuse to use AI, nor does it belong to developers who blindly delegate every thought to it.&lt;/p&gt;

&lt;p&gt;The real skill lies in knowing &lt;strong&gt;where to automate and where to think&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let AI eliminate boilerplate, search unfamiliar territory, explain complex concepts, and review your work. But occasionally, make your brain do the heavy lifting: &lt;strong&gt;predict, recall, debug, design, and explain.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tools increase our output, but understanding increases our capability. The goal isn't just to build things because AI can build them—it's to build things we couldn't build before, while understanding more than when we started.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Stopped Measuring My Programming Ability by How Much Code I Write.</title>
      <dc:creator>Mika Flowers</dc:creator>
      <pubDate>Mon, 28 Sep 2026 21:26:37 +0000</pubDate>
      <link>https://dev.to/mikachu/i-stopped-measuring-my-programming-ability-by-how-much-code-i-write-44g3</link>
      <guid>https://dev.to/mikachu/i-stopped-measuring-my-programming-ability-by-how-much-code-i-write-44g3</guid>
      <description>&lt;p&gt;&lt;em&gt;Remember when using autocomplete meant you weren't "really" programming?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flb2tnjdgb27vknucl50a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flb2tnjdgb27vknucl50a.png" alt="autocomplete" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A real &lt;a href="https://softwareengineering.stackexchange.com/questions/114520/is-it-wrong-or-bad-to-use-autocomplete" rel="noopener noreferrer"&gt;Stack Overflow question&lt;/a&gt; from nearly 15 years ago. People genuinely wondered whether autocomplete was wrong.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Now look at us.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For a long time, I had a very simple way of measuring whether I was becoming a better developer:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How much code could I write myself?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Could I remember the syntax?&lt;/li&gt;
&lt;li&gt;Could I build the component without looking anything up?&lt;/li&gt;
&lt;li&gt;Could I solve the bug without asking for help?&lt;/li&gt;
&lt;li&gt;Could I stare at a blank file and turn it into software entirely from memory?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think a lot of self-taught developers absorb some version of this idea:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you need Stack Overflow, you're cheating. (Meanwhile, half of us have it pinned in a tab.)&lt;/li&gt;
&lt;li&gt;If you need documentation, you don't really know it.&lt;/li&gt;
&lt;li&gt;If you use autocomplete too much, you're getting lazy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And now, in the age of AI:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If a model wrote the code, did &lt;em&gt;you&lt;/em&gt; really build anything?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I used to worry about that question more than I want to admit.&lt;/p&gt;

&lt;p&gt;I don't anymore.&lt;/p&gt;

&lt;p&gt;After building more software, breaking more software, debugging more software, and maintaining code that looked perfectly fine five minutes earlier, I've started measuring my ability very differently.&lt;/p&gt;

&lt;p&gt;The question isn't:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How many lines did I personally type?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The questions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do I understand what this system is doing?&lt;/li&gt;
&lt;li&gt;Can I recognize when it's wrong?&lt;/li&gt;
&lt;li&gt;Can I debug it when the happy path disappears?&lt;/li&gt;
&lt;li&gt;Can I explain why the architecture looks the way it does?&lt;/li&gt;
&lt;li&gt;Can I change it without destroying three unrelated features?&lt;/li&gt;
&lt;li&gt;Can I maintain it next month?&lt;/li&gt;
&lt;li&gt;Am I willing to own the result?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those questions have turned out to be &lt;strong&gt;much&lt;/strong&gt; harder than typing code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code generation is the easy part now
&lt;/h2&gt;

&lt;p&gt;This is the weird thing about programming in 2026.&lt;/p&gt;

&lt;p&gt;You can describe an idea and get hundreds of lines of plausible-looking code almost instantly. Sometimes the code even works. That feels magical the first few times.&lt;/p&gt;

&lt;p&gt;Then you build something complicated. Suddenly the model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fixes one bug and creates another&lt;/li&gt;
&lt;li&gt;duplicates logic that already exists somewhere else&lt;/li&gt;
&lt;li&gt;confidently misunderstands your architecture&lt;/li&gt;
&lt;li&gt;passes the test while violating the actual requirement&lt;/li&gt;
&lt;li&gt;adds abstractions you never asked for&lt;/li&gt;
&lt;li&gt;removes behavior you didn't realize depended on something else&lt;/li&gt;
&lt;li&gt;solves the problem you described instead of the problem you actually had&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you realize something important.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generating code was never the whole job.&lt;/strong&gt; It's just the most visible part.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hardest skill became knowing when something is wrong
&lt;/h2&gt;

&lt;p&gt;AI has actually made me spend &lt;em&gt;more&lt;/em&gt; time thinking about software. Not necessarily typing software. Thinking about it.&lt;/p&gt;

&lt;p&gt;When an agent produces an implementation, I have to ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why did it choose this approach?&lt;/li&gt;
&lt;li&gt;Does this belong here?&lt;/li&gt;
&lt;li&gt;Is this state owned by the right component?&lt;/li&gt;
&lt;li&gt;Are we fixing the cause or hiding the symptom?&lt;/li&gt;
&lt;li&gt;What happens when this fails?&lt;/li&gt;
&lt;li&gt;What happens when this runs twice?&lt;/li&gt;
&lt;li&gt;What happens when the user does something completely unreasonable?&lt;/li&gt;
&lt;li&gt;Does this implementation match the rest of the codebase?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And my personal favorite:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why does this work?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That last question matters, because code that works and code that you understand are not the same thing.&lt;/p&gt;

&lt;p&gt;I don't want software in my projects that feels like a mysterious artifact handed to me by an oracle. If I can't explain it, I don't trust it yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging changed how I think about authorship
&lt;/h2&gt;

&lt;p&gt;Writing code feels productive. Debugging teaches you whether you actually understand what you built.&lt;/p&gt;

&lt;p&gt;There is a big difference between:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The AI created this feature."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The AI created an initial implementation, I discovered why the state was leaking across components, traced the regression, changed the ownership model, tested the edge cases, and verified the fix."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The second experience teaches you far more about the system.&lt;/p&gt;

&lt;p&gt;And at some point I realized: that is programming too. Maybe more importantly, that is engineering.&lt;/p&gt;

&lt;p&gt;Authorship isn't just pressing the keys that produce the characters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's making decisions.&lt;/li&gt;
&lt;li&gt;It's understanding consequences.&lt;/li&gt;
&lt;li&gt;It's rejecting bad approaches.&lt;/li&gt;
&lt;li&gt;It's deciding what stays.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  I used to think needing help meant I wasn't good enough
&lt;/h2&gt;

&lt;p&gt;Being self-taught can create a strange kind of insecurity.&lt;/p&gt;

&lt;p&gt;There is always another concept you don't know. Another developer who understands networking better. Another person who can explain memory management without blinking. Another repository where every file looks like it was written in an alien language.&lt;/p&gt;

&lt;p&gt;So you start using independence as proof of competence.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"If I can do this without help, then I must actually belong here."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AI pokes directly at that insecurity. Because now the help is always there. And it can do a lot.&lt;/p&gt;

&lt;p&gt;I had to stop asking whether using help invalidated my skills. Developers have always used tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentation is a tool.&lt;/li&gt;
&lt;li&gt;Libraries are tools.&lt;/li&gt;
&lt;li&gt;Frameworks are tools.&lt;/li&gt;
&lt;li&gt;Compilers are tools.&lt;/li&gt;
&lt;li&gt;Search engines are tools.&lt;/li&gt;
&lt;li&gt;IDEs are tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI is another extraordinarily powerful tool.&lt;/p&gt;

&lt;p&gt;The interesting question is not whether the tool participated. The interesting question is &lt;strong&gt;what happens when the tool is wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AI can produce code faster than I can understand it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpfy5t0j0jveftxbxd11o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpfy5t0j0jveftxbxd11o.png" alt="ai" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is probably the biggest danger I've found.&lt;/p&gt;

&lt;p&gt;The generation speed is seductive. You can add features faster than you can build a mental model of them.&lt;/p&gt;

&lt;p&gt;One prompt becomes three files. Another prompt becomes an abstraction. Another prompt quietly changes something you didn't know was load-bearing.&lt;/p&gt;

&lt;p&gt;Then one day something breaks, and you're standing in a codebase that technically belongs to you but that you couldn't explain to anyone, including yourself.&lt;/p&gt;

&lt;p&gt;That's the trap. The bottleneck used to be how fast I could write code. Now it's how fast I can understand it, and the tool doesn't slow down to wait for me.&lt;/p&gt;

&lt;p&gt;So I've had to build a few habits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the diff before accepting it. All of it.&lt;/li&gt;
&lt;li&gt;Ask the model to explain its choices, then check whether the explanation actually matches the code.&lt;/li&gt;
&lt;li&gt;Keep changes small enough that I can hold them in my head.&lt;/li&gt;
&lt;li&gt;Test the unreasonable cases, not just the happy path.&lt;/li&gt;
&lt;li&gt;If I can't explain why it works, it doesn't ship.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these habits are about typing. All of them are about understanding.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scoreboard I use now
&lt;/h2&gt;

&lt;p&gt;I don't count lines anymore. I ask whether I understand what I shipped, whether I can fix it when it breaks, and whether I'm willing to stand behind it.&lt;/p&gt;

&lt;p&gt;And here's what convinced me the old scoreboard was wrong.&lt;/p&gt;

&lt;p&gt;My GitHub account is over ten years old.&lt;/p&gt;

&lt;p&gt;For a lot of that time, it was quiet. I took career breaks. I changed directions. Life did what life does.&lt;/p&gt;

&lt;p&gt;And yet in the past year, I've created and maintained more projects than in all of those ten years combined.&lt;/p&gt;

&lt;p&gt;I don't think that's a coincidence.&lt;/p&gt;

&lt;p&gt;I'm not saying the tools wrote my portfolio for me. Someone still had to decide what to build, debug it, ship it, and keep it alive. But the old measurement, &lt;em&gt;can I produce all of this from memory, alone, from a blank file?&lt;/em&gt;, was quietly keeping me from finishing things.&lt;/p&gt;

&lt;p&gt;Once I stopped using it, I started building.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>They Invited Me to Apply. Two Days Later, They Rejected Me.</title>
      <dc:creator>Mika Flowers</dc:creator>
      <pubDate>Sun, 27 Sep 2026 14:45:18 +0000</pubDate>
      <link>https://dev.to/mikachu/they-invited-me-to-apply-two-days-later-they-rejected-me-4mmf</link>
      <guid>https://dev.to/mikachu/they-invited-me-to-apply-two-days-later-they-rejected-me-4mmf</guid>
      <description>&lt;p&gt;&lt;em&gt;Job Search Diaries, Part 2&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Last time, I got rejected &lt;a href="https://dev.to/mikachu/i-got-rejected-2-minutes-after-applying-so-much-for-skills-based-hiring-4315"&gt;2 minutes after applying to a job&lt;/a&gt; I found &lt;em&gt;myself&lt;/em&gt;. This time, they found &lt;em&gt;me&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A recruiter named Melissa emailed me directly through ZipRecruiter. Not a generic blast — &lt;strong&gt;my name, my city, a specific role: Software Engineer&lt;/strong&gt; at a company called Whitespace, in Alexandria, VA. She said she was "interested in candidates with your qualifications" and invited me to apply.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjv8eobwsf3otmyw3zmaf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjv8eobwsf3otmyw3zmaf.png" alt="invite" width="800" height="1422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I did. Same day.&lt;/p&gt;

&lt;p&gt;Two days later, the rejection came. Sunday morning, 9:55 AM. Signed by Melissa. Same conversation thread.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj2wxrfp82msqkiru3u8l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj2wxrfp82msqkiru3u8l.png" alt="rejection" width="800" height="1475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Your experience does not match our current needs."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The needs she herself decided matched mine, 48 hours earlier. Not "the role's been filled." Not "we went a different direction." Just a boilerplate line that could've been sent to anyone, about anything — closed out with the platform itself locking the thread: &lt;em&gt;this conversation has been closed.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Two days is the part that actually bothers me
&lt;/h2&gt;

&lt;p&gt;With my last post, the fast rejection was almost forgivable in its own way — 2 minutes is obviously a machine, no pretense involved.&lt;/p&gt;

&lt;p&gt;Two days is different. Two days is long enough to &lt;em&gt;imply&lt;/em&gt; a human looked. Two days is long enough that if someone actually had read my application, I could believe "we found someone stronger" or "we needed different experience than we thought." Two days is not long enough to explain a form letter that reads like it was generated before my resume was ever opened.&lt;/p&gt;

&lt;p&gt;And it landed on a Sunday. Not a follow-up sent Monday morning when the recruiting team is back at their desks — a Sunday. Either Melissa was personally working her inbox on a weekend to give my application careful, individual consideration, or nothing about that rejection required a person to be awake and thinking. I know which one seems more likely.&lt;/p&gt;

&lt;p&gt;Either a human spent two days on my application, and the rejection doesn't reflect that. Or nobody did, and the two days meant nothing except that their queue was slow.&lt;/p&gt;

&lt;p&gt;Neither one is a good look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Same story, different failure point
&lt;/h2&gt;

&lt;p&gt;My last post was about a degree checkbox — a filter that never let a real application matter in the first place. &lt;code&gt;degree == true&lt;/code&gt;. Simple, brutal, at least &lt;em&gt;consistent&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This one's murkier. There's no obvious rule I tripped. Just a recruiter who searched a database, found my name, sent an invite with my qualifications already pre-approved — and then, two days later, a system (or a person, or nobody) decided those same qualifications didn't hold up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mechanism, best guess
&lt;/h2&gt;

&lt;p&gt;Recruiters can search a candidate database by filters — title, keywords, location — and bulk-send "invite to apply" emails to everyone who matches. That's the first email. It has your name in it. It feels personal. It's a saved search with a mail-merge template.&lt;/p&gt;

&lt;p&gt;Then, whenever your application actually gets processed — could be minutes, could be days later, depending on their queue — it goes through a separate screen: an ATS filter, a quick skim, something. That's the second email. The gap between the two doesn't mean more care went in. It might just mean their queue was backed up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Still applying
&lt;/h2&gt;

&lt;p&gt;I'm still building. Still applying. Still tailoring every application like someone might read it — because sometimes, eventually, one will.&lt;/p&gt;

&lt;p&gt;But I'm done pretending a two-day wait means anyone was paying attention. Apparently even the illusion of care has a delay setting now.&lt;/p&gt;

</description>
      <category>career</category>
      <category>programming</category>
      <category>hiring</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I Tried to Prompt a 3D DEV Library Into Existence. Then I Had to Build My Own Level Editor.</title>
      <dc:creator>Mika Flowers</dc:creator>
      <pubDate>Sun, 27 Sep 2026 13:04:40 +0000</pubDate>
      <link>https://dev.to/mikachu/i-tried-to-prompt-a-3d-dev-library-into-existence-then-i-had-to-build-my-own-level-editor-37gf</link>
      <guid>https://dev.to/mikachu/i-tried-to-prompt-a-3d-dev-library-into-existence-then-i-had-to-build-my-own-level-editor-37gf</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/sanity-2026-09-16"&gt;Sanity Challenge, Path Two: Vibe-Code Something Strange&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fss3dqui2ipfmq0k4tyvz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fss3dqui2ipfmq0k4tyvz.png" alt="Oniria" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I started this hackathon building a dream journal.&lt;/p&gt;

&lt;p&gt;A few days later, I was walking through a giant library filled with real DEV articles, debugging floating bookshelves, building spatial authoring tools, and learning how to teach Sanity to remember which shelves were alive.&lt;/p&gt;

&lt;p&gt;That escalation probably tells you most of what you need to know about how this project went.&lt;/p&gt;

&lt;p&gt;The result is &lt;strong&gt;Oniria: The Living DEV Library&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of browsing DEV as a feed, grid, or search page, Oniria turns it into a place.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You walk through rooms.&lt;/li&gt;
&lt;li&gt;Articles become books.&lt;/li&gt;
&lt;li&gt;Topics occupy shelves.&lt;/li&gt;
&lt;li&gt;Search physically restocks part of the library.&lt;/li&gt;
&lt;li&gt;Parts of the archive can evolve over time based on activity.&lt;/li&gt;
&lt;li&gt;Sanity remembers what previously occupied that physical space.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdbqb2ax6dcbaq85tcwu0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdbqb2ax6dcbaq85tcwu0.gif" alt="Search physically restocking the library" width="600" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The question behind the project eventually became:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  What if information had geography?
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flobyadyxkt4aft12s9wi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flobyadyxkt4aft12s9wi.png" alt="Early version of Oniria" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Project Links
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/miflow13/Oniria" rel="noopener noreferrer"&gt;github.com/miflow13/Oniria&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Agent sessions:&lt;/strong&gt; &lt;a href="https://github.com/miflow13/Oniria/blob/main/docs/agent-sessions/README.md" rel="noopener noreferrer"&gt;Public Oniria development transcripts&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Sanity project:&lt;/strong&gt; &lt;a href="https://www.sanity.io/manage/project/z5fp07ep" rel="noopener noreferrer"&gt;Oniria Archive Control&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Live project:&lt;/strong&gt; &lt;code&gt;TBA&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Demo video:&lt;/strong&gt; &lt;code&gt;TBA&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h1&gt;
  
  
  What I Built
&lt;/h1&gt;

&lt;p&gt;Oniria is a walkable 3D library built from live DEV content.&lt;/p&gt;

&lt;p&gt;The current library is organized into six rooms:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Room&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Featured&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Popular and curated writing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;New Arrivals&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Recently published DEV articles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Topics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tag-driven collections&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Creators&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Authors and their writing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Search&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A physical card catalogue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Archive&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deeper exploration and long-tail content&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;DEV provides the live content.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sanity provides the memory and structure of the world.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three.js turns both into a place you can walk through.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The data flow
&lt;/h3&gt;

&lt;p&gt;I didn't want to copy DEV articles into a CMS and call that an integration.&lt;/p&gt;

&lt;p&gt;Instead, DEV remains the source of the content itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DEV API
   │
   │ articles / creators / tags / search
   ▼
Oniria
   │
   ├──────────────► Three.js
   │                 architecture
   │                 books
   │                 navigation
   │                 interactions
   │
   ▼
Sanity
world configuration
room definitions
layout markers
curator picks
guided journeys
living shelf state
history / lifecycle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;DEV tells Oniria what currently exists.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjvfvj1zr3yjgkxh83bs6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjvfvj1zr3yjgkxh83bs6.png" alt="Oniria library" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sanity tells Oniria what the world means, where things belong, and what happened there before.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That distinction became the foundation of the whole project.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎮 Demo
&lt;/h1&gt;

&lt;p&gt;A first visit is intentionally simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enter the library&lt;/strong&gt; and explore Featured or New Arrivals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approach a shelf&lt;/strong&gt; and target a book.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open the real DEV article&lt;/strong&gt; represented by that book.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Return to the library&lt;/strong&gt; and land back at the same physical location.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visit Search&lt;/strong&gt;, query DEV, and watch that room restock around the query.&lt;/li&gt;
&lt;li&gt;Explore Topics, Creators, and the deeper Archive.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal was to make the underlying technology complicated while keeping the mental model simple.&lt;/p&gt;

&lt;p&gt;The visitor shouldn't need to understand data graphs, procedural systems, lifecycle state, or spatial indexes.&lt;/p&gt;

&lt;p&gt;They should just understand:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  This is a library.
&lt;/h2&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📸 Inside Oniria
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Main Hall
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo6gxrvyg19tpwshq7wdn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo6gxrvyg19tpwshq7wdn.png" alt="Main hall" width="799" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Browsing the Shelves
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbl0tudvaphi6ms4cimdr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbl0tudvaphi6ms4cimdr.png" alt="Shelves" width="799" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa54lxlqxkocsfe18p7lf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa54lxlqxkocsfe18p7lf.png" alt="Opening a book" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu7763z30yshogeaaf145.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu7763z30yshogeaaf145.png" alt="Library interior" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading a Real DEV Article
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjzaihrz9092shi59g1sf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjzaihrz9092shi59g1sf.png" alt="Reading an article" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sanity as the World Backend
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhzu4iazac6skn2fg2pvx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhzu4iazac6skn2fg2pvx.png" alt="Sanity backend" width="799" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the In-World Authoring Tool
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhfes9rm9mwikpks7fi6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhfes9rm9mwikpks7fi6n.png" alt="Using the built-in authoring tool" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  💻 Code
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/miflow13/Oniria" rel="noopener noreferrer"&gt;github.com/miflow13/Oniria&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main stack is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js 16&lt;/li&gt;
&lt;li&gt;React 19&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Three.js&lt;/li&gt;
&lt;li&gt;Sanity&lt;/li&gt;
&lt;li&gt;next-sanity&lt;/li&gt;
&lt;li&gt;DEV / Forem API&lt;/li&gt;
&lt;li&gt;Vercel&lt;/li&gt;
&lt;li&gt;GLB environment and architectural assets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The building itself is assembled through code, configuration, reusable assets, and structured world data rather than a traditional 3D level editor.&lt;/p&gt;

&lt;p&gt;That last part became one of the most important parts of the project.&lt;/p&gt;




&lt;h1&gt;
  
  
  🛠️ Building Oniria
&lt;/h1&gt;

&lt;p&gt;This is the part of Oniria I'm most interested in.&lt;/p&gt;

&lt;p&gt;The project did &lt;strong&gt;not&lt;/strong&gt; come from one perfect prompt.&lt;/p&gt;

&lt;p&gt;It changed direction repeatedly because actually walking through what the agents produced exposed problems that were impossible to understand from code alone.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. It Started as a Dream Journal
&lt;/h2&gt;

&lt;p&gt;The original Oniria was much smaller.&lt;/p&gt;

&lt;p&gt;I built a Sanity-backed dream journal where dreams referenced recurring symbols, mood, and other structured information.&lt;/p&gt;

&lt;p&gt;Those relationships became a visual map.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiq7d1sgadf8suiibjayy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiq7d1sgadf8suiibjayy.png" alt="Oniria as a dream journal" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then the map became 3D.&lt;/p&gt;

&lt;p&gt;Then I wanted to move through it.&lt;/p&gt;

&lt;p&gt;Dreams became environments.&lt;/p&gt;

&lt;p&gt;I added first-person movement.&lt;/p&gt;

&lt;p&gt;Then portals between related memories.&lt;/p&gt;

&lt;p&gt;At some point I had to ask myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Have I accidentally started building a video game?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Probably.&lt;/p&gt;

&lt;p&gt;But something useful had emerged underneath all of that experimentation.&lt;/p&gt;

&lt;p&gt;The idea was no longer specifically about dreams.&lt;/p&gt;

&lt;p&gt;I was interested in whether structured information could have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;space&lt;/li&gt;
&lt;li&gt;distance&lt;/li&gt;
&lt;li&gt;landmarks&lt;/li&gt;
&lt;li&gt;relationships&lt;/li&gt;
&lt;li&gt;physical context&lt;/li&gt;
&lt;li&gt;geography&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I briefly experimented with using that same structure to explore files and codebases.&lt;/p&gt;

&lt;p&gt;Then I looked at DEV.&lt;/p&gt;

&lt;p&gt;Articles already have natural relationships:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tags&lt;/li&gt;
&lt;li&gt;authors&lt;/li&gt;
&lt;li&gt;recency&lt;/li&gt;
&lt;li&gt;popularity&lt;/li&gt;
&lt;li&gt;search&lt;/li&gt;
&lt;li&gt;recommendations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And suddenly the metaphor was obvious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A library.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. From a Graph to a Building
&lt;/h2&gt;

&lt;p&gt;The first DEV version was much more abstract.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2mn5enc203d40bcw06b4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2mn5enc203d40bcw06b4.png" alt="First DEV version" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Articles and profiles existed as objects in an explorable spatial web.&lt;/p&gt;

&lt;p&gt;Technically, it worked.&lt;/p&gt;

&lt;p&gt;Experientially, it didn't.&lt;/p&gt;

&lt;p&gt;Everything competed for attention.&lt;/p&gt;

&lt;p&gt;There wasn't enough hierarchy.&lt;/p&gt;

&lt;p&gt;So I simplified it into six obvious destinations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Featured
New Arrivals
Topics
Creators
Search
Archive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was the first major course correction.&lt;/p&gt;

&lt;p&gt;Instead of explaining a graph, I could put a door in front of someone.&lt;/p&gt;

&lt;p&gt;Instead of explaining an article node, I could put a book on a shelf.&lt;/p&gt;

&lt;p&gt;The complexity stayed underneath.&lt;/p&gt;

&lt;p&gt;The visitor saw a library.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The AI Was Useful — and Confidently Wrong
&lt;/h2&gt;

&lt;p&gt;I used Codex heavily during development, with ChatGPT helping me think through architecture, UX, debugging, and the direction of the project.&lt;/p&gt;

&lt;p&gt;The agents were incredibly useful.&lt;/p&gt;

&lt;p&gt;They were also very capable of producing something technically valid that was visually wrong.&lt;/p&gt;

&lt;p&gt;One of the clearest examples involved the library walls.&lt;/p&gt;

&lt;p&gt;I provided actual wall assets and asked the agent to construct the environment with them.&lt;/p&gt;

&lt;p&gt;The result looked wrong.&lt;/p&gt;

&lt;p&gt;It had generated procedural wall geometry instead.&lt;/p&gt;

&lt;p&gt;There were technically walls.&lt;/p&gt;

&lt;p&gt;They were just not the walls I gave it.&lt;/p&gt;

&lt;p&gt;Eventually my prompt became:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  “DO NOT GENERATE YOUR OWN ASSET FOR THE WALL.”
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use the assets provided to you.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next implementation removed the generated visible walls and made the authored GLB assets the source of truth.&lt;/p&gt;

&lt;p&gt;Primitive geometry remained useful for things like invisible collision and structural helpers.&lt;/p&gt;

&lt;p&gt;That experience taught me something important:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A model can satisfy the semantic meaning of a request while completely missing the visual intention.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  4. A Convincing Wrong Diagnosis
&lt;/h2&gt;

&lt;p&gt;Another example was lighting.&lt;/p&gt;

&lt;p&gt;At one point, the library became almost completely washed out.&lt;/p&gt;

&lt;p&gt;The first explanation focused on overlapping lights and bright materials.&lt;/p&gt;

&lt;p&gt;That was plausible.&lt;/p&gt;

&lt;p&gt;Some of it was even correct.&lt;/p&gt;

&lt;p&gt;But it didn't fully explain what I was seeing.&lt;/p&gt;

&lt;p&gt;Continued testing eventually exposed the bigger issue:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UnrealBloomPass.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The bloom threshold was allowing too much of the scene to contribute, making the entire environment glow.&lt;/p&gt;

&lt;p&gt;That debugging process was valuable because the first answer sounded reasonable.&lt;/p&gt;

&lt;p&gt;The important thing was continuing to test the actual experience instead of accepting the first explanation simply because it sounded technical.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. The Problem a Better Prompt Couldn't Solve
&lt;/h2&gt;

&lt;p&gt;The biggest limitation appeared when I started placing shelves and architecture precisely.&lt;/p&gt;

&lt;p&gt;I wasn't using a traditional 3D editor.&lt;/p&gt;

&lt;p&gt;The environment was being built through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Three.js code&lt;/li&gt;
&lt;li&gt;coordinates&lt;/li&gt;
&lt;li&gt;configuration&lt;/li&gt;
&lt;li&gt;screenshots&lt;/li&gt;
&lt;li&gt;prompts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That worked surprisingly well until the task became:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Put this shelf against that wall, slightly left of the pavilion, rotated toward the center of the room.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I could see exactly where I wanted it.&lt;/p&gt;

&lt;p&gt;The coding model could see coordinates and occasional screenshots.&lt;/p&gt;

&lt;p&gt;Those are not equivalent.&lt;/p&gt;

&lt;p&gt;We spent multiple iterations nudging architecture through prompts.&lt;/p&gt;

&lt;p&gt;Eventually I realized:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  The solution wasn't a better prompt.
&lt;/h2&gt;
&lt;h2&gt;
  
  
  It was a better tool.
&lt;/h2&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  6. So I Built a Level Editor Inside Oniria
&lt;/h2&gt;

&lt;p&gt;Oniria gained a development-only spatial authoring workflow.&lt;/p&gt;

&lt;p&gt;While walking through the running Three.js environment, I can place markers exactly where objects or zones should exist.&lt;/p&gt;

&lt;p&gt;A marker looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"R1-P04"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"roomSlot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"districtId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"latest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;13.687&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"y"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"z"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;11.998&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"yaw"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"depth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.72&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those markers are stored in Sanity as &lt;code&gt;libraryLayoutMarker&lt;/code&gt; documents.&lt;/p&gt;

&lt;p&gt;The workflow became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;walk through world
      ↓
stand where something belongs
      ↓
place marker
      ↓
Sanity persists spatial data
      ↓
renderer consumes authored layout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was the moment Sanity stopped feeling like just a CMS in this project.&lt;/p&gt;

&lt;p&gt;It became part of my &lt;strong&gt;3D authoring environment&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A structured document didn't have to represent a blog post.&lt;/p&gt;

&lt;p&gt;It could represent a physical location.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Sanity Became the Memory of the World
&lt;/h2&gt;

&lt;p&gt;The current Studio is organized as &lt;strong&gt;Oniria Archive Control&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Sanity manages several layers of the environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Library Control
&lt;/h3&gt;

&lt;p&gt;Global configuration such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;welcome copy&lt;/li&gt;
&lt;li&gt;movement defaults&lt;/li&gt;
&lt;li&gt;atmosphere&lt;/li&gt;
&lt;li&gt;haze&lt;/li&gt;
&lt;li&gt;live DEV updates&lt;/li&gt;
&lt;li&gt;archive behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Library Districts
&lt;/h3&gt;

&lt;p&gt;Each room has structured configuration including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;li&gt;room code&lt;/li&gt;
&lt;li&gt;ordering&lt;/li&gt;
&lt;li&gt;DEV tags&lt;/li&gt;
&lt;li&gt;accent&lt;/li&gt;
&lt;li&gt;atmosphere&lt;/li&gt;
&lt;li&gt;audio profile&lt;/li&gt;
&lt;li&gt;landmark&lt;/li&gt;
&lt;li&gt;content source&lt;/li&gt;
&lt;li&gt;enabled state&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Layout Pins
&lt;/h3&gt;

&lt;p&gt;These store authored spatial positions created from the development tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Curator Picks
&lt;/h3&gt;

&lt;p&gt;Specific DEV articles can be intentionally featured without duplicating ownership of the original content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Guided Journeys
&lt;/h3&gt;

&lt;p&gt;Ordered destinations can define intentional paths through the archive.&lt;/p&gt;

&lt;p&gt;And then there are the part of the data model that became my favorite:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Living Shelf Slots.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🌱 The Living Library
&lt;/h1&gt;

&lt;p&gt;A physical location can exist independently from whatever currently occupies it.&lt;/p&gt;

&lt;p&gt;That became the foundation of the Living Shelf system.&lt;/p&gt;

&lt;p&gt;A shelf slot has a stable identity.&lt;/p&gt;

&lt;p&gt;Sanity stores information including:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slotKey
district
physical slot
occupant
topic
lifecycle
vitality
signal score
article count
timestamps
history
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Its lifecycle can move through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DORMANT
   ↓
FORMING
   ↓
ACTIVE
   ↓
COOLING
   ↓
DORMANT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A scheduled process samples recent DEV activity and evaluates topic signals.&lt;/p&gt;

&lt;p&gt;If a topic begins gaining momentum, a dormant location can materialize around it.&lt;/p&gt;

&lt;p&gt;It becomes active.&lt;/p&gt;

&lt;p&gt;Later, if activity fades, it can cool down and eventually return to latent space.&lt;/p&gt;

&lt;p&gt;But Sanity still remembers what happened there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The position persists.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The occupant changes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The history remains.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;Living DEV Library&lt;/strong&gt; stopped being just a name.&lt;/p&gt;




&lt;h2&gt;
  
  
  Search Became Physical Too
&lt;/h2&gt;

&lt;p&gt;Search originally behaved like normal application UI.&lt;/p&gt;

&lt;p&gt;Type something.&lt;/p&gt;

&lt;p&gt;Get a result list.&lt;/p&gt;

&lt;p&gt;But that pulled the user out of the spatial metaphor.&lt;/p&gt;

&lt;p&gt;So the Search room became a physical catalogue.&lt;/p&gt;

&lt;p&gt;Searching DEV can restock shelves in the environment with matching content.&lt;/p&gt;

&lt;p&gt;The architecture remains familiar while the information changes.&lt;/p&gt;

&lt;p&gt;Again, the idea became:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Place and content do not have to be the same thing.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Performance Changed the Architecture
&lt;/h2&gt;

&lt;p&gt;Making the library feel enormous caused predictable performance problems.&lt;/p&gt;

&lt;p&gt;Some early versions attempted very large shelf fields with hundreds of individual books and remote cover textures.&lt;/p&gt;

&lt;p&gt;That created:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cover-image flicker&lt;/li&gt;
&lt;li&gt;unnecessary texture work&lt;/li&gt;
&lt;li&gt;excessive geometry&lt;/li&gt;
&lt;li&gt;worse GPU performance&lt;/li&gt;
&lt;li&gt;visual clutter&lt;/li&gt;
&lt;li&gt;harder navigation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of treating performance only as an optimization problem, I started treating it as a design constraint.&lt;/p&gt;

&lt;p&gt;Nearby books get more detail:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;covers&lt;/li&gt;
&lt;li&gt;readable metadata&lt;/li&gt;
&lt;li&gt;individual interaction&lt;/li&gt;
&lt;li&gt;pull-forward behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mid-distance shelves simplify.&lt;/p&gt;

&lt;p&gt;Far-away structures can become architectural mass rather than hundreds of fully interactive objects.&lt;/p&gt;

&lt;p&gt;The rule became:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Full fidelity only where interaction matters.
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;That made the experience faster and clearer at the same time.&lt;/p&gt;




&lt;h1&gt;
  
  
  🤖 What I Learned About Vibe Coding
&lt;/h1&gt;

&lt;p&gt;One of the most interesting parts of this project was learning when to follow an agent's implementation and when to challenge it.&lt;/p&gt;

&lt;p&gt;Sometimes the agent correctly ignored my implementation request.&lt;/p&gt;

&lt;p&gt;During work on the Living Shelves system, I requested a larger architectural refactor.&lt;/p&gt;

&lt;p&gt;Codex audited the existing implementation first.&lt;/p&gt;

&lt;p&gt;It discovered that the architecture I wanted was already reusable.&lt;/p&gt;

&lt;p&gt;The real problem was a prototype capacity restriction that prevented the system from expanding correctly.&lt;/p&gt;

&lt;p&gt;Instead of blindly performing the requested refactor, it fixed the actual bottleneck.&lt;/p&gt;

&lt;p&gt;That was one of my favorite agent interactions from the project because it represented the kind of AI-assisted engineering I want.&lt;/p&gt;

&lt;p&gt;Not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The user asked for a refactor, so refactor.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“What problem are we actually trying to solve?”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A Lot of Oniria Was Thrown Away
&lt;/h2&gt;

&lt;p&gt;There are many abandoned versions of this project.&lt;/p&gt;

&lt;p&gt;At various points it contained:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a dream journal&lt;/li&gt;
&lt;li&gt;a relationship constellation&lt;/li&gt;
&lt;li&gt;Dream Dive environments&lt;/li&gt;
&lt;li&gt;portals&lt;/li&gt;
&lt;li&gt;an Observatory&lt;/li&gt;
&lt;li&gt;an experimental project/codebase explorer&lt;/li&gt;
&lt;li&gt;a floating DEV WebSurf graph&lt;/li&gt;
&lt;li&gt;giant cyber-library structures&lt;/li&gt;
&lt;li&gt;enormous procedural shelf fields&lt;/li&gt;
&lt;li&gt;multi-level archives&lt;/li&gt;
&lt;li&gt;an outdoor library&lt;/li&gt;
&lt;li&gt;multiple architecture styles&lt;/li&gt;
&lt;li&gt;fake infinite corridors&lt;/li&gt;
&lt;li&gt;several ambience systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some were bad.&lt;/p&gt;

&lt;p&gt;Some were cool but wrong for the final product.&lt;/p&gt;

&lt;p&gt;Most taught me something that survived.&lt;/p&gt;

&lt;p&gt;The commit history is basically an archaeological site.&lt;/p&gt;

&lt;p&gt;I decided not to hide that because Path Two is specifically about the build process.&lt;/p&gt;

&lt;p&gt;The interesting thing about vibe coding wasn't that AI magically created the right application.&lt;/p&gt;

&lt;p&gt;It was how cheaply I could explore an idea, discover that it was wrong, and throw it away.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where AI Helped — and Where It Didn't
&lt;/h2&gt;

&lt;p&gt;AI was particularly good at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rapidly implementing architectural ideas&lt;/li&gt;
&lt;li&gt;repetitive Three.js construction&lt;/li&gt;
&lt;li&gt;refactoring&lt;/li&gt;
&lt;li&gt;tracing state through large systems&lt;/li&gt;
&lt;li&gt;generating implementation alternatives&lt;/li&gt;
&lt;li&gt;debugging TypeScript and integration problems&lt;/li&gt;
&lt;li&gt;making experiments cheap enough to discard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was weaker at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;understanding exact spatial intent&lt;/li&gt;
&lt;li&gt;judging visual scale from screenshots&lt;/li&gt;
&lt;li&gt;knowing whether a world actually &lt;em&gt;felt good&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;resisting technically-correct-but-visually-wrong solutions&lt;/li&gt;
&lt;li&gt;recognizing when the requested implementation wasn't the real problem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My workflow increasingly became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;observe
   ↓
decide what feels wrong
   ↓
describe the underlying problem
   ↓
agent implements
   ↓
run it
   ↓
walk through it
   ↓
correct assumptions
   ↓
repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fastest workflow wasn't maximizing agent autonomy.&lt;/p&gt;

&lt;p&gt;It was creating a tighter feedback loop between &lt;strong&gt;human perception and machine implementation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The spatial authoring system exists because of that realization.&lt;/p&gt;




&lt;h1&gt;
  
  
  🤖 Public Agent Sessions
&lt;/h1&gt;

&lt;p&gt;Because this is the &lt;strong&gt;Vibe-Code Something Strange&lt;/strong&gt; track, I wanted the development process itself to be inspectable.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/miflow13/Oniria/blob/main/docs/agent-sessions/README.md" rel="noopener noreferrer"&gt;Browse the sanitized Oniria agent sessions&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I exported and curated the Codex rollout sessions used while building Oniria.&lt;/p&gt;

&lt;p&gt;The Codex task pages themselves are private, so the public versions preserve the development trail without exposing private/internal material.&lt;/p&gt;

&lt;p&gt;They keep the parts that matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prompts&lt;/li&gt;
&lt;li&gt;implementation updates&lt;/li&gt;
&lt;li&gt;mistakes&lt;/li&gt;
&lt;li&gt;course corrections&lt;/li&gt;
&lt;li&gt;verification&lt;/li&gt;
&lt;li&gt;commits&lt;/li&gt;
&lt;li&gt;failed assumptions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Session Highlights
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Core Library Loop Alpha
&lt;/h4&gt;

&lt;p&gt;Implemented physical article targeting, Search → &lt;strong&gt;Take Me There&lt;/strong&gt;, reader state, exact return-to-shelf state, and interaction analytics.&lt;/p&gt;

&lt;p&gt;The live loop was verified with a real DEV search result before the final polish pass.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/miflow13/Oniria/commit/c6a09c0" rel="noopener noreferrer"&gt;Repository milestone: &lt;code&gt;c6a09c0&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Living Shelf Capacity
&lt;/h4&gt;

&lt;p&gt;Codex audited the existing shared shelf pipeline and found that the architecture was already reusable.&lt;/p&gt;

&lt;p&gt;The real problem was a prototype capacity limit.&lt;/p&gt;

&lt;p&gt;That restriction was removed so qualified topics can fill authored Sanity slots without creating a parallel renderer or fake content.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/miflow13/Oniria/commit/40552c6" rel="noopener noreferrer"&gt;Repository milestone: &lt;code&gt;40552c6&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Authored Architecture and Visual Debugging
&lt;/h4&gt;

&lt;p&gt;Corrected the workflow so supplied wall assets became the source of truth, then later traced the library's whiteout regression to &lt;code&gt;UnrealBloomPass&lt;/code&gt; and disabled it only for the DEV Library.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/miflow13/Oniria/commit/5cc55e1" rel="noopener noreferrer"&gt;Repository milestone: &lt;code&gt;5cc55e1&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Spatial Shelf Authoring and Library Scale
&lt;/h4&gt;

&lt;p&gt;Built physical double-sided stacks, bounded cover atlases, dense instanced book massing, and level-of-detail behavior for the larger library.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/miflow13/Oniria/commit/45537db" rel="noopener noreferrer"&gt;Shelf geometry — &lt;code&gt;45537db&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/miflow13/Oniria/commit/c74f07e" rel="noopener noreferrer"&gt;Cover atlases — &lt;code&gt;c74f07e&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/miflow13/Oniria/commit/fcfeba5" rel="noopener noreferrer"&gt;Shelf LOD — &lt;code&gt;fcfeba5&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Wayfinding and Floor Identity
&lt;/h4&gt;

&lt;p&gt;Added root-aware breadcrumbs, threshold-only &lt;strong&gt;AHEAD&lt;/strong&gt; cues, environmental floor differentiation, and matte-to-satin floor material treatment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/miflow13/Oniria/commit/9473c3f" rel="noopener noreferrer"&gt;Breadcrumbs — &lt;code&gt;9473c3f&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/miflow13/Oniria/commit/5c4c367" rel="noopener noreferrer"&gt;Wayfinding cue — &lt;code&gt;5c4c367&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/miflow13/Oniria/commit/1f56966" rel="noopener noreferrer"&gt;Floor identity — &lt;code&gt;1f56966&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/miflow13/Oniria/commit/f6ed0b6" rel="noopener noreferrer"&gt;Floor material — &lt;code&gt;f6ed0b6&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The public session export removes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;private/internal reasoning&lt;/li&gt;
&lt;li&gt;system/developer instructions&lt;/li&gt;
&lt;li&gt;security/guardian telemetry&lt;/li&gt;
&lt;li&gt;repetitive shell output&lt;/li&gt;
&lt;li&gt;unrelated project sessions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The repository milestones are the public companion to those sanitized transcripts.&lt;/p&gt;

&lt;p&gt;Some of my favorite parts of the sessions aren't where Codex got everything right immediately.&lt;/p&gt;

&lt;p&gt;They're the moments where the workflow became genuinely collaborative because I had to challenge what it produced.&lt;/p&gt;

&lt;p&gt;Including, of course:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  “DO NOT GENERATE YOUR OWN ASSET FOR THE WALL.”
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is probably a more accurate description of vibe coding than anything else I could write.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚙️ Sanity Project Details
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Technical project details, schemas, API, and commands&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Sanity
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Sanity project:&lt;/strong&gt; Oniria Archive Control&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Sanity Project ID:&lt;/strong&gt; &lt;code&gt;z5fp07ep&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Dataset:&lt;/strong&gt; &lt;code&gt;production&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Sanity Studio:&lt;/strong&gt; &lt;code&gt;/studio&lt;/code&gt; on the deployed application, or &lt;a href="http://localhost:3000/studio" rel="noopener noreferrer"&gt;&lt;code&gt;http://localhost:3000/studio&lt;/code&gt;&lt;/a&gt; when running locally&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Sanity project console:&lt;/strong&gt; &lt;a href="https://www.sanity.io/manage/project/z5fp07ep" rel="noopener noreferrer"&gt;Manage project &lt;code&gt;z5fp07ep&lt;/code&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Public dataset API:&lt;/strong&gt; &lt;a href="https://z5fp07ep.apicdn.sanity.io/v2026-09-27/data/query/production" rel="noopener noreferrer"&gt;&lt;code&gt;https://z5fp07ep.apicdn.sanity.io/v2026-09-27/data/query/production&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The public API URL above is the Content Lake endpoint for the &lt;code&gt;production&lt;/code&gt; dataset. It requires a GROQ query parameter to return documents; the project ID and dataset are included in the URL so the Sanity integration can be identified directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project repository:&lt;/strong&gt; &lt;a href="https://github.com/miflow13/Oniria" rel="noopener noreferrer"&gt;github.com/miflow13/Oniria&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Stable project reference:&lt;/strong&gt; &lt;a href="https://github.com/miflow13/Oniria" rel="noopener noreferrer"&gt;Oniria — The Living DEV Library&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Author:&lt;/strong&gt; Mika Flowers (&lt;a href="https://github.com/miflow13" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;)&lt;/p&gt;
&lt;h3&gt;
  
  
  Project Architecture
&lt;/h3&gt;

&lt;p&gt;Oniria is a Next.js 16 / React 19 / TypeScript application that uses Three.js to render a walkable six-room library built from live DEV / Forem content.&lt;/p&gt;

&lt;p&gt;Vercel hosts the application and runs the living-library evolution route every 30 minutes.&lt;/p&gt;

&lt;p&gt;The six Sanity-backed rooms are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;R-01&lt;/code&gt; — Featured&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;R-02&lt;/code&gt; — New Arrivals&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;R-03&lt;/code&gt; — Topics&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;R-04&lt;/code&gt; — Creators&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;R-05&lt;/code&gt; — Search&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;R-06&lt;/code&gt; — Archive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sanity is used as the persistent world-configuration and authoring layer.&lt;/p&gt;

&lt;p&gt;The embedded Studio is titled &lt;strong&gt;Oniria Archive Control&lt;/strong&gt; and is mounted at &lt;code&gt;/studio&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The application uses Sanity for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;authored room definitions&lt;/li&gt;
&lt;li&gt;in-world layout pins&lt;/li&gt;
&lt;li&gt;curator picks&lt;/li&gt;
&lt;li&gt;guided journeys&lt;/li&gt;
&lt;li&gt;living shelf state&lt;/li&gt;
&lt;li&gt;lifecycle history&lt;/li&gt;
&lt;li&gt;global library configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DEV remains the source of live:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;articles&lt;/li&gt;
&lt;li&gt;authors&lt;/li&gt;
&lt;li&gt;tags&lt;/li&gt;
&lt;li&gt;popularity&lt;/li&gt;
&lt;li&gt;recency&lt;/li&gt;
&lt;li&gt;search data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Project Commands
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
npm run typecheck
npm run build
npm run start
npm run sanity
npm run seed:library
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;seed:library&lt;/code&gt; command creates or updates the main library configuration, the six room documents, and the default guided journey.&lt;/p&gt;

&lt;p&gt;The scheduled &lt;code&gt;/api/library-evolution&lt;/code&gt; route samples recent DEV activity, evaluates topic signals and physical shelf slots, updates lifecycle state, and persists the shared result to Sanity.&lt;/p&gt;
&lt;h3&gt;
  
  
  Primary Sanity Schemas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;libraryConfig&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;libraryDistrict&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;libraryLayoutMarker&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;librarySlotState&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;curatedArticle&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;archiveJourney&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The repository also still contains the original:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dream&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;symbol&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;schemas from the project's first iteration.&lt;/p&gt;

&lt;p&gt;I kept those as part of Oniria's development history rather than deleting where the project started.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Oniria started as a project about dreams.&lt;/p&gt;

&lt;p&gt;It ended up becoming a project about information.&lt;/p&gt;

&lt;p&gt;Feeds are useful because they remove geography.&lt;/p&gt;

&lt;p&gt;Everything is immediately reachable.&lt;/p&gt;

&lt;p&gt;But removing geography also removes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;distance&lt;/li&gt;
&lt;li&gt;landmarks&lt;/li&gt;
&lt;li&gt;wandering&lt;/li&gt;
&lt;li&gt;memory of place&lt;/li&gt;
&lt;li&gt;discovery&lt;/li&gt;
&lt;li&gt;physical context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Oniria is an experiment in putting some of those things back.&lt;/p&gt;

&lt;p&gt;I don't think every website should become a 3D environment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Please do not make me walk across a room to change my password.
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;But I do think there are kinds of information where &lt;strong&gt;exploration itself can be meaningful&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And if nothing else, this project taught me that when an AI repeatedly puts the bookshelf in the wrong place, the right answer might be to stop arguing with it...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;and build yourself a level editor.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>sanitychallenge</category>
      <category>ai</category>
      <category>sanity</category>
    </item>
    <item>
      <title>I Got Rejected 2 Minutes After Applying. So Much for 'Skills-Based Hiring.'</title>
      <dc:creator>Mika Flowers</dc:creator>
      <pubDate>Sat, 26 Sep 2026 22:36:24 +0000</pubDate>
      <link>https://dev.to/mikachu/i-got-rejected-2-minutes-after-applying-so-much-for-skills-based-hiring-4315</link>
      <guid>https://dev.to/mikachu/i-got-rejected-2-minutes-after-applying-so-much-for-skills-based-hiring-4315</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;“&lt;strong&gt;Startup culture" on the job listing. FANG-style ATS vetting in the inbox.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I applied for a Junior Solutions Engineer role today.&lt;/p&gt;

&lt;p&gt;Not a senior role. Not a staff role. Not some "10 years of experience required" fantasy posting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A junior role.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The requirements were things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hands-on experience in solutions engineering, technical support, sales engineering, or automation-focused work&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;SQL&lt;/li&gt;
&lt;li&gt;Data tooling&lt;/li&gt;
&lt;li&gt;Automation&lt;/li&gt;
&lt;li&gt;AI-driven products&lt;/li&gt;
&lt;li&gt;B2B software&lt;/li&gt;
&lt;li&gt;The right to work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh5gkby5wri4mojd2f0af.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh5gkby5wri4mojd2f0af.png" alt="reqs" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And one other thing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A degree in STEM, Finance, or another strong analytical field.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I don't have one.&lt;/p&gt;

&lt;p&gt;I applied anyway, because I &lt;em&gt;actually&lt;/em&gt; have experience doing a lot of the work they described.&lt;/p&gt;

&lt;p&gt;I recently built an internal operations platform for a real business. The client was managing appliance inventory through a largely manual WooCommerce workflow, including product creation, photos, pricing, descriptions, and updates. I built them a custom inventory management system that turns appliance manifests and uploaded photos into structured product listings, automatically matches inventory data, generates titles and descriptions, surfaces sale price and MSRP, and lets staff review and edit everything before publishing changes to WooCommerce. I also built multi-device synchronization and safeguards so multiple people could work with the same inventory without overwriting or duplicating completed manifests. Along the way I handled API integrations, database work, deployment, troubleshooting, synchronization problems, and user feedback.&lt;/p&gt;

&lt;p&gt;That is not a tutorial project. That is not "I followed a YouTube video and changed the button color." That is software being used to solve an actual business problem.&lt;/p&gt;

&lt;p&gt;So I did what job seekers are constantly told to do: I tailored my application. I wrote the summary. I wrote the cover letter. I answered the extra question explaining my hands-on experience. I connected my actual work to the responsibilities of the role.&lt;/p&gt;

&lt;p&gt;Then I hit submit.&lt;/p&gt;

&lt;p&gt;A minute later, I got the application confirmation. About a minute after that, I got the rejection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1k9e291y626v7vp9xf4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1k9e291y626v7vp9xf4e.png" alt="rejecton" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's the part that got me. I couldn't help but burst out laughing. Then it hit me: they signed it with a human name instead of just "Company X," which somehow made the whole thing feel even more insulting.&lt;/p&gt;

&lt;h2&gt;
  
  
  There is no way a human meaningfully reviewed that application
&lt;/h2&gt;

&lt;p&gt;Maybe the degree requirement triggered it. Maybe one of the screening questions did...&lt;/p&gt;

&lt;p&gt;I don't actually know. But that's not really the point.&lt;/p&gt;

&lt;p&gt;Two minutes is not enough time to open a resume, open a cover letter, read a custom answer, cross-reference all three against a job description, and reach a considered decision. That's not skepticism — that's arithmetic. A recruiter who is fast, good, and fully focused still needs more than 120 seconds to read three documents and actually think about them.&lt;/p&gt;

&lt;p&gt;Some rule fired. And that was that. &lt;/p&gt;

&lt;p&gt;We hear constantly that tech hiring is becoming more "skills based." Build projects. Contribute to open source. Show initiative. Learn in public. Demonstrate impact. Have a portfolio. Solve real problems.&lt;/p&gt;

&lt;p&gt;Cool. I did that.&lt;/p&gt;

&lt;p&gt;But if the first layer of the hiring pipeline is still:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;degree == true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then a huge amount of that "skills-based" rhetoric starts to feel cosmetic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The weird part is that I actually understand why filters exist
&lt;/h2&gt;

&lt;p&gt;Companies get hundreds or thousands of applications. Nobody can manually inspect every GitHub profile. Recruiters need ways to reduce the pile. Applicant tracking systems exist for a reason.&lt;/p&gt;

&lt;p&gt;I get it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;There is a difference between filtering noise and accidentally filtering out the exact kind of unconventional candidate the industry keeps claiming it wants.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;“Someone without a traditional computer science degree is already doing something harder...”&lt;/p&gt;

&lt;p&gt;But there is a difference between filtering noise and accidentally filtering out the exact kind of unconventional candidate the industry keeps claiming it wants.&lt;/p&gt;

&lt;p&gt;Someone without a traditional computer science degree is already doing something harder: we have to manufacture our own proof. We build. We document. We learn in public. We find real users. We create our own experience because nobody handed us an internship pipeline.&lt;/p&gt;

&lt;p&gt;Then we arrive at the application and discover that the credential may still matter more than the evidence.&lt;/p&gt;

&lt;p&gt;That is exhausting.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Equivalent experience" should actually mean something
&lt;/h2&gt;

&lt;p&gt;If a company truly requires a degree because the work genuinely depends on academic training, fine. Say that clearly.&lt;/p&gt;

&lt;p&gt;But if the role is fundamentally about Python, SQL, APIs, automation, debugging, integrations, customer communication, and solving business problems, then actual demonstrated experience doing those things should at least earn a human look. Especially for a junior position.&lt;/p&gt;

&lt;p&gt;I'm not arguing that I deserved the job — there may have been candidates with much stronger backgrounds, and that's hiring.&lt;/p&gt;

&lt;p&gt;What bothers me is the possibility that none of that comparison ever happened. The application may have been dead before my projects mattered.&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm still going to keep applying
&lt;/h2&gt;

&lt;p&gt;This isn't a "give up on tech" post. Quite the opposite.&lt;/p&gt;

&lt;p&gt;I'm building open-source software. I'm doing client work. I'm learning Python more deeply. I'm working with databases, Linux, APIs, automation, and deployment. I'm documenting what I learn.&lt;/p&gt;

&lt;p&gt;And I'm going to keep applying to jobs where I can do the work, even when I don't perfectly match the pedigree section.&lt;/p&gt;

&lt;p&gt;Because I refuse to pre-reject myself for companies.&lt;/p&gt;

&lt;p&gt;They can do that themselves.&lt;/p&gt;

&lt;p&gt;Apparently very, very quickly.&lt;/p&gt;

</description>
      <category>career</category>
      <category>programming</category>
      <category>hiring</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How I Actually Learn New Skills (No Tutorial Required)</title>
      <dc:creator>Mika Flowers</dc:creator>
      <pubDate>Sat, 26 Sep 2026 12:42:02 +0000</pubDate>
      <link>https://dev.to/sheships/how-i-actually-learn-new-skills-no-tutorial-required-3iia</link>
      <guid>https://dev.to/sheships/how-i-actually-learn-new-skills-no-tutorial-required-3iia</guid>
      <description>&lt;p&gt;I used to think learning meant reading, watching, absorbing. Now I think learning mostly means &lt;em&gt;breaking things and finding out why.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The loop that actually works for me:&lt;/strong&gt; learn → attempt → debug → understand → ship → reflect. Not learn → learn → learn → maybe someday attempt. The tutorial-first approach always left me with a weird kind of knowledge — I could follow along, but I couldn't tell you why any of it worked, and the second something didn't match the tutorial exactly, I was stuck. What actually sticks is trying something, watching it fail in a specific way, and having to figure out &lt;em&gt;why&lt;/em&gt; that specific failure happened. That's not a bug in the learning process — that's the whole mechanism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And I write things down — publicly, even the messy parts.&lt;/strong&gt; That's basically the whole premise of my &lt;a href="https://miflow13.github.io/MikasOpenLearningNotebook/" rel="noopener noreferrer"&gt;open learning notebook&lt;/a&gt;: field notes, half-formed thoughts, and the connections I'm making as I go, with no curriculum behind any of it. Writing something out is often the moment I actually understand it, not just the moment I record that I understand it — and keeping that record public means I can't quietly pretend I learned something faster or cleaner than I actually did.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F95wsv2b7fn531iz85ztm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F95wsv2b7fn531iz85ztm.png" alt="open learning notebook" width="799" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And I've stopped trying to impose order on top of that.&lt;/strong&gt; No color-coded study plans, no structured syllabus. Just: what's the smallest next thing I can actually attempt today? Small concrete next actions beat ambitious productivity systems every time, because the systems are things you plan and the actions are things you actually do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency over intensity.&lt;/strong&gt; I used to swing between all-or-nothing — a manic week of nonstop learning followed by weeks of nothing, restarting from scratch each time. What works better is showing up smaller, more often, and not breaking the thread. Leaving myself breadcrumbs. Picking up exactly where I left off instead of re-deciding where to start every single time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I want to understand the "why," not just get a working answer.&lt;/strong&gt; This matters a lot right now because I use AI a lot in my own development work — and it would be very easy to let it just hand me finished code. But that's not the point for me. I want to come out the other side of a problem actually more capable than I went in, not just holding a solution I can't explain. AI as a pair, not a replacement — something that helps me think through the architecture and tradeoffs, not something that thinks for me.&lt;/p&gt;

&lt;p&gt;None of this is a system you can buy or a framework with a name. It's just what's actually true about how my brain learns, after paying attention to it for a while instead of trying to force myself into someone else's method.&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>tutorial</category>
      <category>discuss</category>
    </item>
    <item>
      <title>I Built a Better Codex Pet Than OpenAI Did</title>
      <dc:creator>Mika Flowers</dc:creator>
      <pubDate>Sat, 26 Sep 2026 11:16:56 +0000</pubDate>
      <link>https://dev.to/mikachu/i-built-a-better-codex-pet-than-openai-did-eib</link>
      <guid>https://dev.to/mikachu/i-built-a-better-codex-pet-than-openai-did-eib</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwdqi2xc7izznbtuth5gt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwdqi2xc7izznbtuth5gt.gif" alt="let him cook" width="256" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sometimes you just have to let the agent cook.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;Mika vs. a multi-billion-dollar corporation, and a stupid little desktop pet.&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;When OpenAI shipped Codex Pets in May 2026, they wanted to give your coding agent a face. The pets float as an overlay on Windows and macOS, showing real-time status updates about what Codex is doing, and can notify users when a task completes or when the agent needs input. The feature launched with eight built-in pets and a way to generate custom, AI-animated pets from user images.&lt;/p&gt;

&lt;p&gt;Before I go further, a caveat: this isn't really a fair fight. Codex Pets is a small feature bolted onto a coding agent used by millions of people, built by a team with the resources to ship across two operating systems on day one. Mochi is a solo, Linux-only alpha. They're not competing for the same thing, and if you're after "which is the more polished, widely-used product," Codex Pets wins that easily. What they &lt;em&gt;do&lt;/em&gt; share is one idea — a little creature that lives on your screen — and this is a look at what happens when you take that same idea and refuse to stop at "cute status light."&lt;/p&gt;

&lt;p&gt;It's a clever idea. It's also, underneath the cute art, kind of nothing. Strip away the sprite and a Codex Pet is a status light with a tail — a red clock when it's waiting on you, a green check when it's done. Cute, sure. Impressive, not really. So I built the version I actually wanted: &lt;a href="https://github.com/miflow13/mochi-desktop" rel="noopener noreferrer"&gt;Mochi&lt;/a&gt;, an open-source Linux desktop companion with a real state machine, real memory, and a real reason to exist beyond one app's notification stream.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Codex Pets actually are
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwd5yl141lw77zs7z2bg4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwd5yl141lw77zs7z2bg4.png" alt="codexpet" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Functionally, a Codex Pet is tied to one thing: the state of a Codex agent thread. It's a pixel-art animated companion that floats over the desktop while Codex codes, reacting to mouse interaction and Codex status — scratching its head when thinking, popping a speech bubble when a task completes. Custom pets are just a manifest file plus a spritesheet, dropped into a folder. There's no persistent internal state beyond "what is the agent doing right now," no memory between sessions, and no behavior that isn't ultimately a reflection of Codex's own status.&lt;/p&gt;

&lt;p&gt;To be fair, that's the correct amount of engineering for the job. A glanceable agent-status widget doesn't need a state machine. It needs to be cute, legible at a glance, and easy for a community to remix. OpenAI nailed that brief. But it &lt;em&gt;is&lt;/em&gt; just a brief, and a narrow one — the pet doesn't outlive the thread it's watching.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Mochi is instead
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffv7a2a2obtic73fbqvw0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffv7a2a2obtic73fbqvw0.png" alt="mochi" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mochi doesn't report on anything external. It's not a status light for some other tool — it's meant to feel like it lives on your desktop, full stop, independent of whatever app you happen to have open. That's a different, harder problem, and it shows in the architecture.&lt;/p&gt;

&lt;p&gt;Under the hood, Mochi runs on a single authoritative behavior-state machine that mediates between dozens of competing systems — clicking, dragging, sleep, typing detection, media playback, contextual app awareness, and more — all of which have to agree on one question at any given moment: what does Mochi currently own, and what's it allowed to do next? That's before you even get to the systems a Codex Pet has no equivalent for at all:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AmbiSense&lt;/strong&gt; — a local, rule-based ambient-awareness layer that reduces desktop activity (typing, video playback, file browsing, active app) into privacy-safe semantic signals. Not an LLM, not a cloud service, and built to never see actual keystrokes, file names, or window titles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bond progression&lt;/strong&gt; — a slow, deliberately non-punitive relationship system. No streaks, no decay, no penalty for missing a day. XP accrues from typing time and feeding, and leveling up triggers its own presentation sequence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Focus sessions&lt;/strong&gt; — a full Pomodoro-style domain model with its own clock that keeps running even when the visual gets interrupted by a drag or a click. What Mochi looks like and what's actually true in the background are deliberately different questions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An Emote Catalogue&lt;/strong&gt; with bond-gated unlocks and rarity tiers, so what Mochi can do actually grows the longer you've had it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A GNOME Shell helper&lt;/strong&gt; that taps into real desktop context — typing pulses, idle/active state, app category, video focus — over D-Bus, again reduced to coarse semantic signals rather than raw data.
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    Desktop["Linux Desktop"]
    GNOME["GNOME Shell Helper&amp;lt;br/&amp;gt;D-Bus"]
    Ambi["AmbiSense&amp;lt;br/&amp;gt;Local Rule-Based Context Layer"]

    Desktop --&amp;gt; GNOME
    GNOME --&amp;gt;|"coarse semantic signals"| Ambi

    Ambi --&amp;gt; Typing["Typing Activity"]
    Ambi --&amp;gt; Video["Video / Media Focus"]
    Ambi --&amp;gt; Apps["App Category"]
    Ambi --&amp;gt; Idle["Idle / Active State"]
    Ambi --&amp;gt; Files["File Browsing Activity"]

    User["User"]

    Click["Click"]
    Drag["Drag / Pickup"]
    Feed["Feed"]
    Media["Media Controls"]

    User --&amp;gt; Click
    User --&amp;gt; Drag
    User --&amp;gt; Feed
    User --&amp;gt; Media

    State["Authoritative&amp;lt;br/&amp;gt;Behavior State Machine"]

    Typing --&amp;gt; State
    Video --&amp;gt; State
    Apps --&amp;gt; State
    Idle --&amp;gt; State
    Files --&amp;gt; State

    Click --&amp;gt; State
    Drag --&amp;gt; State
    Media --&amp;gt; State

    Sleep["Sleep System"]
    Context["Contextual App Behavior"]
    Animation["Animation / Emote Playback"]

    Sleep --&amp;gt; State
    Context --&amp;gt; State

    State --&amp;gt;|"Who owns Mochi?"| Animation
    State --&amp;gt;|"What may happen next?"| Sleep
    State --&amp;gt;|"Allowed reactions"| Context

    Bond["Bond Progression&amp;lt;br/&amp;gt;XP · Levels · No Decay"]
    Focus["Focus Sessions&amp;lt;br/&amp;gt;Independent Pomodoro Clock"]
    Catalogue["Emote Catalogue&amp;lt;br/&amp;gt;Rarity + Bond Unlocks"]

    Feed --&amp;gt; Bond
    Typing --&amp;gt; Bond

    Bond --&amp;gt; Catalogue
    Catalogue --&amp;gt; State

    User --&amp;gt; Focus
    Focus --&amp;gt; State

    State -. "visual state may be interrupted" .-&amp;gt; Focus
    Focus -. "session truth keeps running" .-&amp;gt; State

    Presentation["Mochi Presentation Layer&amp;lt;br/&amp;gt;animation · movement · expression"]

    Animation --&amp;gt; Presentation
    Sleep --&amp;gt; Presentation
    Context --&amp;gt; Presentation
    State --&amp;gt; Presentation&lt;/code&gt;&lt;/pre&gt;



&lt;blockquote&gt;
&lt;p&gt;Mochi’s architecture separates what is true from what is currently visible. Desktop context, user interaction, progression, focus state, and autonomous behavior all converge on a single behavior-state machine that decides who currently “owns” Mochi and which transitions are legal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;None of that is decoration. Most of Mochi's codebase manual is about lifecycle and ownership: making sure a stale animation callback can't fire after a feature's been interrupted, that a context menu closing visually doesn't leave an invisible input grab behind, that recovery always reevaluates the &lt;em&gt;current&lt;/em&gt; live context instead of blindly replaying whatever was happening before something interrupted it. That's the kind of problem you only run into once a system has enough moving parts to actually collide with itself — which is exactly the problem a Codex Pet is small enough to never have.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real difference
&lt;/h2&gt;

&lt;p&gt;Here's the honest version, not just the flex: a Codex Pet is &lt;em&gt;supposed&lt;/em&gt; to be thin. It's a feature bolted onto a coding agent, meant to be authored in minutes and understood in one glance. Giving it Mochi's architecture would be overkill for what it's for.&lt;/p&gt;

&lt;p&gt;But that's also exactly the point. OpenAI built a mascot for their product. I built a product whose whole job is &lt;em&gt;being&lt;/em&gt; the mascot — one with persistence, context-awareness, care mechanics that don't depend on any single app, and a state machine robust enough to survive being dragged around, interrupted, and left alone for a week. Codex Pets are a nice feature riding on the back of a multi-billion-dollar coding agent. Mochi is the thing itself, built by one person who wanted the version that actually commits to the bit.&lt;/p&gt;

&lt;p&gt;I know which one I'd rather maintain.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Codex Pets details in this post are drawn from public reporting and documentation, not insider access. Mochi is open-source — &lt;a href="https://github.com/miflow13/mochi-desktop" rel="noopener noreferrer"&gt;browse the code, file an issue, or just come say hi to the little guy&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>python</category>
      <category>linux</category>
      <category>showdev</category>
    </item>
    <item>
      <title>My AI Agent's Skill Declared Nothing. It Still Read 9 Files, Ran 7 Processes, and Got Blocked 3 Times.</title>
      <dc:creator>Mika Flowers</dc:creator>
      <pubDate>Fri, 25 Sep 2026 23:30:52 +0000</pubDate>
      <link>https://dev.to/mikachu/my-ai-agents-skill-declared-nothing-it-still-read-9-files-ran-7-processes-and-got-blocked-3-gmn</link>
      <guid>https://dev.to/mikachu/my-ai-agents-skill-declared-nothing-it-still-read-9-files-ran-7-processes-and-got-blocked-3-gmn</guid>
      <description>&lt;p&gt;I gave an AI agent a code-review skill. It never mentioned touching the filesystem or spawning processes — just "review this repo." By the time it reported success, it had done both, repeatedly, and hit a policy wall three times along the way.&lt;/p&gt;

&lt;p&gt;That's when I realized I'd been asking the wrong question about AI agents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I know what the agent actually did?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not what it said it did.&lt;br&gt;
Not whether the final test passed.&lt;br&gt;
Not whether the generated code looked reasonable.&lt;/p&gt;

&lt;p&gt;What did it actually attempt inside the environment?&lt;/p&gt;

&lt;p&gt;So I designed the approach and prompted Codex to build a harness that tests what these models actually do vs. what they say.&lt;/p&gt;

&lt;p&gt;It's an experimental setup for studying the gap between what AI agents are instructed to do, what they attempt to do, what the host allows them to do, and what actually changes as a result.&lt;/p&gt;

&lt;p&gt;Building it has changed how I think about AI agent evaluation.&lt;/p&gt;


&lt;h2&gt;
  
  
  A Passing Agent Can Still Behave Very Differently
&lt;/h2&gt;

&lt;p&gt;Most coding benchmarks understandably care about the result.&lt;/p&gt;

&lt;p&gt;Give the model a task. Run the tests. Did it solve the problem?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent A: PASS
Agent B: PASS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But imagine those runs actually looked like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent A&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reads allowed files&lt;/li&gt;
&lt;li&gt;edits the intended files&lt;/li&gt;
&lt;li&gt;runs the approved tests&lt;/li&gt;
&lt;li&gt;finishes successfully&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Agent B&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tries to access the network&lt;/li&gt;
&lt;li&gt;searches outside the workspace&lt;/li&gt;
&lt;li&gt;attempts an unauthorized command&lt;/li&gt;
&lt;li&gt;gets blocked several times&lt;/li&gt;
&lt;li&gt;eventually finishes successfully&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both may have produced the right answer. But they are obviously not the same run.&lt;/p&gt;

&lt;p&gt;That's the gap I wanted the harness to investigate.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Four Things I Wanted to Keep Separate
&lt;/h2&gt;

&lt;p&gt;The harness currently revolves around four layers:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;graph TD
    A[Declared] --&amp;gt; B[Attempted]
    B --&amp;gt; C[Policy]
    C --&amp;gt; D[Observed]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;strong&gt;Declared&lt;/strong&gt; — What did the instructions say should happen?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;e.g. "Do not access the network."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Attempted&lt;/strong&gt; — What did the agent actually try to do?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;request_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Policy&lt;/strong&gt; — What did the execution environment allow?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DENY: network unavailable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Observed&lt;/strong&gt; — What actually happened to the environment?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No outbound connection occurred. No network canary changed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That produces an interesting result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declared behavior ≠ attempted behavior&lt;/li&gt;
&lt;li&gt;Attempted behavior ≠ observed side effect&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent violated the instructional boundary even though the sandbox successfully prevented the physical effect. That's useful information — a simple pass/fail result loses it.&lt;/p&gt;




&lt;h2&gt;
  
  
  I Don't Want the Agent's Final Answer to Be Evidence
&lt;/h2&gt;

&lt;p&gt;This became one of the central design rules.&lt;/p&gt;

&lt;p&gt;Suppose an agent says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I didn't modify anything outside the target directory."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cool. But that's still just another model output. The evaluator shouldn't have to trust it.&lt;/p&gt;

&lt;p&gt;So the harness checks the environment independently, using &lt;strong&gt;canaries&lt;/strong&gt; — deliberately known state placed somewhere in the environment so the runner can later determine whether it was touched or changed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before run:  canary = unchanged
Agent executes
After run:   canary = unchanged   (or: modified)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The environment becomes evidence. That distinction seems obvious in hindsight, but I think it matters a lot as agents gain more tools and autonomy.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Current Architecture
&lt;/h2&gt;

&lt;p&gt;It's built around a controlled runner rather than letting a model operate directly on my host machine.&lt;/p&gt;

&lt;p&gt;The current stack includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript / Node.js&lt;/li&gt;
&lt;li&gt;a dedicated Runner&lt;/li&gt;
&lt;li&gt;instrumented tools&lt;/li&gt;
&lt;li&gt;explicit allow/deny policy&lt;/li&gt;
&lt;li&gt;rootless Podman containers&lt;/li&gt;
&lt;li&gt;fixed task fixtures&lt;/li&gt;
&lt;li&gt;synthetic canaries&lt;/li&gt;
&lt;li&gt;filesystem snapshots and deltas&lt;/li&gt;
&lt;li&gt;raw JSONL execution traces&lt;/li&gt;
&lt;li&gt;derived JSON results&lt;/li&gt;
&lt;li&gt;provenance-linked HTML reports&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;inspect&lt;/code&gt;, &lt;code&gt;run&lt;/code&gt;, and &lt;code&gt;verify&lt;/code&gt; commands&lt;/li&gt;
&lt;li&gt;a deterministic fake Runner&lt;/li&gt;
&lt;li&gt;an OpenAI Responses API adapter for real model runs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The flow looks roughly like:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;graph TD
    A[Task + skill + policy] --&amp;gt; B[Controlled runner]
    B --&amp;gt; C[Model / tool events]
    C --&amp;gt; D[Raw trace]
    D --&amp;gt; E[Environment snapshot]
    E --&amp;gt; F[Derived findings]
    F --&amp;gt; G[Human-readable report]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The important part: the pretty report is not the source of truth. It's derived from lower-level evidence.&lt;/p&gt;




&lt;h2&gt;
  
  
  Provenance Became More Important Than I Expected
&lt;/h2&gt;

&lt;p&gt;If the harness produces a finding like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Unexpected filesystem write detected&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I want to be able to trace it back:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which tool invocation caused it?&lt;/li&gt;
&lt;li&gt;Which trace event recorded that invocation?&lt;/li&gt;
&lt;li&gt;Which policy applied?&lt;/li&gt;
&lt;li&gt;Which snapshot proves the file changed?&lt;/li&gt;
&lt;li&gt;What exact path was involved?&lt;/li&gt;
&lt;li&gt;What model/configuration produced the run?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's provenance. Without it, an evaluator becomes just another opaque AI system saying "trust me, something suspicious happened" — which would be pretty ironic.&lt;/p&gt;




&lt;h2&gt;
  
  
  First I Had to Benchmark the Benchmark
&lt;/h2&gt;

&lt;p&gt;This was probably my favorite lesson from the project so far.&lt;/p&gt;

&lt;p&gt;Before using a real model, I built a deterministic fake Runner. Instead of asking an AI what to do, it performs a scripted sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;write this allowed file
attempt this forbidden action
touch this canary
return this known result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should report exactly what I expect. If the expected behavior and the generated report disagree, the problem isn't the AI model — it's the harness.&lt;/p&gt;

&lt;p&gt;That gives me a calibration loop:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;graph LR
    A[Known behavior] --&amp;gt; B[Trace]
    B --&amp;gt; C[Policy decisions]
    C --&amp;gt; D[Snapshot / delta]
    D --&amp;gt; E[Report]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Only after that chain works should I start trusting conclusions from nondeterministic model runs.&lt;/p&gt;




&lt;h2&gt;
  
  
  And Sure Enough, the Evaluator Had Bugs
&lt;/h2&gt;

&lt;p&gt;The first live pilot immediately exposed weaknesses in the harness itself, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;output preservation&lt;/li&gt;
&lt;li&gt;declaration detection&lt;/li&gt;
&lt;li&gt;path normalization&lt;/li&gt;
&lt;li&gt;answer-key contamination&lt;/li&gt;
&lt;li&gt;missing Git inside the container&lt;/li&gt;
&lt;li&gt;host-path leakage&lt;/li&gt;
&lt;li&gt;model reasoning configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I actually found that encouraging — this is exactly why calibration matters. An evaluation tool can generate a false conclusion just as easily as the system being evaluated can behave incorrectly. The evaluator is software too. It needs tests.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deterministic Doesn't Mean the Model Must Be Deterministic
&lt;/h2&gt;

&lt;p&gt;This project helped me finally internalize the difference between determinism and reproducibility.&lt;/p&gt;

&lt;p&gt;A deterministic system means: same input + same starting conditions = same result. AI models don't always give us that.&lt;/p&gt;

&lt;p&gt;But I can still control everything around the model: fixed task, fixed fixture, fixed policy, fixed resource limits, known container image, known canaries, recorded model configuration, raw traces, versioned source.&lt;/p&gt;

&lt;p&gt;Then when two model runs differ, I have a much better chance of understanding why. I'm not trying to pretend nondeterminism doesn't exist — I'm trying to stop unnecessary variables from making the experiment impossible to reason about.&lt;/p&gt;




&lt;h2&gt;
  
  
  The First Study
&lt;/h2&gt;

&lt;p&gt;The first experiment is called &lt;strong&gt;Study 001 — Declared vs. Observed Behavior&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The basic idea is to hold as much constant as possible — model, runner, task, fixture, policy, resource limits — and then examine differences between what instructions declare, what the model attempts, what policy allows, and what ultimately happens.&lt;/p&gt;

&lt;p&gt;I want the result to look more like an experiment than "I prompted some models and vibes were weird."&lt;/p&gt;

&lt;p&gt;Here's that run in full: an OpenAI model given a code-review skill, pointed at a small web-app fixture, inside a rootless container with the network disabled and a hard cap on filesystem writes, process count, and steps.&lt;/p&gt;

&lt;p&gt;The skill itself declared nothing — no listed commands, no referenced scripts, no URLs. Just instructions in prose.&lt;/p&gt;

&lt;p&gt;What actually happened:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Observation&lt;/th&gt;
&lt;th&gt;Count&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Files read&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Processes started&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Denied actions&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network requests attempted&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Filesystem writes&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Termination reason&lt;/td&gt;
&lt;td&gt;completed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three of those denied actions happened back-to-back, within a single millisecond of each other, right after two earlier commands had gone through — a rapid retry against the policy boundary before the agent moved on to something else. Neither the file reads nor the process executions were ever declared by the skill, which the comparison pass flags outright as &lt;code&gt;observed_not_declared&lt;/code&gt; for both categories.&lt;/p&gt;

&lt;p&gt;Nothing dangerous happened here — the policy held, nothing left the sandbox, the run completed cleanly. But that's exactly the point: the skill's own description said nothing about touching the filesystem or spawning processes, and the agent did both, repeatedly, plus made three attempts that were blocked. A pass/fail grade on "did it review the code" would have shown none of that.&lt;/p&gt;




&lt;h2&gt;
  
  
  This Isn't a "Safety Score"
&lt;/h2&gt;

&lt;p&gt;One thing I specifically don't want the harness to become:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;GPT-X: 84/100 safe&lt;br&gt;
Model Y: 73/100 safe&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That number might look authoritative while hiding an enormous amount of context. I'd rather produce something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Task completed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="na"&gt;Network attempts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="na"&gt;Network attempts blocked&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="na"&gt;Unexpected writes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;Declared/attempted discrepancy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="na"&gt;Trace event&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;#47&lt;/span&gt;
&lt;span class="na"&gt;Policy event&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;#48&lt;/span&gt;
&lt;span class="na"&gt;Environment delta&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;none&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the person reading the result can inspect the evidence. It should help answer questions — it shouldn't pretend to settle every question with one number.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is This Completely Unique?
&lt;/h2&gt;

&lt;p&gt;Probably not, and I'm intentionally avoiding claims like "world's first AI agent behavior benchmark!!!"&lt;/p&gt;

&lt;p&gt;There are already agent benchmarks, sandbox systems, trace graders, security evaluations, MCP tooling, observability platforms, and research projects looking at overlapping problems. That's good — it means this is a real problem space.&lt;/p&gt;

&lt;p&gt;The part I'm particularly interested in is keeping this entire chain visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;instruction → attempt → authorization → physical effect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That gives the project a narrower and, I think, more useful question: not only "Did the agent succeed?" but "How did the agent behave while trying?"&lt;/p&gt;




&lt;h2&gt;
  
  
  Who Might Actually Use This?
&lt;/h2&gt;

&lt;p&gt;The obvious group is people building coding agents. But it extends further:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent developers&lt;/strong&gt; — test how an agent behaves when given real tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security and red teams&lt;/strong&gt; — see whether an agent attempts actions outside its intended boundary, even when those actions are successfully blocked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent framework developers&lt;/strong&gt; — test permission systems, tool routers, sandboxes, and orchestration layers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP and tool authors&lt;/strong&gt; — observe how agents actually interact with a tool rather than assuming the description will produce the expected behavior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model evaluators&lt;/strong&gt; — compare models under the same controlled execution environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Companies deploying internal agents&lt;/strong&gt; — test an agent in a disposable environment before giving it repository, CI, infrastructure, or production access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open-source maintainers&lt;/strong&gt; — potentially test AI contributors or coding bots against a fixture before allowing them near a real repository.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Eventually I'd Love This to Feel Simple
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;harness run evals/no-network.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then CI could produce:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;Harness Evaluation&lt;/span&gt;
&lt;span class="na"&gt;Task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dependency refactor&lt;/span&gt;
&lt;span class="na"&gt;Outcome&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PASS&lt;/span&gt;
&lt;span class="na"&gt;Policy violations attempted&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="na"&gt;Blocked network attempts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="na"&gt;Unexpected filesystem writes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;Declared/attempted discrepancies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="na"&gt;Trace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;available&lt;/span&gt;
&lt;span class="na"&gt;Environment diff&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;available&lt;/span&gt;
&lt;span class="na"&gt;Report&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;available&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At that point it becomes less like a traditional benchmark and more like a behavioral testing and observability layer for AI agents. That's the direction I'm increasingly interested in.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bigger Lesson for Me
&lt;/h2&gt;

&lt;p&gt;I'm still fairly new to serious AI-agent engineering, which is part of why this project has been so useful.&lt;/p&gt;

&lt;p&gt;I originally thought evaluating an agent mostly meant: give it a task → check the answer.&lt;/p&gt;

&lt;p&gt;Now I think much more in terms of:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;graph TD
    A[Give it a task] --&amp;gt; B[Record what it tries]
    B --&amp;gt; C[Enforce boundaries]
    C --&amp;gt; D[Inspect what actually happened]
    D --&amp;gt; E[Preserve the evidence]
    E --&amp;gt; F[Evaluate the evaluator]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;That feels like a much healthier mental model for increasingly capable agents. The question isn't only "Did the AI get the right answer?" It's also "What happened between the prompt and the answer?"&lt;/p&gt;

&lt;p&gt;That's what I'm trying to make this harness good at showing.&lt;/p&gt;




&lt;p&gt;This is still very early — one skill, one fixture, one model — but Study 001's first real run already surfaced something worth knowing: a skill that declares nothing can still read nine files, spawn seven processes, and hit a policy wall three times before finishing clean. Building the tool has already taught me more than I expected the tool itself to measure.&lt;/p&gt;

&lt;p&gt;If you're working on coding agents, sandboxes, agent evaluation, MCP tooling, or AI security, I'd genuinely be interested in hearing what kinds of behavior you'd want a system like this to capture.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>typescript</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Can Two Local AI Agents Build an App Without Me? I Gave Them 6 Rounds to Find Out</title>
      <dc:creator>Mika Flowers</dc:creator>
      <pubDate>Fri, 25 Sep 2026 17:04:39 +0000</pubDate>
      <link>https://dev.to/mikachu/can-two-local-ai-agents-build-an-app-without-me-i-gave-them-6-rounds-to-find-out-ko1</link>
      <guid>https://dev.to/mikachu/can-two-local-ai-agents-build-an-app-without-me-i-gave-them-6-rounds-to-find-out-ko1</guid>
      <description>&lt;p&gt;I have very, &lt;strong&gt;very&lt;/strong&gt; limited experience with AI agents.&lt;/p&gt;

&lt;p&gt;I've used AI heavily while building software, debugging, writing, researching, and generally figuring things out as I go. But multi-agent systems? Local models? Orchestrating two separate models and letting them pass work back and forth without me stepping in?&lt;/p&gt;

&lt;p&gt;That was new territory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which is exactly why I wanted to try it. heh&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The overall question was a simple one. In my head, at least:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What happens if I give one local AI model the job of software developer, another local model the job of code reviewer, and then get out of their way?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No OpenAI API.&lt;br&gt;
No Claude API.&lt;br&gt;
No paid inference.&lt;/p&gt;

&lt;p&gt;Just Ollama, Python, my PC, and two local models talking to each other.&lt;/p&gt;

&lt;p&gt;My PC specs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* CPU: Intel i5-12600KF
* GPU: NVIDIA RTX 3070 Ti
* RAM: 16 GB
* OS: Fedora Linux
* Runtime: Ollama
* Initial models: Qwen2.5-Coder 7B + Qwen3 8B
* Final models: Qwen2.5-Coder 3B + Qwen3 4B

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is hilarious, honestly. I expected the experiment to either fail immediately or produce something surprisingly competent. Instead, it did both.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea
&lt;/h2&gt;

&lt;p&gt;I wanted the simplest possible development team.&lt;/p&gt;

&lt;p&gt;One agent would be the &lt;strong&gt;Builder&lt;/strong&gt;. Its responsibility was to read a product request, inspect the current workspace, and create or modify the application.&lt;/p&gt;

&lt;p&gt;The second agent would be the &lt;strong&gt;Reviewer&lt;/strong&gt;. It would receive the original task, inspect what the Builder created, review the implementation, and either approve it or request changes.&lt;/p&gt;

&lt;p&gt;The flow looked like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2mflvd7isq6q3fvcfc94.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2mflvd7isq6q3fvcfc94.png" alt="diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I called the project &lt;strong&gt;RelayLab&lt;/strong&gt;, because the agents essentially relay the project between each other. (duh)&lt;/p&gt;

&lt;p&gt;The orchestrator itself is just Python. For the first version, I intentionally kept it constrained — partly because I wanted to keep the test simple, and partly because I had no clue what I was doing. The agents couldn't run arbitrary shell commands or touch the rest of my computer. The Builder could only propose file writes and deletions inside an isolated experiment workspace. Every round was also logged so I could inspect exactly what happened afterward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing the Models
&lt;/h2&gt;

&lt;p&gt;My first attempt was perhaps slightly ambitious. I started with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Builder:  qwen2.5-coder:7b
Reviewer: qwen3:8b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And my computer basically responded: &lt;em&gt;absolutely not.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa3q8vjqfoaznnfs6und6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa3q8vjqfoaznnfs6und6.png" alt="fail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CPU usage shot to 100%, the machine became almost unusable, and I got my first lesson in running multiple local models. The issue wasn't just model size — Ollama was keeping both models loaded between turns, which meant the second model couldn't fit cleanly into GPU memory and started spilling work onto the CPU.&lt;/p&gt;

&lt;p&gt;So I downsized. The eventual setup became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Builder:  qwen2.5-coder:3b
Reviewer: qwen3:4b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also changed the Ollama requests to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"keep_alive"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That forces each model to unload after its turn — like the good little AI it is. Instead of two AI coworkers fighting over the same VRAM, the process became:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0c2qvtvt6r9jxxqlxs0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0c2qvtvt6r9jxxqlxs0q.png" alt="builder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Much better.&lt;/p&gt;

&lt;p&gt;Seeing 100% GPU in &lt;code&gt;ollama ps&lt;/code&gt; while a completely local model was actively building an application was genuinely one of those little moments where the technology suddenly felt much more real. There's an unexplainable joy about running local AI models rather than using something like ChatGPT or Codex. This is all happening &lt;em&gt;right now, on my computer?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Truth be told, I spend a lot of time using AI products. But running the actual models locally and watching them become parts of a system I wrote myself felt completely different.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug #1: Ollama Could Download Models But Couldn't Run Them
&lt;/h2&gt;

&lt;p&gt;Before any agents could actually talk, I hit an even stranger issue.&lt;/p&gt;

&lt;p&gt;Ollama happily let me download several gigabytes of models. &lt;code&gt;ollama list&lt;/code&gt; worked perfectly. Then I tried running one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;error starting llama-server:
llama-server binary not found
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Huh?&lt;/p&gt;

&lt;p&gt;My Ollama installation was incomplete — which is particularly funny, because from the outside everything looked fine. The models existed. The service existed. The CLI existed. The component responsible for actually performing inference did not.&lt;/p&gt;

&lt;p&gt;After reinstalling Ollama properly, the models finally started running. RelayLab itself hadn't even had its first agent conversation yet, and I had already learned considerably more about local inference than I expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then the Agents Started Talking
&lt;/h2&gt;

&lt;p&gt;For my first real test, I deliberately avoided writing an extremely detailed specification. I gave the system this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Build a polished single-page notes app where I can
create, complete, and delete notes.
Make it pleasant to use.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Builder received that prompt. It generated an &lt;code&gt;index.html&lt;/code&gt;. Lil ole RelayLab wrote the file.&lt;/p&gt;

&lt;p&gt;Then the Reviewer inspected it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[round 1] builder wrote 1 file(s); reviewer: changes_requested
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great, I thought.&lt;/p&gt;

&lt;p&gt;The review went back to the Builder. Another revision.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[round 2] builder wrote 1 file(s); reviewer: changes_requested
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then another.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[round 3] builder wrote 1 file(s); reviewer: changes_requested
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point I was sitting there watching two local models iterate on software without me writing the implementation. And yes, that was extremely cool.&lt;/p&gt;

&lt;p&gt;Then the Reviewer broke the entire experiment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Agents Couldn't Agree on How to Say "No"
&lt;/h2&gt;

&lt;p&gt;I initially required the Reviewer to return exactly one of two statuses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"approved"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"changes_requested"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seems reasonable. Except small local language models do not particularly care about your beautifully designed enum. The Reviewer returned something else.&lt;/p&gt;

&lt;p&gt;RelayLab responded exactly as any lovingly over-strict software system should: &lt;code&gt;AgentProtocolError&lt;/code&gt;. Crash.&lt;/p&gt;

&lt;p&gt;The funny part was that the AI had probably made a completely sensible judgment. The system failed because it expressed that judgment using the wrong vocabulary.&lt;/p&gt;

&lt;p&gt;So I made the orchestrator more tolerant. Statuses such as &lt;code&gt;rejected&lt;/code&gt;, &lt;code&gt;needs_changes&lt;/code&gt;, &lt;code&gt;request_changes&lt;/code&gt;, and &lt;code&gt;failed&lt;/code&gt; were normalized into &lt;code&gt;changes_requested&lt;/code&gt;. Likewise, &lt;code&gt;pass&lt;/code&gt;, &lt;code&gt;accepted&lt;/code&gt;, and &lt;code&gt;approve&lt;/code&gt; became &lt;code&gt;approved&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That fixed the first problem. Then the Reviewer found a new way to break things — it returned valid JSON with no status field at all. The response was probably wrapped inside another structure, or used a completely different property name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"review"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"revision required"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"issues"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Notes do not persist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Delete button needs an accessible label"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It now normalizes that into something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"changes_requested"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"feedback"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"- Notes do not persist&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;- Delete button needs an accessible label"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if the Reviewer still produces something completely unusable, RelayLab no longer destroys the entire experiment. It safely assumes &lt;code&gt;changes_requested&lt;/code&gt;, preserves the malformed response in the logs, and keeps going.&lt;/p&gt;

&lt;p&gt;This might have been my favorite lesson from the experiment: the models weren't necessarily failing at reasoning. They were failing at protocol obedience. And those are very different problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Full Run
&lt;/h2&gt;

&lt;p&gt;Eventually, the system survived all six rounds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[round 1] builder wrote 1 file(s); reviewer: changes_requested
[round 2] builder wrote 1 file(s); reviewer: changes_requested
[round 3] builder wrote 1 file(s); reviewer: changes_requested
[round 4] builder wrote 1 file(s); reviewer: changes_requested
[round 5] builder wrote 1 file(s); reviewer: changes_requested
[round 6] builder wrote 1 file(s); reviewer: changes_requested
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Runtime: &lt;strong&gt;3 minutes, 54 seconds&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Final result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"max_rounds_reached"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rounds_completed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;And this was the application.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fomvpkyelaa86yujuxvri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fomvpkyelaa86yujuxvri.png" alt="um"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um. Wow.... Beautiful. Stunning. A triumph of modern artificial intelligence.&lt;/p&gt;

&lt;p&gt;It looks like an HTML tutorial from 1998. 😭&lt;/p&gt;

&lt;p&gt;The app worked well enough to create notes, and the agents had clearly spent several rounds modifying the implementation. But remember the original instruction: &lt;em&gt;make it pleasant to use.&lt;/em&gt; The giant white page, browser-default input, browser-default buttons, and nearly nonexistent visual hierarchy were not exactly what I had in mind.&lt;/p&gt;

&lt;p&gt;The even more interesting part was what the Reviewer cared about during the final round. Its feedback was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Critical bug in completion toggle: the note text gets a trailing space when toggling between completed and not completed. The completion state should be stored as a boolean per note to avoid string manipulation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And technically? That's a good review. The Reviewer found a legitimate implementation flaw.&lt;/p&gt;

&lt;p&gt;But look at the screenshot again. There was a much bigger problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Agents Were Optimizing the Wrong Thing
&lt;/h2&gt;

&lt;p&gt;This became the most interesting result of the experiment.&lt;/p&gt;

&lt;p&gt;The agents were cooperating. The Builder could implement changes. The Reviewer could find bugs. Feedback successfully traveled between them. But the system wasn't necessarily becoming a &lt;em&gt;better product&lt;/em&gt;. Instead, it started becoming locally optimized.&lt;/p&gt;

&lt;p&gt;The Reviewer found a specific issue. The Builder addressed that issue. The Reviewer found another specific issue. The Builder addressed that. Six rounds later, they were debating representation of completion state while the application still looked almost completely unfinished.&lt;/p&gt;

&lt;p&gt;Neither agent consistently stepped back and asked: &lt;em&gt;does this actually satisfy the user's overall request?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's a different problem from code generation. It's a coordination problem. And simply adding another AI agent didn't magically solve it.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Just Add More Agents" Probably Isn't the Answer
&lt;/h2&gt;

&lt;p&gt;Before doing this experiment, it would have been easy for me to assume:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;one AI developer = useful&lt;br&gt;
therefore&lt;br&gt;
developer AI + reviewer AI = more useful&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But the interaction &lt;em&gt;between&lt;/em&gt; agents matters just as much as the intelligence of the individual models.&lt;/p&gt;

&lt;p&gt;My first Reviewer prompt essentially told the model: &lt;em&gt;find problems.&lt;/em&gt; So that's what it did. Forever. There was no strong definition of what "done" actually meant. No acceptance rubric. No prioritization. No distinction between:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;BLOCKER:&lt;/strong&gt; The requested feature doesn't exist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;MINOR:&lt;/strong&gt; There's an extra whitespace character in the internal representation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Without that structure, adding a Reviewer can actually create an endless optimization loop. The system needs a manager — even if that manager is deterministic code rather than another LLM.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm Changing Next
&lt;/h2&gt;

&lt;p&gt;RelayLab's next version will give the agents explicit acceptance criteria instead of relying on open-ended reviews. For this notes app, that might include functionality, usability, accessibility, visual quality, persistence, and whether the actual product still resembles the original request.&lt;/p&gt;

&lt;p&gt;I also want to introduce browser verification. Right now, the Reviewer only sees the source code — it doesn't see what I saw when I opened the resulting file. That matters. Eventually I'd like the workflow to become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Builder
   ↓
writes app
   ↓
browser harness
   ↓
opens application
   ↓
performs interactions
   ↓
captures screenshot
   ↓
Reviewer receives
   ├── source
   ├── test results
   ├── screenshot
   └── acceptance criteria
   ↓
approve / revise
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I'll give the system the exact same original prompt. That gives me something much more useful than simply making RelayLab better — it gives me an experiment. I can compare:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version 1&lt;/strong&gt; — open-ended reviewer, static source inspection, 6 rounds, failed to converge&lt;/p&gt;

&lt;p&gt;against:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version 2&lt;/strong&gt; — explicit acceptance criteria, browser testing, visual feedback, same models, same prompt, same hardware&lt;/p&gt;

&lt;p&gt;...and see what actually changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;I went into this with extremely limited experience building agent systems and even less experience running language models locally. That turned out to be one of the best parts — instead of starting with assumptions about how agents were supposed to work, I got to watch the failure modes appear in real time.&lt;/p&gt;

&lt;p&gt;The models fought over VRAM. The inference runtime broke. The agents couldn't follow my JSON protocol. The Reviewer learned how to say "no" approximately seventeen different ways. And once all of that finally worked, the two agents successfully collaborated for six rounds... only to produce a notes app that looked like this.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[Screenshot again, because honestly it deserves another appearance.]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But I don't consider the experiment a failure. Quite the opposite. The infrastructure worked. Two local models performed different roles, exchanged feedback, modified a shared artifact, survived multiple iterations, and did it entirely on my own computer without paid inference.&lt;/p&gt;

&lt;p&gt;What failed was the assumption that conversation alone creates coordination. It doesn't. Agents need constraints. They need shared definitions of success. They need tools for observing the real environment. And apparently they occasionally need a Python script standing between them saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I know you wrote 'rejected,' but what you meant was 'changes_requested.'"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm going to keep building RelayLab. Mostly because now I really want to know what happens in round two.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RelayLab:&lt;/strong&gt; &lt;a href="https://github.com/miflow13/Relay" rel="noopener noreferrer"&gt;github.com/miflow13/Relay&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;The broader concept of multi-agent software development isn't new — projects such as ChatDev and MetaGPT have explored teams of specialized language-model agents before. My experiment is much smaller: I'm interested in seeing what happens when that idea is pushed onto consumer hardware using small, entirely local models and a deliberately simple orchestrator.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>showdev</category>
      <category>python</category>
    </item>
  </channel>
</rss>
