# `jadpo why`: why the language decided something

Much of what surprises people in Jadpo is a decision the language made for
them: policy hid a record, a lifecycle filtered it out, a subscriber didn't
run, or a cache answered. `jadpo why` explains one such decision from what
the compiler knows and what was recorded, and it says so when it doesn't
know.

It covers:

- **policy**: which grant lists were checked against which facts
  ([Policy](policy.md));
- **lifecycle**: a record that normal reads don't see, such as one that
  was soft-deleted ([Lifecycle](lifecycle.md));
- **concealment**: a record policy hid by answering as if it didn't exist
  ([Concealing records](concealing-records.md));
- **cache use**: a read served from a cached copy;
- **subscriber runs**: which subscribers ran for an event, and why others
  didn't ([Subscribers](subscribers.md)).

Give it a request, event or delivery id (`jadpo why <id>`), or a record and
a caller (`jadpo why <Entity> <id> --as <user>`):

```text
$ jadpo why req_0b1e
GET /todos/0192… answered 404 todo_not_found
  Todo 0192… exists, but policy concealed it (area 4: hidden looks absent)
  read: [owner_id]          owner_id is user 0192…a7; caller is user 0192…c3   no match
  policy   domains/planning/entities/todo.jadpo:14

$ jadpo why Todo 0192…f1 --as 0192…a7
Todo 0192…f1 is not visible to normal reads
  lifecycle visible: deleted_at == none   deleted_at is 2026-10-11T08:02:00Z
  purged after config.soft_delete_retention (30d), on 2026-11-10
  lifecycle  domains/planning/entities/todo.jadpo:22

$ jadpo why evt_7c21
TodoCompleted from req_9a40 (complete_todo, committed)
  update_statistics   succeeded, 1 attempt, 12 ms
  send_reminder       not subscribed: listens for ReminderDue

$ jadpo why req_5d3e --query todos_for_owner
todos_for_owner served from cache `cache` (age 14 s, keep: 60 s)
  display read on GET /todos; your own write was older than the copy (area 6)
```

Each answer ends with the `.jadpo` place that made the decision. On your
machine, `jadpo why` reads what `jadpo dev` recorded and the local
database. For production, it reads a log event you exported, as
`jadpo incident` does, so it can only explain what the logs recorded.
