A mail is read alone, by a person who cannot ask what a blank means,
and portal renders an unknown {key} as nothing and sends a dead link as
readily as a live one. iris check now fails on a placeholder no form in
the bucket collects and portal does not fill, on a {site}/path link to
a page the site does not have, on a state that grants a group on a site
with no mail sender (the sign-in link would reach nobody), and on an
invite mail without {link} or with a key the invite cannot fill. It
warns on a placeholder only some forms collect, on a dialogue that does
not close (mailed on the way in, not told how it ended), and on a mail
that tells a person they may now act on their case without their link.
No FAIL on any live content repo (uhhm, redoal, westra, klingenbergbygg,
tomtervel); tomtervel gets two warnings, both real.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The opener that says what the business does and the look-around card
lead nowhere: they are what the page says before its options, so a
task and a simulation step carry them as `page` context and offer
only the cards that lead somewhere. Five personas per round had been
"choosing" the opener and counted as misroutes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every check now compiles the content into portal's Cedar policy and
fails when it does not validate against the schema - a rule the
schema cannot express would grant nothing at runtime. `--access`
prints the matrix: action, resource, who, and the state move where it
applies. Pinned to portal v0.3.40, where the policy lives.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L4jrCgLiKKHAEFuZUJjckH
question_lint becomes `iris check`, needs_replay becomes `iris
replay`, and the needs module and local-checkout loaders come with
them. Portal is a library dependency pinned to the release iris
matches (v0.3.36), so every type iris reads is the site's own and the
two never disagree about what a page is. `iris --path questions`
still works, so a content repo's one-line CI needs only a new path.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L4jrCgLiKKHAEFuZUJjckH