The devil is in the details.
A Detail Devil document is a single Markdown file that tracks a project's open questions as a dependency graph. It exists to catch the thing ordinary documents hide: an answer that rests on something nobody has decided yet.
Everything else follows. Because the rule tests two facts, every question in a document is in exactly one of four states — and one of them has no name in ordinary project tracking:
| all dependencies resolved | some dependency unresolved | |
|---|---|---|
| answered | Resolved | Provisional |
| unanswered | Ready | Blocked |
Provisional is the devil. It is an answer standing on ground that is still open — the decision someone made by quietly assuming something nobody had settled. Teams produce these constantly, and nothing in a normal document or issue tracker makes them visible.
Ready is the other half of the payoff: the questions that can usefully be answered right now, because nothing is in their way. It is a work queue you never have to maintain, and it makes a decent meeting agenda.
# Can we launch v1.0 publicly?
## Which email provider?
Answer: Resend on port 2587 —
DigitalOcean blocks 587.
Assumes [[who pays for infra?]]
lands under $20/mo.
## Who pays for infra?
Need to ask before committing
to a paid tier.
## Do we show contact emails?
### Answer
Yes, on ride cards, to anyone
signed in.
| Who pays for infra? | Ready |
|---|---|
| Which email provider? | Provisional |
| Do we show contact emails? | Resolved |
| Can we launch v1.0? | Blocked |
Nobody wrote any of that down. The states are computed from the file every time it is read, which is why the file cannot misreport its own progress — it records only what a human asserted.
? is a question. Any
other heading is an organizational section, and carries no state.Answer: paragraph, or an ### Answer
section, is the answer. Everything else under a question is notes —
so "blocked on the budget, need to ask Dan" never passes for a decision.[[reference]] is dependency too. It
expresses the edges an outline cannot — between siblings, or to a question
several things depend on. Name one that does not exist yet and you have
declared it, open, without leaving your sentence.Cycles are allowed, because scope really does depend on budget and budget on scope. They are reported as a set to decide jointly rather than rejected — a format that refuses an honest cycle only teaches its authors to write dishonest documents.
Add a DEVILS.md to the root of your project, and open it with
this preamble so that anyone — or any agent — who meets the file cold knows how
to read it:
> **What this file is.** The open questions on this project, and what depends on
> what. A heading ending in `?` is a question; the block marked `Answer:` beneath
> it is its answer.
>
> **The part that isn't obvious.** A question also depends on every question
> nested beneath it, and on any question it names in `[[double brackets]]`. It
> counts as resolved only when it has an answer *and* everything it depends on is
> resolved too. So an answered question sitting on unanswered ones is an
> assumption, not a decision — making those visible is the point of the file.
>
> Format spec: https://devils.md
Then write questions. That is the entire onboarding.
This repository carries a reference implementation in dependency-free Ruby — one file, no gems, and a reporter that reads any document:
$ bin/devils DEVILS.md
devils.md — 12 questions: 6 resolved, 0 provisional, 2 ready, 4 blocked
Ready — answerable now (2)
Is the site published at devils.md? (unblocks 3)
Is there a second implementation? (unblocks 2)
Blocked (4)
Is the Detail Devil Format ready for anyone else to use?
5 unresolved below it
It also computes a trace for any unresolved question — the answer to "why isn't this resolved?" — and leverage, the number of questions waiting on it, which ranks the Ready queue for you.