This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine
What I Built
Lockfile Ofrenda is a DÃa de los Muertos altar for the packages that are still in your package-lock.json after the registry has gone quiet.
npm outdated tells you that you froze a version. It does not tell you that the latest tag on the registry has not moved since 2015, that the maintainer wrote a deprecation note you never read, or that the name 404s now. Those packages are not ghouls in a haunted terminal. They are offerings that never left the table: jade, gulp-util, request, colors. Nested node_modules count. Direct dependencies count. The lockfile is the ofrenda because that is what you actually ship.
The app parses npm lockfile v2/v3 (and the older nested dependencies tree), asks registry.npmjs.org for last publish, deprecation text, and maintainers, then lights a marigold candle for anything unpublished, deprecated, silent for 730 days, or listed with no maintainers. Click a candle and a local Gemma model (via Ollama) may write a remembrance. Code then checks the text against the record. Invented years, invented CVEs, invented replacements are dropped. If Gemma is offline or fails that check, you get a clerk's copy of the registry fields instead, labeled as such.
I built this instead of a possessed shell because the ghosts in my machine were already there, sitting in lockfiles I had not opened in years. The theme asked for something that honors the past. An ofrenda is not a jump scare. It is a list of names and a light.
This is a new project for this window. MIT. No login.
Demo
There is no login and nothing to host a session cookie in. Run it locally, drop a lockfile or use the demo, click a candle.
git clone https://github.com/amrit-contour/lockfile-ofrenda
cd lockfile-ofrenda
cp .env.example .env
npm install
# optional, for spoken remembrances instead of the clerk copy:
ollama serve && ollama pull gemma3:4b
npm start
Open http://localhost:8788. Use the demo lockfile is the fastest path for judges. The sample is seven packages: six quiet, debug still alive. Filter Quiet / All / Direct. Click jade. Snuff a candle if you do not want it spoken of again this session.
If Ollama is not running, the slip still fills. That is not a failed demo. The clerk copy is the product working without a hosted model.
Empty altar:
Quiet packages from the demo lockfile:
jade's slip, copied from the registry when Gemma was silent:
A public Render URL is not part of this entry. render.yaml is in the repo if you want a host. This post does not claim Best Use of Render.
Code
amrit-contour
/
lockfile-ofrenda
DÃa de los Muertos altar for quiet packages in your npm lockfile
Lockfile Ofrenda
A DÃa de los Muertos altar for the quiet packages in your npm lockfile.
Source: github.com/amrit-contour/lockfile-ofrenda
npm outdated tells you that you froze a version. It does not tell you that the registry has not heard from that package in years, or that the maintainer marked it deprecated and you still pull it in transitively. This app reads package-lock.json, asks the public npm registry for last publish / deprecated / maintainers, and lights a candle for anything unpublished, deprecated, silent for two years, or listed with no maintainers.
A local Gemma model (via Ollama) may write a remembrance. Code then checks the text against the record. Invented years and wanderings are dropped. If Gemma is offline or fails the check, you get a clerk’s copy of the registry fields instead.
Why open weights
The lockfile is a map of what you ship. Sending it to a hosted…
Repo: github.com/amrit-contour/lockfile-ofrenda (public, MIT). My DEV GitHub handle is the-AoG-guy; this repo lives on the amrit-contour account I ship from.
flowchart LR
lock[package-lock.json] --> parse[parseLockfile]
parse --> registry[registry.npmjs.org]
registry --> score[score: unpublished / deprecated / silent 730d / no maintainers]
score --> altar[altar UI]
altar --> gemma[Gemma via Ollama]
gemma --> ground[groundEulogy]
ground -->|facts only| slip[remembrance slip]
ground -->|wandered or offline| clerk[clerk copy of the record]
Quiet is scored from the latest tag's publish time, not time.modified. ms in the demo is quiet because the latest publish is 2020-12-08 even though the record has been touched later. That is the point: a bump of metadata is not a release.
How I Built It
Open-weight Gemma is the remembrance, not the scanner. The scanner is TypeScript: a lockfile walk, a registry fetch, a 730-day threshold, a grounding pass. Gemma is allowed to write 90–140 words from a JSON fact bag. Temperature is 0.2. The system prompt is a clerk of a death register, not a poet with a search engine.
"You may only use the JSON facts. Do not invent successors, CVEs, people, or dates."
Then groundEulogy tokenizes the reply against the record. Years that are not in the facts are dropped. If too much of the text is invention, the whole remembrance is refused and the clerk copy is shown. Source is labeled gemma or record so the altar never pretends a model spoke when it did not.
That is the same instinct as PenMunshi: Gemma writes, code checks every fact. A lockfile is a map of what you ship. Sending it to a hosted chat API is a worse deal than reading registry.npmjs.org yourself.
I did not scan package.json alone. Week 4 already has Exorcist hunting declared deps. The ghosts I care about are nested: jade arrives because something else still asks for it. The lockfile is the honest list.
Stack: Node 20, Hono, tsx, vanilla HTML/CSS/JS. Tests cover lockfile parsing. npm test and npm run typecheck are in the README.
Why Does Open Innovation Matter?
A hosted model would have been easier. It would also mean uploading the names and versions of everything I ship, plus asking a vendor to invent a eulogy about software they do not maintain. The ofrenda only needs two networks: the public npm registry, which already published those facts, and optionally localhost Ollama.
If Gemma is down, the altar still works. That is the open-weight contract I wanted: the model is a clerk who may be out of the office. The record is not. A closed API disappearing is the same story this app is telling about packages. I did not want the remembrance layer to be another ghost.
Running Gemma locally also means the tone can be strict. I do not have to hope a remote safety layer will refuse to invent a CVE. I refuse it in ground.ts.
The Spirit of It
The first name that came up on the demo lockfile was jade 1.11.0. Last publish 2015-06-12. The deprecation field still says: Jade has been renamed to pug. Maintainers: forbeslindesay. License: MIT. Description: a clean, whitespace-sensitive template language for writing HTML.
That package taught a lot of people to indent HTML. It is still in lockfiles. The slip does not ask you to feel guilty. It lights a candle and copies the record. Snuff it if you already know.
Prize Categories
-
Best Use of Gemma — local
gemma3:4bthrough Ollama writes the remembrance; grounding code decides whether that text may leave the altar. No other partner category is claimed.



Top comments (0)