DEV Community

Cover image for Sanni Yakuma: An AI Exorcism for Your Code, After a Sri Lankan Healing Ritual
chamod  dhananjaya
chamod dhananjaya

Posted on Edited on

Sanni Yakuma: An AI Exorcism for Your Code, After a Sri Lankan Healing Ritual

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

(https://dev.to/challenges/hacktoberfest-week4-2026-10-26)*

The ritual page for request/request: Kola Sanniya, chief of the 18 demons, between two torches

What I Built

In southern Sri Lanka there is a healing ritual called Sanni Yakuma. It runs from dusk to dawn. It begins with the Ata Paliya, eight dances that bless the patient. Then come the Daha Ata Sanniya: masked dancers bring out the eighteen Sanni demons, one by one. Each demon is believed to cause one illness: deafness, blindness, fever, madness. Each one steps into the torchlight, boasts, and is then mocked, humbled, and persuaded to leave the patient. Last comes their chief, Maha Kola Sanniya, whose mask carries all eighteen demons around his face.

I'm Sri Lankan, and these masks are part of the culture I grew up with. The ritual itself is rarely performed as an exorcism any more; today it lives on mostly as a cultural performance. So for "Ghost in the Machine" I wanted to bring it back in a new place: our codebases.

Sanni Yakuma is an AI exorcism for GitHub repositories. Each of the eighteen demons causes one code sickness:

Demon Brings… …and in code
Bihiri deafness swallowed errors (except: pass, empty catch {})
Kana blindness no tests, so nobody can see if it works
Golu muteness no README, no docs
Naga snake nightmares leaked API keys and committed .env files
Kora paralysis no commits for years, issues nobody answers
Abutha madness not caused by spirits self-made complexity: 137-line functions
…and 12 more

You give it a repository. It finds which demons possess it, shows the evidence from real files and lines, lets each demon speak, and performs the exorcism: a concrete fix. And, like the real ritual, it is kind first. Before any demon appears, it names the repository's blessings: what it already does well.

The "ghosts" in my demo are fitting ones: famous open-source projects that are now retired or silent, like AngularJS, jQuery Mobile and the Node.js library request.

Demo

Live: The Hall of Masks: rituals performed on four well-known retired repositories.

The Hall of Masks: rituals performed on four retired open-source repositories

A demon card on the ritual page: Abutha's mask, its monologue, the evidence and the cure

On each ritual page:

  • the masks are alive: their eyes follow your cursor and they sway like dancers
  • every claim links to the exact line on GitHub
  • each demon has a "Send it away" button. Read the cure, press it, and the mask turns to smoke and leaves the stage. When the last one is gone, only Kola Sanniya remains.

Here is what the ritual found in request, the HTTP library that millions of Node.js projects once depended on:

Abutha Sanniya (severe): "A web of lines I wove in request.js, where init stretches to 137 lines of pure chaos. I watched the developers drown in 58 paths of complexity… You think a few refactors can untangle my knot. Very well, I shall vanish."

Kora Sanniya (severe): "Since February 11, 2020, I have frozen the heart of this machine. One hundred and forty-five souls cry out in the issues, but no hand moves to answer them… I go now to find a living repo."

Both are facts first: Request.prototype.init really is 137 lines with a cyclomatic complexity of 58, and the last commit really was on 11 February 2020. Notice the cure for Kora, too: the model saw that the project is deprecated, so it didn't say "revive it". It said: archive the repository and point users to undici or node-fetch.

And then the verdict of Kola Sanniya, the root cause behind them all, with a blessing verse in Sinhala:

"The project's success led to an accumulation of features that eventually created an unmaintainable monolith."

සාමයෙන් නික්ම යන්න, අලුත් මගක් සොයා ගන්න.
Depart in peace, find a new path.

It also runs on pull requests as a GitHub Action. Here it is on its own repository, where it caught a function I wrote:

The PR comment's evidence and fix: links to the exact lines, and the cure for each demon

The PR comment's evidence and fix: links to the exact lines, and the cure for each demon

Code

Sanni Yakuma

An AI exorcism for codebases, after the healing ritual of southern Sri Lanka.

In the Sanni Yakuma ritual, masked dancers call out the eighteen Sanni demons, each believed to cause one illness. The demons are questioned, mocked, humbled and sent away. The ritual opens with blessings, and the leader of the demons, Kola Sanniya, comes last.

This tool performs the same ritual on a GitHub repository. Each demon causes one code sickness Plain detectors find the evidence in the code, and an open Gemma model names the demons, gives each one a short monologue, and writes a concrete cure.

Visit the Hall of Masks to see rituals performed on well-known repositories.

How it works

  1. Summon. Shallow-clone the repository (or use a local folder).
  2. Read the omens. Eighteen small detectors, with no AI, collect evidence: file, line, snippet numbers.
  3. Diagnosis. Gemma reads only that evidence and returns JSON: the…

uv run sanni omens https://github.com/request/request      # the detectors only, no AI
uv run sanni exorcise https://github.com/request/request   # the full ritual -> out/request-request.html
Enter fullscreen mode Exit fullscreen mode

How I Built It

Architecture: 18 detectors find the evidence without AI, Gemma explains it, and guards keep it honest

Python 3.12 + uv, and Gemma (Google's open-weight model) through Google AI Studio: gemma-4-26b-a4b-it by default, gemma-4-31b-it for some of the gallery.

The most important design decision: the AI does not decide what is wrong. A model asked "what's wrong with this repo?" will happily invent problems. So the work is split in two:

1. Reading the omens (no AI). Eighteen small detectors, one per demon, scan the code and return evidence: file, line, snippet, numbers. Abutha uses lizard for complexity; Deva hashes six-line windows to find copy-paste; Naga matches known key formats (and masks every secret, so the public page never leaks one); Kora reads the git log and GitHub metadata.

2. The diagnosis (Gemma). Gemma receives only that evidence, each piece with an id (E1, E2…), plus the code around it. It returns JSON: the blessings, the demons it confirms with severity and the evidence ids that prove them, a monologue in each demon's voice, a cure, and Kola Sanniya's verdict with a Sinhala verse.

3. Keeping it honest. Gemma's answer is validated with pydantic, and then checked against the evidence. Any demon no detector found, and any evidence id that doesn't exist, is thrown out and listed on the page:

for p in ans.possessions:
    name = next((n for n in BY_NAME if n.lower() == p.demon.strip().lower()), None)
    if name is None or name not in found:
        rejected.append(f"{p.demon}: no detector found this demon")
        continue
    ids = [i for i in p.evidence_ids if i in index and index[i][0] == name]
Enter fullscreen mode Exit fullscreen mode

Code fixes get the same treatment. Models are bad at writing unified diffs by hand (line numbers, hunk headers, whitespace), and my first attempts never applied. So Gemma now writes a simple find/replace edit, and the tool finds those lines in the real file and builds the diff itself with difflib. If the lines aren't there, or the patched Python no longer parses, the fix is dropped. A broken cure is worse than none.

4. The ritual page. One self-contained HTML file per repository (Jinja2, no JavaScript framework). The nineteen masks are original SVGs drawn in code, each with one trait from its illness: Bihiri's ears are bound shut, Kana's eyes are blank, Golu's mouth is sewn, Naga wears a crown of cobras. Kola Sanniya carries the eighteen small faces around his own, as the real masks in museum collections do.

The demons were sometimes false

The best lessons came from false demons, each one a real bug I had to fix:

  • Underscore looked 38% copy-pasted. It wasn't: it commits its own build bundles next to its source. Now generated bundles are recognised: 0%.
  • Test certificates in request were flagged as leaked private keys. They are fixtures, on purpose. Test folders are now skipped.
  • AngularJS was blamed for a function with a complexity of 1,200, in a file whose first line says "Generated file, do not modify". jQuery Mobile was blamed for bugs in its bundled copy of jQuery. Generated and vendored code is now excluded.
  • My favourite: the hotfix-fever demon, Gini Jala, flagged my own commit "feat: add Gini Jala detector for hotfix fever".

A demon is only as honest as its omens.

Making it real

  • A GitHub Action (action.yml) posts the ritual as one pull-request comment, updated on each push, and keeps the full page as an artifact. @mentions in model output are neutralised so the bot can never ping anyone.
  • Hosted inference is not always calm. AI Studio returned 500 INTERNAL often enough that I added retries with backoff, a five-minute timeout, and JSON repair for the odd broken string. Two of the four gallery pages were diagnosed by the smaller model because the larger one was down; each page says which model it used.
  • 67 tests, Ruff-clean, CI on every push.

Why Does Open Innovation Matter?

Your code can stay yours. A code-health tool reads your whole codebase. With a closed API, that code has to leave your machine. Because Gemma's weights are open, the same tool runs against a local Gemma with one setting (MODEL_PROVIDER=ollama), on a laptop, a university server or a company's own hardware, and no line of private code goes anywhere. The provider is a setting, not a dependency: AI Studio, OpenRouter or Ollama.

It speaks my language. Every ritual ends with a blessing verse in Sinhala, a language with about 17 million speakers and very little presence in AI tools. Gemma writes it, I checked every verse myself, and because the model is open, anyone could fine-tune it to write Sinhala better.

It's free to try. The free tier was enough to build and test all of this as a student.

And it keeps a small story alive. Open models and open source let a tradition from one coast of one island show up in developers' pull requests anywhere in the world, on its own terms, with its sources cited.

My Agent Session

I built this with Claude Code as an AI pair programmer, and I want to be open about that. I chose the idea and the mapping from demons to code sicknesses, directed every step, checked every Sinhala line, and reviewed and approved every one of the project's 140+ commits; the agent wrote much of the code and the tests with me. I didn't record the session with DevRelay.

The Spirit of It

In Sanni Yakuma, the demons are not destroyed. They are named, laughed at, humbled, and sent away, and the patient is blessed first. I think that's a better way to talk about code too. You don't shame the people who wrote it. You name the sickness, show the evidence, offer a cure, and let it go.

The humour on these pages belongs to the ritual itself, which mocks its demons. The tradition, its performers and its beliefs are never the joke.

Sources on the ritual: Sanni Yakuma (Wikipedia) and the Science Museum Group's Maha Kola Sanniya mask ("chief disease-demon with victims and 18 attendant demons", Sinhalese, 1771–1910). The masks on my pages are original drawings, not copies of real masks.

Prize Categories

Best Use of Gemma: Gemma (open weights) is the diagnosis engine: it reads the detectors' evidence and writes the blessings, the demons' monologues, the cures as code edits, and a verse in Sinhala. It's served through Google AI Studio, with OpenRouter and local Ollama as drop-in options.

Top comments (0)