This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine
What I Built
Graveyard is a funeral for dead code. Every repo has a graveyard: files deleted with a commit message like "fix stuff" and never thought about again. For the Ghost in the Machine theme, I wanted to dig them up and give each one a tombstone.
A small Node script reads a git repo's history (read-only) and exports every deleted file as JSON. The page then draws a candlelit cemetery with one tombstone per file: born, died, an epitaph, and the real commit message that killed it. The idea is that a local open-weight model, Gemma 3 4B through Ollama, writes the epitaph and the cause of death.
My reading of the theme: the ghost in the machine is the AI inventing a backstory for something that can't correct it. So the part I spent the most time on is a checker that stops the model from making things up.
- Dates, file names and commit hashes come from the repo, never from the model.
- The "cause of death" has to share most of its key words with the real commit message, or it is replaced with "Cause of death unknown" and marked "Unverified claim removed".
- An epitaph that mentions a number, date or hash that isn't in the data is replaced with a plain one.
Demo
Live demo (fake data, canned text, no model): https://p44-code.github.io/graveyard/
In the demo, one tombstone has a cause of death I planted on purpose. Its real commit message is just "fix stuff", but the canned answer talks about memory leaks. The checker catches it, shows "Cause of death unknown", and prints the original commit message underneath.
An important note: the online demo uses canned text, not model output. GitHub Pages can't run Ollama on your computer, so the live demo only shows the page and the checker.
Code
β°οΈ Graveyard: A Funeral for Dead Code
"Theme: Ghost in the Machine β Memorializing the code we wrote, loved, refactored, and purged."
Graveyard is a solemn, client-side digital cemetery for retired source code files. It transforms Git deletion logs into atmospheric, Gothic terminal tombstones commemorating deprecated shims, abandoned hacks, and forgotten features.
Built for open-source AI challenges with a strict security-first architecture:
- Zero Frameworks, Zero Build Step, Zero NPM Runtime Dependencies: Pure HTML5, CSS3, and ES modules.
-
Strict Content-Security-Policy: Enforced via meta tags (
connect-srclocked exclusively to'self'andhttp://localhost:11434). -
Open-Weight Models Only: Runs locally through Ollama with Google's open-weight Gemma (
gemma3:4b). No cloud models, no API keys, and no telemetry. - Honest Verifier: Automatically detects model hallucinations, requiring at least 60% keyword match against Git commit logs before verifying cause-of-death claims.
ποΈ Modes of Operation
-
Demo Mode (Default & Offline)
- Built-inβ¦
MIT licensed. The README explains how to run Demo mode and Local mode.
How I Built It
-
Model: Gemma 3 4B (
gemma3:4b), an open-weight model, served locally through Ollama. The app calls onlyhttp://localhost:11434. A guard in the code throws if the model name doesn't start with "gemma", and there are no API keys anywhere in the app. - App: plain HTML, CSS and JavaScript. No framework, no build step, no npm dependencies. A strict Content-Security-Policy, and all text is rendered with textContent, never innerHTML.
-
Export script: a Node script with no dependencies that runs read-only git commands and writes
graveyard.json. - Safety: commit messages and code are treated as untrusted text. They are wrapped in delimiters in the prompt, and the model's output can only fill text fields. It can't change dates, hashes or settings. This reduces prompt-injection risk but doesn't remove it, since a 4B model can still be fooled.
- Tests: 15 unit tests for the checker, all passing.
I used Google AI Studio's builder (a closed Gemini model) for the first version of the code, and an AI assistant to plan and review it. Then I audited what I got. The builder had added a Gemini API key template, a Gemini config file and a Gemini library to a project that was meant to be Gemma only. The app never used them, but I deleted them. In review we also found a bug in my checker: it read the word "dead" as a commit hash, because d, e, a and d are valid hex letters. In an app about dead code, that matters. It is fixed.
What did not work
On my laptop, Local mode reached Ollama, but the first response timed out after 60 seconds. My machine is slow, and I ran out of time to raise the timeout and retest. So I never saw Gemma write a real eulogy for a real file in this project, and the model-writing path is untested end to end. I'm saying this plainly because the checker's whole point is not to claim things that weren't verified. For the same reason I'm not claiming it works offline.
Other limits
- The checker compares words, not meaning. "Removed" versus "added" could still pass.
- A vague commit message copied word for word still passes as "paraphrased". That is the next thing I would fix.
- Tested on Windows only.
To try Local mode: install Ollama, run ollama pull gemma3:4b, set OLLAMA_ORIGINS=http://localhost:5173, and on a slow machine raise OLLAMA_TIMEOUT_MS in modules/adapters.js.
Why Does Open Innovation Matter?
Deleted code is often private code. Pasting it into a closed cloud API means trusting someone else's server with your repo's history. With an open-weight model running locally, the design keeps everything on your own machine: no API key, no account, no bill, and the app only talks to localhost.
I want to be careful here. I only tested on a fake repo, and I never completed a Local run, so this is a benefit of the design, not something I proved on a real private codebase. What I can say honestly is that open models are what make that design possible at all. A hosted API would have broken the "your code stays with you" idea from the start.
Prize Categories
Best Use of Gemma: the app is built around Gemma 3 4B served locally through Ollama, with a guard that refuses any non-Gemma model. As described above, I did not complete a full Local run, so I understand if this one is a long shot.
Top comments (0)