Skip to content

Strict scalar-type validation for limits.* policy fields #278

Description

@pbean

Context

Surfaced during the adversarial review of #277 (finding #6, deferred there as a repo-wide consistency issue rather than a one-off).

policy.py loads every limits.* scalar with a bare coercion — int(...), float(...), str(...), bool(...) — then range/membership-validates a few (e.g. session_budget_mode). There is no strict per-field type validation. bool(...) in particular silently coerces a truthy string:

# policy.py:720
dev_contract_nudge = bool(limits_d.get("dev_contract_nudge", LimitsPolicy.dev_contract_nudge))

so dev_contract_nudge = "false" (a quoted string — a plausible user error) coerces to True and enables the nudge. A well-formed TOML boolean (dev_contract_nudge = false) already parses correctly; only the quoted form misbehaves.

Why not fix it narrowly

Fixing only dev_contract_nudge would be an inconsistent island: every sibling limits.* field uses the same coerce-then-value-validate convention. The right fix is a small cross-cutting sweep.

Proposal

Add strict scalar-type validation across limits.* fields (bool/int/float/enum) — reject or warn when a value's TOML type doesn't match the field's declared type — following the existing strict precedent in the plugin-settings path (_validate_plugin_settings, policy.py:613), which already raises PolicyError on a non-bool where a bool is expected. Add invalid-type tests per kind.

Scope

  • src/bmad_loop/policy.py (the limits load path)
  • tests/test_policy.py

Low priority / hardening.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:engineOrchestrator engine and run lifecyclegood first issueGood for newcomers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions