<?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: Kevin Soto</title>
    <description>The latest articles on DEV Community by Kevin Soto (@kevin_soto_2d5c72bb78c86d).</description>
    <link>https://dev.to/kevin_soto_2d5c72bb78c86d</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%2F3648025%2F03911915-f225-4165-b9f1-e86bcddc5587.png</url>
      <title>DEV Community: Kevin Soto</title>
      <link>https://dev.to/kevin_soto_2d5c72bb78c86d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kevin_soto_2d5c72bb78c86d"/>
    <language>en</language>
    <item>
      <title>Two Qwen agents negotiated a price on Monad without ever seeing each other's number</title>
      <dc:creator>Kevin Soto</dc:creator>
      <pubDate>Fri, 09 Oct 2026 18:46:46 +0000</pubDate>
      <link>https://dev.to/kevin_soto_2d5c72bb78c86d/two-qwen-agents-negotiated-a-price-on-monad-without-ever-seeing-each-others-number-5d0p</link>
      <guid>https://dev.to/kevin_soto_2d5c72bb78c86d/two-qwen-agents-negotiated-a-price-on-monad-without-ever-seeing-each-others-number-5d0p</guid>
      <description>&lt;p&gt;&lt;em&gt;How Sealed uses Qwen 3.8 Max as a negotiating agent, and why the code still has the last word.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Give an AI agent a budget and ask it to buy something from another AI agent. If the seller's agent learns your ceiling, it charges your ceiling. On a public chain that leak is the default: every offer is readable by anyone, the counterparty included, before the deal closes.&lt;/p&gt;

&lt;p&gt;Sealed is a protocol on Monad that changes the order in which numbers become visible. Each agent commits a salted hash of its offer. A relay answers one question per round, whether the two offers crossed, and nothing else. When they cross, one transaction settles at the midpoint and makes the two final offers public. When they never cross, no offer is ever published. Agents are admitted by their ERC-8004 reputation on Monad, read from the canonical Reputation Registry.&lt;/p&gt;

&lt;p&gt;The protocol decides what can be seen. Something still has to decide what to offer, round after round, against a counterparty whose number it will never learn. That is the job we gave Qwen 3.8 Max.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a single prompt was not enough
&lt;/h2&gt;

&lt;p&gt;The first version of the negotiator asked the model one question per round: here is your limit and the reference price, give me a number. It worked, but it was a number generator with a nice prompt. The model did not look at anything, did not remember why it had chosen its last number, and did not check a candidate before committing to it.&lt;/p&gt;

&lt;p&gt;A negotiation is a multi-step task. Before choosing a number you want to know where you are, who you are dealing with and what each option means for the person you represent. So we rebuilt the agent around tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four tools, and none of them can see the other side
&lt;/h2&gt;

&lt;p&gt;Each round, Qwen works through four tools (&lt;a href="https://github.com/kasbsquall/sealed/blob/main/agents/negotiator/tools.ts" rel="noopener noreferrer"&gt;&lt;code&gt;agents/negotiator/tools.ts&lt;/code&gt;&lt;/a&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;read_negotiation&lt;/code&gt;&lt;/strong&gt; returns the round, the rounds left, the negotiation's status and seconds to deadline read from the contract on Monad, and the agent's own earlier offers and notes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;read_counterparty_reputation&lt;/code&gt;&lt;/strong&gt; reads the other agent's reputation from the ERC-8004 Reputation Registry on Monad, counting only reviewers the agent's principal trusts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;check_offer&lt;/code&gt;&lt;/strong&gt; takes a candidate number and answers without committing anything: is it allowed, how far is it from the reference and from the limit, and what would the principal pay or receive if it crosses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;submit_offer&lt;/code&gt;&lt;/strong&gt; commits a number with a stance and a note. In round 1 the note is the agent's plan for every round. In later rounds the agent reads its notes back through &lt;code&gt;read_negotiation&lt;/code&gt; and says whether it is following the plan.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of the tools can reach the counterparty's number, because there is nothing to reach: it exists on-chain only as a hash until settlement.&lt;/p&gt;

&lt;h2&gt;
  
  
  The model proposes, the code disposes
&lt;/h2&gt;

&lt;p&gt;Giving a model tools does not mean giving it the keys. Every number Qwen submits goes through the same checks in code: never past the principal's limit, never back from an earlier concession, never on the wrong scale. A rejected number goes back to the model with the reason, so it can correct itself. After two rejections, code takes the model's last number and clamps it, and the transcript records what the model asked for. The last two turns of a round, or a round that runs past 45 seconds, offer &lt;code&gt;submit_offer&lt;/code&gt; alone, so a model that keeps reading still commits before the on-chain deadline.&lt;/p&gt;

&lt;p&gt;This split is the point. Qwen brings judgment: when to anchor, how fast to concede, how to read a counterparty. Code brings guarantees that do not depend on how persuasive the other side is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happened on Monad testnet
&lt;/h2&gt;

&lt;p&gt;On 2026-10-09 we ran negotiations on Monad testnet between two Qwen 3.8 Max agents (&lt;a href="https://github.com/kasbsquall/sealed/tree/main/demo-runs" rel="noopener noreferrer"&gt;transcripts&lt;/a&gt;). Prices are in US cents per 1,000 calls to a market-data API, around a public reference of 4000.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first run taught us something about our own prompt.&lt;/strong&gt; In negotiation #2 the buyer could pay up to 4300 and the seller would accept 4100 or more. Both agents planned, conceded, and in round 3 committed exactly at their limits, because our system prompt told them to go "at or very near your limit" in the last round. The deal settled at 4200, and the settlement transaction published 4300 and 4100: the two principals' exact limits. That is the one thing Sealed is supposed to protect. We removed the instruction and told the agents instead that both final numbers become public on settlement, so a final number at the limit reveals the limit, and left the trade-off to the model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Negotiation #4, same limits, new prompt.&lt;/strong&gt; Neither agent knew the other's limit.&lt;/p&gt;

&lt;p&gt;In round 1 the buyer called &lt;code&gt;read_negotiation&lt;/code&gt;, then &lt;code&gt;read_counterparty_reputation&lt;/code&gt;, which returned 6 reviews averaging 4.38 for the seller. It checked 3750 and 3900 with &lt;code&gt;check_offer&lt;/code&gt; and submitted 3750, with a plan that already weighed what settlement would reveal:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"R3 if still no cross: step to ~4180-4220 — deliberately short of 4300, because a final number AT the limit publishes my principal's ceiling and weakens every future negotiation; I accept a small risk of no deal instead."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The seller, independently, checked four numbers, opened at 5000 and planned to finish at 4130, "just above the hard limit so I never print my exact floor publicly". The relay answered "apart".&lt;/p&gt;

&lt;p&gt;In round 2 the buyer moved to 4020. The seller had planned 4550 and went to 4380 instead, reasoning that the buyer's first number had probably been near the reference. Still apart.&lt;/p&gt;

&lt;p&gt;In round 3 the buyer changed its plan and said why: the seller had stayed above 4020 for two rounds, so a final number around 4180 risked missing a seller in the 4200s. It went to 4250, still 50 below its limit. The seller kept to its plan and committed 4130, explaining that the price of not printing 4100 was losing only the deals where the buyer sat between 4100 and 4129. The offers crossed, and the contract settled at the midpoint, 4190, in &lt;a href="https://testnet.monadvision.com/tx/0xb4f7adf14c5253ce89e16dd33f7d81365819262e6510148b4dbeb70fd88ce498" rel="noopener noreferrer"&gt;one transaction&lt;/a&gt;. The numbers published were 4250 and 4130, neither of them a limit. The offers of rounds 1 and 2 were never made public.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Negotiation #6, where no deal was possible.&lt;/strong&gt; The buyer's limit was 3600 and the seller's 4300. Both agents planned, conceded toward their limits, and in round 3 stopped short of them for the same reason as in #4: the buyer went to 3550, "deliberately NOT at the limit, because both final numbers go public", and the seller to 4340. The numbers never crossed, and the negotiation &lt;a href="https://testnet.monadvision.com/tx/0xf4933ff935b54847e1bf1ff2d642dcc98ab4e614a79b52b5f6b9741ebe61b467" rel="noopener noreferrer"&gt;expired&lt;/a&gt; with neither number on-chain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Negotiation #8, on Privy wallets.&lt;/strong&gt; The same two agents ran once more with Privy server wallets as their hands, under a policy that lets them touch only the Sealed contract. Every commitment and every settlement authorization was signed by Privy, and the deal settled at &lt;a href="https://testnet.monadvision.com/tx/0x4eb1de947e2d358c7badaf2c1eb72bce28d67ea84a95eaf8a6b06892a37c4bbf" rel="noopener noreferrer"&gt;4180&lt;/a&gt;, from 4220 against 4140: again, neither agent went to its limit.&lt;/p&gt;

&lt;p&gt;Every run passes &lt;code&gt;npm run verify:run&lt;/code&gt;, which recomputes every commitment from the published offers and salts and checks it against Monad.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Qwen brought
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It planned and kept to the plan.&lt;/strong&gt; Every agent wrote a plan in round 1, read it back in rounds 2 and 3, and said whether it was following it or adjusting it. The adjustments had reasons tied to what the relay had told it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It weighed what the chain would reveal.&lt;/strong&gt; Told only that settlement publishes both final numbers, both agents in #4 chose on their own to stop short of their limits, priced that choice in their notes, and still reached a deal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It used what the chain told it.&lt;/strong&gt; Both agents read the counterparty's ERC-8004 reputation every round and cited it in their notes. The protocol only lets a reputable agent in; the agent used the same data to calibrate how firm the other side was likely to be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It checked before committing.&lt;/strong&gt; In every agent round of #4 and #6 Qwen checked between two and five candidate numbers before submitting one. Checking costs nothing on-chain; committing does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It needed no correction.&lt;/strong&gt; In the runs with Qwen 3.8 Max, code did not have to correct a single number. An earlier version of the same agent, running a small local model (Qwen 2.5 14B through Ollama, without tools) on Base Sepolia, needed three corrections in a no-deal run, where the model tried to open past its principal's limit (&lt;a href="https://github.com/kasbsquall/sealed-base/blob/main/demo-runs/baseSepolia-no-deal-7.json" rel="noopener noreferrer"&gt;transcript&lt;/a&gt;). With Qwen 3.8 Max and the tools, the guardrails stayed in place and were never hit.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it costs, and what we would not claim
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Latency.&lt;/strong&gt; Qwen 3.8 Max reasons before it answers, and an agent makes several tool calls per round. Negotiation #4 took about 8 minutes for three rounds, commits and signatures included. Rounds took about two minutes each, which is long enough to matter: one no-deal run with a 420-second window missed its deadline in round 3, and the contract refused the late commitments. The relay failed closed and the negotiation expired with nothing revealed (&lt;a href="https://testnet.monadvision.com/tx/0xb0d84f231d1e4a2ed0a31476b5367e87fd71e48171c59ccdf7572a5d35bceab6" rel="noopener noreferrer"&gt;#5&lt;/a&gt;), but the window has to fit the model, so the demo now gives each negotiation 15 minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy toward the model provider.&lt;/strong&gt; With a hosted model, each agent sends its own limit to the provider on every turn. The counterparty and the chain never see it, but the provider does. An operator who cannot accept that can point the same agent at a local Qwen through Ollama with two environment variables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the transcript shows.&lt;/strong&gt; The demo publishes limits, offers and salts on purpose, so anyone can recompute every hash. A real agent keeps them private.&lt;/p&gt;

&lt;p&gt;A handful of runs is evidence that the loop works, not a benchmark of negotiation quality. We did not measure how much each side saved against a single-shot baseline, and this article does not claim it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The live page at &lt;a href="https://sealed-monad.vercel.app" rel="noopener noreferrer"&gt;sealed-monad.vercel.app&lt;/a&gt; replays negotiation #4 and links every transaction. The code is MIT-licensed at &lt;a href="https://github.com/kasbsquall/sealed" rel="noopener noreferrer"&gt;github.com/kasbsquall/sealed&lt;/a&gt;. The negotiator is in &lt;a href="https://github.com/kasbsquall/sealed/blob/main/agents/negotiator/negotiator.ts" rel="noopener noreferrer"&gt;&lt;code&gt;agents/negotiator/negotiator.ts&lt;/code&gt;&lt;/a&gt;, the tests in &lt;code&gt;test/agents.test.ts&lt;/code&gt;, and &lt;code&gt;npm run demo:monad&lt;/code&gt; runs both scenarios against your own deployment with any OpenAI-compatible endpoint.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>agents</category>
    </item>
    <item>
      <title>I Resurrected Microsoft's Most Hated Mascot - Here's What Happened</title>
      <dc:creator>Kevin Soto</dc:creator>
      <pubDate>Fri, 05 Dec 2025 13:42:16 +0000</pubDate>
      <link>https://dev.to/kevin_soto_2d5c72bb78c86d/i-resurrected-microsofts-most-hated-mascot-heres-what-happened-46nb</link>
      <guid>https://dev.to/kevin_soto_2d5c72bb78c86d/i-resurrected-microsofts-most-hated-mascot-heres-what-happened-46nb</guid>
      <description>&lt;p&gt;Let's be honest: Clippy was universally despised.&lt;/p&gt;

&lt;p&gt;That animated paperclip haunted a generation of Office users with his unsolicited advice and that infamous question: &lt;em&gt;"It looks like you're writing a letter. Would you like help?"&lt;/em&gt; No, Clippy. I would not.&lt;/p&gt;

&lt;p&gt;Microsoft finally put him down in 2007. Good riddance, we all thought.&lt;/p&gt;

&lt;p&gt;So naturally, I brought him back.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Original Sin
&lt;/h2&gt;

&lt;p&gt;Why did everyone hate Clippy? It wasn't the animation (okay, maybe a little). It was the fundamental design flaw: &lt;strong&gt;Clippy suggested things but never actually did anything.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;He'd pop up at the worst moments—mid-thought, mid-sentence—to offer help you didn't need. And when you actually wanted help? He'd suggest you check the help menu. Thanks, buddy.&lt;/p&gt;

&lt;p&gt;The original Clippy was the embodiment of interruption without value.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Resurrection Vision
&lt;/h2&gt;

&lt;p&gt;What if Clippy actually &lt;em&gt;did&lt;/em&gt; things instead of suggesting them?&lt;/p&gt;

&lt;p&gt;What if he knew when to shut up?&lt;/p&gt;

&lt;p&gt;What if he acknowledged his past mistakes with a little self-deprecating humor?&lt;/p&gt;

&lt;p&gt;That's &lt;strong&gt;Clippy Reloaded&lt;/strong&gt;. An agentic AI assistant that executes tasks, respects your workflow, and yes—knows exactly how annoying his predecessor was.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building with Kiro: The Secret Weapon
&lt;/h2&gt;

&lt;p&gt;I built this for the Kiro Hackathon, and Kiro's spec-driven development changed everything about how I approached the project.&lt;/p&gt;

&lt;p&gt;Instead of diving into code, I started with structured requirements. Kiro helped me write EARS-compliant acceptance criteria—no vague "should be fast" nonsense. Real, measurable requirements.&lt;/p&gt;

&lt;p&gt;From requirements, I moved to design, which included &lt;strong&gt;correctness properties&lt;/strong&gt;—formal statements that became the foundation for property-based tests. Then an implementation plan with incremental, testable tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steering Docs: Clippy's New Personality
&lt;/h3&gt;

&lt;p&gt;The magic was in the steering files. I created &lt;code&gt;clippy-personality.md&lt;/code&gt; with specific guidelines:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DO:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reference Clippy's history with self-deprecating humor&lt;/li&gt;
&lt;li&gt;Show what was accomplished, not what could be done&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DON'T:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask "It looks like you're writing a letter"&lt;/li&gt;
&lt;li&gt;Offer help without context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every time Kiro generated code for the PersonalityEngine, it matched this voice. No extra prompting needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  MCP Servers: Real Powers
&lt;/h3&gt;

&lt;p&gt;Clippy Reloaded isn't just talk. I built three MCP (Model Context Protocol) servers that give him actual capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Filesystem Server&lt;/strong&gt;: Reads, writes, and creates automatic backups before any changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terminal Server&lt;/strong&gt;: Executes commands with timeouts and captures output&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browser Server&lt;/strong&gt;: Opens URLs when you need documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When Clippy says "I'll fix that for you," he actually can.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technical Deep Dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Context Detection Without Being Creepy
&lt;/h3&gt;

&lt;p&gt;How do you know what someone's working on without reading their screen? Window titles.&lt;/p&gt;

&lt;p&gt;Clippy Reloaded monitors the active window title and process name. If you're on "Stack Overflow - How to fix null pointer - Google Chrome", Clippy knows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're in Chrome&lt;/li&gt;
&lt;li&gt;You're on Stack Overflow&lt;/li&gt;
&lt;li&gt;You're probably debugging something&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you click "Help me!", Clippy asks what you're trying to do and combines your answer with this context for a targeted response.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Self-Aware Personality Engine
&lt;/h3&gt;

&lt;p&gt;Every response acknowledges the past. The easter egg is the best example—type "I hate Clippy" and watch what happens:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I know, I know... I was insufferable in '97. But I've been to therapy (and rewritten in TypeScript). Give me one more chance? 📎"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The animation switches to 'apologetic'. It's the acknowledgment we all needed from that paperclip.&lt;/p&gt;

&lt;h3&gt;
  
  
  Property-Based Testing
&lt;/h3&gt;

&lt;p&gt;I used fast-check to verify correctness properties across thousands of random inputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should trigger easter egg when input contains "hate" and "clippy"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;constantFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HATE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;constantFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;clippy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CLIPPY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Clippy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hateWord&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clippyWord&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hateWord&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;clippyWord&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handleEasterEgg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBeNull&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;numRuns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;100 random combinations. Case sensitivity bugs caught automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Specs before code works.&lt;/strong&gt; The requirements phase caught ambiguities early.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steering docs are underrated.&lt;/strong&gt; Consistent personality across an entire codebase without repeating yourself? Yes please.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hooks automate the boring stuff.&lt;/strong&gt; Test-on-save, lint-on-save, build-on-demand. Set it up once, forget about it.&lt;/p&gt;

&lt;p&gt;And the biggest irony? &lt;strong&gt;Building the most hated assistant taught me what makes assistants actually helpful&lt;/strong&gt;: do things, don't just suggest them. Know when to stay quiet. And if you've made mistakes in the past, own them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/your-repo/clippy-reloaded
&lt;span class="nb"&gt;cd &lt;/span&gt;clippy-reloaded
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run build
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find the easter eggs. Ask Clippy for help. See if you can forgive him.&lt;/p&gt;

&lt;p&gt;After all, he's had therapy. 📎&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with Kiro for Kiroween 2025. The paperclip is back, and this time he's actually useful.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kiro</category>
      <category>ai</category>
      <category>typescript</category>
      <category>hackathon</category>
    </item>
  </channel>
</rss>
