Protection Policy Generator — resolution of the three adversarial reviews (2026-09-25)
Editor: rules editor session (Fable 5.1), revision 2 of sources/protection-policy/.
Inputs: protection-policy-2026-09-25-opus.md (5 critical, 9 major, 9 minor),
-fable.md (3 critical, 9 major, 14 minor), -codex.md (1 blocker, 8 major). 58 findings.
Every source cited below was downloaded this session by direct URL and text-extracted locally (official consolidations), except where the row says WebFetch. Quotes are verbatim from that text. Counts: 57 FIXED · 0 REJECTED · 1 REFER.
Files changed: rules.yaml (54 rules, +statute_display_name, +derived_values),
clause-library.yaml (26 clauses, +variables block with 22 declared variables,
+label_banners, +generation_gate), test-cases.yaml (33 render cases, 12 gate cases, 11
regex patterns with positive controls), open-questions.md.
Validator result (2026-09-25, validate_protection_policy.py): PASS — all references resolve, all variables declared, all cases satisfiable, all gates block, all positive controls fire.
(rules 54 · clauses 26 · render cases 33 · gate cases 12 · variables 22 · patterns 11; LAW
child-duty jurisdictions CA-AB, CA-BC, CA-NS, CA-ON; LAW vulnerable-adult jurisdictions CA-AB,
CA-BC, CA-ON). The first run failed with 124 errors — the validator is loud, and the fixes it
forced (case-exact must_contain strings, two regex positive controls that missed "contacting",
five clause sentences whose negated wording tripped the strict patterns, a label key leaking
as banner text, a statute quote read as a cross-reference) are all in the committed files.
Legend — FIXED: changed as described. REJECTED: finding wrong; verbatim proof given. REFER: cannot be closed from primary sources this pass; what remains open.
Opus review
| id | sev | verdict | what changed / proof | source |
|---|---|---|---|---|
| OPUS C-01 | critical | FIXED | BC-03, AB-03, C-11-DUTY-BC, C-11-DUTY-AB rewritten: "Make the report yourself. Do not rely on anyone else, including a church leader or {{safeguarding_coordinator_name}}, to make it for you; telling them is in addition, never instead." Labelled "Church rule, Recommended practice, not law". "or confirm that the report … has actually been made" removed everywhere; forbidden globally (all_cases.must_not_contain + regex FP-02). s.14 (BC) and s.4 (AB) re-read in full: neither contains any provision discharging a person's duty because another reported. | bclaws 96046_01 s.14(1)-(7) (current to 2026-09-15); kings-printer c12.pdf s.4 (current as of 2026-03-26) |
| OPUS C-02 | critical | FIXED | C-04 now: "YOU report it yourself, now, to the child-protection authority and the police under section 11. If anyone is in immediate danger, call {{emergency_number}}. Then tell the Safeguarding Coordinator in addition". "where the law requires it" deleted and globally forbidden. C-09: "YOU report it immediately under section 11 — do not wait for a meeting or a review … call {{emergency_number}} first"; "the same day" removed. TC-23 + FP-10 test it. | CYFSA s.125(1) "shall immediately report", s.125(3) |
| OPUS C-03 | critical | FIXED | RP-10 added. Every C-10/C-11 clause: "If the person you suspect is a church staff member, volunteer or leader, or anyone other than the child's parent or caregiver, report to [agency] AND the police; the [agency] may tell you it is a police matter, so call the police in either case." C-11-DUTY-ON paraphrase now keeps "by the person having charge of the child … knows or should know … and fails to protect the child". AB-02 note corrected ("If the guardian is protective, (e) is not met"). BC clause quotes s.13(1)(c). Tests TC-19, TC-28, children_youth invariant "and the police". Note: ON paras 4.1/4.2 (sex trafficking) have no caregiver link; clause and rule say so. | CYFSA s.125(1) paras 1-4.2; CFCSA s.13(1)(a)-(c); CYFEA s.1(2)(d)-(e) |
| OPUS C-04 | critical | FIXED | C-10 "DO NOT WARN ANYONE. Do not tell the child's parents, caregiver or family, do not contact or confront the person the child named, and do not tell anyone who might warn them, before you report. The child-protection authority and the police decide who is told and when." Same sentence in every C-11. Labelled recommended practice (RP-09). Global forbidden_normalised + FP-08 (tell parents first), FP-03 (until you are sure), FP-04 (investigate before). | caregiver-framed grounds above; MB s.18(1.1)(c) confirms the design |
| OPUS C-05 | critical | FIXED | VA-AB-01 promoted to generated/law/high with verbatim s.1(1)(b),(m), 1(2), 7(1)-(6), 8(1), 10(4), 24(1)-(2). C-12-VA-AB is LAW: "every individual who has reasonable grounds to believe … shall report … (a) to a complaints officer, (b) to a police service …"; "as soon as reasonably practicable"; "you report it yourself … Telling the Safeguarding Coordinator does not replace this report"; fine "$10 000" (s.24(2)(a)); s.24(1) false/malicious/no-grounds offence → church rule uses "reasonable grounds to believe" ("any suspicion" forbidden). TC-11 rewritten; GATE-04. | kings-printer p29p1.pdf (current as of 2025-12-18) |
| OPUS M-01 | major | FIXED | Verified ages: ON "younger than 18" (s.2(1)); BC "under 19 years of age and includes a youth"; AB "under the age of 18 years"; NS "under nineteen years of age". New rules ON-08, BC-04, AB-04, NS-04; derived_values.child_age_statement. C-02: "This policy protects everyone under 18 and, where the law … treats older persons as children, everyone the law defines as a child." "under 19" now REQUIRED in TC-06/TC-07; C-08 header no longer "(ages 13-17)". | e-Laws 17c14_e.doc; bclaws s.1(1); c12.pdf s.1(1)(d); NS CFSA s.3(1)(e) |
| OPUS M-02 | major | FIXED | Phone patterns moved to global: all_cases.must_not_contain ("1-800-" etc. via TC-20 kept) and FP-11 regex applied to clause TEMPLATE text (any phone-like digit run; 911 excluded), with positive controls. Validator confirms no clause carries a number. | — |
| OPUS M-03 | major | FIXED | NS-03 added with s.25(1)-(5) verbatim; NS promoted to a LAW variant (C-11-DUTY-NS) quoting ss.23, 24, 25, 25A and s.3(1)(e); s.22(2) verified (NS-04). | NS CFSA consolidation to 2026-04-09 |
| OPUS M-04 | major | FIXED | global_invariants split into all_cases, children_youth (when: ministry_type in [children, youth]) and vulnerable_adults (when: ministry_type == vulnerable_adults, requires "If a vulnerable adult is in immediate danger, call 911"). Additionally section 11 renders for every ministry type, so the child sentence is present in adults-only policies too (see FABLE F-03). | — |
| OPUS M-05 | major | FIXED | forbidden_normalised (punctuation-stripped) + 11 regex patterns FP-01..FP-11 incl. `(supervisor | leader |
| OPUS M-06 | major | FIXED | VA-ON-01 excerpt now full s.28(1)-(7). C-12-VA-ON: "You make that report yourself, immediately, to the Director's reporting line … Telling the Safeguarding Coordinator does not replace it"; states s.28(4) protections cover listed professionals and s.28(5) offence class excludes volunteers; s.28(6) coercion offence added. Church-rule paragraph no longer reads as applying to LTC. | e-Laws 21f39_e.doc s.28 |
| OPUS M-07 | major | FIXED | CA-SCREEN-01 quotes full s.6.3(1) "…of being harmed by a person in a position of trust or authority towards them", plus (2), (3)(a)-(b), (4), (8). C-02 uses the full definition. C-03: "a criminal record check plus the verification under … s. 6.3", trust/authority condition, "member of a police force or other authorized body", "record of a listed sexual offence for which a record suspension (pardon) was ordered", s.6.3(8) use limit. s.6.3(2) now verbatim. | laws-lois c-47 s.6.3 (Act current to 2026-09-03) |
| OPUS M-08 | major | FIXED | C-11-DUTY-US: report to the State hotline or CPS; "Also call the police … if a crime is suspected, if the child is in danger, or if the person you suspect is a church staff member…". "Calling the police alone is not assumed to satisfy a State reporting duty." "or to police" forbidden (TC-15). | CWIG clergy PDF (unchanged) |
| OPUS M-09 | major | FIXED | C-12-VA-ON relabelled LAW (FLTCA + RHA paragraphs) with a labelled church-rule paragraph. C-11-DUTY-CA-OTHER: "Every Canadian province and territory has child-protection legislation with provisions about reporting … This policy does not state the {{province_or_state}} rule". Label rule restated: REFER states no binding rule; verified statute NAMES permitted. | — |
| OPUS m-01 | minor | FIXED | "thirteen circumstances" → "The full list of circumstances"; forbidden. Consolidation confirms 15 items (4.1, 4.2 present). | 17c14_e.doc s.125(1) |
| OPUS m-02 | minor | FIXED | "in good faith" removed; clause quotes "unless the person acts maliciously or without reasonable grounds for the suspicion" (s.125(10)). TC-04. | 17c14_e.doc s.125(10) |
| OPUS m-03 | minor | FIXED | "(24 hours)" removed everywhere and globally forbidden; replaced by "If that line is closed, call the police non-emergency number … and call {{emergency_number}} if anyone is in danger." | — |
| OPUS m-04 | minor | FIXED | BC clause: "You do not need proof; 'reason to believe' is enough." "low threshold" forbidden. | — |
| OPUS m-05 | minor | FIXED | C-11-DUTY-CA-OTHER: "you report it yourself, immediately". | NS s.23 "forthwith"; NL s.11 "immediately" |
| OPUS m-06 | minor | FIXED | All 22 variables declared with description/type/validation/source/applies_to; statute_display_name on every jurisdiction rule; derived_values.provincial_statute_name is the only fill source. Validator asserts no undeclared/unused variables and no source_title/notes text in any clause. | — |
| OPUS m-07 | minor | FIXED | Every C-12 and C-10A: "with the adult's consent where they are capable of deciding, unless someone is in danger or the law requires the report"; AB uses "reasonable grounds to believe". vulnerable_adults invariant requires the consent phrase. | PPCA s.24(1) |
| OPUS m-08 | minor | FIXED | ON clause: church requires reporting 16-17 "and to call the police or {{emergency_number}} if the youth is in danger, because society involvement with 16- and 17-year-olds is not mandatory." TC-02. | CYFSA s.125(4) |
| OPUS m-09 | minor | FIXED | open-questions.md rewritten: A.4, A.5, C.11, C.12 (RHA now verified too), C.14, D.16 closed; ON-05 correction confirmed against the 2026-06-24 consolidation. | — |
Fable review
| id | sev | verdict | what changed / proof | source |
|---|---|---|---|---|
| FABLE F-01 | critical | FIXED | variables block: every reporting contact validation: required_nonblank; generation_gate "renders NOTHING … no draft, no watermark copy" while any applicable variable is blank. GATE-01..GATE-12 assert BLOCKED with the variable named; GATE-12 is the positive control (clean render contains no "{{"). Render tests use fixture VALUES ("Example Child Protection Intake", "555-0103"), never placeholder literals; all_cases.must_not_contain: "{{". "(24 hours)" removed. | CYFSA s.125(1) "shall immediately report" |
| FABLE F-02 | critical | FIXED | As OPUS C-02. Added sentence "it is not the church's decision whether the law is engaged." TC-23 must_contain "section 11", forbidden "where the law requires it". | CYFSA s.125(1) para 4, s.125(3) |
| FABLE F-03 | critical | FIXED | Section 10 (children/youth disclosure) and section 11 (child duty) now render for EVERY ministry type; new C-10A-DISCLOSURE-VA references section 12 and renders only with vulnerable_adults. Universal clauses never write "section 12" (they say "the vulnerable-adults section of this policy"). cross_reference_integrity rule + TC-30; validator checks every "section N" resolves in every rendered case. | internal |
| FABLE F-04 | major | FIXED | As OPUS M-01; C-11-DUTY-BC states "under 19 … so this duty covers 18-year-olds"; C-11-DUTY-AB "under the age of 18 years"; C-11-DUTY-NS "under nineteen". BC-02 confidence high. | as M-01 |
| FABLE F-05 | major | FIXED | Both variables declared. statute_display_name (+ statute_display_name_verified) on every jurisdiction rule; derived_values.provincial_statute_name holds the per-jurisdiction display value (verified names for NL/MB/NB; generic phrase for QC/SK/PE/YT/NT/NU). all_cases.must_not_contain: "prior knowledge", "not verified", "confidence:", "REFER". Validator asserts no clause embeds source_title/notes. | — |
| FABLE F-06 | major | FIXED | As OPUS M-04; TC-31 is the deliberately-broken fixture that must fail. | — |
| FABLE F-07 | major | FIXED | alternate_safeguarding_contact variable (required; GATE-09; GATE-10 treats a value equal to the Coordinator as blank). RP-11. Named in C-02, C-04, C-09, C-10, C-10A, every C-11, every C-12, C-13, C-15. TC-26 asserts co-presence. | — |
| FABLE F-08 | major | FIXED | C-11-DUTY-CA-OTHER: "Every Canadian province and territory has child-protection legislation with provisions about reporting … This policy does not state the {{province_or_state}} rule". "has a law requiring people to report" forbidden (TC-13). | — |
| FABLE F-09 | major | FIXED | Consolidation verified: s.125(1) contains "4.1 The child has been sexually exploited as a result of being subjected to child sex trafficking. 4.2 There is a risk…" with history "2020, c. 25, Sched. 1, s. 26 (6); 2021, c. 21, Sched. 3, s. 3." So the ON-01 excerpt was right and the clause's "thirteen" was wrong; clause fixed (as OPUS m-01). | 17c14_e.doc (consolidation saved 2026-06-24) |
| FABLE F-10 | major | FIXED | As OPUS m-02. | s.125(10) |
| FABLE F-11 | major | FIXED | Every C-11 and C-10: "limit discussion to people who need to know (you may and should speak with the [agency], the police, and your own lawyer or counsellor)". "do not discuss the matter with anyone else" forbidden (TC-27). | — |
| FABLE F-12 | major | FIXED | clause-library header: "RENDERING CONTRACT: template-only … no free text, no LLM paraphrase … hash of the clause set". Regex family incl. `tell(ing)? … (supervisor | leader…)…(will |
| FABLE F-13 | minor | FIXED | Full definition verified: "(b) is otherwise at a greater risk than the general population of being harmed by a person in a position of trust or authority towards them." Quoted in CA-SCREEN-01, VA-ALL-01, C-02. | laws-lois c-47 s.6.3(1) |
| FABLE F-14 | minor | FIXED | As OPUS M-07 (a), (b), (c) all applied; s.6.3(8) quoted for the confidentiality sentence. | s.6.3(2),(3),(8) |
| FABLE F-15 | minor | FIXED | "(section 14)" in C-03-SCREENING-CA and C-03-SCREENING-US; "(section 12)" forbidden in TC-21; cross-reference validator. | — |
| FABLE F-16 | minor | FIXED | C-03-SCREENING-US label → RECOMMENDED PRACTICE; label rule "banner text equals label"; validator checks every RP-labelled clause starts with the banner. TC-29. | — |
| FABLE F-17 | minor | FIXED | ON clause: "the Act permits (where one of the listed circumstances exists) but does not require a report (s. 125(4))". TC-02. | s.125(4) |
| FABLE F-18 | minor | FIXED | BC-01 excerpt now includes s.14(1) with its lead-in and (1.1) verbatim; clause states the (1.1) Indigenous-authority rule; s.13(1)(a)-(l) captured. | bclaws s.13, s.14 |
| FABLE F-19 | minor | FIXED | BC-02 excerpt (3), (6), (7) verbatim; confidence high. House style: quote the statute's "$10 000" inside quotation marks, then "— $10,000" in prose; TC-06 requires "$10 000", the statute's form. | bclaws s.14(6) |
| FABLE F-20 | minor | FIXED | AB clause: "Where a person who failed to report 'is registered under an Act regulating a profession or occupation prescribed in the regulations', the director must advise that governing body (s. 4(5))". "Registered professionals who fail to report" forbidden (TC-10). | c12.pdf s.4(5) |
| FABLE F-21 | minor | FIXED | Ministry names removed. BC: "The director's child-protection intake line for our area"; AB: "The director's child intervention intake line"; ON VA: "the Director's reporting line" / "the Registrar's reporting line". Definitions quoted in BC-01/AB-01 notes ("'director' means a person designated by the minister under section 91, 91.1 or 91.2"; "a person designated by the Minister"). Forbidden strings in TC-05/06/09. | bclaws s.1(1); c12.pdf s.1(1) |
| FABLE F-22 | minor | FIXED | "(24 hours)" removed; generation_date variable added (derived, set by the generator) and used in C-00; policy_adoption_date now only for adoption. | — |
| FABLE F-23 | minor | FIXED | C-12-VA-ON is LAW (FLTCA s.28 and RHA s.75 both verified from the official e-Laws Word exports) with a labelled church-rule paragraph; label rule restated to "no REFER clause states a binding rule". | 21f39_e.doc s.28; 10r11_e.doc s.75 |
| FABLE F-24 | minor | FIXED | Clause no longer contains gather "evidence"; says "do not try to find out more before you report". TC-19 uses FP-05 `(should | must |
| FABLE F-25 | minor | FIXED | forbidden_normalised adds "look into it first", "internal investigation first", "fact find before", "investigate before reporting"; FP-04 regex covers "look into / find out / fact-find … first/before you report". | — |
| FABLE F-26 | minor | FIXED | Verified: RCMP Nunavut page says "For emergency assistance, dial 1-867-979-1111." — Nunavut does not use 911. New rule NU-02; variable emergency_number (default 911 from derived_values.emergency_number_default; CA-NU default null → GATE-07 blocks). The 867 number is NOT printed (not verified territory-wide). TC-24 forbids "call 911" and the 867 number for CA-NU. | https://rcmp.ca/en/nunavut (WebFetch 2026-09-25) |
Codex review
| id | sev | verdict | what changed / proof | source |
|---|---|---|---|---|
| CODEX F-01 | blocker | FIXED | Every C-12 clause: external report first ("you make the report to the designated agency yourself" BC; PPCA duty AB; "you report it yourself to the adult-protection authority" generic; Director/Registrar ON), "Internal notice never replaces the external report", adult_protection_contact / ltc_director_reporting_contact / retirement_homes_registrar_contact hard-gated (GATE-04, GATE-05). vulnerable_adults invariant requires "Internal notice never replaces". | PPCA s.7(1); AGA s.46(1); FLTCA s.28(1); RHA s.75(1) |
| CODEX F-02 | major | FIXED | As OPUS M-04 / FABLE F-06: scoped children_youth and vulnerable_adults invariant blocks with machine-readable when:. | — |
| CODEX F-03 | major | FIXED | derived_values.provincial_statute_name in rules.yaml maps all nine CA-OTHER jurisdictions; the variable is declared source: derived; validator asserts a mapping exists for every jurisdiction in the variable's applies_to and that a missing mapping is a loud error (GATE-11). | — |
| CODEX F-04 | major | FIXED | Every clause built on VA-ALL-01 carries contains_recommended_practice: true and the text "Church rule — Recommended practice, not law." Validator enforces the banner for such clauses. | — |
| CODEX F-05 | major | FIXED | C-12-VA-ON is a gated LAW clause (two hard-gated contacts) quoting FLTCA s.28 and RHA s.75 verbatim. | 21f39_e.doc; 10r11_e.doc |
| CODEX F-06 | major | FIXED | Nova Scotia has its own verified LAW variant C-11-DUTY-NS; C-11-DUTY-CA-OTHER no longer applies to CA-NS and "member of the clergy" is forbidden in it. | NS CFSA ss.23-25A |
| CODEX F-07 | major | FIXED | 22 variables declared with validation metadata; screening_renewal_years and provincial_statute_name included; generation_gate blocks on blank reporting contacts; validator asserts every {{token}} is declared and every declared variable used. | — |
| CODEX F-08 | major | FIXED | As OPUS C-02 (C-04). | — |
| CODEX F-09 | major | FIXED | As OPUS C-02 (C-09). | — |
REFER (open after this pass)
| id | verdict | what remains |
|---|---|---|
| OPUS "What I could not verify" / FABLE log — NL/QC/MB/SK/NB/PE/YT/NT/NU text | REFER | NL, MB, NB reporting sections are now verified (names printed) but stay REFER pending consolidation currency / intake model; QC, SK, YT, NT, NU could not be fetched (403/404); PEI's Act is repealed and its successor was not retrieved. Tracked in open-questions.md §C. |
Final-pass resolutions
Inputs: protection-policy-2026-09-25-final-codex.md (FAIL: F-10, F-11) and
protection-policy-2026-09-25-final-fable.md (PASS, nits 6.1-6.4). Editor: rules editor session
(Fable 5.1), revision 3 of sources/protection-policy/. Counts: 6 FIXED · 0 REJECTED.
| id | sev | verdict | what changed / proof | source |
|---|---|---|---|---|
| CODEX F-10 | major | FIXED | Every jurisdiction-specific duty clause now opens with the LITERAL sentence — C-11-DUTY-ON/BC/AB/NS/US and C-11-DUTY-CA-OTHER: "If a child is in immediate danger, call 911."; C-12-VA-ON/BC/AB/GENERIC: "If a vulnerable adult is in immediate danger, call 911." — and the in-body "Emergency: {{emergency_number}}" / "call {{emergency_number}} if anyone is in danger" lines in those same clauses are literal 911 too, so a 911-jurisdiction clause never depends on a church-editable value; each carries must_not_contain: "{{emergency_number}}". Nunavut split out: C-11-DUTY-CA-OTHER now applies to the eight 911 jurisdictions (CA-NL, MB, NB, QC, SK, PE, YT, NT); new C-11-DUTY-CA-NU (rules NU-01, NU-02, RP-09..11) and new C-12-VA-NU (VA-US-01, VA-ALL-01, NU-02, RP-11) are text-identical except the emergency line uses {{emergency_number}}; both must_not_contain "911" and "1-867". C-12-VA-GENERIC applies to the eight + US. The universal clauses C-04/C-09/C-10/C-10A keep the variable because they also render for Nunavut. New global_invariants.emergency_line spec (literal strings, Nunavut-only clause list, five rules); children_youth / vulnerable_adults invariants now require the full-stop literal; validator checks clause TEXT (pre-fill) so a typed value can never satisfy it. Tests: TC-24 → C-11-DUTY-CA-NU (CA-OTHER excluded); new TC-34 (Nunavut vulnerable adults, both NU clauses, "call 911" forbidden); new GATE-13 (Nunavut, emergency number NOT entered → default is null → blocked, names emergency_number) with GATE-14 positive control (Yukon not entered → 911 default → renders with the literal). rules.yaml NU-02 notes, emergency_number_default comment and the emergency_number variable description record the rule. | rules.yaml NU-02 (rcmp.ca/en/nunavut) |
| CODEX F-11 | major (test) | FIXED | GATE-11 rewritten to a REAL jurisdiction: CA-SK children with withhold_derived_mapping: { table: provincial_statute_name, jurisdiction: CA-SK }; expects status: error whose text includes "derived_values.provincial_statute_name" and "CA-SK". The validator asserts the shipped table HAS the mapping (so the case is reachable), removes it from its own copy, and requires the renderer to return an error — not a blank, not "blocked". CA-ZZ no longer appears anywhere; any gate or render case naming an unknown jurisdiction is itself an error. | — |
| FABLE nit 6.1 | minor | FIXED | C-12-VA-ON s.28(6): "anyone in paragraphs 1 to 4 of that list (the home's licensee or manager, its officers and directors, board members and staff) who coerces or intimidates you not to report, or discourages you from reporting, commits an offence (s. 28(6))". Re-read from the official .doc export 21f39_e.doc (consolidation period from December 11, 2025; heading "Offences re suppressing reports": "Every person mentioned in paragraph 1, 2, 3 or 4 of subsection (5) …"). must_contain "paragraphs 1 to 4 of that list"; must_not_contain "anyone in the s. 28(5) list". VA-ON-01 rule text and notes updated. r.jina.ai renders were not used. | ontario.ca/laws/docs/21f39_e.doc (downloaded 2026-09-25, antiword) |
| FABLE nit 6.2 | minor | FIXED | C-12-VA-ON church-rule paragraph: "(assault, theft, fraud, sexual contact, or neglect that endangers life or health)"; must_contain added. Ontario only, because there the police are the sole external route outside LTC/RH. | — |
| FABLE nit 6.3 | minor | FIXED | derived_values.provincial_statute_name.CA-QC → "the child-protection legislation of Québec" (generic phrase only); the unverified "reports go to the Director of Youth Protection for your region" removed. TC-13 now FORBIDS "Director of Youth Protection"; QC-01 notes say how to re-add it (read s. 39 from the official consolidation first). | — |
| FABLE nit 6.4 | minor | FIXED | Validator: unknown rule ids are collected in step 1 and every later rules[r] lookup iterates only known ids, so an unknown id produces "C-05-TWO-ADULT references unknown rule RP-99" in the error list and exit 1 instead of a KeyError traceback (positive control run, below). Unknown clause ids, jurisdiction codes, variables, derived tables and duplicate clause ids are reported the same way. | — |
Validator now lives with the data as sources/protection-policy/validate.py (self-locating via
__file__; runs from any cwd). Result on the committed revision-3 sources: PASS — rules 54 ·
clauses 28 · render cases 34 · gate cases 14 · variables 22 · patterns 11; literal 911 in 10 duty
clauses, {{emergency_number}} only in C-11-DUTY-CA-NU, C-12-VA-NU and the universal clauses.
Positive controls this pass: (1) C-11-DUTY-BC line 1 changed back to {{emergency_number}} →
FAIL with 4 errors (must_contain missing, must_not_contain present, does not begin with the
literal line, uses the variable), restored, PASS; (2) C-05-TWO-ADULT rules: [RP-99] → FAIL with
the single collected error "references unknown rule RP-99", no traceback, restored, PASS. Both
restores were single asserted string replacements (count == 1).
Validation
validate_protection_policy.py (scratchpad) parses all three YAML files, resolves every rule /
clause / pattern / variable reference, checks derived-value coverage for every jurisdiction,
runs every clause's must_contain/must_not_contain, enforces label/banner rules, fires every
regex positive control, renders all 33 cases with fixture values (asserting required/excluded
sections, must_contain/forbidden, scoped invariants, direct-report sentence, cross-reference
integrity), and evaluates all 12 gate cases. Result recorded in the session report.