Skip to content

The complete worked example

This is the full source behind the hero example on the front page — the same puzzle, all four subjects, executed and validated during this site's build, not transcribed by hand.

The puzzle

Source: src/guardrail_calculus/examples/landing_hero_puzzle.py

from __future__ import annotations

from dataclasses import dataclass
from typing import Any, TypeAlias

from guardrail_calculus import (
    SubjectFacts,
    SubjectRef,
    clock_from_hhmm,
    duration_hours,
    ref,
    subject,
    subject_ref,
)
from guardrail_calculus.dimension_value_builtins import ClockRef


@dataclass(frozen=True)
class LandingHeroSubject:
    """The subject schema for the landing-page hero puzzle: a departure observable."""

    departure: ClockRef


@dataclass(frozen=True)
class LandingHeroPuzzle[
    AveryT: SubjectFacts[Any, Any, Any],
    BlakeT: SubjectFacts[Any, Any, Any],
    CaseyT: SubjectFacts[Any, Any, Any],
    DrewT: SubjectFacts[Any, Any, Any],
]:
    avery: AveryT
    blake: BlakeT
    casey: CaseyT
    drew: DrewT


SubjectRefFacts: TypeAlias = SubjectFacts[None, Any, SubjectRef[LandingHeroSubject]]

LandingHeroPuzzleRefs: TypeAlias = LandingHeroPuzzle[
    SubjectRefFacts,
    SubjectRefFacts,
    SubjectRefFacts,
    SubjectRefFacts,
]


r = ref[LandingHeroPuzzleRefs]
_ = subject_ref[LandingHeroSubject]


def _build_landing_hero_puzzle():
    """docs/dev/sprints/roadmap/+1/landing-page.md Phase 1: the canonical flight
    puzzle (guardrail_calculus.examples.flight_puzzle) with two edits, so the hero
    shows VERIFIED, FALSIFIED and a contingent UNKNOWN in one small example instead
    of four UNKNOWNs and one VERIFIED. Avery's 06:20 moves from check "A" to a
    given (so check "B" can be falsified against it), and Casey's given ("departs
    at the same time as Avery") is dropped so Casey stays genuinely unconstrained --
    the contingent UNKNOWN, not a backend limit.
    """
    return LandingHeroPuzzle(
        avery=(
            subject()
            .given(
                (_.departure @ clock_from_hhmm(620)).annotate("Avery departs at 06:20.")
            )
            .block()
        ),
        blake=(
            subject()
            .given(
                (_.departure @ (r.drew.own.departure - duration_hours(1))).annotate(
                    "Blake departs one hour before Drew."
                )
            )
            .check(
                "B",
                (_.departure @ r.avery.own.departure).annotate(
                    "Blake departs when Avery does."
                ),
            )
            .check(
                "C",
                (_.departure @ clock_from_hhmm(830)).annotate(
                    "Blake departs at 08:30."
                ),
            )
            .check(
                "D",
                (_.departure > r.avery.own.departure).annotate(
                    "Blake departs after Avery."
                ),
            )
            .block()
        ),
        casey=(
            subject()
            .check(
                "E",
                (_.departure + duration_hours(8) <= clock_from_hhmm(1520)).annotate(
                    "Casey's 8-hour journey ends by 15:20."
                ),
            )
            .block()
        ),
        drew=(
            subject()
            .given(
                (_.departure @ (clock_from_hhmm(1730) - duration_hours(8))).annotate(
                    "Drew departs 8 hours before 17:30."
                )
            )
            .block()
        ),
    )


landing_hero_puzzle = _build_landing_hero_puzzle()

The verdicts

Solving it and classifying every check against the base facts:

Check Proposition Verdict
B Blake departs when Avery does FALSIFIED
C Blake departs at 08:30 VERIFIED
D Blake departs after Avery VERIFIED
E Casey's 8-hour journey ends by 15:20 UNKNOWN

C and D follow from Drew's and Blake's givens by direct derivation. B is refuted by the same derivation — Blake's departure time is fixed at 08:30, and nothing says Avery's matches it. E is genuinely undecided: Casey carries no given at all, so her departure time is unconstrained, and the rule set correctly reports that as UNKNOWN rather than guessing.

Pinned by tests/examples/test_landing_hero_puzzle.py — a future change to the solver breaks that test, not this page.

The provenance graph

Every node below is either a given, a derivation step, or a check; every edge is a real dependency the solver traced, not an illustration.

See how reasoning works for what the node shapes and edge types mean, and how a check's verdict is decided from satisfiability and refutability.