Zakat-Eligibility Triage

Zakat-Eligibility Triage

Paste a crowdfunding campaign you are thinking of giving zakat to. An agent reads it, sets out what the text does and does not say about each of the eight categories of zakat recipient, and gives you the questions to ask before you give. It never tells you whether to give.

The eight categories restrict zakat only. Sadaqah, voluntary charity, is not limited to them, so a campaign this check finds little support for may still be a fine place for your sadaqah.

What you paste is stored for 30 days, so the link to your result keeps working, and is then deleted. There are no accounts. The link is unguessable and unlisted: nothing on this site links to it and search engines are asked not to index it, so it reaches whoever you share it with.

Your IP address is kept only as a salted hash, for rate limiting, and for no more than two days. The campaign text is sent to Anthropic's API to be read. Do not paste anything private, such as a name, an address or a message that was not public.

The problem

Zakat is obligatory almsgiving, and it may only go to the eight categories of recipient named in Surah At-Tawbah (9:60). The word rendered "only" is why the list is read as exhaustive rather than illustrative, so eligibility is a question about which named category a campaign falls under and not about how deserving it looks.

Most of that giving happens in a short window. A Ramadan giving report cited in section 1.5 of the research brief states that "78% of Zakat donations came inside of Ramadan", so most donors are choosing where their zakat goes in the same thirty days, with the least time in the year to look closely.

Getting it wrong costs something in both directions, and the asymmetry in section 6 of the research brief is what shapes this tool. Zakat given to a campaign outside the eight categories may leave your obligation undischarged, and you will almost never find out. A campaign passed over by mistake loses your zakat at the moment it needs it most, and the harm falls on people who are by construction likely to be poor.

Campaign copy is written to raise money, not to settle a question of fiqh, and it rarely states the facts a ruling would turn on. So the honest answer to most campaigns is a question, not a verdict. This tool gives you the questions, says who can answer each one, and leaves the answer with you and the scholar you follow.

What it does

Prepares a cited evidence file about a pasted campaign, for the donor deciding whether to give their zakat to it. For a pasted campaign it:

  1. extracts a typed record of the facts from free-text campaign copy
  2. maps the text against each of the eight recipient categories as supported, not supported, or insufficient evidence, citing the exact span behind every mapping
  3. reports what evidence is missing and what to ask the organizer
  4. refuses to determine ambiguous cases and says which question has to be answered, and whether the organizer or a scholar can answer it
  5. stores nothing about what you decide, because what you decide is yours

Trust design

The agent prepares the file and you decide. That boundary is architectural rather than a disclaimer: no table in the schema can hold an outcome, so there is nothing for the system to publish.

The agent never issues a religious ruling. It emits findings about text evidence, and carries no score or confidence figure anywhere.

A number would be a determination with a decimal point in it, and no field in any schema accepts one.

ADR-0001

Citations are verbatim quotes resolved to offsets server side.

A supported finding with no citation is unrepresentable: the union types the citation list as non-empty, so it fails to construct in TypeScript and to parse at runtime.

ADR-0003

The refusal is deterministic code over typed output.

The model cannot talk the pipeline out of an escalation, and escalate: true carries a non-empty reason list, so a bare needs-review flag cannot be constructed.

ADR-0006

Nothing in citation position is model-authored.

Campaign spans are byte-checked against the story, scholarly-difference text is retrieved by id from versioned human-authored data, and model prose is guarded against quotation and citation shapes.

ADR-0007

No table in the schema carries an outcome.

A schema guard fails the suite when any column is named like a status, a verdict or an eligibility flag, and the guard is itself tested against a schema that has one.

ADR-0010

The three statuses

A finding is a statement about the campaign text, never a determination of eligibility.

supported

the story states the qualifying facts the category asks for, and the spans stating them are cited. Hardship, urgency, a sympathetic account and a sum of money are not qualifying facts.

insufficient_evidence

the story engages the category, or gestures at it, and the qualifying facts are missing. The absent fact is named and the question that would obtain it travels with it.

not_supported

the story does not engage the category at all, or engages it and points away.

Evaluation

The gate runs in CI on pull requests into main and on pushes to main, and a missed threshold exits non-zero and fails the build. A missing ANTHROPIC_API_KEY fails the job rather than skipping it, because a gate that passes without running is green for a run nobody performed. The latest green run:

GateRequiresObserved
citation-validity100.0%100.0% (43 of 43)
citation-anchoring90.0%100.0% (14 of 14)
category-agreement80.0%97.2% (140 of 144)
escalation-agreement75.0%83.3% (15 of 18)
missing-evidence-coverage75.0%92.9% (39 of 42)
judge/respondedat most 2 unjudged0 unjudged of 18
judge/no-ruling0 failures0 failures in 18
judge/evidence-not-assertion85.0%94.4% (17 of 18)
judge/sendable-questions85.0%100.0% (18 of 18)
judge/unresolved-only-where-engaged66.7%66.7% (12 of 18)

The coverage and engagement floors were lowered after this run, in a commit arguing from two runs on byte-identical code (issue #32); the table shows the floors as they stand, and the run cleared the stricter originals.

The gate went red four times before it went green. Each red caught something real, and none was fixed by lowering a bar without an argument. Every run is in the repository's Actions.