Skip to content

C7 follow-up: four false-warning defects in the soft-warning rules (trait pool, Ancestral Exemplar, beastform abilities, unpinned prereq table) #73

Description

@zacgoodwin

Context

C7 (#23) shipped the soft-warning engine. Its adversarial review confirmed all five
acceptance criteria and approved at confidence 90, but recorded four real defects in the
warning rules themselves. They are adjacent to the ACs rather than inside them, so they
did not block the merge — but each produces a false warning shown to a player, which
is exactly what a soft-warning engine must not do.

  1. app/lib/tlc/warnings.rb:69BASE_TRAIT_ALLOWANCE = 3 is hardcoded, while
    app/platforms/tlc/homebrews/species.rb:34 already stores optional_pool_size
    (default 3, author-settable 0..10 via .../species/perform_command.rb:59). A species
    authored with a pool of 5 gets a false trait_count warning at 4 selections. The
    reviewer verified both files.

  2. app/lib/tlc/warnings.rb:117 — the trait allowance omits "+1 per Ancestral Exemplar
    take"
    (docs/players-guide-digest.md:239, the feat at :122). A legal Exemplar
    build warns permanently. QA flagged this in an earlier pass too. Note the ticket body
    itself said "3, or 4 with Mixed Ancestry", so this is ticket-vs-digest, not
    diff-vs-ticket — the rule as specced was incomplete.

  3. app/lib/tlc/warnings.rb:197abilities reads modified_abilities, which
    app/decorators_v2/dnd2024_decorator.rb:81-89 overwrites with beastform scores. A
    druid's multiclass_prereq warning appears and disappears with Wild Shape.

  4. app/lib/tlc/warnings.rb:41-55 — 10 of 13 MULTICLASS_PREREQS rows survive
    mutation.
    Flipping monk/ranger AND→OR leaves the suite green. The values are
    correct against PHB 2024 (verified twice independently) — this is a coverage hole,
    not a wrong constant, and it is precisely where a future wrong constant would hide.

Files

  • app/lib/tlc/warnings.rb
  • app/platforms/tlc/homebrews/species.rb
  • spec/lib/tlc/warnings_spec.rb
  • docs/user-guide/warnings.md

Plan

  1. Trait allowance from data, not a constant. Read optional_pool_size off the
    character's species where one is set; fall back to BASE_TRAIT_ALLOWANCE when absent.
    Keep the Mixed Ancestry +1 that already works.
  2. Ancestral Exemplar. Add +1 per take. Check the digest for whether "free traits
    excluded from count" is a separate rule that also needs encoding — QA raised that
    phrasing and it was never resolved.
  3. Beastform. Read raw abilities rather than modified_abilities for the multiclass
    check, or explicitly skip the check while a beastform is active. Decide which is
    correct for the campaign and say why in a comment.
  4. Pin the prereq table. One table-driven example over all 13 rows closes the hole.

Acceptance Criteria

  • Setup: a species authored with optional_pool_size: 5 → Action: a character of that
    species selects 4 traits → Expected: NO trait_count warning. At 6 selections, the
    warning fires.
  • Setup: a character with Ancestral Exemplar taken twice → Action: select
    base allowance + 2 traits → Expected: no warning. One more → warning.
  • Setup: a druid whose raw abilities meet a multiclass prerequisite, currently in a
    beastform whose scores do not → Action: serialize → Expected: no
    multiclass_prereq warning; and the warning does not change when the beastform ends.
  • Setup: final diff → Action: flip the AND/OR on any single MULTICLASS_PREREQS row →
    Expected: the suite goes red and names that class. All 13 rows.

Tests + evals

  • A spec per acceptance case in spec/lib/tlc/warnings_spec.rb.
  • The prereq pin must be table-driven over all 13 rows, and each row demonstrated red
    under its own mutation.
  • No eval suite: no LLM surface.

Docs pages touched

  • docs/user-guide/warnings.md — the trait-count rule as actually implemented.

Out of scope

  • The registry, dismissal machinery and serializer shape, all verified working.

Depends on #23

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingready-for-agentFully specified, ready for an AFK agent

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions