<!-- Authored per the the-loop:writing skill. -->
Tasks: two bugs in the hooks[] declaration loader
Phase 4 of 4. Each task names the acceptance criterion it satisfies and the testing-plan row that proves it. Bug 2 is fixed in the same change as bug 1 because it is the reason bug 1 was invisible: a fixed bug 1 alone would leave the next non-string key raising the same
TypeError.
- [x] A0 — reproduce. Run the ticket's three snippets on
main; confirm theTruekey fromyaml.safe_load, theTypeErrorfromread_declaration, and thecould not read … TypeErrorfromthe-loop hooks. AC: R2.3 · Test: T5. - [x] A1 — normalise the key.
declaration.pygains_normalise_keys, called in_read_entryafter thenamecheck and before the unknown-key check:True → "on", every other key kept; both spellings together refused with a message naming the entry. AC: R1.1–R1.3 · Test: T1, T2. - [x] A2 — make the refusal total.
unknownis sorted byreprand rendered withrepr, so the refusal is aHooksConfigErrorfor any key type and names every offending key. AC: R2.1, R2.2 · Test: T3. - [x] B1 — regression tests, loader.
test_lifecycle_declaration.py: the documented entry throughyaml.safe_loadwith its premise pinned; quoted"on"and the both-spellings refusal; non-string unknown keys, parametrised, and the mixed-type case. Deps: A1, A2 · AC: R1.4, R2.3 · Test: T1–T3, T5. - [x] B2 — regression test, command.
test_hooks_cmd.py: the ticket's reproduction through a real YAML file andthe-loop hooks --format json. Deps: A1 · AC: R1.5 · Test: T4. - [x] C1 — docs.
docs/config/cli/hooks-options.md§hooks[].onsays both spellings load and why;docs/capabilities/lifecycle-hooks.mdgains the requirement under Declaration and loading and a history row. The guide, the shipped commented example and the JSON schema are unchanged on purpose (bugfix.md§ Out of scope). Deps: A1, A2 · Test: T8. - [x] D1 — verify and record. Full suite from
cli/,ruff,pyright,markdownlint;evidence/verification.mdwith raw output including the negative control;self-review.md,security-review.md,documentation.md,reviewer-briefing.md. Deps: A1–C1 · Test: T5–T8.