Unsaid Archive — the ghost is what the record cannot tell us
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine. What I Built I asked a small archive a simple question: “How did she wait for someone to come home?” One invented letter describes a porch light left burning and soup warmed three times. The model ranked a paragraph about a closed factory above it. That mistake became the center of Unsaid Archive. A system that reads memories should not turn its best guess into someone's voice. This is a browser reading room built around an open sentence-embedding model. It finds potentially related passages, places them beside the complete source, and lets the reader move between candidates. It does not generate a reply in the writer's name. The ghost is the space between what we want to know and what a record actually contains. The demonstration letters are fictional. No family member, testimonial or historical voice has been reconstructed. Demo Try the browser demo: https://e
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine.
What I Built
I asked a small archive a simple question: “How did she wait for someone to come home?”
One invented letter describes a porch light left burning and soup warmed three times. The model ranked a paragraph about a closed factory above it.
That mistake became the center of Unsaid Archive. A system that reads memories should not turn its best guess into someone's voice.
This is a browser reading room built around an open sentence-embedding model. It finds potentially related passages, places them beside the complete source, and lets the reader move between candidates. It does not generate a reply in the writer's name. The ghost is the space between what we want to know and what a record actually contains.
The demonstration letters are fictional. No family member, testimonial or historical voice has been reconstructed.
Demo
Try the browser demo: https://estona815.github.io/unsaid-archive/ . The first search downloads the model; allow about a minute on a slow connection.
Open a small English text file to read your own archive. The app reads it on your device, splits nonempty lines into passages and rebuilds its local index. It does not upload the text. The supplied examples remain explicitly fictional.
The music example retrieves a paragraph about tapping a melody on a kitchen table. Select the second result and the source highlight moves to the paragraph about leaving a piano behind. Every selection shows exact source character offsets and a source-text SHA-256.
The waiting example preserves the retrieval failure. “What were her last words?” returns a low-similarity notice and nearby passages, never invented last words. That is not a promise that the system detects every unanswerable question: similarity cannot establish whether a source contains an answer.
Code
Source code: https://github.com/estona815/unsaid-archive . The repository includes the static browser app, Python reference, tests, fictional letters and component provenance.
How I Built It
The reference implementation uses sentence-transformers/all-MiniLM-L6-v2 through Hugging Face Transformers and PyTorch. It mean-pools token representations with the attention mask, normalizes the vectors, and ranks passages by cosine similarity. The open model is central to retrieval; this is not a keyword lookup relabeled as AI.
Passages retain the original text and offsets. Inputs above 256 model tokens are rejected rather than silently shortened. The browser edition runs the quantized Xenova ONNX conversion through Transformers.js 2.17.2. It fetches the library and model files on first use, then performs inference in browser memory. It does not send the question or imported text to an inference API. The separate Python reference can also run with a loopback-only server.
Eight tests cover source integrity, duplicate identifiers, empty archives, source changes, allowed local routes and cross-origin request rejection. A six-case development evaluation blocked socket connections and still ran with cached model files. Among four related queries, the intended document ranked first in three. Only one cleared the provisional 0.4 threshold. Two unrelated questions remained below it. This is a tiny synthetic development exercise, not a benchmark or measured benefit to users.
In the native browser, a separate imported fictional text returned its orange-mailing sentence for “What did I mail to my sister?” at cosine 0.593. A 300-token query was rejected rather than truncated. Browser quantization changes scores, so the Python results above are not a browser benchmark.
Why Does Open Innovation Matter?
I could inspect the pooling and ranking code, retain exact source spans, run with outbound connections disabled and show the model's failure without handing the private text to an inference service. An archive does not need a recurring inference account to remain readable once its runtime and weights are available.
The browser downloads its library and model files initially; the hosting and model providers receive ordinary file requests. Cache eviction can cause another download, so offline browser reload is not promised. The Python reference was separately tested with network connections blocked. Both editions are English prototypes, not validated multilingual archives.
The Spirit of It
A convincing answer would have made the demo smoother. Keeping the wrong match visible makes the actual boundary legible: these are words to examine, not a person brought back to speak.
OpenAI Codex authored the implementation, synthetic letters and draft under the entrant's direction. No unaided authorship, real family history or user study is claimed. The project began during the Week 4 entry period; only the general-purpose open model and existing runtime were reused.