<?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: Hornet-Wing</title>
    <description>The latest articles on DEV Community by Hornet-Wing (@hornetwing).</description>
    <link>https://dev.to/hornetwing</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%2F962671%2Fdcb7df45-e92d-43f7-91fb-ece251640939.png</url>
      <title>DEV Community: Hornet-Wing</title>
      <link>https://dev.to/hornetwing</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hornetwing"/>
    <language>en</language>
    <item>
      <title>Memory Lantern: finding old stories when you’ve forgotten the words</title>
      <dc:creator>Hornet-Wing</dc:creator>
      <pubDate>Fri, 30 Oct 2026 23:27:13 +0000</pubDate>
      <link>https://dev.to/hornetwing/memory-lantern-finding-old-stories-when-youve-forgotten-the-words-1jhj</link>
      <guid>https://dev.to/hornetwing/memory-lantern-finding-old-stories-when-youve-forgotten-the-words-1jhj</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;Sometimes you remember what a story was about, but not the words someone used to tell it. A dented cake tin. A train ticket. The way somebody fixed a broken radio rather than throwing it away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory Lantern&lt;/strong&gt; is a small collection for those memories. Add notes about people, places, and ordinary moments, then search for what you remember. The AI’s job is to find related passages in the notes you actually saved. Every result opens the original text.&lt;/p&gt;

&lt;p&gt;For “Ghost in the Machine,” I wanted to help the past remain accessible. The app holds onto people’s words and makes them easier to find. An example collection contains eight clearly labeled fictional memories so visitors can try the idea before adding their own.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://hornet-wing.github.io/memory-lantern/" rel="noopener noreferrer"&gt;Try Memory Lantern&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To try the difference between the two search modes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search &lt;strong&gt;food she made for celebrations&lt;/strong&gt; with &lt;strong&gt;Match words&lt;/strong&gt; selected.&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;meaning search&lt;/strong&gt; and compare the results for the same query.&lt;/li&gt;
&lt;li&gt;Open a result to read the complete source note.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The example collection includes a birthday baking memory called “The lemon cake tin.” Its vocabulary differs from the query, which makes it a useful case for checking semantic retrieval. The model ranks the results; the app has no hardcoded answer for this query.&lt;/p&gt;

&lt;p&gt;No account or API key is needed. Initial model loading requires internet, and the interface shows download progress. Visitors can also add a memory, reload to check that it was saved, and export the collection.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/Hornet-Wing/memory-lantern" rel="noopener noreferrer"&gt;Source code and setup instructions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The app and original fictional example collection are MIT licensed. Runtime code and model weights are downloaded separately under their respective licenses.&lt;/p&gt;

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

&lt;p&gt;The app is plain HTML, CSS, and JavaScript, served as static files. Memories are stored in the browser and can be exported as a restorable JSON backup or a self-contained HTML reading copy. The reading copy contains no scripts or external assets.&lt;/p&gt;

&lt;p&gt;Meaning search runs &lt;a href="https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2" rel="noopener noreferrer"&gt;all-MiniLM-L6-v2&lt;/a&gt;, using &lt;a href="https://huggingface.co/Xenova/all-MiniLM-L6-v2" rel="noopener noreferrer"&gt;Xenova’s ONNX port&lt;/a&gt;, in a module Web Worker. Transformers.js 3.8.1 runs q8 weights with ONNX Runtime’s WASM CPU backend. Both queries and notes use mean pooling and L2 normalization.&lt;/p&gt;

&lt;p&gt;Long notes are split into overlapping source passages to reduce truncation. The worker caches their embeddings in memory and re-encodes changed notes on the next search. Cosine similarity selects the best passage for each memory, then ranks the memories. The model encodes and compares text; it does not write any memories or answers.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    Notes[Original memories] --&amp;gt; Passages[Source passages]
    Passages --&amp;gt; Model[Local MiniLM worker]
    Query[Search thought] --&amp;gt; Model
    Model --&amp;gt; Similarity[Cosine ranking]
    Similarity --&amp;gt; Original[Passage and complete original note]
    Notes --&amp;gt; Backup[JSON backup and HTML reading copy]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Two details matter for trust. A nearest neighbor can still be irrelevant, so results show similarity scores and original passages. Word matching stays available for exact details. Download or inference failures produce an error, with no silent change of search method.&lt;/p&gt;

&lt;p&gt;Ten logic tests cover backup round trips, malformed imports, merge behavior, long-note passage coverage, retrieval ranking, safe exports, and worker cancellation/recovery. The repository also includes an optional browser check that downloads the real model and exercises the example query.&lt;/p&gt;

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

&lt;p&gt;The search model is downloadable and can run on the reader’s device. There is no inference account or API key to obtain, and no per-query inference service to pay for. The app can be hosted as static files, and its search code and weights can be inspected or replaced.&lt;/p&gt;

&lt;p&gt;That is especially useful for personal memories. The app does not upload notes or search queries to an inference server. Loading meaning search still fetches code from jsDelivr and files from Hugging Face, which receive normal download metadata. Browser storage is not encrypted, synced, or backed up automatically, so the export feature is part of the core experience.&lt;/p&gt;

&lt;p&gt;There are tradeoffs: the model weights take about 23 MB plus runtime files, the model works best with English, and semantic similarity can miss a useful memory. Code/runtime loading can still need internet after a reload. The standalone reading copy provides a simple way to preserve the collection independently of the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Informed the Build
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/gabrielanhaia/mean-pooling-vs-cls-watch-transformersjs-turn-a-sentence-into-an-embedding-in-node-3bbl"&gt;Gabriel Anhaia’s explanation of pooling and normalization&lt;/a&gt; reinforced the need to encode notes and queries consistently. &lt;a href="https://dev.to/divyakush/similarity-isnt-relevance-the-hard-part-of-semantic-search-4oh"&gt;Divyakush Punjabi’s “Similarity isn't relevance”&lt;/a&gt; informed the way results are presented: source passages and a similarity ranking rather than an assertion that the app knows the answer. No article code was copied.&lt;/p&gt;

&lt;p&gt;This app and post were created with AI coding and writing assistance. The model and Transformers.js are Apache-2.0 licensed; ONNX Runtime is MIT licensed. I’m entering the overall category.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Daylight: A Local AI PA That Makes Room for Work and Life</title>
      <dc:creator>Hornet-Wing</dc:creator>
      <pubDate>Sun, 25 Oct 2026 18:00:58 +0000</pubDate>
      <link>https://dev.to/hornetwing/daylight-a-local-ai-pa-that-makes-room-for-work-and-life-n6k</link>
      <guid>https://dev.to/hornetwing/daylight-a-local-ai-pa-that-makes-room-for-work-and-life-n6k</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 wanted a personal assistant for a small daily problem: I have work tasks and personal tasks, but deciding what to do when is another task in itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Daylight&lt;/strong&gt; turns a task list into a proposed day. Work and personal tasks can share the schedule, with priorities, estimates, fixed appointments and breaks taken into account.&lt;/p&gt;

&lt;p&gt;The workflow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set the hours available and add appointments that cannot move.&lt;/li&gt;
&lt;li&gt;Write one task per line, or add tasks using a form.&lt;/li&gt;
&lt;li&gt;Let a local open-weight model suggest category, priority and duration.&lt;/li&gt;
&lt;li&gt;Review those suggestions, then add them to the schedule.&lt;/li&gt;
&lt;li&gt;Complete tasks or replan the remaining day when something changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tasks that cannot fit appear under &lt;strong&gt;For another time&lt;/strong&gt;, with an explanation. The planner keeps the original estimate and respects the end of the day.&lt;/p&gt;

&lt;p&gt;That is the “Slow and Steady” idea I wanted to explore: spend less effort juggling the list, while still being honest about how much day is left.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Demo video:&lt;/strong&gt; &lt;a href="https://drive.google.com/file/d/18yMAobWiORlU3fwNdyZsS7HDo4Fkqr_L/view?usp=sharing" rel="noopener noreferrer"&gt;Watch the Daylight demo on Google Drive&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During development I tried a mixed list: preparing a challenge entry, packing for a trip, and cleaning a pet’s bowl. The early results exposed useful problems, described below. This was hands-on browser testing, not a formal accuracy evaluation.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Source repository:&lt;/strong&gt; &lt;a href="https://github.com/Hornet-Wing/daylight" rel="noopener noreferrer"&gt;Hornet-Wing/daylight&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The original application code is MIT licensed. The project uses plain HTML, CSS and JavaScript, plus a small Node.js static server for local use. No dependency installation or build step is required for the manual planner.&lt;/p&gt;

&lt;p&gt;From the project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://127.0.0.1:4174&lt;/code&gt;. The AI reader separately downloads its runtime and model when enabled.&lt;/p&gt;

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

&lt;p&gt;I built Daylight with Codex, starting from the behaviour I wanted: list what needs doing, give it rough priorities, and see a realistic day containing both work and personal tasks.&lt;/p&gt;

&lt;p&gt;The AI integration uses &lt;a href="https://webllm.mlc.ai/docs/user/basic_usage.html" rel="noopener noreferrer"&gt;WebLLM&lt;/a&gt; and the open-weight &lt;a href="https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct" rel="noopener noreferrer"&gt;Qwen2.5 0.5B Instruct model&lt;/a&gt;, through its &lt;a href="https://huggingface.co/mlc-ai/Qwen2.5-0.5B-Instruct-q4f32_1-MLC" rel="noopener noreferrer"&gt;MLC WebGPU build&lt;/a&gt;. Inference runs in a browser worker.&lt;/p&gt;

&lt;h3&gt;
  
  
  Give the model a smaller job
&lt;/h3&gt;

&lt;p&gt;The first version asked the model for a complete task list, including optional start and finish times. Browser testing revealed that it could invent full date-and-time strings even when my notes supplied no times. It also omitted one task.&lt;/p&gt;

&lt;p&gt;An earlier error handler hid the useful diagnostic because a worker failure arrived as plain text instead of an Error object. Preserving that text exposed a grammar-initialisation failure, which led to a simpler generation schema.&lt;/p&gt;

&lt;p&gt;Those failures changed the design.&lt;/p&gt;

&lt;p&gt;Each original task line is now kept by application code. The model handles one line at a time and returns only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"personal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"should"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an example of the response format, not a benchmark result.&lt;/p&gt;

&lt;p&gt;The model does not supply task titles or time constraints. Explicit phrases such as “before 5pm” or “after 09:30” are handled separately. Without a supported time phrase, both optional time fields stay blank. Ambiguous source phrases remain visible for correction.&lt;/p&gt;

&lt;p&gt;Explicit user metadata takes precedence too. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Personal: pack for a trip, medium priority, 37 minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That preserves the stated 37 minutes even if the model suggests something else.&lt;/p&gt;

&lt;p&gt;A later trial exposed another limitation: “week 3” became a three-minute estimate, and packing was classified as Work/High. The current request constrains inferred durations to a menu of valid time blocks and includes clearer classification examples. Those changes do not establish that the model’s judgments are accurate. Category, priority and duration still need review.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let scheduling code handle the clock
&lt;/h3&gt;

&lt;p&gt;After review, ordinary code builds the schedule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Original task lines
  → local model suggests category, priority and duration
  → explicit source metadata overrides guesses
  → person reviews and accepts
  → scheduling code fits tasks around appointments and breaks
  → timeline and explicit overflow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tasks are considered by priority, then deadline, then input order. Each receives the earliest uninterrupted slot that fits its full duration and constraints. Fixed appointments stay fixed. Breaks reserve time between tasks.&lt;/p&gt;

&lt;p&gt;This is a greedy scheduling heuristic, not a claim of an optimal schedule. It does not split tasks automatically, and a missed deadline can leave a task unscheduled. The interface explains those cases so I can make the tradeoff myself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check the rules separately from model quality
&lt;/h3&gt;

&lt;p&gt;The current automated suite has &lt;strong&gt;50 passing tests&lt;/strong&gt;, including 120 generated scheduling scenarios.&lt;/p&gt;

&lt;p&gt;The checks cover overlapping appointments, task durations, deadlines, work/personal hours, overflow, backups, server responses, visible error messages, preservation of source lines, and rejection of invented model time fields.&lt;/p&gt;

&lt;p&gt;The AI contract tests use test doubles. They check what the application requests and accepts; they do not measure real-model accuracy. The development environment also restricted automated browser testing. My browser trials supplied the screenshots and failure reports that drove the changes above.&lt;/p&gt;

&lt;p&gt;Two community references helped frame the approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/kohei_wada/building-a-cli-task-manager-that-solves-the-when-to-do-it-problem-taskwarrior-lacked-581n"&gt;Building a CLI Task Manager That Solves the "When to Do It" Problem Taskwarrior Lacked&lt;/a&gt;, by &lt;a href="https://dev.to/kohei_wada"&gt;@kohei_wada&lt;/a&gt;, describes transparent scheduling from priorities, estimates and daily capacity.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/claupttools/stop-ai-from-inventing-facts-in-document-extraction-496b"&gt;Stop AI From Inventing Facts in Document Extraction&lt;/a&gt;, by &lt;a href="https://dev.to/claupttools"&gt;@claupttools&lt;/a&gt;, discusses keeping missing facts unknown and checking proposed values against their source.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;A daily task list can mix work information with personal routines. Local inference is useful because the notes can be processed on my device, without sending them to a hosted inference API.&lt;/p&gt;

&lt;p&gt;The browser still fetches runtime and model files when needed. This is not a claim that the app makes no network requests. The first model load needs a substantial download and compatible WebGPU hardware; cached files may reduce later downloads.&lt;/p&gt;

&lt;p&gt;Open weights and an open runtime also let me inspect the integration, change the prompt or experiment with a different model. The scheduling rules are separate, so changing the model does not mean trusting it to rewrite the clock.&lt;/p&gt;

&lt;p&gt;Daylight stores its plan in one browser, with JSON backup and restore. There is no account or cloud database. Browser storage is not encrypted, and backups include notes. Calendar sync and multi-device sync are outside this prototype.&lt;/p&gt;

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

&lt;p&gt;The intended benefit is less repeated planning: place the tasks once, see what fits, and rebuild the remaining day when plans change.&lt;/p&gt;

&lt;p&gt;I have not measured minutes saved or run a sustained daily-use trial. What I have is a working prototype, hands-on feedback, and a clearer understanding of where a small local model needs boundaries and human correction.&lt;/p&gt;

&lt;p&gt;The next useful measurement is how much I edit its suggestions and how much manual rearranging remains after it proposes a day.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The code and this article were prepared with Codex assistance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Town Centre: An AoE2 Tournament Desk with Local AI</title>
      <dc:creator>Hornet-Wing</dc:creator>
      <pubDate>Sun, 18 Oct 2026 23:20:52 +0000</pubDate>
      <link>https://dev.to/hornetwing/town-centre-an-aoe2-tournament-desk-with-local-ai-1lha</link>
      <guid>https://dev.to/hornetwing/town-centre-an-aoe2-tournament-desk-with-local-ai-1lha</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;Town Centre is an organiser desk for small &lt;strong&gt;Age of Empires II: Definitive Edition 1v1 tournaments&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Picture an eight-player community cup. The first round has four series. One pair has agreed a time, another is waiting for a reply, one player has shared no availability, and two opponents cannot find an overlapping window.&lt;/p&gt;

&lt;p&gt;That is the situation in Town Centre's fictional sample tournament. The organiser can see which matches need attention and take the next action from one dashboard.&lt;/p&gt;

&lt;p&gt;The prototype supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An eight-player single-elimination bracket, with organiser-approved seeds.&lt;/li&gt;
&lt;li&gt;Editable availability in each player's time zone.&lt;/li&gt;
&lt;li&gt;Proposed match times checked against both players' full availability.&lt;/li&gt;
&lt;li&gt;Confirmations recorded by the organiser.&lt;/li&gt;
&lt;li&gt;Manual series results that advance the winner.&lt;/li&gt;
&lt;li&gt;Copyable Discord announcements and JSON backups.&lt;/li&gt;
&lt;li&gt;An AI reader designed to turn informal availability messages into structured windows for review.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The intended customer is a streamer or community organiser who runs tournaments repeatedly. My pricing hypothesis is &lt;strong&gt;$5–$10 per tournament&lt;/strong&gt; for less scheduling administration. That price has not been validated, and I have not measured time saved or collected payments. An open-source app could still have a paid hosted service or event-support offering around it; the prototype does not implement either.&lt;/p&gt;

&lt;p&gt;The next useful test is to put it in front of an organiser: can they arrange the first round more easily, and is the improvement worth paying for?&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Demo video:&lt;/strong&gt; &lt;a href="https://drive.google.com/file/d/1Ydvcfcu1dEXxn8ipawxRkyZj5wgjs5TX/view?usp=sharing" rel="noopener noreferrer"&gt;Watch the Town Centre demo on Google Drive&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The recorded walkthrough uses the fictional &lt;strong&gt;Castle vs Monk&lt;/strong&gt; match to demonstrate the organiser workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Paste a sample availability message for the selected player, extract its availability, and save it.&lt;/li&gt;
&lt;li&gt;Propose a match time once both players have availability.&lt;/li&gt;
&lt;li&gt;Record the fictional players’ confirmations and copy a Discord announcement.&lt;/li&gt;
&lt;li&gt;Enter the series result and show Castle advancing in the bracket.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Testing:&lt;/strong&gt; I recorded the sample workflow described above. Automated checks cover core rules, DOM-adapter interactions, and AI request/response contracts. This is a functional demonstration with fictional players; I have not measured general extraction accuracy, run a real customer tournament, or validated willingness to pay.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Source repository:&lt;/strong&gt; &lt;a href="https://github.com/Hornet-Wing/tourney-organiser" rel="noopener noreferrer"&gt;Hornet-Wing/tourney-organiser&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The original application code is MIT licensed. It is plain HTML, CSS, and JavaScript, with a small Node.js static server for local use. No npm dependency installation or build step is required for the manual tournament workflow.&lt;/p&gt;

&lt;p&gt;From the repository's project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open &lt;code&gt;http://127.0.0.1:4173&lt;/code&gt;. The AI reader separately downloads its browser runtime and model when requested.&lt;/p&gt;

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

&lt;p&gt;I developed the prototype with Codex, starting from the game and event format I wanted to support: AoE2 and competitive 1v1 tournaments. I kept the first version to eight players so the whole competition could be represented and tested.&lt;/p&gt;

&lt;h3&gt;
  
  
  Give the language model a specific job
&lt;/h3&gt;

&lt;p&gt;The AI integration uses &lt;a href="https://webllm.mlc.ai/docs/" rel="noopener noreferrer"&gt;WebLLM&lt;/a&gt; with the open-weight &lt;a href="https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct" rel="noopener noreferrer"&gt;Qwen2.5 0.5B Instruct model&lt;/a&gt;, through its &lt;a href="https://huggingface.co/mlc-ai/Qwen2.5-0.5B-Instruct-q4f32_1-MLC" rel="noopener noreferrer"&gt;MLC WebGPU build&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An organiser chooses a player, supplies their declared time zone and the message's reference date, and pastes that player's availability message. The model is asked for JSON containing complete availability windows and clarification questions.&lt;/p&gt;

&lt;p&gt;Messages are pasted manually in this prototype. There is no automatic Discord import or channel monitoring. After arranging a match, the organiser can copy an announcement and post it to Discord themselves.&lt;/p&gt;

&lt;p&gt;The implementation supplies an explicit JSON Schema string with the JSON-output request, validates the returned fields, converts valid local times to UTC, and presents the interpretation for review. Saving the reviewed output adds availability; it does not confirm or schedule a match automatically.&lt;/p&gt;

&lt;p&gt;The first model load requires a substantial download and a compatible WebGPU device. Manual entry remains available throughout.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep tournament decisions explicit
&lt;/h3&gt;

&lt;p&gt;The rest of the workflow uses ordinary application rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Player message
  → local model extracts proposed windows
  → validation and organiser review
  → saved availability
  → code checks possible match slots
  → organiser proposes a time
  → organiser records player confirmations
  → manual result advances the winner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, the application checks whether a complete reserved series slot fits within both players' availability. A proposed time change clears both confirmations. Later rounds must follow the reserved slots of their prerequisite matches.&lt;/p&gt;

&lt;p&gt;The organiser supplies the estimated series duration, including drafts and breaks. That duration is a scheduling allowance, not an AI prediction of how long an AoE2 series will last.&lt;/p&gt;

&lt;p&gt;The app rejects impossible local times during daylight-saving changes. For a local time that occurs twice when the clocks go back, it asks the organiser to enter the time in UTC instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test the competition rules
&lt;/h3&gt;

&lt;p&gt;The current suite has &lt;strong&gt;26 passing tests&lt;/strong&gt;: 14 core-rule tests, eight DOM-adapter interaction tests, and four AI request/response contract tests.&lt;/p&gt;

&lt;p&gt;They cover daylight-saving cases, availability intersections, invalid scores, winner progression, imported backup validation, UI navigation, confirmations, event creation, and escaping player text.&lt;/p&gt;

&lt;p&gt;The recorded walkthrough supplements these automated checks with a sample browser workflow. It does not establish compatibility across browsers or accuracy across different scheduling messages.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.ageofempires.com/news/tournament_handbook_ageiide/" rel="noopener noreferrer"&gt;World's Edge AoE2 tournament handbook&lt;/a&gt; informed the scheduling workflow. Individual events provide their own rules, maps, settings, and draft links.&lt;/p&gt;

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

&lt;p&gt;Local inference is a useful fit for this particular customer.&lt;/p&gt;

&lt;p&gt;Availability messages may contain players' personal schedules. The integration is designed to process those messages on the organiser's device, avoiding the need to send them to a hosted inference API. The browser still fetches runtime and model files, and the page requests external fonts; this is not a claim that the app makes no network requests.&lt;/p&gt;

&lt;p&gt;There is also no per-message inference API charge in this architecture. That could make a small per-event service easier to operate, although device resources, download size, hosting, support, and maintenance still have costs.&lt;/p&gt;

&lt;p&gt;Open weights and an open runtime make it possible to experiment with a larger model or change the extraction prompt without rebuilding the tournament rules. The small default model keeps the initial scope manageable, but its extraction quality still needs to be evaluated on real scheduling messages.&lt;/p&gt;

&lt;p&gt;The tradeoff is hardware compatibility. Organisers without a suitable GPU can use manual availability, while the model-backed workflow needs a compatible device.&lt;/p&gt;

&lt;h3&gt;
  
  
  What informed the approach
&lt;/h3&gt;

&lt;p&gt;The project builds on lessons other developers have shared:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/scythe2/-i-watched-a-cod-streamer-suffer-through-tournament-admin-and-then-spent-a-month-fixing-it-k8d"&gt;I Watched a Streamer Suffer Through Tournament Admin and Spent A Month Fixing It&lt;/a&gt;, by &lt;a href="https://dev.to/scythe2"&gt;@scythe2&lt;/a&gt;, describes the work of coordinating tournament tools.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/ravendev/building-an-ai-lineup-optimizer-for-a-discord-esports-bot-the-algorithm-not-the-hype-2hjh"&gt;Building an AI lineup optimizer for a Discord esports bot (the algorithm, not the hype)&lt;/a&gt;, by &lt;a href="https://dev.to/ravendev"&gt;@ravendev&lt;/a&gt;, helped frame the division between interpreting messages and enforcing constraints.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/dhruvil_chauhan_eccb4a1eb/i-built-react-components-that-run-qwen25-in-the-browser-via-webgpu-no-server-no-api-key-works-7e0"&gt;I built React components that run Qwen2.5 in the browser via WebGPU – no server, no API key, works offline&lt;/a&gt;, by &lt;a href="https://dev.to/dhruvil_chauhan_eccb4a1eb"&gt;@dhruvil_chauhan_eccb4a1eb&lt;/a&gt;, describes a related local extraction approach. Town Centre does not use that library.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What comes next
&lt;/h3&gt;

&lt;p&gt;The next milestone is an organiser trial using scheduling messages shared with permission. A future Discord integration could reduce copying and pasting, but it is not part of the current prototype. I would measure incorrect interpretations and the organiser's remaining manual work before expanding the scope.&lt;/p&gt;

&lt;p&gt;Town Centre currently stores data in one browser, has no player login or multi-organiser synchronisation, and requires results to be entered manually. No first-user feedback, sales, or partner-category eligibility is claimed in this draft.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The code and this draft were prepared with assistance from Codex. The author should review and verify the content before publishing.&lt;/em&gt;&lt;/p&gt;

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