DEV Community

whaiman
whaiman

Posted on

Acedia: one justified next action from a pile of obligations

Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady Submission πŸ¦₯

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

What I Built

Acedia turns a pile of obligations into one next action. You paste what you owe, with deadlines and "after X" dependencies, in plain text. It answers with a single step and tells you:

  • when that step is done,
  • why it comes before everything else,
  • what can safely wait, and when to look at it again,
  • what it could not know.

This project started life as SLOTH, which fits this week's "Slow and Steady" theme. I renamed it because sloth describes the symptom (slowness), while the real problem is not being able to start anything when too many obligations compete.

The name comes from the Greek ἀκηδία (akΔ“dΓ­a), often translated as β€œlack of care.” In early Christian monastic writing, Evagrius of Pontus described acedia as a troubling state of listlessness and restlessness, associated with the β€œnoonday demon.” Over time, acedia became closely associated with the sin of sloth, though its historical meaning is more complex than ordinary laziness. Here, it means something more specific: the list has grown so long that choosing where to begin has become the hardest task. Acedia takes that choice off your hands by identifying one justified next action. It makes no claim to treat anything beyond that.

Demo

Live demo: https://acedia.onrender.com/ (free tier, so the first load can take about a minute to wake up).

Try the three lines from "How It Works" below, then press "Mark step complete" and watch the next action appear.

Code

https://github.com/whaiman/acedia (MIT)

How It Works

The rule I held to throughout: the model proposes, the engine decides.

your text
   β”‚
   β”œβ”€ model configured? ──► open model proposes obligations (JSON)
   β”‚                              β”‚
   β”‚                        validated against YOUR text
   β”‚                        (quote must appear verbatim, else the
   β”‚                         deadline is dropped; bad output rejected)
   β”‚                              β”‚
   └─ no / failed ───────► rule-based parser (offline fallback)
                                  β”‚
                                  β–Ό
                     deterministic engine: recommend()
                                  β”‚
                                  β–Ό
          action + done-when + reasons + deadline + uncertainty
                     + what waits and when to review it
Enter fullscreen mode Exit fullscreen mode

The engine. recommend() is a pure function: same obligations and same now give the same answer. It chooses among items with no open prerequisites, in this order:

  1. urgent first (effective deadline overdue or within 2 days),
  2. the item that unblocks the most other work,
  3. the earliest effective deadline,
  4. irreversible items,
  5. smaller effort,
  6. original input order.

"Effective deadline" includes deadlines inherited from the items that depend on it. Here is a real run on three lines:

Publish the write-up by 30 October after the demo
Record the demo after the core feature
Build the core feature
Enter fullscreen mode Exit fullscreen mode

On 25 October the engine picks Build the core feature, because two other items cannot start until it is done. Its reason line reads "2 items can't start until this is done", and its deadline note reads "Deadline 2026-10-30 (in 6 days), inherited from 'Publish the write-up'". It never had a deadline of its own. After "Mark step complete" the next action is the demo, with the same inherited deadline. No one asked the engine to be clever; this follows directly from the rules.

Safe waiting. Postponement is a decision, so the engine only calls an item "safe to wait" if it has a verified deadline at least 7 days away, is not irreversible, and comes with a review date and a condition that would reopen the question. Missing information is never treated as permission: no deadline means "can't tell", not "can wait".

The model's job. Reading messy prose ("the report must be submitted by 30 October, but first add the methodology") is where a language model helps. It can't be trusted with the decision itself, so its output goes through a validator. Each obligation must carry a sourceQuote, which has to appear verbatim in what you typed. If the quote isn't there, the deadline is dropped with a warning. Unknown dependencies, duplicate ids and malformed JSON are rejected, and the app falls back to the rule-based parser and says so in the UI.

How I Built It

Next.js 16, React 19, strict TypeScript, Tailwind 4, Vitest. The decision core (src/lib/acedia/) has no UI or network dependency and is tested on its own: 57 tests cover the engine, the parser, the validator and the model client (including retries, garbage output and a failing server).

The model client speaks to any OpenAI-compatible /chat/completions endpoint, so it works with LM Studio, llama.cpp, vLLM, Ollama or a hosted provider. The endpoint and key live only in server-side environment variables. Notes are sanitized and wrapped in delimiters, and the prompt tells the model to ignore instructions inside them. That reduces risk, but it is not a guarantee.

AI assistance: I built this with AI help. The decision core and the early design were drafted in a Claude chat, and I iterated on the UI, validation and tests with an OpenCode agent ([[google/gemma-4-e2b]]). I ran the repo's lint, build and test commands myself before publishing.

Why Does Open Innovation Matter?

Because the whole design depends on being able to swap and inspect the model. I ran google/gemma-4-e2b locally through LM Studio, so my notes never left my machine, and any other open-weight model works by changing three environment variables, which lets me compare them on the same input. The engine, not the model, makes the decision, so every recommendation can be audited and re-run.

Hacktoberfest's own mission puts it this way:

Instead of counting PRs, you'll write your first skills.md, build your own open-source agent, fine-tune an open-weight model, or go wherever your curiosity takes you.

Limitations

  • The offline parser understands ISO dates, "30 October" and "October 30", and "after X and Y". It does not understand "Friday", "next week" or implicit dependencies. That is what the model is for.
  • No persistence: refreshing loses the state.
  • The 7-day rule ignores how long a task takes.
  • A hosted model sends your text to its provider, and the public demo says so.
  • Prompt-injection hardening lowers the risk. It does not remove it.
  • Acedia is a decision aid, not a coach or therapist, and makes no claims about productivity or mental health.

Prize Categories

Best Use of Gemma: the extraction step runs google/gemma-4-e2b locally through LM Studio. The model only proposes obligations; every proposal is validated against the user's text before the engine uses it.

Best Use of Render: the app is deployed as a Render web service at https://acedia.onrender.com. The hosted demo runs the rule-based parser, so it works with no model and no API key.

Top comments (0)