CHAPTER 39: Boolean validation and replayed events

39a: The text false is not the Boolean False
39b: One notification can arrive more than once

HOW TO RUN
Open a terminal in the extracted companion folder, the folder containing
automation, sql and visual_labs. Run:

    python visual_labs/ch39/walkthrough.py

Use python3 or py instead of python if that is the command established in
Chapter 15. No extra Python package is needed. Run it only after predicting
the displayed states. The exact output is also in expected_output.txt.

When a lab imports the automation examples, its short Path/sys.path setup
locates those existing modules relative to this file. It changes where this
Python process looks for imports; it does not change your operating-system
configuration. Preserve the extracted folder structure.

SOURCE AND MEANING
The event fields match the chapter's fictional local example. The script calls
chapter39_webhook.evaluate directly. It starts no web server, sends no message
and contacts no external CRM. Its state is a set that lives in this Python
process; clear() removes its remembered IDs to demonstrate a restart's effect.

FOLLOW BEFORE YOU RUN
Write down the four truth/type answers from board 39a. Explain why quotation
marks matter before reading the answers. Predict three routes: a new False
event, its exact duplicate, then a different event with True permission.

PREDICT, RUN, COMPARE
The lab processes those deliveries, then attempts a fresh event containing
the text "false". It checks that the invalid event was not remembered. Finally
it clears the in-memory set and processes evt-001 again. Match each printed
response to the state before that delivery.

ONE MORE INPUT TO REASON THROUGH
After evt-001 has already been accepted, resend the same event ID with a valid
Boolean True. Does this small receiver change its previous enrolment decision?

EXPLAINED ANSWER
No. It returns already_received before making another decision. The local
example does not compare the repeated event's content or handle revisions.
A genuine permission change needs the provider's distinct event and ordering
rules; this demo does not establish them. To check locally, retain the accepted
set, copy the event dictionary, change its Boolean to True and call evaluate.
This limitation is a reason to describe the duplicate policy precisely.

EXPECTED OUTPUT (verified by execution)

39a: Inspect values before routing
False
True
True
False
39b: Process deliveries with the existing evaluate function
{"status": "received", "decision": "do_not_enrol"}
{"status": "already_received"}
{"status": "received", "decision": "eligible_for_review"}
Remembered: evt-001, evt-002
Wrong type rejected: permission_to_email must be true or false
After simulated restart:
{"status": "received", "decision": "do_not_enrol"}

All data in this lab are fictional teaching examples.
