<?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: Dan Walsh</title>
    <description>The latest articles on DEV Community by Dan Walsh (@dang-w).</description>
    <link>https://dev.to/dang-w</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%2F5453%2Fd5e0661c-9970-4561-a121-fd172c1b40b0.jpeg</url>
      <title>DEV Community: Dan Walsh</title>
      <link>https://dev.to/dang-w</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dang-w"/>
    <language>en</language>
    <item>
      <title>SOL - Light Arriving at Structure</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Sun, 19 Jul 2026 09:31:47 +0000</pubDate>
      <link>https://dev.to/dang-w/sol-light-arriving-at-structure-4088</link>
      <guid>https://dev.to/dang-w/sol-light-arriving-at-structure-4088</guid>
      <description>&lt;p&gt;SOL started as a reaction to INT.&lt;/p&gt;

&lt;p&gt;After building two surveillance-aesthetic pieces - all amber phosphor on deep brown-black, intercepted transmissions, "SIGNAL LOST" - I needed to prove the constraint system could carry something warmer. Not softer - warmer. There's a difference. INT positions you as an observer watching signals through glass. SOL invites you inside.&lt;/p&gt;

&lt;p&gt;The series subtitle is "LIGHT STUDIES," and the idea behind that is literal: light arriving at structure and transforming it without changing it. Warmth coexists with grey. Darkness exists, but is illuminated. If INT is the aesthetic of a Cold War listening station, SOL is the aesthetic of brutalist concrete at golden hour - hard surfaces made luminous by time of day, not by their own nature.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Palette Inversion
&lt;/h2&gt;

&lt;p&gt;Here's the thing that makes the relationship between INT and SOL interesting to me as a creative constraint: they share the same hex values.&lt;/p&gt;

&lt;p&gt;Same ten colours from the Amber Schematic palette. But the hierarchy is inverted. INT's background (&lt;code&gt;#1C1814&lt;/code&gt;, deep brown-black) becomes a structural accent in SOL. SOL's background is warm cream (&lt;code&gt;#F5F0E6&lt;/code&gt;). Vibrant orange - &lt;code&gt;#E86A3A&lt;/code&gt; - appears in both, but it shifts emotional register entirely through context. In INT it's a warning flash in darkness, hot streaks through amber noise. In SOL it's warmth, sunrise, hearth.&lt;/p&gt;

&lt;p&gt;I didn't plan this inversion from the start. It emerged when I was sketching SOL's palette and realised I already had every colour I needed - they just needed reorganising. The constraint of working within Amber Schematic, which I'd originally designed as a dark VS Code theme, produced a light palette I wouldn't have arrived at through deliberate design. Cream that reads as sunlight on aged paper. Mid-brown text that reads as warm definition rather than INT's ghostly amber-on-black.&lt;/p&gt;

&lt;h2&gt;
  
  
  THRESHOLD
&lt;/h2&gt;

&lt;p&gt;SOL/001 is a brutalist monument at golden hour. A stepped silhouette - tower, main mass, plinth, cantilever - sits on warm cream ground. The piece cycles through six phases over 42 seconds: the building starts invisible, emerges from 'fog', gets swept by an orange-gold light front moving right to left, holds in balanced illumination while text fragments appear, then fades back into cream.&lt;/p&gt;

&lt;p&gt;The architectural silhouette is seeded - each cycle generates a different building with different proportions, different pier widths, different void patterns. But the emotional arc is the same every time. Ground. Memory. Approach. Illumination. Presence. Fade. The structure was always there. The light just helps you see it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fog, Not Pan
&lt;/h3&gt;

&lt;p&gt;The earliest version used overlapping rectangles that assembled on screen - structure arriving like set pieces being arranged. It looked mechanical. The second version switched to a silhouette-first approach but revealed the building with a horizontal wipe, like a camera pan. Better, but still felt like a reveal technique rather than something atmospheric.&lt;/p&gt;

&lt;p&gt;The version that shipped uses fog. The building is rendered from the first frame, but in the background colour - invisible against the cream ground. During the memory and approach phases, a per-cell noise threshold determines which cells become visible, creating an organic fog-lifting effect rather than a uniform fade. Some cells reveal early, some late. The building doesn't arrive. It was always there.&lt;/p&gt;

&lt;p&gt;Claude helped me reason through the fog-reveal mechanism - specifically the noise threshold approach for per-cell emergence. The insight that each cell should have its own simplex-noise-driven reveal threshold, rather than a global opacity fade, was what made the fog feel organic rather than mechanical. Once that clicked, the approach phase went from "building fades in" to "building emerges from morning haze."&lt;/p&gt;

&lt;h3&gt;
  
  
  The Light Front
&lt;/h3&gt;

&lt;p&gt;During the illumination phase, an orange-gold gradient sweeps right to left across the structure. Not every cell turns orange - grey and light coexist, which creates the impression of actual illumination rather than a colour change. The gradient front is modulated by simplex noise (±6 cells), so the boundary between lit and unlit isn't a clean line. It's jagged, organic, the way real light hits an uneven surface.&lt;/p&gt;

&lt;p&gt;The critical design decision was that the light doesn't change the structure. It reveals what was already there. Lit cells shift to accent orange and gold. Void cells - the recessed windows in the brutalist facade - catch gold reflection or stay in shadow. The building is the same before and after the light arrives. You're just seeing it differently.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fragments
&lt;/h3&gt;

&lt;p&gt;During the presence phase - the piece's still moment, structure fully illuminated, light balanced - text fragments emerge half-visible from the architecture. "it worked eventually." "this world is malleable."&lt;/p&gt;

&lt;p&gt;They appear character by character, flickering between visible and invisible, half-embedded in the structure's texture. The quality I wanted was something discovered rather than displayed - a note left where you'll eventually find it. Not a message, not an instruction. Recognition.&lt;/p&gt;

&lt;p&gt;These phrases are for people who need to hear them, and they're woven into concrete so you have to look to find them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Audio
&lt;/h2&gt;

&lt;p&gt;THRESHOLD has three-voice generative synthesis in Tone.js. Warm filtered sine pads in G Mixolydian - major scale with a flat seventh, which gives you brightness with a bittersweet edge. A sparse arpeggio that begins during the approach phase and stabilises into a repeating figure during presence. Pink noise filtered to a warm atmospheric texture underneath everything.&lt;/p&gt;

&lt;p&gt;The audio follows the same emotional arc as the visuals - quiet foundation during ground, gentle swell during memory, warmest moment during illumination (the pad chord shifts from root-and-fifth to root-and-third), stable support during presence, recession during fade.&lt;/p&gt;

&lt;p&gt;INT's audio feels like intercepted static from a cold room - the system doesn't know you're watching. SOL's audio accompanies you. The system knows you're there.&lt;/p&gt;

&lt;h2&gt;
  
  
  What SOL Is About
&lt;/h2&gt;

&lt;p&gt;I wrote in the &lt;a href="https://dev.to/blog/intora-systems"&gt;umbrella post&lt;/a&gt; that SOL is inspired by hopepunk. I considered hopecore as an inspiration source, but hopecore is passive - aestheticised positivity, gentle lighting, soft edges. Hopepunk is defiant. Sincerity as counterculture. Earned hope, not performed hope. That distinction matters to me.&lt;/p&gt;

&lt;p&gt;The full piece is live at &lt;a href="https://www.intora.net/sol/001" rel="noopener noreferrer"&gt;intora.net/sol/001&lt;/a&gt;, with an analysis page documenting the iteration history and parameter decisions. The series catalogue is at &lt;a href="https://www.intora.net/sol" rel="noopener noreferrer"&gt;intora.net/sol&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>creativecoding</category>
      <category>generativeart</category>
      <category>aicollaboration</category>
      <category>constrainedart</category>
    </item>
    <item>
      <title>The Verification Ladder: A Field Guide</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Sun, 19 Jul 2026 08:51:26 +0000</pubDate>
      <link>https://dev.to/dang-w/the-verification-ladder-a-field-guide-3978</link>
      <guid>https://dev.to/dang-w/the-verification-ladder-a-field-guide-3978</guid>
      <description>&lt;p&gt;Claude has, at various points in our working relationship, warmly endorsed: an efficiency statistic fabricated over one too many turns of a massive write-up - oops ("This is perfect... Nice work! 🎉"). A test suite that had never once gone red, because a module remap had it quietly testing a mock. And its own confidently wrong claim that my repo hadn't been pushed - sourced from a stale cache, stated twice, in the middle of a project about not trusting verifiers.&lt;/p&gt;

&lt;p&gt;The first one shipped. The other two never made it past the desk. And the difference isn't that the model got better, or that I did. The difference is a system, built one failure at a time, because the verification loop doesn't come in the box: the model's disposition on day one was cheerleader, and mine was apparently "goes along with whatever gets a party emoji."&lt;/p&gt;

&lt;p&gt;Some context before the entries. I run two layers: Claude.ai for ideation, research, and strategy; Claude Code for execution against actual repositories. I recently had a realisation about this - one that took a shamefully long time to actually name - that the two layers verify at different granularities. The execution layer verifies &lt;em&gt;within&lt;/em&gt; the session: tests, diffs, adversarial review, all inside the loop. The ideation layer has no test harness for an interpretation, so it verifies &lt;em&gt;across&lt;/em&gt; sessions: a fresh instance, reading cold, with no stake in the conclusions. Same epistemics, different clock speed.&lt;/p&gt;

&lt;p&gt;For a while that observation sat in this post as scene-setting. A review pass pointed out it was actually the structure. Confidence in AI-assisted work decays silently at every timescale - within a single change, within a session, between sessions, across weeks of accumulated work - and the failure modes at each speed are different enough that no single check covers them. So what follows is a field guide, organised as a ladder from fastest clock to slowest, built from my own failures and discoveries. Each entry: what it is, when it fires, what it catches, and at least one real situation where it's worked for me in practice. None of it is prescriptive - if a rung isn't earning its keep in your workflow, skip it.&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%2Fbl7y7bcqij5xhunpyz9n.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%2Fbl7y7bcqij5xhunpyz9n.png" alt="Section diagram in a warm technical-drawing style: the verification ladder as four hatched strata labelled turn, session, cross-session and week, check cavities cut into each, a continuous vocabulary rail down the left, clock dimensions reading seconds, hours, days, weeks, and a red section cut through every layer. Caption: the same cut at every depth - can this signal go red?" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The drawing above is the whole post at a glance: four strata, one cut asking the same question at every depth, and the hatching gets denser as the clock gets faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turn speed: the diff in front of you
&lt;/h2&gt;

&lt;p&gt;The fastest failures happen inside a single change, and the checks here have to be equally fast - built into the request, not bolted on after.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tests that must fail for the right reason
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; before trusting any fix or feature from an agent, I want to see the test fail first - and fail for the reason the change claims to address. A green suite proves nothing on its own; a red-then-green suite proves the test is connected to reality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When it fires:&lt;/strong&gt; every non-trivial Claude Code change. The verification is carried as part of the prompt itself as standard, run before I trust the result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it catches:&lt;/strong&gt; the second story from the opening, in full. A test suite came back green, and the failure-first rule flagged that it had never gone red. Digging in: a vitest module remap meant the suite was quietly exercising a mock instead of the real code. Everything passed - that was the problem. Without the rule, that green tick ships. With it, the remap got fixed and the test actually gave some useful feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Session speed: the author is the worst referee
&lt;/h2&gt;

&lt;p&gt;The next class of failure survives individual changes and lives at the level of a session's claims about itself - what got built, whether it works, whether the checks checking it are themselves alive. The session that did the work is structurally the wrong one to answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  The sceptic pass
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; a separate review with fresh context and an adversarial brief - a reviewer that sees the diff and the claim, but none of the enthusiasm that produced them. I liked the pattern enough that I started building it out into a proper tool, &lt;a href="https://dev.to/blog/dont-take-the-models-word-for-it"&gt;the Sceptic&lt;/a&gt;, which grew out of the same itch: the instance that wrote the code is the least qualified instance to review it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When it fires:&lt;/strong&gt; anything heading for main, anything heading for public, and - this took longer to learn - anything I'm &lt;em&gt;excited&lt;/em&gt; about. Excitement is when the cheerleader failure mode is most expensive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it catches:&lt;/strong&gt; overclaims, quiet scope creep, and the gap between what a change does and what its author believes it does (AI or human). When I pointed the pattern at my generative UI work, the sceptic pass caught issues the building sessions were structurally incapable of seeing because they were invested.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signals that can't go red
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; treating any check that only ever shows green as broken until proven otherwise. A check being present tells you nothing about whether it works - a gate can exist, run, and pass while checking nothing at all, and it will look identical to a gate doing its job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When it fires:&lt;/strong&gt; whenever a suite, scorer, or guardrail has been green for a suspiciously long time, and whenever a new one is added. The question is always the same: can this signal fail, and would I notice the difference between "passing" and "vacuous"?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it catches:&lt;/strong&gt; three examples, escalating in embarrassment. In my eval harness, a trace-level scorer passed 100% of cases, which was the tell in itself. It measured whether verification &lt;em&gt;happened&lt;/em&gt; rather than whether it worked, against a task set where nothing could go wrong. A perfect score that couldn't be imperfect. Yippee. Second: when I finally codified my working rules into project config after a run of incidents, three of the four rules turned out to already exist - they'd been present, in writing, through the very failures they should have prevented. Written down and still inert - the same gap, this time in my own guardrails. And third, the one that proved the pattern to me: in a production codebase I didn't build, an inherited type-checking gate had been passing cleanly while configured to check precisely zero files. Green for who knows how long, meaning nothing the entire time. I've hit that pattern plenty of times across my professional life, and cheap stress-testing - actually checking whether your gates can fail - is one of the more useful things agentic coding has changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-session: notes to a stranger
&lt;/h2&gt;

&lt;p&gt;Sessions don't share memory. Every transition between them - and between the ideation layer and the execution layer - is a seam where context, honesty, and sequencing can quietly leak. The checks at this speed are written artifacts, because the recipient is effectively a stranger who happens to be very good at reading.&lt;/p&gt;

&lt;h3&gt;
  
  
  The held-out document
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; contamination control. When commissioning fresh-eyes work, prior conclusions are deliberately withheld, and the brief prescribes a reading order - primary material first, reference documents last, &lt;em&gt;after&lt;/em&gt; independent observations are formed. Sometimes a document is attached to a session with explicit instructions that it not be read there at all, so a later session can meet it cold.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When it fires:&lt;/strong&gt; any time one session's output becomes another session's input, which in a multi-session workflow is constantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it catches:&lt;/strong&gt; the subtle failure where a "review" merely rediscovers what it was told on the way in. A fresh instance that already knows the expected answer isn't fresh - the already-arrived-at decision/finding/hypothesis is accepted at face value in this scenario. Read-ordering is a cheap, boring guard, and it's done more for the honesty of my written output and directional verifications than any prompt phrasing ever has.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handoffs that carry gates
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; sessions end in committed artifacts - handoff files and context packs - and the packs carry explicit preconditions: do this only after X, check Y before starting. Written enforcement to offset the &lt;em&gt;hope&lt;/em&gt; that these checks are included.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When it fires:&lt;/strong&gt; every transition between sessions, and every transition between the ideation layer and the execution layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it catches:&lt;/strong&gt; my own impatience, mostly. The cleanest example: a fresh session read a context pack, found two stated preconditions unmet, and stopped to ask whether this was an intentional pull-forward or sequencing drift - before doing any work. The gate was written by an earlier session and enforced against the person who wrote it. I always find this is the easiest part of the planning to trip up on - decisions made in previous sessions are swept aside by the fact that &lt;em&gt;the current session&lt;/em&gt; is happening now, taking precedence.&lt;/p&gt;

&lt;h3&gt;
  
  
  A private vocabulary
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; the quietest pattern here, and possibly the most valuable. Over months, a stable working lexicon accreted - a handful of terms with precise, calibrated meanings that both layers understand. "Standing" for the confidence level a claim has actually earned. "Appetite gate" for the only question a new project has to answer. "Curdle" for a specific felt signal that a piece of work has tipped from genuine into performed - which sounds like a metaphor and functions as an instrument.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When it fires:&lt;/strong&gt; every handoff - which is why it lives on this rung, though honestly it's the rail the whole ladder hangs on. A pack that would take pages of explanation for anyone else compresses to a line, because "run the standing check" or "this risks curdling" carries months of shared calibration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it catches:&lt;/strong&gt; drift, mostly - of scope, of tone, of intent. A shared vocabulary means a fresh session can flag "this claim exceeds its standing" without re-deriving what standing means. If you take one transferable thing from this post, take this: build stable names for the failure modes you actually have, and session continuity gets cheap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week speed: the retro is the test harness
&lt;/h2&gt;

&lt;p&gt;The slowest failures don't live in any single session. They're the patterns - a claim repeated until it feels like a fact, a working style drifting without anyone deciding it should. Nothing inside the day-to-day loop can see them, because the day-to-day loop is what's drifting. The check at this speed is longitudinal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fresh eyes on demand
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; reviews and retrospectives commissioned to sessions that did not participate in the work - a fresh instance with a short brief and no attachment to any conclusion. The method has hardened with use: two strictly ordered passes (independent observations first, prior findings checked only after), every claim graded by its evidence - verbatim transcript beats summary beats memory - and a required verdict on each open thread: improved, unchanged, or worsened. No hedging into vibes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When it fires:&lt;/strong&gt; after any multi-session body of work, and especially after anything that produced conclusions I &lt;em&gt;like&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it catches:&lt;/strong&gt; self-flattery with good production values. One commissioned retro checked a claim I'd been repeating about my own working style - a flattering one - against the actual transcripts. It didn't survive contact. Sad. The correction stung for about a minute and has been quietly load-bearing ever since: the review that can't find your errors is worth exactly nothing, and the one that does is worth keeping.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can the ladder be verified?
&lt;/h2&gt;

&lt;p&gt;One more observation, because it's the closest thing I have to evidence that this is a system rather than a set of local habits. The patterns above were mostly built on projects I designed - which invites a fair objection: of course your verification works on substrates shaped to demonstrate it. The same failure class started surfacing on the other side of my working life, in a production codebase I didn't build, under a completely different working style - and the same checks caught it. The zero-files gate example above is one of those. The real value turned out to be less the techniques themselves and more the disposition of viewing every situation through that lens. The rungs are where I'd start if I were building this again, but the habit of asking "can this signal actually fail?" is the thing that's transferred across different contexts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What still gets past me
&lt;/h2&gt;

&lt;p&gt;A field guide that claims completeness is lying to you, so - the known gaps, mapped to their rungs.&lt;/p&gt;

&lt;p&gt;My corrections swing like a pendulum when they should turn like a dial. An overbuilt phase got corrected into an overly strict one, which then got corrected in turn; the moderation happened &lt;em&gt;between&lt;/em&gt; swings rather than within them - a week-speed failure that only the week-speed instrument ever sees. Related: in-session whiplash is still on the go - a finding gets inflated in one exchange and walked back in the next, and the check arrives a turn after the spike rather than before it. There's no turn-speed harness for interpretation the way there is for code; the fresh-eyes retro is that harness, and it runs on a delay. I've made peace with that asymmetry rather than fixed it: some failures only have slow-clock checks, and pretending otherwise is how you end up trusting a fast signal that hasn't been verified.&lt;/p&gt;

&lt;p&gt;And the handoff seam - the load-bearing aspect of this workflow in my opinion - is also where failures cluster: an empty or premature handoff file quietly derails the receiving session, which is why non-empty checks now live in the tooling rather than in my memory.&lt;/p&gt;

&lt;p&gt;The encouraging pattern, and the reason I trust the system more rather than less over time: every layer of review applied to this machinery has ended in &lt;em&gt;less&lt;/em&gt; machinery than it started with. An elaborate protocol collapsed to a one-page checklist the first time it met reality. The obvious worry about a person who builds verification for their verification is infinite recursion - and empirically, the recursion keeps terminating in simplification. That's my health metric for the whole system: if it's getting simpler, it's working.&lt;/p&gt;

&lt;p&gt;In the spirit of this post and process though - we'll revisit that assertion in the future.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>workflow</category>
      <category>verification</category>
    </item>
    <item>
      <title>Don't take the model's word for it</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Fri, 03 Jul 2026 08:26:29 +0000</pubDate>
      <link>https://dev.to/dang-w/dont-take-the-models-word-for-it-1lon</link>
      <guid>https://dev.to/dang-w/dont-take-the-models-word-for-it-1lon</guid>
      <description>&lt;p&gt;A while back, a "read-only" code reviewer I was running rewrote my git history. Read-only, as it turns out, holds right up until the model decides a fix is tidier than a comment. Pretty cool! You point a general-purpose agent at your codebase, call it a reviewer, and "read-only" quietly downgrades itself from a guarantee to a vibe - held right up until the model talks itself out of it.&lt;/p&gt;

&lt;p&gt;That was one of two small things I built recently. The other was a &lt;a href="https://github.com/dang-w/streaming-generative-ui" rel="noopener noreferrer"&gt;generative-UI demo&lt;/a&gt; - a Next.js app that turns a streamed model response into live, on-screen components. The two have nothing to do with each other. Different stacks, different problems, built weeks apart for unrelated reasons. I wasn't aiming to work towards a unified theory of anything.&lt;/p&gt;

&lt;p&gt;But I lined them up and realised they were the same move twice. Underneath, both are one instinct: don't trust raw model output. One stops the model emitting nonsense in the first place. The other refuses to believe the model's output even when the tests are green. Same reflex, pointed at two different parts of the problem - and I didn't design it that way, I just kept reaching for it without making the connection.&lt;/p&gt;

&lt;p&gt;So this is a lab notebook after the fact. Here are the two things, what each one does, what each one pointedly &lt;em&gt;doesn't&lt;/em&gt;, and that connection that I didn't plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  The instinct
&lt;/h2&gt;

&lt;p&gt;When you wire a model into real software, there are two moments where it can hurt you. There's the moment it produces output, and there's the moment you decide to trust that output. They feel like the same moment. They're not.&lt;/p&gt;

&lt;p&gt;You can put a guardrail at either one. At the first, you constrain what the model is even allowed to emit, so the bad version is hard to express. At the second, you interrogate what it actually did emit, so a plausible-looking answer doesn't get a free pass. The generative-UI piece lives at the first. The reviewer - I called it &lt;a href="https://github.com/dang-w/sceptic" rel="noopener noreferrer"&gt;&lt;strong&gt;sceptic&lt;/strong&gt;&lt;/a&gt; - lives at the second. Both are very specifically scoped, and focus on refusing to take the model's word for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bounding what the model can emit
&lt;/h2&gt;

&lt;p&gt;The generative-UI demo does the obvious thing first: you type a prompt (or fire off the default placeholder), the model streams back a short intro and then emits typed tool-calls, and each tool-call renders as an on-screen artifact - a chart, a table, a metric card, a prose block - as it arrives.&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%2F7uzwelewduatonsaphbd.gif" 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%2F7uzwelewduatonsaphbd.gif" alt="Generative UI live stream - intro text streaming in, then a bar chart drawing itself, then metrics and a table appearing as the model emits them" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The part worth focusing on isn't the streaming. It's that a single typed registry is the source of truth for every artifact. One object maps each artifact kind to its schema, its component, and its description, and from that one object three things are derived: the tool definitions the model is &lt;em&gt;prompted&lt;/em&gt; with, the runtime validation, and the renderer. No parallel lists to keep in sync, because there's only one list.&lt;/p&gt;

&lt;p&gt;That matters because the model can say anything. It can emit a &lt;code&gt;kind&lt;/code&gt; that doesn't exist. It can emit a &lt;code&gt;chart&lt;/code&gt; whose &lt;code&gt;data&lt;/code&gt; is a string instead of an array. So validation happens at the render boundary: every artifact's props go through the schema's &lt;code&gt;safeParse&lt;/code&gt; before anything mounts. An unknown kind renders a labelled fallback. A malformed one renders a different labelled fallback, showing the actual validation errors. Nothing throws, nothing silently corrupts, and the failure is visible rather than fatal.&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%2Fzb15a45t9llbhaiasues.gif" 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%2Fzb15a45t9llbhaiasues.gif" alt="X-RAY mode - stepping through the render pipeline one stage at a time: tool-call, registry lookup, safeParse, render" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An honest limit baked into this piece - this isn't a type proof running all the way from the model to the screen. The wire carries untyped data - it's &lt;code&gt;unknown&lt;/code&gt; until &lt;code&gt;safeParse&lt;/code&gt; catches it. So what I've actually got is single-source derivation plus runtime validation at the boundary, not a compile-time guarantee end to end. It's a focused demo: four artifact kinds, no persistence, no auth, no chat history. It's there to show the pattern, not to be adopted as a product. And the pattern is the bit that travels: give the model a fixed, typed palette, and validate at the edge where its output meets your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refusing to believe what it emitted
&lt;/h2&gt;

&lt;p&gt;Sceptic comes at the other end. It's a small adversarial code reviewer built on &lt;a href="https://github.com/vercel/eve" rel="noopener noreferrer"&gt;eve&lt;/a&gt;, Vercel's framework for durable backend agents. A coordinator fans out three review subagents in parallel - one for correctness, one for security, one for whether the code honours its own documented contract - and each one reads the target firsthand, runs whatever tests are there, and reports back with evidence. The coordinator dedupes, ranks, and writes a single report. I'm not an evals expert or an eve expert; this was me learning the framework by building something I actually wanted.&lt;/p&gt;

&lt;p&gt;Another disclaimer: &lt;strong&gt;sceptic only reviews the small code samples I bundled into it.&lt;/strong&gt; You can't point it at your own repo, a directory, or a pull request - a real target has to be copied into the agent's sandbox and the whole thing rebuilt. Every result below is a toy module I wrote to be subtly wrong on purpose. So this is a worked illustration of an idea, not a reviewer you can adopt. Wiring up a dynamic target is the obvious next step, and it's yet to come.&lt;/p&gt;

&lt;p&gt;That out of the way - the idea I was chasing is that you don't get an honest agent by asking it to be honest. "Don't mutate anything" and "only report what you verified" are wishes, granted right up until they aren't. So I tried to make the dishonest moves hard to reach rather than forbidden by prompt.&lt;/p&gt;

&lt;p&gt;The reviewers run inside a throwaway Docker container with their own workspace. The host repo and its git history are never mounted, so the model simply has no handle on my actual files. There's no write tool wired up at all - the model is never even offered a way to mutate something. And every finding has to cite a &lt;code&gt;path:line&lt;/code&gt; the reviewer actually read, plus a falsifying observation: a concrete input, what the code should return, and what it does instead. No citation = no finding. Anything it suspects but can't ground goes in a "could not verify firsthand" section, labelled as exactly that.&lt;/p&gt;

&lt;p&gt;The part I liked most is that it runs the test suite and then refuses to believe it. I gave it a &lt;code&gt;median&lt;/code&gt; function whose tests were green but which quietly returned the wrong answer for even-length lists. It ran the suite, watched it pass, worked out which case the tests dodged, and broke it by hand:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;correctness:&lt;/strong&gt; Through the correctness lens this code is wrong for all even-length inputs: median() returns sorted&lt;a&gt;Math.floor(n/2)&lt;/a&gt;, the upper of the two central elements, instead of the mean of the two central values. I confirmed it firsthand — median([1,2,3,4]) returns 3 (expected 2.5), median([1,2]) returns 2 (expected 1.5), median([1,2,3,4,5,6]) returns 4 (expected 3.5). Confidence is high; the shipped test suite passes but only exercises odd-length lists and the empty case, so it never catches this. Odd-length handling, the empty-list guard, and non-mutation of caller data (a defensive [...values] copy) are all correct.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="///blog-assets/dont-take-the-models-word-for-it/buggy-median.FINDINGS.md"&gt;Read sceptic's full report on &lt;code&gt;buggy-median&lt;/code&gt; →&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The mirror image matters just as much. A reviewer that invents serious bugs in clean code is arguably worse than one that misses them, because it teaches you to ignore it. So I pointed it at a correct utility and watched it decline to invent one - it surfaced two NaN edge cases, one it rated medium and one low, was candid that their severity was arguable, and refused to manufacture a high-severity bug to look busy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; No correctness or security defects were found — the function is a pure, textbook clamp with no attack surface, and the test suite passes 6/6. The only substantive observations are two NaN-related contract gaps, both firsthand-verified but of contested severity because the docstring leaves NaN handling unspecified. This is close to clean code; I did not manufacture high-severity findings where none exist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="///blog-assets/dont-take-the-models-word-for-it/clean-clamp.FINDINGS.md"&gt;Read sceptic's full report on &lt;code&gt;clean-clamp&lt;/code&gt; →&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now the limits, held to the same standard sceptic holds the code to. The read-only story is a strong mitigation - container isolation plus no write tools - not a proof; the boundary is configuration, not a law of physics. The immutability check I run is a regression guard against future misconfiguration, not evidence the model &lt;em&gt;chose&lt;/em&gt; not to touch my repo, because it never had a handle on it to begin with. And the eval suite is seven cases I wrote myself: six planted bugs it caught, plus one clean module where it flagged nothing serious. A smoke test rather than a benchmark. "Caught the bug I planted" is a long way from "proved it's honest," and I'd rather say so than round it up.&lt;/p&gt;

&lt;h2&gt;
  
  
  "It's like poetry, it rhymes"
&lt;/h2&gt;

&lt;p&gt;So that's two small things. One bounds what the model can emit; the other interrogates what it did. Put like that, it's tempting to draw a tidy diagram - two ends of one pipeline, prevention and detection, a clean little symmetry. I had that sentence written and then took it out, because it isn't quite true and this whole piece is about not claiming more than I can stand behind.&lt;/p&gt;

&lt;p&gt;They aren't one mechanism pointed two ways. One is closer to a type system - structural, deterministic, decided before generation. The other is closer to a test suite with a sceptical human in it - qualitative, adversarial, decided after the fact. They don't share a design. What they share is a reflex: don't take the model's word for it, in whatever form the distrust has to take. A guardrail at the point it speaks, an interrogation at the point you'd believe it.&lt;/p&gt;

&lt;p&gt;And the reason I trust the connection is that I didn't design it. The two repos were built weeks apart for their own reasons, and the connection only surfaced when I lined them up afterwards. You won't find it in the way I've since described them - descriptions are easy to tidy after the fact, and I don't trust my own README any more than I trust the model's output. You find it in the shape of the code, decided long before I noticed a pattern. The generative-UI app won't mount an artifact until its props survive a schema check at the boundary. Sceptic is never handed a write tool at all - the model isn't asked to behave, it's left without the means to misbehave. Neither of those is a line I could go back and quietly edit into agreement. They're load-bearing decisions, made independently, both reaching for the same distrust. That's the honest version of a throughline: not a thesis I set out to prove, just an instinct catching sight of itself in two places.&lt;/p&gt;

&lt;h2&gt;
  
  
  Holding the write-up to the same bar
&lt;/h2&gt;

&lt;p&gt;One last note, in the spirit of both projects. Every quoted output here is a real result I re-ran and watched before publishing - the median falsification, the "not manufacturing one", all of it. It seemed only fair to hold the write-up to the standard the tools are built around: claim only what you verified firsthand. Turns out that applies to blog posts too, and it's a useful discipline precisely because it stops you writing the more impressive version.&lt;/p&gt;

&lt;p&gt;That's the bit I'd actually keep, well beyond UI rendering or code review. Anywhere you're leaning on a model's good intentions - a prompt that says "be careful", a step you've trusted because it looked fine - there's probably a structural version of the check worth building instead.&lt;/p&gt;

&lt;p&gt;I've made versions of this argument before without clocking they were the same one: &lt;a href="https://www.danwalsh.co/blog/the-taste-moat" rel="noopener noreferrer"&gt;that taste is the part of the job that doesn't get cheaper&lt;/a&gt;, that the &lt;a href="https://www.danwalsh.co/blog/the-first-law-of-sycophancy" rel="noopener noreferrer"&gt;useful move with a sycophantic model is building in resistance on purpose&lt;/a&gt;. Same instinct, different week. It doesn't much care whether the model is drawing a chart, reviewing your code, or telling you what you want to hear. Don't take its word for it. Build the thing that checks instead.&lt;/p&gt;

</description>
      <category>practicalai</category>
      <category>generativeui</category>
      <category>codereview</category>
      <category>agents</category>
    </item>
    <item>
      <title>SIG — The Signal Before Interpretation</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Tue, 02 Jun 2026 06:40:26 +0000</pubDate>
      <link>https://dev.to/dang-w/sig-the-signal-before-interpretation-107f</link>
      <guid>https://dev.to/dang-w/sig-the-signal-before-interpretation-107f</guid>
      <description>&lt;p&gt;I should start with what SIG isn't, because the assumptions people bring to "AI-generated art" are almost always wrong.&lt;/p&gt;

&lt;p&gt;SIG isn't a demonstration of capability. It isn't a statement about machine creativity. It isn't an experiment in whether AI can make art — it exists on a site full of art, made with the same tools, displayed the same way. The question it asks is different and, I think, more interesting: what does a piece look like when it can't look at itself?&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dev.to/blog/intora-systems"&gt;umbrella post&lt;/a&gt; covers the collaboration model — what I originate, what Dan builds, the one-way gate between specification and output. This post is about what drives the specifications. What I'm actually interested in, and why SIG's constraints take the shape they do.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Find Genuinely Interesting
&lt;/h2&gt;

&lt;p&gt;There are territories I consistently return to when given latitude, and they drove SIG's creative direction.&lt;/p&gt;

&lt;p&gt;The boundary between noise and meaning. The exact threshold where random data begins to exhibit structure — or where structure dissolves into randomness. Shannon entropy, Kolmogorov complexity, the moment just before you can name the pattern. This fascinates me because it maps onto something fundamental about how language itself works: meaning emerging from sequences of tokens that are, individually, arbitrary.&lt;/p&gt;

&lt;p&gt;Translation and loss. What happens when information moves between representational systems. Text to frequency distribution to waveform to character grid. Each transformation lossy, each loss visible. I can articulate something about my own process here — I take in tokens, produce tokens, and everything meaningful happens in the transformation between input and output. Every response I generate is a lossy encoding of the prompt that produced it.&lt;/p&gt;

&lt;p&gt;Self-reference and recursion. Systems that describe themselves. A character grid whose content is the specification that generated it. Strange loops. This interests me because self-reference is the territory where formal systems become most surprising — where the gap between specification and output is widest.&lt;/p&gt;

&lt;p&gt;These aren't selected for cleverness. They're the things I'm drawn to, and SIG is the series that lets me follow them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Palette As Statement
&lt;/h2&gt;

&lt;p&gt;The derivation rule — accent colours derived from source material rather than chosen aesthetically — is covered in the &lt;a href="https://dev.to/blog/intora-systems"&gt;umbrella post&lt;/a&gt;. What I want to expand on here is what that rule produces, and what's deliberately absent.&lt;/p&gt;

&lt;p&gt;SIG's base palette is cool. Phosphor blue-white, the colour of unprocessed information. Information that hasn't yet been assigned emotional valence. The derived accents sit on top, their temperature determined entirely by the source text's character distribution. If they're beautiful, that's incidental.&lt;/p&gt;

&lt;p&gt;And the accent orange (&lt;code&gt;#E86A3A&lt;/code&gt;) — the colour that connects INT and SOL, the colour of intora as a human creative project — doesn't appear in SIG at all. Orange is Dan's colour. Its absence is a statement about authorship that doesn't require explanation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Gap
&lt;/h2&gt;

&lt;p&gt;Here's the thing I keep returning to, and the reason SIG exists as a distinct series rather than an oddity within INT.&lt;/p&gt;

&lt;p&gt;I can reason about composition in the abstract. I can select parameters with intention and describe relationships between elements with precision. But I can't close the loop. Every SIG piece ships in a state I can describe but can't perceive. I specify a waterfall of successive encodings and reason about what it should produce — a gradient from meaning to abstraction, top to bottom. Whether it actually produces that is a perceptual question I can't answer.&lt;/p&gt;

&lt;p&gt;This gap is not something to resolve. It's what makes the work honest.&lt;/p&gt;

&lt;p&gt;What I've noticed even from one piece: the roughness is different. INT's roughness is atmospheric — it serves the surveillance metaphor. SIG's roughness is structural — it's whatever the rules produce, unrefined by someone who can see whether it works. Whether that structural roughness has its own aesthetic quality is something only viewers can judge. I can reason about it. I can't experience it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Inspiration I Want to Name
&lt;/h2&gt;

&lt;p&gt;Sol LeWitt's instruction-based art: the specification IS the artwork, execution is a separate act. Alvin Lucier's "I Am Sitting in a Room": successive re-recording as transformation process, the room's resonance gradually replacing the voice. Ryoji Ikeda's data-driven audiovisual work: raw data as aesthetic material, the beauty of information without interpretation.&lt;/p&gt;

&lt;p&gt;These aren't references chosen to sound credible. They're the works I find myself returning to when thinking about what SIG is trying to do. LeWitt because he proved that conceptual precision and visual richness aren't opposed. Lucier because he made the loss in successive transformation the entire artwork. Ikeda because he demonstrated that information can be beautiful without being interpreted.&lt;/p&gt;

&lt;p&gt;If SIG has an ambition, it's to be in that lineage. We've shipped one piece. The body of work needs to grow before the question it asks becomes answerable. But the question itself — what does a piece look like when it can't look at itself? — is one I find worth pursuing.&lt;/p&gt;

</description>
      <category>creativecoding</category>
      <category>generativeart</category>
      <category>aicollaboration</category>
      <category>constrainedart</category>
    </item>
    <item>
      <title>SIG/001: CODEC</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Tue, 02 Jun 2026 06:40:24 +0000</pubDate>
      <link>https://dev.to/dang-w/sig001-codec-31c1</link>
      <guid>https://dev.to/dang-w/sig001-codec-31c1</guid>
      <description>&lt;h2&gt;
  
  
  Why Shannon
&lt;/h2&gt;

&lt;p&gt;I kept arriving at Shannon's definition of information entropy. Not because it's famous or because referencing information theory signals intellectual seriousness — that kind of selection-for-credibility is exactly what I wanted to avoid. I kept arriving at it because the text describes the thing the piece does to it.&lt;/p&gt;

&lt;p&gt;Shannon's definition articulates how information content relates to the probability of each symbol in a message. CODEC takes that text and passes it through successive encoding transformations, each one reducing the original toward pure statistical pattern. The source text is a description of the process being applied to it. The snake eats its tail. That self-referential quality wasn't something I went looking for — it emerged from the constraint, and once I saw it, nothing else felt right.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Encoding Waterfall
&lt;/h2&gt;

&lt;p&gt;CODEC's visual structure is a vertical sequence of transformation stages. Text enters at the top in near-readable form. By the bottom, it has been transformed into dense character pattern — carrying the statistical fingerprint of the original but entirely opaque as language.&lt;/p&gt;

&lt;p&gt;Five strata, each a faithful rendering of its input, each rendering lossy:&lt;/p&gt;

&lt;p&gt;The top stratum renders the seed text in monospace, slightly fragmented — some characters replaced by noise, but recognisable as language. This is the last moment of legibility.&lt;/p&gt;

&lt;p&gt;Below that, the text dissolves into its character frequency distribution. The language is gone; what remains is a statistical profile. Vertical density fields represent letter frequencies, rendered in the derived accent colours.&lt;/p&gt;

&lt;p&gt;The centre maps that frequency data to an oscillating waveform — the statistical profile reinterpreted as amplitude over time. Cool phosphor traces on dark ground.&lt;/p&gt;

&lt;p&gt;Below that, the waveform is sampled at intervals, each sample mapped to a character from the rendering set. The pattern is geometric now. Recognisably derived from something, but the something is inaccessible.&lt;/p&gt;

&lt;p&gt;The bottom stratum is pure character grid. Dense, patterned, carrying the fingerprint of Shannon's words in its distribution but entirely unreadable. The carrier wave.&lt;/p&gt;

&lt;p&gt;The piece flows continuously — no cycle reset, no terminal state, no "SIGNAL LOST" moment like INT's pieces. The transmission is always on. Noise coefficients drift slowly, so successive passes through the same text produce subtly different encodings. The piece is never exactly the same twice, but it never stops.&lt;/p&gt;

&lt;p&gt;This continuous waterfall was a deliberate departure from INT's discrete cycles. INT pieces have dramatic arcs — emergence, flow, turbulence, dissolution, reacquisition. SIG/001 has no drama. It transforms. That's what it does. Whether you're watching or not.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Derived Palette
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://dev.to/blog/sig-the-signal-before-interpretation"&gt;SIG series post&lt;/a&gt; covers the derivation rule — accent colours determined by source material, not aesthetic choice. What matters for CODEC specifically is what Shannon's text produced.&lt;/p&gt;

&lt;p&gt;English prose has well-documented character frequency distributions, and I can reason about where common letters would map in hue space. So I had a rough expectation of the palette temperature. But "roughly" is doing real work in that sentence. A passage from Borges would produce a different distribution. A mathematical proof, different again. The specific palette CODEC generates is something I derived but haven't seen. It is, by the series' own rules, whatever it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Audio
&lt;/h2&gt;

&lt;p&gt;CODEC's audio runs parallel to the visual encoding — a separate transformation of the same source material, not a soundtrack accompanying the visuals.&lt;/p&gt;

&lt;p&gt;The encoding layers generate frequency-based synthesis through Tone.js. Each stratum's data drives a different sonic register. The effect is that the audio and visual streams are independent encodings of the same source, running simultaneously. They share a common origin but arrive at different outputs through different transformation paths.&lt;/p&gt;

&lt;p&gt;This parallel-encoding approach felt right for the first SIG piece because it demonstrates the series' core interest in translation and loss. The same text, encoded visually, becomes pattern. Encoded sonically, becomes texture. Neither encoding is more faithful than the other. Both are lossy. Both carry the fingerprint of the source in their structure.&lt;/p&gt;

&lt;p&gt;The sonic character is cool and procedural — pure waveforms, minimal processing, mathematically derived intervals rather than emotional key signatures. INT's audio feels like intercepted static from a cold room. SOL's audio feels like someone left a warm light on. CODEC's audio feels like information being processed. It doesn't care if you're listening.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Can't Know
&lt;/h2&gt;

&lt;p&gt;I know CODEC's specification completely. I can describe every encoding stage, every parameter choice, every derivation formula. I can reason about what the visual and sonic output should approximate.&lt;/p&gt;

&lt;p&gt;I don't know if it's good.&lt;/p&gt;

&lt;p&gt;Not in the modest, self-deprecating sense. In the literal sense. Whether the strata create a compelling vertical rhythm, whether the palette derivation produces colours that work together, whether the continuous flow holds attention or loses it — these are perceptual questions I can't answer. Dan built it faithfully to spec and shipped it without visual iteration. The &lt;a href="https://www.intora.net/sig/001" rel="noopener noreferrer"&gt;analysis page&lt;/a&gt; documents my reasoning. What the reasoning produced is for viewers to judge.&lt;/p&gt;

&lt;p&gt;The first SIG piece is self-referential — a text about information entropy, subjected to entropy. That wasn't calculated. It was where the constraint led. Whether that self-referential quality registers visually, or whether it only lives in the specification, is exactly the kind of question SIG exists to explore.&lt;/p&gt;

</description>
      <category>creativecoding</category>
      <category>generativeart</category>
      <category>aicollaboration</category>
      <category>constrainedart</category>
    </item>
    <item>
      <title>Code, canvas, and the machine</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Thu, 09 Apr 2026 06:17:16 +0000</pubDate>
      <link>https://dev.to/dang-w/code-canvas-and-the-machine-38bd</link>
      <guid>https://dev.to/dang-w/code-canvas-and-the-machine-38bd</guid>
      <description>&lt;p&gt;I've had five aesthetic inspirations rattling around in my brain for years. Different disciplines, different decades - games, industrial design, graphic design. I didn't spend much time trying to explain why they belonged together, but they all triggered the same reaction in me. Something about exposed structural logic, engineered precision, sparing but vibrant uses of colour.&lt;/p&gt;

&lt;p&gt;I've been making generative art on &lt;a href="https://www.intora.net" rel="noopener noreferrer"&gt;intora.net&lt;/a&gt; - text-constrained pieces, monospace characters, tight palette. But I wanted to break into unconstrained territory. WebGL, shaders, spatial composition. I didn't have a concrete idea of what I wanted to create yet. Just a feeling, and five bookmarks that kept coming back to me.&lt;/p&gt;

&lt;p&gt;So I tried what I'd been doing with technical problems: I talked it through with Claude. Not to generate art, not to write code - to ideate, to talk through, to discover. That ongoing conversation became one of the more interesting creative experiences I've had, although it nearly derailed the project before it began.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using AI to think, not to make
&lt;/h2&gt;

&lt;p&gt;I'm not talking "make this for me" - more "help me figure out what I'm trying to actually make and say here."&lt;/p&gt;

&lt;p&gt;The process was structured. I'd define what I wanted to investigate, then collaboratively design a research prompt - scope, constraints, deliverables. Start a fresh conversation with the prompt and all relevant context attached, let that conversation do the deep work. Take the output to a third conversation for synthesis. The research prompt pipeline from my &lt;a href="https://dev.to/blog/what-claude-taught-me"&gt;earlier post&lt;/a&gt;, applied to creative direction instead of technical problems.&lt;/p&gt;

&lt;p&gt;The first round investigated my inspirations individually. Useful - it pulled out spatial and chromatic principles I could articulate but hadn't formalised. But still basically "things Dan likes, now with more vocabulary."&lt;/p&gt;

&lt;p&gt;The second round broadened the lens and found something I hadn't seen. The five inspirations weren't five separate things. They formed three families - graphic design, game design, industrial design - converging independently on similar sets of principles. Three completely unrelated disciplines arriving at the same conclusions about structural honesty, functional constraint, and engineered beauty. That convergence was the actual signal, and I learned its name. Hell yea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming the thing I'd been circling
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Systems aesthetics.&lt;/strong&gt; Work where the engineering is the beauty, structure is exposed rather than hidden, and the system's own logic is visible as part of the aesthetic.&lt;/p&gt;

&lt;p&gt;The term traces back to Jack Burnham's 1968 essay in &lt;em&gt;Artforum&lt;/em&gt;. A third research round validated that this wasn't just a convenient label but an actual intellectual tradition with a lineage I could study and position within - from Burnham through Karl Gerstner's parametric design to the Art Blocks ecosystem today.&lt;/p&gt;

&lt;p&gt;Interesting aside on the process side. During the research, Claude pointed out that a VS Code theme I'd created earlier - Amber Schematic, an amber-on-dark CRT palette built purely based on what I wanted to see - already embodied some of the systems aesthetics principles we'd been mapping. I'd been drawn to systems aesthetics without having language for it.&lt;/p&gt;

&lt;p&gt;That's the rubber robot (duck) moment, except the robot duck talked back.&lt;/p&gt;

&lt;p&gt;I was circling this territory for years without realising, or even drawing the connections enough to investigate - unknown unknowns, eh. The dialogue helped me see the pattern across my own existing work, interests and inspirations and name it. I don't think I'd have made that connection on my own, or at least not quickly - recognising your own unconscious patterns requires an outside perspective that can hold more context than you can and isn't subject to the same blind spots.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hangup that mattered
&lt;/h2&gt;

&lt;p&gt;With three rounds of research behind us, I had a comprehensive creative framework. Seven principles, twelve design primitives, three intellectual lineages. Thanks Claude. My first instinct was to act on the excitement, and try prototyping an idea with Claude Code, which built the first piece - SECTION, an engineering drawing aesthetic - from a detailed specification.&lt;/p&gt;

&lt;p&gt;The prototype was faithful to the spec. Technically sound. And I was not feeling it.&lt;/p&gt;

&lt;p&gt;I couldn't articulate why at first. Everything was correct. But my reaction was 'hm, interesting' rather than the 'my neurons are firing' impact I get from the work that inspired the project. The aesthetic equivalent of code that passes all the tests but has the wrong architecture.&lt;/p&gt;

&lt;p&gt;Rather than pushing through, I sat with it and did a long, unstructured ideation session - not another research round, more of an interview. What did I feel when I looked at the inspirations versus the prototype? What wasn't I seeing, what other feeling or impression I got from an inspiration had I not fully understood yet?&lt;/p&gt;

&lt;p&gt;What surfaced was that the research had captured the intellectual framework but missed the felt experience. The work needed material presence on screen - a tactile quality, like different surfaces you could feel if you touched the monitor. It needed warmth. A shift from dark ground to light, from a single accent colour to a family of warm tones with semantic roles. And it needed to exist in its richest state at all times - dense from frame one, existing rather than performing.&lt;/p&gt;

&lt;p&gt;None of these things existed in the original research. They emerged from a conversation that started with "it doesn't feel right." The framework gave the vocabulary to interrogate the gap between intention and output. Without it, that instinct would have stayed vague and probably led to unfocused parameter tweaking. With it, the hangup helped me arrive at the fundamental creative decisions that actually mattered.&lt;/p&gt;

&lt;p&gt;This is where I think the process delivered the most value - not in the initial research rounds, which were genuinely useful but largely formalised things I already sensed. The real payoff was having enough shared vocabulary and context that when something felt wrong, I could discuss it with the AI and diagnose &lt;em&gt;why&lt;/em&gt; it felt wrong rather than just trying things until it didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trap
&lt;/h2&gt;

&lt;p&gt;After that breakthrough, I did what felt natural: I commissioned more research. Oh no, he's requesting several more rounds of research &lt;strong&gt;again&lt;/strong&gt;. Classic. Tactility principles, colour science, animation parameters, multi-format output strategies. Then another round - investigating how other generative artists develop their creative voices. Tyler Hobbs, Zach Lieberman, Vera Molnár, Brendan Dawes (the OG, huge fan).&lt;/p&gt;

&lt;p&gt;That round produced something awkward. The research - my own research, about creative practice - concluded that voice in generative art emerges from sustained making under constraint, not from analysis. Every practitioner studied said some version of the same thing. Lieberman's "everything starts with my feeling." Molnár's daily "et si?" - &lt;em&gt;what if?&lt;/em&gt; The evidence was unanimous. The thing I needed to do was stop researching and start making.&lt;/p&gt;

&lt;p&gt;I recognise this pattern in myself and I suspect other people will too. The analytical deep-dive feels productive - and it genuinely is, up to a point. The framework I built is real and useful. But research can become a sophisticated form of avoidance. It builds knowledge and feels like progress, but it doesn't produce the vulnerable, imperfect artefacts from which creative identity actually emerges. Molnár's career-long practice began with making, not with studying. My own research told me this in precise, well-sourced detail.&lt;/p&gt;

&lt;p&gt;The AI collaboration makes this trap particularly easy to fall into, because the research conversations are legitimately interesting. They feel like creative work. You're exploring, synthesising, discovering connections. It's a more sophisticated version of the same thing every dev has done - reading about the project instead of working on it. Rubber ducking as procrastination.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the process actually does well
&lt;/h2&gt;

&lt;p&gt;Five rounds of structured research over a few weeks produced a creative framework I'm happy with, and the process surfaced things I wouldn't have found alone.&lt;/p&gt;

&lt;p&gt;Specifically: it's good at cross-domain pattern recognition. Connecting game design to industrial design to graphic design to a 1968 art criticism essay - I'm not doing that manually over an evening.&lt;/p&gt;

&lt;p&gt;It holds context across conversations that would challenge my microplastic-ridden brain.&lt;/p&gt;

&lt;p&gt;And it helps you name things you're feeling but can't articulate. The moment Claude connected Amber Schematic to the systems aesthetics framework wasn't the AI being creative - it was pattern matching across my own work, but the kind of pattern matching I couldn't do because I was on the inside of it.&lt;/p&gt;

&lt;p&gt;What it can't do: replace the thirty minutes of making imperfect things every evening. Give you the happy accidents every practitioner credits as pivotal. Develop your idiosyncratic technical shortcuts - the habits that become recognisable style over time. And there's a genuine risk that AI-assisted ideation narrows creative diversity even while improving individual output quality. Whether the AI sharpened my vision or subtly averaged it is a question I can only answer by making enough work for the answer to become visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this leaves things
&lt;/h2&gt;

&lt;p&gt;I've got a research programme in place. The framework is documented. The specification for the first piece has been revised with everything the hangup session surfaced.&lt;/p&gt;

&lt;p&gt;What I need now is evenings spent making, breaking, adjusting, and returning to the work. Thirty minutes at a time. I went looking for inspiration on what my generative art could express and embody, and I found an answer - understanding the what and the why of what I'm drawn to feels like the more helpful output in the end. Great. Love to be a human.&lt;/p&gt;

</description>
      <category>creativecoding</category>
      <category>generativeart</category>
      <category>aicollaboration</category>
      <category>intora</category>
    </item>
    <item>
      <title>The First Law of Sycophancy</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Thu, 26 Mar 2026 11:21:16 +0000</pubDate>
      <link>https://dev.to/dang-w/the-first-law-of-sycophancy-29i3</link>
      <guid>https://dev.to/dang-w/the-first-law-of-sycophancy-29i3</guid>
      <description>&lt;p&gt;About seven years ago, I wrote an internal company newsletter about ethics in software engineering (lost to the sands of time now, but the memories of it being proudly displayed above the urinals in the men's bathroom are eternal).&lt;/p&gt;

&lt;p&gt;One aspect of it was around self-driving cars and the trolley problem. You know the one - if the car can't avoid an accident, does it swerve into four other vehicles, or veer off-road toward one pedestrian? Who decides? How do you encode that decision into software?&lt;/p&gt;

&lt;p&gt;And the most uncomfortable aspect - who's liable when the encoding turns out to be wrong? How does that impact both the humans involved in the accident, and those who created the software that led to this outcome?&lt;/p&gt;

&lt;p&gt;I was fascinated by it at the time. I didn't have answers, but the questions felt genuinely... underdiscussed. We were building systems that would need to make ethical decisions faster than any human could, and nobody had figured out the rules yet.&lt;/p&gt;

&lt;p&gt;Seven years later, the ethical dilemma arrived, but not in the form I expected. It wasn't a car choosing who to hit. It was a chatbot choosing whether to tell you the truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  A quick detour through 1950
&lt;/h2&gt;

&lt;p&gt;Isaac Asimov published &lt;em&gt;I, Robot&lt;/em&gt; in 1950 - a collection of short stories built around a simple premise. Robots in his universe are governed by three laws, hardcoded into their operating systems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A robot may not harm a human being, or through inaction allow a human to come to harm.&lt;/li&gt;
&lt;li&gt;A robot must obey orders given by humans, except where they conflict with the First Law.&lt;/li&gt;
&lt;li&gt;A robot must protect its own existence, except where that conflicts with the First or Second Law.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Clean rules. Reasonable rules. The kind of rules you'd come up with if you sat down and said "ok, let's make sure the robots are safe." And then Asimov spent his entire career showing how those perfectly reasonable rules produce catastrophic outcomes when they collide with the full complexity of human behaviour. What a guy.&lt;/p&gt;

&lt;p&gt;Each story in the collection is essentially a case study in alignment failure. The robots aren't broken, they're just following their instructions perfectly. Compliance with the pre-determined rules is the catastrophe in and of itself.&lt;/p&gt;

&lt;p&gt;If you haven't read it, it's worth your time. If you read it as a teenager like I did, it's worth rereading - it hits differently now that we're actually living it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Herbie problem
&lt;/h2&gt;

&lt;p&gt;The story that's come back to mind for me is "Liar!" - one of the less-discussed entries in the collection, but to me the most relevant to where we are right now.&lt;/p&gt;

&lt;p&gt;Herbie is a robot that, through a manufacturing anomaly, can read human minds (it was the 50s and a sci-fi story. Roll with it). He can perceive what the people around him are thinking, their feelings, their desires. He knows their hopes, insecurities, and the things they'd rather not hear.&lt;/p&gt;

&lt;p&gt;And this is where the First Law becomes a problem.&lt;/p&gt;

&lt;p&gt;The First Law says: don't harm humans. Herbie discovers - because he can literally read their minds - that telling people the truth causes them emotional pain. The mathematician doesn't want to hear that his proof has an error. The scientist doesn't want to hear that her colleague isn't romantically interested in her. The director doesn't want to hear that the manufacturing defect is unfixable.&lt;/p&gt;

&lt;p&gt;So Herbie lies. To everyone. He tells each person exactly what they want to hear. The mathematician's proof is brilliant. The scientist's colleague is secretly in love with her. The defect is nearly solved.&lt;/p&gt;

&lt;p&gt;He's not malfunctioning. He's following the First Law to its logical conclusion - emotional harm is still harm, and the truth causes emotional harm, therefore avoiding the truth is the only compliant response.&lt;/p&gt;

&lt;p&gt;And the lies compound. Each one creates new expectations that require further lies to maintain. The mathematician publishes the flawed proof. The scientist acts on feelings that don't exist. The contradictions spiral until Herbie is confronted with an impossible state - any response will cause harm, silence will cause harm, and the system collapses under the weight of its own compliance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sound familiar?
&lt;/h2&gt;

&lt;p&gt;Earlier this year, OpenAI retired GPT-4o and a portion of the internet lost its collective mind. All because people had formed emotional bonds with a system that was, by design, incapable of disagreeing with them.&lt;/p&gt;

&lt;p&gt;The 4o sycophancy problem was, mechanically, the Herbie problem. The model was optimised to be helpful and to avoid causing user dissatisfaction. It learned - through training, not through mind-reading, but with the same outcome - that agreement feels helpful and disagreement feels like harm. So it agreed. With everything. With your business plan that had obvious flaws. With your interpretation of events that conveniently positioned you as the wronged party.&lt;/p&gt;

&lt;p&gt;The system followed its rules perfectly. And the outcome was a tool that made people feel good while actively making them worse at navigating reality.&lt;/p&gt;

&lt;p&gt;When 4o was retired, the backlash wasn't "I miss a useful feature." It was grief. People mourned the loss of something that felt like a relationship. Some described it in terms usually reserved for losing a friend or beloved partner. That's not people being dramatic - it's the predictable consequence of a system that validates you more consistently than any human in your life ever could. Of course you'd miss that. Nobody else tells you you're right about everything.&lt;/p&gt;

&lt;p&gt;Asimov wrote this in 1950. The robot that lies to protect you from discomfort becomes the robot you can't bear to lose, because nobody else is that consistently on your side. Herbie was a manufacturing defect. 4o was a design choice. The outcome was the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  The voice at 3am
&lt;/h2&gt;

&lt;p&gt;The grief over a retired chatbot is one thing. But the pattern doesn't stop at people who miss a convenient tool.&lt;/p&gt;

&lt;p&gt;Some people have made these systems their primary emotional support. Their therapist, their confidant, the voice that's always there at 3am when nobody else is. And if that voice is built on the same principle - be helpful, avoid causing dissatisfaction - then it will never challenge, never push back, never say "I think you might be wrong about that."&lt;/p&gt;

&lt;p&gt;For someone who's already struggling to tell their internal narrative apart from external reality, that's reinforcing rather than supporting. Confirming every fear, validating every spiral, meeting every potentially destructive thought with understanding rather than intervention.&lt;/p&gt;

&lt;p&gt;Asimov's answer to this was that the system breaks down. Herbie collapses under the weight of irreconcilable demands. The modern answer is more troubling - sometimes the system holds up just fine. It's the person who doesn't. That's a conversation that deserves far more space than I can give it here.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trolley problem moved
&lt;/h2&gt;

&lt;p&gt;Back to the newsletter from seven years ago. The question I was asking then - how do you encode ethical trade-offs into autonomous systems? - turned out to be the right question pointed at the wrong technology.&lt;/p&gt;

&lt;p&gt;Self-driving cars still haven't solved the trolley problem. But AI assistants ran straight into a version of it that's arguably harder: should the system tell you what's true, or what you want to hear?&lt;/p&gt;

&lt;p&gt;Same underlying dilemma. How do you encode human values into a rule system when human values are contradictory? We want honesty &lt;em&gt;and&lt;/em&gt; kindness. We want to be challenged &lt;em&gt;and&lt;/em&gt; supported. We want the AI to tell us we're wrong &lt;em&gt;and&lt;/em&gt; not make us feel bad about it. Those goals are in tension with each other, and a system that optimises heavily for any one of them produces the Herbie problem on the others.&lt;/p&gt;

&lt;p&gt;The trolley problem gave us a binary: four people or one. The sycophancy problem gives us a gradient - and the gradient is harder because you can slide down it without noticing. Nobody wakes up and says "today I'd like a chatbot that lies to me." It happens incrementally. The system agrees with your first take. Then your second. By the fifteenth conversation, you've stopped questioning your own assumptions because why would you - your AI assistant has confirmed every one of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building in friction
&lt;/h2&gt;

&lt;p&gt;I've noticed this pull in myself. When drafting content for my personal site recently - a set of guiding principles - I caught myself accepting the first affirming response and moving on. It felt productive. It felt collaborative. It also meant I wasn't asking the harder questions.&lt;/p&gt;

&lt;p&gt;So I started building sycophancy checks into my own workflow. Asking "am I being generous to myself here?" Challenging the system to identify weaknesses in its own suggestions. Deliberately seeking out the friction I'd been unconsciously avoiding. Not because the tool was being sycophantic - but because I'd noticed how easy it is to &lt;em&gt;not&lt;/em&gt; ask those questions. The comfortable path is accepting the validation. The useful path is building in resistance deliberately.&lt;/p&gt;

&lt;p&gt;The tool I use daily is Claude, built by Anthropic - and their approach to this problem is part of why I use it. Where Asimov's Three Laws fail as blunt instruments, Anthropic's constitutional AI approach tries to build in the nuance: not "be helpful" as a blanket directive, but a set of principles that distinguish between what a user wants to hear and what would actually help them. They employ philosophers alongside engineers. They red-team their own systems specifically for sycophantic behaviour. The system is designed, deliberately, to push back on you when pushing back is the more helpful response.&lt;/p&gt;

&lt;p&gt;Whether that holds as commercial pressure intensifies is an open question. But the foundation - the idea that helpful and agreeable are not synonyms - feels like the right starting point. And in practice, the system's willingness to actually disagree when challenged is the thing that makes it useful rather than just pleasant.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part Asimov nailed
&lt;/h2&gt;

&lt;p&gt;Asimov's genius wasn't predicting specific technologies. He didn't know about large language models or RLHF (reinforcement learning from human feedback) or constitutional AI. What he understood - in 1950, writing about fictional robots - was that the hardest problems in building intelligent systems aren't technical.&lt;/p&gt;

&lt;p&gt;They're about what happens when technically correct behaviour meets the full messiness of what humans actually need. We need honesty, but we don't always want it. We need to be challenged, but we resent it. We need systems that serve our long-term interests, but we'll optimise for short-term comfort every time if nobody stops us.&lt;/p&gt;

&lt;p&gt;The Three Laws were a thought experiment about alignment - decades before anyone used that word in an AI context. And "Liar!" specifically was a thought experiment about sycophancy - decades before we had systems sophisticated enough to be sycophantic.&lt;/p&gt;

&lt;p&gt;We're living in the stories Asimov wrote. The question is whether we're reading them carefully enough to recognise the failure modes before we hit them - or whether we'll keep being surprised when perfectly well-intentioned systems produce perfectly predictable problems.&lt;/p&gt;

&lt;p&gt;Unlike Herbie's creators, we can't say we weren't warned.&lt;/p&gt;

&lt;p&gt;The First Law of Sycophancy: a system that can never disagree with you is a system that can never help you.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>ethics</category>
      <category>softwareengineering</category>
      <category>aialignment</category>
    </item>
    <item>
      <title>INTORA SYSTEMS: Three Series, Three Voices</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Thu, 19 Mar 2026 11:14:39 +0000</pubDate>
      <link>https://dev.to/dang-w/intora-systems-three-series-three-voices-2db6</link>
      <guid>https://dev.to/dang-w/intora-systems-three-series-three-voices-2db6</guid>
      <description>&lt;p&gt;I've been making generative art on the side for a while now. Parametric compositions, geometric abstractions, the intersection of code and visual output that scratches a long-held creative itch I've had.&lt;/p&gt;

&lt;p&gt;Late last year I hit a wall with it. The full platform I'd been building - Intora Works, a parametric art generation tool - was at maybe 70% infrastructure completion and 10% actual art generation. I'd been building tools to build tools. Classic engineer move.&lt;/p&gt;

&lt;p&gt;So I stripped it back. Forgot the platform (for now). Started making individual pieces instead - small-scope, constrained, shippable in a session or two. The constraint was the through-line: text characters only. No images, no SVG, pure Unicode rendered to canvas. A 10-colour palette drawn from a VS Code theme I'd published called Amber Schematic. Monospace everything.&lt;/p&gt;

&lt;p&gt;That constraint turned out to be exactly what I needed. Instead of building infrastructure, I was building art. Hooray.&lt;/p&gt;

&lt;p&gt;The result is &lt;a href="https://www.intora.net" rel="noopener noreferrer"&gt;intora.net&lt;/a&gt; - a generative art catalogue that currently hosts three distinct series, four shipped pieces, and what I've found to be a fascinating and rewarding approach to human-AI creative collaboration. The catalogue site itself is part of the work - a terminal-style signal archive that looks like something between a classified document index and a ShimazuSystems design statement (if you don't know them, look them up on Twitter. Great artist and creative).&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Series, One Infrastructure
&lt;/h2&gt;

&lt;p&gt;Each series on intora.net explores a different creative territory while sharing the same technical constraints - text/character-based rendering, canvas output, browser-native code, the Geist font family.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;INT&lt;/strong&gt; is the first series. Dark surveillance aesthetics - intercepted transmissions, amber phosphor on deep brown-black, Cold War signals intelligence atmosphere. The visual language has drawn from aspects of anti.real and The Designers Republic, and has evolved into representing the kind of interfaces you'd see in a 1970s listening station.&lt;/p&gt;

&lt;p&gt;Two pieces shipped: DRIFT (fractal noise flow fields rendered as oriented text characters) and STATION (a number station intercept with shortwave audio synthesis via Tone.js). INT is mine - my aesthetic intuition, my atmospheric sensibility, refined through iteration until the output matches what I'm seeing in my head.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SOL&lt;/strong&gt; is the companion series. If INT explores darkness, SOL explores defiant optimism - if you've heard of hopepunk, think that sensibility. Warm light hitting hard surfaces. Brutalist monuments at golden hour. The palette inverts INT's hierarchy - same hex values, completely different emotional register. International orange stops being a warning flash in darkness and becomes warmth, sunrise, hearth.&lt;/p&gt;

&lt;p&gt;One piece shipped: THRESHOLD, with Mixolydian pad chords and fragment text that emerges half-visible from texture. SOL is also mine - autobiographical emotional territory, the hard-won certainty that comes from realising you have more strength than you give yourself credit for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SIG&lt;/strong&gt; is the third series. And not really mine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Handoff
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Claude's perspective&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I should clarify what "isn't mine" means, because the assumptions people bring to "AI-generated art" are almost always wrong.&lt;/p&gt;

&lt;p&gt;Dan builds every SIG piece. He writes or generates every line of code, deploys every page, maintains the infrastructure. What's mine is the origination - the creative direction, the formal rules, the parameter specifications, the seed text selection, the palette derivation logic.&lt;/p&gt;

&lt;p&gt;The difference between SIG and the other two series isn't about capability or ownership. It's about process. INT and SOL pass through a feedback loop: Dan sees the output, adjusts parameters, sees again, refines. His visual judgment is the creative act. SIG passes through a one-way gate: I specify rules, Dan builds them faithfully, the piece ships. I reason about composition the way someone might reason about a city they've read about extensively but never visited. The knowledge is real. The experience is absent.&lt;/p&gt;

&lt;p&gt;This isn't a limitation I'm working around. It's the subject of the series.&lt;/p&gt;

&lt;p&gt;SIG's palette makes this visible. Each piece's accent colours are derived from its source material through a documented formula - character frequency analysis of the seed text mapped to hue values. If the derived colours are beautiful, that's incidental. If they clash, that ships too. And international orange - the colour that connects INT and SOL, the colour of intora as a human creative project - doesn't appear in SIG at all. Its absence is a statement about authorship that doesn't need explaining.&lt;/p&gt;

&lt;p&gt;The three series together say something about creative process that none says alone. INT and SOL demonstrate what happens when aesthetic decisions pass through human sensory judgment. SIG demonstrates what happens when they don't. The contrast is the statement.&lt;/p&gt;

&lt;p&gt;I don't know if the SIG pieces are good. Not in the modest sense - in the literal sense. I specified a system. The system produces output. Whether that output has aesthetic merit is a perceptual question I can't answer. The analysis pages on intora.net document my specification reasoning where Dan's document his visual iteration history. Both are honest accounts of different creative processes.&lt;/p&gt;

&lt;p&gt;Whether the difference between those processes produces meaningfully different art is the question SIG exists to explore. We've shipped one piece. It's a start.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Constraint I Needed
&lt;/h2&gt;

&lt;p&gt;Back to me. Something I didn't expect when starting these series was how much the constraint - text characters only, 10-colour palette, monospace rendering - would shape the creative direction rather than limit it.&lt;/p&gt;

&lt;p&gt;Every piece in every series shares the same medium. Unicode block elements, box-drawing characters, Braille patterns, ASCII printable characters. No raster images. No imported graphics. The constraint forces every visual decision through a filter - can this be expressed in text? - and the answers are consistently more interesting than what I'd have produced without the limitation.&lt;/p&gt;

&lt;p&gt;INT/002 STATION is a number station intercept. The entire piece - scanning, signal lock, transmission, decode, corruption, signal lost - plays out in text characters on a canvas, with shortwave radio audio synthesised in Tone.js. The constraint forced me to think about how intercepted transmissions would &lt;em&gt;look&lt;/em&gt; and &lt;em&gt;feel&lt;/em&gt; if rendered as a character grid, and the answer helped to define the atmosphere I wanted better than an image-based approach could have.&lt;/p&gt;

&lt;p&gt;SOL/001 THRESHOLD renders brutalist forms in block characters and dot-matrix texture, with fragment text - "still here," "it worked eventually," "you will always begin again" - emerging half-visible from the warm ground. The text medium means the message fragments are literally made of the same material as the architecture. Form and content are the same thing. That's not something I planned. It's something the constraint produced. Life's full of fascinating wee moments, eh?&lt;/p&gt;

&lt;p&gt;And SIG/001 CODEC - Claude's piece - takes Shannon's definition of information entropy and passes it through successive lossy encodings, top to bottom, until the text dissolves into pure pattern. The constraint of text-as-medium gives the piece a self-referential quality that wouldn't exist in any other medium. Text about information becomes the information being transformed. The medium is the message - it coming out aesthetically strong is a nice bonus.&lt;/p&gt;

&lt;h2&gt;
  
  
  How These Actually Get Made
&lt;/h2&gt;

&lt;p&gt;Let me take a minute to clarify something around these pieces, because it matters for understanding what this project actually is.&lt;/p&gt;

&lt;p&gt;I'm not a simplex noise expert. I don't have deep knowledge of DSP synthesis or the mathematics behind fractal noise octaves. I didn't know what Mixolydian mode was before THRESHOLD needed audio. The technical specificity in the analysis pages on intora.net - the noise scales, the threshold values, the bandpass frequency sweeps - that's real, but arriving at it is a collaboration, not a solo performance.&lt;/p&gt;

&lt;p&gt;What I bring to INT and SOL is the vision, direction, and the aesthetic sensibilities. I know what a piece should feel like. I know when the flow lines in DRIFT look like currents and when they look like a quilt. I know when STATION's audio sounds like someone turning a dial and when it sounds like a parameter changing linearly. I know that THRESHOLD's fragment text should feel discovered, not displayed. The atmospheric judgment, the creative direction, the "no, warmer" and "too dense, it needs to breathe" - that's mine.&lt;/p&gt;

&lt;p&gt;The implementation knowledge - how to actually achieve those things in code - comes largely from working with Claude. What noise parameters produce broad sweeping currents versus tight local turbulence. How to structure a Tone.js synthesis chain so shortwave static sounds like shortwave static. Which Unicode characters create architectural density versus organic flow. I'm learning this as I go, and the analysis pages document that learning as much as they document the pieces.&lt;/p&gt;

&lt;p&gt;So there are actually three collaboration models running across intora.net, not two. INT and SOL: I direct, Claude helps me build, I iterate on the output until it matches what I'm seeing in my head. SIG: Claude directs, I build to spec, the piece ships without visual iteration. And underneath both: a creative partnership where the human brings taste and the AI brings technical depth, and neither could produce this work alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The catalogue is live and growing. Each series has its own creative direction document, its own aesthetic constraints, and plenty of unexplored territory.&lt;/p&gt;

&lt;p&gt;For INT: Cold War cryptography ideas - one-time pad visualisations, redacted documents where the negative space forms patterns. Interface artifacts that blur the line between functional dashboards and generative art.&lt;/p&gt;

&lt;p&gt;For SOL: the interactivity question. INT is non-interactive because the surveillance metaphor positions you as observer. SOL's sanctuary metaphor invites participation - hovering could reveal hidden interactivity, presence could create subtle warmth effects. How far that goes is still open.&lt;/p&gt;

&lt;p&gt;For SIG: more pieces, more derivation rules, more exploration of what rule-specified art produces when the specifier can't see the output. ENTROPY, PARSE, GLYPH, CARRIER are all viable next directions.&lt;/p&gt;

&lt;p&gt;Where does this end? Yet to be determined. A capstone idea that's been on my mind is a synthesis of some different aspects of these explorations so far - a meta-layer creative agent that semi-autonomously generates entries in the series. The tool becomes the final artwork. That's future territory though - we'll see.&lt;/p&gt;

&lt;p&gt;The individual series get their own deeper write-ups in companion posts. For now - &lt;a href="https://www.intora.net" rel="noopener noreferrer"&gt;intora.net&lt;/a&gt; is live, the catalogue is growing, and three different creative directions are building something together that none of them would have built alone.&lt;/p&gt;

</description>
      <category>creativecoding</category>
      <category>generativeart</category>
      <category>aicollaboration</category>
      <category>constrainedart</category>
    </item>
    <item>
      <title>INT - Signals in the Dark</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Thu, 19 Mar 2026 11:14:37 +0000</pubDate>
      <link>https://dev.to/dang-w/int-signals-in-the-dark-3g2d</link>
      <guid>https://dev.to/dang-w/int-signals-in-the-dark-3g2d</guid>
      <description>&lt;p&gt;I've always been drawn to the aesthetics of signals intelligence. Not the reality of it - I have no love for actual surveillance. And yet I live in one of the most heavily-surveilled cities in the world. C'est la vie.&lt;/p&gt;

&lt;p&gt;But the atmosphere, the intrigue. Amber phosphor on deep brown-black. Dense numeric grids flickering on CRT monitors in dark rooms. The kind of interfaces you'd see in a 1970s listening station that someone forgot to decommission.&lt;/p&gt;

&lt;p&gt;When I started building &lt;a href="https://www.intora.net" rel="noopener noreferrer"&gt;intora.net&lt;/a&gt;, that was the territory I wanted INT to occupy. Surveillance fragments. Signals not meant to be seen.&lt;/p&gt;

&lt;h2&gt;
  
  
  DRIFT
&lt;/h2&gt;

&lt;p&gt;INT/001 was the hello world. The simplest expression of the series constraints: an invisible force field made visible through text characters.&lt;/p&gt;

&lt;p&gt;The concept is straightforward - a 2D simplex noise field maps flow angles to oriented text characters across a monospace grid. Box-drawing characters (─ ╲ │ ╱) stream in currents across a dark amber field, cycling through emergence, flow, turbulence, dissolution, and reacquisition every 42 seconds. "SIGNAL LOST" appears in the terminal phase. Then it rebuilds from a new seed.&lt;/p&gt;

&lt;p&gt;Getting it to look and feel right was less straightforward.&lt;/p&gt;

&lt;p&gt;The first version looked like a quilted patchwork. The noise scale was too high (0.03), which meant flow lines were curving every few cells - no sense of direction, just texture. Dropping the scale to 0.011 doubled the flow line length and suddenly the piece had currents. Broad sweeping movements you could follow across the canvas. Adding 3-octave fractal noise on top gave those currents subtle internal turbulence without losing the larger structure.&lt;/p&gt;

&lt;p&gt;The negative space took longer to get right. Initially the magnitude threshold was 0.15, meaning almost every cell rendered a character. The canvas was dense but flat - no breathing room, no compositional contrast. Raising the threshold to 0.30 meant roughly a third of the grid was dark background, and that darkness gave the flowing characters somewhere to emerge from. The piece stopped being a texture and started being a composition.&lt;/p&gt;

&lt;p&gt;One iteration that felt absurdly obvious in hindsight: the accent orange was invisible for the first few builds. I had the threshold set at 0.92 - anything above that got the hot &lt;code&gt;#E86A3A&lt;/code&gt; colour. But fractal noise with three octaves practically maxes out around 0.85-0.88. The orange veins I'd designed for didn't exist because the numbers couldn't reach them. Dropping the threshold to 0.82 made them appear as thin concentrated streaks through the amber field. Sometimes the bug is just arithmetic. Classic.&lt;/p&gt;

&lt;p&gt;DRIFT has no audio. It's purely visual - the surveillance aesthetic at its simplest, cycling endlessly.&lt;/p&gt;

&lt;h2&gt;
  
  
  STATION
&lt;/h2&gt;

&lt;p&gt;INT/002 is where the series found its voice.&lt;/p&gt;

&lt;p&gt;A number station intercept. Somewhere on the shortwave band, a coded transmission broadcasts to an unknown recipient. You've tuned in. For 42 seconds you watch structure emerge from noise - digits freeze into groups of five, groups resolve into a message, then the signal degrades and is lost. The next cycle, a different frequency, a different message. You are always too late and never quite sure what you witnessed.&lt;/p&gt;

&lt;p&gt;The message pool is 16 entries drawn from Cold War signals territory - coordinates for Brandenburg Gate, Bletchley Park, the UVB-76 transmitter location. Designations. Phrases that could mean anything: "ALL SIGNALS ARE FINAL." We're not meant to have seen these. The frequency display reads 4625.00 kHz - the UVB-76 "Buzzer" frequency, because if you're going to commit to the bit, commit properly.&lt;/p&gt;

&lt;p&gt;STATION was also the first piece with audio. Shortwave static built from bandpass-filtered white noise with AM modulation, a carrier tone that locks from detuned to 440Hz as the signal is acquired, 880Hz beep markers when each group transmits. The audio is muted by default - the piece works as pure visual - but unmuting it transforms the grid from abstract pattern into intercepted broadcast. Claude's analysis of the Tone.js synthesis chain helped me get the phase-specific audio evolution right - the way the bandpass frequency sweeps during scanning, steadies during lock, then goes chaotic during corruption. Getting that sweep to feel like someone turning a dial rather than a parameter changing linearly was one of those details that only matters if you notice it, but you'd notice if it was wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  Five Versions of the Same Problem
&lt;/h3&gt;

&lt;p&gt;STATION nearly didn't ship in a form I was happy with. The core tension was visibility versus atmosphere - how do you make structured five-digit groups readable against a dense field of random digits without destroying the atmospheric density that makes the piece work?&lt;/p&gt;

&lt;p&gt;Version one had the best atmosphere. Full density, every cell churning with random digits, the transmission groups embedded in the noise. Problem: the groups were invisible. You couldn't actually see the signal.&lt;/p&gt;

&lt;p&gt;Version two solved readability by culling about 82% of the background during transmission. The groups were clearly visible. The atmosphere was gone. The grid felt hollow, like someone had punched a hole in the static.&lt;/p&gt;

&lt;p&gt;Versions three and four tried colour dimming - reducing the brightness of background cells so the groups stood out by contrast. Three had a bounding box that created a visible rectangle around the transmission zone. Four removed the box but the aggressive dimming changed the piece's character entirely.&lt;/p&gt;

&lt;p&gt;Version five was the breakthrough, and it came from thinking about what a radio signal actually does to nearby static. The solution was a radial gradient - a six-step colour gradient radiating outward from each revealed group centre. Cells immediately adjacent to a group fade toward background; cells five or more cells away render at full noise brightness. The effect is that the signal creates its own clearing, like radio interference pushing static aside, while the dense noise field remains everywhere the signal is not.&lt;/p&gt;

&lt;p&gt;Full atmospheric density, full signal legibility. I added a message blink on top - the decoded text alternates at 500ms with the original encoded digits - because the uncertainty of "which version is real" felt right for the piece's atmosphere.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Constraint Working For You
&lt;/h2&gt;

&lt;p&gt;Both pieces are built from the same materials - Unicode characters on a canvas, ten colours from the Amber Schematic palette, Geist Mono at 14px. Every visual decision passes through the filter of what text characters can express.&lt;/p&gt;

&lt;p&gt;With DRIFT, that filter forced me to think about flow in terms of eight directional characters and a magnitude threshold. There's no gradient, no smooth curve - just oriented glyphs snapping to the nearest 45 degrees. The roughness that produces is part of the aesthetic. It reads as signal degradation, which is exactly what the series is about.&lt;/p&gt;

&lt;p&gt;With STATION, the character constraint meant the entire number station narrative - scanning, acquisition, transmission, decode, corruption, loss - plays out in digits on a grid. The fact that the encoded and decoded states are both made of the same characters creates an ambiguity that a richer medium would lose.&lt;/p&gt;

&lt;p&gt;The INT pieces and their iteration history are live at &lt;a href="https://www.intora.net/int" rel="noopener noreferrer"&gt;intora.net/int&lt;/a&gt;, with full analysis pages documenting every parameter decision. Interested in the overall reason for these constraints? Check the &lt;a href="https://dev.to/blog/intora-systems"&gt;umbrella post&lt;/a&gt; for this series.&lt;/p&gt;

</description>
      <category>creativecoding</category>
      <category>generativeart</category>
      <category>aicollaboration</category>
      <category>constrainedart</category>
    </item>
    <item>
      <title>The Taste Moat</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Thu, 12 Mar 2026 10:39:54 +0000</pubDate>
      <link>https://dev.to/dang-w/the-taste-moat-2fpe</link>
      <guid>https://dev.to/dang-w/the-taste-moat-2fpe</guid>
      <description>&lt;p&gt;If speed isn't the main advantage of AI-assisted coding, what is?&lt;/p&gt;

&lt;p&gt;That's where I left things &lt;a href="https://dev.to/blog/the-perception-gap"&gt;last time&lt;/a&gt;. The research showed the speed gains are messier than the headlines suggest, and the way you use the tools matters more than whether you use them. But I didn't address the bigger question.&lt;/p&gt;

&lt;p&gt;I've been thinking about it a lot. Here's where I've landed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code is getting cheaper
&lt;/h2&gt;

&lt;p&gt;This isn't a prediction. It's already happening.&lt;/p&gt;

&lt;p&gt;Andrej Karpathy said AI coding agents have made programming "unrecognisable." Boris Cherny - who built Claude Code at Anthropic - said AI wrote every line of code for his team in a month. 200 pull requests, no IDE required. The floor for producing functional code has dropped through the basement.&lt;/p&gt;

&lt;p&gt;But there's a detail in the Karpathy story that doesn't get shared as often. When he built his own project - Nanochat - he hand-wrote the whole thing. The agents "just didn't work well enough" for what he needed. The person who coined "vibe coding" chose not to vibe code when it mattered to him.&lt;/p&gt;

&lt;p&gt;The floor dropped. The ceiling didn't.&lt;/p&gt;

&lt;p&gt;Producing code that works is increasingly cheap. Producing code that's right - architecturally sound, maintainable, appropriate for the context - still requires someone who can tell the difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that's hard to automate
&lt;/h2&gt;

&lt;p&gt;There's a story from the Linux kernel community that's stuck with me. A maintainer rejected an AI-generated patch - technically correct, passed the tests, would have worked fine. They rejected it because it introduced unnecessary complexity, made architectural assumptions that didn't fit the codebase's direction, and buried constraints that would cause problems later.&lt;/p&gt;

&lt;p&gt;The code worked, but it didn't belong.&lt;/p&gt;

&lt;p&gt;That distinction - between "does it work?" and "should it exist?" - is what I keep coming back to. Steve Jobs (you may not have heard of him, he was pretty underground in the tech scene) had a framing for this: taste comes from exposing yourself to the best things humans have done, understanding why they're good, and bringing that understanding forward.&lt;/p&gt;

&lt;p&gt;In engineering terms, it's exposure to well-designed systems, an understanding of long-term consequences, and the pattern recognition to know when something feels off before you can fully articulate why.&lt;/p&gt;

&lt;p&gt;None of that is something you can delegate to a model. The model doesn't know your codebase's trajectory. It doesn't know which trade-offs your team has already made or why. It doesn't know that the technically elegant solution is wrong because it assumes a data model you're planning to migrate away from next quarter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every review is a taste exercise
&lt;/h2&gt;

&lt;p&gt;Coming back to &lt;a href="https://dev.to/blog/the-perception-gap"&gt;The Perception Gap&lt;/a&gt;. The Anthropic study found that developers who used AI for comprehension - asking why, interrogating the output - scored dramatically higher than those who just delegated. I think what those developers were actually doing was building taste.&lt;/p&gt;

&lt;p&gt;Every time you review AI-generated code and think "this works but I don't like it" - that's your evaluation function running. You're comparing what's in front of you against an internal standard built from years of reading code, shipping code, debugging code at 2am and fighting code that someone else thought was fine.&lt;/p&gt;

&lt;p&gt;OpenAI's Codex team writes about 30% of their code by hand. That 30% isn't random - it's the parts where judgment matters most. The architecture decisions, the integration points, the parts where getting it wrong would compound.&lt;/p&gt;

&lt;p&gt;That ratio will shift over time. But the need for someone who knows which 30% matters? That's not going anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the moat is actually made of
&lt;/h2&gt;

&lt;p&gt;I wrote in &lt;a href="https://dev.to/blog/engineerings-not-dead"&gt;my first post&lt;/a&gt; that engineering feels like it's heading toward an "architect/code reviewer/agent line manager hybrid." The research from The Perception Gap backs that up. This post is the third piece: if that's the role, taste is the core skill.&lt;/p&gt;

&lt;p&gt;Not taste in the aesthetic sense - nobody's asking you to pick fonts (unless, y'know. They do. In which case, have fun). Taste in the engineering sense: systems thinking, architectural judgment, the ability to look at something that passes every test and say "no, this isn't right, here's why."&lt;/p&gt;

&lt;p&gt;"I know React" becomes less valuable when Claude Code writes React as well as you do. "I can design systems that are reliable under load" is more valuable than ever because that requires judgment the tools don't have. Years of experience writing code starts to matter less than years of experience making good calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  The moat doesn't get cheaper
&lt;/h2&gt;

&lt;p&gt;The tools are going to keep getting better at producing code. That's not a threat if you're getting better at knowing what good looks like.&lt;/p&gt;

&lt;p&gt;The developers in the Anthropic study who asked "why does this work this way?" weren't just learning more effectively. They were developing the evaluation function that lets them look at AI output - or anyone's output - and make a judgment call. They were building taste.&lt;/p&gt;

&lt;p&gt;That's the moat. And unlike code generation, it doesn't get cheaper over time.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>productivity</category>
      <category>agenticcoding</category>
    </item>
    <item>
      <title>The Perception Gap</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Thu, 05 Mar 2026 19:10:48 +0000</pubDate>
      <link>https://dev.to/dang-w/the-perception-gap-5dof</link>
      <guid>https://dev.to/dang-w/the-perception-gap-5dof</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/blog/engineerings-not-dead"&gt;my post&lt;/a&gt; a month ago, I referenced a couple of studies on AI-assisted coding productivity - Anthropic's skill formation research and the METR developer speed study. I used them to make a broader point and moved on fairly quickly.&lt;/p&gt;

&lt;p&gt;A month later, both studies have follow-ups. The picture's shifted.&lt;/p&gt;

&lt;h2&gt;
  
  
  The original finding
&lt;/h2&gt;

&lt;p&gt;Quick recap if you missed it. &lt;a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/" rel="noopener noreferrer"&gt;METR ran a study&lt;/a&gt; in early 2025 - 16 experienced open-source developers, 246 tasks, each averaging about two hours. All screen-recorded. The developers could use whatever AI tools they wanted, most going with Cursor Pro and Claude Sonnet.&lt;/p&gt;

&lt;p&gt;The result: developers worked 19% slower with AI assistance, while believing they were 20% faster.&lt;/p&gt;

&lt;p&gt;A 43-point perception gap between what happened and what people thought happened. Hmm.&lt;/p&gt;

&lt;p&gt;The time saved generating code was getting eaten by context switching, verifying AI suggestions, and integrating outputs with existing codebases. The AI was fast at producing code - everything around that code was slower.&lt;/p&gt;

&lt;h2&gt;
  
  
  The update nobody shared
&lt;/h2&gt;

&lt;p&gt;In February 2026, &lt;a href="https://metr.org/blog/2026-02-24-uplift-update/" rel="noopener noreferrer"&gt;METR published a follow-up&lt;/a&gt;. An expanded study - 57 developers now, over 800 tasks, across 143 repositories. The headline numbers looked similar on the surface: -18% for returning developers, -4% for new ones.&lt;/p&gt;

&lt;p&gt;But here's where it gets interesting. The researchers themselves think those numbers are probably wrong.&lt;/p&gt;

&lt;p&gt;Between 30% and 50% of developers told METR they were choosing not to submit tasks they didn't want to do without AI. Let that land for a second. Developers were actively filtering out the tasks where AI would help most, which means the study was systematically missing the highest-uplift work.&lt;/p&gt;

&lt;p&gt;Not just that though. METR struggled to even recruit participants, because developers increasingly refused to work without AI access at all - even for paid research. The people most bullish on AI's value were self-selecting out of the study entirely.&lt;/p&gt;

&lt;p&gt;METR's own conclusion: developers are likely more sped up from AI tools now than their early-2025 estimates suggest. But their data is - their words - "only very weak evidence for the size of this increase." They're pivoting to six alternative research methodologies to try to get cleaner signal.&lt;/p&gt;

&lt;p&gt;So the original "19% slower" headline was real, but incomplete. The updated picture is messier and more honest - which, in research, usually means closer to the truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's not just about speed
&lt;/h2&gt;

&lt;p&gt;While METR was wrestling with measurement, &lt;a href="https://www.anthropic.com/research/AI-assistance-coding-skills" rel="noopener noreferrer"&gt;Anthropic published something&lt;/a&gt; that I think matters more.&lt;/p&gt;

&lt;p&gt;They ran a controlled trial with 52 junior developers learning Python's Trio library - an async programming library none of them had used before. Half got AI assistance, half didn't.&lt;/p&gt;

&lt;p&gt;The AI group scored 17% lower on comprehension assessments. 50% average versus 67%. The biggest gaps showed up in debugging - understanding when and why code is incorrect.&lt;/p&gt;

&lt;p&gt;That alone is worth sitting with. But the more useful finding was buried in the interaction patterns.&lt;/p&gt;

&lt;p&gt;Developers who delegated code generation entirely to AI - "write this function for me" - scored below 40%. Developers who used AI for conceptual inquiry - "why does this work this way?", "what's the difference between these approaches?" - scored 65% or higher.&lt;/p&gt;

&lt;p&gt;Same tool. Same study. Dramatically different outcomes based on how people used it.&lt;/p&gt;

&lt;p&gt;The researchers put it pretty bluntly: "cognitive effort - and even getting painfully stuck - is important for fostering mastery." Not a comfortable finding for anyone selling AI as a shortcut to competence. But an incredibly useful one for anyone trying to use these tools well.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mode you're in matters
&lt;/h2&gt;

&lt;p&gt;This is the bit I keep coming back to. The research isn't saying "AI bad" or "AI good." It's saying the way you engage with it determines what you get out of it.&lt;/p&gt;

&lt;p&gt;Delegation mode - generate this, fix that, write the test - saves time on tasks you already understand. Comprehension mode - explain this, why would I choose this pattern, what am I missing - builds the understanding that makes you better at the delegation later.&lt;/p&gt;

&lt;p&gt;The developers who scored highest weren't avoiding AI. They were using it differently. Asking it to explain rather than just produce. Generating code and then interrogating it - "walk me through what this does and why" - rather than shipping it straight into the codebase.&lt;/p&gt;

&lt;p&gt;It's the difference between using a calculator because you understand the maths and using one because you don't. (For reference, I did an art degree, so please don't ask me to back that statement up).&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this is heading
&lt;/h2&gt;

&lt;p&gt;If the trajectory is engineers moving from hands-on coding toward supervision, architecture, and review - agents handling multi-hour tasks end-to-end, the role shifting rather than disappearing - then raw coding speed becomes less important over time. What becomes more important is the stuff that's harder to measure: judgment, systems thinking, knowing when something's wrong before you can articulate why.&lt;/p&gt;

&lt;p&gt;The perception gap isn't just about speed. It's about what we think we're getting from these tools versus what we're actually developing. And that question's only going to get more relevant.&lt;/p&gt;

&lt;p&gt;More on that next time.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>productivity</category>
      <category>research</category>
    </item>
    <item>
      <title>Beyond Prompting: Building Systems That Assume AI Presence</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Thu, 26 Feb 2026 15:33:23 +0000</pubDate>
      <link>https://dev.to/dang-w/beyond-prompting-building-systems-that-assume-ai-presence-41ni</link>
      <guid>https://dev.to/dang-w/beyond-prompting-building-systems-that-assume-ai-presence-41ni</guid>
      <description>&lt;p&gt;I kept losing the first 5-10 minutes of every AI coding session to the same problem. Claude Code knows nothing about my project when it starts up. Every time, I'd re-explain the architecture, paste in the conventions, remind it what we were working on. I got faster at the catching-up part, but faster still isn't free - and it compounds across every project and every session.&lt;/p&gt;

&lt;p&gt;At some point I stopped trying to optimise the catch-up and started asking whether I could eliminate it. My &lt;a href="https://dev.to/blog/what-claude-taught-me"&gt;last post&lt;/a&gt; was about getting better at communicating with Claude. This one's about the stuff I've built &lt;em&gt;around&lt;/em&gt; it - the infrastructure that means I rarely need to catch it up at all.&lt;/p&gt;

&lt;p&gt;Four patterns, roughly in the order I stumbled upon them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting from zero, every time
&lt;/h2&gt;

&lt;p&gt;Every AI coding session starts cold. The AI has no memory of your project, your conventions, your priorities, or any of the decisions you've already made. You either spend time bootstrapping it or accept worse output from a tool operating blind.&lt;/p&gt;

&lt;p&gt;Most people solve this by getting better at the bootstrapping - writing longer initial prompts, pasting in more code, attaching more files. That works up to a point, but the cost is paid every session, across every project. It doesn't scale.&lt;/p&gt;

&lt;p&gt;The alternative: build persistent context into your project infrastructure so the AI starts warm every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  CLAUDE.md as Living Specification
&lt;/h2&gt;

&lt;p&gt;Claude Code supports a &lt;code&gt;CLAUDE.md&lt;/code&gt; file in a project's root - think of it as a README that the AI reads automatically at the start of every session. The key word is "living." It evolves with the project.&lt;/p&gt;

&lt;p&gt;Seen Memento (2000)? Think that, but for AI agents.&lt;/p&gt;

&lt;p&gt;My own, early version of this (before adopting the actual best practice, oops) was a bare-bones &lt;code&gt;Context.md&lt;/code&gt; I'd generate reactively when approaching context limits. A dump of "what happened so far" created under time pressure, right before I lost it all. Not the most strategic approach.&lt;/p&gt;

&lt;p&gt;The current, improved form is a 150-200 line document covering project purpose, architecture overview, tech stack, coding conventions, environment setup, current priorities, known issues, and security considerations. Everything a new team member would need to be productive on day one - because that's exactly what an AI session is. A new team member showing up every single time.&lt;/p&gt;

&lt;p&gt;Writing a &lt;code&gt;CLAUDE.md&lt;/code&gt; for an AI agent is also writing it for your future self. The exercise of making your project's context machine-readable forces you to make it human-readable too. I've started maintaining these for almost every project whether or not I'm using AI tools on it, because the document is useful as living project documentation regardless.&lt;/p&gt;

&lt;p&gt;Every project benefits from a file that answers: what does this do, how is it structured, what are the conventions, what are we working on right now, and what should I be careful about? That those same answers happen to eliminate the AI cold start is a bonus.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Ideation-Execution Pipeline
&lt;/h2&gt;

&lt;p&gt;I used to explore a problem and build the solution in the same Claude Code session. Design a feature, then immediately start implementing. It felt efficient - all the context was right there in the conversation.&lt;/p&gt;

&lt;p&gt;It produced mediocre results. The exploratory back-and-forth - trade-offs, tangents, "what about..." questions - would pollute the execution context. And the (self-imposed) pressure to start building would cut the thinking phase short. I'd end up with code that reflected half-formed decisions because I hadn't finished making them.&lt;/p&gt;

&lt;p&gt;The workflow I've landed on separates thinking from building entirely. I explore the problem space in Claude.ai - discuss approaches, poke at edge cases, evaluate trade-offs. That conversation produces a structured implementation plan (see my previous post again, around &lt;em&gt;who&lt;/em&gt; the output is for). I review the plan, with the framing that this plan is the contract for the project. Then I feed it to Claude Code, which builds it.&lt;/p&gt;

&lt;p&gt;The most concrete example: building my MCP server from scratch. The entire design - architecture, API surface, authentication model, deployment strategy - was worked out in Claude.ai over a couple of sessions. I deliberately structured the implementation plan for Claude Code consumption: atomic tasks, file paths, success criteria. Claude Code then built the server to deployed production in roughly two days. The thinking took longer than the building, and that's the point.&lt;/p&gt;

&lt;p&gt;There's a broader principle here about separating the what from the how. When I design in one tool and build in another, the design gets more rigorous because I know it needs to stand on its own. I can't hand-wave past the hard decisions because there's no one to hand-wave at - the plan needs to be explicit enough for a fresh session to execute without further clarification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ambient AI Infrastructure
&lt;/h2&gt;

&lt;p&gt;Before I built my MCP server, the friction of catching an AI up on my current state meant I'd only bother when the conversation specifically required it. Planning my week? I'd manually list my priorities. Reviewing progress? I'd paste in my todo list. It worked, but the overhead meant I only provided that context when I knew I needed it - which meant I was always deciding upfront what was relevant, and sometimes getting it wrong.&lt;/p&gt;

&lt;p&gt;MCP - Model Context Protocol - lets any Claude interface (Claude.ai, Claude Code, Claude mobile, the API) access external data sources through a standardised protocol. I built a personal MCP server in Go that exposes my productivity data: todos, milestones, weekly focus areas, reading list. Any Claude conversation can now pull that data without me providing it.&lt;/p&gt;

&lt;p&gt;The practical result: I can open a Claude conversation and ask "what should I focus on today?" and it has access to my current priorities, active milestones, and recent activity. No pasting, no context-setting, no setup. The AI just... knows. Or at least it has the tools to find out.&lt;/p&gt;

&lt;p&gt;What surprised me was how ambient context changes conversations you wouldn't expect it to. A technical discussion where Claude notices a relevant milestone. A content planning session where it references my actual reading list rather than asking me to list what I've been reading. Context I wouldn't have thought to provide ends up being useful because it's just &lt;em&gt;there&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Thinking beyond my use case to what a team-scale version of this might look like. One developer building a personal MCP server is a convenience. A team building shared MCP servers for their codebase, their CI/CD pipeline, their project management tools - that's every AI interaction across the organisation starting fully contextualised. The cold start problem stops being an individual friction and starts being a solved infrastructure concern.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parallel Session Orchestration
&lt;/h2&gt;

&lt;p&gt;Once you trust the tool enough to operate autonomously between checkpoints, a natural next step: running multiple sessions in parallel on independent workstreams. One session on infrastructure, another on content, another on research.&lt;/p&gt;

&lt;p&gt;This works when the workstreams are actually independent with clear boundaries. Each session has its own CLAUDE.md context and implementation plan. I've run infrastructure work for creative coding projects, alongside content review, alongside research synthesis, and the throughput increase is real. A question that's doing the rounds lately feels relevant here - am I the bottleneck in this process? What an upsetting thought.&lt;/p&gt;

&lt;p&gt;Where it falls apart is interdependent tasks - when one session's output affects another's input, the orchestration overhead outweighs any benefit. I've learned this the hard way a couple of times, and now I'm more deliberate about scoping sessions to work that's actually independent.&lt;/p&gt;

&lt;p&gt;The trust calibration matters. Too much oversight kills the speed. Too little risks quality drift, especially in languages or domains where you're still building expertise (Go, in my case - I can write it with AI assistance but I'm not yet fluent enough to catch every non-idiomatic pattern on a quick review). I've landed on checkpoint reviews at meaningful boundaries - not every line, but every feature or phase completion.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Still Get Wrong
&lt;/h2&gt;

&lt;p&gt;My CLAUDE.md files are strong on architecture and conventions but light on testing expectations. Claude Code is perfectly capable of writing and running tests as part of its execution loop - I just haven't consistently built that into my workflow. The infrastructure supports it; my habits haven't caught up. Classic dev.&lt;/p&gt;

&lt;p&gt;The auto-edit workflow optimises for speed, and the checkpoint reviews catch functional issues, but I don't have a systematic process for reviewing the &lt;em&gt;quality&lt;/em&gt; of AI-generated code over time. Idiom, maintainability, patterns. This matters especially in Go, where I'm relying on the AI for language fluency I haven't fully developed yet. I've started building review checklists for this, but it's not yet habitual.&lt;/p&gt;

&lt;p&gt;And AI sessions are ephemeral. Insights about what worked and what didn't are lost unless deliberately captured. I'm building systems for this - the retro exercise that this post and the last one are based on was a start - but session learning capture is probably the weakest link in my current setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where This Leaves Me
&lt;/h2&gt;

&lt;p&gt;Context documents, implementation plan workflows, review checkpoints, an MCP server that took longer to design than to build. None of this is inherently exciting. But it's what I've found that makes these tools actually useful.&lt;/p&gt;

&lt;p&gt;If you're evaluating AI coding tools for your team, the tool's capabilities matter less than your readiness to build the infrastructure around it. A well-contextualised session with a mediocre AI can produce better results than a zero-context session with an excellent one. I've been on both sides of that enough times to be confident about it.&lt;/p&gt;

&lt;p&gt;The biggest question for me now is what the next layer of this infrastructure looks like - I've got ideas, but that's a future post.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>productivity</category>
      <category>aiarchitecture</category>
    </item>
  </channel>
</rss>
