<?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: dipak agrahari</title>
    <description>The latest articles on DEV Community by dipak agrahari (@sea_deep).</description>
    <link>https://dev.to/sea_deep</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%2F4154647%2F0778f593-6955-40d1-813f-6e00f76a40c5.png</url>
      <title>DEV Community: dipak agrahari</title>
      <link>https://dev.to/sea_deep</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sea_deep"/>
    <language>en</language>
    <item>
      <title>DEADNET: a murder mystery on a dead friend's old computer</title>
      <dc:creator>dipak agrahari</dc:creator>
      <pubDate>Thu, 29 Oct 2026 19:07:46 +0000</pubDate>
      <link>https://dev.to/sea_deep/her-last-message-was-to-you-you-never-answered-it-38e5</link>
      <guid>https://dev.to/sea_deep/her-last-message-was-to-you-you-never-answered-it-38e5</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26"&gt;Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;DEADNET&lt;/strong&gt; is a short murder mystery that takes place on a dead woman's computer.&lt;/p&gt;

&lt;p&gt;Nora Vale died in her room on Halloween night, 1999. The police called it an accident. You play Adam, her friend. Her neighbour Mara leaves you Nora's old computer with a note asking you to take a look before it's collected.&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%2Fdoyvazonrkqyp56aa4eb.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%2Fdoyvazonrkqyp56aa4eb.png" alt="Mara's note and Nora's computer" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The computer is a late-90s desktop with ordinary apps: Messenger, Mail, Photos, a Calendar, My Computer, a Trash Bin and a few games. You insert a recovery USB, hear it boot, and start opening things. The clues are in her conversations, emails and photo captions. You learn what happened by noticing where people's stories don't line up.&lt;/p&gt;

&lt;p&gt;The day before she died, Nora was making fun of Mara for cooking enough soup for twelve people. “she owns two bowls adam.” Her calendar still has dinner at Mara's in it. Bring bread. Stay for once.&lt;/p&gt;

&lt;p&gt;Her last conversation in Messenger is with you. You didn't answer it in time.&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%2Fygjixm9lgem8t8k2duu9.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%2Fygjixm9lgem8t8k2duu9.png" alt="Nora's Messenger" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then her account comes back online, in a window called &lt;strong&gt;Unknown Signal&lt;/strong&gt;. You can talk to her and show her what you've found. She's played by an open-weight model, and she only knows what you've shown her, so she can't just tell you the answer.&lt;/p&gt;

&lt;p&gt;When you think you've worked it out, you open the &lt;strong&gt;Casebook&lt;/strong&gt; on your recovery USB and answer three questions: who came into the room, why, and how they got in. A wrong answer doesn't end the game. It just tells you something doesn't fit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://room317.onrender.com" rel="noopener noreferrer"&gt;Play it in your browser&lt;/a&gt;&lt;/strong&gt;. It takes about 15 minutes. Each visitor gets their own copy of the case, and progress saves automatically. If nobody has played for a while, the first load can take up to a minute while the server starts.&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%2Fwuh5odn178bqw45znm7j.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%2Fwuh5odn178bqw45znm7j.png" alt="The desktop" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  One thread to pull
&lt;/h3&gt;

&lt;p&gt;Start with &lt;strong&gt;Mail → “Home, somehow.”&lt;/strong&gt;, sent by Len at &lt;strong&gt;03:07&lt;/strong&gt; on Halloween morning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Made the 2:58 by about six seconds. Ticket machine’s broken, so the driver wrote one out by hand. Kept it. First thing I’ve won all week.&lt;/p&gt;

&lt;p&gt;I’m home. It’s raining through my kitchen window again. Tell Mara I’ll look at her heater Monday.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It sounds like someone getting home from a miserable shift. Then you read management's statement, which puts Len on the third floor at &lt;strong&gt;03:17&lt;/strong&gt;. Both accounts can't be right.&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%2Ffwvm3l7nu1fisyjr6s3p.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%2Ffwvm3l7nu1fisyjr6s3p.png" alt="Len's email was sent at 03:07, before management says he was upstairs" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Save the email to your USB Casebook, then attach it in Unknown Signal.&lt;/strong&gt; You can ask Nora what she remembers about Len leaving. Her next reply is generated from the conversation and the evidence she's actually seen; opening an email on your own doesn't give her that knowledge.&lt;/p&gt;

&lt;p&gt;The next connection is yours to make. A photo caption records someone borrowing an office spare. Nora's last chat explains what she had found and who wanted to speak to her. Together, the records give you a timeline, a way into the room, and a reason for the visit.&lt;/p&gt;

&lt;p&gt;In the Casebook, choose a person, a motive and a way in. If you name the wrong person, the game sends you back to the contradiction:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;that doesn’t fit what you found. who asked to come to my room? and who had already gone home?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can reopen the records and revise your theory without restarting. You don't need to win a mini-game to finish; those are simply games Nora kept on her computer.&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%2Fpvebxg19n7dov19rcw86.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%2Fpvebxg19n7dov19rcw86.png" alt="The Casebook after saving three personal items" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/sea-deep" rel="noopener noreferrer"&gt;
        sea-deep
      &lt;/a&gt; / &lt;a href="https://github.com/sea-deep/deadnet" rel="noopener noreferrer"&gt;
        deadnet
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A murder mystery on a dead friend's 1999 computer. Investigate her messages, confront an AI ghost, and solve Room 317.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;DEADNET — Room 317&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Mara gives you her dead friend’s computer. You are Adam Moore. The last message Nora sent was to you.&lt;/p&gt;
&lt;p&gt;Insert your recovery USB, turn on the computer, and look through Nora’s Messenger, mail, photos and calendar. Get to know the person who lived here. When her account signs in again, show her what you find. Her memory is uncertain; the things she left behind can contradict it.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/sea-deep/deadnet/docs/evidence/revamp-messenger-desktop.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fsea-deep%2Fdeadnet%2FHEAD%2Fdocs%2Fevidence%2Frevamp-messenger-desktop.png" alt="Nora’s Messenger"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://room317.onrender.com" rel="nofollow noopener noreferrer"&gt;Play online&lt;/a&gt; · &lt;a href="https://dev.to/sea_deep/her-last-message-was-to-you-you-never-answered-it-38e5" rel="nofollow"&gt;The story behind it (DEV)&lt;/a&gt; · &lt;a href="https://github.com/sea-deep/deadnet" rel="noopener noreferrer"&gt;Source&lt;/a&gt; · &lt;a href="https://sea-deep.github.io/deadnet/" rel="nofollow noopener noreferrer"&gt;Scripted static exhibition&lt;/a&gt; · &lt;a href="https://github.com/sea-deep/deadnet/docs/CREDITS.md" rel="noopener noreferrer"&gt;Credits and licenses&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Run&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Node 22.13+ and npm:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm ci
cp .env.example .env
npm run dev&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Open &lt;a href="http://127.0.0.1:3000" rel="nofollow noopener noreferrer"&gt;http://127.0.0.1:3000&lt;/a&gt;. Insert the USB, then power on. The computer fills the browser; the tray also offers browser fullscreen. Windows drag, resize, minimize and maximize. On phones, a single tap opens an app and each window fills the available space.&lt;/p&gt;
&lt;p&gt;For live dialogue, add &lt;code&gt;OPENROUTER_API_KEY&lt;/code&gt; to the…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/sea-deep/deadnet" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;MIT licensed. Borrowed code, fonts, images and sounds are credited in &lt;a href="https://github.com/sea-deep/deadnet/blob/main/docs/CREDITS.md" rel="noopener noreferrer"&gt;CREDITS&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The desktop is React with &lt;a href="https://github.com/jdan/98.css" rel="noopener noreferrer"&gt;98.css&lt;/a&gt;. A small Node server stores each player's case and talks to the model, so no API keys reach the browser.&lt;/p&gt;

&lt;p&gt;The main design decision was splitting what's fixed from what's live:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fixed:&lt;/strong&gt; the evidence and the solution. Every player gets the same messages, timestamps and photos, and the same answer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live:&lt;/strong&gt; the characters. The model decides what Nora remembers, how sure she is and what she asks you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I did this because language models are good at sounding unsure and bad at keeping facts straight. If the model could change the evidence, it could also accidentally solve the case for you, or make it unsolvable.&lt;/p&gt;

&lt;p&gt;So each character only sees what they've actually been shown. Replies come back in a fixed format and get checked before they're saved. A reply that cites an invented or unwitnessed evidence ID is rejected. Dialogue can still be mistaken, but it cannot create a collectable clue, change the evidence or decide whether your theory wins.&lt;/p&gt;

&lt;h3&gt;
  
  
  The clue Nora shouldn't know yet
&lt;/h3&gt;

&lt;p&gt;One bug made that distinction concrete. The photograph looked harmless in the UI, but its model-facing description also explained the motive from a different conversation. Show Nora the key photo, and the prompt had already handed her an answer you hadn't discovered together.&lt;/p&gt;

&lt;p&gt;The fix was in the information I gave her:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before:&lt;/strong&gt; the photograph's description established access &lt;strong&gt;and&lt;/strong&gt; explained why someone wanted to silence Nora.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After:&lt;/strong&gt; the photograph establishes access. The motive has to come from the separate conversation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also removed a later memory hint that named the key's owner before Nora had seen the photo caption. The tests now check all eight combinations of the three items she can have seen. Showing her one item must not quietly give her the other two.&lt;/p&gt;

&lt;p&gt;That changed how I thought about the ghost. Her uncertainty needs a reason. She is piecing the night together with you, and each thing you show her changes what she can say.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The model.&lt;/strong&gt; The browser version now uses Gemma 4 31B through OpenRouter, pinned to &lt;code&gt;google/gemma-4-31b-it:free&lt;/code&gt;. It runs on a hosted provider, not inside your browser. The local option is Gemma 4 E2B through Ollama. Both use the same character prompts and evidence rules; System Monitor records the actual model and request trace.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making it feel like someone's computer
&lt;/h3&gt;

&lt;p&gt;My first version was a file hunt: log files, a damaged backup you had to unlock, and at one point you had to play mini-games to recover it. It worked, but it felt like an escape room rather than someone's computer. I rebuilt it around chats with friends, emails, a photo album and a calendar.&lt;/p&gt;

&lt;p&gt;That gave the ordinary messages a job, too. An earlier chat has Nora complaining that Adam's bat game ate her evening when she was supposed to be packing. She says she's finally moving in November, somewhere with a window that opens. Later, you're reading that conversation knowing she never got to move.&lt;/p&gt;

&lt;p&gt;The same desktop can tell you she was funny, she was planning a future, and somebody's account of her last night is wrong. I wanted the player to notice all three.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hosting.&lt;/strong&gt; It runs on Render. Each browser gets its own private case, so players never see each other's conversations. The game autosaves, and you can save to a file, load it back or start over from the Start menu. If the free model is busy, it tells you and lets you explicitly switch to labelled scripted replies. It never silently replaces a failed live response. Requests are capped at eight per visitor and thirty globally per day, with burst limits and cooldowns; resetting the case doesn't reset the allowance.&lt;/p&gt;

&lt;p&gt;There's also one voice clip: Nora's last voicemail, recorded with ElevenLabs' premade Lily voice, hushed and hurried. She warns Adam not to come through the lobby and says Len wasn't in the building. It's something to compare with the email and management's statement, rather than a narrator explaining the solution.&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%2Flid654x8llwi8aed5880.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%2Flid654x8llwi8aed5880.png" alt="Nora's last call, in Mail" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The clip is cached, so replaying it doesn't generate more audio. There's a transcript next to it. Voice, model, transcript and delivery settings identify the cache entry; concurrent playback requests share a single render. The existing &lt;a href="https://github.com/sea-deep/deadnet/blob/main/docs/evidence/elevenlabs-case.json" rel="noopener noreferrer"&gt;render record&lt;/a&gt; documents one generation taking 1.927 seconds; replay used the saved audio.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Following Nora's reply with Sentry.&lt;/strong&gt; After finding the premature clue, I wanted to see the boundary around a whole turn: which evidence is available, when the model runs, whether the reply passes validation, and what gets saved. Each turn now has a Sentry agent trace with those steps underneath it. Live model spans record the provider, model and token counts. Players' messages, prompts and replies stay out of the telemetry.&lt;/p&gt;

&lt;p&gt;One verification gives Nora an invalid reply that tries to contact Mara from the private signal. The validator rejects it and the root trace is marked rejected; Nora's private message never reaches another resident. Here is the actual Sentry trace, captured in Safari:&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%2Fgggde8462kbbuj25d0dq.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%2Fgggde8462kbbuj25d0dq.png" alt="Sentry's Agent Activity view: the private reply is rejected at validate_reply, whose status is error" width="799" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This capture uses a deterministic fixture in Sentry's verification environment. It checks the guard and the tracing, rather than measuring hosted Gemma's speed. &lt;a href="https://github.com/sea-deep/deadnet/tree/main/docs/evidence/sentry" rel="noopener noreferrer"&gt;Trace record and screenshots&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checking the case.&lt;/strong&gt; There are 40 Node tests for knowledge boundaries, invented evidence, wrong theories, the ending, saves, request limits, the audio cache and telemetry privacy. Another 38 browser scenarios cover desktop and phone layouts, including a complete investigation with a wrong accusation and recovery. They use fixtures, so these checks don't spend model or voice credits. &lt;a href="https://github.com/sea-deep/deadnet/blob/main/docs/VERIFICATION-REVAMP.md" rel="noopener noreferrer"&gt;Verification&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/sea-deep/deadnet/blob/main/.github/workflows/checks.yml" rel="noopener noreferrer"&gt;GitHub Actions checks&lt;/a&gt; run the tests, typecheck, both builds and the browser scenarios on every push. A &lt;a href="https://github.com/sea-deep/deadnet/blob/main/.github/workflows/pages.yml" rel="noopener noreferrer"&gt;second workflow&lt;/a&gt; deploys the scripted exhibition to GitHub Pages. That makes a broken desktop or ending a failing build, rather than something a judge has to find.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It keeps the game playable.&lt;/strong&gt; The story is about a computer that keeps answering after its owner is gone. With open-weight models, Nora doesn't depend on one company keeping one model available. The prompts and rules are in the repo, and any compatible open model can play her.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It can run privately.&lt;/strong&gt; You can run the whole thing locally with Gemma through Ollama, so your conversations never leave your machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's free to play.&lt;/strong&gt; The hosted version uses a free Gemma route with a small daily request budget to protect the account. Running Gemma locally removes that shared API allowance; there is no per-message provider charge.&lt;/p&gt;

&lt;p&gt;The most useful lesson was learning where to put the model. It brings a voice to the conversation; the code keeps track of what happened and what each character has seen. That division is small enough to inspect, test and change with another open model.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Spirit of It
&lt;/h2&gt;

&lt;p&gt;Mara keeps writing to Nora after she's gone. There's a scarf on her chair, a dinner in the calendar, and a deleted letter in which Nora almost says yes to a new flat. Before you have a suspect, you have the shape of a life that was supposed to continue.&lt;/p&gt;

&lt;p&gt;Halloween is the night that life stops. On November 2, you're sitting at the computer with everything she left behind. You can put a name on what happened. You can't get back to 03:14 and answer her in time.&lt;/p&gt;

&lt;p&gt;The ending, if you'd like to see where the investigation leads&lt;/p&gt;

&lt;p&gt;After a supported report, Mara writes: “i printed her name properly this time. NORA VALE. not ‘the woman in 317’.” Nora hears the rain again, and the line goes quiet.&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%2Fhfrrxerpi2116pbqvjk3.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%2Fhfrrxerpi2116pbqvjk3.png" alt="The actual ending after the player submits a supported report" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;I used Entire to capture the actual Codex session behind the evidence fix. The checkpoint links the conversation and tool work to &lt;a href="https://github.com/sea-deep/deadnet/commit/b98c419a3383c6fe680520ff4237ed478425360d" rel="noopener noreferrer"&gt;the implementation commit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sea-deep/deadnet/blob/main/docs/evidence/entire-session.md" rel="noopener noreferrer"&gt;The session excerpt&lt;/a&gt; includes the edit that removed the premature clue and the test results that followed. It was exported from checkpoint &lt;code&gt;01M682MCRY0YFDMAADPPK7ETN8&lt;/code&gt;; private setup and internal reasoning are omitted. The native checkpoint stays local, and the public excerpt can be read without an account. &lt;a href="https://github.com/sea-deep/deadnet/blob/main/docs/ENTIRE.md" rel="noopener noreferrer"&gt;Entire setup and capture details&lt;/a&gt;.&lt;/p&gt;


&lt;div class="ltag-agent-session"&gt;
  &lt;div class="agent-session-header"&gt;
    
    &lt;span class="agent-session-tool-icon-badge" title="Codex"&gt;
&lt;/span&gt;
    &lt;span class="agent-session-title"&gt;DEADNET: the clue Nora should not know yet&lt;/span&gt;
  &lt;/div&gt;

  &lt;div class="agent-session-scroll"&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;make sure to integrate the entire sponsor category hahaha since i have used codex u should be able to do it all yourself&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;I’ll integrate Entire and check that it captures a real Codex session linked to a commit. I’ll also review the new brief and update the submission materials, without spending AI or voice credits.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;The README already describes the murder mystery. The main gap is that the hosted app uses a generic free-model router, which doesn’t guarantee Gemma. I’ll pin it to a free Gemma route and add tests for the evidence boundaries.&lt;/p&gt;

&lt;p&gt;I’m using the challenge rules skills to check the submission requirements. Entire’s category specifically asks for agent work shared in the write-up, so I’ll produce a linked session alongside the setup.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Entire is installed and configured for Codex. I’ll attach this existing session to the changes using Entire’s supported command, since the session started before its hooks were installed. Raw transcripts will stay local; the submission will link to a reviewed excerpt.&lt;/p&gt;

&lt;p&gt;I also found a spoiler leak: the spare-key evidence described the motive even before Nora had seen the final chat. I’m separating those facts and adding a regression test.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-applypatch"&gt;apply_patch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;*** Begin Patch
*** Update File: server/seed.ts
@@
-    fact: "Nora’s October...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight diff"&gt;&lt;code&gt;*** Begin Patch
*** Update File: server/seed.ts
&lt;span class="p"&gt;@@
-    fact: "Nora’s October 28 photo caption says she borrowed Owen Keene’s office spare to get back into her room after locking herself out. The pictured brass key and the caption establish that the manager had a way into her room. Combined with Nora’s final conversation, this establishes Owen’s access and motive to silence her about the forged fire inspections. The image alone does not identify an owner; the ownership is in Nora’s caption.",
+    fact: "Nora’s October 28 photo caption says she borrowed Owen Keene’s office spare to get back into her room after locking herself out. The pictured brass key and the caption establish that the manager had a way into her room. The image alone does not identify an owner; the ownership is in Nora’s caption. This photograph does not establish a motive or what happened on Halloween night.",
*** Update File: server/model.ts
@@&lt;/span&gt;
&lt;span class="gd"&gt;-                      "A brass key scraping your desk. You did not open the door. Once shown the photo caption, you recognize the spare from Owen’s office, not Len’s red staff key.",
&lt;/span&gt;&lt;span class="gi"&gt;+                      "A key scraping your desk. You did not open the door. You cannot place its owner or connect it to a photograph you have not been shown.",
&lt;/span&gt;*** End Patch&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight diff"&gt;&lt;code&gt;{}&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;The 39 offline tests pass, including the new evidence checks and pinned Gemma request. I’ve corrected the GitHub description and drafted the stronger DEV entry with a complete investigation walkthrough, voicemail explanation and Entire section. The full desktop and phone checks are still running.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-execcommand"&gt;exec_command&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;npm run test:e2e&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ npm run test:e2e&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;38 passed (1.6m)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-execcommand"&gt;exec_command&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;npm test&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ npm test&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;✔ every Nora evidence subset scopes both prompt records and decoding to witnessed items (1.29525ms)
✔ a late ungrounded memory does not reveal whose key Nora heard (0.715958ms)
✔ invented prose cannot create case evidence, change the solution, or satisfy report prerequisites (0.40825ms)
✔ hosted default is a pinned free Gemma route, with no router or paid fallback (13.893458ms)
ℹ tests 39
ℹ pass 39
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;All 38 desktop and phone scenarios pass, including finding evidence, showing it to Nora, revising a wrong theory and reaching the ending. Both builds pass too.&lt;/p&gt;

&lt;p&gt;I’m now linking the real Codex session to the implementation commit and preparing the public excerpt for the Entire category.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class="agent-session-footer"&gt;
    &lt;span class="agent-session-meta"&gt;
        9 of 9 messages
    &lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Render:&lt;/strong&gt; the game is hosted on Render as a web service, with a private case per visitor, automatic saving, and API keys kept on the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Gemma drives the characters through the pinned OpenRouter route online, or through Ollama for private local play.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of ElevenLabs:&lt;/strong&gt; Nora's last voicemail, an important clue, is an ElevenLabs recording, cached and shown with a transcript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Entire:&lt;/strong&gt; the actual Codex development session is linked to its commit, with the debugging edit and test output shared above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Sentry Agent Tracing:&lt;/strong&gt; evidence scoping, model execution, reply validation and persistence are traced together; the verification capture shows a rejected private reply, and tests check that telemetry excludes conversation text and credentials.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of GitHub Copilot:&lt;/strong&gt; entered through the challenge's GitHub Actions route. The existing workflows test and build the game, check the complete browser investigation, and deploy the scripted exhibition.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All characters and events are fictional. &lt;em&gt;I used AI coding assistants while building DEADNET and while writing this post.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The answer was already in another thread, so I built ThreadSherpa</title>
      <dc:creator>dipak agrahari</dc:creator>
      <pubDate>Fri, 23 Oct 2026 18:10:54 +0000</pubDate>
      <link>https://dev.to/sea_deep/the-answer-was-already-in-another-thread-so-i-built-threadsherpa-khm</link>
      <guid>https://dev.to/sea_deep/the-answer-was-already-in-another-thread-so-i-built-threadsherpa-khm</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;I got the idea from the MLH Discord.&lt;/p&gt;

&lt;p&gt;People kept asking about account names, missing offer codes and student benefits. Different people, same questions. The useful answer was usually already there, buried in another thread, and a moderator had to go find it and type it out again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ThreadSherpa&lt;/strong&gt; is a Discord support bot that remembers the answer so the moderator doesn't have to. A moderator replies normally, right-clicks their message and picks &lt;strong&gt;Apps → Save this answer&lt;/strong&gt;. That one click is the approval. The next time someone asks the same thing in different words, ThreadSherpa writes a fresh reply for that person from the saved facts and links back to the original.&lt;/p&gt;

&lt;p&gt;The part I care about most: &lt;strong&gt;when the saved answers don't cover a question, ThreadSherpa says nothing.&lt;/strong&gt; No "I'm not sure, maybe try…", no guessing. The question goes into a quiet moderator queue instead. A small open model is only as good as what you give it, so ThreadSherpa only gives it facts a human already approved, and stays out of the way otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://threadsherpa.onrender.com/try/" rel="noopener noreferrer"&gt;Try it in your browser&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://threadsherpa.onrender.com/" rel="noopener noreferrer"&gt;Website and walkthrough&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://github.com/sea-deep/threadsherpa/blob/main/docs/SETUP.md" rel="noopener noreferrer"&gt;Setup guide&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;/try/&lt;/code&gt; sandbox is a fictional community where you can save a moderator's reply, ask a new question and watch it answered, all in your browser with no Discord server needed.&lt;/p&gt;

&lt;p&gt;Below is a real run in my test server, with separate moderator and participant accounts, on a Minecraft support question: which version can join the server?&lt;/p&gt;

&lt;p&gt;The moderator answers and saves the reply:&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%2Fdaifqtjkyeuw2z5iiyor.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%2Fdaifqtjkyeuw2z5iiyor.png" alt="The moderator answers a Minecraft version question and receives a private Saved confirmation." width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Later, a participant describes the same problem in completely different words, an "Outdated client" error. ThreadSherpa answers on its own, tells them which version to pick, and links to the moderator's original guidance:&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%2F3y9hm0gcqkdcm2d9itw9.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%2F3y9hm0gcqkdcm2d9itw9.png" alt="A participant reports an Outdated client error. ThreadSherpa explains which version to select and links to the original answer." width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paper Instruments' Ultramarine wrote this reply and MongoDB Atlas stored the saved answer. The exact same flow also runs fully local on Gemma 4 through Ollama.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/sea-deep" rel="noopener noreferrer"&gt;
        sea-deep
      &lt;/a&gt; / &lt;a href="https://github.com/sea-deep/threadsherpa" rel="noopener noreferrer"&gt;
        threadsherpa
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A Discord support bot that saves moderator answers and writes short, sourced replies for repeat questions.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Built solo, Apache-2.0 licensed. There's also a &lt;a href="https://gitlab.com/wdipak/threadsherpa" rel="noopener noreferrer"&gt;GitLab mirror&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;TypeScript and discord.js. Saved answers, versions, support cases and evidence live in MongoDB Atlas. Models plug in through one provider interface, with two first-class options: &lt;strong&gt;Gemma 4 (&lt;code&gt;gemma4:e4b-it-qat&lt;/code&gt;) running locally through Ollama&lt;/strong&gt;, or &lt;strong&gt;Paper Instruments' Ultramarine&lt;/strong&gt; through its API. &lt;strong&gt;EmbeddingGemma&lt;/strong&gt; handles embeddings locally either way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Moderator saves a reply
  → keep their exact wording, check for duplicates, store it in Atlas

New forum question + thread context
  → retrieve this server's current answers (exact, keyword and vector match)
  → give only that evidence to the model
  → check every citation and link in the draft
  → reply in the thread, or queue it quietly for a moderator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Retrieval combines exact matching, keyword search and embeddings, ranked with Atlas Vector Search. Every server has its own memory, so one community's answers never leak into another's.&lt;/p&gt;

&lt;h3&gt;
  
  
  Saving keeps the human's words; answering is a separate job
&lt;/h3&gt;

&lt;p&gt;My first version stuffed titles, review details, versions and labels around a two-line answer, and pasted old messages back almost verbatim. It felt like a filing cabinet, not a helper.&lt;/p&gt;

&lt;p&gt;So I split the two jobs. Saving stores the moderator's wording exactly as written. In the &lt;a href="https://github.com/sea-deep/threadsherpa/blob/main/src/memory/learner.ts" rel="noopener noreferrer"&gt;learning pipeline&lt;/a&gt; that's simply:&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="nx"&gt;canonical_answer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;adminMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generation happens later, with the new question and its thread in front of the model, so each reply fits the person asking. Saving the same answer twice reuses the existing entry.&lt;/p&gt;

&lt;h3&gt;
  
  
  Staying quiet is a feature
&lt;/h3&gt;

&lt;p&gt;During testing the bot posted "I couldn't check this. A moderator can help." under a question a moderator had already answered. It added noise and helped nobody.&lt;/p&gt;

&lt;p&gt;Now a queued result sends nothing. The &lt;a href="https://github.com/sea-deep/threadsherpa/blob/main/src/bot/handlers/router.ts" rel="noopener noreferrer"&gt;Discord handler&lt;/a&gt; only posts when it has something useful:&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="k"&gt;if &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;policyResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;queue&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;case_id&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;A few other guardrails sit around that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Narrow answers ask first.&lt;/strong&gt; If a saved answer only applies under certain conditions, ThreadSherpa asks a clarifying question instead of guessing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Account actions go to humans.&lt;/strong&gt; Sensitive requests are routed to moderators, never answered by the model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No open web search.&lt;/strong&gt; Besides saved answers, the bot can only read documentation URLs a moderator explicitly adds with &lt;code&gt;/sources&lt;/code&gt;, fetched through an SSRF-safe fetcher.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  It learns from how the conversation ends
&lt;/h3&gt;

&lt;p&gt;Each reply comes with &lt;strong&gt;Solved&lt;/strong&gt; and &lt;strong&gt;Need help&lt;/strong&gt; buttons, and the bot also reads plain follow-ups. "That worked" closes the case. "That didn't help" hands it to a moderator and adds the failed advice to the context, so the bot doesn't keep suggesting the same fix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Moderators stay in control
&lt;/h3&gt;

&lt;p&gt;Three autonomy modes, picked in &lt;code&gt;/setup&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quiet:&lt;/strong&gt; record new posts, no replies. Good for a trial week.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On request:&lt;/strong&gt; reply only to &lt;code&gt;/ask&lt;/code&gt; and follow-ups.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic:&lt;/strong&gt; answer new support questions on its own.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And a set of moderator tools:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/memory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Private panel to search, add, edit, expire or remove saved answers, and import FAQs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/teach&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Save knowledge when there's no existing message to save&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/answers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Find or remove saved guidance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/queue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;See waiting questions, grouped so repeated gaps stand out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/sources&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Manage the documentation URLs the bot is allowed to read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/stats&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Questions, confirmed solves and handoffs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/ask&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ask explicitly instead of waiting for an automatic reply&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;/memory&lt;/code&gt; panel is visible only to the moderator using 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%2Fivjigq43fcx91u1jjxan.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%2Fivjigq43fcx91u1jjxan.png" alt="The private memory panel shows the saved Minecraft answer, its version, and controls to add or import answers." width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Already have a FAQ? &lt;strong&gt;Import FAQs&lt;/strong&gt; takes pasted Markdown, shows a preview, and saves it in one go, skipping duplicates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Can I submit by myself?&lt;/span&gt;
Yes, solo projects are fine.

&lt;span class="gu"&gt;## Do I need a video?&lt;/span&gt;
A video is optional.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Answers can have a source, conditions and an expiry date. Expired answers stay visible in the panel for review but stop being used in replies, so last month's deadline never gets quoted as this month's.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/queue&lt;/code&gt; is also where the lazy loop closes: if the same unanswered question shows up five times, the moderator sees it grouped together, answers once, saves it, and it's handled from then on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;140 automated tests&lt;/strong&gt; cover routing, approval, duplicate saves, expiry, source checks, FAQ import and panel permissions, and run on every push through &lt;a href="https://github.com/sea-deep/threadsherpa/blob/main/.github/workflows/checks.yml" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;12 support scenarios&lt;/strong&gt; (paraphrases, a different event with a similar name, expired guidance and a correction) passed on both &lt;strong&gt;local Gemma&lt;/strong&gt; and &lt;strong&gt;Ultramarine&lt;/strong&gt;. Reproduce them with &lt;code&gt;npm run eval:local&lt;/code&gt; or &lt;code&gt;npm run eval:paper&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atlas&lt;/strong&gt; was checked for persistence across processes, real vector queries and per-server isolation with &lt;code&gt;npm run verify:atlas&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run demo&lt;/code&gt; runs the whole flow on fixtures, with no Discord and no paid inference.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Ultramarine eval made &lt;strong&gt;10 generation calls (5,408 input and 1,109 output tokens) for about $0.0014&lt;/strong&gt; at the 23 October rates, roughly a hundredth of a cent per generated reply.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tracing every answer with Sentry
&lt;/h3&gt;

&lt;p&gt;Every answer runs inside a Sentry agent trace. Each &lt;code&gt;support.answer&lt;/code&gt; agent span contains the &lt;code&gt;tool.search_knowledge&lt;/code&gt; tool call that finds the saved answers, then the &lt;code&gt;GroundedAnswerDraft&lt;/code&gt; model call and the HTTP request behind it. Embedding calls get their own spans too. Model spans record the model name and input and output token counts; message text and prompts are never sent, only numbers.&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%2Fitb8kilpq6omjfz0z8s1.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%2Fitb8kilpq6omjfz0z8s1.png" alt="Sentry trace waterfall: support.answer agent spans, each with a tool.search_knowledge tool call and a GroundedAnswerDraft model request to Paper Instruments' API." width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On a traced Ultramarine eval run, each reply used &lt;strong&gt;506–588 input and 50–176 output tokens&lt;/strong&gt;, and the model call took &lt;strong&gt;1.1–3.2 seconds&lt;/strong&gt;. Knowledge search took under a millisecond and local embeddings a few milliseconds, so almost all of the answer time is the model writing. The trace showed something else useful: some questions the bot shouldn't answer stop right after the search, without calling the model at all, so those declines cost no tokens.&lt;/p&gt;

&lt;p&gt;Set &lt;code&gt;SENTRY_DSN&lt;/code&gt; and both the bot and &lt;code&gt;npm run eval&lt;/code&gt; send these traces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A community's support knowledge stays with the community.&lt;/strong&gt; Moderator answers often touch account names, offer codes and other things members don't want shared. With Gemma running through Ollama, generation and embeddings happen on the machine the operator controls, and no third-party model provider ever sees them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's cheap enough for volunteers.&lt;/strong&gt; Most Discord communities are run by volunteers, and a support bot with a big bill is a bot nobody keeps switched on. On local Gemma, one more answer costs nothing extra. On Ultramarine, the whole eval run cost about a seventh of a cent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Moderators can see and change everything.&lt;/strong&gt; The prompts, retrieval and policy rules are all in the repo. If a community wants a stricter bot, a friendlier tone or a different model, they change a config value or a prompt, not a vendor contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open models make the choice the community's.&lt;/strong&gt; Because both Gemma and Ultramarine are open models (Paper has announced Ultramarine's weights), a community isn't locked in. Run Gemma on a spare laptop for full privacy, use Ultramarine through the API for stronger writing at a tiny cost, or self-host Ultramarine once its weights are out. I swapped between the two without touching any of the saving, retrieval or Discord code. The community owns its knowledge and picks where its model runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;Before: a moderator sees a question, remembers answering it last week, scrolls through old threads, finds it, and types it out again. Then does the same thing tomorrow.&lt;/p&gt;

&lt;p&gt;After: the moderator answers once and clicks &lt;strong&gt;Save this answer&lt;/strong&gt;. Every future version of that question, in whatever words, gets a tailored reply with a source, while the moderator is asleep. Questions the bot can't answer wait quietly in &lt;code&gt;/queue&lt;/code&gt; until someone has time.&lt;/p&gt;

&lt;p&gt;That's the sloth approach: do the work once, properly, and let it keep paying off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Gemma 4 through Ollama is the default reply model and handles duplicate comparisons, with EmbeddingGemma for local retrieval embeddings. It passed the full scenario suite locally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of MongoDB Atlas:&lt;/strong&gt; Atlas holds saved answers, versions, cases and evidence, scoped per server, with Atlas Vector Search ranking retrieval candidates. Persistence and real vector queries are verified by &lt;code&gt;npm run verify:atlas&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Ultramarine:&lt;/strong&gt; Ultramarine wrote the replies in the Discord demo above, working only from the moderator-approved evidence, and passed the full scenario suite. The eval run cost about $0.0014 for 10 generations, broken down above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Render:&lt;/strong&gt; Render hosts ThreadSherpa's front end at &lt;a href="https://threadsherpa.onrender.com/" rel="noopener noreferrer"&gt;threadsherpa.onrender.com&lt;/a&gt;, including the interactive &lt;a href="https://threadsherpa.onrender.com/try/" rel="noopener noreferrer"&gt;&lt;code&gt;/try/&lt;/code&gt; sandbox&lt;/a&gt; where anyone can run the save → ask → reply loop, deployed from the repo's &lt;code&gt;render.yaml&lt;/code&gt; Blueprint. The repo also ships a &lt;a href="https://github.com/sea-deep/threadsherpa/blob/main/deploy/render-worker.yaml" rel="noopener noreferrer"&gt;background-worker Blueprint&lt;/a&gt; that runs the Discord bot itself on Render, preconfigured for Ultramarine or a Gemma endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Sentry Agent Tracing:&lt;/strong&gt; every answer is a Sentry agent trace with tool, model and HTTP spans, plus token counts and latency per model call. The trace screenshot and the numbers are in the tracing section above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of GitHub Copilot:&lt;/strong&gt; the &lt;a href="https://github.com/sea-deep/threadsherpa/blob/main/.github/workflows/checks.yml" rel="noopener noreferrer"&gt;Checks workflow&lt;/a&gt; in GitHub Actions type-checks, tests and builds the bot, verifies the fixture flow, and checks and builds the website on every push.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;I used AI coding assistants while building ThreadSherpa and while writing this post.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>GitQuest: Visual Interactive Git DAG Simulator &amp; Adventure Game</title>
      <dc:creator>dipak agrahari</dc:creator>
      <pubDate>Mon, 12 Oct 2026 20:27:53 +0000</pubDate>
      <link>https://dev.to/sea_deep/gitquest-visual-interactive-git-github-dag-simulator-228n</link>
      <guid>https://dev.to/sea_deep/gitquest-visual-interactive-git-github-dag-simulator-228n</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Git can be overwhelming when you're just starting out. You run commands like &lt;code&gt;git commit&lt;/code&gt;, &lt;code&gt;git branch&lt;/code&gt;, or &lt;code&gt;git merge&lt;/code&gt;, but what actually happens behind the scenes remains invisible. What is &lt;code&gt;HEAD&lt;/code&gt;? How do branches point to commits? Why do merge conflicts happen?&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;GitQuest&lt;/strong&gt;, an interactive visual simulator and puzzle adventure that teaches version control from absolute zero.&lt;/p&gt;

&lt;p&gt;Instead of throwing users into an abstract command line, GitQuest pairs a live Git repository directly with a tactile 2D arcade world. Players configure files, stage changes (&lt;code&gt;git add&lt;/code&gt;), save checkpoints (&lt;code&gt;git commit&lt;/code&gt;), create branches, resolve 3-way merge conflicts, and push to remotes. Every single operation immediately updates the live commit graph, file staging areas, &lt;code&gt;.git&lt;/code&gt; internals, and physically powers conduits and bridges for a runner to reach the goal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Who Would Pay For It?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Engineering Bootcamps &amp;amp; CS Universities:&lt;/strong&gt; Onboarding cohorts onto Git is notoriously painful and consumes hours of mentor time. A structured, self-paced visual simulator replaces static slide decks with interactive verification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer Training &amp;amp; Corporate Onboarding:&lt;/strong&gt; Engineering teams onboarding junior developers or career switchers can license interactive sandboxes to evaluate practical Git proficiency without breaking company repos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Individual Developers (Freemium/Pro):&lt;/strong&gt; Self-paced learners who want guided interactive mastery of advanced Git scenarios (interactive rebasing, cherry-picking, complex merge conflict triage).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Play Live in Browser:&lt;/strong&gt; &lt;strong&gt;&lt;a href="https://gitquest-five.vercel.app" rel="noopener noreferrer"&gt;https://gitquest-five.vercel.app&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Run:&lt;/strong&gt; Run GitQuest locally in seconds:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://gitlab.com/wdipak/gitquest.git
&lt;span class="nb"&gt;cd &lt;/span&gt;gitquest
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Visual Preview
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7jzj9q5q1981aqxryf9g.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%2F7jzj9q5q1981aqxryf9g.png" alt="GitQuest Cover" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitLab:&lt;/strong&gt; &lt;a href="https://gitlab.com/wdipak/gitquest" rel="noopener noreferrer"&gt;https://gitlab.com/wdipak/gitquest&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is fully open source under the MIT License, built with React, TypeScript, Vite, Tailwind CSS, and Web Audio API for interactive audio feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;GitQuest is built around a custom client-side Git virtual machine and world engine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;From-Scratch Virtual Workspace:&lt;/strong&gt; Implements a sandboxed virtual filesystem supporting &lt;code&gt;mkdir&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;, &lt;code&gt;touch&lt;/code&gt;, &lt;code&gt;echo&lt;/code&gt;, and file inspection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pure JavaScript Git State Engine:&lt;/strong&gt; Models Git's true object model (&lt;code&gt;blobs&lt;/code&gt;, &lt;code&gt;trees&lt;/code&gt;, &lt;code&gt;commits&lt;/code&gt;) along with references (&lt;code&gt;refs/heads/*&lt;/code&gt;, &lt;code&gt;refs/remotes/*&lt;/code&gt;, and &lt;code&gt;HEAD&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3 Dynamic Views:&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Commit Map:&lt;/strong&gt; Real-time visual graph of all commits, branch pointers, and HEAD movements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File Stages:&lt;/strong&gt; Visualizes file flow across Working Directory -&amp;gt; Staging Area -&amp;gt; Local Repo -&amp;gt; Remotes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Behind the Scenes (.git):&lt;/strong&gt; Interactive inspection of &lt;code&gt;.git/HEAD&lt;/code&gt;, &lt;code&gt;.git/refs&lt;/code&gt;, and simulated object trees.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tactile Puzzle Progression:&lt;/strong&gt; A 2D interactive arcade scene where versioned configuration files directly power bridges, gates, and runner routes, paired with multi-level hint systems and fair move-budget scoring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;6 Campaign Missions + Free Play Sandbox:&lt;/strong&gt; From basic commits to branching, 3-way merging, remote synchronization, conflict resolution, and an open sandbox.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Open innovation is what made Git the foundation of modern software engineering, and it is essential for developer education tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero Walled Gardens:&lt;/strong&gt; Anyone can run GitQuest locally, fork it, and add custom curricula or level packs without recurring subscription lock-in or proprietary cloud dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transparent Learning:&lt;/strong&gt; Because the entire simulation engine is open source and client-side, learners can open developer tools to inspect exactly how the virtual Git engine computes graph nodes and commits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Forge Neutrality:&lt;/strong&gt; Real-world software happens across open platforms. Open tooling ensures learners aren't locked into a single proprietary vendor.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best Use of a .tech Domain&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
