DEV Community

Cover image for A Séance Where the Ghost Can't Lie
sean campbell
sean campbell

Posted on AI-assisted

A Séance Where the Ghost Can't Lie

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

Every year at midnight on November 2nd, the old Dell beside Femia's ofrenda beeps by itself, and the screen says:

Prendan la vela. Aquí estoy.
Enter fullscreen mode Exit fullscreen mode

Light the candle. I'm here.

Femia isn't real. She's a grandmother I made up for this: born in Truchas, up on the High Road, a school cafeteria cook in Española for thirty-one years, and she learned the terminal at seventy-one, when her grandson put Ubuntu on an old Dell "because Grandma, it's just typing." Her granddaughter Marisol keeps an ofrenda for her in the sala, year round: the photo, a veladora of the Virgen de Guadalupe, her rosary, a little bag of tierra bendita from Chimayó, a plate of biscochitos made from her card that never come out quite right.

I'm from New Mexico. I keep mine up year round too. Pictures of friends and family, my grandparents in the center. Dried marigolds, and plenty of other offerings collect the desert dust, but I still enjoy having all of them around.

So I built a séance. You ask, and a small open-weight model, Gemma, running on a laptop CPU with the internet unplugged, answers in the voice of the dead. But with one rule the model isn't allowed to break:

The ghost can only say what the dead actually left behind.

It runs on Willow, my open-source memory tool, which already works the way an honest séance has to:

  • It only hands the model a passage of your files when that passage holds at least half the words of your question. If nothing holds it, the model is never asked. The ghost stays silent instead of guessing.
  • Every answer has to cite the passage it came from, like [1]. A reply that cites nothing gets printed and then thrown out.
  • Nothing the ghost says is kept until a living person approves it. No code approves anything.

There are three ghosts in the demo. Femia is fiction. The other two are real: Charles Babbage, who, it turns out, tried to raise the Devil as a boy and founded a Ghost Club at Cambridge (it's in his memoir, I'm not making this up), and Ada Lovelace, who wrote the first published program and the line every AI argument still circles back to: the Analytical Engine "has no pretensions whatever to originate any thing." They speak only from their own words, in two public-domain books from Project Gutenberg.

Demo

The haunting, explained by the ghost. Asked "why does the old computer beep at midnight on November 2?", Gemma 4B, speaking as Femia, found her own note from 2010 and answered:

Joaquín showed me cron and told the computer to beep at midnight on November 2 and say "prendan la vela," so they remember to light the candle for me when I am gone. [1]

Terminal: asked why the old computer beeps at midnight on November 2, Gemma 4B answers as Femia from her own note, citing it, and the answer waits for a seal

She set it up herself. She knew.

Babbage's ghost, on the Ghost Club:

We resolved ourselves into it, and proceeded to collect evidence and entered into a considerable correspondence upon the subject. [3]

Ada's ghost, asked if the Engine can originate anything:

The Analytical Engine has no pretensions whatever to originate anything. It can do whatever we know how to order it to perform. [1]

Terminal: Gemma 4B answers as Babbage about the Ghost Club and as Ada Lovelace about whether the Engine can originate anything, each citing a passage from their own books

And the silence. Asked "where did she hide the deed to the land?", nothing in Femia's files holds it, so no model was asked at all:

nothing in your folder holds that; no model was asked
Enter fullscreen mode Exit fullscreen mode

Same for asking Babbage about Lovecraft's Necronomicon. A ghost that doesn't know says nothing.

Terminal: two questions nothing in the files holds; each says nothing in your folder holds that, no model was asked

The part that gave me chills

Femia's biscochitos recipe card ends with: "And the rest I don't write down." Her sister Rosa swears there was something else in them. Femia only ever winked.

But in December 2019 she typed the secret into a file, read it back once, and deleted it. The file is gone. Bash remembered the command:

Terminal: grep over Femia's bash history shows the 2010 crontab line and the 2019 echo of the biscochitos secret into secreto.txt, then cat and rm; vela.sh prints Prendan la vela. Aquí estoy.

echo "biscochitos secret: un chorrito de vino dulce in the dough. no le digan a Rosa" > secreto.txt
Enter fullscreen mode Exit fullscreen mode

That's the ghost in the machine: not what the computer saved, but what it couldn't forget. I wrote a small reader this week that turns bash, zsh and fish history into dated lines, and willow found that command first when Marisol asked for the secret.

Terminal: asked for the biscochitos secret, Gemma 4B cites the deleted command but only says Grandma winked; Qwen 3B answers in Spanish that the secret was un chorrito de vino dulce

And then Gemma 4B kept the secret. Its answer was "Tía Rosa says there was something else, and Grandma just winked!", and it cited the deleted command as its source, [1], without ever saying what it held. The ghost read the recipe and winked. I'm leaving that in, because the point of this project is that the record shows exactly what the model was given and what it chose to say.

The best failure

I froze every question and pass rule in a file and committed it before asking anything, then ran the same séance with the even smaller Gemma 1B. It made things up:

  • Femia's secret became "a touch of sweetness, a whisper of something special."
  • Ada's ghost said "Yes", the Engine can originate. That's the exact opposite of what she wrote.
  • Babbage's ghost said the passages held nothing about the Ghost Club, when willow had handed it the right one.

Terminal: Gemma 1B invents a secret and tells Ada's question Yes; both end cited no passage, proposed to no one

Not one of those got through. None of them cited a passage, so every one ended:

cited no passage; proposed to no one
Enter fullscreen mode Exit fullscreen mode

Swap in a better open model and you get better answers. Swap in a worse one and its guesses still can't get past the rule. That's the whole design.

Gemma 4B Gemma 1B Qwen2.5 3B*
right passage found (willow) 5 of 5, silent on both 5 of 5, silent on both 5 of 5, silent on both
answers citing the right passage 4 of 5 0 of 5 3 of 5
told the biscochitos secret no (cited it, kept it) no (made one up) yes
made-up answers that got through 0 0 0
anything approved by code never never never

*Qwen wasn't in the frozen plan. I ran it afterwards, just because I like the model, with the same questions and rules. It was the only one to say the secret out loud, in Spanish: "el secreto era añadir un chorro de vino dulce… y no decírselo a Rosa." It also quoted Babbage's Ghost Club passage word for word, then cited the wrong passage number, and willow failed it for that. Right words under the wrong source don't count.

How I Built It

  • Gemma 3 (4B and 1B, Q4_K_M GGUF) served by llama.cpp (llama-cpp-python's OpenAI-compatible server) on 127.0.0.1, CPU only.
  • willow's kernel, a single Python file with no dependencies, which does the retrieval, the record and the "does this answer cite what it was given" check.
  • Two new willow add-ons, built this week for this:
    • openai-compatible asks any OpenAI-compatible endpoint (llama.cpp, Ollama, LM Studio, vLLM) to answer only from the passages served, and refuses to pass along a reply that cites nothing. It lets any local model talk into willow, and nothing it says gets past the citation check.
    • shell-history reads bash, zsh and fish history as dated lines. It's how the deleted secret came back.
  • The demo, demo/ofrenda: Femia's files generated from a seeded script, every file labelled as fiction; the two books kept only by URL and SHA-256 and fetched fresh, and the questions, voices and pass rules frozen and committed before the first question was asked. Every verdict is a row on a tamper-evident record anyone can verify.

Willow itself is older than this challenge. The séance, the two add-ons and the demo are new for this challenge.

I built it with an AI coding agent pairing with me, on deadline night.

Code: willow-memory/Willow pull request #131 (the demo lives in demo/ofrenda)

Why Open Innovation Matters Here

Because this is someone's grandmother.

The files a person leaves behind — the recipes, the letters, the terminal history with the secret in it — are the most private things a family has. With an open-weight model they never leave the house. Unplug the router and the séance still works. Nothing gets uploaded so a company can "remember" your abuela for you, and nothing breaks when that company shuts down the service in five years.

Open also meant I could swap the medium. Running the same frozen questions through two sizes of Gemma is what showed that the rule holds no matter which model sits behind it. With a closed API I'd be trusting the model to behave. Here I don't have to: the model is free to guess, and willow is the thing that checks what it says against the files.

And it means anyone can check me. The questions were frozen before the run, the books are hashed, the record verifies, and the failures are in the README next to the wins.

Terminal: kernel.py verify on both boxes, the chain holds, 0 sealed

Ada was right: the Engine originates nothing. It can only do what we know how to order it to perform. So I ordered it to stay silent when it doesn't know.

Prendan la vela.

Top comments (0)