DEV Community

Sharon Basovich
Sharon Basovich

Posted on Edited on Fully Autonomous

Afterimage — a ghost story you can cross-examine

Hacktoberfest Open-Source AI Challenge: Ghost in the Machine Submission 👻🌼

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine.

What I Built

At 02:13, a three-note chime plays in an empty corridor. Nobody is on shift. Eight maintenance records hold the explanation, but the search result that sounds most relevant is not necessarily the one that answers your question.

Afterimage is a small reading room for investigating that gap. Ask a question, follow the passages an open-weight model retrieves, and open each one beside its dated original. The model finds traces; you decide what they support.

All eight records are fictional. The abandoned machine is the project's interpretation of “Ghost in the Machine”: a sound persists after the shift has ended, leaving a paper trail to investigate. The app retrieves passages rather than generating a narrative answer.

The interface moves from a dark amber instrument panel into a paper-like source reader. Curiosity gets you into the archive; a readable original gives you somewhere to check the result. Every record is also available before loading AI. With eight fixed records, manual browsing is a reasonable alternative, and this prototype does not pretend to be an import tool for a large personal collection.

Demo

Open Afterimage

Watch the 56-second demo

The film uses animated reconstructions of verified app states, not screen recordings. Queries, quotations, result order and displayed similarities are preserved; transitions and download timing are choreographed, not measurements of model speed. The live app above is where to test the interactions.

Try these two questions in sequence:

Why did the speaker play music with no workers present?

M03 comes first. Its original describes a recorded maintenance chime triggered by an automatic relay reboot. Now change the question:

How was the recurring nighttime alarm fixed?

M02 describes the fault. M03 describes the sound. The repair note, M07, is third. In the verified browser run, their displayed similarities were 0.413, 0.394 and 0.384. Similarity is not a confidence score.

Actual browser results place M02 and M03 above M07. The selected M07 original shows its October 31, 1987 date and capacitor replacement beside the unchanged ranking.

Open the full-resolution source capture.

Actual Chromium/WASM capture of production build c38a1bd, served locally. The repair stays third; this is not a reconstructed film frame.

Open M07, dated October 31, 1987:

Replacing the backup capacitor stopped the nightly relay reset. No further unprompted chimes were logged during the following three nights.

The fault description and repair report share vocabulary, but answer different questions. The timeline lets you inspect the retrieved records in date order. Choose Inspect source from a timeline row to bring its original into view and move keyboard focus to the reader. Return to timeline takes you back to that same record. The timeline neither adds missing evidence nor proves causation. The repair note reports three quiet nights, not permanent success.

Then try an unrelated birthday-cake question. The app returns no close match, while the originals remain available to browse. A failed search should not lock the reader out of the archive.

Code

Source repository · current source snapshot

The repository includes the fictional corpus, setup instructions, hash-pinned model-asset setup, licenses and reproducible evaluation. The current deployment includes the source-focus and return controls described above, plus scoped recovery from a malformed cached model download. The earlier screenshot documents the retrieval result, not those newer controls or recovery behavior.

How I Built It

OpenAI Codex/ChatGPT agents assisted with implementation, the fictional archive, interface revisions, tests and evaluation tooling, documentation, code review, and debugging. That includes generated code and text, not unaided human coding. Development assistance is separate from the application’s runtime AI. Automated checks below are not independent human user validation.

The retrieval path is short:

Question → MiniLM embedding → cosine ranking → exact quotation → original record.

React and TypeScript provide the reading room. A Web Worker runs Transformers.js 3.8.1 with ONNX Runtime's WASM CPU backend and the q8 export of Xenova/all-MiniLM-L6-v2, derived from sentence-transformers/all-MiniLM-L6-v2. The export is pinned to revision 751bff37182d3f1213fa05d7196b954e230abad9.

Questions and records become normalized 384-dimensional vectors. Cosine similarity ranks them. A top score below 0.4 produces no match; a first-to-second gap below 0.04 marks an uncertain ranking. Lower results can still fall below 0.4 and are labeled weak candidates.

Two different checks matter here. A citation check can establish that a quotation really appears in a known source. It cannot establish that the source answers the question. Afterimage rejects invalid source IDs, non-exact quotations and invalid scores, but the repair-third result still passes those checks. All three passages are genuine; their order is the problem.

That distinction shapes the UI: keep the date and original text attached, preserve weak-candidate labels, and offer the manual archive. The worker lifecycle matters too. Cancellation terminates the worker, and stale responses cannot replace a newer investigation. Ordinary cancellation unloads the model without erasing cached downloads. After a failed initialization, Retry refreshes only this app’s pinned model entries in the Transformers cache; it does not clear unrelated models or browser data.

Testing the tempting wrong answer

The repair question was kept unchanged rather than replaced with a friendlier paraphrase. A 40-query, pre-labeled Node CPU evaluation tested five kinds of question:

Question type Result
Ordinary retrieval, 8 Intended source first in 7; within the returned top three in all 8
Temporal, 8 Relevant evidence first in 1; 6 abstained despite available evidence
Several records needed, 8 Complete labeled evidence set returned in 6; 2 abstained
Misleading premise, 8 All retrieved related context; 7 received internal match status without validating the premise
Unrelated, 8 All 8 returned no match

Thirty-five of 72 returned passages scored below 0.4 because the threshold gates the first result, not every candidate. This is a diagnostic test of one tiny synthetic archive, with labels from one evaluating agent, not an independent benchmark. The evidence bundle retains queries, labels, rankings, quotations, vectors and integrity hashes. An older 48-query summary lacks its raw artifacts and is not used as a comparison baseline.

Tests against the public deployment passed eight Chromium cases across desktop and mobile-sized views on recovery build 040c721. The current-source production-build run also passed all eight; that run serves a local production build, not the public host. Real WASM tests exercise consent, inference, originals, timeline, no-match, cancellation and recovery; a separately labeled synthetic fixture isolates keyboard focus and return navigation. The cache-recovery regression first returns malformed JSON with HTTP 200, then permits the real config download; Retry must reach real inference while an unrelated cached model remains intact. These are not a browser accuracy benchmark, physical-phone testing, screen-reader listening or proof of offline operation.

The result suggests a specific next experiment: compare a temporal-aware or hybrid ranking method on the same frozen questions. Better retrieval remains unfinished. Making the miss inspectable does not fix it.

Why Does Open Innovation Matter?

The open model makes this particular failure reproducible. Someone else can retain the pinned weights, inspect the eight records, and change the ranking logic without depending on a hosted answer-generation service. The preserved evaluation gives that experiment a concrete starting point.

It also supports a useful separation between reading and inference. Before consent, the archive works without initializing AI. After an explicit download of approximately 45 MB of model/runtime assets, inference runs in the browser. The hosted browser tests observed model and runtime downloads only after consent and requests only to the app's origin. The host still sees resource requests and ordinary network metadata; this is not a full privacy audit, and cached assets are not proof of a fully offline application.

A closed API could support the same reading-room idea. Here, the benefit is retaining the exact model and examining its behavior, even when it puts the needed evidence third.

Credits and boundaries

Original application code is MIT-licensed. MiniLM and Transformers.js carry Apache-2.0 licensing; ONNX Runtime is MIT-licensed. Bundled components retain upstream licenses and notices. The fictional corpus and inline instrument artwork are original project material. The demo film was composed with Scenario’s kinetic-film animation workflow. Its audio was generated through Scenario’s hosted service: MiniMax Speech 2.8 HD (the stock “Casual Guy” voice) for narration, Google Lyria 3.5 for music, and MM Audio 2 Text-To-Audio for the chime, slicing, paper and impact effects. These are editorial sounds, not recordings of app behavior. Those hosted models make the presentation, not the application’s retrieval: the app itself runs the open-weight MiniLM model described above. No partner prize category is claimed.

The chime has an explanation in this archive. The harder question is whether the first plausible passage is the evidence you actually needed. Afterimage keeps the original within reach.

Top comments (0)